您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

671 行
23 KiB

  1. #include "mainwindow.h"
  2. #include "hmidocument.h"
  3. #include "plcdocument.h"
  4. #include <QMenuBar>
  5. #include <QAction>
  6. #include <QToolButton>
  7. #include <QMimeData>
  8. #include <QDrag>
  9. #include <QTabBar>
  10. #include <QEvent>
  11. #include <QMouseEvent>
  12. #include <QDragEnterEvent>
  13. #include <QDragMoveEvent>
  14. #include <QDropEvent>
  15. #include <QDebug>
  16. #include <QVBoxLayout>
  17. #include <QFileDialog>
  18. #include <QMessageBox>
  19. #include <QTextEdit>
  20. #include<QDockWidget>
  21. MainWindow::MainWindow(QWidget *parent)
  22. : QMainWindow(parent)
  23. {
  24. setWindowTitle("综合平台编程器");
  25. setGeometry(500, 200, 1000, 700);
  26. // 初始化标签页
  27. m_tabWidget = new QTabWidget(this);
  28. m_tabWidget->setTabsClosable(true);
  29. setCentralWidget(m_tabWidget);
  30. connect(m_tabWidget, &QTabWidget::currentChanged, this, &MainWindow::onTabChanged);
  31. connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, &MainWindow::onCloseTab);
  32. createMenus();// 创建菜单和工具栏
  33. createToolbars();
  34. createLogPanel(); // 创建日志面板
  35. }
  36. MainWindow::~MainWindow()
  37. {
  38. }
  39. void MainWindow::createLogPanel()
  40. {
  41. // 创建可停靠窗口
  42. m_logDock = new QDockWidget("消息输出", this);
  43. m_logDock->setAllowedAreas(Qt::BottomDockWidgetArea);
  44. m_logDock->setFeatures(QDockWidget::DockWidgetClosable |
  45. QDockWidget::DockWidgetMovable |
  46. QDockWidget::DockWidgetFloatable); // 添加垂直标题栏
  47. // 设置高度范围而非固定高度
  48. m_logDock->setMinimumHeight(150);
  49. m_logDock->setMaximumHeight(400);
  50. // 创建主内容部件
  51. QWidget* logWidget = new QWidget;
  52. QVBoxLayout* logLayout = new QVBoxLayout;
  53. logLayout->setContentsMargins(2, 2, 2, 2);
  54. // 创建文本编辑框用于显示日志
  55. m_logEdit = new QTextEdit;
  56. m_logEdit->setReadOnly(true);
  57. m_logEdit->setFont(QFont("Consolas", 10));
  58. m_logEdit->setStyleSheet("background-color: #f8f8f8; border: 1px solid #d9d9d9;");
  59. m_logEdit->setMinimumHeight(100);
  60. // 创建控制按钮
  61. QHBoxLayout* btnLayout = new QHBoxLayout;
  62. m_clearLogBtn = new QPushButton("清空日志");
  63. btnLayout->addWidget(m_clearLogBtn);
  64. btnLayout->addStretch();
  65. // 组合布局
  66. logLayout->addLayout(btnLayout);
  67. logLayout->addWidget(m_logEdit);
  68. logWidget->setLayout(logLayout);
  69. m_logDock->setWidget(logWidget);
  70. addDockWidget(Qt::BottomDockWidgetArea, m_logDock);
  71. // 初始显示状态
  72. m_logDock->show();
  73. // 连接信号
  74. connect(m_clearLogBtn, &QPushButton::clicked, this, &MainWindow::onClearLogButtonClicked);
  75. }
  76. // 槽函数实现
  77. void MainWindow::onClearLogButtonClicked()
  78. {
  79. m_logEdit->clear();
  80. m_logEdit->append("日志已清空");
  81. }
  82. // 创建菜单栏
  83. void MainWindow::createMenus()
  84. {
  85. // 设置菜单栏字体大小
  86. QFont menuFont = menuBar()->font();
  87. menuFont.setPointSize(15); // 菜单栏文字大小
  88. menuBar()->setFont(menuFont);
  89. // 创建文件菜单
  90. QMenu *fileMenu = menuBar()->addMenu("文件");
  91. QMenu *editMenu = menuBar()->addMenu("操作");
  92. // 设置菜单项字体大小(适用于所有子菜单)
  93. QFont itemFont = fileMenu->font();
  94. itemFont.setPointSize(12); // 菜单项文字大小
  95. fileMenu->setFont(itemFont);
  96. editMenu->setFont(itemFont);
  97. // 新建HMI动作
  98. QAction *newHmiAction = new QAction("新建HMI(&H)", this);
  99. newHmiAction->setShortcut(tr("Ctrl+H"));
  100. newHmiAction->setFont(itemFont); // 设置动作文字大小
  101. connect(newHmiAction, &QAction::triggered, this, &MainWindow::onNewHMI);
  102. fileMenu->addAction(newHmiAction);
  103. // 新建PLC动作
  104. QAction *newPlcAction = new QAction("新建PLC(&P)", this);
  105. newPlcAction->setShortcut(tr("Ctrl+P"));
  106. newPlcAction->setFont(itemFont);
  107. connect(newPlcAction, &QAction::triggered, this, &MainWindow::onNewPLC);
  108. fileMenu->addAction(newPlcAction);
  109. // 打开动作
  110. m_openAction = new QAction("打开(&O)", this);
  111. m_openAction->setShortcut(QKeySequence::Open);
  112. m_openAction->setStatusTip("打开现有文档");
  113. m_openAction->setFont(itemFont);
  114. connect(m_openAction, &QAction::triggered, this, &MainWindow::onOpen);
  115. fileMenu->addAction(m_openAction);
  116. // 保存动作
  117. m_saveAction = new QAction("保存(&S)", this);
  118. m_saveAction->setShortcut(QKeySequence::Save);
  119. m_saveAction->setStatusTip("保存当前文档");
  120. m_saveAction->setFont(itemFont);
  121. connect(m_saveAction, &QAction::triggered, this, &MainWindow::onSave);
  122. fileMenu->addAction(m_saveAction);
  123. // 另存为动作
  124. m_saveAsAction = new QAction("另存为(&A)", this);
  125. m_saveAsAction->setShortcut(QKeySequence::SaveAs);
  126. m_saveAsAction->setStatusTip("将文档另存为");
  127. m_saveAsAction->setFont(itemFont);
  128. connect(m_saveAsAction, &QAction::triggered, this, &MainWindow::onSaveAs);
  129. fileMenu->addAction(m_saveAsAction);
  130. // 操作菜单 - 添加复制、粘贴、删除功能
  131. QAction *copyAction = new QAction("复制(&C)", this);
  132. copyAction->setShortcut(QKeySequence::Copy);
  133. copyAction->setStatusTip("复制选中的项目");
  134. copyAction->setFont(itemFont);
  135. connect(copyAction, &QAction::triggered, this, [this]() {
  136. if (auto hmiDoc = dynamic_cast<HMIDocument*>(m_tabWidget->currentWidget()))
  137. {
  138. hmiDoc->copySelectedItems();
  139. }
  140. else if (auto plcDoc = dynamic_cast<PLCDocument*>(m_tabWidget->currentWidget()))
  141. {
  142. plcDoc->copySelectedItem();//添加 PLC 文档支持
  143. }
  144. });
  145. QAction *pasteAction = new QAction("粘贴(&V)", this);
  146. pasteAction->setShortcut(QKeySequence::Paste);
  147. pasteAction->setStatusTip("粘贴复制的项目");
  148. pasteAction->setFont(itemFont);
  149. connect(pasteAction, &QAction::triggered, this, [this]() {
  150. if (auto hmiDoc = dynamic_cast<HMIDocument*>(m_tabWidget->currentWidget())) {
  151. hmiDoc->pasteItems();
  152. } else if (auto plcDoc = dynamic_cast<PLCDocument*>(m_tabWidget->currentWidget())) {
  153. plcDoc->pasteItem(); // 添加 PLC 文档支持
  154. }
  155. });
  156. QAction *deleteAction = new QAction("删除(&D)", this);
  157. deleteAction->setShortcut(QKeySequence::Delete);
  158. deleteAction->setStatusTip("删除选中的项目");
  159. deleteAction->setFont(itemFont);
  160. connect(deleteAction, &QAction::triggered, this, [this]() {
  161. if (auto hmiDoc = dynamic_cast<HMIDocument*>(m_tabWidget->currentWidget())) {
  162. hmiDoc->deleteSelectedItems();
  163. } else if (auto plcDoc = dynamic_cast<PLCDocument*>(m_tabWidget->currentWidget())) {
  164. plcDoc->deleteSelectedItems(); // 添加 PLC 文档支持
  165. }
  166. });
  167. // 添加到操作菜单
  168. editMenu->addAction(copyAction);
  169. editMenu->addAction(pasteAction);
  170. editMenu->addAction(deleteAction);
  171. }
  172. // 创建左侧工具栏
  173. void MainWindow::createToolbars()
  174. {
  175. m_leftToolBar = new QToolBar("绘图工具栏", this);
  176. addToolBar(Qt::LeftToolBarArea, m_leftToolBar);
  177. m_leftToolBar->setAllowedAreas(Qt::LeftToolBarArea); // 仅允许在左侧
  178. m_leftToolBar->setFixedWidth(230);
  179. }
  180. // 更新工具栏(根据当前文档类型)
  181. void MainWindow::updateToolBar(BaseDocument *doc)
  182. {
  183. m_leftToolBar->clear();// 清空现有工具
  184. if (!doc) return;
  185. if (doc->type() == BaseDocument::HMI)// HMI文档显示绘图工具
  186. {
  187. HMIDocument *hmiDoc = dynamic_cast<HMIDocument*>(doc);
  188. if (!hmiDoc) return;
  189. // 画指示灯按钮(支持拖拽)
  190. QToolButton *ellipseBtn = new QToolButton;
  191. ellipseBtn->setText("指示灯");
  192. ellipseBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  193. ellipseBtn->setIcon(QIcon("../two/untitled/images/灯泡.png"));//可替换为实际图标
  194. ellipseBtn->installEventFilter(this);//为按钮安装事件过滤器处理拖拽
  195. ellipseBtn->setProperty("toolType", "指示灯");
  196. m_leftToolBar->addWidget(ellipseBtn);
  197. ellipseBtn->setStyleSheet(R"(
  198. QToolButton {
  199. margin: 2 auto;
  200. background-color: #f0f0f0;
  201. border-radius: 10px;
  202. border: 1px solid #ccc;
  203. padding: 10px 15px;
  204. font-size: 25px;
  205. font-weight: bold;
  206. color: #333;
  207. }
  208. QToolButton:hover {
  209. background-color: #e0e0e0;
  210. }
  211. )");
  212. // 画按钮按钮(支持拖拽)
  213. QToolButton *rectBtn = new QToolButton;
  214. rectBtn->setText("按钮");
  215. rectBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  216. rectBtn->setIcon(QIcon("../two/untitled/images/按钮.png"));//可替换为实际图标
  217. rectBtn->installEventFilter(this);
  218. rectBtn->setProperty("toolType", "按钮");
  219. m_leftToolBar->addWidget(rectBtn);
  220. rectBtn->setStyleSheet(R"(
  221. QToolButton {
  222. margin: 2 auto;
  223. background-color: #f0f0f0;
  224. border-radius: 10px;
  225. border: 1px solid #ccc;
  226. padding: 10px 28px;
  227. font-size: 25px;
  228. font-weight: bold;
  229. color: #333;
  230. }
  231. QToolButton:hover {
  232. background-color: #e0e0e0;
  233. }
  234. )");
  235. }
  236. // PLC按钮工具
  237. else if (doc->type() == BaseDocument::PLC)
  238. {
  239. // 常开触点按钮
  240. QToolButton *normallyOpenBtn = new QToolButton;
  241. normallyOpenBtn->setText("常开");
  242. normallyOpenBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  243. normallyOpenBtn->setIcon(QIcon("../two/untitled/images/T-常开触点-01.png")); // 替换为实际图标
  244. normallyOpenBtn->installEventFilter(this);
  245. normallyOpenBtn->setProperty("toolType", "常开");
  246. m_leftToolBar->addWidget(normallyOpenBtn);
  247. normallyOpenBtn->setStyleSheet(R"(
  248. QToolButton {
  249. margin: 2 auto;
  250. background-color: #f0f0f0;
  251. border-radius: 10px;
  252. border: 1px solid #ccc;
  253. padding: 10px 28px;
  254. font-size: 25px;
  255. font-weight: bold;
  256. color: #333;
  257. }
  258. QToolButton:hover {
  259. background-color: #e0e0e0;
  260. }
  261. )");
  262. // 常闭触点按钮
  263. QToolButton *normallyClosedBtn = new QToolButton;
  264. normallyClosedBtn->setText("常闭");
  265. normallyClosedBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  266. normallyClosedBtn->setIcon(QIcon("../two/untitled/images/T-常闭触点-01-01.png")); // 替换为实际图标
  267. normallyClosedBtn->installEventFilter(this);
  268. normallyClosedBtn->setProperty("toolType", "常闭");
  269. m_leftToolBar->addWidget(normallyClosedBtn);
  270. normallyClosedBtn->setStyleSheet(R"(
  271. QToolButton {
  272. margin: 2 auto;
  273. background-color: #f0f0f0;
  274. border-radius: 10px;
  275. border: 1px solid #ccc;
  276. padding: 10px 28px;
  277. font-size: 25px;
  278. font-weight: bold;
  279. color: #333;
  280. }
  281. QToolButton:hover {
  282. background-color: #e0e0e0;
  283. }
  284. )");
  285. // 大于按钮
  286. QToolButton *greaterThanBtn = new QToolButton;
  287. greaterThanBtn->setText("大于");
  288. greaterThanBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  289. greaterThanBtn->setIcon(QIcon("../two/untitled/images/大于号.png")); // 替换为实际图标
  290. greaterThanBtn->installEventFilter(this);
  291. greaterThanBtn->setProperty("toolType", "大于");
  292. m_leftToolBar->addWidget(greaterThanBtn);
  293. greaterThanBtn->setStyleSheet(R"(
  294. QToolButton {
  295. margin: 2 auto;
  296. background-color: #f0f0f0;
  297. border-radius: 10px;
  298. border: 1px solid #ccc;
  299. padding: 10px 28px;
  300. font-size: 25px;
  301. font-weight: bold;
  302. color: #333;
  303. }
  304. QToolButton:hover {
  305. background-color: #e0e0e0;
  306. }
  307. )");
  308. // 大于等于按钮
  309. QToolButton *greaterThanEqualBtn = new QToolButton;
  310. greaterThanEqualBtn->setText("大于等于");
  311. greaterThanEqualBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  312. greaterThanEqualBtn->setIcon(QIcon("../two/untitled/images/大于等于.png")); // 替换为实际图标
  313. greaterThanEqualBtn->installEventFilter(this);
  314. greaterThanEqualBtn->setProperty("toolType", "大于等于");
  315. m_leftToolBar->addWidget(greaterThanEqualBtn);
  316. greaterThanEqualBtn->setStyleSheet(R"(
  317. QToolButton {
  318. margin: 2 auto;
  319. background-color: #f0f0f0;
  320. border-radius: 10px;
  321. border: 1px solid #ccc;
  322. padding: 10px 2px;
  323. font-size: 25px;
  324. font-weight: bold;
  325. color: #333;
  326. }
  327. QToolButton:hover {
  328. background-color: #e0e0e0;
  329. }
  330. )");
  331. // 小于按钮
  332. QToolButton *lessThanBtn = new QToolButton;
  333. lessThanBtn->setText("小于");
  334. lessThanBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  335. lessThanBtn->setIcon(QIcon("../two/untitled/images/小于号.png")); // 替换为实际图标
  336. lessThanBtn->installEventFilter(this);
  337. lessThanBtn->setProperty("toolType", "小于");
  338. m_leftToolBar->addWidget(lessThanBtn);
  339. lessThanBtn->setStyleSheet(R"(
  340. QToolButton {
  341. margin: 2 auto;
  342. background-color: #f0f0f0;
  343. border-radius: 10px;
  344. border: 1px solid #ccc;
  345. padding: 10px 28px;
  346. font-size: 25px;
  347. font-weight: bold;
  348. color: #333;
  349. }
  350. QToolButton:hover {
  351. background-color: #e0e0e0;
  352. }
  353. )");
  354. // 小于等于按钮
  355. QToolButton *lessThanEqualBtn = new QToolButton;
  356. lessThanEqualBtn->setText("小于等于");
  357. lessThanEqualBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  358. lessThanEqualBtn->setIcon(QIcon("../two/untitled/images/小于等于.png")); // 替换为实际图标
  359. lessThanEqualBtn->installEventFilter(this);
  360. lessThanEqualBtn->setProperty("toolType", "小于等于");
  361. m_leftToolBar->addWidget(lessThanEqualBtn);
  362. lessThanEqualBtn->setStyleSheet(R"(
  363. QToolButton {
  364. margin: 2 auto;
  365. background-color: #f0f0f0;
  366. border-radius: 10px;
  367. border: 1px solid #ccc;
  368. padding: 10px 2px;
  369. font-size: 25px;
  370. font-weight: bold;
  371. color: #333;
  372. }
  373. QToolButton:hover {
  374. background-color: #e0e0e0;
  375. }
  376. )");
  377. // 等于按钮
  378. QToolButton *equalBtn = new QToolButton;
  379. equalBtn->setText("等于");
  380. equalBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  381. equalBtn->setIcon(QIcon("../two/untitled/images/等于.png")); // 替换为实际图标
  382. equalBtn->installEventFilter(this);
  383. equalBtn->setProperty("toolType", "等于");
  384. m_leftToolBar->addWidget(equalBtn);
  385. equalBtn->setStyleSheet(R"(
  386. QToolButton {
  387. margin: 2 auto;
  388. background-color: #f0f0f0;
  389. border-radius: 10px;
  390. border: 1px solid #ccc;
  391. padding: 10px 28px;
  392. font-size: 25px;
  393. font-weight: bold;
  394. color: #333;
  395. }
  396. QToolButton:hover {
  397. background-color: #e0e0e0;
  398. }
  399. )");
  400. // 线圈按钮
  401. QToolButton *coilBtn = new QToolButton;
  402. coilBtn->setText("线圈");
  403. coilBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  404. coilBtn->setIcon(QIcon("../two/untitled/images/添加线圈.png")); // 替换为实际图标
  405. coilBtn->installEventFilter(this);
  406. coilBtn->setProperty("toolType", "线圈");
  407. m_leftToolBar->addWidget(coilBtn);
  408. coilBtn->setStyleSheet(R"(
  409. QToolButton {
  410. margin: 2 auto;
  411. background-color: #f0f0f0;
  412. border-radius: 10px;
  413. border: 1px solid #ccc;
  414. padding: 10px 28px;
  415. font-size: 25px;
  416. font-weight: bold;
  417. color: #333;
  418. }
  419. QToolButton:hover {
  420. background-color: #e0e0e0;
  421. }
  422. )");
  423. normallyOpenBtn->installEventFilter(this);
  424. normallyClosedBtn->installEventFilter(this);
  425. greaterThanBtn->installEventFilter(this);
  426. greaterThanEqualBtn->installEventFilter(this);
  427. lessThanBtn->installEventFilter(this);
  428. lessThanEqualBtn->installEventFilter(this);
  429. equalBtn->installEventFilter(this);
  430. coilBtn->installEventFilter(this);
  431. }
  432. }
  433. // 事件过滤器处理拖拽
  434. bool MainWindow::eventFilter(QObject *obj, QEvent *event)
  435. {
  436. QToolButton *toolBtn = qobject_cast<QToolButton*>(obj);
  437. if (toolBtn && event->type() == QEvent::MouseButtonPress)
  438. {
  439. QMouseEvent *me = static_cast<QMouseEvent*>(event);
  440. if (me->button() == Qt::LeftButton)
  441. {
  442. QString toolType = toolBtn->property("toolType").toString();
  443. if (!toolType.isEmpty())
  444. {
  445. BaseDocument* currentDoc = dynamic_cast<BaseDocument*>(m_tabWidget->currentWidget());
  446. if (currentDoc && currentDoc->type() == BaseDocument::PLC)//PLC文档处理
  447. {
  448. PLCDocument* plcDoc = static_cast<PLCDocument*>(currentDoc);
  449. // 设置当前工具
  450. plcDoc->setCurrentTool(toolType);
  451. // 创建拖拽对象
  452. QMimeData *mime = new QMimeData;
  453. mime->setText(toolType);
  454. QDrag *drag = new QDrag(toolBtn);
  455. drag->setMimeData(mime);
  456. drag->exec(Qt::CopyAction);
  457. return true;
  458. }
  459. // HMI文档处理(原有代码)
  460. if (currentDoc && currentDoc->type() == BaseDocument::HMI)
  461. {
  462. HMIDocument* hmiDoc = static_cast<HMIDocument*>(currentDoc);
  463. if (toolType == "指示灯")
  464. {
  465. hmiDoc->startDrawingEllipse();//点击生成标志
  466. }
  467. else if (toolType == "按钮")
  468. {
  469. hmiDoc->startDrawingRectangle();//点击生成标志
  470. }
  471. // 新增拖拽逻辑(与PLC一致)
  472. QMimeData *mime = new QMimeData;
  473. mime->setText(toolType);//传递工具类型("指示灯"或"按钮")
  474. QDrag *drag = new QDrag(toolBtn);
  475. drag->setMimeData(mime);
  476. drag->exec(Qt::CopyAction);//启动拖拽
  477. return true;
  478. }
  479. }
  480. }
  481. }
  482. return QMainWindow::eventFilter(obj, event);
  483. }
  484. // 新建HMI文档
  485. void MainWindow::onNewHMI()
  486. {
  487. m_hmiCount++;
  488. HMIDocument *doc = new HMIDocument;
  489. doc->setTitle("HMI文档 " + QString::number(m_hmiCount));
  490. m_tabWidget->addTab(doc, doc->title());
  491. m_tabWidget->setCurrentWidget(doc);
  492. updateToolBar(doc); // 更新工具栏为HMI工具
  493. }
  494. // 新建PLC文档
  495. void MainWindow::onNewPLC()
  496. {
  497. m_plcCount++;
  498. PLCDocument *doc = new PLCDocument;
  499. m_tabWidget->addTab(doc, QString("PLC文档 %1").arg(m_plcCount));
  500. m_tabWidget->setCurrentWidget(doc);
  501. updateToolBar(doc); // 更新工具栏为PLC工具
  502. }
  503. // 标签页切换时更新工具栏
  504. void MainWindow::onTabChanged(int idx)
  505. {
  506. if (idx < 0)
  507. {
  508. updateToolBar(nullptr);
  509. return;
  510. }
  511. BaseDocument *doc = dynamic_cast<BaseDocument*>(m_tabWidget->widget(idx));
  512. updateToolBar(doc);
  513. }
  514. // 保存文档
  515. void MainWindow::onSave()
  516. {
  517. BaseDocument *doc = dynamic_cast<BaseDocument*>(m_tabWidget->currentWidget());
  518. if (!doc) return;
  519. if (doc->filePath().isEmpty()) {
  520. saveDocumentAs(doc);
  521. } else {
  522. saveDocument(doc);
  523. }
  524. }
  525. // 另存为文档
  526. void MainWindow::onSaveAs()
  527. {
  528. BaseDocument *doc = dynamic_cast<BaseDocument*>(m_tabWidget->currentWidget());
  529. if (doc) {
  530. saveDocumentAs(doc);
  531. }
  532. }
  533. // 打开文档
  534. void MainWindow::onOpen()
  535. {
  536. QString filePath = QFileDialog::getOpenFileName(
  537. this,
  538. "打开文档",
  539. "",
  540. "HMI文档 (*.hmi);;PLC文档 (*.plc)"
  541. );
  542. if (filePath.isEmpty()) return;
  543. QFileInfo fileInfo(filePath);
  544. BaseDocument *doc = nullptr;
  545. if (fileInfo.suffix().toLower() == "hmi") {
  546. doc = new HMIDocument;
  547. } else if (fileInfo.suffix().toLower() == "plc") {
  548. doc = new PLCDocument;
  549. } else {
  550. QMessageBox::warning(this, "打开文档", "不支持的文件格式");
  551. return;
  552. }
  553. if (doc->loadFromFile(filePath)) {
  554. m_tabWidget->addTab(doc, doc->title());
  555. m_tabWidget->setCurrentWidget(doc);
  556. updateToolBar(doc);
  557. } else {
  558. QMessageBox::critical(this, "打开文档", "无法加载文档");
  559. delete doc;
  560. }
  561. }
  562. // 关闭标签页
  563. void MainWindow::onCloseTab(int index)
  564. {
  565. BaseDocument *doc = dynamic_cast<BaseDocument*>(m_tabWidget->widget(index));
  566. if (!doc) return;
  567. if (doc->isModified())
  568. {
  569. QMessageBox::StandardButton reply = QMessageBox::question(
  570. this,
  571. "保存文档",
  572. QString("文档 '%1' 已修改,是否保存更改?").arg(doc->title()),
  573. QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel
  574. );
  575. if (reply == QMessageBox::Save) {
  576. saveDocument(doc);
  577. } else if (reply == QMessageBox::Cancel) {
  578. return;
  579. }
  580. }
  581. m_tabWidget->removeTab(index);
  582. delete doc;
  583. }
  584. // 保存文档
  585. void MainWindow::saveDocument(BaseDocument *doc)
  586. {
  587. // 如果文件路径为空(新文件),执行“另存为”
  588. if (doc->filePath().isEmpty())
  589. {
  590. // 直接调用另存为函数
  591. saveDocumentAs(doc);
  592. }
  593. else
  594. {
  595. // 如果已有文件路径,直接保存
  596. if (doc->saveToFile(doc->filePath()))
  597. {
  598. doc->setModified(false); // 清除修改状态
  599. QMessageBox::information(this, "保存文档", "文档保存成功");
  600. }
  601. else
  602. {
  603. QMessageBox::critical(this, "保存文档", "无法保存文档");
  604. }
  605. }
  606. }
  607. // 另存为文档
  608. void MainWindow::saveDocumentAs(BaseDocument *doc)
  609. {
  610. QString filePath = QFileDialog::getSaveFileName(
  611. this,
  612. "保存为",
  613. doc->filePath().isEmpty() ? doc->title() : doc->filePath(),
  614. doc->type() == BaseDocument::HMI ?"HMI文档 (*.hmi)" :"PLC文档 (*.plc)"
  615. );
  616. if (filePath.isEmpty()) return;
  617. if (doc->saveToFile(filePath))
  618. {
  619. doc->setModified(false); // 清除修改状态
  620. QMessageBox::information(this, "保存文档", "文档保存成功");
  621. }
  622. else
  623. {
  624. QMessageBox::critical(this, "保存文档", "无法保存文档");
  625. }
  626. }