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/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/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 d15805f4..4687896a 100644 --- a/DSView/pv/dock/keywordlineedit.cpp +++ b/DSView/pv/dock/keywordlineedit.cpp @@ -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); } \ No newline at end of file diff --git a/DSView/pv/dock/keywordlineedit.h b/DSView/pv/dock/keywordlineedit.h index 205de9e2..6365905e 100644 --- a/DSView/pv/dock/keywordlineedit.h +++ b/DSView/pv/dock/keywordlineedit.h @@ -23,25 +23,32 @@ #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(); + + 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; }; diff --git a/DSView/pv/dock/protocoldock.cpp b/DSView/pv/dock/protocoldock.cpp index c17c9843..ae559d04 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,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 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::listObjectHandle); + 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 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..b68988be --- /dev/null +++ b/DSView/pv/dock/searchcombobox.cpp @@ -0,0 +1,169 @@ +#include "searchcombobox.h" +#include +#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); +} + +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); + } diff --git a/DSView/pv/dock/searchcombobox.h b/DSView/pv/dock/searchcombobox.h new file mode 100644 index 00000000..466a3f3a --- /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/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 6b2732f4..229919b0 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..18ac770f 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(); @@ -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/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/decodetrace.cpp b/DSView/pv/view/decodetrace.cpp index 57e9ddd2..836efaa4 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); @@ -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); 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/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; diff --git a/doc/Decoder develop base course.docx b/doc/Decoder develop base course.docx index 2d013a11..b0b03154 100644 Binary files a/doc/Decoder develop base course.docx and b/doc/Decoder develop base course.docx differ diff --git a/libsigrokdecode4DSL/decoders/example/pd.py b/libsigrokdecode4DSL/decoders/example/pd.py index d193c301..0cf0e7c6 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