#include "srcedit_storyunit.h" #include "keywordshighlighter.h" #include #include #include #include #include #include using namespace Core; using namespace Parse::Result; using namespace Components; using namespace Enhancement; StoryunitSourceEdit::StoryunitSourceEdit() : edit_square(new QTextEdit), refers_descriptions(new QTableView()), refers_model(new QStandardItemModel()), split(new QSplitter()), words_highlighter(new KeywordsHighlighter(this)) { words_highlighter->setDocument(this->edit_square->document()); refers_descriptions->setModel(refers_model); connect(this->edit_square, &QTextEdit::textChanged, [this](){ emit this->dataChanged(filepath_store); }); split->addWidget(edit_square); split->addWidget(this->refers_descriptions); } StoryunitSourceEdit::~StoryunitSourceEdit() { delete this->refers_descriptions; split->deleteLater(); } void StoryunitSourceEdit::modeReset(const QString &) const { } QList StoryunitSourceEdit::modes() const { return QList() << "源码"; } QString StoryunitSourceEdit::currentMode() const { return modes()[0]; } void StoryunitSourceEdit::cursor_contex_query() { refers_model->clear(); refers_model->setHorizontalHeaderLabels(QStringList() << "故事" << "内容"); auto cursor = edit_square->textCursor(); auto doc = this->core_ins->parseCore()->queryDocument(QFileInfo(this->absoluteTargetPath())); auto words = doc->getWords(cursor.block().blockNumber()); QList frags; for (auto &w : words) { QHash nodes; auto xhost = w->host(); while (xhost != nullptr){ nodes[xhost->typeValue()] = xhost; xhost = xhost->parent(); } if(!nodes.contains(NODE_STORYFRAGMENT)) continue; xhost = nodes[NODE_STORYFRAGMENT]; if(!frags.contains(xhost)) frags << xhost; } auto less_equal_than = [](std::pair a, std::pair b)->bool{ if(a.first < b.first) return true; else if(a.first == b.first) return a.second <= b.second; return false; }; for(auto &x : frags){ auto first = x->refered().first(); auto last = x->refered().last(); auto tcursor = std::make_pair(cursor.block().blockNumber(), cursor.positionInBlock()); auto fcursor = std::make_pair(first->row(), first->column()); auto lcursor = std::make_pair(last->row(), last->column()+last->length()); if(less_equal_than(fcursor, tcursor) && less_equal_than(tcursor, lcursor)) { auto name = static_cast(x)->name(); present_refersed_tips(name[1], name[0]); break; } } } void StoryunitSourceEdit::present_refersed_tips(const QString &unit, const QString &frag) { QHash nodes; auto storys = core_ins->parseCore()->allStoryBoards(); for (auto &s : storys) { auto xins = static_cast(s); auto refs_x = s->children(); for(auto &ref : refs_x) if(ref->typeValue() == NODE_FRAGMENTREFERENCE){ auto nm_ref = static_cast(ref); if(nm_ref->name()[0] == frag && nm_ref->name()[1] == unit){ nodes[xins->name()[0]] = ref; break; } } } for(auto &nm : nodes.keys()) { QList row; row << new QStandardItem(nm); row.last()->setEditable(false); row << new QStandardItem(nodes[nm]->toString()); row.last()->setEditable(false); refers_model->appendRow(row); } refers_descriptions->resizeColumnsToContents(); refers_descriptions->resizeRowsToContents(); } void StoryunitSourceEdit::contexBinding(Core::AppCore *app) { this->core_ins = app; connect(edit_square, &QTextEdit::cursorPositionChanged, this, &StoryunitSourceEdit::cursor_contex_query); } void StoryunitSourceEdit::renderRepeat() const { this->words_highlighter->rehighlight(); } QList StoryunitSourceEdit::suffixes() const { return QList() << "storyunit"; } std::tuple StoryunitSourceEdit::create(const QDir &target, const QString &name, const QString &suffix) { auto filepath = target.filePath(QString("%1.%2").arg(name, suffix)); if(QFileInfo::exists(filepath)) return std::make_tuple(false, filepath); QFile nf(filepath); if(!nf.open(QIODevice::WriteOnly|QIODevice::Text)) throw new SimpleException("新建文件错误:指定文件无法创建:"+filepath); return std::make_tuple(true, filepath); } MakeTools::FilePresent *StoryunitSourceEdit::newInst() const { return new StoryunitSourceEdit(); } void StoryunitSourceEdit::applySetting(const QString &name, Core::AppCore *core) { this->name_store = name; } QString StoryunitSourceEdit::name() const { return name_store; } void StoryunitSourceEdit::load(const QFileInfo &target_file) { if(!target_file.exists()) throw new SimpleException("文件打开:指定文件无法不存在:"+target_file.absoluteFilePath()); if(!target_file.isFile()) throw new SimpleException("文件打开:指定文件无效:" + target_file.absoluteFilePath()); filepath_store = target_file.absoluteFilePath(); QFile bin(filepath_store); if(!bin.open(QIODevice::ReadOnly|QIODevice::Text)) throw new SimpleException("文件打开:指定的文件无法打开:"+filepath_store); QTextStream tin(&bin); tin.setCodec("UTF-8"); this->edit_square->setText(tin.readAll()); } void StoryunitSourceEdit::saveAs(const QString &path) { if(!path.isEmpty()) filepath_store = path; QFile bout(filepath_store); if(!bout.open(QIODevice::WriteOnly|QIODevice::Text)) throw new SimpleException("保存出错:无法写出到指定文件:"+filepath_store); QTextStream tout(&bout); tout.setCodec("UTF-8"); tout << this->edit_square->toPlainText(); tout.flush(); } QString StoryunitSourceEdit::relativeTargetPath(const QDir &base) const { return base.relativeFilePath(filepath_store); } QString StoryunitSourceEdit::absoluteTargetPath() const { return filepath_store; } QString StoryunitSourceEdit::getText() const { return edit_square->toPlainText(); } bool StoryunitSourceEdit::isModified() const { return true; } void StoryunitSourceEdit::jumpTo(const QList &path) { auto fpath = this->absoluteTargetPath(); auto core = core_ins->parseCore(); if(path.size()){ auto storynode = core->queryStoryUnit(path[0]).first(); auto first_word = storynode->refered()[0]; auto textblock = this->edit_square->document()->findBlockByNumber(first_word->row()); auto cur = this->edit_square->textCursor(); cur.setPosition(textblock.position()); cur.select(QTextCursor::SelectionType::LineUnderCursor); this->edit_square->setTextCursor(cur); if(path.size() > 1){ auto storypoint = core->queryStoryFragment(storynode, path[1]).first(); first_word = storypoint->refered()[0]; auto textblock = this->edit_square->document()->findBlockByNumber(first_word->row()); cur.setPosition(textblock.position()); cur.select(QTextCursor::SelectionType::LineUnderCursor); this->edit_square->setTextCursor(cur); } } edit_square->setFocus(); } QWidget *StoryunitSourceEdit::widget() const { return split; } MakeTools::FilePresent::Features StoryunitSourceEdit::features() { return Feature::Compile | Feature::HighLight; }