39 #include <tqapplication.h>
41 #include <tqlineedit.h>
44 #include <tqspinbox.h>
52 #include "knumvalidator.h"
53 #include "knuminput.h"
55 static inline int calcDiffByTen(
int x,
int y ) {
57 return ( x / 10 ) - ( y / 10 ) + ( x % 10 - y % 10 ) / 10;
63 : TQWidget(parent, name)
69 : TQWidget(parent, name)
74 m_next = below->m_next;
78 m_next->m_prev =
this;
82 void KNumInput::init()
85 m_colw1 = m_colw2 = 0;
92 KNumInput::~KNumInput()
95 m_prev->m_next = m_next;
98 m_next->m_prev = m_prev;
103 if(label.isEmpty()) {
109 if (m_label) m_label->setText(label);
110 else m_label =
new TQLabel(label,
this,
"KNumInput::TQLabel");
111 m_label->setAlignment((a & (~(AlignTop|AlignBottom|AlignVCenter)))
114 if(!(a & (AlignTop|AlignBottom|AlignVCenter)))
124 if (m_label)
return m_label->text();
125 return TQString::null;
134 m_sizeLabel = (m_label ? m_label->sizeHint() : TQSize(0,0));
136 if(m_label && (m_alignment & AlignVCenter))
137 m_colw1 = m_sizeLabel.width() + 4;
142 m_sizeSlider = (m_slider ? m_slider->sizeHint() : TQSize(0, 0));
155 w1 = QMAX(w1, p->m_colw1);
156 w2 = QMAX(w2, p->m_colw2);
163 w1 = QMAX(w1, p->m_colw1);
164 w2 = QMAX(w2, p->m_colw2);
187 return TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Fixed );
192 return minimumSizeHint();
198 m_slider->setSteps( minor, major );
205 : TQSpinBox(0, 99, 1, parent, name)
207 editor()->setAlignment(AlignRight);
218 TQWidget* parent,
const char* name)
219 : TQSpinBox(lower, upper, step, parent, name)
221 editor()->setAlignment(AlignRight);
244 return TQString::number(v, val_base);
249 return cleanText().toInt(ok, val_base);
254 editor()->setFocus();
256 editor()->selectAll();
262 class KIntNumInput::KIntNumInputPrivate {
266 KIntNumInputPrivate(
int r )
268 blockRelative( 0 ) {}
273 int _base,
const char* name)
292 void KIntNumInput::init(
int val,
int _base)
294 d =
new KIntNumInputPrivate( val );
295 m_spin =
new KIntSpinBox(INT_MIN, INT_MAX, 1, val, _base,
this,
"KIntNumInput::KIntSpinBox");
300 m_spin->setValidator(
new KIntValidator(
this, _base,
"KNumInput::KIntValidtr"));
302 connect(m_spin, TQT_SIGNAL(
valueChanged(
int)), TQT_SLOT(spinValueChanged(
int)));
304 TQT_SLOT(slotEmitRelativeValueChanged(
int)));
306 setFocusProxy(m_spin);
313 d->referencePoint = ref;
317 return d->referencePoint;
320 void KIntNumInput::spinValueChanged(
int val)
323 m_slider->setValue(val);
328 void KIntNumInput::slotEmitRelativeValueChanged(
int value ) {
329 if ( d->blockRelative || !d->referencePoint )
return;
335 upper = kMax(upper, lower);
336 lower = kMin(upper, lower);
337 m_spin->setMinValue(lower);
338 m_spin->setMaxValue(upper);
339 m_spin->setLineStep(step);
341 step = m_spin->lineStep();
345 m_slider->setRange(lower, upper);
347 m_slider =
new TQSlider(lower, upper, step, m_spin->value(),
348 Qt::Horizontal,
this);
349 m_slider->setTickmarks(TQSlider::Below);
355 int major = calcDiffByTen( upper, lower );
356 if ( major==0 ) major = step;
358 m_slider->setSteps(step, major);
359 m_slider->setTickInterval(major);
374 setRange(min, m_spin->maxValue(), m_spin->lineStep(), m_slider);
379 return m_spin->minValue();
384 setRange(m_spin->minValue(), max, m_spin->lineStep(), m_slider);
389 return m_spin->maxValue();
394 m_spin->setSuffix(suffix);
401 return m_spin->suffix();
406 m_spin->setPrefix(prefix);
413 return m_spin->prefix();
428 h = 2 + QMAX(m_sizeSpin.height(), m_sizeSlider.height());
431 if(m_label && (m_alignment & (AlignBottom|AlignTop)))
432 h += 4 + m_sizeLabel.height();
435 h = QMAX(h, m_sizeLabel.height() + 2);
437 w = m_slider ? m_slider->sizeHint().width() + 8 : 0;
438 w += m_colw1 + m_colw2;
440 if(m_alignment & (AlignTop|AlignBottom))
441 w = QMAX(w, m_sizeLabel.width() + 4);
448 m_sizeSpin = m_spin->sizeHint();
449 m_colw2 = m_sizeSpin.width();
452 m_label->setBuddy(m_spin);
455 void KIntNumInput::resizeEvent(TQResizeEvent* e)
460 if(m_label && (m_alignment & AlignTop)) {
461 m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height());
465 if(m_label && (m_alignment & AlignVCenter))
466 m_label->setGeometry(0, 0, w, m_sizeSpin.height());
468 if (tqApp->reverseLayout())
470 m_spin->setGeometry(w, h, m_slider ? m_colw2 : QMAX(m_colw2, e->size().width() - w), m_sizeSpin.height());
474 m_slider->setGeometry(w, h, e->size().width() - w, m_sizeSpin.height());
477 m_slider->setGeometry(w, h, e->size().width() - (w + m_colw2 +
KDialog::spacingHint()), m_sizeSpin.height());
478 m_spin->setGeometry(w + m_slider->size().width() +
KDialog::spacingHint(), h, m_colw2, m_sizeSpin.height());
481 m_spin->setGeometry(w, h, QMAX(m_colw2, e->size().width() - w), m_sizeSpin.height());
484 h += m_sizeSpin.height() + 2;
486 if(m_label && (m_alignment & AlignBottom))
487 m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height());
497 m_spin->setValue(val);
502 if ( !d->referencePoint )
return;
504 setValue(
int( d->referencePoint * r + 0.5 ) );
509 if ( !d->referencePoint )
return 0;
510 return double(
value() ) / double ( d->referencePoint );
515 return m_spin->value();
520 m_spin->setSpecialValueText(text);
526 return m_spin->specialValueText();
534 m_label->setBuddy(m_spin);
539 class KDoubleNumInput::KDoubleNumInputPrivate {
541 KDoubleNumInputPrivate(
double r )
544 blockRelative ( 0 ) {}
553 init(0.0, 0.0, 9999.0, 0.01, 2);
557 double step,
int precision, TQWidget* parent,
561 init(value, lower, upper, step, precision);
565 double lower,
double upper,
double value,
566 double step,
int precision, TQWidget* parent,
570 init(value, lower, upper, step, precision);
576 init(value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 );
583 init( value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 );
593 bool KDoubleNumInput::eventFilter( TQObject * o, TQEvent * e ) {
594 return KNumInput::eventFilter( o, e );
597 void KDoubleNumInput::resetEditBox() {
605 void KDoubleNumInput::init(
double value,
double lower,
double upper,
606 double step,
int precision )
615 d =
new KDoubleNumInputPrivate( value );
617 d->spin =
new KDoubleSpinBox( lower, upper, step, value, precision,
618 this,
"KDoubleNumInput::d->spin" );
619 setFocusProxy(d->spin);
623 this, TQT_SLOT(slotEmitRelativeValueChanged(
double)) );
625 updateLegacyMembers();
630 void KDoubleNumInput::updateLegacyMembers() {
635 m_step = d->spin->lineStep();
640 double KDoubleNumInput::mapSliderToSpin(
int val )
const
643 double spinmin = d->spin->minValue();
644 double spinmax = d->spin->maxValue();
645 double slidemin = m_slider->minValue();
646 double slidemax = m_slider->maxValue();
647 double rel = ( double(val) - slidemin ) / ( slidemax - slidemin );
648 return spinmin + rel * ( spinmax - spinmin );
651 void KDoubleNumInput::sliderMoved(
int val)
653 d->spin->setValue( mapSliderToSpin( val ) );
656 void KDoubleNumInput::slotEmitRelativeValueChanged(
double value )
658 if ( !d->referencePoint )
return;
662 TQSize KDoubleNumInput::minimumSizeHint()
const
669 h = 2 + QMAX(m_sizeEdit.height(), m_sizeSlider.height());
672 if(m_label && (m_alignment & (AlignBottom|AlignTop)))
673 h += 4 + m_sizeLabel.height();
676 h = QMAX(h, m_sizeLabel.height() + 2);
678 w = m_slider ? m_slider->sizeHint().width() + 8 : 0;
679 w += m_colw1 + m_colw2;
681 if(m_alignment & (AlignTop|AlignBottom))
682 w = QMAX(w, m_sizeLabel.width() + 4);
687 void KDoubleNumInput::resizeEvent(TQResizeEvent* e)
692 if(m_label && (m_alignment & AlignTop)) {
693 m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height());
694 h += m_sizeLabel.height() + 4;
697 if(m_label && (m_alignment & AlignVCenter))
698 m_label->setGeometry(0, 0, w, m_sizeEdit.height());
700 if (tqApp->reverseLayout())
702 d->spin->setGeometry(w, h, m_slider ? m_colw2
703 : e->size().width() - w, m_sizeEdit.height());
707 m_slider->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height());
710 m_slider->setGeometry(w, h, e->size().width() -
712 m_sizeEdit.height());
714 m_colw2, m_sizeEdit.height());
717 d->spin->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height());
720 h += m_sizeEdit.height() + 2;
722 if(m_label && (m_alignment & AlignBottom))
723 m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height());
728 m_sizeEdit = d->spin->sizeHint();
729 m_colw2 = m_sizeEdit.width();
734 d->spin->setValue( val );
739 if ( !d->referencePoint )
return;
749 d->referencePoint = ref;
757 TQSpinBox * spin = d->spin;
759 m_slider, TQT_SLOT(
setValue(
int)) );
761 d->spin->setRange( lower, upper, step, d->spin->precision() );
765 TQSpinBox * spin = d->spin;
766 int slmax = spin->maxValue();
767 int slmin = spin->minValue();
768 int slvalue = spin->value();
769 int slstep = spin->lineStep();
771 m_slider->setRange(slmin, slmax);
772 m_slider->setLineStep(slstep);
773 m_slider->setValue(slvalue);
775 m_slider =
new TQSlider(slmin, slmax, slstep, slvalue,
776 Qt::Horizontal,
this);
777 m_slider->setTickmarks(TQSlider::Below);
780 TQT_SLOT(sliderMoved(
int)) );
783 m_slider, TQT_SLOT(
setValue(
int)) );
785 int major = calcDiffByTen( slmax, slmin );
786 if ( !major ) major = slstep;
787 m_slider->setTickInterval(major);
796 updateLegacyMembers();
806 return d->spin->minValue();
816 return d->spin->maxValue();
821 return d->spin->value();
826 if ( !d->referencePoint )
return 0;
827 return value() / d->referencePoint;
832 return d->referencePoint;
837 return d->spin->suffix();
842 return d->spin->prefix();
847 d->spin->setSuffix( suffix );
854 d->spin->setPrefix( prefix );
861 d->spin->setPrecision( precision );
868 return d->spin->precision();
873 d->spin->setSpecialValueText( text );
876 updateLegacyMembers();
884 m_label->setBuddy(d->spin);
894 KDoubleSpinBoxValidator(
double bottom,
double top,
int decimals,
KDoubleSpinBox* sb,
const char *name )
895 :
KDoubleValidator( bottom, top, decimals, TQT_TQOBJECT(sb), name ), spinBox( sb ) { }
897 virtual State
validate( TQString& str,
int& pos )
const;
903 TQValidator::State KDoubleSpinBoxValidator::validate( TQString& str,
int& pos )
const
905 TQString pref = spinBox->prefix();
906 TQString suff = spinBox->suffix();
907 TQString suffStriped = suff.stripWhiteSpace();
908 uint overhead = pref.length() + suff.length();
909 State state = Invalid;
911 if ( overhead == 0 ) {
914 bool stripedVersion =
false;
915 if ( str.length() >= overhead && str.startsWith(pref)
916 && (str.endsWith(suff)
917 || (stripedVersion = str.endsWith(suffStriped))) ) {
918 if ( stripedVersion )
919 overhead = pref.length() + suffStriped.length();
920 TQString core = str.mid( pref.length(), str.length() - overhead );
921 int corePos = pos - pref.length();
923 pos = corePos + pref.length();
924 str.replace( pref.length(), str.length() - overhead, core );
927 if ( state == Invalid ) {
929 TQString special = spinBox->specialValueText().stripWhiteSpace();
930 TQString candidate = str.stripWhiteSpace();
932 if ( special.startsWith(candidate) ) {
933 if ( candidate.length() == special.length() ) {
936 state = Intermediate;
955 class KDoubleSpinBox::Private {
957 Private(
int precision=1 )
958 : mPrecision( precision ),
965 for (
int i = 0 ; i < mPrecision ; ++i ) f *= 10;
969 double basicStep()
const {
970 return 1.0/double(factor());
973 int mapToInt(
double value,
bool * ok )
const {
975 const double f = factor();
976 if ( value >
double(INT_MAX) / f ) {
977 kdWarning() <<
"KDoubleSpinBox: can't represent value " << value
978 <<
"in terms of fixed-point numbers with precision "
979 << mPrecision <<
endl;
982 }
else if ( value <
double(INT_MIN) / f ) {
983 kdWarning() <<
"KDoubleSpinBox: can't represent value " << value
984 <<
"in terms of fixed-point numbers with precision "
985 << mPrecision <<
endl;
990 return int( value * f + ( value < 0 ? -0.5 : 0.5 ) );
994 double mapToDouble(
int value )
const {
995 return double(value) * basicStep();
999 KDoubleSpinBoxValidator * mValidator;
1003 : TQSpinBox( parent, name )
1005 editor()->setAlignment( Qt::AlignRight );
1008 connect(
this, TQT_SIGNAL(
valueChanged(
int)), TQT_SLOT(slotValueChanged(
int)) );
1012 double value,
int precision,
1013 TQWidget * parent,
const char * name )
1014 : TQSpinBox( parent, name )
1016 editor()->setAlignment( Qt::AlignRight );
1018 setRange( lower, upper, step, precision );
1020 connect(
this, TQT_SIGNAL(
valueChanged(
int)), TQT_SLOT(slotValueChanged(
int)) );
1023 KDoubleSpinBox::~KDoubleSpinBox() {
1028 if ( !d->mValidator )
return true;
1030 return d->mValidator->acceptLocalizedNumbers();
1034 if ( !d->mValidator ) updateValidator();
1035 d->mValidator->setAcceptLocalizedNumbers( accept );
1040 lower = kMin(upper, lower);
1041 upper = kMax(upper, lower);
1049 return d->mPrecision;
1057 if ( precision < 1 )
return;
1059 int maxPrec = maxPrecision();
1060 if ( precision > maxPrec )
1061 precision = maxPrec;
1067 int KDoubleSpinBox::maxPrecision()
const {
1073 if ( maxAbsValue == 0 )
return 6;
1075 return int( floor( log10(
double(INT_MAX) / maxAbsValue ) ) );
1079 return d->mapToDouble( base::value() );
1083 if ( value == this->
value() )
return;
1085 base::setValue( base::minValue() );
1087 base::setValue( base::maxValue() );
1090 base::setValue( d->mapToInt( value, &ok ) );
1096 return d->mapToDouble( base::minValue() );
1101 int min = d->mapToInt( value, &ok );
1102 base::setMinValue( min );
1108 return d->mapToDouble( base::maxValue() );
1113 int max = d->mapToInt( value, &ok );
1114 base::setMaxValue( max );
1119 return d->mapToDouble( base::lineStep() );
1125 base::setLineStep( 1 );
1127 base::setLineStep( kMax( d->mapToInt( step, &ok ), 1 ) );
1130 TQString KDoubleSpinBox::mapValueToText(
int value ) {
1133 ->
formatNumber( d->mapToDouble( value ), d->mPrecision );
1135 return TQString().setNum( d->mapToDouble( value ),
'f', d->mPrecision );
1138 int KDoubleSpinBox::mapTextToValue(
bool * ok ) {
1143 value = cleanText().toDouble( ok );
1144 if ( !*ok )
return 0;
1149 return d->mapToInt( value, ok );
1156 void KDoubleSpinBox::slotValueChanged(
int value ) {
1160 void KDoubleSpinBox::updateValidator() {
1161 if ( !d->mValidator ) {
1163 this,
"d->mValidator" );
1164 base::setValidator( d->mValidator );
1169 void KNumInput::virtual_hook(
int,
void* )
1172 void KIntNumInput::virtual_hook(
int id,
void* data )
1173 { KNumInput::virtual_hook(
id, data ); }
1175 void KDoubleNumInput::virtual_hook(
int id,
void* data )
1176 { KNumInput::virtual_hook(
id, data ); }
1178 void KIntSpinBox::virtual_hook(
int,
void* )
1181 void KDoubleSpinBox::virtual_hook(
int,
void* )
1184 #include "knuminput.moc"