File indexing completed on 2024-05-12 03:48:29

0001 /*
0002     File                 : NumberSpinBox.h
0003     Project              : LabPlot
0004     Description          : widget for setting numbers with a spinbox
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2022 Martin Marmsoler <martin.marmsoler@gmail.com>
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #ifndef NUMBERSPINBOX_H
0010 #define NUMBERSPINBOX_H
0011 
0012 #include <QDoubleSpinBox>
0013 
0014 class NumberSpinBox : public QDoubleSpinBox {
0015     Q_OBJECT
0016 
0017 public:
0018     struct NumberProperties {
0019         QChar integerSign;
0020         bool groupSeparators;
0021         int integer;
0022         int intergerDigits;
0023 
0024         bool fraction; // 5. is a valid number, so just setting fractionDigits to 0 is not correct
0025         int fractionPos;
0026         int fractionDigits;
0027 
0028         QChar exponentLetter;
0029         int exponentPos;
0030         QChar exponentSign;
0031         int exponent;
0032         int exponentDigits;
0033     };
0034 
0035     enum class Errors {
0036         NoError,
0037         NoNumber,
0038         Invalid,
0039         Min, // value smaller than min
0040         Max, // value larger than max
0041     };
0042 
0043     Q_PROPERTY(bool feedback READ feedback WRITE setFeedback NOTIFY feedbackChanged)
0044 
0045 public:
0046     explicit NumberSpinBox(QWidget* parent = nullptr);
0047     explicit NumberSpinBox(double initValue, QWidget* parent = nullptr);
0048     explicit NumberSpinBox(double initValue, bool feedback, QWidget* parent = nullptr);
0049     QString errorToString(Errors);
0050     bool setValue(double);
0051     void setFeedback(bool enable);
0052     bool feedback();
0053     void setStrongFocus(bool);
0054     double value();
0055     void setClearButtonEnabled(bool);
0056     double minimum() const;
0057     void setMinimum(double min);
0058     double maximum() const;
0059     void setMaximum(double max);
0060 
0061 Q_SIGNALS:
0062     void valueChanged(double);
0063     void feedbackChanged(bool);
0064 
0065 private:
0066     void init(double initValue, bool feedback);
0067     void keyPressEvent(QKeyEvent*) override;
0068     void wheelEvent(QWheelEvent* event) override;
0069     void setInvalid(Errors e);
0070     void setInvalid(const QString& str);
0071     bool properties(const QString& value, NumberProperties& p) const;
0072     QString createStringNumber(double integerFraction, int exponent, const NumberProperties&) const;
0073     void stepBy(int steps) override;
0074     Errors step(int steps);
0075     QString strip(const QString& t) const;
0076     virtual QString textFromValue(double value) const override;
0077     virtual double valueFromText(const QString&) const override;
0078     QAbstractSpinBox::StepEnabled stepEnabled() const override;
0079     virtual QValidator::State validate(QString& input, int& pos) const override;
0080     Errors validate(QString& input, double& value, QString& valueStr) const;
0081     void setText(const QString&);
0082 
0083     void increaseValue();
0084     void decreaseValue();
0085     void valueChanged();
0086 
0087 private:
0088     QString m_valueStr;
0089     // See https://invent.kde.org/education/labplot/-/merge_requests/167
0090     // for explanation of the feature
0091     bool m_feedback{true}; // defines if the spinbox expects a feedback
0092     bool m_waitFeedback{false};
0093 
0094     bool m_strongFocus{true};
0095 
0096     // The value stored in QAbstractSpinBox is rounded to
0097     // decimals and this is not desired
0098     double m_value{0};
0099     double m_maximum{std::numeric_limits<double>::max()};
0100     double m_minimum{std::numeric_limits<double>::lowest()};
0101 
0102     friend class SpinBoxTest;
0103 };
0104 
0105 #endif // NUMBERSPINBOX_H