1 /*
2     SPDX-FileCopyrightText: 2017 Robert Lancaster <rlancaste@gmail.com>
3 
4     Based on an idea discussed in the QT Centre: http://www.qtcentre.org/threads/47535-QDoubleSpinBox-with-nonlinear-values
5 
6     SPDX-License-Identifier: GPL-2.0-or-later
7 */
8 
9 #include "auxiliary/nonlineardoublespinbox.h"
10 
NonLinearDoubleSpinBox(QWidget * parent)11 NonLinearDoubleSpinBox::NonLinearDoubleSpinBox(QWidget *parent) : QDoubleSpinBox(parent)
12 {
13     m_Values << 0.01 << 0.02 << 0.05 << 0.1 << 0.2 << 0.25 << 0.5 << 1 << 1.5 << 2 << 2.5 << 3 << 5 << 6 << 7 << 8 << 9 << 10 << 20 << 30 << 40 << 50 << 60 << 120 << 180 << 300 << 600 << 900;
14     setRange(m_Values.first() , m_Values.last());
15 
16     //This will update the _idx variable to the index of the new value.  It will give -1 if not in the list, and the index if it is in the list.
17     connect(this, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
18             [=](double d){ m_idx = m_Values.indexOf(d); });
19 }
20 
stepBy(int steps)21 void NonLinearDoubleSpinBox::stepBy(int steps)
22 {
23     // If the current value is not currently in the list, it will find where the value falls in the list and set it to the
24     // appropriate one whether going up or down.
25     if(m_idx == -1)
26     {
27         int i = 0;
28         while(value() > m_Values.at(i))
29             i++;
30         if(steps > 0 )
31             m_idx = i;
32         else
33             m_idx = i - 1;
34     }
35     else
36         m_idx += steps;
37 
38     //This makes sure that it doesn't go past the ends of the list.
39     if(m_idx<0)
40         m_idx=0;
41     else if(m_idx >= m_Values.count())
42         m_idx = m_Values.count()-1;
43 
44     //This sets the value to the value at that index in the list.
45     setValue( m_Values.at(m_idx) );
46 }
47 
setRecommendedValues(QList<double> values)48 void NonLinearDoubleSpinBox::setRecommendedValues(QList<double> values)
49 {
50     m_Values = values;
51     updateRecommendedValues();
52 }
53 
addRecommendedValue(double v)54 void NonLinearDoubleSpinBox::addRecommendedValue(double v)
55 {
56     m_Values.append(v);  //This will be sorted into place in the next command.
57     updateRecommendedValues();
58 }
59 
updateRecommendedValues()60 void NonLinearDoubleSpinBox::updateRecommendedValues()
61 {
62     std::sort(m_Values.begin(), m_Values.end());  //This will make sure they are all in order.
63     m_idx = m_Values.indexOf(value());  //This will update the _idx variable to the index of the new value.  It will search for current value in the new list or set it to negative 1 if it isn't in the list.
64     setRange(m_Values.first() , m_Values.last());
65     //This makes sure all the values are in the range.  The range is expanded if necessary.
66     if(m_Values.first() < minimum())
67         setMinimum(m_Values.first());
68     if(m_Values.last() > maximum())
69         setMaximum(m_Values.last());
70 }
71 
getRecommendedValues()72 QList<double> NonLinearDoubleSpinBox::getRecommendedValues()
73 {
74     return m_Values;
75 }
76 
getRecommendedValuesString()77 QString NonLinearDoubleSpinBox::getRecommendedValuesString()
78 {
79     QString returnString;
80     for(int i=0; i < m_Values.size() - 1; i++)
81         returnString += QString::number(m_Values.at(i)) + ", ";
82     returnString += QString::number(m_Values.last());
83     return returnString;
84 }
85