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