From d0b698645514f2e52528dd7adf9ee9278dc4da9b Mon Sep 17 00:00:00 2001 From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de> Date: Fri, 7 Jul 2023 11:27:00 +0200 Subject: [PATCH] Make instrument spinboxes safe (closes #476) --- CHANGELOG | 1 + GUI/View/Device/SphericalAxisForm.cpp | 19 +++++++++++-------- GUI/View/Device/SphericalAxisForm.h | 7 +++---- GUI/View/Numeric/DoubleSpinBox.cpp | 4 ++-- GUI/View/Numeric/DoubleSpinBox.h | 2 +- GUI/View/Numeric/ScientificSpinBox.cpp | 12 +++++++++++- GUI/View/Numeric/ScientificSpinBox.h | 6 +++++- 7 files changed, 34 insertions(+), 17 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 69ca47ed66d..c515ce057d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,7 @@ BornAgain-21.0, in preparation > Bug fixes: * Fix averaging magnetic materials (#76) * Repair polarization analysis in GUI (#190) + * Protect all spinboxes from accidental scrolling (#476) * Repair specular intensity for polarized GISANS (#541) * Repair axis ticks display in linear scale in GUI (#575) * Prevent crash in QRE loader (#589) diff --git a/GUI/View/Device/SphericalAxisForm.cpp b/GUI/View/Device/SphericalAxisForm.cpp index 5e842143ea4..ad0f9707666 100644 --- a/GUI/View/Device/SphericalAxisForm.cpp +++ b/GUI/View/Device/SphericalAxisForm.cpp @@ -15,6 +15,7 @@ #include "GUI/View/Device/SphericalAxisForm.h" #include "GUI/Model/Axis/BasicAxisItem.h" #include "GUI/View/Numeric/SafeSpinBox.h" +#include "GUI/View/Numeric/ScientificSpinBox.h" SphericalAxisForm::SphericalAxisForm(QFormLayout* form, QWidget* parent) : QObject(parent) @@ -26,19 +27,21 @@ SphericalAxisForm::SphericalAxisForm(QFormLayout* form, QWidget* parent) &SphericalAxisForm::onNbinsValueChanged); form->addRow("# scan points:", m_nbinsSpinBox); - m_minimumSpinBox = new QDoubleSpinBox(parent); - m_minimumSpinBox->setRange(0, 90); - m_minimumSpinBox->setDecimals(3); + m_minimumSpinBox = new ScientificSpinBox(parent); + m_minimumSpinBox->setMinimum(0); + m_minimumSpinBox->setMaximum(90); + m_minimumSpinBox->setDecimals(5); m_minimumSpinBox->setSingleStep(0.01); - connect(m_minimumSpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, + connect(m_minimumSpinBox, &ScientificSpinBox::valueChanged, this, &SphericalAxisForm::onMinimumValueChanged); form->addRow("Initial angle [deg]:", m_minimumSpinBox); - m_maximumSpinBox = new QDoubleSpinBox(parent); - m_maximumSpinBox->setRange(0, 90); - m_maximumSpinBox->setDecimals(3); + m_maximumSpinBox = new ScientificSpinBox(parent); + m_maximumSpinBox->setMinimum(0); + m_maximumSpinBox->setMaximum(90); + m_maximumSpinBox->setDecimals(5); m_maximumSpinBox->setSingleStep(0.01); - connect(m_maximumSpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, + connect(m_maximumSpinBox, &ScientificSpinBox::valueChanged, this, &SphericalAxisForm::onMaximumValueChanged); form->addRow("Final angle [deg]:", m_maximumSpinBox); } diff --git a/GUI/View/Device/SphericalAxisForm.h b/GUI/View/Device/SphericalAxisForm.h index c4ea7451e3d..9e41d17fc42 100644 --- a/GUI/View/Device/SphericalAxisForm.h +++ b/GUI/View/Device/SphericalAxisForm.h @@ -15,12 +15,11 @@ #ifndef BORNAGAIN_GUI_VIEW_DEVICE_SPHERICALAXISFORM_H #define BORNAGAIN_GUI_VIEW_DEVICE_SPHERICALAXISFORM_H -#include <QDoubleSpinBox> #include <QFormLayout> -#include <QWidget> class BasicAxisItem; class SafeSpinBox; +class ScientificSpinBox; /// The form for a spherical axis: contains the bare bone widgets for the user to enter /// the number of bins and to select the range in degrees (minimum & maximum) @@ -46,8 +45,8 @@ private slots: private: SafeSpinBox* m_nbinsSpinBox; - QDoubleSpinBox* m_minimumSpinBox; - QDoubleSpinBox* m_maximumSpinBox; + ScientificSpinBox* m_minimumSpinBox; + ScientificSpinBox* m_maximumSpinBox; BasicAxisItem* m_axisItem; }; diff --git a/GUI/View/Numeric/DoubleSpinBox.cpp b/GUI/View/Numeric/DoubleSpinBox.cpp index f050298af2a..dddb2d01dcd 100644 --- a/GUI/View/Numeric/DoubleSpinBox.cpp +++ b/GUI/View/Numeric/DoubleSpinBox.cpp @@ -19,7 +19,7 @@ DoubleSpinBox::DoubleSpinBox(DoubleProperty& d, bool easyScrollable, QWidget* parent) : QDoubleSpinBox(parent) , m_valueProperty(d) - , easyScrollable(easyScrollable) + , m_easyScrollable(easyScrollable) { setFocusPolicy(Qt::StrongFocus); GUI::View::NumberUtil::configSpinbox(this, d.decimals(), d.limits()); @@ -90,7 +90,7 @@ void DoubleSpinBox::setBaseValue(double baseValue) void DoubleSpinBox::wheelEvent(QWheelEvent* event) { - if (hasFocus() || easyScrollable) + if (hasFocus() || m_easyScrollable) QDoubleSpinBox::wheelEvent(event); else event->ignore(); diff --git a/GUI/View/Numeric/DoubleSpinBox.h b/GUI/View/Numeric/DoubleSpinBox.h index 7d716d5c21f..1b62117322d 100644 --- a/GUI/View/Numeric/DoubleSpinBox.h +++ b/GUI/View/Numeric/DoubleSpinBox.h @@ -75,7 +75,7 @@ private: Unit m_displayUnit = Unit::unitless; DoubleProperty& m_valueProperty; - bool easyScrollable; + bool m_easyScrollable; //! it was decided to not show the unit as a suffix. However, this may be user //! selectable once, therefore the code is kept and controlled by this flag diff --git a/GUI/View/Numeric/ScientificSpinBox.cpp b/GUI/View/Numeric/ScientificSpinBox.cpp index 7b557f6c94b..a7f89b721e7 100644 --- a/GUI/View/Numeric/ScientificSpinBox.cpp +++ b/GUI/View/Numeric/ScientificSpinBox.cpp @@ -15,6 +15,7 @@ #include "GUI/View/Numeric/ScientificSpinBox.h" #include <QLineEdit> #include <QRegularExpression> +#include <QWheelEvent> #include <cmath> namespace { @@ -28,13 +29,14 @@ bool useExponentialNotation(double val); } // namespace -ScientificSpinBox::ScientificSpinBox(QWidget* parent) +ScientificSpinBox::ScientificSpinBox(QWidget* parent, bool easyScrollable) : QAbstractSpinBox(parent) , m_value(0.0) , m_min(-max_val) , m_max(max_val) , m_step(1.0) , m_decimals(3) + , m_easyScrollable(easyScrollable) { QLocale locale; locale.setNumberOptions(QLocale::RejectGroupSeparator); @@ -147,6 +149,14 @@ double ScientificSpinBox::round(double val, int decimals) return QString::number(val, 'e', decimals).toDouble(); } +void ScientificSpinBox::wheelEvent(QWheelEvent* event) +{ + if (hasFocus() || m_easyScrollable) + QAbstractSpinBox::wheelEvent(event); + else + event->ignore(); +} + QAbstractSpinBox::StepEnabled ScientificSpinBox::stepEnabled() const { return isReadOnly() ? StepNone : StepUpEnabled | StepDownEnabled; diff --git a/GUI/View/Numeric/ScientificSpinBox.h b/GUI/View/Numeric/ScientificSpinBox.h index 6b193939730..0ab0a6733b4 100644 --- a/GUI/View/Numeric/ScientificSpinBox.h +++ b/GUI/View/Numeric/ScientificSpinBox.h @@ -21,7 +21,7 @@ class ScientificSpinBox : public QAbstractSpinBox { Q_OBJECT Q_PROPERTY(double value MEMBER m_value READ value WRITE setValue NOTIFY valueChanged USER true) public: - ScientificSpinBox(QWidget* parent = nullptr); + ScientificSpinBox(QWidget* parent = nullptr, bool easyScrollable = false); ~ScientificSpinBox() override; double value() const; @@ -48,6 +48,9 @@ public: double default_value); static double round(double val, int decimals); +protected: + void wheelEvent(QWheelEvent* event) override; + signals: void valueChanged(double value); @@ -61,6 +64,7 @@ private: double m_value, m_min, m_max; double m_step; int m_decimals; + bool m_easyScrollable; QDoubleValidator m_validator; }; -- GitLab