32 #include <QtGui/QApplication>
33 #include <QtGui/QLabel>
34 #include <QtGui/QLineEdit>
35 #include <QtGui/QResizeEvent>
36 #include <QtGui/QSlider>
45 return (x / 10) - (y / 10) + (x % 10 - y % 10) / 10;
50 class KNumInputPrivate
64 nextNumInput = below->d->nextNumInput;
65 previousNumInput = below;
66 below->d->nextNumInput = q;
68 nextNumInput->d->previousNumInput = q;
73 static KNumInputPrivate *
get(
const KNumInput *i) {
78 KNumInput* previousNumInput, *nextNumInput;
79 int column1Width, column2Width;
83 QSize sliderSize, labelSize;
85 Qt::Alignment labelAlignment;
89 #define K_USING_KNUMINPUT_P(_d) KNumInputPrivate *_d = KNumInputPrivate::get(this)
92 :
QWidget(parent), d(new KNumInputPrivate(this))
94 setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed));
95 setFocusPolicy(Qt::StrongFocus);
98 #ifndef KDE_NO_DEPRECATED
100 :
QWidget(parent), d(new KNumInputPrivate(this, below))
102 setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed));
103 setFocusPolicy(Qt::StrongFocus);
109 if (d->previousNumInput) {
110 d->previousNumInput->d->nextNumInput = d->nextNumInput;
113 if (d->nextNumInput) {
114 d->nextNumInput->d->previousNumInput = d->previousNumInput;
132 if (label.isEmpty()) {
135 d->labelAlignment = 0;
138 d->label =
new QLabel(
this);
140 d->label->setText(label);
141 d->label->setObjectName(
"KNumInput::QLabel");
142 d->label->setAlignment(a);
144 if (!(a & (Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter))) {
147 d->labelAlignment = a;
155 return d->label ? d->label->text() :
QString();
160 int w1 = d->column1Width;
161 int w2 = d->column2Width;
164 d->labelSize = (d->label ? d->label->sizeHint() :
QSize(0, 0));
166 if (d->label && (d->labelAlignment & Qt::AlignVCenter)) {
167 d->column1Width = d->labelSize.width() + 4;
173 d->sliderSize = (d->slider ? d->slider->sizeHint() :
QSize(0, 0));
178 d->column1Width = w1;
179 d->column2Width = w2;
183 w2 = d->column2Width;
188 w1 = qMax(w1, p->d->column1Width);
189 w2 = qMax(w2, p->d->column2Width);
190 p = p->d->previousNumInput;
196 w1 = qMax(w1, p->d->column1Width);
197 w2 = qMax(w2, p->d->column2Width);
198 p = p->d->nextNumInput;
203 p->d->column1Width = w1;
204 p->d->column2Width = w2;
205 p = p->d->previousNumInput;
210 p->d->column1Width = w1;
211 p->d->column2Width = w2;
212 p = p->d->nextNumInput;
220 return minimumSizeHint();
226 d->slider->setSingleStep(minor);
227 d->slider->setPageStep(major);
239 connect(q, SIGNAL(valueChanged(
int)), q, SLOT(updateSuffix(
int)));
242 void updateSuffix(
int value)
244 if (!pluralSuffix.isEmpty()) {
256 :
QSpinBox(parent), d(new KIntSpinBoxPrivate(this))
267 :
QSpinBox(parent), d(new KIntSpinBoxPrivate(this, base))
269 setRange(lower, upper);
270 setSingleStep(singleStep);
287 return QString::number(v, d->val_base);
294 if (theText.startsWith(
prefix())) {
295 theText.remove(0,
prefix().length());
297 if (theText.endsWith(suffix())) {
298 theText.chop(suffix().length());
300 return theText.trimmed().toInt(&ok, d->val_base);
305 lineEdit()->setFocus();
307 lineEdit()->selectAll();
313 d->pluralSuffix = suffix;
317 d->updateSuffix(value());
329 QSize intSpinBoxSize;
338 #ifndef KDE_NO_DEPRECATED
341 , d(new KIntNumInputPrivate(this, val))
349 , d(new KIntNumInputPrivate(this, 0))
356 , d(new KIntNumInputPrivate(this, val))
363 return d->intSpinBox;
366 void KIntNumInput::init(
int val,
int _base)
368 d->intSpinBox =
new KIntSpinBox(INT_MIN, INT_MAX, 1, val,
this, _base);
369 d->intSpinBox->setObjectName(
"KIntNumInput::KIntSpinBox");
375 kWarning() <<
"WARNING: Validation is broken in KIntNumInput! Needs to be fixed.";
379 connect(d->intSpinBox, SIGNAL(
valueChanged(
int)), SLOT(spinValueChanged(
int)));
381 SLOT(slotEmitRelativeValueChanged(
int)));
383 setFocusProxy(d->intSpinBox);
391 d->referencePoint = ref;
396 return d->referencePoint;
399 void KIntNumInput::spinValueChanged(
int val)
404 priv->slider->setValue(val);
410 void KIntNumInput::slotEmitRelativeValueChanged(
int value)
412 if (d->blockRelative || !d->referencePoint) {
423 priv->slider =
new QSlider(Qt::Horizontal,
this);
425 d->intSpinBox, SLOT(
setValue(
int)));
426 priv->slider->setTickPosition(QSlider::TicksBelow);
430 const int value = d->intSpinBox->value();
431 priv->slider->setRange(d->intSpinBox->minimum(), d->intSpinBox->maximum());
432 priv->slider->setPageStep(d->intSpinBox->singleStep());
433 priv->slider->setValue(value);
436 const int major =
calcDiffByTen(d->intSpinBox->maximum(), d->intSpinBox->minimum());
438 priv->slider->setSingleStep(d->intSpinBox->singleStep());
439 priv->slider->setPageStep(qMax(1, major));
440 priv->slider->setTickInterval(major);
452 if (upper < lower || singleStep <= 0) {
453 kWarning() <<
"WARNING: KIntNumInput::setRange() called with bad arguments. Ignoring call...";
457 d->intSpinBox->setMinimum(lower);
458 d->intSpinBox->setMaximum(upper);
459 d->intSpinBox->setSingleStep(singleStep);
461 singleStep = d->intSpinBox->singleStep();
473 #ifndef KDE_NO_DEPRECATED
483 setRange(min, d->intSpinBox->maximum(), d->intSpinBox->singleStep());
488 return d->intSpinBox->minimum();
493 setRange(d->intSpinBox->minimum(), max, d->intSpinBox->singleStep());
498 return d->intSpinBox->maximum();
503 return d->intSpinBox->singleStep();
508 d->intSpinBox->setSingleStep(singleStep);
513 d->intSpinBox->setSuffix(suffix);
520 d->intSpinBox->setSuffix(suffix);
526 return d->intSpinBox->suffix();
531 d->intSpinBox->setPrefix(prefix);
538 return d->intSpinBox->prefix();
543 d->intSpinBox->setEditFocus(mark);
554 h = qMax(d->intSpinBoxSize.height(), priv->sliderSize.height());
557 if (priv->label && (priv->labelAlignment & (Qt::AlignBottom | Qt::AlignTop))) {
558 h += 4 + priv->labelSize.height();
561 h = qMax(h, priv->labelSize.height() + 2);
565 w += priv->column1Width + priv->column2Width;
567 if (priv->labelAlignment & (Qt::AlignTop | Qt::AlignBottom)) {
568 w = qMax(w, priv->labelSize.width() + 4);
578 d->intSpinBoxSize = d->intSpinBox->sizeHint();
579 priv->column2Width = d->intSpinBoxSize.width();
582 priv->label->setBuddy(d->intSpinBox);
590 int w = priv->column1Width;
593 if (priv->label && (priv->labelAlignment & Qt::AlignTop)) {
594 priv->label->setGeometry(0, 0, e->size().width(), priv->labelSize.height());
598 if (priv->label && (priv->labelAlignment & Qt::AlignVCenter)) {
599 priv->label->setGeometry(0, 0, w, d->intSpinBoxSize.height());
602 if (qApp->layoutDirection() == Qt::RightToLeft) {
603 d->intSpinBox->setGeometry(w, h, priv->slider ? priv->column2Width : qMax(priv->column2Width, e->size().width() - w), d->intSpinBoxSize.height());
607 priv->slider->setGeometry(w, h, e->size().width() - w, d->intSpinBoxSize.height() +
KDialog::spacingHint());
609 }
else if (priv->slider) {
611 d->intSpinBox->setGeometry(w + priv->slider->size().width() +
KDialog::spacingHint(), h, priv->column2Width, d->intSpinBoxSize.height());
613 d->intSpinBox->setGeometry(w, h, qMax(priv->column2Width, e->size().width() - w), d->intSpinBoxSize.height());
616 h += d->intSpinBoxSize.height() + 2;
618 if (priv->label && (priv->labelAlignment & Qt::AlignBottom)) {
619 priv->label->setGeometry(0, h, priv->labelSize.width(), priv->labelSize.height());
630 d->intSpinBox->setValue(val);
636 if (!d->referencePoint) {
640 setValue(qRound(d->referencePoint * r + 0.5));
646 if (!d->referencePoint) {
654 return d->intSpinBox->value();
659 d->intSpinBox->setSpecialValueText(text);
665 return d->intSpinBox->specialValueText();
675 priv->label->setBuddy(d->intSpinBox);
689 QDoubleSpinBox * spin;
699 , d(new KDoubleNumInputPrivate(0.0))
702 init(0.0, 0.0, 9999.0, 0.01, 2);
706 double singleStep,
int precision)
708 , d(new KDoubleNumInputPrivate(value))
710 init(value, lower, upper, singleStep, precision);
713 #ifndef KDE_NO_DEPRECATED
715 double lower,
double upper,
double value,
QWidget *parent,
716 double singleStep,
int precision)
718 , d(new KDoubleNumInputPrivate(value))
720 init(value, lower, upper, singleStep, precision);
731 return d->specialValue;
735 void KDoubleNumInput::init(
double value,
double lower,
double upper,
736 double singleStep,
int precision)
738 d->spin =
new QDoubleSpinBox(
this);
739 d->spin->setRange(lower, upper);
740 d->spin->setSingleStep(singleStep);
741 d->spin->setValue(value);
742 d->spin->setDecimals(precision);
744 d->spin->setObjectName(
"KDoubleNumInput::QDoubleSpinBox");
745 setFocusProxy(d->spin);
749 this, SLOT(slotEmitRelativeValueChanged(
double)));
751 updateLegacyMembers();
756 void KDoubleNumInput::updateLegacyMembers()
761 double KDoubleNumInput::mapSliderToSpin(
int val)
const
766 const double spinmin = d->spin->minimum();
767 const double spinmax = d->spin->maximum();
768 const double slidemin = priv->slider->minimum();
769 const double slidemax = priv->slider->maximum();
770 const double rel = (
double(val) - slidemin) / (slidemax - slidemin);
771 Q_ASSERT(d->exponentRatio > 0.0);
772 return spinmin + pow(rel, d->exponentRatio ) * (spinmax - spinmin);
775 void KDoubleNumInput::sliderMoved(
int val)
777 d->spin->setValue(mapSliderToSpin(val));
780 void KDoubleNumInput::spinBoxChanged(
double val)
784 const double spinmin = d->spin->minimum();
785 const double spinmax = d->spin->maximum();
786 const double slidemin = priv->slider->minimum();
787 const double slidemax = priv->slider->maximum();
789 Q_ASSERT(d->exponentRatio > 0.0);
790 const double rel = pow((val - spinmin) / (spinmax - spinmin) , 1.0 / d->exponentRatio);
793 priv->slider->blockSignals(
true);
794 priv->slider->setValue(qRound(slidemin + rel * (slidemax - slidemin)));
795 priv->slider->blockSignals(
false);
799 void KDoubleNumInput::slotEmitRelativeValueChanged(
double value)
801 if (!d->referencePoint) {
816 h = qMax(d->editSize.height(), priv->sliderSize.height());
819 if (priv->label && (priv->labelAlignment & (Qt::AlignBottom | Qt::AlignTop))) {
820 h += 4 + priv->labelSize.height();
823 h = qMax(h, priv->labelSize.height() + 2);
827 w += priv->column1Width + priv->column2Width;
829 if (priv->labelAlignment & (Qt::AlignTop | Qt::AlignBottom)) {
830 w = qMax(w, priv->labelSize.width() + 4);
840 int w = priv->column1Width;
843 if (priv->label && (priv->labelAlignment & Qt::AlignTop)) {
844 priv->label->setGeometry(0, 0, e->size().width(), priv->labelSize.height());
845 h += priv->labelSize.height() + 4;
848 if (priv->label && (priv->labelAlignment & Qt::AlignVCenter)) {
849 priv->label->setGeometry(0, 0, w, d->editSize.height());
852 if (qApp->layoutDirection() == Qt::RightToLeft) {
853 d->spin->setGeometry(w, h, priv->slider ? priv->column2Width
854 : e->size().width() - w, d->editSize.height());
858 priv->slider->setGeometry(w, h, e->size().width() - w, d->editSize.height() +
KDialog::spacingHint());
859 }
else if (priv->slider) {
860 priv->slider->setGeometry(w, h, e->size().width() -
864 priv->column2Width, d->editSize.height());
866 d->spin->setGeometry(w, h, e->size().width() - w, d->editSize.height());
869 h += d->editSize.height() + 2;
871 if (priv->label && (priv->labelAlignment & Qt::AlignBottom)) {
872 priv->label->setGeometry(0, h, priv->labelSize.width(), priv->labelSize.height());
880 d->editSize = d->spin->sizeHint();
881 priv->column2Width = d->editSize.width();
886 d->spin->setValue(val);
891 if (!d->referencePoint) {
903 d->referencePoint = ref;
913 QDoubleSpinBox * spin = d->spin;
917 d->spin->setRange(lower, upper);
918 d->spin->setSingleStep(singleStep);
925 updateLegacyMembers();
932 QDoubleSpinBox * spin = d->spin;
933 const double range = spin->maximum() - spin->minimum();
934 const double steps = range * pow(10.0, spin->decimals());
936 priv->slider =
new QSlider(Qt::Horizontal,
this);
937 priv->slider->setTickPosition(QSlider::TicksBelow);
940 SLOT(sliderMoved(
int)));
943 if (steps > 1000 || d->exponentRatio != 1.0) {
944 priv->slider->setRange(0, 1000);
945 priv->slider->setSingleStep(1);
946 priv->slider->setPageStep(50);
948 const int singleSteps = qRound(steps);
949 priv->slider->setRange(0, singleSteps);
950 priv->slider->setSingleStep(1);
951 const int pageSteps = qBound(1, singleSteps / 20, 10);
952 priv->slider->setPageStep(pageSteps);
954 spinBoxChanged(spin->value());
955 connect(spin, SIGNAL(
valueChanged(
double)), SLOT(spinBoxChanged(
double)));
974 return d->spin->minimum();
985 return d->spin->maximum();
990 return d->spin->singleStep();
995 d->spin->setSingleStep(singleStep);
1000 return d->spin->value();
1005 if (!d->referencePoint) {
1008 return value() / d->referencePoint;
1013 return d->referencePoint;
1018 return d->spin->suffix();
1023 return d->spin->prefix();
1028 d->spin->setSuffix(suffix);
1035 d->spin->setPrefix(prefix);
1042 d->spin->setDecimals(decimals);
1049 return d->spin->decimals();
1054 d->spin->setSpecialValueText(text);
1057 updateLegacyMembers();
1067 priv->label->setBuddy(d->spin);
1073 return d->exponentRatio;
1078 Q_ASSERT(dbl > 0.0);
1080 d->exponentRatio = dbl;
1081 spinBoxChanged( d->spin->value() );
1083 kError() <<
"ExponentRatio need to be strictly positive.";
1088 #include "knuminput.moc"