配置文件和项目管理exception化

This commit is contained in:
玉宇清音 2023-02-25 15:19:27 +08:00
parent 173ca0eb31
commit ce0c238b7d
8 changed files with 146 additions and 79 deletions

View File

@ -7,14 +7,36 @@
#include <QDir>
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<QString> &path) = 0;

View File

@ -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.

View File

@ -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 << "<?xml version='1.0'?>" << 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("指定配置文件:%1row:%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<QString> &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<QString> &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<QString> &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<QString> &path, const QList<QString> &list)
auto telm = rebuild_exists_elms(root, path);
auto childs = telm.childNodes();
QList<QDomNode> nodes;
for(auto idx=0; idx<childs.count(); ++idx){
for(auto idx= 0; idx<childs.count(); ++idx){
auto node = childs.at(idx);
if(node.isElement() && node.toElement().tagName() == "list")
nodes << node;
telm.removeChild(node);
}
for(auto &it : nodes)
telm.removeChild(it);
for(auto &it : list){
auto nelm = doc_ins.createElement("list");
nelm.setAttribute("value", it);
@ -132,10 +150,8 @@ void XMLConfig::setMap(const QList<QString> &path, const QHash<QString, QString>
for(auto idx=0; idx<childs.count(); ++idx){
auto child = childs.at(idx);
if(child.isElement() && child.toElement().tagName() == "map")
nodes << child;
telm.removeChild(child);
}
for(auto &it : nodes)
telm.removeChild(it);
for(auto &key : map.keys()){
auto nelm = doc_ins.createElement("map");
@ -226,9 +242,6 @@ QDomElement XMLConfig::rebuild_exists_elms(QDomElement &elm_base, const QList<QS

View File

@ -17,7 +17,7 @@ namespace Config {
// Configration interface
public:
virtual int loadFile(const QString &path) override;
virtual void loadFile(const QString &path) override;
virtual QDir currentDir() const override;
virtual void save() const override;
virtual void deleteX(const QList<QString> &path) override;

View File

@ -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){}
}

View File

@ -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 \

View File

@ -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
* </package>
* </project>
*/
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("项目文件格式错误:%1row%2col%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<ProjectNode*>(mode_holder->item(0));
auto pnode = static_cast<ProjectNode*>(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; idx<pnode->rowCount(); ++idx){
auto item = static_cast<ProjectNode*>(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<QString> &path, const QString &name, const QString &suffix)
{
auto pnode = static_cast<ProjectNode*>(mode_holder->item(0));
auto pnode = static_cast<ProjectNode*>(project_structure->item(0));
auto group = node_follows(pnode, path);
if(group == nullptr)
return -1;
@ -197,7 +218,7 @@ int XMLProjectManager::createFile(const QList<QString> &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<QString> &path, const QString &nam
bool XMLProjectManager::deletePath(const QList<QString> &path)
{
auto root_node = static_cast<ProjectNode*>(mode_holder->item(0));
auto root_node = static_cast<ProjectNode*>(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<QString> &path)
QList<std::tuple<QFileInfo, QString> > 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<ProjectNode*>(root_project), suffix);
}
QStandardItem *XMLProjectManager::newPath(const QList<QString> &path)
{
auto pnode = mode_holder->item(0);
auto pnode = project_structure->item(0);
return groups_rebuild(static_cast<ProjectNode*>(pnode), path);
}
QFileInfo XMLProjectManager::queryWith(const QList<QString> &path)
{
auto root = mode_holder->item(0);
auto root = project_structure->item(0);
auto item = node_follows(static_cast<ProjectNode*>(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<QString> &path_remains)
@ -271,7 +292,7 @@ ProjectNode *XMLProjectManager::node_follows(ProjectNode *pnode, const QList<QSt
QList<std::tuple<QFileInfo, QString> > XMLProjectManager::nodes_search(ProjectNode *pnode, const QString &suffix) const
{
auto root_dir = QFileInfo(file_path).dir();
auto root_dir = QFileInfo(filepath_store).dir();
QList<std::tuple<QFileInfo, QString>> infos_return;
for(auto idx=0; idx<pnode->rowCount(); ++idx){
@ -322,7 +343,7 @@ ProjectNode* XMLProjectManager::groups_rebuild(ProjectNode *pnode, const QList<Q
bool XMLProjectManager::moveTo(const QList<QString> &item_path, const QList<QString> &target_group, int index)
{
auto root = mode_holder->item(0);
auto root = project_structure->item(0);
auto file = node_follows(static_cast<ProjectNode*>(root), item_path);
if(file == nullptr || file->nodeType() == NodeType::GROUP)

View File

@ -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);