#include "storypresent.h" #include #include #include #include using namespace dags; using namespace xast_parse; StoryPresent::StoryPresent(QWidget* parent) : QMainWindow(parent), _story_present(new DAGActiveView(this)) { setCentralWidget(_story_present); auto mbar = menuBar(); auto view = mbar->addMenu(u8"视图"); view->addAction(u8"缩小", this, &StoryPresent::lesser, Qt::CTRL + Qt::Key_N); view->addAction(u8"放大", this, &StoryPresent::bigger, Qt::CTRL + Qt::Key_P); auto layout = mbar->addMenu(u8"布局调整"); layout->addAction(u8"正向布局", this, &StoryPresent::forwardLayout, Qt::CTRL + Qt::Key_F); layout->addAction(u8"逆向布局", this, &StoryPresent::backwardLayout, Qt::CTRL + Qt::Key_B); layout->addAction(u8"调整布局", this, &StoryPresent::adjustLayout, Qt::CTRL+Qt::Key_A); connect(_story_present, &DAGActiveView::nodeClicked, this, &StoryPresent::nodeClickAccept); } StoryPresent::~StoryPresent() {} #include "xast_parse.h" void StoryPresent::loadXAST(const QString& ast_path) { QFileInfo finfo(ast_path); if (!finfo.exists() || !finfo.isFile()) { QMessageBox::critical(this, u8"文件错误", QString(u8"指定文件(%1)非法!").arg(ast_path)); return; } xast_parse::XAST_Parser t(ast_path); this->_story_graph = t.storyGraph(); QList arrows; for (auto& key : this->_story_graph.keys()) { auto story_line = this->_story_graph[key]; auto arrow_start = story_line->name(); auto frag_temp = story_line->firstChild(); while (frag_temp) { switch (frag_temp->type()) { case SliceType::FragmentDefines: { auto arrow_tail = std::dynamic_pointer_cast(frag_temp)->name() + u8"@" + story_line->name(); arrows << graph_data::Arrow(arrow_start, arrow_tail); arrow_start = arrow_tail; }break; case SliceType::FragmentRefers: { auto conv_refer = std::dynamic_pointer_cast(frag_temp); auto arrow_tail = conv_refer->fragmentRefer() + u8"@" + conv_refer->storyRefer(); arrows << graph_data::Arrow(arrow_start, arrow_tail); arrow_start = arrow_tail; }break; default: break; } frag_temp = frag_temp->nextSlice(); } } this->_story_present->updateWithEdges(arrows); } #include void StoryPresent::nodeClickAccept(const QPointF& pos, const QString& node_name) { // 起始节点 if (!node_name.contains(u8"@")) { auto story_line = this->_story_graph[node_name]; QList node_names; node_names << node_name; auto temp_node = story_line->firstChild(); while (temp_node) { switch (temp_node->type()) { case SliceType::FragmentDefines: { auto fragm = std::dynamic_pointer_cast(temp_node); node_names << QString(u8"%1@%2").arg(fragm->name(), node_name); }break; case SliceType::FragmentRefers: { auto frefer = std::dynamic_pointer_cast(temp_node); node_names << QString(u8"%1@%2").arg(frefer->fragmentRefer(), frefer->storyRefer()); } break; default: break; } temp_node = temp_node->nextSlice(); } QList arrows; for (auto idx = 1; idx < node_names.size(); ++idx) { auto from = node_names[idx - 1]; auto to = node_names[idx]; arrows << graph_data::Arrow(from, to); } this->_story_present->highlightGraphLink(arrows); } else { auto splits = node_name.split(u8"@", QString::SkipEmptyParts); auto story_line = this->_story_graph[splits.last()]; auto fragm_slice = story_line->getFragment(splits.first()); auto fragm_defn = std::dynamic_pointer_cast(fragm_slice); auto refers = fragm_defn->referSlices(); if (!refers.size()) { this->nodeClickAccept(QPointF(), story_line->name()); return; } QList> vparent_slices; std::transform(refers.begin(), refers.end(), std::back_inserter(vparent_slices), [](std::shared_ptr ins) { return ins->parentSlice().lock(); }); QList> parent_slices; std::copy_if(vparent_slices.begin(), vparent_slices.end(), std::back_inserter(parent_slices), [](std::shared_ptr ins) -> bool { return ins != nullptr; }); decltype(parent_slices) fliter_slices; std::copy_if(parent_slices.begin(), parent_slices.end(), std::back_inserter(fliter_slices), [](std::shared_ptr ins) { return ins->type() == SliceType::StoryDefines; }); QList> lines = { story_line }; std::transform(fliter_slices.begin(), fliter_slices.end(), std::back_inserter(lines), [](std::shared_ptr ins) { return std::dynamic_pointer_cast(ins); }); QMenu msep; for (auto ln : lines) { msep.addAction(ln->name(), [=](){ this->nodeClickAccept(QPointF(), ln->name()); }); } msep.exec(this->_story_present->mapToParent(pos.toPoint())); } } void StoryPresent::bigger() { _scale_value *= 1.1; QTransform trans_base; trans_base.scale(_scale_value, _scale_value); this->_story_present->setTransform(trans_base); } void StoryPresent::lesser() { _scale_value /= 1.1; QTransform trans_base; trans_base.scale(_scale_value, _scale_value); this->_story_present->setTransform(trans_base); } void StoryPresent::forwardLayout() { this->_story_present->layoutEngine()->forwardsLayoutImpls(); this->_story_present->refreshGraph(); } void StoryPresent::backwardLayout() { this->_story_present->layoutEngine()->backwardsLayoutImpls(); this->_story_present->refreshGraph(); } void StoryPresent::adjustLayout() { this->_story_present->layoutEngine()->adjustLayoutImpls(); this->_story_present->refreshGraph(); }