From: Soeren Apel Date: Thu, 23 Jul 2015 21:30:44 +0000 (+0200) Subject: Fix #121 by implementing sticky scrolling X-Git-Tag: pulseview-0.3.0~167 X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=commitdiff_plain;h=c7b03d9daa9574bd633fbac2d5976716f58027f5 Fix #121 by implementing sticky scrolling --- diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index 3a775edd..6d28194b 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -106,6 +106,7 @@ MainWindow::MainWindow(DeviceManager &device_manager, action_view_zoom_out_(new QAction(this)), action_view_zoom_fit_(new QAction(this)), action_view_zoom_one_to_one_(new QAction(this)), + action_view_sticky_scrolling_(new QAction(this)), action_view_show_cursors_(new QAction(this)), action_about_(new QAction(this)) #ifdef ENABLE_DECODE @@ -160,6 +161,11 @@ QAction* MainWindow::action_view_zoom_one_to_one() const return action_view_zoom_one_to_one_; } +QAction* MainWindow::action_view_sticky_scrolling() const +{ + return action_view_sticky_scrolling_; +} + QAction* MainWindow::action_view_show_cursors() const { return action_view_show_cursors_; @@ -411,6 +417,18 @@ void MainWindow::setup_ui() QString::fromUtf8("actionViewZoomOneToOne")); menu_view->addAction(action_view_zoom_one_to_one_); + menu_file->addSeparator(); + + action_view_sticky_scrolling_->setCheckable(true); + action_view_sticky_scrolling_->setChecked(true); + action_view_sticky_scrolling_->setShortcut(QKeySequence(Qt::Key_R)); + action_view_sticky_scrolling_->setObjectName( + QString::fromUtf8("actionViewStickyScrolling")); + action_view_sticky_scrolling_->setText(tr("Sticky Sc&rolling")); + menu_view->addAction(action_view_sticky_scrolling_); + + view_->enable_sticky_scrolling(action_view_sticky_scrolling_->isChecked()); + menu_view->addSeparator(); action_view_show_cursors_->setCheckable(true); @@ -473,6 +491,11 @@ void MainWindow::setup_ui() SLOT(capture_state_changed(int))); connect(&session_, SIGNAL(device_selected()), this, SLOT(device_selected())); + + // Setup view_ events + connect(view_, SIGNAL(sticky_scrolling_changed(bool)), this, + SLOT(sticky_scrolling_changed(bool))); + } void MainWindow::select_init_device() { @@ -715,6 +738,11 @@ void MainWindow::on_actionViewZoomOneToOne_triggered() view_->zoom_one_to_one(); } +void MainWindow::on_actionViewStickyScrolling_triggered() +{ + view_->enable_sticky_scrolling(action_view_sticky_scrolling_->isChecked()); +} + void MainWindow::on_actionViewShowCursors_triggered() { assert(view_); @@ -732,6 +760,11 @@ void MainWindow::on_actionAbout_triggered() dlg.exec(); } +void MainWindow::sticky_scrolling_changed(bool state) +{ + action_view_sticky_scrolling_->setChecked(state); +} + void MainWindow::add_decoder(srd_decoder *decoder) { #ifdef ENABLE_DECODE diff --git a/pv/mainwindow.hpp b/pv/mainwindow.hpp index 6a4bdfc8..ad7e6b2b 100644 --- a/pv/mainwindow.hpp +++ b/pv/mainwindow.hpp @@ -90,6 +90,7 @@ public: QAction* action_view_zoom_out() const; QAction* action_view_zoom_fit() const; QAction* action_view_zoom_one_to_one() const; + QAction* action_view_sticky_scrolling() const; QAction* action_view_show_cursors() const; QAction* action_about() const; @@ -152,6 +153,8 @@ private Q_SLOTS: void on_actionViewZoomOneToOne_triggered(); + void on_actionViewStickyScrolling_triggered(); + void on_actionViewShowCursors_triggered(); void on_actionAbout_triggered(); @@ -161,6 +164,8 @@ private Q_SLOTS: void capture_state_changed(int state); void device_selected(); + void sticky_scrolling_changed(bool state); + private: DeviceManager &device_manager_; @@ -181,6 +186,7 @@ private: QAction *const action_view_zoom_out_; QAction *const action_view_zoom_fit_; QAction *const action_view_zoom_one_to_one_; + QAction *const action_view_sticky_scrolling_; QAction *const action_view_show_cursors_; QAction *const action_about_; diff --git a/pv/toolbars/mainbar.cpp b/pv/toolbars/mainbar.cpp index b404b3da..a1761291 100644 --- a/pv/toolbars/mainbar.cpp +++ b/pv/toolbars/mainbar.cpp @@ -135,13 +135,19 @@ MainBar::MainBar(Session &session, MainWindow &main_window) : add_decoder_button->setMenu(main_window_.menu_decoder_add()); #endif - // Setup the menu + // Setup the burger menu QMenu *const menu = new QMenu(this); + QMenu *const menu_view = new QMenu; + menu_view->setTitle(tr("&View")); + menu_view->addAction(main_window.action_view_sticky_scrolling()); + QMenu *const menu_help = new QMenu; menu_help->setTitle(tr("&Help")); menu_help->addAction(main_window.action_about()); + menu->addAction(menu_view->menuAction()); + menu->addSeparator(); menu->addAction(menu_help->menuAction()); menu->addSeparator(); menu->addAction(main_window.action_quit()); diff --git a/pv/view/view.cpp b/pv/view/view.cpp index 2ae0a714..130d2d78 100644 --- a/pv/view/view.cpp +++ b/pv/view/view.cpp @@ -86,6 +86,7 @@ const double View::MaxScale = 1e9; const double View::MinScale = 1e-15; const int View::MaxScrollValue = INT_MAX / 2; +const int View::MaxViewAutoUpdateRate = 25; // No more than 25 Hz const int View::ScaleUnits[3] = {1, 2, 5}; @@ -98,6 +99,7 @@ View::View(Session &session, QWidget *parent) : scale_(1e-3), offset_(0), updating_scroll_(false), + sticky_scrolling_(false), // Default setting is set in MainWindow::setup_ui() tick_period_(0.0), tick_prefix_(0), show_cursors_(false), @@ -136,6 +138,11 @@ View::View(Session &session, QWidget *parent) : this, SLOT(process_sticky_events())); lazy_event_handler_.setSingleShot(true); + connect(&delayed_view_updater_, SIGNAL(timeout()), + this, SLOT(perform_delayed_view_update())); + delayed_view_updater_.setSingleShot(true); + delayed_view_updater_.setInterval(1000 / MaxViewAutoUpdateRate); + setViewport(viewport_); viewport_->installEventFilter(this); @@ -288,6 +295,13 @@ void View::zoom_one_to_one() void View::set_scale_offset(double scale, double offset) { + // Disable sticky scrolling when acquisition runs and user drags the viewport + if ((scale_ == scale) && (offset_ != offset) && + sticky_scrolling_ && (session_.get_capture_state() == Session::Running)) { + sticky_scrolling_ = false; + sticky_scrolling_changed(false); + } + scale_ = scale; offset_ = offset; @@ -339,6 +353,11 @@ pair View::get_time_extents() const return make_pair(left_time, right_time); } +void View::enable_sticky_scrolling(bool state) +{ + sticky_scrolling_ = state; +} + bool View::cursors_shown() const { return show_cursors_; @@ -674,6 +693,13 @@ void View::h_scroll_value_changed(int value) if (updating_scroll_) return; + // Disable sticky scrolling when user moves the horizontal scroll bar + // during a running acquisition + if (sticky_scrolling_ && (session_.get_capture_state() == Session::Running)) { + sticky_scrolling_ = false; + sticky_scrolling_changed(false); + } + const int range = horizontalScrollBar()->maximum(); if (range < MaxScrollValue) offset_ = scale_ * value; @@ -821,10 +847,31 @@ void View::signals_changed() void View::data_updated() { - // Update the scroll bars - update_scroll(); + if (sticky_scrolling_) { + if (!delayed_view_updater_.isActive()) + delayed_view_updater_.start(); + } else { + update_scroll(); + ruler_->update(); + viewport_->update(); + } +} + +void View::perform_delayed_view_update() +{ + if (sticky_scrolling_) { + // Make right side of the view sticky + double length = 0, offset; + get_scroll_layout(length, offset); + + const QSize areaSize = viewport_->size(); + length = max(length - areaSize.width(), 0.0); + + offset_ = scale_ * length; + } - // Repaint the view + update_scroll(); + ruler_->update(); viewport_->update(); } diff --git a/pv/view/view.hpp b/pv/view/view.hpp index 3e0a3471..b29fb157 100644 --- a/pv/view/view.hpp +++ b/pv/view/view.hpp @@ -69,6 +69,7 @@ private: static const double MinScale; static const int MaxScrollValue; + static const int MaxViewAutoUpdateRate; static const int ScaleUnits[3]; @@ -152,6 +153,12 @@ public: std::pair get_time_extents() const; + /** + * Enables or disables sticky scrolling, i.e. the view always shows + * the most recent samples when capturing data. + */ + void enable_sticky_scrolling(bool state); + /** * Returns true if cursors are displayed. false otherwise. */ @@ -200,6 +207,8 @@ Q_SIGNALS: void scale_offset_changed(); + void sticky_scrolling_changed(bool state); + private: void get_scroll_layout(double &length, double &offset) const; @@ -269,6 +278,8 @@ private Q_SLOTS: void signals_changed(); void data_updated(); + void perform_delayed_view_update(); + void process_sticky_events(); void on_hover_point_changed(); @@ -287,6 +298,8 @@ private: double offset_; bool updating_scroll_; + bool sticky_scrolling_; + QTimer delayed_view_updater_; double tick_period_; unsigned int tick_prefix_;