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 @@
+
+
+
+
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);
}
}