QBinaryTranslate/TranslateUI/ExtractRuleView.cpp

330 lines
11 KiB
C++

#include "ExtractRuleView.h"
#include "TranslateBasic.h"
#include "extract_basic.h"
#include "WrapConfigs.h"
#include <QGridLayout>
#include <QLabel>
#include <QComboBox>
#include <QJsonDocument>
#include <QPushButton>
#include <QSplitter>
#include <QGroupBox>
#include <QTabWidget>
#include <QTextCodec>
#include <QMenu>
#include <QHeaderView>
using namespace unit_configurations;
using namespace size_provider;
using namespace extract;
ExtractRuleView::ExtractRuleView(std::shared_ptr<TranslateBasic> base,
std::shared_ptr<extract::AsRuleSet> inst_r, QWidget* p /*= nullptr*/)
: QWidget(p), _rule_base(inst_r), _base_bind(base),
_member_units(new QTableView(this)),
_member_model(new QStandardItemModel(this)),
_configs_stack(new QStackedWidget(this))
{
this->_current_fields_cache = std::make_shared<FieldManagerLayer>("", nullptr);
auto layout = new QVBoxLayout(this);
auto split = new QSplitter(Qt::Horizontal, this);
layout->addWidget(split);
split->addWidget(_member_units);
split->addWidget(_configs_stack);
_configs_stack->addWidget(new configurations::EmptyConfiguration(this));
auto single_configs = new SingleBasedConfiguration(base, this);
_configs_stack->addWidget(single_configs);
auto list_configs = new ListBasedConfiguration(base, this);
_configs_stack->addWidget(list_configs);
auto union_configs = new UnionBasedConfiguration(base, this);
_configs_stack->addWidget(union_configs);
connect(_member_units, &QTableView::clicked, [=](const QModelIndex& target) {
if (!target.isValid())
return;
auto unit = _rule_base->operator[](target.row());
if (unit->baseType() == SingleBasedUnit::topic()) {
_configs_stack->setCurrentIndex(1);
single_configs->currentAccept(unit, target);
}
else if (unit->baseType() == ListBasedUnit::topic()) {
_configs_stack->setCurrentIndex(2);
list_configs->currentAccept(unit, target);
}
else if (unit->baseType() == UnionBasedUnit::topic()) {
_configs_stack->setCurrentIndex(3);
union_configs->currentAccept(unit, target);
}
else {
_configs_stack->setCurrentIndex(0);
}
});
_member_units->setModel(_member_model);
_member_model->setHorizontalHeaderLabels(QStringList() << "FieldName" << "OffsetSpan" << "UnitType");
_member_units->setContextMenuPolicy(Qt::CustomContextMenu);
connect(_member_units, &QTableView::customContextMenuRequested, [=](const QPoint& pt) {
QMenu m;
m.addAction("Append Unit", this, &ExtractRuleView::appendUnit);
m.exec(_member_units->mapToGlobal(pt));
});
}
void ExtractRuleView::reload()
{
auto cnt = _member_model->rowCount();
_member_model->removeRows(0, cnt);
auto list = _rule_base->fieldNames();
for (auto key : list) {
auto field_mbr = _rule_base->operator[](key);
QList<QStandardItem*> row;
row << new QStandardItem(field_mbr->name());
row << new QStandardItem(QString("%1").arg(field_mbr->offsetSpan()));
row.last()->setEditable(false);
row << new QStandardItem(field_mbr->baseType());
_member_model->appendRow(row);
}
_member_units->resizeColumnsToContents();
}
#include <QInputDialog>
void ExtractRuleView::appendUnit()
{
auto name_u = QInputDialog::getText(this, "FieldName Enter", "Name");
if (name_u == "")
return;
auto inst_u = _base_bind->defaultExtractUnitType()->newDefault();
auto new_unit = std::dynamic_pointer_cast<SingleBasedUnit>(inst_u);
new_unit->setName(name_u);
auto delt_key = _base_bind->delegateAlias().first();
auto delt_o = _base_bind->operator[](delt_key);
auto delt_u = delt_o->newDefault();
QJsonObject content;
delt_o->saveTo(content);
delt_u->loadFrom(_base_bind, content);
new_unit->setDelegate(std::dynamic_pointer_cast<ExtractDelegate>(delt_u));
this->_rule_base->append(new_unit);
reload();
}
void ExtractRuleView::showEvent(QShowEvent* e)
{
QWidget::showEvent(e);
reload();
}
ListBasedConfiguration::ListBasedConfiguration(
std::shared_ptr<TranslateBasic> core, QWidget* p /*= nullptr*/)
:QWidget(p), _bind_core(core),
_offset_enter(new QSpinBox(this)),
_delegate_sync(new QPushButton("Sync", this)),
_delegate_select(new QComboBox(this)),
_size_layout_select(new QComboBox(this)),
_configs_stack(new QStackedWidget(this)),
_content_display(new QTextBrowser(this)),
_const_number_input(new QSpinBox(this)),
_prev_field_refer(new QComboBox(this))
{
auto layout = new QGridLayout(this);
layout->addWidget(new QLabel("OffsetSpan:", this), 0, 0);
layout->addWidget(this->_offset_enter, 0, 1);
layout->addWidget(this->_delegate_sync, 0, 2);
layout->addWidget(new QLabel(tr("Delegate:")), 1, 0);
layout->addWidget(_delegate_select, 1, 1, 1, 2);
layout->addWidget(new QLabel(tr("Size:")), 2, 0);
layout->addWidget(_size_layout_select, 2, 1, 1, 2);
layout->addWidget(_configs_stack, 3, 0, 2, 3);
_configs_stack->addWidget(_const_number_input);
_configs_stack->addWidget(_prev_field_refer);
layout->addWidget(this->_content_display, 5, 0, 3, 3);
layout->setRowStretch(7, 1);
layout->setColumnStretch(1, 1);
connect(_offset_enter, QOverload<int>::of(&QSpinBox::valueChanged),
[=](int v) {
this->_bind_u->setOffsetSpan(v);
currentAccept(_bind_u, _bind_index, _fields_getter);
emit this->reloadRequest();
});
connect(_delegate_select, QOverload<const QString&>::of(&QComboBox::currentTextChanged),
[=](const QString& current_delegate) {
auto delt_o = _bind_core->operator[](current_delegate);
QJsonObject object;
delt_o->saveTo(object);
auto delt_ins = delt_o->newDefault();
delt_ins->loadFrom(_bind_core, object);
_bind_u->setDelegate(std::dynamic_pointer_cast<ExtractDelegate>(delt_ins));
currentAccept(_bind_u, _bind_index, _fields_getter);
emit this->reloadRequest();
});
connect(_size_layout_select, QOverload<const QString&>::of(&QComboBox::currentTextChanged),
[=](const QString& size_provider_name) {
auto size_o = _bind_core->sizeProviderMap()[size_provider_name];
auto size_ins = std::dynamic_pointer_cast<SizeProvider>(size_o->newDefault());
this->_bind_u->setSizeProvider(size_ins);
if (size_provider_name == ConstNumberProvider::topic()) {
_configs_stack->setCurrentIndex(0);
size_ins->setExpression("0");
_const_number_input->setValue(0);
}
if (size_provider_name == InterpretedNumberPrivider::topic()) {
_configs_stack->setCurrentIndex(1);
QSignalBlocker s(_prev_field_refer);
_prev_field_refer->clear();
s.unblock();
auto fields_map = _fields_getter->prevFields();
for (auto field_name : fields_map.keys()) {
_prev_field_refer->addItem(field_name, (int)fields_map[field_name]);
}
}
currentAccept(_bind_u, _bind_index, _fields_getter);
emit this->reloadRequest();
});
connect(_const_number_input, QOverload<int>::of(&QSpinBox::valueChanged),
[=](int value) {
auto size_ins = _bind_u->sizeProvider();
size_ins->setExpression(QString("%1").arg(value));
currentAccept(_bind_u, _bind_index, _fields_getter);
emit this->reloadRequest();
});
connect(_prev_field_refer, QOverload<const QString&>::of(&QComboBox::currentTextChanged),
[=](const QString& current_field) {
auto size_ins = _bind_u->sizeProvider();
size_ins->setExpression(current_field);
currentAccept(_bind_u, _bind_index, _fields_getter);
emit this->reloadRequest();
});
}
void ListBasedConfiguration::currentAccept(std::shared_ptr<ExtractUnit> inst_u,
const QModelIndex& idx, std::shared_ptr<ScopeFieldsGetter> get)
{
_bind_u = std::dynamic_pointer_cast<ListBasedUnit>(inst_u);
_bind_index = idx;
_fields_getter = get;
QSignalBlocker v(_offset_enter);
_offset_enter->setRange(0, INT_MAX);
_offset_enter->setValue(inst_u->offsetSpan());
QSignalBlocker vx(_delegate_select);
this->_bind_u = std::dynamic_pointer_cast<extract::ListBasedUnit>(inst_u);
_delegate_select->clear();
_delegate_select->addItems(_bind_core->delegateAlias());
_delegate_select->setCurrentText(this->_bind_u->delegateInst()->aliasName());
QSignalBlocker vv(_size_layout_select);
this->_size_layout_select->clear();
this->_size_layout_select->addItems(_bind_core->sizeProviderMap().keys());
this->_size_layout_select->setCurrentText(_bind_u->sizeProvider()->name());
if (this->_size_layout_select->currentText() == ConstNumberProvider::topic()) {
_configs_stack->setCurrentIndex(0);
auto size_const = std::dynamic_pointer_cast<ConstNumberProvider>(_bind_u->sizeProvider());
QSignalBlocker s(_const_number_input);
_const_number_input->setValue(size_const->value(size_const->expression()));
}
if (this->_size_layout_select->currentText() == InterpretedNumberPrivider::topic()) {
_configs_stack->setCurrentIndex(1);
auto size_rt = std::dynamic_pointer_cast<InterpretedNumberPrivider>(_bind_u->sizeProvider());
QSignalBlocker s(_prev_field_refer);
_prev_field_refer->clear();
auto fields_map = get->prevFields();
for (auto field_name : fields_map.keys()) {
_prev_field_refer->addItem(field_name, (int)fields_map[field_name]);
}
_prev_field_refer->setCurrentText(size_rt->expression());
}
QJsonObject content;
_bind_u->saveTo(content);
_content_display->setText(
QString::fromUtf8(QJsonDocument(content).toJson())
);
}
SingleBasedConfiguration::SingleBasedConfiguration(std::shared_ptr<TranslateBasic> core, QWidget* p /*= nullptr*/)
: QWidget(p), _bind_core(core),
_offset_enter(new QSpinBox(this)),
_delegate_changed(new QComboBox(this)),
_delegate_sync(new QPushButton("Sync", this)),
_content_display(new QTextBrowser(this))
{
auto layout = new QGridLayout(this);
layout->addWidget(new QLabel("Offset:", this), 0, 0);
layout->addWidget(this->_offset_enter, 0, 1);
layout->addWidget(this->_delegate_sync, 0, 2);
layout->addWidget(new QLabel("Delegate:", this), 1, 0);
layout->addWidget(this->_delegate_changed, 1, 1, 1, 2);
layout->addWidget(this->_content_display, 2, 0, 3, 3);
layout->setColumnStretch(1, 1);
connect(this->_offset_enter, QOverload<int>::of(&QSpinBox::valueChanged),
[=](int v_offset) {
inst_current->setOffsetSpan(v_offset);
currentAccept(this->inst_current, this->idx_current);
emit this->reloadRequest();
});
connect(this->_delegate_changed, QOverload<const QString&>::of(&QComboBox::currentTextChanged),
[=](const QString& current_alias) {
auto o_inst = _bind_core->operator[](current_alias);
auto v_inst = o_inst->newDefault();
QJsonObject content;
o_inst->saveTo(content);
v_inst->loadFrom(_bind_core, content);
inst_current->setDelegate(std::dynamic_pointer_cast<ExtractDelegate>(v_inst));
currentAccept(this->inst_current, this->idx_current);
emit this->reloadRequest();
});
}
void SingleBasedConfiguration::currentAccept(std::shared_ptr<ExtractUnit> inst_u, const QModelIndex& idx)
{
inst_current = std::dynamic_pointer_cast<SingleBasedUnit>(inst_u);
idx_current = idx;
QSignalBlocker b(_offset_enter);
_offset_enter->setRange(0, INT_MAX);
_offset_enter->setValue(inst_u->offsetSpan());
QSignalBlocker v(_delegate_changed);
_delegate_changed->clear();
_delegate_changed->addItems(_bind_core->delegateAlias());
auto conv = std::dynamic_pointer_cast<SingleBasedUnit>(inst_u);
_delegate_changed->setCurrentText(conv->delegateInst()->aliasName());
QJsonObject contents;
inst_u->saveTo(contents);
this->_content_display->setPlainText(QString::fromUtf8(
QJsonDocument(contents).toJson()
));
}
UnionBasedConfiguration::UnionBasedConfiguration(std::shared_ptr<TranslateBasic> core, QWidget* p /*= nullptr*/)
{
}
void UnionBasedConfiguration::currentAccept(std::shared_ptr<ExtractUnit> inst_u, const QModelIndex& idx)
{
}