Warning, file /office/calligra/libs/widgets/KoUnitDoubleSpinBox.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002    Copyright (C) 2002, Rob Buis(buis@kde.org)
0003    Copyright (C) 2004, Nicolas GOUTTE <goutte@kde.org>
0004    Copyright (C) 2007, Thomas Zander <zander@kde.org>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "KoUnitDoubleSpinBox.h"
0023 
0024 #include <KoUnit.h>
0025 
0026 #include <WidgetsDebug.h>
0027 
0028 #include <klocalizedstring.h>
0029 
0030 // #define DEBUG_VALIDATOR
0031 // #define DEBUG_VALUEFROMTEXT
0032 
0033 class Q_DECL_HIDDEN KoUnitDoubleSpinBox::Private
0034 {
0035 public:
0036     Private(double low, double up, double step)
0037         : lowerInPoints(low),
0038         upperInPoints(up),
0039         stepInPoints(step),
0040         unit(KoUnit(KoUnit::Point))
0041     {
0042     }
0043 
0044     double lowerInPoints; ///< lowest value in points
0045     double upperInPoints; ///< highest value in points
0046     double stepInPoints;  ///< step in points
0047     KoUnit unit;
0048 };
0049 
0050 KoUnitDoubleSpinBox::KoUnitDoubleSpinBox( QWidget *parent)
0051     : QDoubleSpinBox( parent ),
0052     d( new Private(-9999, 9999, 1))
0053 {
0054     QDoubleSpinBox::setDecimals( 2 );
0055     //setAcceptLocalizedNumbers( true );
0056     setUnit( KoUnit(KoUnit::Point) );
0057     setAlignment( Qt::AlignRight );
0058 
0059     connect(this, SIGNAL(valueChanged(double)), SLOT(privateValueChanged()));
0060 }
0061 
0062 KoUnitDoubleSpinBox::~KoUnitDoubleSpinBox()
0063 {
0064     delete d;
0065 }
0066 
0067 QValidator::State KoUnitDoubleSpinBox::validate(QString &input, int &pos) const
0068 {
0069 #ifdef DEBUG_VALIDATOR
0070     debugWidgets <<"KoUnitDoubleSpinBox::validate :" << input <<" at" << pos;
0071 #else
0072     Q_UNUSED(pos);
0073 #endif
0074 
0075     QRegExp regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end
0076     const int res = input.indexOf( regexp );
0077 
0078     if ( res == -1 )
0079     {
0080         // Nothing like an unit? The user is probably editing the unit
0081 #ifdef DEBUG_VALIDATOR
0082         debugWidgets <<"Intermediate (no unit)";
0083 #endif
0084         return QValidator::Intermediate;
0085     }
0086 
0087     // ### TODO: are all the QString::trimmed really necessary?
0088     const QString number ( input.left( res ).trimmed() );
0089     const QString unitName ( regexp.cap( 1 ).trimmed().toLower() );
0090 
0091 #ifdef DEBUG_VALIDATOR
0092     debugWidgets <<"Split:" << number <<":" << unitName <<":";
0093 #endif
0094 
0095     const double value = valueFromText( number );
0096     double newVal = 0.0;
0097     if (!qIsNaN(value)) {
0098         bool ok;
0099         const KoUnit unit = KoUnit::fromSymbol(unitName, &ok);
0100         if ( ok )
0101             newVal = unit.fromUserValue( value );
0102         else
0103         {
0104             // Probably the user is trying to edit the unit
0105 #ifdef DEBUG_VALIDATOR
0106             debugWidgets <<"Intermediate (unknown unit)";
0107 #endif
0108             return QValidator::Intermediate;
0109         }
0110     }
0111     else
0112     {
0113         warnWidgets << "Not a number: " << number;
0114         return QValidator::Invalid;
0115     }
0116     newVal = KoUnit::ptToUnit( newVal, d->unit );
0117     //input = textFromValue( newVal ); // don't overwrite for now; the effect is not exactly what I expect...
0118 
0119     return QValidator::Acceptable;
0120 }
0121 
0122 void KoUnitDoubleSpinBox::changeValue( double val )
0123 {
0124     QDoubleSpinBox::setValue( d->unit.toUserValue( val ) );
0125     // TODO: emit valueChanged ONLY if the value was out-of-bounds
0126     // This will allow the 'user' dialog to set a dirty bool and ensure
0127     // a proper value is getting saved.
0128 }
0129 
0130 void KoUnitDoubleSpinBox::privateValueChanged() {
0131     emit valueChangedPt( value () );
0132 }
0133 
0134 void KoUnitDoubleSpinBox::setUnit( const KoUnit &unit )
0135 {
0136     if (unit == d->unit) return;
0137 
0138     double oldvalue = d->unit.fromUserValue( QDoubleSpinBox::value() );
0139     QDoubleSpinBox::setMinimum( unit.toUserValue( d->lowerInPoints ) );
0140     QDoubleSpinBox::setMaximum( unit.toUserValue( d->upperInPoints ) );
0141 
0142     qreal step = unit.toUserValue( d->stepInPoints );
0143 
0144     if (unit.type() == KoUnit::Pixel) {
0145         // limit the pixel step by 1.0
0146         step = qMax(qreal(1.0), step);
0147     }
0148 
0149     QDoubleSpinBox::setSingleStep( step );
0150     d->unit = unit;
0151     QDoubleSpinBox::setValue( KoUnit::ptToUnit( oldvalue, unit ) );
0152     setSuffix(unit.symbol().prepend(QLatin1Char(' ')));
0153 }
0154 
0155 double KoUnitDoubleSpinBox::value( ) const
0156 {
0157     return d->unit.fromUserValue( QDoubleSpinBox::value() );
0158 }
0159 
0160 void KoUnitDoubleSpinBox::setMinimum( double min )
0161 {
0162   d->lowerInPoints = min;
0163   QDoubleSpinBox::setMinimum( d->unit.toUserValue( min ) );
0164 }
0165 
0166 void KoUnitDoubleSpinBox::setMaximum( double max )
0167 {
0168   d->upperInPoints = max;
0169   QDoubleSpinBox::setMaximum( d->unit.toUserValue( max ) );
0170 }
0171 
0172 void KoUnitDoubleSpinBox::setLineStep( double step )
0173 {
0174   d->stepInPoints = KoUnit(KoUnit::Point).toUserValue(step);
0175   QDoubleSpinBox::setSingleStep( step );
0176 }
0177 
0178 void KoUnitDoubleSpinBox::setLineStepPt( double step )
0179 {
0180   d->stepInPoints = step;
0181   QDoubleSpinBox::setSingleStep( d->unit.toUserValue( step ) );
0182 }
0183 
0184 void KoUnitDoubleSpinBox::setMinMaxStep( double min, double max, double step )
0185 {
0186   setMinimum( min );
0187   setMaximum( max );
0188   setLineStepPt( step );
0189 }
0190 
0191 QString KoUnitDoubleSpinBox::textFromValue( double value ) const
0192 {
0193     //debugWidgets <<"textFromValue:" << QString::number( value, 'f', 12 ) <<" =>" << num;
0194     //const QString num(QString("%1%2").arg(QLocale().toString(value, d->precision ), m_unit.symbol()));
0195     //const QString num ( QString( "%1").arg( QLocale().toString( value, d->precision )) );
0196     return QLocale().toString( value, 'f', decimals() );
0197 }
0198 
0199 double KoUnitDoubleSpinBox::valueFromText( const QString& str ) const
0200 {
0201     QString str2( str );
0202     str2.remove(d->unit.symbol());
0203     return QLocale().toDouble(str2);
0204 //    QString str2( str );
0205 //    /* KLocale::readNumber wants the thousand separator exactly at 1000.
0206 //       But when editing, it might be anywhere. So we need to remove it. */
0207 //    const QString sep( KGlobal::locale()->thousandsSeparator() );
0208 //    if ( !sep.isEmpty() )
0209 //        str2.remove( sep );
0210 //    str2.remove(d->unit.symbol());
0211 //    bool ok;
0212 //    const double dbl = KGlobal::locale()->readNumber( str2, &ok );
0213 //#ifdef DEBUG_VALUEFROMTEXT
0214 //    if ( ok )
0215 //      debugWidgets <<"valueFromText:" << str <<": => :" << str2 <<": =>" << QString::number( dbl, 'f', 12 );
0216 //    else
0217 //        warnWidgets << "valueFromText error:" << str << ": => :" << str2 << ":";
0218 //#endif
0219 //    return dbl;
0220 }