Added a search feature in the All Watch variables window
[clinton/Virtual-Jaguar-Rx.git] / src / debugger / allwatchbrowser.cpp
1 //
2 // allwatchbrowser.cpp - All Watch
3 //
4 // by Jean-Paul Mari
5 //
6 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
7 //
8 // Who When What
9 // --- ---------- -----------------------------------------------------------
10 // JPM 12/07/2017 Created this file
11 // JPM 09/14/2018 Added a status bar, better status report and set information values in a tab
12 // JPM April/2019 Added a sorting filter, tableview unique rows creation
13 // JPM April/2021 Added a search feature.
14 //
15
16 // STILL TO DO:
17 // Better presentation
18 // To set the information display at the right
19 // To understand/fix the problem with the sorting filter
20 // Display arrays information
21 // Display structures information
22 //
23
24 //#define AW_SORTINGFILTER // Authorise the sorting filtes
25 //#define AW_DEBUGNUMVARIABLE 4415 // Set the global variable number to debug
26 #ifndef AW_DEBUGNUMVARIABLE
27 #define AW_STARTNUMVARIABLE 0 // Must be kept to 0 in case of no debug is required
28 #else
29 #define AW_STARTNUMVARIABLE AW_DEBUGNUMVARIABLE - 1
30 #endif
31
32
33 #include "debugger/allwatchbrowser.h"
34 #include "memory.h"
35 #include "debugger/DBGManager.h"
36
37
38 //
39 AllWatchBrowserWindow::AllWatchBrowserWindow(QWidget * parent/*= 0*/) : QWidget(parent, Qt::Dialog),
40 layout(new QVBoxLayout),
41 symbol(new QLineEdit),
42 search(new QPushButton(tr("Search"))),
43 #ifdef AW_LAYOUTTEXTS
44 text(new QTextBrowser),
45 #else
46 TableView(new QTableView),
47 model(new QStandardItemModel),
48 #endif
49 NbWatch(0),
50 CurrentWatch(0),
51 statusbar(new QStatusBar),
52 PtrWatchInfo(NULL)
53 {
54 setWindowTitle(tr("All Watch"));
55
56 // set the font
57 QFont fixedFont("Lucida Console", 8, QFont::Normal);
58 fixedFont.setStyleHint(QFont::TypeWriter);
59
60 #ifdef AW_LAYOUTTEXTS
61 // Set original layout
62 text->setFont(fixedFont);
63 layout->addWidget(text);
64 #else
65 // Set the new layout with proper identation and readibility
66 model->setColumnCount(3);
67 model->setHeaderData(0, Qt::Horizontal, QObject::tr("Name"));
68 model->setHeaderData(1, Qt::Horizontal, QObject::tr("Value"));
69 model->setHeaderData(2, Qt::Horizontal, QObject::tr("Type"));
70 // Information table
71 TableView->setModel(model);
72 TableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
73 TableView->setShowGrid(0);
74 TableView->setFont(fixedFont);
75 TableView->verticalHeader()->setDefaultSectionSize(TableView->verticalHeader()->minimumSectionSize());
76 TableView->verticalHeader()->setDefaultAlignment(Qt::AlignRight);
77 layout->addWidget(TableView);
78 #endif
79
80 // search bar
81 QHBoxLayout * hbox1 = new QHBoxLayout;
82 symbol->setPlaceholderText("symbol name");
83 hbox1->addWidget(symbol);
84 hbox1->addWidget(search);
85 layout->addLayout(hbox1);
86
87 // status bar
88 layout->addWidget(statusbar);
89 setLayout(layout);
90
91 // connect slot
92 connect(search, SIGNAL(clicked()), this, SLOT(SearchSymbol()));
93 connect(symbol, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(SelectSearchSymbol()));
94 }
95
96
97 //
98 AllWatchBrowserWindow::~AllWatchBrowserWindow(void)
99 {
100 Reset();
101 }
102
103
104 // Search the symbol in the watch list
105 void AllWatchBrowserWindow::SearchSymbol(void)
106 {
107 bool found = false;
108 size_t i;
109
110 // user cannot enter symbol to allow the search
111 symbol->setDisabled(true);
112
113 // look for the symbol in the watch list
114 for (i = AW_STARTNUMVARIABLE; (i < NbWatch) && !found; i++)
115 {
116 // check symbol presence
117 if (!symbol->text().compare(((S_VariablesStruct*)PtrWatchInfo[i])->PtrName, Qt::CaseSensitive))
118 {
119 found = true;
120 }
121 }
122
123 if (found)
124 {
125 // remove previous highlight
126 if (CurrentWatch)
127 {
128 model->item((int)(CurrentWatch - 1), 0)->setBackground(QColor(255, 255, 255));
129 model->item((int)(CurrentWatch - 1), 1)->setBackground(QColor(255, 255, 255));
130 model->item((int)(CurrentWatch - 1), 2)->setBackground(QColor(255, 255, 255));
131 }
132 // Get the slider maximum position
133 int MaxSlider = TableView->verticalScrollBar()->maximum();
134 // Number of items displayed in the scroll bar slider
135 int DeltaSlider = (int)NbWatch - MaxSlider;
136 // set the scroll bar
137 TableView->verticalScrollBar()->setSliderPosition((int)i - (DeltaSlider / 2) - 1);
138 // highlight watch symbol
139 CurrentWatch = i;
140 model->item((int)(CurrentWatch - 1), 0)->setBackground(QColor(0xff, 0xfa, 0xcd));
141 model->item((int)(CurrentWatch - 1), 1)->setBackground(QColor(0xff, 0xfa, 0xcd));
142 model->item((int)(CurrentWatch - 1), 2)->setBackground(QColor(0xff, 0xfa, 0xcd));
143 // allow new symbol
144 symbol->setText("");
145 }
146 else
147 {
148 // invalid symbol
149 symbol->setStyleSheet("color: red");
150 }
151
152 // user can enter a symbol
153 symbol->setEnabled(true);
154 symbol->setFocus();
155 }
156
157
158 //
159 void AllWatchBrowserWindow::SelectSearchSymbol(void)
160 {
161 symbol->setStyleSheet("color: black");
162 }
163
164
165 //
166 void AllWatchBrowserWindow::Reset(void)
167 {
168 free(PtrWatchInfo);
169 NbWatch = 0;
170 PtrWatchInfo = NULL;
171 }
172
173
174 //
175 void AllWatchBrowserWindow::RefreshContents(void)
176 {
177 char msg[100];
178 #ifdef AW_LAYOUTTEXTS
179 char string[1024];
180 #endif
181 QString WatchAll;
182 size_t Error = AW_NOERROR;
183 char *PtrValue;
184 //S_VariablesStruct* Var;
185
186 if (isVisible())
187 {
188 if (!NbWatch)
189 {
190 // Pre-catch the information for each global variables
191 if (NbWatch = DBGManager_GetNbVariables(NULL))
192 {
193 PtrWatchInfo = (void**)calloc(NbWatch, sizeof(S_VariablesStruct*));
194 #ifndef AW_LAYOUTTEXTS
195 #ifdef AW_SORTINGFILTER
196 TableView->setSortingEnabled(false);
197 #endif
198 model->setRowCount(0);
199 #endif
200 for (uint32_t i = AW_STARTNUMVARIABLE; i < NbWatch; i++)
201 {
202 if ((PtrWatchInfo[i] = (void*)DBGManager_GetInfosVariable(NULL, i + 1)))
203 {
204 #ifdef AW_LAYOUTTEXTS
205 PtrWatchInfo[i].addr = DBGManager_GetGlobalVariableAdr(i + 1);
206 if (!strlen(PtrWatchInfo[i].PtrVariableBaseTypeName = DBGManager_GetGlobalVariableTypeName(i + 1)))
207 {
208 PtrWatchInfo[i].PtrVariableBaseTypeName = (char *)"<font color='#ff0000'>N/A</font>";
209 }
210 #else
211 model->insertRow(i);
212 #endif
213 }
214 }
215 }
216 }
217
218 if (NbWatch)
219 {
220 for (uint32_t i = AW_STARTNUMVARIABLE; i < NbWatch; i++)
221 {
222 if (((S_VariablesStruct*)PtrWatchInfo[i])->TypeTag & (DBG_TAG_TYPE_array | DBG_TAG_TYPE_structure))
223 {
224 #if defined(AW_SUPPORTARRAY) || defined(AW_SUPPORTSTRUCTURE)
225 //PtrValue = (char *)memcpy(Value, &jaguarMainRAM[PtrWatchInfo[i].addr], 20);
226 PtrValue = NULL;
227 #else
228 PtrValue = NULL;
229 #endif
230 }
231 else
232 {
233 PtrValue = DBGManager_GetVariableValueFromAdr(((S_VariablesStruct*)PtrWatchInfo[i])->Addr, ((S_VariablesStruct*)PtrWatchInfo[i])->TypeEncoding, ((S_VariablesStruct*)PtrWatchInfo[i])->TypeByteSize);
234 }
235 #ifdef AW_LAYOUTTEXTS
236 if (i)
237 {
238 WatchAll += QString("<br>");
239 }
240 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>");
241 WatchAll += QString(string);
242 #else
243 model->setItem(i, 0, new QStandardItem(QString("%1").arg(((S_VariablesStruct*)PtrWatchInfo[i])->PtrName)));
244 model->setItem(i, 1, new QStandardItem(QString("%1").arg(PtrValue)));
245 model->setItem(i, 2, new QStandardItem(QString("%1").arg(((S_VariablesStruct*)PtrWatchInfo[i])->PtrTypeName)));
246 #endif
247 }
248 #ifdef AW_LAYOUTTEXTS
249 text->clear();
250 text->setText(WatchAll);
251 #else
252 #ifdef AW_SORTINGFILTER
253 TableView->setSortingEnabled(true);
254 #endif
255 #endif
256 sprintf(msg, "Ready");
257 }
258 else
259 {
260 sprintf(msg, "No watches");
261 Error = AW_NOALLWATCH;
262 }
263
264 // Display status bar
265 if (Error)
266 {
267 if ((Error & AW_WARNING))
268 {
269 statusbar->setStyleSheet("background-color: lightyellow; font: bold");
270 }
271 else
272 {
273 statusbar->setStyleSheet("background-color: tomato; font: bold");
274 }
275 }
276 else
277 {
278 statusbar->setStyleSheet("background-color: lightgreen; font: bold");
279 }
280 statusbar->showMessage(QString(msg));
281 }
282 }
283
284
285 // Handle keyboard event
286 void AllWatchBrowserWindow::keyPressEvent(QKeyEvent * e)
287 {
288 // ESC to close / hide the window
289 if (e->key() == Qt::Key_Escape)
290 {
291 hide();
292 }
293 else
294 {
295 // search symbol
296 if (e->key() == Qt::Key_Return)
297 {
298 SearchSymbol();
299 }
300 }
301 }
302