#include "ExtractRuleView.h" #include "TranslateBasic.h" #include "extract_basic.h" #include "WrapConfigs.h" #include #include #include #include #include #include #include #include #include #include #include using namespace unit_configurations; using namespace size_provider; using namespace extract; ExtractRuleView::ExtractRuleView(std::shared_ptr base, std::shared_ptr inst_r, QWidget* p /*= nullptr*/) : QWidget(p), _current_rule(inst_r), _basic_bind(base), _member_units(new QTableView(this)), _members_model(new QStandardItemModel(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(_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(single_configs, &SingleBasedConfiguration::reloadRequest, this, &ExtractRuleView::reload); connect(list_configs, &ListBasedConfiguration::reloadRequest, this, &ExtractRuleView::reload); connect(union_configs, &UnionBasedConfiguration::reloadRequest, this, &ExtractRuleView::reload); connect(_member_units, &QTableView::clicked, [=](const QModelIndex& target) { if (!target.isValid()) return; auto unit = _current_rule->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); FieldManagerLayer::__Private::fields_map.clear(); _current_fields_cache = std::make_shared("{self}"); this->_current_rule->registSubField(_current_fields_cache); auto current_field = this->_current_rule->operator[](target.row()); _current_fields_cache->bindCurrent(current_field->name()); list_configs->currentAccept(unit, target, _current_fields_cache); } else if (unit->baseType() == UnionBasedUnit::topic()) { _configs_stack->setCurrentIndex(3); FieldManagerLayer::__Private::fields_map.clear(); _current_fields_cache = std::make_shared("{self}"); this->_current_rule->registSubField(_current_fields_cache); auto current_field = this->_current_rule->operator[](target.row()); _current_fields_cache->bindCurrent(current_field->name()); union_configs->currentAccept(unit, target, _current_fields_cache); } else { _configs_stack->setCurrentIndex(0); } }); _member_units->setModel(_members_model); connect(_members_model, &QStandardItemModel::itemChanged, this, &ExtractRuleView::dataChanged); _member_units->setItemDelegateForColumn(2, new UnitSelectDelegate(_basic_bind)); _members_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 = _members_model->rowCount(); _members_model->removeRows(0, cnt); auto list = _current_rule->fieldNames(); for (auto key : list) { auto field_mbr = _current_rule->operator[](key); QList row; row << new QStandardItem(field_mbr->name()); row << new QStandardItem(QString("%1 bytes").arg(field_mbr->offsetSpan())); row.last()->setEditable(false); row << new QStandardItem(field_mbr->baseType()); _members_model->appendRow(row); } _member_units->resizeColumnsToContents(); } #include #include void ExtractRuleView::appendUnit() { auto name_u = QInputDialog::getText(this, "FieldName Enter", "Name"); if (name_u == "") return; if (this->_current_rule->fieldNames().contains(name_u)) { QMessageBox::critical(this, "DataValidate", "Field can't repeat"); return; } auto unit_template = _basic_bind->defaultExtractUnitType()->newDefault(); auto new_unit = std::dynamic_pointer_cast(unit_template); new_unit->setName(name_u); auto delt_key = _basic_bind->customDelegateAlias().first(); auto delt_o = _basic_bind->operator[](delt_key); QJsonObject content; delt_o->saveTo(content); auto delt_u = delt_o->newDefault(); delt_u->loadFrom(_basic_bind, content); new_unit->setDelegate(std::dynamic_pointer_cast(delt_u)); this->_current_rule->append(new_unit); reload(); } void ExtractRuleView::dataChanged(QStandardItem* item) { auto current_unit = this->_current_rule->operator[](item->row()); switch (item->column()) { case 0: { auto fields_names = this->_current_rule->fieldNames(); if (fields_names.contains(item->text())) { QMessageBox::critical(this, "DataValidate", "Field can't repeat"); } else { current_unit->setName(item->text()); } reload(); }break; case 2: { // 提取Template名称 auto unit_template = this->_basic_bind->extractUnitTypeMap()[item->text()]; // 创建新单元副本 auto unit_ins = std::dynamic_pointer_cast(unit_template->newDefault()); unit_ins->setName(current_unit->name()); // 替换旧有单元类型 this->_current_rule->replace(item->row(), unit_ins); // 单数据解构类型 if (unit_ins->baseType() == SingleBasedUnit::topic()) { auto single_ins = std::dynamic_pointer_cast(unit_ins); auto delt_name = _basic_bind->customDelegateAlias().first(); auto delt_base = _basic_bind->operator[](delt_name); QJsonObject object; delt_base->saveTo(object); auto delt_conv = std::dynamic_pointer_cast(delt_base->newDefault()); delt_conv->loadFrom(_basic_bind, object); single_ins->setDelegate(std::dynamic_pointer_cast(delt_conv)); } // 列表数据解构类型 if (unit_ins->baseType() == ListBasedUnit::topic()) { auto list_ins = std::dynamic_pointer_cast(unit_ins); auto delt_name = _basic_bind->customDelegateAlias().first(); auto delt_base = _basic_bind->operator[](delt_name); QJsonObject object; delt_base->saveTo(object); auto delt_elm = std::dynamic_pointer_cast(delt_base->newDefault()); delt_elm->loadFrom(_basic_bind, object); list_ins->setDelegate(delt_elm); auto size_o = _basic_bind->defaultSizeProviderType(); QJsonObject mobject; size_o->saveTo(mobject); auto size_copy = std::dynamic_pointer_cast(size_o->newDefault()); size_copy->loadFrom(_basic_bind, mobject); list_ins->setSizeProvider(size_copy); } }break; default: break; } } void ExtractRuleView::showEvent(QShowEvent* e) { QWidget::showEvent(e); reload(); } ListBasedConfiguration::ListBasedConfiguration( std::shared_ptr 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(new QLabel(tr("Exprs:")), 3, 0); layout->addWidget(_configs_stack, 3, 1, 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::of(&QSpinBox::valueChanged), [=](int v) { this->_bind_u->setOffsetSpan(v); currentAccept(_bind_u, _bind_index, _fields_getter); emit this->reloadRequest(); }); connect(_delegate_select, QOverload::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(delt_ins)); currentAccept(_bind_u, _bind_index, _fields_getter); emit this->reloadRequest(); }); connect(_size_layout_select, QOverload::of(&QComboBox::currentTextChanged), [=](const QString& size_provider_name) { auto size_o = _bind_core->sizeProviderTypeMap()[size_provider_name]; auto size_ins = std::dynamic_pointer_cast(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()) { switch (fields_map[field_name]) { case DataType::Integer: case DataType::Unsigned: _prev_field_refer->addItem(tr("BindField:") + field_name, field_name); default: break; } } } currentAccept(_bind_u, _bind_index, _fields_getter); emit this->reloadRequest(); }); connect(_const_number_input, QOverload::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::of(&QComboBox::currentTextChanged), [=]() { auto current_field = _prev_field_refer->currentData().toString(); 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 inst_u, const QModelIndex& idx, std::shared_ptr get) { _bind_u = std::dynamic_pointer_cast(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(inst_u); _delegate_select->clear(); _delegate_select->addItems(_bind_core->customDelegateAlias()); _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->sizeProviderTypeMap().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(_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(_bind_u->sizeProvider()); QSignalBlocker s(_prev_field_refer); _prev_field_refer->clear(); auto fields_map = _fields_getter->prevFields(); for (auto field_name : fields_map.keys()) { switch (fields_map[field_name]) { case DataType::Integer: case DataType::Unsigned: _prev_field_refer->addItem(tr("BindField:") + field_name, field_name); default: break; } } if (size_rt->expression() == QString()) { auto text_expr = _prev_field_refer->currentData().toString(); size_rt->setExpression(text_expr); } for (auto idx = 0; idx < _prev_field_refer->count(); ++idx) { auto expr_t = _prev_field_refer->itemData(idx).toString(); if (size_rt->expression() == expr_t) { _prev_field_refer->setCurrentIndex(idx); break; } } } QJsonObject content; _bind_u->saveTo(content); _content_display->setText( QString::fromUtf8(QJsonDocument(content).toJson()) ); } SingleBasedConfiguration::SingleBasedConfiguration(std::shared_ptr 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::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::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(v_inst)); currentAccept(this->inst_current, this->idx_current); emit this->reloadRequest(); }); } void SingleBasedConfiguration::currentAccept(std::shared_ptr inst_u, const QModelIndex& idx) { inst_current = std::dynamic_pointer_cast(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->customDelegateAlias()); auto conv = std::dynamic_pointer_cast(inst_u); _delegate_changed->setCurrentText(conv->delegateInst()->aliasName()); QJsonObject contents; inst_u->saveTo(contents); this->_content_display->setPlainText(QString::fromUtf8( QJsonDocument(contents).toJson() )); } #include UnionBasedConfiguration::UnionBasedConfiguration(std::shared_ptr core, QWidget* p /*= nullptr*/) : QWidget(p), _offset_enter(new QSpinBox(this)), _size_input(new QSpinBox(this)), _context_present(new QTextEdit(this)), _match_select(new QComboBox(this)), _delegate_select(new QComboBox(this)), _members_present(new QTableView(this)), _members_model(new QStandardItemModel(this)), _intfield_bind(new QComboBox(this)), _compare_op(new QComboBox(this)), _value_enters(new QSpinBox(this)) { _members_present->setModel(_members_model); auto layout = new QGridLayout(this); layout->addWidget(new QLabel(tr("OffsetSpan:")), 0, 0); layout->addWidget(_offset_enter, 0, 1, 1, 2); layout->addWidget(new QLabel(tr("SizeConst:")), 1, 0); layout->addWidget(_size_input, 1, 1, 1, 2); // ==================================================== auto tabw = new QTabWidget(this); layout->addWidget(tabw, 2, 0, 3, 3); tabw->addTab(_context_present, tr("Unit")); layout->setColumnStretch(1, 1); // ===================================================== auto custom_panel = new QWidget(this); tabw->addTab(custom_panel, tr("Members")); auto cust_layout = new QGridLayout(custom_panel); cust_layout->addWidget(_members_present, 0, 0, 3, 3); cust_layout->addWidget(new QPushButton(tr("AppendNew")), 3, 1); cust_layout->addWidget(new QPushButton(tr("Delete")), 3, 2); cust_layout->addWidget(new QLabel(tr("MatchType:")), 4, 0); cust_layout->addWidget(_match_select, 4, 1, 1, 2); cust_layout->addWidget(new QLabel(tr("Delegate:")), 5, 0); cust_layout->addWidget(_delegate_select, 5, 1, 1, 2); auto toolbox = new QStackedWidget(this); cust_layout->addWidget(toolbox, 6, 0, 3, 3); auto panelx = new QWidget(this); toolbox->addWidget(panelx); auto gpanelx = new QGridLayout(panelx); gpanelx->addWidget(new QLabel(tr("BindField:")), 0, 0); gpanelx->addWidget(_intfield_bind, 0, 1, 1, 2); gpanelx->addWidget(new QLabel(tr("Operator:")), 1, 0); gpanelx->addWidget(_compare_op, 1, 1, 1, 2); gpanelx->addWidget(new QLabel(tr("Value:")), 2, 0); gpanelx->addWidget(_value_enters, 2, 1, 1, 2); gpanelx->setColumnStretch(1, 1); gpanelx->setColumnStretch(2, 1); gpanelx->setMargin(0); cust_layout->setRowStretch(1, 1); cust_layout->setColumnStretch(1, 1); cust_layout->setColumnStretch(2, 1); } void UnionBasedConfiguration::currentAccept(std::shared_ptr inst_u, const QModelIndex& idx, std::shared_ptr get) { } UnitSelectDelegate::UnitSelectDelegate(std::shared_ptr ins) : _kernel(ins) { } QWidget* UnitSelectDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { return new QComboBox(parent); } void UnitSelectDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { auto combo = dynamic_cast(editor); combo->addItems(_kernel->extractUnitTypeMap().keys()); combo->setCurrentText(index.data(Qt::DisplayRole).toString()); } void UnitSelectDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { auto combo = dynamic_cast(editor); model->setData(index, combo->currentText(), Qt::EditRole); } void UnitSelectDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { editor->setGeometry(option.rect); }