#include "StructuralRuleView.h" #include "TranslateBasic.h" #include "extract_basic.h" #include #include #include #include #include #include #include #include #include using namespace configuration_panel; using namespace size_provider; ExtractRuleView::ExtractRuleView(std::shared_ptr base, std::shared_ptr 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("", 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 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(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::of(&QSpinBox::valueChanged), [=](int value) { if (this->_bind_u) { auto ptr = std::dynamic_pointer_cast(this->_bind_u); if (ptr) { ptr->setCountWithin(value); emit this->currentRuleChanged(_bind_index); } } }); } void CountWithinConfiguration::currentRuleAccept(std::shared_ptr 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::of(&QSpinBox::valueChanged), [=](int value) { if (this->_bind_u) { auto ptr = std::dynamic_pointer_cast(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::of(&QComboBox::currentIndexChanged), [=](const QString& value) { if (this->_bind_u) { auto ptr = std::dynamic_pointer_cast(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 u, const QModelIndex& i) { this->_bind_u = u; this->_bind_index = i; _count_input->setValue(u->countWithin()); auto codec_name = std::dynamic_pointer_cast(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::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 u, const QModelIndex& i) { this->_bind_u = std::dynamic_pointer_cast(u);; this->_bind_index = i; this->reloadContent(this->_bind_u); } void BitCombineConfiguration::reloadContent(std::shared_ptr 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 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 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{"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::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::of(&QSpinBox::valueChanged), this, &ListUnitConfiguration::constProviderBind); connect(this->_prev_field_refer, &QComboBox::currentTextChanged, this, &ListUnitConfiguration::fieldProviderBind); } void ListUnitConfiguration::currentRuleAccept(std::shared_ptr u, const QModelIndex& i, std::shared_ptr getter) { this->_bind_u = std::dynamic_pointer_cast(u); this->_bind_index = i; reloadContent(this->_bind_u, getter); } void ListUnitConfiguration::reloadContent(std::shared_ptr u, std::shared_ptr 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(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(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(ninst)); auto u = this->_bind_u; auto const_conv = std::dynamic_pointer_cast(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(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); }