Skip to content

Commit

Permalink
选择窗口添加一层文件名节点;添加右键删除变量;添加启动时检查openocd进程;调整帮助信息样式;版本号更新至1.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Skythinker616 committed Aug 8, 2022
1 parent 033393b commit 996b3d4
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 25 deletions.
2 changes: 1 addition & 1 deletion LinkScope.pro
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ CONFIG += c++11
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS \
APP_VERSION=\\\"1.2.1\\\"
APP_VERSION=\\\"1.2.2\\\"

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
Expand Down
2 changes: 1 addition & 1 deletion LinkScope.pro.user
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.0, 2022-03-30T17:03:19. -->
<!-- Written by QtCreator 4.11.0, 2022-08-08T00:56:42. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

* 在主窗口表格最后一行变量名(编辑框)处手动填写也可以添加变量

* 在主窗口中选中变量名按Del键可删除变量
* 在变量名上右键可删除变量,或在选中变量名后按Del键

* 变量名不仅可以填入单个变量名,还可以填入合法的C语言表达式(GDB支持即可);复合类型不能修改和绘图,只能实时查看

Expand Down Expand Up @@ -112,8 +112,6 @@

## TODO

* 增加对不同文件中同名变量的区分

* 提升采样频率

* 增加对本地程序的支持
Expand Down
2 changes: 1 addition & 1 deletion aboutwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;hr width=&quot;300&quot;/&gt;&lt;p align=&quot;center&quot;&gt;版本号:V1.2.1&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;更新时间:2022/3/30&lt;/p&gt;&lt;hr width=&quot;300&quot;/&gt;&lt;p align=&quot;center&quot;&gt;Developed by Skythinker&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;hr width=&quot;300&quot;/&gt;&lt;p align=&quot;center&quot;&gt;版本号:V1.2.2&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;更新时间:2022/8/7&lt;/p&gt;&lt;hr width=&quot;300&quot;/&gt;&lt;p align=&quot;center&quot;&gt;Developed by Skythinker&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
Expand Down
51 changes: 48 additions & 3 deletions helpwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-390</y>
<y>0</y>
<width>523</width>
<height>1308</height>
<height>1283</height>
</rect>
</property>
<property name="autoFillBackground">
Expand All @@ -53,7 +53,52 @@
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;LinkScope简介&lt;/span&gt;&lt;/p&gt;&lt;p&gt;本程序使用QT编写,用于硬件设备的调试,可直接驱动串口或各种调试器(基于OpenOCD支持),有以下几个主要功能&lt;/p&gt;&lt;p&gt;1.实时查看和修改变量值&lt;/p&gt;&lt;p&gt;2.变量值波形实时绘制&lt;/p&gt;&lt;p&gt;3.采样数据导出为CSV表格&lt;/p&gt;&lt;p&gt;4.格式化日志输出&lt;/p&gt;&lt;p&gt;调试器连接模式理论上支持OpenOCD允许GDB连接的各种调试器及硬件芯片,如STLink、JLink、CMSIS-DAP等以及STM32全系列等&lt;/p&gt;&lt;hr/&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;使用方法&lt;/span&gt;&lt;/p&gt;&lt;p&gt;1.点击【设置符号文件】选择编译器输出的符号文件,然后添加变量到列表中&lt;/p&gt;&lt;p&gt;&amp;gt; 加载符号文件后即可在变量选择窗口添加需要查看的变量,可以直接添加到列表或添加到编辑框后进行手动编辑&lt;/p&gt;&lt;p&gt;&amp;gt; 在主窗口表格最后一行变量名(编辑框)处手动填写也可以添加变量&lt;/p&gt;&lt;p&gt;&amp;gt; 在主窗口中选中变量名按Del键可删除变量&lt;/p&gt;&lt;p&gt;&amp;gt; 变量名不仅可以填入单个变量名,还可以填入合法的C语言表达式(GDB支持即可);复合类型不能修改和绘图,只能实时查看&lt;/p&gt;&lt;p&gt;2.选择连接模式,连接芯片,连接后程序开始循环采样,勾选【监视日志】后即可将下位机输出的日志实时显示出来&lt;/p&gt;&lt;p&gt;&amp;gt; 调试器模式下,在下拉框中选择调试器和芯片类型,点击连接目标&lt;/p&gt;&lt;p&gt;&amp;gt; 串口模式下,点击刷新串口加载串口列表,选中所连接的串口,点击连接目标&lt;/p&gt;&lt;p&gt;&amp;gt; 串口功能和日志功能都需要修改下位机程序,可以在菜单中进入主页查看说明&lt;/p&gt;&lt;p&gt;3.编辑【修改变量】列可以修改变量值,双击【图线颜色】列可以选择绘图颜色 &lt;/p&gt;&lt;p&gt;4.单击【变量名】列选中对应的变量,可以在绘图窗口查看历史数据,并会加粗绘制 &lt;/p&gt;&lt;p&gt;5.绘图界面说明请到绘图窗口点击操作说明 &lt;/p&gt;&lt;p&gt;6.点击菜单中的保存/导入配置可以将当前配置保存到INI文件或从文件中恢复配置,点击导出数据可以将获取到的采样数据导出到CSV表格文件&lt;/p&gt;&lt;hr/&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;注意事项 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;1.修改符号文件路径后需要重新连接 &lt;/p&gt;&lt;p&gt;2.连接目标前请确认已使用该调试器为目标芯片下载过指定程序 &lt;/p&gt;&lt;p&gt;3.若程序闪退后发现下一次运行时无法连接目标,请尝试手动结束openocd.exe进程 &lt;/p&gt;&lt;p&gt;4.连接配置文件位于openocd/share/openocd/scripts下的target和interface中,用户可按照openocd语法编写配置脚本,放入对应目录下后点击“刷新连接配置”菜单项&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;
&lt;head&gt;
&lt;style&gt;
li{margin-top: 10px;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;&lt;span style=&quot;font-weight:600;&quot;&gt;LinkScope简介&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;本程序使用QT编写,用于硬件设备的调试,可直接驱动串口或各种调试器(基于OpenOCD支持),有以下几个主要功能&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;实时查看和修改变量值&lt;/li&gt;
&lt;li&gt;变量值波形实时绘制&lt;/li&gt;
&lt;li&gt;采样数据导出为CSV表格&lt;/li&gt;
&lt;li&gt;格式化日志输出&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;调试器连接模式理论上支持OpenOCD允许GDB连接的各种调试器及硬件芯片,如STLink、JLink、CMSIS-DAP等以及STM32全系列等&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;span style=&quot;font-weight:600;&quot;&gt;使用方法&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;点击【设置符号文件】选择编译器输出的符号文件,然后添加变量到列表中&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;加载符号文件后即可在变量选择窗口添加需要查看的变量,可以直接添加到列表或添加到编辑框后进行手动编辑&lt;/li&gt;
&lt;li&gt;在主窗口表格最后一行变量名(编辑框)处手动填写也可以添加变量&lt;/li&gt;
&lt;li&gt;在变量名上右键可删除变量,或在选中变量名后按Del键&lt;/li&gt;
&lt;li&gt;变量名不仅可以填入单个变量名,还可以填入合法的C语言表达式(GDB支持即可);复合类型不能修改和绘图,只能实时查看&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;选择连接模式,连接芯片,连接后程序开始循环采样,勾选【监视日志】后即可将下位机输出的日志实时显示出来&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;调试器模式下,在下拉框中选择调试器和芯片类型,点击连接目标&lt;/li&gt;
&lt;li&gt;串口模式下,点击刷新串口加载串口列表,选中所连接的串口,点击连接目标&lt;/li&gt;
&lt;li&gt;串口功能和日志功能都需要修改下位机程序,可以在菜单中进入主页查看说明&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;编辑【修改变量】列可以修改变量值,双击【图线颜色】列可以选择绘图颜色 &lt;/li&gt;
&lt;li&gt;单击【变量名】列选中对应的变量,可以在绘图窗口查看历史数据,并会加粗绘制 &lt;/li&gt;
&lt;li&gt;绘图界面说明请到绘图窗口点击操作说明 &lt;/li&gt;
&lt;li&gt;点击菜单中的保存/导入配置可以将当前配置保存到INI文件或从文件中恢复配置,点击导出数据可以将获取到的采样数据导出到CSV表格文件&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;span style=&quot;font-weight:600;&quot;&gt;注意事项 &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改符号文件路径后需要重新连接 &lt;/li&gt;
&lt;li&gt;连接目标前请确认已使用该调试器为目标芯片下载过指定程序 &lt;/li&gt;
&lt;li&gt;连接配置文件位于openocd/share/openocd/scripts下的target和interface中,用户可按照openocd语法编写配置脚本,放入对应目录下后点击“刷新连接配置”菜单项&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
Expand Down
72 changes: 64 additions & 8 deletions listwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ QString ListWindow::getVarFullName(const VarNode &node)
{
const VarNode *curNode=&node;
QString fullName=node.name;
while(curNode->parent->parent)//到父节点为根节点为止
while(curNode->parent->parent->parent)//到父节点为文件节点为止
{
if(curNode->name.contains('['))//若为数组元素,父节点为数组名,直接拼接(无需加'.')
fullName=curNode->parent->name+fullName;
Expand All @@ -41,14 +41,51 @@ QString ListWindow::getVarFullName(const VarNode &node)
return fullName;
}

//计算一个节点所在的文件名
QString ListWindow::getVarFileName(const VarNode &node,bool isFull)
{
const VarNode *curNode=&node;
while(curNode->parent->parent)//到父节点为根节点为止
curNode=curNode->parent;
QString filename=curNode->name;
if(isFull)
return filename;//返回全路径
else
return filename.split("/").last().split("\\").last();//返回文件名部分
}

//解析一个节点的子节点,并更新子节点的可展开状态
void ListWindow::parseVarChildren(VarNode &node)
{
static QString rawVarInfo="";//展开根节点时保存"info variables"结果,展开文件名时直接从中解析,提高效率

if(node.parent==NULL)//传入的是根节点
{
QString rawVarList=gdb->runCmd("info variables\r\n");//使用info variables指令列出axf中所有变量
gdb->removeInnerSection(rawVarList,0);//移除内部直接嵌套的部分
QStringList varList=gdb->getVarListFromRawOutput(rawVarList);//解析出变量列表
rawVarInfo=gdb->runCmd("info variables\r\n");//使用info variables指令列出axf中所有变量
gdb->removeInnerSection(rawVarInfo,0);//移除内部直接嵌套的部分

QRegExp fileRx("\\nFile\\s(.*):\\r\\n");//正则匹配获取所有文件名并添加为节点
fileRx.setMinimal(true);
int pos=0;
while((pos=fileRx.indexIn(rawVarInfo,pos))!=-1)
{
node.append(fileRx.cap(1));
node.children.last().expandable=true;
pos+=fileRx.matchedLength();
}
}
else if(node.parent->parent==NULL)//传入的是文件名节点
{
QString regName="";
for(int i=0;i<node.name.length();i++)//将文件名每个字符转换为16进制格式,用于正则匹配
regName+=QString("\\x%1").arg(node.name.at(i).unicode(),0,16);

int startPos=QRegExp(QString("\\nFile\\s%1:\\r\\n").arg(regName)).indexIn(rawVarInfo);//找到文件名所在位置
int endPos=QRegExp("\\nFile\\s(.*):\\r\\n").indexIn(rawVarInfo,startPos+1);//找到下一个文件名所在位置
if(endPos==-1)
endPos=rawVarInfo.length()-1;

QStringList varList=gdb->getVarListFromRawOutput(rawVarInfo.mid(startPos,endPos-startPos));//截取两个位置之间的子串解析变量列表
foreach(QString name,varList)//依次添加子节点并更新可展开状态
{
node.append(name);
Expand Down Expand Up @@ -146,8 +183,15 @@ void ListWindow::on_btn_add2edit_clicked()
if(index.row()==-1)
return;
VarNode &node=*(VarNode*)(treeModel->itemFromIndex(index)->data().toULongLong());//获取所选节点
if(node.parent)
emit add2Edit(getVarFullName(node));//将变量全名使用信号发出去
if(node.parent && node.parent->parent)
{
QString varName=getVarFullName(node);
if(ui->cb_use_path->isChecked())
emit add2Edit("\'"+getVarFileName(node,ui->cb_full_path->isChecked())+"\'::"+varName);
else
emit add2Edit(varName);
}

}

//添加到列表按钮槽函数(逻辑与添加到编辑框相同,仅发送的信号不同)
Expand All @@ -157,6 +201,18 @@ void ListWindow::on_btn_add2list_clicked()
if(index.row()==-1)
return;
VarNode &node=*(VarNode*)(treeModel->itemFromIndex(index)->data().toULongLong());
if(node.parent)
emit add2List(getVarFullName(node));
if(node.parent && node.parent->parent)
{
QString varName=getVarFullName(node);
if(ui->cb_use_path->isChecked())
emit add2List("\'"+getVarFileName(node,ui->cb_full_path->isChecked())+"\'::"+varName);
else
emit add2List(varName);
}
}

//附带文件名选框槽函数
void ListWindow::on_cb_use_path_toggled(bool checked)
{
ui->cb_full_path->setEnabled(checked);
}
2 changes: 2 additions & 0 deletions listwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ private slots:
void on_tree_expanded(const QModelIndex &index);
void on_btn_add2edit_clicked();
void on_btn_add2list_clicked();
void on_cb_use_path_toggled(bool checked);

private:
Ui::ListWindow *ui;
Expand All @@ -65,6 +66,7 @@ private slots:
VarNode varTree;
QStandardItemModel *treeModel;
QString getVarFullName(const VarNode &node);
QString getVarFileName(const VarNode &node,bool isFull);
void parseVarChildren(VarNode &node);
void updateTree();
};
Expand Down
39 changes: 34 additions & 5 deletions listwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,47 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="btn_add2list">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>直接添加到列表</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="btn_add2edit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>添加到编辑框</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_add2list">
<item row="0" column="1">
<widget class="QCheckBox" name="cb_use_path">
<property name="text">
<string>直接添加到列表</string>
<string>附带文件名</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="cb_full_path">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>使用全路径</string>
</property>
</widget>
</item>
Expand Down
58 changes: 58 additions & 0 deletions mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ MainWindow::MainWindow(QWidget *parent)
tableModel=new QStandardItemModel(this);//创建并初始化表格
initTable();

tablePopMenu=new QMenu(ui->tb_var);//创建表格右键菜单
tablePopMenu->addAction(ui->action_del_var);

openocd=new OpenOCD();//创建OpenOCD对象并连接错误处理槽
connect(openocd,&OpenOCD::onErrorOccur,this,&MainWindow::slotOnConnErrorOccur,Qt::QueuedConnection);

Expand All @@ -64,6 +67,8 @@ MainWindow::MainWindow(QWidget *parent)
loadConfFileList();//从openocd文件夹中读取配置文件列表
loadGlobalConf();//加载软件全局配置
loadFromFile("autosave.ini");//加载自动保存的工程配置

QTimer::singleShot(100,this,&MainWindow::checkOpenocdProcess);//窗口加载完成后检查是否有正在运行的openocd进程
}

MainWindow::~MainWindow()
Expand All @@ -80,6 +85,7 @@ MainWindow::~MainWindow()
gdb->stop();//结束gdb进程
delete ui;
delete tableModel;
delete tablePopMenu;
delete openocd;
delete gdb;
delete stampTimer;
Expand Down Expand Up @@ -602,6 +608,16 @@ void MainWindow::on_tb_var_clicked(const QModelIndex &index)
}
}

//表格右键菜单槽函数
void MainWindow::on_tb_var_customContextMenuRequested(const QPoint &pos)
{
QModelIndex index=ui->tb_var->indexAt(pos);//获取所点击的单元格索引
if(index.column()==0 && index.row()<varList.size())
{
tablePopMenu->exec(QCursor::pos());//弹出右键菜单
}
}

//保存配置菜单点击
void MainWindow::on_action_save_triggered()
{
Expand Down Expand Up @@ -715,6 +731,23 @@ void MainWindow::on_action_feedback_triggered()
QDesktopServices::openUrl(QUrl("https://support.qq.com/product/378753"));//打开反馈页面
}

//删除选中变量槽函数
void MainWindow::on_action_del_var_triggered()
{
if(ui->tb_var->currentIndex().column()==0)//确定已选中某个变量的变量名
{
int index=ui->tb_var->currentIndex().row();//获取所选变量的下标
if(index<varList.size())
{
varList.removeAt(index);//删除变量
redrawTable();

if(connected)//若正在连接状态则向gdb发送新的变量列表
updateGDBList();
}
}
}

//检查更新
void MainWindow::checkUpdate()
{
Expand Down Expand Up @@ -767,6 +800,31 @@ void MainWindow::checkUpdate()
manager->get(request);
}

//检查后台是否存在openocd进程,存在的话询问用户是否关闭
void MainWindow::checkOpenocdProcess()
{
QProcess listProcess(0);//使用tasklist查找openocd进程
listProcess.setProgram("tasklist");
listProcess.setNativeArguments("/fi \"imagename eq openocd.exe\"");
listProcess.start();
listProcess.waitForFinished();
if(listProcess.readAllStandardOutput().contains("openocd.exe"))//后台存在openocd进程
{
QMessageBox msgBox;
msgBox.setWindowTitle("提示");
msgBox.setText("发现正在运行的OpenOCD进程,可能是由于上次不正常退出导致的,是否强制结束?(若您没有其他正在调试的程序建议结束)");
msgBox.setStandardButtons(QMessageBox::Yes|QMessageBox::No);
if(msgBox.exec()==QMessageBox::Yes)
{
QProcess killProcess(0);//用taskkill强行结束进程
killProcess.setProgram("taskkill");
killProcess.setNativeArguments("/F /IM openocd.exe");
killProcess.start();
killProcess.waitForFinished();
}
}
}

//检查更新菜单点击
void MainWindow::on_action_checkupdate_triggered()
{
Expand Down
Loading

0 comments on commit 996b3d4

Please sign in to comment.