diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f65c990..ca4af85 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -126,6 +126,7 @@ set(HEADER_FILES QEditDelegate.h QHContainerWidget.h QImageViewer.h + QMessageListWidget.h ) set(SOURCE_FILES @@ -213,6 +214,7 @@ set(SOURCE_FILES QEditDelegate.cpp QHContainerWidget.cpp QImageViewer.cpp + QMessageListWidget.cpp ) if(${QTVERSION} STREQUAL "QT6") diff --git a/src/QMessageListWidget.cpp b/src/QMessageListWidget.cpp new file mode 100644 index 0000000..cb3d9e6 --- /dev/null +++ b/src/QMessageListWidget.cpp @@ -0,0 +1,90 @@ +#include "QMessageListWidget.h" +#include +#include +#include +#include +#include +#include + + +QMessageListWidget::QMessageListWidget (QWidget* parent) : QWidget(parent) { + + // Construct the UI. + setupUi(this); + + // Setup the widgets. + messageTreeWidget->setSortingEnabled(false); + messageTreeWidget->resizeColumnToContents(0); // timestamp + messageTreeWidget->resizeColumnToContents(1); // message type icon + messageTreeWidget->resizeColumnToContents(2); // message + messageTreeWidget->clear(); + + // Get icons. + QStyle* style = QApplication::style(); + + _informationIcon = style->standardIcon(QStyle::SP_MessageBoxInformation, 0, this); + _warningIcon = style->standardIcon(QStyle::SP_MessageBoxWarning, 0, this); + _criticalIcon = style->standardIcon(QStyle::SP_MessageBoxCritical, 0, this); + _questionIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, 0, this); + + // Connect things. + QObject::connect(okPushButton, &QToolButton::clicked, this, &QMessageListWidget::handleOkButtonClicked); + + hide(); +} + +QMessageListWidget::~QMessageListWidget () { +} + +void QMessageListWidget::addMessage (const QString& message, QMessageBox::Icon messageType) { + + show(); + raise(); + + // 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). + messageTreeWidget->addTopLevelItem(item); + + // Re-adjust column sizes. + messageTreeWidget->resizeColumnToContents(0); + messageTreeWidget->resizeColumnToContents(1); + messageTreeWidget->resizeColumnToContents(2); + + // Scroll to the bottom. + QTreeWidgetItem* lastItem = messageTreeWidget->topLevelItem(messageTreeWidget->topLevelItemCount()-1); + if (lastItem) { + messageTreeWidget->scrollToItem(lastItem); + } +} + +void QMessageListWidget::handleOkButtonClicked () { + + hide(); +} + diff --git a/src/QMessageListWidget.h b/src/QMessageListWidget.h new file mode 100644 index 0000000..3333e9b --- /dev/null +++ b/src/QMessageListWidget.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include +#include "ui_QMessageListWidget.h" + +class QMessageListWidget : public QWidget, protected Ui::QMessageListWidget { + + Q_OBJECT + + public: + explicit QMessageListWidget (QWidget* parent = 0); + ~QMessageListWidget (); + + signals: + + public slots: + void addMessage (const QString& message, QMessageBox::Icon messageType); + + protected slots: + void handleOkButtonClicked (); + + protected: + private: + QIcon _noIcon; + QIcon _informationIcon; + QIcon _warningIcon; + QIcon _criticalIcon; + QIcon _questionIcon; +}; + diff --git a/src/QMessageListWidget.ui b/src/QMessageListWidget.ui new file mode 100644 index 0000000..3c3a4fc --- /dev/null +++ b/src/QMessageListWidget.ui @@ -0,0 +1,74 @@ + + + QMessageListWidget + + + + 0 + 0 + 534 + 266 + + + + Messages + + + + + + QAbstractItemView::NoEditTriggers + + + + Timestamp + + + + + Type + + + AlignLeading|AlignVCenter + + + + + Message + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + + + + + + + okPushButton + messageTreeWidget + + + + diff --git a/src/SeerBreakpointsBrowserWidget.cpp b/src/SeerBreakpointsBrowserWidget.cpp index 93c25e6..e2d1429 100644 --- a/src/SeerBreakpointsBrowserWidget.cpp +++ b/src/SeerBreakpointsBrowserWidget.cpp @@ -32,7 +32,8 @@ SeerBreakpointsBrowserWidget::SeerBreakpointsBrowserWidget (QWidget* parent) : Q breakpointsTreeWidget->resizeColumnToContents(10); // cond breakpointsTreeWidget->resizeColumnToContents(11); // times breakpointsTreeWidget->resizeColumnToContents(12); // ignore - breakpointsTreeWidget->resizeColumnToContents(13); // original-location + //breakpointsTreeWidget->resizeColumnToContents(13); // script Too long to show + breakpointsTreeWidget->resizeColumnToContents(14); // original-location /* breakpointsTreeWidget->setColumnHidden(1, true); // ??? Hide or have a config to hide/show columns. @@ -99,6 +100,7 @@ void SeerBreakpointsBrowserWidget::handleText (const QString& text) { // thread-groups=["i1"], // cond="1 == 1", // times="0", + // script={"print i argc"}, // original-location="function1"} // ] // } @@ -128,6 +130,7 @@ void SeerBreakpointsBrowserWidget::handleText (const QString& text) { QString cond_text = Seer::parseFirst(bkpt_text, "cond=", '"', '"', false); QString times_text = Seer::parseFirst(bkpt_text, "times=", '"', '"', false); QString ignore_text = Seer::parseFirst(bkpt_text, "ignore=", '"', '"', false); + QString script_text = Seer::parseFirst(bkpt_text, "script=", '{', '}', false); QString original_location_text = Seer::parseFirst(bkpt_text, "original-location=", '"', '"', false); // Only look for 'breakpoint' type break points. @@ -150,7 +153,8 @@ void SeerBreakpointsBrowserWidget::handleText (const QString& text) { topItem->setText(10, cond_text); topItem->setText(11, times_text); topItem->setText(12, ignore_text); - topItem->setText(13, original_location_text); + topItem->setText(13, script_text); + topItem->setText(14, original_location_text); breakpointsTreeWidget->addTopLevelItem(topItem); } @@ -176,7 +180,8 @@ void SeerBreakpointsBrowserWidget::handleText (const QString& text) { breakpointsTreeWidget->resizeColumnToContents(10); breakpointsTreeWidget->resizeColumnToContents(11); breakpointsTreeWidget->resizeColumnToContents(12); - breakpointsTreeWidget->resizeColumnToContents(13); + //breakpointsTreeWidget->resizeColumnToContents(13); + breakpointsTreeWidget->resizeColumnToContents(14); QApplication::restoreOverrideCursor(); } @@ -323,7 +328,7 @@ void SeerBreakpointsBrowserWidget::handleConditionToolButton () { // Get the condition text. bool ok; - QString condition = QInputDialog::getText(this, "Seer", "Enter the condition for this breakpoint.\nA blank condition will remove an existing one.", QLineEdit::Normal, QString(), &ok); + QString condition = QInputDialog::getText(this, "Seer", "Enter the condition for this breakpoint.\nA blank condition will remove an existing one.", QLineEdit::Normal, items.front()->text(10), &ok); if (ok == false) { return; @@ -352,7 +357,7 @@ void SeerBreakpointsBrowserWidget::handleIgnoreToolButton () { // Get the ignore text. bool ok; - int count = QInputDialog::getInt(this, "Seer", "Enter the ignore count for this breakpoint.\nA count of 0 will remove an existing one.", 0, 0, 2147483647, 1, &ok); + int count = QInputDialog::getInt(this, "Seer", "Enter the ignore count for this breakpoint.\nA count of 0 will remove an existing one.", items.front()->text(12).toInt(), 0, 2147483647, 1, &ok); if (ok == false) { return; diff --git a/src/SeerBreakpointsBrowserWidget.ui b/src/SeerBreakpointsBrowserWidget.ui index cd35648..2a357fd 100644 --- a/src/SeerBreakpointsBrowserWidget.ui +++ b/src/SeerBreakpointsBrowserWidget.ui @@ -6,8 +6,8 @@ 0 0 - 896 - 528 + 979 + 625 @@ -17,7 +17,7 @@ - 14 + 15 @@ -84,6 +84,11 @@ Ignore + + + Commands + + Original Location @@ -165,7 +170,7 @@ Add ignore count to selected breakpoint. - 5 + # diff --git a/src/SeerMainWindow.cpp b/src/SeerMainWindow.cpp index 063cc3d..9104bf7 100644 --- a/src/SeerMainWindow.cpp +++ b/src/SeerMainWindow.cpp @@ -108,6 +108,9 @@ SeerMainWindow::SeerMainWindow(QWidget* parent) : QMainWindow(parent) { setKeySettings(SeerKeySettings::populate()); setProjectFilename(""); + // Create the message list. + _messageList = new QMessageListWidget; + // // Set up signals/slots. // @@ -782,7 +785,7 @@ void SeerMainWindow::handleText (const QString& text) { return; } - QMessageBox::warning(this, "Error.", Seer::filterEscapes(msg_text)); + _messageList->addMessage(Seer::filterEscapes(msg_text), QMessageBox::Warning); return; @@ -902,7 +905,7 @@ void SeerMainWindow::handleText (const QString& text) { QString signalname_text = Seer::parseFirst(text, "signal-name=", '"', '"', false); - QMessageBox::warning(this, "Warning.", "Program encountered a '" + signalname_text + "' signal."); + _messageList->addMessage("Program encountered a '" + signalname_text + "' signal.", QMessageBox::Warning); }else if (reason_text == "breakpoint-hit") { @@ -910,9 +913,9 @@ void SeerMainWindow::handleText (const QString& text) { QString disp_text = Seer::parseFirst(text, "disp=", '"', '"', false); if (disp_text == "del") { - QMessageBox::information(this, "Note.", "Program reached temporary breakpoint '" + bkptno_text + "'."); + _messageList->addMessage("Program reached temporary breakpoint '" + bkptno_text + "'.", QMessageBox::Information); }else{ - QMessageBox::information(this, "Note.", "Program reached breakpoint '" + bkptno_text + "'."); + _messageList->addMessage("Program reached breakpoint '" + bkptno_text + "'.", QMessageBox::Information); } }else if (reason_text == "watchpoint-trigger") { @@ -925,7 +928,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); - QMessageBox::information(this, "Note.", 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) ); + _messageList->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" @@ -936,7 +939,7 @@ void SeerMainWindow::handleText (const QString& text) { QString value_text = Seer::parseFirst(text, "value=", '{', '}', false); QString value_text2 = Seer::parseFirst(value_text, "value=", '"', '"', false); - QMessageBox::information(this, "Note.", QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nValue: %3").arg(number_text).arg(exp_text).arg(value_text2) ); + _messageList->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" @@ -948,33 +951,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); - QMessageBox::information(this, "Note.", 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) ); + _messageList->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); - QMessageBox::information(this, "Note.", QString("Watchpoint went out of scope. Will be deleted.\n\nNumber: %1").arg(wpnum_text) ); + _messageList->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" - QMessageBox::information(this, "Note.", "Program exited normally."); + _messageList->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); - QMessageBox::information(this, "Note.", "Program exited with code '" + exitcode_text +"'"); + _messageList->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); - QMessageBox::warning(this, "Error.", "Program exited abnormally.\n\nIt encountered a '" + signalname_text + "' signal."); + _messageList->addMessage("Program exited abnormally.\nIt encountered a '" + signalname_text + "' signal.", QMessageBox::Warning); }else if (reason_text == "unknown") { @@ -982,7 +985,8 @@ void SeerMainWindow::handleText (const QString& text) { // Attaching to a pid will generate an unknown *stopped message that is useless. //qDebug() << "Text=" << text; - //QMessageBox::warning(this, "Warning.", "Program encountered an unknown problem. See the Gdb output tab for messages."); + + _messageList->addMessage("Program encountered an unknown problem. See the Gdb output tab for messages.", QMessageBox::Warning); } return; diff --git a/src/SeerMainWindow.h b/src/SeerMainWindow.h index 68b6aa2..aff76f3 100644 --- a/src/SeerMainWindow.h +++ b/src/SeerMainWindow.h @@ -4,6 +4,7 @@ #include "SeerRunStatusIndicator.h" #include "SeerKeySettings.h" #include "SeerProgressIndicator.h" +#include "QMessageListWidget.h" #include #include #include @@ -102,5 +103,6 @@ class SeerMainWindow : public QMainWindow, protected Ui::SeerMainWindowForm { SeerProgressIndicator* _progressIndicator; SeerKeySettings _keySettings; QString _projectFile; + QMessageListWidget* _messageList; };