#include "storyunitspresent.h" #include "DocsManager.h" #include "command_list.h" #include "opstream.h" #include #include using namespace Components; using namespace Parse::Result; using namespace Operate; using namespace DataModel; StoryunitsPresentModel::StoryunitsPresentModel(Core::AppCore *core) : core_ins(core), model_ins(new QStandardItemModel), details_backend(new QTextDocument) {} StoryunitsPresentModel::~StoryunitsPresentModel() { delete model_ins; delete details_backend; } QStandardItemModel *StoryunitsPresentModel::treeModel() const { return model_ins; } QTextDocument *StoryunitsPresentModel::detailsBackend() const { return details_backend; } void StoryunitsPresentModel::refreshTree() { model_ins->clear(); auto units = core_ins->parseCore()->allStoryUnits(); for (auto &unit : units) { auto unit_node = new QStandardItem(static_cast(unit)->name()[0]); unit_node->setEditable(false); model_ins->appendRow(unit_node); auto children = unit->children(); for (auto &frag : children) { if (frag->typeValue() == NODE_STORYFRAGMENT) { auto frag_node = new QStandardItem( static_cast(frag)->name()[0]); frag_node->setEditable(false); unit_node->appendRow(frag_node); } } } } void StoryunitsPresentModel::details_show(const QList &path) { QStandardItem *item = nullptr; // 迭代路径获取故事链节点 for (auto &it : path) { auto result = OpStream([this, &item](int &cnt, int idx) -> QStandardItem * { if (!item) { cnt = model_ins->rowCount(); if (cnt <= 0) return nullptr; return model_ins->item(idx); } else { cnt = item->rowCount(); if (cnt <= 0) return nullptr; return item->child(idx); } }).filter([it](QStandardItem *const &xit) { return it == xit->text(); }).toList(); if (!result.size()) { throw new SimpleException("指定的Storychain路径无效:" + path.join("/")); } else { item = result.at(0); } } // 填充详细内容 QString contents; if (item->parent() == nullptr) { auto node = core_ins->parseCore()->queryStoryUnit(item->text()); auto children = node.first()->children(); for (auto &it : children) { if (it->typeValue() != NODE_STORYFRAGMENT) { contents += it->toString() + "\n"; } } } else { auto node = core_ins->parseCore()->queryStoryUnit(item->parent()->text()); auto point = core_ins->parseCore()->queryStoryFragment(node.first(), item->text()); auto children = point.first()->children(); for (auto &it : children) { contents += it->toString() + "\n"; } } details_backend->setPlainText(contents); } QString StoryunitsPresentModel::name() const { return NAME(StoryunitsPresentModel); } StoryunitsPresent::StoryunitsPresent(Schedule::CommandsDispatcher *core, StoryunitsPresentModel *backend, QWidget *parent) : QWidget(parent), disp_core(core), units_view(new QTreeView(this)), details_show(new QTextEdit(this)) { units_view->setHeaderHidden(true); units_view->setModel(backend->treeModel()); details_show->setReadOnly(true); details_show->setDocument(backend->detailsBackend()); auto layout = new QVBoxLayout(this); auto splitter = new QSplitter(Qt::Vertical, this); layout->addWidget(splitter); splitter->addWidget(units_view); splitter->addWidget(details_show); layout->setMargin(0); connect(units_view, &QTreeView::clicked, this, &StoryunitsPresent::show_details); connect(units_view, &QTreeView::doubleClicked, this, &StoryunitsPresent::jump_to); } QString StoryunitsPresent::name() const { return NAME(StoryunitsPresent); } QWidget *StoryunitsPresent::widget() const { return (QWidget *)this; } using namespace CommandList; void StoryunitsPresent::jump_to(const QModelIndex &curr) { QList path; QModelIndex node = curr; while (true) { auto node_name = node.data().toString(); if (node_name.isEmpty()) break; path.insert(0, node_name); node = node.parent(); } disp_core->postCommand(StoryunitJumpTo(path)); } void StoryunitsPresent::show_details(const QModelIndex &curr) { QList path; QModelIndex node = curr; while (true) { auto node_name = node.data().toString(); if (node_name.isEmpty()) break; path.insert(0, node_name); node = node.parent(); } disp_core->postCommand(StoryunitDetailShow(path)); }