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 }