From 8fd695d93937b06bacc0372423db382cc6b3b6ff Mon Sep 17 00:00:00 2001 From: Nicholas Johnson Date: Mon, 28 Oct 2024 19:15:40 -0400 Subject: [PATCH] Add rule functions and classes. --- rule.cpp | 202 +++++++++++++ rule.h | 134 +++++++++ ruledialog.cpp | 298 +++++++++++++++++++ ruledialog.h | 64 ++++ ruledialog.ui | 756 ++++++++++++++++++++++++++++++++++++++++++++++++ rulepreview.cpp | 140 +++++++++ rulepreview.h | 53 ++++ rulepreview.ui | 19 ++ 8 files changed, 1666 insertions(+) create mode 100644 rule.cpp create mode 100644 rule.h create mode 100644 ruledialog.cpp create mode 100644 ruledialog.h create mode 100644 ruledialog.ui create mode 100644 rulepreview.cpp create mode 100644 rulepreview.h create mode 100644 rulepreview.ui diff --git a/rule.cpp b/rule.cpp new file mode 100644 index 0000000..953d1ff --- /dev/null +++ b/rule.cpp @@ -0,0 +1,202 @@ +#include "rule.h" + +Rule::Rule() { + pName = ""; + pType = TYPE_NONE; + pProps = QVariantMap(); + pColor = pGenerateColor(); + pByteOrder = BYTE_ORDER_NONE; + pLength = -1; + pValue = ""; + pRepeatCount = 0; + pPreSkipCount = 0; + pPostSkipCount = 0; +} + +Rule::Rule(const Rule &rule) { + pName = rule.Name(); + pType = rule.Type(); + pProps = rule.Properties(); + pColor = rule.Color(); + pByteOrder = rule.ByteOrder(); + pLength = rule.Length(); + pValue = rule.Value(); + pRepeatCount = rule.RepeatCount(); + pPreSkipCount = rule.PreSkipCount(); + pPostSkipCount = rule.PostSkipCount(); +} + +Rule &Rule::operator=(const Rule &rule) { + if (this == &rule) { + return *this; + } + + pName = rule.Name(); + pType = rule.Type(); + pProps = rule.Properties(); + pColor = rule.Color(); + pByteOrder = rule.ByteOrder(); + pLength = rule.Length(); + pValue = rule.Value(); + pRepeatCount = rule.RepeatCount(); + pPreSkipCount = rule.PreSkipCount(); + pPostSkipCount = rule.PostSkipCount(); + + return *this; +} + +bool Rule::operator==(const Rule &rule) const { + bool nameMatch = pName == rule.Name(); + bool typeMatch = pType == rule.Type(); + bool propsMatch = pProps == rule.Properties(); + bool byteOrderMatch = pByteOrder == rule.ByteOrder(); + bool lengthMatch = pLength == rule.Length(); + bool valueMatch = pValue == rule.Value(); + bool repeatMatch = pRepeatCount == rule.RepeatCount(); + bool preSkipMatch = pPreSkipCount == rule.PreSkipCount(); + bool postSkipMatch = pPostSkipCount == rule.PostSkipCount(); + return nameMatch && typeMatch && propsMatch && + byteOrderMatch && lengthMatch && valueMatch && + repeatMatch && preSkipMatch && postSkipMatch; +} + +bool Rule::operator!=(const Rule &rule) const { + return !operator==(rule); +} + +void Rule::SetName(const QString name) { + pName = name; +} + +QString Rule::Name() const { + return pName; +} + +void Rule::SetType(RULE_TYPE type) { + pType = type; + + if (pLength == -1) { + pLength = pGetTypeLength(type); + } +} + +RULE_TYPE Rule::Type() const { + return pType; +} + +void Rule::SetColor(const QColor color) { + pColor = color; +} + +QColor Rule::Color() const { + return pColor; +} + +void Rule::SetByteOrder(BYTE_ORDER byteOrder) { + pByteOrder = byteOrder; +} + +BYTE_ORDER Rule::ByteOrder() const { + return pByteOrder; +} + +void Rule::SetLength(int length) { + pLength = length; +} + +int Rule::Length() const { + return pLength; +} + +void Rule::SetValue(QString value) { + pValue = value; +} + +QString Rule::Value() const { + return pValue; +} + +QVariant Rule::GetProperty(QString propName) const { + return pProps[propName]; +} + +void Rule::SetProperties(QVariantMap props) { + pProps = props; +} + +QVariantMap Rule::Properties() const { + return pProps; +} + +void Rule::SetRepeatCount(int repeatCount) { + pRepeatCount = repeatCount; +} + +int Rule::RepeatCount() const { + return pRepeatCount; +} + +void Rule::SetPreSkipCount(int preSkipCount) { + pPreSkipCount = preSkipCount; +} + +int Rule::PreSkipCount() const { + return pPreSkipCount; +} + +void Rule::SetPostSkipCount(int postSkipCount) { + pPostSkipCount = postSkipCount; +} + +int Rule::PostSkipCount() const { + return pPostSkipCount; +} + +QColor Rule::pGenerateColor() { + QRandomGenerator64 *globalRand = QRandomGenerator64::global(); + double rRand = globalRand->generateDouble(); + double gRand = globalRand->generateDouble(); + double bRand = globalRand->generateDouble(); + return QColor(rRand * 255, gRand * 255, bRand * 255); +} + +int Rule::pGetTypeLength(RULE_TYPE ruleType) { + int typeLength = 0; + switch ((int)ruleType) { + case 1: // TYPE_SKIP + typeLength = 0; + break; + case 2: // TYPE_INT_8 + typeLength = 1; + break; + case 3: // TYPE_UINT_8 + typeLength = 1; + break; + case 4: // TYPE_INT_16 + typeLength = 2; + break; + case 5: // TYPE_UINT_16 + typeLength = 2; + break; + case 6: // TYPE_INT_32 + typeLength = 4; + break; + case 7: // TYPE_UINT_32 + typeLength = 4; + break; + case 8: // TYPE_INT_64 + typeLength = 8; + break; + case 9: // TYPE_UINT_64 + typeLength = 8; + break; + default: // Unknown + typeLength = 0; + break; + } + return typeLength; +} + +void Rule::SetProperty(QString propName, QVariant propData) { + pProps[propName] = propData; +} diff --git a/rule.h b/rule.h new file mode 100644 index 0000000..fa7c257 --- /dev/null +++ b/rule.h @@ -0,0 +1,134 @@ +#ifndef RULE_H +#define RULE_H + +#include +#include +#include +#include +#include + +enum RULE_TYPE { + TYPE_NONE = 0, + TYPE_SKIP = 1, + TYPE_INT_8 = 2, + TYPE_UINT_8 = 3, + TYPE_INT_16 = 4, + TYPE_UINT_16 = 5, + TYPE_INT_32 = 6, + TYPE_UINT_32 = 7, + TYPE_INT_64 = 8, + TYPE_UINT_64 = 9 +}; + +enum BYTE_ORDER { + BYTE_ORDER_NONE = 0, + BYTE_ORDER_LE = 1, + BYTE_ORDER_BE = 2 +}; + +class Rule : public QObject +{ + Q_OBJECT + +public: + Rule(); + Rule(const Rule &rule); + + Rule &operator=(const Rule &rule); + bool operator==(const Rule& rule) const; + bool operator!=(const Rule& rule) const; + + friend QDataStream &operator<<(QDataStream &arch, const Rule &rule) { + arch << rule.Name(); + arch << rule.Type(); + arch << rule.Properties(); + arch << rule.Color(); + arch << rule.ByteOrder(); + arch << rule.Length(); + arch << rule.Value(); + return arch; + } + friend QDataStream &operator>>(QDataStream &arch, Rule &rule) { + QString ruleName = ""; + RULE_TYPE ruleType = TYPE_NONE; + QVariantMap ruleProps = QVariantMap(); + QColor ruleColor = QColor(); + BYTE_ORDER ruleByteOrder = BYTE_ORDER_NONE; + int ruleLength = 0; + QString ruleValue = ""; + + arch >> ruleName; + rule.SetName(ruleName); + + arch >> ruleType; + rule.SetType(ruleType); + + arch >> ruleProps; + rule.SetProperties(ruleProps); + + arch >> ruleColor; + rule.SetColor(ruleColor); + + arch >> ruleByteOrder; + rule.SetByteOrder(ruleByteOrder); + + arch >> ruleLength; + rule.SetLength(ruleLength); + + arch >> ruleValue; + rule.SetValue(ruleValue); + + return arch; + } + + void SetName(const QString name); + QString Name() const; + + void SetType(RULE_TYPE type); + RULE_TYPE Type() const; + + void SetColor(const QColor color); + QColor Color() const; + + void SetByteOrder(BYTE_ORDER byteOrder); + BYTE_ORDER ByteOrder() const; + + void SetLength(int length); + int Length() const; + + void SetValue(QString value); + QString Value() const; + + void SetProperty(QString propName, QVariant propData); + QVariant GetProperty(QString propName) const; + + void SetProperties(QVariantMap props); + QVariantMap Properties() const; + + void SetRepeatCount(int repeatCount); + int RepeatCount() const; + + void SetPreSkipCount(int preSkipCount); + int PreSkipCount() const; + + void SetPostSkipCount(int postSkipCount); + int PostSkipCount() const; + +private: + QString pName; + RULE_TYPE pType; + QVariantMap pProps; + QColor pColor; + BYTE_ORDER pByteOrder; + int pLength; + QString pValue; + int pRepeatCount; + int pPreSkipCount; + int pPostSkipCount; + + QColor pGenerateColor(); + int pGetTypeLength(RULE_TYPE ruleType); +}; +Q_DECLARE_METATYPE(Rule) + +#endif // RULE_H diff --git a/ruledialog.cpp b/ruledialog.cpp new file mode 100644 index 0000000..b0f5bc6 --- /dev/null +++ b/ruledialog.cpp @@ -0,0 +1,298 @@ +#include "ruledialog.h" +#include "ui_ruledialog.h" + +RuleDialog::RuleDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::RuleDialog) { + ui->setupUi(this); + + pRuleNames = QStringList(); + pVars = QMap(); + pDefaultRuleCount = 1; + pRules = QVector(); + + pHideLayout(ui->layout_Skip); + ui->groupBox_2->hide(); + ui->groupBox_PreSkip->hide(); + ui->groupBox_PostSkip->hide(); + + connect(ui->verticalScrollBar, &QScrollBar::valueChanged, ui->widget_RulePreview, &RulePreview::SetScrollValue); + connect(ui->widget_RulePreview, &RulePreview::ScrollMaxChanged, ui->verticalScrollBar, &QScrollBar::setMaximum); + + connect(ui->pushButton_QueueRule, &QPushButton::clicked, this, &RuleDialog::pQueueRule); + connect(ui->pushButton_Cancel, &QPushButton::clicked, this, &RuleDialog::pCancelDialog); + connect(ui->pushButton_Clear, &QPushButton::clicked, this, &RuleDialog::pClearRules); + connect(ui->pushButton_PopFirstRule, &QPushButton::clicked, this, &RuleDialog::pPopFirstRule); + connect(ui->pushButton_PopLastRule, &QPushButton::clicked, this, &RuleDialog::pPopLastRule); + connect(ui->pushButton_Save, &QPushButton::clicked, this, &RuleDialog::pSaveRules); + connect(ui->comboBox_Type, &QComboBox::currentIndexChanged, this, &RuleDialog::pTypeChanged); + + connect(this, &RuleDialog::RulesChanged, ui->widget_RulePreview, &RulePreview::SetRules); + + connect(ui->groupBox_RepeatRule, &QGroupBox::toggled, this, &RuleDialog::pRepeatToggled); + + ui->comboBox_Vars->hide(); + connect(ui->radioButton_PrevVar, &QRadioButton::toggled, this, &RuleDialog::pPrevVarToggled); + connect(ui->radioButton_StaticVal, &QRadioButton::toggled, this, &RuleDialog::pStaticValToggled); + + ui->comboBox_Pre_Vars->hide(); + connect(ui->radioButton_Pre_StaticVal, &QRadioButton::toggled, this, &RuleDialog::pPre_StaticValToggled); + connect(ui->radioButton_Pre_PrevVar, &QRadioButton::toggled, this, &RuleDialog::pPre_PrevVarToggled); + + ui->comboBox_Post_Vars->hide(); + connect(ui->radioButton_Post_StaticVal, &QRadioButton::toggled, this, &RuleDialog::pPost_StaticValToggled); + connect(ui->radioButton_Post_PrevVar, &QRadioButton::toggled, this, &RuleDialog::pPost_PrevVarToggled); +} + +RuleDialog::~RuleDialog() { + delete ui; +} + +void RuleDialog::pQueueRule() { + int index = ui->comboBox_Type->currentIndex(); + RULE_TYPE type = (RULE_TYPE)index; + if (type == TYPE_NONE) { return; } + + int repeatCount = 0; + int preSkip = 0; + int postSkip = 0; + if (ui->groupBox_RepeatRule->isChecked()) { + if (ui->radioButton_PrevVar->isChecked()) { + QString itemText = ui->comboBox_Vars->currentText(); + const QString leadingNumber = itemText.split('.').first() + "."; + const QString varText = itemText.replace(leadingNumber, "") + .split('(').first().trimmed(); + BlockValue blockVal = pVars[varText]; + repeatCount = blockVal.ValueToInt(); + } else if (ui->radioButton_StaticVal->isChecked()) { + repeatCount = ui->spinBox_2->value(); + } + } + QString name = ui->lineEdit_Name->text(); + if (name == "") { return; } + + if (ui->groupBox_PreSkip->isChecked()) { + if (ui->radioButton_Pre_StaticVal->isChecked()) { + preSkip = ui->spinBox_Pre_StaticVal->value(); + } else { + QString itemText = ui->comboBox_Pre_Vars->currentText(); + const QString leadingNumber = itemText.split('.').first() + "."; + const QString varText = itemText.replace(leadingNumber, "") + .split('(').first().trimmed(); + BlockValue blockVal = pVars[varText]; + preSkip = blockVal.ValueToInt(); + } + } + + if (ui->groupBox_PostSkip->isChecked()) { + if (ui->radioButton_Post_StaticVal->isChecked()) { + postSkip = ui->spinBox_Post_StaticVal->value(); + } else { + QString itemText = ui->comboBox_Post_Vars->currentText(); + const QString leadingNumber = itemText.split('.').first() + "."; + const QString varText = itemText.replace(leadingNumber, "") + .split('(').first().trimmed(); + BlockValue blockVal = pVars[varText]; + postSkip = blockVal.ValueToInt(); + } + } + + QString ruleName = name; + + BYTE_ORDER byteOrder = BYTE_ORDER_NONE; + if (ui->radioButton_BE->isChecked()) { + byteOrder = BYTE_ORDER_BE; + } else { + byteOrder = BYTE_ORDER_LE; + } + + Rule rule; + rule.SetName(ruleName); + rule.SetType(type); + rule.SetByteOrder(byteOrder); + rule.SetRepeatCount(repeatCount); + rule.SetPreSkipCount(preSkip); + rule.SetPostSkipCount(postSkip); + + if (index == 1) { // skip + rule.SetLength(ui->spinBox->value()); + } + + pRules.push_back(rule); + ui->widget_RulePreview->SetRules(pRules); +} + +void RuleDialog::pSaveRules() { + emit RulesChanged(pRules); + close(); +} + +void RuleDialog::pClearRules() { + pRules.clear(); + ui->widget_RulePreview->SetRules(pRules); +} + +void RuleDialog::pPopFirstRule() { + pRules.pop_front(); + ui->widget_RulePreview->SetRules(pRules); +} + +void RuleDialog::pPopLastRule() { + pRules.pop_back(); + ui->widget_RulePreview->SetRules(pRules); +} + +void RuleDialog::pCancelDialog() { + pDefaultRuleCount--; + close(); +} + +void RuleDialog::pHideLayout(QLayout* layout) { + if (!layout) + return; + + for (int i = 0; i < layout->count(); ++i) { + QWidget *widget = layout->itemAt(i)->widget(); + if (widget) { + widget->hide(); // Hide each widget in the layout + } + } +} + +void RuleDialog::pShowLayout(QLayout* layout) { + if (!layout) + return; + + for (int i = 0; i < layout->count(); ++i) { + QWidget *widget = layout->itemAt(i)->widget(); + if (widget) { + widget->show(); // Hide each widget in the layout + } + } +} + + +void RuleDialog::pTypeChanged(int index) { + pHideLayout(ui->layout_Skip); + pShowLayout(ui->layout_ByteOrder); + + switch (index) { + case 0: // none + break; + case 1: // skip + pShowLayout(ui->layout_Skip); + pHideLayout(ui->layout_ByteOrder); + break; + case 2: // int8 [1] + break; + case 3: // uint8 [1] + break; + case 4: // int16 [2] + break; + case 5: // uint16 [2] + break; + case 6: // int32 [3] + break; + case 7: // uint32 [3] + break; + case 8: // int64 [4] + break; + case 9: // uint64 [4] + break; + } +} + +void RuleDialog::pRepeatToggled(bool toggled) { + ui->groupBox_PreSkip->setVisible(toggled); + ui->groupBox_PostSkip->setVisible(toggled); +} + +void RuleDialog::pPrevVarToggled(bool toggled) { + ui->comboBox_Vars->setVisible(toggled); + ui->spinBox_2->setVisible(!toggled); +} + +void RuleDialog::pStaticValToggled(bool toggled) { + ui->comboBox_Vars->setVisible(!toggled); + ui->spinBox_2->setVisible(toggled); +} + +void RuleDialog::pPre_PrevVarToggled(bool toggled) { + ui->comboBox_Pre_Vars->setVisible(toggled); + ui->spinBox_Pre_StaticVal->setVisible(!toggled); +} + +void RuleDialog::pPre_StaticValToggled(bool toggled) { + ui->comboBox_Pre_Vars->setVisible(!toggled); + ui->spinBox_Pre_StaticVal->setVisible(toggled); +} + +void RuleDialog::pPost_PrevVarToggled(bool toggled) { + ui->comboBox_Post_Vars->setVisible(toggled); + ui->spinBox_Post_StaticVal->setVisible(!toggled); +} + +void RuleDialog::pPost_StaticValToggled(bool toggled) { + ui->comboBox_Post_Vars->setVisible(!toggled); + ui->spinBox_Post_StaticVal->setVisible(toggled); +} + +void RuleDialog::closeEvent(QCloseEvent *event) { + pDefaultRuleCount++; + + const QString defaultName = QString("RULE %1").arg(pDefaultRuleCount); + ui->lineEdit_Name->setText(defaultName); + ui->comboBox_Type->setCurrentIndex(0); + + ui->radioButton_LE->setChecked(true); + ui->spinBox->setValue(1); + + ui->radioButton_StaticVal->setChecked(true); + ui->spinBox_2->setValue(1); + ui->comboBox_Vars->setCurrentIndex(0); + + pRules.clear(); + ui->widget_RulePreview->SetRules(pRules); + + QDialog::closeEvent(event); +} + +Rule RuleDialog::GetRule() { + return pRule; +} + +void RuleDialog::SetRule(const Rule rule) { + ui->lineEdit_Name->setText(rule.Name()); + + if (rule.Type() == TYPE_SKIP) { + ui->spinBox->setValue(rule.Length()); + } +} + +void RuleDialog::SetRuleNames(QStringList ruleNames) { + pRuleNames = ruleNames; +} + +void RuleDialog::SetVars(QMap vars) { + ui->comboBox_Vars->clear(); + ui->comboBox_Vars->addItem("Select Variable"); + + ui->comboBox_Pre_Vars->clear(); + ui->comboBox_Pre_Vars->addItem("Select Variable"); + + ui->comboBox_Post_Vars->clear(); + ui->comboBox_Post_Vars->addItem("Select Variable"); + + int i = 0; + for (auto [key, value] : vars.asKeyValueRange()) { + i++; + QString varName = (QString)key; + BlockValue varVal = (BlockValue)value; + QString itemName = QString("%1. %2 (%3)") + .arg(QString::number(i), varName, varVal.Value().toString()); + ui->comboBox_Vars->addItem(itemName); + ui->comboBox_Pre_Vars->addItem(itemName); + ui->comboBox_Post_Vars->addItem(itemName); + } + pVars = vars; +} diff --git a/ruledialog.h b/ruledialog.h new file mode 100644 index 0000000..be8123b --- /dev/null +++ b/ruledialog.h @@ -0,0 +1,64 @@ +#ifndef RULEDIALOG_H +#define RULEDIALOG_H + +#include "rule.h" +#include "blockvalue.h" +#include "rulepreview.h" + +#include +#include + +namespace Ui { +class RuleDialog; +} + +class RuleDialog : public QDialog +{ + Q_OBJECT + +public: + explicit RuleDialog(QWidget *parent = nullptr); + ~RuleDialog(); + + Rule GetRule(); + void SetRule(const Rule rule); + + void SetRuleNames(QStringList ruleNames); + void SetVars(QMap vars); + +private slots: + void pQueueRule(); + void pClearRules(); + void pSaveRules(); + void pPopFirstRule(); + void pPopLastRule(); + void pCancelDialog(); + void pTypeChanged(int index); + void pRepeatToggled(bool toggled); + void pPrevVarToggled(bool toggled); + void pStaticValToggled(bool toggled); + void pPre_PrevVarToggled(bool toggled); + void pPre_StaticValToggled(bool toggled); + void pPost_PrevVarToggled(bool toggled); + void pPost_StaticValToggled(bool toggled); + +signals: + void RuleChanged(Rule rule); + void RulesChanged(QVector rules); + +protected: + void closeEvent(QCloseEvent *event) override; + +private: + Ui::RuleDialog *ui; + Rule pRule; + QStringList pRuleNames; + QMap pVars; + int pDefaultRuleCount; + QVector pRules; + + void pHideLayout(QLayout *layout); + void pShowLayout(QLayout *layout); +}; + +#endif // RULEDIALOG_H diff --git a/ruledialog.ui b/ruledialog.ui new file mode 100644 index 0000000..eee0378 --- /dev/null +++ b/ruledialog.ui @@ -0,0 +1,756 @@ + + + RuleDialog + + + + 0 + 0 + 546 + 595 + + + + + 546 + 538 + + + + Add Rule + + + + + + + + + + + 0 + 0 + + + + + CommitMono + + + + Preview + + + + + + + + + + + + :/icons/delete.png:/icons/delete.png + + + + + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 0 + + + + + + + + 0 + + + 100 + + + 250 + + + Qt::Orientation::Vertical + + + + + + + + + + + + + + + + + CommitMono + + + + Rule Options + + + + + + + + + CommitMono + + + + Name: + + + + + + + + CommitMono + + + + RULE + + + 10 + + + Rule Name + + + + + + + + + + + Type: + + + + + + + + CommitMono + + + + + Select Input + + + + + Skip n Bytes + + + + + int8 [1] + + + + + uint8 [1] + + + + + int16 [2] + + + + + uint16 [2] + + + + + int32 [3] + + + + + uint32 [3] + + + + + int64 [4] + + + + + uint64 [4] + + + + + + + + + + + + + CommitMono + + + + Little Endian + + + true + + + + + + + + CommitMono + + + + Big Endian + + + + + + + + + + + + CommitMono + + + + Skip: + + + + + + + + CommitMono + + + + bytes + + + 1 + + + 100000 + + + + + + + + + + + + + CommitMono + + + + Repeat Rule + + + true + + + false + + + + + + + + + CommitMono + + + + Static Value + + + true + + + + + + + + CommitMono + + + + Previous Var + + + + + + + + + + + + CommitMono + + + + Repeat #: + + + + + + + + CommitMono + + + + times + + + 1 + + + 100000 + + + + + + + + CommitMono + + + + + Select Variable + + + + + + + + + + + + + + CommitMono + + + + Pre-Repeat Skip + + + true + + + false + + + + + + + + + CommitMono + + + + Static Value + + + true + + + + + + + + CommitMono + + + + Previous Var + + + + + + + + + + + + CommitMono + + + + Skip: + + + + + + + + CommitMono + + + + bytes + + + 1 + + + 100000 + + + + + + + + CommitMono + + + + + Select Variable + + + + + + + + + + + + + + CommitMono + + + + Post-Repeat Skip + + + true + + + false + + + + + + + + + CommitMono + + + + Static Value + + + true + + + + + + + + CommitMono + + + + Previous Var + + + + + + + + + + + + CommitMono + + + + Skip: + + + + + + + + CommitMono + + + + bytes + + + 1 + + + 100000 + + + + + + + + CommitMono + + + + + Select Variable + + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + + + CommitMono + + + + Queue Rule + + + + + + + + CommitMono + + + + Pop First + + + + + + + + CommitMono + + + + Pop Last + + + + + + + + CommitMono + + + + Clear + + + + + + + + + + CommitMono + + + + GroupBox + + + + + + + + + + + + + + CommitMono + + + + Save Rule + + + + + + + + CommitMono + + + + Import Snippet + + + + + + + + CommitMono + + + + Export Snippet + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + CommitMono + + + + Cancel + + + + + + + + + + RulePreview + QWidget +
rulepreview.h
+ 1 +
+
+ + + + +
diff --git a/rulepreview.cpp b/rulepreview.cpp new file mode 100644 index 0000000..d82e977 --- /dev/null +++ b/rulepreview.cpp @@ -0,0 +1,140 @@ +#include "rulepreview.h" +#include "ui_rulepreview.h" + +RulePreview::RulePreview(QWidget *parent) : + QWidget(parent), + ui(new Ui::RulePreview) +{ + ui->setupUi(this); + + pRules = QQueue(); + pScrollValue = 0; + pScrollMax = 0; +} + +RulePreview::~RulePreview() { + delete ui; +} + +void RulePreview::AddRule(const Rule rule) { + pRules.enqueue(rule); + update(); +} + +void RulePreview::AddRules(const QVector rules) { + for (int i = 0; i < rules.size(); i++) { + pRules.enqueue(rules[i]); + } + update(); +} + +void RulePreview::DeleteRule(const Rule rule) { + if (!pRules.contains(rule)) { return; } + if (pRules.size() == 0) { return; } + + for (int i = 0; i < pRules.size(); i++) { + Rule currentRule = pRules.dequeue(); + + if (currentRule != rule) { + pRules.enqueue(currentRule); + } + } + update(); +} + +void RulePreview::DeleteRuleByName(const QString ruleName) { + if (pRules.size() == 0) { return; } + + for (int i = 0; i < pRules.size(); i++) { + Rule currentRule = pRules.dequeue(); + + if (currentRule.Name() != ruleName) { + pRules.enqueue(currentRule); + } + } + update(); +} + +void RulePreview::SetRules(const QVector rules) { + pRules.clear(); + AddRules(rules); +} + +void RulePreview::SetScrollValue(int scrollValue) { + pScrollValue = scrollValue; + update(); +} + +void RulePreview::paintEvent(QPaintEvent *event) { + Q_UNUSED(event); + + QPainter painter(this); + + int ruleIndex = 1; + QRectF rulesRect = event->rect(); + painter.setBrush(Qt::white); + painter.drawRect(rulesRect); + + painter.setFont(QFont("CommitMono", 7)); + + QRectF clipRect(0, rulesRect.top(), width(), rulesRect.height()); + painter.setClipRect(clipRect); + + foreach (Rule rule, pRules) { + painter.setPen(QPen(rule.Color(), 1)); + + QString typeText = ""; + + QColor ruleBackground(rule.Color()); + ruleBackground.setAlpha(75); + painter.setBrush(ruleBackground); + + // Draw the rule information in the rule stack on the right side + QRectF ruleBackgroundRect(rulesRect.left(), -pScrollValue + rulesRect.top() + 1 + (QFontMetrics(painter.font()).height() * 3) * (ruleIndex - 1), + rulesRect.width(), QFontMetrics(painter.font()).height() * 3); + QRectF ruleRect(rulesRect.left() + 1, -pScrollValue + rulesRect.top() + 2 + (QFontMetrics(painter.font()).height() * 3) * (ruleIndex - 1), + rulesRect.width() - 2, QFontMetrics(painter.font()).height() * 3); + painter.drawRect(ruleBackgroundRect); + + pScrollMax = qMax(pScrollMax, (int)ruleRect.bottom()); + + bool isSkip = false; + switch ((int)rule.Type()) { + case 1: // TYPE_SKIP + typeText = QString("Skip %1 byte(s)").arg(rule.Length()); + isSkip = true; + break; + case 2: // TYPE_INT_8 + case 3: // TYPE_UINT_8 + case 4: // TYPE_INT_16 + case 5: // TYPE_UINT_16 + case 6: // TYPE_INT_32 + case 7: // TYPE_UINT_32 + case 8: // TYPE_INT_64 + case 9: // TYPE_UINT_64 + typeText = QString("%1-BIT %2 INTEGER").arg(rule.Length() * 8).arg(rule.Type() % 2 == 0 ? "" : "US"); + break; + default: + typeText = "UH-OH"; + break; + } + + painter.setPen(Qt::black); + QString paddedIndex = QString::number(ruleIndex).rightJustified(2, '0'); + QString ruleName = rule.Name().toUpper(); + + QString ruleText = QString("%1. %2\n%3\nN/A\n").arg(paddedIndex, ruleName, typeText); + painter.drawText(ruleRect, Qt::TextWrapAnywhere, ruleText); + QString ruleByteOrder = QString(rule.ByteOrder() == BYTE_ORDER_BE ? "BE" : "LE") + "\n\n"; + if (!isSkip) { + painter.drawText(ruleRect, Qt::AlignRight, ruleByteOrder); + } + + ruleIndex++; + } + emit ScrollMaxChanged(qMax(0, static_cast(pScrollMax - rulesRect.height()))); +} + +QSize RulePreview::sizeHint() const { + return parentWidget()->size(); +} diff --git a/rulepreview.h b/rulepreview.h new file mode 100644 index 0000000..1fe3365 --- /dev/null +++ b/rulepreview.h @@ -0,0 +1,53 @@ +#ifndef RULEPREVIEW_H +#define RULEPREVIEW_H + +#include "rule.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { +class RulePreview; +} + +class RuleDialog; + +class RulePreview : public QWidget +{ + Q_OBJECT + +public: + explicit RulePreview(QWidget *parent = nullptr); + ~RulePreview(); + +public slots: + void AddRule(const Rule rule); + void AddRules(const QVector rules); + void DeleteRule(const Rule rule); + void DeleteRuleByName(const QString ruleName); + void SetRules(const QVector rules); + + void SetScrollValue(int scrollValue); + +signals: + void ScrollMaxChanged(int scrollMax); + +protected: + void paintEvent(QPaintEvent *event) override; + QSize sizeHint() const override; + +private: + Ui::RulePreview *ui; + QQueue pRules; + int pScrollValue; + int pScrollMax; +}; + +#endif // RULEPREVIEW_H diff --git a/rulepreview.ui b/rulepreview.ui new file mode 100644 index 0000000..ffdb9b3 --- /dev/null +++ b/rulepreview.ui @@ -0,0 +1,19 @@ + + + RulePreview + + + + 0 + 0 + 400 + 300 + + + + Form + + + + +