2025-07-17 16:17:39 +00:00
|
|
|
|
#include "SequenceView.h"
|
|
|
|
|
#include <QSpinBox>
|
2025-07-18 14:41:36 +00:00
|
|
|
|
#include <QJsonDocument>
|
|
|
|
|
#include <QJsonObject>
|
2025-07-18 16:38:08 +00:00
|
|
|
|
#include "TranslateBasic.h"
|
|
|
|
|
|
|
|
|
|
using namespace extract;
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
|
|
|
|
IntDelegate::IntDelegate(int min, int max)
|
2025-07-18 14:41:36 +00:00
|
|
|
|
: _min_value(min), _max_value(max) {
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
{
|
2025-07-18 14:41:36 +00:00
|
|
|
|
auto spin = dynamic_cast<QSpinBox*>(editor);
|
|
|
|
|
spin->setRange(_min_value, _max_value);
|
|
|
|
|
spin->setValue(index.data(Qt::DisplayRole).toInt());
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IntDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
|
|
|
|
|
{
|
|
|
|
|
auto value = dynamic_cast<QSpinBox*>(editor);
|
2025-07-18 14:41:36 +00:00
|
|
|
|
model->setData(index, value->value(), Qt::EditRole);
|
|
|
|
|
|
|
|
|
|
emit this->valueChanged(index);
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IntDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
|
|
|
|
{
|
|
|
|
|
editor->setGeometry(option.rect);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 15:39:28 +00:00
|
|
|
|
void SequenceRulesView::currentRuleRefresh(const QModelIndex& idx)
|
2025-07-18 14:41:36 +00:00
|
|
|
|
{
|
2025-08-04 01:27:04 +00:00
|
|
|
|
auto rule_insv = _view._ruleset->_rules[idx.row()];
|
2025-07-18 14:41:36 +00:00
|
|
|
|
|
|
|
|
|
auto offset_index = idx.sibling(idx.row(), 1);
|
2025-08-01 23:06:42 +00:00
|
|
|
|
auto offset_number = offset_index.data(Qt::DisplayRole).toInt();
|
2025-08-04 01:27:04 +00:00
|
|
|
|
rule_insv.second->setOffsetSpan(offset_number);
|
2025-07-18 14:41:36 +00:00
|
|
|
|
|
2025-08-01 07:03:35 +00:00
|
|
|
|
auto count_index = idx.sibling(idx.row(), 3);
|
2025-08-04 01:27:04 +00:00
|
|
|
|
_view._sequence_model->setData(offset_index, rule_insv.second->offsetSpan(), Qt::EditRole);
|
|
|
|
|
_view._sequence_model->setData(count_index, rule_insv.second->countWithin(), Qt::EditRole);
|
2025-07-18 14:41:36 +00:00
|
|
|
|
|
|
|
|
|
auto param_index = idx.sibling(idx.row(), 4);
|
|
|
|
|
QJsonObject obj;
|
2025-08-04 01:27:04 +00:00
|
|
|
|
rule_insv.second->saveTo(obj);
|
2025-07-18 14:41:36 +00:00
|
|
|
|
auto bytes = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
2025-08-04 01:27:04 +00:00
|
|
|
|
_view._sequence_model->setData(param_index, QString::fromUtf8(bytes));
|
2025-07-18 14:58:49 +00:00
|
|
|
|
|
|
|
|
|
this->resizeColumnsToContents();
|
2025-07-18 14:41:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 15:39:28 +00:00
|
|
|
|
void SequenceRulesView::peersRuleChanged(const QModelIndex& idx)
|
2025-07-18 15:33:21 +00:00
|
|
|
|
{
|
2025-08-04 01:27:04 +00:00
|
|
|
|
auto field_idx = idx.sibling(idx.row(), 0);
|
|
|
|
|
auto field_name = field_idx.data(Qt::DisplayRole).toString();
|
|
|
|
|
|
2025-08-01 07:03:35 +00:00
|
|
|
|
auto rule_idx = idx.sibling(idx.row(), 2);
|
2025-08-04 01:27:04 +00:00
|
|
|
|
auto rule_name = rule_idx.data(Qt::DisplayRole).toString();
|
|
|
|
|
|
|
|
|
|
auto rule_nm = _view.base->extractUnitList()[rule_name];
|
2025-07-18 15:33:21 +00:00
|
|
|
|
auto new_inst = std::dynamic_pointer_cast<ExtractUnit>(rule_nm->newDefault());
|
2025-08-04 01:27:04 +00:00
|
|
|
|
_view._ruleset->_rules.replace(idx.row(), std::make_pair(field_name, new_inst));
|
2025-07-18 15:33:21 +00:00
|
|
|
|
|
2025-08-04 01:27:04 +00:00
|
|
|
|
// <20><>ListUnitִ<74><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2025-08-01 23:06:42 +00:00
|
|
|
|
if (typeid(*new_inst.get()) == typeid(BytesAsList)) {
|
|
|
|
|
auto conv = std::dynamic_pointer_cast<BytesAsList>(new_inst);
|
|
|
|
|
if (!conv->elementRule()) {
|
2025-08-04 01:27:04 +00:00
|
|
|
|
conv->appendElementRule(this->_view.base->defaultExtractUnit());
|
2025-08-01 23:06:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!conv->sizeProvider()) {
|
2025-08-04 01:27:04 +00:00
|
|
|
|
conv->setSizeProvider(this->_view.base->defaultSizeProvider());
|
2025-08-01 23:06:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 15:33:21 +00:00
|
|
|
|
currentRuleRefresh(idx);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 14:58:49 +00:00
|
|
|
|
#include <QItemSelectionModel>
|
2025-08-04 01:27:04 +00:00
|
|
|
|
SequenceRulesView::SequenceRulesView(std::shared_ptr<extract::BytesAsRuleSet> rule_set, QWidget* p /*= nullptr*/)
|
2025-08-03 09:26:53 +00:00
|
|
|
|
:QTableView(p)
|
2025-07-17 16:17:39 +00:00
|
|
|
|
{
|
2025-08-04 01:27:04 +00:00
|
|
|
|
_view._ruleset = rule_set;
|
|
|
|
|
_view._sequence_model = new QStandardItemModel();
|
|
|
|
|
_view.base = std::make_shared<TranslateBasic>();
|
2025-08-03 09:26:53 +00:00
|
|
|
|
|
2025-08-04 01:27:04 +00:00
|
|
|
|
this->setModel(_view._sequence_model);
|
|
|
|
|
_view._sequence_model->setHorizontalHeaderLabels(QStringList()
|
2025-08-01 23:06:42 +00:00
|
|
|
|
<< tr(u8"Field Name") << tr(u8"Bytes Offset") << tr(u8"Translate Rule")
|
2025-08-01 07:03:35 +00:00
|
|
|
|
<< tr(u8"Bytes Count") << tr(u8"Arguments"));
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
2025-07-18 14:41:36 +00:00
|
|
|
|
auto int_delegate = new IntDelegate(0, INT_MAX);
|
|
|
|
|
this->setItemDelegateForColumn(1, int_delegate);
|
2025-08-04 01:27:04 +00:00
|
|
|
|
auto rule_delegate = new RuleSelectDelegate(_view.base);
|
2025-08-01 07:03:35 +00:00
|
|
|
|
this->setItemDelegateForColumn(2, rule_delegate);
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
|
|
|
|
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
2025-07-18 15:39:28 +00:00
|
|
|
|
connect(this, &QTableView::customContextMenuRequested, this, &SequenceRulesView::customTranslateRuleEdit);
|
|
|
|
|
connect(rule_delegate, &RuleSelectDelegate::dataChanged, this, &SequenceRulesView::peersRuleChanged);
|
|
|
|
|
connect(int_delegate, &IntDelegate::valueChanged, this, &SequenceRulesView::currentRuleRefresh);
|
2025-07-18 14:58:49 +00:00
|
|
|
|
|
2025-07-19 02:58:46 +00:00
|
|
|
|
connect(this, &QTableView::clicked, [=](const QModelIndex& curr) {
|
2025-07-18 15:12:48 +00:00
|
|
|
|
if (!curr.isValid())
|
|
|
|
|
return;
|
|
|
|
|
|
2025-08-04 01:27:04 +00:00
|
|
|
|
emit this->currentRuleChanged(_view._ruleset->_rules[curr.row()].second, curr);
|
2025-08-01 23:06:42 +00:00
|
|
|
|
});
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include <QMenu>
|
2025-07-18 15:39:28 +00:00
|
|
|
|
void SequenceRulesView::customTranslateRuleEdit(const QPoint& pos)
|
2025-07-17 16:17:39 +00:00
|
|
|
|
{
|
|
|
|
|
QMenu immediate;
|
2025-07-18 15:39:28 +00:00
|
|
|
|
immediate.addAction(u8"Add Unit", this, &SequenceRulesView::addTranslateUnit);
|
|
|
|
|
immediate.addAction(u8"Remove Unit", this, &SequenceRulesView::removeTranslateUnit);
|
2025-07-17 16:17:39 +00:00
|
|
|
|
immediate.exec(this->mapToGlobal(pos));
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 15:39:28 +00:00
|
|
|
|
void SequenceRulesView::addTranslateUnit()
|
2025-07-17 16:17:39 +00:00
|
|
|
|
{
|
2025-08-04 01:27:04 +00:00
|
|
|
|
auto row_cnt = this->_view._sequence_model->rowCount();
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
|
|
|
|
QList<QStandardItem*> new_row;
|
|
|
|
|
new_row << new QStandardItem(QString(u8"rule_%1").arg(row_cnt));
|
|
|
|
|
new_row << new QStandardItem(u8"0");
|
2025-08-04 01:27:04 +00:00
|
|
|
|
new_row << new QStandardItem(_view.base->defaultExtractUnit()->name());
|
2025-08-01 07:03:35 +00:00
|
|
|
|
new_row << new QStandardItem(u8"1");
|
|
|
|
|
new_row.last()->setEditable(false);
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
2025-08-04 01:27:04 +00:00
|
|
|
|
auto curr_rule = _view.base->defaultExtractUnit()->newDefault();
|
|
|
|
|
this->_view._ruleset->_rules.append(
|
|
|
|
|
new_row.first()->text(), std::static_pointer_cast<ExtractUnit>(curr_rule));
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
|
|
|
|
auto hex_rule = std::static_pointer_cast<BytesAsHex>(curr_rule);
|
2025-07-30 16:39:26 +00:00
|
|
|
|
hex_rule->setCountWithin(1);
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
|
|
|
|
QJsonObject obj;
|
|
|
|
|
curr_rule->saveTo(obj);
|
|
|
|
|
auto bytes = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
|
|
|
|
auto json_doc = QString::fromUtf8(bytes);
|
|
|
|
|
new_row << new QStandardItem(json_doc);
|
2025-07-19 02:58:46 +00:00
|
|
|
|
new_row.last()->setEditable(false);
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
2025-08-04 01:27:04 +00:00
|
|
|
|
this->_view._sequence_model->appendRow(new_row);
|
2025-07-18 15:12:48 +00:00
|
|
|
|
this->resizeColumnsToContents();
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 15:39:28 +00:00
|
|
|
|
void SequenceRulesView::removeTranslateUnit()
|
2025-07-17 16:17:39 +00:00
|
|
|
|
{
|
2025-07-18 15:12:48 +00:00
|
|
|
|
auto idx_curr = this->currentIndex();
|
|
|
|
|
if (!idx_curr.isValid())
|
|
|
|
|
return;
|
2025-07-17 16:17:39 +00:00
|
|
|
|
|
2025-08-04 01:27:04 +00:00
|
|
|
|
_view._ruleset->_rules.removeAt(idx_curr.row());
|
|
|
|
|
_view._sequence_model->removeRow(idx_curr.row());
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-08-01 23:06:42 +00:00
|
|
|
|
|
2025-07-18 14:41:36 +00:00
|
|
|
|
RuleSelectDelegate::RuleSelectDelegate(std::shared_ptr<TranslateBasic> ins)
|
|
|
|
|
:_kernel(ins) {
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include <QComboBox>
|
|
|
|
|
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
|
|
|
|
|
{
|
2025-08-02 07:02:35 +00:00
|
|
|
|
auto rule_names = this->_kernel->extractUnitList().keys();
|
2025-07-17 16:17:39 +00:00
|
|
|
|
std::sort(rule_names.begin(), rule_names.end());
|
|
|
|
|
|
2025-07-18 14:41:36 +00:00
|
|
|
|
auto combo = dynamic_cast<QComboBox*>(editor);
|
|
|
|
|
combo->addItems(rule_names);
|
|
|
|
|
combo->setCurrentText(index.data(Qt::DisplayRole).toString());
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RuleSelectDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
|
|
|
|
|
{
|
|
|
|
|
auto rule_name = dynamic_cast<QComboBox*>(editor)->currentText();
|
|
|
|
|
model->setData(index, rule_name, Qt::EditRole);
|
|
|
|
|
|
2025-07-18 14:41:36 +00:00
|
|
|
|
emit this->dataChanged(index);
|
2025-07-17 16:17:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RuleSelectDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
|
|
|
|
{
|
|
|
|
|
editor->setGeometry(option.rect);
|
|
|
|
|
}
|