TabularDecView: Implement "hide hidden rows/classes" checkbox
authorSoeren Apel <soeren@apelpie.net>
Sat, 25 Apr 2020 22:41:43 +0000 (00:41 +0200)
committerUwe Hermann <uwe@hermann-uwe.de>
Sun, 3 May 2020 15:20:55 +0000 (17:20 +0200)
Also adds the non-functional view mode selector.

pv/data/decode/annotation.cpp
pv/data/decode/annotation.hpp
pv/data/decode/row.cpp
pv/data/decode/row.hpp
pv/views/tabular_decoder/model.cpp
pv/views/tabular_decoder/view.cpp
pv/views/tabular_decoder/view.hpp

index 27a44fe4808208b09240d575910ff4f72b68cc42..1a331b3e143aeb46e0969b5936dac60e7fa314aa 100644 (file)
@@ -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_);
index 57ca46950384d16632cab87b0596b0fba9baab43..edc27bee4dfa52947477980622e137863aaa14f2 100644 (file)
@@ -62,6 +62,8 @@ public:
        const vector<QString>* annotations() const;
        const QString longest_annotation() const;
 
+       bool visible() const;
+
        const QColor color() const;
        const QColor bright_color() const;
        const QColor dark_color() const;
index 70c430ac9d7395722192fe3b5a29e16a4036174d..4f0e245fc65c359528a7cf3e5a5d8c3760671740 100644 (file)
@@ -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_) ||
index 000bdf9e6b935c8ee838367c7a5c8460badfcca9..71945f2e0cf0899ffc911001ef5beff0e4f17bb4 100644 (file)
@@ -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;
index ffd151a5300c4278a297a45fe040b84f22e4e246..1d4d839e4757be2ad20169c09b621f04044013b1 100644 (file)
@@ -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;
index e41734a101e62e580e3e3e61aed7e39e11feb820..0a425e66188119de060ed662914f9a9da6fdb81f 100644 (file)
@@ -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<data::DecodeSignal> 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;
index 9c251382c675bbb2e2cb074dbde47016eb02afc7..999501a2541b90626f0758e37e17a9cec40ad72d 100644 (file)
@@ -21,6 +21,7 @@
 #define PULSEVIEW_PV_VIEWS_TABULARDECODER_VIEW_HPP
 
 #include <QAction>
+#include <QCheckBox>
 #include <QComboBox>
 #include <QTableView>
 #include <QToolButton>
@@ -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<QVariant> header_data_;
        const deque<const Annotation*>* all_annotations_;
+       deque<const Annotation*> all_annotations_without_hidden_;
+       const deque<const Annotation*>* 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_;