From caec10a243cb14260b4cb40956871ec7db8a6bc0 Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Tue, 6 Jan 2026 08:57:08 -0600 Subject: [PATCH] WIP --- src/CMakeLists.txt | 2 + src/SeerCommandLogsWidget.cpp | 420 ++++++++++++++++++++++++++++++++++ src/SeerCommandLogsWidget.h | 77 +++++++ src/SeerCommandLogsWidget.ui | 168 ++++++++++++++ src/SeerGdbWidget.cpp | 1 - src/SeerGdbWidget.h | 1 - 6 files changed, 667 insertions(+), 2 deletions(-) create mode 100644 src/SeerCommandLogsWidget.cpp create mode 100644 src/SeerCommandLogsWidget.h create mode 100644 src/SeerCommandLogsWidget.ui diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b0babe7..d09f0f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,6 +79,7 @@ set(HEADER_FILES SeerPrintpointCreateDialog.h SeerPrintpointsBrowserWidget.h SeerCheckpointsBrowserWidget.h + SeerCommandLogsWidget.h SeerSeerLogWidget.h SeerConsoleWidget.h SeerConfigDialog.h @@ -189,6 +190,7 @@ set(SOURCE_FILES SeerPrintpointCreateDialog.cpp SeerPrintpointsBrowserWidget.cpp SeerCheckpointsBrowserWidget.cpp + SeerCommandLogsWidget.cpp SeerSeerLogWidget.cpp SeerConsoleWidget.cpp SeerConfigDialog.cpp diff --git a/src/SeerCommandLogsWidget.cpp b/src/SeerCommandLogsWidget.cpp new file mode 100644 index 0000000..1868608 --- /dev/null +++ b/src/SeerCommandLogsWidget.cpp @@ -0,0 +1,420 @@ +// SPDX-FileCopyrightText: 2026 Ernie Pasveer +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "SeerCommandLogsWidget.h" +#include "SeerLogWidget.h" +#include "SeerMemoryVisualizerWidget.h" +#include "SeerArrayVisualizerWidget.h" +#include "SeerMatrixVisualizerWidget.h" +#include "SeerStructVisualizerWidget.h" +#include "SeerVarVisualizerWidget.h" +#include "SeerImageVisualizerWidget.h" +#include "SeerHelpPageDialog.h" +#include "SeerUtl.h" +#include "QHContainerWidget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SeerCommandLogsWidget::SeerCommandLogsWidget (QWidget* parent) : QWidget(parent) { + + _consoleWidget = 0; + _consoleIndex = -1; + _consoleScrollLines = 1000; + _rememberManualCommandCount = 10; + + setupUi(this); + + // Setup the widgets + QFont font; + font.setFamily("monospace [Consolas]"); + font.setFixedPitch(true); + font.setStyleHint(QFont::TypeWriter); + + _messagesBrowserWidget = new SeerMessagesBrowserWidget(this); + _breakpointsBrowserWidget = new SeerBreakpointsBrowserWidget(this); + _watchpointsBrowserWidget = new SeerWatchpointsBrowserWidget(this); + _catchpointsBrowserWidget = new SeerCatchpointsBrowserWidget(this); + _printpointsBrowserWidget = new SeerPrintpointsBrowserWidget(this); + _checkpointsBrowserWidget = new SeerCheckpointsBrowserWidget(this); + + _gdbOutputLog = new SeerGdbLogWidget(this); + _seerOutputLog = new SeerSeerLogWidget(this); + _gdbOutputLog->setPlaceholderText("[gdb output]"); + _seerOutputLog->setPlaceholderText("[seer output]"); + + logsTabWidget->clear(); + logsTabWidget->addTab(_messagesBrowserWidget, "Messages"); + logsTabWidget->addTab(_breakpointsBrowserWidget, "Breakpoints"); + logsTabWidget->addTab(_watchpointsBrowserWidget, "Watchpoints"); + logsTabWidget->addTab(_catchpointsBrowserWidget, "Catchpoints"); + logsTabWidget->addTab(_printpointsBrowserWidget, "Printpoints"); + logsTabWidget->addTab(_checkpointsBrowserWidget, "Checkpoints"); + logsTabWidget->addTab(_gdbOutputLog, "GDB output"); + logsTabWidget->addTab(_seerOutputLog, "Seer output"); + logsTabWidget->setCurrentIndex(0); + + // Create the console tab. + // Each RUN method will create and connect to the console's terminal. + createConsole(); + + // Create editor options bar. + QToolButton* breakpointsLoadToolButton = new QToolButton(logsTabWidget); + breakpointsLoadToolButton->setIcon(QIcon(":/seer/resources/RelaxLightIcons/document-open.svg")); + breakpointsLoadToolButton->setToolTip("Load previously saved breakpoints."); + + QToolButton* breakpointsSaveToolButton = new QToolButton(logsTabWidget); + breakpointsSaveToolButton->setIcon(QIcon(":/seer/resources/RelaxLightIcons/document-save-as.svg")); + breakpointsSaveToolButton->setToolTip("Save breakpoints to a file."); + + QToolButton* helpToolButton = new QToolButton(logsTabWidget); + helpToolButton->setIcon(QIcon(":/seer/resources/RelaxLightIcons/help-about.svg")); + helpToolButton->setToolTip("Help on Breakpoint/Gdb/Seer information."); + + QHContainerWidget* hcontainer = new QHContainerWidget(this); + hcontainer->setSpacing(3); + hcontainer->addWidget(breakpointsLoadToolButton); + hcontainer->addWidget(breakpointsSaveToolButton); + hcontainer->addWidget(helpToolButton); + + logsTabWidget->setCornerWidget(hcontainer, Qt::TopRightCorner); + + // Set manual command settings. + manualCommandComboBox->setFont(font); + manualCommandComboBox->setEditable(true); + manualCommandComboBox->lineEdit()->setPlaceholderText("Manually enter a gdb/mi command..."); + manualCommandComboBox->lineEdit()->setToolTip("Manually enter a gdb/mi command."); + manualCommandComboBox->lineEdit()->setClearButtonEnabled(true); + + // Connect things. + QObject::connect(logsTabWidget->tabBar(), &QTabBar::tabMoved, this, &SeerCommandLogsWidget::handleLogsTabMoved); + QObject::connect(logsTabWidget->tabBar(), &QTabBar::currentChanged, this, &SeerCommandLogsWidget::handleLogsTabChanged); + + // Restore tab ordering. + readSettings(); +} + +SeerCommandLogsWidget::~SeerCommandLogsWidget () { + + deleteConsole(); +} + +QLineEdit* SeerCommandLogsWidget::commandLineEdit () { + + return manualCommandComboBox->lineEdit(); +} + +SeerMessagesBrowserWidget* SeerCommandLogsWidget::messagesBrowser () { + + return _messagesBrowserWidget; +} + +SeerBreakpointsBrowserWidget* SeerCommandLogsWidget::breakpointsBrowser () { + + return _breakpointsBrowserWidget; +} + +SeerWatchpointsBrowserWidget* SeerCommandLogsWidget::watchpointsBrowser () { + + return _watchpointsBrowserWidget; +} + +SeerCatchpointsBrowserWidget* SeerCommandLogsWidget::catchpointsBrowser () { + + return _catchpointsBrowserWidget; +} + +SeerPrintpointsBrowserWidget* SeerCommandLogsWidget::printpointsBrowser () { + + return _printpointsBrowserWidget; +} + +SeerCheckpointsBrowserWidget* SeerCommandLogsWidget::checkpointsBrowser () { + + return _checkpointsBrowserWidget; +} + +SeerGdbLogWidget* SeerCommandLogsWidget::gdbOutputLog () { + + return _gdbOutputLog; +} + +SeerSeerLogWidget* SeerCommandLogsWidget::seerOutputLog () { + + return _seerOutputLog; +} + +SeerConsoleWidget* SeerCommandLogsWidget::console () { + + return _consoleWidget; +} + +void SeerCommandLogsWidget::createConsole () { + + if (_consoleWidget == 0) { + + _consoleWidget = new SeerConsoleWidget(0); + + // Connect window title changes. + // XXX QObject::connect(this, &SeerGdbWidget::changeWindowTitle, _consoleWidget, &SeerConsoleWidget::handleChangeWindowTitle); + + // The console needs to know when it's detached or reattached. + QObject::connect(logsTabWidget, qOverload(&QDetachTabWidget::tabDetached), _consoleWidget, &SeerConsoleWidget::handleTabDetached); + QObject::connect(logsTabWidget, qOverload(&QDetachTabWidget::tabReattached), _consoleWidget, &SeerConsoleWidget::handleTabReattached); + + _consoleIndex = logsTabWidget->addTab(_consoleWidget, "Console output"); + + QObject::connect(_consoleWidget, &SeerConsoleWidget::newTextAdded, this, &SeerCommandLogsWidget::handleConsoleNewTextAdded); + QObject::connect(_consoleWidget, &SeerConsoleWidget::newTextViewed, this, &SeerCommandLogsWidget::handleConsoleNewTextViewed); + + setConsoleMode(consoleMode()); + setConsoleScrollLines(consoleScrollLines()); + } +} + +void SeerCommandLogsWidget::deleteConsole () { + + if (_consoleWidget) { + + if (_consoleIndex >= 0) { + logsTabWidget->removeTab(_consoleIndex); + } + + delete _consoleWidget; + _consoleWidget = 0; + _consoleIndex = -1; + } +} + +void SeerCommandLogsWidget::reattachConsole () { + + if (_consoleIndex < 0) { + return; + } + + if (_consoleWidget == nullptr) { + return; + } + + _consoleMode = "attached"; + + logsTabWidget->reattachTab(_consoleIndex); +} + +void SeerCommandLogsWidget::setConsoleMode (const QString& mode) { + + _consoleMode = mode; + + handleConsoleModeChanged(); +} + +QString SeerCommandLogsWidget::consoleMode () const { + + return _consoleMode; +} + +void SeerCommandLogsWidget::setConsoleScrollLines (int count) { + + _consoleScrollLines = count; + + if (_consoleWidget) { + _consoleWidget->setScrollLines(_consoleScrollLines); + } +} + +int SeerCommandLogsWidget::consoleScrollLines () const { + + return _consoleScrollLines; +} + +void SeerCommandLogsWidget::handleLogsTabMoved (int to, int from) { + + Q_UNUSED(from); + Q_UNUSED(to); + + // Keep track of console tab if it moved. + if (_consoleIndex == from) { + _consoleIndex = to; + } + + // Don't handle anything here if Seer is exiting. + /* XXX + if (isQuitting()) { + return; + } + */ + + writeSettings(); +} + +void SeerCommandLogsWidget::handleLogsTabChanged (int index) { + + Q_UNUSED(index); + + // Don't handle anything here if Seer is exiting. + /* XXX + if (isQuitting()) { + return; + } + */ + + writeSettings(); +} + +void SeerCommandLogsWidget::handleRaiseMessageTab () { + + int idx = logsTabWidget->indexOf(_messagesBrowserWidget); + + if (idx < 0) { + return; + } + + logsTabWidget->setCurrentIndex(idx); +} + +void SeerCommandLogsWidget::handleConsoleModeChanged () { + + if (_consoleIndex < 0) { + return; + } + + if (_consoleWidget == nullptr) { + return; + } + + if (_consoleMode == "detached") { + logsTabWidget->detachTab(_consoleIndex, false); + _consoleWidget->raise(); + _consoleWidget->resetSize(); + }else if (_consoleMode == "detachedminimized") { + logsTabWidget->detachTab(_consoleIndex, true); + _consoleWidget->resetSize(); + }else if (_consoleMode == "attached") { + logsTabWidget->reattachTab(_consoleIndex); + }else{ + logsTabWidget->reattachTab(_consoleIndex); + } +} + +void SeerCommandLogsWidget::handleConsoleNewTextAdded () { + + if (_consoleIndex >= 0) { + logsTabWidget->setTabIcon(_consoleIndex, QIcon(":/seer/resources/RelaxLightIcons/data-information.svg")); + } +} + +void SeerCommandLogsWidget::handleConsoleNewTextViewed () { + + if (_consoleIndex >= 0) { + logsTabWidget->setTabIcon(_consoleIndex, QIcon()); + } +} + +void SeerCommandLogsWidget::writeSettings () { + + // Write tab order to settings. + QStringList tabs; + + for (int i=0; itabBar()->count(); i++) { + tabs.append(logsTabWidget->tabBar()->tabText(i)); + } + + QString current = logsTabWidget->tabBar()->tabText(logsTabWidget->tabBar()->currentIndex()); + + //qDebug() << "Tabs" << tabs; + //qDebug() << "Current" << current; + + QSettings settings; + + settings.beginGroup("logsmanagerwindow"); { + settings.setValue("taborder", tabs.join(',')); + settings.setValue("tabcurrent", current); + } settings.endGroup(); +} + +void SeerCommandLogsWidget::readSettings () { + + // Can't move things? + if (logsTabWidget->tabBar()->isMovable() == false) { + return; + } + + // Read tab order from settings. + QSettings settings; + QStringList tabs; + QString current; + + settings.beginGroup("logsmanagerwindow"); { + tabs = settings.value("taborder").toString().split(','); + current = settings.value("tabcurrent").toString(); + } settings.endGroup(); + + //qDebug() << "Tabs" << tabs; + //qDebug() << "Current" << current; + + // Move tabs to the requested order. + for (int i=0; itabBar()->count(); j++) { + if (logsTabWidget->tabBar()->tabText(j) == tab) { + tb = j; + break; + } + } + + if (tb != -1) { + logsTabWidget->tabBar()->moveTab(tb, i); + } + } + + // Find the console tab index. + _consoleIndex = -1; + for (int i=0; itabBar()->count(); i++) { + if (logsTabWidget->tabBar()->tabText(i) == "Console output") { + _consoleIndex = i; + break; + } + } + + if (_consoleIndex < 0) { + qDebug() << "The console tab index is not in the settings."; + } + + // Make a tab current. + if (current != "") { + for (int i=0; itabBar()->count(); i++) { + if (logsTabWidget->tabBar()->tabText(i) == current) { + logsTabWidget->setCurrentIndex(i); + break; + } + } + }else{ + logsTabWidget->setCurrentIndex(0); + } +} + diff --git a/src/SeerCommandLogsWidget.h b/src/SeerCommandLogsWidget.h new file mode 100644 index 0000000..9ac2e28 --- /dev/null +++ b/src/SeerCommandLogsWidget.h @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: 2026 Ernie Pasveer +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "SeerConsoleWidget.h" +#include "SeerGdbLogWidget.h" +#include "SeerSeerLogWidget.h" +#include "SeerMessagesBrowserWidget.h" +#include "SeerBreakpointsBrowserWidget.h" +#include "SeerWatchpointsBrowserWidget.h" +#include "SeerCatchpointsBrowserWidget.h" +#include "SeerPrintpointsBrowserWidget.h" +#include "SeerCheckpointsBrowserWidget.h" +#include + +#include "ui_SeerCommandLogsWidget.h" + +class SeerCommandLogsWidget : public QWidget, protected Ui::SeerCommandLogsWidgetForm { + + Q_OBJECT + + public: + explicit SeerCommandLogsWidget (QWidget* parent = 0); + ~SeerCommandLogsWidget (); + + QLineEdit* commandLineEdit (); + SeerMessagesBrowserWidget* messagesBrowser (); + SeerBreakpointsBrowserWidget* breakpointsBrowser (); + SeerWatchpointsBrowserWidget* watchpointsBrowser (); + SeerCatchpointsBrowserWidget* catchpointsBrowser (); + SeerPrintpointsBrowserWidget* printpointsBrowser (); + SeerCheckpointsBrowserWidget* checkpointsBrowser (); + SeerGdbLogWidget* gdbOutputLog (); + SeerSeerLogWidget* seerOutputLog (); + + void createConsole (); + void deleteConsole (); + void reattachConsole (); + SeerConsoleWidget* console (); + void setConsoleMode (const QString& mode); + QString consoleMode () const; + void setConsoleScrollLines (int count); + int consoleScrollLines () const; + + public slots: + void handleLogsTabMoved (int to, int from); + void handleLogsTabChanged (int index); + void handleRaiseMessageTab (); + void handleConsoleModeChanged (); + void handleConsoleNewTextAdded (); + void handleConsoleNewTextViewed (); + + signals: + + protected: + void writeSettings (); + void readSettings (); + + private: + SeerConsoleWidget* _consoleWidget; + int _consoleIndex; + QString _consoleMode; + int _consoleScrollLines; + int _rememberManualCommandCount; + + SeerMessagesBrowserWidget* _messagesBrowserWidget; + SeerBreakpointsBrowserWidget* _breakpointsBrowserWidget; + SeerWatchpointsBrowserWidget* _watchpointsBrowserWidget; + SeerCatchpointsBrowserWidget* _catchpointsBrowserWidget; + SeerPrintpointsBrowserWidget* _printpointsBrowserWidget; + SeerCheckpointsBrowserWidget* _checkpointsBrowserWidget; + SeerGdbLogWidget* _gdbOutputLog; + SeerSeerLogWidget* _seerOutputLog; +}; + diff --git a/src/SeerCommandLogsWidget.ui b/src/SeerCommandLogsWidget.ui new file mode 100644 index 0000000..9ab2c2f --- /dev/null +++ b/src/SeerCommandLogsWidget.ui @@ -0,0 +1,168 @@ + + + SeerCommandLogsWidgetForm + + + + 0 + 0 + 975 + 384 + + + + Seer - Commands and Logs + + + + + + + + M1 macro. Hold down to edit. + + + M1 + + + + + + + M2 macro. Hold down to edit. + + + M2 + + + + + + + M3 macro. Hold down to edit. + + + M3 + + + + + + + M4 macro. Hold down to edit. + + + M4 + + + + + + + M5 macro. Hold down to edit. + + + M5 + + + + + + + M6 macro. Hold down to edit. + + + M6 + + + + + + + M7 macro. Hold down to edit. + + + M7 + + + + + + + M8 macro. Hold down to edit. + + + M8 + + + + + + + M9 macro. Hold down to edit. + + + M9 + + + + + + + M0 macro. Hold down to edit. + + + M0 + + + + + + + Qt::Horizontal + + + + 578 + 20 + + + + + + + + + + + + + false + + + + + + + 0 + + + + Tab 1 + + + + + + + + + QDetachTabWidget + QTabWidget +
QDetachTabWidget.h
+ 1 +
+
+ + +
diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index 90673bc..0631311 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -87,7 +87,6 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { _gdbRecordDirection = ""; _consoleScrollLines = 1000; _rememberManualCommandCount = 10; - _currentFrame = -1; setIsQuitting(false); setNewExecutableFlag(true); diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h index d7a0bef..50e0e84 100644 --- a/src/SeerGdbWidget.h +++ b/src/SeerGdbWidget.h @@ -465,7 +465,6 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { QStringList _executablePreGdbCommands; QStringList _executablePostGdbCommands; bool _newExecutableFlag; - int _currentFrame; SeerConsoleWidget* _consoleWidget; int _consoleIndex;