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 | ... | ... |