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