From 86d4b8e3e52a422fe3a6956d6bbef27f1859717b Mon Sep 17 00:00:00 2001 From: Soeren Apel Date: Sun, 26 Apr 2020 00:41:43 +0200 Subject: [PATCH] TabularDecView: Implement "hide hidden rows/classes" checkbox Also adds the non-functional view mode selector. --- pv/data/decode/annotation.cpp | 7 ++++ pv/data/decode/annotation.hpp | 2 + pv/data/decode/row.cpp | 5 +++ pv/data/decode/row.hpp | 1 + pv/views/tabular_decoder/model.cpp | 67 ++++++++++++++++++++++++++---- pv/views/tabular_decoder/view.cpp | 46 +++++++++++++++++++- pv/views/tabular_decoder/view.hpp | 21 ++++++++++ 7 files changed, 138 insertions(+), 11 deletions(-) diff --git a/pv/data/decode/annotation.cpp b/pv/data/decode/annotation.cpp index 27a44fe4..1a331b3e 100644 --- a/pv/data/decode/annotation.cpp +++ b/pv/data/decode/annotation.cpp @@ -122,6 +122,13 @@ const QString Annotation::longest_annotation() const return texts_->front(); } +bool Annotation::visible() const +{ + const Row* row = data_->row(); + + return (row->visible() && row->class_is_visible(ann_class_id_)); +} + const QColor Annotation::color() const { return data_->row()->get_class_color(ann_class_id_); diff --git a/pv/data/decode/annotation.hpp b/pv/data/decode/annotation.hpp index 57ca4695..edc27bee 100644 --- a/pv/data/decode/annotation.hpp +++ b/pv/data/decode/annotation.hpp @@ -62,6 +62,8 @@ public: const vector* annotations() const; const QString longest_annotation() const; + bool visible() const; + const QColor color() const; const QColor bright_color() const; const QColor dark_color() const; diff --git a/pv/data/decode/row.cpp b/pv/data/decode/row.cpp index 70c430ac..4f0e245f 100644 --- a/pv/data/decode/row.cpp +++ b/pv/data/decode/row.cpp @@ -169,6 +169,11 @@ bool Row::has_hidden_classes() const return false; } +bool Row::class_is_visible(uint32_t ann_class_id) const +{ + return decoder_->get_ann_class_by_id(ann_class_id)->visible; +} + bool Row::operator<(const Row& other) const { return (decoder_ < other.decoder_) || diff --git a/pv/data/decode/row.hpp b/pv/data/decode/row.hpp index 000bdf9e..71945f2e 100644 --- a/pv/data/decode/row.hpp +++ b/pv/data/decode/row.hpp @@ -66,6 +66,7 @@ public: const QColor get_dark_class_color(uint32_t ann_class_id) const; bool has_hidden_classes() const; + bool class_is_visible(uint32_t ann_class_id) const; bool operator<(const Row& other) const; bool operator==(const Row& other) const; diff --git a/pv/views/tabular_decoder/model.cpp b/pv/views/tabular_decoder/model.cpp index ffd151a5..1d4d839e 100644 --- a/pv/views/tabular_decoder/model.cpp +++ b/pv/views/tabular_decoder/model.cpp @@ -40,9 +40,11 @@ namespace tabular_decoder { AnnotationCollectionModel::AnnotationCollectionModel(QObject* parent) : QAbstractTableModel(parent), all_annotations_(nullptr), + dataset_(nullptr), signal_(nullptr), prev_segment_(0), - prev_last_row_(0) + prev_last_row_(0), + hide_hidden_(false) { GlobalSettings::add_change_handler(this); theme_is_dark_ = GlobalSettings::current_theme_is_dark(); @@ -131,13 +133,15 @@ QModelIndex AnnotationCollectionModel::index(int row, int column, assert(row >= 0); assert(column >= 0); - if (!all_annotations_) + if (!dataset_) return QModelIndex(); - if ((size_t)row > all_annotations_->size()) - return QModelIndex(); + QModelIndex idx; + + if ((size_t)row < dataset_->size()) + idx = createIndex(row, column, (void*)dataset_->at(row)); - return createIndex(row, column, (void*)(all_annotations_->at(row))); + return idx; } QModelIndex AnnotationCollectionModel::parent(const QModelIndex& index) const @@ -151,10 +155,10 @@ int AnnotationCollectionModel::rowCount(const QModelIndex& parent_idx) const { (void)parent_idx; - if (!all_annotations_) + if (!dataset_) return 0; - return all_annotations_->size(); + return dataset_->size(); } int AnnotationCollectionModel::columnCount(const QModelIndex& parent_idx) const @@ -168,7 +172,9 @@ void AnnotationCollectionModel::set_signal_and_segment(data::DecodeSignal* signa { if (!signal) { all_annotations_ = nullptr; + dataset_ = nullptr; signal_ = nullptr; + dataChanged(QModelIndex(), QModelIndex()); layoutChanged(); return; @@ -177,12 +183,17 @@ void AnnotationCollectionModel::set_signal_and_segment(data::DecodeSignal* signa all_annotations_ = signal->get_all_annotations_by_segment(current_segment); signal_ = signal; - if (!all_annotations_ || all_annotations_->empty()) { + if (hide_hidden_) + update_annotations_without_hidden(); + else + dataset_ = all_annotations_; + + if (!dataset_ || dataset_->empty()) { prev_segment_ = current_segment; return; } - const size_t new_row_count = all_annotations_->size() - 1; + const size_t new_row_count = dataset_->size() - 1; // Force the view associated with this model to update when the segment changes if (prev_segment_ != current_segment) { @@ -201,6 +212,44 @@ void AnnotationCollectionModel::set_signal_and_segment(data::DecodeSignal* signa prev_last_row_ = new_row_count; } +void AnnotationCollectionModel::set_hide_hidden(bool hide_hidden) +{ + hide_hidden_ = hide_hidden; + + if (hide_hidden_) { + dataset_ = &all_annotations_without_hidden_; + update_annotations_without_hidden(); + } else { + dataset_ = all_annotations_; + all_annotations_without_hidden_.clear(); // To conserve memory + } +} + +void AnnotationCollectionModel::update_annotations_without_hidden() +{ + uint64_t count = 0; + + if (!all_annotations_ || all_annotations_->empty()) { + all_annotations_without_hidden_.clear(); + return; + } + + for (const Annotation* ann : *all_annotations_) { + if (!ann->visible()) + continue; + + if (all_annotations_without_hidden_.size() < (count + 100)) + all_annotations_without_hidden_.resize(count + 100); + + all_annotations_without_hidden_[count++] = ann; + } + + all_annotations_without_hidden_.resize(count); + + dataChanged(index(0, 0, QModelIndex()), index(count, 0, QModelIndex())); + layoutChanged(); +} + void AnnotationCollectionModel::on_setting_changed(const QString &key, const QVariant &value) { (void)key; diff --git a/pv/views/tabular_decoder/view.cpp b/pv/views/tabular_decoder/view.cpp index e41734a1..0a425e66 100644 --- a/pv/views/tabular_decoder/view.cpp +++ b/pv/views/tabular_decoder/view.cpp @@ -56,6 +56,12 @@ const char* SaveTypeNames[SaveTypeCount] = { "CSV, fields quoted" }; +const char* ViewModeNames[ViewModeCount] = { + "Show all", + "Show all and focus on newest", + "Show visible in main view" +}; + QSize QCustomTableView::minimumSizeHint() const { QSize size(QTableView::sizeHint()); @@ -82,6 +88,8 @@ View::View(Session &session, bool is_main_view, QMainWindow *parent) : // Note: Place defaults in View::reset_view_state(), not here parent_(parent), decoder_selector_(new QComboBox()), + hide_hidden_cb_(new QCheckBox()), + view_mode_selector_(new QComboBox()), save_button_(new QToolButton()), save_action_(new QAction(this)), table_view_(new QCustomTableView()), @@ -102,13 +110,27 @@ View::View(Session &session, bool is_main_view, QMainWindow *parent) : toolbar->addWidget(decoder_selector_); toolbar->addSeparator(); toolbar->addWidget(save_button_); + toolbar->addSeparator(); + toolbar->addWidget(view_mode_selector_); + toolbar->addSeparator(); + toolbar->addWidget(hide_hidden_cb_); connect(decoder_selector_, SIGNAL(currentIndexChanged(int)), this, SLOT(on_selected_decoder_changed(int))); + connect(view_mode_selector_, SIGNAL(currentIndexChanged(int)), + this, SLOT(on_view_mode_changed(int))); + connect(hide_hidden_cb_, SIGNAL(toggled(bool)), + this, SLOT(on_hide_hidden_changed(bool))); // Configure widgets decoder_selector_->setSizeAdjustPolicy(QComboBox::AdjustToContents); + for (int i = 0; i < ViewModeCount; i++) + view_mode_selector_->addItem(ViewModeNames[i], QVariant::fromValue(i)); + + hide_hidden_cb_->setText(tr("Hide Hidden Rows/Classes")); + hide_hidden_cb_->setChecked(true); + // Configure actions save_action_->setText(tr("&Save...")); save_action_->setIcon(QIcon::fromTheme("document-save-as", @@ -224,13 +246,20 @@ void View::remove_decode_signal(shared_ptr signal) void View::save_settings(QSettings &settings) const { ViewBase::save_settings(settings); + + settings.setValue("view_mode", view_mode_selector_->currentIndex()); + settings.setValue("hide_hidden", hide_hidden_cb_->isChecked()); } void View::restore_settings(QSettings &settings) { - // Note: It is assumed that this function is only called once, - // immediately after restoring a previous session. ViewBase::restore_settings(settings); + + if (settings.contains("view_mode")) + view_mode_selector_->setCurrentIndex(settings.value("view_mode").toInt()); + + if (settings.contains("hide_hidden")) + hide_hidden_cb_->setChecked(settings.value("hide_hidden").toBool()); } void View::reset_data() @@ -361,6 +390,19 @@ void View::on_selected_decoder_changed(int index) update_data(); } +void View::on_hide_hidden_changed(bool checked) +{ + model_->set_hide_hidden(checked); + + // Force repaint, otherwise the new selection isn't shown for some reason + table_view_->viewport()->update(); +} + +void View::on_view_mode_changed(int index) +{ + (void)index; +} + void View::on_signal_name_changed(const QString &name) { (void)name; diff --git a/pv/views/tabular_decoder/view.hpp b/pv/views/tabular_decoder/view.hpp index 9c251382..999501a2 100644 --- a/pv/views/tabular_decoder/view.hpp +++ b/pv/views/tabular_decoder/view.hpp @@ -21,6 +21,7 @@ #define PULSEVIEW_PV_VIEWS_TABULARDECODER_VIEW_HPP #include +#include #include #include #include @@ -43,7 +44,16 @@ enum SaveType { SaveTypeCount // Indicates how many save types there are, must always be last }; +// When adding an entry here, don't forget to update ViewModeNames as well +enum ViewModeType { + ViewModeAll, + ViewModeLatest, + ViewModeVisible, + ViewModeCount // Indicates how many save types there are, must always be last +}; + extern const char* SaveTypeNames[SaveTypeCount]; +extern const char* ViewModeNames[ViewModeCount]; class AnnotationCollectionModel : public QAbstractTableModel, public GlobalSettingsInterface @@ -68,15 +78,21 @@ public: int columnCount(const QModelIndex& parent_idx = QModelIndex()) const override; void set_signal_and_segment(data::DecodeSignal* signal, uint32_t current_segment); + void set_hide_hidden(bool hide_hidden); + + void update_annotations_without_hidden(); void on_setting_changed(const QString &key, const QVariant &value) override; private: vector header_data_; const deque* all_annotations_; + deque all_annotations_without_hidden_; + const deque* dataset_; data::DecodeSignal* signal_; uint32_t prev_segment_; uint64_t prev_last_row_; + bool hide_hidden_; bool theme_is_dark_; }; @@ -121,6 +137,9 @@ private: private Q_SLOTS: void on_selected_decoder_changed(int index); + void on_hide_hidden_changed(bool checked); + void on_view_mode_changed(int index); + void on_signal_name_changed(const QString &name); void on_signal_color_changed(const QColor &color); void on_new_annotations(); @@ -142,6 +161,8 @@ private: QWidget* parent_; QComboBox* decoder_selector_; + QCheckBox* hide_hidden_cb_; + QComboBox* view_mode_selector_; QToolButton* save_button_; QAction* save_action_; -- 2.30.2