|
- #include "hmimodule.h"
- #include <QGraphicsScene>
- #include <QGraphicsView>
- #include <QDateTime>
- #include <QTabWidget>
- #include <QMessageBox>
- #include <QVBoxLayout>
- #include <algorithm>
- #include <QColorDialog>
- #include <QFile>
- #include <QJsonDocument>
- #include <QJsonArray>
- #include <QJsonObject>
- #include <QDebug>
-
- HMIModule::HMIModule(Ui::MainWindow* ui, QObject *parent)
- : QObject{parent}, ui_(ui), m_scene(nullptr)
- {
- // 初始化 m_pageOrder
- m_pageOrder.append(1); // 初始页面
- }
-
- void HMIModule::setButtonIcon(QAbstractButton *button, const QString &iconPath)
- {
- button->setIcon(QIcon(iconPath));
- button->setIconSize(QSize(30, 30));
- }
-
- void HMIModule::init() {
- setButtonIcon(ui_->button, ":/resource/image/button.png");
- setButtonIcon(ui_->lamp, ":/resource/image/lamp.png");
- setButtonIcon(ui_->addPage, ":/resource/image/add.png");
- setButtonIcon(ui_->deletePage, ":/resource/image/delete.png");
- setButtonIcon(ui_->prePage, ":/resource/image/pre.png");
- setButtonIcon(ui_->nextPage, ":/resource/image/next.png");
-
- if (!ui_->hmiGraphicsView->scene()) {
- m_scene = new CustomGraphicsScene(ui_->hmiGraphicsView, this);
- m_scene->setSceneRect(0, 0, 800, 600);
- ui_->hmiGraphicsView->setScene(m_scene);
- } else {
- m_scene = qobject_cast<CustomGraphicsScene*>(ui_->hmiGraphicsView->scene());
- Q_ASSERT(m_scene);
- }
-
- connect(ui_->button, &QPushButton::clicked, this, &HMIModule::prepareToCreateButton);
- connect(ui_->lamp, &QPushButton::clicked, this, &HMIModule::prepareToCreateIndicator);
- connect(m_scene, &CustomGraphicsScene::componentCreated, this, &HMIModule::onComponentCreated);
- connect(m_scene, &CustomGraphicsScene::copyRequestFromScene, this, &HMIModule::onCopyRequested);
- connect(m_scene, &CustomGraphicsScene::pasteRequestFromScene, this, &HMIModule::onPasteRequested);
- connect(m_scene, &CustomGraphicsScene::deleteRequestFromScene, this, &HMIModule::onDeleteRequested);
-
- // 连接新增的槽函数
- connect(ui_->addPage, &QPushButton::clicked, this, &HMIModule::addPage);
- connect(ui_->deletePage, &QPushButton::clicked, this, &HMIModule::deletePage);
- connect(ui_->prePage, &QPushButton::clicked, this, &HMIModule::prePage);
- connect(ui_->nextPage, &QPushButton::clicked, this, &HMIModule::nextPage);
-
- // 连接信号和槽
- connect(this, &HMIModule::pageAdded, this, &HMIModule::onPageAdded);
- connect(this, &HMIModule::pageRemoved, this, &HMIModule::onPageRemoved);
- }
-
- bool HMIModule::saveToFile(const QString& filePath)
- {
- QTabWidget* tabWidget = ui_->tabWidget_2;
-
- QJsonArray pagesArray;
-
- for (int i = 0; i < tabWidget->count(); ++i) {
- QWidget* page = tabWidget->widget(i);
- QString pageName = tabWidget->tabText(i);
-
- QGraphicsView* graphicsView = page->findChild<QGraphicsView*>();
- if (!graphicsView) continue;
-
- QGraphicsScene* scene = graphicsView->scene();
- if (!scene) continue;
-
- QJsonObject pageObject;
- pageObject["pageName"] = pageName;
-
- QJsonArray componentsArray;
-
- for (QGraphicsItem* item : scene->items()) {
- HmiComponent* component = dynamic_cast<HmiComponent*>(item);
- if (!component)
- continue;
-
- QJsonObject compObj;
- // 组件类型
- if (dynamic_cast<HmiButton*>(component)) {
- compObj["type"] = "Button";
- } else if (dynamic_cast<HmiIndicator*>(component)) {
- compObj["type"] = "Indicator";
- } else {
- continue; // 忽略未知类型
- }
-
- // 位置
- QPointF pos = component->pos();
- compObj["x"] = pos.x();
- compObj["y"] = pos.y();
-
- // 颜色 (保存在HEX)
- compObj["color"] = component->color().name();
- // On / Off颜色
- compObj["onColor"] = component->onColor().name();
- compObj["offColor"] = component->offColor().name();
- // 组件名称
- compObj["componentName"] = component->componentName();
- // 新增地址属性
- compObj["address"] = component->address();
-
- componentsArray.append(compObj);
- }
-
- pageObject["components"] = componentsArray;
- pagesArray.append(pageObject);
- }
-
- QJsonObject rootObject;
- rootObject["pages"] = pagesArray;
-
- QJsonDocument doc(rootObject);
-
- QFile file(filePath);
- if (!file.open(QIODevice::WriteOnly)) {
- emit logMessageGenerated(QString("无法打开文件进行保存: %1").arg(filePath));
- return false;
- }
-
- file.write(doc.toJson(QJsonDocument::Indented));
- file.close();
-
- emit logMessageGenerated(QString("[%1] 保存成功: %2")
- .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
- .arg(filePath));
- return true;
- }
-
- // 清空所有页面,重建页面并加载组件
- bool HMIModule::openFromFile(const QString& filePath)
- {
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- emit logMessageGenerated(QString("无法打开文件进行加载: %1").arg(filePath));
- return false;
- }
-
- QByteArray data = file.readAll();
- file.close();
-
- QJsonParseError parseError;
- QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
- if (parseError.error != QJsonParseError::NoError) {
- emit logMessageGenerated(QString("JSON解析错误: %1").arg(parseError.errorString()));
- return false;
- }
-
- if (!doc.isObject()) {
- emit logMessageGenerated("JSON格式错误,不是对象");
- return false;
- }
-
- QJsonObject rootObj = doc.object();
- if (!rootObj.contains("pages") || !rootObj["pages"].isArray()) {
- emit logMessageGenerated("JSON缺少pages数组");
- return false;
- }
-
- QJsonArray pagesArray = rootObj["pages"].toArray();
-
- QTabWidget* tabWidget = ui_->tabWidget_2;
-
- // 清空所有现有页面
- while (tabWidget->count() > 0) {
- QWidget* page = tabWidget->widget(0);
- tabWidget->removeTab(0);
- delete page;
- }
-
- m_availablePageNumbers.clear();
- m_pageOrder.clear();
-
- for (const QJsonValue& pageVal : pagesArray) {
- if (!pageVal.isObject())
- continue;
-
- QJsonObject pageObj = pageVal.toObject();
-
- QString pageName = pageObj["pageName"].toString("Unnamed");
- int pageNumber = 0;
- if (pageName.startsWith("Page ")) {
- pageNumber = pageName.mid(5).toInt();
- }
-
- // 新建页面
- QWidget* newPage = new QWidget(tabWidget);
- newPage->setObjectName(pageName);
-
- QGraphicsView* newGraphicsView = new QGraphicsView(newPage);
- CustomGraphicsScene* newScene = new CustomGraphicsScene(newGraphicsView, this);
-
- // 设置大小,与默认页面相同
- QSize defaultSize(691, 381);
- newGraphicsView->resize(defaultSize);
- newScene->setSceneRect(0, 0, 800, 600);
-
- newGraphicsView->setScene(newScene);
-
- QVBoxLayout* layout = new QVBoxLayout(newPage);
- layout->addWidget(newGraphicsView);
- newPage->setLayout(layout);
-
- int tabIndex = tabWidget->addTab(newPage, pageName);
-
- // 连接信号
- connect(newScene, &CustomGraphicsScene::componentCreated, this, &HMIModule::onComponentCreated);
- connect(newScene, &CustomGraphicsScene::copyRequestFromScene, this, &HMIModule::onCopyRequested);
- connect(newScene, &CustomGraphicsScene::pasteRequestFromScene, this, &HMIModule::onPasteRequested);
- connect(newScene, &CustomGraphicsScene::deleteRequestFromScene, this, &HMIModule::onDeleteRequested);
-
- m_pageOrder.append(pageNumber);
-
- QJsonArray compArray = pageObj["components"].toArray();
- for (const QJsonValue& compVal : compArray) {
- if (!compVal.isObject())
- continue;
-
- QJsonObject compObj = compVal.toObject();
-
- QString typeStr = compObj["type"].toString();
- double x = compObj["x"].toDouble();
- double y = compObj["y"].toDouble();
- QString colorName = compObj["color"].toString();
- QString onColorName = compObj["onColor"].toString();
- QString offColorName = compObj["offColor"].toString();
- QString componentName = compObj["componentName"].toString();
- int address = compObj["address"].toInt(0);
-
- HmiComponent* newItem = nullptr;
- if (typeStr == "Button") {
- newItem = new HmiButton();
- } else if (typeStr == "Indicator") {
- newItem = new HmiIndicator();
- } else {
- continue;
- }
-
- if (newItem) {
- newItem->setPos(QPointF(x, y));
- QColor color(colorName);
- if (color.isValid()) {
- newItem->setColor(color);
- }
- QColor onColor(onColorName);
- if (onColor.isValid())
- newItem->setOnColor(onColor);
- QColor offColor(offColorName);
- if (offColor.isValid())
- newItem->setOffColor(offColor);
-
- QColor currentColor(colorName);
- if (currentColor.isValid()) {
- // 可以根据实际业务逻辑判断,是否恢复为onColor或offColor
- // 这里直接恢复当前颜色
- newItem->setColor(currentColor);
- } else {
- // 如果当前颜色无效,则使用 offColor 作为默认颜色
- newItem->setColor(newItem->offColor());
- }
-
- newItem->setComponentName(componentName);
- // 设置地址
- newItem->setAddress(address);
- newScene->addItem(newItem);
- setupNewComponent(newItem);
- }
- }
- }
-
- // 自动切换到第一页
- if (tabWidget->count() > 0) {
- tabWidget->setCurrentIndex(0);
- }
-
- emit logMessageGenerated(QString("[%1] 打开文件成功: %2")
- .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
- .arg(filePath));
- return true;
- }
-
- void HMIModule::setupNewComponent(HmiComponent* item)
- {
- if (!item) return;
-
- connect(item, &HmiComponent::selected, this, &HMIModule::onComponentSelected);
- connect(item, &HmiComponent::copyRequested, this, &HMIModule::onCopyRequested);
- connect(item, &HmiComponent::deleteRequested, this, &HMIModule::onDeleteRequested);
- connect(item, &HmiComponent::changeOnColorRequested, this, &HMIModule::onChangeOnColorRequested);
- connect(item, &HmiComponent::changeOffColorRequested, this, &HMIModule::onChangeOffColorRequested);
-
-
- QString currentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
- QString log = QString("[%1] 创建 %2 组件").arg(currentTime).arg(item->componentName());
- emit logMessageGenerated(log);
- }
-
- void HMIModule::prepareToCreateButton()
- {
- // 获取当前 TabWidget 中选中的 GraphicsView
- QTabWidget* tabWidget = ui_->tabWidget_2;
- QWidget* currentPage = tabWidget->currentWidget();
- QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
- CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
-
- if (currentScene) {
- currentScene->setComponentTypeToCreate(ComponentType::Button);
- currentScene->setMode(CustomGraphicsScene::Mode::CreateItem);
- }
- }
-
- void HMIModule::prepareToCreateIndicator()
- {
- // 获取当前 TabWidget 中选中的 GraphicsView
- QTabWidget* tabWidget = ui_->tabWidget_2;
- QWidget* currentPage = tabWidget->currentWidget();
- QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
- CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
-
- if (currentScene) {
- currentScene->setComponentTypeToCreate(ComponentType::Indicator);
- currentScene->setMode(CustomGraphicsScene::Mode::CreateItem);
- }
- }
-
- void HMIModule::onComponentCreated(HmiComponent* item)
- {
- setupNewComponent(item);
- }
-
- void HMIModule::onCopyRequested()
- {
- // 获取当前 TabWidget 中选中的 GraphicsView
- QTabWidget* tabWidget = ui_->tabWidget_2;
- QWidget* currentPage = tabWidget->currentWidget();
- QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
- CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
-
- QList<QGraphicsItem*> selected = currentScene->selectedItems();
- if (selected.isEmpty()) return;
-
- HmiComponent* itemToCopy = qgraphicsitem_cast<HmiComponent*>(selected.first());
- if (!itemToCopy) return;
-
- if (dynamic_cast<HmiButton*>(itemToCopy)) {
- m_copiedType = ComponentType::Button;
- } else if (dynamic_cast<HmiIndicator*>(itemToCopy)) {
- m_copiedType = ComponentType::Indicator;
- }
- m_copiedColor = itemToCopy->color();
- m_hasCopiedItem = true;
-
- emit logMessageGenerated(QString("[%1] 复制组件: %2")
- .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
- .arg(itemToCopy->componentName()));
- }
-
- void HMIModule::onPasteRequested(const QPointF& scenePos)
- {
- if (!m_hasCopiedItem) return;
-
- // 获取当前 TabWidget 中选中的 GraphicsView
- QTabWidget* tabWidget = ui_->tabWidget_2;
- QWidget* currentPage = tabWidget->currentWidget();
- QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
- CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
-
- HmiComponent* newItem = nullptr;
- if (m_copiedType == ComponentType::Button) {
- newItem = new HmiButton();
- } else {
- newItem = new HmiIndicator();
- }
-
- if (newItem) {
- newItem->setColor(m_copiedColor);
- newItem->setPos(scenePos);
- currentScene->addItem(newItem); // 使用当前页面的 scene
- setupNewComponent(newItem);
- }
- }
-
- void HMIModule::onDeleteRequested()
- {
- // 获取当前 TabWidget 中选中的 GraphicsView
- QTabWidget* tabWidget = ui_->tabWidget_2;
- QWidget* currentPage = tabWidget->currentWidget();
- QGraphicsView* currentGraphicsView = currentPage->findChild<QGraphicsView*>();
- CustomGraphicsScene* currentScene = qobject_cast<CustomGraphicsScene*>(currentGraphicsView->scene());
-
- QList<QGraphicsItem*> selected = currentScene->selectedItems();
- if (selected.isEmpty()) return;
-
- emit logMessageGenerated(QString("[%1] 删除 %2 个组件")
- .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
- .arg(selected.count()));
-
- for (int i = selected.count() - 1; i >= 0; --i) {
- QGraphicsItem* item = selected.at(i);
- currentScene->removeItem(item); // 使用当前页面的 scene
- delete item;
- }
- }
-
-
- // 添加页面后的槽函数
- void HMIModule::onPageAdded(int pageNumber, int index)
- {
- if (index < m_pageOrder.size()) {
- m_pageOrder[index] = pageNumber;
- } else {
- m_pageOrder.append(pageNumber);
- }
- }
-
- // 删除页面后的槽函数
- void HMIModule::onPageRemoved(int pageNumber, int index)
- {
- if (index < m_pageOrder.size()) {
- m_pageOrder[index] = -1;
- }
- }
-
- void HMIModule::onChangeOnColorRequested(HmiComponent* item)
- {
- QColor color = QColorDialog::getColor(item->onColor(), nullptr, "选择 ON 状态颜色");
- if (color.isValid()) {
- item->setOnColor(color);
- emit logMessageGenerated(QString("[%1] 设置 %2 的 ON 状态颜色为 %3")
- .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
- .arg(item->componentName())
- .arg(color.name()));
- }
- }
-
- void HMIModule::onChangeOffColorRequested(HmiComponent* item)
- {
- QColor color = QColorDialog::getColor(item->offColor(), nullptr, "选择 OFF 状态颜色");
- if (color.isValid()) {
- item->setOffColor(color); // 同时更新当前显示颜色
- emit logMessageGenerated(QString("[%1] 设置 %2 的 OFF 状态颜色为 %3")
- .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
- .arg(item->componentName())
- .arg(color.name()));
- }
- }
-
- void HMIModule::onComponentSelected(HmiComponent* item)
- {
- // 不需要任何操作,可以留空
- }
-
- // 新增页面的槽函数
- void HMIModule::addPage()
- {
- QTabWidget* tabWidget = ui_->tabWidget_2;
- int pageNumber;
- int insertIndex = -1;
- int tabIndex; // 在此处声明 tabIndex
-
- // 检查是否有可用的页面编号
- if (!m_availablePageNumbers.isEmpty()) {
- pageNumber = m_availablePageNumbers.first();
- m_availablePageNumbers.removeFirst();
-
- // 查找可用的插入位置
- for (int i = 0; i < m_pageOrder.size(); ++i) {
- if (m_pageOrder[i] == -1) {
- insertIndex = i;
- break;
- }
- }
- } else {
- pageNumber = ++m_pageCount;
- }
- // 获取 Page 1 的 Scene
- CustomGraphicsScene* firstScene = m_scene;
-
- // 创建新的页面部件
- QWidget* newPage = new QWidget(tabWidget);
- QString pageName = QString("Page %1").arg(pageNumber);
- newPage->setObjectName(pageName);
-
- // 创建新的 GraphicsView 和 Scene
- QGraphicsView* newGraphicsView = new QGraphicsView(newPage);
- CustomGraphicsScene* newScene = new CustomGraphicsScene(newGraphicsView, this);
-
- // 设置 GraphicsView 的大小
- QSize newViewSize(691, 381); // 设置为指定的宽度和高度
- newGraphicsView->resize(newViewSize);
-
- // 设置 GraphicsScene 的大小与 Page 1 相同
- QRectF newSceneRect = firstScene->sceneRect();
- newScene->setSceneRect(newSceneRect);
-
- newGraphicsView->setScene(newScene);
-
- // 布局
- QVBoxLayout* layout = new QVBoxLayout(newPage);
- layout->addWidget(newGraphicsView);
- newPage->setLayout(layout);
-
- // 添加到 TabWidget
- if (insertIndex != -1) {
- tabIndex = insertIndex;
- tabWidget->insertTab(tabIndex, newPage, pageName);
- } else {
- tabIndex = tabWidget->addTab(newPage, pageName);
- }
-
- // 连接信号和槽
- connect(newScene, &CustomGraphicsScene::componentCreated, this, &HMIModule::onComponentCreated);
- connect(newScene, &CustomGraphicsScene::copyRequestFromScene, this, &HMIModule::onCopyRequested);
- connect(newScene, &CustomGraphicsScene::pasteRequestFromScene, this, &HMIModule::onPasteRequested);
- connect(newScene, &CustomGraphicsScene::deleteRequestFromScene, this, &HMIModule::onDeleteRequested);
-
- // 发送 pageAdded 信号
- emit pageAdded(pageNumber, tabIndex);
-
- tabWidget->setCurrentWidget(newPage);
-
- // 记录日志
- emit logMessageGenerated(QString("[%1] 添加页面: %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(pageName));
- }
-
- // 删除页面的槽函数
- void HMIModule::deletePage()
- {
- QTabWidget* tabWidget = ui_->tabWidget_2;
- int currentIndex = tabWidget->currentIndex();
-
- if (tabWidget->count() == 1) {
- QMessageBox::information(nullptr, "提示", "这是最后一页,不能删除!");
- return;
- }
-
- if (currentIndex >= 0) {
- // 获取要删除的页面
- QWidget* currentPage = tabWidget->widget(currentIndex);
- QString pageName = tabWidget->tabText(currentIndex);
-
- // 从页面名称中提取页面编号
- int pageNumber = pageName.remove("Page ").toInt();
-
- // 将删除的页面编号添加到可用列表中
- m_availablePageNumbers.append(pageNumber);
- std::sort(m_availablePageNumbers.begin(), m_availablePageNumbers.end());
-
- // 从 TabWidget 中移除页面
- tabWidget->removeTab(currentIndex);
-
- // 删除页面
- delete currentPage;
-
- // 发送 pageRemoved 信号
- emit pageRemoved(pageNumber, currentIndex);
-
- // 记录日志
- emit logMessageGenerated(QString("[%1] 删除页面: %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(pageName));
- }
- }
-
- // 前一页的槽函数
- void HMIModule::prePage()
- {
- QTabWidget* tabWidget = ui_->tabWidget_2;
- int currentIndex = tabWidget->currentIndex();
- if (currentIndex > 0) {
- tabWidget->setCurrentIndex(currentIndex - 1);
- }
- }
-
- // 后一页的槽函数
- void HMIModule::nextPage()
- {
- QTabWidget* tabWidget = ui_->tabWidget_2;
- int currentIndex = tabWidget->currentIndex();
- if (currentIndex < tabWidget->count() - 1) {
- tabWidget->setCurrentIndex(currentIndex + 1);
- }
- }
|