summaryrefslogtreecommitdiff
path: root/noncore/settings/networksettings/ppp/knuminput.cpp
Unidiff
Diffstat (limited to 'noncore/settings/networksettings/ppp/knuminput.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/settings/networksettings/ppp/knuminput.cpp1103
1 files changed, 1103 insertions, 0 deletions
diff --git a/noncore/settings/networksettings/ppp/knuminput.cpp b/noncore/settings/networksettings/ppp/knuminput.cpp
new file mode 100644
index 0000000..afaa581
--- a/dev/null
+++ b/noncore/settings/networksettings/ppp/knuminput.cpp
@@ -0,0 +1,1103 @@
1// -*- c-basic-offset: 4 -*-
2/*
3 * knuminput.cpp
4 *
5 * Initial implementation:
6 * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca>
7 * Rewritten and maintained by:
8 * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org>
9 * KDoubleSpinBox:
10 * Copyright (c) 2002 Marc Mutz <mutz@kde.org>
11 *
12 * Requires the Qt widget libraries, available at no cost at
13 * http://www.troll.no/
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Library General Public
17 * License as published by the Free Software Foundation; either
18 * version 2 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Library General Public License for more details.
24 *
25 * You should have received a copy of the GNU Library General Public License
26 * along with this library; see the file COPYING.LIB. If not, write to
27 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28 * Boston, MA 02111-1307, USA.
29 */
30
31//#include <config.h>
32#ifdef HAVE_LIMITS_H
33#include <limits.h>
34#endif
35#include <assert.h>
36#include <math.h>
37#include <algorithm>
38
39#include <qlabel.h>
40#include <qlineedit.h>
41#include <qsize.h>
42#include <qslider.h>
43#include <qspinbox.h>
44#include <qstyle.h>
45
46//#include <kglobal.h>
47
48template<class T>
49inline const T& kMin (const T& a, const T& b) { return a < b ? a : b; }
50
51template<class T>
52inline const T& kMax (const T& a, const T& b) { return b < a ? a : b; }
53
54//#include <klocale.h>
55#define i18n QObject::tr
56//#include <kdebug.h>
57
58#include "knumvalidator.h"
59#include "knuminput.h"
60
61static inline int calcDiffByTen( int x, int y ) {
62 // calculate ( x - y ) / 10 without overflowing ints:
63 return ( x / 10 ) - ( y / 10 ) + ( x % 10 - y % 10 ) / 10;
64};
65
66// ----------------------------------------------------------------------------
67
68KNumInput::KNumInput(QWidget* parent, const char* name)
69 : QWidget(parent, name)
70{
71 init();
72}
73
74KNumInput::KNumInput(KNumInput* below, QWidget* parent, const char* name)
75 : QWidget(parent, name)
76{
77 init();
78
79 if(below) {
80 m_next = below->m_next;
81 m_prev = below;
82 below->m_next = this;
83 if(m_next)
84 m_next->m_prev = this;
85 }
86}
87
88void KNumInput::init()
89{
90 m_prev = m_next = 0;
91 m_colw1 = m_colw2 = 0;
92
93 m_label = 0;
94 m_slider = 0;
95 m_alignment = 0;
96}
97
98KNumInput::~KNumInput()
99{
100 if(m_prev)
101 m_prev->m_next = m_next;
102
103 if(m_next)
104 m_next->m_prev = m_prev;
105}
106
107void KNumInput::setLabel(const QString & label, int a)
108{
109 if(label.isEmpty()) {
110 delete m_label;
111 m_label = 0;
112 m_alignment = 0;
113 }
114 else {
115 if (m_label) m_label->setText(label);
116 else m_label = new QLabel(label, this, "KNumInput::QLabel");
117 m_label->setAlignment((a & (~(AlignTop|AlignBottom|AlignVCenter)))
118 | AlignVCenter);
119 // if no vertical alignment set, use Top alignment
120 if(!(a & (AlignTop|AlignBottom|AlignVCenter)))
121 a |= AlignTop;
122 m_alignment = a;
123 }
124
125 layout(true);
126}
127
128QString KNumInput::label() const
129{
130 if (m_label) return m_label->text();
131 return QString::null;
132}
133
134void KNumInput::layout(bool deep)
135{
136 int w1 = m_colw1;
137 int w2 = m_colw2;
138
139 // label sizeHint
140 m_sizeLabel = (m_label ? m_label->sizeHint() : QSize(0,0));
141
142 if(m_label && (m_alignment & AlignVCenter))
143 m_colw1 = m_sizeLabel.width() + 4;
144 else
145 m_colw1 = 0;
146
147 // slider sizeHint
148 m_sizeSlider = (m_slider ? m_slider->sizeHint() : QSize(0, 0));
149
150 doLayout();
151
152 if(!deep) {
153 m_colw1 = w1;
154 m_colw2 = w2;
155 return;
156 }
157
158 KNumInput* p = this;
159 while(p) {
160 p->doLayout();
161 w1 = QMAX(w1, p->m_colw1);
162 w2 = QMAX(w2, p->m_colw2);
163 p = p->m_prev;
164 }
165
166 p = m_next;
167 while(p) {
168 p->doLayout();
169 w1 = QMAX(w1, p->m_colw1);
170 w2 = QMAX(w2, p->m_colw2);
171 p = p->m_next;
172 }
173
174 p = this;
175 while(p) {
176 p->m_colw1 = w1;
177 p->m_colw2 = w2;
178 p = p->m_prev;
179 }
180
181 p = m_next;
182 while(p) {
183 p->m_colw1 = w1;
184 p->m_colw2 = w2;
185 p = p->m_next;
186 }
187
188// kdDebug() << "w1 " << w1 << " w2 " << w2 << endl;
189}
190
191QSizePolicy KNumInput::sizePolicy() const
192{
193 return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
194}
195
196QSize KNumInput::sizeHint() const
197{
198 return minimumSizeHint();
199}
200
201void KNumInput::setSteps(int minor, int major)
202{
203 if(m_slider)
204 m_slider->setSteps( minor, major );
205}
206
207
208// ----------------------------------------------------------------------------
209
210KIntSpinBox::KIntSpinBox(QWidget *parent, const char *name)
211 : QSpinBox(0, 99, 1, parent, name)
212{
213 editor()->setAlignment(AlignRight);
214 val_base = 10;
215 setValue(0);
216}
217
218KIntSpinBox::~KIntSpinBox()
219{
220}
221
222KIntSpinBox::KIntSpinBox(int lower, int upper, int step, int value, int base,
223 QWidget* parent, const char* name)
224 : QSpinBox(lower, upper, step, parent, name)
225{
226 editor()->setAlignment(AlignRight);
227 val_base = base;
228 setValue(value);
229}
230
231void KIntSpinBox::setBase(int base)
232{
233 val_base = base;
234}
235
236
237int KIntSpinBox::base() const
238{
239 return val_base;
240}
241
242QString KIntSpinBox::mapValueToText(int v)
243{
244 return QString::number(v, val_base);
245}
246
247int KIntSpinBox::mapTextToValue(bool* ok)
248{
249 return cleanText().toInt(ok, val_base);
250}
251
252void KIntSpinBox::setEditFocus(bool mark)
253{
254 editor()->setFocus();
255 if(mark)
256 editor()->selectAll();
257}
258
259
260// ----------------------------------------------------------------------------
261
262class KIntNumInput::KIntNumInputPrivate {
263public:
264 int referencePoint;
265 short blockRelative;
266 KIntNumInputPrivate( int r )
267 : referencePoint( r ),
268 blockRelative( 0 ) {}
269};
270
271
272KIntNumInput::KIntNumInput(KNumInput* below, int val, QWidget* parent,
273 int _base, const char* name)
274 : KNumInput(below, parent, name)
275{
276 init(val, _base);
277}
278
279KIntNumInput::KIntNumInput(QWidget *parent, const char *name)
280 : KNumInput(parent, name)
281{
282 init(0, 10);
283}
284
285KIntNumInput::KIntNumInput(int val, QWidget *parent, int _base, const char *name)
286 : KNumInput(parent, name)
287{
288 init(val, _base);
289
290}
291
292void KIntNumInput::init(int val, int _base)
293{
294 d = new KIntNumInputPrivate( val );
295 m_spin = new KIntSpinBox(INT_MIN, INT_MAX, 1, val, _base, this, "KIntNumInput::KIntSpinBox");
296 m_spin->setValidator(new KIntValidator(this, _base, "KNumInput::KIntValidtr"));
297 connect(m_spin, SIGNAL(valueChanged(int)), SLOT(spinValueChanged(int)));
298 connect(this, SIGNAL(valueChanged(int)),
299 SLOT(slotEmitRelativeValueChanged(int)));
300
301 setFocusProxy(m_spin);
302 layout(true);
303}
304
305void KIntNumInput::setReferencePoint( int ref ) {
306 // clip to valid range:
307 ref = kMin( maxValue(), kMax( minValue(), ref ) );
308 d->referencePoint = ref;
309}
310
311int KIntNumInput::referencePoint() const {
312 return d->referencePoint;
313}
314
315void KIntNumInput::spinValueChanged(int val)
316{
317 if(m_slider)
318 m_slider->setValue(val);
319
320 emit valueChanged(val);
321}
322
323void KIntNumInput::slotEmitRelativeValueChanged( int value ) {
324 if ( d->blockRelative || !d->referencePoint ) return;
325 emit relativeValueChanged( double( value ) / double( d->referencePoint ) );
326}
327
328void KIntNumInput::setRange(int lower, int upper, int step, bool slider)
329{
330 upper = kMax(upper, lower);
331 lower = kMin(upper, lower);
332 m_spin->setMinValue(lower);
333 m_spin->setMaxValue(upper);
334 m_spin->setLineStep(step);
335
336 step = m_spin->lineStep(); // maybe QRangeControl didn't like out lineStep?
337
338 if(slider) {
339 if (m_slider)
340 m_slider->setRange(lower, upper);
341 else {
342 m_slider = new QSlider(lower, upper, step, m_spin->value(),
343 QSlider::Horizontal, this);
344 m_slider->setTickmarks(QSlider::Below);
345 connect(m_slider, SIGNAL(valueChanged(int)),
346 m_spin, SLOT(setValue(int)));
347 }
348
349 // calculate (upper-lower)/10 without overflowing int's:
350 int major = calcDiffByTen( upper, lower );
351 if ( major==0 ) major = step; // #### workaround Qt bug in 2.1-beta4
352
353 m_slider->setSteps(step, major);
354 m_slider->setTickInterval(major);
355 }
356 else {
357 delete m_slider;
358 m_slider = 0;
359 }
360
361 // check that reference point is still inside valid range:
362 setReferencePoint( referencePoint() );
363
364 layout(true);
365}
366
367void KIntNumInput::setMinValue(int min)
368{
369 setRange(min, m_spin->maxValue(), m_spin->lineStep(), m_slider);
370}
371
372int KIntNumInput::minValue() const
373{
374 return m_spin->minValue();
375}
376
377void KIntNumInput::setMaxValue(int max)
378{
379 setRange(m_spin->minValue(), max, m_spin->lineStep(), m_slider);
380}
381
382int KIntNumInput::maxValue() const
383{
384 return m_spin->maxValue();
385}
386
387void KIntNumInput::setSuffix(const QString &suffix)
388{
389 m_spin->setSuffix(suffix);
390
391 layout(true);
392}
393
394QString KIntNumInput::suffix() const
395{
396 return m_spin->suffix();
397}
398
399void KIntNumInput::setPrefix(const QString &prefix)
400{
401 m_spin->setPrefix(prefix);
402
403 layout(true);
404}
405
406QString KIntNumInput::prefix() const
407{
408 return m_spin->prefix();
409}
410
411void KIntNumInput::setEditFocus(bool mark)
412{
413 m_spin->setEditFocus(mark);
414}
415
416QSize KIntNumInput::minimumSizeHint() const
417{
418 constPolish();
419
420 int w;
421 int h;
422
423 h = 2 + QMAX(m_sizeSpin.height(), m_sizeSlider.height());
424
425 // if in extra row, then count it here
426 if(m_label && (m_alignment & (AlignBottom|AlignTop)))
427 h += 4 + m_sizeLabel.height();
428 else
429 // label is in the same row as the other widgets
430 h = QMAX(h, m_sizeLabel.height() + 2);
431
432 w = m_slider ? m_slider->sizeHint().width() + 8 : 0;
433 w += m_colw1 + m_colw2;
434
435 if(m_alignment & (AlignTop|AlignBottom))
436 w = QMAX(w, m_sizeLabel.width() + 4);
437
438 return QSize(w, h);
439}
440
441void KIntNumInput::doLayout()
442{
443 m_sizeSpin = m_spin->sizeHint();
444 m_colw2 = m_sizeSpin.width();
445
446 if (m_label)
447 m_label->setBuddy(m_spin);
448}
449
450void KIntNumInput::resizeEvent(QResizeEvent* e)
451{
452 int w = m_colw1;
453 int h = 0;
454
455 if(m_label && (m_alignment & AlignTop)) {
456 m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height());
457 h += m_sizeLabel.height() + 4;
458 }
459
460 if(m_label && (m_alignment & AlignVCenter))
461 m_label->setGeometry(0, 0, w, m_sizeSpin.height());
462
463 m_spin->setGeometry(w, h, m_slider ? m_colw2 : QMAX(m_colw2, e->size().width() - w), m_sizeSpin.height());
464 w += m_colw2 + 8;
465
466 if(m_slider)
467 m_slider->setGeometry(w, h, e->size().width() - w, m_sizeSpin.height());
468
469 h += m_sizeSpin.height() + 2;
470
471 if(m_label && (m_alignment & AlignBottom))
472 m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height());
473}
474
475KIntNumInput::~KIntNumInput()
476{
477 delete d;
478}
479
480void KIntNumInput::setValue(int val)
481{
482 m_spin->setValue(val);
483 // slider value is changed by spinValueChanged
484}
485
486void KIntNumInput::setRelativeValue( double r ) {
487 if ( !d->referencePoint ) return;
488 ++d->blockRelative;
489 setValue( int( d->referencePoint * r + 0.5 ) );
490 --d->blockRelative;
491}
492
493double KIntNumInput::relativeValue() const {
494 if ( !d->referencePoint ) return 0;
495 return double( value() ) / double ( d->referencePoint );
496}
497
498int KIntNumInput::value() const
499{
500 return m_spin->value();
501}
502
503void KIntNumInput::setSpecialValueText(const QString& text)
504{
505 m_spin->setSpecialValueText(text);
506 layout(true);
507};
508
509QString KIntNumInput::specialValueText() const
510{
511 return m_spin->specialValueText();
512}
513
514void KIntNumInput::setLabel(const QString & label, int a)
515{
516 KNumInput::setLabel(label, a);
517
518 if(m_label)
519 m_label->setBuddy(m_spin);
520}
521
522// ----------------------------------------------------------------------------
523
524class KDoubleNumInput::KDoubleNumInputPrivate {
525public:
526 KDoubleNumInputPrivate( double r )
527 : spin( 0 ),
528 referencePoint( r ),
529 blockRelative ( 0 ) {}
530 KDoubleSpinBox * spin;
531 double referencePoint;
532 short blockRelative;
533};
534
535KDoubleNumInput::KDoubleNumInput(QWidget *parent, const char *name)
536 : KNumInput(parent, name)
537{
538 init(0.0, 0.0, 9999.0, 0.01, 2);
539}
540
541KDoubleNumInput::KDoubleNumInput(double lower, double upper, double value,
542 double step, int precision, QWidget* parent,
543 const char *name)
544 : KNumInput(parent, name)
545{
546 init(value, lower, upper, step, precision);
547}
548
549KDoubleNumInput::KDoubleNumInput(KNumInput *below,
550 double lower, double upper, double value,
551 double step, int precision, QWidget* parent,
552 const char *name)
553 : KNumInput(below, parent, name)
554{
555 init(value, lower, upper, step, precision);
556}
557
558KDoubleNumInput::KDoubleNumInput(double value, QWidget *parent, const char *name)
559 : KNumInput(parent, name)
560{
561 init(value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 );
562}
563
564KDoubleNumInput::KDoubleNumInput(KNumInput* below, double value, QWidget* parent,
565 const char* name)
566 : KNumInput(below, parent, name)
567{
568 init( value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 );
569}
570
571KDoubleNumInput::~KDoubleNumInput()
572{
573 delete d;
574}
575
576// ### remove when BIC changes are allowed again:
577
578bool KDoubleNumInput::eventFilter( QObject * o, QEvent * e ) {
579 return KNumInput::eventFilter( o, e );
580}
581
582void KDoubleNumInput::resetEditBox() {
583
584}
585
586// ### end stuff to remove when BIC changes are allowed again
587
588
589
590void KDoubleNumInput::init(double value, double lower, double upper,
591 double step, int precision )
592{
593 // ### init no longer used members:
594 edit = 0;
595 m_range = true;
596 m_value = 0.0;
597 m_precision = 2;
598 // ### end
599
600 d = new KDoubleNumInputPrivate( value );
601
602 d->spin = new KDoubleSpinBox( lower, upper, step, value, precision,
603 this, "KDoubleNumInput::d->spin" );
604 setFocusProxy(d->spin);
605 connect( d->spin, SIGNAL(valueChanged(double)),
606 this, SIGNAL(valueChanged(double)) );
607 connect( this, SIGNAL(valueChanged(double)),
608 this, SLOT(slotEmitRelativeValueChanged(double)) );
609
610 updateLegacyMembers();
611
612 layout(true);
613}
614
615void KDoubleNumInput::updateLegacyMembers() {
616 // ### update legacy members that are either not private or for
617 // which an inlined getter exists:
618 m_lower = minValue();
619 m_upper = maxValue();
620 m_step = d->spin->lineStep();
621 m_specialvalue = specialValueText();
622}
623
624
625double KDoubleNumInput::mapSliderToSpin( int val ) const
626{
627 // map [slidemin,slidemax] to [spinmin,spinmax]
628 double spinmin = d->spin->minValue();
629 double spinmax = d->spin->maxValue();
630 double slidemin = m_slider->minValue(); // cast int to double to avoid
631 double slidemax = m_slider->maxValue(); // overflow in rel denominator
632 double rel = ( double(val) - slidemin ) / ( slidemax - slidemin );
633 return spinmin + rel * ( spinmax - spinmin );
634}
635
636void KDoubleNumInput::sliderMoved(int val)
637{
638 d->spin->setValue( mapSliderToSpin( val ) );
639}
640
641void KDoubleNumInput::slotEmitRelativeValueChanged( double value )
642{
643 if ( !d->referencePoint ) return;
644 emit relativeValueChanged( value / d->referencePoint );
645}
646
647QSize KDoubleNumInput::minimumSizeHint() const
648{
649 constPolish();
650
651 int w;
652 int h;
653
654 h = 2 + QMAX(m_sizeEdit.height(), m_sizeSlider.height());
655
656 // if in extra row, then count it here
657 if(m_label && (m_alignment & (AlignBottom|AlignTop)))
658 h += 4 + m_sizeLabel.height();
659 else
660 // label is in the same row as the other widgets
661 h = QMAX(h, m_sizeLabel.height() + 2);
662
663 w = m_slider ? m_slider->sizeHint().width() + 8 : 0;
664 w += m_colw1 + m_colw2;
665
666 if(m_alignment & (AlignTop|AlignBottom))
667 w = QMAX(w, m_sizeLabel.width() + 4);
668
669 return QSize(w, h);
670}
671
672void KDoubleNumInput::resizeEvent(QResizeEvent* e)
673{
674 int w = m_colw1;
675 int h = 0;
676
677 if(m_label && (m_alignment & AlignTop)) {
678 m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height());
679 h += m_sizeLabel.height() + 4;
680 }
681
682 if(m_label && (m_alignment & AlignVCenter))
683 m_label->setGeometry(0, 0, w, m_sizeEdit.height());
684
685 d->spin->setGeometry(w, h, m_slider ? m_colw2
686 : e->size().width() - w, m_sizeEdit.height());
687 w += m_colw2 + 8;
688
689 if(m_slider)
690 m_slider->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height());
691
692 h += m_sizeEdit.height() + 2;
693
694 if(m_label && (m_alignment & AlignBottom))
695 m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height());
696}
697
698void KDoubleNumInput::doLayout()
699{
700 m_sizeEdit = d->spin->sizeHint();
701 m_colw2 = m_sizeEdit.width();
702}
703
704void KDoubleNumInput::setValue(double val)
705{
706 d->spin->setValue( val );
707}
708
709void KDoubleNumInput::setRelativeValue( double r )
710{
711 if ( !d->referencePoint ) return;
712 ++d->blockRelative;
713 setValue( r * d->referencePoint );
714 --d->blockRelative;
715}
716
717void KDoubleNumInput::setReferencePoint( double ref )
718{
719 // clip to valid range:
720 ref = kMin( maxValue(), kMax( minValue(), ref ) );
721 d->referencePoint = ref;
722}
723
724void KDoubleNumInput::setRange(double lower, double upper, double step,
725 bool slider)
726{
727 if( m_slider ) {
728 // don't update the slider to avoid an endless recursion
729 QSpinBox * spin = d->spin;
730 disconnect(spin, SIGNAL(valueChanged(int)),
731 m_slider, SLOT(setValue(int)) );
732 }
733 d->spin->setRange( lower, upper, step, d->spin->precision() );
734
735 if(slider) {
736 // upcast to base type to get the min/maxValue in int form:
737 QSpinBox * spin = d->spin;
738 int slmax = spin->maxValue();
739 int slmin = spin->minValue();
740 int slvalue = spin->value();
741 int slstep = spin->lineStep();
742 if (m_slider) {
743 m_slider->setRange(slmin, slmax);
744 m_slider->setLineStep(slstep);
745 m_slider->setValue(slvalue);
746 } else {
747 m_slider = new QSlider(slmin, slmax, slstep, slvalue,
748 QSlider::Horizontal, this);
749 m_slider->setTickmarks(QSlider::Below);
750 // feedback line: when one moves, the other moves, too:
751 connect(m_slider, SIGNAL(valueChanged(int)),
752 SLOT(sliderMoved(int)) );
753 }
754 connect(spin, SIGNAL(valueChanged(int)),
755 m_slider, SLOT(setValue(int)) );
756 // calculate ( slmax - slmin ) / 10 without overflowing ints:
757 int major = calcDiffByTen( slmax, slmin );
758 if ( !major ) major = slstep; // ### needed?
759 m_slider->setTickInterval(major);
760 } else {
761 delete m_slider;
762 m_slider = 0;
763 }
764
765 setReferencePoint( referencePoint() );
766
767 layout(true);
768 updateLegacyMembers();
769}
770
771void KDoubleNumInput::setMinValue(double min)
772{
773 setRange(min, maxValue(), d->spin->lineStep(), m_slider);
774}
775
776double KDoubleNumInput::minValue() const
777{
778 return d->spin->minValue();
779}
780
781void KDoubleNumInput::setMaxValue(double max)
782{
783 setRange(minValue(), max, d->spin->lineStep(), m_slider);
784}
785
786double KDoubleNumInput::maxValue() const
787{
788 return d->spin->maxValue();
789}
790
791double KDoubleNumInput::value() const
792{
793 return d->spin->value();
794}
795
796double KDoubleNumInput::relativeValue() const
797{
798 if ( !d->referencePoint ) return 0;
799 return value() / d->referencePoint;
800}
801
802double KDoubleNumInput::referencePoint() const
803{
804 return d->referencePoint;
805}
806
807QString KDoubleNumInput::suffix() const
808{
809 return d->spin->suffix();
810}
811
812QString KDoubleNumInput::prefix() const
813{
814 return d->spin->prefix();
815}
816
817void KDoubleNumInput::setSuffix(const QString &suffix)
818{
819 d->spin->setSuffix( suffix );
820
821 layout(true);
822}
823
824void KDoubleNumInput::setPrefix(const QString &prefix)
825{
826 d->spin->setPrefix( prefix );
827
828 layout(true);
829}
830
831void KDoubleNumInput::setPrecision(int precision)
832{
833 d->spin->setPrecision( precision );
834
835 layout(true);
836}
837
838int KDoubleNumInput::precision() const
839{
840 return d->spin->precision();
841}
842
843void KDoubleNumInput::setSpecialValueText(const QString& text)
844{
845 d->spin->setSpecialValueText( text );
846
847 layout(true);
848 updateLegacyMembers();
849};
850
851void KDoubleNumInput::setLabel(const QString & label, int a)
852{
853 KNumInput::setLabel(label, a);
854
855 if(m_label)
856 m_label->setBuddy(d->spin);
857
858}
859
860// ----------------------------------------------------------------------------
861
862
863// We use a kind of fixed-point arithmetic to represent the range of
864// doubles [mLower,mUpper] in steps of 10^(-mPrecision). Thus, the
865// following relations hold:
866//
867// 1. factor = 10^mPrecision
868// 2. basicStep = 1/factor = 10^(-mPrecision);
869// 3. lowerInt = lower * factor;
870// 4. upperInt = upper * factor;
871// 5. lower = lowerInt * basicStep;
872// 6. upper = upperInt * basicStep;
873class KDoubleSpinBox::Private {
874public:
875 Private( int precision=1 )
876 : mPrecision( precision ),
877 mValidator( 0 )
878 {
879 }
880
881 int factor() const {
882 int f = 1;
883 for ( int i = 0 ; i < mPrecision ; ++i ) f *= 10;
884 return f;
885 }
886
887 double basicStep() const {
888 return 1.0/double(factor());
889 }
890
891 int mapToInt( double value, bool * ok ) const {
892 assert( ok );
893 const double f = factor();
894 if ( value > double(INT_MAX) / f ) {
895// kdWarning() << "KDoubleSpinBox: can't represent value " << value
896 // << "in terms of fixed-point numbers with precision "
897 // << mPrecision << endl;
898 *ok = false;
899 return INT_MAX;
900 } else if ( value < double(INT_MIN) / f ) {
901// kdWarning() << "KDoubleSpinBox: can't represent value " << value
902 // << "in terms of fixed-point numbers with precision "
903 // << mPrecision << endl;
904 *ok = false;
905 return INT_MIN;
906 } else {
907 *ok = true;
908 return int( value * f + ( value < 0 ? -0.5 : 0.5 ) );
909 }
910 }
911
912 double mapToDouble( int value ) const {
913 return double(value) * basicStep();
914 }
915
916 int mPrecision;
917 KDoubleValidator * mValidator;
918};
919
920KDoubleSpinBox::KDoubleSpinBox( QWidget * parent, const char * name )
921 : QSpinBox( parent, name )
922{
923 editor()->setAlignment( Qt::AlignRight );
924 d = new Private();
925 updateValidator();
926}
927
928KDoubleSpinBox::KDoubleSpinBox( double lower, double upper, double step,
929 double value, int precision,
930 QWidget * parent, const char * name )
931 : QSpinBox( parent, name )
932{
933 editor()->setAlignment( Qt::AlignRight );
934 d = new Private();
935 setRange( lower, upper, step, precision );
936 setValue( value );
937 connect( this, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)) );
938}
939
940KDoubleSpinBox::~KDoubleSpinBox() {
941 delete d; d = 0;
942}
943
944bool KDoubleSpinBox::acceptLocalizedNumbers() const {
945 if ( !d->mValidator ) return true; // we'll set one that does;
946 // can't do it now, since we're const
947 return d->mValidator->acceptLocalizedNumbers();
948}
949
950void KDoubleSpinBox::setAcceptLocalizedNumbers( bool accept ) {
951 if ( !d->mValidator ) updateValidator();
952 d->mValidator->setAcceptLocalizedNumbers( accept );
953}
954
955void KDoubleSpinBox::setRange( double lower, double upper, double step,
956 int precision ) {
957 lower = kMin(upper, lower);
958 upper = kMax(upper, lower);
959 setPrecision( precision, true ); // disable bounds checking, since
960 setMinValue( lower ); // it's done in set{Min,Max}Value
961 setMaxValue( upper ); // anyway and we want lower, upper
962 setLineStep( step ); // and step to have the right precision
963}
964
965int KDoubleSpinBox::precision() const {
966 return d->mPrecision;
967}
968
969void KDoubleSpinBox::setPrecision( int precision ) {
970 setPrecision( precision, false );
971}
972
973void KDoubleSpinBox::setPrecision( int precision, bool force ) {
974 if ( precision < 1 ) return;
975 if ( !force ) {
976 int maxPrec = maxPrecision();
977 if ( precision > maxPrec )
978 precision = maxPrec;
979 }
980 d->mPrecision = precision;
981 updateValidator();
982}
983
984int KDoubleSpinBox::maxPrecision() const {
985 // INT_MAX must be > maxAbsValue * 10^precision
986 // ==> 10^precision < INT_MAX / maxAbsValue
987 // ==> precision < log10 ( INT_MAX / maxAbsValue )
988 // ==> maxPrecision = floor( log10 ( INT_MAX / maxAbsValue ) );
989 double maxAbsValue = kMax( fabs(minValue()), fabs(maxValue()) );
990 if ( maxAbsValue == 0 ) return 6; // return arbitrary value to avoid dbz...
991
992 return int( floor( log10( double(INT_MAX) / maxAbsValue ) ) );
993}
994
995double KDoubleSpinBox::value() const {
996 return d->mapToDouble( base::value() );
997}
998
999void KDoubleSpinBox::setValue( double value ) {
1000 if ( value == this->value() ) return;
1001 if ( value < minValue() )
1002 base::setValue( base::minValue() );
1003 else if ( value > maxValue() )
1004 base::setValue( base::maxValue() );
1005 else {
1006 bool ok = false;
1007 base::setValue( d->mapToInt( value, &ok ) );
1008 assert( ok );
1009 }
1010}
1011
1012double KDoubleSpinBox::minValue() const {
1013 return d->mapToDouble( base::minValue() );
1014}
1015
1016void KDoubleSpinBox::setMinValue( double value ) {
1017 bool ok = false;
1018 int min = d->mapToInt( value, &ok );
1019 if ( !ok ) return;
1020 base::setMinValue( min );
1021 updateValidator();
1022}
1023
1024
1025double KDoubleSpinBox::maxValue() const {
1026 return d->mapToDouble( base::maxValue() );
1027}
1028
1029void KDoubleSpinBox::setMaxValue( double value ) {
1030 bool ok = false;
1031 int max = d->mapToInt( value, &ok );
1032 if ( !ok ) return;
1033 base::setMaxValue( max );
1034 updateValidator();
1035}
1036
1037double KDoubleSpinBox::lineStep() const {
1038 return d->mapToDouble( base::lineStep() );
1039}
1040
1041void KDoubleSpinBox::setLineStep( double step ) {
1042 bool ok = false;
1043 if ( step > maxValue() - minValue() )
1044 base::setLineStep( 1 );
1045 else
1046 base::setLineStep( kMax( d->mapToInt( step, &ok ), 1 ) );
1047}
1048
1049QString KDoubleSpinBox::mapValueToText( int value ) {
1050// if ( acceptLocalizedNumbers() )
1051// return KGlobal::locale()
1052// ->formatNumber( d->mapToDouble( value ), d->mPrecision );
1053// else
1054 return QString().setNum( d->mapToDouble( value ), 'f', d->mPrecision );
1055}
1056
1057int KDoubleSpinBox::mapTextToValue( bool * ok ) {
1058 double value;
1059// if ( acceptLocalizedNumbers() )
1060// value = KGlobal::locale()->readNumber( cleanText(), ok );
1061// else
1062 value = cleanText().toDouble( ok );
1063 if ( !*ok ) return 0;
1064 if ( value > maxValue() )
1065 value = maxValue();
1066 else if ( value < minValue() )
1067 value = minValue();
1068 return d->mapToInt( value, ok );
1069}
1070
1071void KDoubleSpinBox::setValidator( const QValidator * ) {
1072 // silently discard the new validator. We don't want another one ;-)
1073}
1074
1075void KDoubleSpinBox::slotValueChanged( int value ) {
1076 emit valueChanged( d->mapToDouble( value ) );
1077}
1078
1079void KDoubleSpinBox::updateValidator() {
1080 if ( !d->mValidator ) {
1081 d->mValidator = new KDoubleValidator( minValue(), maxValue(), precision(),
1082 this, "d->mValidator" );
1083 base::setValidator( d->mValidator );
1084 } else
1085 d->mValidator->setRange( minValue(), maxValue(), precision() );
1086}
1087
1088void KNumInput::virtual_hook( int, void* )
1089{ /*BASE::virtual_hook( id, data );*/ }
1090
1091void KIntNumInput::virtual_hook( int id, void* data )
1092{ KNumInput::virtual_hook( id, data ); }
1093
1094void KDoubleNumInput::virtual_hook( int id, void* data )
1095{ KNumInput::virtual_hook( id, data ); }
1096
1097void KIntSpinBox::virtual_hook( int, void* )
1098{ /*BASE::virtual_hook( id, data );*/ }
1099
1100void KDoubleSpinBox::virtual_hook( int, void* )
1101{ /*BASE::virtual_hook( id, data );*/ }
1102
1103//#include "knuminput.moc"