diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2011-05-07 00:02:01 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@nokia.com> | 2011-05-07 00:02:01 +0200 |
commit | f67b8df3ebdba2d398b9cce686b7c644adffff08 (patch) | |
tree | 062dd469f7cf8daa01a32d3e7b767b8fbdb7573a /src/gui/widgets/qabstractspinbox.cpp | |
parent | 32ce4fe9e6a94e77828e976776cf08da85254ff2 (diff) |
library split
Diffstat (limited to 'src/gui/widgets/qabstractspinbox.cpp')
-rw-r--r-- | src/gui/widgets/qabstractspinbox.cpp | 2122 |
1 files changed, 0 insertions, 2122 deletions
diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp deleted file mode 100644 index 34991ab236..0000000000 --- a/src/gui/widgets/qabstractspinbox.cpp +++ /dev/null @@ -1,2122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qplatformdefs.h> -#include <private/qabstractspinbox_p.h> -#include <private/qdatetime_p.h> -#include <private/qlineedit_p.h> -#include <qabstractspinbox.h> - -#ifndef QT_NO_SPINBOX - -#include <qapplication.h> -#include <qclipboard.h> -#include <qdatetime.h> -#include <qdatetimeedit.h> -#include <qevent.h> -#include <qmenu.h> -#include <qpainter.h> -#include <qpalette.h> -#include <qstylepainter.h> -#include <qdebug.h> -#ifndef QT_NO_ACCESSIBILITY -# include <qaccessible.h> -#endif - -#if defined(Q_WS_X11) -#include <limits.h> -#endif - -#if defined(Q_OS_SYMBIAN) -#include <w32std.h> -#include <private/qt_s60_p.h> -#endif - -//#define QABSTRACTSPINBOX_QSBDEBUG -#ifdef QABSTRACTSPINBOX_QSBDEBUG -# define QASBDEBUG qDebug -#else -# define QASBDEBUG if (false) qDebug -#endif - -QT_BEGIN_NAMESPACE - -/*! - \class QAbstractSpinBox - \brief The QAbstractSpinBox class provides a spinbox and a line edit to - display values. - - \ingroup abstractwidgets - - The class is designed as a common super class for widgets like - QSpinBox, QDoubleSpinBox and QDateTimeEdit - - Here are the main properties of the class: - - \list 1 - - \i \l text: The text that is displayed in the QAbstractSpinBox. - - \i \l alignment: The alignment of the text in the QAbstractSpinBox. - - \i \l wrapping: Whether the QAbstractSpinBox wraps from the - minimum value to the maximum value and vica versa. - - \endlist - - QAbstractSpinBox provides a virtual stepBy() function that is - called whenever the user triggers a step. This function takes an - integer value to signify how many steps were taken. E.g. Pressing - Qt::Key_Down will trigger a call to stepBy(-1). - - QAbstractSpinBox also provide a virtual function stepEnabled() to - determine whether stepping up/down is allowed at any point. This - function returns a bitset of StepEnabled. - - \sa QAbstractSlider, QSpinBox, QDoubleSpinBox, QDateTimeEdit, - {Spin Boxes Example} -*/ - -/*! - \enum QAbstractSpinBox::StepEnabledFlag - - \value StepNone - \value StepUpEnabled - \value StepDownEnabled -*/ - -/*! - \fn void QAbstractSpinBox::editingFinished() - - This signal is emitted editing is finished. This happens when the - spinbox loses focus and when enter is pressed. -*/ - -/*! - Constructs an abstract spinbox with the given \a parent with default - \l wrapping, and \l alignment properties. -*/ - -QAbstractSpinBox::QAbstractSpinBox(QWidget *parent) - : QWidget(*new QAbstractSpinBoxPrivate, parent, 0) -{ - Q_D(QAbstractSpinBox); - d->init(); -} - -/*! - \internal -*/ -QAbstractSpinBox::QAbstractSpinBox(QAbstractSpinBoxPrivate &dd, QWidget *parent) - : QWidget(dd, parent, 0) -{ - Q_D(QAbstractSpinBox); - d->init(); -} - -/*! - Called when the QAbstractSpinBox is destroyed. -*/ - -QAbstractSpinBox::~QAbstractSpinBox() -{ -} - -/*! - \enum QAbstractSpinBox::ButtonSymbols - - This enum type describes the symbols that can be displayed on the buttons - in a spin box. - - \inlineimage qspinbox-updown.png - \inlineimage qspinbox-plusminus.png - - \value UpDownArrows Little arrows in the classic style. - \value PlusMinus \bold{+} and \bold{-} symbols. - \value NoButtons Don't display buttons. - - \sa QAbstractSpinBox::buttonSymbols -*/ - -/*! - \property QAbstractSpinBox::buttonSymbols - - \brief the current button symbol mode - - The possible values can be either \c UpDownArrows or \c PlusMinus. - The default is \c UpDownArrows. - - Note that some styles might render PlusMinus and UpDownArrows - identically. - - \sa ButtonSymbols -*/ - -QAbstractSpinBox::ButtonSymbols QAbstractSpinBox::buttonSymbols() const -{ - Q_D(const QAbstractSpinBox); - return d->buttonSymbols; -} - -void QAbstractSpinBox::setButtonSymbols(ButtonSymbols buttonSymbols) -{ - Q_D(QAbstractSpinBox); - if (d->buttonSymbols != buttonSymbols) { - d->buttonSymbols = buttonSymbols; - d->updateEditFieldGeometry(); - update(); - } -} - -/*! - \property QAbstractSpinBox::text - - \brief the spin box's text, including any prefix and suffix - - There is no default text. -*/ - -QString QAbstractSpinBox::text() const -{ - return lineEdit()->displayText(); -} - - -/*! - \property QAbstractSpinBox::specialValueText - \brief the special-value text - - If set, the spin box will display this text instead of a numeric - value whenever the current value is equal to minimum(). Typical use - is to indicate that this choice has a special (default) meaning. - - For example, if your spin box allows the user to choose a scale factor - (or zoom level) for displaying an image, and your application is able - to automatically choose one that will enable the image to fit completely - within the display window, you can set up the spin box like this: - - \snippet examples/widgets/spinboxes/window.cpp 3 - - The user will then be able to choose a scale from 1% to 1000% - or select "Auto" to leave it up to the application to choose. Your code - must then interpret the spin box value of 0 as a request from the user - to scale the image to fit inside the window. - - All values are displayed with the prefix and suffix (if set), \e - except for the special value, which only shows the special value - text. This special text is passed in the QSpinBox::valueChanged() - signal that passes a QString. - - To turn off the special-value text display, call this function - with an empty string. The default is no special-value text, i.e. - the numeric value is shown as usual. - - If no special-value text is set, specialValueText() returns an - empty string. -*/ - -QString QAbstractSpinBox::specialValueText() const -{ - Q_D(const QAbstractSpinBox); - return d->specialValueText; -} - -void QAbstractSpinBox::setSpecialValueText(const QString &specialValueText) -{ - Q_D(QAbstractSpinBox); - - d->specialValueText = specialValueText; - d->cachedSizeHint = QSize(); // minimumSizeHint doesn't care about specialValueText - d->clearCache(); - d->updateEdit(); -} - -/*! - \property QAbstractSpinBox::wrapping - - \brief whether the spin box is circular. - - If wrapping is true stepping up from maximum() value will take you - to the minimum() value and vica versa. Wrapping only make sense if - you have minimum() and maximum() values set. - - \snippet doc/src/snippets/code/src_gui_widgets_qabstractspinbox.cpp 0 - - \sa QSpinBox::minimum(), QSpinBox::maximum() -*/ - -bool QAbstractSpinBox::wrapping() const -{ - Q_D(const QAbstractSpinBox); - return d->wrapping; -} - -void QAbstractSpinBox::setWrapping(bool wrapping) -{ - Q_D(QAbstractSpinBox); - d->wrapping = wrapping; -} - - -/*! - \property QAbstractSpinBox::readOnly - \brief whether the spin box is read only. - - In read-only mode, the user can still copy the text to the - clipboard, or drag and drop the text; - but cannot edit it. - - The QLineEdit in the QAbstractSpinBox does not show a cursor in - read-only mode. - - \sa QLineEdit::readOnly -*/ - -bool QAbstractSpinBox::isReadOnly() const -{ - Q_D(const QAbstractSpinBox); - return d->readOnly; -} - -void QAbstractSpinBox::setReadOnly(bool enable) -{ - Q_D(QAbstractSpinBox); - d->readOnly = enable; - d->edit->setReadOnly(enable); - update(); -} - -/*! - \property QAbstractSpinBox::keyboardTracking - \brief whether keyboard tracking is enabled for the spinbox. - \since 4.3 - - If keyboard tracking is enabled (the default), the spinbox - emits the valueChanged() signal while the new value is being - entered from the keyboard. - - E.g. when the user enters the value 600 by typing 6, 0, and 0, - the spinbox emits 3 signals with the values 6, 60, and 600 - respectively. - - If keyboard tracking is disabled, the spinbox doesn't emit the - valueChanged() signal while typing. It emits the signal later, - when the return key is pressed, when keyboard focus is lost, or - when other spinbox functionality is used, e.g. pressing an arrow - key. -*/ - -bool QAbstractSpinBox::keyboardTracking() const -{ - Q_D(const QAbstractSpinBox); - return d->keyboardTracking; -} - -void QAbstractSpinBox::setKeyboardTracking(bool enable) -{ - Q_D(QAbstractSpinBox); - d->keyboardTracking = enable; -} - -/*! - \property QAbstractSpinBox::frame - \brief whether the spin box draws itself with a frame - - If enabled (the default) the spin box draws itself inside a frame, - otherwise the spin box draws itself without any frame. -*/ - -bool QAbstractSpinBox::hasFrame() const -{ - Q_D(const QAbstractSpinBox); - return d->frame; -} - - -void QAbstractSpinBox::setFrame(bool enable) -{ - Q_D(QAbstractSpinBox); - d->frame = enable; - update(); - d->updateEditFieldGeometry(); -} - -/*! - \property QAbstractSpinBox::accelerated - \brief whether the spin box will accelerate the frequency of the steps when - pressing the step Up/Down buttons. - \since 4.2 - - If enabled the spin box will increase/decrease the value faster - the longer you hold the button down. -*/ - -void QAbstractSpinBox::setAccelerated(bool accelerate) -{ - Q_D(QAbstractSpinBox); - d->accelerate = accelerate; - -} -bool QAbstractSpinBox::isAccelerated() const -{ - Q_D(const QAbstractSpinBox); - return d->accelerate; -} - -/*! - \enum QAbstractSpinBox::CorrectionMode - - This enum type describes the mode the spinbox will use to correct - an \l{QValidator::}{Intermediate} value if editing finishes. - - \value CorrectToPreviousValue The spinbox will revert to the last - valid value. - - \value CorrectToNearestValue The spinbox will revert to the nearest - valid value. - - \sa correctionMode -*/ - -/*! - \property QAbstractSpinBox::correctionMode - \brief the mode to correct an \l{QValidator::}{Intermediate} - value if editing finishes - \since 4.2 - - The default mode is QAbstractSpinBox::CorrectToPreviousValue. - - \sa acceptableInput, validate(), fixup() -*/ -void QAbstractSpinBox::setCorrectionMode(CorrectionMode correctionMode) -{ - Q_D(QAbstractSpinBox); - d->correctionMode = correctionMode; - -} -QAbstractSpinBox::CorrectionMode QAbstractSpinBox::correctionMode() const -{ - Q_D(const QAbstractSpinBox); - return d->correctionMode; -} - - -/*! - \property QAbstractSpinBox::acceptableInput - \brief whether the input satisfies the current validation - \since 4.2 - - \sa validate(), fixup(), correctionMode -*/ - -bool QAbstractSpinBox::hasAcceptableInput() const -{ - Q_D(const QAbstractSpinBox); - return d->edit->hasAcceptableInput(); -} - -/*! - \property QAbstractSpinBox::alignment - \brief the alignment of the spin box - - Possible Values are Qt::AlignLeft, Qt::AlignRight, and Qt::AlignHCenter. - - By default, the alignment is Qt::AlignLeft - - Attempting to set the alignment to an illegal flag combination - does nothing. - - \sa Qt::Alignment -*/ - -Qt::Alignment QAbstractSpinBox::alignment() const -{ - Q_D(const QAbstractSpinBox); - - return (Qt::Alignment)d->edit->alignment(); -} - -void QAbstractSpinBox::setAlignment(Qt::Alignment flag) -{ - Q_D(QAbstractSpinBox); - - d->edit->setAlignment(flag); -} - -/*! - Selects all the text in the spinbox except the prefix and suffix. -*/ - -void QAbstractSpinBox::selectAll() -{ - Q_D(QAbstractSpinBox); - - - if (!d->specialValue()) { - const int tmp = d->edit->displayText().size() - d->suffix.size(); - d->edit->setSelection(tmp, -(tmp - d->prefix.size())); - } else { - d->edit->selectAll(); - } -} - -/*! - Clears the lineedit of all text but prefix and suffix. -*/ - -void QAbstractSpinBox::clear() -{ - Q_D(QAbstractSpinBox); - - d->edit->setText(d->prefix + d->suffix); - d->edit->setCursorPosition(d->prefix.size()); - d->cleared = true; -} - -/*! - Virtual function that determines whether stepping up and down is - legal at any given time. - - The up arrow will be painted as disabled unless (stepEnabled() & - StepUpEnabled) != 0. - - The default implementation will return (StepUpEnabled| - StepDownEnabled) if wrapping is turned on. Else it will return - StepDownEnabled if value is > minimum() or'ed with StepUpEnabled if - value < maximum(). - - If you subclass QAbstractSpinBox you will need to reimplement this function. - - \sa QSpinBox::minimum(), QSpinBox::maximum(), wrapping() -*/ - - -QAbstractSpinBox::StepEnabled QAbstractSpinBox::stepEnabled() const -{ - Q_D(const QAbstractSpinBox); - if (d->readOnly || d->type == QVariant::Invalid) - return StepNone; - if (d->wrapping) - return StepEnabled(StepUpEnabled | StepDownEnabled); - StepEnabled ret = StepNone; - if (d->variantCompare(d->value, d->maximum) < 0) { - ret |= StepUpEnabled; - } - if (d->variantCompare(d->value, d->minimum) > 0) { - ret |= StepDownEnabled; - } - return ret; -} - -/*! - This virtual function is called by the QAbstractSpinBox to - determine whether \a input is valid. The \a pos parameter indicates - the position in the string. Reimplemented in the various - subclasses. -*/ - -QValidator::State QAbstractSpinBox::validate(QString & /* input */, int & /* pos */) const -{ - return QValidator::Acceptable; -} - -/*! - This virtual function is called by the QAbstractSpinBox if the - \a input is not validated to QValidator::Acceptable when Return is - pressed or interpretText() is called. It will try to change the - text so it is valid. Reimplemented in the various subclasses. -*/ - -void QAbstractSpinBox::fixup(QString & /* input */) const -{ -} - -/*! - Steps up by one linestep - Calling this slot is analogous to calling stepBy(1); - \sa stepBy(), stepDown() -*/ - -void QAbstractSpinBox::stepUp() -{ - stepBy(1); -} - -/*! - Steps down by one linestep - Calling this slot is analogous to calling stepBy(-1); - \sa stepBy(), stepUp() -*/ - -void QAbstractSpinBox::stepDown() -{ - stepBy(-1); -} -/*! - Virtual function that is called whenever the user triggers a step. - The \a steps parameter indicates how many steps were taken, e.g. - Pressing Qt::Key_Down will trigger a call to stepBy(-1), - whereas pressing Qt::Key_Prior will trigger a call to - stepBy(10). - - If you subclass QAbstractSpinBox you must reimplement this - function. Note that this function is called even if the resulting - value will be outside the bounds of minimum and maximum. It's this - function's job to handle these situations. -*/ - -void QAbstractSpinBox::stepBy(int steps) -{ - Q_D(QAbstractSpinBox); - - const QVariant old = d->value; - QString tmp = d->edit->displayText(); - int cursorPos = d->edit->cursorPosition(); - bool dontstep = false; - EmitPolicy e = EmitIfChanged; - if (d->pendingEmit) { - dontstep = validate(tmp, cursorPos) != QValidator::Acceptable; - d->cleared = false; - d->interpret(NeverEmit); - if (d->value != old) - e = AlwaysEmit; - } - if (!dontstep) { - d->setValue(d->bound(d->value + (d->singleStep * steps), old, steps), e); - } else if (e == AlwaysEmit) { - d->emitSignals(e, old); - } - selectAll(); -} - -/*! - This function returns a pointer to the line edit of the spin box. -*/ - -QLineEdit *QAbstractSpinBox::lineEdit() const -{ - Q_D(const QAbstractSpinBox); - - return d->edit; -} - - -/*! - \fn void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit) - - Sets the line edit of the spinbox to be \a lineEdit instead of the - current line edit widget. \a lineEdit can not be 0. - - QAbstractSpinBox takes ownership of the new lineEdit - - If QLineEdit::validator() for the \a lineEdit returns 0, the internal - validator of the spinbox will be set on the line edit. -*/ - -void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit) -{ - Q_D(QAbstractSpinBox); - - if (!lineEdit) { - Q_ASSERT(lineEdit); - return; - } - delete d->edit; - d->edit = lineEdit; - if (!d->edit->validator()) - d->edit->setValidator(d->validator); - - if (d->edit->parent() != this) - d->edit->setParent(this); - - d->edit->setFrame(false); - d->edit->setFocusProxy(this); - d->edit->setAcceptDrops(false); - - if (d->type != QVariant::Invalid) { - connect(d->edit, SIGNAL(textChanged(QString)), - this, SLOT(_q_editorTextChanged(QString))); - connect(d->edit, SIGNAL(cursorPositionChanged(int,int)), - this, SLOT(_q_editorCursorPositionChanged(int,int))); - } - d->updateEditFieldGeometry(); - d->edit->setContextMenuPolicy(Qt::NoContextMenu); - - if (isVisible()) - d->edit->show(); - if (isVisible()) - d->updateEdit(); -} - - -/*! - This function interprets the text of the spin box. If the value - has changed since last interpretation it will emit signals. -*/ - -void QAbstractSpinBox::interpretText() -{ - Q_D(QAbstractSpinBox); - d->interpret(EmitIfChanged); -} - -/* - Reimplemented in 4.6, so be careful. - */ -/*! - \reimp -*/ -QVariant QAbstractSpinBox::inputMethodQuery(Qt::InputMethodQuery query) const -{ - Q_D(const QAbstractSpinBox); - return d->edit->inputMethodQuery(query); -} - -/*! - \reimp -*/ - -bool QAbstractSpinBox::event(QEvent *event) -{ - Q_D(QAbstractSpinBox); - switch (event->type()) { - case QEvent::FontChange: - case QEvent::StyleChange: - d->cachedSizeHint = d->cachedMinimumSizeHint = QSize(); - break; - case QEvent::ApplicationLayoutDirectionChange: - case QEvent::LayoutDirectionChange: - d->updateEditFieldGeometry(); - break; - case QEvent::HoverEnter: - case QEvent::HoverLeave: - case QEvent::HoverMove: - if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event)) - d->updateHoverControl(he->pos()); - break; - case QEvent::ShortcutOverride: - if (d->edit->event(event)) - return true; - break; -#ifdef QT_KEYPAD_NAVIGATION - case QEvent::EnterEditFocus: - case QEvent::LeaveEditFocus: - if (QApplication::keypadNavigationEnabled()) { - const bool b = d->edit->event(event); - d->edit->setSelection(d->edit->displayText().size() - d->suffix.size(),0); - if (event->type() == QEvent::LeaveEditFocus) - emit editingFinished(); - if (b) - return true; - } - break; -#endif - case QEvent::InputMethod: - return d->edit->event(event); - default: - break; - } - return QWidget::event(event); -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::showEvent(QShowEvent *) -{ - Q_D(QAbstractSpinBox); - d->reset(); - - if (d->ignoreUpdateEdit) { - d->ignoreUpdateEdit = false; - } else { - d->updateEdit(); - } -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::changeEvent(QEvent *event) -{ - Q_D(QAbstractSpinBox); - - switch (event->type()) { - case QEvent::StyleChange: - d->spinClickTimerInterval = style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatRate, 0, this); - d->spinClickThresholdTimerInterval = - style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold, 0, this); - d->reset(); - d->updateEditFieldGeometry(); - break; - case QEvent::EnabledChange: - if (!isEnabled()) { - d->reset(); - } - break; - case QEvent::ActivationChange: - if (!isActiveWindow()){ - d->reset(); - if (d->pendingEmit) // pendingEmit can be true even if it hasn't changed. - d->interpret(EmitIfChanged); // E.g. 10 to 10.0 - } - break; - default: - break; - } - QWidget::changeEvent(event); -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::resizeEvent(QResizeEvent *event) -{ - Q_D(QAbstractSpinBox); - QWidget::resizeEvent(event); - - d->updateEditFieldGeometry(); - update(); -} - -/*! - \reimp -*/ - -QSize QAbstractSpinBox::sizeHint() const -{ - Q_D(const QAbstractSpinBox); - if (d->cachedSizeHint.isEmpty()) { - ensurePolished(); - - const QFontMetrics fm(fontMetrics()); - int h = d->edit->sizeHint().height(); - int w = 0; - QString s; - s = d->prefix + d->textFromValue(d->minimum) + d->suffix + QLatin1Char(' '); - s.truncate(18); - w = qMax(w, fm.width(s)); - s = d->prefix + d->textFromValue(d->maximum) + d->suffix + QLatin1Char(' '); - s.truncate(18); - w = qMax(w, fm.width(s)); - if (d->specialValueText.size()) { - s = d->specialValueText; - w = qMax(w, fm.width(s)); - } - w += 2; // cursor blinking space - - QStyleOptionSpinBox opt; - initStyleOption(&opt); - QSize hint(w, h); - QSize extra(35, 6); - opt.rect.setSize(hint + extra); - extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt, - QStyle::SC_SpinBoxEditField, this).size(); - // get closer to final result by repeating the calculation - opt.rect.setSize(hint + extra); - extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt, - QStyle::SC_SpinBoxEditField, this).size(); - hint += extra; - - opt.rect = rect(); - d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this) - .expandedTo(QApplication::globalStrut()); - } - return d->cachedSizeHint; -} - -/*! - \reimp -*/ - -QSize QAbstractSpinBox::minimumSizeHint() const -{ - Q_D(const QAbstractSpinBox); - if (d->cachedMinimumSizeHint.isEmpty()) { - ensurePolished(); - - const QFontMetrics fm(fontMetrics()); - int h = d->edit->minimumSizeHint().height(); - int w = fm.width(QLatin1String("1000")); - w += 2; // cursor blinking space - - QStyleOptionSpinBox opt; - initStyleOption(&opt); - QSize hint(w, h); - QSize extra(35, 6); - opt.rect.setSize(hint + extra); - extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt, - QStyle::SC_SpinBoxEditField, this).size(); - // get closer to final result by repeating the calculation - opt.rect.setSize(hint + extra); - extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt, - QStyle::SC_SpinBoxEditField, this).size(); - hint += extra; - - opt.rect = rect(); - - d->cachedMinimumSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this) - .expandedTo(QApplication::globalStrut()); - } - return d->cachedMinimumSizeHint; -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::paintEvent(QPaintEvent *) -{ - QStyleOptionSpinBox opt; - initStyleOption(&opt); - QStylePainter p(this); - p.drawComplexControl(QStyle::CC_SpinBox, opt); -} - -/*! - \reimp - - This function handles keyboard input. - - The following keys are handled specifically: - \table - \row \i Enter/Return - \i This will reinterpret the text and emit a signal even if the value has not changed - since last time a signal was emitted. - \row \i Up - \i This will invoke stepBy(1) - \row \i Down - \i This will invoke stepBy(-1) - \row \i Page up - \i This will invoke stepBy(10) - \row \i Page down - \i This will invoke stepBy(-10) - \endtable -*/ - - -void QAbstractSpinBox::keyPressEvent(QKeyEvent *event) -{ - Q_D(QAbstractSpinBox); - - if (!event->text().isEmpty() && d->edit->cursorPosition() < d->prefix.size()) - d->edit->setCursorPosition(d->prefix.size()); - - int steps = 1; - bool isPgUpOrDown = false; - switch (event->key()) { - case Qt::Key_PageUp: - case Qt::Key_PageDown: - steps *= 10; - isPgUpOrDown = true; - case Qt::Key_Up: - case Qt::Key_Down: { -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { - // Reserve up/down for nav - use left/right for edit. - if (!hasEditFocus() && (event->key() == Qt::Key_Up - || event->key() == Qt::Key_Down)) { - event->ignore(); - return; - } - } -#endif - event->accept(); - const bool up = (event->key() == Qt::Key_PageUp || event->key() == Qt::Key_Up); - if (!(stepEnabled() & (up ? StepUpEnabled : StepDownEnabled))) - return; - if (!up) - steps *= -1; - if (style()->styleHint(QStyle::SH_SpinBox_AnimateButton, 0, this)) { - d->buttonState = (Keyboard | (up ? Up : Down)); - } - if (d->spinClickTimerId == -1) - stepBy(steps); - if(event->isAutoRepeat() && !isPgUpOrDown) { - if(d->spinClickThresholdTimerId == -1 && d->spinClickTimerId == -1) { - d->updateState(up, true); - } - } -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(this, 0, QAccessible::ValueChanged); -#endif - return; - } -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Left: - case Qt::Key_Right: - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { - event->ignore(); - return; - } - break; - case Qt::Key_Back: - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { - event->ignore(); - return; - } - break; -#endif - case Qt::Key_Enter: - case Qt::Key_Return: - d->edit->d_func()->control->clearUndo(); - d->interpret(d->keyboardTracking ? AlwaysEmit : EmitIfChanged); - selectAll(); - event->ignore(); - emit editingFinished(); - return; - -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Select: - if (QApplication::keypadNavigationEnabled()) { - // Toggles between left/right moving cursor and inc/dec. - setEditFocus(!hasEditFocus()); - } - return; -#endif - -#ifdef Q_WS_X11 // only X11 - case Qt::Key_U: - if (event->modifiers() & Qt::ControlModifier) { - event->accept(); - if (!isReadOnly()) - clear(); - return; - } - break; -#endif - - case Qt::Key_End: - case Qt::Key_Home: - if (event->modifiers() & Qt::ShiftModifier) { - int currentPos = d->edit->cursorPosition(); - const QString text = d->edit->displayText(); - if (event->key() == Qt::Key_End) { - if ((currentPos == 0 && !d->prefix.isEmpty()) || text.size() - d->suffix.size() <= currentPos) { - break; // let lineedit handle this - } else { - d->edit->setSelection(currentPos, text.size() - d->suffix.size() - currentPos); - } - } else { - if ((currentPos == text.size() && !d->suffix.isEmpty()) || currentPos <= d->prefix.size()) { - break; // let lineedit handle this - } else { - d->edit->setSelection(currentPos, d->prefix.size() - currentPos); - } - } - event->accept(); - return; - } - break; - - default: -#ifndef QT_NO_SHORTCUT - if (event == QKeySequence::SelectAll) { - selectAll(); - event->accept(); - return; - } -#endif - break; - } - - d->edit->event(event); - if (!isVisible()) - d->ignoreUpdateEdit = true; -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::keyReleaseEvent(QKeyEvent *event) -{ - Q_D(QAbstractSpinBox); - - if (d->buttonState & Keyboard && !event->isAutoRepeat()) { - d->reset(); - } else { - d->edit->event(event); - } -} - -/*! - \reimp -*/ - -#ifndef QT_NO_WHEELEVENT -void QAbstractSpinBox::wheelEvent(QWheelEvent *event) -{ - const int steps = (event->delta() > 0 ? 1 : -1); - if (stepEnabled() & (steps > 0 ? StepUpEnabled : StepDownEnabled)) - stepBy(event->modifiers() & Qt::ControlModifier ? steps * 10 : steps); - event->accept(); -} -#endif - - -/*! - \reimp -*/ -void QAbstractSpinBox::focusInEvent(QFocusEvent *event) -{ - Q_D(QAbstractSpinBox); - - d->edit->event(event); - if (event->reason() == Qt::TabFocusReason || event->reason() == Qt::BacktabFocusReason) { - selectAll(); - } - QWidget::focusInEvent(event); -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::focusOutEvent(QFocusEvent *event) -{ - Q_D(QAbstractSpinBox); - - if (d->pendingEmit) - d->interpret(EmitIfChanged); - - d->reset(); - d->edit->event(event); - d->updateEdit(); - QWidget::focusOutEvent(event); - -#ifdef QT_KEYPAD_NAVIGATION - // editingFinished() is already emitted on LeaveEditFocus - if (!QApplication::keypadNavigationEnabled()) -#endif - emit editingFinished(); -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::closeEvent(QCloseEvent *event) -{ - Q_D(QAbstractSpinBox); - - d->reset(); - if (d->pendingEmit) - d->interpret(EmitIfChanged); - QWidget::closeEvent(event); -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::hideEvent(QHideEvent *event) -{ - Q_D(QAbstractSpinBox); - d->reset(); - if (d->pendingEmit) - d->interpret(EmitIfChanged); - QWidget::hideEvent(event); -} - - -/*! - \internal - - Used when acceleration is turned on. We need to get the - keyboard auto repeat rate from OS. This value is used as - argument when starting acceleration related timers. - - Every platform should, either, use native calls to obtain - the value or hard code some reasonable rate. - - Remember that time value should be given in msecs. -*/ -static int getKeyboardAutoRepeatRate() { - int ret = 30; -#if defined(Q_OS_SYMBIAN) - TTimeIntervalMicroSeconds32 initialTime; - TTimeIntervalMicroSeconds32 time; - S60->wsSession().GetKeyboardRepeatRate(initialTime, time); - ret = time.Int() / 1000; // msecs -#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - DWORD time; - if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &time, 0) != FALSE) - ret = static_cast<int>(1000 / static_cast<int>(time)); // msecs -#endif - return ret; // msecs -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::timerEvent(QTimerEvent *event) -{ - Q_D(QAbstractSpinBox); - - bool doStep = false; - if (event->timerId() == d->spinClickThresholdTimerId) { - killTimer(d->spinClickThresholdTimerId); - d->spinClickThresholdTimerId = -1; - d->effectiveSpinRepeatRate = d->buttonState & Keyboard - ? getKeyboardAutoRepeatRate() - : d->spinClickTimerInterval; - d->spinClickTimerId = startTimer(d->effectiveSpinRepeatRate); - doStep = true; - } else if (event->timerId() == d->spinClickTimerId) { - if (d->accelerate) { - d->acceleration = d->acceleration + (int)(d->effectiveSpinRepeatRate * 0.05); - if (d->effectiveSpinRepeatRate - d->acceleration >= 10) { - killTimer(d->spinClickTimerId); - d->spinClickTimerId = startTimer(d->effectiveSpinRepeatRate - d->acceleration); - } - } - doStep = true; - } - - if (doStep) { - const StepEnabled st = stepEnabled(); - if (d->buttonState & Up) { - if (!(st & StepUpEnabled)) { - d->reset(); - } else { - stepBy(1); - } - } else if (d->buttonState & Down) { - if (!(st & StepDownEnabled)) { - d->reset(); - } else { - stepBy(-1); - } - } - return; - } - QWidget::timerEvent(event); - return; -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::contextMenuEvent(QContextMenuEvent *event) -{ -#ifdef QT_NO_CONTEXTMENU - Q_UNUSED(event); -#else - Q_D(QAbstractSpinBox); - - QPointer<QMenu> menu = d->edit->createStandardContextMenu(); - if (!menu) - return; - - d->reset(); - - QAction *selAll = new QAction(tr("&Select All"), menu); - menu->insertAction(d->edit->d_func()->selectAllAction, - selAll); - menu->removeAction(d->edit->d_func()->selectAllAction); - menu->addSeparator(); - const uint se = stepEnabled(); - QAction *up = menu->addAction(tr("&Step up")); - up->setEnabled(se & StepUpEnabled); - QAction *down = menu->addAction(tr("Step &down")); - down->setEnabled(se & StepDownEnabled); - menu->addSeparator(); - - const QPointer<QAbstractSpinBox> that = this; - const QPoint pos = (event->reason() == QContextMenuEvent::Mouse) - ? event->globalPos() : mapToGlobal(QPoint(event->pos().x(), 0)) + QPoint(width() / 2, height() / 2); - const QAction *action = menu->exec(pos); - delete static_cast<QMenu *>(menu); - if (that && action) { - if (action == up) { - stepBy(1); - } else if (action == down) { - stepBy(-1); - } else if (action == selAll) { - selectAll(); - } - } - event->accept(); -#endif // QT_NO_CONTEXTMENU -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::mouseMoveEvent(QMouseEvent *event) -{ - Q_D(QAbstractSpinBox); - - d->updateHoverControl(event->pos()); - - // If we have a timer ID, update the state - if (d->spinClickTimerId != -1 && d->buttonSymbols != NoButtons) { - const StepEnabled se = stepEnabled(); - if ((se & StepUpEnabled) && d->hoverControl == QStyle::SC_SpinBoxUp) - d->updateState(true); - else if ((se & StepDownEnabled) && d->hoverControl == QStyle::SC_SpinBoxDown) - d->updateState(false); - else - d->reset(); - event->accept(); - } -} - -/*! - \reimp -*/ - -void QAbstractSpinBox::mousePressEvent(QMouseEvent *event) -{ - Q_D(QAbstractSpinBox); - - if (event->button() != Qt::LeftButton || d->buttonState != None) { - return; - } - - d->updateHoverControl(event->pos()); - event->accept(); - - const StepEnabled se = (d->buttonSymbols == NoButtons) ? StepEnabled(StepNone) : stepEnabled(); - if ((se & StepUpEnabled) && d->hoverControl == QStyle::SC_SpinBoxUp) { - d->updateState(true); - } else if ((se & StepDownEnabled) && d->hoverControl == QStyle::SC_SpinBoxDown) { - d->updateState(false); - } else { - event->ignore(); - } -} - -/*! - \reimp -*/ -void QAbstractSpinBox::mouseReleaseEvent(QMouseEvent *event) -{ - Q_D(QAbstractSpinBox); - - if ((d->buttonState & Mouse) != 0) - d->reset(); - event->accept(); -} - -// --- QAbstractSpinBoxPrivate --- - -/*! - \internal - Constructs a QAbstractSpinBoxPrivate object -*/ - -QAbstractSpinBoxPrivate::QAbstractSpinBoxPrivate() - : edit(0), type(QVariant::Invalid), spinClickTimerId(-1), - spinClickTimerInterval(100), spinClickThresholdTimerId(-1), spinClickThresholdTimerInterval(-1), - effectiveSpinRepeatRate(1), buttonState(None), cachedText(QLatin1String("\x01")), - cachedState(QValidator::Invalid), pendingEmit(false), readOnly(false), wrapping(false), - ignoreCursorPositionChanged(false), frame(true), accelerate(false), keyboardTracking(true), - cleared(false), ignoreUpdateEdit(false), correctionMode(QAbstractSpinBox::CorrectToPreviousValue), - acceleration(0), hoverControl(QStyle::SC_None), buttonSymbols(QAbstractSpinBox::UpDownArrows), validator(0) -{ -} - -/* - \internal - Called when the QAbstractSpinBoxPrivate is destroyed -*/ -QAbstractSpinBoxPrivate::~QAbstractSpinBoxPrivate() -{ -} - -/*! - \internal - Updates the old and new hover control. Does nothing if the hover - control has not changed. -*/ -bool QAbstractSpinBoxPrivate::updateHoverControl(const QPoint &pos) -{ - Q_Q(QAbstractSpinBox); - QRect lastHoverRect = hoverRect; - QStyle::SubControl lastHoverControl = hoverControl; - bool doesHover = q->testAttribute(Qt::WA_Hover); - if (lastHoverControl != newHoverControl(pos) && doesHover) { - q->update(lastHoverRect); - q->update(hoverRect); - return true; - } - return !doesHover; -} - -/*! - \internal - Returns the hover control at \a pos. - This will update the hoverRect and hoverControl. -*/ -QStyle::SubControl QAbstractSpinBoxPrivate::newHoverControl(const QPoint &pos) -{ - Q_Q(QAbstractSpinBox); - - QStyleOptionSpinBox opt; - q->initStyleOption(&opt); - opt.subControls = QStyle::SC_All; - hoverControl = q->style()->hitTestComplexControl(QStyle::CC_SpinBox, &opt, pos, q); - hoverRect = q->style()->subControlRect(QStyle::CC_SpinBox, &opt, hoverControl, q); - return hoverControl; -} - -/*! - \internal - Strips any prefix/suffix from \a text. -*/ - -QString QAbstractSpinBoxPrivate::stripped(const QString &t, int *pos) const -{ - QString text = t; - if (specialValueText.size() == 0 || text != specialValueText) { - int from = 0; - int size = text.size(); - bool changed = false; - if (prefix.size() && text.startsWith(prefix)) { - from += prefix.size(); - size -= from; - changed = true; - } - if (suffix.size() && text.endsWith(suffix)) { - size -= suffix.size(); - changed = true; - } - if (changed) - text = text.mid(from, size); - } - - const int s = text.size(); - text = text.trimmed(); - if (pos) - (*pos) -= (s - text.size()); - return text; - -} - -void QAbstractSpinBoxPrivate::updateEditFieldGeometry() -{ - Q_Q(QAbstractSpinBox); - QStyleOptionSpinBox opt; - q->initStyleOption(&opt); - opt.subControls = QStyle::SC_SpinBoxEditField; - edit->setGeometry(q->style()->subControlRect(QStyle::CC_SpinBox, &opt, - QStyle::SC_SpinBoxEditField, q)); -} -/*! - \internal - Returns true if a specialValueText has been set and the current value is minimum. -*/ - -bool QAbstractSpinBoxPrivate::specialValue() const -{ - return (value == minimum && !specialValueText.isEmpty()); -} - -/*! - \internal Virtual function that emits signals when the value - changes. Reimplemented in the different subclasses. -*/ - -void QAbstractSpinBoxPrivate::emitSignals(EmitPolicy, const QVariant &) -{ -} - -/*! - \internal - - Slot connected to the line edit's textChanged(const QString &) - signal. -*/ - -void QAbstractSpinBoxPrivate::_q_editorTextChanged(const QString &t) -{ - Q_Q(QAbstractSpinBox); - - if (keyboardTracking) { - QString tmp = t; - int pos = edit->cursorPosition(); - QValidator::State state = q->validate(tmp, pos); - if (state == QValidator::Acceptable) { - const QVariant v = valueFromText(tmp); - setValue(v, EmitIfChanged, tmp != t); - pendingEmit = false; - } else { - pendingEmit = true; - } - } else { - pendingEmit = true; - } -} - -/*! - \internal - - Virtual slot connected to the line edit's - cursorPositionChanged(int, int) signal. Will move the cursor to a - valid position if the new one is invalid. E.g. inside the prefix. - Reimplemented in Q[Date|Time|DateTime]EditPrivate to account for - the different sections etc. -*/ - -void QAbstractSpinBoxPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos) -{ - if (!edit->hasSelectedText() && !ignoreCursorPositionChanged && !specialValue()) { - ignoreCursorPositionChanged = true; - - bool allowSelection = true; - int pos = -1; - if (newpos < prefix.size() && newpos != 0) { - if (oldpos == 0) { - allowSelection = false; - pos = prefix.size(); - } else { - pos = oldpos; - } - } else if (newpos > edit->text().size() - suffix.size() - && newpos != edit->text().size()) { - if (oldpos == edit->text().size()) { - pos = edit->text().size() - suffix.size(); - allowSelection = false; - } else { - pos = edit->text().size(); - } - } - if (pos != -1) { - const int selSize = edit->selectionStart() >= 0 && allowSelection - ? (edit->selectedText().size() - * (newpos < pos ? -1 : 1)) - newpos + pos - : 0; - - const bool wasBlocked = edit->blockSignals(true); - if (selSize != 0) { - edit->setSelection(pos - selSize, selSize); - } else { - edit->setCursorPosition(pos); - } - edit->blockSignals(wasBlocked); - } - ignoreCursorPositionChanged = false; - } -} - -/*! - \internal - - Initialises the QAbstractSpinBoxPrivate object. -*/ - -void QAbstractSpinBoxPrivate::init() -{ - Q_Q(QAbstractSpinBox); - - q->setLineEdit(new QLineEdit(q)); - edit->setObjectName(QLatin1String("qt_spinbox_lineedit")); - validator = new QSpinBoxValidator(q, this); - edit->setValidator(validator); - - QStyleOptionSpinBox opt; - q->initStyleOption(&opt); - spinClickTimerInterval = q->style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatRate, &opt, q); - spinClickThresholdTimerInterval = q->style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold, &opt, q); - q->setFocusPolicy(Qt::WheelFocus); - q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::SpinBox)); - q->setAttribute(Qt::WA_InputMethodEnabled); - - q->setAttribute(Qt::WA_MacShowFocusRect); -} - -/*! - \internal - - Resets the state of the spinbox. E.g. the state is set to - (Keyboard|Up) if Key up is currently pressed. -*/ - -void QAbstractSpinBoxPrivate::reset() -{ - Q_Q(QAbstractSpinBox); - - buttonState = None; - if (q) { - if (spinClickTimerId != -1) - q->killTimer(spinClickTimerId); - if (spinClickThresholdTimerId != -1) - q->killTimer(spinClickThresholdTimerId); - spinClickTimerId = spinClickThresholdTimerId = -1; - acceleration = 0; - q->update(); - } -} - -/*! - \internal - - Updates the state of the spinbox. -*/ - -void QAbstractSpinBoxPrivate::updateState(bool up, bool fromKeyboard /* = false */) -{ - Q_Q(QAbstractSpinBox); - if ((up && (buttonState & Up)) || (!up && (buttonState & Down))) - return; - reset(); - if (q && (q->stepEnabled() & (up ? QAbstractSpinBox::StepUpEnabled - : QAbstractSpinBox::StepDownEnabled))) { - spinClickThresholdTimerId = q->startTimer(spinClickThresholdTimerInterval); - buttonState = (up ? Up : Down) | (fromKeyboard ? Keyboard : Mouse); - q->stepBy(up ? 1 : -1); -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged); -#endif - } -} - - -/*! - 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 | QStyle::SC_SpinBoxEditField; - 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; - cleared = 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() || cleared) - 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) -{ - Q_Q(QAbstractSpinBox); - - clearCache(); - minimum = min; - maximum = (variantCompare(min, max) < 0 ? max : min); - cachedSizeHint = QSize(); // minimumSizeHint doesn't care about min/max - - reset(); - if (!(bound(value) == value)) { - setValue(bound(value), EmitIfChanged); - } else if (value == minimum && !specialValueText.isEmpty()) { - updateEdit(); - } - - q->updateGeometry(); -} - -/*! - \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; - 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 || cleared) - 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); - pos += dptr->prefix.length(); - } - - 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; - } -} - - -QT_END_NAMESPACE - -#include "moc_qabstractspinbox.cpp" - -#endif // QT_NO_SPINBOX |