src/qt3support/widgets/q3spinwidget.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3Support module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "q3rangecontrol.h"
       
    43 
       
    44 #ifndef QT_NO_SPINWIDGET
       
    45 
       
    46 #include "qabstractspinbox.h"
       
    47 #include "qevent.h"
       
    48 #include "qpainter.h"
       
    49 #include "qrect.h"
       
    50 #include "qstyle.h"
       
    51 #include "qstyleoption.h"
       
    52 #include "qtimer.h"
       
    53 
       
    54 QT_BEGIN_NAMESPACE
       
    55 
       
    56 class Q3SpinWidgetPrivate
       
    57 {
       
    58 public:
       
    59     Q3SpinWidgetPrivate()
       
    60         : upEnabled(true),
       
    61           downEnabled(true),
       
    62           theButton(0),
       
    63           buttonDown(0),
       
    64           timerUp(0),
       
    65           bsyms(Q3SpinWidget::UpDownArrows),
       
    66           ed (0) {}
       
    67     uint upEnabled :1;
       
    68     uint downEnabled :1;
       
    69     uint theButton :2;
       
    70     uint buttonDown :2;
       
    71     uint timerUp : 1;
       
    72     QRect up;
       
    73     QRect down;
       
    74     QTimer auRepTimer;
       
    75     Q3SpinWidget::ButtonSymbols bsyms;
       
    76     QWidget *ed;
       
    77     void startTimer(int msec) { auRepTimer.start(msec, true); }
       
    78     void startTimer(bool up, int msec) { timerUp = up; startTimer(msec); }
       
    79     void stopTimer() { auRepTimer.stop(); }
       
    80 };
       
    81 
       
    82 /*!
       
    83     \class Q3SpinWidget
       
    84     \brief The Q3SpinWidget class is an internal range control related class.
       
    85 
       
    86     \internal
       
    87 
       
    88     Constructs an empty range control widget with parent \a parent
       
    89     called \a name.
       
    90 
       
    91 */
       
    92 
       
    93 Q3SpinWidget::Q3SpinWidget(QWidget* parent, const char* name)
       
    94     : QWidget(parent, name)
       
    95 {
       
    96     d = new Q3SpinWidgetPrivate();
       
    97     connect(&d->auRepTimer, SIGNAL(timeout()), this, SLOT(timerDone()));
       
    98     setFocusPolicy(Qt::StrongFocus);
       
    99 
       
   100     arrange();
       
   101     updateDisplay();
       
   102 }
       
   103 
       
   104 
       
   105 /*! Destroys the object and frees any allocated resources.
       
   106 
       
   107 */
       
   108 
       
   109 Q3SpinWidget::~Q3SpinWidget()
       
   110 {
       
   111     delete d;
       
   112 }
       
   113 
       
   114 /*! */
       
   115 QWidget * Q3SpinWidget::editWidget()
       
   116 {
       
   117     return d->ed;
       
   118 }
       
   119 
       
   120 /*!
       
   121     Sets the editing widget to \a w.
       
   122 */
       
   123 void Q3SpinWidget::setEditWidget(QWidget * w)
       
   124 {
       
   125     if (w) {
       
   126         if (w->parentWidget() != this)
       
   127             w->setParent(this);
       
   128         setFocusProxy(w);
       
   129     }
       
   130     d->ed = w;
       
   131     arrange();
       
   132     updateDisplay();
       
   133 }
       
   134 
       
   135 /*! \reimp
       
   136 
       
   137 */
       
   138 
       
   139 void Q3SpinWidget::mousePressEvent(QMouseEvent *e)
       
   140 {
       
   141     if (e->button() != Qt::LeftButton) {
       
   142         d->stopTimer();
       
   143         d->buttonDown = 0;
       
   144         d->theButton = 0;
       
   145         repaint(d->down.united(d->up));
       
   146         return;
       
   147     }
       
   148 
       
   149     uint oldButtonDown = d->buttonDown;
       
   150 
       
   151     if (d->down.contains(e->pos()) && d->downEnabled)
       
   152         d->buttonDown = 1;
       
   153     else if (d->up.contains(e->pos()) && d->upEnabled)
       
   154         d->buttonDown = 2;
       
   155     else
       
   156         d->buttonDown = 0;
       
   157 
       
   158     d->theButton = d->buttonDown;
       
   159     if (oldButtonDown != d->buttonDown) {
       
   160         if (!d->buttonDown) {
       
   161             repaint(d->down.united(d->up));
       
   162         } else if (d->buttonDown & 1) {
       
   163             repaint(d->down);
       
   164             stepDown();
       
   165             d->startTimer(false, 300);
       
   166         } else if (d->buttonDown & 2) {
       
   167             repaint(d->up);
       
   168             stepUp();
       
   169             d->startTimer(true, 300);
       
   170         }
       
   171     }
       
   172 
       
   173     if (!oldButtonDown && !d->buttonDown)
       
   174         e->ignore();
       
   175 
       
   176 }
       
   177 
       
   178 static QStyleOptionSpinBox getStyleOption(const Q3SpinWidget *spin)
       
   179 {
       
   180     QStyleOptionSpinBox opt;
       
   181     opt.init(spin);
       
   182     opt.frame = true;
       
   183     opt.subControls = 0;
       
   184     opt.buttonSymbols = (QAbstractSpinBox::ButtonSymbols)spin->buttonSymbols();
       
   185     opt.stepEnabled = 0;
       
   186     if (spin->isUpEnabled())
       
   187         opt.stepEnabled |= QAbstractSpinBox::StepUpEnabled;
       
   188     if (spin->isDownEnabled())
       
   189         opt.stepEnabled |= QAbstractSpinBox::StepDownEnabled;
       
   190     opt.activeSubControls = 0;
       
   191     return opt;
       
   192 }
       
   193 
       
   194 /*!
       
   195 
       
   196 */
       
   197 
       
   198 void Q3SpinWidget::arrange()
       
   199 {
       
   200     QStyleOptionSpinBox opt = getStyleOption(this);
       
   201     d->up = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxUp, this);
       
   202     d->down = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxDown, this);
       
   203     if (d->ed) {
       
   204         QRect r = style()->subControlRect(QStyle::CC_SpinBox, &opt,
       
   205                                           QStyle::SC_SpinBoxEditField, this);
       
   206         d->ed->setGeometry(r);
       
   207     }
       
   208 }
       
   209 
       
   210 /*!
       
   211 
       
   212 */
       
   213 
       
   214 void Q3SpinWidget::stepUp()
       
   215 {
       
   216     emit stepUpPressed();
       
   217 }
       
   218 
       
   219 void Q3SpinWidget::resizeEvent(QResizeEvent*)
       
   220 {
       
   221     arrange();
       
   222 }
       
   223 
       
   224 /*!
       
   225 
       
   226 */
       
   227 
       
   228 void Q3SpinWidget::stepDown()
       
   229 {
       
   230     emit stepDownPressed();
       
   231 }
       
   232 
       
   233 
       
   234 void Q3SpinWidget::timerDone()
       
   235 {
       
   236     // we use a double timer to make it possible for users to do
       
   237     // something with 0-timer on valueChanged.
       
   238     QTimer::singleShot(1, this, SLOT(timerDoneEx()));
       
   239 }
       
   240 
       
   241 void Q3SpinWidget::timerDoneEx()
       
   242 {
       
   243     if (!d->buttonDown)
       
   244         return;
       
   245     if (d->timerUp)
       
   246         stepUp();
       
   247     else
       
   248         stepDown();
       
   249     d->startTimer(100);
       
   250 }
       
   251 
       
   252 
       
   253 /*!
       
   254     The event is passed in \a e.
       
   255 */
       
   256 
       
   257 void Q3SpinWidget::mouseReleaseEvent(QMouseEvent *e)
       
   258 {
       
   259     if (e->button() != Qt::LeftButton)
       
   260         return;
       
   261 
       
   262     uint oldButtonDown = d->theButton;
       
   263     d->theButton = 0;
       
   264     if (oldButtonDown != d->theButton) {
       
   265         if (oldButtonDown & 1)
       
   266             repaint(d->down);
       
   267         else if (oldButtonDown & 2)
       
   268             repaint(d->up);
       
   269     }
       
   270     d->stopTimer();
       
   271     d->buttonDown = 0;
       
   272 
       
   273     if (!oldButtonDown && !d->buttonDown)
       
   274         e->ignore();
       
   275 }
       
   276 
       
   277 
       
   278 /*!
       
   279     The event is passed in \a e.
       
   280 */
       
   281 
       
   282 void Q3SpinWidget::mouseMoveEvent(QMouseEvent *e)
       
   283 {
       
   284     if (!(e->state() & Qt::LeftButton))
       
   285         return;
       
   286 
       
   287     uint oldButtonDown = d->theButton;
       
   288     if (oldButtonDown & 1 && !d->down.contains(e->pos())) {
       
   289         d->stopTimer();
       
   290         d->theButton = 0;
       
   291         repaint(d->down);
       
   292     } else if (oldButtonDown & 2 && !d->up.contains(e->pos())) {
       
   293         d->stopTimer();
       
   294         d->theButton = 0;
       
   295         repaint(d->up);
       
   296     } else if (!oldButtonDown && d->up.contains(e->pos()) && d->buttonDown & 2) {
       
   297         d->startTimer(500);
       
   298         d->theButton = 2;
       
   299         repaint(d->up);
       
   300     } else if (!oldButtonDown && d->down.contains(e->pos()) && d->buttonDown & 1) {
       
   301         d->startTimer(500);
       
   302         d->theButton = 1;
       
   303         repaint(d->down);
       
   304     }
       
   305 
       
   306     if (!oldButtonDown && !d->buttonDown)
       
   307         e->ignore();
       
   308 }
       
   309 
       
   310 
       
   311 /*!
       
   312     The event is passed in \a e.
       
   313 */
       
   314 #ifndef QT_NO_WHEELEVENT
       
   315 void Q3SpinWidget::wheelEvent(QWheelEvent *e)
       
   316 {
       
   317     e->accept();
       
   318     static float offset = 0;
       
   319     static Q3SpinWidget* offset_owner = 0;
       
   320     if (offset_owner != this) {
       
   321         offset_owner = this;
       
   322         offset = 0;
       
   323     }
       
   324     offset += -e->delta()/120;
       
   325     if (QABS(offset) < 1)
       
   326         return;
       
   327     int ioff = int(offset);
       
   328     int i;
       
   329     for(i=0; i < QABS(ioff); i++)
       
   330         offset > 0 ? stepDown() : stepUp();
       
   331     offset -= ioff;
       
   332 }
       
   333 #endif
       
   334 
       
   335 /*!
       
   336 
       
   337 */
       
   338 void Q3SpinWidget::paintEvent(QPaintEvent *)
       
   339 {
       
   340     QPainter p(this);
       
   341     QStyleOptionSpinBox opt = getStyleOption(this);
       
   342 
       
   343     if (d->theButton & 1)
       
   344         opt.activeSubControls = QStyle::SC_SpinBoxDown;
       
   345     else if (d->theButton & 2)
       
   346         opt.activeSubControls = QStyle::SC_SpinBoxUp;
       
   347     else
       
   348         opt.activeSubControls = QStyle::SC_None;
       
   349     opt.rect = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxFrame, this);
       
   350     opt.subControls = QStyle::SC_All;
       
   351     style()->drawComplexControl(QStyle::CC_SpinBox, &opt, &p, this);
       
   352 }
       
   353 
       
   354 
       
   355 // ### What does the QEvent passed in contain? It used to be the previous style.
       
   356 /*!
       
   357     The previous style is passed in \a ev.
       
   358 */
       
   359 void Q3SpinWidget::changeEvent(QEvent *ev)
       
   360 {
       
   361     if(ev->type() == QEvent::StyleChange) {
       
   362         arrange();
       
   363     } else if(ev->type() == QEvent::ActivationChange) {
       
   364         if (!isActiveWindow() && d->buttonDown) {         //was active, but lost focus
       
   365             d->stopTimer();
       
   366             d->buttonDown = 0;
       
   367             d->theButton = 0;
       
   368         }
       
   369     } else if(ev->type() == QEvent::EnabledChange) {
       
   370         d->upEnabled = isEnabled();
       
   371         d->downEnabled = isEnabled();
       
   372         updateDisplay();
       
   373     }
       
   374     QWidget::changeEvent(ev);
       
   375 }
       
   376 
       
   377 /*!
       
   378 */
       
   379 
       
   380 QRect Q3SpinWidget::upRect() const
       
   381 {
       
   382     return d->up;
       
   383 }
       
   384 
       
   385 /*!
       
   386 */
       
   387 
       
   388 QRect Q3SpinWidget::downRect() const
       
   389 {
       
   390     return d->down;
       
   391 }
       
   392 
       
   393 /*!
       
   394 */
       
   395 
       
   396 void Q3SpinWidget::updateDisplay()
       
   397 {
       
   398     if (!isEnabled()) {
       
   399         d->upEnabled = false;
       
   400         d->downEnabled = false;
       
   401     }
       
   402     if (d->theButton & 1 && (d->downEnabled) == 0) {
       
   403         d->theButton &= ~1;
       
   404         d->buttonDown &= ~1;
       
   405     }
       
   406 
       
   407     if (d->theButton & 2 && (d->upEnabled) == 0) {
       
   408         d->theButton &= ~2;
       
   409         d->buttonDown &= ~2;
       
   410     }
       
   411     repaint();
       
   412 }
       
   413 
       
   414 /*!
       
   415     Sets up-enabled to \a on.
       
   416 */
       
   417 
       
   418 void Q3SpinWidget::setUpEnabled(bool on)
       
   419 {
       
   420     if ((bool)d->upEnabled != on) {
       
   421         d->upEnabled = on;
       
   422         updateDisplay();
       
   423     }
       
   424 }
       
   425 
       
   426 /*!
       
   427 */
       
   428 
       
   429 bool Q3SpinWidget::isUpEnabled() const
       
   430 {
       
   431     return d->upEnabled;
       
   432 }
       
   433 
       
   434 /*!
       
   435     Sets down-enabled to \a on.
       
   436 */
       
   437 
       
   438 void Q3SpinWidget::setDownEnabled(bool on)
       
   439 {
       
   440     if ((bool)d->downEnabled != on) {
       
   441         d->downEnabled = on;
       
   442         updateDisplay();
       
   443     }
       
   444 }
       
   445 
       
   446 /*!
       
   447 */
       
   448 
       
   449 bool Q3SpinWidget::isDownEnabled() const
       
   450 {
       
   451     return d->downEnabled;
       
   452 }
       
   453 
       
   454 /*!
       
   455     Sets the button symbol to \a bs.
       
   456 */
       
   457 
       
   458 void Q3SpinWidget::setButtonSymbols(ButtonSymbols bs)
       
   459 {
       
   460     d->bsyms = bs;
       
   461 }
       
   462 
       
   463 /*!
       
   464 */
       
   465 
       
   466 Q3SpinWidget::ButtonSymbols Q3SpinWidget::buttonSymbols() const
       
   467 {
       
   468     return d->bsyms;
       
   469 }
       
   470 
       
   471 QT_END_NAMESPACE
       
   472 
       
   473 #endif