QBinaryTranslate/TranslateUI/SequenceView.cpp

214 lines
6.7 KiB
C++
Raw Permalink Normal View History

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>
#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-07-18 15:33:21 +00:00
auto new_inst = _rule_sequence.at(idx.row());
auto rule_insv = std::dynamic_pointer_cast<AbstractExtractor>(new_inst);
2025-07-18 14:41:36 +00:00
auto offset_index = idx.sibling(idx.row(), 1);
auto count_index = idx.sibling(idx.row(), 2);
if (rule_insv) {
2025-07-18 15:33:21 +00:00
auto offset_number = offset_index.data(Qt::DisplayRole).toInt();
auto count_number = count_index.data(Qt::DisplayRole).toInt();
2025-07-18 14:41:36 +00:00
rule_insv->setOffsetFromPrevious(offset_number);
rule_insv->setCountWithinParse(count_number);
}
2025-07-18 15:12:48 +00:00
_sequence_model->setData(offset_index, new_inst->offsetFromPrevious(), Qt::EditRole);
_sequence_model->setData(count_index, new_inst->countWithinParse(), Qt::EditRole);
2025-07-18 14:41:36 +00:00
auto param_index = idx.sibling(idx.row(), 4);
QJsonObject obj;
rule_insv->saveTo(obj);
auto bytes = QJsonDocument(obj).toJson(QJsonDocument::Compact);
2025-07-18 15:12:48 +00:00
_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
{
auto rule_idx = idx.sibling(idx.row(), 3);
auto rule_nm = base->extactors()[rule_idx.data(Qt::DisplayRole).toString()];
auto new_inst = std::dynamic_pointer_cast<ExtractUnit>(rule_nm->newDefault());
_rule_sequence.replace(idx.row(), new_inst);
currentRuleRefresh(idx);
}
2025-07-18 14:58:49 +00:00
#include <QItemSelectionModel>
2025-07-18 15:39:28 +00:00
SequenceRulesView::SequenceRulesView(QWidget* p /*= nullptr*/)
2025-07-17 16:17:39 +00:00
:QTableView(p),
2025-07-18 15:12:48 +00:00
_sequence_model(new QStandardItemModel),
2025-07-17 16:17:39 +00:00
base(std::make_shared<TranslateBasic>())
{
2025-07-18 15:12:48 +00:00
this->setModel(_sequence_model);
_sequence_model->setHorizontalHeaderLabels(QStringList()
2025-07-17 16:17:39 +00:00
<< tr(u8"Field Name") << tr(u8"Bytes Offset") << tr(u8"Bytes Count")
<< tr(u8"Translate Rule") << tr(u8"Arguments"));
2025-07-18 14:41:36 +00:00
auto int_delegate = new IntDelegate(0, INT_MAX);
this->setItemDelegateForColumn(1, int_delegate);
this->setItemDelegateForColumn(2, int_delegate);
auto rule_delegate = new RuleSelectDelegate(base);
this->setItemDelegateForColumn(3, 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-07-19 02:58:46 +00:00
emit this->currentRuleChanged(_rule_sequence[curr.row()], curr);
2025-07-18 15:39:28 +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-07-18 15:12:48 +00:00
auto row_cnt = this->_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");
new_row << new QStandardItem(u8"1");
new_row << new QStandardItem(base->defaultRule()->name());
auto curr_rule = base->defaultRule()->newDefault();
2025-07-18 15:12:48 +00:00
this->_rule_sequence << std::static_pointer_cast<AbstractExtractor>(curr_rule);
2025-07-17 16:17:39 +00:00
auto hex_rule = std::static_pointer_cast<BytesAsHex>(curr_rule);
hex_rule->setCountWithinParse(1);
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-07-18 15:12:48 +00:00
this->_sequence_model->appendRow(new_row);
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-07-18 15:12:48 +00:00
_rule_sequence.removeAt(idx_curr.row());
_sequence_model->removeRow(idx_curr.row());
2025-07-17 16:17:39 +00:00
}
TranslateBasic::TranslateBasic()
{
std::shared_ptr<ExtractUnit> u_ptr = std::make_shared<BytesAsBitCombine>();
_extractor_types[u_ptr->name()] = u_ptr;
u_ptr = std::make_shared<BytesAsInteger>();
_extractor_types[u_ptr->name()] = u_ptr;
u_ptr = std::make_shared<BytesAsString>();
_extractor_types[u_ptr->name()] = u_ptr;
u_ptr = std::make_shared<BytesAsHex>();
_extractor_types[u_ptr->name()] = u_ptr;
this->_default_translate_rule = u_ptr;
u_ptr = std::make_shared<BytesAsFloat>();
_extractor_types[u_ptr->name()] = u_ptr;
u_ptr = std::make_shared<BytesAsDouble>();
_extractor_types[u_ptr->name()] = u_ptr;
2025-07-17 16:17:39 +00:00
}
std::shared_ptr<ExtractUnit> TranslateBasic::defaultRule() const
{
return _default_translate_rule;
}
2025-07-18 14:41:36 +00:00
QHash<QString, std::shared_ptr<ExtractUnit>> TranslateBasic::extactors() const
2025-07-17 16:17:39 +00:00
{
return _extractor_types;
}
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-07-18 14:41:36 +00:00
auto rule_names = this->_kernel->extactors().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);
}