diff options
Diffstat (limited to 'lib/kofficeui/KoUnitWidgets.cpp')
-rw-r--r-- | lib/kofficeui/KoUnitWidgets.cpp | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/lib/kofficeui/KoUnitWidgets.cpp b/lib/kofficeui/KoUnitWidgets.cpp new file mode 100644 index 00000000..00899882 --- /dev/null +++ b/lib/kofficeui/KoUnitWidgets.cpp @@ -0,0 +1,455 @@ +/* This file is part of the KDE project + Copyright (C) 2002, Rob Buis(buis@kde.org) + Copyright (C) 2004, Nicolas GOUTTE <goutte@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "KoUnitWidgets.h" +#include "KoUnitWidgets.moc" +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <qpushbutton.h> +#include <qlayout.h> + + +// ---------------------------------------------------------------- +// Support classes + + +KoUnitDoubleValidator::KoUnitDoubleValidator( KoUnitDoubleBase *base, QObject *parent, const char *name ) +: KDoubleValidator( parent, name ), m_base( base ) +{ +} + +QValidator::State +KoUnitDoubleValidator::validate( QString &s, int &pos ) const +{ + + kdDebug(30004) << "KoUnitDoubleValidator::validate : " << s << " at " << pos << endl; + QValidator::State result = Acceptable; + + QRegExp regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end + const int res = regexp.search( s ); + + if ( res == -1 ) + { + // Nothing like an unit? The user is probably editing the unit + kdDebug(30004) << "Intermediate (no unit)" << endl; + return Intermediate; + } + + // ### TODO: are all the QString::stripWhiteSpace really necessary? + const QString number ( s.left( res ).stripWhiteSpace() ); + const QString unitName ( regexp.cap( 1 ).stripWhiteSpace().lower() ); + + kdDebug(30004) << "Split:" << number << ":" << unitName << ":" << endl; + + bool ok = false; + const double value = m_base->toDouble( number, &ok ); + double newVal = 0.0; + if( ok ) + { + KoUnit::Unit unit = KoUnit::unit( unitName, &ok ); + if ( ok ) + newVal = KoUnit::fromUserValue( value, unit ); + else + { + // Probably the user is trying to edit the unit + kdDebug(30004) << "Intermediate (unknown unit)" << endl; + return Intermediate; + } + } + else + { + kdWarning(30004) << "Not a number: " << number << endl; + return Invalid; + } + + newVal = KoUnit::ptToUnit( newVal, m_base->m_unit ); + + s = m_base->getVisibleText( newVal ); + + return result; +} + + +QString KoUnitDoubleBase::getVisibleText( double value ) const +{ + const QString num ( QString( "%1%2").arg( KGlobal::locale()->formatNumber( value, m_precision ), KoUnit::unitName( m_unit ) ) ); + kdDebug(30004) << "getVisibleText: " << QString::number( value, 'f', 12 ) << " => " << num << endl; + return num; +} + +double KoUnitDoubleBase::toDouble( const QString& str, bool* ok ) const +{ + QString str2( str ); + /* KLocale::readNumber wants the thousand separator exactly at 1000. + But when editing, it might be anywhere. So we need to remove it. */ + const QString sep( KGlobal::locale()->thousandsSeparator() ); + if ( !sep.isEmpty() ) + str2.remove( sep ); + str2.remove( KoUnit::unitName( m_unit ) ); + const double dbl = KGlobal::locale()->readNumber( str2, ok ); + if ( ok ) + kdDebug(30004) << "toDouble:" << str << ": => :" << str2 << ": => " << QString::number( dbl, 'f', 12 ) << endl; + else + kdWarning(30004) << "toDouble error:" << str << ": => :" << str2 << ":" << endl; + return dbl; +} + + +// ---------------------------------------------------------------- +// Widget classes + + +KoUnitDoubleSpinBox::KoUnitDoubleSpinBox( QWidget *parent, const char *name ) + : KDoubleSpinBox( parent, name ), KoUnitDoubleBase( KoUnit::U_PT, 2 ) + , m_lowerInPoints( -9999 ) + , m_upperInPoints( 9999 ) + , m_stepInPoints( 1 ) +{ + KDoubleSpinBox::setPrecision( 2 ); + m_validator = new KoUnitDoubleValidator( this, this ); + QSpinBox::setValidator( m_validator ); + setAcceptLocalizedNumbers( true ); + setUnit( KoUnit::U_PT ); + + connect(this, SIGNAL(valueChanged( double )), SLOT(privateValueChanged())); +} + + +KoUnitDoubleSpinBox::KoUnitDoubleSpinBox( QWidget *parent, + double lower, double upper, + double step, + double value, + KoUnit::Unit unit, + unsigned int precision, + const char *name ) + : KDoubleSpinBox( lower, upper, step, value, precision, parent, name ), + KoUnitDoubleBase( unit, precision ), + m_lowerInPoints( lower ), m_upperInPoints( upper ), m_stepInPoints( step ) +{ + m_unit = KoUnit::U_PT; + m_validator = new KoUnitDoubleValidator( this, this ); + QSpinBox::setValidator( m_validator ); + setAcceptLocalizedNumbers( true ); + setUnit( unit ); + changeValue( value ); + setLineStep( 0.5 ); + + connect(this, SIGNAL(valueChanged( double )), SLOT(privateValueChanged())); +} + +void +KoUnitDoubleSpinBox::changeValue( double val ) +{ + KDoubleSpinBox::setValue( KoUnit::toUserValue( val, m_unit ) ); + // TODO: emit valueChanged ONLY if the value was out-of-bounds + // This will allow the 'user' dialog to set a dirty bool and ensure + // a proper value is getting saved. +} + +void KoUnitDoubleSpinBox::privateValueChanged() { + emit valueChangedPt( value () ); +} + +void +KoUnitDoubleSpinBox::setUnit( KoUnit::Unit unit ) +{ + double oldvalue = KoUnit::fromUserValue( KDoubleSpinBox::value(), m_unit ); + KDoubleSpinBox::setMinValue( KoUnit::toUserValue( m_lowerInPoints, unit ) ); + KDoubleSpinBox::setMaxValue( KoUnit::toUserValue( m_upperInPoints, unit ) ); + KDoubleSpinBox::setLineStep( KoUnit::toUserValue( m_stepInPoints, unit ) ); + KDoubleSpinBox::setValue( KoUnit::ptToUnit( oldvalue, unit ) ); + m_unit = unit; + setSuffix( KoUnit::unitName( unit ).prepend( ' ' ) ); +} + +double KoUnitDoubleSpinBox::value( void ) const +{ + return KoUnit::fromUserValue( KDoubleSpinBox::value(), m_unit ); +} + +void KoUnitDoubleSpinBox::setMinValue( double min ) +{ + m_lowerInPoints = min; + KDoubleSpinBox::setMinValue( KoUnit::toUserValue( m_lowerInPoints, m_unit ) ); +} + +void KoUnitDoubleSpinBox::setMaxValue( double max ) +{ + m_upperInPoints = max; + KDoubleSpinBox::setMaxValue( KoUnit::toUserValue( m_upperInPoints, m_unit ) ); +} + +void KoUnitDoubleSpinBox::setLineStep( double step ) +{ + m_stepInPoints = KoUnit::toUserValue(step, KoUnit::U_PT ); + KDoubleSpinBox::setLineStep( step ); +} + +void KoUnitDoubleSpinBox::setLineStepPt( double step ) +{ + m_stepInPoints = step; + KDoubleSpinBox::setLineStep( KoUnit::toUserValue( m_stepInPoints, m_unit ) ); +} + +void KoUnitDoubleSpinBox::setMinMaxStep( double min, double max, double step ) +{ + setMinValue( min ); + setMaxValue( max ); + setLineStepPt( step ); +} + +// ---------------------------------------------------------------- + + +KoUnitDoubleLineEdit::KoUnitDoubleLineEdit( QWidget *parent, const char *name ) + : KLineEdit( parent, name ), KoUnitDoubleBase( KoUnit::U_PT, 2 ), m_value( 0.0 ), m_lower( 0.0 ), m_upper( 9999.99 ), + m_lowerInPoints( 0.0 ), m_upperInPoints( 9999.99 ) +{ + setAlignment( Qt::AlignRight ); + m_validator = new KoUnitDoubleValidator( this, this ); + setValidator( m_validator ); + setUnit( KoUnit::U_PT ); + changeValue( KoUnit::ptToUnit( 0.0, KoUnit::U_PT ) ); +} + +KoUnitDoubleLineEdit::KoUnitDoubleLineEdit( QWidget *parent, double lower, double upper, double value, KoUnit::Unit unit, + unsigned int precision, const char *name ) + : KLineEdit( parent, name ), KoUnitDoubleBase( unit, precision ), m_value( value ), m_lower( lower ), m_upper( upper ), + m_lowerInPoints( lower ), m_upperInPoints( upper ) +{ + setAlignment( Qt::AlignRight ); + m_validator = new KoUnitDoubleValidator( this, this ); + setValidator( m_validator ); + setUnit( unit ); + changeValue( KoUnit::ptToUnit( value, unit ) ); +} + +void +KoUnitDoubleLineEdit::changeValue( double value ) +{ + m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value ); + setText( getVisibleText( m_value ) ); +} + +void +KoUnitDoubleLineEdit::setUnit( KoUnit::Unit unit ) +{ + KoUnit::Unit old = m_unit; + m_unit = unit; + m_lower = KoUnit::ptToUnit( m_lowerInPoints, unit ); + m_upper = KoUnit::ptToUnit( m_upperInPoints, unit ); + changeValue( KoUnit::ptToUnit( KoUnit::fromUserValue( m_value, old ), unit ) ); +} + +bool +KoUnitDoubleLineEdit::eventFilter( QObject* o, QEvent* ev ) +{ +#if 0 + if( ev->type() == QEvent::FocusOut || ev->type() == QEvent::Leave || ev->type() == QEvent::Hide ) + { + bool ok; + double value = toDouble( text(), &ok ); + changeValue( value ); + return false; + } + else +#endif + return QLineEdit::eventFilter( o, ev ); +} + +double KoUnitDoubleLineEdit::value( void ) const +{ + return KoUnit::fromUserValue( m_value, m_unit ); +} + + +// ---------------------------------------------------------------- + + +KoUnitDoubleComboBox::KoUnitDoubleComboBox( QWidget *parent, const char *name ) + : KComboBox( true, parent, name ), KoUnitDoubleBase( KoUnit::U_PT, 2 ), m_value( 0.0 ), m_lower( 0.0 ), m_upper( 9999.99 ), m_lowerInPoints( 0.0 ), m_upperInPoints( 9999.99 ) +{ + lineEdit()->setAlignment( Qt::AlignRight ); + m_validator = new KoUnitDoubleValidator( this, this ); + lineEdit()->setValidator( m_validator ); + setUnit( KoUnit::U_PT ); + changeValue( KoUnit::ptToUnit( 0.0, KoUnit::U_PT ) ); + connect( this, SIGNAL( activated( int ) ), this, SLOT( slotActivated( int ) ) ); +} + +KoUnitDoubleComboBox::KoUnitDoubleComboBox( QWidget *parent, double lower, double upper, double value, KoUnit::Unit unit, + unsigned int precision, const char *name ) + : KComboBox( true, parent, name ), KoUnitDoubleBase( unit, precision ), m_value( value ), m_lower( lower ), m_upper( upper ), + m_lowerInPoints( lower ), m_upperInPoints( upper ) +{ + lineEdit()->setAlignment( Qt::AlignRight ); + m_validator = new KoUnitDoubleValidator( this, this ); + lineEdit()->setValidator( m_validator ); + setUnit( unit ); + changeValue( KoUnit::ptToUnit( value, unit ) ); + connect( this, SIGNAL( activated( int ) ), this, SLOT( slotActivated( int ) ) ); +} + +void +KoUnitDoubleComboBox::changeValue( double value ) +{ + QString oldLabel = lineEdit()->text(); + updateValue( value ); + if( lineEdit()->text() != oldLabel ) + emit valueChanged( m_value ); +} + +void +KoUnitDoubleComboBox::updateValue( double value ) +{ + m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value ); + lineEdit()->setText( getVisibleText( m_value ) ); +} + +void +KoUnitDoubleComboBox::insertItem( double value, int index ) +{ + KComboBox::insertItem( getVisibleText( value ), index ); +} + +void +KoUnitDoubleComboBox::slotActivated( int index ) +{ + double oldvalue = m_value; + bool ok; + double value = toDouble( text( index ), &ok ); + m_value = value < m_lower ? m_lower : ( value > m_upper ? m_upper : value ); + if( m_value != oldvalue ) + emit valueChanged( m_value ); +} + +void +KoUnitDoubleComboBox::setUnit( KoUnit::Unit unit ) +{ + KoUnit::Unit old = m_unit; + m_unit = unit; + m_lower = KoUnit::ptToUnit( m_lowerInPoints, unit ); + m_upper = KoUnit::ptToUnit( m_upperInPoints, unit ); + changeValue( KoUnit::ptToUnit( KoUnit::fromUserValue( m_value, old ), unit ) ); +} + +bool +KoUnitDoubleComboBox::eventFilter( QObject* o, QEvent* ev ) +{ +#if 0 + if( ev->type() == QEvent::FocusOut || ev->type() == QEvent::Leave || ev->type() == QEvent::Hide ) + { + bool ok; + double value = toDouble( lineEdit()->text(), &ok ); + changeValue( value ); + return false; + } + else +#endif + return QComboBox::eventFilter( o, ev ); +} + +double KoUnitDoubleComboBox::value( void ) const +{ + return KoUnit::fromUserValue( m_value, m_unit ); +} + + +// ---------------------------------------------------------------- + + +KoUnitDoubleSpinComboBox::KoUnitDoubleSpinComboBox( QWidget *parent, const char *name ) + : QWidget( parent ), m_step( 1.0 ) +{ + QGridLayout *layout = new QGridLayout( this, 2, 3 ); + //layout->setMargin( 2 ); + QPushButton *up = new QPushButton( "+", this ); + //up->setFlat( true ); + up->setMaximumHeight( 15 ); + up->setMaximumWidth( 15 ); + layout->addWidget( up, 0, 0 ); + connect( up, SIGNAL( clicked() ), this, SLOT( slotUpClicked() ) ); + + QPushButton *down = new QPushButton( "-", this ); + down->setMaximumHeight( 15 ); + down->setMaximumWidth( 15 ); + layout->addWidget( down, 1, 0 ); + connect( down, SIGNAL( clicked() ), this, SLOT( slotDownClicked() ) ); + + m_combo = new KoUnitDoubleComboBox( this, KoUnit::ptToUnit( 0.0, KoUnit::U_PT ), KoUnit::ptToUnit( 9999.99, KoUnit::U_PT ), 0.0, KoUnit::U_PT, 2, name ); + connect( m_combo, SIGNAL( valueChanged( double ) ), this, SIGNAL( valueChanged( double ) ) ); + layout->addMultiCellWidget( m_combo, 0, 1, 2, 2 ); +} + +KoUnitDoubleSpinComboBox::KoUnitDoubleSpinComboBox( QWidget *parent, double lower, double upper, double step, double value, + KoUnit::Unit unit, unsigned int precision, const char *name ) + : QWidget( parent ), m_step( step )//, m_lowerInPoints( lower ), m_upperInPoints( upper ) +{ + QGridLayout *layout = new QGridLayout( this, 2, 3 ); + //layout->setMargin( 2 ); + QPushButton *up = new QPushButton( "+", this ); + //up->setFlat( true ); + up->setMaximumHeight( 15 ); + up->setMaximumWidth( 15 ); + layout->addWidget( up, 0, 0 ); + connect( up, SIGNAL( clicked() ), this, SLOT( slotUpClicked() ) ); + + QPushButton *down = new QPushButton( "-", this ); + down->setMaximumHeight( 15 ); + down->setMaximumWidth( 15 ); + layout->addWidget( down, 1, 0 ); + connect( down, SIGNAL( clicked() ), this, SLOT( slotDownClicked() ) ); + + m_combo = new KoUnitDoubleComboBox( this, KoUnit::ptToUnit( lower, unit ), KoUnit::ptToUnit( upper, unit ), value, unit, precision, name ); + connect( m_combo, SIGNAL( valueChanged( double ) ), this, SIGNAL( valueChanged( double ) ) ); + layout->addMultiCellWidget( m_combo, 0, 1, 2, 2 ); +} + +void +KoUnitDoubleSpinComboBox::slotUpClicked() +{ + m_combo->changeValue( m_combo->value() + m_step ); +} + +void +KoUnitDoubleSpinComboBox::slotDownClicked() +{ + m_combo->changeValue( m_combo->value() - m_step ); +} + +void +KoUnitDoubleSpinComboBox::insertItem( double value, int index ) +{ + m_combo->insertItem( value, index ); +} + +void +KoUnitDoubleSpinComboBox::updateValue( double value ) +{ + m_combo->updateValue( value ); +} + +double +KoUnitDoubleSpinComboBox::value() const +{ + return m_combo->value(); +} + |