diff --git a/LinkScope.pro b/LinkScope.pro index e20c9f8..3a2421c 100644 --- a/LinkScope.pro +++ b/LinkScope.pro @@ -19,6 +19,7 @@ DEFINES += QT_DEPRECATED_WARNINGS \ SOURCES += \ aboutwindow.cpp \ + gdbprocess.cpp \ graphwindow.cpp \ helpwindow.cpp \ listwindow.cpp \ @@ -27,6 +28,7 @@ SOURCES += \ HEADERS += \ aboutwindow.h \ + gdbprocess.h \ graphwindow.h \ helpwindow.h \ listwindow.h \ diff --git a/LinkScope.pro.user b/LinkScope.pro.user index da2022c..948f7e3 100644 --- a/LinkScope.pro.user +++ b/LinkScope.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/gdbprocess.cpp b/gdbprocess.cpp new file mode 100644 index 0000000..46aeb9b --- /dev/null +++ b/gdbprocess.cpp @@ -0,0 +1,182 @@ +#include "gdbprocess.h" + +GDBProcess::GDBProcess(QObject *parent) : QObject(parent) +{ + process=new QProcess(); +} + +GDBProcess::~GDBProcess() +{ + delete process; +} + +//运行一条GDB命令并获取输出字符串 +QString GDBProcess::runCmd(const QString &cmd) +{ + process->readAllStandardOutput(); + process->write(cmd.toStdString().c_str()); + QString res=""; + do{ + process->waitForReadyRead(); + res+=process->readAllStandardOutput(); + }while(!res.endsWith("(gdb) ")); + return res; +} + +//启动GDB进程 +void GDBProcess::start() +{ + process->setProgram(QCoreApplication::applicationDirPath()+"/gdb/gdb.exe");//设置程序路径 + process->setWorkingDirectory(QCoreApplication::applicationDirPath()+"/gdb");//设置工作路径 + process->setNativeArguments("-q");//设置gdb在安静模式下打开 + process->start(); + runCmd("set confirm off\r\n");//设置不要手动确认 + runCmd("set print pretty on\r\n");//设置结构体规范打印 +} + +//停止GDB进程 +void GDBProcess::stop() +{ + if(process->state()!=QProcess::NotRunning) + process->kill(); +} + +//命令GDB连接到远程目标,参数为"地址:端口号" +void GDBProcess::connectToRemote(const QString &addr) +{ + runCmd("target remote "+addr+"\r\n"); +} + +//命令GDB从远处目标断开 +void GDBProcess::disconnectFromRemote() +{ + runCmd("disconnect\r\n"); +} + +//设定临时符号文件名,文件位于GDB程序目录下 +void GDBProcess::setTempSymbolFileName(const QString &name) +{ + tempSymbolFileName=name; +} + +//加载符号文件,将指定文件复制到临时文件中,并加载到GDB中 +void GDBProcess::loadSymbolFile(const QString &path) +{ + unloadSymbolFile();//确保卸载当前的临时文件 + QString tempPath=QCoreApplication::applicationDirPath()+"/gdb/"+tempSymbolFileName;//拼接临时文件路径 + QFile::copy(path,tempPath);//将所选符号文件复制为临时文件 + runCmd("symbol-file "+tempSymbolFileName+"\r\n");//设置符号文件 +} + +//卸载符号文件 +void GDBProcess::unloadSymbolFile() +{ + runCmd("symbol-file\r\n");//取消符号文件,解除文件占用 + QString tempPath=QCoreApplication::applicationDirPath()+"/gdb/"+tempSymbolFileName;//拼接临时文件路径 + QFile::remove(tempPath);//删除复制过来的临时文件 +} + +//设置display列表 +void GDBProcess::setDisplayList(QStringList &list) +{ + runCmd("delete display\r\n");//删除之前发送的变量列表 + foreach(QString name,list)//向display表中依次添加变量名 + runCmd("display "+name+"\r\n"); +} + +//截取display指令所返回字符串中指定变量名的变量值 +QString GDBProcess::captureValueFromDisplay(const QString &rawDisplay, const QString &name) +{ + QString regName=""; + for(int i=0;i +#include +#include +#include +#include + +class GDBProcess : public QObject +{ + Q_OBJECT +public: + explicit GDBProcess(QObject *parent = nullptr); + ~GDBProcess(); + QString runCmd(const QString &cmd); + void start(); + void stop(); + void connectToRemote(const QString &addr); + void disconnectFromRemote(); + void setTempSymbolFileName(const QString &name); + void loadSymbolFile(const QString &path); + void unloadSymbolFile(); + void setDisplayList(QStringList &list); + QString captureValueFromDisplay(const QString &rawDisplay,const QString &name); + bool getDoubleFromDisplayValue(const QString &rawValue,double &result); + void setVarValue(const QString &varFullName,double value); + bool checkExpandableType(const QString &varFullName); + QStringList getVarListFromRawOutput(const QString &rawVarList); + void removeInnerSection(QString &raw,int offset); + +private: + QProcess *process; + QString tempSymbolFileName; +}; + +#endif // GDBPROCESS_H diff --git a/listwindow.cpp b/listwindow.cpp index fa26500..7ef8f3b 100644 --- a/listwindow.cpp +++ b/listwindow.cpp @@ -11,114 +11,20 @@ ListWindow::ListWindow(QWidget *parent) : treeModel=new QStandardItemModel(ui->tree); ui->tree->setModel(treeModel); - gdbProcess=new QProcess(); - - setGDBState(true);//启动GDB进程 + gdb=new GDBProcess();//创建并启动GDB + gdb->setTempSymbolFileName("tmp_list");//设定临时符号文件名 + gdb->start(); } ListWindow::~ListWindow() { - deleteTempFile();//删除临时文件 - setGDBState(false);//结束GDB进程 - delete gdbProcess; + gdb->unloadSymbolFile();//删除临时文件 + gdb->stop();//结束GDB进程 + delete gdb; delete treeModel; delete ui; } -//设置GDB进程状态 -void ListWindow::setGDBState(bool run) -{ - if(run)//启动进程 - { - gdbProcess->setProgram(QCoreApplication::applicationDirPath()+"/gdb/gdb.exe");//设置程序路径 - gdbProcess->setWorkingDirectory(QCoreApplication::applicationDirPath()+"/gdb");//设置工作路径 - gdbProcess->setNativeArguments("-q");//设置gdb在安静模式下打开 - gdbProcess->start(); - runGDBCmd("set confirm off\r\n");//设置不要手动确认 - runGDBCmd("set print pretty on\r\n");//设置结构体规范打印 - } - else//结束进程 - { - gdbProcess->kill(); - } -} - -//向GDB进程发送命令并获取标准输出 -QString ListWindow::runGDBCmd(const QString &input) -{ - gdbProcess->readAllStandardOutput(); - gdbProcess->write(input.toStdString().c_str()); - QString res=""; - do{ - gdbProcess->waitForReadyRead(); - res+=gdbProcess->readAllStandardOutput(); - }while(!res.endsWith("(gdb) ")); - return res; -} - -//使用GDB检查变量名是否为可展开类型 -bool ListWindow::checkCanExpand(const QString &varFullName) -{ - QString whatis=runGDBCmd(QString("whatis %1\r\n").arg(varFullName));//先使用whatis指令判断数组和函数指针 - whatis.remove("type = "); - whatis.remove("\r\n(gdb) "); - if(whatis.contains("[")) - return true; - if(whatis.contains('(')) - return false; - QString ptype=runGDBCmd(QString("ptype %1\r\n").arg(varFullName));//再使用ptype指令判断是否是其他可展开类型 - ptype.remove("type = "); - if(ptype.startsWith("struct")||ptype.startsWith("union")) - return true; - return false; -} - -//从原始变量列表字符串中解析出变量列表 -QStringList ListWindow::parseVarList(const QString &raw) -{ - QStringList list; - QRegExp rootRx("\\s([^ (]*\\(\\*|)([^ )]+)(\\)\\(.*\\)|\\s:\\s\\d+|);");//正则匹配模板 - rootRx.setMinimal(true);//非贪心匹配 - int pos=0; - while((pos=rootRx.indexIn(raw,pos))!=-1) - { - QString name=rootRx.cap(2);//获取截取出的变量名部分 - if(name.contains('*'))//手动剔除'*' - name.remove('*'); - if(name.contains('['))//手动剔除数组长度部分 - name.remove(QRegExp("\\[\\d+\\]")); - list.append(name); - pos+=rootRx.matchedLength(); - } - return list; -} - -//删除一个原始变量列表字符串中的嵌套部分,跳过前offset个字符 -void ListWindow::removeInnerSection(QString &raw,int offset) -{ - for(int startPos=offset;startPosrunCmd("info variables\r\n");//使用info variables指令列出axf中所有变量 + QStringList varList=gdb->getVarListFromRawOutput(rawVarList);//解析出变量列表 foreach(QString name,varList)//依次添加子节点并更新可展开状态 { node.append(name); - node.children.last().canExpand=checkCanExpand(getVarFullName(node.children.last())); + node.children.last().expandable=gdb->checkExpandableType(getVarFullName(node.children.last())); } } else//传入的是普通节点 { QString fullName=getVarFullName(node);//计算节点全名 - QString rawVarType=runGDBCmd(QString("whatis %1\r\n").arg(fullName));//使用whatis指令获取类型 + QString rawVarType=gdb->runCmd(QString("whatis %1\r\n").arg(fullName));//使用whatis指令获取类型 rawVarType.remove("type = "); rawVarType.remove("\r\n(gdb) "); if(rawVarType.contains("["))//判定是否为数组类型 @@ -164,24 +70,24 @@ void ListWindow::parseVarChildren(VarNode &node) { node.append(QString("[%1]").arg(i)); if(i==0)//若是第一个元素,计算是否可展开 - node.children[0].canExpand=checkCanExpand(getVarFullName(node.children[0])); + node.children[0].expandable=gdb->checkExpandableType(getVarFullName(node.children[0])); else//若不是第一个元素,直接用前一个元素的可展开状态即可 - node.children[i].canExpand=node.children[i-1].canExpand; + node.children[i].expandable=node.children[i-1].expandable; } } else if(!rawVarType.contains('('))//不是数组类型,排除函数类型,判定是否为可展开类型 { - QString detailRawVarType=runGDBCmd(QString("ptype %1\r\n").arg(fullName));//用ptype指令获取详细类型 + QString detailRawVarType=gdb->runCmd(QString("ptype %1\r\n").arg(fullName));//用ptype指令获取详细类型 detailRawVarType.remove("type = "); detailRawVarType.remove("\r\n(gdb) "); if(detailRawVarType.startsWith("struct")||detailRawVarType.startsWith("union"))//判定为可展开类型 { - removeInnerSection(detailRawVarType,detailRawVarType.indexOf('{')+1);//移除内部直接嵌套的部分 - QStringList varList=parseVarList(detailRawVarType);//解析出变量列表 + gdb->removeInnerSection(detailRawVarType,detailRawVarType.indexOf('{')+1);//移除内部直接嵌套的部分 + QStringList varList=gdb->getVarListFromRawOutput(detailRawVarType);//解析出变量列表 foreach(QString name,varList)//依次添加子节点及其可展开状态 { node.append(name); - node.children.last().canExpand=checkCanExpand(getVarFullName(node.children.last())); + node.children.last().expandable=gdb->checkExpandableType(getVarFullName(node.children.last())); } } } @@ -192,31 +98,15 @@ void ListWindow::parseVarChildren(VarNode &node) //加载AXF文件 void ListWindow::loadNewAxfFile(const QString &path) { - updateTempFile(path);//更新AXF文件配置 + gdb->loadSymbolFile(path); updateTree();//更新树状图 } -//更新临时文件 -void ListWindow::updateTempFile(const QString &path) -{ - QString tmpFilePath=QCoreApplication::applicationDirPath()+"/gdb/tmp_list";//临时符号文件路径 - deleteTempFile();//确保删除当前的临时文件 - QFile::copy(path,tmpFilePath);//将所选符号文件复制为临时文件 - runGDBCmd("symbol-file tmp_list \r\n");//设置符号文件 -} - -//删除临时文件 -void ListWindow::deleteTempFile() -{ - runGDBCmd("symbol-file\r\n");//取消符号文件,解除文件占用 - QFile::remove(QCoreApplication::applicationDirPath()+"/gdb/tmp_list");//删除复制过来的临时文件 -} - //更新整个树状图和节点树 void ListWindow::updateTree() { varTree.clear();//从根节点开始递归清理 - varTree.canExpand=true;//设定根节点可展开 + varTree.expandable=true;//设定根节点可展开 QStandardItem *rootItem=new QStandardItem("");//创建根节点对应的item rootItem->setData((qlonglong)&varTree);//将item的数据指向根节点 @@ -241,7 +131,7 @@ void ListWindow::on_tree_expanded(const QModelIndex &index) QStandardItem *childItem=new QStandardItem();//创建item childItem->setText(childNode.name);//设定item显示变量名 childItem->setData((qlonglong)&childNode);//建立item到对应节点的寻址方式 - if(childNode.canExpand)//若该子节点可展开,则添加一个空item使其显示为可展开状态 + if(childNode.expandable)//若该子节点可展开,则添加一个空item使其显示为可展开状态 childItem->appendRow(new QStandardItem()); item->appendRow(childItem);//子节点item附加到当前被展开的item下 } diff --git a/listwindow.h b/listwindow.h index cea289e..a878379 100644 --- a/listwindow.h +++ b/listwindow.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace Ui { class ListWindow; @@ -19,7 +20,7 @@ public: QString name;//变量名 QList children;//子节点 VarNode *parent=NULL;//父节点 - bool canExpand=false;//可展开状态,即该变量类型是否可被展开 + bool expandable=false;//可展开状态,即该变量类型是否可被展开 bool parsed=false;//是否已经解析出子节点信息 VarNode(const QString &_name="",VarNode *_parent=NULL) { @@ -35,7 +36,7 @@ public: { children.clear(); name=""; - canExpand=parsed=false; + expandable=parsed=false; } }; @@ -60,17 +61,11 @@ private slots: private: Ui::ListWindow *ui; QProcess *gdbProcess; + GDBProcess *gdb; VarNode varTree; QStandardItemModel *treeModel; - void setGDBState(bool run); - QString runGDBCmd(const QString &input); - QStringList parseVarList(const QString &raw); - void removeInnerSection(QString &raw,int offset=0); QString getVarFullName(const VarNode &node); - bool checkCanExpand(const QString &varFullName); void parseVarChildren(VarNode &node); - void updateTempFile(const QString &path); - void deleteTempFile(); void updateTree(); }; diff --git a/mainwindow.cpp b/mainwindow.cpp index 349093f..47016d9 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -38,8 +38,9 @@ MainWindow::MainWindow(QWidget *parent) ocdProcess=new QProcess(0);//创建openocd进程 connect(ocdProcess,SIGNAL(readyReadStandardError()),this,SLOT(slotOCDErrorReady())); - gdbProcess=new QProcess(0);//创建并运行gdb进程 - setGDBState(true); + gdb=new GDBProcess();//创建并启动GDB + gdb->setTempSymbolFileName("tmp");//设定临时符号文件名 + gdb->start(); loadConfFileList();//从openocd文件夹中读取配置文件列表 } @@ -47,12 +48,15 @@ MainWindow::MainWindow(QWidget *parent) MainWindow::~MainWindow() { if(connected)//若处于连接状态则断开连接 - setConnState(false); - setGDBState(false);//结束gdb进程 + { + gdb->disconnectFromRemote(); + gdb->unloadSymbolFile(); + } + gdb->stop();//结束gdb进程 delete ui; delete tableModel; delete ocdProcess; - delete gdbProcess; + delete gdb; delete stampTimer; delete watchTimer; delete tableTimer; @@ -121,7 +125,12 @@ void MainWindow::slotTableEdit(QModelIndex topleft, QModelIndex bottomright) redrawTable();//重绘表格 if(connected)//若正在连接状态则向gdb发送新的变量列表 - setGDBDispList(); + { + QStringList nameList; + for(int index=0;indexsetDisplayList(nameList); + } } } else if(topleft.column()==2 && topleft.row()!=varList.size())//若编辑的是第二列,表示需进行变量值修改 @@ -130,7 +139,7 @@ void MainWindow::slotTableEdit(QModelIndex topleft, QModelIndex bottomright) QString valueStr=tableModel->item(topleft.row(),2)->text(); if(!valueStr.isEmpty()) { - setVar(name,valueStr.toDouble());//向gdb发送命令写入变量值 + gdb->setVarValue(name,valueStr.toDouble());//向gdb发送命令写入变量值 tableModel->item(topleft.row(),2)->setText("");//清空编辑框 } } @@ -143,9 +152,18 @@ void MainWindow::slotWatchTimerTrig() return; isWatchProcessing=true; - QString rawGDB; - getGDBRawDisp(rawGDB);//获取gdb查看得到的原始值 - parseGDBRawDisp(rawGDB);//进行正则匹配,更新变量列表内容 + qint64 timestamp=stampTimer->nsecsElapsed()/1000;//获取时间戳 + QString rawDisplay=gdb->runCmd("display\r\n");//获取gdb查看得到的原始值 + for(int index=0;indexcaptureValueFromDisplay(rawDisplay,varList.at(index).name);//进行正则匹配,截取出变量值部分 + SamplePoint sample; + if(gdb->getDoubleFromDisplayValue(varList[index].rawValue,sample.value))//尝试转换为double,生成采样点并写入采样点列表 + { + sample.timestamp=timestamp; + varList[index].samples.append(sample); + } + } isWatchProcessing=false; } @@ -179,7 +197,9 @@ void MainWindow::slotOnVarAdd2Edit(const QString &name) //选择器窗口添加到列表槽函数 void MainWindow::slotOnVarAdd2List(const QString &name) { - tableModel->item(tableModel->rowCount()-1,0)->setText(name); + QStandardItem *editItem=tableModel->item(tableModel->rowCount()-1,0); + editItem->setText("");//清空编辑框 + editItem->setText(name);//在编辑框中填入变量名,会直接添加到列表中 } //连接按钮点击,触发连接状态切换 @@ -207,14 +227,23 @@ void MainWindow::setConnState(bool connect) sleep(500);//等待500ms if(ocdProcess->state()==QProcess::Running)//若ocd成功启动 { - setGDBConnState(true);//连接gdb到ocd + gdb->loadSymbolFile(ui->txt_axf_path->text());//设置gdb符号文件 + gdb->connectToRemote("localhost:3333");//连接gdb到ocd + QStringList nameList; + for(int index=0;indexsetDisplayList(nameList); + for(int i=0;irestart();//开启时间戳计时 watchTimer->start();//开启定时查看变量值 tableTimer->start();//开启表格定时刷新 + ui->bt_conn->setText("断开连接"); ui->bt_reset->setEnabled(true);//使能复位按钮 + connected=true;//更新连接标志 } ui->bt_conn->setEnabled(true);//恢复连接按钮 @@ -223,8 +252,9 @@ void MainWindow::setConnState(bool connect) { watchTimer->stop();//停止定时查看和定时刷新表格 tableTimer->stop(); - setGDBConnState(false);//断开gdb,停止ocd - setOCDState(false); + gdb->disconnectFromRemote();//断开gdb + gdb->unloadSymbolFile();//卸载符号文件 + setOCDState(false);//结束ocd进程 ui->bt_conn->setText("连接目标"); ui->bt_reset->setEnabled(false);//禁用复位按钮 connected=false;//更新连接标志 @@ -256,96 +286,6 @@ void MainWindow::setOCDState(bool connect) } } -//参数true:运行gdb进程;参数false:结束gdb进程 -void MainWindow::setGDBState(bool run) -{ - if(run) - { - gdbProcess->setProgram(QCoreApplication::applicationDirPath()+"/gdb/gdb.exe");//设置程序路径 - gdbProcess->setWorkingDirectory(QCoreApplication::applicationDirPath()+"/gdb");//设置工作路径 - gdbProcess->setNativeArguments("-q");//设置gdb在安静模式下打开 - gdbProcess->start(); - } - else - { - gdbProcess->kill(); - } -} - -//参数true:gdb连接到本机3333端口,设置调试参数;参数false:断开gdb连接 -void MainWindow::setGDBConnState(bool connect) -{ - QString tmpFilePath=QCoreApplication::applicationDirPath()+"/gdb/tmp";//临时符号文件路径 - if(connect) - { - gdbProcess->write("target remote localhost:3333\r\n");//连接到3333端口 - QFile::remove(tmpFilePath);//确保删除当前的临时文件 - QFile::copy(ui->txt_axf_path->text(),tmpFilePath);//将所选符号文件复制为临时文件 - gdbProcess->write(QString("symbol-file %1 \r\n").arg("tmp").toStdString().c_str());//设置符号文件 - gdbProcess->write("set confirm off\r\n");//设置不要手动确认 - gdbProcess->write("set print pretty on\r\n");//设置结构体规范打印 - setGDBDispList();//向gdb发送当前的变量列表 - } - else - { - gdbProcess->write("symbol-file\r\n");//取消符号文件 - gdbProcess->write("disconnect\r\n");//断开gdb连接 - sleep(10);//确保对临时文件取消占用 - QFile::remove(tmpFilePath);//删除复制过来的临时文件 - } -} - -//向gdb发送变量列表 -void MainWindow::setGDBDispList() -{ - gdbProcess->write("delete display\r\n");//删除之前发送的变量列表 - foreach(VarInfo info,varList) - gdbProcess->write(QString("display %1 \r\n").arg(info.name).toStdString().c_str());//向display表中依次添加变量名 -} - -//向gdb请求读取所有变量,获取返回的原始字符串 -void MainWindow::getGDBRawDisp(QString &raw) -{ - if(!connected) - return; - gdbProcess->readAllStandardOutput(); - gdbProcess->write("display\r\n");//向gdb发送display指令 - raw=""; - do{ - gdbProcess->waitForReadyRead(); - raw+=gdbProcess->readAllStandardOutput(); - }while(!raw.endsWith("(gdb) "));//不断读取直到读到字符串"gdb ",表示指令执行完成 -} - -//解析由gdb返回的display原始字符串,更新变量值 -void MainWindow::parseGDBRawDisp(QString &raw) -{ - qint64 timestamp=stampTimer->nsecsElapsed()/1000;//获取时间戳 - - for(int index=0;indexsetWindowTitle(QStringLiteral("选中文件")); fileDialog->setDirectory("."); - fileDialog->setNameFilter(tr("AXF/ELF File (*.axf *.elf)"));//设置文件过滤器为axf/elf + fileDialog->setNameFilters(QStringList()<setFileMode(QFileDialog::ExistingFile); fileDialog->setViewMode(QFileDialog::Detail); if(fileDialog->exec()) @@ -427,26 +367,6 @@ void MainWindow::redrawTable() tableModel->setItem(lastRow,0,new QStandardItem(""));//末尾添加空行,用于用户添加变量 } -//发送gdb指令,修改变量值 -void MainWindow::setVar(const QString &name, double value) -{ - if(!connected) - return; - gdbProcess->write(QString("set %1=%2\r\n").arg(name).arg(value).toStdString().c_str()); -} - -//尝试从变量值原始字符串中解析出double值,返回是否解析成功 -bool MainWindow::getValueFromRaw(const QString &rawValue,double &value) -{ - if(rawValue.isEmpty()) - return false; - if(rawValue.contains('{')||rawValue.contains('(') - ||rawValue.contains('<')||rawValue.contains('['))//若含有这些符号,表示该变量可能为复合类型,不能被解析 - return false; - value=rawValue.mid(0,rawValue.indexOf(' ')).toDouble(); - return true; -} - //保存配置到指定路径的文件 void MainWindow::saveToFile(const QString &filename) { @@ -541,7 +461,7 @@ bool MainWindow::exportCSV(const QString &filename) void MainWindow::on_bt_reset_clicked() { if(connected) - gdbProcess->write("monitor reset\r\n"); + gdb->runCmd("monitor reset\r\n"); } //表格双击事件,进行图线颜色修改 diff --git a/mainwindow.h b/mainwindow.h index ccb92c7..beac909 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -24,6 +24,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -65,7 +66,8 @@ private slots: private: Ui::MainWindow *ui; - QProcess *ocdProcess,*gdbProcess;//ocd和gdb进程指针 + QProcess *ocdProcess; + GDBProcess *gdb;//GDB进程控制 bool connected=false;//标记当前是否已连接 QStandardItemModel *tableModel;//表格数据 QList varList;//变量列表 @@ -79,17 +81,10 @@ private: void setStylesheet(); void setConnState(bool connect); void setOCDState(bool connect); - void setGDBState(bool run); - void setGDBConnState(bool connect); - void setGDBDispList(); - void getGDBRawDisp(QString &raw); - void parseGDBRawDisp(QString &raw); void sleep(uint32_t ms); void loadConfFileList(); void initTable(); void redrawTable(); - void setVar(const QString &name,double value); - bool getValueFromRaw(const QString &rawValue,double &value); void saveToFile(const QString &filename); void loadFromFile(const QString &filename); bool exportCSV(const QString &filename);