From d3f0438af47d2c9ed6fa5b5696f14b165ffb300b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=89=E5=AE=87=E6=B8=85=E9=9F=B3?= <2422523675@qq.com> Date: Fri, 9 Dec 2022 03:43:42 +0800 Subject: [PATCH] save --- DesParser/example.storyunit | 4 +- DesParser/main.cpp | 2 +- QtNovelDesc.pro.user | 2 +- WordsIDE/WordsIDE.pro | 2 + WordsIDE/fragmentsorderview.cpp | 77 ++++++++++++++++ WordsIDE/fragmentsorderview.h | 31 +++++++ WordsIDE/mainwindow.cpp | 15 ++- WordsIDE/mainwindow.h | 2 + libParse/StoryBoardDocumentParser.cpp | 35 ++++++- libParse/StoryBoardDocumentParser.h | 3 + libParse/StoryChainDocumentParser.cpp | 5 +- libParse/StoryOutlineDocumentParser.cpp | 3 +- libParse/StoryTool.cpp | 6 +- libParse/StoryTool.h | 2 + libParse/StoryUnitDocumentParser.cpp | 116 ++++++++---------------- libParse/StoryUnitDocumentParser.h | 6 +- libParse/libParse.cpp | 30 ++++++ libParse/libParse.h | 17 +++- libParse/libParse.pro | 2 + libParse/parsechecks.cpp | 49 ++++++++++ libParse/parsechecks.h | 47 ++++++++++ libParse/storyconceptdocumentparser.cpp | 4 +- 22 files changed, 361 insertions(+), 99 deletions(-) create mode 100644 WordsIDE/fragmentsorderview.cpp create mode 100644 WordsIDE/fragmentsorderview.h create mode 100644 libParse/parsechecks.cpp create mode 100644 libParse/parsechecks.h diff --git a/DesParser/example.storyunit b/DesParser/example.storyunit index 5f30eed..ccdcbad 100644 --- a/DesParser/example.storyunit +++ b/DesParser/example.storyunit @@ -1,7 +1,7 @@ #单元 中南世界的故事片段 { 中南世界,主角从一个小角色,逐渐混成大佬的事迹。 - #情节 故事的开端{ + #情节 故事的开端 19201202{ 中南世界的街头,异常热闹的故事开场{@节点 示例脉络 示例节点},主角从这里出发 } } @@ -9,7 +9,7 @@ { 中南世界,主角从一个小角色,逐渐混成大佬的事迹。 asfjlakdjf;aldkjf;aldsf - #情节 故事的开端{ + #情节 故事的开端 16601045{ 中南世界的街头,异常热闹的故事开场{@节点 示例脉络 示例节点},主角从这里出发 } } diff --git a/DesParser/main.cpp b/DesParser/main.cpp index 3aeda15..9c5a6b4 100644 --- a/DesParser/main.cpp +++ b/DesParser/main.cpp @@ -40,7 +40,7 @@ int main(int argc, char *argv[]) MakeTools::StoryTool tool(&core); // auto path = "D:\\Projects\\Cpp\\QtNovelDesc\\DesParser\\example.storyvolume"; - auto path = "D:\\Projects\\Cpp\\QtNovelDesc\\DesParser\\example.storyconcept"; + auto path = "D:\\Projects\\Cpp\\QtNovelDesc\\DesParser\\example.storyunit"; tool.compile(QFileInfo(path), "后台编译"); auto doc = core.queryDocument(QFileInfo(path)); diff --git a/QtNovelDesc.pro.user b/QtNovelDesc.pro.user index 6bce140..f8748d8 100644 --- a/QtNovelDesc.pro.user +++ b/QtNovelDesc.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/WordsIDE/WordsIDE.pro b/WordsIDE/WordsIDE.pro index 6d3cd60..c9febe3 100644 --- a/WordsIDE/WordsIDE.pro +++ b/WordsIDE/WordsIDE.pro @@ -13,6 +13,7 @@ SOURCES += \ SensitiveCore.cpp \ SourceEditView.cpp \ appcore.cpp \ + fragmentsorderview.cpp \ keywordshightlighter.cpp \ main.cpp \ mainwindow.cpp \ @@ -34,6 +35,7 @@ HEADERS += \ SensitiveCore.h \ SourceEditView.h \ appcore.h \ + fragmentsorderview.h \ keywordshightlighter.h \ mainwindow.h \ messagepresent.h \ diff --git a/WordsIDE/fragmentsorderview.cpp b/WordsIDE/fragmentsorderview.cpp new file mode 100644 index 0000000..313eb4e --- /dev/null +++ b/WordsIDE/fragmentsorderview.cpp @@ -0,0 +1,77 @@ +#include "fragmentsorderview.h" +#include "SensitiveCore.h" +#include +#include +#include + +using namespace Components; +using namespace Parse; + +FragmentsOrderView::FragmentsOrderView(Core::AppCore *core, QWidget *parent) + : QWidget(parent), core_ins(core), table_view(new QTableView(this)), + table_base(new QStandardItemModel(this)) +{ + this->table_view->setModel(table_base); + table_base->setHorizontalHeaderLabels(QStringList() << "情节名称" << "单元名称" << "索引值"); + + auto layout = new QVBoxLayout(this); + layout->addWidget(table_view); + connect(this->table_view, &QTableView::doubleClicked, this, &FragmentsOrderView::double_click); +} + +void FragmentsOrderView::refresh() +{ + table_base->clear(); + table_base->setHorizontalHeaderLabels(QStringList() << "情节名称" << "单元名称" << "索引值"); + + auto node_list = core_ins->parseCore()->queryOrdersFragment(); + + for(auto &ins : node_list){ + QList row; + row << new QStandardItem(ins.first->name()[0]); + row << new QStandardItem(ins.first->name()[1]); + row << new QStandardItem(QString("%1").arg(ins.second, 8, 'f')); + + for(auto &i : row) i->setEditable(false); + + table_base->appendRow(row); + } +} + +void FragmentsOrderView::double_click(const QModelIndex &index) +{ + if(!index.isValid()) + return; + + auto frag = table_base->item(index.row()); + auto unit = table_base->item(index.row(), 1); + + QList path; + path << unit->text() << frag->text(); + + + auto unit_ins = this->core_ins->parseCore()->queryStoryUnit(path[0]).first(); + auto unit_doc = unit_ins->doc(); + this->core_ins->openTextDocument(unit_doc->filePath(), unit_doc->docName()); + auto present = this->core_ins->getFramework()->queryTextComponent(QFileInfo(unit_doc->filePath())); + + if(path.size()){ + present->jumpTo(path); + } +} + + + + + + + + + + + + + + + + diff --git a/WordsIDE/fragmentsorderview.h b/WordsIDE/fragmentsorderview.h new file mode 100644 index 0000000..c7d49f6 --- /dev/null +++ b/WordsIDE/fragmentsorderview.h @@ -0,0 +1,31 @@ +#ifndef FRAGMENTSORDERVIEW_H +#define FRAGMENTSORDERVIEW_H + +#include +#include +#include +#include +#include "appcore.h" + +namespace Components { + + class FragmentsOrderView : public QWidget + { + Q_OBJECT + public: + explicit FragmentsOrderView(Core::AppCore *core, QWidget *parent = nullptr); + + void refresh(); + + void double_click(const QModelIndex &index); + + private: + Core::AppCore *const core_ins; + QTableView *const table_view; + QStandardItemModel *const table_base; + + }; +} + + +#endif // FRAGMENTSORDERVIEW_H diff --git a/WordsIDE/mainwindow.cpp b/WordsIDE/mainwindow.cpp index daca349..c0a679d 100644 --- a/WordsIDE/mainwindow.cpp +++ b/WordsIDE/mainwindow.cpp @@ -45,7 +45,8 @@ MainWindow::MainWindow(QWidget *parent) units_view(new StoryUnitsPresent(app_core, this)), errors_present(new MessagePresent(app_core->getMake_tool(), this)), boards_view(new StoryBoardsPresent(app_core, this)), - concept_view(new StoryConceptsPresent(app_core, this)) + concept_view(new StoryConceptsPresent(app_core, this)), + fragments_order(new FragmentsOrderView(app_core, this)) { QApplication::instance()->installEventFilter(this); this->app_core->setCurrentProject(project_manager); @@ -58,6 +59,7 @@ MainWindow::MainWindow(QWidget *parent) errors_present->setVisible(false); boards_view->setVisible(false); concept_view->setVisible(false); + fragments_order->setVisible(false); project_structure->setVisible(false); left_funcs->setVisible(false); right_funcs->setVisible(false); @@ -277,6 +279,15 @@ MainWindow::MainWindow(QWidget *parent) sync_kernel->registerAutoRun([this]()->bool{return right_funcs->indexOf(concept_view)!=-1;}, [concept_v](bool v){if(v != concept_v->isChecked()) concept_v->setChecked(v);}); } + // 情节序列 + { + auto fragments_v = func->addAction("情节序列", [this](bool v){ + toggle_widget_visible(v, right_funcs, fragments_order, "情节序列"); + }); + fragments_v->setCheckable(true); + sync_kernel->registerAutoRun([this]()->bool{return right_funcs->indexOf(fragments_order)!=-1;}, + [fragments_v](bool v){if(v != fragments_v->isChecked()) fragments_v->setChecked(v);}); + } // 工具菜单 auto tool = mbar->addMenu("工具"); @@ -361,6 +372,7 @@ MainWindow::MainWindow(QWidget *parent) this->errors_present->refresh(); this->boards_view->refresh(); this->concept_view->refresh(); + this->fragments_order->refresh(); }); @@ -425,6 +437,7 @@ void MainWindow::build_internal(bool all_from_disk) units_view->refresh(); boards_view->refresh(); concept_view->refresh(); + fragments_order->refresh(); } void MainWindow::toggle_widget_visible(bool visible, QTabWidget *con, QWidget *target, const QString &title) diff --git a/WordsIDE/mainwindow.h b/WordsIDE/mainwindow.h index a8cf670..4360f87 100644 --- a/WordsIDE/mainwindow.h +++ b/WordsIDE/mainwindow.h @@ -16,6 +16,7 @@ #include "ContentPresent.h" #include "storyboardspresent.h" #include "storyconceptspresent.h" +#include "fragmentsorderview.h" #include "tools.h" class MainWindow : public QMainWindow @@ -49,6 +50,7 @@ private: Components::MessagePresent *const errors_present; Components::StoryBoardsPresent *const boards_view; Components::StoryConceptsPresent *const concept_view; + Components::FragmentsOrderView *const fragments_order; // 内部逻辑 =========================================== void build_internal(bool all_from_disk = false); diff --git a/libParse/StoryBoardDocumentParser.cpp b/libParse/StoryBoardDocumentParser.cpp index 50e0ee4..a6e53fc 100644 --- a/libParse/StoryBoardDocumentParser.cpp +++ b/libParse/StoryBoardDocumentParser.cpp @@ -18,7 +18,12 @@ void NodeStoryBoard::setIndex(const QString &val) QString NodeStoryBoard::index() const { - return index_store; + return this->index_store; +} + +int NodeStoryBoard::indexValue(bool &valid) const +{ + return index_store.toInt(&valid); } bool NodeStoryBoard::check(QList &reasons) const @@ -26,7 +31,7 @@ bool NodeStoryBoard::check(QList &reasons) const auto nodes = doc()->core()->queryStoryBoard(name()[0]); if(nodes.size() > 1){ - ErrorMessage ins; + ErrorMessage ins(this); ins.Reason = "重复定义大纲"; ins.Text = name()[0]; ins.FilePath = doc()->filePath(); @@ -35,12 +40,27 @@ bool NodeStoryBoard::check(QList &reasons) const reasons << ins; } + bool is_valid = false; + indexValue(is_valid); + if(!is_valid){ + ErrorMessage msg(this); + msg.CodeRow = refered().first()->row(); + msg.CodeCol = refered().first()->column(); + msg.FilePath = doc()->filePath(); + msg.Text = index(); + msg.Reason = "指定故事编排索引格式错误"; + + reasons << msg; + return false; + } + return nodes.size() == 1; } QString NodeStoryBoard::toString() const { - QString des = "#故事 "+name()[0] + " " + index() +" {"; + bool ignore; + QString des = "#故事 "+name()[0] + " " + QString("%1").arg(indexValue(ignore)) +" {"; for(auto n : children()) des += "\n" + n->toString(); des += "\n}"; @@ -59,11 +79,16 @@ QString NodeStoryFragmentRefer::unit() const{ return this->unit_name_store; } +QString NodeStoryFragmentRefer::fragment() const +{ + return this->fragment_name; +} + bool NodeStoryFragmentRefer::check(QList &reasons) const { auto unitx = doc()->core()->queryStoryUnit(unit()); if(!unitx.size()){ - ErrorMessage ins; + ErrorMessage ins(this); ins.Reason = "指定的单元不存在"; ins.Text = unit(); ins.FilePath = doc()->filePath(); @@ -75,7 +100,7 @@ bool NodeStoryFragmentRefer::check(QList &reasons) const auto fragment = doc()->core()->queryStoryFragment(unitx[0], name()[0]); if(!fragment.size()){ - ErrorMessage ins; + ErrorMessage ins(this); ins.Reason = "指定的情节不存在"; ins.Text = unit() + ":" + name()[0]; ins.FilePath = doc()->filePath(); diff --git a/libParse/StoryBoardDocumentParser.h b/libParse/StoryBoardDocumentParser.h index 646ab04..192e1dd 100644 --- a/libParse/StoryBoardDocumentParser.h +++ b/libParse/StoryBoardDocumentParser.h @@ -19,6 +19,7 @@ namespace Parse { void setIndex(const QString &val); QString index() const; + int indexValue(bool &valid) const; // DesNode interface public: @@ -58,6 +59,8 @@ namespace Parse { void setUnit(const QString &name); QString unit() const; + QString fragment() const; + // DesNode interface public: virtual bool check(QList &reasons) const override; diff --git a/libParse/StoryChainDocumentParser.cpp b/libParse/StoryChainDocumentParser.cpp index 7d27ee1..0eb4fde 100644 --- a/libParse/StoryChainDocumentParser.cpp +++ b/libParse/StoryChainDocumentParser.cpp @@ -155,7 +155,7 @@ bool NodeStoryChain::check(QList &reasons) const { auto nodes = doc()->core()->queryStoryChain(name()[0]); if(nodes.size() > 1){ - ErrorMessage ins; + ErrorMessage ins(this); ins.Reason = "重复定义脉络"; ins.Text = name()[0]; ins.FilePath = doc()->filePath(); @@ -190,7 +190,8 @@ bool NodeStoryPoint::check(QList &reasons) const auto chain = parent(); auto nodes = chain->doc()->core()->queryStoryPoint(chain, name()[0]); - if(nodes.size() > 1){ ErrorMessage ins; + if(nodes.size() > 1){ + ErrorMessage ins(this); ins.Reason = "重复定义脉络节点"; ins.Text = static_cast(chain)->name()[0] +":"+ name()[0]; ins.FilePath = doc()->filePath(); diff --git a/libParse/StoryOutlineDocumentParser.cpp b/libParse/StoryOutlineDocumentParser.cpp index 635240b..18797d6 100644 --- a/libParse/StoryOutlineDocumentParser.cpp +++ b/libParse/StoryOutlineDocumentParser.cpp @@ -79,7 +79,8 @@ bool NodeStoryDepiction::check(QList &reasons) const { auto nodes = doc()->core()->queryStoryDepiction(name()[0]); - if(nodes.size() > 1){ ErrorMessage ins; + if(nodes.size() > 1){ + ErrorMessage ins(this); ins.Reason = "重复定义叙述"; ins.Text = name()[0]; ins.FilePath = doc()->filePath(); diff --git a/libParse/StoryTool.cpp b/libParse/StoryTool.cpp index 7120e85..08823ba 100644 --- a/libParse/StoryTool.cpp +++ b/libParse/StoryTool.cpp @@ -9,9 +9,10 @@ using namespace MakeTools; using namespace Parse; using namespace Parse::Result; +using namespace CheckTools; StoryTool::StoryTool(Parse::Result::ParseCore *core) - : parse_core(core){} + : parse_core(core), fragment_check(new FragmentsCheck(core)){} QList StoryTool::compile(const QFileInfo &file, const QString &doc_name) { @@ -118,7 +119,7 @@ bool StoryTool::checkPass(QList &errors) auto docs = this->parse_core->allDocuments(); for(auto &d : docs){ for(auto &w : d->unknowns()->refered()){ - ErrorMessage error; + ErrorMessage error(w->host()); error.Reason = "无法识别内容"; error.Text = w->toString(); error.FilePath = d->filePath(); @@ -131,6 +132,7 @@ bool StoryTool::checkPass(QList &errors) for(auto &n : this->parse_core->queryRootNodes(d)) error_check(n, errors); } + fragment_check->check(errors); return errors.size() == 0; } diff --git a/libParse/StoryTool.h b/libParse/StoryTool.h index 5952bc0..717e12e 100644 --- a/libParse/StoryTool.h +++ b/libParse/StoryTool.h @@ -3,6 +3,7 @@ #include "SyntaxBase.h" #include "libParse.h" +#include "parsechecks.h" #include @@ -22,6 +23,7 @@ namespace MakeTools { private: Parse::Result::ParseCore *const parse_core; + CheckTools::FragmentsCheck *const fragment_check; bool error_check(Parse::Result::DesNode *node, QList &err_out); }; diff --git a/libParse/StoryUnitDocumentParser.cpp b/libParse/StoryUnitDocumentParser.cpp index 1ecf07b..5386ad4 100644 --- a/libParse/StoryUnitDocumentParser.cpp +++ b/libParse/StoryUnitDocumentParser.cpp @@ -14,7 +14,7 @@ bool NodeStoryUnit::check(QList &reasons) const auto unit_nodes = doc()->core()->queryStoryUnit(name()[0]); if(unit_nodes.size() > 1){ - ErrorMessage ins; + ErrorMessage ins(this); ins.Reason = "重复定义单元"; ins.Text = name()[0]; ins.FilePath = doc()->filePath(); @@ -22,6 +22,7 @@ bool NodeStoryUnit::check(QList &reasons) const ins.CodeCol = refered().first()->column(); reasons << ins; } + return unit_nodes.size() == 1; } @@ -35,14 +36,24 @@ QString NodeStoryUnit::toString() const } -NodeStoryFragment::NodeStoryFragment(NodeStoryUnit * unit, const QString & name) - : Result::NamedNode(name, unit->doc(), NODE_STORYFRAGMENT, unit){ store_name = name; } +NodeStoryFragment::NodeStoryFragment(NodeStoryUnit * unit, const QString & name, const QString &order) + : Result::NamedNode(name, unit->doc(), NODE_STORYFRAGMENT, unit){ store_name = name; order_text = order; } + +QString NodeStoryFragment::order() const +{ + return order_text; +} + +double NodeStoryFragment::orderValue(bool &isvalid) const +{ + return order_text.toDouble(&isvalid); +} bool NodeStoryFragment::check(QList &reasons) const { auto nodes = doc()->core()->queryStoryFragment(parent(), name()[0]); if(nodes.size() > 1){ - ErrorMessage ins; + ErrorMessage ins(this); ins.Reason = "重复定义情节"; ins.Text = name()[0]; ins.FilePath = doc()->filePath(); @@ -51,13 +62,27 @@ bool NodeStoryFragment::check(QList &reasons) const reasons << ins; } + bool isvalid = false; + this->orderValue(isvalid); + if(!isvalid){ + ErrorMessage msg(this); + msg.CodeRow = refered().first()->row(); + msg.CodeCol = refered().first()->column(); + msg.FilePath = doc()->filePath(); + msg.Text = this->order(); + msg.Reason = "指定情节序列格式错误"; + + reasons << msg; + return false; + } + return nodes.size() == 1; } QString NodeStoryFragment::toString() const { - QString rets = QString(depth(), ' ') + "#情节 " + name()[0] + "{"; - for (auto cin : children()) + QString rets = QString(depth(), ' ') + "#情节 " + name()[0] +" " + order() + "{"; + for (auto &cin : children()) rets += "\n" + QString(depth(), ' ') + cin->toString(); return rets + "\n"+QString(depth(), ' ') + "}"; } @@ -88,7 +113,7 @@ bool NodeStoryPointRefer::check(QList &reasons) const { auto chain = doc()->core()->queryStoryChain(chainName()); if(!chain.size()){ - ErrorMessage ins; + ErrorMessage ins(this); ins.Reason = "指定脉络不存在"; ins.Text = chainName(); ins.FilePath = doc()->filePath(); @@ -100,7 +125,7 @@ bool NodeStoryPointRefer::check(QList &reasons) const else{ auto point = doc()->core()->queryStoryPoint(chain[0], pointName()); if(!point.size()){ - ErrorMessage ins; + ErrorMessage ins(this); ins.Reason = "指定脉络节点不存在"; ins.Text = chainName() + ":" + pointName(); ins.FilePath = doc()->filePath(); @@ -118,72 +143,6 @@ QString NodeStoryPointRefer::toString() const return QString("{@节点 %1 %2}").arg(chain_name).arg(point_name); } -//NodeStoryFragmentComment::NodeStoryFragmentComment(DesNode * parent, -// const QString &order, const QString & name) -// : parent_ins(parent), name_store(name), order_name(order) -//{ -//} - -//QString NodeStoryFragmentComment::order() const -//{ -// return order_name; -//} - -//DocCore * NodeStoryFragmentComment::document() const -//{ -// return parent_ins->document(); -//} - -//int NodeStoryFragmentComment::typeValue() const -//{ -// return NODE_ORDEREDCOMMENT; -//} - -//DesNode * NodeStoryFragmentComment::parent() const -//{ -// return parent_ins; -//} - -//void NodeStoryFragmentComment::appendChild(DesNode * ins) -//{ -// children_nodes << ins; -//} - -//QList NodeStoryFragmentComment::children() const -//{ -// return children_nodes; -//} - -//bool NodeStoryFragmentComment::check(QList& reasons) const -//{ -// return false; -//} - -//QString NodeStoryFragmentComment::toString() const -//{ -// auto xrets = QString(depth(), ' ') + "#注解 " + name() +" "+ order() +" "+ orderValue() + "{"; -// for (auto it : children_nodes) -// xrets += "\n" + QString(depth(), ' ') + it->toString(); -// xrets += "\n" + QString(depth(), ' ') + "}"; - -// return xrets; -//} - -//QString NodeStoryFragmentComment::name() const -//{ -// return name_store; -//} - -//QString NodeStoryFragmentComment::orderValue() const -//{ -// return order_value; -//} - -//void NodeStoryFragmentComment::resetValue(const QString &value) -//{ -// this->order_value = value; -//} - NodeStoryUnitParser::NodeStoryUnitParser(ParseCore * core) : XSyntaxBase("故事单元"), pjt_core(core) { @@ -256,22 +215,25 @@ NodeStoryFragmentParser::NodeStoryFragmentParser(NodeStoryUnitParser * pparser) { set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)}); auto rule = addRule("进入情节解析", 0, [this](const QList &seqs, int cnt)->ParseResult { - auto nmidx = cnt - 1, defidx = cnt - 2;; + auto nmidx = cnt - 2, defidx = cnt - 3, ordidx=cnt-1; auto parent_parser = nodeStoryUnitParser(); - auto node = new NodeStoryFragment(static_cast(parent_parser->currNode()), seqs[nmidx].Text); + auto node = new NodeStoryFragment(static_cast(parent_parser->currNode()), + seqs[nmidx].Text, seqs[ordidx].Text); this->refocusNode(node); parent_parser->currNode()->appendChild(node); auto word0 = new Words(node, docRef(), seqs[defidx].Text, seqs[defidx].StartRow, seqs[defidx].StartCol); auto word1 = new Words(node, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol); + auto word2 = new Words(node, docRef(), seqs[ordidx].Text, seqs[ordidx].StartRow, seqs[ordidx].StartCol); docRef()->append(word0); docRef()->append(word1); + docRef()->append(word2); return ParseResult::SelfManipulate; }); - rule->addExpression("基础情节解析", { Elm("{情节定义}"), Elm("{描述文本}", true) }); + rule->addExpression("基础情节解析", { Elm("{情节定义}"), Elm("{描述文本}1"), Elm("{描述文本}2", true) }); rule->addExpression("拓展情节解析", { Exp("::换行前缀"), Exp("基础情节解析", true) }); rule = addRule("情节成分解析", 1, [this](const QList &seqs, int cnt)->ParseResult { diff --git a/libParse/StoryUnitDocumentParser.h b/libParse/StoryUnitDocumentParser.h index 12d3003..9a72c00 100644 --- a/libParse/StoryUnitDocumentParser.h +++ b/libParse/StoryUnitDocumentParser.h @@ -37,9 +37,12 @@ namespace Parse { class NodeStoryFragment : public Result::NamedNode { public: - explicit NodeStoryFragment(NodeStoryUnit* unit, const QString &name); + explicit NodeStoryFragment(NodeStoryUnit* unit, const QString &name, const QString& order); virtual ~NodeStoryFragment() = default; + QString order() const; + double orderValue(bool &isvalid) const; + // 通过 NamedNode 继承 virtual bool check(QList& reasons) const override; virtual QString toString() const override; @@ -48,6 +51,7 @@ namespace Parse { private: QString store_name; + QString order_text; }; /** diff --git a/libParse/libParse.cpp b/libParse/libParse.cpp index 9d4ad53..93d9c2d 100644 --- a/libParse/libParse.cpp +++ b/libParse/libParse.cpp @@ -1,5 +1,6 @@ #include "libParse.h" #include "SyntaxBase.h" +#include "StoryUnitDocumentParser.h" #include using namespace Parse; @@ -29,6 +30,8 @@ namespace Parse { }; } +ErrorMessage::ErrorMessage(const DesNode *obj): object(obj){} + NamedNode::NamedNode(const QString &name, DocCore *core, int type, DesNode *pnode) : Result::DesNode(core, type, pnode), name_store(name){} @@ -230,6 +233,33 @@ QList ParseCore::queryStoryFragment(DesNode *unit, const QStri return retlist; } +QList > ParseCore::queryOrdersFragment() const +{ + QList> node_list; + auto units = allStoryUnits(); + for(auto &uins : units){ + auto children = uins->children(); + for(auto &c : children){ + if(c->typeValue() != NODE_STORYFRAGMENT) + continue; + + bool isvalid; + auto fragment = static_cast(c); + node_list << std::make_pair(fragment, fragment->orderValue(isvalid)); + } + } + + std::sort(node_list.begin(), node_list.end(), + [](const std::pair &a, const std::pair &b)->bool{ + bool valid; + auto val_a = static_cast(a.first)->orderValue(valid); + auto val_b = static_cast(b.first)->orderValue(valid); + return val_a < val_b; + }); + + return node_list; +} + QList ParseCore::allStoryBoards() const { QList retlist; diff --git a/libParse/libParse.h b/libParse/libParse.h index 5daf54c..b4022d1 100644 --- a/libParse/libParse.h +++ b/libParse/libParse.h @@ -10,20 +10,28 @@ namespace Parse { - struct ErrorMessage + namespace Result { + class DesNode; + } + + class ErrorMessage + { + public: + ErrorMessage(const Result::DesNode *obj); + QString Reason; QString Text; QString FilePath; int CodeRow; int CodeCol; + + const Result::DesNode *const object; }; - namespace Result - { + namespace Result{ class ParseCore; class DocCore; - class DesNode; enum class DocType { @@ -314,6 +322,7 @@ namespace Parse virtual QList allStoryUnits() const; virtual QList queryStoryUnit(const QString &name) const; virtual QList queryStoryFragment(Result::DesNode *unit, const QString &name) const; + virtual QList> queryOrdersFragment() const; virtual QList allStoryBoards() const; virtual QList queryStoryBoard(const QString &name) const; diff --git a/libParse/libParse.pro b/libParse/libParse.pro index 2c3e169..ba0c488 100644 --- a/libParse/libParse.pro +++ b/libParse/libParse.pro @@ -20,6 +20,7 @@ SOURCES += \ WordsPeak.cpp \ XSyntaxBase.cpp \ libParse.cpp \ + parsechecks.cpp \ storyconceptdocumentparser.cpp HEADERS += \ @@ -36,6 +37,7 @@ HEADERS += \ XSyntaxBase.h \ libParse.h \ libParse_global.h \ + parsechecks.h \ storyconceptdocumentparser.h TRANSLATIONS += \ diff --git a/libParse/parsechecks.cpp b/libParse/parsechecks.cpp new file mode 100644 index 0000000..e285cce --- /dev/null +++ b/libParse/parsechecks.cpp @@ -0,0 +1,49 @@ +#include "parsechecks.h" +#include "StoryBoardDocumentParser.h" +#include "StoryUnitDocumentParser.h" +#include "../WordsIDE/opstream.h" + +using namespace Parse; + +CheckTools::FragmentsCheck::FragmentsCheck(Parse::Result::ParseCore *const core) + : core_ins(core){} + +bool CheckTools::FragmentsCheck::check(QList &reasons) const +{ + auto stories = core_ins->allStoryBoards(); + + // 编排索引顺序校验 + for(auto &ins : stories){ + auto xins = static_cast(ins); + + double temp = -DBL_MAX; + auto refers = xins->children(); + for(auto &ref : refers){ + if(ref->typeValue() == NODE_FRAGMENTREFERENCE){ + auto ins_ref = static_cast(ref); + auto u = core_ins->queryStoryUnit(ins_ref->unit()); + auto frag = core_ins->queryStoryFragment(u[0], ins_ref->fragment()); + auto frag_ins = static_cast(frag[0]); + + bool isvalid; + double order_value = frag_ins->orderValue(isvalid); + if(temp > order_value) + { + ErrorMessage msg(ins_ref); + msg.CodeRow = ins_ref->refered().first()->row(); + msg.CodeCol = ins_ref->refered().first()->column(); + msg.FilePath = ins_ref->doc()->filePath(); + msg.Text = ins_ref->unit() + ":"+ ins_ref->fragment(); + msg.Reason = QString("%1:指定节点索引顺序颠倒").arg(ins_ref->fragment()); + + reasons << msg; + return false; + } + + temp = order_value; + } + } + } + + return true; +} diff --git a/libParse/parsechecks.h b/libParse/parsechecks.h new file mode 100644 index 0000000..96d44c0 --- /dev/null +++ b/libParse/parsechecks.h @@ -0,0 +1,47 @@ +#ifndef PARSECHECKS_H +#define PARSECHECKS_H + +#include "libParse.h" + +namespace CheckTools { + /** + * @brief 情节校对工具 + */ + class FragmentsCheck + { + public: + FragmentsCheck(Parse::Result::ParseCore *const core); + + /** + * @brief 错误校验 + * @param reasons 错误原因 + * @return 错误指示 + */ + bool check(QList &reasons) const; + + private: + Parse::Result::ParseCore *const core_ins; + }; +} + + +#endif // PARSECHECKS_H + + + + + + + + + + + + + + + + + + + diff --git a/libParse/storyconceptdocumentparser.cpp b/libParse/storyconceptdocumentparser.cpp index a3afb1f..48fb6b5 100644 --- a/libParse/storyconceptdocumentparser.cpp +++ b/libParse/storyconceptdocumentparser.cpp @@ -32,7 +32,7 @@ bool NodeStoryConcept::check(QList &reasons) const { auto nodes = doc()->core()->queryStoryConcept(name()[0]); if(nodes.size() > 1){ - ErrorMessage ins; + ErrorMessage ins(this); ins.CodeRow = refered().first()->row(); ins.CodeCol = refered().first()->column(); ins.FilePath = doc()->filePath(); @@ -66,7 +66,7 @@ bool NodeStoryStrongPoint::check(QList &reasons) const auto concept = parent(); auto nodes = doc()->core()->queryStoryStrongPoint(concept, name()[0]); if(nodes.size() > 1){ - ErrorMessage ins; + ErrorMessage ins(this); ins.CodeRow = refered().first()->row(); ins.CodeCol = refered().first()->column(); ins.FilePath = doc()->filePath();