38 #include <tqapplication.h>
40 #include <tqlineedit.h>
43 #include <tqspinbox.h>
46 #include <tdeglobal.h>
51 #include "knumvalidator.h"
52 #include "knuminput.h"
54 static inline int calcDiffByTen(
int x,
int y ) {
56 return ( x / 10 ) - ( y / 10 ) + ( x % 10 - y % 10 ) / 10;
62 : TQWidget(parent, name)
68 : TQWidget(parent, name)
73 m_next = below->m_next;
77 m_next->m_prev =
this;
81 void KNumInput::init()
84 m_colw1 = m_colw2 = 0;
91 KNumInput::~KNumInput()
94 m_prev->m_next = m_next;
97 m_next->m_prev = m_prev;
102 if(label.isEmpty()) {
108 if (m_label) m_label->setText(label);
109 else m_label =
new TQLabel(label,
this,
"KNumInput::TQLabel");
110 m_label->setAlignment((a & (~(AlignTop|AlignBottom|AlignVCenter)))
113 if(!(a & (AlignTop|AlignBottom|AlignVCenter)))
123 if (m_label)
return m_label->text();
124 return TQString::null;
133 m_sizeLabel = (m_label ? m_label->sizeHint() : TQSize(0,0));
135 if(m_label && (m_alignment & AlignVCenter))
136 m_colw1 = m_sizeLabel.width() + 4;
141 m_sizeSlider = (m_slider ? m_slider->sizeHint() : TQSize(0, 0));
154 w1 = TQMAX(w1, p->m_colw1);
155 w2 = TQMAX(w2, p->m_colw2);
162 w1 = TQMAX(w1, p->m_colw1);
163 w2 = TQMAX(w2, p->m_colw2);
186 return TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Fixed );
191 return minimumSizeHint();
197 m_slider->setSteps( minor, major );
204 : TQSpinBox(0, 99, 1, parent, name)
206 editor()->setAlignment(AlignRight);
217 TQWidget* parent,
const char* name)
218 : TQSpinBox(lower, upper, step, parent, name)
220 editor()->setAlignment(AlignRight);
243 return TQString::number(v, val_base);
248 return cleanText().toInt(ok, val_base);
253 editor()->setFocus();
255 editor()->selectAll();
261 class KIntNumInput::KIntNumInputPrivate {
265 KIntNumInputPrivate(
int r )
267 blockRelative( 0 ) {}
272 int _base,
const char* name)
291 void KIntNumInput::init(
int val,
int _base)
293 d =
new KIntNumInputPrivate( val );
294 m_spin =
new KIntSpinBox(INT_MIN, INT_MAX, 1, val, _base,
this,
"KIntNumInput::KIntSpinBox");
299 m_spin->setValidator(
new KIntValidator(
this, _base,
"KNumInput::KIntValidtr"));
301 connect(m_spin, TQT_SIGNAL(
valueChanged(
int)), TQT_SLOT(spinValueChanged(
int)));
303 TQT_SLOT(slotEmitRelativeValueChanged(
int)));
305 setFocusProxy(m_spin);
312 d->referencePoint = ref;
316 return d->referencePoint;
319 void KIntNumInput::spinValueChanged(
int val)
322 m_slider->setValue(val);
327 void KIntNumInput::slotEmitRelativeValueChanged(
int value ) {
328 if ( d->blockRelative || !d->referencePoint )
return;
334 upper = kMax(upper, lower);
335 lower = kMin(upper, lower);
336 m_spin->setMinValue(lower);
337 m_spin->setMaxValue(upper);
338 m_spin->setLineStep(step);
340 step = m_spin->lineStep();
344 m_slider->setRange(lower, upper);
346 m_slider =
new TQSlider(lower, upper, step, m_spin->value(),
347 Qt::Horizontal,
this);
348 m_slider->setTickmarks(TQSlider::Below);
354 int major = calcDiffByTen( upper, lower );
355 if ( major==0 ) major = step;
357 m_slider->setSteps(step, major);
358 m_slider->setTickInterval(major);
373 setRange(min, m_spin->maxValue(), m_spin->lineStep(), m_slider);
378 return m_spin->minValue();
383 setRange(m_spin->minValue(), max, m_spin->lineStep(), m_slider);
388 return m_spin->maxValue();
393 m_spin->setSuffix(suffix);
400 return m_spin->suffix();
405 m_spin->setPrefix(prefix);
412 return m_spin->prefix();
427 h = 2 + TQMAX(m_sizeSpin.height(), m_sizeSlider.height());
430 if(m_label && (m_alignment & (AlignBottom|AlignTop)))
431 h += 4 + m_sizeLabel.height();
434 h = TQMAX(h, m_sizeLabel.height() + 2);
436 w = m_slider ? m_slider->sizeHint().width() + 8 : 0;
437 w += m_colw1 + m_colw2;
439 if(m_alignment & (AlignTop|AlignBottom))
440 w = TQMAX(w, m_sizeLabel.width() + 4);
447 m_sizeSpin = m_spin->sizeHint();
448 m_colw2 = m_sizeSpin.width();
451 m_label->setBuddy(m_spin);
454 void KIntNumInput::resizeEvent(TQResizeEvent* e)
459 if(m_label && (m_alignment & AlignTop)) {
460 m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height());
464 if(m_label && (m_alignment & AlignVCenter))
465 m_label->setGeometry(0, 0, w, m_sizeSpin.height());
467 if (tqApp->reverseLayout())
469 m_spin->setGeometry(w, h, m_slider ? m_colw2 : TQMAX(m_colw2, e->size().width() - w), m_sizeSpin.height());
473 m_slider->setGeometry(w, h, e->size().width() - w, m_sizeSpin.height());
476 m_slider->setGeometry(w, h, e->size().width() - (w + m_colw2 +
KDialog::spacingHint()), m_sizeSpin.height());
477 m_spin->setGeometry(w + m_slider->size().width() +
KDialog::spacingHint(), h, m_colw2, m_sizeSpin.height());
480 m_spin->setGeometry(w, h, TQMAX(m_colw2, e->size().width() - w), m_sizeSpin.height());
483 h += m_sizeSpin.height() + 2;
485 if(m_label && (m_alignment & AlignBottom))
486 m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height());
496 m_spin->setValue(val);
501 if ( !d->referencePoint )
return;
503 setValue(
int( d->referencePoint * r + 0.5 ) );
508 if ( !d->referencePoint )
return 0;
509 return double(
value() ) / double ( d->referencePoint );
514 return m_spin->value();
519 m_spin->setSpecialValueText(text);
525 return m_spin->specialValueText();
533 m_label->setBuddy(m_spin);
538 class KDoubleNumInput::KDoubleNumInputPrivate {
540 KDoubleNumInputPrivate(
double r )
543 blockRelative ( 0 ) {}
552 init(0.0, 0.0, 9999.0, 0.01, 2);
556 double step,
int precision, TQWidget* parent,
560 init(value, lower, upper, step, precision);
564 double lower,
double upper,
double value,
565 double step,
int precision, TQWidget* parent,
569 init(value, lower, upper, step, precision);
575 init(value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 );
582 init( value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 );
592 bool KDoubleNumInput::eventFilter( TQObject * o, TQEvent * e ) {
593 return KNumInput::eventFilter( o, e );
596 void KDoubleNumInput::resetEditBox() {
604 void KDoubleNumInput::init(
double value,
double lower,
double upper,
605 double step,
int precision )
614 d =
new KDoubleNumInputPrivate( value );
616 d->spin =
new KDoubleSpinBox( lower, upper, step, value, precision,
617 this,
"KDoubleNumInput::d->spin" );
618 setFocusProxy(d->spin);
622 this, TQT_SLOT(slotEmitRelativeValueChanged(
double)) );
624 updateLegacyMembers();
629 void KDoubleNumInput::updateLegacyMembers() {
634 m_step = d->spin->lineStep();
639 double KDoubleNumInput::mapSliderToSpin(
int val )
const
642 double spinmin = d->spin->minValue();
643 double spinmax = d->spin->maxValue();
644 double slidemin = m_slider->minValue();
645 double slidemax = m_slider->maxValue();
646 double rel = ( double(val) - slidemin ) / ( slidemax - slidemin );
647 return spinmin + rel * ( spinmax - spinmin );
650 void KDoubleNumInput::sliderMoved(
int val)
652 d->spin->setValue( mapSliderToSpin( val ) );
655 void KDoubleNumInput::slotEmitRelativeValueChanged(
double value )
657 if ( !d->referencePoint )
return;
661 TQSize KDoubleNumInput::minimumSizeHint()
const
668 h = 2 + TQMAX(m_sizeEdit.height(), m_sizeSlider.height());
671 if(m_label && (m_alignment & (AlignBottom|AlignTop)))
672 h += 4 + m_sizeLabel.height();
675 h = TQMAX(h, m_sizeLabel.height() + 2);
677 w = m_slider ? m_slider->sizeHint().width() + 8 : 0;
678 w += m_colw1 + m_colw2;
680 if(m_alignment & (AlignTop|AlignBottom))
681 w = TQMAX(w, m_sizeLabel.width() + 4);
686 void KDoubleNumInput::resizeEvent(TQResizeEvent* e)
691 if(m_label && (m_alignment & AlignTop)) {
692 m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height());
693 h += m_sizeLabel.height() + 4;
696 if(m_label && (m_alignment & AlignVCenter))
697 m_label->setGeometry(0, 0, w, m_sizeEdit.height());
699 if (tqApp->reverseLayout())
701 d->spin->setGeometry(w, h, m_slider ? m_colw2
702 : e->size().width() - w, m_sizeEdit.height());
706 m_slider->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height());
709 m_slider->setGeometry(w, h, e->size().width() -
711 m_sizeEdit.height());
713 m_colw2, m_sizeEdit.height());
716 d->spin->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height());
719 h += m_sizeEdit.height() + 2;
721 if(m_label && (m_alignment & AlignBottom))
722 m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height());
727 m_sizeEdit = d->spin->sizeHint();
728 m_colw2 = m_sizeEdit.width();
733 d->spin->setValue( val );
738 if ( !d->referencePoint )
return;
748 d->referencePoint = ref;
756 TQSpinBox * spin = d->spin;
758 m_slider, TQT_SLOT(
setValue(
int)) );
760 d->spin->setRange( lower, upper, step, d->spin->precision() );
764 TQSpinBox * spin = d->spin;
765 int slmax = spin->maxValue();
766 int slmin = spin->minValue();
767 int slvalue = spin->value();
768 int slstep = spin->lineStep();
770 m_slider->setRange(slmin, slmax);
771 m_slider->setValue(slvalue);
773 m_slider =
new TQSlider(slmin, slmax, slstep, slvalue,
774 Qt::Horizontal,
this);
775 m_slider->setTickmarks(TQSlider::Below);
778 TQT_SLOT(sliderMoved(
int)) );
781 m_slider, TQT_SLOT(
setValue(
int)) );
783 int major = calcDiffByTen( slmax, slmin );
784 if ( !major ) major = slstep;
785 m_slider->setSteps(slstep, major);
786 m_slider->setTickInterval(major);
795 updateLegacyMembers();
805 return d->spin->minValue();
815 return d->spin->maxValue();
820 return d->spin->value();
825 if ( !d->referencePoint )
return 0;
826 return value() / d->referencePoint;
831 return d->referencePoint;
836 return d->spin->suffix();
841 return d->spin->prefix();
846 d->spin->setSuffix( suffix );
853 d->spin->setPrefix( prefix );
860 d->spin->setPrecision( precision );
863 TQSpinBox * spin = d->spin;
864 m_slider->setRange(spin->minValue(), spin->maxValue());
865 m_slider->setValue(spin->value());
866 int major = calcDiffByTen(spin->maxValue(), spin->minValue());
867 if ( !major ) major = spin->lineStep();
868 m_slider->setSteps(spin->lineStep(), major);
869 m_slider->setTickInterval(major);
877 return d->spin->precision();
882 d->spin->setSpecialValueText( text );
885 updateLegacyMembers();
893 m_label->setBuddy(d->spin);
903 KDoubleSpinBoxValidator(
double bottom,
double top,
int decimals,
KDoubleSpinBox* sb,
const char *name )
904 :
KDoubleValidator( bottom, top, decimals, TQT_TQOBJECT(sb), name ), spinBox( sb ) { }
906 virtual State
validate( TQString& str,
int& pos )
const;
914 TQString pref = spinBox->prefix();
915 TQString suff = spinBox->suffix();
916 TQString suffStriped = suff.stripWhiteSpace();
917 uint overhead = pref.length() + suff.length();
918 State state = Invalid;
920 if ( overhead == 0 ) {
923 bool stripedVersion =
false;
924 if ( str.length() >= overhead && str.startsWith(pref)
925 && (str.endsWith(suff)
926 || (stripedVersion = str.endsWith(suffStriped))) ) {
927 if ( stripedVersion )
928 overhead = pref.length() + suffStriped.length();
929 TQString core = str.mid( pref.length(), str.length() - overhead );
930 int corePos = pos - pref.length();
932 pos = corePos + pref.length();
933 str.replace( pref.length(), str.length() - overhead, core );
936 if ( state == Invalid ) {
938 TQString special = spinBox->specialValueText().stripWhiteSpace();
939 TQString candidate = str.stripWhiteSpace();
941 if ( special.startsWith(candidate) ) {
942 if ( candidate.length() == special.length() ) {
945 state = Intermediate;
964 class KDoubleSpinBox::Private {
966 Private(
int precision=1 )
967 : mPrecision( precision ),
974 for (
int i = 0 ; i < mPrecision ; ++i ) f *= 10;
978 double basicStep()
const {
979 return 1.0/double(factor());
982 int mapToInt(
double value,
bool * ok )
const {
984 const double f = factor();
985 if ( value >
double(INT_MAX) / f ) {
986 kdWarning() <<
"KDoubleSpinBox: can't represent value " << value
987 <<
"in terms of fixed-point numbers with precision "
988 << mPrecision <<
endl;
991 }
else if ( value <
double(INT_MIN) / f ) {
992 kdWarning() <<
"KDoubleSpinBox: can't represent value " << value
993 <<
"in terms of fixed-point numbers with precision "
994 << mPrecision <<
endl;
999 return int( value * f + ( value < 0 ? -0.5 : 0.5 ) );
1003 double mapToDouble(
int value )
const {
1004 return double(value) * basicStep();
1008 KDoubleSpinBoxValidator * mValidator;
1012 : TQSpinBox( parent, name )
1014 editor()->setAlignment( Qt::AlignRight );
1017 connect(
this, TQT_SIGNAL(
valueChanged(
int)), TQT_SLOT(slotValueChanged(
int)) );
1021 double value,
int precision,
1022 TQWidget * parent,
const char * name )
1023 : TQSpinBox( parent, name )
1025 editor()->setAlignment( Qt::AlignRight );
1027 setRange( lower, upper, step, precision );
1029 connect(
this, TQT_SIGNAL(
valueChanged(
int)), TQT_SLOT(slotValueChanged(
int)) );
1032 KDoubleSpinBox::~KDoubleSpinBox() {
1037 if ( !d->mValidator )
return true;
1039 return d->mValidator->acceptLocalizedNumbers();
1043 if ( !d->mValidator ) updateValidator();
1044 d->mValidator->setAcceptLocalizedNumbers( accept );
1049 lower = kMin(upper, lower);
1050 upper = kMax(upper, lower);
1058 return d->mPrecision;
1066 if ( precision < 0 )
return;
1068 int maxPrec = maxPrecision();
1069 if ( precision > maxPrec )
1071 precision = maxPrec;
1075 int oldPrecision = d->mPrecision;
1076 double oldValue =
value();
1081 if (precision != oldPrecision)
1091 int KDoubleSpinBox::maxPrecision()
const {
1097 if ( maxAbsValue == 0 )
return 6;
1099 return int( floor( log10(
double(INT_MAX) / maxAbsValue ) ) );
1103 return d->mapToDouble( base::value() );
1107 if ( value == this->
value() )
return;
1120 return d->mapToDouble( base::minValue() );
1125 int min = d->mapToInt( value, &ok );
1132 return d->mapToDouble( base::maxValue() );
1137 int max = d->mapToInt( value, &ok );
1143 return d->mapToDouble( base::lineStep() );
1154 TQString KDoubleSpinBox::mapValueToText(
int value ) {
1157 ->
formatNumber( d->mapToDouble( value ), d->mPrecision );
1159 return TQString().setNum( d->mapToDouble( value ),
'f', d->mPrecision );
1162 int KDoubleSpinBox::mapTextToValue(
bool * ok ) {
1167 value = cleanText().toDouble( ok );
1168 if ( !*ok )
return 0;
1173 return d->mapToInt( value, ok );
1180 void KDoubleSpinBox::slotValueChanged(
int value ) {
1184 void KDoubleSpinBox::updateValidator() {
1185 if ( !d->mValidator ) {
1187 this,
"d->mValidator" );
1193 void KNumInput::virtual_hook(
int,
void* )
1196 void KIntNumInput::virtual_hook(
int id,
void* data )
1197 { KNumInput::virtual_hook(
id, data ); }
1199 void KDoubleNumInput::virtual_hook(
int id,
void* data )
1200 { KNumInput::virtual_hook(
id, data ); }
1202 void KIntSpinBox::virtual_hook(
int,
void* )
1205 void KDoubleSpinBox::virtual_hook(
int,
void* )
1208 #include "knuminput.moc"