forked from Ivasoft/DSView
Merge branch 'dev-tai' of https://github.com/DreamSourceLab/DSView into dev-tai
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <QDir>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QWidget>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <string>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -20,29 +20,41 @@
|
||||
*/
|
||||
|
||||
#include "keywordlineedit.h"
|
||||
#include "../config/appconfig.h"
|
||||
|
||||
KeywordLineEdit::KeywordLineEdit(QComboBox *comboBox)
|
||||
:QLineEdit()
|
||||
{
|
||||
assert(comboBox);
|
||||
_comboBox = comboBox;
|
||||
#define PROTOCOL_FIND_TITLE "Protocol search..."
|
||||
#define PROTOCOL_FIND_TITLE_cn "协议查找..."
|
||||
|
||||
KeywordLineEdit::KeywordLineEdit(QWidget *parent, IKeywordActive *active)
|
||||
:QLineEdit(parent)
|
||||
{
|
||||
_bText = false;
|
||||
_active = active;
|
||||
this->ResetText();
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
QLineEdit::focusOutEvent(e);
|
||||
void KeywordLineEdit::ResetText()
|
||||
{
|
||||
if (_bText){
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->text() == ""){
|
||||
this->setText(PROTOCOL_FIND_TITLE);
|
||||
}
|
||||
if (AppConfig::Instance().IsLangCn())
|
||||
this->setText(PROTOCOL_FIND_TITLE_cn);
|
||||
else
|
||||
this->setText(PROTOCOL_FIND_TITLE);
|
||||
}
|
||||
|
||||
void KeywordLineEdit::SetInputText(QString text)
|
||||
{
|
||||
_bText = true;
|
||||
this->setText(text);
|
||||
}
|
||||
@@ -23,25 +23,32 @@
|
||||
#define KEY_WORD_LINE_EDIT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QFocusEvent>
|
||||
#include <QLineEdit>
|
||||
#include <QMouseEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#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();
|
||||
|
||||
void SetInputText(QString text);
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent *e) override;
|
||||
void focusOutEvent(QFocusEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
|
||||
private:
|
||||
QComboBox *_comboBox;
|
||||
IKeywordActive *_active;
|
||||
bool _bText;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <QToolButton>
|
||||
|
||||
#include <algorithm>
|
||||
#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<GSList*>(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<QFrame*>();
|
||||
QWidget *wid1 = popup1->findChild<QWidget*>();
|
||||
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,20 +242,13 @@ 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"));
|
||||
_matchs_title_label->setText(tr("Matching Items:"));
|
||||
_dn_title_label->setText(tr("Protocol List Viewer"));
|
||||
|
||||
_keyword_edit->ResetText();
|
||||
}
|
||||
|
||||
void ProtocolDock::reStyle()
|
||||
@@ -296,16 +263,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();
|
||||
@@ -319,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);
|
||||
}
|
||||
|
||||
@@ -332,7 +308,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 +316,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<data::decode::Decoder*> sub_decoders;
|
||||
|
||||
@@ -373,7 +350,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 +395,7 @@ bool ProtocolDock::add_protocol_by_id(QString id, bool silent, std::list<pv::dat
|
||||
return false;
|
||||
}
|
||||
|
||||
srd_decoder *const decoder = (srd_decoder *)(_decoderInfoList[dex]->ObjectHandle);
|
||||
srd_decoder *const decoder = (srd_decoder *)(_decoderInfoList[dex]->_data_handle);
|
||||
DecoderStatus *dstatus = new DecoderStatus();
|
||||
dstatus->m_format = (int)DecoderDataFormat::hex;
|
||||
|
||||
@@ -924,54 +901,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 +937,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 +973,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 +991,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->SetInputText(QString(dec->name));
|
||||
_selected_protocol_id = QString(dec->id);
|
||||
this->on_add_protocol();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dock
|
||||
} // namespace pv
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <QTableView>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QLineEdit>
|
||||
#include <QToolButton>
|
||||
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
@@ -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 <ProtocolItemLayer*> _protocol_lay_items; //protocol item layers
|
||||
|
||||
@@ -162,14 +166,12 @@ private:
|
||||
QPushButton *_dn_nav_button;
|
||||
QPushButton *_search_button;
|
||||
std::vector<DecoderInfoItem*> _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
|
||||
|
||||
169
DSView/pv/dock/searchcombobox.cpp
Normal file
169
DSView/pv/dock/searchcombobox.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#include "searchcombobox.h"
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPoint>
|
||||
#include <QLineEdit>
|
||||
#include <QScrollBar>
|
||||
#include <QDebug>
|
||||
|
||||
//----------------------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);
|
||||
}
|
||||
|
||||
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 = 550;
|
||||
int eh = 20;
|
||||
|
||||
if (editline != NULL){
|
||||
w = editline->width();
|
||||
}
|
||||
|
||||
this->setFixedSize(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);
|
||||
eh = edit->height();
|
||||
|
||||
QWidget *panel= new QWidget(this);
|
||||
panel->setContentsMargins(0,0,0,0);
|
||||
panel->setFixedSize(w, h - eh);
|
||||
grid->addWidget(panel);
|
||||
|
||||
QWidget *listPanel = new QWidget(panel);
|
||||
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);
|
||||
_scroll->setStyleSheet("QScrollArea{border:none;}");
|
||||
_scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
_scroll->setFixedSize(w, h - eh);
|
||||
|
||||
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)
|
||||
{
|
||||
if (_items.size() == 0)
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
79
DSView/pv/dock/searchcombobox.h
Normal file
79
DSView/pv/dock/searchcombobox.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef SEARCHCOMBOBOX_H
|
||||
#define SEARCHCOMBOBOX_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDialog>
|
||||
#include <QWidget>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
#include <QEvent>
|
||||
#include <QScrollArea>
|
||||
|
||||
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<SearchDataItem*> _items;
|
||||
ISearchItemClick *_item_click;
|
||||
QScrollArea *_scroll;
|
||||
};
|
||||
|
||||
#endif // SEARCHCOMBOBOX_H
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "dsvdef.h"
|
||||
#include "config/appconfig.h"
|
||||
#include "ui/msgbox.h"
|
||||
#include "appcontrol.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
@@ -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;
|
||||
|
||||
@@ -178,7 +178,7 @@ private:
|
||||
void data_received();
|
||||
|
||||
//------private
|
||||
bool gen_session_json(QJsonArray &array);
|
||||
bool gen_session_json(QJsonObject &sessionVar);
|
||||
|
||||
private:
|
||||
AppControl *_control;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <QStyleOption>
|
||||
#include <assert.h>
|
||||
#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 ){
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
#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");
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "../dsvdef.h"
|
||||
#include "../ui/dscombobox.h"
|
||||
#include "../ui/msgbox.h"
|
||||
#include "../appcontrol.h"
|
||||
#include <QDebug>
|
||||
|
||||
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);
|
||||
|
||||
@@ -741,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 =
|
||||
@@ -756,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) {
|
||||
@@ -777,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);
|
||||
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Binary file not shown.
@@ -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个通道的匹配信息,通过位运算来获取具体信息。
|
||||
Reference in New Issue
Block a user