diff --git a/QtNovelDesc.pro.user b/QtNovelDesc.pro.user index ac0b4f1..cf0130c 100644 --- a/QtNovelDesc.pro.user +++ b/QtNovelDesc.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/WordsIDE/command_list.cpp b/WordsIDE/command_list.cpp index eddde58..ced85de 100644 --- a/WordsIDE/command_list.cpp +++ b/WordsIDE/command_list.cpp @@ -336,3 +336,49 @@ QString StoryunitJumpTo::toText() const { return unit_nav.join("/"); } void StoryunitJumpTo::fromText(const QString &line) { unit_nav = line.split("/"); } + +#include "storyconceptspresent.h" +StoryconceptDetailShow::StoryconceptDetailShow(const QList &path) { + navi_path.append(path); +} + +QString StoryconceptDetailShow::name() const { + return NAME(StoryconceptDetailShow); +} + +void StoryconceptDetailShow::run(Schedule::CommandsDispatcher *core) const { + auto vmgr = + core->get(NAME(StoryconceptsPresentModel)); + vmgr->detailsShow(navi_path); +} + +QString StoryconceptDetailShow::toText() const { return navi_path.join("/"); } + +void StoryconceptDetailShow::fromText(const QString &line) { + navi_path = line.split("/"); +} + +StoryconceptJumpTo::StoryconceptJumpTo(const QList &path) { + navi_path.append(path); +} + +QString StoryconceptJumpTo::name() const { return NAME(StoryconceptJumpTo); } + +void StoryconceptJumpTo::run(Schedule::CommandsDispatcher *core) const { + auto core_ins = core->get(NAME(AppCore)); + auto vmgr = core->get(NAME(DocumentsManager)); + + auto cept_ins = + core_ins->parseCore()->queryStoryConcept(navi_path[0]).first(); + auto cept_doc = cept_ins->doc(); + auto idx = vmgr->projectManager()->queryIndex(cept_doc->filePath()); + auto route = vmgr->converter(idx); + vmgr->openFile(route); + vmgr->activePresentOf(route)->jumpTo(navi_path); +} + +QString StoryconceptJumpTo::toText() const { return navi_path.join("/"); } + +void StoryconceptJumpTo::fromText(const QString &line) { + navi_path = line.split("/"); +} diff --git a/WordsIDE/command_list.h b/WordsIDE/command_list.h index cc009fa..9ab6bd1 100644 --- a/WordsIDE/command_list.h +++ b/WordsIDE/command_list.h @@ -180,6 +180,36 @@ namespace CommandList { QList unit_nav; }; + class StoryconceptDetailShow : public Schedule::GeCommand { + public: + StoryconceptDetailShow(const QList &path); + + // GeCommand interface + public: + virtual QString name() const override; + virtual void run(Schedule::CommandsDispatcher *core) const override; + virtual QString toText() const override; + virtual void fromText(const QString &line) override; + + private: + QList navi_path; + }; + + class StoryconceptJumpTo : public Schedule::GeCommand { + public: + StoryconceptJumpTo(const QList &path); + + // GeCommand interface + public: + virtual QString name() const override; + virtual void run(Schedule::CommandsDispatcher *core) const override; + virtual QString toText() const override; + virtual void fromText(const QString &line) override; + + private: + QList navi_path; + }; + } // namespace CommandList #endif // COMMAND_LIST_H diff --git a/WordsIDE/storyconceptspresent.cpp b/WordsIDE/storyconceptspresent.cpp index 380c621..8fbe3ee 100644 --- a/WordsIDE/storyconceptspresent.cpp +++ b/WordsIDE/storyconceptspresent.cpp @@ -1,5 +1,6 @@ #include "storyconceptspresent.h" #include "DocsManager.h" +#include "command_list.h" #include "opstream.h" #include @@ -10,101 +11,176 @@ using namespace Components; using namespace Core; using namespace Parse::Result; using namespace Tools; +using namespace Schedule; +using namespace CommandList; -StoryConceptsPresent::StoryConceptsPresent(Core::AppCore *core, QWidget *parent) - : QWidget(parent), core_ins(core), - tree_view(new QTreeView(this)), - model_base(new QStandardItemModel(this)), - details_view(new QTextBrowser(this)), - concept_model(new ModelSyncs( - model_base, - [](DesNode* dbase, QStandardItem *it)->bool{ return static_cast(dbase)->name()[0] == it->text(); }, -[](DesNode* dbase, QStandardItem *it){ it->setText(static_cast(dbase)->name()[0]); })){ -tree_view->setHeaderHidden(true); +StoryconceptsPresent::StoryconceptsPresent(CommandsDispatcher *core, + QWidget *parent) + : QWidget(parent), core_ins(core), tree_view(new QTreeView(this)), + details_view(new QTextBrowser(this)) { + auto backend = + core->get(NAME(StoryconceptsPresentModel)); -auto layout = new QVBoxLayout(this); -layout->setMargin(0); + tree_view->setModel(backend->treeModel()); + tree_view->setHeaderHidden(true); + details_view->setDocument(backend->detailsBackend()); + details_view->setReadOnly(true); -auto splitter = new QSplitter(Qt::Vertical, this); -layout->addWidget(splitter); + auto layout = new QVBoxLayout(this); + layout->setMargin(0); -splitter->addWidget(tree_view); -splitter->addWidget(details_view); + auto splitter = new QSplitter(Qt::Vertical, this); + layout->addWidget(splitter); + splitter->addWidget(tree_view); + splitter->addWidget(details_view); -tree_view->setModel(model_base); -details_view->setReadOnly(true); - -connect(tree_view, &QTreeView::clicked, this, &StoryConceptsPresent::show_node_description); -connect(tree_view, &QTreeView::doubleClicked, this, &StoryConceptsPresent::click_to); + connect(tree_view, &QTreeView::clicked, this, + &StoryconceptsPresent::show_details); + connect(tree_view, &QTreeView::doubleClicked, this, + &StoryconceptsPresent::jump_to); } -void StoryConceptsPresent::refresh() -{ - this->concept_model->presentSync([this](DesNode *dit){ - if(dit){ - QList rets; +void StoryconceptsPresent::show_details(const QModelIndex &curr) { + if(!curr.isValid()) + return; + + QList path; + QModelIndex node = curr; + while (true) { + auto name = node.data().toString(); + if (name.isEmpty()) + break; + path.insert(0, name); + node = node.parent(); + } + + core_ins->postCommand(StoryconceptDetailShow(path)); +} + +void StoryconceptsPresent::jump_to(const QModelIndex &curr) { + if(!curr.isValid()) + return; + + QList path; + QModelIndex node = curr; + while (true) { + auto name = node.data().toString(); + if (name.isEmpty()) + break; + path.insert(0, name); + node = node.parent(); + } + + core_ins->postCommand(StoryconceptJumpTo(path)); +} + +StoryconceptsPresentModel::StoryconceptsPresentModel(Core::AppCore *core) + : core_ins(core), model_base(new QStandardItemModel), + detail_backend(new QTextDocument) { + concept_model = new TreeSyncs( + model_base, + [](DesNode *dbase, QStandardItem *it) -> bool { + return static_cast(dbase)->name()[0] == it->text(); + }, + [](DesNode *dbase, QStandardItem *it) { + it->setText(static_cast(dbase)->name()[0]); + }); +} + +StoryconceptsPresentModel::~StoryconceptsPresentModel() { + delete model_base; + delete detail_backend; + delete concept_model; +} + +QStandardItemModel *StoryconceptsPresentModel::treeModel() const { + return model_base; +} + +QTextDocument *StoryconceptsPresentModel::detailsBackend() const { + return detail_backend; +} + +void StoryconceptsPresentModel::refreshTree() { + this->concept_model->presentSync([this](DesNode *dit) { + if (dit) { + QList rets; auto children = dit->children(); - for(auto &frag : children){ - if(frag->typeValue() == NODE_STORYSTRONGPOINT){ + for (auto &frag : children) { + if (frag->typeValue() == NODE_STORYSTRONGPOINT) { rets << frag; } } return rets; - } - else{ + } else { return core_ins->parseCore()->allStoryConcept(); } }); - } -void StoryConceptsPresent::show_node_description(const QModelIndex &curr) -{ - if(!curr.isValid()) - return; +void StoryconceptsPresentModel::detailsShow(const QList &path) { + // 获取第一级初始集合 + QList item_list = + OpStream([this](int &cnt, int idx) -> QStandardItem * { + cnt = model_base->rowCount(); + if (cnt <= 0) + return nullptr; + return model_base->item(idx); + }) + .select() + .toList(); - details_view->clear(); - auto item = model_base->itemFromIndex(curr); - if(item->parent() == nullptr){ + // 迭代路径获取故事链节点 + for (auto it : path) { + auto result = OpStream(item_list) + .filter([it](QStandardItem *const &xit) { + return it == xit->text(); + }) + .toList(); + + if (!result.size()) { + throw new SimpleException("指定的Storychain路径无效:" + + path.join("/")); + } + + item_list = OpStream( + [&result](int &cnt, int idx) -> QStandardItem * { + cnt = result[0]->rowCount(); + if (cnt <= 0) + return nullptr; + return result[0]->child(idx); + }) + .select() + .toList(); + } + + // 填充详细内容 + auto item = item_list[0]; + QString contents; + if (item->parent() == nullptr) { auto node = core_ins->parseCore()->queryStoryConcept(item->text()); auto children = node.first()->children(); - for(auto &it : children){ - if(it->typeValue() != NODE_STORYSTRONGPOINT){ - details_view->append(it->toString()); + for (auto &it : children) { + if (it->typeValue() != NODE_STORYSTRONGPOINT) { + contents += it->toString() + "\n"; } } - } - else{ - auto node = core_ins->parseCore()->queryStoryConcept(item->parent()->text()); - auto point = core_ins->parseCore()->queryStoryStrongPoint(node.first(), item->text()); + } else { + auto node = + core_ins->parseCore()->queryStoryConcept(item->parent()->text()); + auto point = core_ins->parseCore()->queryStoryStrongPoint(node.first(), + item->text()); auto children = point.first()->children(); - for(auto &it : children){ - details_view->append(it->toString()); + for (auto &it : children) { + contents += it->toString() + "\n"; } } + detail_backend->setPlainText(contents); } -void StoryConceptsPresent::click_to(const QModelIndex &curr) -{ - if(!curr.isValid()) - return; - - auto pnode = this->model_base->itemFromIndex(curr); - QList path; - while (pnode) { - path.insert(0, pnode->text()); - pnode = pnode->parent(); - } - - auto unit_ins = this->core_ins->parseCore()->queryStoryConcept(path[0]).first(); - auto chain_doc = unit_ins->doc(); - this->core_ins->getDocsManager()->openTextDocument(chain_doc->filePath(), chain_doc->docName()); - auto present = this->core_ins->getDocsManager()->queryTextComponent(QFileInfo(chain_doc->filePath())); - - if(path.size()){ - present->jumpTo(path); - } +QString StoryconceptsPresentModel::name() const { + return NAME(StoryconceptsPresentModel); } diff --git a/WordsIDE/storyconceptspresent.h b/WordsIDE/storyconceptspresent.h index fe57572..dea77c9 100644 --- a/WordsIDE/storyconceptspresent.h +++ b/WordsIDE/storyconceptspresent.h @@ -11,22 +11,41 @@ #include namespace Components { - class StoryConceptsPresent : public QWidget - { - public: - StoryConceptsPresent(Core::AppCore *core, QWidget *parent=nullptr); + class StoryconceptsPresentModel : public Schedule::AccessibleObject { + public: + StoryconceptsPresentModel(Core::AppCore *core); + virtual ~StoryconceptsPresentModel(); - virtual void refresh(); + QStandardItemModel *treeModel() const; + QTextDocument *detailsBackend() const; - private: + void refreshTree(); + void detailsShow(const QList &path); + + // AccessibleObject interface + public: + virtual QString name() const override; + + private: Core::AppCore *const core_ins; - QTreeView *const tree_view; QStandardItemModel *const model_base; - QTextBrowser *const details_view; - Tools::ModelSyncs * concept_model; + QTextDocument *const detail_backend; + Tools::TreeSyncs *concept_model; + }; - void show_node_description(const QModelIndex &curr); - void click_to(const QModelIndex &curr); + class StoryconceptsPresent : public QWidget, + public Schedule::AccessibleObject { + public: + StoryconceptsPresent(Schedule::CommandsDispatcher *core, + QWidget *parent = nullptr); + + private: + Schedule::CommandsDispatcher *const core_ins; + QTreeView *const tree_view; + QTextBrowser *const details_view; + + void show_details(const QModelIndex &curr); + void jump_to(const QModelIndex &curr); }; }