-//\r
-// localbrowser.cpp - Local variables\r
-//\r
-// by Jean-Paul Mari\r
-//\r
-// JPM = Jean-Paul Mari <djipi.mari@gmail.com>\r
-// RG = Richard Goedeken\r
-//\r
-// Who When What\r
-// --- ---------- -----------------------------------------------------------\r
-// JPM 11/03/2017 Created this file\r
-// JPM Sept./2018 Added a status bar and better status report, and set information values in a tab\r
-// RG Jan./2021 Linux build fixes\r
-//\r
-\r
-// STILL TO DO:\r
-// Feature to list the pointer(s) in the code using the allocation\r
-// To set the information display at the right\r
-// To support the array\r
-// To support the static variables\r
-// To add a filter\r
-//\r
-\r
-#include <stdlib.h>\r
-\r
-#include "debugger/localbrowser.h"\r
-#include "memory.h"\r
-#include "debugger/DBGManager.h"\r
-#include "settings.h"\r
-#include "m68000/m68kinterface.h"\r
-\r
-\r
-// \r
-LocalBrowserWindow::LocalBrowserWindow(QWidget * parent/*= 0*/) : QWidget(parent, Qt::Dialog),\r
-layout(new QVBoxLayout),\r
-#ifdef LOCAL_LAYOUTTEXTS\r
-text(new QTextBrowser),\r
-#else\r
-TableView(new QTableView),\r
-model(new QStandardItemModel),\r
-#endif\r
-NbLocal(0),\r
-FuncName((char *)calloc(1, 1)),\r
-LocalInfo(NULL),\r
-statusbar(new QStatusBar)\r
-{\r
- setWindowTitle(tr("Locals"));\r
-\r
- // Set the font\r
- QFont fixedFont("Lucida Console", 8, QFont::Normal);\r
- fixedFont.setStyleHint(QFont::TypeWriter);\r
-\r
-#ifdef LOCAL_LAYOUTTEXTS\r
- // Set original layout\r
- text->setFont(fixedFont);\r
- layout->addWidget(text);\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
- // Status bar\r
- layout->addWidget(statusbar);\r
- setLayout(layout);\r
-}\r
-\r
-\r
-//\r
-LocalBrowserWindow::~LocalBrowserWindow(void)\r
-{\r
- free(LocalInfo);\r
- free(FuncName);\r
-}\r
-\r
-\r
-//\r
-bool LocalBrowserWindow::UpdateInfos(void)\r
-{\r
- size_t Adr;\r
- char *Ptr;\r
-\r
- if (NbLocal = DBGManager_GetNbLocalVariables(Adr = m68k_get_reg(NULL, M68K_REG_PC)))\r
- {\r
- if (Ptr = DBGManager_GetFunctionName(Adr))\r
- {\r
- if (strcmp(FuncName, Ptr))\r
- {\r
- if (FuncName = (char *)realloc(FuncName, strlen(Ptr) + 1))\r
- {\r
- strcpy(FuncName, Ptr);\r
-\r
- if (LocalInfo = (WatchInfo *)realloc(LocalInfo, (sizeof(WatchInfo) * NbLocal)))\r
- {\r
- for (size_t i = 0; i < NbLocal; i++)\r
- {\r
- // Get local variable name and his information\r
- if (LocalInfo[i].PtrVariableName = DBGManager_GetLocalVariableName(Adr, i + 1))\r
- {\r
- LocalInfo[i].Op = DBGManager_GetLocalVariableOp(Adr, i + 1);\r
- LocalInfo[i].Adr = NULL;\r
- LocalInfo[i].PtrCPURegisterName = NULL;\r
- LocalInfo[i].TypeTag = DBGManager_GetLocalVariableTypeTag(Adr, i + 1);\r
- LocalInfo[i].PtrVariableBaseTypeName = DBGManager_GetLocalVariableTypeName(Adr, i + 1);\r
- LocalInfo[i].TypeEncoding = DBGManager_GetLocalVariableTypeEncoding(Adr, i + 1);\r
- LocalInfo[i].TypeByteSize = DBGManager_GetLocalVariableTypeByteSize(Adr, i + 1);\r
- LocalInfo[i].Offset = DBGManager_GetLocalVariableOffset(Adr, i + 1);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- return true;\r
- }\r
- }\r
-\r
- *FuncName = 0;\r
-\r
- return false;\r
-}\r
-\r
-\r
-//\r
-void LocalBrowserWindow::RefreshContents(void)\r
-{\r
-#ifdef LOCAL_LAYOUTTEXTS\r
- char string[1024];\r
-#endif\r
- size_t Error = LOCAL_NOERROR;\r
- QString Local;\r
- QString MSG;\r
- char Value1[100];\r
-#ifdef LOCAL_SUPPORTARRAY\r
- char Value[100];\r
-#endif\r
- char *PtrValue;\r
-\r
- const char *CPURegName[] = { "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" };\r
-\r
- if (isVisible())\r
- {\r
-#ifndef LOCAL_LAYOUTTEXTS\r
- model->setRowCount(0);\r
-#endif\r
- if (UpdateInfos())\r
- {\r
- for (size_t i = 0; i < NbLocal; i++)\r
- {\r
- if (LocalInfo[i].PtrVariableName)\r
- {\r
- memset(Value1, 0, sizeof(Value1));\r
-#ifdef LOCAL_LAYOUTTEXTS\r
- if (i)\r
- {\r
- Local += QString("<br>");\r
- }\r
-#else\r
- model->insertRow(i);\r
-#endif\r
- // Local or parameters variables\r
- if (((LocalInfo[i].Op >= DBG_OP_breg0) && (LocalInfo[i].Op <= DBG_OP_breg31)) || (LocalInfo[i].Op == DBG_OP_fbreg))\r
- {\r
- LocalInfo[i].Adr = m68k_get_reg(NULL, M68K_REG_A6) + LocalInfo[i].Offset;\r
-\r
- if ((LocalInfo[i].Op == DBG_OP_fbreg))\r
- {\r
- LocalInfo[i].Adr += 8;\r
- }\r
-\r
- if ((LocalInfo[i].Adr >= 0) && (LocalInfo[i].Adr < vjs.DRAM_size))\r
- {\r
- if ((LocalInfo[i].TypeTag & (DBG_TAG_TYPE_array | DBG_TAG_TYPE_structure)))\r
- {\r
-#if defined(LOCAL_SUPPORTARRAY) || defined(LOCAL_SUPPORTSTRUCTURE)\r
- //memcpy(Value1, &jaguarMainRAM[LocalInfo[i].Adr], 20);\r
-#ifdef LOCAL_LAYOUTTEXTS\r
- //sprintf(Value, "\"%s\"", Value1);\r
-#else\r
- //sprintf(Value, "0x%06X, \"%s\"", LocalInfo[i].Adr, Value1);\r
-#endif\r
- //PtrValue = Value;\r
- PtrValue = NULL;\r
-#else\r
- PtrValue = NULL;\r
-#endif\r
- }\r
- else\r
- {\r
- PtrValue = DBGManager_GetVariableValueFromAdr(LocalInfo[i].Adr, LocalInfo[i].TypeEncoding, LocalInfo[i].TypeByteSize);\r
- }\r
- }\r
- else\r
- {\r
- PtrValue = NULL;\r
- }\r
- }\r
- else\r
- {\r
- // Value from CPU register\r
- if ((LocalInfo[i].Op >= DBG_OP_reg0) && (LocalInfo[i].Op <= DBG_OP_reg31))\r
- {\r
- LocalInfo[i].PtrCPURegisterName = (char *)CPURegName[(LocalInfo[i].Op - DBG_OP_reg0)];\r
- sprintf(Value1, "%d", m68k_get_reg(NULL, (m68k_register_t)((size_t)M68K_REG_D0 + (LocalInfo[i].Op - DBG_OP_reg0))));\r
- PtrValue = Value1;\r
- }\r
- else\r
- {\r
- PtrValue = NULL;\r
- }\r
- }\r
-\r
-#ifndef LOCAL_LAYOUTTEXTS\r
- model->setItem(i, 0, new QStandardItem(QString("%1").arg(LocalInfo[i].PtrVariableName)));\r
-#endif\r
- // Check if the local variable is use by the code\r
- if (!LocalInfo[i].Op)\r
- {\r
-#ifdef LOCAL_LAYOUTTEXTS\r
- sprintf(string, "<font color='#A52A2A'>%i : %s | %s | [Not used]</font>", (i + 1), (LocalInfo[i].PtrVariableBaseTypeName ? LocalInfo[i].PtrVariableBaseTypeName : (char *)"<font color='#ff0000'>N/A</font>"), LocalInfo[i].PtrVariableName);\r
-#else\r
-#endif\r
- }\r
- else\r
- {\r
-#ifndef LOCAL_LAYOUTTEXTS\r
- model->setItem(i, 1, new QStandardItem(QString("%1").arg(PtrValue)));\r
-#else\r
- sprintf(string, "%i : %s | %s | ", (i + 1), (LocalInfo[i].PtrVariableBaseTypeName ? LocalInfo[i].PtrVariableBaseTypeName : (char *)"<font color='#ff0000'>N/A</font>"), LocalInfo[i].PtrVariableName);\r
- Local += QString(string);\r
-\r
- if ((unsigned int)LocalInfo[i].Adr)\r
- {\r
- sprintf(string, "0x%06X", (unsigned int)LocalInfo[i].Adr);\r
- }\r
- else\r
- {\r
- if (LocalInfo[i].PtrCPURegisterName)\r
- {\r
- sprintf(string, "<font color='#0000FF'>%s</font>", LocalInfo[i].PtrCPURegisterName);\r
- }\r
- else\r
- {\r
- sprintf(string, "%s", (char *)"<font color='#ff0000'>N/A</font>");\r
- }\r
- }\r
-\r
- Local += QString(string);\r
- sprintf(string, " | %s", (!PtrValue ? (char *)"<font color='#ff0000'>N/A</font>" : PtrValue));\r
-#endif\r
- }\r
-#ifndef LOCAL_LAYOUTTEXTS\r
- model->setItem(i, 2, new QStandardItem(QString("%1").arg((LocalInfo[i].PtrVariableBaseTypeName ? LocalInfo[i].PtrVariableBaseTypeName : (char *)"<font color='#ff0000'>N/A</font>"))));\r
-#else\r
- Local += QString(string);\r
-#endif\r
- }\r
- }\r
-\r
- MSG += QString("Ready");\r
-#ifdef LOCAL_LAYOUTTEXTS\r
- text->clear();\r
- text->setText(Local);\r
-#endif\r
- }\r
- else\r
- {\r
- // No locals\r
- MSG += QString("No locals");\r
- Error = LOCAL_NOLOCALS;\r
-#ifdef LOCAL_LAYOUTTEXTS\r
- text->clear();\r
-#endif\r
- }\r
-\r
- // Display status bar\r
- if (Error)\r
- {\r
- if ((Error & LOCAL_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(MSG);\r
- }\r
-}\r
-\r
-\r
-// \r
-void LocalBrowserWindow::keyPressEvent(QKeyEvent * e)\r
-{\r
- if (e->key() == Qt::Key_Escape)\r
- {\r
- hide();\r
- }\r
-}\r
+//\r
+// localbrowser.cpp - Local variables\r
+//\r
+// by Jean-Paul Mari\r
+//\r
+// JPM = Jean-Paul Mari <djipi.mari@gmail.com>\r
+// RG = Richard Goedeken\r
+//\r
+// Who When What\r
+// --- ---------- -----------------------------------------------------------\r
+// JPM 11/03/2017 Created this file\r
+// JPM Sept./2018 Added a status bar and better status report, and set information values in a tab\r
+// RG Jan./2021 Linux build fixes\r
+// JPM May/2021 Display the structure's members\r
+//\r
+\r
+// STILL TO DO:\r
+// Feature to list the pointer(s) in the code using the allocation\r
+// To set the information display at the right\r
+// To support the array\r
+// To support the union\r
+// To support the static variables\r
+// To add a filter\r
+//\r
+\r
+#include <stdlib.h>\r
+\r
+#include "debugger/localbrowser.h"\r
+#include "memory.h"\r
+#include "debugger/DBGManager.h"\r
+#include "settings.h"\r
+#include "m68000/m68kinterface.h"\r
+\r
+\r
+// \r
+LocalBrowserWindow::LocalBrowserWindow(QWidget * parent/*= 0*/) : QWidget(parent, Qt::Dialog),\r
+layout(new QVBoxLayout),\r
+TableView(new QTreeView),\r
+model(new QStandardItemModel),\r
+NbLocal(0),\r
+FuncName(NULL),\r
+LocalInfo(NULL),\r
+statusbar(new QStatusBar)\r
+{\r
+ setWindowTitle(tr("Locals"));\r
+#ifdef LOCAL_FONTS\r
+ // Set the font\r
+ QFont fixedFont("Lucida Console", 8, QFont::Normal);\r
+ fixedFont.setStyleHint(QFont::TypeWriter);\r
+#endif\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
+#ifdef LOCAL_FONTS\r
+ TableView->setFont(fixedFont);\r
+#endif\r
+ layout->addWidget(TableView);\r
+\r
+ // Status bar\r
+ layout->addWidget(statusbar);\r
+ setLayout(layout);\r
+}\r
+\r
+\r
+//\r
+LocalBrowserWindow::~LocalBrowserWindow(void)\r
+{\r
+ free(LocalInfo);\r
+}\r
+\r
+\r
+// Get the local variables information\r
+// Return true for a new local variables set\r
+bool LocalBrowserWindow::UpdateInfos(void)\r
+{\r
+ size_t Adr;\r
+ char *Ptr;\r
+\r
+ // get number of local variables located in the M68K PC address\r
+ if ((NbLocal = DBGManager_GetNbVariables(Adr = m68k_get_reg(NULL, M68K_REG_PC))))\r
+ {\r
+ // get function name from the M68K PC address\r
+ if ((Ptr = DBGManager_GetFunctionName(Adr)))\r
+ {\r
+ // avoid to read the same information in case of the function has not changed\r
+ if (!FuncName || strcmp(FuncName, Ptr))\r
+ {\r
+ // function is different\r
+ FuncName = Ptr;\r
+ if (LocalInfo = (S_LocalInfo*)realloc(LocalInfo, (sizeof(S_LocalInfo) * NbLocal)))\r
+ {\r
+ for (size_t i = 0; i < NbLocal; i++)\r
+ {\r
+ // get local variable name and his information\r
+ if ((LocalInfo[i].PtrVariable = DBGManager_GetInfosVariable(Adr, i + 1)))\r
+ {\r
+ LocalInfo[i].Adr = 0;\r
+ LocalInfo[i].PtrCPURegisterName = NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+\r
+ FuncName = NULL;\r
+\r
+ return false;\r
+}\r
+\r
+\r
+// Prepare a complete row based on the variable information\r
+// The row will append rows if necessary\r
+QList<QStandardItem *> LocalBrowserWindow::prepareRow(void* Info)\r
+{\r
+ // set the list\r
+ QList<QStandardItem *> ptrRow = { new QStandardItem(((S_VariablesStruct*)Info)->PtrName), new QStandardItem(""), new QStandardItem(((S_VariablesStruct*)Info)->PtrTypeName) };\r
+\r
+ // check if variable has additional variables (such as structure)\r
+ if (size_t nb = ((S_VariablesStruct*)Info)->NbTabVariables)\r
+ {\r
+ for (size_t i = 0; i < nb; i++)\r
+ {\r
+ ptrRow.first()->appendRow(prepareRow(((S_VariablesStruct*)Info)->TabVariables[i]));\r
+ }\r
+ }\r
+\r
+ // return the list\r
+ return ptrRow;\r
+}\r
+\r
+\r
+// Set the values of each line in accordance of the rows created from prepareRow() function\r
+void LocalBrowserWindow::setValueRow(QStandardItem *Row, size_t Adr, char* Value, void* Info)\r
+{\r
+ QStandardItem *child = Row->child(0, 1);\r
+ if (child)\r
+ {\r
+ // check if variable has additional variables list (such as structure)\r
+ if (size_t nb = ((S_VariablesStruct*)Info)->NbTabVariables)\r
+ {\r
+ // get the pointer's value\r
+ Adr = GET32(jagMemSpace, Adr);\r
+\r
+ for (size_t i = 0; i < nb; i++)\r
+ {\r
+ // do not display arrays\r
+ if (!((((S_VariablesStruct*)Info)->TabVariables[i]->TypeTag & DBG_TAG_TYPE_array)))\r
+ {\r
+ // set value in the row\r
+ Value = DBGManager_GetVariableValueFromAdr(Adr + ((S_VariablesStruct*)Info)->TabVariables[i]->Offset, ((S_VariablesStruct*)Info)->TabVariables[i]->TypeEncoding, ((S_VariablesStruct*)Info)->TabVariables[i]->TypeByteSize);\r
+ child = Row->child((int)i, 1);\r
+ child->setText(QString("%1").arg(Value));\r
+ setValueRow(child, Adr + ((S_VariablesStruct*)Info)->TabVariables[i]->Offset, Value, (void*)((S_VariablesStruct*)Info)->TabVariables[i]);\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+// Refresh the local and/or parameters contents list\r
+void LocalBrowserWindow::RefreshContents(void)\r
+{\r
+ size_t Error = LOCAL_NOERROR;\r
+ QString Local;\r
+ QString MSG;\r
+ char Value1[100];\r
+ char *PtrValue;\r
+\r
+ // local variables may come from M68K registers\r
+ const char *CPURegName[] = { "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" };\r
+\r
+ // refresh only if local's window is displayed\r
+ if (isVisible())\r
+ {\r
+ // get local's information\r
+ if (UpdateInfos())\r
+ {\r
+ // erase the previous variables list\r
+ model->setRowCount(0);\r
+\r
+ // loop on the locals found\r
+ for (size_t i = 0; i < NbLocal; i++)\r
+ {\r
+ // check variable's name validity\r
+ if (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->PtrName)\r
+ {\r
+ // insert the row\r
+ model->appendRow(prepareRow(LocalInfo[i].PtrVariable));\r
+\r
+ // check if the local variable is use by the code\r
+ if (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op)\r
+ {\r
+ // local or parameters variables\r
+ if (((((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op >= DBG_OP_breg0) && (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op <= DBG_OP_breg31)) || (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op == DBG_OP_fbreg))\r
+ {\r
+ // get variable's address\r
+ LocalInfo[i].Adr = m68k_get_reg(NULL, M68K_REG_A6) + ((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Offset;\r
+ // check variable's parameter op\r
+ if ((((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op == DBG_OP_fbreg))\r
+ {\r
+ LocalInfo[i].Adr += 8;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // variable type from CPU register\r
+ if ((((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op >= DBG_OP_reg0) && (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op <= DBG_OP_reg31))\r
+ {\r
+ // set color text for a register type variable\r
+ model->item((int)i, 0)->setForeground(QColor(0, 0, 0xfe));\r
+ model->item((int)i, 1)->setForeground(QColor(0, 0, 0xfe));\r
+ model->item((int)i, 2)->setForeground(QColor(0, 0, 0xfe));\r
+ // get the register's name\r
+ LocalInfo[i].PtrCPURegisterName = (char *)CPURegName[(((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op - DBG_OP_reg0)];\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // set color text for unused variable (no need to set it for the value's field as no values will be displayed)\r
+ model->item((int)i, 0)->setForeground(QColor(0xc8, 0xc8, 0xc8));\r
+ model->item((int)i, 2)->setForeground(QColor(0xc8, 0xc8, 0xc8));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // set the values in the fields\r
+ if (NbLocal)\r
+ {\r
+ // loop on the locals found\r
+ for (size_t i = 0; i < NbLocal; i++)\r
+ {\r
+ // variable's address must fit in RAM\r
+ if ((LocalInfo[i].Adr >= 4) && (LocalInfo[i].Adr < vjs.DRAM_size))\r
+ {\r
+ // get the variable's value\r
+ PtrValue = DBGManager_GetVariableValueFromAdr(LocalInfo[i].Adr, ((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->TypeEncoding, ((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->TypeByteSize);\r
+ }\r
+ else\r
+ {\r
+ // check CPU register's type variable\r
+ if (LocalInfo[i].PtrCPURegisterName)\r
+ {\r
+ // get the value from register\r
+ memset(Value1, 0, sizeof(Value1));\r
+ sprintf(Value1, "0x%x", m68k_get_reg(NULL, (m68k_register_t)((size_t)M68K_REG_D0 + (((S_VariablesStruct*)(LocalInfo[i].PtrVariable))->Op - DBG_OP_reg0))));\r
+ PtrValue = Value1;\r
+ }\r
+ else\r
+ {\r
+ // no value can be found\r
+ PtrValue = NULL;\r
+ }\r
+ }\r
+\r
+ // do not display arrays\r
+ if (!(((S_VariablesStruct*)LocalInfo[i].PtrVariable)->TypeTag & DBG_TAG_TYPE_array))\r
+ {\r
+ // set the local's variable value\r
+ model->item((int)i, 1)->setText(QString("%1").arg(PtrValue));\r
+ setValueRow(model->item((int)i), LocalInfo[i].Adr, PtrValue, (S_VariablesStruct*)(LocalInfo[i].PtrVariable));\r
+ }\r
+ }\r
+\r
+ MSG += QString("Ready");\r
+ }\r
+ else\r
+ {\r
+ // erase the previous variables list\r
+ model->setRowCount(0);\r
+\r
+ // No locals\r
+ MSG += QString("No locals");\r
+ Error = LOCAL_NOLOCALS;\r
+ }\r
+\r
+ // display status bar\r
+ if (Error)\r
+ {\r
+ if ((Error & LOCAL_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(MSG);\r
+ }\r
+}\r
+\r
+\r
+// Handle keyboard actions\r
+void LocalBrowserWindow::keyPressEvent(QKeyEvent * e)\r
+{\r
+ // close / hide the window\r
+ if (e->key() == Qt::Key_Escape)\r
+ {\r
+ hide();\r
+ }\r
+}\r