diff --git a/icons/navigation.svg b/icons/navigation.svg new file mode 100644 index 00000000..cbafe7b3 --- /dev/null +++ b/icons/navigation.svg @@ -0,0 +1,535 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pulseview.qrc b/pulseview.qrc index ceda06df..069dd8eb 100644 --- a/pulseview.qrc +++ b/pulseview.qrc @@ -16,6 +16,7 @@ icons/media-playback-pause.png icons/media-playback-start.png icons/menu.svg + icons/navigation.svg icons/preferences-system.png icons/settings-general.png icons/settings-views.svg diff --git a/pv/dialogs/settings.cpp b/pv/dialogs/settings.cpp index efe854af..50eedece 100644 --- a/pv/dialogs/settings.cpp +++ b/pv/dialogs/settings.cpp @@ -144,6 +144,15 @@ void Settings::create_pages() viewButton->setTextAlignment(Qt::AlignVCenter); viewButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + // Navigation page + pages->addWidget(get_navigation_settings_form(pages)); + + QListWidgetItem *navButton = new QListWidgetItem(page_list); + navButton->setIcon(QIcon(":/icons/navigation.svg")); + navButton->setText(tr("Navigation")); + navButton->setTextAlignment(Qt::AlignVCenter); + navButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + #ifdef ENABLE_DECODE // Decoder page pages->addWidget(get_decoder_settings_form(pages)); @@ -384,6 +393,54 @@ QWidget *Settings::get_view_settings_form(QWidget *parent) const return form; } +QWidget *Settings::get_navigation_settings_form(QWidget *parent) +{ + GlobalSettings settings; + + QWidget *form = new QWidget(parent); + QVBoxLayout *form_layout = new QVBoxLayout(form); + + // Navigation control settings + QGroupBox *nav_group = new QGroupBox(tr("Trace Navigation Controls")); + form_layout->addWidget(nav_group); + + QGridLayout *nav_layout = new QGridLayout(); + nav_group->setLayout(nav_layout); + + int row = 0; + + // buttons for default settings + QPushButton *zoom_but = new QPushButton( tr("Reset to &Zoom as main controls") ); + connect(zoom_but, SIGNAL(clicked(bool)), this, SLOT(on_nav_resetZoomControls_clicked(bool))); + nav_layout->addWidget(zoom_but, row, 0); + QPushButton *move_but = new QPushButton( tr("Reset to &Move as main controls") ); + connect(move_but, SIGNAL(clicked(bool)), this, SLOT(on_nav_resetMoveControls_clicked(bool))); + nav_layout->addWidget(move_but, row, 1); + row++; + + // heading + QLabel *hdr1_label = new QLabel(tr("Control")); + hdr1_label->setAlignment(Qt::AlignLeft); + nav_layout->addWidget(hdr1_label, row, 0); + QLabel *hdr2_label = new QLabel(tr("Operation")); + hdr2_label->setAlignment(Qt::AlignLeft); + nav_layout->addWidget(hdr2_label, row, 1); + QLabel *hdr3_label = new QLabel(tr("NumPages or NumTimes")); + hdr3_label->setAlignment(Qt::AlignLeft); + nav_layout->addWidget(hdr3_label, row, 2); + row++; + // entries + NAV_SETTINGS_ROWS(UpDown, "Up / Down", row); row++; + NAV_SETTINGS_ROWS(LeftRight,"Left / Right", row); row++; + NAV_SETTINGS_ROWS(PageUpDown,"PageUp / PageDown", row); row++; + NAV_SETTINGS_ROWS(WheelHori,"Mouse Wheel Horizontal", row); row++; + NAV_SETTINGS_ROWS(WheelVert,"Mouse Wheel Vertical", row); row++; + + nav_load_gui_from_settings(); + + return form; +} + QWidget *Settings::get_decoder_settings_form(QWidget *parent) { #ifdef ENABLE_DECODE @@ -769,6 +826,38 @@ void Settings::on_view_defaultLogicHeight_changed(int value) settings.setValue(GlobalSettings::Key_View_DefaultLogicHeight, value); } +void Settings::on_nav_resetZoomControls_clicked(bool checked) +{ + printf("on_nav_resetZoomControls_clicked : %d\n", checked?1:0); + GlobalSettings settings; + settings.set_nav_zoom_defaults(true); + nav_load_gui_from_settings(); +} + +void Settings::on_nav_resetMoveControls_clicked(bool checked) +{ + printf("on_nav_resetMoveControls_clicked : %d\n", checked?1:0); + GlobalSettings settings; + settings.set_nav_move_defaults(true); + nav_load_gui_from_settings(); +} + +NAV_SETTINGS_FUNC_DEFINE(UpDown) +NAV_SETTINGS_FUNC_DEFINE(LeftRight) +NAV_SETTINGS_FUNC_DEFINE(PageUpDown) +NAV_SETTINGS_FUNC_DEFINE(WheelHori) +NAV_SETTINGS_FUNC_DEFINE(WheelVert) + +void Settings::nav_load_gui_from_settings() +{ + GlobalSettings settings; + NAV_SETTINGS_LOAD(UpDown); + NAV_SETTINGS_LOAD(LeftRight); + NAV_SETTINGS_LOAD(PageUpDown); + NAV_SETTINGS_LOAD(WheelHori); + NAV_SETTINGS_LOAD(WheelVert); +} + #ifdef ENABLE_DECODE void Settings::on_dec_initialStateConfigurable_changed(int state) { diff --git a/pv/dialogs/settings.hpp b/pv/dialogs/settings.hpp index 157fa6ba..764a8c99 100644 --- a/pv/dialogs/settings.hpp +++ b/pv/dialogs/settings.hpp @@ -27,6 +27,79 @@ #include #include #include +#include + +#define NAV_SETTINGS_FUNC_DECLARE1(name) \ + void on_nav_ ## name ## Type_changed(int type); \ + void on_nav_ ## name ## Amount_changed(const QString& astr) + +#define NAV_SETTINGS_FUNC_DECLARE(name) \ + NAV_SETTINGS_FUNC_DECLARE1(name); \ + NAV_SETTINGS_FUNC_DECLARE1(name ## Alt);\ + NAV_SETTINGS_FUNC_DECLARE1(name ## Ctrl);\ + NAV_SETTINGS_FUNC_DECLARE1(name ## Shift) + +#define NAV_SETTINGS_FUNC_DEFINE1(name) \ + void Settings::on_nav_ ## name ## Type_changed(int type){ \ + GlobalSettings settings; \ + settings.setValue(GlobalSettings::Key_Nav_ ## name ## Type, type); \ + } \ + void Settings::on_nav_ ## name ## Amount_changed(const QString& astr) { \ + GlobalSettings settings; \ + settings.setValue(GlobalSettings::Key_Nav_ ## name ## Amount, astr.toDouble()); \ + } + +#define NAV_SETTINGS_FUNC_DEFINE(name) \ + NAV_SETTINGS_FUNC_DEFINE1(name) \ + NAV_SETTINGS_FUNC_DEFINE1(name ## Alt) \ + NAV_SETTINGS_FUNC_DEFINE1(name ## Ctrl) \ + NAV_SETTINGS_FUNC_DEFINE1(name ## Shift) + +#define NAV_SETTINGS_ROW(name, text, row) \ + QLabel * name ## _label = new QLabel(tr(text));\ + name ## _label->setAlignment(Qt::AlignLeft); \ + nav_layout->addWidget(name ## _label, row, 0); \ + \ + name ## _type_cb_ = new QComboBox(); \ + name ## _type_cb_->addItem(tr("None"), NAV_TYPE_NONE); \ + name ## _type_cb_->addItem(tr("Zoom"), NAV_TYPE_ZOOM); \ + name ## _type_cb_->addItem(tr("Move Horizontally"), NAV_TYPE_HORI); \ + name ## _type_cb_->addItem(tr("Move Vertically"), NAV_TYPE_VERT); \ + name ## _type_cb_->setCurrentIndex( settings.value(GlobalSettings::Key_Nav_ ## name ## Type).toInt() ); \ + connect(name ## _type_cb_, SIGNAL(currentIndexChanged(int)), this, SLOT(on_nav_ ## name ## Type_changed(int))); \ + nav_layout->addWidget(name ## _type_cb_, row, 1); \ + \ + name ## _amount_edit_ = new QLineEdit(); \ + name ## _amount_edit_->setText( settings.value(GlobalSettings::Key_Nav_ ## name ## Amount).toString() ); \ + connect(name ## _amount_edit_, SIGNAL(textChanged(const QString&)), this, SLOT(on_nav_ ## name ## Amount_changed(const QString&))); \ + nav_layout->addWidget(name ## _amount_edit_, row, 2) +// name ## _amount_edit_->setValidator( new QDoubleValidator(name ## _amount_edit_) ); + +#define NAV_SETTINGS_ROWS(name, text, row) \ + NAV_SETTINGS_ROW(name, text, row*4 + 0); \ + NAV_SETTINGS_ROW(name ## Alt, text " + Alt", row*4 + 1); \ + NAV_SETTINGS_ROW(name ## Ctrl, text " + Ctrl", row*4 + 2); \ + NAV_SETTINGS_ROW(name ## Shift, text " + Shift", row*4 + 3) + +#define NAV_SETTINGS_VAR_DECLARE1(name) \ + QComboBox * name ## _type_cb_; \ + QLineEdit* name ## _amount_edit_ + +#define NAV_SETTINGS_VAR_DECLARE(name) \ + NAV_SETTINGS_VAR_DECLARE1(name); \ + NAV_SETTINGS_VAR_DECLARE1(name ## Alt); \ + NAV_SETTINGS_VAR_DECLARE1(name ## Ctrl); \ + NAV_SETTINGS_VAR_DECLARE1(name ## Shift) + +#define NAV_SETTINGS_LOAD1(name) \ + name ## _type_cb_->setCurrentIndex( settings.value(GlobalSettings::Key_Nav_ ## name ## Type).toInt() ); \ + name ## _amount_edit_->setText( settings.value(GlobalSettings::Key_Nav_ ## name ## Amount).toString() ) + +#define NAV_SETTINGS_LOAD(name) \ + NAV_SETTINGS_LOAD1(name); \ + NAV_SETTINGS_LOAD1(name ## Alt); \ + NAV_SETTINGS_LOAD1(name ## Ctrl); \ + NAV_SETTINGS_LOAD1(name ## Shift) namespace pv { @@ -49,6 +122,7 @@ class Settings : public QDialog QWidget *get_general_settings_form(QWidget *parent) const; QWidget *get_view_settings_form(QWidget *parent) const; + QWidget *get_navigation_settings_form(QWidget *parent); QWidget *get_decoder_settings_form(QWidget *parent); QWidget *get_about_page(QWidget *parent) const; QWidget *get_logging_page(QWidget *parent) const; @@ -77,7 +151,15 @@ private Q_SLOTS: void on_view_conversionThresholdDispMode_changed(int state); void on_view_defaultDivHeight_changed(int value); void on_view_defaultLogicHeight_changed(int value); -#ifdef ENABLE_DECODE + void on_nav_resetZoomControls_clicked(bool checked); + void on_nav_resetMoveControls_clicked(bool checked); + NAV_SETTINGS_FUNC_DECLARE(UpDown); + NAV_SETTINGS_FUNC_DECLARE(LeftRight); + NAV_SETTINGS_FUNC_DECLARE(PageUpDown); + NAV_SETTINGS_FUNC_DECLARE(WheelHori); + NAV_SETTINGS_FUNC_DECLARE(WheelVert); + void nav_load_gui_from_settings(); + #ifdef ENABLE_DECODE void on_dec_initialStateConfigurable_changed(int state); void on_dec_exportFormat_changed(const QString &text); void on_dec_alwaysshowallrows_changed(int state); @@ -91,6 +173,11 @@ private Q_SLOTS: DeviceManager &device_manager_; PageListWidget *page_list; QStackedWidget *pages; + NAV_SETTINGS_VAR_DECLARE(UpDown); + NAV_SETTINGS_VAR_DECLARE(LeftRight); + NAV_SETTINGS_VAR_DECLARE(PageUpDown); + NAV_SETTINGS_VAR_DECLARE(WheelHori); + NAV_SETTINGS_VAR_DECLARE(WheelVert); #ifdef ENABLE_DECODE QLineEdit *ann_export_format_; diff --git a/pv/globalsettings.cpp b/pv/globalsettings.cpp index ca649bef..34ad983b 100644 --- a/pv/globalsettings.cpp +++ b/pv/globalsettings.cpp @@ -70,6 +70,11 @@ const QString GlobalSettings::Key_View_CursorFillColor = "View_CursorFillColor"; const QString GlobalSettings::Key_View_CursorShowFrequency = "View_CursorShowFrequency"; const QString GlobalSettings::Key_View_CursorShowInterval = "View_CursorShowInterval"; const QString GlobalSettings::Key_View_CursorShowSamples = "View_CursorShowSamples"; +NAV_GSETTINGS_VAR_SETUP(UpDown); +NAV_GSETTINGS_VAR_SETUP(LeftRight); +NAV_GSETTINGS_VAR_SETUP(PageUpDown); +NAV_GSETTINGS_VAR_SETUP(WheelHori); +NAV_GSETTINGS_VAR_SETUP(WheelVert); const QString GlobalSettings::Key_Dec_InitialStateConfigurable = "Dec_InitialStateConfigurable"; const QString GlobalSettings::Key_Dec_ExportFormat = "Dec_ExportFormat"; const QString GlobalSettings::Key_Dec_AlwaysShowAllRows = "Dec_AlwaysShowAllRows"; @@ -98,6 +103,72 @@ void GlobalSettings::save_internal_defaults() default_palette_ = QApplication::palette(); } +// make controls zoom the traces when not using any key modifiers +// these controls are similar to the old controls used before customisation was introduced. +void GlobalSettings::set_nav_zoom_defaults(bool force) +{ + // zoom + NAV_GSETTINGS_VAR_DEFAULT(UpDown, NAV_TYPE_ZOOM, 0.25); // up/down arrow will zoom the traces by 1/4x + // small vertical movement + NAV_GSETTINGS_VAR_DEFAULT(UpDownCtrl, NAV_TYPE_VERT, 0.125); // up/down with any modifier will move traces vertically by 1/8 page + NAV_GSETTINGS_VAR_DEFAULT(UpDownAlt, NAV_TYPE_VERT, 0.125); + NAV_GSETTINGS_VAR_DEFAULT(UpDownShift, NAV_TYPE_VERT, 0.125); + // small horizontal movement + NAV_GSETTINGS_VAR_DEFAULT(LeftRight, NAV_TYPE_HORI, 0.125); // left/right arrow will move the trace by 1/8 page + NAV_GSETTINGS_VAR_DEFAULT(LeftRightShift, NAV_TYPE_HORI, 0.125); // left/right arrow + ctrl will move the trace by 1/8 page + NAV_GSETTINGS_VAR_DEFAULT(LeftRightCtrl, NAV_TYPE_HORI, 0.25); // left/right arrow + ctrl will move the trace by 1/4 page + NAV_GSETTINGS_VAR_DEFAULT(LeftRightAlt, NAV_TYPE_HORI, 0.5); // left/right arrow + alt will move the trace by 1/2 page + // big vertical movement + NAV_GSETTINGS_VAR_DEFAULT(PageUpDown, NAV_TYPE_VERT, 1.0); // page up/down will move traces vertically by 1 page + NAV_GSETTINGS_VAR_DEFAULT(PageUpDownShift, NAV_TYPE_VERT, 1.0); // page up/down + shift will move traces vertically by 1 page + NAV_GSETTINGS_VAR_DEFAULT(PageUpDownCtrl, NAV_TYPE_VERT, 2.0); // page up/down + ctrl will move traces vertically by 2 page + NAV_GSETTINGS_VAR_DEFAULT(PageUpDownAlt, NAV_TYPE_VERT, 4.0); // page up/down + alt will move traces vertically by 4 page + // vertical mosewheel can zoom and move horizontally and vertically + NAV_GSETTINGS_VAR_DEFAULT(WheelVert, NAV_TYPE_ZOOM, 0.25); // vertical mousewheel will zoom the traces by 1/4x + NAV_GSETTINGS_VAR_DEFAULT(WheelVertShift, NAV_TYPE_ZOOM, 0.25); // vertical mousewheel + shift will zoom the traces by 1/4x + NAV_GSETTINGS_VAR_DEFAULT(WheelVertCtrl, NAV_TYPE_VERT, 0.5); // vertical mousewheel + ctrl will move the traces by 1/2 page + NAV_GSETTINGS_VAR_DEFAULT(WheelVertAlt, NAV_TYPE_HORI, 1.0); // vertical mousewheel + alt will move the traces by 1 page + // horizontal mousewheel always moves horizontally + NAV_GSETTINGS_VAR_DEFAULT(WheelHori, NAV_TYPE_HORI, 0.25); // horizontal mousewheel will move the traces by 1/4 page + NAV_GSETTINGS_VAR_DEFAULT(WheelHoriShift, NAV_TYPE_HORI, 0.25); // horizontal mousewheel + shift will move the traces by 1/4 page + NAV_GSETTINGS_VAR_DEFAULT(WheelHoriCtrl, NAV_TYPE_HORI, 0.5); // horizontal mousewheel + ctrl will move the traces by 1/2 page + NAV_GSETTINGS_VAR_DEFAULT(WheelHoriAlt, NAV_TYPE_HORI, 1.0); // horizontal mousewheel + alt will move the traces by 1 page +} + +// make controls move the traces without key modifiers. +// slow speed move is default +// ctrl modifier does medium speed move +// alt modifier does fast speed move +// shift key always does zoom +void GlobalSettings::set_nav_move_defaults(bool force) +{ + // vertical movement + NAV_GSETTINGS_VAR_DEFAULT(UpDown, NAV_TYPE_VERT, 0.125); // up/down arrow will move the traces by 1/8 page + // zoom + NAV_GSETTINGS_VAR_DEFAULT(WheelHoriShift, NAV_TYPE_ZOOM, 0.25); // horizontal mousewheel + shift will zoom in/out by 1/4 x + NAV_GSETTINGS_VAR_DEFAULT(WheelVertShift, NAV_TYPE_ZOOM, 0.25); // vertical mousewheel + shift will zoom in/out by 1/4 x + NAV_GSETTINGS_VAR_DEFAULT(UpDownShift, NAV_TYPE_ZOOM, 1.0); // up/down arrow + shift will zoom in/out by 1x + NAV_GSETTINGS_VAR_DEFAULT(PageUpDownShift, NAV_TYPE_ZOOM, 2.0); // page up/down + shift will zoom in/out by 2x + // horizontal movement + NAV_GSETTINGS_VAR_DEFAULT(LeftRight, NAV_TYPE_HORI, 0.125); // left/right arrow will move the trace by 1/8 page + NAV_GSETTINGS_VAR_DEFAULT(LeftRightCtrl, NAV_TYPE_HORI, 0.25); // left/right arrow + ctrl will move the trace by 1/4 page + NAV_GSETTINGS_VAR_DEFAULT(LeftRightAlt, NAV_TYPE_HORI, 0.5); // left/right arrow + alt will move the trace by 1/2 page + NAV_GSETTINGS_VAR_DEFAULT(PageUpDown, NAV_TYPE_HORI, 1.0); // page up/down will move the trace by 1 page + NAV_GSETTINGS_VAR_DEFAULT(PageUpDownCtrl, NAV_TYPE_HORI, 2.0); // page up/down + ctrl will move the trace by 2 pages + NAV_GSETTINGS_VAR_DEFAULT(PageUpDownAlt, NAV_TYPE_HORI, 4.0); // page up/down + alt will move the trace by 4 pages + // horizontal movement with mousewheel + NAV_GSETTINGS_VAR_DEFAULT(WheelHori, NAV_TYPE_HORI, 0.25); // horizontal mousewheel will move the traces by 1/4 page + NAV_GSETTINGS_VAR_DEFAULT(WheelVert, NAV_TYPE_HORI, 0.25); // vertical mousewheel will move the traces by 1/4 page + NAV_GSETTINGS_VAR_DEFAULT(WheelHoriCtrl, NAV_TYPE_HORI, 0.5); // horizontal mousewheel + ctrl will move the traces by 1/2 page + NAV_GSETTINGS_VAR_DEFAULT(WheelVertCtrl, NAV_TYPE_HORI, 0.5); // vertical mousewheel + ctrl will move the traces by 1/2 page + NAV_GSETTINGS_VAR_DEFAULT(WheelHoriAlt, NAV_TYPE_HORI, 1.0); // horizontal mousewheel + alt will move the traces by 1 page + NAV_GSETTINGS_VAR_DEFAULT(WheelVertAlt, NAV_TYPE_HORI, 1.0); // vertical mousewheel + alt will move the traces by 1 page + // not used + NAV_GSETTINGS_VAR_DEFAULT(UpDownCtrl, NAV_TYPE_NONE, 0); + NAV_GSETTINGS_VAR_DEFAULT(UpDownAlt, NAV_TYPE_NONE, 0); + NAV_GSETTINGS_VAR_DEFAULT(LeftRightShift, NAV_TYPE_NONE, 0); +} + void GlobalSettings::set_defaults_where_needed() { if (!contains(Key_General_Language)) { @@ -154,7 +225,9 @@ void GlobalSettings::set_defaults_where_needed() if (!contains(Key_View_CursorShowFrequency)) setValue(Key_View_CursorShowFrequency, true); - + + set_nav_zoom_defaults(false); + // %c was used for the row name in the past so we need to transition such users if (!contains(Key_Dec_ExportFormat) || value(Key_Dec_ExportFormat).toString() == "%s %d: %c: %1") diff --git a/pv/globalsettings.hpp b/pv/globalsettings.hpp index e41c2ea9..151c300e 100644 --- a/pv/globalsettings.hpp +++ b/pv/globalsettings.hpp @@ -48,6 +48,39 @@ class GlobalSettingsInterface }; +// type of navigation to perform +#define NAV_TYPE_NONE 0 +#define NAV_TYPE_ZOOM 1 +#define NAV_TYPE_HORI 2 +#define NAV_TYPE_VERT 3 + +#define NAV_GSETTINGS_VAR_DECLARE(name) \ + static const QString Key_Nav_ ## name ## Type; \ + static const QString Key_Nav_ ## name ## Amount; \ + static const QString Key_Nav_ ## name ## AltType; \ + static const QString Key_Nav_ ## name ## AltAmount; \ + static const QString Key_Nav_ ## name ## CtrlType; \ + static const QString Key_Nav_ ## name ## CtrlAmount; \ + static const QString Key_Nav_ ## name ## ShiftType; \ + static const QString Key_Nav_ ## name ## ShiftAmount + +#define NAV_GSETTINGS_VAR_SETUP(name) \ + const QString GlobalSettings::Key_Nav_ ## name ## Type = "Nav_" #name "Type"; \ + const QString GlobalSettings::Key_Nav_ ## name ## Amount = "Nav_" #name "Amount"; \ + const QString GlobalSettings::Key_Nav_ ## name ## AltType = "Nav_" #name "AltType"; \ + const QString GlobalSettings::Key_Nav_ ## name ## AltAmount = "Nav_" #name "AltAmount"; \ + const QString GlobalSettings::Key_Nav_ ## name ## CtrlType = "Nav_" #name "CtrlType"; \ + const QString GlobalSettings::Key_Nav_ ## name ## CtrlAmount = "Nav_" #name "CtrlAmount"; \ + const QString GlobalSettings::Key_Nav_ ## name ## ShiftType = "Nav_" #name "ShiftType"; \ + const QString GlobalSettings::Key_Nav_ ## name ## ShiftAmount = "Nav_" #name "ShiftAmount" + +#define NAV_GSETTINGS_VAR_DEFAULT(name, type, amount) \ + if (!contains(Key_Nav_ ## name ## Type) || force) \ + setValue(Key_Nav_ ## name ## Type, type); \ + if (!contains(Key_Nav_ ## name ## Amount) || force) \ + setValue(Key_Nav_ ## name ## Amount, amount) + + class GlobalSettings : public QSettings { Q_OBJECT @@ -75,6 +108,11 @@ class GlobalSettings : public QSettings static const QString Key_View_CursorShowInterval; static const QString Key_View_CursorShowFrequency; static const QString Key_View_CursorShowSamples; + NAV_GSETTINGS_VAR_DECLARE(UpDown); + NAV_GSETTINGS_VAR_DECLARE(LeftRight); + NAV_GSETTINGS_VAR_DECLARE(PageUpDown); + NAV_GSETTINGS_VAR_DECLARE(WheelHori); + NAV_GSETTINGS_VAR_DECLARE(WheelVert); static const QString Key_Dec_InitialStateConfigurable; static const QString Key_Dec_ExportFormat; static const QString Key_Dec_AlwaysShowAllRows; @@ -92,6 +130,8 @@ class GlobalSettings : public QSettings void save_internal_defaults(); void set_defaults_where_needed(); + void set_nav_zoom_defaults(bool force); + void set_nav_move_defaults(bool force); void set_bright_theme_default_colors(); void set_dark_theme_default_colors(); diff --git a/pv/views/trace/view.cpp b/pv/views/trace/view.cpp index 47cb96b2..dd519b8e 100644 --- a/pv/views/trace/view.cpp +++ b/pv/views/trace/view.cpp @@ -223,11 +223,6 @@ View::View(Session &session, bool is_main_view, QMainWindow *parent) : 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); @@ -254,6 +249,26 @@ View::View(Session &session, bool is_main_view, QMainWindow *parent) : this, [=]{grabbed_widget_ = nullptr;}); cancel_grab_shortcut_->setAutoRepeat(false); + // Keyboard navigation + // This sets them all up as disabled initially. + NAV_KB_VAR_SETUP(up, Qt::Key_Up); + NAV_KB_VAR_SETUP(down, Qt::Key_Down); + NAV_KB_VAR_SETUP(left, Qt::Key_Left); + NAV_KB_VAR_SETUP(right, Qt::Key_Right); + NAV_KB_VAR_SETUP(pageup, Qt::Key_PageUp); + NAV_KB_VAR_SETUP(pagedown, Qt::Key_PageDown); + // Mousewheel navigation + // This sets them all up as disabled initially. + NAV_MW_VAR_SETUP(hori); + NAV_MW_VAR_SETUP(vert); + + // Load settings for keyboard and mousewheel navigation + NAV_KB_SETTING_LOAD(UpDown, up, down); + NAV_KB_SETTING_LOAD(LeftRight, left, right); + NAV_KB_SETTING_LOAD(PageUpDown, pageup, pagedown); + NAV_MW_SETTING_LOAD(WheelHori, hori); + NAV_MW_SETTING_LOAD(WheelVert, vert); + // Trigger the initial event manually. The default device has signals // which were created before this object came into being signals_changed(); @@ -1195,6 +1210,12 @@ void View::on_setting_changed(const QString &key, const QVariant &value) if (key == GlobalSettings::Key_View_SnapDistance) snap_distance_ = settings.value(GlobalSettings::Key_View_SnapDistance).toInt(); + + NAV_KB_SETTING_CHANGED(UpDown, up, down) + NAV_KB_SETTING_CHANGED(LeftRight, left, right) + NAV_KB_SETTING_CHANGED(PageUpDown, pageup, pagedown) + NAV_MW_SETTING_CHANGED(WheelHori, hori) + NAV_MW_SETTING_CHANGED(WheelVert, vert) } void View::trigger_event(int segment_id, util::Timestamp location) @@ -1738,6 +1759,91 @@ void View::on_scroll_to_end_shortcut_triggered() set_h_offset(get_h_scrollbar_maximum()); } + +void View::nav_zoom(double numTimes) +{ + QPoint global_point = QCursor::pos(); + printf("nav_zoom() global_point(%d, %d) %d\n", global_point.x(), global_point.y(), global_point.isNull()?1:0); + if( global_point.isNull() ) + { + zoom(-numTimes); + return; + } + + QPoint widget_point = viewport_->mapFromGlobal(global_point); + printf("nav_zoom() widget_point(%d, %d) %d\n", widget_point.x(), widget_point.y(), widget_point.isNull()?1:0); + if( widget_point.isNull() || + widget_point.x() < 0 || widget_point.x() > viewport_->width() || + widget_point.y() < 0 || widget_point.y() > viewport_->height()) + { + zoom(-numTimes); + return; + } + + printf("zoom t mouse\n"); + zoom(-numTimes, widget_point.x()); +} + +void View::nav_zoom(double numTimes, int offset) +{ + zoom(-numTimes, offset); +} + +void View::nav_move_hori(double numPages) +{ + double page_width = viewport_->width(); + double move_amount = numPages * page_width; + int curr_pos = scrollarea_->horizontalScrollBar()->sliderPosition(); + int new_pos = curr_pos + move_amount; + +// printf("nav_move_hori(): page_width=%g move_amount=%g curr_pos=%d new_pos=%d\n", +// page_width, move_amount, curr_pos, new_pos); + + set_h_offset(new_pos); +} + +// amount is double value representing numPages. +// 1.0 is a full page down +// -1.0 is a full page up +void View::nav_move_vert(double numPages) +{ + double page_height = viewport_->height(); + double move_amount = numPages * page_height; + int curr_pos = scrollarea_->verticalScrollBar()->sliderPosition(); + int new_pos = curr_pos + move_amount; + +// printf("nav_move_vert(): page_height=%g move_amount=%g curr_pos=%d new_pos=%d\n", +// page_height, move_amount, curr_pos, new_pos); + + set_v_offset(new_pos); +} + +NAV_KB_FUNC_DEFINE(up) +NAV_KB_FUNC_DEFINE(down) +NAV_KB_FUNC_DEFINE(left) +NAV_KB_FUNC_DEFINE(right) +NAV_KB_FUNC_DEFINE(pageup) +NAV_KB_FUNC_DEFINE(pagedown) + +NAV_MW_FUNC_DEFINE(hori) +NAV_MW_FUNC_DEFINE(vert) + +void View::on_mw_vert_all(QWheelEvent *event) +{ + if (event->modifiers() & Qt::AltModifier) on_mw_vert_alt(event); + else if (event->modifiers() & Qt::ControlModifier) on_mw_vert_ctrl(event); + else if (event->modifiers() & Qt::ShiftModifier) on_mw_vert_shift(event); + else on_mw_vert(event); +} + +void View::on_mw_hori_all(QWheelEvent *event) +{ + if (event->modifiers() & Qt::AltModifier) on_mw_hori_alt(event); + else if (event->modifiers() & Qt::ControlModifier) on_mw_hori_ctrl(event); + else if (event->modifiers() & Qt::ShiftModifier) on_mw_hori_shift(event); + else on_mw_hori(event); +} + void View::h_scroll_value_changed(int value) { if (updating_scroll_) diff --git a/pv/views/trace/view.hpp b/pv/views/trace/view.hpp index f8506cf4..d3c02c0d 100644 --- a/pv/views/trace/view.hpp +++ b/pv/views/trace/view.hpp @@ -80,6 +80,192 @@ class CustomScrollArea : public QAbstractScrollArea bool viewportEvent(QEvent *event); }; +// This Navigation code handles customisation of keyboard and mousewheel controls +// for navigating the traces by moving them and zooming them. +// +// There are 5 sets of keys/mousewheels usable for customisation: +// up/down, left/right, pageup/pagedown, +// horizontal mousewheel and vertical mousewheel. +// There are 3 modifier keys that can be used with the above, as well as using +// no modifier. These are: +// none, alt, ctrl, shift. +// Together the main and modifiers provide 5 * 4 = 20 different navigation controls +// for customisation. +// +// There are 4 types of navigation that the above can be assigned to do: +// none = no operation performed (same as disabling the operation) +// zoom = zoom in/out of the trace view +// hori = move the trace horizontally to see previous or next sample data +// vert = move the trace vertically to see channels above or below +// +// There is an "amount" variable of type "double" to be used with navigation. +// When moving traces horizontally or vertically the "amount" value is equal to +// the number of pages to move. So a value of 1.0 would move 1 page forward. +// A value of -0.5 would move half a page backwards. +// When zooming into traces the "amount" value is equal to the zoom multiplier. +// So a value of 1.0 will zoom out by 1x and a value of -2.0 will zoom in by 2x. +// +// A "Navigation" page has been added to the Settings to allow the user to +// customise the navigation controls to their liking. + +// type of navigation to perform +#define NAV_TYPE_NONE 0 +#define NAV_TYPE_ZOOM 1 +#define NAV_TYPE_HORI 2 +#define NAV_TYPE_VERT 3 + +// navigation using keyboard +typedef struct { + int type; // NAV_TYPE_??? value + double amount; // amount to perform nav operation by + QShortcut* sc; +} NavKb_t; + +// navigation using mousewheel +typedef struct { + int type; // NAV_TYPE_??? value + double amount; // amount to perform nav operation by +} NavMw_t; + +// keyboard +#define NAV_KB_VAR_DECLARE(name) \ + NavKb_t name ## _nav_, name ## _alt_nav_, name ## _ctrl_nav_, name ## _shift_nav_ + +#define NAV_KB_VAR_SETUP(name, keys) \ + name ## _nav_.type = NAV_TYPE_NONE;\ + name ## _alt_nav_.type = NAV_TYPE_NONE;\ + name ## _ctrl_nav_.type = NAV_TYPE_NONE;\ + name ## _shift_nav_.type = NAV_TYPE_NONE;\ + name ## _nav_.amount = 0; \ + name ## _alt_nav_.amount = 0; \ + name ## _ctrl_nav_.amount = 0; \ + name ## _shift_nav_.amount = 0; \ + name ## _nav_.sc = new QShortcut(QKeySequence(keys), this, SLOT(on_kb_ ##name ()), nullptr, Qt::WidgetWithChildrenShortcut); \ + name ## _alt_nav_.sc = new QShortcut(QKeySequence(keys + Qt::ALT), this, SLOT(on_kb_ ##name## _alt()), nullptr, Qt::WidgetWithChildrenShortcut); \ + name ## _ctrl_nav_.sc = new QShortcut(QKeySequence(keys + Qt::CTRL), this, SLOT(on_kb_ ##name## _ctrl()), nullptr, Qt::WidgetWithChildrenShortcut); \ + name ## _shift_nav_.sc = new QShortcut(QKeySequence(keys + Qt::SHIFT), this, SLOT(on_kb_ ##name## _shift()), nullptr, Qt::WidgetWithChildrenShortcut) + +#define NAV_KB_FUNC_DECLARE1(name) \ + void on_kb_ ## name () + +#define NAV_KB_FUNC_DECLARE(name) \ + NAV_KB_FUNC_DECLARE1(name); \ + NAV_KB_FUNC_DECLARE1(name ## _alt); \ + NAV_KB_FUNC_DECLARE1(name ## _ctrl); \ + NAV_KB_FUNC_DECLARE1(name ## _shift) + +#define NAV_KB_FUNC_DEFINE1(name) \ + void View::on_kb_ ## name () { \ + if ( name ## _nav_.type == NAV_TYPE_NONE )return; \ + else if (name ## _nav_.type == NAV_TYPE_ZOOM )nav_zoom(name ## _nav_.amount); \ + else if (name ## _nav_.type == NAV_TYPE_HORI )nav_move_hori(name ## _nav_.amount); \ + else if (name ## _nav_.type == NAV_TYPE_VERT )nav_move_vert(name ## _nav_.amount); \ + } + +#define NAV_KB_FUNC_DEFINE(name) \ + NAV_KB_FUNC_DEFINE1(name) \ + NAV_KB_FUNC_DEFINE1(name ## _alt) \ + NAV_KB_FUNC_DEFINE1(name ## _ctrl) \ + NAV_KB_FUNC_DEFINE1(name ## _shift) + +#define NAV_KB_SETTING_CHANGED1(name, k1, k2) \ + if (key == GlobalSettings::Key_Nav_ ## name ## Type) { \ + k1 ## _nav_.type = settings.value(GlobalSettings::Key_Nav_ ## name ## Type).toInt(); \ + k2 ## _nav_.type = settings.value(GlobalSettings::Key_Nav_ ## name ## Type).toInt(); \ + } \ + if (key == GlobalSettings::Key_Nav_ ## name ## Amount) { \ + k1 ## _nav_.amount = -settings.value(GlobalSettings::Key_Nav_ ## name ## Amount).toDouble(); \ + k2 ## _nav_.amount = settings.value(GlobalSettings::Key_Nav_ ## name ## Amount).toDouble(); \ + } + +#define NAV_KB_SETTING_CHANGED(name, k1, k2) \ + NAV_KB_SETTING_CHANGED1(name, k1, k2) \ + NAV_KB_SETTING_CHANGED1(name ## Alt, k1 ## _alt, k2 ## _alt) \ + NAV_KB_SETTING_CHANGED1(name ## Ctrl, k1 ## _ctrl, k2 ## _ctrl) \ + NAV_KB_SETTING_CHANGED1(name ## Shift, k1 ## _shift, k2 ## _shift) + +#define NAV_KB_SETTING_LOAD1(name, k1, k2) \ + if (settings.contains(GlobalSettings::Key_Nav_ ## name ## Type)) { \ + k1 ## _nav_.type = settings.value(GlobalSettings::Key_Nav_ ## name ## Type).toInt(); \ + k2 ## _nav_.type = settings.value(GlobalSettings::Key_Nav_ ## name ## Type).toInt(); \ + } \ + if (settings.contains(GlobalSettings::Key_Nav_ ## name ## Amount)) { \ + k1 ## _nav_.amount = -settings.value(GlobalSettings::Key_Nav_ ## name ## Amount).toDouble(); \ + k2 ## _nav_.amount = settings.value(GlobalSettings::Key_Nav_ ## name ## Amount).toDouble(); \ + } + +#define NAV_KB_SETTING_LOAD(name, k1, k2) \ + NAV_KB_SETTING_LOAD1(name, k1, k2) \ + NAV_KB_SETTING_LOAD1(name ## Alt, k1 ## _alt, k2 ## _alt) \ + NAV_KB_SETTING_LOAD1(name ## Ctrl, k1 ## _ctrl, k2 ## _ctrl) \ + NAV_KB_SETTING_LOAD1(name ## Shift, k1 ## _shift, k2 ## _shift) + +// mousewheel +#define NAV_MW_VAR_DECLARE(name) \ + NavMw_t name ## _nav_, name ## _alt_nav_, name ## _ctrl_nav_, name ## _shift_nav_ + +#define NAV_MW_VAR_SETUP(name) \ + name ## _nav_.type = NAV_TYPE_NONE;\ + name ## _alt_nav_.type = NAV_TYPE_NONE;\ + name ## _ctrl_nav_.type = NAV_TYPE_NONE;\ + name ## _shift_nav_.type = NAV_TYPE_NONE;\ + name ## _nav_.amount = 0; \ + name ## _alt_nav_.amount = 0; \ + name ## _ctrl_nav_.amount = 0; \ + name ## _shift_nav_.amount = 0 + +#define NAV_MW_FUNC_DECLARE1(name) \ + void on_mw_ ## name (QWheelEvent *event) + +#define NAV_MW_FUNC_DECLARE(name) \ + NAV_MW_FUNC_DECLARE1(name); \ + NAV_MW_FUNC_DECLARE1(name ## _alt); \ + NAV_MW_FUNC_DECLARE1(name ## _ctrl); \ + NAV_MW_FUNC_DECLARE1(name ## _shift) + +#define NAV_MW_FUNC_DEFINE1(name) \ + void View::on_mw_ ## name (QWheelEvent *event) { \ + if ( name ## _nav_.type == NAV_TYPE_NONE )return; \ + else if (name ## _nav_.type == NAV_TYPE_ZOOM )nav_zoom( (-event->delta() * name ## _nav_.amount)/120.0, event->x()); \ + else if (name ## _nav_.type == NAV_TYPE_HORI )nav_move_hori((-event->delta() * name ## _nav_.amount)/120.0); \ + else if (name ## _nav_.type == NAV_TYPE_VERT )nav_move_vert((-event->delta() * name ## _nav_.amount)/120.0); \ + } + +#define NAV_MW_FUNC_DEFINE(name) \ + NAV_MW_FUNC_DEFINE1(name) \ + NAV_MW_FUNC_DEFINE1(name ## _alt) \ + NAV_MW_FUNC_DEFINE1(name ## _ctrl) \ + NAV_MW_FUNC_DEFINE1(name ## _shift) + +#define NAV_MW_SETTING_CHANGED1(name, mw) \ + if (key == GlobalSettings::Key_Nav_ ## name ## Type) { \ + mw ## _nav_.type = settings.value(GlobalSettings::Key_Nav_ ## name ## Type).toInt(); \ + } \ + if (key == GlobalSettings::Key_Nav_ ## name ## Amount) { \ + mw ## _nav_.amount = settings.value(GlobalSettings::Key_Nav_ ## name ## Amount).toDouble(); \ + } + +#define NAV_MW_SETTING_CHANGED(name, mw) \ + NAV_MW_SETTING_CHANGED1(name, mw) \ + NAV_MW_SETTING_CHANGED1(name ## Alt, mw ## _alt) \ + NAV_MW_SETTING_CHANGED1(name ## Ctrl, mw ## _ctrl) \ + NAV_MW_SETTING_CHANGED1(name ## Shift, mw ## _shift) + +#define NAV_MW_SETTING_LOAD1(name, mw) \ + if (settings.contains(GlobalSettings::Key_Nav_ ## name ## Type)) { \ + mw ## _nav_.type = settings.value(GlobalSettings::Key_Nav_ ## name ## Type).toInt(); \ + } \ + if (settings.contains(GlobalSettings::Key_Nav_ ## name ## Amount)) { \ + mw ## _nav_.amount = settings.value(GlobalSettings::Key_Nav_ ## name ## Amount).toDouble(); \ + } + +#define NAV_MW_SETTING_LOAD(name, mw) \ + NAV_MW_SETTING_LOAD1(name, mw) \ + NAV_MW_SETTING_LOAD1(name ## Alt, mw ## _alt) \ + NAV_MW_SETTING_LOAD1(name ## Ctrl, mw ## _ctrl) \ + NAV_MW_SETTING_LOAD1(name ## Shift, mw ## _shift) + + class View : public ViewBase, public TraceTreeItemOwner, public GlobalSettingsInterface { Q_OBJECT @@ -429,6 +615,14 @@ public Q_SLOTS: void extents_changed(bool horz, bool vert); + void nav_zoom(double amount); + void nav_zoom(double amount, int offset); + void nav_move_hori(double amount); + void nav_move_vert(double amount); + + void on_mw_vert_all(QWheelEvent *event); + void on_mw_hori_all(QWheelEvent *event); + private Q_SLOTS: void on_signal_name_changed(); void on_splitter_moved(); @@ -446,6 +640,16 @@ private Q_SLOTS: void signals_changed(); void capture_state_updated(int state); + // keyboard and mousewheel navigation functions + NAV_KB_FUNC_DECLARE(up); + NAV_KB_FUNC_DECLARE(down); + NAV_KB_FUNC_DECLARE(left); + NAV_KB_FUNC_DECLARE(right); + NAV_KB_FUNC_DECLARE(pageup); + NAV_KB_FUNC_DECLARE(pagedown); + NAV_MW_FUNC_DECLARE(hori); + NAV_MW_FUNC_DECLARE(vert); + void on_new_segment(int new_segment_id); void on_segment_completed(int new_segment_id); void on_segment_changed(int segment); @@ -504,12 +708,21 @@ private Q_SLOTS: Header *header_; QSplitter *splitter_; - QShortcut *zoom_in_shortcut_, *zoom_in_shortcut_2_; - QShortcut *zoom_out_shortcut_, *zoom_out_shortcut_2_; + QShortcut *zoom_in_shortcut_, *zoom_out_shortcut_; QShortcut *home_shortcut_, *end_shortcut_; QShortcut *grab_ruler_left_shortcut_, *grab_ruler_right_shortcut_; QShortcut *cancel_grab_shortcut_; - + + // keyboard and mousewheel navigation variables + NAV_KB_VAR_DECLARE(up); + NAV_KB_VAR_DECLARE(down); + NAV_KB_VAR_DECLARE(left); + NAV_KB_VAR_DECLARE(right); + NAV_KB_VAR_DECLARE(pageup); + NAV_KB_VAR_DECLARE(pagedown); + NAV_MW_VAR_DECLARE(hori); + NAV_MW_VAR_DECLARE(vert); + mutable mutex signal_mutex_; vector< shared_ptr > signals_; diff --git a/pv/views/trace/viewport.cpp b/pv/views/trace/viewport.cpp index 0c73ec49..7753dc60 100644 --- a/pv/views/trace/viewport.cpp +++ b/pv/views/trace/viewport.cpp @@ -212,19 +212,9 @@ void Viewport::wheelEvent(QWheelEvent *event) assert(event); if (event->orientation() == Qt::Vertical) { - if (event->modifiers() & Qt::ControlModifier) { - // Vertical scrolling with the control key pressed - // is intrepretted as vertical scrolling - view_.set_v_offset(-view_.owner_visual_v_offset() - - (event->delta() * height()) / (8 * 120)); - } else { - // Vertical scrolling is interpreted as zooming in/out - view_.zoom(event->delta() / 120.0, event->x()); - } + view_.on_mw_vert_all(event); } else if (event->orientation() == Qt::Horizontal) { - // Horizontal scrolling is interpreted as moving left/right - view_.set_scale_offset(view_.scale(), - event->delta() * view_.scale() + view_.offset()); + view_.on_mw_hori_all(event); } }