lib Library API Documentation

koUnitWidgets.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002, Rob Buis(buis@kde.org)
00003    Copyright (C) 2004, Nicolas GOUTTE <goutte@kde.org>
00004    
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include "koUnitWidgets.moc"
00022 #include <kglobal.h>
00023 #include <klocale.h>
00024 #include <kdebug.h>
00025 #include <qpushbutton.h>
00026 #include <qlayout.h>
00027 
00028 #include <koUnit.h>
00029 
00030 // Taken from KoUnit::unit of KOffice CVS HEAD
00031 static KoUnit::Unit getUnit( const QString &_unitName, bool* ok )
00032 {
00033     if ( ok )
00034         *ok = true;
00035     if ( _unitName == QString::fromLatin1( "mm" ) ) return KoUnit::U_MM;
00036     if ( _unitName == QString::fromLatin1( "cm" ) ) return KoUnit::U_CM;
00037     if ( _unitName == QString::fromLatin1( "dm" ) ) return KoUnit::U_DM;
00038     if ( _unitName == QString::fromLatin1( "in" )
00039          || _unitName == QString::fromLatin1("inch") /*compat*/ ) return KoUnit::U_INCH;
00040     if ( _unitName == QString::fromLatin1( "pi" ) ) return KoUnit::U_PI;
00041     if ( _unitName == QString::fromLatin1( "dd" ) ) return KoUnit::U_DD;
00042     if ( _unitName == QString::fromLatin1( "cc" ) ) return KoUnit::U_CC;
00043     if ( _unitName == QString::fromLatin1( "pt" ) ) return KoUnit::U_PT;
00044     if ( ok )
00045         *ok = false;
00046     return KoUnit::U_PT;
00047 }
00048 
00049 // Taken from KoUnit::fromUserValue of KOffice CVS HEAD
00050 static double getUserValue( double value, KoUnit::Unit unit )
00051 {
00052     switch ( unit ) {
00053     case KoUnit::U_MM:
00054         return MM_TO_POINT( value );
00055     case KoUnit::U_CM:
00056         return CM_TO_POINT( value );
00057     case KoUnit::U_DM:
00058         return DM_TO_POINT( value );
00059     case KoUnit::U_INCH:
00060         return INCH_TO_POINT( value );
00061     case KoUnit::U_PI:
00062         return PI_TO_POINT( value );
00063     case KoUnit::U_DD:
00064         return DD_TO_POINT( value );
00065     case KoUnit::U_CC:
00066         return CC_TO_POINT( value );
00067     case KoUnit::U_PT:
00068     default:
00069         return value;
00070     }
00071 }
00072 
00073 
00074 KoUnitDoubleValidator::KoUnitDoubleValidator( KoUnitDoubleBase *base, QObject *parent, const char *name )
00075 : KDoubleValidator( parent, name ), m_base( base )
00076 {
00077 }
00078 
00079 QValidator::State
00080 KoUnitDoubleValidator::validate( QString &s, int &pos ) const
00081 {
00082 
00083     kdDebug(30004) << "KoUnitDoubleValidator::validate : " << s << " at " << pos << endl;
00084     QValidator::State result = Acceptable;
00085 
00086     QRegExp regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end
00087     const int res = regexp.search( s );
00088 
00089     if ( res == -1 )
00090     {
00091         // Nothing like an unit? The user is probably editing the unit
00092         kdDebug(30004) << "Intermediate (no unit)" << endl;
00093         return Intermediate;
00094     }
00095 
00096     // ### TODO: are all the QString::stripWhiteSpace really necessary?
00097     const QString number ( s.left( res ).stripWhiteSpace() );
00098     const QString unitName ( regexp.cap( 1 ).stripWhiteSpace().lower() );
00099 
00100     kdDebug(30004) << "Split:" << number << ":" << unitName << ":" << endl;
00101 
00102     bool ok = false;
00103     const double value = KoUnitDoubleBase::toDouble( number, &ok );
00104     double newVal = 0.0;
00105     if( ok )
00106     {
00107         KoUnit::Unit unit = getUnit( unitName, &ok );
00108         if ( ok )
00109             newVal = getUserValue( value, unit );
00110         else
00111         {
00112             // Probably the user is trying to edit the unit
00113             kdDebug(30004) << "Intermediate (unknown unit)" << endl;
00114             return Intermediate;
00115         }
00116     }
00117     else
00118     {
00119         kdWarning(30004) << "Not a number: " << number << endl;
00120         return Invalid;
00121     }
00122 
00123     newVal = KoUnit::ptToUnit( newVal, m_base->m_unit );
00124 
00125     m_base->changeValue( newVal );
00126     s = m_base->getVisibleText( newVal );
00127 
00128     return result;
00129 }
00130 
00131 QString KoUnitDoubleBase::getVisibleText( double value ) const
00132 {
00133 #if QT_VERSION > 0x030102
00134     const QString num ( QString( "%1%2").arg( KGlobal::locale()->formatNumber( value, m_precision ), KoUnit::unitName( m_unit ) ) );
00135 #else
00136     const QString num ( QString( "%1%2").arg( KGlobal::locale()->formatNumber( value, m_precision ) ).arg( KoUnit::unitName( m_unit ) ) );
00137 #endif
00138 
00139     kdDebug(30004) << "getVisibleText: " << QString::number( value, 'f', 12 ) << " => " << num << endl;
00140     return num;
00141 }
00142 
00143 double KoUnitDoubleBase::toDouble( const QString& str, bool* ok )
00144 {
00145     QString str2( str );
00146     /* KLocale::readNumber wants the thousand separator exactly at 1000.
00147        But when editing, it might be anywhere. So we need to remove it. */
00148     const QString sep( KGlobal::locale()->thousandsSeparator() );
00149     if ( !sep.isEmpty() )
00150         str2.remove( sep );
00151     const double dbl = KGlobal::locale()->readNumber( str2, ok );
00152     if ( ok )
00153         kdDebug(30004) << "toDouble:" << str << ": => :" << str2 << ": => " << QString::number( dbl, 'f', 12 ) << endl;
00154     else
00155         kdWarning(30004) << "toDouble error:" << str << ": => :" << str2 << ":" << endl;
00156     return dbl;
00157 }
00158 
00159 KoUnitDoubleSpinBox::KoUnitDoubleSpinBox( QWidget *parent, double lower, double upper, double step, double value, KoUnit::Unit unit, unsigned int precision, const char *name )
00160     : KDoubleSpinBox( lower, upper, step, value, precision, parent, name ), KoUnitDoubleBase( unit, precision )
00161 {
00162     m_validator = new KoUnitDoubleValidator( this, this );
00163     QSpinBox::setValidator( m_validator );
00164     setAcceptLocalizedNumbers( true );
00165     setUnit( unit );
00166 }
00167 
00168 void
00169 KoUnitDoubleSpinBox::changeValue( double val )
00170 {
00171     KDoubleSpinBox::setValue( val );
00172 }
00173 
00174 void
00175 KoUnitDoubleSpinBox::setUnit( KoUnit::Unit unit )
00176 {
00177     double oldvalue = KoUnit::ptFromUnit( value(), m_unit );
00178     setMinValue( KoUnit::ptToUnit( KoUnit::ptFromUnit( minValue(), m_unit ), unit ) );
00179     setMaxValue( KoUnit::ptToUnit( KoUnit::ptFromUnit( maxValue(), m_unit ), unit ) );
00180     KDoubleSpinBox::setValue( KoUnit::ptToUnit( oldvalue, unit ) );
00181     m_unit = unit;
00182     setSuffix( KoUnit::unitName( unit ) );
00183 }
00184 
00185 
00186 KoUnitDoubleLineEdit::KoUnitDoubleLineEdit( QWidget *parent, double lower, double upper, double value, KoUnit::Unit unit, unsigned int precision, const char *name )
00187     : KLineEdit( parent, name ), KoUnitDoubleBase( unit, precision ), m_value( value ), m_lower( lower ), m_upper( upper )
00188 {
00189     setAlignment( Qt::AlignRight );
00190     m_validator = new KoUnitDoubleValidator( this, this );
00191     setValidator( m_validator );
00192     changeValue( value );
00193 }
00194 
00195 void
00196 KoUnitDoubleLineEdit::changeValue( double value )
00197 {
00198     m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value );
00199         setText( getVisibleText( m_value ) );
00200 }
00201 
00202 void
00203 KoUnitDoubleLineEdit::setUnit( KoUnit::Unit unit )
00204 {
00205     KoUnit::Unit old = m_unit;
00206     m_unit = unit;
00207     m_lower = KoUnit::ptToUnit( KoUnit::ptFromUnit( m_lower, old ), unit );
00208     m_upper = KoUnit::ptToUnit( KoUnit::ptFromUnit( m_upper, old ), unit );
00209     changeValue( KoUnit::ptToUnit( KoUnit::ptFromUnit( m_value, old ), unit ) );
00210 }
00211 
00212 bool
00213 KoUnitDoubleLineEdit::eventFilter( QObject* o, QEvent* ev )
00214 {
00215     if( ev->type() == QEvent::FocusOut || ev->type() == QEvent::Leave || ev->type() == QEvent::Hide )
00216     {
00217         bool ok;
00218                 const double value = KoUnitDoubleBase::toDouble( text(), &ok );
00219         changeValue( value );
00220         return false;
00221     }
00222     else
00223         return QLineEdit::eventFilter( o, ev );
00224 }
00225 
00226 
00227 
00228 KoUnitDoubleComboBox::KoUnitDoubleComboBox( QWidget *parent, double lower, double upper, double value, KoUnit::Unit unit, unsigned int precision, const char *name )
00229     : KComboBox( true, parent, name ), KoUnitDoubleBase( unit, precision ), m_value( value ), m_lower( lower ), m_upper( upper )
00230 {
00231     lineEdit()->setAlignment( Qt::AlignRight );
00232     m_validator = new KoUnitDoubleValidator( this, this );
00233     lineEdit()->setValidator( m_validator );
00234     changeValue( value );
00235     connect( this, SIGNAL( activated( int ) ), this, SLOT( slotActivated( int ) ) );
00236 }
00237 
00238 void
00239 KoUnitDoubleComboBox::changeValue( double value )
00240 {
00241     QString oldLabel = lineEdit()->text();
00242     updateValue( value );
00243     if( lineEdit()->text() != oldLabel )
00244         emit valueChanged( m_value );
00245 }
00246 
00247 void
00248 KoUnitDoubleComboBox::updateValue( double value )
00249 {
00250     m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value );
00251         lineEdit()->setText( getVisibleText( m_value ) );
00252 }
00253 
00254 void
00255 KoUnitDoubleComboBox::insertItem( double value, int index )
00256 {
00257     KComboBox::insertItem( getVisibleText( value ), index );
00258 }
00259 
00260 void
00261 KoUnitDoubleComboBox::slotActivated( int index )
00262 {
00263     double oldvalue = m_value;
00264     bool ok;
00265         const double value = KoUnitDoubleBase::toDouble( text( index ), &ok );
00266     m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value );
00267     if( m_value != oldvalue )
00268         emit valueChanged( m_value );
00269 }
00270 
00271 void
00272 KoUnitDoubleComboBox::setUnit( KoUnit::Unit unit )
00273 {
00274     KoUnit::Unit old = m_unit;
00275     m_unit = unit;
00276     m_lower = KoUnit::ptToUnit( KoUnit::ptFromUnit( m_lower, old ), unit );
00277     m_upper = KoUnit::ptToUnit( KoUnit::ptFromUnit( m_upper, old ), unit );
00278     changeValue( KoUnit::ptToUnit( getUserValue( m_value, old ), unit ) );
00279 }
00280 
00281 bool
00282 KoUnitDoubleComboBox::eventFilter( QObject* o, QEvent* ev )
00283 {
00284     if( ev->type() == QEvent::FocusOut || ev->type() == QEvent::Leave || ev->type() == QEvent::Hide )
00285     {
00286         bool ok;
00287                 const double value = KoUnitDoubleBase::toDouble( lineEdit()->text(), &ok );
00288         changeValue( value );
00289         return false;
00290     }
00291     else
00292         return QComboBox::eventFilter( o, ev );
00293 }
00294 
00295 KoUnitDoubleSpinComboBox::KoUnitDoubleSpinComboBox( QWidget *parent, double lower, double upper, double step, double value, KoUnit::Unit unit, unsigned int precision, const char *name )
00296     : QWidget( parent ), m_step( step )
00297 {
00298     QGridLayout *layout = new QGridLayout( this, 2, 3 );
00299     //layout->setMargin( 2 );
00300     QPushButton *up = new QPushButton( "+", this );
00301     //up->setFlat( true );
00302     up->setMaximumHeight( 15 );
00303     up->setMaximumWidth( 15 );
00304     layout->addWidget( up, 0, 0 );
00305     connect( up, SIGNAL( clicked() ), this, SLOT( slotUpClicked() ) );
00306 
00307     QPushButton *down = new QPushButton( "-", this );
00308     down->setMaximumHeight( 15 );
00309     down->setMaximumWidth( 15 );
00310     layout->addWidget( down, 1, 0 );
00311     connect( down, SIGNAL( clicked() ), this, SLOT( slotDownClicked() ) );
00312 
00313     m_combo = new KoUnitDoubleComboBox( this, lower, upper, value, unit, precision, name );
00314     connect( m_combo, SIGNAL( valueChanged( double ) ), this, SIGNAL( valueChanged( double ) ) );
00315     layout->addMultiCellWidget( m_combo, 0, 1, 2, 2 );
00316 }
00317 
00318 void
00319 KoUnitDoubleSpinComboBox::slotUpClicked()
00320 {
00321     m_combo->changeValue( m_combo->value() + m_step );
00322 }
00323 
00324 void
00325 KoUnitDoubleSpinComboBox::slotDownClicked()
00326 {
00327     m_combo->changeValue( m_combo->value() - m_step );
00328 }
00329 
00330 void
00331 KoUnitDoubleSpinComboBox::insertItem( double value, int index )
00332 {
00333     m_combo->insertItem( value, index );
00334 }
00335 
00336 void
00337 KoUnitDoubleSpinComboBox::updateValue( double value )
00338 {
00339     m_combo->updateValue( value );
00340 }
00341 
00342 double
00343 KoUnitDoubleSpinComboBox::value() const
00344 {
00345     return m_combo->value();
00346 }
00347 
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Nov 17 13:19:27 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2003