From 93b8719fac5773d53bc3ebaf028f2fc9231b40cf Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Thu, 5 Oct 2023 19:17:12 -0500 Subject: [PATCH] Move gdb messages into a tab in the breakpoints manager. --- src/CMakeLists.txt | 2 + src/SeerGdbWidget.cpp | 13 +++- src/SeerGdbWidget.h | 5 ++ src/SeerMainWindow.cpp | 35 ++++------ src/SeerMainWindow.h | 3 - src/SeerMainWindow.ui | 1 - src/SeerMessagesBrowserWidget.cpp | 108 ++++++++++++++++++++++++++++++ src/SeerMessagesBrowserWidget.h | 36 ++++++++++ src/SeerMessagesBrowserWidget.ui | 83 +++++++++++++++++++++++ 9 files changed, 259 insertions(+), 27 deletions(-) create mode 100644 src/SeerMessagesBrowserWidget.cpp create mode 100644 src/SeerMessagesBrowserWidget.h create mode 100644 src/SeerMessagesBrowserWidget.ui diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c051227..1b71a5b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,7 @@ set(HEADER_FILES GdbMonitor.h SeerArgumentsDialog.h SeerBreakpointCreateDialog.h + SeerMessagesBrowserWidget.h SeerBreakpointsBrowserWidget.h SeerCatchpointCreateDialog.h SeerCatchpointsBrowserWidget.h @@ -135,6 +136,7 @@ set(SOURCE_FILES GdbMonitor.cpp SeerArgumentsDialog.cpp SeerBreakpointCreateDialog.cpp + SeerMessagesBrowserWidget.cpp SeerBreakpointsBrowserWidget.cpp SeerCatchpointCreateDialog.cpp SeerCatchpointsBrowserWidget.cpp diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index d49a753..4f9a0b7 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -76,6 +76,7 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { font.setFixedPitch(true); font.setStyleHint(QFont::TypeWriter); + _messagesBrowserWidget = new SeerMessagesBrowserWidget(this); _breakpointsBrowserWidget = new SeerBreakpointsBrowserWidget(this); _watchpointsBrowserWidget = new SeerWatchpointsBrowserWidget(this); _catchpointsBrowserWidget = new SeerCatchpointsBrowserWidget(this); @@ -86,11 +87,12 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { _gdbOutputLog->setPlaceholderText("[gdb output]"); _seerOutputLog->setPlaceholderText("[seer output]"); + logsTabWidget->addTab(_messagesBrowserWidget, "Messages"); logsTabWidget->addTab(_breakpointsBrowserWidget, "Breakpoints"); logsTabWidget->addTab(_watchpointsBrowserWidget, "Watchpoints"); logsTabWidget->addTab(_catchpointsBrowserWidget, "Catchpoints"); logsTabWidget->addTab(_printpointsBrowserWidget, "Printpoints"); - logsTabWidget->addTab(_gdbOutputLog, "GDB output"); + logsTabWidget->addTab(_gdbOutputLog, "GDB output"); logsTabWidget->addTab(_seerOutputLog, "Seer output"); logsTabWidget->setCurrentIndex(0); @@ -680,6 +682,15 @@ const SeerEditorManagerWidget* SeerGdbWidget::editorManager () const { return editorManagerWidget; } +void SeerGdbWidget::addMessage (const QString& message, QMessageBox::Icon messageType) { + + if (_messagesBrowserWidget == 0) { + return; + } + + _messagesBrowserWidget->addMessage(message, messageType); +} + void SeerGdbWidget::handleLogsTabMoved (int from, int to) { Q_UNUSED(from); diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h index 9265923..1ae7e81 100644 --- a/src/SeerGdbWidget.h +++ b/src/SeerGdbWidget.h @@ -4,6 +4,7 @@ #include "SeerEditorWidgetSource.h" #include "SeerGdbLogWidget.h" #include "SeerSeerLogWidget.h" +#include "SeerMessagesBrowserWidget.h" #include "SeerBreakpointsBrowserWidget.h" #include "SeerWatchpointsBrowserWidget.h" #include "SeerCatchpointsBrowserWidget.h" @@ -194,6 +195,9 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { SeerEditorManagerWidget* editorManager (); const SeerEditorManagerWidget* editorManager () const; + // Messages + void addMessage (const QString& message, QMessageBox::Icon messageType); + // Settings void writeSettings (); void readSettings (); @@ -403,6 +407,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { QString _consoleMode; int _consoleScrollLines; int _rememberManualCommandCount; + SeerMessagesBrowserWidget* _messagesBrowserWidget; SeerBreakpointsBrowserWidget* _breakpointsBrowserWidget; SeerWatchpointsBrowserWidget* _watchpointsBrowserWidget; SeerCatchpointsBrowserWidget* _catchpointsBrowserWidget; diff --git a/src/SeerMainWindow.cpp b/src/SeerMainWindow.cpp index eab1db5..75b63e7 100644 --- a/src/SeerMainWindow.cpp +++ b/src/SeerMainWindow.cpp @@ -108,9 +108,6 @@ SeerMainWindow::SeerMainWindow(QWidget* parent) : QMainWindow(parent) { setKeySettings(SeerKeySettings::populate()); setProjectFilename(""); - // Create the message list. - _executionMessages = new SeerMessagesDialog(this); - // // Set up signals/slots. // @@ -123,7 +120,6 @@ SeerMainWindow::SeerMainWindow(QWidget* parent) : QMainWindow(parent) { QObject::connect(actionViewBasicStructVisualizer, &QAction::triggered, this, &SeerMainWindow::handleViewStructVisualizer); QObject::connect(actionViewImageVisualizer, &QAction::triggered, this, &SeerMainWindow::handleViewImageVisualizer); QObject::connect(actionViewAssembly, &QAction::triggered, this, &SeerMainWindow::handleViewAssembly); - QObject::connect(actionViewExecutionMessages, &QAction::triggered, this, &SeerMainWindow::handleViewExecutionMessages); QObject::connect(actionConsoleNormal, &QAction::triggered, this, &SeerMainWindow::handleViewConsoleNormal); QObject::connect(actionConsoleHidden, &QAction::triggered, this, &SeerMainWindow::handleViewConsoleHidden); QObject::connect(actionConsoleMinimized, &QAction::triggered, this, &SeerMainWindow::handleViewConsoleMinimized); @@ -572,11 +568,6 @@ void SeerMainWindow::handleViewAssembly () { gdbWidget->editorManager()->showAssembly(); } -void SeerMainWindow::handleViewExecutionMessages () { - - _executionMessages->showMessages(); -} - void SeerMainWindow::handleViewAssemblyShown (bool shown) { // Corefile always have them off. @@ -828,7 +819,7 @@ void SeerMainWindow::handleText (const QString& text) { return; } - _executionMessages->addMessage(Seer::filterEscapes(msg_text), QMessageBox::Warning); + gdbWidget->addMessage(Seer::filterEscapes(msg_text), QMessageBox::Warning); return; @@ -948,7 +939,7 @@ void SeerMainWindow::handleText (const QString& text) { QString signalname_text = Seer::parseFirst(text, "signal-name=", '"', '"', false); - _executionMessages->addMessage("Program encountered a '" + signalname_text + "' signal.", QMessageBox::Warning); + gdbWidget->addMessage("Program encountered a '" + signalname_text + "' signal.", QMessageBox::Warning); }else if (reason_text == "breakpoint-hit") { @@ -956,9 +947,9 @@ void SeerMainWindow::handleText (const QString& text) { QString disp_text = Seer::parseFirst(text, "disp=", '"', '"', false); if (disp_text == "del") { - _executionMessages->addMessage("Program reached temporary breakpoint '" + bkptno_text + "'.", QMessageBox::Information); + gdbWidget->addMessage("Program reached temporary breakpoint '" + bkptno_text + "'.", QMessageBox::Information); }else{ - _executionMessages->addMessage("Program reached breakpoint '" + bkptno_text + "'.", QMessageBox::Information); + gdbWidget->addMessage("Program reached breakpoint '" + bkptno_text + "'.", QMessageBox::Information); } }else if (reason_text == "watchpoint-trigger") { @@ -971,7 +962,7 @@ void SeerMainWindow::handleText (const QString& text) { QString old_text = Seer::parseFirst(value_text, "old=", '"', '"', false); QString new_text = Seer::parseFirst(value_text, "new=", '"', '"', false); - _executionMessages->addMessage(QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nOld value: %3\nNew value: %4").arg(number_text).arg(exp_text).arg(old_text).arg(new_text), QMessageBox::Information); + gdbWidget->addMessage(QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nOld value: %3\nNew value: %4").arg(number_text).arg(exp_text).arg(old_text).arg(new_text), QMessageBox::Information); }else if (reason_text == "read-watchpoint-trigger") { //*stopped,reason="read-watchpoint-trigger",hw-rwpt={number="5",exp="i"},value={value="42"},frame={addr="0x0000000000400d9a",func="function1",args=[{name="text",value="\"Hello, World!\""}],file="function1.cpp",fullname="/home/erniep/Development/Peak/src/Seer/helloworld/function1.cpp",line="11",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="4" @@ -982,7 +973,7 @@ void SeerMainWindow::handleText (const QString& text) { QString value_text = Seer::parseFirst(text, "value=", '{', '}', false); QString value_text2 = Seer::parseFirst(value_text, "value=", '"', '"', false); - _executionMessages->addMessage(QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nValue: %3").arg(number_text).arg(exp_text).arg(value_text2), QMessageBox::Information); + gdbWidget->addMessage(QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nValue: %3").arg(number_text).arg(exp_text).arg(value_text2), QMessageBox::Information); }else if (reason_text == "access-watchpoint-trigger") { //*stopped,reason="access-watchpoint-trigger",hw-awpt={number="3",exp="v"},value={old="1",new="11"},frame={addr="0x000000000040059a",func="bar",args=[{name="v",value="11"}],file="helloonefile.cpp",fullname="/home/erniep/Development/Peak/src/Seer/helloonefile/helloonefile.cpp",line="15",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="3" @@ -994,33 +985,33 @@ void SeerMainWindow::handleText (const QString& text) { QString old_text = Seer::parseFirst(value_text, "old=", '"', '"', false); QString new_text = Seer::parseFirst(value_text, "new=", '"', '"', false); - _executionMessages->addMessage(QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nOld value: %3\nNew value: %4").arg(number_text).arg(exp_text).arg(old_text).arg(new_text), QMessageBox::Information); + gdbWidget->addMessage(QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nOld value: %3\nNew value: %4").arg(number_text).arg(exp_text).arg(old_text).arg(new_text), QMessageBox::Information); }else if (reason_text == "watchpoint-scope") { //*stopped,reason="watchpoint-scope",wpnum="5", frame={func="callee3",args=[{name="strarg", value="0x11940 \"A string argument.\""}], file="../../../devo/gdb/testsuite/gdb.mi/basics.c", fullname="/home/foo/bar/devo/gdb/testsuite/gdb.mi/basics.c",line="18"} QString wpnum_text = Seer::parseFirst(text, "wpnum=", '"', '"', false); - _executionMessages->addMessage(QString("Watchpoint went out of scope. Will be deleted.\n\nNumber: %1").arg(wpnum_text), QMessageBox::Information); + gdbWidget->addMessage(QString("Watchpoint went out of scope. Will be deleted.\n\nNumber: %1").arg(wpnum_text), QMessageBox::Information); }else if (reason_text == "exited-normally") { //*stopped,reason="exited-normally" - _executionMessages->addMessage("Program exited normally.", QMessageBox::Information); + gdbWidget->addMessage("Program exited normally.", QMessageBox::Information); }else if (reason_text == "exited") { //*stopped,reason="exited",exit-code="01" QString exitcode_text = Seer::parseFirst(text, "exit-code=", '"', '"', false); - _executionMessages->addMessage("Program exited with code '" + exitcode_text +"'", QMessageBox::Information); + gdbWidget->addMessage("Program exited with code '" + exitcode_text +"'", QMessageBox::Information); }else if (reason_text == "exited-signalled") { //*stopped,reason="exited-signalled",signal-name="SIGSEGV",signal-meaning="Segmentation fault" QString signalname_text = Seer::parseFirst(text, "signal-name=", '"', '"', false); - _executionMessages->addMessage("Program exited abnormally.\nIt encountered a '" + signalname_text + "' signal.", QMessageBox::Warning); + gdbWidget->addMessage("Program exited abnormally.\nIt encountered a '" + signalname_text + "' signal.", QMessageBox::Warning); }else if (reason_text == "unknown") { @@ -1029,7 +1020,7 @@ void SeerMainWindow::handleText (const QString& text) { //qDebug() << "Text=" << text; - _executionMessages->addMessage("Program encountered an unknown problem. See the Gdb output tab for messages.", QMessageBox::Warning); + gdbWidget->addMessage("Program encountered an unknown problem. See the Gdb output tab for messages.", QMessageBox::Warning); } return; @@ -1041,7 +1032,7 @@ void SeerMainWindow::handleText (const QString& text) { //qDebug() << "Inferior pid = " << pid_text; - _executionMessages->addMessage("Program started. (pid=" + pid_text +")", QMessageBox::Information); + gdbWidget->addMessage("Program started. (pid=" + pid_text +")", QMessageBox::Information); return; diff --git a/src/SeerMainWindow.h b/src/SeerMainWindow.h index ff0ff20..2c67c74 100644 --- a/src/SeerMainWindow.h +++ b/src/SeerMainWindow.h @@ -4,7 +4,6 @@ #include "SeerRunStatusIndicator.h" #include "SeerKeySettings.h" #include "SeerProgressIndicator.h" -#include "SeerMessagesDialog.h" #include #include #include @@ -73,7 +72,6 @@ class SeerMainWindow : public QMainWindow, protected Ui::SeerMainWindowForm { void handleViewVarVisualizer (); void handleViewImageVisualizer (); void handleViewAssembly (); - void handleViewExecutionMessages (); void handleViewAssemblyShown (bool shown); void handleViewConsoleNormal (); void handleViewConsoleHidden (); @@ -108,6 +106,5 @@ class SeerMainWindow : public QMainWindow, protected Ui::SeerMainWindowForm { SeerProgressIndicator* _progressIndicator; SeerKeySettings _keySettings; QString _projectFile; - SeerMessagesDialog* _executionMessages; }; diff --git a/src/SeerMainWindow.ui b/src/SeerMainWindow.ui index eb73b16..c170be5 100644 --- a/src/SeerMainWindow.ui +++ b/src/SeerMainWindow.ui @@ -73,7 +73,6 @@ - diff --git a/src/SeerMessagesBrowserWidget.cpp b/src/SeerMessagesBrowserWidget.cpp new file mode 100644 index 0000000..8ed7eea --- /dev/null +++ b/src/SeerMessagesBrowserWidget.cpp @@ -0,0 +1,108 @@ +#include "SeerMessagesBrowserWidget.h" +#include +#include +#include +#include +#include + +SeerMessagesBrowserWidget::SeerMessagesBrowserWidget (QWidget* parent) : QWidget(parent) { + + // Construct the UI. + setupUi(this); + + // Setup the widgets + QString style = "QTreeWidget::item:!selected " // Items in tree widget will have a border. + "{ " + "border: 1px solid gainsboro; " + "border-left: none; " + "border-top: none; " + "}" + "QTreeWidget::item:selected {}"; + + messagesTreeWidget->setRootIsDecorated(false); + messagesTreeWidget->setStyleSheet(style); + messagesTreeWidget->setSortingEnabled(false); + messagesTreeWidget->resizeColumnToContents(0); // timestamp + messagesTreeWidget->resizeColumnToContents(1); // message type icon + messagesTreeWidget->resizeColumnToContents(2); // message + + // Get icons. + _informationIcon = QIcon(":/seer/resources/RelaxLightIcons/data-information.svg"); + _warningIcon = QIcon(":/seer/resources/RelaxLightIcons/data-warning.svg"); + _criticalIcon = QIcon(":/seer/resources/RelaxLightIcons/data-error.svg"); + _questionIcon = QIcon(":/seer/resources/RelaxLightIcons/dialog-question.svg"); + + + // Connect things. + QObject::connect(deleteMessagesToolButton, &QToolButton::clicked, this, &SeerMessagesBrowserWidget::handleDeleteToolButton); + + // Clear messages + clearMessages(); +} + +SeerMessagesBrowserWidget::~SeerMessagesBrowserWidget () { +} + +void SeerMessagesBrowserWidget::addMessage (const QString& message, QMessageBox::Icon messageType) { + + // Give this dialog the focus. + //setFocus(Qt::OtherFocusReason); + + // Show messages any time a messaged is added. + emit showMessages(); + + // Create an entry with our message. + QTreeWidgetItem* item = new QTreeWidgetItem; + item->setText(0, QTime::currentTime().toString(Qt::TextDate)); + + switch (messageType) { + case QMessageBox::NoIcon: + item->setIcon(1, _noIcon); + break; + case QMessageBox::Information: + item->setIcon(1, _informationIcon); + break; + case QMessageBox::Warning: + item->setIcon(1, _warningIcon); + break; + case QMessageBox::Critical: + item->setIcon(1, _criticalIcon); + break; + case QMessageBox::Question: + item->setIcon(1, _questionIcon); + break; + default: + item->setIcon(1, _noIcon); + break; + } + + item->setText(2, message); + + // Insert the entry (at the end). + messagesTreeWidget->addTopLevelItem(item); + + // Re-adjust column sizes. + messagesTreeWidget->resizeColumnToContents(0); + messagesTreeWidget->resizeColumnToContents(1); + messagesTreeWidget->resizeColumnToContents(2); + + // Scroll to the bottom. + QTreeWidgetItem* lastItem = messagesTreeWidget->topLevelItem(messagesTreeWidget->topLevelItemCount()-1); + if (lastItem) { + messagesTreeWidget->scrollToItem(lastItem); + messagesTreeWidget->clearSelection(); + lastItem->setSelected(true); + } +} + +void SeerMessagesBrowserWidget::clearMessages () { + + messagesTreeWidget->clear(); +} + +void SeerMessagesBrowserWidget::handleDeleteToolButton () { + + // Delete all messages. + clearMessages(); +} + diff --git a/src/SeerMessagesBrowserWidget.h b/src/SeerMessagesBrowserWidget.h new file mode 100644 index 0000000..140cec5 --- /dev/null +++ b/src/SeerMessagesBrowserWidget.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include +#include "ui_SeerMessagesBrowserWidget.h" + +class SeerMessagesBrowserWidget : public QWidget, protected Ui::SeerMessagesBrowserWidgetForm { + + Q_OBJECT + + public: + explicit SeerMessagesBrowserWidget (QWidget* parent = 0); + ~SeerMessagesBrowserWidget (); + + public slots: + void addMessage (const QString& message, QMessageBox::Icon messageType); + void clearMessages (); + + private slots: + void handleDeleteToolButton (); + + signals: + void showMessages (); + + protected: + + private: + QIcon _noIcon; + QIcon _informationIcon; + QIcon _warningIcon; + QIcon _criticalIcon; + QIcon _questionIcon; +}; + diff --git a/src/SeerMessagesBrowserWidget.ui b/src/SeerMessagesBrowserWidget.ui new file mode 100644 index 0000000..86154da --- /dev/null +++ b/src/SeerMessagesBrowserWidget.ui @@ -0,0 +1,83 @@ + + + SeerMessagesBrowserWidgetForm + + + + 0 + 0 + 1162 + 625 + + + + Form + + + + + + + + QAbstractItemView::NoEditTriggers + + + + Timestamp + + + + + Type + + + AlignLeading|AlignVCenter + + + + + Message + + + + + + + + + + Delete all messages. + + + ... + + + + :/seer/resources/RelaxLightIcons/edit-delete.svg:/seer/resources/RelaxLightIcons/edit-delete.svg + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + +