QBinaryTranslate/TranslateUI/SequenceView.cpp

198 lines
6.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "SequenceView.h"
#include <QSpinBox>
#include <QJsonDocument>
#include <QJsonObject>
#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<QSpinBox*>(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<QSpinBox*>(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 SequenceRulesView::currentRuleRefresh(const QModelIndex& idx)
{
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.second->setOffsetSpan(offset_number);
auto count_index = idx.sibling(idx.row(), 3);
_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.second->saveTo(obj);
auto bytes = QJsonDocument(obj).toJson(QJsonDocument::Compact);
_view._sequence_model->setData(param_index, QString::fromUtf8(bytes));
this->resizeColumnsToContents();
}
void SequenceRulesView::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<ExtractUnit>(rule_nm->newDefault());
_view._ruleset->_rules.replace(idx.row(), std::make_pair(field_name, new_inst));
// <20><>ListUnitִ<74><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (typeid(*new_inst.get()) == typeid(BytesAsList)) {
auto conv = std::dynamic_pointer_cast<BytesAsList>(new_inst);
if (!conv->elementRule()) {
conv->appendElementRule(this->_view.base->defaultExtractUnit());
}
if (!conv->sizeProvider()) {
conv->setSizeProvider(this->_view.base->defaultSizeProvider());
}
}
currentRuleRefresh(idx);
}
#include <QItemSelectionModel>
SequenceRulesView::SequenceRulesView(std::shared_ptr<extract::BytesAsRuleSet> rule_set, QWidget* p /*= nullptr*/)
:QTableView(p)
{
_view._ruleset = rule_set;
_view._sequence_model = new QStandardItemModel();
_view.base = std::make_shared<TranslateBasic>();
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(_view.base);
this->setItemDelegateForColumn(2, rule_delegate);
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &QTableView::customContextMenuRequested, this, &SequenceRulesView::customTranslateRuleEdit);
connect(rule_delegate, &RuleSelectDelegate::dataChanged, this, &SequenceRulesView::peersRuleChanged);
connect(int_delegate, &IntDelegate::valueChanged, this, &SequenceRulesView::currentRuleRefresh);
connect(this, &QTableView::clicked, [=](const QModelIndex& curr) {
if (!curr.isValid())
return;
emit this->currentRuleChanged(_view._ruleset->_rules[curr.row()].second, curr);
});
}
#include <QMenu>
void SequenceRulesView::customTranslateRuleEdit(const QPoint& pos)
{
QMenu immediate;
immediate.addAction(u8"Add Unit", this, &SequenceRulesView::addTranslateUnit);
immediate.addAction(u8"Remove Unit", this, &SequenceRulesView::removeTranslateUnit);
immediate.exec(this->mapToGlobal(pos));
}
void SequenceRulesView::addTranslateUnit()
{
auto row_cnt = this->_view._sequence_model->rowCount();
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(_view.base->defaultExtractUnit()->name());
new_row << new QStandardItem(u8"1");
new_row.last()->setEditable(false);
auto curr_rule = _view.base->defaultExtractUnit()->newDefault();
this->_view._ruleset->_rules.append(
new_row.first()->text(), std::static_pointer_cast<ExtractUnit>(curr_rule));
auto hex_rule = std::static_pointer_cast<BytesAsHex>(curr_rule);
hex_rule->setCountWithin(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);
new_row.last()->setEditable(false);
this->_view._sequence_model->appendRow(new_row);
this->resizeColumnsToContents();
}
void SequenceRulesView::removeTranslateUnit()
{
auto idx_curr = this->currentIndex();
if (!idx_curr.isValid())
return;
_view._ruleset->_rules.removeAt(idx_curr.row());
_view._sequence_model->removeRow(idx_curr.row());
}
RuleSelectDelegate::RuleSelectDelegate(std::shared_ptr<TranslateBasic> ins)
:_kernel(ins) {
}
#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
{
auto rule_names = this->_kernel->extractUnitList().keys();
std::sort(rule_names.begin(), rule_names.end());
auto combo = dynamic_cast<QComboBox*>(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<QComboBox*>(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);
}