From: Soeren Apel Date: Thu, 23 Apr 2020 18:20:45 +0000 (+0200) Subject: TabularDecView: Column header context menu and focus-on-double-click X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=9a35b05d2f2e5329f1ecaddb04289d4adeea2752;p=pulseview.git TabularDecView: Column header context menu and focus-on-double-click --- diff --git a/pv/views/tabular_decoder/model.cpp b/pv/views/tabular_decoder/model.cpp index b502395c..bd9e174c 100644 --- a/pv/views/tabular_decoder/model.cpp +++ b/pv/views/tabular_decoder/model.cpp @@ -90,9 +90,9 @@ QVariant AnnotationCollectionModel::data(const QModelIndex& index, int role) con Qt::ItemFlags AnnotationCollectionModel::flags(const QModelIndex& index) const { if (!index.isValid()) - return 0; + return Qt::NoItemFlags; - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren; } QVariant AnnotationCollectionModel::headerData(int section, Qt::Orientation orientation, diff --git a/pv/views/tabular_decoder/view.cpp b/pv/views/tabular_decoder/view.cpp index 1f79be03..99da2c35 100644 --- a/pv/views/tabular_decoder/view.cpp +++ b/pv/views/tabular_decoder/view.cpp @@ -35,6 +35,7 @@ #include "view.hpp" #include "pv/globalsettings.hpp" +#include "pv/session.hpp" #include "pv/util.hpp" #include "pv/data/decode/decoder.hpp" @@ -122,6 +123,8 @@ View::View(Session &session, bool is_main_view, QMainWindow *parent) : // Set up the table view table_view_->setModel(model_); + table_view_->setSelectionBehavior(QAbstractItemView::SelectRows); + table_view_->setSelectionMode(QAbstractItemView::SingleSelection); table_view_->setSortingEnabled(true); table_view_->sortByColumn(0, Qt::AscendingOrder); @@ -131,10 +134,18 @@ View::View(Session &session, bool is_main_view, QMainWindow *parent) : table_view_->horizontalHeader()->setStretchLastSection(true); table_view_->horizontalHeader()->setCascadingSectionResizes(true); table_view_->horizontalHeader()->setSectionsMovable(true); + table_view_->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); table_view_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); parent->setSizePolicy(table_view_->sizePolicy()); + connect(table_view_, SIGNAL(clicked(const QModelIndex&)), + this, SLOT(on_table_item_clicked(const QModelIndex&))); + connect(table_view_, SIGNAL(doubleClicked(const QModelIndex&)), + this, SLOT(on_table_item_double_clicked(const QModelIndex&))); + connect(table_view_->horizontalHeader(), SIGNAL(customContextMenuRequested(const QPoint&)), + this, SLOT(on_table_header_requested(const QPoint&))); + reset_view_state(); } @@ -387,6 +398,55 @@ void View::on_actionSave_triggered(QAction* action) save_data(); } +void View::on_table_item_clicked(const QModelIndex& index) +{ + (void)index; + + // Force repaint, otherwise the new selection isn't shown for some reason + table_view_->viewport()->update(); +} + +void View::on_table_item_double_clicked(const QModelIndex& index) +{ + const Annotation* ann = static_cast(index.internalPointer()); + + shared_ptr main_view = session_.main_view(); + + main_view->focus_on_range(ann->start_sample(), ann->end_sample()); +} + +void View::on_table_header_requested(const QPoint& pos) +{ + QMenu* menu = new QMenu(this); + + for (int i = 0; i < table_view_->horizontalHeader()->count(); i++) { + int column = table_view_->horizontalHeader()->logicalIndex(i); + + const QString title = model_->headerData(column, Qt::Horizontal, Qt::DisplayRole).toString(); + QAction* action = new QAction(title, this); + + action->setCheckable(true); + action->setChecked(!table_view_->horizontalHeader()->isSectionHidden(column)); + action->setData(column); + + connect(action, SIGNAL(toggled(bool)), this, SLOT(on_table_header_toggled(bool))); + + menu->addAction(action); + } + + menu->popup(table_view_->horizontalHeader()->viewport()->mapToGlobal(pos)); +} + +void View::on_table_header_toggled(bool checked) +{ + QAction* action = qobject_cast(QObject::sender()); + assert(action); + + const int column = action->data().toInt(); + + table_view_->horizontalHeader()->setSectionHidden(column, !checked); +} + void View::perform_delayed_view_update() { update_data(); diff --git a/pv/views/tabular_decoder/view.hpp b/pv/views/tabular_decoder/view.hpp index 461cc7cd..a7215f7b 100644 --- a/pv/views/tabular_decoder/view.hpp +++ b/pv/views/tabular_decoder/view.hpp @@ -120,6 +120,11 @@ private Q_SLOTS: void on_actionSave_triggered(QAction* action = nullptr); + void on_table_item_clicked(const QModelIndex& index); + void on_table_item_double_clicked(const QModelIndex& index); + void on_table_header_requested(const QPoint& pos); + void on_table_header_toggled(bool checked); + virtual void perform_delayed_view_update(); private: diff --git a/pv/views/trace/view.cpp b/pv/views/trace/view.cpp index 227fadfd..33122047 100644 --- a/pv/views/trace/view.cpp +++ b/pv/views/trace/view.cpp @@ -783,6 +783,26 @@ void View::zoom_fit(bool gui_state) set_scale_offset(scale.convert_to(), extents.first); } +void View::focus_on_range(uint64_t start_sample, uint64_t end_sample) +{ + assert(viewport_); + const int w = viewport_->width(); + if (w <= 0) + return; + + const double samplerate = session_.get_samplerate(); + + const uint64_t sample_delta = (end_sample - start_sample); + + // Note: We add 20% margin on the left and 5% on the right + const Timestamp delta = (sample_delta * 1.25) / samplerate; + + const Timestamp scale = max(min(delta / w, MaxScale), MinScale); + const Timestamp offset = (start_sample - sample_delta * 0.20) / samplerate; + + set_scale_offset(scale.convert_to(), offset); +} + void View::set_scale_offset(double scale, const Timestamp& offset) { // Disable sticky scrolling / always zoom to fit when acquisition runs diff --git a/pv/views/trace/view.hpp b/pv/views/trace/view.hpp index d57acd91..5863bc9d 100644 --- a/pv/views/trace/view.hpp +++ b/pv/views/trace/view.hpp @@ -154,7 +154,6 @@ public: const Ruler* ruler() const; virtual void save_settings(QSettings &settings) const; - virtual void restore_settings(QSettings &settings); /** @@ -254,6 +253,8 @@ public: void zoom_fit(bool gui_state); + virtual void focus_on_range(uint64_t start_sample, uint64_t end_sample); + /** * Sets the scale and offset. * @param scale The new view scale in seconds per pixel. diff --git a/pv/views/viewbase.cpp b/pv/views/viewbase.cpp index 9e5a2887..7be88222 100644 --- a/pv/views/viewbase.cpp +++ b/pv/views/viewbase.cpp @@ -146,6 +146,12 @@ void ViewBase::restore_settings(QSettings &settings) (void)settings; } +void ViewBase::focus_on_range(uint64_t start_sample, uint64_t end_sample) +{ + (void)start_sample; + (void)end_sample; +} + void ViewBase::trigger_event(int segment_id, util::Timestamp location) { (void)segment_id; diff --git a/pv/views/viewbase.hpp b/pv/views/viewbase.hpp index e3a3c6a4..73d7a179 100644 --- a/pv/views/viewbase.hpp +++ b/pv/views/viewbase.hpp @@ -105,9 +105,10 @@ public: #endif virtual void save_settings(QSettings &settings) const; - virtual void restore_settings(QSettings &settings); + virtual void focus_on_range(uint64_t start_sample, uint64_t end_sample); + public Q_SLOTS: virtual void trigger_event(int segment_id, util::Timestamp location); virtual void signals_changed();