BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ScientificSpinBox.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Views/JobWidgets/ScientificSpinBox.cpp
6 //! @brief Implements class ScientificSpinBox
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
16 #include <QLineEdit>
17 #include <cmath>
18 
19 namespace {
20 const double upper_switch = 100;
21 const double lower_switch = 0.1;
22 const double min_val = std::numeric_limits<double>::min();
23 const double max_val = std::numeric_limits<double>::max();
24 
25 bool useExponentialNotation(double val);
26 } // namespace
27 
29  : QAbstractSpinBox(parent)
30  , m_value(0.0)
31  , m_min(-max_val)
32  , m_max(max_val)
33  , m_step(1.0)
34  , m_decimals(3)
35 {
36  QLocale locale;
37  locale.setNumberOptions(QLocale::RejectGroupSeparator);
38  m_validator.setLocale(locale);
39  m_validator.setNotation(QDoubleValidator::ScientificNotation);
40 
41  connect(this, &QAbstractSpinBox::editingFinished, this, &ScientificSpinBox::updateValue);
42 }
43 
45 
47 {
48  return m_value;
49 }
50 
52 {
53  double old_val = m_value;
54  m_value = round(val, m_decimals);
55  updateText();
56  if (std::abs(old_val - m_value) > min_val)
57  emit valueChanged(m_value);
58 }
59 
61 {
62  double new_val = toDouble(text(), m_validator, m_min, m_max, m_value);
63  setValue(new_val);
64 }
65 
67 {
68  return m_step;
69 }
70 
72 {
73  m_step = step;
74 }
75 
77 {
78  return m_min;
79 }
80 
82 {
83  m_min = min;
84  if (m_value < m_min)
85  setValue(m_min);
86 }
87 
89 {
90  return m_max;
91 }
92 
94 {
95  m_max = max;
96  if (m_value > m_max)
97  setValue(m_max);
98 }
99 
101 {
102  if (val <= 0)
103  return;
104  m_decimals = val;
105  setValue(m_value);
106 }
107 
109 {
110  return m_decimals;
111 }
112 
114 {
115  double new_val = round(m_value + m_step * steps, m_decimals);
116  if (inRange(new_val))
117  setValue(new_val);
118 }
119 
120 QString ScientificSpinBox::toString(double val, int decimal_points)
121 {
122  QString result = useExponentialNotation(val) ? QString::number(val, 'e', decimal_points)
123  : QString::number(val, 'f', decimal_points);
124 
125  return result.replace(QRegExp("(\\.?0+)?((e{1}[\\+|-]{1})(0+)?([1-9]{1}.*))?$"), "\\3\\5");
126 }
127 
128 double ScientificSpinBox::toDouble(QString text, const QDoubleValidator& validator, double min,
129  double max, double default_value)
130 {
131  int pos = 0;
132  if (validator.validate(text, pos) == QValidator::Acceptable) {
133  double new_val = validator.locale().toDouble(text);
134  if (std::abs(new_val) < min_val)
135  new_val = 0.0;
136  return new_val >= min && new_val <= max ? new_val : default_value;
137  }
138  return default_value;
139 }
140 
141 double ScientificSpinBox::round(double val, int decimals)
142 {
143  return QString::number(val, 'e', decimals).toDouble();
144 }
145 
146 QAbstractSpinBox::StepEnabled ScientificSpinBox::stepEnabled() const
147 {
148  return isReadOnly() ? StepNone : StepUpEnabled | StepDownEnabled;
149 }
150 
152 {
153  QString new_text = toString(m_value, m_decimals);
154  if (new_text != text())
155  lineEdit()->setText(new_text);
156 }
157 
158 bool ScientificSpinBox::inRange(double val) const
159 {
160  return val >= m_min && val <= m_max;
161 }
162 
163 namespace {
164 bool useExponentialNotation(double val)
165 {
166  const double abs_val = std::abs(val);
167 
168  if (abs_val <= min_val)
169  return false;
170 
171  return abs_val >= upper_switch || abs_val < lower_switch;
172 }
173 } // namespace
Defines class ScientificSpinBox.
double minimum() const
ScientificSpinBox(QWidget *parent=nullptr)
void stepBy(int steps) override
static double toDouble(QString text, const QDoubleValidator &validator, double min, double max, double default_value)
void setMaximum(double max)
void setMinimum(double min)
~ScientificSpinBox() override
double maximum() const
void setValue(double val)
void setSingleStep(double step)
QDoubleValidator m_validator
static double round(double val, int decimals)
bool inRange(double val) const
QAbstractSpinBox::StepEnabled stepEnabled() const override
static QString toString(double val, int decimal_points)
void valueChanged(double value)
double singleStep() const