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 }
01003
01004 KDoubleSpinBox::KDoubleSpinBox(
double lower,
double upper,
double step,
01005
double value,
int precision,
01006
QWidget * parent,
const char * name )
01007 :
QSpinBox( parent, name )
01008 {
01009
editor()->setAlignment( Qt::AlignRight );
01010 d =
new Private();
01011
setRange( lower, upper, step, precision );
01012
setValue( value );
01013 connect(
this, SIGNAL(
valueChanged(
int)), SLOT(slotValueChanged(
int)) );
01014 }
01015
01016 KDoubleSpinBox::~KDoubleSpinBox() {
01017
delete d; d = 0;
01018 }
01019
01020
bool KDoubleSpinBox::acceptLocalizedNumbers()
const {
01021
if ( !d->mValidator )
return true;
01022
01023
return d->mValidator->acceptLocalizedNumbers();
01024 }
01025
01026 void KDoubleSpinBox::setAcceptLocalizedNumbers(
bool accept ) {
01027
if ( !d->mValidator ) updateValidator();
01028 d->mValidator->setAcceptLocalizedNumbers( accept );
01029 }
01030
01031 void KDoubleSpinBox::setRange(
double lower,
double upper,
double step,
01032
int precision ) {
01033 lower = kMin(upper, lower);
01034 upper = kMax(upper, lower);
01035
setPrecision( precision,
true );
01036
setMinValue( lower );
01037
setMaxValue( upper );
01038
setLineStep( step );
01039 }
01040
01041
int KDoubleSpinBox::precision()
const {
01042
return d->mPrecision;
01043 }
01044
01045 void KDoubleSpinBox::setPrecision(
int precision ) {
01046
setPrecision( precision,
false );
01047 }
01048
01049 void KDoubleSpinBox::setPrecision(
int precision,
bool force ) {
01050
if ( precision < 1 )
return;
01051
if ( !force ) {
01052
int maxPrec = maxPrecision();
01053
if ( precision > maxPrec )
01054 precision = maxPrec;
01055 }
01056 d->mPrecision = precision;
01057 updateValidator();
01058 }
01059
01060
int KDoubleSpinBox::maxPrecision()
const {
01061
01062
01063
01064
01065
double maxAbsValue = kMax( fabs(
minValue()), fabs(
maxValue()) );
01066
if ( maxAbsValue == 0 )
return 6;
01067
01068
return int( floor( log10(
double(INT_MAX) / maxAbsValue ) ) );
01069 }
01070
01071 double KDoubleSpinBox::value()
const {
01072
return d->mapToDouble( base::value() );
01073 }
01074
01075 void KDoubleSpinBox::setValue(
double value ) {
01076
if ( value == this->
value() )
return;
01077
if ( value <
minValue() )
01078 base::setValue( base::minValue() );
01079
else if ( value >
maxValue() )
01080 base::setValue( base::maxValue() );
01081
else {
01082
bool ok =
false;
01083 base::setValue( d->mapToInt( value, &ok ) );
01084 assert( ok );
01085 }
01086 }
01087
01088 double KDoubleSpinBox::minValue()
const {
01089
return d->mapToDouble( base::minValue() );
01090 }
01091
01092 void KDoubleSpinBox::setMinValue(
double value ) {
01093
bool ok =
false;
01094
int min = d->mapToInt( value, &ok );
01095
if ( !ok )
return;
01096 base::setMinValue( min );
01097 updateValidator();
01098 }
01099
01100
01101 double KDoubleSpinBox::maxValue()
const {
01102
return d->mapToDouble( base::maxValue() );
01103 }
01104
01105 void KDoubleSpinBox::setMaxValue(
double value ) {
01106
bool ok =
false;
01107
int max = d->mapToInt( value, &ok );
01108
if ( !ok )
return;
01109 base::setMaxValue( max );
01110 updateValidator();
01111 }
01112
01113 double KDoubleSpinBox::lineStep()
const {
01114
return d->mapToDouble( base::lineStep() );
01115 }
01116
01117 void KDoubleSpinBox::setLineStep(
double step ) {
01118
bool ok =
false;
01119
if ( step >
maxValue() -
minValue() )
01120 base::setLineStep( 1 );
01121
else
01122 base::setLineStep( kMax( d->mapToInt( step, &ok ), 1 ) );
01123 }
01124
01125
QString KDoubleSpinBox::mapValueToText(
int value ) {
01126
if (
acceptLocalizedNumbers() )
01127
return KGlobal::locale()
01128 ->
formatNumber( d->mapToDouble( value ), d->mPrecision );
01129
else
01130
return QString().
setNum( d->mapToDouble( value ),
'f', d->mPrecision );
01131 }
01132
01133
int KDoubleSpinBox::mapTextToValue(
bool * ok ) {
01134
double value;
01135
if (
acceptLocalizedNumbers() )
01136 value =
KGlobal::locale()->
readNumber(
cleanText(), ok );
01137
else
01138 value =
cleanText().toDouble( ok );
01139
if ( !*ok )
return 0;
01140
if ( value >
maxValue() )
01141 value =
maxValue();
01142
else if ( value <
minValue() )
01143 value =
minValue();
01144
return d->mapToInt( value, ok );
01145 }
01146
01147 void KDoubleSpinBox::setValidator(
const QValidator * ) {
01148
01149 }
01150
01151
void KDoubleSpinBox::slotValueChanged(
int value ) {
01152 emit valueChanged( d->mapToDouble( value ) );
01153 }
01154
01155
void KDoubleSpinBox::updateValidator() {
01156
if ( !d->mValidator ) {
01157 d->mValidator =
new KDoubleSpinBoxValidator(
minValue(),
maxValue(),
precision(),
01158
this,
"d->mValidator" );
01159 base::setValidator( d->mValidator );
01160 }
else
01161 d->mValidator->setRange(
minValue(),
maxValue(),
precision() );
01162 }
01163
01164
void KNumInput::virtual_hook(
int,
void* )
01165 { }
01166
01167
void KIntNumInput::virtual_hook(
int id,
void* data )
01168 { KNumInput::virtual_hook(
id, data ); }
01169
01170
void KDoubleNumInput::virtual_hook(
int id,
void* data )
01171 { KNumInput::virtual_hook(
id, data ); }
01172
01173
void KIntSpinBox::virtual_hook(
int,
void* )
01174 { }
01175
01176
void KDoubleSpinBox::virtual_hook(
int,
void* )
01177 { }
01178
01179
#include "knuminput.moc"