]> sigrok.org Git - pulseview.git/blobdiff - pv/views/trace/view.cpp
TraceView: Add shortcuts for attaching the cursor edges to the mouse
[pulseview.git] / pv / views / trace / view.cpp
index f2a3335e6990fe4363996606cf87e70846d0cbba..c8a7a2b88d08ce8aff081dee9c98c39238f27e53 100644 (file)
@@ -124,13 +124,14 @@ bool CustomScrollArea::viewportEvent(QEvent *event)
        }
 }
 
-View::View(Session &session, bool is_main_view, QWidget *parent) :
+View::View(Session &session, bool is_main_view, QMainWindow *parent) :
        ViewBase(session, is_main_view, parent),
 
        // Note: Place defaults in View::reset_view_state(), not here
        splitter_(new QSplitter()),
        header_was_shrunk_(false),  // The splitter remains unchanged after a reset, so this goes here
-       sticky_scrolling_(false)  // Default setting is set in MainWindow::setup_ui()
+       sticky_scrolling_(false),  // Default setting is set in MainWindow::setup_ui()
+       scroll_needs_defaults_(true)
 {
        QVBoxLayout *root_layout = new QVBoxLayout(this);
        root_layout->setContentsMargins(0, 0, 0, 0);
@@ -205,11 +206,48 @@ View::View(Session &session, bool is_main_view, QWidget *parent) :
                this, SLOT(process_sticky_events()));
        lazy_event_handler_.setSingleShot(true);
 
+       // Set up local keyboard shortcuts
+       zoom_in_shortcut_ = new QShortcut(QKeySequence(Qt::Key_Plus), this,
+                       SLOT(on_zoom_in_shortcut_triggered()), nullptr, Qt::WidgetWithChildrenShortcut);
+       zoom_in_shortcut_->setAutoRepeat(false);
+
+       zoom_out_shortcut_ = new QShortcut(QKeySequence(Qt::Key_Minus), this,
+               SLOT(on_zoom_out_shortcut_triggered()), nullptr, Qt::WidgetWithChildrenShortcut);
+       zoom_out_shortcut_->setAutoRepeat(false);
+
+       zoom_in_shortcut_2_ = new QShortcut(QKeySequence(Qt::Key_Up), this,
+               SLOT(on_zoom_in_shortcut_triggered()), nullptr, Qt::WidgetWithChildrenShortcut);
+       zoom_out_shortcut_2_ = new QShortcut(QKeySequence(Qt::Key_Down), this,
+               SLOT(on_zoom_out_shortcut_triggered()), nullptr, Qt::WidgetWithChildrenShortcut);
+
+       home_shortcut_ = new QShortcut(QKeySequence(Qt::Key_Home), this,
+               SLOT(on_scroll_to_start_shortcut_triggered()), nullptr, Qt::WidgetWithChildrenShortcut);
+       home_shortcut_->setAutoRepeat(false);
+
+       end_shortcut_ = new QShortcut(QKeySequence(Qt::Key_End), this,
+               SLOT(on_scroll_to_end_shortcut_triggered()), nullptr, Qt::WidgetWithChildrenShortcut);
+       end_shortcut_->setAutoRepeat(false);
+
+       grab_ruler_left_shortcut_ = new QShortcut(QKeySequence(Qt::Key_1), this);
+       connect(grab_ruler_left_shortcut_, &QShortcut::activated,
+               this, [=]{on_grab_ruler(1);});
+       grab_ruler_left_shortcut_->setAutoRepeat(false);
+
+       grab_ruler_right_shortcut_ = new QShortcut(QKeySequence(Qt::Key_2), this);
+       connect(grab_ruler_right_shortcut_, &QShortcut::activated,
+               this, [=]{on_grab_ruler(2);});
+       grab_ruler_right_shortcut_->setAutoRepeat(false);
+
+       cancel_grab_shortcut_ = new QShortcut(QKeySequence(Qt::Key_Escape), this);
+       connect(cancel_grab_shortcut_, &QShortcut::activated,
+               this, [=]{grabbed_widget_ = nullptr;});
+       cancel_grab_shortcut_->setAutoRepeat(false);
+
        // Trigger the initial event manually. The default device has signals
        // which were created before this object came into being
        signals_changed();
 
-       // make sure the transparent widgets are on the top
+       // Make sure the transparent widgets are on the top
        ruler_->raise();
        header_->raise();
 
@@ -221,6 +259,11 @@ View::~View()
        GlobalSettings::remove_change_handler(this);
 }
 
+ViewType View::get_type() const
+{
+       return ViewTypeTrace;
+}
+
 void View::reset_view_state()
 {
        ViewBase::reset_view_state();
@@ -242,6 +285,7 @@ void View::reset_view_state()
        next_flag_text_ = 'A';
        trigger_markers_.clear();
        hover_widget_ = nullptr;
+       grabbed_widget_ = nullptr;
        hover_point_ = QPoint(-1, -1);
        scroll_needs_defaults_ = true;
        saved_v_offset_ = 0;
@@ -275,9 +319,22 @@ unordered_set< shared_ptr<Signal> > View::signals() const
        return signals_;
 }
 
+shared_ptr<Signal> View::get_signal_by_signalbase(shared_ptr<data::SignalBase> base) const
+{
+       shared_ptr<Signal> ret_val;
+
+       for (const shared_ptr<Signal>& s : signals_)
+               if (s->base() == base) {
+                       ret_val = s;
+                       break;
+               }
+
+       return ret_val;
+}
+
 void View::clear_signals()
 {
-       ViewBase::clear_signalbases();
+       ViewBase::clear_signals();
        signals_.clear();
 }
 
@@ -296,11 +353,14 @@ void View::add_signal(const shared_ptr<Signal> signal)
 #ifdef ENABLE_DECODE
 void View::clear_decode_signals()
 {
+       ViewBase::clear_decode_signals();
        decode_traces_.clear();
 }
 
 void View::add_decode_signal(shared_ptr<data::DecodeSignal> signal)
 {
+       ViewBase::add_decode_signal(signal);
+
        shared_ptr<DecodeTrace> d(
                new DecodeTrace(session_, signal, decode_traces_.size()));
        decode_traces_.push_back(d);
@@ -320,6 +380,8 @@ void View::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
                        signals_changed();
                        return;
                }
+
+       ViewBase::remove_decode_signal(signal);
 }
 #endif
 
@@ -348,6 +410,11 @@ const Viewport* View::viewport() const
        return viewport_;
 }
 
+QAbstractScrollArea* View::scrollarea() const
+{
+       return scrollarea_;
+}
+
 const Ruler* View::ruler() const
 {
        return ruler_;
@@ -775,26 +842,6 @@ pair<Timestamp, Timestamp> View::get_time_extents() const
        return make_pair(*left_time, *right_time);
 }
 
-void View::enable_show_sampling_points(bool state)
-{
-       (void)state;
-
-       viewport_->update();
-}
-
-void View::enable_show_analog_minor_grid(bool state)
-{
-       (void)state;
-
-       viewport_->update();
-}
-
-void View::enable_colored_bg(bool state)
-{
-       colored_bg_ = state;
-       viewport_->update();
-}
-
 bool View::colored_bg() const
 {
        return colored_bg_;
@@ -1014,13 +1061,22 @@ int View::header_width() const
 
 void View::on_setting_changed(const QString &key, const QVariant &value)
 {
+       GlobalSettings settings;
+
+       if (key == GlobalSettings::Key_View_ColoredBG) {
+               colored_bg_ = settings.value(GlobalSettings::Key_View_ColoredBG).toBool();
+               viewport_->update();
+       }
+
+       if ((key == GlobalSettings::Key_View_ShowSamplingPoints) ||
+          (key == GlobalSettings::Key_View_ShowAnalogMinorGrid))
+               viewport_->update();
+
        if (key == GlobalSettings::Key_View_TriggerIsZeroTime)
                on_settingViewTriggerIsZeroTime_changed(value);
 
-       if (key == GlobalSettings::Key_View_SnapDistance) {
-               GlobalSettings settings;
+       if (key == GlobalSettings::Key_View_SnapDistance)
                snap_distance_ = settings.value(GlobalSettings::Key_View_SnapDistance).toInt();
-       }
 }
 
 void View::trigger_event(int segment_id, util::Timestamp location)
@@ -1347,6 +1403,7 @@ void View::determine_time_unit()
 bool View::eventFilter(QObject *object, QEvent *event)
 {
        const QEvent::Type type = event->type();
+
        if (type == QEvent::MouseMove) {
 
                if (object)
@@ -1364,6 +1421,28 @@ bool View::eventFilter(QObject *object, QEvent *event)
 
                update_hover_point();
 
+               if (grabbed_widget_) {
+                       int64_t nearest = get_nearest_level_change(hover_point_);
+                       pv::util::Timestamp mouse_time = offset_ + hover_point_.x() * scale_;
+
+                       if (nearest == -1) {
+                               grabbed_widget_->set_time(mouse_time);
+                       } else {
+                               grabbed_widget_->set_time(nearest / get_signal_under_mouse_cursor()->base()->get_samplerate());
+                       }
+               }
+
+       } else if (type == QEvent::MouseButtonPress) {
+               grabbed_widget_ = nullptr;
+
+               const QMouseEvent *const mouse_event = (QMouseEvent*)event;
+               if ((object == viewport_) && (mouse_event->button() & Qt::LeftButton)) {
+                       // Send event to all trace tree items
+                       const vector<shared_ptr<TraceTreeItem>> trace_tree_items(
+                               list_by_type<TraceTreeItem>());
+                       for (const shared_ptr<TraceTreeItem>& r : trace_tree_items)
+                               r->mouse_left_press_event(mouse_event);
+               }
        } else if (type == QEvent::Leave) {
                hover_point_ = QPoint(-1, -1);
                update_hover_point();
@@ -1490,6 +1569,26 @@ void View::on_splitter_moved()
                resize_header_to_fit();
 }
 
+void View::on_zoom_in_shortcut_triggered()
+{
+       zoom(1);
+}
+
+void View::on_zoom_out_shortcut_triggered()
+{
+       zoom(-1);
+}
+
+void View::on_scroll_to_start_shortcut_triggered()
+{
+       set_h_offset(0);
+}
+
+void View::on_scroll_to_end_shortcut_triggered()
+{
+       set_h_offset(get_h_scrollbar_maximum());
+}
+
 void View::h_scroll_value_changed(int value)
 {
        if (updating_scroll_)
@@ -1522,6 +1621,22 @@ void View::v_scroll_value_changed()
        viewport_->update();
 }
 
+void View::on_grab_ruler(int ruler_id)
+{
+       if (cursors_shown()) {
+               // Release the grabbed widget if its trigger hotkey was pressed twice
+               if (ruler_id == 1)
+                       grabbed_widget_ = (grabbed_widget_ == cursors_->first().get()) ?
+                               nullptr : cursors_->first().get();
+               else
+                       grabbed_widget_ = (grabbed_widget_ == cursors_->second().get()) ?
+                               nullptr : cursors_->second().get();
+
+               if (grabbed_widget_)
+                       grabbed_widget_->set_time(offset_ + mapFromGlobal(QCursor::pos()).x() * scale_);
+       }
+}
+
 void View::signals_changed()
 {
        using sigrok::Channel;