191 lines
5.7 KiB
C++
191 lines
5.7 KiB
C++
#include "storyconceptspresent.h"
|
||
#include "DocsManager.h"
|
||
#include "command_list.h"
|
||
#include "opstream.h"
|
||
|
||
#include <QSplitter>
|
||
#include <QVBoxLayout>
|
||
|
||
using namespace Operate;
|
||
using namespace Components;
|
||
using namespace Core;
|
||
using namespace Parse::Result;
|
||
using namespace Tools;
|
||
using namespace Schedule;
|
||
using namespace CommandList;
|
||
|
||
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<StoryconceptsPresentModel>(NAME(StoryconceptsPresentModel));
|
||
|
||
tree_view->setModel(backend->treeModel());
|
||
tree_view->setHeaderHidden(true);
|
||
details_view->setDocument(backend->detailsBackend());
|
||
details_view->setReadOnly(true);
|
||
|
||
auto layout = new QVBoxLayout(this);
|
||
layout->setMargin(0);
|
||
|
||
auto splitter = new QSplitter(Qt::Vertical, this);
|
||
layout->addWidget(splitter);
|
||
splitter->addWidget(tree_view);
|
||
splitter->addWidget(details_view);
|
||
|
||
connect(tree_view, &QTreeView::clicked, this,
|
||
&StoryconceptsPresent::show_details);
|
||
connect(tree_view, &QTreeView::doubleClicked, this,
|
||
&StoryconceptsPresent::jump_to);
|
||
}
|
||
|
||
void StoryconceptsPresent::show_details(const QModelIndex &curr) {
|
||
if(!curr.isValid())
|
||
return;
|
||
|
||
QList<QString> 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<QString> 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));
|
||
}
|
||
|
||
QString StoryconceptsPresent::name() const {
|
||
return NAME(StoryconceptsPresent);
|
||
}
|
||
|
||
StoryconceptsPresentModel::StoryconceptsPresentModel(Core::AppCore *core)
|
||
: core_ins(core), model_base(new QStandardItemModel),
|
||
detail_backend(new QTextDocument) {
|
||
concept_model = new TreeSyncs<DesNode *>(
|
||
model_base,
|
||
[](DesNode *dbase, QStandardItem *it) -> bool {
|
||
return static_cast<NamedNode *>(dbase)->name()[0] == it->text();
|
||
},
|
||
[](DesNode *dbase, QStandardItem *it) {
|
||
it->setText(static_cast<NamedNode *>(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<DesNode *> rets;
|
||
auto children = dit->children();
|
||
for (auto &frag : children) {
|
||
if (frag->typeValue() == NODE_STORYSTRONGPOINT) {
|
||
rets << frag;
|
||
}
|
||
}
|
||
|
||
return rets;
|
||
} else {
|
||
return core_ins->parseCore()->allStoryConcept();
|
||
}
|
||
});
|
||
}
|
||
|
||
void StoryconceptsPresentModel::detailsShow(const QList<QString> &path) {
|
||
// 获取第一级初始集合
|
||
QList<QStandardItem *> item_list =
|
||
OpStream<QStandardItem *>([this](int &cnt, int idx) -> QStandardItem * {
|
||
cnt = model_base->rowCount();
|
||
if (cnt <= 0)
|
||
return nullptr;
|
||
return model_base->item(idx);
|
||
})
|
||
.select()
|
||
.toList();
|
||
|
||
// 迭代路径获取故事链节点
|
||
for (auto it : path) {
|
||
auto result = OpStream<QStandardItem *>(item_list)
|
||
.filter([it](QStandardItem *const &xit) {
|
||
return it == xit->text();
|
||
})
|
||
.toList();
|
||
|
||
if (!result.size()) {
|
||
throw new SimpleException("指定的Storychain路径无效:" +
|
||
path.join("/"));
|
||
}
|
||
|
||
item_list = OpStream<QStandardItem *>(
|
||
[&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) {
|
||
contents += it->toString() + "\n";
|
||
}
|
||
}
|
||
} 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) {
|
||
contents += it->toString() + "\n";
|
||
}
|
||
}
|
||
detail_backend->setPlainText(contents);
|
||
}
|
||
|
||
QString StoryconceptsPresentModel::name() const {
|
||
return NAME(StoryconceptsPresentModel);
|
||
}
|