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