📄 qabstractspinbox.cpp
字号:
reset(); if (q && (q->stepEnabled() & (up ? QAbstractSpinBox::StepUpEnabled : QAbstractSpinBox::StepDownEnabled))) { spinClickThresholdTimerId = q->startTimer(spinClickThresholdTimerInterval); buttonState = (up ? (Mouse | Up) : (Mouse | Down)); q->stepBy(up ? 1 : -1); }}/*! Initialize \a option with the values from this QSpinBox. This method is useful for subclasses when they need a QStyleOptionSpinBox, but don't want to fill in all the information themselves. \sa QStyleOption::initFrom()*/void QAbstractSpinBox::initStyleOption(QStyleOptionSpinBox *option) const{ if (!option) return; Q_D(const QAbstractSpinBox); option->initFrom(this); option->activeSubControls = QStyle::SC_None; option->buttonSymbols = d->buttonSymbols; option->subControls = QStyle::SC_SpinBoxFrame; if (d->buttonSymbols != QAbstractSpinBox::NoButtons) { option->subControls |= QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown; if (d->buttonState & Up) { option->activeSubControls = QStyle::SC_SpinBoxUp; } else if (d->buttonState & Down) { option->activeSubControls = QStyle::SC_SpinBoxDown; } } if (d->buttonState) { option->state |= QStyle::State_Sunken; } else { option->activeSubControls = d->hoverControl; } option->stepEnabled = style()->styleHint(QStyle::SH_SpinControls_DisableOnBounds) ? stepEnabled() : (QAbstractSpinBox::StepDownEnabled|QAbstractSpinBox::StepUpEnabled); option->frame = d->frame;}/*! \internal Bounds \a val to be within minimum and maximum. Also tries to be clever about setting it at min and max depending on what it was and what direction it was changed etc.*/QVariant QAbstractSpinBoxPrivate::bound(const QVariant &val, const QVariant &old, int steps) const{ QVariant v = val; if (!wrapping || steps == 0 || old.isNull()) { if (variantCompare(v, minimum) < 0) { v = wrapping ? maximum : minimum; } if (variantCompare(v, maximum) > 0) { v = wrapping ? minimum : maximum; } } else { const bool wasMin = old == minimum; const bool wasMax = old == maximum; const int oldcmp = variantCompare(v, old); const int maxcmp = variantCompare(v, maximum); const int mincmp = variantCompare(v, minimum); const bool wrapped = (oldcmp > 0 && steps < 0) || (oldcmp < 0 && steps > 0); if (maxcmp > 0) { v = ((wasMax && !wrapped && steps > 0) || (steps < 0 && !wasMin && wrapped)) ? minimum : maximum; } else if (wrapped && (maxcmp > 0 || mincmp < 0)) { v = (wasMax && steps > 0 || (!wasMin && steps < 0)) ? minimum : maximum; } else if (mincmp < 0) { v = (!wasMax && !wasMin ? minimum : maximum); } } return v;}/*! \internal Sets the value of the spin box to \a val. Depending on the value of \a ep it will also emit signals.*/void QAbstractSpinBoxPrivate::setValue(const QVariant &val, EmitPolicy ep, bool doUpdate){ Q_Q(QAbstractSpinBox); const QVariant old = value; value = bound(val); pendingEmit = false; if (doUpdate) { updateEdit(); } q->update(); if (ep == AlwaysEmit || (ep == EmitIfChanged && old != value)) { emitSignals(ep, old); }}/*! \internal Updates the line edit to reflect the current value of the spin box.*/void QAbstractSpinBoxPrivate::updateEdit(){ Q_Q(QAbstractSpinBox); if (type == QVariant::Invalid) return; const QString newText = specialValue() ? specialValueText : prefix + textFromValue(value) + suffix; if (newText == edit->displayText()) return; const bool empty = edit->text().isEmpty(); int cursor = edit->cursorPosition(); int selsize = edit->selectedText().size(); const bool sb = edit->blockSignals(true); edit->setText(newText); if (!specialValue()) { cursor = qBound(prefix.size(), cursor, edit->displayText().size() - suffix.size()); if (selsize > 0) { edit->setSelection(cursor, selsize); } else { edit->setCursorPosition(empty ? prefix.size() : cursor); } } edit->blockSignals(sb); q->update();}/*! \internal Convenience function to set min/max values.*/void QAbstractSpinBoxPrivate::setRange(const QVariant &min, const QVariant &max){ clearCache(); minimum = min; maximum = (variantCompare(min, max) < 0 ? max : min); reset(); if (!(bound(value) == value)) { setValue(bound(value), EmitIfChanged); } else if (value == minimum && !specialValueText.isEmpty()) { updateEdit(); }}/*! \internal Convenience function to get a variant of the right type.*/QVariant QAbstractSpinBoxPrivate::getZeroVariant() const{ QVariant ret; switch (type) { case QVariant::Int: ret = QVariant((int)0); break; case QVariant::Double: ret = QVariant((double)0.0); break; case QVariant::Time: ret = QVariant(QTime()); break; case QVariant::Date: ret = QVariant(QDATETIMEEDIT_DATE_INITIAL); break; case QVariant::DateTime: ret = QVariant(QDateTime(QDATETIMEEDIT_DATE_INITIAL, QTime())); break; default: break; } return ret;}/*! \internal Virtual method called that calls the public textFromValue() functions in the subclasses. Needed to change signature from QVariant to int/double/QDateTime etc. Used when needing to display a value textually. This method is reimeplemented in the various subclasses.*/QString QAbstractSpinBoxPrivate::textFromValue(const QVariant &) const{ return QString();}/*! \internal Virtual method called that calls the public valueFromText() functions in the subclasses. Needed to change signature from QVariant to int/double/QDateTime etc. Used when needing to interpret a string as another type. This method is reimeplemented in the various subclasses.*/QVariant QAbstractSpinBoxPrivate::valueFromText(const QString &) const{ return QVariant();}/*! \internal Interprets text and emits signals. Called when the spinbox needs to interpret the text on the lineedit.*/void QAbstractSpinBoxPrivate::interpret(EmitPolicy ep){ Q_Q(QAbstractSpinBox); if (type == QVariant::Invalid) return; QVariant v = getZeroVariant(); bool doInterpret = true; QString tmp = edit->displayText(); int pos = edit->cursorPosition(); const int oldpos = pos; if (q->validate(tmp, pos) != QValidator::Acceptable) { const QString copy = tmp; q->fixup(tmp); QASBDEBUG() << "QAbstractSpinBoxPrivate::interpret() text '" << edit->displayText() << "' >> '" << copy << "'" << "' >> '" << tmp << "'"; doInterpret = tmp != copy && (q->validate(tmp, pos) == QValidator::Acceptable); if (!doInterpret) { v = (correctionMode == QAbstractSpinBox::CorrectToNearestValue ? variantBound(minimum, v, maximum) : value); } } if (doInterpret) { v = valueFromText(tmp); } clearCache(); setValue(v, ep, true); if (oldpos != pos) edit->setCursorPosition(pos);}void QAbstractSpinBoxPrivate::clearCache() const{ cachedText.clear(); cachedValue.clear(); cachedState = QValidator::Acceptable;}// --- QSpinBoxValidator ---/*! \internal Constructs a QSpinBoxValidator object*/QSpinBoxValidator::QSpinBoxValidator(QAbstractSpinBox *qp, QAbstractSpinBoxPrivate *dp) : QValidator(qp), qptr(qp), dptr(dp){ setObjectName(QLatin1String("qt_spinboxvalidator"));}/*! \internal Checks for specialValueText, prefix, suffix and calls the virtual QAbstractSpinBox::validate function.*/QValidator::State QSpinBoxValidator::validate(QString &input, int &pos) const{ if (dptr->specialValueText.size() > 0 && input == dptr->specialValueText) return QValidator::Acceptable; if (!dptr->prefix.isEmpty() && !input.startsWith(dptr->prefix)) input.prepend(dptr->prefix); if (!dptr->suffix.isEmpty() && !input.endsWith(dptr->suffix)) input.append(dptr->suffix); return qptr->validate(input, pos);}/*! \internal Calls the virtual QAbstractSpinBox::fixup function.*/void QSpinBoxValidator::fixup(QString &input) const{ qptr->fixup(input);}// --- global ---/*! \internal Adds two variants together and returns the result.*/QVariant operator+(const QVariant &arg1, const QVariant &arg2){ QVariant ret; if (arg1.type() != arg2.type()) qWarning("QAbstractSpinBox: Internal error: Different types (%s vs %s) (%s:%d)", arg1.typeName(), arg2.typeName(), __FILE__, __LINE__); switch (arg1.type()) { case QVariant::Int: ret = QVariant(arg1.toInt() + arg2.toInt()); break; case QVariant::Double: ret = QVariant(arg1.toDouble() + arg2.toDouble()); break; case QVariant::DateTime: { QDateTime a2 = arg2.toDateTime(); QDateTime a1 = arg1.toDateTime().addDays(QDATETIMEEDIT_DATETIME_MIN.daysTo(a2)); a1.setTime(a1.time().addMSecs(QTime().msecsTo(a2.time()))); ret = QVariant(a1); } default: break; } return ret;}/*! \internal Subtracts two variants and returns the result.*/QVariant operator-(const QVariant &arg1, const QVariant &arg2){ QVariant ret; if (arg1.type() != arg2.type()) qWarning("QAbstractSpinBox: Internal error: Different types (%s vs %s) (%s:%d)", arg1.typeName(), arg2.typeName(), __FILE__, __LINE__); switch (arg1.type()) { case QVariant::Int: ret = QVariant(arg1.toInt() - arg2.toInt()); break; case QVariant::Double: ret = QVariant(arg1.toDouble() - arg2.toDouble()); break; case QVariant::DateTime: { QDateTime a1 = arg1.toDateTime(); QDateTime a2 = arg2.toDateTime(); int days = a2.daysTo(a1); int secs = a2.secsTo(a1); int msecs = qMax(0, a1.time().msec() - a2.time().msec()); if (days < 0 || secs < 0 || msecs < 0) { ret = arg1; } else { QDateTime dt = a2.addDays(days).addSecs(secs); if (msecs > 0) dt.setTime(dt.time().addMSecs(msecs)); ret = QVariant(dt); } } default: break; } return ret;}/*! \internal Multiplies \a arg1 by \a multiplier and returns the result.*/QVariant operator*(const QVariant &arg1, double multiplier){ QVariant ret; switch (arg1.type()) { case QVariant::Int: ret = QVariant((int)(arg1.toInt() * multiplier)); break; case QVariant::Double: ret = QVariant(arg1.toDouble() * multiplier); break; case QVariant::DateTime: { double days = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDateTime().date()) * multiplier; int daysInt = (int)days; days -= daysInt; long msecs = (long)((QDATETIMEEDIT_TIME_MIN.msecsTo(arg1.toDateTime().time()) * multiplier) + (days * (24 * 3600 * 1000))); ret = QDateTime(QDate().addDays(int(days)), QTime().addMSecs(msecs)); break; } default: ret = arg1; break; } return ret;}double operator/(const QVariant &arg1, const QVariant &arg2){ double a1 = 0; double a2 = 0; switch (arg1.type()) { case QVariant::Int: a1 = (double)arg1.toInt(); a2 = (double)arg2.toInt(); break; case QVariant::Double: a1 = arg1.toDouble(); a2 = arg2.toDouble(); break; case QVariant::DateTime: a1 = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDate()); a2 = QDATETIMEEDIT_DATE_MIN.daysTo(arg2.toDate()); a1 += (double)QDATETIMEEDIT_TIME_MIN.msecsTo(arg1.toDateTime().time()) / (long)(3600 * 24 * 1000); a2 += (double)QDATETIMEEDIT_TIME_MIN.msecsTo(arg2.toDateTime().time()) / (long)(3600 * 24 * 1000); default: break; } return (a1 != 0 && a2 != 0) ? (a1 / a2) : 0.0;}int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant &arg2){ switch (arg2.type()) { case QVariant::Date: Q_ASSERT_X(arg1.type() == QVariant::Date, "QAbstractSpinBoxPrivate::variantCompare", qPrintable(QString::fromAscii("Internal error 1 (%1)"). arg(QString::fromAscii(arg1.typeName())))); if (arg1.toDate() == arg2.toDate()) { return 0; } else if (arg1.toDate() < arg2.toDate()) { return -1; } else { return 1; } case QVariant::Time: Q_ASSERT_X(arg1.type() == QVariant::Time, "QAbstractSpinBoxPrivate::variantCompare", qPrintable(QString::fromAscii("Internal error 2 (%1)"). arg(QString::fromAscii(arg1.typeName())))); if (arg1.toTime() == arg2.toTime()) { return 0; } else if (arg1.toTime() < arg2.toTime()) { return -1; } else { return 1; } case QVariant::DateTime: if (arg1.toDateTime() == arg2.toDateTime()) { return 0; } else if (arg1.toDateTime() < arg2.toDateTime()) { return -1; } else { return 1; } case QVariant::Int: if (arg1.toInt() == arg2.toInt()) { return 0; } else if (arg1.toInt() < arg2.toInt()) { return -1; } else { return 1; } case QVariant::Double: if (arg1.toDouble() == arg2.toDouble()) { return 0; } else if (arg1.toDouble() < arg2.toDouble()) { return -1; } else { return 1; } case QVariant::Invalid: if (arg2.type() == QVariant::Invalid) return 0; default: Q_ASSERT_X(0, "QAbstractSpinBoxPrivate::variantCompare", qPrintable(QString::fromAscii("Internal error 3 (%1 %2)"). arg(QString::fromAscii(arg1.typeName())). arg(QString::fromAscii(arg2.typeName())))); } return -2;}QVariant QAbstractSpinBoxPrivate::variantBound(const QVariant &min, const QVariant &value, const QVariant &max){ Q_ASSERT(variantCompare(min, max) <= 0); if (variantCompare(min, value) < 0) { const int compMax = variantCompare(value, max); return (compMax < 0 ? value : max); } else { return min; }}#include "moc_qabstractspinbox.cpp"#endif // QT_NO_SPINBOX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -