239 lines
7.5 KiB
C++
239 lines
7.5 KiB
C++
#ifndef DOCUMENT_H
|
||
#define DOCUMENT_H
|
||
|
||
#include <QString>
|
||
#include <QDateTime>
|
||
#include <QMap>
|
||
#include <QVariant>
|
||
#include <QObject>
|
||
#include <QByteArray>
|
||
|
||
/**
|
||
* @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. 如果 filename 为空且 m_filename 不为空,使用 m_filename
|
||
* 2. 序列化场景内容到 JSON 格式
|
||
* 3. 写入文件
|
||
* 4. 更新 lastSavedTime,调用 setModified(false)
|
||
* 5. 发出 saveStatusChanged 信号
|
||
*
|
||
* 注意:此方法不会更新 m_filename,仅用于覆盖已有文件
|
||
*/
|
||
bool saveToFile(const QString& filename = QString());
|
||
|
||
/**
|
||
* @brief 另存为(Save As)
|
||
* @param filename 目标文件路径
|
||
* @return 成功返回 true
|
||
*
|
||
* 另存为流程:
|
||
* 1. 序列化场景内容到 JSON 格式
|
||
* 2. 写入文件
|
||
* 3. 更新 m_filename 为目标文件路径
|
||
* 4. 更新 lastSavedTime,调用 setModified(false)
|
||
* 5. 发出 filenameChanged 和 modifiedChanged 信号
|
||
*
|
||
* 与 saveToFile() 的区别:
|
||
* - saveAsToFile() 总是会更新 m_filename
|
||
* - saveAsToFile() 适用于"另存为"操作,改变文档的默认保存路径
|
||
*/
|
||
bool saveAsToFile(const QString& filename);
|
||
|
||
/**
|
||
* @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<QString, QVariant> m_metaData; // 自定义元数据
|
||
|
||
DesignerScene* m_pScene; // 关联的场景(组合关系,非拥有所有权)
|
||
};
|
||
|
||
#endif // DOCUMENT_H
|