#ifndef DOCUMENT_H #define DOCUMENT_H #include #include #include #include #include #include /** * @brief BayTemplate 文档类 * * Document 类作为持久化层,位于 Model 层之下,负责: * 1. 序列化/反序列化:将 DesignerScene 中的图元层次结构保存到 JSON/XML,从文件重建场景 * 2. 状态管理:文件名、保存状态(是否修改过)、版本信息、元数据 * 3. 与现有架构的集成:通过组合方式持有 DesignerScene 的引用,提供信号与 CMainWindow 通信 * * 设计原则: * - 组合优于继承:Document 持有 DesignerScene 的弱引用,不继承 Scene * - 单向依赖:Document 只依赖 DesignerScene 的接口,不依赖 CMainWindow * - 信号槽通信:通过信号与外部通信修改状态,避免紧耦合 */ class DesignerScene; class GraphicsBaseItem; class GraphicsItemGroup; class QGraphicsScene; class QGraphicsItem; class QJsonObject; class Document : public QObject { Q_OBJECT public: explicit Document(QObject *parent = nullptr); ~Document(); // ================================================================= // 场景关联(组合关系) // ================================================================= /** * @brief 关联到 DesignerScene * @param scene 场景对象,Document 持有其弱引用 * * 通过组合方式关联场景,而不是继承。这符合开闭原则, * Document 可以独立于 Scene 存在,需要序列化时才使用 scene 引用。 */ void setScene(DesignerScene* scene); /** * @brief 获取关联的场景 */ DesignerScene* scene() const; // ================================================================= // 文件操作 // ================================================================= /** * @brief 保存文档到文件 * @param filename 文件路径,为空则使用当前 filename() * @return 成功返回 true * * 序列化流程: * 1. 遍历 scene->items() 获取顶层图元 * 2. 递归序列化每个图元及其子图元(对于组图元) * 3. 写入 JSON 格式文件 * 4. 调用 setModified(false) */ bool saveToFile(const QString& filename = QString()); /** * @brief 从文件加载文档 * @param filename 文件路径 * @return 成功返回 true * * 反序列化流程: * 1. 读取 JSON 文件 * 2. 清空当前 scene 的内容 * 3. 递归重建图元层次结构 * 4. 更新 m_filename 和 m_modified */ bool loadFromFile(const QString& filename); // ================================================================= // 序列化接口(二进制格式) // ================================================================= /** * @brief 序列化为 QByteArray * @return JSON 格式的字节数组 */ QByteArray serialize() const; /** * @brief 从 QByteArray 反序列化 * @param data JSON 格式的字节数组 * @return 成功返回 true */ bool deserialize(const QByteArray& data); // ================================================================= // 状态管理 // ================================================================= /** * @brief 文档文件名(可能为空,表示未保存的新文档) */ QString filename() const { return m_filename; } void setFilename(const QString& filename) { m_filename = filename; } /** * @brief 文档是否被修改过(需要保存) */ bool isModified() const { return m_modified; } void setModified(bool modified) { if (m_modified != modified) { m_modified = modified; emit modifiedChanged(m_modified); } } /** * @brief 文档版本(文件格式版本,用于向前/向后兼容) */ QString version() const { return m_version; } /** * @brief 创建时间 */ QDateTime created() const { return m_created; } /** * @brief 最后修改时间 */ QDateTime modifiedTime() const { return m_modifiedTime; } /** * @brief 最后保存时间 */ QDateTime lastSavedTime() const { return m_lastSavedTime; } // ================================================================= // 元数据(可扩展) // ================================================================= /** * @brief 设置自定义元数据 * @param key 键名 * @param value 值 */ void setMetaData(const QString& key, const QVariant& value); /** * @brief 获取自定义元数据 */ QVariant metaData(const QString& key) const; signals: /** * @brief 修改状态改变时发出 * @param modified 新的修改状态 * * CMainWindow 可连接此信号来更新窗口标题(添加 * 标记) */ void modifiedChanged(bool modified); /** * @brief 文件名改变时发出(新建、另存为等操作) * @param filename 新的文件名 * * CMainWindow 可连接此信号来更新窗口标题 */ void filenameChanged(const QString& filename); /** * @brief 保存/加载操作完成时发出 * @param success 操作是否成功 * @param message 成功或失败的消息 */ void saveStatusChanged(bool success, const QString& message); private: // 内部实现 bool saveInternal(const QString& filename); bool loadInternal(const QString& filename); // 图元序列化/反序列化 QJsonObject serializeItem(GraphicsBaseItem* item) const; void deserializeItem(const QJsonObject& obj, QGraphicsScene* scene, QGraphicsItem* parent); QString getTypeString(GraphicsBaseItem* item) const; QJsonObject serializeItemProperties(GraphicsBaseItem* item) const; // QVariant <-> QJsonValue 转换 QJsonValue toJsonValue(const QVariant& value) const; QVariant fromJsonValue(const QJsonValue& value) const; GraphicsBaseItem* deserializeRectItem(const QJsonObject& obj); GraphicsBaseItem* deserializeBusSectionItem(const QJsonObject& obj); GraphicsItemGroup* deserializeItemGroup(const QJsonObject& obj, QGraphicsScene* scene, QGraphicsItem* parent); QString m_filename; // 文档文件名 bool m_modified; // 是否被修改 QString m_version; // 文件格式版本 QDateTime m_created; // 创建时间 QDateTime m_modifiedTime; // 最后修改时间 QDateTime m_lastSavedTime; // 最后保存时间 QMap m_metaData; // 自定义元数据 DesignerScene* m_pScene; // 关联的场景(组合关系,非拥有所有权) }; #endif // DOCUMENT_H