Krita Source Code Documentation
Loading...
Searching...
No Matches
KoUnitDoubleSpinBox.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2002 Rob Buis (buis@kde.org)
3 SPDX-FileCopyrightText: 2004 Nicolas GOUTTE <goutte@kde.org>
4 SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
10
11#include <KoUnit.h>
12
13#include <QRegExp>
14
15#include <WidgetsDebug.h>
16
17#include <klocalizedstring.h>
18#include <qnumeric.h>
19
20// #define DEBUG_VALIDATOR
21// #define DEBUG_VALUEFROMTEXT
22
23class Q_DECL_HIDDEN KoUnitDoubleSpinBox::Private
24{
25public:
26 Private(double low, double up, double step)
27 : lowerInPoints(low),
28 upperInPoints(up),
29 stepInPoints(step),
30 unit(KoUnit(KoUnit::Point))
31 {
32 }
33
36 double stepInPoints;
38};
39
41 : QDoubleSpinBox( parent ),
42 d( new Private(-9999, 9999, 1))
43{
44 QDoubleSpinBox::setDecimals( 2 );
45 //setAcceptLocalizedNumbers( true );
47 setAlignment( Qt::AlignRight );
48
49 connect(this, SIGNAL(valueChanged(double)), SLOT(privateValueChanged()));
50}
51
56
57QValidator::State KoUnitDoubleSpinBox::validate(QString &input, int &pos) const
58{
59#ifdef DEBUG_VALIDATOR
60 debugWidgets <<"KoUnitDoubleSpinBox::validate :" << input <<" at" << pos;
61#else
62 Q_UNUSED(pos);
63#endif
64
65 QRegExp regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end
66 const int res = regexp.indexIn(input);
67
68 if ( res == -1 )
69 {
70 // Nothing like an unit? The user is probably editing the unit
71#ifdef DEBUG_VALIDATOR
72 debugWidgets <<"Intermediate (no unit)";
73#endif
74 return QValidator::Intermediate;
75 }
76
77 // ### TODO: are all the QString::trimmed really necessary?
78 const QString number ( input.left( res ).trimmed() );
79 const QString unitName ( regexp.cap( 1 ).trimmed().toLower() );
80
81#ifdef DEBUG_VALIDATOR
82 debugWidgets <<"Split:" << number <<":" << unitName <<":";
83#endif
84
85 const double value = valueFromText( number );
86 double newVal = 0.0;
87 if (!qIsNaN(value)) {
88 bool ok;
89 const KoUnit unit = KoUnit::fromSymbol(unitName, &ok);
90 if ( ok )
91 newVal = unit.fromUserValue( value );
92 else
93 {
94 // Probably the user is trying to edit the unit
95#ifdef DEBUG_VALIDATOR
96 debugWidgets <<"Intermediate (unknown unit)";
97#endif
98 return QValidator::Intermediate;
99 }
100 }
101 else
102 {
103 warnWidgets << "Not a number: " << number;
104 return QValidator::Invalid;
105 }
106 newVal = d->unit.toUserValuePrecise(newVal);
107 //input = textFromValue( newVal ); // don't overwrite for now; the effect is not exactly what I expect...
108
109 return QValidator::Acceptable;
110}
111
113{
114 QDoubleSpinBox::setValue( d->unit.toUserValue( val ) );
115 // TODO: Q_EMIT valueChanged ONLY if the value was out-of-bounds
116 // This will allow the 'user' dialog to set a dirty bool and ensure
117 // a proper value is getting saved.
118}
119
123
125{
126 if (unit == d->unit) return;
127
128 double oldvalue = d->unit.fromUserValue( QDoubleSpinBox::value() );
129 QDoubleSpinBox::setMinimum( unit.toUserValue( d->lowerInPoints ) );
130 QDoubleSpinBox::setMaximum( unit.toUserValue( d->upperInPoints ) );
131
132 qreal step = unit.toUserValue( d->stepInPoints );
133
134 if (unit.type() == KoUnit::Pixel) {
135 // limit the pixel step by 1.0
136 step = qMax(qreal(1.0), step);
137 }
138
139 QDoubleSpinBox::setSingleStep( step );
140 d->unit = unit;
141 QDoubleSpinBox::setValue(unit.toUserValuePrecise(oldvalue));
142 setSuffix(unit.symbol().prepend(QLatin1Char(' ')));
143}
144
146{
147 return d->unit.fromUserValue( QDoubleSpinBox::value() );
148}
149
151{
152 d->lowerInPoints = min;
153 QDoubleSpinBox::setMinimum( d->unit.toUserValue( min ) );
154}
155
157{
158 d->upperInPoints = max;
159 QDoubleSpinBox::setMaximum( d->unit.toUserValue( max ) );
160}
161
163{
164 d->stepInPoints = KoUnit(KoUnit::Point).toUserValue(step);
165 QDoubleSpinBox::setSingleStep( step );
166}
167
169{
170 d->stepInPoints = step;
171 QDoubleSpinBox::setSingleStep( d->unit.toUserValue( step ) );
172}
173
174void KoUnitDoubleSpinBox::setMinMaxStep( double min, double max, double step )
175{
176 setMinimum( min );
177 setMaximum( max );
178 setLineStepPt( step );
179}
180
182{
183 //debugWidgets <<"textFromValue:" << QString::number( value, 'f', 12 ) <<" =>" << num;
184 //const QString num(QString("%1%2").arg(QLocale().toString(value, d->precision ), m_unit.symbol()));
185 //const QString num ( QString( "%1").arg( QLocale().toString( value, d->precision )) );
186 return QLocale().toString( value, 'f', decimals() );
187}
188
189double KoUnitDoubleSpinBox::valueFromText( const QString& str ) const
190{
191 QString str2( str );
192 str2.remove(d->unit.symbol());
193 return QLocale().toDouble(str2);
194// QString str2( str );
195// /* KLocale::readNumber wants the thousand separator exactly at 1000.
196// But when editing, it might be anywhere. So we need to remove it. */
197// const QString sep( KGlobal::locale()->thousandsSeparator() );
198// if ( !sep.isEmpty() )
199// str2.remove( sep );
200// str2.remove(d->unit.symbol());
201// bool ok;
202// const double dbl = KGlobal::locale()->readNumber( str2, &ok );
203//#ifdef DEBUG_VALUEFROMTEXT
204// if ( ok )
205// debugWidgets <<"valueFromText:" << str <<": => :" << str2 <<": =>" << QString::number( dbl, 'f', 12 );
206// else
207// warnWidgets << "valueFromText error:" << str << ": => :" << str2 << ":";
208//#endif
209// return dbl;
210}
float value(const T *src, size_t ch)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
#define warnWidgets
#define debugWidgets
double stepInPoints
step in points
QString textFromValue(double value) const override
virtual void changeValue(double newValue)
void setLineStep(double step)
Set step size in the current unit.
Private(double low, double up, double step)
virtual void setUnit(const KoUnit &)
void valueChangedPt(qreal)
emitted like valueChanged in the parent, but this one emits the point value
double valueFromText(const QString &str) const override
double lowerInPoints
lowest value in points
double upperInPoints
highest value in points
void setMaximum(double max)
Set maximum value in points.
QValidator::State validate(QString &input, int &pos) const override
reimplemented from superclass, will forward to KoUnitDoubleValidator
void setMinMaxStep(double min, double max, double step)
Set minimum, maximum value and the step size (all in points)
KoUnitDoubleSpinBox(QWidget *parent=0)
void setLineStepPt(double step)
Set step size in points.
void setMinimum(double min)
Set minimum value in points.
qreal fromUserValue(qreal value) const
Definition KoUnit.cpp:201
KoUnit::Type type() const
Definition KoUnit.h:118
qreal toUserValuePrecise(const qreal ptValue) const
Definition KoUnit.cpp:161
static KoUnit fromSymbol(const QString &symbol, bool *ok=0)
Definition KoUnit.cpp:271
QString symbol() const
Get the symbol string of the unit.
Definition KoUnit.cpp:347
@ Point
Postscript point, 1/72th of an Inco.
Definition KoUnit.h:76
@ Pixel
Definition KoUnit.h:82
qreal toUserValue(qreal ptValue, bool rounding=true) const
Definition KoUnit.cpp:186