diff --git a/DSView/pv/dock/protocoldock.cpp b/DSView/pv/dock/protocoldock.cpp index 6081c64f..2be0a286 100755 --- a/DSView/pv/dock/protocoldock.cpp +++ b/DSView/pv/dock/protocoldock.cpp @@ -37,14 +37,14 @@ #include #include #include -#include #include #include #include #include #include #include - +#include +#include #include #include "../ui/msgbox.h" @@ -53,7 +53,7 @@ #include "../data/decode/decoderstatus.h" using namespace std; - + namespace pv { namespace dock { @@ -75,22 +75,58 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio _del_all_button = new QPushButton(_up_widget); _del_all_button->setFlat(true); _del_all_button->setCheckable(true); - _protocol_combobox = new DsComboBox(_up_widget); - GSList *l = g_slist_sort(g_slist_copy( - (GSList*)srd_decoder_list()), decoder_name_cmp); + _protocol_combobox = new DsComboBox(_up_widget); + _protocol_combobox->setEditable(true); + _protocol_combobox->setCompleter(NULL); + + GSList *l = g_slist_sort(g_slist_copy((GSList*)srd_decoder_list()), decoder_name_cmp); + int protocol_index = 0; + std::map pro_key_table; + QString repeatNammes; + 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; + if (true == have_probes) { - _protocol_combobox->addItem(QString::fromUtf8(d->name), QVariant::fromValue(l->data)); + DecoderInfoItem *info = new DecoderInfoItem(); + strncpy(info->Name, d->name, DECODER_NAME_LEN-1); + strncpy(info->Id, d->id, DECODER_NAME_LEN-1); + info->Index = protocol_index; + info->ObjectHandle = l->data; + protocol_index++; + + _decoderInfoList.push_back(info); + + std::string prokey(info->Id); + if (pro_key_table.find(prokey) != pro_key_table.end()){ + if (repeatNammes != "") + repeatNammes += ","; + repeatNammes += info->Id; + } + else{ + pro_key_table[prokey] = 1; + } } } g_slist_free(l); + //sort protocol list + sort(_decoderInfoList.begin(), _decoderInfoList.end(), ProtocolDock::protocol_sort_callback); + + for (auto info : _decoderInfoList){ + _protocol_combobox->addItem(QString::fromUtf8(info->Name), QVariant::fromValue(info->Index)); + } + + if (repeatNammes != ""){ + QString err = "Any protocol have repeated id or name: "; + err += repeatNammes; + MsgBox::Show("error", err.toLatin1().data()); + } + hori_layout->addWidget(_add_button); hori_layout->addWidget(_del_all_button); hori_layout->addWidget(_protocol_combobox); @@ -103,9 +139,6 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio _up_widget->setLayout(_up_layout); _up_widget->setMinimumHeight(150); -// this->setWidget(_widget); -// _widget->setGeometry(0, 0, sizeHint().width(), 500); -// _widget->setObjectName("protocolWidget"); _dn_widget = new QWidget(this); @@ -179,9 +212,10 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio this->setWidgetResizable(true); this->setWidget(_split_widget); - _split_widget->setObjectName("protocolWidget"); + retranslateUi(); + 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())); @@ -192,19 +226,26 @@ ProtocolDock::ProtocolDock(QWidget *parent, view::View &view, SigSession *sessio connect(this, SIGNAL(protocol_updated()), this, SLOT(update_model())); connect(_table_view, SIGNAL(clicked(QModelIndex)), this, SLOT(item_clicked(QModelIndex))); - connect(_table_view->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(column_resize(int, int, int))); + + connect(_table_view->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), + this, SLOT(column_resize(int, int, int))); + connect(_search_edit, SIGNAL(editingFinished()), this, SLOT(search_changed())); - retranslateUi(); + connect(_protocol_combobox->lineEdit(), SIGNAL(textEdited(const QString &)), + this, SLOT(on_decoder_name_edited(const QString &))); } ProtocolDock::~ProtocolDock() { //destroy protocol item layers - for (auto it = _protocol_items.begin(); it != _protocol_items.end(); it++){ + for (auto it = _protocol_lay_items.begin(); it != _protocol_lay_items.end(); it++){ DESTROY_QT_LATER(*it); } - _protocol_items.clear(); + _protocol_lay_items.clear(); + + //clear protocol infos list + RELEASE_ARRAY(_decoderInfoList); } void ProtocolDock::changeEvent(QEvent *event) @@ -236,7 +277,7 @@ void ProtocolDock::reStyle() _nxt_button->setIcon(QIcon(iconPath+"/next.svg")); _search_button->setIcon(QIcon(iconPath+"/search.svg")); - for (auto it = _protocol_items.begin(); it != _protocol_items.end(); it++){ + for (auto it = _protocol_lay_items.begin(); it != _protocol_lay_items.end(); it++){ (*it)->ResetStyle(); } } @@ -267,65 +308,60 @@ int ProtocolDock::decoder_name_cmp(const void *a, const void *b) ((const srd_decoder*)b)->name); } -bool ProtocolDock::sel_protocol(QString id) +int ProtocolDock::get_protocol_index_by_id(QString id) { - QString name; - GSList *l = g_slist_sort(g_slist_copy( - (GSList*)srd_decoder_list()), decoder_name_cmp); - 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; - if (true == have_probes && - QString::fromUtf8(d->id) == id) { - name = QString::fromUtf8(d->name); - break; + int dex = 0; + for (auto info : _decoderInfoList){ + QString proid(info->Id); + if (id == proid){ + return dex; } + ++dex; } - g_slist_free(l); - - _protocol_combobox->setCurrentText(name); - if (_protocol_combobox->currentText() == name) - return true; - else - return false; + return -1; } void ProtocolDock::on_add_protocol() -{ - add_protocol(false); -} - -void ProtocolDock::add_protocol(bool silent) -{ - if (_session->get_device()->dev_inst()->mode != LOGIC) { - MsgBox::Show(NULL, "Protocol Analyzer\nProtocol Analyzer is only valid in Digital Mode!", this); +{ + if (_decoderInfoList.size() == 0){ + MsgBox::Show(NULL, "Protocol list is empty!"); return; - } - - //have no protocol - if (_protocol_combobox->count() == 0){ - if (!silent){ - MsgBox::Show(NULL, "Protocol list is empty!"); - } + } + if (_protocol_combobox->currentIndex() == -1){ + MsgBox::Show(NULL, "Please select a protocol!"); return; } - srd_decoder *const decoder = - (srd_decoder *)(_protocol_combobox->itemData(_protocol_combobox->currentIndex())).value(); + int dex = _protocol_combobox->itemData(_protocol_combobox->currentIndex()).toInt(); + QString pro_id(_decoderInfoList[dex]->Id); + add_protocol_by_id(pro_id, false); +} + +bool ProtocolDock::add_protocol_by_id(QString id, bool silent) +{ + if (_session->get_device()->dev_inst()->mode != LOGIC) { + qDebug()<<"Protocol Analyzer\nProtocol Analyzer is only valid in Digital Mode!"; + return false; + } + + int dex = this->get_protocol_index_by_id(id); + if (dex == -1){ + qDebug()<<"Protocol not exists! id:"<< id; + return false; + } + + srd_decoder *const decoder = (srd_decoder *)(_decoderInfoList[dex]->ObjectHandle); DecoderStatus *dstatus = new DecoderStatus(); dstatus->m_format = (int)DecoderDataFormat::hex; if (_session->add_decoder(decoder, silent, dstatus)) { - //crate item layer - QString protocolName = _protocol_combobox->currentText(); + //create item layer + QString protocolName(_decoderInfoList[dex]->Name); ProtocolItemLayer *layer = new ProtocolItemLayer(_up_widget, protocolName, this); - _protocol_items.push_back(layer); - _up_layout->insertLayout(_protocol_items.size(), layer); + _protocol_lay_items.push_back(layer); + _up_layout->insertLayout(_protocol_lay_items.size(), layer); layer->m_decoderStatus = dstatus; //set current protocol format @@ -341,11 +377,15 @@ void ProtocolDock::add_protocol(bool silent) connect(decode_sigs.back(), SIGNAL(decoded_progress(int)), this, SLOT(decoded_progress(int))); protocol_updated(); + + return true; } + + return false; } void ProtocolDock::on_del_all_protocol(){ - if (_protocol_items.size() == 0){ + if (_protocol_lay_items.size() == 0){ MsgBox::Show(NULL, "No Protocol Analyzer to delete!", this); return; } @@ -353,21 +393,20 @@ void ProtocolDock::add_protocol(bool silent) if (MsgBox::Confirm("Are you sure to remove all protocol analyzer?", this)){ del_all_protocol(); } - } - + } void ProtocolDock::del_all_protocol() { - if (_protocol_items.size() > 0) + if (_protocol_lay_items.size() > 0) { _session->clear_all_decoder(); - for (auto it = _protocol_items.begin(); it != _protocol_items.end(); it++) + for (auto it = _protocol_lay_items.begin(); it != _protocol_lay_items.end(); it++) { DESTROY_QT_LATER((*it)); //destory control } - _protocol_items.clear(); + _protocol_lay_items.clear(); protocol_updated(); } } @@ -386,19 +425,10 @@ void ProtocolDock::decoded_progress(int progress) if (d->decoder()->out_of_memory()) err = tr("(Out of Memory)"); - if (index < _protocol_items.size()) + if (index < _protocol_lay_items.size()) { - ProtocolItemLayer &lay = *(_protocol_items.at(index)); + ProtocolItemLayer &lay = *(_protocol_lay_items.at(index)); lay.SetProgress(pg, err); - - //when decode complete, check data format - if (pg == 100) - { - // bool flag = ((DecoderStatus*)lay.m_decoderStatus)->m_bNumerical; - // lay.LoadFormatSelect(!flag); - // QString &protocolName = lay.GetProtocolName(); - // lay.SetProtocolFormat(protocolName.toStdString().c_str()); - } } index++; @@ -771,7 +801,7 @@ void ProtocolDock::search_update() //-------------------IProtocolItemLayerCallback void ProtocolDock::OnProtocolSetting(void *handle){ int dex = 0; - for (auto it = _protocol_items.begin(); it != _protocol_items.end(); it++){ + for (auto it = _protocol_lay_items.begin(); it != _protocol_lay_items.end(); it++){ if ((*it) == handle){ _session->rst_decoder(dex); protocol_updated(); @@ -787,10 +817,10 @@ void ProtocolDock::OnProtocolDelete(void *handle){ } int dex = 0; - for (auto it = _protocol_items.begin(); it != _protocol_items.end(); it++){ + for (auto it = _protocol_lay_items.begin(); it != _protocol_lay_items.end(); it++){ if ((*it) == handle){ DESTROY_QT_LATER(*it); - _protocol_items.remove(dex); + _protocol_lay_items.remove(dex); _session->remove_decoder(dex); protocol_updated(); break; @@ -800,7 +830,7 @@ void ProtocolDock::OnProtocolDelete(void *handle){ } void ProtocolDock::OnProtocolFormatChanged(QString format, void *handle){ - for (auto it = _protocol_items.begin(); it != _protocol_items.end(); it++){ + for (auto it = _protocol_lay_items.begin(); it != _protocol_lay_items.end(); it++){ if ((*it) == handle){ QString &name = (*it)->GetProtocolName(); AppConfig::Instance().SetProtocolFormat(name.toStdString(), format.toStdString()); @@ -810,6 +840,59 @@ void ProtocolDock::OnProtocolFormatChanged(QString format, void *handle){ } } } + +void ProtocolDock::on_decoder_name_edited(const QString &value) +{ + while (_protocol_combobox->count()) + { + _protocol_combobox->removeItem(0); + } + + for (auto &info: _decoderInfoList){ + QString name(info->Name); + if (value == "" || name.indexOf(value, 0, Qt::CaseInsensitive) != -1){ + _protocol_combobox->addItem(QString::fromUtf8(info->Name), QVariant::fromValue(info->Index)); + } + } + + _protocol_combobox->setCurrentIndex(-1); + _protocol_combobox->lineEdit()->setText(value); +} + +bool ProtocolDock::protocol_sort_callback(const DecoderInfoItem *o1, const DecoderInfoItem *o2) +{ + const char *s1 = o1->Name; + const char *s2 = o2->Name; + char c1 = 0; + char c2 = 0; + + while (*s1 && *s2) + { + c1 = *s1; + c2 = *s2; + + if (c1 >= 'a' && c1 <= 'z') c1 -= 32; + if (c2 >= 'a' && c2 <= 'z') c2 -= 32; + + if (c1 > c2) + return false; + else if (c1 < c2) + return true; + + s1++; + s2++; + } + + if (*s1) + return false; + else if (*s2) + return true; + + return true; +} + + + //------------------------- diff --git a/DSView/pv/dock/protocoldock.h b/DSView/pv/dock/protocoldock.h index c01245f0..0e017316 100755 --- a/DSView/pv/dock/protocoldock.h +++ b/DSView/pv/dock/protocoldock.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,16 @@ #include "../data/decodermodel.h" #include "protocolitemlayer.h" #include "../ui/dscombobox.h" +#include "../dstimer.h" +#define DECODER_NAME_LEN 20 + +struct DecoderInfoItem{ + char Name[DECODER_NAME_LEN]; + char Id[DECODER_NAME_LEN]; + int Index; + void *ObjectHandle; //srd_decoder* type +}; namespace pv { @@ -58,7 +68,7 @@ class View; namespace dock { -class ProtocolDock : public QScrollArea,public IProtocolItemLayerCallback +class ProtocolDock : public QScrollArea, public IProtocolItemLayerCallback { Q_OBJECT @@ -69,9 +79,8 @@ public: ProtocolDock(QWidget *parent, view::View &view, SigSession *session); ~ProtocolDock(); - void del_all_protocol(); - bool sel_protocol(QString name); - void add_protocol(bool silent); + void del_all_protocol(); + bool add_protocol_by_id(QString id, bool silent); private: void changeEvent(QEvent *event); @@ -87,6 +96,7 @@ private: void OnProtocolSetting(void *handle); void OnProtocolDelete(void *handle); void OnProtocolFormatChanged(QString format, void *handle); + int get_protocol_index_by_id(QString id); signals: void protocol_updated(); @@ -108,10 +118,12 @@ private slots: void search_done(); void search_changed(); void search_update(); - + void on_decoder_name_edited(const QString &value); + 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); private: SigSession *_session; @@ -136,14 +148,14 @@ private: QPushButton *_add_button; QPushButton *_del_all_button; DsComboBox *_protocol_combobox; - QVector _protocol_index_list; QVBoxLayout *_up_layout; - QVector _protocol_items; //protocol item layers + QVector _protocol_lay_items; //protocol item layers QPushButton *_dn_set_button; QPushButton *_dn_save_button; QPushButton *_dn_nav_button; QPushButton *_search_button; + std::vector _decoderInfoList; mutable std::mutex _search_mutex; bool _search_edited; diff --git a/DSView/pv/storesession.cpp b/DSView/pv/storesession.cpp index 87fb50b4..8116cc12 100755 --- a/DSView/pv/storesession.cpp +++ b/DSView/pv/storesession.cpp @@ -993,13 +993,11 @@ bool StoreSession::load_decoders(dock::ProtocolDock *widget, QJsonArray dec_arra std::vector &pre_dsigs = _session->get_decode_signals(); //set current protocol - if (widget->sel_protocol(dec_obj["id"].toString())) + bool ret = widget->add_protocol_by_id(dec_obj["id"].toString(), true); + if (!ret) { - widget->add_protocol(true); - } - else{ continue; //protocol is not exists; - } + } std::vector &aft_dsigs = _session->get_decode_signals();