Commit 8b0c40cbe0a30242ec6178a52056c8220cf7bb1a
1 parent
63d52619
Add missing SiSpinBox sources
Showing
2 changed files
with
251 additions
and
0 deletions
openhantek/src/sispinbox.cpp
0 → 100644
| 1 | +//////////////////////////////////////////////////////////////////////////////// | ||
| 2 | +// | ||
| 3 | +// OpenHantek | ||
| 4 | +// sispinbox.cpp | ||
| 5 | +// | ||
| 6 | +// Copyright (C) 2012 Oliver Haag | ||
| 7 | +// oliver.haag@gmail.com | ||
| 8 | +// | ||
| 9 | +// This program is free software: you can redistribute it and/or modify it | ||
| 10 | +// under the terms of the GNU General Public License as published by the Free | ||
| 11 | +// Software Foundation, either version 3 of the License, or (at your option) | ||
| 12 | +// any later version. | ||
| 13 | +// | ||
| 14 | +// This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 15 | +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 16 | +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 17 | +// more details. | ||
| 18 | +// | ||
| 19 | +// You should have received a copy of the GNU General Public License along with | ||
| 20 | +// this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 21 | +// | ||
| 22 | +//////////////////////////////////////////////////////////////////////////////// | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +#include <cfloat> | ||
| 26 | +#include <cmath> | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +#include "sispinbox.h" | ||
| 30 | + | ||
| 31 | +#include "helper.h" | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +//////////////////////////////////////////////////////////////////////////////// | ||
| 35 | +// class OpenHantekMainWindow | ||
| 36 | +/// \brief Initializes the SiSpinBox internals. | ||
| 37 | +/// \param parent The parent widget. | ||
| 38 | +SiSpinBox::SiSpinBox(QWidget *parent) : QDoubleSpinBox(parent) { | ||
| 39 | + this->init(); | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +/// \brief Initializes the SiSpinBox, allowing the user to choose the unit. | ||
| 43 | +/// \param unit The unit shown for the value in the spin box. | ||
| 44 | +/// \param parent The parent widget. | ||
| 45 | +SiSpinBox::SiSpinBox(Helper::Unit unit, QWidget *parent) : QDoubleSpinBox(parent) { | ||
| 46 | + this->init(); | ||
| 47 | + | ||
| 48 | + this->setUnit(unit); | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +/// \brief Cleans up the main window. | ||
| 52 | +SiSpinBox::~SiSpinBox() { | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +/// \brief Validates the text after user input. | ||
| 56 | +/// \param input The content of the text box. | ||
| 57 | +/// \param pos The position of the cursor in the text box. | ||
| 58 | +/// \return Validity of the current text. | ||
| 59 | +QValidator::State SiSpinBox::validate(QString &input, int &pos) const { | ||
| 60 | + Q_UNUSED(pos); | ||
| 61 | + | ||
| 62 | + bool ok; | ||
| 63 | + double value = Helper::stringToValue(input, this->unit, &ok); | ||
| 64 | + | ||
| 65 | + if(!ok) | ||
| 66 | + return QValidator::Invalid; | ||
| 67 | + | ||
| 68 | + if(input == this->textFromValue(value)) | ||
| 69 | + return QValidator::Acceptable; | ||
| 70 | + return QValidator::Intermediate; | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | +/// \brief Parse value from input text. | ||
| 74 | +/// \param text The content of the text box. | ||
| 75 | +/// \return Value in base unit. | ||
| 76 | +double SiSpinBox::valueFromText(const QString &text) const { | ||
| 77 | + return Helper::stringToValue(text, this->unit); | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +/// \brief Get string representation of value. | ||
| 81 | +/// \param val Value in base unit. | ||
| 82 | +/// \return String representation containing value and (prefix+)unit. | ||
| 83 | +QString SiSpinBox::textFromValue(double val) const { | ||
| 84 | + return Helper::valueToString(val, this->unit, -1) + this->unitPostfix; | ||
| 85 | +} | ||
| 86 | + | ||
| 87 | +/// \brief Fixes the text after the user finished changing it. | ||
| 88 | +/// \param input The content of the text box. | ||
| 89 | +void SiSpinBox::fixup(QString &input) const { | ||
| 90 | + bool ok; | ||
| 91 | + double value = Helper::stringToValue(input, this->unit, &ok); | ||
| 92 | + | ||
| 93 | + if(!ok) | ||
| 94 | + value = this->value(); | ||
| 95 | + | ||
| 96 | + input = this->textFromValue(value); | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +/// \brief Increase/decrease the values in fixed steps. | ||
| 100 | +/// \param steps The number of steps, positive means increase. | ||
| 101 | +void SiSpinBox::stepBy(int steps) { | ||
| 102 | + double stepsSpan = this->steps.last() / this->steps.first(); | ||
| 103 | + int stepsCount = this->steps.size() - 1; | ||
| 104 | + | ||
| 105 | + if(!this->steppedTo) { // No step done directly before this one, so we need to check where we are | ||
| 106 | + // Get how often the steps have to be fully ran through | ||
| 107 | + int stepsFully = (int) floor(log(this->value() / this->steps.first()) / log(stepsSpan)); | ||
| 108 | + // And now the remaining multiple | ||
| 109 | + double stepMultiple = this->value() / pow(stepsSpan, stepsFully); | ||
| 110 | + // Now get the neighbours of the current value from our steps list | ||
| 111 | + int remainingSteps = 0; | ||
| 112 | + for(; remainingSteps <= stepsCount; ++remainingSteps) { | ||
| 113 | + if(this->steps[remainingSteps] > stepMultiple) | ||
| 114 | + break; | ||
| 115 | + } | ||
| 116 | + if(remainingSteps > 0) // Shouldn't happen, but double may have rounding errors | ||
| 117 | + --remainingSteps; | ||
| 118 | + this->stepId = stepsFully * stepsCount + remainingSteps; | ||
| 119 | + // We need to do one step less down if we are inbetween two of them since our step is lower than the value | ||
| 120 | + if(steps < 0 && this->steps[remainingSteps] < stepMultiple) | ||
| 121 | + ++this->stepId; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + this->stepId += steps; | ||
| 125 | + int stepsId = this->stepId % stepsCount; | ||
| 126 | + if(stepsId < 0) | ||
| 127 | + stepsId += stepsCount; | ||
| 128 | + double value = pow(stepsSpan, floor((double) this->stepId / stepsCount)) * this->steps[stepsId]; | ||
| 129 | + this->setValue(value); | ||
| 130 | + value = this->value(); | ||
| 131 | + this->steppedTo = true; | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +/// \brief Set the unit for this spin box. | ||
| 135 | +/// \param unit The unit shown for the value in the spin box. | ||
| 136 | +/// \return true on success, false on invalid unit. | ||
| 137 | +bool SiSpinBox::setUnit(Helper::Unit unit) { | ||
| 138 | + if((unsigned int) unit >= Helper::UNIT_COUNT) | ||
| 139 | + return false; | ||
| 140 | + | ||
| 141 | + this->unit = unit; | ||
| 142 | + return true; | ||
| 143 | +} | ||
| 144 | + | ||
| 145 | +/// \brief Set the unit postfix for this spin box. | ||
| 146 | +/// \param postfix the string shown after the unit in the spin box. | ||
| 147 | +void SiSpinBox::setUnitPostfix(const QString &postfix) { | ||
| 148 | + this->unitPostfix = postfix; | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +/// \brief Set the steps the spin box will take. | ||
| 152 | +/// \param steps The steps, will be extended with the ratio from the start after the last element. | ||
| 153 | +void SiSpinBox::setSteps(const QList<double> &steps) { | ||
| 154 | + this->steps = steps; | ||
| 155 | +} | ||
| 156 | + | ||
| 157 | +/// \brief Generic initializations. | ||
| 158 | +void SiSpinBox::init() { | ||
| 159 | + this->setMinimum(1e-12); | ||
| 160 | + this->setMaximum(1e12); | ||
| 161 | + this->setValue(1.0); | ||
| 162 | + this->setDecimals(DBL_MAX_10_EXP + DBL_DIG); // Disable automatic rounding | ||
| 163 | + this->unit = unit; | ||
| 164 | + this->steps << 1.0 << 2.0 << 5.0 << 10.0; | ||
| 165 | + | ||
| 166 | + this->steppedTo = false; | ||
| 167 | + this->stepId = 0; | ||
| 168 | + | ||
| 169 | + connect(this, SIGNAL(valueChanged(double)), this, SLOT(resetSteppedTo())); | ||
| 170 | +} | ||
| 171 | + | ||
| 172 | +/// \brief Resets the ::steppedTo flag after the value has been changed. | ||
| 173 | +void SiSpinBox::resetSteppedTo() { | ||
| 174 | + this->steppedTo = false; | ||
| 175 | +} |
openhantek/src/sispinbox.h
0 → 100644
| 1 | +//////////////////////////////////////////////////////////////////////////////// | ||
| 2 | +// | ||
| 3 | +// OpenHantek | ||
| 4 | +/// \file sispinbox.h | ||
| 5 | +/// \brief Declares the SiSpinBox class. | ||
| 6 | +// | ||
| 7 | +// Copyright (C) 2010, 2011 Oliver Haag | ||
| 8 | +// oliver.haag@gmail.com | ||
| 9 | +// | ||
| 10 | +// This program is free software: you can redistribute it and/or modify it | ||
| 11 | +// under the terms of the GNU General Public License as published by the Free | ||
| 12 | +// Software Foundation, either version 3 of the License, or (at your option) | ||
| 13 | +// any later version. | ||
| 14 | +// | ||
| 15 | +// This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 16 | +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 17 | +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 18 | +// more details. | ||
| 19 | +// | ||
| 20 | +// You should have received a copy of the GNU General Public License along with | ||
| 21 | +// this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 22 | +// | ||
| 23 | +//////////////////////////////////////////////////////////////////////////////// | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +#ifndef SISPINBOX_H | ||
| 27 | +#define SISPINBOX_H | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +#include <QDoubleSpinBox> | ||
| 31 | +#include <QStringList> | ||
| 32 | + | ||
| 33 | +#include "helper.h" | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +//////////////////////////////////////////////////////////////////////////////// | ||
| 37 | +/// \class SiSpinBox sispinbox.h | ||
| 38 | +/// \brief A spin box with SI prefix support. | ||
| 39 | +/// This spin box supports the SI prefixes (k/M/G/T) after its value and allows | ||
| 40 | +/// floating point values. The step size is increasing in an exponential way, to | ||
| 41 | +/// keep the percentual difference between the steps at equal levels. | ||
| 42 | +class SiSpinBox : public QDoubleSpinBox | ||
| 43 | +{ | ||
| 44 | + Q_OBJECT | ||
| 45 | + | ||
| 46 | + public: | ||
| 47 | + explicit SiSpinBox(QWidget *parent = 0); | ||
| 48 | + SiSpinBox(Helper::Unit unit, QWidget *parent = 0); | ||
| 49 | + ~SiSpinBox(); | ||
| 50 | + | ||
| 51 | + QValidator::State validate(QString &input, int &pos) const; | ||
| 52 | + double valueFromText(const QString &text) const; | ||
| 53 | + QString textFromValue(double val) const; | ||
| 54 | + void fixup(QString &input) const; | ||
| 55 | + void stepBy(int steps); | ||
| 56 | + bool setUnit(Helper::Unit unit); | ||
| 57 | + void setUnitPostfix(const QString &postfix); | ||
| 58 | + void setSteps(const QList<double> &steps); | ||
| 59 | + | ||
| 60 | + private: | ||
| 61 | + void init(); | ||
| 62 | + | ||
| 63 | + Helper::Unit unit; ///< The SI unit used for this spin box | ||
| 64 | + QString unitPostfix; ///< Shown after the unit | ||
| 65 | + QList<double> steps; ///< The steps, begins from start after last element | ||
| 66 | + | ||
| 67 | + bool steppedTo; ///< true, if the current value was reached using stepBy | ||
| 68 | + int stepId; ///< The index of the last step reached using stepBy | ||
| 69 | + | ||
| 70 | + signals: | ||
| 71 | + | ||
| 72 | + private slots: | ||
| 73 | + void resetSteppedTo(); | ||
| 74 | +}; | ||
| 75 | + | ||
| 76 | +#endif |