QBinaryTranslate/TranslateUI/StructuralRuleView.cpp

422 lines
14 KiB
C++

#include "StructuralRuleView.h"
#include "TranslateBasic.h"
#include "extract_basic.h"
#include <QGridLayout>
#include <QLabel>
#include <QComboBox>
#include <QPushButton>
#include <QSplitter>
#include <QGroupBox>
#include <QTabWidget>
#include <QTextCodec>
#include <QHeaderView>
using namespace configuration_panel;
using namespace size_provider;
ExtractRuleView::ExtractRuleView(std::shared_ptr<TranslateBasic> base,
std::shared_ptr<extract::AsRuleSet> inst_r, QWidget* p /*= nullptr*/)
: QWidget(p), _rule_base(inst_r),
_sequence_view(new RuleSetCustom(base, inst_r, 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(_sequence_view);
split->addWidget(_configs_stack);
_configs_stack->addWidget(new EmptyConfiguration(this));
auto count_span = new CountWithinConfiguration(this);
_configs_stack->addWidget(count_span);
auto encode_config = new EncodingConfiguration(this);
_configs_stack->addWidget(encode_config);
auto combine_config = new BitCombineConfiguration(this);
_configs_stack->addWidget(combine_config);
auto list_config = new ListUnitConfiguration(base, this);
_configs_stack->addWidget(list_config);
connect(count_span, &CountWithinConfiguration::currentRuleChanged,
_sequence_view, &RuleSetCustom::targetRuleRefresh);
connect(encode_config, &EncodingConfiguration::currentRuleChanged,
_sequence_view, &RuleSetCustom::targetRuleRefresh);
connect(combine_config, &BitCombineConfiguration::currentRuleChanged,
_sequence_view, &RuleSetCustom::targetRuleRefresh);
connect(list_config, &ListUnitConfiguration::currentRuleChanged,
_sequence_view, &RuleSetCustom::targetRuleRefresh);
connect(_sequence_view, &RuleSetCustom::currentRuleChanged,
[=](std::shared_ptr<ExtractUnit> u, const QModelIndex& i) {
switch (u->outType()) {
case DataType::TextString:
if (typeid(*u.get()) == typeid(extract::AsString)) {
_configs_stack->setCurrentIndex(2);
encode_config->currentRuleAccept(u, i);
break;
}
else if (typeid(*u.get()) == typeid(extract::AsBitCombine)) {
_configs_stack->setCurrentIndex(3);
combine_config->currentRuleAccept(u, i);
break;
}
case DataType::Integer:
case DataType::Unsigned:
_configs_stack->setCurrentIndex(1);
count_span->currentRuleAccept(u, i);
break;
case DataType::LIST_COLLECTION:
_configs_stack->setCurrentIndex(4);
cacheRefresh(i, list_config);
break;
default:
_configs_stack->setCurrentIndex(0);
break;
}
});
}
void ExtractRuleView::cacheRefresh(const QModelIndex& curr, ListUnitConfiguration* t)
{
if (!curr.isValid())
return;
this->_current_fields_cache->clear();
this->_rule_base->registSubField(this->_current_fields_cache);
auto field_idx = curr.sibling(curr.row(), 0);
this->_current_fields_cache->bindCurrent(field_idx.data(Qt::DisplayRole).toString());
auto ins = this->_rule_base->operator[](curr.row());
auto conv = std::dynamic_pointer_cast<extract::AsList>(ins.second);
if (conv) {
t->currentRuleAccept(conv, curr, this->_current_fields_cache);
}
}
EmptyConfiguration::EmptyConfiguration(QWidget* p/*=nullptr*/)
{
auto layout = new QVBoxLayout(this);
auto label = new QLabel(u8"Can't Configurate.", this);
label->setAlignment(Qt::AlignCenter);
layout->addWidget(label);
}
CountWithinConfiguration::CountWithinConfiguration(QWidget* p /*= nullptr*/)
: QWidget(p), _bind_u(nullptr), _count_input(new QSpinBox(this))
{
auto layout = new QGridLayout(this);
layout->addWidget(new QLabel(tr("BytesCount:")));
layout->addWidget(_count_input, 0, 1);
_count_input->setRange(1, 100);
layout->setRowStretch(1, 1);
layout->setColumnStretch(1, 1);
connect(_count_input, QOverload<int>::of(&QSpinBox::valueChanged), [=](int value) {
if (this->_bind_u) {
auto ptr = std::dynamic_pointer_cast<extract::AbstractExtractor>(this->_bind_u);
if (ptr) {
ptr->setCountWithin(value);
emit this->currentRuleChanged(_bind_index);
}
}
});
}
void CountWithinConfiguration::currentRuleAccept(std::shared_ptr<ExtractUnit> u, const QModelIndex& i)
{
this->_bind_u = u;
this->_bind_index = i;
_count_input->setValue(u->countWithin());
}
EncodingConfiguration::EncodingConfiguration(QWidget* p /*= nullptr*/)
: QWidget(p), _bind_u(nullptr), _count_input(new QSpinBox(this)),
_encoding_set(new QComboBox(this))
{
auto layout = new QGridLayout(this);
layout->addWidget(new QLabel(tr("BytesCount:")));
layout->addWidget(_count_input, 0, 1);
layout->addWidget(new QLabel(tr("Encoding:")), 1, 0);
layout->addWidget(_encoding_set, 1, 1);
layout->setRowStretch(2, 1);
layout->setColumnStretch(1, 1);
connect(_count_input, QOverload<int>::of(&QSpinBox::valueChanged), [=](int value) {
if (this->_bind_u) {
auto ptr = std::dynamic_pointer_cast<extract::AbstractExtractor>(this->_bind_u);
if (ptr) {
ptr->setCountWithin(value);
emit this->currentRuleChanged(_bind_index);
}
}
});
auto codec_list = QTextCodec::availableCodecs();
for (auto codec : codec_list)
_encoding_set->addItem(QString::fromLatin1(codec));
connect(_encoding_set, QOverload<const QString&>::of(&QComboBox::currentIndexChanged),
[=](const QString& value) {
if (this->_bind_u) {
auto ptr = std::dynamic_pointer_cast<extract::AsString>(this->_bind_u);
if (ptr) {
auto insx = QTextCodec::codecForName(value.toUtf8());
ptr->setStrCodec(insx);
emit this->currentRuleChanged(_bind_index);
}
}
});
}
void EncodingConfiguration::currentRuleAccept(std::shared_ptr<ExtractUnit> u, const QModelIndex& i)
{
this->_bind_u = u;
this->_bind_index = i;
_count_input->setValue(u->countWithin());
auto codec_name = std::dynamic_pointer_cast<extract::AsString>(u)->codecName();
QSignalBlocker x(this->_encoding_set);
this->_encoding_set->setCurrentText(codec_name);
}
BitCombineConfiguration::BitCombineConfiguration(QWidget* p /*= nullptr*/)
: QWidget(p), _bind_u(nullptr),
_count_input(new QSpinBox(this)),
_bit_items(new QTableView(this)),
_bit_model(new QStandardItemModel(this)),
_index_appoint(new QSpinBox(this)),
_bit_means(new QLineEdit(this))
{
auto layout = new QGridLayout(this);
layout->addWidget(new QLabel(tr("BytesCount:")));
layout->addWidget(_count_input, 0, 1, 1, 2);
auto group_box = new QGroupBox(tr("BitsContent"));
layout->addWidget(group_box, 1, 0, 3, 3);
layout->setColumnStretch(1, 1);
layout = new QGridLayout(group_box);
layout->addWidget(_bit_items, 0, 0, 3, 3);
layout->addWidget(new QLabel(tr("Bit Index:")), 3, 0);
layout->addWidget(_index_appoint, 3, 1, 1, 2);
layout->addWidget(new QLabel(tr("Bit Means:")), 4, 0);
layout->addWidget(_bit_means, 4, 1, 1, 2);
auto remove = new QPushButton(tr("RemoveItem"));
layout->addWidget(remove, 5, 1);
auto append = new QPushButton(tr("AppendNew"));
layout->addWidget(append, 5, 2);
layout->setColumnStretch(1, 1);
layout->setColumnStretch(2, 1);
_bit_items->setModel(this->_bit_model);
this->_bit_model->setHorizontalHeaderLabels(QStringList() << tr("No.") << tr("Means"));
this->_count_input->setRange(1, 100);
connect(this->_count_input, QOverload<int>::of(&QSpinBox::valueChanged), [=](int value) {
this->_bind_u->setCountWithin(value);
this->_index_appoint->setRange(0, value * 8);
auto options = this->_bind_u->switchOptions();
this->_bind_u->clearOptions();
for (auto key : options.keys()) {
if (key > value * 8)
continue;
this->_bind_u->setSwitchOption(key, options[key]);
}
emit this->currentRuleChanged(_bind_index);
});
connect(append, &QPushButton::clicked, [=]() {
this->_bind_u->setSwitchOption(
this->_index_appoint->value(), this->_bit_means->text());
this->reloadContent(_bind_u);
emit this->currentRuleChanged(this->_bind_index);
});
connect(remove, &QPushButton::clicked, [=]() {
});
}
void BitCombineConfiguration::currentRuleAccept(std::shared_ptr<ExtractUnit> u, const QModelIndex& i)
{
this->_bind_u = std::dynamic_pointer_cast<extract::AsBitCombine>(u);;
this->_bind_index = i;
this->reloadContent(this->_bind_u);
}
void BitCombineConfiguration::reloadContent(std::shared_ptr<extract::AsBitCombine> u)
{
this->_count_input->setValue(u->countWithin());
this->_index_appoint->setRange(0, u->countWithin() * 8);
this->_bit_model->removeRows(0, this->_bit_model->rowCount());
auto items = this->_bind_u->switchOptions();
auto keys = items.keys();
std::sort(keys.begin(), keys.end());
for (auto index : keys) {
auto content = items[index];
QList<QStandardItem*> row;
row << new QStandardItem(QString("%1").arg(index));
row << new QStandardItem(content);
for (auto i : row) i->setEditable(false);
this->_bit_model->appendRow(row);
}
this->_bit_items->resizeColumnsToContents();
this->_bit_items->verticalHeader()->setVisible(false);
}
#define CUSTOM_RULE 0
#define BASIC_RULE 1
ListUnitConfiguration::ListUnitConfiguration(
std::shared_ptr<TranslateBasic> core, QWidget* p /*= nullptr*/)
:QWidget(p), _bind_core(core), _bind_u(nullptr),
_rule_select(new QComboBox(this)),
_size_layout_select(new QComboBox(this)),
_configs_stack(new QStackedWidget(this)),
_const_number_input(new QSpinBox(this)),
_prev_field_refer(new QComboBox(this))
{
auto layout = new QGridLayout(this);
layout->addWidget(new QLabel(tr("RuleAppoint:")), 0, 0);
layout->addWidget(_rule_select, 0, 1, 1, 2);
layout->addWidget(new QLabel(tr("SizeAppoint:")), 1, 0);
layout->addWidget(_size_layout_select, 1, 1, 1, 2);
layout->addWidget(_configs_stack, 2, 0, 2, 3);
_configs_stack->addWidget(_const_number_input);
_configs_stack->addWidget(_prev_field_refer);
layout->setRowStretch(4, 1);
layout->setColumnStretch(1, 1);
for (auto key : this->_bind_core->customRules().keys())
_rule_select->addItem(key, CUSTOM_RULE);
for (auto key : this->_bind_core->extractUnitList().keys())
if (!QList<QString>{"AsList", "AsUnion", "AsRuleSet"}.contains(key))
_rule_select->addItem(key, BASIC_RULE);
auto keys = this->_bind_core->sizeProviderList().keys();
std::sort(keys.begin(), keys.end());
_size_layout_select->addItems(keys);
connect(_size_layout_select, QOverload<int>::of(&QComboBox::currentIndexChanged),
[=](int idx) {
this->_configs_stack->setCurrentIndex(
this->_size_layout_select->currentIndex()
);
});
connect(this->_size_layout_select, &QComboBox::currentTextChanged,
this, &ListUnitConfiguration::sizeProviderSet);
connect(this->_rule_select, &QComboBox::currentTextChanged,
this, &ListUnitConfiguration::elmRuleSet);
connect(this->_const_number_input, QOverload<int>::of(&QSpinBox::valueChanged),
this, &ListUnitConfiguration::constProviderBind);
connect(this->_prev_field_refer, &QComboBox::currentTextChanged,
this, &ListUnitConfiguration::fieldProviderBind);
}
void ListUnitConfiguration::currentRuleAccept(std::shared_ptr<ExtractUnit> u,
const QModelIndex& i, std::shared_ptr<ScopeFieldsGetter> getter)
{
this->_bind_u = std::dynamic_pointer_cast<extract::AsList>(u);
this->_bind_index = i;
reloadContent(this->_bind_u, getter);
}
void ListUnitConfiguration::reloadContent(std::shared_ptr<extract::AsList> u,
std::shared_ptr<ScopeFieldsGetter> getter)
{
QSignalBlocker v(_rule_select);
_rule_select->setCurrentText(u->elementRule()->name());
QSignalBlocker m(_size_layout_select);
_size_layout_select->setCurrentText(u->sizeProvider()->name());
QSignalBlocker vll(_prev_field_refer);
auto item_list = getter->prevFields();
this->_prev_field_refer->clear();
this->_prev_field_refer->addItems(item_list.keys());
auto const_conv = std::dynamic_pointer_cast<ConstNumberProvider>(u->sizeProvider());
if (const_conv) {
_configs_stack->setCurrentIndex(0);
QSignalBlocker v(_const_number_input);
_const_number_input->setValue(const_conv->value(const_conv->expression()));
}
auto runtime_conv = std::dynamic_pointer_cast<InterpretedNumberPrivider>(u->sizeProvider());
if (runtime_conv) {
_configs_stack->setCurrentIndex(1);
this->_prev_field_refer->setCurrentText(runtime_conv->name());
}
}
void ListUnitConfiguration::elmRuleSet(const QString& name)
{
auto type_mark = this->_rule_select->currentData().toInt();
switch (type_mark) {
case CUSTOM_RULE: {
auto target_rule = this->_bind_core->customRules()[name];
_bind_u->setElementRule(target_rule);
}break;
default: {
auto target_unit = this->_bind_core->extractUnitList()[name];
_bind_u->setElementRule(target_unit);
}break;
}
emit this->currentRuleChanged(this->_bind_index);
}
void ListUnitConfiguration::sizeProviderSet(const QString& name)
{
if (name == this->_bind_u->sizeProvider()->name())
return;
auto ninst = this->_bind_core->sizeProviderList()[name]->newDefault();
this->_bind_u->setSizeProvider(std::dynamic_pointer_cast<SizeProvider>(ninst));
auto u = this->_bind_u;
auto const_conv = std::dynamic_pointer_cast<ConstNumberProvider>(u->sizeProvider());
if (const_conv) {
_configs_stack->setCurrentIndex(0);
_const_number_input->setValue(const_conv->value(const_conv->expression()));
}
auto runtime_conv = std::dynamic_pointer_cast<InterpretedNumberPrivider>(u->sizeProvider());
if (runtime_conv) {
_configs_stack->setCurrentIndex(1);
this->_prev_field_refer->setCurrentText(runtime_conv->name());
}
emit this->currentRuleChanged(this->_bind_index);
}
void ListUnitConfiguration::fieldProviderBind(const QString& name)
{
this->_bind_u->sizeProvider()->setExpression(name);
emit this->currentRuleChanged(this->_bind_index);
}
void ListUnitConfiguration::constProviderBind(int value)
{
this->_bind_u->sizeProvider()->setExpression(QString("%1").arg(value));
emit this->currentRuleChanged(this->_bind_index);
}