QtNovelUI/libProjectManager/xmlprojectmanager.cpp

401 lines
10 KiB
C++
Raw Normal View History

2022-11-17 08:26:05 +00:00
#include "xmlprojectmanager.h"
#include <xmlconfig.h>
#include <QDir>
#include <QRandomGenerator>
#include <QDateTime>
#include <QTextStream>
#include <QCoreApplication>
#include <QIcon>
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;
}
/*
* <?xml version='1.0'?>
* <project name="project-name" config="xml-path">
* <package name="name" path="filepath">
* <file name="name" path="filepath"/>
* <package name="name2" path="filepath" />
* </package>
* </project>
*/
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<ProjectNode*>(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; idx<children.count(); ++idx) {
auto node = children.at(idx);
if(node.isElement()){
auto xnode = node.toElement();
ProjectNode *node = nullptr;
if(xnode.tagName()=="package"){
node = new ProjectNode(NodeType::GROUP, xnode.attribute("name"));
}
else{
node = new ProjectNode(NodeType::FILE, xnode.attribute("name"));
node->setFile(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; 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");
e.setAttribute("name", item->text());
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)
{
2022-11-29 03:47:12 +00:00
auto pnode = static_cast<ProjectNode*>(mode_holder->item(0));
auto group = node_follows(pnode, path);
if(group == nullptr)
return -1;
if(group->nodeType() == NodeType::FILE)
return -2;
for(auto idx=0; idx<group->rowCount(); ++idx)
if(group->child(idx)->text() == name)
return -3;
2022-11-17 08:26:05 +00:00
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 filenode = new ProjectNode(NodeType::FILE, name);
filenode->setFile(filename);
group->appendRow(filenode);
return 0;
}
bool XMLProjectManager::deletePath(const QList<QString> &path)
{
auto root_node = static_cast<ProjectNode*>(mode_holder->item(0));
auto xnode = node_follows(root_node, path);
if(xnode == nullptr)
return false;
xnode->parent()->removeRow(xnode->row());
return true;
}
QList<std::tuple<QFileInfo, QString> > XMLProjectManager::filesWithEnds(const QString &suffix) const
2022-11-17 08:26:05 +00:00
{
auto root_project = mode_holder->item(0);
return nodes_search(static_cast<ProjectNode*>(root_project), suffix);
}
QStandardItem *XMLProjectManager::newPath(const QList<QString> &path)
{
auto pnode = mode_holder->item(0);
return groups_rebuild(static_cast<ProjectNode*>(pnode), path);
}
QFileInfo XMLProjectManager::queryWith(const QList<QString> &path)
{
auto root = mode_holder->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()));
}
ProjectNode *XMLProjectManager::node_follows(ProjectNode *pnode, const QList<QString> &path_remains)
{
if(path_remains.size()==0)
return nullptr;
for(auto idx=0; idx<pnode->rowCount(); ++idx){
auto node = static_cast<ProjectNode*>(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<std::tuple<QFileInfo, QString> > XMLProjectManager::nodes_search(ProjectNode *pnode, const QString &suffix) const
2022-11-17 08:26:05 +00:00
{
auto root_dir = QFileInfo(file_path).dir();
QList<std::tuple<QFileInfo, QString>> infos_return;
2022-11-17 08:26:05 +00:00
for(auto idx=0; idx<pnode->rowCount(); ++idx){
auto item = static_cast<ProjectNode*>(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());
2022-11-17 08:26:05 +00:00
}
else{
auto elist = nodes_search(item, suffix);
infos_return.append(elist);
}
}
return infos_return;
}
ProjectNode* XMLProjectManager::groups_rebuild(ProjectNode *pnode, const QList<QString> &path_remains)
{
// 查找对匹配结果
for(auto idx=0; idx<pnode->rowCount(); ++idx){
auto item = static_cast<ProjectNode*>(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<QString> &item_path, const QList<QString> &target_group, int index)
{
auto root = mode_holder->item(0);
auto file = node_follows(static_cast<ProjectNode*>(root), item_path);
if(file == nullptr || file->nodeType() == NodeType::GROUP)
return false;
auto group = node_follows(static_cast<ProjectNode*>(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"));
2022-11-17 08:26:05 +00:00
}
QString ProjectNode::file() const
{return filename;}