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