diff options
Diffstat (limited to 'src/widgets/qspinbox.cpp')
-rw-r--r-- | src/widgets/qspinbox.cpp | 1116 |
1 files changed, 1116 insertions, 0 deletions
diff --git a/src/widgets/qspinbox.cpp b/src/widgets/qspinbox.cpp new file mode 100644 index 0000000..76b5906 --- /dev/null +++ b/src/widgets/qspinbox.cpp @@ -0,0 +1,1116 @@ +/**************************************************************************** +** +** Implementation of QSpinBox widget class +** +** Created : 970101 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.QPL +** included in the packaging of this file. Licensees holding valid Qt +** Commercial licenses may use this file in accordance with the Qt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qspinbox.h" +#ifndef QT_NO_SPINBOX + +#include "qcursor.h" +#include "qpushbutton.h" +#include "qpainter.h" +#include "qbitmap.h" +#include "qlineedit.h" +#include "qvalidator.h" +#include "qpixmapcache.h" +#include "qapplication.h" +#include "qstyle.h" +#if defined(QT_ACCESSIBILITY_SUPPORT) +#include "qaccessible.h" +#endif + +static bool sumOutOfRange(int current, int add) +{ + if (add > 0 && INT_MAX - add < current) { + return true; + } + if (add < 0 && INT_MIN - add > current) { + return true; + } + return false; +} + +class QSpinBoxPrivate +{ +public: + QSpinBoxPrivate() {} + QSpinWidget* controls; + uint selreq : 1; +}; + +class QSpinBoxValidator : public QIntValidator +{ +public: + QSpinBoxValidator( QSpinBox *sb, const char *name ) + : QIntValidator( sb, name ), spinBox( sb ) { } + + virtual State validate( QString& str, int& pos ) const; + +private: + QSpinBox *spinBox; +}; + +QValidator::State QSpinBoxValidator::validate( QString& str, int& pos ) const +{ + QString pref = spinBox->prefix(); + QString suff = spinBox->suffix(); + QString suffStriped = suff.stripWhiteSpace(); + uint overhead = pref.length() + suff.length(); + State state = Invalid; + + ((QIntValidator *) this)->setRange( spinBox->minValue(), + spinBox->maxValue() ); + if ( overhead == 0 ) { + state = QIntValidator::validate( str, pos ); + } else { + bool stripedVersion = FALSE; + if ( str.length() >= overhead && str.startsWith(pref) + && (str.endsWith(suff) + || (stripedVersion = str.endsWith(suffStriped))) ) { + if ( stripedVersion ) + overhead = pref.length() + suffStriped.length(); + QString core = str.mid( pref.length(), str.length() - overhead ); + int corePos = pos - pref.length(); + state = QIntValidator::validate( core, corePos ); + pos = corePos + pref.length(); + str.replace( pref.length(), str.length() - overhead, core ); + } else { + state = QIntValidator::validate( str, pos ); + if ( state == Invalid ) { + // stripWhiteSpace(), cf. QSpinBox::interpretText() + QString special = spinBox->specialValueText().stripWhiteSpace(); + QString candidate = str.stripWhiteSpace(); + + if ( special.startsWith(candidate) ) { + if ( candidate.length() == special.length() ) { + state = Acceptable; + } else { + state = Intermediate; + } + } + } + } + } + return state; +} + +/*! + \class QSpinBox + \brief The QSpinBox class provides a spin box widget (spin button). + + \ingroup basic + \mainclass + + QSpinBox allows the user to choose a value either by clicking the + up/down buttons to increase/decrease the value currently displayed + or by typing the value directly into the spin box. If the value is + entered directly into the spin box, Enter (or Return) must be + pressed to apply the new value. The value is usually an integer. + + Every time the value changes QSpinBox emits the valueChanged() + signal. The current value can be fetched with value() and set + with setValue(). + + The spin box keeps the value within a numeric range, and to + multiples of the lineStep() size (see QRangeControl for details). + Clicking the up/down buttons or using the keyboard accelerator's + up and down arrows will increase or decrease the current value in + steps of size lineStep(). The minimum and maximum value and the + step size can be set using one of the constructors, and can be + changed later with setMinValue(), setMaxValue() and setLineStep(). + + Most spin boxes are directional, but QSpinBox can also operate as + a circular spin box, i.e. if the range is 0-99 and the current + value is 99, clicking "up" will give 0. Use setWrapping() if you + want circular behavior. + + The displayed value can be prepended and appended with arbitrary + strings indicating, for example, currency or the unit of + measurement. See setPrefix() and setSuffix(). The text in the spin + box is retrieved with text() (which includes any prefix() and + suffix()), or with cleanText() (which has no prefix(), no suffix() + and no leading or trailing whitespace). currentValueText() returns + the spin box's current value as text. + + Normally the spin box displays up and down arrows in the buttons. + You can use setButtonSymbols() to change the display to show + <b>+</b> and <b>-</b> symbols if you prefer. In either case the up + and down arrow keys work as expected. + + It is often desirable to give the user a special (often default) + choice in addition to the range of numeric values. See + setSpecialValueText() for how to do this with QSpinBox. + + The default \l QWidget::focusPolicy() is StrongFocus. + + If using prefix(), suffix() and specialValueText() don't provide + enough control, you can ignore them and subclass QSpinBox instead. + + QSpinBox can easily be subclassed to allow the user to input + things other than an integer value as long as the allowed input + can be mapped to a range of integers. This can be done by + overriding the virtual functions mapValueToText() and + mapTextToValue(), and setting another suitable validator using + setValidator(). + + For example, these functions could be changed so that the user + provided values from 0.0 to 10.0, or -1 to signify 'Auto', while + the range of integers used inside the program would be -1 to 100: + + \code + class MySpinBox : public QSpinBox + { + Q_OBJECT + public: + ... + + QString mapValueToText( int value ) + { + if ( value == -1 ) // special case + return QString( "Auto" ); + + return QString( "%1.%2" ) // 0.0 to 10.0 + .arg( value / 10 ).arg( value % 10 ); + } + + int mapTextToValue( bool *ok ) + { + if ( text() == "Auto" ) // special case + return -1; + + return (int) ( 10 * text().toFloat() ); // 0 to 100 + } + }; + \endcode + + <img src=qspinbox-m.png> <img src=qspinbox-w.png> + + \sa QScrollBar QSlider + \link guibooks.html#fowler GUI Design Handbook: Spin Box \endlink +*/ + + +/*! + Constructs a spin box with the default QRangeControl range and + step values. It is called \a name and has parent \a parent. + + \sa minValue(), maxValue(), setRange(), lineStep(), setSteps() +*/ + +QSpinBox::QSpinBox( QWidget * parent , const char *name ) + : QWidget( parent, name, WNoAutoErase ), + QRangeControl() +{ + initSpinBox(); +} + + +/*! + Constructs a spin box that allows values from \a minValue to \a + maxValue inclusive, with step amount \a step. The value is + initially set to \a minValue. + + The spin box is called \a name and has parent \a parent. + + \sa minValue(), maxValue(), setRange(), lineStep(), setSteps() +*/ + +QSpinBox::QSpinBox( int minValue, int maxValue, int step, QWidget* parent, + const char* name ) + : QWidget( parent, name, WNoAutoErase ), + QRangeControl( minValue, maxValue, step, step, minValue ) +{ + initSpinBox(); +} + +/* + \internal Initialization. +*/ + +void QSpinBox::initSpinBox() +{ + d = new QSpinBoxPrivate; + + d->controls = new QSpinWidget( this, "controls" ); + connect( d->controls, SIGNAL( stepUpPressed() ), SLOT( stepUp() ) ); + connect( d->controls, SIGNAL( stepDownPressed() ), SLOT( stepDown() ) ); + + wrap = FALSE; + edited = FALSE; + d->selreq = FALSE; + + validate = new QSpinBoxValidator( this, "validator" ); + vi = new QLineEdit( this, "qt_spinbox_edit" ); + d->controls->setEditWidget( vi ); + vi->setValidator( validate ); + vi->installEventFilter( this ); + vi->setFrame( FALSE ); + setFocusProxy( vi ); + + setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) ); + setBackgroundMode( PaletteBackground, PaletteBase ); + + updateDisplay(); + + connect( vi, SIGNAL(textChanged(const QString&)), SLOT(textChanged()) ); +} + +/*! + Destroys the spin box, freeing all memory and other resources. +*/ + +QSpinBox::~QSpinBox() +{ + delete d; +} + + +/*! + \property QSpinBox::text + \brief the spin box's text, including any prefix() and suffix() + + There is no default text. + + \sa value() +*/ + +QString QSpinBox::text() const +{ + return vi->text(); +} + + + +/*! + \property QSpinBox::cleanText + \brief the spin box's text with no prefix(), suffix() or leading + or trailing whitespace. + + \sa text, prefix, suffix +*/ + +QString QSpinBox::cleanText() const +{ + QString s = QString(text()).stripWhiteSpace(); + if ( !prefix().isEmpty() ) { + QString px = QString(prefix()).stripWhiteSpace(); + int len = px.length(); + if ( len && s.left(len) == px ) // Remove _only_ if it is the prefix + s.remove( (uint)0, len ); + } + if ( !suffix().isEmpty() ) { + QString sx = QString(suffix()).stripWhiteSpace(); + int len = sx.length(); + if ( len && s.right(len) == sx ) // Remove _only_ if it is the suffix + s.truncate( s.length() - len ); + } + return s.stripWhiteSpace(); +} + + +/*! + \property QSpinBox::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 minVal(). Typical use + is to indicate that this choice has a special (default) meaning. + + For example, if your spin box allows the user to choose the margin + width in a print dialog and your application is able to + automatically choose a good margin width, you can set up the spin + box like this: + \code + QSpinBox marginBox( -1, 20, 1, parent, "marginBox" ); + marginBox->setSuffix( " mm" ); + marginBox->setSpecialValueText( "Auto" ); + \endcode + The user will then be able to choose a margin width from 0-20 + millimeters or select "Auto" to leave it to the application to + choose. Your code must then interpret the spin box value of -1 as + the user requesting automatic margin width. + + All values are displayed with the prefix() and suffix() (if set), + \e except for the special value, which only shows the special + value text. + + 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 + QString::null. +*/ + +void QSpinBox::setSpecialValueText( const QString &text ) +{ + specText = text; + updateDisplay(); +} + + +QString QSpinBox::specialValueText() const +{ + if ( specText.isEmpty() ) + return QString::null; + else + return specText; +} + + +/*! + \property QSpinBox::prefix + \brief the spin box's prefix + + The prefix is prepended to the start of the displayed value. + Typical use is to display a unit of measurement or a currency + symbol. For example: + + \code + sb->setPrefix( "$" ); + \endcode + + To turn off the prefix display, set this property to an empty + string. The default is no prefix. The prefix is not displayed for + the minValue() if specialValueText() is not empty. + + If no prefix is set, prefix() returns QString::null. + + \sa suffix() +*/ + +void QSpinBox::setPrefix( const QString &text ) +{ + pfix = text; + updateDisplay(); +} + + +QString QSpinBox::prefix() const +{ + if ( pfix.isEmpty() ) + return QString::null; + else + return pfix; +} + + +/*! + \property QSpinBox::suffix + \brief the suffix of the spin box + + The suffix is appended to the end of the displayed value. Typical + use is to display a unit of measurement or a currency symbol. For + example: + + \code + sb->setSuffix( " km" ); + \endcode + + To turn off the suffix display, set this property to an empty + string. The default is no suffix. The suffix is not displayed for + the minValue() if specialValueText() is not empty. + + If no suffix is set, suffix() returns a QString::null. + + \sa prefix() +*/ + +void QSpinBox::setSuffix( const QString &text ) +{ + sfix = text; + updateDisplay(); +} + +QString QSpinBox::suffix() const +{ + if ( sfix.isEmpty() ) + return QString::null; + else + return sfix; +} + + +/*! + \property QSpinBox::wrapping + \brief whether it is possible to step the value from the highest + value to the lowest value and vice versa + + By default, wrapping is turned off. + + If you have a range of 0..100 and wrapping is off when the user + reaches 100 and presses the Up Arrow nothing will happen; but if + wrapping is on the value will change from 100 to 0, then to 1, + etc. When wrapping is on, navigating past the highest value takes + you to the lowest and vice versa. + + \sa minValue, maxValue, setRange() +*/ + +void QSpinBox::setWrapping( bool on ) +{ + wrap = on; + updateDisplay(); +} + +bool QSpinBox::wrapping() const +{ + return wrap; +} + +/*! + \reimp +*/ +QSize QSpinBox::sizeHint() const +{ + constPolish(); + QSize sz = vi->sizeHint(); + int h = sz.height(); + QFontMetrics fm( font() ); + int w = 35; + int wx = fm.width( ' ' )*2; + QString s; + s = prefix() + ( (QSpinBox*)this )->mapValueToText( minValue() ) + suffix(); + w = QMAX( w, fm.width( s ) + wx); + s = prefix() + ( (QSpinBox*)this )->mapValueToText( maxValue() ) + suffix(); + w = QMAX(w, fm.width( s ) + wx ); + if ( !specialValueText().isEmpty() ) { + s = specialValueText(); + w = QMAX( w, fm.width( s ) + wx ); + } + return style().sizeFromContents(QStyle::CT_SpinBox, this, + QSize( w + d->controls->downRect().width(), + h + style().pixelMetric( QStyle::PM_DefaultFrameWidth ) * 2). + expandedTo( QApplication::globalStrut() )); +} + + +/*! + \reimp +*/ +QSize QSpinBox::minimumSizeHint() const +{ + int w = vi->minimumSizeHint().width() + d->controls->downRect().width(); + int h = QMAX( vi->minimumSizeHint().height(), d->controls->minimumSizeHint().height() ); + return QSize( w, h ); +} + +// Does the layout of the lineedit and the buttons + +void QSpinBox::arrangeWidgets() +{ + d->controls->arrange(); +} + +/*! + \property QSpinBox::value + \brief the value of the spin box + + \sa QRangeControl::setValue() +*/ + +void QSpinBox::setValue( int value ) +{ + edited = FALSE; // we ignore anything entered and not yet interpreted + QRangeControl::setValue( value ); + updateDisplay(); +} + +int QSpinBox::value() const +{ + QSpinBox * that = (QSpinBox *) this; + if ( edited ) { + that->edited = FALSE; // avoid recursion + that->interpretText(); + } + return QRangeControl::value(); +} + + +/*! + Increases the spin box's value by one lineStep(), wrapping as + necessary if wrapping() is TRUE. This is the same as clicking on + the pointing-up button and can be used for keyboard accelerators, + for example. + + \sa stepDown(), addLine(), lineStep(), setSteps(), setValue(), value() +*/ + +void QSpinBox::stepUp() +{ + if ( edited ) + interpretText(); + if ( wrapping() && ( value()+lineStep() > maxValue() || sumOutOfRange(value(), lineStep() ) ) ) { + setValue( minValue() ); + } else { + addLine(); + } +} + + +/*! + Decreases the spin box's value one lineStep(), wrapping as + necessary if wrapping() is TRUE. This is the same as clicking on + the pointing-down button and can be used for keyboard + accelerators, for example. + + \sa stepUp(), subtractLine(), lineStep(), setSteps(), setValue(), value() +*/ + +void QSpinBox::stepDown() +{ + if ( edited ) + interpretText(); + if ( wrapping() && ( value()-lineStep() < minValue() || sumOutOfRange(value(), -lineStep() ) ) ) { + setValue( maxValue() ); + } else { + subtractLine(); + } +} + + +/*! + \fn void QSpinBox::valueChanged( int value ) + + This signal is emitted every time the value of the spin box + changes; the new value is passed in \a value. This signal will be + emitted as a result of a call to setValue(), or because the user + changed the value by using a keyboard accelerator or mouse click, + etc. + + Note that the valueChanged() signal is emitted \e every time, not + just for the "last" step; i.e. if the user clicks "up" three + times, this signal is emitted three times. + + \sa value() +*/ + + +/*! + \fn void QSpinBox::valueChanged( const QString& valueText ) + + \overload + + This signal is emitted whenever the valueChanged( int ) signal is + emitted, i.e. every time the value of the spin box changes + (whatever the cause, e.g. by setValue(), by a keyboard + accelerator, by mouse clicks, etc.). + + The \a valueText parameter is the same string that is displayed in + the edit field of the spin box. + + \sa value() prefix() suffix() specialValueText() +*/ + + + +/*! + Intercepts and handles the events coming to the embedded QLineEdit + that have special meaning for the QSpinBox. The object is passed + as \a o and the event is passed as \a ev. +*/ + +bool QSpinBox::eventFilter( QObject* o, QEvent* ev ) +{ + if (o != vi) + return QWidget::eventFilter(o,ev); + + if ( ev->type() == QEvent::KeyPress ) { + QKeyEvent* k = (QKeyEvent*)ev; + + bool retval = FALSE; // workaround for MSVC++ optimization bug + if( (k->key() == Key_Tab) || (k->key() == Key_BackTab) ){ + if ( k->state() & Qt::ControlButton ) + return FALSE; + if ( edited ) + interpretText(); + qApp->sendEvent( this, ev ); + retval = TRUE; + } if ( k->key() == Key_Up ) { + stepUp(); + retval = TRUE; + } else if ( k->key() == Key_Down ) { + stepDown(); + retval = TRUE; + } else if ( k->key() == Key_Enter || k->key() == Key_Return ) { + interpretText(); + return FALSE; + } + if ( retval ) + return retval; + } else if ( ev->type() == QEvent::FocusOut || ev->type() == QEvent::Hide ) { + if ( edited ) { + interpretText(); + } + return FALSE; + } + return FALSE; +} + +/*! + \reimp + */ +void QSpinBox::setEnabled( bool enabled ) +{ + QWidget::setEnabled( enabled ); + updateDisplay(); +} + +/*! + \reimp +*/ +void QSpinBox::leaveEvent( QEvent* ) +{ +} + + +/*! + \reimp +*/ +void QSpinBox::resizeEvent( QResizeEvent* ) +{ + d->controls->resize( width(), height() ); +} + +/*! + \reimp +*/ +#ifndef QT_NO_WHEELEVENT +void QSpinBox::wheelEvent( QWheelEvent * e ) +{ + e->accept(); + static float offset = 0; + static QSpinBox* offset_owner = 0; + if (offset_owner != this) { + offset_owner = this; + offset = 0; + } + offset += -e->delta()/120; + if (QABS(offset) < 1) + return; + int ioff = int(offset); + int i; + for (i=0; i<QABS(ioff); i++) + offset > 0 ? stepDown() : stepUp(); + offset -= ioff; +} +#endif + +/*! + This virtual function is called by QRangeControl whenever the + value has changed. The QSpinBox reimplementation updates the + display and emits the valueChanged() signals; if you need + additional processing, either reimplement this or connect to one + of the valueChanged() signals. +*/ + +void QSpinBox::valueChange() +{ + d->selreq = hasFocus(); + updateDisplay(); + d->selreq = FALSE; + emit valueChanged( value() ); + emit valueChanged( currentValueText() ); +#if defined(QT_ACCESSIBILITY_SUPPORT) + QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged ); +#endif +} + + +/*! + This virtual function is called by QRangeControl whenever the + range has changed. It adjusts the default validator and updates + the display; if you need additional processing, you can + reimplement this function. +*/ + +void QSpinBox::rangeChange() +{ + updateDisplay(); +} + + +/*! + Sets the validator to \a v. The validator controls what keyboard + input is accepted when the user is editing in the value field. The + default is to use a suitable QIntValidator. + + Use setValidator(0) to turn off input validation (entered input + will still be kept within the spin box's range). +*/ + +void QSpinBox::setValidator( const QValidator* v ) +{ + if ( vi ) + vi->setValidator( v ); +} + + +/*! + Returns the validator that constrains editing for this spin box if + there is any; otherwise returns 0. + + \sa setValidator() QValidator +*/ + +const QValidator * QSpinBox::validator() const +{ + return vi ? vi->validator() : 0; +} + +/*! + Updates the contents of the embedded QLineEdit to reflect the + current value using mapValueToText(). Also enables/disables the + up/down push buttons accordingly. + + \sa mapValueToText() +*/ +void QSpinBox::updateDisplay() +{ + vi->setUpdatesEnabled( FALSE ); + vi->setText( currentValueText() ); + if ( d->selreq && isVisible() && ( hasFocus() || vi->hasFocus() ) ) { + selectAll(); + } else { + if ( !suffix().isEmpty() && vi->text().endsWith(suffix()) ) + vi->setCursorPosition( vi->text().length() - suffix().length() ); + } + vi->setUpdatesEnabled( TRUE ); + vi->repaint( FALSE ); // immediate repaint needed for some reason + edited = FALSE; + + bool upEnabled = isEnabled() && ( wrapping() || value() < maxValue() ); + bool downEnabled = isEnabled() && ( wrapping() || value() > minValue() ); + + d->controls->setUpEnabled( upEnabled ); + d->controls->setDownEnabled( downEnabled ); + vi->setEnabled( isEnabled() ); + repaint( FALSE ); +} + + +/*! + QSpinBox calls this after the user has manually edited the + contents of the spin box (i.e. by typing in the embedded + QLineEdit, rather than using the up/down buttons/keys). + + The default implementation of this function interprets the new + text using mapTextToValue(). If mapTextToValue() is successful, it + changes the spin box's value; if not, the value is left unchanged. + + \sa editor() +*/ + +void QSpinBox::interpretText() +{ + bool ok = TRUE; + bool done = FALSE; + int newVal = 0; + if ( !specialValueText().isEmpty() ) { + QString s = text().stripWhiteSpace(); + QString t = specialValueText().stripWhiteSpace(); + if ( s == t ) { + newVal = minValue(); + done = TRUE; + } + } + if ( !done ) + newVal = mapTextToValue( &ok ); + if ( ok ) + setValue( newVal ); + updateDisplay(); // sometimes redundant +} + + +/*! + Returns the geometry of the "up" button. +*/ + +QRect QSpinBox::upRect() const +{ + return d->controls->upRect(); +} + + +/*! + Returns the geometry of the "down" button. +*/ + +QRect QSpinBox::downRect() const +{ + return d->controls->downRect(); +} + + +/*! + Returns a pointer to the embedded QLineEdit. +*/ + +QLineEdit* QSpinBox::editor() const +{ + return vi; +} + + +/*! + This slot is called whenever the user edits the spin box's text. +*/ + +void QSpinBox::textChanged() +{ + edited = TRUE; // this flag is cleared in updateDisplay() +} + + +/*! + This virtual function is used by the spin box whenever it needs to + display value \a v. The default implementation returns a string + containing \a v printed in the standard way. Reimplementations may + return anything. (See the example in the detailed description.) + + Note that Qt does not call this function for specialValueText() + and that neither prefix() nor suffix() are included in the return + value. + + If you reimplement this, you may also need to reimplement + mapTextToValue(). + + \sa updateDisplay(), mapTextToValue() +*/ + +QString QSpinBox::mapValueToText( int v ) +{ + QString s; + s.setNum( v ); + return s; +} + + +/*! + This virtual function is used by the spin box whenever it needs to + interpret text entered by the user as a value. The text is + available as text() and as cleanText(), and this function must + parse it if possible. If \a ok is not 0: if it parses the text + successfully, \a *ok is set to TRUE; otherwise \a *ok is set to + FALSE. + + Subclasses that need to display spin box values in a non-numeric + way need to reimplement this function. + + Note that Qt handles specialValueText() separately; this function + is only concerned with the other values. + + The default implementation tries to interpret the text() as an + integer in the standard way and returns the integer value. + + \sa interpretText(), mapValueToText() +*/ + +int QSpinBox::mapTextToValue( bool* ok ) +{ + QString s = text(); + int newVal = s.toInt( ok ); + if ( !(*ok) && !( !prefix() && !suffix() ) ) {// Try removing any pre/suffix + s = cleanText(); + newVal = s.toInt( ok ); + } + return newVal; +} + + +/*! + Returns the full text calculated from the current value, including + any prefix and suffix. If there is special value text and the + value is minValue() the specialValueText() is returned. +*/ + +QString QSpinBox::currentValueText() +{ + QString s; + if ( (value() == minValue()) && !specialValueText().isEmpty() ) { + s = specialValueText(); + } else { + s = prefix(); + s.append( mapValueToText( value() ) ); + s.append( suffix() ); + } + return s; +} + +/*! + \reimp +*/ + +void QSpinBox::styleChange( QStyle& old ) +{ + arrangeWidgets(); + QWidget::styleChange( old ); +} + + +/*! + \enum QSpinBox::ButtonSymbols + + This enum type determines what the buttons in a spin box show. + + \value UpDownArrows the buttons show little arrows in the classic + style. + + \value PlusMinus the buttons show <b>+</b> and <b>-</b> symbols. + + \sa QSpinBox::buttonSymbols +*/ + +/*! + \property QSpinBox::buttonSymbols + + \brief the current button symbol mode + + The possible values can be either \c UpDownArrows or \c PlusMinus. + The default is \c UpDownArrows. + + \sa ButtonSymbols +*/ + +void QSpinBox::setButtonSymbols( ButtonSymbols newSymbols ) +{ + if ( buttonSymbols() == newSymbols ) + return; + + switch ( newSymbols ) { + case UpDownArrows: + d->controls->setButtonSymbols( QSpinWidget::UpDownArrows ); + break; + case PlusMinus: + d->controls->setButtonSymbols( QSpinWidget::PlusMinus ); + break; + } + // repaint( FALSE ); +} + +QSpinBox::ButtonSymbols QSpinBox::buttonSymbols() const +{ + switch( d->controls->buttonSymbols() ) { + case QSpinWidget::UpDownArrows: + return UpDownArrows; + case QSpinWidget::PlusMinus: + return PlusMinus; + } + return UpDownArrows; +} + +/*! + \property QSpinBox::minValue + + \brief the minimum value of the spin box + + When setting this property, \l QSpinBox::maxValue is adjusted, if + necessary, to ensure that the range remains valid. + + \sa setRange() setSpecialValueText() +*/ + +int QSpinBox::minValue() const +{ + return QRangeControl::minValue(); +} + +void QSpinBox::setMinValue( int minVal ) +{ + QRangeControl::setMinValue( minVal ); +} + +/*! + \property QSpinBox::maxValue + \brief the maximum value of the spin box + + When setting this property, \l QSpinBox::minValue is adjusted, if + necessary, to ensure that the range remains valid. + + \sa setRange() setSpecialValueText() +*/ + +int QSpinBox::maxValue() const +{ + return QRangeControl::maxValue(); +} + +void QSpinBox::setMaxValue( int maxVal ) +{ + QRangeControl::setMaxValue( maxVal ); +} + +/*! + \property QSpinBox::lineStep + \brief the line step + + When the user uses the arrows to change the spin box's value the + value will be incremented/decremented by the amount of the line + step. + + The setLineStep() function calls the virtual stepChange() function + if the new line step is different from the previous setting. + + \sa QRangeControl::setSteps() setRange() +*/ + +int QSpinBox::lineStep() const +{ + return QRangeControl::lineStep(); +} + +void QSpinBox::setLineStep( int i ) +{ + setSteps( i, pageStep() ); +} + +/*! + Selects all the text in the spin box's editor. +*/ + +void QSpinBox::selectAll() +{ + int overhead = prefix().length() + suffix().length(); + if ( !overhead || currentValueText() == specialValueText() ) { + vi->selectAll(); + } else { + vi->setSelection( prefix().length(), vi->text().length() - overhead ); + } +} + +#endif |