From 313eef1ed4c6e197005210f53e7095f925ccfec1 Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Sat, 23 Dec 2023 12:45:45 -0600 Subject: [PATCH 1/5] First pass at register profiles. --- src/CMakeLists.txt | 4 + src/SeerGdbWidget.cpp | 4 + src/SeerRegisterProfileDialog.cpp | 143 +++++++++++++++++++ src/SeerRegisterProfileDialog.h | 35 +++++ src/SeerRegisterProfileDialog.ui | 174 ++++++++++++++++++++++++ src/SeerRegisterTreeWidgetItem.cpp | 26 ++++ src/SeerRegisterTreeWidgetItem.h | 23 ++++ src/SeerRegisterValuesBrowserWidget.cpp | 139 +++++++++++++------ src/SeerRegisterValuesBrowserWidget.h | 6 + src/SeerRegisterValuesBrowserWidget.ui | 107 ++++++++++----- 10 files changed, 585 insertions(+), 76 deletions(-) create mode 100644 src/SeerRegisterProfileDialog.cpp create mode 100644 src/SeerRegisterProfileDialog.h create mode 100644 src/SeerRegisterProfileDialog.ui create mode 100644 src/SeerRegisterTreeWidgetItem.cpp create mode 100644 src/SeerRegisterTreeWidgetItem.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b6fe293..7d0c40bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -90,6 +90,8 @@ set(HEADER_FILES SeerImageVisualizerWidget.h SeerRegisterValuesBrowserWidget.h SeerRegisterEditValueDialog.h + SeerRegisterProfileDialog.h + SeerRegisterTreeWidgetItem.h SeerRunStatusIndicator.h SeerLibraryBrowserWidget.h SeerSourceBrowserWidget.h @@ -181,6 +183,8 @@ set(SOURCE_FILES SeerImageVisualizerWidget.cpp SeerRegisterValuesBrowserWidget.cpp SeerRegisterEditValueDialog.cpp + SeerRegisterProfileDialog.cpp + SeerRegisterTreeWidgetItem.cpp SeerRunStatusIndicator.cpp SeerLibraryBrowserWidget.cpp SeerSourceBrowserWidget.cpp diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index 1224129b..c6efb942 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -2253,6 +2253,10 @@ void SeerGdbWidget::handleGdbRegisterListValues (QString fmt) { fmt = "N"; } + // XXX Not sure what --skip-unavailable does. + // XXX Perhaps skips registers that can't get value for. + // XXX handleGdbCommand("-data-list-register-values --skip-unavailable " + fmt); + handleGdbCommand("-data-list-register-values " + fmt); } diff --git a/src/SeerRegisterProfileDialog.cpp b/src/SeerRegisterProfileDialog.cpp new file mode 100644 index 00000000..2ea9cdec --- /dev/null +++ b/src/SeerRegisterProfileDialog.cpp @@ -0,0 +1,143 @@ +#include "SeerRegisterProfileDialog.h" +#include "SeerRegisterTreeWidgetItem.h" +#include +#include +#include +#include + +SeerRegisterProfileDialog::SeerRegisterProfileDialog (QWidget* parent) : QDialog(parent) { + + // Set up the UI. + setupUi(this); + + registersTreeWidget->setSortingEnabled(true); // We can sort on columns. + registersTreeWidget->sortByColumn(0, Qt::AscendingOrder); + registersTreeWidget->resizeColumnToContents(0); // index + registersTreeWidget->resizeColumnToContents(1); // name + registersTreeWidget->resizeColumnToContents(2); // checkbox + registersTreeWidget->clear(); + + // Setup the widgets + setRegisters(QStringList(), QVector()); + + // Connect things. + QObject::connect(enablePushButton, &QPushButton::clicked, this, &SeerRegisterProfileDialog::handleEnableSelected); + QObject::connect(disablePushButton, &QPushButton::clicked, this, &SeerRegisterProfileDialog::handleDisableSelected); + + // Restore window settings. + readSettings(); +} + +SeerRegisterProfileDialog::~SeerRegisterProfileDialog () { +} + +void SeerRegisterProfileDialog::setRegisters (const QStringList& registerNames, const QVector& registerEnabled) { + + registersTreeWidget->clear(); + + for (int i=0; isetText(0, QString::number(i)); + topItem->setText(1, registerNames[i]); + + if (registerEnabled[i] == true) { + topItem->setCheckState(2, Qt::Checked); + }else{ + topItem->setCheckState(2, Qt::Unchecked); + } + + registersTreeWidget->addTopLevelItem(topItem); + } + + registersTreeWidget->resizeColumnToContents(0); + registersTreeWidget->resizeColumnToContents(1); + registersTreeWidget->resizeColumnToContents(2); +} + +QStringList SeerRegisterProfileDialog::registerNames () const { + + QStringList registerNames; + + for (int i=0; itopLevelItemCount(); i++) { + + QTreeWidgetItem* topItem = registersTreeWidget->topLevelItem(i); + + registerNames.push_back(topItem->text(1)); + } + + return registerNames; +} + +QVector SeerRegisterProfileDialog::registerEnabled () const { + + QVector registerEnabled; + + for (int i=0; itopLevelItemCount(); i++) { + + QTreeWidgetItem* topItem = registersTreeWidget->topLevelItem(i); + + if (topItem->checkState(2) == Qt::Checked) { + registerEnabled.push_back(true); + }else{ + registerEnabled.push_back(false); + } + } + + return registerEnabled; +} + +void SeerRegisterProfileDialog::accept () { + + if (profileNameLineEdit->text() == "") { + QMessageBox::warning(this, "Seer", "The register profile name is blank.", QMessageBox::Ok); + return; + } + + QDialog::accept(); +} + +void SeerRegisterProfileDialog::handleEnableSelected () { + + QList selected = registersTreeWidget->selectedItems(); + + foreach (QTreeWidgetItem* item, selected) { + item->setCheckState(2, Qt::Checked); + } +} + +void SeerRegisterProfileDialog::handleDisableSelected () { + + QList selected = registersTreeWidget->selectedItems(); + + foreach (QTreeWidgetItem* item, selected) { + item->setCheckState(2, Qt::Unchecked); + } +} + +void SeerRegisterProfileDialog::writeSettings() { + + QSettings settings; + + settings.beginGroup("registerprofiledialog"); { + settings.setValue("size", size()); + }settings.endGroup(); +} + +void SeerRegisterProfileDialog::readSettings() { + + QSettings settings; + + settings.beginGroup("registerprofiledialog"); { + resize(settings.value("size", QSize(600, 600)).toSize()); + } settings.endGroup(); +} + +void SeerRegisterProfileDialog::resizeEvent (QResizeEvent* event) { + + // Write window settings. + writeSettings(); + + QWidget::resizeEvent(event); +} + diff --git a/src/SeerRegisterProfileDialog.h b/src/SeerRegisterProfileDialog.h new file mode 100644 index 00000000..23db347d --- /dev/null +++ b/src/SeerRegisterProfileDialog.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +#include "ui_SeerRegisterProfileDialog.h" + +class SeerRegisterProfileDialog : public QDialog, protected Ui::SeerRegisterProfileDialogForm { + + Q_OBJECT + + public: + explicit SeerRegisterProfileDialog (QWidget* parent = 0); + ~SeerRegisterProfileDialog (); + + void setRegisters (const QStringList& registerNames, const QVector& registerEnabled); + QStringList registerNames () const; + QVector registerEnabled () const; + + public slots: + void accept (); + + private slots: + void handleEnableSelected (); + void handleDisableSelected (); + + protected: + void writeSettings (); + void readSettings (); + void resizeEvent (QResizeEvent* event); + + private: +}; + diff --git a/src/SeerRegisterProfileDialog.ui b/src/SeerRegisterProfileDialog.ui new file mode 100644 index 00000000..2eeefec4 --- /dev/null +++ b/src/SeerRegisterProfileDialog.ui @@ -0,0 +1,174 @@ + + + SeerRegisterProfileDialogForm + + + + 0 + 0 + 600 + 601 + + + + Seer - Register Profile Editor + + + + + + + 100 + 0 + + + + QAbstractItemView::ExtendedSelection + + + true + + + + # + + + + + Name + + + + + Enabled + + + + + + + + + + + + Profile name + + + + + + + Enable Selected + + + + + + + Disable Selected + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 40 + + + + + + + + + + Import + + + + + + + Export + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 318 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + SeerRegisterProfileDialogForm + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SeerRegisterProfileDialogForm + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/SeerRegisterTreeWidgetItem.cpp b/src/SeerRegisterTreeWidgetItem.cpp new file mode 100644 index 00000000..0939826c --- /dev/null +++ b/src/SeerRegisterTreeWidgetItem.cpp @@ -0,0 +1,26 @@ +#include "SeerRegisterTreeWidgetItem.h" +#include +#include +#include + +// +// SeerRegisterTreeWidgetItem +// +bool SeerRegisterTreeWidgetItem::operator< (const QTreeWidgetItem& other) const { + + int column = treeWidget()->sortColumn(); + + // If no sort column set, then default to ascending order. + if (column < 0) { + return true; + } + + // If sort on column 0, then compare numerically. + if (column == 0) { + return text(column).toInt() < other.text(column).toInt(); + } + + // Otherwise, all other columns are textual. + return text(column) < other.text(column); +} + diff --git a/src/SeerRegisterTreeWidgetItem.h b/src/SeerRegisterTreeWidgetItem.h new file mode 100644 index 00000000..0e35757a --- /dev/null +++ b/src/SeerRegisterTreeWidgetItem.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +class SeerRegisterTreeWidgetItem : public QTreeWidgetItem { + + public: + /* Do we need to specify the base constructors? + QTreeWidgetItem(const QTreeWidgetItem &other) + QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *preceding, int type = Type) + QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings, int type = Type) + QTreeWidgetItem(QTreeWidgetItem *parent, int type = Type) + QTreeWidgetItem(QTreeWidget *parent, QTreeWidgetItem *preceding, int type = Type) + QTreeWidgetItem(QTreeWidget *parent, const QStringList &strings, int type = Type) + QTreeWidgetItem(QTreeWidget *parent, int type = Type) + QTreeWidgetItem(const QStringList &strings, int type = Type) + QTreeWidgetItem(int type = Type) + */ + + virtual bool operator< (const QTreeWidgetItem& other) const; +}; + diff --git a/src/SeerRegisterValuesBrowserWidget.cpp b/src/SeerRegisterValuesBrowserWidget.cpp index 700f9472..847df56b 100644 --- a/src/SeerRegisterValuesBrowserWidget.cpp +++ b/src/SeerRegisterValuesBrowserWidget.cpp @@ -1,63 +1,26 @@ #include "SeerRegisterValuesBrowserWidget.h" #include "SeerRegisterEditValueDialog.h" +#include "SeerRegisterProfileDialog.h" +#include "SeerRegisterTreeWidgetItem.h" #include "SeerUtl.h" #include "QEditDelegate.h" #include #include #include #include +#include #include #include #include +#include #include -// -// SeerRegisterTreeWidgetItem -// -class SeerRegisterTreeWidgetItem : public QTreeWidgetItem { - - public: - /* Do we need to specify the base constructors? - QTreeWidgetItem(const QTreeWidgetItem &other) - QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *preceding, int type = Type) - QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings, int type = Type) - QTreeWidgetItem(QTreeWidgetItem *parent, int type = Type) - QTreeWidgetItem(QTreeWidget *parent, QTreeWidgetItem *preceding, int type = Type) - QTreeWidgetItem(QTreeWidget *parent, const QStringList &strings, int type = Type) - QTreeWidgetItem(QTreeWidget *parent, int type = Type) - QTreeWidgetItem(const QStringList &strings, int type = Type) - QTreeWidgetItem(int type = Type) - */ - - virtual bool operator< (const QTreeWidgetItem& other) const; -}; - -bool SeerRegisterTreeWidgetItem::operator< (const QTreeWidgetItem& other) const { - - int column = treeWidget()->sortColumn(); - - // If no sort column set, then default to ascending order. - if (column < 0) { - return true; - } - - // If sort on column 0, then compare numerically. - if (column == 0) { - return text(column).toInt() < other.text(column).toInt(); - } - - // Otherwise, all other columns are textual. - return text(column) < other.text(column); -} - - -// -// Seer Register Tree -// - SeerRegisterValuesBrowserWidget::SeerRegisterValuesBrowserWidget (QWidget* parent) : QWidget(parent) { + _newProfileAction = 0; + _deleteProfileAction = 0; + // Construct the UI. setupUi(this); @@ -90,12 +53,24 @@ SeerRegisterValuesBrowserWidget::SeerRegisterValuesBrowserWidget (QWidget* paren registersTreeWidget->setItemDelegateForColumn(2, editDelegate); registersTreeWidget->setItemDelegateForColumn(3, new QNoEditDelegate(this)); + + // Preference menu. + QMenu* menu = new QMenu(); + + _newProfileAction = menu->addAction("New profile"); + _deleteProfileAction = menu->addAction("Delete profile"); + + preferencesToolButton->setMenu(menu); + preferencesToolButton->setPopupMode(QToolButton::InstantPopup); + // Connect things. QObject::connect(registersTreeWidget, &QTreeWidget::itemEntered, this, &SeerRegisterValuesBrowserWidget::handleItemEntered); QObject::connect(registersTreeWidget, &QTreeWidget::customContextMenuRequested, this, &SeerRegisterValuesBrowserWidget::handleContextMenu); QObject::connect(editDelegate, &QAllowEditDelegate::editingFinished, this, &SeerRegisterValuesBrowserWidget::handleIndexEditingFinished); QObject::connect(registerFormatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerRegisterValuesBrowserWidget::handleFormatChanged); QObject::connect(registersTreeWidget->header(), &QHeaderView::sectionClicked, this, &SeerRegisterValuesBrowserWidget::handleColumnSelected); + QObject::connect(_newProfileAction, &QAction::triggered, this, &SeerRegisterValuesBrowserWidget::handleNewProfile); + QObject::connect(_deleteProfileAction, &QAction::triggered, this, &SeerRegisterValuesBrowserWidget::handleDeleteProfile); // Restore settings. readSettings(); @@ -136,6 +111,8 @@ void SeerRegisterValuesBrowserWidget::handleText (const QString& text) { int i = 0; for ( const auto& name_text : name_list ) { + // XXX Commenting this out will get extra registers. + // XXX Are they valid? if (name_text == "") { continue; } @@ -411,6 +388,80 @@ void SeerRegisterValuesBrowserWidget::handleColumnSelected (int logicalIndex) { writeSettings(); } +void SeerRegisterValuesBrowserWidget::handleNewProfile () { + + if (registersTreeWidget->topLevelItemCount() == 0) { + QMessageBox::warning(this, "Seer", "When creating a profile, Seer needs to be debugging a program.", QMessageBox::Ok); + return; + } + + // Build a list of registers. + QStringList registerNames; + QVector registerEnabled; + + for (int i=0; itopLevelItemCount(); i++) { + + QTreeWidgetItem* item = registersTreeWidget->topLevelItem(i); + + registerNames.push_back(item->text(1)); + registerEnabled.push_back(true); + } + + // Bring up the register profile dialog. + SeerRegisterProfileDialog dlg(this); + + dlg.setRegisters(registerNames, registerEnabled); + + if (dlg.exec()) { + + registerNames = dlg.registerNames(); + registerEnabled = dlg.registerEnabled(); + + handleShowHideRegisters(registerNames, registerEnabled); + } +} + +void SeerRegisterValuesBrowserWidget::handleDeleteProfile () { + + QMessageBox::warning(this, "Seer", "There are no profiles to delete.", QMessageBox::Ok); +} + +void SeerRegisterValuesBrowserWidget::handleShowHideRegisters (const QStringList& registerNames, QVector& registerEnabled) { + + // If the list is empty, show all. + if (registerNames.count() == 0 || registerEnabled.count() == 0) { + + for (int i=0; itopLevelItemCount(); i++) { + + QTreeWidgetItem* topItem = registersTreeWidget->topLevelItem(i); + topItem->setHidden(false); + } + return; + } + + // There is a list. Hide all, then show which ones are enabled. + for (int i=0; itopLevelItemCount(); i++) { + + QTreeWidgetItem* topItem = registersTreeWidget->topLevelItem(i); + topItem->setHidden(true); + } + + for (int i=0; i matches = registersTreeWidget->findItems(registerName, Qt::MatchExactly, 1); + + for (int i=0; isetHidden(false); + } + } +} + void SeerRegisterValuesBrowserWidget::writeSettings () { QSettings settings; diff --git a/src/SeerRegisterValuesBrowserWidget.h b/src/SeerRegisterValuesBrowserWidget.h index c06e7474..889d17f8 100644 --- a/src/SeerRegisterValuesBrowserWidget.h +++ b/src/SeerRegisterValuesBrowserWidget.h @@ -2,6 +2,7 @@ #include "ui_SeerRegisterValuesBrowserWidget.h" #include +#include #include #include @@ -27,6 +28,9 @@ class SeerRegisterValuesBrowserWidget : public QWidget, protected Ui::SeerRegist void handleIndexEditingFinished (const QModelIndex& index); void handleFormatChanged (int index); void handleColumnSelected (int logicalIndex); + void handleNewProfile (); + void handleDeleteProfile (); + void handleShowHideRegisters (const QStringList& registerNames, QVector& registerEnabled); signals: void refreshRegisterNames (); @@ -40,6 +44,8 @@ class SeerRegisterValuesBrowserWidget : public QWidget, protected Ui::SeerRegist private: bool _needsRegisterNames; + QAction* _newProfileAction; + QAction* _deleteProfileAction; }; diff --git a/src/SeerRegisterValuesBrowserWidget.ui b/src/SeerRegisterValuesBrowserWidget.ui index 3fd53f95..5beebeb3 100644 --- a/src/SeerRegisterValuesBrowserWidget.ui +++ b/src/SeerRegisterValuesBrowserWidget.ui @@ -13,38 +13,79 @@ Form - - - - - Format - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - - 638 - 20 - - - + + + + + + + Format + + + + + + + + 0 + 0 + + + + Register Value Format. + + + + + + + Profile + + + + + + + + 0 + 0 + + + + Register Profile Selection. + + + + + + + Qt::Horizontal + + + + 468 + 23 + + + + + + + + Preferences + + + + + + + :/seer/resources/RelaxLightIcons/application-menu.svg:/seer/resources/RelaxLightIcons/application-menu.svg + + + + - + 4 @@ -83,6 +124,8 @@
QIndexTreeWidget.h
- + + + From 217145a310ad05f4c3baabeca8d3c145ff1cd00e Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Sun, 24 Dec 2023 11:09:00 -0600 Subject: [PATCH 2/5] More work on register profiles. --- src/SeerRegisterProfileDialog.cpp | 21 ++++ src/SeerRegisterProfileDialog.h | 3 + src/SeerRegisterProfileDialog.ui | 18 ++++ src/SeerRegisterValuesBrowserWidget.cpp | 137 ++++++++++++++++++++++-- src/SeerRegisterValuesBrowserWidget.h | 9 +- src/SeerRegisterValuesBrowserWidget.ui | 7 +- 6 files changed, 181 insertions(+), 14 deletions(-) diff --git a/src/SeerRegisterProfileDialog.cpp b/src/SeerRegisterProfileDialog.cpp index 2ea9cdec..45320b35 100644 --- a/src/SeerRegisterProfileDialog.cpp +++ b/src/SeerRegisterProfileDialog.cpp @@ -1,6 +1,8 @@ #include "SeerRegisterProfileDialog.h" #include "SeerRegisterTreeWidgetItem.h" #include +#include +#include #include #include #include @@ -17,6 +19,10 @@ SeerRegisterProfileDialog::SeerRegisterProfileDialog (QWidget* parent) : QDialog registersTreeWidget->resizeColumnToContents(2); // checkbox registersTreeWidget->clear(); + QRegularExpressionValidator* validator = new QRegularExpressionValidator(QRegularExpression("[a-z0-9]+")); + + profileNameLineEdit->setValidator(validator); + // Setup the widgets setRegisters(QStringList(), QVector()); @@ -87,6 +93,16 @@ QVector SeerRegisterProfileDialog::registerEnabled () const { return registerEnabled; } +void SeerRegisterProfileDialog::setProfileName (const QString& profileName) { + + profileNameLineEdit->setText(profileName); +} + +QString SeerRegisterProfileDialog::profileName () const { + + return profileNameLineEdit->text(); +} + void SeerRegisterProfileDialog::accept () { if (profileNameLineEdit->text() == "") { @@ -94,6 +110,11 @@ void SeerRegisterProfileDialog::accept () { return; } + if (profileNameLineEdit->text() == "allregisters") { + QMessageBox::warning(this, "Seer", "The register profile name of 'allregisters' is reserved.\n\nChoose a different name.", QMessageBox::Ok); + return; + } + QDialog::accept(); } diff --git a/src/SeerRegisterProfileDialog.h b/src/SeerRegisterProfileDialog.h index 23db347d..bdf21eb7 100644 --- a/src/SeerRegisterProfileDialog.h +++ b/src/SeerRegisterProfileDialog.h @@ -18,6 +18,9 @@ class SeerRegisterProfileDialog : public QDialog, protected Ui::SeerRegisterProf QStringList registerNames () const; QVector registerEnabled () const; + void setProfileName (const QString& profileName); + QString profileName () const; + public slots: void accept (); diff --git a/src/SeerRegisterProfileDialog.ui b/src/SeerRegisterProfileDialog.ui index 2eeefec4..578cd00f 100644 --- a/src/SeerRegisterProfileDialog.ui +++ b/src/SeerRegisterProfileDialog.ui @@ -51,13 +51,22 @@ + + Profile name (lowercase letters and numbers). + Profile name + + true + + + Enable selected items. + Enable Selected @@ -65,6 +74,9 @@ + + Disable selected items. + Disable Selected @@ -92,6 +104,9 @@ + + Import items from a file. + Import @@ -99,6 +114,9 @@ + + Export items to a file. + Export diff --git a/src/SeerRegisterValuesBrowserWidget.cpp b/src/SeerRegisterValuesBrowserWidget.cpp index 847df56b..15c38904 100644 --- a/src/SeerRegisterValuesBrowserWidget.cpp +++ b/src/SeerRegisterValuesBrowserWidget.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -43,6 +44,8 @@ SeerRegisterValuesBrowserWidget::SeerRegisterValuesBrowserWidget (QWidget* paren registerFormatComboBox->addItem("Decimal", QVariant("d")); registerFormatComboBox->addItem("Raw", QVariant("r")); + registerProfileComboBox->addItem("allregisters"); + _needsRegisterNames = true; // Create edit delegate. @@ -71,6 +74,7 @@ SeerRegisterValuesBrowserWidget::SeerRegisterValuesBrowserWidget (QWidget* paren QObject::connect(registersTreeWidget->header(), &QHeaderView::sectionClicked, this, &SeerRegisterValuesBrowserWidget::handleColumnSelected); QObject::connect(_newProfileAction, &QAction::triggered, this, &SeerRegisterValuesBrowserWidget::handleNewProfile); QObject::connect(_deleteProfileAction, &QAction::triggered, this, &SeerRegisterValuesBrowserWidget::handleDeleteProfile); + QObject::connect(registerProfileComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerRegisterValuesBrowserWidget::handleProfileChanged); // Restore settings. readSettings(); @@ -131,6 +135,8 @@ void SeerRegisterValuesBrowserWidget::handleText (const QString& text) { i++; } + handleShowHideRegisters(); + _needsRegisterNames = false; }else if (text.startsWith("^done,register-values=[") && text.endsWith("]")) { @@ -414,10 +420,26 @@ void SeerRegisterValuesBrowserWidget::handleNewProfile () { if (dlg.exec()) { + QString profileName = dlg.profileName(); + + if (profileName == "") { + return; + } + registerNames = dlg.registerNames(); registerEnabled = dlg.registerEnabled(); - handleShowHideRegisters(registerNames, registerEnabled); + registerProfileComboBox->addItem(profileName); + registerProfileComboBox->setCurrentText(profileName); + + writeProfileSettings(profileName, registerNames, registerEnabled); + writeSettings(); + + // Use them. + _registerNames = registerNames; + _registerEnabled = registerEnabled; + + handleShowHideRegisters(); } } @@ -426,16 +448,17 @@ void SeerRegisterValuesBrowserWidget::handleDeleteProfile () { QMessageBox::warning(this, "Seer", "There are no profiles to delete.", QMessageBox::Ok); } -void SeerRegisterValuesBrowserWidget::handleShowHideRegisters (const QStringList& registerNames, QVector& registerEnabled) { +void SeerRegisterValuesBrowserWidget::handleShowHideRegisters () { // If the list is empty, show all. - if (registerNames.count() == 0 || registerEnabled.count() == 0) { + if (_registerNames.count() == 0 || _registerEnabled.count() == 0) { for (int i=0; itopLevelItemCount(); i++) { QTreeWidgetItem* topItem = registersTreeWidget->topLevelItem(i); topItem->setHidden(false); } + return; } @@ -446,13 +469,13 @@ void SeerRegisterValuesBrowserWidget::handleShowHideRegisters (const QStringList topItem->setHidden(true); } - for (int i=0; i matches = registersTreeWidget->findItems(registerName, Qt::MatchExactly, 1); @@ -462,28 +485,120 @@ void SeerRegisterValuesBrowserWidget::handleShowHideRegisters (const QStringList } } +void SeerRegisterValuesBrowserWidget::handleProfileChanged (int index) { + + // Get the profile. + QString profileName = registerProfileComboBox->itemText(index); + + // Build a list of registers. + QStringList registerNames; + QVector registerEnabled; + + bool f = readProfileSettings(profileName, registerNames, registerEnabled); + + if (f == false) { + return; + } + + // Use them. + _registerNames = registerNames; + _registerEnabled = registerEnabled; + + handleShowHideRegisters(); + writeSettings(); +} + void SeerRegisterValuesBrowserWidget::writeSettings () { QSettings settings; - settings.beginGroup("registerswindow"); { - settings.setValue("sortcolumn", registersTreeWidget->header()->sortIndicatorSection()); - settings.setValue("sortorder", registersTreeWidget->header()->sortIndicatorOrder()); - }settings.endGroup(); + QStringList registerprofiles; + + for (int i=0; icount(); i++) { + if (registerProfileComboBox->itemText(i) == "allregisters") { + continue; + } + registerprofiles.push_back(registerProfileComboBox->itemText(i)); + } + + settings.beginGroup("registerwindow"); { + settings.setValue("sortcolumn", registersTreeWidget->header()->sortIndicatorSection()); + settings.setValue("sortorder", registersTreeWidget->header()->sortIndicatorOrder()); + settings.setValue("registerprofile", registerProfileComboBox->currentText()); + settings.setValue("registerprofiles", registerprofiles); + } settings.endGroup(); } void SeerRegisterValuesBrowserWidget::readSettings () { QSettings settings; - settings.beginGroup("registerswindow"); { + settings.beginGroup("registerwindow"); { int column = settings.value("sortcolumn", 0).toInt(); int order = settings.value("sortorder", Qt::AscendingOrder).toInt(); registersTreeWidget->header()->setSortIndicator(column, (Qt::SortOrder)order); + QString registerProfileName = settings.value("registerprofile").toString(); + QStringList registerProfiles = settings.value("registerprofiles").toStringList(); + + registerProfileComboBox->addItems(registerProfiles); + registerProfileComboBox->setCurrentText(registerProfileName); + + } settings.endGroup(); +} + +void SeerRegisterValuesBrowserWidget::writeProfileSettings (const QString& profileName, const QStringList& registerNames, const QVector& registerEnabled) { + + QSettings settings; + QStringList registerEnabledFlags; + + for (int i=0; i& registerEnabled) { + + if (profileName == "" || profileName == "allregisters") { + + registerNames.resize(0); + registerEnabled.resize(0); + + return true; + } + + QSettings settings; + + settings.beginGroup("registerprofile_" + profileName); { + + QVariant registerNamesVariant = settings.value("registernames"); + QVariant registerEnabledVariant = settings.value("registerenabled"); + QStringList registerEnabledFlags; + + // Not found? Return with error. + if (registerNamesVariant == QVariant() || registerEnabledVariant == QVariant()) { + return false; + } + + // Okay, we found it. Populate the containters. + registerNames = registerNamesVariant.toStringList(); + registerEnabledFlags = registerEnabledVariant.toStringList(); + + registerEnabled.resize(0); + for (int i=0; i #include #include +#include +#include #include class SeerRegisterValuesBrowserWidget : public QWidget, protected Ui::SeerRegisterValuesBrowserWidgetForm { @@ -30,7 +32,8 @@ class SeerRegisterValuesBrowserWidget : public QWidget, protected Ui::SeerRegist void handleColumnSelected (int logicalIndex); void handleNewProfile (); void handleDeleteProfile (); - void handleShowHideRegisters (const QStringList& registerNames, QVector& registerEnabled); + void handleShowHideRegisters (); + void handleProfileChanged (int index); signals: void refreshRegisterNames (); @@ -41,9 +44,13 @@ class SeerRegisterValuesBrowserWidget : public QWidget, protected Ui::SeerRegist void showEvent (QShowEvent* event); void readSettings (); void writeSettings (); + bool readProfileSettings (const QString& profileName, QStringList& registerNames, QVector& registerEnabled); + void writeProfileSettings (const QString& profileName, const QStringList& registerNames, const QVector& registerEnabled); private: bool _needsRegisterNames; + QStringList _registerNames; + QVector _registerEnabled; QAction* _newProfileAction; QAction* _deleteProfileAction; diff --git a/src/SeerRegisterValuesBrowserWidget.ui b/src/SeerRegisterValuesBrowserWidget.ui index 5beebeb3..9e2d71f9 100644 --- a/src/SeerRegisterValuesBrowserWidget.ui +++ b/src/SeerRegisterValuesBrowserWidget.ui @@ -6,7 +6,7 @@ 0 0 - 794 + 733 528
@@ -47,13 +47,16 @@ - 0 + 50 0 Register Profile Selection. + + QComboBox::AdjustToContentsOnFirstShow +
From 2edcc0092c30757332dc1eb4d3bf955eea6af0ba Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Sun, 24 Dec 2023 12:07:58 -0600 Subject: [PATCH 3/5] More register work. --- src/SeerRegisterProfileDialog.cpp | 2 +- src/SeerRegisterValuesBrowserWidget.cpp | 53 ++++++++++++++++++++++++- src/SeerRegisterValuesBrowserWidget.h | 45 +++++++++++---------- 3 files changed, 76 insertions(+), 24 deletions(-) diff --git a/src/SeerRegisterProfileDialog.cpp b/src/SeerRegisterProfileDialog.cpp index 45320b35..7100a174 100644 --- a/src/SeerRegisterProfileDialog.cpp +++ b/src/SeerRegisterProfileDialog.cpp @@ -19,7 +19,7 @@ SeerRegisterProfileDialog::SeerRegisterProfileDialog (QWidget* parent) : QDialog registersTreeWidget->resizeColumnToContents(2); // checkbox registersTreeWidget->clear(); - QRegularExpressionValidator* validator = new QRegularExpressionValidator(QRegularExpression("[a-z0-9]+")); + QRegularExpressionValidator* validator = new QRegularExpressionValidator(QRegularExpression("[a-z0-9\\.\\-\\_]+")); profileNameLineEdit->setValidator(validator); diff --git a/src/SeerRegisterValuesBrowserWidget.cpp b/src/SeerRegisterValuesBrowserWidget.cpp index 15c38904..67237924 100644 --- a/src/SeerRegisterValuesBrowserWidget.cpp +++ b/src/SeerRegisterValuesBrowserWidget.cpp @@ -61,7 +61,8 @@ SeerRegisterValuesBrowserWidget::SeerRegisterValuesBrowserWidget (QWidget* paren QMenu* menu = new QMenu(); _newProfileAction = menu->addAction("New profile"); - _deleteProfileAction = menu->addAction("Delete profile"); + _modifyProfileAction = menu->addAction("Modify current profile"); + _deleteProfileAction = menu->addAction("Delete current profile"); preferencesToolButton->setMenu(menu); preferencesToolButton->setPopupMode(QToolButton::InstantPopup); @@ -73,6 +74,7 @@ SeerRegisterValuesBrowserWidget::SeerRegisterValuesBrowserWidget (QWidget* paren QObject::connect(registerFormatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerRegisterValuesBrowserWidget::handleFormatChanged); QObject::connect(registersTreeWidget->header(), &QHeaderView::sectionClicked, this, &SeerRegisterValuesBrowserWidget::handleColumnSelected); QObject::connect(_newProfileAction, &QAction::triggered, this, &SeerRegisterValuesBrowserWidget::handleNewProfile); + QObject::connect(_modifyProfileAction, &QAction::triggered, this, &SeerRegisterValuesBrowserWidget::handleModifyProfile); QObject::connect(_deleteProfileAction, &QAction::triggered, this, &SeerRegisterValuesBrowserWidget::handleDeleteProfile); QObject::connect(registerProfileComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerRegisterValuesBrowserWidget::handleProfileChanged); @@ -443,9 +445,47 @@ void SeerRegisterValuesBrowserWidget::handleNewProfile () { } } +void SeerRegisterValuesBrowserWidget::handleModifyProfile () { + + QMessageBox::warning(this, "Seer", "There are no profiles to modify.", QMessageBox::Ok); +} + void SeerRegisterValuesBrowserWidget::handleDeleteProfile () { - QMessageBox::warning(this, "Seer", "There are no profiles to delete.", QMessageBox::Ok); + int index = registerProfileComboBox->currentIndex(); + + if (index < 0) { + return; + } + + QString profileName = registerProfileComboBox->itemText(index); + + if (profileName == "") { + return; + } + + if (profileName == "allregisters") { + QMessageBox::warning(this, "Seer", "The profile 'allregisters' is reserved.\n\nIt can't be deleted.", QMessageBox::Ok); + return; + } + + // Delete the profile from the settings. + deleteProfileSettings(profileName); + + // Delete the profile from the list of profiles. + registerProfileComboBox->removeItem(index); + + // Write the current settings. + writeSettings(); + + // Switch to the next profile in the list of profiles. + index = registerProfileComboBox->currentIndex(); + + if (index < 0) { + return; + } + + handleProfileChanged (index); } void SeerRegisterValuesBrowserWidget::handleShowHideRegisters () { @@ -601,6 +641,15 @@ bool SeerRegisterValuesBrowserWidget::readProfileSettings (const QString& profil return true; } +void SeerRegisterValuesBrowserWidget::deleteProfileSettings (const QString& profileName) { + + QSettings settings; + + settings.beginGroup("registerprofile_" + profileName); { + settings.remove(""); //removes the group, and all it keys + } settings.endGroup(); +} + void SeerRegisterValuesBrowserWidget::showEvent (QShowEvent* event) { QWidget::showEvent(event); diff --git a/src/SeerRegisterValuesBrowserWidget.h b/src/SeerRegisterValuesBrowserWidget.h index a97b2f49..0680ab76 100644 --- a/src/SeerRegisterValuesBrowserWidget.h +++ b/src/SeerRegisterValuesBrowserWidget.h @@ -17,41 +17,44 @@ class SeerRegisterValuesBrowserWidget : public QWidget, protected Ui::SeerRegist ~SeerRegisterValuesBrowserWidget (); public: - void setRegisterFormat (QString fmt); + void setRegisterFormat (QString fmt); public slots: - void handleText (const QString& text); - void handleStoppingPointReached (); - void refresh (); + void handleText (const QString& text); + void handleStoppingPointReached (); + void refresh (); protected slots: - void handleItemEntered (QTreeWidgetItem* item, int column); - void handleContextMenu (const QPoint& pos); - void handleIndexEditingFinished (const QModelIndex& index); - void handleFormatChanged (int index); - void handleColumnSelected (int logicalIndex); - void handleNewProfile (); - void handleDeleteProfile (); - void handleShowHideRegisters (); - void handleProfileChanged (int index); + void handleItemEntered (QTreeWidgetItem* item, int column); + void handleContextMenu (const QPoint& pos); + void handleIndexEditingFinished (const QModelIndex& index); + void handleFormatChanged (int index); + void handleColumnSelected (int logicalIndex); + void handleNewProfile (); + void handleModifyProfile (); + void handleDeleteProfile (); + void handleShowHideRegisters (); + void handleProfileChanged (int index); signals: - void refreshRegisterNames (); - void refreshRegisterValues (QString fmt); - void setRegisterValue (QString fmt, QString name, QString value); + void refreshRegisterNames (); + void refreshRegisterValues (QString fmt); + void setRegisterValue (QString fmt, QString name, QString value); protected: - void showEvent (QShowEvent* event); - void readSettings (); - void writeSettings (); - bool readProfileSettings (const QString& profileName, QStringList& registerNames, QVector& registerEnabled); - void writeProfileSettings (const QString& profileName, const QStringList& registerNames, const QVector& registerEnabled); + void showEvent (QShowEvent* event); + void readSettings (); + void writeSettings (); + bool readProfileSettings (const QString& profileName, QStringList& registerNames, QVector& registerEnabled); + void writeProfileSettings (const QString& profileName, const QStringList& registerNames, const QVector& registerEnabled); + void deleteProfileSettings (const QString& profileName); private: bool _needsRegisterNames; QStringList _registerNames; QVector _registerEnabled; QAction* _newProfileAction; + QAction* _modifyProfileAction; QAction* _deleteProfileAction; }; From 0f3361753e88ca7c5f451efd09c7c2328e0a6eb2 Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Mon, 25 Dec 2023 12:34:17 -0600 Subject: [PATCH 4/5] More register profile changes. --- src/SeerRegisterValuesBrowserWidget.cpp | 52 ++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/SeerRegisterValuesBrowserWidget.cpp b/src/SeerRegisterValuesBrowserWidget.cpp index 67237924..0a66be44 100644 --- a/src/SeerRegisterValuesBrowserWidget.cpp +++ b/src/SeerRegisterValuesBrowserWidget.cpp @@ -447,7 +447,51 @@ void SeerRegisterValuesBrowserWidget::handleNewProfile () { void SeerRegisterValuesBrowserWidget::handleModifyProfile () { - QMessageBox::warning(this, "Seer", "There are no profiles to modify.", QMessageBox::Ok); + QString profileName = registerProfileComboBox->currentText(); + + if (profileName == "allregisters") { + QMessageBox::warning(this, "Seer", "The profile 'allregisters' is reserved.\n\nIt can't be modified.", QMessageBox::Ok); + return; + } + + // Build a list of registers. + QStringList registerNames = _registerNames; + QVector registerEnabled = _registerEnabled; + + // Bring up the register profile dialog. + SeerRegisterProfileDialog dlg(this); + + dlg.setProfileName(profileName); + dlg.setRegisters(registerNames, registerEnabled); + + if (dlg.exec()) { + + // Get the (potenially new) profile name. + QString newProfileName = dlg.profileName(); + + if (newProfileName == "") { + return; + } + + registerNames = dlg.registerNames(); + registerEnabled = dlg.registerEnabled(); + + // If it's a new name, add it to the list and switch to it. + if (newProfileName != profileName) { + registerProfileComboBox->addItem(newProfileName); + registerProfileComboBox->setCurrentText(newProfileName); + } + + // Write out the setting changes. + writeProfileSettings(newProfileName, registerNames, registerEnabled); + writeSettings(); + + // Use them. + _registerNames = registerNames; + _registerEnabled = registerEnabled; + + handleShowHideRegisters(); + } } void SeerRegisterValuesBrowserWidget::handleDeleteProfile () { @@ -469,6 +513,12 @@ void SeerRegisterValuesBrowserWidget::handleDeleteProfile () { return; } + QMessageBox::StandardButton ans = QMessageBox::question(this, "Seer", "Delete profile '" + profileName + "'?"); + + if (ans != QMessageBox::Yes) { + return; + } + // Delete the profile from the settings. deleteProfileSettings(profileName); From 8ba8d65fe6c4d12b7c0ab57cdc641fcf09cc86d6 Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Mon, 25 Dec 2023 13:51:25 -0600 Subject: [PATCH 5/5] Final changes for register profiles. --- CHANGELOG.md | 1 + src/SeerMemoryVisualizerWidget.cpp | 3 +- src/SeerRegisterProfileDialog.cpp | 144 ++++++++++++++++++ src/SeerRegisterProfileDialog.h | 2 + .../help/VariableRegisterInfoBrowser.md | 6 + 5 files changed, 155 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f866e97a..b5deaf00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Fixed long tooltips text by restricting them to 100 characters. (#189) The text in the various viewing dialogs is still the full length. The 100 limit probably needs to be configurable. +* Added register profiles to show only interesting/relevant registers. ## [2.3] - 2023-11-19 * In the margins of the source windows, allow CTRL+DoubleClick to do a quick RunToLine or RunToAddress. diff --git a/src/SeerMemoryVisualizerWidget.cpp b/src/SeerMemoryVisualizerWidget.cpp index 9d4f9b35..48f3f944 100644 --- a/src/SeerMemoryVisualizerWidget.cpp +++ b/src/SeerMemoryVisualizerWidget.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include SeerMemoryVisualizerWidget::SeerMemoryVisualizerWidget (QWidget* parent) : QWidget(parent) { @@ -376,7 +377,7 @@ void SeerMemoryVisualizerWidget::handlePrintButton () { void SeerMemoryVisualizerWidget::handleSaveButton () { - QFileDialog dialog(this, "Seer visualizer file", "./", "Logs (*.log);;Text files (*.txt);;All files (*.*)"); + QFileDialog dialog(this, "Seer Visualizer File", "./", "Logs (*.log);;Text files (*.txt);;All files (*.*)"); dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setFileMode(QFileDialog::AnyFile); dialog.setDefaultSuffix("log"); diff --git a/src/SeerRegisterProfileDialog.cpp b/src/SeerRegisterProfileDialog.cpp index 7100a174..8d011a38 100644 --- a/src/SeerRegisterProfileDialog.cpp +++ b/src/SeerRegisterProfileDialog.cpp @@ -1,6 +1,7 @@ #include "SeerRegisterProfileDialog.h" #include "SeerRegisterTreeWidgetItem.h" #include +#include #include #include #include @@ -29,6 +30,8 @@ SeerRegisterProfileDialog::SeerRegisterProfileDialog (QWidget* parent) : QDialog // Connect things. QObject::connect(enablePushButton, &QPushButton::clicked, this, &SeerRegisterProfileDialog::handleEnableSelected); QObject::connect(disablePushButton, &QPushButton::clicked, this, &SeerRegisterProfileDialog::handleDisableSelected); + QObject::connect(importPushButton, &QPushButton::clicked, this, &SeerRegisterProfileDialog::handleImportFile); + QObject::connect(exportPushButton, &QPushButton::clicked, this, &SeerRegisterProfileDialog::handleExportFile); // Restore window settings. readSettings(); @@ -136,6 +139,147 @@ void SeerRegisterProfileDialog::handleDisableSelected () { } } +void SeerRegisterProfileDialog::handleImportFile () { + + // + // Get the name of the file to import. + // + QFileDialog dialog(this, "Seer Register Profile File", "./", "Text files (*.txt);;All files (*.*)"); + dialog.setAcceptMode(QFileDialog::AcceptOpen); + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setDefaultSuffix("txt"); + dialog.selectFile("registerprofile.txt"); + + if (dialog.exec() != QDialog::Accepted) { + return; + } + + QStringList files = dialog.selectedFiles(); + + if (files.size() == 0) { + return; + } + + if (files.size() > 1) { + QMessageBox::critical(this, tr("Error"), tr("Select only 1 file.")); + return; + } + + // + // Open the file and read from it. + // A simple format of: + // + // + QFile file(files[0]); + + if (file.open(QIODevice::ReadOnly)) { + + QStringList registerNames; + QVector registerEnabled; + QTextStream stream(&file); + + while (stream.atEnd() == false) { + + QString line = stream.readLine(); + + QStringList words = line.split(QRegularExpression("\\s+")); + + // Ignore empty lines. + if (words.count() == 0) { + continue; + } + + // Ignore null lines. + if (words.count() == 1 && words[0] == "") { + continue; + } + + // There should be only two words on each line. + if (words.count() != 2) { + QMessageBox::critical(this, tr("Error"), tr("Can't load register profile file.\nEncountered a line not the form of:\n\n ")); + return; + } + + // The second word must be 'enabled' or 'disabled'. + if (words[1] != "enabled" && words[1] != "disabled") { + QMessageBox::critical(this, tr("Error"), tr("Can't load register profile file.\nEncountered a line not the form of:\n\n ")); + return; + } + + registerNames.push_back(words[0]); + registerEnabled.push_back(words[1] == "enabled" ? true : false); + } + + // Populate the list with the imported values. + setRegisters (registerNames, registerEnabled); + + QMessageBox::information(this, "Seer", "Loaded."); + + }else{ + + QMessageBox::critical(this, tr("Error"), tr("Can't open register profile file.")); + return; + } + +} + +void SeerRegisterProfileDialog::handleExportFile () { + + // + // Get the name of the file to export. + // + QFileDialog dialog(this, "Seer Register Profile File", "./", "Text files (*.txt);;All files (*.*)"); + dialog.setAcceptMode(QFileDialog::AcceptSave); + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setDefaultSuffix("txt"); + dialog.selectFile("registerprofile.txt"); + + if (dialog.exec() != QDialog::Accepted) { + return; + } + + QStringList files = dialog.selectedFiles(); + + if (files.size() == 0) { + return; + } + + if (files.size() > 1) { + QMessageBox::critical(this, tr("Error"), tr("Select only 1 file.")); + return; + } + + // + // Create the file and write to it. + // A simple format of: + // + // + QFile file(files[0]); + + if (file.open(QIODevice::ReadWrite)) { + + QTextStream stream(&file); + + QStringList names = registerNames(); + QVector enabled = registerEnabled(); + + for (int i=0; i