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