dtkWidgetsSpinBoxDouble.cpp 5.32 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Version: $Id$
//
//

// Commentary:
//
//

// Change Log:
//
//

// Code:

15
#include "dtkWidgetsSpinBoxDouble.h"
16

17
class dtkWidgetsSpinBoxDoublePrivate : public QObject
18
{
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
19 20 21 22 23 24
    Q_OBJECT

public slots:
    void update();
    void touch();

25
public:
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
26 27
    double            value;

28 29
    QDoubleValidator *validator;
    bool              scientific;
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
30 31 32
    int               decimals;
    double            minimum;
    double            maximum;
33

SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
34 35 36
public:
    QString textFromValue ( double ) const;
    double  valueFromText ( const QString& ) const;
37

SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
38
    QValidator::State validate(QString&, int&) const;
39 40


SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
41
public:
42
    dtkWidgetsSpinBoxDouble *q;
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
43 44
};

45
void dtkWidgetsSpinBoxDoublePrivate::update(void)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
46 47 48
{
    this->value = valueFromText( q->text());
    this->touch();
49 50
}

51
void dtkWidgetsSpinBoxDoublePrivate::touch()
52
{
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
53
    q->emit valueChanged(this->value);
54 55
}

56
QString dtkWidgetsSpinBoxDoublePrivate::textFromValue ( double value ) const
57 58
{
    QString strValue;
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
59 60 61 62 63 64 65

    if (value < this->minimum)
        value = this->minimum;

    if (value > this->maximum)
        value = this->maximum;

SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
66 67
    if (this->scientific)
        strValue = QString::number(value, 'e', this->decimals);
68
    else
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
69
        strValue = QString::number(value, 'f', this->decimals);
70 71 72 73

    return strValue;
}

74
double dtkWidgetsSpinBoxDoublePrivate::valueFromText ( const QString & text ) const
75
{
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    // truncate the input text to the right decimal
    QString work_on = text;

    QStringList mant_exp;
    if ( this->scientific ) { // split mantisse + exp
        mant_exp = text.split(QRegExp("e"));
        work_on = mant_exp[0];
    }

    QStringList int_dec;
    int_dec = work_on.split(QRegExp("\\."));

    // truncate decimals
    if (int_dec.size() > 1) {
        if ( int_dec[1].length() > this->decimals) {
            int_dec[1] = int_dec[1].left(this->decimals);
        }
    }

    QString result = int_dec[0] + "." + int_dec[1];
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
96 97 98 99 100 101 102
    if ( this->scientific ) {
        if (mant_exp.size() > 1) {
            result += "e" + mant_exp[1];
        }
        else {
            result += "e+0" ;
        }
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
103
    }
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
104

SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
105
    double dblValue = result.toDouble();
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
106 107 108 109 110 111 112

    // check min/max ? What if decimals or min and max are inadequate ?
    if (dblValue < this->minimum)
        dblValue = this->minimum;
    if (dblValue > this->maximum)
        dblValue = this->maximum;

SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
113 114 115 116
    //q->lineEdit()->blockSignals(true);  // protected !!
    //q->lineEdit()->setText(result);
    //q->lineEdit()->blockSignals(false);
    q->setValue(dblValue);
117 118 119
    return dblValue;
}

120
QValidator::State dtkWidgetsSpinBoxDoublePrivate::validate(QString &text, int &pos) const
121 122 123 124 125 126 127
{
    // check user input
    bool input_check;
    text.toDouble(&input_check);

    return (input_check ? QValidator::Acceptable : QValidator::Invalid);
}
128

SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
129 130 131

///

132
dtkWidgetsSpinBoxDouble::dtkWidgetsSpinBoxDouble(QDoubleValidator::Notation notation, QWidget *parent) : QAbstractSpinBox(parent)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
133
{
134
    d = new dtkWidgetsSpinBoxDoublePrivate;
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    d->q = this;

    this->setLocale(QLocale::C);

    d->value = 0.0;

    d->validator = new QDoubleValidator();
    d->validator->setNotation(notation);

    d->scientific = ( notation == QDoubleValidator::ScientificNotation);

    //this->setMaximum(std::numeric_limits<double>::max());    // instead of default 99.99
    //this->setMaximum(std::numeric_limits<double>::lowest());
    //this->setDecimals(32);
    d->maximum = std::numeric_limits<double>::max();    // instead of default 99.99
    d->minimum = std::numeric_limits<double>::lowest();
    d->decimals = 32;

    this->setReadOnly(false);
    this->setButtonSymbols(QAbstractSpinBox::PlusMinus);
    this->setCorrectionMode(QAbstractSpinBox::CorrectToPreviousValue);
    this->setKeyboardTracking(true);
    this->lineEdit()->setValidator(d->validator);
    this->lineEdit()->setReadOnly(false);

    connect(this,
            SIGNAL(editingFinished()),
            d,
            SLOT(update()));

}

167
dtkWidgetsSpinBoxDouble::~dtkWidgetsSpinBoxDouble(void)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
168 169 170 171 172
{
    delete d->validator;
    delete d;
}

173
void dtkWidgetsSpinBoxDouble::stepBy(int step)
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
{
    if (step == 0 ) {
        return;
    }
    if (step < 0) {
        int i = step;
        while ( i < 0 ) {
            stepDown();
            i++;
        }
    }
    else  {
        int i = step;
        while ( i > 0) {
            stepUp();
            i--;
        }
    }
}

194
void dtkWidgetsSpinBoxDouble::stepDown(void)
195 196
{
    if (d->scientific)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
197
        d->value /= 10.0;
198
    else
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
199 200 201
        d->value -= 1.0;

    d->touch();
202 203
}

204
void dtkWidgetsSpinBoxDouble::stepUp(void)
205 206
{
    if (d->scientific)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
207
        d->value *= 10.0;
208
    else
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
209 210 211 212 213 214
        d->value += 1.0;

    d->touch();
}


215
void dtkWidgetsSpinBoxDouble::setMinimum(double min)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
216 217 218 219
{
    d->minimum = min;
}

220
void dtkWidgetsSpinBoxDouble::setMaximum(double max)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
221 222 223 224
{
    d->maximum = max;
}

225
void dtkWidgetsSpinBoxDouble::setValue(double val)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
226 227 228 229 230
{
    d->value = val;
    this->lineEdit()->blockSignals(true);
    this->lineEdit()->setText(d->textFromValue(val));
    this->lineEdit()->blockSignals(false);
231
}
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
232

233
void dtkWidgetsSpinBoxDouble::setDecimals(int dec)
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
234 235 236 237 238
{
    d->decimals = dec;
    this->setValue(d->value);  // muste change the text in the widget accordingly
}

239
QAbstractSpinBox::StepEnabled dtkWidgetsSpinBoxDouble::stepEnabled(void) const
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
240 241 242 243 244
{
    return ( QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled ) ;
}


245
#include "dtkWidgetsSpinBoxDouble.moc"
SZPYRKA Jean-Luc's avatar
SZPYRKA Jean-Luc committed
246

247
//
248
// dtkWidgetsSpinBoxDouble.h ends here