/**************************************************************************** ** ** Implementation of QSpinWidget class ** ** 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 "qrangecontrol.h" #ifndef QT_NO_SPINWIDGET #include "qrect.h" #include "qtimer.h" #include "qstyle.h" #include "qpainter.h" class QSpinWidgetPrivate { public: QSpinWidgetPrivate() : upEnabled( TRUE ), downEnabled( TRUE ), theButton( 0 ), buttonDown( 0 ), timerUp( 0 ), bsyms( QSpinWidget::UpDownArrows ), ed ( 0 ) {} uint upEnabled :1; uint downEnabled :1; uint theButton :2; uint buttonDown :2; uint timerUp : 1; QRect up; QRect down; QTimer auRepTimer; QSpinWidget::ButtonSymbols bsyms; QWidget *ed; void startTimer( int msec ) { auRepTimer.start( msec, TRUE ); } void startTimer( bool up, int msec ) { timerUp = up; startTimer( msec ); } void stopTimer() { auRepTimer.stop(); } }; /*! \class QSpinWidget qspinwidget.h \brief The QSpinWidget class is an internal range control related class. \internal Constructs an empty range control widget with parent \a parent called \a name. */ QSpinWidget::QSpinWidget( QWidget* parent, const char* name ) : QWidget( parent, name ) { d = new QSpinWidgetPrivate(); connect( &d->auRepTimer, SIGNAL( timeout() ), this, SLOT( timerDone() ) ); setFocusPolicy( StrongFocus ); arrange(); updateDisplay(); } /*! Destroys the object and frees any allocated resources. */ QSpinWidget::~QSpinWidget() { delete d; } /*! */ QWidget * QSpinWidget::editWidget() { return d->ed; } /*! Sets the editing widget to \a w. */ void QSpinWidget::setEditWidget( QWidget * w ) { if ( w ) { if (w->parentWidget() != this) w->reparent( this, QPoint( 0, 0 ) ); setFocusProxy( w ); } d->ed = w; arrange(); updateDisplay(); } /*! \reimp */ void QSpinWidget::mousePressEvent( QMouseEvent *e ) { if ( e->button() != LeftButton ) { d->stopTimer(); d->buttonDown = 0; d->theButton = 0; repaint( d->down.unite( d->up ), FALSE ); return; } uint oldButtonDown = d->buttonDown; if ( d->down.contains( e->pos() ) && d->downEnabled ) d->buttonDown = 1; else if ( d->up.contains( e->pos() ) && d->upEnabled ) d->buttonDown = 2; else d->buttonDown = 0; d->theButton = d->buttonDown; if ( oldButtonDown != d->buttonDown ) { if ( !d->buttonDown ) { repaint( d->down.unite( d->up ), FALSE ); } else if ( d->buttonDown & 1 ) { repaint( d->down, FALSE ); stepDown(); d->startTimer( FALSE, 300 ); } else if ( d->buttonDown & 2 ) { repaint( d->up, FALSE ); stepUp(); d->startTimer( TRUE, 300 ); } } } /*! */ void QSpinWidget::arrange() { d->up = QStyle::visualRect( style().querySubControlMetrics( QStyle::CC_SpinWidget, this, QStyle::SC_SpinWidgetUp ), this ); d->down = QStyle::visualRect( style().querySubControlMetrics( QStyle::CC_SpinWidget, this, QStyle::SC_SpinWidgetDown ), this ); if ( d->ed ) { QRect r = QStyle::visualRect( style().querySubControlMetrics( QStyle::CC_SpinWidget, this, QStyle::SC_SpinWidgetEditField ), this ); d->ed->setGeometry( r ); } } /*! */ void QSpinWidget::stepUp() { emit stepUpPressed(); } void QSpinWidget::resizeEvent( QResizeEvent* ) { arrange(); } /*! */ void QSpinWidget::stepDown() { emit stepDownPressed(); } void QSpinWidget::timerDone() { // we use a double timer to make it possible for users to do // something with 0-timer on valueChanged. QTimer::singleShot( 1, this, SLOT( timerDoneEx() ) ); } void QSpinWidget::timerDoneEx() { if ( !d->buttonDown ) return; if ( d->timerUp ) stepUp(); else stepDown(); d->startTimer( 100 ); } void QSpinWidget::windowActivationChange( bool oldActive ) { //was active, but lost focus if ( oldActive && d->buttonDown ) { d->stopTimer(); d->buttonDown = 0; d->theButton = 0; } QWidget::windowActivationChange( oldActive ); } /*! The event is passed in \a e. */ void QSpinWidget::mouseReleaseEvent( QMouseEvent *e ) { if ( e->button() != LeftButton ) return; uint oldButtonDown = d->theButton; d->theButton = 0; if ( oldButtonDown != d->theButton ) { if ( oldButtonDown & 1 ) repaint( d->down, FALSE ); else if ( oldButtonDown & 2 ) repaint( d->up, FALSE ); } d->stopTimer(); d->buttonDown = 0; } /*! The event is passed in \a e. */ void QSpinWidget::mouseMoveEvent( QMouseEvent *e ) { if ( !(e->state() & LeftButton ) ) return; uint oldButtonDown = d->theButton; if ( oldButtonDown & 1 && !d->down.contains( e->pos() ) ) { d->stopTimer(); d->theButton = 0; repaint( d->down, FALSE ); } else if ( oldButtonDown & 2 && !d->up.contains( e->pos() ) ) { d->stopTimer(); d->theButton = 0; repaint( d->up, FALSE ); } else if ( !oldButtonDown && d->up.contains( e->pos() ) && d->buttonDown & 2 ) { d->startTimer( 500 ); d->theButton = 2; repaint( d->up, FALSE ); } else if ( !oldButtonDown && d->down.contains( e->pos() ) && d->buttonDown & 1 ) { d->startTimer( 500 ); d->theButton = 1; repaint( d->down, FALSE ); } } /*! The event is passed in \a e. */ #ifndef QT_NO_WHEELEVENT void QSpinWidget::wheelEvent( QWheelEvent *e ) { e->accept(); static float offset = 0; static QSpinWidget* 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 /*! */ void QSpinWidget::paintEvent( QPaintEvent * ) { QPainter p( this ); QStyle::SFlags flags = QStyle::Style_Default; if (isEnabled()) flags |= QStyle::Style_Enabled; if (hasMouse()) flags |= QStyle::Style_MouseOver; if (hasFocus() || (focusProxy() && focusProxy()->hasFocus())) flags |= QStyle::Style_HasFocus; QStyle::SCFlags active; if ( d->theButton & 1 ) active = QStyle::SC_SpinWidgetDown; else if ( d->theButton & 2 ) active = QStyle::SC_SpinWidgetUp; else active = QStyle::SC_None; QRect fr = QStyle::visualRect( style().querySubControlMetrics( QStyle::CC_SpinWidget, this, QStyle::SC_SpinWidgetFrame ), this ); style().drawComplexControl( QStyle::CC_SpinWidget, &p, this, fr, colorGroup(), flags, (uint)QStyle::SC_All, active ); } /*! The previous style is passed in \a old. */ void QSpinWidget::styleChange( QStyle& old ) { arrange(); QWidget::styleChange( old ); } /*! */ QRect QSpinWidget::upRect() const { return d->up; } /*! */ QRect QSpinWidget::downRect() const { return d->down; } /*! */ void QSpinWidget::updateDisplay() { if ( !isEnabled() ) { d->upEnabled = FALSE; d->downEnabled = FALSE; } if ( d->theButton & 1 && ( d->downEnabled ) == 0 ) { d->theButton &= ~1; d->buttonDown &= ~1; } if ( d->theButton & 2 && ( d->upEnabled ) == 0 ) { d->theButton &= ~2; d->buttonDown &= ~2; } repaint( FALSE ); } /*! The previous enabled state is passed in \a old. */ void QSpinWidget::enableChanged( bool ) { d->upEnabled = isEnabled(); d->downEnabled = isEnabled(); updateDisplay(); } /*! Sets up-enabled to \a on. */ void QSpinWidget::setUpEnabled( bool on ) { if ( (bool)d->upEnabled != on ) { d->upEnabled = on; updateDisplay(); } } /*! */ bool QSpinWidget::isUpEnabled() const { return d->upEnabled; } /*! Sets down-enabled to \a on. */ void QSpinWidget::setDownEnabled( bool on ) { if ( (bool)d->downEnabled != on ) { d->downEnabled = on; updateDisplay(); } } /*! */ bool QSpinWidget::isDownEnabled() const { return d->downEnabled; } /*! Sets the button symbol to \a bs. */ void QSpinWidget::setButtonSymbols( ButtonSymbols bs ) { d->bsyms = bs; } /*! */ QSpinWidget::ButtonSymbols QSpinWidget::buttonSymbols() const { return d->bsyms; } #endif