diff --git a/TranslateUI/SequenceView.cpp b/TranslateUI/SequenceView.cpp index 6a66502..2d002d3 100644 --- a/TranslateUI/SequenceView.cpp +++ b/TranslateUI/SequenceView.cpp @@ -37,40 +37,46 @@ void IntDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewIt void SequenceRulesView::currentRuleRefresh(const QModelIndex& idx) { - auto rule_insv = _rule_v._rule_sequence.at(idx.row()); + auto rule_insv = _view._ruleset->_rules[idx.row()]; auto offset_index = idx.sibling(idx.row(), 1); auto offset_number = offset_index.data(Qt::DisplayRole).toInt(); - rule_insv->setOffsetSpan(offset_number); + rule_insv.second->setOffsetSpan(offset_number); auto count_index = idx.sibling(idx.row(), 3); - _rule_v._sequence_model->setData(offset_index, rule_insv->offsetSpan(), Qt::EditRole); - _rule_v._sequence_model->setData(count_index, rule_insv->countWithin(), Qt::EditRole); + _view._sequence_model->setData(offset_index, rule_insv.second->offsetSpan(), Qt::EditRole); + _view._sequence_model->setData(count_index, rule_insv.second->countWithin(), Qt::EditRole); auto param_index = idx.sibling(idx.row(), 4); QJsonObject obj; - rule_insv->saveTo(obj); + rule_insv.second->saveTo(obj); auto bytes = QJsonDocument(obj).toJson(QJsonDocument::Compact); - _rule_v._sequence_model->setData(param_index, QString::fromUtf8(bytes)); + _view._sequence_model->setData(param_index, QString::fromUtf8(bytes)); this->resizeColumnsToContents(); } void SequenceRulesView::peersRuleChanged(const QModelIndex& idx) { - auto rule_idx = idx.sibling(idx.row(), 2); - auto rule_nm = _rule_v.base->extractUnitList()[rule_idx.data(Qt::DisplayRole).toString()]; - auto new_inst = std::dynamic_pointer_cast(rule_nm->newDefault()); - _rule_v._rule_sequence.replace(idx.row(), new_inst); + 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->_rules.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->_rule_v.base->defaultExtractUnit()); + conv->appendElementRule(this->_view.base->defaultExtractUnit()); } if (!conv->sizeProvider()) { - conv->setSizeProvider(this->_rule_v.base->defaultSizeProvider()); + conv->setSizeProvider(this->_view.base->defaultSizeProvider()); } } @@ -78,20 +84,21 @@ void SequenceRulesView::peersRuleChanged(const QModelIndex& idx) } #include -SequenceRulesView::SequenceRulesView(QWidget* p /*= nullptr*/) +SequenceRulesView::SequenceRulesView(std::shared_ptr rule_set, QWidget* p /*= nullptr*/) :QTableView(p) { - _rule_v._sequence_model = new QStandardItemModel(); - _rule_v.base = std::make_shared(); + _view._ruleset = rule_set; + _view._sequence_model = new QStandardItemModel(); + _view.base = std::make_shared(); - this->setModel(_rule_v._sequence_model); - _rule_v._sequence_model->setHorizontalHeaderLabels(QStringList() + this->setModel(_view._sequence_model); + _view._sequence_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(_rule_v.base); + auto rule_delegate = new RuleSelectDelegate(_view.base); this->setItemDelegateForColumn(2, rule_delegate); this->setContextMenuPolicy(Qt::CustomContextMenu); @@ -103,7 +110,7 @@ SequenceRulesView::SequenceRulesView(QWidget* p /*= nullptr*/) if (!curr.isValid()) return; - emit this->currentRuleChanged(_rule_v._rule_sequence[curr.row()], curr); + emit this->currentRuleChanged(_view._ruleset->_rules[curr.row()].second, curr); }); } @@ -118,17 +125,18 @@ void SequenceRulesView::customTranslateRuleEdit(const QPoint& pos) void SequenceRulesView::addTranslateUnit() { - auto row_cnt = this->_rule_v._sequence_model->rowCount(); + auto row_cnt = this->_view._sequence_model->rowCount(); QList new_row; new_row << new QStandardItem(QString(u8"rule_%1").arg(row_cnt)); new_row << new QStandardItem(u8"0"); - new_row << new QStandardItem(_rule_v.base->defaultExtractUnit()->name()); + new_row << new QStandardItem(_view.base->defaultExtractUnit()->name()); new_row << new QStandardItem(u8"1"); new_row.last()->setEditable(false); - auto curr_rule = _rule_v.base->defaultExtractUnit()->newDefault(); - this->_rule_v._rule_sequence << std::static_pointer_cast(curr_rule); + auto curr_rule = _view.base->defaultExtractUnit()->newDefault(); + this->_view._ruleset->_rules.append( + new_row.first()->text(), std::static_pointer_cast(curr_rule)); auto hex_rule = std::static_pointer_cast(curr_rule); hex_rule->setCountWithin(1); @@ -140,7 +148,7 @@ void SequenceRulesView::addTranslateUnit() new_row << new QStandardItem(json_doc); new_row.last()->setEditable(false); - this->_rule_v._sequence_model->appendRow(new_row); + this->_view._sequence_model->appendRow(new_row); this->resizeColumnsToContents(); } @@ -150,8 +158,8 @@ void SequenceRulesView::removeTranslateUnit() if (!idx_curr.isValid()) return; - _rule_v._rule_sequence.removeAt(idx_curr.row()); - _rule_v._sequence_model->removeRow(idx_curr.row()); + _view._ruleset->_rules.removeAt(idx_curr.row()); + _view._sequence_model->removeRow(idx_curr.row()); } diff --git a/TranslateUI/SequenceView.h b/TranslateUI/SequenceView.h index e1740a3..58f78c6 100644 --- a/TranslateUI/SequenceView.h +++ b/TranslateUI/SequenceView.h @@ -61,8 +61,8 @@ public: struct __Private { QStandardItemModel* _sequence_model; std::shared_ptr base = nullptr; - QList> _rule_sequence; - } _rule_v; + std::shared_ptr _ruleset = nullptr; + } _view; signals: void currentRuleChanged(std::shared_ptr u, const QModelIndex& i) const; @@ -72,7 +72,7 @@ public: void peersRuleChanged(const QModelIndex& idx_rule); public: - SequenceRulesView(QWidget* p = nullptr); + SequenceRulesView(std::shared_ptr rule_set, QWidget* p = nullptr); void customTranslateRuleEdit(const QPoint& pos); void addTranslateUnit(); diff --git a/TranslateUI/StructuralRuleView.cpp b/TranslateUI/StructuralRuleView.cpp index 5a49d61..e66026c 100644 --- a/TranslateUI/StructuralRuleView.cpp +++ b/TranslateUI/StructuralRuleView.cpp @@ -8,11 +8,14 @@ #include #include "TranslateBasic.h" -StructuralRuleView::StructuralRuleView(QWidget* p /*= nullptr*/) - :QWidget(p), - _sequence_view(new SequenceRulesView(this)), +StructuralRuleView::StructuralRuleView( + std::shared_ptr inst_r, QWidget* p /*= nullptr*/) + : QWidget(p), + _sequence_view(new SequenceRulesView(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); @@ -27,7 +30,7 @@ StructuralRuleView::StructuralRuleView(QWidget* p /*= nullptr*/) _configs_stack->addWidget(encode_config); auto combine_config = new BitCombineConfiguration(this); _configs_stack->addWidget(combine_config); - auto list_config = new ListUnitConfiguration(this->_sequence_view->_rule_v.base, this); + auto list_config = new ListUnitConfiguration(this->_sequence_view->_view.base, this); _configs_stack->addWidget(list_config); connect(count_span, &CountWithinConfiguration::currentRuleChanged, @@ -58,6 +61,7 @@ StructuralRuleView::StructuralRuleView(QWidget* p /*= nullptr*/) break; case DataType::LIST_COLLECTION: _configs_stack->setCurrentIndex(4); + cacheRefresh(i, list_config); break; default: _configs_stack->setCurrentIndex(0); @@ -66,6 +70,24 @@ StructuralRuleView::StructuralRuleView(QWidget* p /*= nullptr*/) }); } +void StructuralRuleView::cacheRefresh(const QModelIndex& curr, ListUnitConfiguration* t) +{ + if (!curr.isValid()) + return; + + this->_current_fields_cache->clear(); + this->_sequence_view->_view._ruleset->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->_sequence_view->_view._ruleset->_rules[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); @@ -311,6 +333,11 @@ void ListUnitConfiguration::reloadContent( 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()); + if (typeid(*u->sizeProvider().get()) == typeid(ConstNumberProvider)) { _configs_stack->setCurrentIndex(0); QSignalBlocker v(_const_number_input); @@ -320,10 +347,6 @@ void ListUnitConfiguration::reloadContent( else if (typeid(*u->sizeProvider().get()) == typeid(InterpretedNumberPrivider)) { _configs_stack->setCurrentIndex(1); auto conv = std::dynamic_pointer_cast(u->sizeProvider()); - QSignalBlocker v(_prev_field_refer); - auto item_list = getter->prevFields(); - this->_prev_field_refer->clear(); - this->_prev_field_refer->addItems(item_list.keys()); this->_prev_field_refer->setCurrentText(conv->name()); } } diff --git a/TranslateUI/StructuralRuleView.h b/TranslateUI/StructuralRuleView.h index a41b200..c1945c6 100644 --- a/TranslateUI/StructuralRuleView.h +++ b/TranslateUI/StructuralRuleView.h @@ -119,8 +119,11 @@ private: SequenceRulesView* const _sequence_view; QStackedWidget* const _configs_stack; -public: - StructuralRuleView(QWidget* p = nullptr); + std::shared_ptr _current_fields_cache = nullptr; +public: + StructuralRuleView(std::shared_ptr inst_r, QWidget* p = nullptr); + + void cacheRefresh(const QModelIndex &curr, ListUnitConfiguration* t); }; diff --git a/TranslateUI/TranslateBasic.cpp b/TranslateUI/TranslateBasic.cpp index 7d08965..4e80213 100644 --- a/TranslateUI/TranslateBasic.cpp +++ b/TranslateUI/TranslateBasic.cpp @@ -93,7 +93,7 @@ QHash> TranslateBasic::ruleMatchList() const void ConstNumberProvider::bindInput(std::shared_ptr inst) { - + } QString ConstNumberProvider::name() const @@ -208,13 +208,49 @@ QVariant ValueAccess::get(const QString& unique_key) const return QVariant(); } -FieldSetterLayer::FieldSetterLayer(const QString& self, std::shared_ptr instp) +bool FieldManagerLayer::bindCurrent(const QString& unique_key) +{ + for (auto index = 0; index < __Private::_fields_map.size(); ++index) { + auto pair = __Private::_fields_map[index]; + if (pair.first == unique_key) { + __Private::_fields_map = __Private::_fields_map.mid(0, index); + return true; + } + } + return false; +} + +QHash FieldManagerLayer::prevFields() const +{ + QHash fields; + for(auto pair : __Private::_fields_map) + fields[pair.first] = pair.second; + + return fields; +} + +void FieldManagerLayer::clear() +{ + __Private::_fields_map.clear(); +} + +FieldManagerLayer::FieldManagerLayer(const QString& self, std::shared_ptr instp) { _setter._rule_name = self; _setter._parent_setter = instp; } -void FieldSetterLayer::setField(const QString& name, DataType type) +#include +void FieldManagerLayer::setField(const QString& name, DataType type) { - _setter._parent_setter->setField(QString("%1.%2").arg(_setter._rule_name, name), type); + if (_setter._parent_setter) + _setter._parent_setter->setField(QString("%1.%2").arg(_setter._rule_name, name), type); + else { + for (auto pair : __Private::_fields_map) { + if (pair.first == name) + throw new std::invalid_argument("字段名称重复"); + } + __Private::_fields_map << std::make_pair(name, type); + } } +QList> FieldManagerLayer::__Private::_fields_map; \ No newline at end of file diff --git a/TranslateUI/TranslateBasic.h b/TranslateUI/TranslateBasic.h index 65c4ddd..e3fcc90 100644 --- a/TranslateUI/TranslateBasic.h +++ b/TranslateUI/TranslateBasic.h @@ -34,6 +34,8 @@ public: /// /// virtual void setField(const QString& name, DataType type) = 0; + + virtual void clear() = 0; }; // ================================================================ @@ -199,15 +201,21 @@ public: QVariant get(const QString& unique_key) const override; }; -class FieldSetterLayer : public ScopeFieldsSetter { +class FieldManagerLayer : public ScopeFieldsSetter, public ScopeFieldsGetter { public: struct __Private { QString _rule_name; - std::shared_ptr _parent_setter; + std::shared_ptr _parent_setter = nullptr; + static QList> _fields_map; }_setter; + + bool bindCurrent(const QString& unique_key) override; + QHash prevFields() const override; + void clear() override; + public: - FieldSetterLayer(const QString& self, std::shared_ptr instp); + FieldManagerLayer(const QString& self, std::shared_ptr instp); void setField(const QString& name, DataType type) override; -}; \ No newline at end of file +}; diff --git a/TranslateUI/extract_basic.cpp b/TranslateUI/extract_basic.cpp index 87bb117..fb5717e 100644 --- a/TranslateUI/extract_basic.cpp +++ b/TranslateUI/extract_basic.cpp @@ -435,7 +435,7 @@ std::shared_ptr BytesAsList::newDefault() const void BytesAsList::registSubField(std::shared_ptr inst) { inst->setField("ls", this->_list._bind_unit->outType()); - auto layer = std::make_shared("ls", inst); + auto layer = std::make_shared("ls", inst); this->_list._bind_unit->registSubField(layer); } @@ -552,17 +552,17 @@ void BytesAsUnion::registSubField(std::shared_ptr inst) { for (auto rl : this->_union._rule_list) { inst->setField(rl->name(), rl->bindRule()->outType()); - auto layer = std::make_shared(rl->name(), inst); + auto layer = std::make_shared(rl->name(), inst); rl->bindRule()->registSubField(layer); } } void BytesAsRuleSet::registSubField(std::shared_ptr inst) { - for (auto rl_key : this->_rules._sub_rules.keys()){ - auto rlinst = this->_rules._sub_rules[rl_key]; + for (auto rl_key : this->_rules.fieldNames()){ + auto rlinst = this->_rules[rl_key]; inst->setField(rl_key, rlinst->outType()); - auto layer = std::make_shared(rl_key, inst); + auto layer = std::make_shared(rl_key, inst); rlinst->registSubField(layer); } } @@ -570,11 +570,11 @@ void BytesAsRuleSet::registSubField(std::shared_ptr inst) void BytesAsRuleSet::parse(const QByteArray& bytes, std::shared_ptr out) const { auto bufx = bytes; - for (auto keym : this->_rules._sub_rules.keys()) { + for (auto keym : this->_rules.fieldNames()) { auto rule_context = std::make_shared(); rule_context->init(keym, out); - auto rule = this->_rules._sub_rules[keym]; + auto rule = this->_rules[keym]; bufx = bufx.mid(rule->offsetSpan()); auto count = rule->countWithin(); auto secx = bufx.mid(0, count); @@ -627,7 +627,7 @@ void BytesAsRuleSet::loadFrom(std::shared_ptr core, const QJsonO auto xdev = core->extractUnitList()[match_name]->newDefault(); xdev->loadFrom(core, match_obj); - _rules._sub_rules[key] = std::dynamic_pointer_cast(xdev); + _rules._sub_rules << std::make_pair(key, std::dynamic_pointer_cast(xdev)); } } @@ -637,10 +637,11 @@ void BytesAsRuleSet::saveTo(QJsonObject& obj) const INT32_SAVE(_rules._byte_offset, obj); QJsonArray array; - for (auto key : _rules._sub_rules.keys()) { + for (auto pairk : _rules._sub_rules) { QJsonObject rule_obj, match_obj; - auto info = _rules._sub_rules[key]; + auto key = pairk.first; + auto info = pairk.second; STRING_SAVE(key, rule_obj); QString match_name = info->name(); STRING_SAVE(match_name, rule_obj); @@ -656,3 +657,43 @@ std::shared_ptr BytesAsRuleSet::newDefault() const { return std::make_shared(); } + +std::pair> BytesAsRuleSet::__Private::operator[](int index) const +{ + return this->_sub_rules[index]; +} + +void BytesAsRuleSet::__Private::replace(int index, std::pair> inst) +{ + this->_sub_rules.replace(index, inst); +} + +extract::BytesAsRuleSet::__Private& BytesAsRuleSet::__Private::append(const QString& nm, std::shared_ptr u) +{ + this->_sub_rules.append(std::make_pair(nm, u)); + return *this; +} + +void BytesAsRuleSet::__Private::removeAt(int index) +{ + this->_sub_rules.removeAt(index); +} + +QList BytesAsRuleSet::__Private::fieldNames() const +{ + QList fields_store; + for (auto fpair : this->_sub_rules) { + fields_store << fpair.first; + } + return fields_store;; +} + +std::shared_ptr BytesAsRuleSet::__Private::operator[](const QString& field) const +{ + for (auto pair : this->_sub_rules) { + if(pair.first == field) + return pair.second; + } + + return std::shared_ptr(); +} diff --git a/TranslateUI/extract_basic.h b/TranslateUI/extract_basic.h index 26498b7..29a3403 100644 --- a/TranslateUI/extract_basic.h +++ b/TranslateUI/extract_basic.h @@ -255,7 +255,16 @@ namespace extract { public: struct __Private { int _byte_offset = 0, _byte_count = 1; - QHash> _sub_rules; + QList>> _sub_rules; + + QList fieldNames() const; + std::shared_ptr operator[](const QString &field) const; + + + std::pair> operator[](int index) const; + void replace(int index, std::pair> inst); + void removeAt(int index); + __Private& append(const QString& nm, std::shared_ptr u); }_rules; public: diff --git a/TranslateUI/main.cpp b/TranslateUI/main.cpp index 8ff7c80..26cf9fb 100644 --- a/TranslateUI/main.cpp +++ b/TranslateUI/main.cpp @@ -10,7 +10,8 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); - StructuralRuleView v; + auto vx = std::make_shared< extract::BytesAsRuleSet>(); + StructuralRuleView v(vx); v.show(); return app.exec();