WsParser_VS/StoryPresent/cmp_present.cpp

324 lines
10 KiB
C++

#include "cmp_present.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSplitter>
#include <QDebug>
using namespace views;
using namespace xast_parse;
using namespace std;
using namespace compare;
StoryChangePresent::StoryChangePresent(
const QHash<QString, shared_ptr<StoryDefine>>& g_base,
const QHash<QString, shared_ptr<StoryDefine>>& g_old,
QWidget* parent) :
QWidget(parent),
base_compare(Compare(g_base)), g_old(g_old),
_type_appoint(new QToolBox(this)),
_fragment_summary(new QTableView(this)),
_upstream_summary(new QTableView(this)),
_change_model(new QStandardItemModel(this)),
_story_appoint(new QComboBox(this)),
_edit_splitter(new QSplitter(this)),
_define_view(new QListView(this)),
_refer_view(new QListView(this)),
_defn_fragment(new StorylineModel),
_curr_refslice(new StorylineModel) {
_type_appoint->layout()->setMargin(1);
_type_appoint->layout()->setSpacing(1);
auto _base_layout = new QVBoxLayout(this);
_base_layout->setMargin(0);
_base_layout->setSpacing(0);
// 功能区域左右分割
auto area_splitter = new QSplitter(this);
_base_layout->addWidget(area_splitter);
area_splitter->addWidget(_type_appoint);
// 编辑区域
auto edit_area = new QWidget(this);
area_splitter->addWidget(edit_area);
auto edit_layout = new QVBoxLayout(edit_area);
edit_layout->setMargin(0);
edit_layout->addWidget(_story_appoint);
edit_layout->addWidget(_edit_splitter, 1);
_edit_splitter->addWidget(_refer_view);
_edit_splitter->addWidget(_define_view);
// ============================
_type_appoint->addItem(_upstream_summary, u8"上游修改");
_type_appoint->addItem(_fragment_summary, u8"情节修改");
auto font_default = this->font();
font_default.setPointSize(16);
this->setFont(font_default);
_define_view->setModel(_defn_fragment);
_refer_view->setModel(_curr_refslice);
_fragment_summary->setModel(_change_model);
_upstream_summary->setModel(_change_model);
// ===========================
connect(_type_appoint, &QToolBox::currentChanged, this, &StoryChangePresent::type_change);
type_change(0);
_define_view->setWordWrap(true);
_define_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
_define_view->setItemDelegate(new StorylineDelegate(_define_view));
_refer_view->setWordWrap(true);
_refer_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
_refer_view->setItemDelegate(new StorylineDelegate(_refer_view));
}
Compare& StoryChangePresent::compareTool() {
return this->base_compare;
}
void StoryChangePresent::type_change(int idx) {
disconnect(_story_appoint, QOverload<const QString&>::of(&QComboBox::currentIndexChanged), nullptr, nullptr);
disconnect(_upstream_summary, &QTableView::pressed, nullptr, nullptr);
disconnect(_fragment_summary, &QTableView::pressed, nullptr, nullptr);
_story_appoint->clear();
_story_appoint->setEnabled(false);
_defn_fragment->loadCurrentSlice(nullptr);
_curr_refslice->loadCurrentSlice(nullptr);
_change_model->clear();
QList<shared_ptr<PointDefines>> fragms;
if (!idx) {
fragms = base_compare.changeCompare(Type::UpstreamAlter, g_old);
}
else {
fragms = base_compare.changeCompare(Type::FragmentAlter, g_old);
}
_change_model->setHorizontalHeaderLabels(QStringList() << u8"故事名称" << u8"情节名称");
for (auto fragm : fragms) {
auto story = dynamic_pointer_cast<StoryDefine>(fragm->parentSlice().lock());
QList<QStandardItem*> row;
row << new QStandardItem(story->name());
row << new QStandardItem(fragm->name());
_change_model->appendRow(row);
}
_upstream_summary->resizeColumnsToContents();
_fragment_summary->resizeColumnsToContents();
connect(_upstream_summary, &QTableView::pressed, this, &StoryChangePresent::fragment_selected);
connect(_fragment_summary, &QTableView::pressed, this, &StoryChangePresent::fragment_selected);
}
pair<QString, qlonglong> combine_with(const QList<QString>& sections) {
if (sections.isEmpty())
return pair<QString, qlonglong>();
auto head_rst = combine_with(sections.mid(0, sections.size() - 1));
auto target_str = sections.last();
auto final_rst = make_pair(
head_rst.first + "/" + target_str,
head_rst.second << 8 + target_str.size()
);
return final_rst;
}
void StoryChangePresent::fragment_selected(const QModelIndex& item) {
if (!item.isValid())
return;
disconnect(_story_appoint, QOverload<const QString&>::of(&QComboBox::currentIndexChanged), nullptr, nullptr);
_story_appoint->clear();
_story_appoint->setEnabled(true);
auto story_index = item.sibling(item.row(), 0);
auto fragm_index = item.sibling(item.row(), 1);
auto story_item = this->_change_model->itemFromIndex(story_index);
auto fragm_item = this->_change_model->itemFromIndex(fragm_index);
auto story_inst = this->base_compare.graphBind()[story_item->text()];
auto fragm_slice = story_inst->getFragment(fragm_item->text());
auto fragm_def = dynamic_pointer_cast<PointDefines>(fragm_slice);
_defn_fragment->loadCurrentSlice(fragm_def);
connect(_story_appoint, QOverload<const QString&>::of(&QComboBox::currentIndexChanged),
this, &StoryChangePresent::storyline_selected);
for (auto refer : fragm_def->referSlices()) {
auto def_v = combine_with(refer->nameSet());
_story_appoint->addItem(def_v.first, def_v.second);
}
}
void StoryChangePresent::storyline_selected(const QString& line) {
auto def_fragm = dynamic_pointer_cast<PointDefines>(_defn_fragment->currentSlice());
auto flag = _story_appoint->currentData();
for (auto slice : def_fragm->referSlices()) {
auto defv = combine_with(slice->nameSet());
if (flag == defv.second && line == defv.first) {
_curr_refslice->loadCurrentSlice(slice);
break;
}
}
}
void StorylineModel::loadCurrentSlice(shared_ptr<IElementSlice> target_node) {
this->beginResetModel();
this->_current_slice = target_node;
_nodes_temp.clear();
if (this->_current_slice) {
auto pslice = this->_current_slice->parentSlice().lock();
auto conn = dynamic_pointer_cast<ICollection>(pslice);
auto temp_node = conn->firstChild();
while (temp_node) {
_nodes_temp << temp_node;
temp_node = temp_node->nextSlice();
}
}
this->endResetModel();
}
shared_ptr<IElementSlice> StorylineModel::currentSlice() {
return this->_current_slice;
}
QModelIndex StorylineModel::index(int row, int column, const QModelIndex& parent) const {
return createIndex(row, column);
}
QModelIndex StorylineModel::parent(const QModelIndex& child) const {
return QModelIndex();
}
int StorylineModel::rowCount(const QModelIndex& parent) const {
return _nodes_temp.size();
}
int StorylineModel::columnCount(const QModelIndex& parent) const {
return 1;
}
QVariant StorylineModel::data(const QModelIndex& index, int role) const {
switch (role) {
case Qt::EditRole:
case Qt::DisplayRole:
{
auto curr_node = _nodes_temp.at(index.row());
switch (curr_node->type()) {
case SliceType::TextPragraph:
{
auto node = dynamic_pointer_cast<TextParagraph>(curr_node);
return node->getLines();
}
case SliceType::FragmentDefines:
{
auto node = dynamic_pointer_cast<PointDefines>(curr_node);
return node->getTextNode()->getLines();
}
case SliceType::PointRefers:
{
auto node = dynamic_pointer_cast<FragmentRefer>(curr_node);
return node->getTextNode()->getLines();
}
}
}
case Qt::BackgroundRole:
{
auto curr_node = _nodes_temp.at(index.row());
if (curr_node == _current_slice) {
return QColor(Qt::lightGray);
}
return QColor(Qt::white);
}
default:
return QVariant();
}
}
Qt::ItemFlags StorylineModel::flags(const QModelIndex& idx) const {
auto flags = QAbstractItemModel::flags(idx);
auto curr_node = _nodes_temp.at(idx.row());
if (curr_node == _current_slice)
return flags | Qt::ItemIsEditable;
return flags;
}
bool StorylineModel::setData(const QModelIndex& index, const QVariant& value, int role) {
if (role == Qt::EditRole) {
auto curr_node = _nodes_temp.at(index.row());
switch (curr_node->type()) {
case SliceType::TextPragraph:
{
auto tnode = dynamic_pointer_cast<TextParagraph>(curr_node);
tnode->setLines(value.toString());
}break;
case SliceType::FragmentDefines:
{
auto defnode = dynamic_pointer_cast<PointDefines>(curr_node);
defnode->getTextNode()->setLines(value.toString());
}break;
case SliceType::PointRefers:
{
auto refnode = dynamic_pointer_cast<FragmentRefer>(curr_node);
refnode->getTextNode()->setLines(value.toString());
}break;
default:
return false;
}
this->dataChanged(index, index, QVector<int>() << Qt::EditRole << Qt::DisplayRole);
return true;
}
else {
return QAbstractItemModel::setData(index, value, role);
}
}
#include <QTextEdit>
StorylineDelegate::StorylineDelegate(QAbstractItemView* pwidget)
:QStyledItemDelegate(pwidget), bind_view(pwidget) { }
QWidget* StorylineDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
return new QTextEdit(bind_view);
}
void StorylineDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const {
static_cast<QTextEdit*>(editor)->setText(index.data(Qt::EditRole).toString());
}
void StorylineDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const {
auto ned = static_cast<QTextEdit*>(editor);
model->setData(index, ned->toPlainText(), Qt::EditRole);
}
void StorylineDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const {
editor->setGeometry(option.rect);
}
QSize StorylineDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const {
return QStyledItemDelegate::sizeHint(option, index) + QSize(0, 20);
}
#include <QMenu>
#include <QMenuBar>
#include <QFileDialog>
CompareWindow::CompareWindow(QFileInfo filebase, QFileInfo fileold)
:_graph_base(XAST_Parser(filebase.canonicalFilePath())),
_graph_old(XAST_Parser(fileold.canonicalFilePath())),
_cmp_widget(new StoryChangePresent(_graph_base.storyGraph(), _graph_old.storyGraph())) {
auto mbar = menuBar();
auto file = mbar->addMenu(u8"文件");
file->addAction(u8"另存为", [=]() {
auto target = QFileDialog::getExistingDirectory(this, "获取目标文件夹", QDir::homePath());
if (target == u8"")
return;
this->_graph_base.output(QDir(target));
});
this->setCentralWidget(_cmp_widget);
}