/***************************************************************************
 *   Copyright (C) 2003-2006 by David Saxton                               *
 *   david@bluehaze.org                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#ifndef DOUBLESPINBOX_H
#define DOUBLESPINBOX_H

#include <QDoubleSpinBox>

/**
Where appropriate, function names with value in them should
be prefixed with "real" - e.g. realValue() - to get the value stored in the
spin box plus the SI magnitude symbol it is showing

@author David Saxton
*/
class DoubleSpinBox : public QDoubleSpinBox
{
    Q_OBJECT
public:
    DoubleSpinBox(double lower, double upper, double minAbs, double value, const QString &unit, QWidget *parent = nullptr);
    DoubleSpinBox(QWidget *parent = nullptr);
    ~DoubleSpinBox() override;

    /**
     * The minimum value is the lowest number that the user can enter.
     */
    // 		double minValue() const { return m_minValue; }
    /**
     * @see minValue
     */
    // 		void setMinValue( double minValue ) { m_minValue = minValue; }
    /**
     * The minimum value is the lowest number that the user can enter.
     */
    // 		void setMinValue( int minValue ) { m_minValue = minValue; }
    /**
     * The maximum value is the highest number that the user can enter.
     */
    // 		double maxValue() const { return m_maxValue; }
    /**
     * @see maxValue
     */
    // 		void setMaxValue( double maxValue ) { m_maxValue = maxValue; }
    /**
     * @see maxValue
     */
    // 		void setMaxValue( int maxValue ) { m_maxValue = maxValue; }
    /**
     * The minimum absolute value is the smallest value that the user can
     * enter before the value is considered 0.
     */
    void setMinAbsValue(double minAbsValue)
    {
        m_minAbsValue = minAbsValue;
    }
    /**
     * The actual value that the user has entered - e.g. if the spinbox
     * displays "100 kF", then the value returned will be 1e5.
     */
    // 		double value();
    /**
     * Sets the unit used, e.g. "F"
     */
    // 		void setUnit( const QString & unit );

    QValidator::State validate(QString &text, int &pos) const override;

public slots:
    // 		virtual void stepUp(); // QDoubleSpinBox has these
    // 		virtual void stepDown();
    /**
     * Set the value to be displayed - e.g. if value is 1e5, then the
     * spinbox might display "100 kF".
     */
    // 		void setValue( double value );

signals:
    /**
     * This value is emitted whenever the value of the spinbox changes.
     */
    // 		void valueChanged( double value ); // exists in QDoubleSpinBox

protected slots:
    /**
     * Checks if the value has changed - and if so, emits a valueChanged
     * signal.
     */
    // 		void checkIfChanged(double value);
    /**
     * Sets the suffix from m_queuedSuffix. Called from QTimer::singleShot
     * to avoid strange recursion problems.
     */
    // 		void setQueuedSuffix();

protected:
    /**
     * make Qt enable the up/down step arrows
     */
    StepEnabled stepEnabled() const override;
    /**
     * Change the value of the spin box, because of user interaction
     */
    void stepBy(int steps) override;

    double getNextUpStepValue(double in);
    double getNextDownStepValue(double in);

    /**
     * Updates the suffix using m_unit and value.
     */
    void updateSuffix(double value);
    /**
     * Returns the multiplication number from what is displayed
     * in the box, e.g. "10 kV" will return "1000" due to the letter "k" presence
     */
    // 		double getMult();
    /**
     * Returns the number currently displayed in the spin box.
     */
    // 		double getDisplayedNumber( bool * ok );
    /**
     *  Overloaded the method in QSpinxBox to allow SI prefixes to be entered
     */
    // 		virtual int mapTextToValue( bool * ok );
    double valueFromText(const QString &text) const override;
    /**
     *  Overloaded the method in QSpinxBox to allow SI prefixes to be entered
     */
    // 		virtual QString mapValueToText( int v );
    QString textFromValue(double value) const override;
    /**
     * Returns value rounded off to one significant figure.
     */
    static double roundToOneSF(double value);

    void init();

    // 		QString m_queuedSuffix; ///< Used
    QString m_unit;
    // 		double m_minValue;
    // 		double m_maxValue;
    double m_minAbsValue;
    double m_lastEmittedValue;
};

#endif
