You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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