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 <QRegularExpression>
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 QRegularExpression regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end
66 QRegularExpressionMatch match;
67 const int res = input.indexOf(regexp, 0, &match);
68
69 if ( res == -1 )
70 {
71 // Nothing like an unit? The user is probably editing the unit
72#ifdef DEBUG_VALIDATOR
73 debugWidgets <<"Intermediate (no unit)";
74#endif
75 return QValidator::Intermediate;
76 }
77
78 // ### TODO: are all the QString::trimmed really necessary?
79 const QString number ( input.left( res ).trimmed() );
80 const QString unitName ( match.captured( 1 ).trimmed().toLower() );
81
82#ifdef DEBUG_VALIDATOR
83 debugWidgets <<"Split:" << number <<":" << unitName <<":";
84#endif
85
86 const double value = valueFromText( number );
87 double newVal = 0.0;
88 if (!qIsNaN(value)) {
89 bool ok;
90 const KoUnit unit = KoUnit::fromSymbol(unitName, &ok);
91 if ( ok )
92 newVal = unit.fromUserValue( value );
93 else
94 {
95 // Probably the user is trying to edit the unit
96#ifdef DEBUG_VALIDATOR
97 debugWidgets <<"Intermediate (unknown unit)";
98#endif
99 return QValidator::Intermediate;
100 }
101 }
102 else
103 {
104 warnWidgets << "Not a number: " << number;
105 return QValidator::Invalid;
106 }
107 newVal = d->unit.toUserValuePrecise(newVal);
108 //input = textFromValue( newVal ); // don't overwrite for now; the effect is not exactly what I expect...
109
110 return QValidator::Acceptable;
111}
112
114{
115 QDoubleSpinBox::setValue( d->unit.toUserValue( val ) );
116 // TODO: Q_EMIT valueChanged ONLY if the value was out-of-bounds
117 // This will allow the 'user' dialog to set a dirty bool and ensure
118 // a proper value is getting saved.
119}
120
124
126{
127 if (unit == d->unit) return;
128
129 double oldvalue = d->unit.fromUserValue( QDoubleSpinBox::value() );
130 QDoubleSpinBox::setMinimum( unit.toUserValue( d->lowerInPoints ) );
131 QDoubleSpinBox::setMaximum( unit.toUserValue( d->upperInPoints ) );
132
133 qreal step = unit.toUserValue( d->stepInPoints );
134
135 if (unit.type() == KoUnit::Pixel) {
136 // limit the pixel step by 1.0
137 step = qMax(qreal(1.0), step);
138 }
139
140 QDoubleSpinBox::setSingleStep( step );
141 d->unit = unit;
142 QDoubleSpinBox::setValue(unit.toUserValuePrecise(oldvalue));
143 setSuffix(unit.symbol().prepend(QLatin1Char(' ')));
144}
145
147{
148 return d->unit.fromUserValue( QDoubleSpinBox::value() );
149}
150
152{
153 d->lowerInPoints = min;
154 QDoubleSpinBox::setMinimum( d->unit.toUserValue( min ) );
155}
156
158{
159 d->upperInPoints = max;
160 QDoubleSpinBox::setMaximum( d->unit.toUserValue( max ) );
161}
162
164{
165 d->stepInPoints = KoUnit(KoUnit::Point).toUserValue(step);
166 QDoubleSpinBox::setSingleStep( step );
167}
168
170{
171 d->stepInPoints = step;
172 QDoubleSpinBox::setSingleStep( d->unit.toUserValue( step ) );
173}
174
175void KoUnitDoubleSpinBox::setMinMaxStep( double min, double max, double step )
176{
177 setMinimum( min );
178 setMaximum( max );
179 setLineStepPt( step );
180}
181
183{
184 //debugWidgets <<"textFromValue:" << QString::number( value, 'f', 12 ) <<" =>" << num;
185 //const QString num(QString("%1%2").arg(QLocale().toString(value, d->precision ), m_unit.symbol()));
186 //const QString num ( QString( "%1").arg( QLocale().toString( value, d->precision )) );
187 return QLocale().toString( value, 'f', decimals() );
188}
189
190double KoUnitDoubleSpinBox::valueFromText( const QString& str ) const
191{
192 QString str2( str );
193 str2.remove(d->unit.symbol());
194 return QLocale().toDouble(str2);
195// QString str2( str );
196// /* KLocale::readNumber wants the thousand separator exactly at 1000.
197// But when editing, it might be anywhere. So we need to remove it. */
198// const QString sep( KGlobal::locale()->thousandsSeparator() );
199// if ( !sep.isEmpty() )
200// str2.remove( sep );
201// str2.remove(d->unit.symbol());
202// bool ok;
203// const double dbl = KGlobal::locale()->readNumber( str2, &ok );
204//#ifdef DEBUG_VALUEFROMTEXT
205// if ( ok )
206// debugWidgets <<"valueFromText:" << str <<": => :" << str2 <<": =>" << QString::number( dbl, 'f', 12 );
207// else
208// warnWidgets << "valueFromText error:" << str << ": => :" << str2 << ":";
209//#endif
210// return dbl;
211}
float value(const T *src, size_t ch)
#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