#include "xmlprojectmanager.h" #include #include #include #include #include #include #include using namespace Project; using namespace Config; XMLProjectManager::XMLProjectManager(QObject *parent) : Project::ProjectManager(parent), project_config(new XMLConfig(this)), mode_holder(new QStandardItemModel(this)), open_status(false){ } XMLProjectManager::~XMLProjectManager(){ delete project_config; } bool XMLProjectManager::isOpen() const { return open_status; } /* * * * * * * * */ int XMLProjectManager::openProject(const QString &project_file) { file_path = project_file; QFileInfo info(project_file); if(!info.exists()) return -1; // 获取项目文件内容 QFile project_in(project_file); if(!project_in.open(QIODevice::ReadOnly|QIODevice::Text)) return -2; // 载入文件内容 QDomDocument doc; QString err; int row, col; if(!doc.setContent(&project_in, false, &err, &row, &col)) return -3; // 构建项目组织树 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); // 载入项目配置 auto config = root_elm.attribute("config"); auto config_path = info.dir().filePath(config); project_config->loadFile(config_path); structure_parser(root_elm, pnode); open_status = true; pnode->setIcon(QIcon(":/icons/toplevel.png")); return 0; } int 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; QFileInfo info(project_file); if(info.exists()) return -1; // 构建项目表示树 auto project_node = new ProjectNode(NodeType::GROUP, name); project_node->setFile(".project_config.xml"); mode_holder->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(); } void XMLProjectManager::save() { project_config->save(); QDomDocument doc; auto pnode = static_cast(mode_holder->item(0)); doc.appendChild(doc.createProcessingInstruction("xml", "version='1.0'")); auto project_elm = doc.createElement("project"); project_elm.setAttribute("name", pnode->text()); project_elm.setAttribute("config", pnode->file()); doc.appendChild(project_elm); structure_severlize(pnode, project_elm); QFile records(file_path); if(!records.open(QIODevice::WriteOnly|QIODevice::Text)) return; QTextStream txout(&records); doc.save(txout, 4); } QString XMLProjectManager::projectName() const { return mode_holder->item(0)->text(); } Configration *XMLProjectManager::configraions() const { return this->project_config; } QStandardItemModel *XMLProjectManager::model() const { return mode_holder; } void XMLProjectManager::structure_parser(QDomElement struct_elm, ProjectNode *pnode) { auto children = struct_elm.childNodes(); for(auto idx=0; idxsetFile(xnode.attribute("path")); } pnode->appendRow(node); structure_parser(xnode, node); } } } 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"); e.setAttribute("name", item->text()); 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 root = QFileInfo(file_path).dir(); QRandomGenerator xgen(QDateTime::currentDateTime().offsetFromUtc()); QString filename = ""; do{ QString number = QString("%1").arg(xgen.generate()); filename = QString("contentfile_%1.%2").arg(number, suffix); }while(QFileInfo::exists(root.absoluteFilePath(filename))); QFile tfile(root.absoluteFilePath(filename)); if(!tfile.open(QIODevice::Text|QIODevice::WriteOnly)) return -3; tfile.close(); auto pnode = static_cast(mode_holder->item(0)); auto group = node_follows(pnode, path); if(group == nullptr) return -1; if(group->nodeType() == NodeType::FILE) return -2; auto filenode = new ProjectNode(NodeType::FILE, name); filenode->setFile(filename); group->appendRow(filenode); return 0; } bool XMLProjectManager::deletePath(const QList &path) { auto root_node = static_cast(mode_holder->item(0)); auto xnode = node_follows(root_node, path); if(xnode == nullptr) return false; xnode->parent()->removeRow(xnode->row()); return true; } QList > XMLProjectManager::filesWithEnds(const QString &suffix) const { auto root_project = mode_holder->item(0); return nodes_search(static_cast(root_project), suffix); } QStandardItem *XMLProjectManager::newPath(const QList &path) { auto pnode = mode_holder->item(0); return groups_rebuild(static_cast(pnode), path); } QFileInfo XMLProjectManager::queryWith(const QList &path) { auto root = mode_holder->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())); } ProjectNode *XMLProjectManager::node_follows(ProjectNode *pnode, const QList &path_remains) { if(path_remains.size()==0) return nullptr; for(auto idx=0; idxrowCount(); ++idx){ auto node = static_cast(pnode->child(idx)); if(node->text() == path_remains[0]){ if(path_remains.size() == 1) return node; else return node_follows(node, path_remains.mid(1)); } } return nullptr; } QList > XMLProjectManager::nodes_search(ProjectNode *pnode, const QString &suffix) const { auto root_dir = QFileInfo(file_path).dir(); QList> infos_return; for(auto idx=0; idxrowCount(); ++idx){ auto item = static_cast(pnode->child(idx)); if(item->nodeType() == NodeType::FILE){ auto file_path = root_dir.filePath(item->file()); QFileInfo xinfo(file_path); if(xinfo.suffix() == suffix) infos_return << std::make_tuple(xinfo, item->text()); } else{ auto elist = nodes_search(item, suffix); infos_return.append(elist); } } return infos_return; } ProjectNode* XMLProjectManager::groups_rebuild(ProjectNode *pnode, const QList &path_remains) { // 查找对匹配结果 for(auto idx=0; idxrowCount(); ++idx){ auto item = static_cast(pnode->child(idx)); if(item->text() == path_remains[0] && item->nodeType() == NodeType::GROUP){ if(path_remains.size() > 1) return groups_rebuild(item, path_remains.mid(1)); return item; } } auto item = new ProjectNode(NodeType::GROUP, path_remains[0]); pnode->appendRow(item); if(path_remains.size() > 1) return groups_rebuild(item, path_remains.mid(1)); return item; } // 完成线 ======================================================================================================= bool XMLProjectManager::moveTo(const QList &item_path, const QList &target_group, int index) { auto root = mode_holder->item(0); auto file = node_follows(static_cast(root), item_path); if(file == nullptr || file->nodeType() == NodeType::GROUP) return false; auto group = node_follows(static_cast(root), target_group); if(group->rowCount() <= index) group->insertRow(index, file); else group->appendRow(file); return true; } ProjectNode::ProjectNode(NodeType t, const QString &name) : QStandardItem(name),type_indi(t) { if(t == NodeType::FILE) { setIcon(QIcon(":/icons/文件.png")); } else { setIcon(QIcon(":/icons/集合.png")); } setEditable(false); } NodeType ProjectNode::nodeType() const {return type_indi;} void ProjectNode::setFile(const QString &name) { this->filename = name; if(name.endsWith("storychain")) setIcon(QIcon(":/icons/脉络.png")); if(name.endsWith("storyunit")) setIcon(QIcon(":/icons/单元.png")); if(name.endsWith("storyboard")) setIcon(QIcon(":/icons/故事.png")); if(name.endsWith("storyvolume")) setIcon(QIcon(":/icons/叙述.png")); if(name.endsWith("txt")) setIcon(QIcon(":/icons/文件.png")); if(name.endsWith("storyconcept")) setIcon(QIcon(":/icons/概念.png")); } QString ProjectNode::file() const {return filename;}