|
|
@@ -0,0 +1,288 @@ |
|
|
|
#include "filemanager.h" |
|
|
|
#include <QFile> |
|
|
|
#include <QJsonDocument> |
|
|
|
#include <QJsonArray> |
|
|
|
#include <QMessageBox> |
|
|
|
#include <QDebug> |
|
|
|
#include "modules/HMI/hmicontrolitem.h" |
|
|
|
#include "modules/HMI/hmibutton.h" |
|
|
|
#include "modules/HMI/hmiled.h" |
|
|
|
|
|
|
|
FileManager::FileManager(QObject* parent) : QObject(parent) {} |
|
|
|
|
|
|
|
bool FileManager::saveFile(EditorWidget* editor, const QString& filePath) { |
|
|
|
if (!editor || filePath.isEmpty()) { |
|
|
|
qDebug() << "保存文件失败:无效的编辑器部件或文件路径"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
HmiEditorWidget* hmiWidget = dynamic_cast<HmiEditorWidget*>(editor); |
|
|
|
PlcEditorWidget* plcWidget = dynamic_cast<PlcEditorWidget*>(editor); |
|
|
|
|
|
|
|
if (hmiWidget) { |
|
|
|
return saveHmiFile(hmiWidget, filePath); |
|
|
|
} else if (plcWidget) { |
|
|
|
return savePlcFile(plcWidget, filePath); |
|
|
|
} |
|
|
|
|
|
|
|
qDebug() << "保存文件失败:无法识别的编辑器类型"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
bool FileManager::loadFile(EditorWidget* editor, const QString& filePath) { |
|
|
|
if (!editor || filePath.isEmpty()) { |
|
|
|
qDebug() << "加载文件失败:无效的编辑器部件或文件路径"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
HmiEditorWidget* hmiWidget = dynamic_cast<HmiEditorWidget*>(editor); |
|
|
|
PlcEditorWidget* plcWidget = dynamic_cast<PlcEditorWidget*>(editor); |
|
|
|
|
|
|
|
if (hmiWidget) { |
|
|
|
return loadHmiFile(hmiWidget, filePath); |
|
|
|
} else if (plcWidget) { |
|
|
|
return loadPlcFile(plcWidget, filePath); |
|
|
|
} |
|
|
|
|
|
|
|
qDebug() << "加载文件失败:无法识别的编辑器类型"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
bool FileManager::saveHmiFile(HmiEditorWidget* widget, const QString& filePath) { |
|
|
|
if (!widget || filePath.isEmpty()) { |
|
|
|
qDebug() << "保存HMI文件失败:无效的编辑器部件或文件路径"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QList<QGraphicsScene*> pages = widget->getPages(); |
|
|
|
if (pages.isEmpty()) { |
|
|
|
qDebug() << "保存HMI文件失败:没有页面数据"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QJsonObject jsonObj = serializeHmiPages(pages); |
|
|
|
jsonObj["currentPageIndex"] = widget->getCurrentPageIndex(); |
|
|
|
jsonObj["type"] = "HMI"; // 新增:标记文件类型 |
|
|
|
|
|
|
|
QJsonDocument doc(jsonObj); |
|
|
|
QFile file(filePath); |
|
|
|
if (!file.open(QIODevice::WriteOnly)) { |
|
|
|
qDebug() << "保存HMI文件失败:无法打开文件" << filePath; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
file.write(doc.toJson(QJsonDocument::Indented)); |
|
|
|
file.close(); |
|
|
|
qDebug() << "HMI文件保存成功:" << filePath; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
bool FileManager::loadHmiFile(HmiEditorWidget* widget, const QString& filePath) { |
|
|
|
qDebug() << "尝试加载 HMI 文件:" << filePath; |
|
|
|
|
|
|
|
QFile file(filePath); |
|
|
|
if (!file.open(QIODevice::ReadOnly)) { |
|
|
|
qDebug() << "加载HMI文件失败:无法打开文件" << filePath; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QByteArray fileData = file.readAll(); |
|
|
|
file.close(); |
|
|
|
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(fileData); |
|
|
|
if (doc.isNull() || !doc.isObject()) { |
|
|
|
qDebug() << "加载HMI文件失败:无效的JSON格式"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QJsonObject jsonObj = doc.object(); |
|
|
|
if (jsonObj.value("type").toString() != "HMI") { |
|
|
|
qDebug() << "加载HMI文件失败:文件类型不匹配"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
qDebug() << "JSON 数据解析成功,准备反序列化页面..."; |
|
|
|
return deserializeHmiPages(widget, jsonObj); |
|
|
|
} |
|
|
|
|
|
|
|
bool FileManager::savePlcFile(PlcEditorWidget* widget, const QString& filePath) { |
|
|
|
if (!widget || filePath.isEmpty()) { |
|
|
|
qDebug() << "保存PLC文件失败:无效的编辑器部件或文件路径"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QGraphicsScene* scene = widget->getCurrentScene(); |
|
|
|
if (!scene) { |
|
|
|
qDebug() << "保存PLC文件失败:没有场景数据"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QJsonObject jsonObj = serializePlcScene(scene); |
|
|
|
jsonObj["type"] = "PLC"; // 新增:标记文件类型 |
|
|
|
|
|
|
|
QJsonDocument doc(jsonObj); |
|
|
|
QFile file(filePath); |
|
|
|
if (!file.open(QIODevice::WriteOnly)) { |
|
|
|
qDebug() << "保存PLC文件失败:无法打开文件" << filePath; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
file.write(doc.toJson(QJsonDocument::Indented)); |
|
|
|
file.close(); |
|
|
|
qDebug() << "PLC文件保存成功:" << filePath; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
bool FileManager::loadPlcFile(PlcEditorWidget* widget, const QString& filePath) { |
|
|
|
if (!widget || filePath.isEmpty()) { |
|
|
|
qDebug() << "加载PLC文件失败:无效的编辑器部件或文件路径"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QFile file(filePath); |
|
|
|
if (!file.open(QIODevice::ReadOnly)) { |
|
|
|
qDebug() << "加载PLC文件失败:无法打开文件" << filePath; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); |
|
|
|
file.close(); |
|
|
|
|
|
|
|
if (doc.isNull() || !doc.isObject()) { |
|
|
|
qDebug() << "加载PLC文件失败:无效的JSON格式"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QJsonObject jsonObj = doc.object(); |
|
|
|
if (jsonObj.value("type").toString() != "PLC") { |
|
|
|
qDebug() << "加载PLC文件失败:文件类型不匹配"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
return deserializePlcScene(widget, jsonObj); |
|
|
|
} |
|
|
|
|
|
|
|
QJsonObject FileManager::serializeHmiPages(const QList<QGraphicsScene*>& pages) { |
|
|
|
QJsonObject jsonObj; |
|
|
|
QJsonArray pagesArray; |
|
|
|
|
|
|
|
for (int i = 0; i < pages.size(); ++i) { |
|
|
|
QJsonObject pageObj; |
|
|
|
QJsonArray itemsArray; |
|
|
|
QGraphicsScene* scene = pages[i]; |
|
|
|
|
|
|
|
// 保存场景尺寸 |
|
|
|
pageObj["sceneWidth"] = scene->width(); |
|
|
|
pageObj["sceneHeight"] = scene->height(); |
|
|
|
|
|
|
|
for (QGraphicsItem* item : scene->items()) { |
|
|
|
HmiControlItem* controlItem = dynamic_cast<HmiControlItem*>(item); |
|
|
|
if (controlItem) { |
|
|
|
QVariantMap itemData = controlItem->saveToClipboard(); |
|
|
|
QJsonObject itemObj; |
|
|
|
for (auto it = itemData.constBegin(); it != itemData.constEnd(); ++it) { |
|
|
|
itemObj.insert(it.key(), QJsonValue::fromVariant(it.value())); |
|
|
|
} |
|
|
|
itemsArray.append(itemObj); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pageObj["items"] = itemsArray; |
|
|
|
pagesArray.append(pageObj); |
|
|
|
} |
|
|
|
|
|
|
|
jsonObj["pages"] = pagesArray; |
|
|
|
jsonObj["version"] = "1.1"; |
|
|
|
return jsonObj; |
|
|
|
} |
|
|
|
|
|
|
|
bool FileManager::deserializeHmiPages(HmiEditorWidget* widget, const QJsonObject& jsonObj) { |
|
|
|
if (!widget) { |
|
|
|
qDebug() << "反序列化失败:widget 为空"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (!jsonObj.contains("pages") || !jsonObj["pages"].isArray()) { |
|
|
|
qDebug() << "反序列化HMI页面失败:缺少页面数据"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
QJsonArray pagesArray = jsonObj["pages"].toArray(); |
|
|
|
if (pagesArray.isEmpty()) { |
|
|
|
qDebug() << "反序列化HMI页面失败:pagesArray 为空"; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
widget->clearPages(); |
|
|
|
qDebug() << "已清空现有页面,准备加载新页面..."; |
|
|
|
|
|
|
|
widget->clearPages(); |
|
|
|
|
|
|
|
// 获取保存的当前页面索引 |
|
|
|
int savedPageIndex = jsonObj.value("currentPageIndex").toInt(0); |
|
|
|
|
|
|
|
pagesArray = jsonObj["pages"].toArray(); |
|
|
|
for (const QJsonValue& pageVal : pagesArray) { |
|
|
|
if (!pageVal.isObject()) continue; |
|
|
|
QJsonObject pageObj = pageVal.toObject(); |
|
|
|
|
|
|
|
widget->createNewPage(); |
|
|
|
int currentPageIndex = widget->getCurrentPageIndex(); |
|
|
|
if (currentPageIndex < 0) continue; |
|
|
|
|
|
|
|
QList<QGraphicsScene*> pages = widget->getPages(); |
|
|
|
QGraphicsScene* scene = pages[currentPageIndex]; |
|
|
|
|
|
|
|
// 恢复场景尺寸 |
|
|
|
if (pageObj.contains("sceneWidth") && pageObj.contains("sceneHeight")) { |
|
|
|
scene->setSceneRect(0, 0, |
|
|
|
pageObj["sceneWidth"].toDouble(), |
|
|
|
pageObj["sceneHeight"].toDouble()); |
|
|
|
} |
|
|
|
|
|
|
|
if (pageObj.contains("items") && pageObj["items"].isArray()) { |
|
|
|
QJsonArray itemsArray = pageObj["items"].toArray(); |
|
|
|
for (const QJsonValue& itemVal : itemsArray) { |
|
|
|
if (!itemVal.isObject()) continue; |
|
|
|
QJsonObject itemObj = itemVal.toObject(); |
|
|
|
QVariantMap itemData; |
|
|
|
for (auto it = itemObj.constBegin(); it != itemObj.constEnd(); ++it) { |
|
|
|
itemData.insert(it.key(), it.value().toVariant()); |
|
|
|
} |
|
|
|
|
|
|
|
QPointF pos(itemData.value("posX", 0.0).toDouble(), |
|
|
|
itemData.value("posY", 0.0).toDouble()); |
|
|
|
HmiControlItem* newItem = HmiControlItem::createFromClipboard(itemData, pos); |
|
|
|
if (newItem) { |
|
|
|
scene->addItem(newItem); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 恢复保存时的当前页面 |
|
|
|
if (!widget->getPages().isEmpty()) { |
|
|
|
savedPageIndex = qBound(0, savedPageIndex, widget->getPages().size() - 1); |
|
|
|
widget->switchToPage(savedPageIndex); |
|
|
|
QMetaObject::invokeMethod(widget, [widget]() { |
|
|
|
widget->refreshView(); |
|
|
|
}, Qt::QueuedConnection); |
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
QJsonObject FileManager::serializePlcScene(QGraphicsScene* /*scene*/) |
|
|
|
{ |
|
|
|
// 现在先不做 PLC 场景的序列化,返回一个空对象即可 |
|
|
|
QJsonObject obj; |
|
|
|
obj["type"] = "plc_scene_stub"; |
|
|
|
return obj; |
|
|
|
} |
|
|
|
|
|
|
|
bool FileManager::deserializePlcScene(PlcEditorWidget* /*widget*/, const QJsonObject& /*jsonObj*/) |
|
|
|
{ |
|
|
|
// 暂不实现反序列化,返回 false 表示“未处理” |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
|