summaryrefslogtreecommitdiffstats
path: root/lib/kofficeui/KoUnitWidgets.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kofficeui/KoUnitWidgets.cpp')
-rw-r--r--lib/kofficeui/KoUnitWidgets.cpp455
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();
+}
+