综合平台编辑器
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

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