QBinaryTranslate/TranslateUI/SequenceView.cpp

215 lines
6.9 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 "TranslateBasic.h"
#include <QSpinBox>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMenu>
#include <QComboBox>
#include <QItemSelectionModel>
using namespace extract;
using namespace unit_func;
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);
}
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)[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<ExtractUnit>(rule_nm->newDefault());
_view._ruleset->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());
}
}
targetRuleRefresh(idx);
}
void RuleSetCustom::showEvent(QShowEvent* e)
{
QTableView::showEvent(e);
membersPresent(this->_view._ruleset, this->_view._seqs_model);
}
RuleSetCustom::RuleSetCustom(std::shared_ptr<TranslateBasic> base,
std::shared_ptr<extract::BytesAsRuleSet> rule_set, QWidget* p /*= nullptr*/)
:QTableView(p)
{
_view._ruleset = rule_set;
_view._seqs_model = new QStandardItemModel();
_view.base = std::make_shared<TranslateBasic>();
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(_view._seqs_model, &QAbstractItemModel::dataChanged, this, &RuleSetCustom::targetRuleRefresh);
connect(this, &QTableView::clicked, [=](const QModelIndex& curr) {
if (!curr.isValid())
return;
emit this->currentRuleChanged(_view._ruleset->operator[](curr.row()).second, curr);
});
}
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->append(
QString(u8"rule_%1").arg(_view._ruleset->memberCount()),
std::static_pointer_cast<ExtractUnit>(curr_rule));
auto hex_rule = std::static_pointer_cast<BytesAsHex>(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->removeAt(idx_curr.row());
_view._seqs_model->removeRow(idx_curr.row());
}
void RuleSetCustom::membersPresent(std::shared_ptr<extract::BytesAsRuleSet> ruleset, QStandardItemModel* model)
{
model->removeRows(0, model->rowCount());
for (auto uidx = 0; uidx < ruleset->memberCount(); ++uidx) {
auto u_pair = ruleset->operator[](uidx);
QList<QStandardItem*> 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<TranslateBasic> ins)
:_kernel(ins) {
}
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);
}