From 84ed78c87602c985d23a51de6fc65f8c366b03f7 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Tue, 12 Apr 2022 16:44:51 +0800 Subject: [PATCH 1/5] update: protocol example --- libsigrokdecode4DSL/decoders/example/pd.py | 195 ++++++++++++--------- 1 file changed, 114 insertions(+), 81 deletions(-) diff --git a/libsigrokdecode4DSL/decoders/example/pd.py b/libsigrokdecode4DSL/decoders/example/pd.py index d193c301..c84ec240 100644 --- a/libsigrokdecode4DSL/decoders/example/pd.py +++ b/libsigrokdecode4DSL/decoders/example/pd.py @@ -20,148 +20,181 @@ ## ## 开发脚本的前提条件是必须掌握python语言 -## 非windows用户,想要打印出信息,用self.printlog(string),并在控制台下运行DSView。但是最终需要注释掉,因为影响性能。 ## 更复杂的协议请查考(0-i2c、0-spi、 0-uart、1-i2c、1-spi、1-uart) -## 底层模块提供的属性有: -## 1. samplenum 数据样品位置 -## 2. matched 本次查找调用wait匹配的信息,返回一个uint64类型数值,表示0到63个通道的匹配信息 -## The prerequisite for developing scripts is to master Python language ## text block fill color table: ## [#EF2929,#F66A32,#FCAE3E,#FBCA47,#FCE94F,#CDF040,#8AE234,#4EDC44,#55D795,#64D1D2 ## ,#729FCF,#D476C4,#9D79B9,#AD7FA8,#C2629B,#D7476F] -## 导出核心模块类 +# 导出核心模块类,c代码实现的类 import sigrokdecode as srd -## 本协议模块类 +# 协议模块类 class Decoder(srd.Decoder): - ## 必须的 + # 这里定义类的一些全局变量,有一些是底层框架要求必须要写的,其它提根据需要 + # 自己加,注意缩进,不清楚请查看python手册 + + # 说明需要安装的python版本 api_version = 3 - ## 协议标识,必须唯一 - ## The protocol ID, which must be unique + # 协议标识,必须唯一,这里我们用"example"给协议命名 id = 'example' - ## 协议名称, 不一定要求跟标识一致 - ## The protocol name, it not necessarily consistent with ID - name = 'example' + # 协议名称, 不一定要求跟标识一致 + name = 'Example' - ## 协议长名称 - ## Long name - longname = 'example-devel' + # 协议长名称 + longname = 'example-lala' - ## 简介内容 - ## Descript text - desc = 'This is an example of protocol development' + # 简介内容 + desc = 'This is an example of protocol' - ## 开源协议 + # 开源协议 license = 'gplv2+' - ## 接收的输入的数据源名 - ## Ten input data source name + # 接收的输入的数据源名,如果是多层协议一起工作,可使用上一个协议的输出名 inputs = ['logic'] - ## 输出的数据类别名,可作为下层协议的输入数据源名 - ## The output data source name + # 输出的数据源名,多层协议模式下,可作为下层协议的输入数据源名 outputs = ['test'] - ## 适用范围标签 + # 适用范围标签 tags = ['Embedded/industrial'] - ## 必须要绑定的通道定义,将在界面上可见 - ## id:通道标识, 任意命名 - ## type:类型,根据需要设置一个值, -1:COMMON,0:SCLK,1:SDATA,2:ADATA - ## name:标签名 - ## desc:该通道的说明 + # 必须要绑定的通道定义,将在界面上可见 + # id:通道标识, 任意命名 + # type:类型,根据需要设置一个值, -1:COMMON,0:SCLK,1:SDATA,2:ADATA + # name:标签名 + # desc:该通道的说明 + # 注意元组的最后的逗号不能少 channels = ( {'id': 'c1', type:0, 'name': 'c1', 'desc': 'chan1-input'}, ) - ## 可选通道,其它跟上面的一样 + # 可选通道,其它跟上面的一样 optional_channels = ( - {'id': 'c2', type:0, 'name': 'c2', 'desc': 'chan2-input'}, + {'id': 'c2', type:0, 'name': 'c2', 'desc': 'chan2-input'}, ) - ## 提供给用户通过界面设置的参数,根据业务需要来定义 + # 提供给用户通过界面设置的参数,根据业务需要来定义 + # 通过self.options[id]取值,id就是各个项的id值,比如下面的"wordsize" options = ( - {'id': 'bit-len', 'desc': 'match bit length', 'default': 16, 'values': (8,16)}, - {'id': 'mode', 'desc': 'work mode', 'default': 'up','values': ('up','low')}, + # 这种参数是一个下拉列表 + {'id': 'debug_bits', 'desc': 'Print each bit', 'default': 'no', + 'values': ('yes', 'no')}, + + # 这是一个输入框 + {'id': 'wordsize', 'desc': 'Data wordsize (# bus cycles)', 'default': 0}, ) - ## 解析结果项定义 - ## annotations里的每一项可以有2到3个属性,当有3个属性时,第一个表示类型 - ## 类型对应0-16个颜色,当类型范围在200-299时,将绘制边沿箭头 + # 解析结果项定义 + # annotations里的每一项可以有2到3个属性,当有3个属性时,第一个表示类型 + # 类型对应0-16个颜色,当类型范围在200-299时,将绘制边沿箭头 annotations = ( - ('1', 'test-data1', 'example test data1'), - ('2', 'test-data2', 'example test data2'), - ('222', 'test-data3', 'example test data3'), + ('1', 'data1', 'test data1'), + ('2', 'data2', 'test data2'), + ('222', 'data3', 'test data3'), ) - ## 解析结果的行定义 + # 解析结果行定义 annotation_rows = ( - ('lab1', 'the lab1', (0,)), #可输出第1个定义的annotations类型 - ('lab2', 'the lab2', (1,2)), #可输出第1个和第2个定义的annotations类型 + # (0,)表示可输出第1个定义的annotations类型 + ('lab1', 'row1', (0,)), + + # (1,2)表示可输出第1个和第2个定义的annotations类型 + ('lab2', 'row2', (1,2)), ) - ## 构造函数,自动被调用 + # 构造函数,自动被调用 def __init__(self): + # 这里调用一个类成员函数,完成一些参数的初始化 self.reset() - ## 在这里做一些重置和定义私有变量工作 + # 重置函数,在这里做一些重置和定义类私有变量工作 def reset(self): + # 定义一个私有变量count self.count = 0 - ## 脚本开始运行时,会自动调用 - ## 注册一些解析结果类型 - ## 有: OUTPUT_ANN,OUTPUT_PYTHON,OUTPUT_BINARY,OUTPUT_META + # 开始执行解码任务时,由c底层代码自动调用一次 + # 这里,完成一些解码结果项annotation类型的注册 + # 类型有: OUTPUT_ANN,OUTPUT_PYTHON,OUTPUT_BINARY,OUTPUT_META + # self.register函数是c底层类提供的 def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) - #self.out_python = self.register(srd.OUTPUT_PYTHON) - ## 定义一个输出函数 - ## a,b为采样起点和终点, value为要输出的数值 - def put_row1(self, a, b, value): - # '@%02X', 前边加@是告诉底层模块这是一个数值数据,显示格式可转化为hex/oct/bin/acii/dec - # {$}是占位符,内容由数值部分填充 - # @特殊符号和{$}占位符的特性,只有DSView版本在1.2.0以上才支持 - # []描述输出内容,第一个元素表示annotation序号,annotation的输出在哪一行由annotation_rows集合定决定 - self.put(a, b, self.out_ann, [0, ['r1:{$}', '@%02X' % value]]) - - def put_row2(self, a, b, value): - self.put(a, b, self.out_ann, [2, ['r2:{$}', '@%02X' % value]]) - + # 定义一个输出函数 + # a,b为采样位置的起点和终点 + # ann为annotations定义的项序号 + # data是一个列表,列表里有1到3个字符串,它们将显示到屏幕 + # annotation输出到哪一行由annotation_rows决定 + # self.out_ann就是上面注册的消息类型了 + # self.put是c底层类提供的函数 + def put_ann(self, a, b, ann, data): + self.put(a, b, self.out_ann, [ann, data]) - ## 触发解析工作 + # 解码函数,解码任务开始时由c底层代码调用 + # 这里不断循环等待所有采样数据被处理完成 + # 下面的未例代码是想以一对向上边沿和向下边沿,输出它们的样品位置差值, + # 同时奇数次显示第二行,偶数次显示在第一行,我们只要指定了annotations里定义的序号 + # 软件会自动根据annotation_rows的设置,决定显示在哪一行 def decode(self): + # 次数计数 times = 0 - lst_dex = self.samplenum + + # 向上边沿样品位置 + rising_sample = 0 + + # 条件参数列表 flag_arr = [{0:'r'}, {0:'f'}] + + # wait参数的条件序号 flag_dex = 0 + # 不断循环,处理完所有数据 while True: - # 从原始数据中按条件匹配数据,用于接受返回值的元组里的变量个数由通道数决定 - # 如果可选通道未绑定真实通道,则返回255,比如这里的b变成255 - # wait()不带条件,表示进行所有匹配 - #(a,b) = self.wait() - - (a,b) = self.wait(flag_arr[flag_dex]) + # 边沿条件 + edge = flag_arr[flag_dex] + + # 取一个条件,调用wait函数,找到符合条件的数据 + # (a,b)是一个元组,里边的变量数一定要跟channel数一致 + (a,b) = self.wait(edge) + # 条件在向上边沿和向下边沿中切换 + # 初始是向上边沿,取到样品位置后,切换成下向边沿 if flag_dex == 0: flag_dex = 1 - lst_dex = self.samplenum + + # 保存向上边沿采样位置 + rising_sample = self.samplenum else: flag_dex = 0 + + # 打印次数计数加1 times += 1 - if times % 2 == 0: - self.put_row1(lst_dex, self.samplenum, self.samplenum - lst_dex) - else: - self.put_row2(lst_dex, self.samplenum, self.samplenum - lst_dex) - #self.put_row3(lst_dex, self.samplenum, 0) + + # 向下边沿采样位置 + falling_sample = self.samplenum + + # 向下边沿和向上边沿采样位置差 + v = falling_sample - rising_sample + + # 转换成16进制的字符串 + s = '%02X' % v + + # 对times求余得值在0和1中变换,对应annotation的序号 + ann = times % 2 + self.put_ann(rising_sample, falling_sample, ann, [s]) - # wait({0:'f'}), 0表示通道序号(从0开始),'f'表示查找下边沿 - # wait()可传多个条件,与条件:{0:'f',1:'r'}, 或条件:[{0:'f'},{1:'r'}] - # h:高电平,l:低电平,r:上边沿,f:下边沿,e:上沿或下沿, n:要么0,要么1 - # (a,b) = self.wait([{0:'f'}]) - + # self.wait()可带参数,也可以不带参数,不带参数时将返回每个采样数据 + # 参数{0:'r'}, 0表示匹配channels第1项绑定的通道,'r'表示查找向上边沿 + # wait函数可传多个条件,与条件:{0:'f',1:'r'}, 或条件:[{0:'f'},{1:'r'}] + # h:高电平,l:低电平,r:向上边沿,f:向下边沿,e:向上沿或向下沿, n:要么0,要么1 + # wait函数前的变量(a,b),对应的数量由定义的channels里的通道数决定,包括可选通道 + # optional_channels 。例如:channels和optional_channels共定义了4个通道, + # 则变成(a,b,c,d) = self.wait(),共四个变量 + + # 底层模块提供的属性: + # 1. self.samplenum 当前wait()调用匹配结束的采样点位置 + # 2. self.matched 本次调用wait()后所有通道的匹配结果信息,是一个uint64类型数值, + # 表示0到63个通道的匹配信息,通过位运算来获取具体信息。 \ No newline at end of file From f5bc2b1ee759cbfecc0e91eae61f5035457d94d4 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 15 Apr 2022 15:51:36 +0800 Subject: [PATCH 2/5] add: Reduce the rolling trigger sensitivity of logic analyzer --- DSView/pv/appcontrol.cpp | 12 ++++++++++- DSView/pv/appcontrol.h | 22 +++++++++++++++++---- DSView/pv/dsvdef.cpp | 17 ---------------- DSView/pv/dsvdef.h | 6 +----- DSView/pv/mainframe.cpp | 5 +++-- DSView/pv/mainwindow.cpp | 2 +- DSView/pv/toolbars/titlebar.cpp | 4 +++- DSView/pv/ui/msgbox.cpp | 7 ++++--- DSView/pv/view/viewport.cpp | 23 +++++++++++++++++++++- DSView/pv/view/viewport.h | 9 +++++---- libsigrokdecode4DSL/decoders/example/pd.py | 4 ++-- 11 files changed, 70 insertions(+), 41 deletions(-) diff --git a/DSView/pv/appcontrol.cpp b/DSView/pv/appcontrol.cpp index a5a70b4e..280e9ce4 100644 --- a/DSView/pv/appcontrol.cpp +++ b/DSView/pv/appcontrol.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "devicemanager.h" #include "sigsession.h" @@ -35,7 +36,8 @@ AppControl::AppControl() { sr_ctx = NULL; - + _topWindow = NULL; + _device_manager = new pv::DeviceManager(); _session = new pv::SigSession(_device_manager); } @@ -149,3 +151,11 @@ const char *AppControl::GetLastError() sr_log_loglevel_set(level); srd_log_loglevel_set(level); } + + bool AppControl::TopWindowIsMaximized() + { + if (_topWindow != NULL){ + return _topWindow->isMaximized(); + } + return false; + } diff --git a/DSView/pv/appcontrol.h b/DSView/pv/appcontrol.h index d674024c..82bbd3dd 100644 --- a/DSView/pv/appcontrol.h +++ b/DSView/pv/appcontrol.h @@ -24,6 +24,7 @@ #include struct sr_context; +class QWidget; namespace pv{ class DeviceManager; @@ -54,11 +55,23 @@ public: void SetLogLevel(int level); - inline pv::SigSession* GetSession() - { return _session;} + inline pv::SigSession* GetSession(){ + return _session; + } - inline pv::DeviceManager& GetDeviceManager() - { return *_device_manager;} + inline pv::DeviceManager& GetDeviceManager(){ + return *_device_manager; + } + + inline void SetTopWindow(QWidget *w){ + _topWindow = w; + } + + inline QWidget* GetTopWindow(){ + return _topWindow; + } + + bool TopWindowIsMaximized(); public: std::string _open_file_name; @@ -68,4 +81,5 @@ private: struct sr_context *sr_ctx; pv::DeviceManager *_device_manager; pv::SigSession *_session; + QWidget *_topWindow; }; diff --git a/DSView/pv/dsvdef.cpp b/DSView/pv/dsvdef.cpp index 1e2a4856..dfd42fd8 100644 --- a/DSView/pv/dsvdef.cpp +++ b/DSView/pv/dsvdef.cpp @@ -62,23 +62,6 @@ namespace DecoderDataFormat namespace app { - QWidget* get_app_window_instance(QWidget *ins, bool bSet){ - - static QWidget *g_ins = NULL; - if (bSet){ - g_ins = ins; - } - return g_ins; - } - - bool is_app_top_window(QWidget* w){ - QWidget *top =get_app_window_instance(NULL, NULL); - if (top && top == w){ - return true; - } - return false; - } - void set_utf8(QTextStream &stream){ #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) stream.setEncoding(QStringConverter::Utf8); diff --git a/DSView/pv/dsvdef.h b/DSView/pv/dsvdef.h index 6c87ae53..abfb851d 100644 --- a/DSView/pv/dsvdef.h +++ b/DSView/pv/dsvdef.h @@ -53,7 +53,7 @@ class QTextStream; #define RELEASE_ARRAY(a) for (auto ptr : (a)){delete ptr;} (a).clear(); -#define ABS_VAL(x) (x>0?x:-x) +#define ABS_VAL(x) ((x) > 0 ? (x) : -(x)) namespace DecoderDataFormat { @@ -71,10 +71,6 @@ namespace DecoderDataFormat namespace app { - QWidget* get_app_window_instance(QWidget *ins, bool bSet); - - bool is_app_top_window(QWidget* w); - void set_utf8(QTextStream &stream); } diff --git a/DSView/pv/mainframe.cpp b/DSView/pv/mainframe.cpp index adab48f6..03e10548 100644 --- a/DSView/pv/mainframe.cpp +++ b/DSView/pv/mainframe.cpp @@ -47,6 +47,7 @@ #include "dsvdef.h" #include "config/appconfig.h" #include "ui/msgbox.h" +#include "appcontrol.h" #include @@ -61,6 +62,8 @@ MainFrame::MainFrame() _titleBar = NULL; _mainWindow = NULL; + AppControl::Instance()->SetTopWindow(this); + setAttribute(Qt::WA_TranslucentBackground); // Make this a borderless window which can't // be resized or moved via the window system @@ -77,8 +80,6 @@ MainFrame::MainFrame() QIcon icon; icon.addFile(QString::fromUtf8(":/icons/logo.svg"), QSize(), QIcon::Normal, QIcon::Off); setWindowIcon(icon); - - app::get_app_window_instance(this, true); // Title _titleBar = new toolbars::TitleBar(true, this); diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index c8bc5c70..5657b2a0 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -103,7 +103,7 @@ MainWindow::MainWindow(QWidget *parent) : _msg(NULL) { _control = AppControl::Instance(); - _control->GetSession()->set_callback(this); + _control->GetSession()->set_callback(this); _bFirstLoad = true; setup_ui(); diff --git a/DSView/pv/toolbars/titlebar.cpp b/DSView/pv/toolbars/titlebar.cpp index ab2ebfdf..77e97d85 100755 --- a/DSView/pv/toolbars/titlebar.cpp +++ b/DSView/pv/toolbars/titlebar.cpp @@ -32,6 +32,7 @@ #include #include #include "../config/appconfig.h" +#include "../appcontrol.h" #include "../dsvdef.h" @@ -192,7 +193,8 @@ void TitleBar::mousePressEvent(QMouseEvent* event) { int x = event->pos().x(); int y = event->pos().y(); - bool bTopWidow = app::is_app_top_window(_parent); + + bool bTopWidow = AppControl::Instance()->GetTopWindow() == _parent; bool bClick = (x >= 6 && y >= 5 && x <= width() - 6); //top window need resize hit check if (!bTopWidow || bClick ){ diff --git a/DSView/pv/ui/msgbox.cpp b/DSView/pv/ui/msgbox.cpp index 0e456b34..73c6494b 100644 --- a/DSView/pv/ui/msgbox.cpp +++ b/DSView/pv/ui/msgbox.cpp @@ -25,6 +25,7 @@ #include #include #include "../dsvdef.h" +#include "../appcontrol.h" //QMessageBox::information(NULL, "Title", "Content",QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); //QMessageBox::information(NULL, "Title", "Content",QMessageBox::Yes|QMessageBox::No); @@ -40,7 +41,7 @@ void MsgBox::Show(const char *title, const char *text, QWidget *parent) str.append(text); if (parent == NULL){ - parent = app::get_app_window_instance(NULL, false); + parent = AppControl::Instance()->GetTopWindow(); } pv::dialogs::DSMessageBox msg(parent, title); @@ -59,8 +60,8 @@ bool MsgBox::Confirm(const char *text, QWidget *parent) str.append("\n"); str.append(text); - if (parent == NULL){ - parent = app::get_app_window_instance(NULL, false); + if (parent == NULL){ + parent = AppControl::Instance()->GetTopWindow(); } pv::dialogs::DSMessageBox msg(parent, "Question"); diff --git a/DSView/pv/view/viewport.cpp b/DSView/pv/view/viewport.cpp index 61a5f0c4..a5e60458 100755 --- a/DSView/pv/view/viewport.cpp +++ b/DSView/pv/view/viewport.cpp @@ -44,6 +44,7 @@ #include "../config/appconfig.h" #include "../dsvdef.h" +#include "../appcontrol.h" using namespace std; @@ -88,6 +89,7 @@ Viewport::Viewport(View &parent, View_type type) : _edge_hit = false; transfer_started = false; timer_cnt = 0; + _clickX = 0; // drag inertial _drag_strength = 0; @@ -499,6 +501,7 @@ void Viewport::mousePressEvent(QMouseEvent *event) { assert(event); + _clickX = event->globalPos().x(); _mouse_down_point = event->pos(); _mouse_down_offset = _view.offset(); _drag_strength = 0; @@ -757,6 +760,9 @@ void Viewport::mouseMoveEvent(QMouseEvent *event) void Viewport::mouseReleaseEvent(QMouseEvent *event) { assert(event); + + bool quickScroll = AppConfig::Instance()._appOptions.quickScroll; + bool isMaxWindow = AppControl::Instance()->TopWindowIsMaximized(); if (_type != TIME_VIEW){ update(); @@ -769,7 +775,22 @@ void Viewport::mouseReleaseEvent(QMouseEvent *event) _view.session().get_capture_state() == SigSession::Stopped) { //priority 1 //try to quick scroll view... - if (_action_type == NO_ACTION && AppConfig::Instance()._appOptions.quickScroll) { + int curX = event->globalPos().x(); + int moveLong = ABS_VAL(curX - _clickX); + int maxWidth = this->geometry().width(); + float mvk = (float) moveLong / (float)maxWidth; + + if (quickScroll){ + quickScroll = false; + if (isMaxWindow && mvk > 0.5f){ + quickScroll = true; + } + else if (!isMaxWindow && mvk > 0.6f){ + quickScroll = true; + } + } + + if (_action_type == NO_ACTION && quickScroll) { const double strength = _drag_strength*DragTimerInterval*1.0/_elapsed_time.elapsed(); if (_elapsed_time.elapsed() < 200 && abs(_drag_strength) < MinorDragOffsetUp && diff --git a/DSView/pv/view/viewport.h b/DSView/pv/view/viewport.h index bd1e1840..fc244fdb 100755 --- a/DSView/pv/view/viewport.h +++ b/DSView/pv/view/viewport.h @@ -217,10 +217,11 @@ private: int _dso_ym_start; int _dso_ym_end; - int _waiting_trig; - bool _dso_trig_moved; - bool _curs_moved; - bool _xcurs_moved; + int _waiting_trig; + bool _dso_trig_moved; + bool _curs_moved; + bool _xcurs_moved; + int _clickX; }; } // namespace view diff --git a/libsigrokdecode4DSL/decoders/example/pd.py b/libsigrokdecode4DSL/decoders/example/pd.py index c84ec240..0cf0e7c6 100644 --- a/libsigrokdecode4DSL/decoders/example/pd.py +++ b/libsigrokdecode4DSL/decoders/example/pd.py @@ -134,8 +134,8 @@ class Decoder(srd.Decoder): # 解码函数,解码任务开始时由c底层代码调用 # 这里不断循环等待所有采样数据被处理完成 - # 下面的未例代码是想以一对向上边沿和向下边沿,输出它们的样品位置差值, - # 同时奇数次显示第二行,偶数次显示在第一行,我们只要指定了annotations里定义的序号 + # 下面的示例代码是解析某一通道的数据,从向上边沿开始到向下边沿结束,输出它们的样品位置差值, + # 奇数次显示第二行,偶数次显示在第一行,我们只指定annotations里定义的序号 # 软件会自动根据annotation_rows的设置,决定显示在哪一行 def decode(self): # 次数计数 From e1c5daf93f991146aa7921037fa2c68404432d9e Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Tue, 19 Apr 2022 15:59:15 +0800 Subject: [PATCH 3/5] fix: save session config error --- DSView/pv/mainwindow.cpp | 19 +++++++++---------- DSView/pv/mainwindow.h | 2 +- doc/Decoder develop base course.docx | Bin 66662 -> 66544 bytes 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index 5657b2a0..18ac770f 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -1140,7 +1140,7 @@ bool MainWindow::load_session_json(QJsonDocument json, bool file_dev, bool bDeco return true; } -bool MainWindow::gen_session_json(QJsonArray &array){ +bool MainWindow::gen_session_json(QJsonObject &sessionVar){ SigSession *_session = _control->GetSession(); AppConfig &app = AppConfig::Instance(); @@ -1148,7 +1148,7 @@ bool MainWindow::gen_session_json(QJsonArray &array){ GVariant *gvar; gsize num_opts; const sr_dev_inst *const sdi = _session->get_device()->dev_inst(); - QJsonObject sessionVar; + QJsonArray channelVar; sessionVar["Version"]= QJsonValue::fromVariant(Session_Version); sessionVar["Device"] = QJsonValue::fromVariant(sdi->driver->name); @@ -1230,8 +1230,7 @@ bool MainWindow::gen_session_json(QJsonArray &array){ if (_session->get_device()->dev_inst()->mode == DSO) { sessionVar["measure"] = _view->get_viewstatus()->get_session(); } - - array.push_back(sessionVar); + return true; } @@ -1246,10 +1245,10 @@ bool MainWindow::on_store_session(QString name) QTextStream outStream(&sessionFile); app::set_utf8(outStream); - QJsonArray jsonArray; - if (!gen_session_json(jsonArray)) + QJsonObject sessionVar; + if (!gen_session_json(sessionVar)) return false; - QJsonDocument sessionDoc(jsonArray); + QJsonDocument sessionDoc(sessionVar); //sessionFile.write(QString::fromUtf8(sessionDoc.toJson())); outStream << QString::fromUtf8(sessionDoc.toJson()); sessionFile.close(); @@ -1258,10 +1257,10 @@ bool MainWindow::on_store_session(QString name) bool MainWindow::genSessionData(std::string &str) { - QJsonArray jsonArray; - if (!gen_session_json(jsonArray)) + QJsonObject sessionVar; + if (!gen_session_json(sessionVar)) return false; - QJsonDocument sessionDoc(jsonArray); + QJsonDocument sessionDoc(sessionVar); QString data = QString::fromUtf8(sessionDoc.toJson()); str.append(data.toLatin1().data()); return true; diff --git a/DSView/pv/mainwindow.h b/DSView/pv/mainwindow.h index c8a318e7..4000fac8 100755 --- a/DSView/pv/mainwindow.h +++ b/DSView/pv/mainwindow.h @@ -178,7 +178,7 @@ private: void data_received(); //------private - bool gen_session_json(QJsonArray &array); + bool gen_session_json(QJsonObject &sessionVar); private: AppControl *_control; diff --git a/doc/Decoder develop base course.docx b/doc/Decoder develop base course.docx index 2d013a11d6f1ac68b17bba118860bd117d6885f9..b0b031545d212dbf92b7128c5e828bd80f842a77 100644 GIT binary patch delta 34959 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 N3p6+>kJ|kZ`X>b(5cU87 delta 35011 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%0DBK>V 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 From fcddf9d974cc448773a7a9c628670a7f11d2235c Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Thu, 21 Apr 2022 16:17:03 +0800 Subject: [PATCH 4/5] update: protocol search ui --- DSView/CMakeLists.txt | 2 + DSView/pv/dock/keywordlineedit.cpp | 32 +++-- DSView/pv/dock/keywordlineedit.h | 20 +-- DSView/pv/dock/protocoldock.cpp | 187 ++++++++++------------------- DSView/pv/dock/protocoldock.h | 40 +++--- DSView/pv/dock/searchcombobox.cpp | 171 ++++++++++++++++++++++++++ DSView/pv/dock/searchcombobox.h | 79 ++++++++++++ DSView/pv/view/decodetrace.cpp | 4 +- DSView/themes/dark.qss | 12 ++ DSView/themes/light.qss | 12 ++ 10 files changed, 389 insertions(+), 170 deletions(-) create mode 100644 DSView/pv/dock/searchcombobox.cpp create mode 100644 DSView/pv/dock/searchcombobox.h diff --git a/DSView/CMakeLists.txt b/DSView/CMakeLists.txt index bea982d7..be360be9 100755 --- a/DSView/CMakeLists.txt +++ b/DSView/CMakeLists.txt @@ -248,6 +248,7 @@ set(DSView_SOURCES pv/minizip/ioapi.c pv/dialogs/applicationpardlg.cpp pv/dock/keywordlineedit.cpp + pv/dock/searchcombobox.cpp ) set(DSView_HEADERS @@ -332,6 +333,7 @@ set(DSView_HEADERS pv/minizip/ioapi.h pv/dialogs/applicationpardlg.h pv/dock/keywordlineedit.h + pv/dock/searchcombobox.h ) set(DSView_FORMS diff --git a/DSView/pv/dock/keywordlineedit.cpp b/DSView/pv/dock/keywordlineedit.cpp index d15805f4..ec1bebbe 100644 --- a/DSView/pv/dock/keywordlineedit.cpp +++ b/DSView/pv/dock/keywordlineedit.cpp @@ -21,28 +21,24 @@ #include "keywordlineedit.h" -KeywordLineEdit::KeywordLineEdit(QComboBox *comboBox) -:QLineEdit() -{ - assert(comboBox); - _comboBox = comboBox; +#define PROTOCOL_FIND_TITLE "Protocol search..." + +KeywordLineEdit::KeywordLineEdit(QWidget *parent, IKeywordActive *active) +:QLineEdit(parent) +{ + _active = active; + this->setText(PROTOCOL_FIND_TITLE); } - - void KeywordLineEdit::focusInEvent(QFocusEvent *e) + void KeywordLineEdit::mousePressEvent(QMouseEvent *e) { - QLineEdit::focusInEvent(e); - QString key(PROTOCOL_FIND_TITLE); - if (this->text() == key){ - this->setText(""); - } + if (e->button() == Qt::LeftButton && _active != NULL){ + _active->BeginEditKeyword(); + } + QLineEdit::mousePressEvent(e); } -void KeywordLineEdit::focusOutEvent(QFocusEvent *e) + void KeywordLineEdit::ResetText() { - QLineEdit::focusOutEvent(e); - - if (this->text() == ""){ - this->setText(PROTOCOL_FIND_TITLE); - } + this->setText(PROTOCOL_FIND_TITLE); } \ No newline at end of file diff --git a/DSView/pv/dock/keywordlineedit.h b/DSView/pv/dock/keywordlineedit.h index 205de9e2..bf85514b 100644 --- a/DSView/pv/dock/keywordlineedit.h +++ b/DSView/pv/dock/keywordlineedit.h @@ -23,25 +23,29 @@ #define KEY_WORD_LINE_EDIT_H #include -#include -#include -#include +#include +#include +#include -#define PROTOCOL_FIND_TITLE "Protocol search..." +class IKeywordActive{ +public: + virtual void BeginEditKeyword()=0; +}; class KeywordLineEdit : public QLineEdit { Q_OBJECT public: - KeywordLineEdit(QComboBox *comboBox); + KeywordLineEdit(QWidget *parent, IKeywordActive *active); + + void ResetText(); protected: - void focusInEvent(QFocusEvent *e) override; - void focusOutEvent(QFocusEvent *e) override; + void mousePressEvent(QMouseEvent *e); private: - QComboBox *_comboBox; + IKeywordActive *_active; }; diff --git a/DSView/pv/dock/protocoldock.cpp b/DSView/pv/dock/protocoldock.cpp index c17c9843..36eb923c 100755 --- a/DSView/pv/dock/protocoldock.cpp +++ b/DSView/pv/dock/protocoldock.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "../ui/msgbox.h" @@ -53,6 +54,7 @@ #include "../data/decode/decoderstatus.h" #include "../data/decode/decoder.h" + using namespace std; @@ -65,10 +67,7 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio { _session = session; _cur_search_index = -1; - _search_edited = false; - _searching = false; - _add_silent = false; - _bSettingList = false; + _search_edited = false; _up_widget = new QWidget(this); @@ -78,12 +77,8 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio _del_all_button->setFlat(true); _del_all_button->setCheckable(true); - _protocol_combobox = new DsComboBox(_up_widget); - _protocol_combobox->setEditable(true); - _protocol_combobox->setLineEdit(new KeywordLineEdit(_protocol_combobox)); - _protocol_combobox->setCompleter(NULL); - - //GSList *l = g_slist_sort(g_slist_copy((GSList*)srd_decoder_list()), decoder_name_cmp); + _keyword_edit = new KeywordLineEdit(_up_widget, this); + _keyword_edit->setReadOnly(true); GSList *l = const_cast(srd_decoder_list()); @@ -93,13 +88,12 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio for(; l; l = l->next) { const srd_decoder *const d = (srd_decoder*)l->data; - assert(d); - // const bool have_probes = (d->channels || d->opt_channels) != 0; + assert(d); if (true) { DecoderInfoItem *info = new DecoderInfoItem(); srd_decoder *dec = (srd_decoder *)(l->data); - info->ObjectHandle = dec; + info->_data_handle = dec; _decoderInfoList.push_back(info); std::string prokey(dec->id); @@ -117,34 +111,23 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio //sort protocol list sort(_decoderInfoList.begin(), _decoderInfoList.end(), ProtocolDock::protocol_sort_callback); - - _bSettingList = true; - int protocol_index = 0; - for (auto info : _decoderInfoList){ - info->Index = protocol_index; - protocol_index++; - srd_decoder *dec = (srd_decoder *)(info->ObjectHandle); - _protocol_combobox->addItem(QString::fromUtf8(dec->name), QVariant::fromValue(info->Index)); - } - - _protocol_combobox->setCurrentIndex(-1); - _protocol_combobox->lineEdit()->setText(PROTOCOL_FIND_TITLE); - _bSettingList = false; - + if (repeatNammes != ""){ QString err = "Any protocol have repeated id or name: "; err += repeatNammes; MsgBox::Show("error", err.toUtf8().data()); } - - _up_layout = new QVBoxLayout(); + + _arrow = new QToolButton(_up_widget); QHBoxLayout *hori_layout = new QHBoxLayout(); hori_layout->addWidget(_add_button); hori_layout->addWidget(_del_all_button); - hori_layout->addWidget(_protocol_combobox); + hori_layout->addWidget(_keyword_edit); + hori_layout->addWidget(_arrow); hori_layout->addStretch(1); + _up_layout = new QVBoxLayout(); _up_layout->addLayout(hori_layout); _up_layout->addStretch(1); @@ -228,12 +211,6 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio retranslateUi(); - _key_find_timer.SetCallback(std::bind(&ProtocolDock::show_protocol_list_panel, this)); - //when porotocol list panel was showPopup statu, receive key press event - QWidget *popup1 = _protocol_combobox->findChild(); - QWidget *wid1 = popup1->findChild(); - wid1->installEventFilter(this); - connect(_dn_nav_button, SIGNAL(clicked()),this, SLOT(nav_table_view())); connect(_dn_save_button, SIGNAL(clicked()),this, SLOT(export_table_view())); connect(_dn_set_button, SIGNAL(clicked()),this, SLOT(set_model())); @@ -250,10 +227,7 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio connect(_search_edit, SIGNAL(editingFinished()), this, SLOT(search_changed())); - connect(_protocol_combobox->lineEdit(), SIGNAL(textEdited(const QString &)), - this, SLOT(on_decoder_name_edited(const QString &))); - - connect(_protocol_combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(on_new_decoder_selected(int))); + connect(_arrow, SIGNAL(clicked()), this, SLOT(show_protocol_select())); } ProtocolDock::~ProtocolDock() @@ -268,15 +242,6 @@ ProtocolDock::~ProtocolDock() RELEASE_ARRAY(_decoderInfoList); } -void ProtocolDock::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::LanguageChange) - retranslateUi(); - else if (event->type() == QEvent::StyleChange) - reStyle(); - QScrollArea::changeEvent(event); -} - void ProtocolDock::retranslateUi() { _search_edit->setPlaceholderText(tr("search")); @@ -296,16 +261,24 @@ void ProtocolDock::reStyle() _pre_button->setIcon(QIcon(iconPath+"/pre.svg")); _nxt_button->setIcon(QIcon(iconPath+"/next.svg")); _search_button->setIcon(QIcon(iconPath+"/search.svg")); + _arrow->setIcon(QIcon(iconPath + "/search.svg")); for (auto it = _protocol_lay_items.begin(); it != _protocol_lay_items.end(); it++){ (*it)->ResetStyle(); } } -void ProtocolDock::paintEvent(QPaintEvent *) -{ +void ProtocolDock::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) + retranslateUi(); + else if (event->type() == QEvent::StyleChange) + reStyle(); + QScrollArea::changeEvent(event); } +//void ProtocolDock::paintEvent(QPaintEvent *){} + void ProtocolDock::resizeEvent(QResizeEvent *event) { int width = this->visibleRegion().boundingRect().width(); @@ -332,7 +305,7 @@ int ProtocolDock::get_protocol_index_by_id(QString id) { int dex = 0; for (auto info : _decoderInfoList){ - srd_decoder *dec = (srd_decoder *)(info->ObjectHandle); + srd_decoder *dec = (srd_decoder *)(info->_data_handle); QString proid(dec->id); if (id == proid){ return dex; @@ -340,23 +313,24 @@ int ProtocolDock::get_protocol_index_by_id(QString id) ++dex; } return -1; -} +} void ProtocolDock::on_add_protocol() { - if (_decoderInfoList.size() == 0){ + if (_decoderInfoList.size() == 0){ MsgBox::Show(NULL, "Protocol list is empty!"); return; } - if (_protocol_combobox->currentIndex() == -1){ + if (_selected_protocol_id == ""){ MsgBox::Show(NULL, "Please select a protocol!"); return; } - int dex = _protocol_combobox->itemData(_protocol_combobox->currentIndex()).toInt(); + int dex = this->get_protocol_index_by_id(_selected_protocol_id); + assert(dex >= 0); //check the base protocol - srd_decoder *const dec = (srd_decoder *)(_decoderInfoList[dex]->ObjectHandle); + srd_decoder *const dec = (srd_decoder *)(_decoderInfoList[dex]->_data_handle); QString pro_id(dec->id); std::list sub_decoders; @@ -373,7 +347,7 @@ void ProtocolDock::on_add_protocol() while (base_dex != -1) { - srd_decoder *base_dec = (srd_decoder *)(_decoderInfoList[base_dex]->ObjectHandle); + srd_decoder *base_dec = (srd_decoder *)(_decoderInfoList[base_dex]->_data_handle); pro_id = QString(base_dec->id); //change base protocol assert(base_dec->inputs); @@ -418,7 +392,7 @@ bool ProtocolDock::add_protocol_by_id(QString id, bool silent, std::listObjectHandle); + srd_decoder *const decoder = (srd_decoder *)(_decoderInfoList[dex]->_data_handle); DecoderStatus *dstatus = new DecoderStatus(); dstatus->m_format = (int)DecoderDataFormat::hex; @@ -924,54 +898,12 @@ void ProtocolDock::OnProtocolFormatChanged(QString format, void *handle){ } } } - -void ProtocolDock::on_decoder_name_edited(const QString &value) -{ - _bSettingList = true; - - while (_protocol_combobox->count()) - { - _protocol_combobox->removeItem(0); - } - - for (auto info: _decoderInfoList){ - srd_decoder *dec = (srd_decoder *)(info->ObjectHandle); - QString name(dec->name); - QString id(dec->id); - - if (value == "" - || name.indexOf(value, 0, Qt::CaseInsensitive) != -1 - || id.indexOf(value, 0, Qt::CaseInsensitive) != -1 ){ - _protocol_combobox->addItem(QString::fromUtf8(dec->name), QVariant::fromValue(info->Index)); - } - } - _protocol_combobox->setCurrentIndex(-1); - _protocol_combobox->lineEdit()->setText(value); - _bSettingList = false; - - if (_key_find_timer.IsActived() == false){ - //check input keep time - _key_find_timer.Start(100); - } - else{ - _key_find_timer.ResetActiveTime(); - } -} - - void ProtocolDock::show_protocol_list_panel() - { - //press key end, to popup list panel - if (_key_find_timer.GetActiveTimeLong() >= 1000){ - _key_find_timer.Stop(); - _protocol_combobox->showPopup(); - } - } bool ProtocolDock::protocol_sort_callback(const DecoderInfoItem *o1, const DecoderInfoItem *o2) { - srd_decoder *dec1 = (srd_decoder *)(o1->ObjectHandle); - srd_decoder *dec2 = (srd_decoder *)(o2->ObjectHandle); + srd_decoder *dec1 = (srd_decoder *)(o1->_data_handle); + srd_decoder *dec2 = (srd_decoder *)(o2->_data_handle); const char *s1 = dec1->name; const char *s2 = dec2->name; char c1 = 0; @@ -1002,24 +934,6 @@ bool ProtocolDock::protocol_sort_callback(const DecoderInfoItem *o1, const Decod return true; } -bool ProtocolDock::eventFilter(QObject *object, QEvent *event) -{ - if ( event->type() == QEvent::KeyPress ) - { - if (_protocol_combobox->IsPopup()){ - _protocol_combobox->hidePopup(); - } - } - return false; -} - - void ProtocolDock::on_new_decoder_selected(int index) - { - if (index >= 0 && _bSettingList == false){ - on_add_protocol(); - } - } - QString ProtocolDock::parse_protocol_id(const char *id) { if (id == NULL || *id == 0){ @@ -1056,7 +970,7 @@ bool ProtocolDock::eventFilter(QObject *object, QEvent *event) for (auto info : _decoderInfoList) { - srd_decoder *dec = (srd_decoder *)(info->ObjectHandle); + srd_decoder *dec = (srd_decoder *)(info->_data_handle); if (dec->outputs) { QString output_id = parse_protocol_id((char*)dec->outputs->data); @@ -1074,10 +988,35 @@ bool ProtocolDock::eventFilter(QObject *object, QEvent *event) return -1; } - -//------------------------- + void ProtocolDock::BeginEditKeyword() + { + show_protocol_select(); + } + void ProtocolDock::show_protocol_select() + { + SearchComboBox *panel = new SearchComboBox(this); + + for (auto info : _decoderInfoList) + { + srd_decoder *dec = (srd_decoder *)(info->_data_handle); + panel->AddDataItem(QString(dec->id), QString(dec->name), info); + } + panel->SetItemClickHandle(this); + panel->ShowDlg(_keyword_edit); + } + + void ProtocolDock::OnItemClick(void *sender, void *data_handle) + { + if (data_handle != NULL){ + DecoderInfoItem *info = (DecoderInfoItem*)data_handle; + srd_decoder *dec = (srd_decoder *)(info->_data_handle); + this->_keyword_edit->setText( QString(dec->name)); + _selected_protocol_id = QString(dec->id); + this->on_add_protocol(); + } + } } // namespace dock } // namespace pv diff --git a/DSView/pv/dock/protocoldock.h b/DSView/pv/dock/protocoldock.h index a8e2c4e8..141b9a41 100755 --- a/DSView/pv/dock/protocoldock.h +++ b/DSView/pv/dock/protocoldock.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -42,13 +43,11 @@ #include "../data/decodermodel.h" #include "protocolitemlayer.h" -#include "../ui/dscombobox.h" -#include "../dstimer.h" #include "keywordlineedit.h" +#include "searchcombobox.h" struct DecoderInfoItem{ - int Index; - void *ObjectHandle; //srd_decoder* type + void *_data_handle; //srd_decoder* type }; namespace pv { @@ -68,7 +67,10 @@ class View; namespace dock { -class ProtocolDock : public QScrollArea, public IProtocolItemLayerCallback +class ProtocolDock : public QScrollArea, +public IProtocolItemLayerCallback, +public IKeywordActive, +public ISearchItemClick { Q_OBJECT @@ -88,7 +90,7 @@ private: void reStyle(); protected: - void paintEvent(QPaintEvent *); + //void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *); int get_protocol_index_by_id(QString id); @@ -101,6 +103,12 @@ private: void OnProtocolDelete(void *handle); void OnProtocolFormatChanged(QString format, void *handle); + //IKeywordActive + void BeginEditKeyword(); + + //ISearchItemClick + void OnItemClick(void *sender, void *data_handle); + signals: void protocol_updated(); @@ -121,15 +129,12 @@ private slots: void search_done(); void search_changed(); void search_update(); - void on_decoder_name_edited(const QString &value); - void on_new_decoder_selected(int index); + void show_protocol_select(); -private: +private: static int decoder_name_cmp(const void *a, const void *b); void resize_table_view(data::DecoderModel *decoder_model); static bool protocol_sort_callback(const DecoderInfoItem *o1, const DecoderInfoItem *o2); - void show_protocol_list_panel(); - bool eventFilter(QObject *object, QEvent *event); private: SigSession *_session; @@ -152,8 +157,7 @@ private: QLabel *_dn_title_label; QPushButton *_add_button; - QPushButton *_del_all_button; - DsComboBox *_protocol_combobox; + QPushButton *_del_all_button; QVBoxLayout *_up_layout; std::vector _protocol_lay_items; //protocol item layers @@ -162,14 +166,12 @@ private: QPushButton *_dn_nav_button; QPushButton *_search_button; std::vector _decoderInfoList; + KeywordLineEdit *_keyword_edit; + QString _selected_protocol_id; + QToolButton *_arrow; mutable std::mutex _search_mutex; - bool _search_edited; - bool _searching; - - bool _add_silent; - DsTimer _key_find_timer; - bool _bSettingList; + bool _search_edited; }; } // namespace dock diff --git a/DSView/pv/dock/searchcombobox.cpp b/DSView/pv/dock/searchcombobox.cpp new file mode 100644 index 00000000..5f469b40 --- /dev/null +++ b/DSView/pv/dock/searchcombobox.cpp @@ -0,0 +1,171 @@ +#include "searchcombobox.h" +#include +#include +#include +#include +#include + + +//----------------------ComboButtonItem + +ComboButtonItem::ComboButtonItem(QWidget *parent, ISearchItemClick *click, void *data_handle) +:QPushButton(parent) +{ + _click = click; + _data_handle = data_handle; +} + +void ComboButtonItem::mousePressEvent(QMouseEvent *e) +{ + if (_click != NULL){ + _click->OnItemClick(this, _data_handle); + } +} + +//----------------------SearchComboBox + +SearchComboBox::SearchComboBox(QWidget *parent) + : QDialog(parent) +{ + _bShow = false; + _item_click = NULL; + + setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); + // setAttribute(Qt::WA_TranslucentBackground); +} + +SearchComboBox::~SearchComboBox(){ + //release resource + for (auto o : _items){ + delete o; + } + _items.clear(); +} + +void SearchComboBox::ShowDlg(QWidget *editline) +{ + if (_bShow) + return; + + _bShow = true; + + int w = 350; + int h = 450; + + if (editline != NULL){ + w = editline->width() + 7; + } + + this->setMinimumSize(w, h); + this->setMaximumSize(w, h); + + QVBoxLayout *grid = new QVBoxLayout(this); + this->setLayout(grid); + grid->setContentsMargins(0,0,0,0); + grid->setAlignment(Qt::AlignTop); + grid->setSpacing(2); + + QLineEdit *edit = new QLineEdit(this); + edit->setMaximumWidth(this->width()); + grid->addWidget(edit); + + QWidget *panel = new QWidget(this); + grid->addWidget(panel); + + panel->setContentsMargins(0,0,0,0); + panel->setMinimumSize(w, h - edit->height() - 5); + panel->setMaximumSize(w, h - edit->height() - 5); + + QWidget *listPanel = new QWidget(panel); + listPanel->setMinimumSize(w-2, panel->height()); + listPanel->setMaximumWidth(w-2); + + QVBoxLayout *listLay = new QVBoxLayout(listPanel); + listLay->setContentsMargins(2, 2, 20, 2); + listLay->setSpacing(0); + listLay->setAlignment(Qt::AlignTop); + + for(auto o : _items) + { + ComboButtonItem *bt = new ComboButtonItem(panel, this, o); + bt->setText(o->_name); + bt->setObjectName("flat"); + bt->setMaximumWidth(w - 20); + bt->setMinimumWidth(w - 20); + o->_control = bt; + listLay->addWidget(bt); + } + + _scroll = new QScrollArea(panel); + _scroll->setWidget(listPanel); + // pScrollArea->setStyleSheet("QScrollArea{border:none; background:red;}"); + _scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + if (editline != NULL) + { + QPoint p1 = editline->pos(); + QPoint p2 = editline->mapToGlobal(p1); + int x = p2.x() - p1.x(); + int y = p2.y() - p1.y(); + this->move(x, y); + } + + edit->setFocus(); + this->show(); + + + connect(edit, SIGNAL(textEdited(const QString &)), + this, SLOT(on_keyword_changed(const QString &))); +} + +void SearchComboBox::AddDataItem(QString id, QString name, void *data_handle) +{ + SearchDataItem *item = new SearchDataItem(); + item->_id = id; + item->_name = name; + item->_data_handle = data_handle; + this->_items.push_back(item); +} + + void SearchComboBox::changeEvent(QEvent *event) + { + if (event->type() == QEvent::ActivationChange){ + if (this->isActiveWindow() == false){ + this->close(); + this->deleteLater(); + return; + } + } + + QWidget::changeEvent(event); + } + + void SearchComboBox::OnItemClick(void *sender, void *data_handle) + { + if (data_handle != NULL && _item_click){ + SearchDataItem *item = (SearchDataItem*)data_handle; + this->close(); + ISearchItemClick *click = _item_click; + this->deleteLater(); + click->OnItemClick(this, item->_data_handle); + } + } + + void SearchComboBox::on_keyword_changed(const QString &value) + { + for(auto o : _items) + { + if (value == "" + || o->_name.indexOf(value, 0, Qt::CaseInsensitive) >= 0 + || o->_id.indexOf(value, 0, Qt::CaseInsensitive) >= 0){ + if (o->_control->isHidden()){ + o->_control->show(); + } + } + else if (o->_control->isHidden() == false){ + o->_control->hide(); + } + } + + _scroll->verticalScrollBar()->setValue(0); + } diff --git a/DSView/pv/dock/searchcombobox.h b/DSView/pv/dock/searchcombobox.h new file mode 100644 index 00000000..bb3446a5 --- /dev/null +++ b/DSView/pv/dock/searchcombobox.h @@ -0,0 +1,79 @@ +#ifndef SEARCHCOMBOBOX_H +#define SEARCHCOMBOBOX_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ISearchItemClick{ +public: + virtual void OnItemClick(void *sender, void *data_handle)=0; +}; + +//----------------------ComboButtonItem +class ComboButtonItem : public QPushButton + { + Q_OBJECT +public: + ComboButtonItem(QWidget *parent, ISearchItemClick *click, void *data_handle); + +protected: + void mousePressEvent(QMouseEvent *e); + +private: + void *_data_handle; + ISearchItemClick *_click; + }; + +//----------------------SearchDataItem + +class SearchDataItem{ +public: + QString _id; + QString _name; + void *_data_handle; + QWidget *_control; +}; + +//----------------------SearchComboBox + +class SearchComboBox : public QDialog, ISearchItemClick +{ + Q_OBJECT +public: + explicit SearchComboBox(QWidget *parent = nullptr); + + ~SearchComboBox(); + + void ShowDlg(QWidget *editline); + + void AddDataItem(QString id, QString name, void *data_handle); + + inline void SetItemClickHandle(ISearchItemClick *click){ + _item_click = click; + } + +protected: + void changeEvent(QEvent *event); + +private slots: + void on_keyword_changed(const QString &value); + +private: + //ISearchItemClick + void OnItemClick(void *sender, void *data_handle); + +private: + bool _bShow; + std::vector _items; + ISearchItemClick *_item_click; + QScrollArea *_scroll; +}; + +#endif // SEARCHCOMBOBOX_H diff --git a/DSView/pv/view/decodetrace.cpp b/DSView/pv/view/decodetrace.cpp index 57e9ddd2..87edbd23 100755 --- a/DSView/pv/view/decodetrace.cpp +++ b/DSView/pv/view/decodetrace.cpp @@ -55,6 +55,7 @@ #include "../dsvdef.h" #include "../ui/dscombobox.h" #include "../ui/msgbox.h" +#include "../appcontrol.h" #include using namespace boost; @@ -357,7 +358,8 @@ bool DecodeTrace::create_popup() _form_base_height = 0; _decoder_container = NULL; - dialogs::DSDialog dlg; + QWidget *topWindow = AppControl::Instance()->GetTopWindow(); + dialogs::DSDialog dlg(topWindow); //dlg.setMinimumSize(500,600); create_popup_form(&dlg); diff --git a/DSView/themes/dark.qss b/DSView/themes/dark.qss index d9d62acd..c7ab2d9f 100755 --- a/DSView/themes/dark.qss +++ b/DSView/themes/dark.qss @@ -62,6 +62,18 @@ QWidget:item:selected } */ +QPushButton#flat{ + text-align:left; + border:none; + font-size:14px; +} + +QPushButton#flat:hover +{ + background-color: #177cb0; + color: #801dae; +} + QCheckBox { spacing: 0px; diff --git a/DSView/themes/light.qss b/DSView/themes/light.qss index 06b47f2e..28d1d09b 100755 --- a/DSView/themes/light.qss +++ b/DSView/themes/light.qss @@ -59,6 +59,18 @@ QWidget:item:selected } */ +QPushButton#flat{ + text-align:left; + border:none; + font-size:14px; +} + +QPushButton#flat:hover +{ + background-color: #44cef6; + color: #801dae; +} + QCheckBox { spacing: 0px; From aae3278be08ef9743d09d74a097c96630824394d Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Fri, 22 Apr 2022 10:04:35 +0800 Subject: [PATCH 5/5] update: protocol search panel size --- DSView/pv/config/appconfig.h | 5 +++++ DSView/pv/dock/keywordlineedit.cpp | 20 ++++++++++++++++-- DSView/pv/dock/keywordlineedit.h | 3 +++ DSView/pv/dock/protocoldock.cpp | 9 +++++--- DSView/pv/dock/searchcombobox.cpp | 34 ++++++++++++++---------------- DSView/pv/dock/searchcombobox.h | 6 +++--- DSView/pv/view/decodetrace.cpp | 8 +++---- 7 files changed, 54 insertions(+), 31 deletions(-) diff --git a/DSView/pv/config/appconfig.h b/DSView/pv/config/appconfig.h index a78a85eb..88a168df 100644 --- a/DSView/pv/config/appconfig.h +++ b/DSView/pv/config/appconfig.h @@ -116,6 +116,11 @@ public: void SetProtocolFormat(const std::string &protocolName, const std::string &value); std::string GetProtocolFormat(const std::string &protocolName); + inline bool IsLangCn() + { + return _frameOptions.language == LAN_CN; + } + public: AppOptions _appOptions; UserHistory _userHistory; diff --git a/DSView/pv/dock/keywordlineedit.cpp b/DSView/pv/dock/keywordlineedit.cpp index ec1bebbe..4687896a 100644 --- a/DSView/pv/dock/keywordlineedit.cpp +++ b/DSView/pv/dock/keywordlineedit.cpp @@ -20,14 +20,17 @@ */ #include "keywordlineedit.h" +#include "../config/appconfig.h" #define PROTOCOL_FIND_TITLE "Protocol search..." +#define PROTOCOL_FIND_TITLE_cn "协议查找..." KeywordLineEdit::KeywordLineEdit(QWidget *parent, IKeywordActive *active) :QLineEdit(parent) { + _bText = false; _active = active; - this->setText(PROTOCOL_FIND_TITLE); + this->ResetText(); } void KeywordLineEdit::mousePressEvent(QMouseEvent *e) @@ -39,6 +42,19 @@ KeywordLineEdit::KeywordLineEdit(QWidget *parent, IKeywordActive *active) } void KeywordLineEdit::ResetText() + { + if (_bText){ + return; + } + + if (AppConfig::Instance().IsLangCn()) + this->setText(PROTOCOL_FIND_TITLE_cn); + else + this->setText(PROTOCOL_FIND_TITLE); + } + + void KeywordLineEdit::SetInputText(QString text) { - this->setText(PROTOCOL_FIND_TITLE); + _bText = true; + this->setText(text); } \ No newline at end of file diff --git a/DSView/pv/dock/keywordlineedit.h b/DSView/pv/dock/keywordlineedit.h index bf85514b..6365905e 100644 --- a/DSView/pv/dock/keywordlineedit.h +++ b/DSView/pv/dock/keywordlineedit.h @@ -41,11 +41,14 @@ public: void ResetText(); + void SetInputText(QString text); + protected: void mousePressEvent(QMouseEvent *e); private: IKeywordActive *_active; + bool _bText; }; diff --git a/DSView/pv/dock/protocoldock.cpp b/DSView/pv/dock/protocoldock.cpp index 36eb923c..ae559d04 100755 --- a/DSView/pv/dock/protocoldock.cpp +++ b/DSView/pv/dock/protocoldock.cpp @@ -78,7 +78,7 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio _del_all_button->setCheckable(true); _keyword_edit = new KeywordLineEdit(_up_widget, this); - _keyword_edit->setReadOnly(true); + _keyword_edit->setReadOnly(true); GSList *l = const_cast(srd_decoder_list()); @@ -247,6 +247,8 @@ void ProtocolDock::retranslateUi() _search_edit->setPlaceholderText(tr("search")); _matchs_title_label->setText(tr("Matching Items:")); _dn_title_label->setText(tr("Protocol List Viewer")); + + _keyword_edit->ResetText(); } void ProtocolDock::reStyle() @@ -265,7 +267,7 @@ void ProtocolDock::reStyle() for (auto it = _protocol_lay_items.begin(); it != _protocol_lay_items.end(); it++){ (*it)->ResetStyle(); - } + } } void ProtocolDock::changeEvent(QEvent *event) @@ -292,6 +294,7 @@ void ProtocolDock::resizeEvent(QResizeEvent *event) _pre_button->width()-_nxt_button->width(); width = std::max(width, 0); _search_edit->setMinimumWidth(width); + _keyword_edit->setMinimumWidth(width-20); QScrollArea::resizeEvent(event); } @@ -1012,7 +1015,7 @@ bool ProtocolDock::protocol_sort_callback(const DecoderInfoItem *o1, const Decod if (data_handle != NULL){ DecoderInfoItem *info = (DecoderInfoItem*)data_handle; srd_decoder *dec = (srd_decoder *)(info->_data_handle); - this->_keyword_edit->setText( QString(dec->name)); + this->_keyword_edit->SetInputText(QString(dec->name)); _selected_protocol_id = QString(dec->id); this->on_add_protocol(); } diff --git a/DSView/pv/dock/searchcombobox.cpp b/DSView/pv/dock/searchcombobox.cpp index 5f469b40..b68988be 100644 --- a/DSView/pv/dock/searchcombobox.cpp +++ b/DSView/pv/dock/searchcombobox.cpp @@ -4,7 +4,7 @@ #include #include #include - +#include //----------------------ComboButtonItem @@ -29,9 +29,7 @@ SearchComboBox::SearchComboBox(QWidget *parent) { _bShow = false; _item_click = NULL; - setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); - // setAttribute(Qt::WA_TranslucentBackground); } SearchComboBox::~SearchComboBox(){ @@ -50,14 +48,14 @@ void SearchComboBox::ShowDlg(QWidget *editline) _bShow = true; int w = 350; - int h = 450; + int h = 550; + int eh = 20; if (editline != NULL){ - w = editline->width() + 7; + w = editline->width(); } - this->setMinimumSize(w, h); - this->setMaximumSize(w, h); + this->setFixedSize(w, h); QVBoxLayout *grid = new QVBoxLayout(this); this->setLayout(grid); @@ -67,19 +65,15 @@ void SearchComboBox::ShowDlg(QWidget *editline) QLineEdit *edit = new QLineEdit(this); edit->setMaximumWidth(this->width()); - grid->addWidget(edit); - - QWidget *panel = new QWidget(this); - grid->addWidget(panel); + grid->addWidget(edit); + eh = edit->height(); + QWidget *panel= new QWidget(this); panel->setContentsMargins(0,0,0,0); - panel->setMinimumSize(w, h - edit->height() - 5); - panel->setMaximumSize(w, h - edit->height() - 5); + panel->setFixedSize(w, h - eh); + grid->addWidget(panel); QWidget *listPanel = new QWidget(panel); - listPanel->setMinimumSize(w-2, panel->height()); - listPanel->setMaximumWidth(w-2); - QVBoxLayout *listLay = new QVBoxLayout(listPanel); listLay->setContentsMargins(2, 2, 20, 2); listLay->setSpacing(0); @@ -98,8 +92,9 @@ void SearchComboBox::ShowDlg(QWidget *editline) _scroll = new QScrollArea(panel); _scroll->setWidget(listPanel); - // pScrollArea->setStyleSheet("QScrollArea{border:none; background:red;}"); + _scroll->setStyleSheet("QScrollArea{border:none;}"); _scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + _scroll->setFixedSize(w, h - eh); if (editline != NULL) { @@ -153,6 +148,9 @@ void SearchComboBox::AddDataItem(QString id, QString name, void *data_handle) void SearchComboBox::on_keyword_changed(const QString &value) { + if (_items.size() == 0) + return; + for(auto o : _items) { if (value == "" @@ -166,6 +164,6 @@ void SearchComboBox::AddDataItem(QString id, QString name, void *data_handle) o->_control->hide(); } } - + _scroll->verticalScrollBar()->setValue(0); } diff --git a/DSView/pv/dock/searchcombobox.h b/DSView/pv/dock/searchcombobox.h index bb3446a5..466a3f3a 100644 --- a/DSView/pv/dock/searchcombobox.h +++ b/DSView/pv/dock/searchcombobox.h @@ -70,10 +70,10 @@ private: void OnItemClick(void *sender, void *data_handle); private: - bool _bShow; + bool _bShow; std::vector _items; - ISearchItemClick *_item_click; - QScrollArea *_scroll; + ISearchItemClick *_item_click; + QScrollArea *_scroll; }; #endif // SEARCHCOMBOBOX_H diff --git a/DSView/pv/view/decodetrace.cpp b/DSView/pv/view/decodetrace.cpp index 87edbd23..836efaa4 100755 --- a/DSView/pv/view/decodetrace.cpp +++ b/DSView/pv/view/decodetrace.cpp @@ -743,7 +743,7 @@ void DecodeTrace::create_decoder_form( decoder_form->setFormAlignment(Qt::AlignLeft); decoder_form->setLabelAlignment(Qt::AlignLeft); decoder_form->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); - + // Add the mandatory channels for(l = decoder->channels; l; l = l->next) { const struct srd_channel *const pdch = @@ -758,7 +758,7 @@ void DecodeTrace::create_decoder_form( _probe_selectors.push_back(s); connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(on_probe_selected(int))); - } + } // Add the optional channels for(l = decoder->opt_channels; l; l = l->next) { @@ -779,10 +779,8 @@ void DecodeTrace::create_decoder_form( // Add the options auto binding = new prop::binding::DecoderOptions(decoder_stack, dec); binding->add_properties_to_form(decoder_form, true); - _bindings.push_back(binding); - - + pv::widgets::DecoderGroupBox *const group = new pv::widgets::DecoderGroupBox(decoder_stack, dec, decoder_form, parent);