综合平台编辑器
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.

700 lines
24 KiB

  1. #include "hmimodule.h"
  2. #include <QGraphicsScene>
  3. #include <QGraphicsView>
  4. #include <QDateTime>
  5. #include <QTabWidget>
  6. #include <QMessageBox>
  7. #include <QVBoxLayout>
  8. #include <algorithm>
  9. #include <QColorDialog>
  10. #include <QFile>
  11. #include <QJsonDocument>
  12. #include <QJsonArray>
  13. #include <QJsonObject>
  14. #include <QDebug>
  15. HMIModule::HMIModule(Ui::MainWindow* ui, QObject *parent)
  16. : QObject{parent}, ui_(ui), m_scene(nullptr)
  17. {
  18. // 初始化 m_pageOrder
  19. m_pageOrder.append(1); // 初始页面
  20. }
  21. void HMIModule::setButtonIcon(QAbstractButton *button, const QString &iconPath)
  22. {
  23. button->setIcon(QIcon(iconPath));
  24. button->setIconSize(QSize(30, 30));
  25. }
  26. void HMIModule::init() {
  27. setButtonIcon(ui_->button, ":/resource/image/button.png");
  28. setButtonIcon(ui_->lamp, ":/resource/image/lamp.png");
  29. setButtonIcon(ui_->addPage, ":/resource/image/add.png");
  30. setButtonIcon(ui_->deletePage, ":/resource/image/delete.png");
  31. setButtonIcon(ui_->prePage, ":/resource/image/pre.png");
  32. setButtonIcon(ui_->nextPage, ":/resource/image/next.png");
  33. if (!ui_->hmiGraphicsView->scene()) {
  34. m_scene = new CustomGraphicsScene(ui_->hmiGraphicsView, this);
  35. m_scene->setSceneRect(0, 0, 800, 600);
  36. ui_->hmiGraphicsView->setScene(m_scene);
  37. } else {
  38. m_scene = qobject_cast<CustomGraphicsScene*>(ui_->hmiGraphicsView->scene());
  39. Q_ASSERT(m_scene);
  40. }
  41. connect(ui_->button, &QPushButton::clicked, this, &HMIModule::prepareToCreateButton);
  42. connect(ui_->lamp, &QPushButton::clicked, this, &HMIModule::prepareToCreateIndicator);
  43. connect(m_scene, &CustomGraphicsScene::componentCreated, this, &HMIModule::onComponentCreated);
  44. connect(m_scene, &CustomGraphicsScene::copyRequestFromScene, this, &HMIModule::onCopyRequested);
  45. connect(m_scene, &CustomGraphicsScene::pasteRequestFromScene, this, &HMIModule::onPasteRequested);
  46. connect(m_scene, &CustomGraphicsScene::deleteRequestFromScene, this, &HMIModule::onDeleteRequested);
  47. // 连接新增的槽函数
  48. connect(ui_->addPage, &QPushButton::clicked, this, &HMIModule::addPage);
  49. connect(ui_->deletePage, &QPushButton::clicked, this, &HMIModule::deletePage);
  50. connect(ui_->prePage, &QPushButton::clicked, this, &HMIModule::prePage);
  51. connect(ui_->nextPage, &QPushButton::clicked, this, &HMIModule::nextPage);
  52. // 连接信号和槽
  53. connect(this, &HMIModule::pageAdded, this, &HMIModule::onPageAdded);
  54. connect(this, &HMIModule::pageRemoved, this, &HMIModule::onPageRemoved);
  55. }
  56. bool HMIModule::saveToFile(const QString& filePath)
  57. {
  58. QTabWidget* tabWidget = ui_->tabWidget_2;
  59. QJsonArray pagesArray;
  60. for (int i = 0; i < tabWidget->count(); ++i) {
  61. QWidget* page = tabWidget->widget(i);
  62. QString pageName = tabWidget->tabText(i);
  63. QGraphicsView* graphicsView = page->findChild<QGraphicsView*>();
  64. if (!graphicsView) continue;
  65. QGraphicsScene* scene = graphicsView->scene();
  66. if (!scene) continue;
  67. QJsonObject pageObject;
  68. pageObject["pageName"] = pageName;
  69. QJsonArray componentsArray;
  70. for (QGraphicsItem* item : scene->items()) {
  71. HmiComponent* component = dynamic_cast<HmiComponent*>(item);
  72. if (!component)
  73. continue;
  74. QJsonObject compObj;
  75. // 组件类型
  76. if (dynamic_cast<HmiButton*>(component)) {
  77. compObj["type"] = "Button";
  78. } else if (dynamic_cast<HmiIndicator*>(component)) {
  79. compObj["type"] = "Indicator";
  80. } else {
  81. continue; // 忽略未知类型
  82. }
  83. // 位置
  84. QPointF pos = component->pos();
  85. compObj["x"] = pos.x();
  86. compObj["y"] = pos.y();
  87. // 颜色 (保存在HEX)
  88. compObj["color"] = component->color().name();
  89. // On / Off颜色
  90. compObj["onColor"] = component->onColor().name();
  91. compObj["offColor"] = component->offColor().name();
  92. // 组件名称
  93. compObj["componentName"] = component->componentName();
  94. // 新增地址属性
  95. compObj["address"] = component->address();
  96. // 添加按钮状态
  97. compObj["isOn"] = false; // 默认false
  98. if (auto btn = dynamic_cast<HmiButton*>(component)) {
  99. compObj["isOn"] = btn->isOn();
  100. }
  101. componentsArray.append(compObj);
  102. }
  103. pageObject["components"] = componentsArray;
  104. pagesArray.append(pageObject);
  105. }
  106. QJsonObject rootObject;
  107. rootObject["pages"] = pagesArray;
  108. QJsonDocument doc(rootObject);
  109. QFile file(filePath);
  110. if (!file.open(QIODevice::WriteOnly)) {
  111. emit logMessageGenerated(QString("无法打开文件进行保存: %1").arg(filePath));
  112. return false;
  113. }
  114. file.write(doc.toJson(QJsonDocument::Indented));
  115. file.close();
  116. emit logMessageGenerated(QString("[%1] 保存成功: %2")
  117. .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
  118. .arg(filePath));
  119. m_isModified = false;
  120. setModified(false);
  121. return true;
  122. }
  123. // 清空所有页面,重建页面并加载组件
  124. bool HMIModule::openFromFile(const QString& filePath)
  125. {
  126. QFile file(filePath);
  127. if (!file.open(QIODevice::ReadOnly)) {
  128. emit logMessageGenerated(QString("无法打开文件进行加载: %1").arg(filePath));
  129. return false;
  130. }
  131. QByteArray data = file.readAll();
  132. file.close();
  133. QJsonParseError parseError;
  134. QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
  135. if (parseError.error != QJsonParseError::NoError) {
  136. emit logMessageGenerated(QString("JSON解析错误: %1").arg(parseError.errorString()));
  137. return false;
  138. }
  139. if (!doc.isObject()) {
  140. emit logMessageGenerated("JSON格式错误,不是对象");
  141. return false;
  142. }
  143. QJsonObject rootObj = doc.object();
  144. if (!rootObj.contains("pages") || !rootObj["pages"].isArray()) {
  145. emit logMessageGenerated("JSON缺少pages数组");
  146. return false;
  147. }
  148. QJsonArray pagesArray = rootObj["pages"].toArray();
  149. QTabWidget* tabWidget = ui_->tabWidget_2;
  150. // 清空所有现有页面
  151. while (tabWidget->count() > 0) {
  152. QWidget* page = tabWidget->widget(0);
  153. tabWidget->removeTab(0);
  154. delete page;
  155. }
  156. m_availablePageNumbers.clear();
  157. m_pageOrder.clear();
  158. for (const QJsonValue& pageVal : pagesArray) {
  159. if (!pageVal.isObject())
  160. continue;
  161. QJsonObject pageObj = pageVal.toObject();
  162. QString pageName = pageObj["pageName"].toString("Unnamed");
  163. int pageNumber = 0;
  164. if (pageName.startsWith("Page ")) {
  165. pageNumber = pageName.mid(5).toInt();
  166. }
  167. // 新建页面
  168. QWidget* newPage = new QWidget(tabWidget);
  169. newPage->setObjectName(pageName);
  170. QGraphicsView* newGraphicsView = new QGraphicsView(newPage);
  171. CustomGraphicsScene* newScene = new CustomGraphicsScene(newGraphicsView, this);
  172. // 设置大小,与默认页面相同
  173. QSize defaultSize(691, 381);
  174. newGraphicsView->resize(defaultSize);
  175. newScene->setSceneRect(0, 0, 800, 600);
  176. newGraphicsView->setScene(newScene);
  177. QVBoxLayout* layout = new QVBoxLayout(newPage);
  178. layout->addWidget(newGraphicsView);
  179. newPage->setLayout(layout);
  180. int tabIndex = tabWidget->addTab(newPage, pageName);
  181. // 连接信号
  182. connect(newScene, &CustomGraphicsScene::componentCreated, this, &HMIModule::onComponentCreated);
  183. connect(newScene, &CustomGraphicsScene::copyRequestFromScene, this, &HMIModule::onCopyRequested);
  184. connect(newScene, &CustomGraphicsScene::pasteRequestFromScene, this, &HMIModule::onPasteRequested);
  185. connect(newScene, &CustomGraphicsScene::deleteRequestFromScene, this, &HMIModule::onDeleteRequested);
  186. m_pageOrder.append(pageNumber);
  187. QJsonArray compArray = pageObj["components"].toArray();
  188. for (const QJsonValue& compVal : compArray) {
  189. if (!compVal.isObject())
  190. continue;
  191. QJsonObject compObj = compVal.toObject();
  192. QString typeStr = compObj["type"].toString();
  193. double x = compObj["x"].toDouble();
  194. double y = compObj["y"].toDouble();
  195. QString colorName = compObj["color"].toString();
  196. QString onColorName = compObj["onColor"].toString();
  197. QString offColorName = compObj["offColor"].toString();
  198. QString componentName = compObj["componentName"].toString();
  199. int address = compObj["address"].toInt(0);
  200. HmiComponent* newItem = nullptr;
  201. if (typeStr == "Button") {
  202. newItem = new HmiButton();
  203. } else if (typeStr == "Indicator") {
  204. newItem = new HmiIndicator();
  205. } else {
  206. continue;
  207. }
  208. if (newItem) {
  209. newItem->setPos(QPointF(x, y));
  210. QColor color(colorName);
  211. if (color.isValid()) {
  212. newItem->setColor(color);
  213. }
  214. QColor onColor(onColorName);
  215. if (onColor.isValid())
  216. newItem->setOnColor(onColor);
  217. QColor offColor(offColorName);
  218. if (offColor.isValid())
  219. newItem->setOffColor(offColor);
  220. // 恢复 isOn 状态
  221. bool isOn = false;
  222. if (compObj.contains("isOn")) {
  223. isOn = compObj["isOn"].toBool();
  224. }
  225. if (auto btn = dynamic_cast<HmiButton*>(newItem)) {
  226. btn->setOn(isOn);
  227. }
  228. QColor currentColor(colorName);
  229. if (currentColor.isValid()) {
  230. // 根据实际业务逻辑判断,是否恢复为onColor或offColor,这里直接恢复当前颜色
  231. newItem->setColor(currentColor);
  232. } else {
  233. // 如果当前颜色无效,则使用 offColor 作为默认颜色
  234. newItem->setColor(newItem->offColor());
  235. }
  236. newItem->setComponentName(componentName);
  237. // 设置地址
  238. newItem->setAddress(address);
  239. newScene->addItem(newItem);
  240. setupNewComponent(newItem);
  241. }
  242. }
  243. }
  244. // 自动切换到第一页
  245. if (tabWidget->count() > 0) {
  246. tabWidget->setCurrentIndex(0);
  247. }
  248. emit logMessageGenerated(QString("[%1] 打开文件成功: %2")
  249. .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
  250. .arg(filePath));
  251. setModified(false);
  252. return true;
  253. }
  254. void HMIModule::resetPages()
  255. {
  256. QTabWidget* tabWidget = ui_->tabWidget_2;
  257. if (tabWidget->count() == 0) {
  258. // 没有页面,创建第一页
  259. m_pageCount = 1;
  260. m_availablePageNumbers.clear();
  261. m_pageOrder.clear();
  262. QWidget* newPage = new QWidget(tabWidget);
  263. QString pageName = QString("Page 1");
  264. newPage->setObjectName(pageName);
  265. QGraphicsView* newGraphicsView = new QGraphicsView(newPage);
  266. CustomGraphicsScene* newScene = new CustomGraphicsScene(newGraphicsView, this);
  267. QSize defaultSize(691, 381);
  268. newGraphicsView->resize(defaultSize);
  269. newScene->setSceneRect(0, 0, 800, 600);
  270. newGraphicsView->setScene(newScene);
  271. QVBoxLayout* layout = new QVBoxLayout(newPage);
  272. layout->addWidget(newGraphicsView);
  273. newPage->setLayout(layout);
  274. tabWidget->addTab(newPage, pageName);
  275. m_pageOrder.append(1);
  276. connect(newScene, &CustomGraphicsScene::componentCreated, this, &HMIModule::onComponentCreated);
  277. connect(newScene, &CustomGraphicsScene::copyRequestFromScene, this, &HMIModule::onCopyRequested);
  278. connect(newScene, &CustomGraphicsScene::pasteRequestFromScene, this, &HMIModule::onPasteRequested);
  279. connect(newScene, &CustomGraphicsScene::deleteRequestFromScene, this, &HMIModule::onDeleteRequested);
  280. return;
  281. }
  282. // 有页面时:
  283. // 删除除第一页以外的所有页面
  284. while (tabWidget->count() > 1) {
  285. QWidget* page = tabWidget->widget(1);
  286. tabWidget->removeTab(1);
  287. delete page;
  288. }
  289. // 清空第一页场景
  290. QWidget* firstPage = tabWidget->widget(0);
  291. QGraphicsView* view = firstPage->findChild<QGraphicsView*>();
  292. if (view && view->scene()) {
  293. view->scene()->clear();
  294. }
  295. // 重置页面编号管理
  296. m_availablePageNumbers.clear();
  297. m_pageOrder.clear();
  298. m_pageCount = 1;
  299. m_pageOrder.append(1);
  300. // 可以选择更新第一页Tab名称(如果可能被改名)
  301. tabWidget->setTabText(0, "Page 1");
  302. firstPage->setObjectName("Page 1");
  303. }
  304. bool HMIModule::isModified() const
  305. {
  306. return m_isModified;
  307. }
  308. void HMIModule::setModified(bool modified)
  309. {
  310. m_isModified = modified;
  311. }
  312. void HMIModule::setupNewComponent(HmiComponent* item)
  313. {
  314. if (!item) return;
  315. connect(item, &HmiComponent::selected, this, &HMIModule::onComponentSelected);
  316. connect(item, &HmiComponent::copyRequested, this, &HMIModule::onCopyRequested);
  317. connect(item, &HmiComponent::deleteRequested, this, &HMIModule::onDeleteRequested);
  318. connect(item, &HmiComponent::changeOnColorRequested, this, &HMIModule::onChangeOnColorRequested);
  319. connect(item, &HmiComponent::changeOffColorRequested, this, &HMIModule::onChangeOffColorRequested);
  320. QString currentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
  321. QString log = QString("[%1] 创建 %2 组件").arg(currentTime).arg(item->componentName());
  322. emit logMessageGenerated(log);
  323. }
  324. void HMIModule::prepareToCreateButton()
  325. {
  326. // 获取当前 TabWidget 中选中的 GraphicsView
  327. QTabWidget* tabWidget = ui_->tabWidget_2;
  328. QWidget* currentPage = tabWidget->currentWidget();
  329. QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
  330. CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
  331. if (currentScene) {
  332. currentScene->setComponentTypeToCreate(ComponentType::Button);
  333. currentScene->setMode(CustomGraphicsScene::Mode::CreateItem);
  334. }
  335. }
  336. void HMIModule::prepareToCreateIndicator()
  337. {
  338. // 获取当前 TabWidget 中选中的 GraphicsView
  339. QTabWidget* tabWidget = ui_->tabWidget_2;
  340. QWidget* currentPage = tabWidget->currentWidget();
  341. QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
  342. CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
  343. if (currentScene) {
  344. currentScene->setComponentTypeToCreate(ComponentType::Indicator);
  345. currentScene->setMode(CustomGraphicsScene::Mode::CreateItem);
  346. }
  347. }
  348. void HMIModule::onComponentCreated(HmiComponent* item)
  349. {
  350. setupNewComponent(item);
  351. setModified(true); // 标记已修改
  352. }
  353. void HMIModule::onCopyRequested()
  354. {
  355. // 获取当前 TabWidget 中选中的 GraphicsView
  356. QTabWidget* tabWidget = ui_->tabWidget_2;
  357. QWidget* currentPage = tabWidget->currentWidget();
  358. QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
  359. CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
  360. QList<QGraphicsItem*> selected = currentScene->selectedItems();
  361. if (selected.isEmpty()) return;
  362. HmiComponent* itemToCopy = qgraphicsitem_cast<HmiComponent*>(selected.first());
  363. if (!itemToCopy) return;
  364. if (dynamic_cast<HmiButton*>(itemToCopy)) {
  365. m_copiedType = ComponentType::Button;
  366. } else if (dynamic_cast<HmiIndicator*>(itemToCopy)) {
  367. m_copiedType = ComponentType::Indicator;
  368. }
  369. m_copiedColor = itemToCopy->color();
  370. // 新增复制以下属性
  371. m_copiedOnColor = itemToCopy->onColor();
  372. m_copiedOffColor = itemToCopy->offColor();
  373. m_copiedComponentName = itemToCopy->componentName();
  374. m_copiedAddress = itemToCopy->address();
  375. m_hasCopiedItem = true;
  376. emit logMessageGenerated(QString("[%1] 复制组件: %2")
  377. .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
  378. .arg(itemToCopy->componentName()));
  379. }
  380. void HMIModule::onPasteRequested(const QPointF& scenePos)
  381. {
  382. if (!m_hasCopiedItem) return;
  383. // 获取当前 TabWidget 中选中的 GraphicsView
  384. QTabWidget* tabWidget = ui_->tabWidget_2;
  385. QWidget* currentPage = tabWidget->currentWidget();
  386. QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
  387. CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
  388. HmiComponent* newItem = nullptr;
  389. if (m_copiedType == ComponentType::Button) {
  390. newItem = new HmiButton();
  391. } else {
  392. newItem = new HmiIndicator();
  393. }
  394. if (newItem) {
  395. newItem->setColor(m_copiedColor);
  396. newItem->setOnColor(m_copiedOnColor);
  397. newItem->setOffColor(m_copiedOffColor);
  398. newItem->setComponentName(m_copiedComponentName);
  399. newItem->setAddress(m_copiedAddress);
  400. newItem->setPos(scenePos);
  401. currentScene->addItem(newItem); // 使用当前页面的 scene
  402. setupNewComponent(newItem);
  403. }
  404. setModified(true); // 内容改变
  405. }
  406. void HMIModule::onDeleteRequested()
  407. {
  408. // 获取当前 TabWidget 中选中的 GraphicsView
  409. QTabWidget* tabWidget = ui_->tabWidget_2;
  410. QWidget* currentPage = tabWidget->currentWidget();
  411. QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
  412. CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
  413. QList<QGraphicsItem*> selected = currentScene->selectedItems();
  414. if (selected.isEmpty()) return;
  415. emit logMessageGenerated(QString("[%1] 删除 %2 个组件")
  416. .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
  417. .arg(selected.count()));
  418. for (int i = selected.count() - 1; i >= 0; --i) {
  419. QGraphicsItem* item = selected.at(i);
  420. currentScene->removeItem(item); // 使用当前页面的 scene
  421. delete item;
  422. }
  423. setModified(true); // 标记已修改
  424. }
  425. // 添加页面后的槽函数
  426. void HMIModule::onPageAdded(int pageNumber, int index)
  427. {
  428. if (index < m_pageOrder.size()) {
  429. m_pageOrder[index] = pageNumber;
  430. } else {
  431. m_pageOrder.append(pageNumber);
  432. }
  433. }
  434. // 删除页面后的槽函数
  435. void HMIModule::onPageRemoved(int pageNumber, int index)
  436. {
  437. if (index < m_pageOrder.size()) {
  438. m_pageOrder[index] = -1;
  439. }
  440. }
  441. void HMIModule::onChangeOnColorRequested(HmiComponent* item)
  442. {
  443. QColor color = QColorDialog::getColor(item->onColor(), nullptr, "选择 ON 状态颜色");
  444. if (color.isValid()) {
  445. item->setOnColor(color);
  446. emit logMessageGenerated(QString("[%1] 设置 %2 的 ON 状态颜色为 %3")
  447. .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
  448. .arg(item->componentName())
  449. .arg(color.name()));
  450. }
  451. }
  452. void HMIModule::onChangeOffColorRequested(HmiComponent* item)
  453. {
  454. QColor color = QColorDialog::getColor(item->offColor(), nullptr, "选择 OFF 状态颜色");
  455. if (color.isValid()) {
  456. item->setOffColor(color); // 同时更新当前显示颜色
  457. emit logMessageGenerated(QString("[%1] 设置 %2 的 OFF 状态颜色为 %3")
  458. .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
  459. .arg(item->componentName())
  460. .arg(color.name()));
  461. }
  462. }
  463. void HMIModule::onComponentSelected(HmiComponent* item)
  464. {
  465. // 不需要任何操作,可以留空
  466. }
  467. // 新增页面的槽函数
  468. void HMIModule::addPage()
  469. {
  470. QTabWidget* tabWidget = ui_->tabWidget_2;
  471. int pageNumber;
  472. int insertIndex = -1;
  473. int tabIndex; // 在此处声明 tabIndex
  474. // 检查是否有可用的页面编号
  475. if (!m_availablePageNumbers.isEmpty()) {
  476. pageNumber = m_availablePageNumbers.first();
  477. m_availablePageNumbers.removeFirst();
  478. // 查找可用的插入位置
  479. for (int i = 0; i < m_pageOrder.size(); ++i) {
  480. if (m_pageOrder[i] == -1) {
  481. insertIndex = i;
  482. break;
  483. }
  484. }
  485. } else {
  486. pageNumber = ++m_pageCount;
  487. }
  488. // 获取 Page 1 的 Scene
  489. CustomGraphicsScene* firstScene = m_scene;
  490. // 创建新的页面部件
  491. QWidget* newPage = new QWidget(tabWidget);
  492. QString pageName = QString("Page %1").arg(pageNumber);
  493. newPage->setObjectName(pageName);
  494. // 创建新的 GraphicsView 和 Scene
  495. QGraphicsView* newGraphicsView = new QGraphicsView(newPage);
  496. CustomGraphicsScene* newScene = new CustomGraphicsScene(newGraphicsView, this);
  497. // 设置 GraphicsView 的大小
  498. QSize newViewSize(691, 381); // 设置为指定的宽度和高度
  499. newGraphicsView->resize(newViewSize);
  500. // 设置 GraphicsScene 的大小与 Page 1 相同
  501. QRectF newSceneRect = firstScene->sceneRect();
  502. newScene->setSceneRect(newSceneRect);
  503. newGraphicsView->setScene(newScene);
  504. // 布局
  505. QVBoxLayout* layout = new QVBoxLayout(newPage);
  506. layout->addWidget(newGraphicsView);
  507. newPage->setLayout(layout);
  508. // 添加到 TabWidget
  509. if (insertIndex != -1) {
  510. tabIndex = insertIndex;
  511. tabWidget->insertTab(tabIndex, newPage, pageName);
  512. } else {
  513. tabIndex = tabWidget->addTab(newPage, pageName);
  514. }
  515. // 连接信号和槽
  516. connect(newScene, &CustomGraphicsScene::componentCreated, this, &HMIModule::onComponentCreated);
  517. connect(newScene, &CustomGraphicsScene::copyRequestFromScene, this, &HMIModule::onCopyRequested);
  518. connect(newScene, &CustomGraphicsScene::pasteRequestFromScene, this, &HMIModule::onPasteRequested);
  519. connect(newScene, &CustomGraphicsScene::deleteRequestFromScene, this, &HMIModule::onDeleteRequested);
  520. // 发送 pageAdded 信号
  521. emit pageAdded(pageNumber, tabIndex);
  522. tabWidget->setCurrentWidget(newPage);
  523. // 记录日志
  524. emit logMessageGenerated(QString("[%1] 添加页面: %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(pageName));
  525. setModified(true); // 页面变更,标记已修改
  526. }
  527. // 删除页面的槽函数
  528. void HMIModule::deletePage()
  529. {
  530. QTabWidget* tabWidget = ui_->tabWidget_2;
  531. int currentIndex = tabWidget->currentIndex();
  532. if (tabWidget->count() == 1) {
  533. QMessageBox::information(nullptr, "提示", "这是最后一页,不能删除!");
  534. return;
  535. }
  536. if (currentIndex >= 0) {
  537. // 获取要删除的页面
  538. QWidget* currentPage = tabWidget->widget(currentIndex);
  539. QString pageName = tabWidget->tabText(currentIndex);
  540. // 从页面名称中提取页面编号
  541. int pageNumber = pageName.remove("Page ").toInt();
  542. // 将删除的页面编号添加到可用列表中
  543. m_availablePageNumbers.append(pageNumber);
  544. std::sort(m_availablePageNumbers.begin(), m_availablePageNumbers.end());
  545. // 从 TabWidget 中移除页面
  546. tabWidget->removeTab(currentIndex);
  547. // 删除页面
  548. delete currentPage;
  549. // 发送 pageRemoved 信号
  550. emit pageRemoved(pageNumber, currentIndex);
  551. // 记录日志
  552. emit logMessageGenerated(QString("[%1] 删除页面: %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(pageName));
  553. }
  554. setModified(true); // 标记已修改
  555. }
  556. // 前一页的槽函数
  557. void HMIModule::prePage()
  558. {
  559. QTabWidget* tabWidget = ui_->tabWidget_2;
  560. int currentIndex = tabWidget->currentIndex();
  561. if (currentIndex > 0) {
  562. tabWidget->setCurrentIndex(currentIndex - 1);
  563. }
  564. }
  565. // 后一页的槽函数
  566. void HMIModule::nextPage()
  567. {
  568. QTabWidget* tabWidget = ui_->tabWidget_2;
  569. int currentIndex = tabWidget->currentIndex();
  570. if (currentIndex < tabWidget->count() - 1) {
  571. tabWidget->setCurrentIndex(currentIndex + 1);
  572. }
  573. }