• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

knuminput.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002  * Initial implementation:
00003  *     Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca>
00004  * Rewritten and maintained by:
00005  *     Copyright (c) 2000 Dirk Mueller <mueller@kde.org>
00006  *
00007  *  This library is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *  License as published by the Free Software Foundation; either
00010  *  version 2 of the License, or (at your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public License
00018  *  along with this library; see the file COPYING.LIB.  If not, write to
00019  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  *  Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #include "knuminput.h"
00024 
00025 #include <config.h>
00026 #ifdef HAVE_LIMITS_H
00027 #include <limits.h>
00028 #endif
00029 #include <assert.h>
00030 #include <math.h>
00031 
00032 #include <QtGui/QApplication>
00033 #include <QtGui/QLabel>
00034 #include <QtGui/QLineEdit>
00035 #include <QtGui/QResizeEvent>
00036 #include <QtGui/QSlider>
00037 
00038 #include <kdebug.h>
00039 #include <kdialog.h>
00040 #include <kglobal.h>
00041 #include <klocale.h>
00042 #include <knumvalidator.h>
00043 
00044 static inline int calcDiffByTen( int x, int y ) {
00045     // calculate ( x - y ) / 10 without overflowing ints:
00046     return ( x / 10 ) - ( y / 10 )  +  ( x % 10 - y % 10 ) / 10;
00047 }
00048 
00049 // ----------------------------------------------------------------------------
00050 
00051 class KNumInputPrivate
00052 {
00053 public:
00054     KNumInputPrivate(KNumInput *q, KNumInput *below = 0):
00055         q(q),
00056         m_prev(0),
00057         m_next(0),
00058         m_colw1(0),
00059         m_colw2(0),
00060         m_label(0),
00061         m_slider(0),
00062         m_alignment(0)
00063     {
00064         if(below) {
00065             m_next = below->d->m_next;
00066             m_prev = below;
00067             below->d->m_next = q;
00068             if(m_next)
00069                 m_next->d->m_prev = q;
00070         }
00071     }
00072 
00073     static KNumInputPrivate *get(const KNumInput *i)
00074     {
00075         return i->d;
00076     }
00077 
00078     KNumInput *q;
00079     KNumInput* m_prev, *m_next;
00080     int m_colw1, m_colw2;
00081 
00082     QLabel*  m_label;
00083     QSlider* m_slider;
00084     QSize    m_sizeSlider, m_sizeLabel;
00085 
00086     Qt::Alignment m_alignment;
00087 };
00088 
00089 
00090 #define K_USING_KNUMINPUT_P(_d) KNumInputPrivate *_d = KNumInputPrivate::get(this)
00091 
00092 KNumInput::KNumInput(QWidget* parent)
00093     : QWidget(parent), d(new KNumInputPrivate(this))
00094 {
00095   setSizePolicy(QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ));
00096 }
00097 
00098 KNumInput::KNumInput(QWidget* parent, KNumInput* below)
00099     : QWidget(parent), d(new KNumInputPrivate(this, below))
00100 {
00101   setSizePolicy(QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ));
00102 }
00103 
00104 KNumInput::~KNumInput()
00105 {
00106     if(d->m_prev)
00107         d->m_prev->d->m_next = d->m_next;
00108 
00109     if(d->m_next)
00110         d->m_next->d->m_prev = d->m_prev;
00111 
00112     delete d;
00113 }
00114 
00115 QSlider *KNumInput::slider() const
00116 {
00117   return d->m_slider;
00118 }
00119 
00120 bool KNumInput::showSlider() const
00121 {
00122     return d->m_slider;
00123 }
00124 
00125 void KNumInput::setLabel(const QString & label, Qt::Alignment a)
00126 {
00127     if(label.isEmpty()) {
00128         delete d->m_label;
00129         d->m_label = 0;
00130         d->m_alignment = 0;
00131     }
00132     else {
00133         if (d->m_label) d->m_label->setText(label);
00134         else d->m_label = new QLabel(label, this);
00135         d->m_label->setObjectName("KNumInput::QLabel");
00136         d->m_label->setAlignment(a);
00137         // if no vertical alignment set, use Top alignment
00138         if(!(a & (Qt::AlignTop|Qt::AlignBottom|Qt::AlignVCenter)))
00139            a |= Qt::AlignTop;
00140         d->m_alignment = a;
00141     }
00142 
00143     layout(true);
00144 }
00145 
00146 QString KNumInput::label() const
00147 {
00148     if (d->m_label) return d->m_label->text();
00149     return QString();
00150 }
00151 
00152 void KNumInput::layout(bool deep)
00153 {
00154     int w1 = d->m_colw1;
00155     int w2 = d->m_colw2;
00156 
00157     // label sizeHint
00158     d->m_sizeLabel = (d->m_label ? d->m_label->sizeHint() : QSize(0,0));
00159 
00160     if(d->m_label && (d->m_alignment & Qt::AlignVCenter))
00161         d->m_colw1 = d->m_sizeLabel.width() + 4;
00162     else
00163         d->m_colw1 = 0;
00164 
00165     // slider sizeHint
00166     d->m_sizeSlider = (d->m_slider ? d->m_slider->sizeHint() : QSize(0, 0));
00167 
00168     doLayout();
00169 
00170     if(!deep) {
00171         d->m_colw1 = w1;
00172         d->m_colw2 = w2;
00173         return;
00174     }
00175 
00176     KNumInput* p = this;
00177     while(p) {
00178         p->doLayout();
00179         w1 = qMax(w1, p->d->m_colw1);
00180         w2 = qMax(w2, p->d->m_colw2);
00181         p = p->d->m_prev;
00182     }
00183 
00184     p = d->m_next;
00185     while(p) {
00186         p->doLayout();
00187         w1 = qMax(w1, p->d->m_colw1);
00188         w2 = qMax(w2, p->d->m_colw2);
00189         p = p->d->m_next;
00190     }
00191 
00192     p = this;
00193     while(p) {
00194         p->d->m_colw1 = w1;
00195         p->d->m_colw2 = w2;
00196         p = p->d->m_prev;
00197     }
00198 
00199     p = d->m_next;
00200     while(p) {
00201         p->d->m_colw1 = w1;
00202         p->d->m_colw2 = w2;
00203         p = p->d->m_next;
00204     }
00205 
00206 //    kDebug() << "w1 " << w1 << " w2 " << w2;
00207 }
00208 
00209 QSize KNumInput::sizeHint() const
00210 {
00211     return minimumSizeHint();
00212 }
00213 
00214 void KNumInput::setSteps(int minor, int major)
00215 {
00216     if(d->m_slider)
00217     {
00218         d->m_slider->setSingleStep( minor );
00219         d->m_slider->setPageStep( major );
00220     }
00221 }
00222 
00223 
00224 // ----------------------------------------------------------------------------
00225 
00226 class KIntSpinBox::KIntSpinBoxPrivate
00227 {
00228 public:
00229     KIntSpinBoxPrivate(KIntSpinBox *q, int val_base = 10): q(q), val_base(val_base) {}
00230 
00231     KIntSpinBox *q;
00232     int val_base;
00233 };
00234 
00235 KIntSpinBox::KIntSpinBox(QWidget *parent)
00236     : QSpinBox(parent), d(new KIntSpinBoxPrivate(this))
00237 {
00238     setRange(0,99);
00239     setSingleStep(1);
00240     lineEdit()->setAlignment(Qt::AlignRight);
00241     setValue(0);
00242 }
00243 
00244 KIntSpinBox::~KIntSpinBox()
00245 {
00246     delete d;
00247 }
00248 
00249 KIntSpinBox::KIntSpinBox(int lower, int upper, int step, int value, QWidget *parent,int base)
00250     : QSpinBox(parent), d(new KIntSpinBoxPrivate(this, base))
00251 {
00252     setRange(lower,upper);
00253     setSingleStep(step);
00254     lineEdit()->setAlignment(Qt::AlignRight);
00255     setValue(value);
00256 }
00257 
00258 void KIntSpinBox::setBase(int base)
00259 {
00260     d->val_base = base;
00261 }
00262 
00263 
00264 int KIntSpinBox::base() const
00265 {
00266     return d->val_base;
00267 }
00268 
00269 QString KIntSpinBox::textFromValue(int v) const
00270 {
00271     return QString::number(v, d->val_base);
00272 }
00273 
00274 int KIntSpinBox::valueFromText(const QString &text) const
00275 {
00276     bool ok;
00277     QString theText = text;
00278     if (theText.endsWith(suffix())) theText.chop(suffix().length());
00279     return theText.toInt(&ok, d->val_base);
00280 }
00281 
00282 void KIntSpinBox::setEditFocus(bool mark)
00283 {
00284     lineEdit()->setFocus();
00285     if(mark)
00286         lineEdit()->selectAll();
00287 }
00288 
00289 
00290 // ----------------------------------------------------------------------------
00291 
00292 class KIntNumInput::KIntNumInputPrivate {
00293 public:
00294     KIntNumInput *q;
00295     int referencePoint;
00296     short blockRelative;
00297     KIntSpinBox* m_spin;
00298     QSize        m_sizeSpin;
00299 
00300     KIntNumInputPrivate( KIntNumInput *q, int r )
00301         : q(q),
00302           referencePoint( r ),
00303           blockRelative( 0 ) {}
00304 };
00305 
00306 
00307 KIntNumInput::KIntNumInput(KNumInput* below, int val,QWidget *parent,int _base)
00308     : KNumInput(parent,below)
00309     , d( new KIntNumInputPrivate( this, val ) )
00310 {
00311     init(val, _base);
00312 }
00313 
00314 KIntNumInput::KIntNumInput(QWidget *parent)
00315     : KNumInput(parent)
00316     , d( new KIntNumInputPrivate( this, 0 ) )
00317 {
00318     init(0, 10);
00319 }
00320 
00321 KIntNumInput::KIntNumInput(int val, QWidget *parent,int _base)
00322     : KNumInput(parent)
00323     , d( new KIntNumInputPrivate( this, val ) )
00324 {
00325     init(val, _base);
00326 }
00327 
00328 QSpinBox *KIntNumInput::spinBox() const
00329 {
00330     return d->m_spin;
00331 }
00332 
00333 void KIntNumInput::init(int val, int _base)
00334 {
00335     d->m_spin = new KIntSpinBox(INT_MIN, INT_MAX, 1, val, this, _base);
00336     d->m_spin->setObjectName("KIntNumInput::KIntSpinBox");
00337     // the KIntValidator is broken beyond believe for
00338     // spinboxes which have suffix or prefix texts, so
00339     // better don't use it unless absolutely necessary
00340 #ifdef __GNUC__
00341 #warning KDE4 we NEED to fix the validation of values here
00342 #endif
00343 //        if (_base != 10)
00344 //        m_spin->setValidator(new KIntValidator(this, _base, "KNumInput::KIntValidtr"));
00345 
00346     connect(d->m_spin, SIGNAL(valueChanged(int)), SLOT(spinValueChanged(int)));
00347     connect(this, SIGNAL(valueChanged(int)),
00348             SLOT(slotEmitRelativeValueChanged(int)));
00349 
00350     setFocusProxy(d->m_spin);
00351     layout(true);
00352 }
00353 
00354 void KIntNumInput::setReferencePoint( int ref ) {
00355     // clip to valid range:
00356     ref = qMin( maximum(), qMax( minimum(),  ref ) );
00357     d->referencePoint = ref;
00358 }
00359 
00360 int KIntNumInput::referencePoint() const {
00361     return d->referencePoint;
00362 }
00363 
00364 void KIntNumInput::spinValueChanged(int val)
00365 {
00366     K_USING_KNUMINPUT_P(priv);
00367 
00368     if(priv->m_slider)
00369         priv->m_slider->setValue(val);
00370 
00371     emit valueChanged(val);
00372 }
00373 
00374 void KIntNumInput::slotEmitRelativeValueChanged( int value ) {
00375     if ( d->blockRelative || !d->referencePoint ) return;
00376     emit relativeValueChanged( double( value ) / double( d->referencePoint ) );
00377 }
00378 
00379 void KIntNumInput::setSliderEnabled(bool slider)
00380 {
00381     K_USING_KNUMINPUT_P(priv);
00382     if(slider) {
00383         if (!priv->m_slider) {
00384             priv->m_slider = new QSlider(Qt::Horizontal, this);
00385             connect(priv->m_slider, SIGNAL(valueChanged(int)),
00386                     d->m_spin, SLOT(setValue(int)));
00387             priv->m_slider->setTickPosition(QSlider::TicksBelow);
00388         }
00389 
00390         priv->m_slider->setRange(d->m_spin->minimum(), d->m_spin->maximum());
00391         priv->m_slider->setPageStep(d->m_spin->singleStep());
00392         priv->m_slider->setValue(d->m_spin->value());
00393 
00394         // calculate (upper-lower)/10 without overflowing int's:
00395         int major = calcDiffByTen( d->m_spin->maximum(), d->m_spin->minimum() );
00396 
00397         priv->m_slider->setSingleStep(d->m_spin->singleStep());
00398         priv->m_slider->setPageStep(major);
00399         priv->m_slider->setTickInterval(major);
00400     }
00401     else {
00402         delete priv->m_slider;
00403         priv->m_slider = 0;
00404     }
00405 }
00406 
00407 void KIntNumInput::setRange(int lower, int upper, int step)
00408 {
00409     upper = qMax(upper, lower);
00410     lower = qMin(upper, lower);
00411     d->m_spin->setMinimum(lower);
00412     d->m_spin->setMaximum(upper);
00413     d->m_spin->setSingleStep(step);
00414 
00415     step = d->m_spin->singleStep(); // maybe QRangeControl didn't like out lineStep?
00416 
00417     // check that reference point is still inside valid range:
00418     setReferencePoint( referencePoint() );
00419 
00420     layout(true);
00421 }
00422 
00423 void KIntNumInput::setRange(int lower, int upper, int step, bool slider)
00424 {
00425     setRange(lower, upper, step);
00426     setSliderEnabled(slider);
00427 }
00428 
00429 void KIntNumInput::setMinimum(int min)
00430 {
00431     setRange(min, d->m_spin->maximum(), d->m_spin->singleStep());
00432 }
00433 
00434 int KIntNumInput::minimum() const
00435 {
00436     return d->m_spin->minimum();
00437 }
00438 
00439 void KIntNumInput::setMaximum(int max)
00440 {
00441     setRange(d->m_spin->minimum(), max, d->m_spin->singleStep());
00442 }
00443 
00444 int KIntNumInput::maximum() const
00445 {
00446     return d->m_spin->maximum();
00447 }
00448 
00449 void KIntNumInput::setSuffix(const QString &suffix)
00450 {
00451     d->m_spin->setSuffix(suffix);
00452 
00453     layout(true);
00454 }
00455 
00456 QString KIntNumInput::suffix() const
00457 {
00458     return d->m_spin->suffix();
00459 }
00460 
00461 void KIntNumInput::setPrefix(const QString &prefix)
00462 {
00463     d->m_spin->setPrefix(prefix);
00464 
00465     layout(true);
00466 }
00467 
00468 QString KIntNumInput::prefix() const
00469 {
00470     return d->m_spin->prefix();
00471 }
00472 
00473 void KIntNumInput::setEditFocus(bool mark)
00474 {
00475     d->m_spin->setEditFocus(mark);
00476 }
00477 
00478 QSize KIntNumInput::minimumSizeHint() const
00479 {
00480     K_USING_KNUMINPUT_P(priv);
00481     ensurePolished();
00482 
00483     int w;
00484     int h;
00485 
00486     h = 2 + qMax(d->m_sizeSpin.height(), priv->m_sizeSlider.height());
00487 
00488     // if in extra row, then count it here
00489     if(priv->m_label && (priv->m_alignment & (Qt::AlignBottom|Qt::AlignTop)))
00490         h += 4 + priv->m_sizeLabel.height();
00491     else
00492         // label is in the same row as the other widgets
00493         h = qMax(h, priv->m_sizeLabel.height() + 2);
00494 
00495     w = priv->m_slider ? priv->m_slider->sizeHint().width() + 8 : 0;
00496     w += priv->m_colw1 + priv->m_colw2;
00497 
00498     if(priv->m_alignment & (Qt::AlignTop|Qt::AlignBottom))
00499         w = qMax(w, priv->m_sizeLabel.width() + 4);
00500 
00501     return QSize(w, h);
00502 }
00503 
00504 void KIntNumInput::doLayout()
00505 {
00506     K_USING_KNUMINPUT_P(priv);
00507 
00508     d->m_sizeSpin = d->m_spin->sizeHint();
00509     priv->m_colw2 = d->m_sizeSpin.width();
00510 
00511     if (priv->m_label)
00512         priv->m_label->setBuddy(d->m_spin);
00513 }
00514 
00515 void KIntNumInput::resizeEvent(QResizeEvent* e)
00516 {
00517     K_USING_KNUMINPUT_P(priv);
00518 
00519     int w = priv->m_colw1;
00520     int h = 0;
00521 
00522     if(priv->m_label && (priv->m_alignment & Qt::AlignTop)) {
00523         priv->m_label->setGeometry(0, 0, e->size().width(), priv->m_sizeLabel.height());
00524         h += priv->m_sizeLabel.height() + KDialog::spacingHint();
00525     }
00526 
00527     if(priv->m_label && (priv->m_alignment & Qt::AlignVCenter))
00528         priv->m_label->setGeometry(0, 0, w, d->m_sizeSpin.height());
00529 
00530     if (qApp->layoutDirection())
00531     {
00532         d->m_spin->setGeometry(w, h, priv->m_slider ? priv->m_colw2 : qMax(priv->m_colw2, e->size().width() - w), d->m_sizeSpin.height());
00533         w += priv->m_colw2 + 8;
00534 
00535         if(priv->m_slider)
00536             priv->m_slider->setGeometry(w, h, e->size().width() - w, d->m_sizeSpin.height() + KDialog::spacingHint());
00537     }
00538     else if(priv->m_slider) {
00539         priv->m_slider->setGeometry(w, h, e->size().width() - (w + priv->m_colw2 + KDialog::spacingHint()), d->m_sizeSpin.height() + KDialog::spacingHint());
00540         d->m_spin->setGeometry(w + priv->m_slider->size().width() + KDialog::spacingHint(), h, priv->m_colw2, d->m_sizeSpin.height());
00541     }
00542     else {
00543         d->m_spin->setGeometry(w, h, qMax(priv->m_colw2, e->size().width() - w), d->m_sizeSpin.height());
00544     }
00545 
00546     h += d->m_sizeSpin.height() + 2;
00547 
00548     if(priv->m_label && (priv->m_alignment & Qt::AlignBottom))
00549         priv->m_label->setGeometry(0, h, priv->m_sizeLabel.width(), priv->m_sizeLabel.height());
00550 }
00551 
00552 KIntNumInput::~KIntNumInput()
00553 {
00554     delete d;
00555 }
00556 
00557 void KIntNumInput::setValue(int val)
00558 {
00559     d->m_spin->setValue(val);
00560     // slider value is changed by spinValueChanged
00561 }
00562 
00563 void KIntNumInput::setRelativeValue( double r ) {
00564     if ( !d->referencePoint ) return;
00565     ++d->blockRelative;
00566     setValue( int( d->referencePoint * r + 0.5 ) );
00567     --d->blockRelative;
00568 }
00569 
00570 double KIntNumInput::relativeValue() const {
00571     if ( !d->referencePoint ) return 0;
00572     return double( value() ) / double ( d->referencePoint );
00573 }
00574 
00575 int KIntNumInput::value() const
00576 {
00577     return d->m_spin->value();
00578 }
00579 
00580 void KIntNumInput::setSpecialValueText(const QString& text)
00581 {
00582     d->m_spin->setSpecialValueText(text);
00583     layout(true);
00584 }
00585 
00586 QString KIntNumInput::specialValueText() const
00587 {
00588     return d->m_spin->specialValueText();
00589 }
00590 
00591 void KIntNumInput::setLabel(const QString & label, Qt::Alignment a)
00592 {
00593     K_USING_KNUMINPUT_P(priv);
00594 
00595     KNumInput::setLabel(label, a);
00596 
00597     if(priv->m_label)
00598         priv->m_label->setBuddy(d->m_spin);
00599 }
00600 
00601 // ----------------------------------------------------------------------------
00602 
00603 class KDoubleNumInput::KDoubleNumInputPrivate {
00604 public:
00605     KDoubleNumInputPrivate( double r )
00606         : spin( 0 ),
00607           referencePoint( r ),
00608           blockRelative ( 0 ) {}
00609     QDoubleSpinBox * spin;
00610     double referencePoint;
00611     short blockRelative;
00612     QSize m_sizeEdit;
00613     QString m_specialvalue;
00614 };
00615 
00616 KDoubleNumInput::KDoubleNumInput(QWidget *parent)
00617     : KNumInput(parent)
00618     , d( new KDoubleNumInputPrivate( 0.0 ) )
00619 
00620 {
00621     init(0.0, 0.0, 9999.0, 0.01, 2);
00622 }
00623 
00624 KDoubleNumInput::KDoubleNumInput(double lower, double upper, double value, QWidget *parent,
00625                                  double step, int precision)
00626     : KNumInput(parent)
00627     , d( new KDoubleNumInputPrivate( value ) )
00628 {
00629     init(value, lower, upper, step, precision);
00630 }
00631 
00632 KDoubleNumInput::KDoubleNumInput(KNumInput *below,
00633                                  double lower, double upper, double value, QWidget *parent,
00634                                  double step, int precision)
00635     : KNumInput(parent,below)
00636     , d( new KDoubleNumInputPrivate( value ) )
00637 {
00638     init(value, lower, upper, step, precision);
00639 }
00640 
00641 KDoubleNumInput::~KDoubleNumInput()
00642 {
00643     delete d;
00644 }
00645 
00646 QString KDoubleNumInput::specialValueText() const
00647 {
00648     return d->m_specialvalue;
00649 }
00650 
00651 
00652 void KDoubleNumInput::init(double value, double lower, double upper,
00653                            double step, int precision )
00654 {
00655     d->spin = new QDoubleSpinBox(this);
00656     d->spin->setRange(lower, upper);
00657     d->spin->setSingleStep(step);
00658     d->spin->setValue(value);
00659     d->spin->setDecimals(precision);
00660     d->spin->setAlignment(Qt::AlignRight);
00661 
00662     d->spin->setObjectName("KDoubleNumInput::d->spin" );
00663     setFocusProxy(d->spin);
00664     connect( d->spin, SIGNAL(valueChanged(double)),
00665              this, SIGNAL(valueChanged(double)) );
00666     connect( this, SIGNAL(valueChanged(double)),
00667              this, SLOT(slotEmitRelativeValueChanged(double)) );
00668 
00669     updateLegacyMembers();
00670 
00671     layout(true);
00672 }
00673 
00674 void KDoubleNumInput::updateLegacyMembers() {
00675     d->m_specialvalue = specialValueText();
00676 }
00677 
00678 
00679 double KDoubleNumInput::mapSliderToSpin( int val ) const
00680 {
00681     K_USING_KNUMINPUT_P(priv);
00682 
00683     // map [slidemin,slidemax] to [spinmin,spinmax]
00684     double spinmin = d->spin->minimum();
00685     double spinmax = d->spin->maximum();
00686     double slidemin = priv->m_slider->minimum(); // cast int to double to avoid
00687     double slidemax = priv->m_slider->maximum(); // overflow in rel denominator
00688     double rel = ( double(val) - slidemin ) / ( slidemax - slidemin );
00689     return spinmin + rel * ( spinmax - spinmin );
00690 }
00691 
00692 void KDoubleNumInput::sliderMoved(int val)
00693 {
00694     d->spin->setValue( mapSliderToSpin( val ) );
00695 }
00696 
00697 void KDoubleNumInput::spinBoxChanged(double val)
00698 {
00699     K_USING_KNUMINPUT_P(priv);
00700 
00701     double spinmin = d->spin->minimum();
00702     double spinmax = d->spin->maximum();
00703     double slidemin = priv->m_slider->minimum(); // cast int to double to avoid
00704     double slidemax = priv->m_slider->maximum(); // overflow in rel denominator
00705 
00706     double rel = ( val - spinmin) / (spinmax - spinmin);
00707 
00708     if (priv->m_slider) {
00709         priv->m_slider->blockSignals(true);
00710         priv->m_slider->setValue(int(slidemin + rel * (slidemax - slidemin)));
00711         priv->m_slider->blockSignals(false);
00712     }
00713 }
00714 
00715 void KDoubleNumInput::slotEmitRelativeValueChanged( double value )
00716 {
00717     if ( !d->referencePoint ) return;
00718     emit relativeValueChanged( value / d->referencePoint );
00719 }
00720 
00721 QSize KDoubleNumInput::minimumSizeHint() const
00722 {
00723     K_USING_KNUMINPUT_P(priv);
00724 
00725     ensurePolished();
00726 
00727     int w;
00728     int h;
00729 
00730     h = 2 + qMax(d->m_sizeEdit.height(), priv->m_sizeSlider.height());
00731 
00732     // if in extra row, then count it here
00733     if(priv->m_label && (priv->m_alignment & (Qt::AlignBottom|Qt::AlignTop)))
00734         h += 4 + priv->m_sizeLabel.height();
00735     else
00736         // label is in the same row as the other widgets
00737         h = qMax(h, priv->m_sizeLabel.height() + 2);
00738 
00739     w = priv->m_slider ? priv->m_slider->sizeHint().width() + 8 : 0;
00740     w += priv->m_colw1 + priv->m_colw2;
00741 
00742     if(priv->m_alignment & (Qt::AlignTop|Qt::AlignBottom))
00743         w = qMax(w, priv->m_sizeLabel.width() + 4);
00744 
00745     return QSize(w, h);
00746 }
00747 
00748 void KDoubleNumInput::resizeEvent(QResizeEvent* e)
00749 {
00750     K_USING_KNUMINPUT_P(priv);
00751 
00752     int w = priv->m_colw1;
00753     int h = 0;
00754 
00755     if(priv->m_label && (priv->m_alignment & Qt::AlignTop)) {
00756         priv->m_label->setGeometry(0, 0, e->size().width(), priv->m_sizeLabel.height());
00757         h += priv->m_sizeLabel.height() + 4;
00758     }
00759 
00760     if(priv->m_label && (priv->m_alignment & Qt::AlignVCenter))
00761         priv->m_label->setGeometry(0, 0, w, d->m_sizeEdit.height());
00762 
00763     if (qApp->layoutDirection())
00764     {
00765         d->spin->setGeometry(w, h, priv->m_slider ? priv->m_colw2
00766                                             : e->size().width() - w, d->m_sizeEdit.height());
00767         w += priv->m_colw2 + KDialog::spacingHint();
00768 
00769         if(priv->m_slider)
00770             priv->m_slider->setGeometry(w, h, e->size().width() - w, d->m_sizeEdit.height() + KDialog::spacingHint());
00771     }
00772     else if(priv->m_slider) {
00773         priv->m_slider->setGeometry(w, h, e->size().width() -
00774                                     (priv->m_colw1 + priv->m_colw2 + KDialog::spacingHint()),
00775                               d->m_sizeEdit.height() + KDialog::spacingHint());
00776         d->spin->setGeometry(w + priv->m_slider->width() + KDialog::spacingHint(), h,
00777                              priv->m_colw2, d->m_sizeEdit.height());
00778     }
00779     else {
00780         d->spin->setGeometry(w, h, e->size().width() - w, d->m_sizeEdit.height());
00781     }
00782 
00783     h += d->m_sizeEdit.height() + 2;
00784 
00785     if(priv->m_label && (priv->m_alignment & Qt::AlignBottom))
00786         priv->m_label->setGeometry(0, h, priv->m_sizeLabel.width(), priv->m_sizeLabel.height());
00787 }
00788 
00789 void KDoubleNumInput::doLayout()
00790 {
00791     K_USING_KNUMINPUT_P(priv);
00792 
00793     d->m_sizeEdit = d->spin->sizeHint();
00794     priv->m_colw2 = d->m_sizeEdit.width();
00795 }
00796 
00797 void KDoubleNumInput::setValue(double val)
00798 {
00799     d->spin->setValue( val );
00800 }
00801 
00802 void KDoubleNumInput::setRelativeValue( double r )
00803 {
00804     if ( !d->referencePoint ) return;
00805     ++d->blockRelative;
00806     setValue( r * d->referencePoint );
00807     --d->blockRelative;
00808 }
00809 
00810 void KDoubleNumInput::setReferencePoint( double ref )
00811 {
00812     // clip to valid range:
00813     ref = qMin( maximum(), qMax( minimum(), ref ) );
00814     d->referencePoint = ref;
00815 }
00816 
00817 void KDoubleNumInput::setRange(double lower, double upper, double step,
00818                                                            bool slider)
00819 {
00820     K_USING_KNUMINPUT_P(priv);
00821 
00822     if( priv->m_slider ) {
00823         // don't update the slider to avoid an endless recursion
00824         QDoubleSpinBox * spin = d->spin;
00825         disconnect(spin, SIGNAL(valueChanged(int)),
00826                 priv->m_slider, SLOT(setValue(int)) );
00827     }
00828     d->spin->setRange( lower, upper);
00829     d->spin->setSingleStep(step);
00830 
00831     if(slider) {
00832         // upcast to base type to get the minimum/maximum in int form:
00833         QDoubleSpinBox * spin = d->spin;
00834         int slmax = spin->maximum();
00835         int slmin = spin->minimum();
00836         int slvalue = spin->value();
00837         int slstep = spin->singleStep();
00838         if (priv->m_slider) {
00839             priv->m_slider->setRange(slmin, slmax);
00840             priv->m_slider->setSingleStep(slstep);
00841             priv->m_slider->setValue(slvalue);
00842         } else {
00843             priv->m_slider = new QSlider(Qt::Horizontal, this);
00844             priv->m_slider->setMinimum(slmin);
00845             priv->m_slider->setMaximum(slmax);
00846             priv->m_slider->setSingleStep(slstep);
00847             priv->m_slider->setValue(slvalue);
00848             priv->m_slider->setTickPosition(QSlider::TicksBelow);
00849             // feedback line: when one moves, the other moves, too:
00850             connect(priv->m_slider, SIGNAL(valueChanged(int)),
00851                     SLOT(sliderMoved(int)) );
00852         }
00853         connect(spin, SIGNAL(valueChanged(double)), SLOT(spinBoxChanged(double)) );
00854         // calculate ( slmax - slmin ) / 10 without overflowing ints:
00855         int major = calcDiffByTen( slmax, slmin );
00856         if ( !major ) major = slstep; // ### needed?
00857         priv->m_slider->setTickInterval(major);
00858     } else {
00859         delete priv->m_slider;
00860         priv->m_slider = 0;
00861     }
00862 
00863     setReferencePoint( referencePoint() );
00864 
00865     layout(true);
00866     updateLegacyMembers();
00867 }
00868 
00869 void KDoubleNumInput::setMinimum(double min)
00870 {
00871     K_USING_KNUMINPUT_P(priv);
00872     setRange(min, maximum(), d->spin->singleStep(), priv->m_slider);
00873 }
00874 
00875 double KDoubleNumInput::minimum() const
00876 {
00877     return d->spin->minimum();
00878 }
00879 
00880 void KDoubleNumInput::setMaximum(double max)
00881 {
00882     K_USING_KNUMINPUT_P(priv);
00883     setRange(minimum(), max, d->spin->singleStep(), priv->m_slider);
00884 }
00885 
00886 double KDoubleNumInput::maximum() const
00887 {
00888     return d->spin->maximum();
00889 }
00890 
00891 double KDoubleNumInput::value() const
00892 {
00893     return d->spin->value();
00894 }
00895 
00896 double KDoubleNumInput::relativeValue() const
00897 {
00898     if ( !d->referencePoint ) return 0;
00899     return value() / d->referencePoint;
00900 }
00901 
00902 double KDoubleNumInput::referencePoint() const
00903 {
00904     return d->referencePoint;
00905 }
00906 
00907 QString KDoubleNumInput::suffix() const
00908 {
00909     return d->spin->suffix();
00910 }
00911 
00912 QString KDoubleNumInput::prefix() const
00913 {
00914     return d->spin->prefix();
00915 }
00916 
00917 void KDoubleNumInput::setSuffix(const QString &suffix)
00918 {
00919     d->spin->setSuffix( suffix );
00920 
00921     layout(true);
00922 }
00923 
00924 void KDoubleNumInput::setPrefix(const QString &prefix)
00925 {
00926     d->spin->setPrefix( prefix );
00927 
00928     layout(true);
00929 }
00930 
00931 void KDoubleNumInput::setDecimals(int decimals)
00932 {
00933     d->spin->setDecimals(decimals);
00934 
00935     layout(true);
00936 }
00937 
00938 int KDoubleNumInput::decimals() const
00939 {
00940     return d->spin->decimals();
00941 }
00942 
00943 void KDoubleNumInput::setSpecialValueText(const QString& text)
00944 {
00945     d->spin->setSpecialValueText( text );
00946 
00947     layout(true);
00948     updateLegacyMembers();
00949 }
00950 
00951 void KDoubleNumInput::setLabel(const QString & label, Qt::Alignment a)
00952 {
00953     K_USING_KNUMINPUT_P(priv);
00954 
00955     KNumInput::setLabel(label, a);
00956 
00957     if(priv->m_label)
00958         priv->m_label->setBuddy(d->spin);
00959 
00960 }
00961 
00962 #include "knuminput.moc"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal