25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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