#include "SequenceView.h" #include #include #include #include "TranslateBasic.h" using namespace extract; IntDelegate::IntDelegate(int min, int max) : _min_value(min), _max_value(max) { } QWidget* IntDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { return new QSpinBox(parent); } void IntDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { auto spin = dynamic_cast(editor); spin->setRange(_min_value, _max_value); spin->setValue(index.data(Qt::DisplayRole).toInt()); } void IntDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { auto value = dynamic_cast(editor); model->setData(index, value->value(), Qt::EditRole); emit this->valueChanged(index); } void IntDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { editor->setGeometry(option.rect); } void RuleSetCustom::targetRuleRefresh(const QModelIndex& idx) { auto rule_insv = _view._ruleset->_bind[idx.row()]; auto offset_index = idx.sibling(idx.row(), 1); auto offset_number = offset_index.data(Qt::DisplayRole).toInt(); rule_insv.second->setOffsetSpan(offset_number); auto count_index = idx.sibling(idx.row(), 3); _view._seqs_model->setData(offset_index, rule_insv.second->offsetSpan(), Qt::EditRole); _view._seqs_model->setData(count_index, rule_insv.second->countWithin(), Qt::EditRole); auto param_index = idx.sibling(idx.row(), 4); QJsonObject obj; rule_insv.second->saveTo(obj); auto bytes = QJsonDocument(obj).toJson(QJsonDocument::Compact); _view._seqs_model->setData(param_index, QString::fromUtf8(bytes)); this->resizeColumnsToContents(); } void RuleSetCustom::peersRuleChanged(const QModelIndex& idx) { auto field_idx = idx.sibling(idx.row(), 0); auto field_name = field_idx.data(Qt::DisplayRole).toString(); auto rule_idx = idx.sibling(idx.row(), 2); auto rule_name = rule_idx.data(Qt::DisplayRole).toString(); auto rule_nm = _view.base->extractUnitList()[rule_name]; auto new_inst = std::dynamic_pointer_cast(rule_nm->newDefault()); _view._ruleset->_bind.replace(idx.row(), std::make_pair(field_name, new_inst)); // 对ListUnit执行特殊初始化步骤 if (typeid(*new_inst.get()) == typeid(BytesAsList)) { auto conv = std::dynamic_pointer_cast(new_inst); if (!conv->elementRule()) { conv->appendElementRule(this->_view.base->defaultExtractUnit()); } if (!conv->sizeProvider()) { conv->setSizeProvider(this->_view.base->defaultSizeProvider()); } } targetRuleRefresh(idx); } void RuleSetCustom::showEvent(QShowEvent* e) { QTableView::showEvent(e); membersPresent(this->_view._ruleset, this->_view._seqs_model); } #include RuleSetCustom::RuleSetCustom(std::shared_ptr base, std::shared_ptr rule_set, QWidget* p /*= nullptr*/) :QTableView(p) { _view._ruleset = rule_set; _view._seqs_model = new QStandardItemModel(); _view.base = std::make_shared(); this->setModel(_view._seqs_model); _view._seqs_model->setHorizontalHeaderLabels(QStringList() << tr(u8"Field Name") << tr(u8"Bytes Offset") << tr(u8"Translate Rule") << tr(u8"Bytes Count") << tr(u8"Arguments")); auto int_delegate = new IntDelegate(0, INT_MAX); this->setItemDelegateForColumn(1, int_delegate); auto rule_delegate = new RuleSelectDelegate(_view.base); this->setItemDelegateForColumn(2, rule_delegate); this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &QTableView::customContextMenuRequested, this, &RuleSetCustom::customTranslateRuleEdit); connect(rule_delegate, &RuleSelectDelegate::dataChanged, this, &RuleSetCustom::peersRuleChanged); connect(int_delegate, &IntDelegate::valueChanged, this, &RuleSetCustom::targetRuleRefresh); connect(this, &QTableView::clicked, [=](const QModelIndex& curr) { if (!curr.isValid()) return; emit this->currentRuleChanged(_view._ruleset->_bind[curr.row()].second, curr); }); } #include void RuleSetCustom::customTranslateRuleEdit(const QPoint& pos) { QMenu immediate; immediate.addAction(u8"Add Unit", this, &RuleSetCustom::addTranslateUnit); immediate.addAction(u8"Remove Unit", this, &RuleSetCustom::removeTranslateUnit); immediate.exec(this->mapToGlobal(pos)); } void RuleSetCustom::addTranslateUnit() { auto curr_rule = _view.base->defaultExtractUnit()->newDefault(); this->_view._ruleset->_bind.append( QString(u8"rule_%1").arg(_view._ruleset->_bind.sub_units.size()), std::static_pointer_cast(curr_rule)); auto hex_rule = std::static_pointer_cast(curr_rule); hex_rule->setCountWithin(1); membersPresent(this->_view._ruleset, this->_view._seqs_model); } void RuleSetCustom::removeTranslateUnit() { auto idx_curr = this->currentIndex(); if (!idx_curr.isValid()) return; _view._ruleset->_bind.removeAt(idx_curr.row()); _view._seqs_model->removeRow(idx_curr.row()); } void RuleSetCustom::membersPresent(std::shared_ptr ruleset, QStandardItemModel* model) { model->removeRows(0, model->rowCount()); auto units = ruleset->_bind.sub_units; for (auto uidx = 0; uidx < units.size(); ++uidx) { auto u_pair = units.at(uidx); QList new_row; new_row << new QStandardItem(u_pair.first); new_row << new QStandardItem(QString("%1").arg(u_pair.second->offsetSpan())); new_row << new QStandardItem(_view.base->defaultExtractUnit()->name()); new_row << new QStandardItem(QString("%1").arg(u_pair.second->countWithin())); new_row.last()->setEditable(false); QJsonObject obj; u_pair.second->saveTo(obj); auto bytes = QJsonDocument(obj).toJson(QJsonDocument::Compact); auto json_doc = QString::fromUtf8(bytes); new_row << new QStandardItem(json_doc); new_row.last()->setEditable(false); this->_view._seqs_model->appendRow(new_row); } this->resizeColumnsToContents(); } RuleSelectDelegate::RuleSelectDelegate(std::shared_ptr ins) :_kernel(ins) { } #include QWidget* RuleSelectDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { return new QComboBox(parent); } void RuleSelectDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { auto rule_names = this->_kernel->extractUnitList().keys(); std::sort(rule_names.begin(), rule_names.end()); auto combo = dynamic_cast(editor); combo->addItems(rule_names); combo->setCurrentText(index.data(Qt::DisplayRole).toString()); } void RuleSelectDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { auto rule_name = dynamic_cast(editor)->currentText(); model->setData(index, rule_name, Qt::EditRole); emit this->dataChanged(index); } void RuleSelectDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { editor->setGeometry(option.rect); }