X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fsubwindows%2Fdecoder_selector%2Fsubwindow.cpp;h=719d2efa1456142ac940936ec80560e671ad2a6e;hp=80b0f382faee4182fb860452f78421f4fa860c30;hb=b229a1b72d6f675e0fcf14aa83285e5c3ca122be;hpb=97378470ded88af84edaa0f1063d10d834475665 diff --git a/pv/subwindows/decoder_selector/subwindow.cpp b/pv/subwindows/decoder_selector/subwindow.cpp index 80b0f382..719d2efa 100644 --- a/pv/subwindows/decoder_selector/subwindow.cpp +++ b/pv/subwindows/decoder_selector/subwindow.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -36,26 +37,89 @@ namespace subwindows { namespace decoder_selector { +bool QCustomSortFilterProxyModel::filterAcceptsRow(int source_row, + const QModelIndex& source_parent) const +{ + // Search model recursively + + if (QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent)) + return true; + + const QModelIndex index = sourceModel()->index(source_row, 0, source_parent); + + for (int i = 0; i < sourceModel()->rowCount(index); i++) + if (filterAcceptsRow(i, index)) + return true; + + return false; +} + + +void QCustomTreeView::currentChanged(const QModelIndex& current, + const QModelIndex& previous) +{ + QTreeView::currentChanged(current, previous); + currentChanged(current); +} + + SubWindow::SubWindow(Session& session, QWidget* parent) : SubWindowBase(session, parent), splitter_(new QSplitter()), - tree_view_(new QTreeView()), - model_(new DecoderCollectionModel()) + tree_view_(new QCustomTreeView()), + info_box_(new QWidget()), + info_label_header_(new QLabel()), + info_label_body_(new QLabel()), + info_label_footer_(new QLabel()), + model_(new DecoderCollectionModel()), + sort_filter_model_(new QCustomSortFilterProxyModel()) { QVBoxLayout* root_layout = new QVBoxLayout(this); root_layout->setContentsMargins(0, 0, 0, 0); root_layout->addWidget(splitter_); - splitter_->addWidget(tree_view_); + QWidget* upper_container = new QWidget(); + QVBoxLayout* upper_layout = new QVBoxLayout(upper_container); + upper_layout->setContentsMargins(0, 5, 0, 0); + QLineEdit* filter = new QLineEdit(); + upper_layout->addWidget(filter); + upper_layout->addWidget(tree_view_); + + splitter_->setOrientation(Qt::Vertical); + splitter_->addWidget(upper_container); + splitter_->addWidget(info_box_); + + const QIcon filter_icon(QIcon::fromTheme("search", + QIcon(":/icons/search.svg"))); + filter->setClearButtonEnabled(true); + filter->addAction(filter_icon, QLineEdit::LeadingPosition); + + sort_filter_model_->setSourceModel(model_); + sort_filter_model_->setFilterCaseSensitivity(Qt::CaseInsensitive); - tree_view_->setModel(model_); + tree_view_->setModel(sort_filter_model_); tree_view_->setRootIsDecorated(true); + tree_view_->setSortingEnabled(true); + tree_view_->sortByColumn(0, Qt::AscendingOrder); // Hide the columns that hold the detailed item information tree_view_->hideColumn(2); // ID - connect(tree_view_, SIGNAL(doubleClicked(const QModelIndex&)), - this, SLOT(on_item_double_clicked(const QModelIndex&))); + info_box_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + QVBoxLayout* info_box_layout = new QVBoxLayout(info_box_); + info_box_layout->addWidget(info_label_header_); + info_box_layout->addWidget(info_label_body_); + info_box_layout->addWidget(info_label_footer_); + info_label_body_->setWordWrap(true); + info_label_body_->setText(tr("Select a decoder to see its description here.")); + + connect(filter, SIGNAL(textChanged(const QString&)), + this, SLOT(on_filter_changed(const QString&))); + + connect(tree_view_, SIGNAL(currentChanged(const QModelIndex&)), + this, SLOT(on_item_changed(const QModelIndex&))); + connect(tree_view_, SIGNAL(activated(const QModelIndex&)), + this, SLOT(on_item_activated(const QModelIndex&))); connect(this, SIGNAL(new_decoders_selected(vector)), &session, SLOT(on_new_decoders_selected(vector))); @@ -125,7 +189,41 @@ vector SubWindow::decoders_providing(const char* output) con return ret_val; } -void SubWindow::on_item_double_clicked(const QModelIndex& index) +void SubWindow::on_item_changed(const QModelIndex& index) +{ + if (!index.isValid()) + return; + + QModelIndex id_index = index.model()->index(index.row(), 2, index.parent()); + QString decoder_name = index.model()->data(id_index, Qt::DisplayRole).toString(); + + if (decoder_name.isEmpty()) + return; + + const srd_decoder* d = get_srd_decoder_from_id(decoder_name); + + const QString id = QString::fromUtf8(d->id); + const QString longname = QString::fromUtf8(d->longname); + const QString desc = QString::fromUtf8(d->desc); + const QString doc = QString::fromUtf8(srd_decoder_doc_get(d)); + + QString tags; + GSList* l = g_slist_copy((GSList*)d->tags); + for (GSList* li = l; li; li = li->next) { + QString s = (li == l) ? + tr((char*)li->data) : + QString(tr(", %1")).arg(tr((char*)li->data)); + tags.append(s); + } + g_slist_free(l); + + info_label_header_->setText(QString("%1 (%2)
%3") + .arg(longname, id, desc)); + info_label_body_->setText(doc); + info_label_footer_->setText(tr("

Tags: %1

").arg(tags)); +} + +void SubWindow::on_item_activated(const QModelIndex& index) { if (!index.isValid()) return; @@ -193,6 +291,11 @@ void SubWindow::on_item_double_clicked(const QModelIndex& index) new_decoders_selected(decoders); } +void SubWindow::on_filter_changed(const QString& text) +{ + sort_filter_model_->setFilterFixedString(text); +} + } // namespace decoder_selector } // namespace subwindows } // namespace pv