diff --git a/libConfig/libConfig.h b/libConfig/libConfig.h index 2298686..d4b32db 100644 --- a/libConfig/libConfig.h +++ b/libConfig/libConfig.h @@ -7,14 +7,36 @@ #include namespace Config { + /** + * @brief 配置文件解析过程异常 + */ + class ParseException: public std::exception + { + public: + virtual QString reason() const = 0; + virtual QString title() const = 0; + }; + + /** + * @brief 配置读写交互端口 + */ class Configration : public QObject { public: explicit Configration(QObject *parent); virtual ~Configration() = default; - virtual int loadFile(const QString &path) = 0; + /** + * @brief 载入配置文件 + * @param path 指定配置文件路径 + * @throw ParseException* 配置文件解析异常 + */ + virtual void loadFile(const QString &path) = 0; virtual QDir currentDir() const = 0; + /** + * @brief 保存配置内容会原始配置文件 + * @throws ParseException* 保存过程中异常 + */ virtual void save() const = 0; virtual void deleteX(const QList &path) = 0; diff --git a/libConfig/libConfig.pro b/libConfig/libConfig.pro index f42a27b..1d09805 100644 --- a/libConfig/libConfig.pro +++ b/libConfig/libConfig.pro @@ -5,6 +5,7 @@ TEMPLATE = lib DEFINES += LIBCONFIG_LIBRARY CONFIG += c++11 +CONFIG += exceptions # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. diff --git a/libConfig/xmlconfig.cpp b/libConfig/xmlconfig.cpp index fd21351..19c5032 100644 --- a/libConfig/xmlconfig.cpp +++ b/libConfig/xmlconfig.cpp @@ -5,17 +5,41 @@ using namespace Config; +class Impl_ParseException : public ParseException +{ +public: + Impl_ParseException(const QString &title, const QString &reason) + : reason_store(reason), title_store(title){} + virtual ~Impl_ParseException() = default; + // exception interface +public: + virtual const char *what() const override{ + return reason_store.toLocal8Bit();} + + // ParseException interface +public: + virtual QString reason() const override{ return reason_store;} + virtual QString title() const override{ return title_store;} + +private: + QString reason_store; + QString title_store; +}; + + + XMLConfig::XMLConfig(QObject *parent) : Configration(parent) { } -int XMLConfig::loadFile(const QString &path) +void XMLConfig::loadFile(const QString &path) { file_path = path; QFile config(path); if(!config.exists()){ - config.open(QIODevice::WriteOnly); + if(!config.open(QIODevice::WriteOnly|QIODevice::Text)) + throw new Impl_ParseException("解析错误", QString("指定路径无法创建配置文件:%1").arg(path)); QTextStream tout(&config); tout << "" << endl; @@ -27,16 +51,12 @@ int XMLConfig::loadFile(const QString &path) } - if(!config.open(QIODevice::Text|QIODevice::ReadOnly)){ - return -1; - } + if(!config.open(QIODevice::Text|QIODevice::ReadOnly)) + throw new Impl_ParseException("解析错误", QString("指定路径:%1,配置文件无法打开").arg(path)); QString err_str; int err_row, err_col; - if(doc_ins.setContent(&config, false, &err_str, &err_row, &err_col)){ - return -2; - } - - return 0; + if(doc_ins.setContent(&config, false, &err_str, &err_row, &err_col)) + throw new Impl_ParseException("解析错误", QString("指定配置文件:%1,row:%2,col:%3,格式错误。").arg(err_col).arg(err_row).arg(err_col)); } QDir XMLConfig::currentDir() const @@ -47,10 +67,9 @@ QDir XMLConfig::currentDir() const void XMLConfig::save() const { QFile fout(this->file_path); - if(!fout.open(QIODevice::WriteOnly | QIODevice::Text)){ - qDebug() << "配置文件保存错误" << QString("指定配置文件%1保存过程中,无法打开").arg(file_path); - return; - } + if(!fout.open(QIODevice::WriteOnly | QIODevice::Text)) + throw new Impl_ParseException("配置文件保存错误", QString("指定配置文件%1保存过程中,无法打开").arg(file_path)); + QTextStream tout(&fout); tout << this->doc_ins.toString(4); tout.flush(); @@ -63,6 +82,7 @@ void XMLConfig::deleteX(const QList &path) auto elm = local_exists_elm(doc_ins.documentElement(), path); if(elm.isNull()) return; + elm.parentNode().removeChild(elm); } @@ -70,6 +90,7 @@ void XMLConfig::setConfig(const QList &path, const QString &value) { auto doc = doc_ins.documentElement(); auto elm = rebuild_exists_elms(doc, path); + elm.setAttribute("value", value); } @@ -78,6 +99,7 @@ QString XMLConfig::getConfig(const QList &path) const auto elm = local_exists_elm(doc_ins.documentElement(), path); if(elm.isNull()) return ""; + return elm.attribute("value"); } @@ -87,17 +109,13 @@ void XMLConfig::setList(const QList &path, const QList &list) auto telm = rebuild_exists_elms(root, path); auto childs = telm.childNodes(); - QList nodes; - for(auto idx=0; idx &path, const QHash for(auto idx=0; idx &path) override; diff --git a/libProjectManager/libProjectManager.h b/libProjectManager/libProjectManager.h index 412e22b..8468d42 100644 --- a/libProjectManager/libProjectManager.h +++ b/libProjectManager/libProjectManager.h @@ -9,6 +9,11 @@ namespace Project { + /** + * @brief 项目解析过程异常 + */ + class ProjectException : public Config::ParseException { }; + /** * @brief 项目管理 * 项目名称 @@ -17,10 +22,9 @@ namespace Project { * ==包名称 * ==包名称 */ - class ProjectManager : public QObject + class ProjectManager { public: - ProjectManager(QObject *pins); virtual ~ProjectManager() = default; // 项目操作========================================================= @@ -33,22 +37,23 @@ namespace Project { /** * @brief 载入项目组织文件 * @param project_file 组织文件路径 - * @return 0-成功,<0各种失败原因 + * @throw ProjectException, ParseException */ - virtual int openProject(const QString &project_file) = 0; + virtual void openProject(const QString &project_file) = 0; /** * @brief 指定项目文件夹,建立项目文件,一个文件夹只能建立一个项目 * @param project_dir 项目文件夹 * @param name 项目文件名 - * @return 0-成功,<0各种失败原因 + * @throw ProjectException, ParseException */ - virtual int newProject(const QString &project_dir, const QString &name) = 0; + virtual void newProject(const QString &project_dir, const QString &name) = 0; /** * @brief 关闭当前项目 */ virtual void closeProject() = 0; /** * @brief save 保存当前项目 + * @throw ProjectException, ParseException */ virtual void save() = 0; /** @@ -115,7 +120,6 @@ namespace Project { }; - inline ProjectManager::ProjectManager(QObject *pins):QObject(pins){} } diff --git a/libProjectManager/libProjectManager.pro b/libProjectManager/libProjectManager.pro index 221061d..ed96f73 100644 --- a/libProjectManager/libProjectManager.pro +++ b/libProjectManager/libProjectManager.pro @@ -5,6 +5,7 @@ TEMPLATE = lib DEFINES += LIBPROJECTMANAGER_LIBRARY CONFIG += c++11 +CONFIG += exceptions # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. @@ -13,6 +14,11 @@ CONFIG += c++11 SOURCES += \ xmlprojectmanager.cpp +msvc{ + QMAKE_CXXFLAGS += /utf-8 + QMAKE_CFLAGS += /utf-8 +} + HEADERS += \ libProjectManager.h \ libProjectManager_global.h \ diff --git a/libProjectManager/xmlprojectmanager.cpp b/libProjectManager/xmlprojectmanager.cpp index 32a8434..a5fadad 100644 --- a/libProjectManager/xmlprojectmanager.cpp +++ b/libProjectManager/xmlprojectmanager.cpp @@ -11,10 +11,31 @@ using namespace Project; using namespace Config; +class Impl_ProjectException : public ProjectException +{ +public: + Impl_ProjectException(const QString& title, const QString& reason) + : reason_store(reason), title_store(title) {} + +private: + QString reason_store; + QString title_store; + + // exception interface +public: + virtual const char *what() const override{return reason_store.toLocal8Bit();} + + // ParseException interface +public: + virtual QString reason() const override{ return reason_store;} + virtual QString title() const override{return title_store;} +}; + + XMLProjectManager::XMLProjectManager(QObject *parent) - : Project::ProjectManager(parent), + : QObject(parent), project_config(new XMLConfig(this)), - mode_holder(new QStandardItemModel(this)), + project_structure(new QStandardItemModel(this)), open_status(false){ } XMLProjectManager::~XMLProjectManager(){ @@ -35,30 +56,30 @@ bool XMLProjectManager::isOpen() const * * */ -int XMLProjectManager::openProject(const QString &project_file) +void XMLProjectManager::openProject(const QString &project_file) { - file_path = project_file; + filepath_store = project_file; QFileInfo info(project_file); if(!info.exists()) - return -1; + throw new Impl_ProjectException("打开失败", "指定的项目文件不存在:"+project_file); // 获取项目文件内容 QFile project_in(project_file); if(!project_in.open(QIODevice::ReadOnly|QIODevice::Text)) - return -2; + throw new Impl_ProjectException("打开失败", "指定的项目文件无法打开:" + project_file); // 载入文件内容 QDomDocument doc; QString err; int row, col; if(!doc.setContent(&project_in, false, &err, &row, &col)) - return -3; + throw new Impl_ProjectException("打开失败", QString("项目文件格式错误:%1,row:%2,col:%3").arg(err).arg(row).arg(col)); // 构建项目组织树 auto root_elm = doc.documentElement(); auto name = root_elm.attribute("name"); auto pnode = new ProjectNode(NodeType::GROUP, name); pnode->setFile(root_elm.attribute("config")); - mode_holder->appendRow(pnode); + project_structure->appendRow(pnode); // 载入项目配置 auto config = root_elm.attribute("config"); @@ -69,38 +90,37 @@ int XMLProjectManager::openProject(const QString &project_file) open_status = true; pnode->setIcon(QIcon(":/icons/toplevel.png")); - return 0; } -int XMLProjectManager::newProject(const QString &project_dir, const QString &name) +void XMLProjectManager::newProject(const QString &project_dir, const QString &name) { // 确定目标项目文件 QDir root(project_dir); QDir::setCurrent(root.path()); - auto project_file = root.filePath(name+".nsf"); - file_path = project_file; + auto project_file = root.filePath(name + ".nsf"); + filepath_store = project_file; QFileInfo info(project_file); if(info.exists()) - return -1; + throw new Impl_ProjectException("新建错误", "指定路径的项目文件已经存在,无法构建新项目"); // 构建项目表示树 auto project_node = new ProjectNode(NodeType::GROUP, name); project_node->setFile(".project_config.xml"); - mode_holder->appendRow(project_node); + project_structure->appendRow(project_node); + project_config->loadFile(root.filePath(project_node->file())); // 写出到磁盘 save(); open_status = true; project_node->setIcon(QIcon(":/icons/toplevel.png")); - return 0; } void XMLProjectManager::closeProject() { open_status = false; - mode_holder->clear(); + project_structure->clear(); } void XMLProjectManager::save() @@ -108,7 +128,7 @@ void XMLProjectManager::save() project_config->save(); QDomDocument doc; - auto pnode = static_cast(mode_holder->item(0)); + auto pnode = static_cast(project_structure->item(0)); doc.appendChild(doc.createProcessingInstruction("xml", "version='1.0'")); auto project_elm = doc.createElement("project"); project_elm.setAttribute("name", pnode->text()); @@ -117,17 +137,18 @@ void XMLProjectManager::save() structure_severlize(pnode, project_elm); - QFile records(file_path); + QFile records(filepath_store); if(!records.open(QIODevice::WriteOnly|QIODevice::Text)) - return; + throw new Impl_ProjectException("保存错误", "保存过程中,指定项目文件无法打开保存:" + filepath_store); QTextStream txout(&records); doc.save(txout, 4); + txout.flush(); } QString XMLProjectManager::projectName() const { - return mode_holder->item(0)->text(); + return project_structure->item(0)->text(); } Configration *XMLProjectManager::configraions() const @@ -137,7 +158,7 @@ Configration *XMLProjectManager::configraions() const QStandardItemModel *XMLProjectManager::model() const { - return mode_holder; + return project_structure; } void XMLProjectManager::structure_parser(QDomElement struct_elm, ProjectNode *pnode) @@ -149,18 +170,16 @@ void XMLProjectManager::structure_parser(QDomElement struct_elm, ProjectNode *pn if(node.isElement()){ auto xnode = node.toElement(); - ProjectNode *node = nullptr; if(xnode.tagName()=="package"){ node = new ProjectNode(NodeType::GROUP, xnode.attribute("name")); } - else{ + else if(xnode.tagName() == "file"){ node = new ProjectNode(NodeType::FILE, xnode.attribute("name")); node->setFile(xnode.attribute("path")); } pnode->appendRow(node); - structure_parser(xnode, node); } } @@ -171,21 +190,23 @@ void XMLProjectManager::structure_severlize(ProjectNode *pnode, QDomElement &elm auto doc = elm.ownerDocument(); for(auto idx=0; idxrowCount(); ++idx){ auto item = static_cast(pnode->child(idx)); - QDomElement e = doc.createElement("file"); - if(item->nodeType() == NodeType::GROUP) - e.setTagName("package"); + QDomElement e = doc.createElement("package"); e.setAttribute("name", item->text()); - e.setAttribute("path", item->file()); - elm.appendChild(e); + if(item->nodeType() == NodeType::FILE){ + e.setTagName("file"); + e.setAttribute("path", item->file()); + } + + elm.appendChild(e); structure_severlize(item, e); } } int XMLProjectManager::createFile(const QList &path, const QString &name, const QString &suffix) { - auto pnode = static_cast(mode_holder->item(0)); + auto pnode = static_cast(project_structure->item(0)); auto group = node_follows(pnode, path); if(group == nullptr) return -1; @@ -197,7 +218,7 @@ int XMLProjectManager::createFile(const QList &path, const QString &nam if(group->child(idx)->text() == name) return -3; - auto root = QFileInfo(file_path).dir(); + auto root = QFileInfo(filepath_store).dir(); QRandomGenerator xgen(QDateTime::currentDateTime().offsetFromUtc()); QString filename = ""; @@ -219,7 +240,7 @@ int XMLProjectManager::createFile(const QList &path, const QString &nam bool XMLProjectManager::deletePath(const QList &path) { - auto root_node = static_cast(mode_holder->item(0)); + auto root_node = static_cast(project_structure->item(0)); auto xnode = node_follows(root_node, path); if(xnode == nullptr) return false; @@ -230,25 +251,25 @@ bool XMLProjectManager::deletePath(const QList &path) QList > XMLProjectManager::filesWithEnds(const QString &suffix) const { - auto root_project = mode_holder->item(0); + auto root_project = project_structure->item(0); return nodes_search(static_cast(root_project), suffix); } QStandardItem *XMLProjectManager::newPath(const QList &path) { - auto pnode = mode_holder->item(0); + auto pnode = project_structure->item(0); return groups_rebuild(static_cast(pnode), path); } QFileInfo XMLProjectManager::queryWith(const QList &path) { - auto root = mode_holder->item(0); + auto root = project_structure->item(0); auto item = node_follows(static_cast(root), path); if(item == nullptr || item->nodeType() == NodeType::GROUP) return QFileInfo(); - return QFileInfo(QFileInfo(file_path).dir().filePath(item->file())); + return QFileInfo(QFileInfo(filepath_store).dir().filePath(item->file())); } ProjectNode *XMLProjectManager::node_follows(ProjectNode *pnode, const QList &path_remains) @@ -271,7 +292,7 @@ ProjectNode *XMLProjectManager::node_follows(ProjectNode *pnode, const QList > XMLProjectManager::nodes_search(ProjectNode *pnode, const QString &suffix) const { - auto root_dir = QFileInfo(file_path).dir(); + auto root_dir = QFileInfo(filepath_store).dir(); QList> infos_return; for(auto idx=0; idxrowCount(); ++idx){ @@ -322,7 +343,7 @@ ProjectNode* XMLProjectManager::groups_rebuild(ProjectNode *pnode, const QList &item_path, const QList &target_group, int index) { - auto root = mode_holder->item(0); + auto root = project_structure->item(0); auto file = node_follows(static_cast(root), item_path); if(file == nullptr || file->nodeType() == NodeType::GROUP) diff --git a/libProjectManager/xmlprojectmanager.h b/libProjectManager/xmlprojectmanager.h index 8c4db42..ef87d1e 100644 --- a/libProjectManager/xmlprojectmanager.h +++ b/libProjectManager/xmlprojectmanager.h @@ -32,7 +32,7 @@ namespace Project { class LIBPROJECTMANAGER_EXPORT XMLProjectManager - : public Project::ProjectManager + : public QObject, public Project::ProjectManager { public: XMLProjectManager(QObject *parent = nullptr); @@ -42,8 +42,8 @@ namespace Project { // ProjectManager interface public: virtual bool isOpen() const override; - virtual int openProject(const QString &project_file) override; - virtual int newProject(const QString &project_dir, const QString &name) override; + virtual void openProject(const QString &project_file) override; + virtual void newProject(const QString &project_dir, const QString &name) override; virtual void closeProject() override; virtual void save() override; virtual QString projectName() const override; @@ -61,8 +61,8 @@ namespace Project { private: Config::Configration *const project_config; - QStandardItemModel*const mode_holder; - QString file_path; + QStandardItemModel*const project_structure; + QString filepath_store; bool open_status; void structure_parser(QDomElement struct_elm, ProjectNode *pnode);