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.

289 rader
9.2 KiB

  1. #include "filemanager.h"
  2. #include <QFile>
  3. #include <QJsonDocument>
  4. #include <QJsonArray>
  5. #include <QMessageBox>
  6. #include <QDebug>
  7. #include "modules/HMI/hmicontrolitem.h"
  8. #include "modules/HMI/hmibutton.h"
  9. #include "modules/HMI/hmiled.h"
  10. FileManager::FileManager(QObject* parent) : QObject(parent) {}
  11. bool FileManager::saveFile(EditorWidget* editor, const QString& filePath) {
  12. if (!editor || filePath.isEmpty()) {
  13. qDebug() << "保存文件失败:无效的编辑器部件或文件路径";
  14. return false;
  15. }
  16. HmiEditorWidget* hmiWidget = dynamic_cast<HmiEditorWidget*>(editor);
  17. PlcEditorWidget* plcWidget = dynamic_cast<PlcEditorWidget*>(editor);
  18. if (hmiWidget) {
  19. return saveHmiFile(hmiWidget, filePath);
  20. } else if (plcWidget) {
  21. return savePlcFile(plcWidget, filePath);
  22. }
  23. qDebug() << "保存文件失败:无法识别的编辑器类型";
  24. return false;
  25. }
  26. bool FileManager::loadFile(EditorWidget* editor, const QString& filePath) {
  27. if (!editor || filePath.isEmpty()) {
  28. qDebug() << "加载文件失败:无效的编辑器部件或文件路径";
  29. return false;
  30. }
  31. HmiEditorWidget* hmiWidget = dynamic_cast<HmiEditorWidget*>(editor);
  32. PlcEditorWidget* plcWidget = dynamic_cast<PlcEditorWidget*>(editor);
  33. if (hmiWidget) {
  34. return loadHmiFile(hmiWidget, filePath);
  35. } else if (plcWidget) {
  36. return loadPlcFile(plcWidget, filePath);
  37. }
  38. qDebug() << "加载文件失败:无法识别的编辑器类型";
  39. return false;
  40. }
  41. bool FileManager::saveHmiFile(HmiEditorWidget* widget, const QString& filePath) {
  42. if (!widget || filePath.isEmpty()) {
  43. qDebug() << "保存HMI文件失败:无效的编辑器部件或文件路径";
  44. return false;
  45. }
  46. QList<QGraphicsScene*> pages = widget->getPages();
  47. if (pages.isEmpty()) {
  48. qDebug() << "保存HMI文件失败:没有页面数据";
  49. return false;
  50. }
  51. QJsonObject jsonObj = serializeHmiPages(pages);
  52. jsonObj["currentPageIndex"] = widget->getCurrentPageIndex();
  53. jsonObj["type"] = "HMI"; // 新增:标记文件类型
  54. QJsonDocument doc(jsonObj);
  55. QFile file(filePath);
  56. if (!file.open(QIODevice::WriteOnly)) {
  57. qDebug() << "保存HMI文件失败:无法打开文件" << filePath;
  58. return false;
  59. }
  60. file.write(doc.toJson(QJsonDocument::Indented));
  61. file.close();
  62. qDebug() << "HMI文件保存成功:" << filePath;
  63. return true;
  64. }
  65. bool FileManager::loadHmiFile(HmiEditorWidget* widget, const QString& filePath) {
  66. qDebug() << "尝试加载 HMI 文件:" << filePath;
  67. QFile file(filePath);
  68. if (!file.open(QIODevice::ReadOnly)) {
  69. qDebug() << "加载HMI文件失败:无法打开文件" << filePath;
  70. return false;
  71. }
  72. QByteArray fileData = file.readAll();
  73. file.close();
  74. QJsonDocument doc = QJsonDocument::fromJson(fileData);
  75. if (doc.isNull() || !doc.isObject()) {
  76. qDebug() << "加载HMI文件失败:无效的JSON格式";
  77. return false;
  78. }
  79. QJsonObject jsonObj = doc.object();
  80. if (jsonObj.value("type").toString() != "HMI") {
  81. qDebug() << "加载HMI文件失败:文件类型不匹配";
  82. return false;
  83. }
  84. qDebug() << "JSON 数据解析成功,准备反序列化页面...";
  85. return deserializeHmiPages(widget, jsonObj);
  86. }
  87. bool FileManager::savePlcFile(PlcEditorWidget* widget, const QString& filePath) {
  88. if (!widget || filePath.isEmpty()) {
  89. qDebug() << "保存PLC文件失败:无效的编辑器部件或文件路径";
  90. return false;
  91. }
  92. QGraphicsScene* scene = widget->getCurrentScene();
  93. if (!scene) {
  94. qDebug() << "保存PLC文件失败:没有场景数据";
  95. return false;
  96. }
  97. QJsonObject jsonObj = serializePlcScene(scene);
  98. jsonObj["type"] = "PLC"; // 新增:标记文件类型
  99. QJsonDocument doc(jsonObj);
  100. QFile file(filePath);
  101. if (!file.open(QIODevice::WriteOnly)) {
  102. qDebug() << "保存PLC文件失败:无法打开文件" << filePath;
  103. return false;
  104. }
  105. file.write(doc.toJson(QJsonDocument::Indented));
  106. file.close();
  107. qDebug() << "PLC文件保存成功:" << filePath;
  108. return true;
  109. }
  110. bool FileManager::loadPlcFile(PlcEditorWidget* widget, const QString& filePath) {
  111. if (!widget || filePath.isEmpty()) {
  112. qDebug() << "加载PLC文件失败:无效的编辑器部件或文件路径";
  113. return false;
  114. }
  115. QFile file(filePath);
  116. if (!file.open(QIODevice::ReadOnly)) {
  117. qDebug() << "加载PLC文件失败:无法打开文件" << filePath;
  118. return false;
  119. }
  120. QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
  121. file.close();
  122. if (doc.isNull() || !doc.isObject()) {
  123. qDebug() << "加载PLC文件失败:无效的JSON格式";
  124. return false;
  125. }
  126. QJsonObject jsonObj = doc.object();
  127. if (jsonObj.value("type").toString() != "PLC") {
  128. qDebug() << "加载PLC文件失败:文件类型不匹配";
  129. return false;
  130. }
  131. return deserializePlcScene(widget, jsonObj);
  132. }
  133. QJsonObject FileManager::serializeHmiPages(const QList<QGraphicsScene*>& pages) {
  134. QJsonObject jsonObj;
  135. QJsonArray pagesArray;
  136. for (int i = 0; i < pages.size(); ++i) {
  137. QJsonObject pageObj;
  138. QJsonArray itemsArray;
  139. QGraphicsScene* scene = pages[i];
  140. // 保存场景尺寸
  141. pageObj["sceneWidth"] = scene->width();
  142. pageObj["sceneHeight"] = scene->height();
  143. for (QGraphicsItem* item : scene->items()) {
  144. HmiControlItem* controlItem = dynamic_cast<HmiControlItem*>(item);
  145. if (controlItem) {
  146. QVariantMap itemData = controlItem->saveToClipboard();
  147. QJsonObject itemObj;
  148. for (auto it = itemData.constBegin(); it != itemData.constEnd(); ++it) {
  149. itemObj.insert(it.key(), QJsonValue::fromVariant(it.value()));
  150. }
  151. itemsArray.append(itemObj);
  152. }
  153. }
  154. pageObj["items"] = itemsArray;
  155. pagesArray.append(pageObj);
  156. }
  157. jsonObj["pages"] = pagesArray;
  158. jsonObj["version"] = "1.1";
  159. return jsonObj;
  160. }
  161. bool FileManager::deserializeHmiPages(HmiEditorWidget* widget, const QJsonObject& jsonObj) {
  162. if (!widget) {
  163. qDebug() << "反序列化失败:widget 为空";
  164. return false;
  165. }
  166. if (!jsonObj.contains("pages") || !jsonObj["pages"].isArray()) {
  167. qDebug() << "反序列化HMI页面失败:缺少页面数据";
  168. return false;
  169. }
  170. QJsonArray pagesArray = jsonObj["pages"].toArray();
  171. if (pagesArray.isEmpty()) {
  172. qDebug() << "反序列化HMI页面失败:pagesArray 为空";
  173. return false;
  174. }
  175. widget->clearPages();
  176. qDebug() << "已清空现有页面,准备加载新页面...";
  177. widget->clearPages();
  178. // 获取保存的当前页面索引
  179. int savedPageIndex = jsonObj.value("currentPageIndex").toInt(0);
  180. pagesArray = jsonObj["pages"].toArray();
  181. for (const QJsonValue& pageVal : pagesArray) {
  182. if (!pageVal.isObject()) continue;
  183. QJsonObject pageObj = pageVal.toObject();
  184. widget->createNewPage();
  185. int currentPageIndex = widget->getCurrentPageIndex();
  186. if (currentPageIndex < 0) continue;
  187. QList<QGraphicsScene*> pages = widget->getPages();
  188. QGraphicsScene* scene = pages[currentPageIndex];
  189. // 恢复场景尺寸
  190. if (pageObj.contains("sceneWidth") && pageObj.contains("sceneHeight")) {
  191. scene->setSceneRect(0, 0,
  192. pageObj["sceneWidth"].toDouble(),
  193. pageObj["sceneHeight"].toDouble());
  194. }
  195. if (pageObj.contains("items") && pageObj["items"].isArray()) {
  196. QJsonArray itemsArray = pageObj["items"].toArray();
  197. for (const QJsonValue& itemVal : itemsArray) {
  198. if (!itemVal.isObject()) continue;
  199. QJsonObject itemObj = itemVal.toObject();
  200. QVariantMap itemData;
  201. for (auto it = itemObj.constBegin(); it != itemObj.constEnd(); ++it) {
  202. itemData.insert(it.key(), it.value().toVariant());
  203. }
  204. QPointF pos(itemData.value("posX", 0.0).toDouble(),
  205. itemData.value("posY", 0.0).toDouble());
  206. HmiControlItem* newItem = HmiControlItem::createFromClipboard(itemData, pos);
  207. if (newItem) {
  208. scene->addItem(newItem);
  209. }
  210. }
  211. }
  212. }
  213. // 恢复保存时的当前页面
  214. if (!widget->getPages().isEmpty()) {
  215. savedPageIndex = qBound(0, savedPageIndex, widget->getPages().size() - 1);
  216. widget->switchToPage(savedPageIndex);
  217. QMetaObject::invokeMethod(widget, [widget]() {
  218. widget->refreshView();
  219. }, Qt::QueuedConnection);
  220. }
  221. return true;
  222. }
  223. QJsonObject FileManager::serializePlcScene(QGraphicsScene* /*scene*/)
  224. {
  225. // 现在先不做 PLC 场景的序列化,返回一个空对象即可
  226. QJsonObject obj;
  227. obj["type"] = "plc_scene_stub";
  228. return obj;
  229. }
  230. bool FileManager::deserializePlcScene(PlcEditorWidget* /*widget*/, const QJsonObject& /*jsonObj*/)
  231. {
  232. // 暂不实现反序列化,返回 false 表示“未处理”
  233. return false;
  234. }