Search feature in the all watches window
[clinton/Virtual-Jaguar-Rx.git] / src / debugger / allwatchbrowser.cpp
index 302b462..6aa7d6c 100644 (file)
 // Who  When        What\r
 // ---  ----------  -----------------------------------------------------------\r
 // JPM  12/07/2017  Created this file\r
+// JPM  09/14/2018  Added a status bar, better status report and set information values in a tab\r
+// JPM  April/2019  Added a sorting filter, tableview unique rows creation\r
 //\r
 \r
 // STILL TO DO:\r
+// Better presentation\r
+// To set the information display at the right\r
+// To understand/fix the problem with the sorting filter\r
+// Display arrays information\r
+// Display structures information\r
 //\r
 \r
+//#define AW_SORTINGFILTER                                                                     // Authorise the sorting filtes\r
+//#define AW_DEBUGNUMVARIABLE          4415                                            // Set the global variable number to debug\r
+#ifndef AW_DEBUGNUMVARIABLE\r
+#define AW_STARTNUMVARIABLE            0                                                       // Must be kept to 0 in case of no debug is required\r
+#else\r
+#define AW_STARTNUMVARIABLE            AW_DEBUGNUMVARIABLE - 1\r
+#endif\r
+\r
+\r
 #include "debugger/allwatchbrowser.h"\r
 #include "memory.h"\r
 #include "debugger/DBGManager.h"\r
 \r
 \r
+// \r
 AllWatchBrowserWindow::AllWatchBrowserWindow(QWidget * parent/*= 0*/) : QWidget(parent, Qt::Dialog),\r
-       layout(new QVBoxLayout), text(new QTextBrowser),\r
-//     layout(new QVBoxLayout), text(new QLabel),\r
-//     refresh(new QPushButton(tr("Refresh"))),\r
-//     address(new QLineEdit),\r
-//     go(new QPushButton(tr("Go"))),\r
-//     memBase(0),\r
-       NbWatch(0),\r
-       PtrWatchInfo(NULL)\r
+layout(new QVBoxLayout),\r
+symbol(new QLineEdit),\r
+search(new QPushButton(tr("Search"))),\r
+#ifdef AW_LAYOUTTEXTS\r
+text(new QTextBrowser),\r
+#else\r
+TableView(new QTableView),\r
+model(new QStandardItemModel),\r
+#endif\r
+NbWatch(0),\r
+CurrentWatch(0),\r
+statusbar(new QStatusBar),\r
+PtrWatchInfo(NULL)\r
 {\r
        setWindowTitle(tr("All Watch"));\r
 \r
-//     address->setInputMask("hhhhhh");\r
-//     QHBoxLayout * hbox1 = new QHBoxLayout;\r
-//     hbox1->addWidget(refresh);\r
-//     hbox1->addWidget(address);\r
-//     hbox1->addWidget(go);\r
-\r
-       // Need to set the size as well...\r
-//     resize(560, 480);\r
-\r
+       // set the font\r
        QFont fixedFont("Lucida Console", 8, QFont::Normal);\r
-//     QFont fixedFont("", 8, QFont::Normal);\r
        fixedFont.setStyleHint(QFont::TypeWriter);\r
-       text->setFont(fixedFont);\r
-////   layout->setSizeConstraint(QLayout::SetFixedSize);\r
-       setLayout(layout);\r
 \r
+#ifdef AW_LAYOUTTEXTS\r
+       // Set original layout\r
+       text->setFont(fixedFont);\r
        layout->addWidget(text);\r
-//     layout->addWidget(refresh);\r
-//     layout->addLayout(hbox1);\r
+#else\r
+       // Set the new layout with proper identation and readibility\r
+       model->setColumnCount(3);\r
+       model->setHeaderData(0, Qt::Horizontal, QObject::tr("Name"));\r
+       model->setHeaderData(1, Qt::Horizontal, QObject::tr("Value"));\r
+       model->setHeaderData(2, Qt::Horizontal, QObject::tr("Type"));\r
+       // Information table\r
+       TableView->setModel(model);\r
+       TableView->setEditTriggers(QAbstractItemView::NoEditTriggers);\r
+       TableView->setShowGrid(0);\r
+       TableView->setFont(fixedFont);\r
+       TableView->verticalHeader()->setDefaultSectionSize(TableView->verticalHeader()->minimumSectionSize());\r
+       TableView->verticalHeader()->setDefaultAlignment(Qt::AlignRight);\r
+       layout->addWidget(TableView);\r
+#endif\r
+\r
+       // search bar\r
+       QHBoxLayout * hbox1 = new QHBoxLayout;\r
+       symbol->setPlaceholderText("symbol name");\r
+       hbox1->addWidget(symbol);\r
+       hbox1->addWidget(search);\r
+       layout->addLayout(hbox1);\r
+\r
+       // status bar\r
+       layout->addWidget(statusbar);\r
+       setLayout(layout);\r
 \r
-//     connect(refresh, SIGNAL(clicked()), this, SLOT(RefreshContents()));\r
-//     connect(go, SIGNAL(clicked()), this, SLOT(GoToAddress()));\r
+       // connect slot\r
+       connect(search, SIGNAL(clicked()), this, SLOT(SearchSymbol()));\r
+       connect(symbol, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(SelectSearchSymbol()));\r
 }\r
 \r
 \r
 //\r
 AllWatchBrowserWindow::~AllWatchBrowserWindow(void)\r
 {\r
-       NbWatch = 0;\r
+       Reset();\r
+}\r
+\r
+\r
+// Search the symbol in the watch list\r
+void AllWatchBrowserWindow::SearchSymbol(void)
+{
+       bool found = false;
+       size_t i;
+
+       // user cannot enter symbol to allow the search
+       symbol->setDisabled(true);
+
+       // look for the symbol in the watch list
+       for (i = AW_STARTNUMVARIABLE; (i < NbWatch) && !found; i++)\r
+       {\r
+               // check symbol presence\r
+               if (!symbol->text().compare(PtrWatchInfo[i].PtrVariableName, Qt::CaseSensitive))\r
+               {\r
+                       found = true;\r
+               }\r
+       }\r
+\r
+       if (found)\r
+       {\r
+               // remove previous highlight\r
+               if (CurrentWatch)\r
+               {\r
+                       model->item((int)(CurrentWatch - 1), 0)->setBackground(QColor(255, 255, 255));\r
+                       model->item((int)(CurrentWatch - 1), 1)->setBackground(QColor(255, 255, 255));\r
+                       model->item((int)(CurrentWatch - 1), 2)->setBackground(QColor(255, 255, 255));\r
+               }\r
+               // Get the slider maximum position\r
+               int MaxSlider = TableView->verticalScrollBar()->maximum();              \r
+               // Number of items displayed in the scroll bar slider\r
+               int DeltaSlider = (int)NbWatch - MaxSlider;\r
+               // set the scroll bar\r
+               TableView->verticalScrollBar()->setSliderPosition((int)i - (DeltaSlider / 2) - 1);\r
+               // highlight watch symbol\r
+               CurrentWatch = i;\r
+               model->item((int)(CurrentWatch - 1), 0)->setBackground(QColor(0xff, 0xfa, 0xcd));\r
+               model->item((int)(CurrentWatch - 1), 1)->setBackground(QColor(0xff, 0xfa, 0xcd));\r
+               model->item((int)(CurrentWatch - 1), 2)->setBackground(QColor(0xff, 0xfa, 0xcd));\r
+               // allow new symbol\r
+               symbol->setText("");\r
+       }\r
+       else\r
+       {\r
+               // invalid symbol\r
+               symbol->setStyleSheet("color: red");\r
+       }\r
+
+       // user can enter a symbol
+       symbol->setEnabled(true);
+       symbol->setFocus();
+}
+
+
+//
+void AllWatchBrowserWindow::SelectSearchSymbol(void)\r
+{\r
+       symbol->setStyleSheet("color: black");\r
+}\r
+\r
+\r
+//\r
+void AllWatchBrowserWindow::Reset(void)\r
+{\r
        free(PtrWatchInfo);\r
+       NbWatch = 0;\r
+       PtrWatchInfo = NULL;\r
 }\r
 \r
 \r
 //\r
 void AllWatchBrowserWindow::RefreshContents(void)\r
 {\r
+       char msg[100];\r
+#ifdef AW_LAYOUTTEXTS\r
        char string[1024];\r
-//     char buf[64];\r
+#endif\r
        QString WatchAll;\r
+       size_t Error = AW_NOERROR;\r
+       char *PtrValue;\r
 \r
        if (isVisible())\r
        {\r
                if (!NbWatch)\r
                {\r
+                       // Pre-catch the information for each global variables\r
                        if (NbWatch = DBGManager_GetNbGlobalVariables())\r
                        {\r
                                PtrWatchInfo = (WatchInfo *)calloc(NbWatch, sizeof(WatchInfo));\r
-#ifdef _MSC_VER\r
-#pragma message("Warning: !!! Need to check the memory desalocation for PtrWatchInfo !!!")\r
-#else\r
-                               #warning "!!! Need to do the memory desalocation for PtrWatchInfo !!!"\r
-#endif // _MSC_VER\r
-                                       \r
-                               for (uint32_t i = 0; i < NbWatch; i++)\r
+#ifndef AW_LAYOUTTEXTS\r
+#ifdef AW_SORTINGFILTER\r
+                               TableView->setSortingEnabled(false);\r
+#endif\r
+                               model->setRowCount(0);\r
+#endif\r
+                               for (uint32_t i = AW_STARTNUMVARIABLE; i < NbWatch; i++)\r
                                {\r
                                        PtrWatchInfo[i].PtrVariableName = DBGManager_GetGlobalVariableName(i + 1);\r
-                                       PtrWatchInfo[i].addr = DBGManager_GetGlobalVariableAdr(i + 1);\r
                                        PtrWatchInfo[i].TypeTag = DBGManager_GetGlobalVariableTypeTag(i + 1);\r
+#ifdef AW_LAYOUTTEXTS\r
+                                       PtrWatchInfo[i].addr = DBGManager_GetGlobalVariableAdr(i + 1);\r
                                        if (!strlen(PtrWatchInfo[i].PtrVariableBaseTypeName = DBGManager_GetGlobalVariableTypeName(i + 1)))\r
                                        {\r
                                                PtrWatchInfo[i].PtrVariableBaseTypeName = (char *)"<font color='#ff0000'>N/A</font>";\r
                                        }\r
+#else\r
+                                       PtrWatchInfo[i].PtrVariableBaseTypeName = DBGManager_GetGlobalVariableTypeName(i + 1);\r
+                                       model->insertRow(i);\r
+#endif\r
                                }\r
                        }\r
                }\r
 \r
-               for (uint32_t i = 0; i < NbWatch; i++)\r
+               if (NbWatch)\r
                {\r
-                       if (PtrWatchInfo[i].PtrVariableName && PtrWatchInfo[i].PtrVariableBaseTypeName)\r
+                       for (uint32_t i = AW_STARTNUMVARIABLE; i < NbWatch; i++)\r
                        {\r
-                               sprintf(string, "%i : %s | %s | 0x%06X | %s", (i + 1), PtrWatchInfo[i].PtrVariableBaseTypeName, PtrWatchInfo[i].PtrVariableName, (unsigned int)PtrWatchInfo[i].addr, (PtrWatchInfo[i].TypeTag & 0x8) ? "" : DBGManager_GetGlobalVariableValue(i + 1));\r
-                               WatchAll += QString(string);\r
-                               sprintf(string, "<br>");\r
+                               if ((PtrWatchInfo[i].TypeTag & (DBG_TAG_TYPE_array | DBG_TAG_TYPE_structure)))\r
+                               {\r
+#if defined(AW_SUPPORTARRAY) || defined(AW_SUPPORTSTRUCTURE)\r
+                                       //PtrValue = (char *)memcpy(Value, &jaguarMainRAM[PtrWatchInfo[i].addr], 20);\r
+                                       PtrValue = NULL;\r
+#else\r
+                                       PtrValue = NULL;\r
+#endif\r
+                               }\r
+                               else\r
+                               {\r
+                                       PtrValue = DBGManager_GetGlobalVariableValue(i + 1);\r
+                               }\r
+#ifdef AW_LAYOUTTEXTS\r
+                               if (i)\r
+                               {\r
+                                       WatchAll += QString("<br>");\r
+                               }\r
+                               sprintf(string, "%i : %s | %s | 0x%06X | %s", (i + 1), PtrWatchInfo[i].PtrVariableBaseTypeName, PtrWatchInfo[i].PtrVariableName, (unsigned int)PtrWatchInfo[i].addr, PtrValue ? PtrValue : (char *)"<font color='#ff0000'>N/A</font>");\r
                                WatchAll += QString(string);\r
+#else\r
+                               model->setItem(i, 0, new QStandardItem(QString("%1").arg(PtrWatchInfo[i].PtrVariableName)));\r
+                               model->setItem(i, 1, new QStandardItem(QString("%1").arg(PtrValue)));\r
+                               model->setItem(i, 2, new QStandardItem(QString("%1").arg(PtrWatchInfo[i].PtrVariableBaseTypeName)));\r
+#endif\r
                        }\r
+#ifdef AW_LAYOUTTEXTS\r
+                       text->clear();\r
+                       text->setText(WatchAll);\r
+#else\r
+#ifdef AW_SORTINGFILTER\r
+                       TableView->setSortingEnabled(true);\r
+#endif\r
+#endif\r
+                       sprintf(msg, "Ready");\r
+               }\r
+               else\r
+               {\r
+                       sprintf(msg, "No watches");\r
+                       Error = AW_NOALLWATCH;\r
                }\r
 \r
-               text->clear();\r
-               text->setText(WatchAll);\r
+               // Display status bar\r
+               if (Error)\r
+               {\r
+                       if ((Error & AW_WARNING))\r
+                       {\r
+                               statusbar->setStyleSheet("background-color: lightyellow; font: bold");\r
+                       }\r
+                       else\r
+                       {\r
+                               statusbar->setStyleSheet("background-color: tomato; font: bold");\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       statusbar->setStyleSheet("background-color: lightgreen; font: bold");\r
+               }\r
+               statusbar->showMessage(QString(msg));\r
        }\r
 }\r
 \r
 \r
-#if 0\r
+//  Handle keyboard event\r
 void AllWatchBrowserWindow::keyPressEvent(QKeyEvent * e)\r
 {\r
+       // ESC to close / hide the window\r
        if (e->key() == Qt::Key_Escape)\r
-               hide();\r
-       else if (e->key() == Qt::Key_PageUp)\r
-       {\r
-               memBase -= 480;\r
-\r
-               if (memBase < 0)\r
-                       memBase = 0;\r
-\r
-               RefreshContents();\r
-       }\r
-       else if (e->key() == Qt::Key_PageDown)\r
        {\r
-               memBase += 480;\r
-\r
-               if (memBase > (0x200000 - 480))\r
-                       memBase = 0x200000 - 480;\r
-\r
-               RefreshContents();\r
-       }\r
-       else if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Minus)\r
-       {\r
-               memBase -= 16;\r
-\r
-               if (memBase < 0)\r
-                       memBase = 0;\r
-\r
-               RefreshContents();\r
+               hide();\r
        }\r
-       else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Equal)\r
+       else\r
        {\r
-               memBase += 16;\r
-\r
-               if (memBase > (0x200000 - 480))\r
-                       memBase = 0x200000 - 480;\r
-\r
-               RefreshContents();\r
+               // select the \r
+               if (e->key() == Qt::Key_Return)\r
+               {\r
+                       SearchSymbol();\r
+               }\r
        }\r
 }\r
-#endif\r
-\r
-\r
-#if 0\r
-void AllWatchBrowserWindow::GoToAddress(void)\r
-{\r
-       bool ok;\r
-       QString newAddress = address->text();\r
-       memBase = newAddress.toUInt(&ok, 16);\r
-       RefreshContents();\r
-}\r
-#endif\r
 \r