551QAbstractSpinBox::StepEnabled QAbstractSpinBox::stepEnabled()
const
553 Q_D(
const QAbstractSpinBox);
554 if (d->readOnly || d->type == QMetaType::UnknownType)
557 return StepEnabled(StepUpEnabled | StepDownEnabled);
558 StepEnabled ret = StepNone;
559 if (QAbstractSpinBoxPrivate::variantCompare(d->value, d->maximum) < 0) {
560 ret |= StepUpEnabled;
562 if (QAbstractSpinBoxPrivate::variantCompare(d->value, d->minimum) > 0) {
563 ret |= StepDownEnabled;
626void QAbstractSpinBox::stepBy(
int steps)
628 Q_D(QAbstractSpinBox);
630 const QVariant old = d->value;
631 QString tmp = d->edit->displayText();
632 int cursorPos = d->edit->cursorPosition();
633 bool dontstep =
false;
634 EmitPolicy e = EmitIfChanged;
635 if (d->pendingEmit) {
636 dontstep = validate(tmp, cursorPos) != QValidator::Acceptable;
638 d->interpret(NeverEmit);
644 switch (d->stepType) {
645 case QAbstractSpinBox::StepType::AdaptiveDecimalStepType:
646 singleStep = d->calculateAdaptiveDecimalStep(steps);
649 singleStep = d->singleStep;
651 d->setValue(d->bound(d->value + (singleStep * steps), old, steps), e);
652 }
else if (e == AlwaysEmit) {
653 d->emitSignals(e, old);
655 if (style()->styleHint(QStyle::SH_SpinBox_SelectOnStep,
nullptr,
this,
nullptr))
683void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit)
685 Q_D(QAbstractSpinBox);
692 if (lineEdit == d->edit)
697 setProperty(
"_q_spinbox_lineedit", QVariant::fromValue<QWidget *>(d->edit));
698 if (!d->edit->validator())
699 d->edit->setValidator(d->validator);
701 if (d->edit->parent() !=
this)
702 d->edit->setParent(
this);
704 d->edit->setFrame(!style()->styleHint(QStyle::SH_SpinBox_ButtonsInsideFrame,
nullptr,
this));
705 d->edit->setFocusProxy(
this);
706 d->edit->setAcceptDrops(
false);
708 if (d->type != QMetaType::UnknownType) {
709 QObjectPrivate::connect(d->edit, &QLineEdit::textChanged,
710 d, &QAbstractSpinBoxPrivate::editorTextChanged);
711 QObjectPrivate::connect(d->edit, &QLineEdit::cursorPositionChanged,
712 d, &QAbstractSpinBoxPrivate::editorCursorPositionChanged);
713 connect(d->edit, &QLineEdit::cursorPositionChanged,
714 this, [
this]() { updateMicroFocus(); });
715 connect(d->edit->d_func()->control, &QWidgetLineControl::updateMicroFocus,
716 this, [
this]() { updateMicroFocus(); });
718 d->updateEditFieldGeometry();
719 d->edit->setContextMenuPolicy(Qt::NoContextMenu);
720 d->edit->d_func()->control->setAccessibleObject(
this);
765bool QAbstractSpinBox::event(QEvent *event)
767 Q_D(QAbstractSpinBox);
768 switch (event->type()) {
769 case QEvent::FontChange:
770 case QEvent::StyleChange:
771 d->cachedSizeHint = d->cachedMinimumSizeHint = QSize();
773 case QEvent::ApplicationLayoutDirectionChange:
774 case QEvent::LayoutDirectionChange:
775 d->updateEditFieldGeometry();
777 case QEvent::HoverEnter:
778 case QEvent::HoverLeave:
779 case QEvent::HoverMove:
780 d->updateHoverControl(
static_cast<
const QHoverEvent *>(event)->position().toPoint());
782 case QEvent::ShortcutOverride:
783 if (d->edit->event(event))
786#ifdef QT_KEYPAD_NAVIGATION
787 case QEvent::EnterEditFocus:
788 case QEvent::LeaveEditFocus:
789 if (QApplicationPrivate::keypadNavigationEnabled()) {
790 const bool b = d->edit->event(event);
791 d->edit->setSelection(d->edit->displayText().size() - d->suffix.size(),0);
792 if (event->type() == QEvent::LeaveEditFocus)
793 emit editingFinished();
799 case QEvent::InputMethod:
800 return d->edit->event(event);
804 return QWidget::event(event);
827void QAbstractSpinBox::changeEvent(QEvent *event)
829 Q_D(QAbstractSpinBox);
831 switch (event->type()) {
832 case QEvent::StyleChange:
833 d->spinClickTimerInterval = style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatRate,
nullptr,
this);
834 d->spinClickThresholdTimerInterval =
835 style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold,
nullptr,
this);
837 d->edit->setFrame(!style()->styleHint(QStyle::SH_SpinBox_ButtonsInsideFrame,
nullptr,
this));
838 d->stepModifier =
static_cast<Qt::KeyboardModifier>(style()->styleHint(QStyle::SH_SpinBox_StepModifier,
nullptr,
this));
840 d->updateEditFieldGeometry();
842 case QEvent::LocaleChange:
845 case QEvent::EnabledChange:
850 case QEvent::ActivationChange:
851 if (!isActiveWindow()){
854 d->interpret(EmitIfChanged);
860 QWidget::changeEvent(event);
880QSize QAbstractSpinBox::sizeHint()
const
882 Q_D(
const QAbstractSpinBox);
883 if (d->cachedSizeHint.isEmpty()) {
886 const QFontMetrics fm(fontMetrics());
887 int h = d->edit->sizeHint().height();
890 QString fixedContent = d->prefix + d->suffix + u' ';
891 s = d->textFromValue(d->minimum);
894 w = qMax(w, fm.horizontalAdvance(s));
895 s = d->textFromValue(d->maximum);
898 w = qMax(w, fm.horizontalAdvance(s));
900 if (d->specialValueText.size()) {
901 s = d->specialValueText;
902 w = qMax(w, fm.horizontalAdvance(s));
906 QStyleOptionSpinBox opt;
907 initStyleOption(&opt);
909 d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint,
this);
911 return d->cachedSizeHint;
918QSize QAbstractSpinBox::minimumSizeHint()
const
920 Q_D(
const QAbstractSpinBox);
921 if (d->cachedMinimumSizeHint.isEmpty()) {
925 const QFontMetrics fm(fontMetrics());
926 int h = d->edit->minimumSizeHint().height();
930 QString fixedContent = d->prefix + u' ';
931 s = d->textFromValue(d->minimum);
934 w = qMax(w, fm.horizontalAdvance(s));
935 s = d->textFromValue(d->maximum);
938 w = qMax(w, fm.horizontalAdvance(s));
940 if (d->specialValueText.size()) {
941 s = d->specialValueText;
942 w = qMax(w, fm.horizontalAdvance(s));
946 QStyleOptionSpinBox opt;
947 initStyleOption(&opt);
950 d->cachedMinimumSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint,
this);
952 return d->cachedMinimumSizeHint;
991void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
993 Q_D(QAbstractSpinBox);
995 d->keyboardModifiers = event->modifiers();
997 if (!event->text().isEmpty() && d->edit->cursorPosition() < d->prefix.size())
998 d->edit->setCursorPosition(d->prefix.size());
1001 bool isPgUpOrDown =
false;
1002 switch (event->key()) {
1003 case Qt::Key_PageUp:
1004 case Qt::Key_PageDown:
1006 isPgUpOrDown =
true;
1009 case Qt::Key_Down: {
1010#ifdef QT_KEYPAD_NAVIGATION
1011 if (QApplicationPrivate::keypadNavigationEnabled()) {
1013 if (!hasEditFocus() && (event->key() == Qt::Key_Up
1014 || event->key() == Qt::Key_Down)) {
1021 const bool up = (event->key() == Qt::Key_PageUp || event->key() == Qt::Key_Up);
1022 if (!(stepEnabled() & (up ? StepUpEnabled : StepDownEnabled)))
1024 if (!isPgUpOrDown && (event->modifiers() & d->stepModifier))
1028 if (style()->styleHint(QStyle::SH_SpinBox_AnimateButton,
nullptr,
this)) {
1029 d->buttonState = (Keyboard | (up ? Up : Down));
1031 if (!d->spinClickTimer.isActive())
1033 if (event->isAutoRepeat() && !isPgUpOrDown) {
1034 if (!d->spinClickThresholdTimer.isActive() && !d->spinClickTimer.isActive()) {
1035 d->updateState(up,
true);
1038#if QT_CONFIG(accessibility)
1039 QAccessibleValueChangeEvent event(
this, d->value);
1040 QAccessible::updateAccessibility(&event);
1044#ifdef QT_KEYPAD_NAVIGATION
1047 if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) {
1053 if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus()) {
1060 case Qt::Key_Return:
1061 d->edit->d_func()->control->clearUndo();
1062 d->interpret(d->keyboardTracking ? AlwaysEmit : EmitIfChanged);
1065 emit editingFinished();
1066 emit returnPressed();
1067 emit d->edit->returnPressed();
1070#ifdef QT_KEYPAD_NAVIGATION
1071 case Qt::Key_Select:
1072 if (QApplicationPrivate::keypadNavigationEnabled()) {
1074 setEditFocus(!hasEditFocus());
1080 if (event->modifiers() & Qt::ControlModifier
1081 && QGuiApplication::platformName() ==
"xcb"_L1) {
1091 if (event->modifiers() & Qt::ShiftModifier) {
1092 int currentPos = d->edit->cursorPosition();
1093 const QString text = d->edit->displayText();
1094 if (event->key() == Qt::Key_End) {
1095 if ((currentPos == 0 && !d->prefix.isEmpty()) || text.size() - d->suffix.size() <= currentPos) {
1098 d->edit->setSelection(currentPos, text.size() - d->suffix.size() - currentPos);
1101 if ((currentPos == text.size() && !d->suffix.isEmpty()) || currentPos <= d->prefix.size()) {
1104 d->edit->setSelection(currentPos, d->prefix.size() - currentPos);
1113#ifndef QT_NO_SHORTCUT
1114 if (event == QKeySequence::SelectAll) {
1123 d->edit->event(event);
1124 if (!d->edit->text().isEmpty())
1127 d->ignoreUpdateEdit =
true;
1246void QAbstractSpinBox::timerEvent(QTimerEvent *event)
1248 Q_D(QAbstractSpinBox);
1250 bool doStep =
false;
1251 if (event->id() == d->spinClickThresholdTimer.id()) {
1252 d->spinClickThresholdTimer.stop();
1253 d->effectiveSpinRepeatRate = d->buttonState & Keyboard
1254 ? QGuiApplication::styleHints()->keyboardAutoRepeatRateF()
1255 : d->spinClickTimerInterval;
1256 d->spinClickTimer.start(d->effectiveSpinRepeatRate,
this);
1258 }
else if (event->id() == d->spinClickTimer.id()) {
1259 if (d->accelerate) {
1260 d->acceleration = d->acceleration + (
int)(d->effectiveSpinRepeatRate * 0.05);
1261 auto interval =
int(d->effectiveSpinRepeatRate - d->acceleration) * 1ms;
1262 if (interval >= 10ms)
1263 d->spinClickTimer.start(interval,
this);
1269 const bool increaseStepRate = d->keyboardModifiers & d->stepModifier;
1270 const StepEnabled st = stepEnabled();
1271 if (d->buttonState & Up) {
1272 if (!(st & StepUpEnabled)) {
1275 stepBy(increaseStepRate ? 10 : 1);
1277 }
else if (d->buttonState & Down) {
1278 if (!(st & StepDownEnabled)) {
1281 stepBy(increaseStepRate ? -10 : -1);
1286 QWidget::timerEvent(event);
1348void QAbstractSpinBox::mouseMoveEvent(QMouseEvent *event)
1350 Q_D(QAbstractSpinBox);
1352 d->keyboardModifiers = event->modifiers();
1353 d->updateHoverControl(event->position().toPoint());
1356 if (d->spinClickTimer.isActive() && d->buttonSymbols != NoButtons) {
1357 const StepEnabled se = stepEnabled();
1358 if ((se & StepUpEnabled) && d->hoverControl == QStyle::SC_SpinBoxUp)
1359 d->updateState(
true);
1360 else if ((se & StepDownEnabled) && d->hoverControl == QStyle::SC_SpinBoxDown)
1361 d->updateState(
false);
1372void QAbstractSpinBox::mousePressEvent(QMouseEvent *event)
1374 Q_D(QAbstractSpinBox);
1376 d->keyboardModifiers = event->modifiers();
1377 if (event->button() != Qt::LeftButton || d->buttonState != None) {
1382 d->updateHoverControl(event->position().toPoint());
1385 const StepEnabled se = (d->buttonSymbols == NoButtons) ? StepEnabled(StepNone) : stepEnabled();
1386 if ((se & StepUpEnabled) && d->hoverControl == QStyle::SC_SpinBoxUp) {
1387 d->updateState(
true);
1388 }
else if ((se & StepDownEnabled) && d->hoverControl == QStyle::SC_SpinBoxDown) {
1389 d->updateState(
false);
1435bool QAbstractSpinBoxPrivate::updateHoverControl(
const QPoint &pos)
1437 Q_Q(QAbstractSpinBox);
1438 QRect lastHoverRect = hoverRect;
1439 QStyle::SubControl lastHoverControl = hoverControl;
1440 bool doesHover = q->testAttribute(Qt::WA_Hover);
1441 if (lastHoverControl != newHoverControl(pos) && doesHover) {
1442 q->update(lastHoverRect);
1443 q->update(hoverRect);
1454QStyle::SubControl QAbstractSpinBoxPrivate::newHoverControl(
const QPoint &pos)
1456 Q_Q(QAbstractSpinBox);
1458 QStyleOptionSpinBox opt;
1459 q->initStyleOption(&opt);
1460 opt.subControls = QStyle::SC_All;
1461 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_SpinBox, &opt, pos, q);
1462 hoverRect = q->style()->subControlRect(QStyle::CC_SpinBox, &opt, hoverControl, q);
1463 return hoverControl;
1471QString QAbstractSpinBoxPrivate::stripped(
const QString &t,
int *pos)
const
1473 QStringView text(t);
1474 if (specialValueText.size() == 0 || text != specialValueText) {
1476 int size = text.size();
1477 bool changed =
false;
1478 if (prefix.size() && text.startsWith(prefix)) {
1479 from += prefix.size();
1483 if (suffix.size() && text.endsWith(suffix)) {
1484 size -= suffix.size();
1488 text = text.mid(from, size);
1491 const int s = text.size();
1492 text = text.trimmed();
1494 (*pos) -= (s - text.size());
1495 return text.toString();
1499void QAbstractSpinBoxPrivate::updateEditFieldGeometry()
1501 Q_Q(QAbstractSpinBox);
1502 QStyleOptionSpinBox opt;
1503 q->initStyleOption(&opt);
1504 opt.subControls = QStyle::SC_SpinBoxEditField;
1505 edit->setGeometry(q->style()->subControlRect(QStyle::CC_SpinBox, &opt,
1506 QStyle::SC_SpinBoxEditField, q));
1534void QAbstractSpinBoxPrivate::editorTextChanged(
const QString &t)
1536 Q_Q(QAbstractSpinBox);
1538 if (keyboardTracking) {
1540 int pos = edit->cursorPosition();
1541 QValidator::State state = q->validate(tmp, pos);
1542 if (state == QValidator::Acceptable) {
1543 const QVariant v = valueFromText(tmp);
1544 setValue(v, EmitIfChanged, tmp != t);
1545 pendingEmit =
false;
1564void QAbstractSpinBoxPrivate::editorCursorPositionChanged(
int oldpos,
int newpos)
1566 if (!edit->hasSelectedText() && !ignoreCursorPositionChanged && !specialValue()) {
1567 ignoreCursorPositionChanged =
true;
1569 bool allowSelection =
true;
1571 if (newpos < prefix.size() && newpos != 0) {
1573 allowSelection =
false;
1574 pos = prefix.size();
1578 }
else if (newpos > edit->text().size() - suffix.size()
1579 && newpos != edit->text().size()) {
1580 if (oldpos == edit->text().size()) {
1581 pos = edit->text().size() - suffix.size();
1582 allowSelection =
false;
1584 pos = edit->text().size();
1588 const int selSize = edit->selectionStart() >= 0 && allowSelection
1589 ? (edit->selectedText().size()
1590 * (newpos < pos ? -1 : 1)) - newpos + pos
1593 const QSignalBlocker blocker(edit);
1595 edit->setSelection(pos - selSize, selSize);
1597 edit->setCursorPosition(pos);
1600 ignoreCursorPositionChanged =
false;
1610void QAbstractSpinBoxPrivate::init()
1612 Q_Q(QAbstractSpinBox);
1614 q->setLineEdit(
new QLineEdit(q));
1615 edit->setObjectName(
"qt_spinbox_lineedit"_L1);
1616 validator =
new QSpinBoxValidator(q,
this);
1617 edit->setValidator(validator);
1619 QStyleOptionSpinBox opt;
1622 q->initStyleOption(&opt);
1623 spinClickTimerInterval = q->style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatRate, &opt, q);
1624 spinClickThresholdTimerInterval = q->style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold, &opt, q);
1625 q->setFocusPolicy(Qt::WheelFocus);
1626 q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::SpinBox));
1627 q->setAttribute(Qt::WA_InputMethodEnabled);
1629 q->setAttribute(Qt::WA_MacShowFocusRect);
1658void QAbstractSpinBoxPrivate::updateState(
bool up,
bool fromKeyboard )
1660 Q_Q(QAbstractSpinBox);
1661 if ((up && (buttonState & Up)) || (!up && (buttonState & Down)))
1664 if (q && (q->stepEnabled() & (up ? QAbstractSpinBox::StepUpEnabled
1665 : QAbstractSpinBox::StepDownEnabled))) {
1666 buttonState = (up ? Up : Down) | (fromKeyboard ? Keyboard : Mouse);
1667 int steps = up ? 1 : -1;
1668 if (keyboardModifiers & stepModifier)
1671 spinClickThresholdTimer.start(spinClickThresholdTimerInterval * 1ms, q);
1672#if QT_CONFIG(accessibility)
1673 QAccessibleValueChangeEvent event(q, value);
1674 QAccessible::updateAccessibility(&event);
1687void QAbstractSpinBox::initStyleOption(QStyleOptionSpinBox *option)
const
1692 Q_D(
const QAbstractSpinBox);
1693 option->initFrom(
this);
1694 option->activeSubControls = QStyle::SC_None;
1695 option->buttonSymbols = d->buttonSymbols;
1696 option->subControls = QStyle::SC_SpinBoxEditField;
1697 if (style()->styleHint(QStyle::SH_SpinBox_ButtonsInsideFrame,
nullptr,
this))
1698 option->subControls |= QStyle::SC_SpinBoxFrame;
1699 if (d->buttonSymbols != QAbstractSpinBox::NoButtons) {
1700 option->subControls |= QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown;
1701 if (d->buttonState & Up) {
1702 option->activeSubControls = QStyle::SC_SpinBoxUp;
1703 }
else if (d->buttonState & Down) {
1704 option->activeSubControls = QStyle::SC_SpinBoxDown;
1708 if (d->buttonState) {
1709 option->state |= QStyle::State_Sunken;
1711 option->activeSubControls = d->hoverControl;
1714 option->stepEnabled = style()->styleHint(QStyle::SH_SpinControls_DisableOnBounds,
nullptr,
this)
1716 : (QAbstractSpinBox::StepDownEnabled|QAbstractSpinBox::StepUpEnabled);
1718 option->frame = d->frame;
1729QVariant QAbstractSpinBoxPrivate::bound(
const QVariant &val,
const QVariant &old,
int steps)
const
1732 if (!wrapping || steps == 0 || old.isNull()) {
1733 if (variantCompare(v, minimum) < 0) {
1734 v = wrapping ? maximum : minimum;
1736 if (variantCompare(v, maximum) > 0) {
1737 v = wrapping ? minimum : maximum;
1740 const bool wasMin = old == minimum;
1741 const bool wasMax = old == maximum;
1742 const int oldcmp = variantCompare(v, old);
1743 const int maxcmp = variantCompare(v, maximum);
1744 const int mincmp = variantCompare(v, minimum);
1745 const bool wrapped = (oldcmp > 0 && steps < 0) || (oldcmp < 0 && steps > 0);
1747 v = ((wasMax && !wrapped && steps > 0) || (steps < 0 && !wasMin && wrapped))
1748 ? minimum : maximum;
1749 }
else if (wrapped && (maxcmp > 0 || mincmp < 0)) {
1750 v = ((wasMax && steps > 0) || (!wasMin && steps < 0)) ? minimum : maximum;
1751 }
else if (mincmp < 0) {
1752 v = (!wasMax && !wasMin ? minimum : maximum);
1790void QAbstractSpinBoxPrivate::updateEdit()
1792 Q_Q(QAbstractSpinBox);
1793 if (type == QMetaType::UnknownType)
1795 const QString newText = specialValue() ? specialValueText : prefix + textFromValue(value) + suffix;
1796 if (newText == edit->displayText() || cleared)
1799 const bool empty = edit->text().isEmpty();
1800 int cursor = edit->cursorPosition();
1801 int selsize = edit->selectedText().size();
1802 const QSignalBlocker blocker(edit);
1803 edit->setText(newText);
1805 if (!specialValue()) {
1806 cursor = qBound(prefix.size(), cursor, edit->displayText().size() - suffix.size());
1809 edit->setSelection(cursor, selsize);
1811 edit->setCursorPosition(empty ? prefix.size() : cursor);
1823void QAbstractSpinBoxPrivate::setRange(
const QVariant &min,
const QVariant &max)
1825 Q_Q(QAbstractSpinBox);
1829 maximum = (variantCompare(min, max) < 0 ? max : min);
1830 cachedSizeHint = QSize();
1831 cachedMinimumSizeHint = QSize();
1834 if (!(bound(value) == value)) {
1835 setValue(bound(value), EmitIfChanged);
1836 }
else if (value == minimum && !specialValueText.isEmpty()) {
1840 q->updateGeometry();
1898void QAbstractSpinBoxPrivate::interpret(EmitPolicy ep)
1900 Q_Q(QAbstractSpinBox);
1901 if (type == QMetaType::UnknownType || cleared)
1904 QVariant v = getZeroVariant();
1905 bool doInterpret =
true;
1906 QString tmp = edit->displayText();
1907 int pos = edit->cursorPosition();
1908 const int oldpos = pos;
1910 if (q->validate(tmp, pos) != QValidator::Acceptable) {
1911 const QString copy = tmp;
1913 QASBDEBUG() <<
"QAbstractSpinBoxPrivate::interpret() text '"
1914 << edit->displayText()
1915 <<
"' >> '" << copy <<
'\''
1916 <<
"' >> '" << tmp <<
'\'';
1918 doInterpret = tmp != copy && (q->validate(tmp, pos) == QValidator::Acceptable);
1920 v = (correctionMode == QAbstractSpinBox::CorrectToNearestValue
1921 ? variantBound(minimum, v, maximum) : value);
1925 v = valueFromText(tmp);
1928 setValue(v, ep,
true);
1930 edit->setCursorPosition(pos);
1966QValidator::State QSpinBoxValidator::validate(QString &input,
int &pos)
const
1968 if (dptr->specialValueText.size() > 0 && input == dptr->specialValueText)
1969 return QValidator::Acceptable;
1971 if (!dptr->prefix.isEmpty() && !input.startsWith(dptr->prefix)) {
1972 input.prepend(dptr->prefix);
1973 pos += dptr->prefix.size();
1976 if (!dptr->suffix.isEmpty() && !input.endsWith(dptr->suffix))
1977 input.append(dptr->suffix);
1979 return qptr->validate(input, pos);
1998QVariant
operator+(
const QVariant &arg1,
const QVariant &arg2)
2001 if (Q_UNLIKELY(arg1.userType() != arg2.userType()))
2002 qWarning(
"QAbstractSpinBox: Internal error: Different types (%s vs %s) (%s:%d)",
2003 arg1.typeName(), arg2.typeName(), __FILE__, __LINE__);
2004 switch (arg1.userType()) {
2005 case QMetaType::Int: {
2006 const int int1 = arg1.toInt();
2007 const int int2 = arg2.toInt();
2008 if (int1 > 0 && (int2 >= INT_MAX - int1)) {
2010 ret = QVariant(INT_MAX);
2011 }
else if (int1 < 0 && (int2 <= INT_MIN - int1)) {
2013 ret = QVariant(INT_MIN);
2015 ret = QVariant(int1 + int2);
2019 case QMetaType::Double: ret = QVariant(arg1.toDouble() + arg2.toDouble());
break;
2020#if QT_CONFIG(datetimeparser)
2021 case QMetaType::QDateTime: {
2022 QDateTime a2 = arg2.toDateTime();
2023 QDateTime a1 = arg1.toDateTime().addDays(QDATETIMEEDIT_DATE_MIN.daysTo(a2.date()));
2024 a1.setTime(a1.time().addMSecs(a2.time().msecsSinceStartOfDay()));
2040QVariant
operator-(
const QVariant &arg1,
const QVariant &arg2)
2043 if (Q_UNLIKELY(arg1.userType() != arg2.userType()))
2044 qWarning(
"QAbstractSpinBox: Internal error: Different types (%s vs %s) (%s:%d)",
2045 arg1.typeName(), arg2.typeName(), __FILE__, __LINE__);
2046 switch (arg1.userType()) {
2047 case QMetaType::Int: ret = QVariant(arg1.toInt() - arg2.toInt());
break;
2048 case QMetaType::Double: ret = QVariant(arg1.toDouble() - arg2.toDouble());
break;
2049 case QMetaType::QDateTime: {
2050 QDateTime a1 = arg1.toDateTime();
2051 QDateTime a2 = arg2.toDateTime();
2052 int days = a2.daysTo(a1);
2053 int secs = a2.secsTo(a1);
2054 int msecs = qMax(0, a1.time().msec() - a2.time().msec());
2055 if (days < 0 || secs < 0 || msecs < 0) {
2058 QDateTime dt = a2.addDays(days).addSecs(secs);
2060 dt.setTime(dt.time().addMSecs(msecs));
2075QVariant
operator*(
const QVariant &arg1,
double multiplier)
2079 switch (arg1.userType()) {
2080 case QMetaType::Int:
2081 ret =
static_cast<
int>(qBound<
double>(INT_MIN, arg1.toInt() * multiplier, INT_MAX));
2083 case QMetaType::Double: ret = QVariant(arg1.toDouble() * multiplier);
break;
2084#if QT_CONFIG(datetimeparser)
2085 case QMetaType::QDateTime: {
2086 double days = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDateTime().date()) * multiplier;
2087 const qint64 daysInt = qint64(days);
2089 qint64 msecs = qint64(arg1.toDateTime().time().msecsSinceStartOfDay() * multiplier
2090 + days * (24 * 3600 * 1000));
2091 ret = QDATETIMEEDIT_DATE_MIN.addDays(daysInt).startOfDay().addMSecs(msecs);
2095 default: ret = arg1;
break;
2103double operator/(
const QVariant &arg1,
const QVariant &arg2)
2108 switch (arg1.userType()) {
2109 case QMetaType::Int:
2110 a1 = (
double)arg1.toInt();
2111 a2 = (
double)arg2.toInt();
2113 case QMetaType::Double:
2114 a1 = arg1.toDouble();
2115 a2 = arg2.toDouble();
2117#if QT_CONFIG(datetimeparser)
2118 case QMetaType::QDateTime:
2119 a1 = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDate());
2120 a2 = QDATETIMEEDIT_DATE_MIN.daysTo(arg2.toDate());
2121 a1 += arg1.toDateTime().time().msecsSinceStartOfDay() / (36e5 * 24);
2122 a2 += arg2.toDateTime().time().msecsSinceStartOfDay() / (36e5 * 24);
2128 return (a1 != 0 && a2 != 0) ? (a1 / a2) : 0.0;
2131int QAbstractSpinBoxPrivate::variantCompare(
const QVariant &arg1,
const QVariant &arg2)
2133 switch (arg2.userType()) {
2134 case QMetaType::QDate:
2135 Q_ASSERT_X(arg1.userType() == QMetaType::QDate,
"QAbstractSpinBoxPrivate::variantCompare",
2136 qPrintable(QString::fromLatin1(
"Internal error 1 (%1)").
2137 arg(QString::fromLatin1(arg1.typeName()))));
2138 if (arg1.toDate() == arg2.toDate()) {
2140 }
else if (arg1.toDate() < arg2.toDate()) {
2145 case QMetaType::QTime:
2146 Q_ASSERT_X(arg1.userType() == QMetaType::QTime,
"QAbstractSpinBoxPrivate::variantCompare",
2147 qPrintable(QString::fromLatin1(
"Internal error 2 (%1)").
2148 arg(QString::fromLatin1(arg1.typeName()))));
2149 if (arg1.toTime() == arg2.toTime()) {
2151 }
else if (arg1.toTime() < arg2.toTime()) {
2158 case QMetaType::QDateTime:
2159 if (arg1.toDateTime() == arg2.toDateTime()) {
2161 }
else if (arg1.toDateTime() < arg2.toDateTime()) {
2166 case QMetaType::Int:
2167 if (arg1.toInt() == arg2.toInt()) {
2169 }
else if (arg1.toInt() < arg2.toInt()) {
2174 case QMetaType::Double:
2175 if (arg1.toDouble() == arg2.toDouble()) {
2177 }
else if (arg1.toDouble() < arg2.toDouble()) {
2182 case QMetaType::UnknownType:
2183 if (arg2.userType() == QMetaType::UnknownType)
2187 Q_ASSERT_X(0,
"QAbstractSpinBoxPrivate::variantCompare",
2188 qPrintable(QString::fromLatin1(
"Internal error 3 (%1 %2)").
2189 arg(QString::fromLatin1(arg1.typeName()),
2190 QString::fromLatin1(arg2.typeName()))));
2195QVariant QAbstractSpinBoxPrivate::variantBound(
const QVariant &min,
2196 const QVariant &value,
2197 const QVariant &max)
2199 Q_ASSERT(variantCompare(min, max) <= 0);
2200 if (variantCompare(min, value) < 0) {
2201 const int compMax = variantCompare(value, max);
2202 return (compMax < 0 ? value : max);