src/declarative/graphicsitems/qdeclarativemousearea.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 QtDeclarative 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 "private/qdeclarativemousearea_p.h"
       
    43 #include "private/qdeclarativemousearea_p_p.h"
       
    44 
       
    45 #include "private/qdeclarativeevents_p_p.h"
       
    46 
       
    47 #include <QGraphicsSceneMouseEvent>
       
    48 
       
    49 QT_BEGIN_NAMESPACE
       
    50 static const int PressAndHoldDelay = 800;
       
    51 
       
    52 QDeclarativeDrag::QDeclarativeDrag(QObject *parent)
       
    53 : QObject(parent), _target(0), _axis(XandYAxis), _xmin(0), _xmax(0), _ymin(0), _ymax(0),
       
    54 _active(false)
       
    55 {
       
    56 }
       
    57 
       
    58 QDeclarativeDrag::~QDeclarativeDrag()
       
    59 {
       
    60 }
       
    61 
       
    62 QGraphicsObject *QDeclarativeDrag::target() const
       
    63 {
       
    64     return _target;
       
    65 }
       
    66 
       
    67 void QDeclarativeDrag::setTarget(QGraphicsObject *t)
       
    68 {
       
    69     if (_target == t)
       
    70         return;
       
    71     _target = t;
       
    72     emit targetChanged();
       
    73 }
       
    74 
       
    75 void QDeclarativeDrag::resetTarget()
       
    76 {
       
    77     if (!_target)
       
    78         return;
       
    79     _target = 0;
       
    80     emit targetChanged();
       
    81 }
       
    82 
       
    83 QDeclarativeDrag::Axis QDeclarativeDrag::axis() const
       
    84 {
       
    85     return _axis;
       
    86 }
       
    87 
       
    88 void QDeclarativeDrag::setAxis(QDeclarativeDrag::Axis a)
       
    89 {
       
    90     if (_axis == a)
       
    91         return;
       
    92     _axis = a;
       
    93     emit axisChanged();
       
    94 }
       
    95 
       
    96 qreal QDeclarativeDrag::xmin() const
       
    97 {
       
    98     return _xmin;
       
    99 }
       
   100 
       
   101 void QDeclarativeDrag::setXmin(qreal m)
       
   102 {
       
   103     if (_xmin == m)
       
   104         return;
       
   105     _xmin = m;
       
   106     emit minimumXChanged();
       
   107 }
       
   108 
       
   109 qreal QDeclarativeDrag::xmax() const
       
   110 {
       
   111     return _xmax;
       
   112 }
       
   113 
       
   114 void QDeclarativeDrag::setXmax(qreal m)
       
   115 {
       
   116     if (_xmax == m)
       
   117         return;
       
   118     _xmax = m;
       
   119     emit maximumXChanged();
       
   120 }
       
   121 
       
   122 qreal QDeclarativeDrag::ymin() const
       
   123 {
       
   124     return _ymin;
       
   125 }
       
   126 
       
   127 void QDeclarativeDrag::setYmin(qreal m)
       
   128 {
       
   129     if (_ymin == m)
       
   130         return;
       
   131     _ymin = m;
       
   132     emit minimumYChanged();
       
   133 }
       
   134 
       
   135 qreal QDeclarativeDrag::ymax() const
       
   136 {
       
   137     return _ymax;
       
   138 }
       
   139 
       
   140 void QDeclarativeDrag::setYmax(qreal m)
       
   141 {
       
   142     if (_ymax == m)
       
   143         return;
       
   144     _ymax = m;
       
   145     emit maximumYChanged();
       
   146 }
       
   147 
       
   148 bool QDeclarativeDrag::active() const
       
   149 {
       
   150     return _active;
       
   151 }
       
   152 
       
   153 void QDeclarativeDrag::setActive(bool drag)
       
   154 {
       
   155     if (_active == drag)
       
   156         return;
       
   157     _active = drag;
       
   158     emit activeChanged();
       
   159 }
       
   160 
       
   161 QDeclarativeMouseAreaPrivate::~QDeclarativeMouseAreaPrivate()
       
   162 {
       
   163     delete drag;
       
   164 }
       
   165 
       
   166 
       
   167 /*!
       
   168     \qmlclass MouseArea QDeclarativeMouseArea
       
   169     \since 4.7
       
   170     \brief The MouseArea item enables simple mouse handling.
       
   171     \inherits Item
       
   172 
       
   173     A MouseArea is typically used in conjunction with a visible item,
       
   174     where the MouseArea effectively 'proxies' mouse handling for that
       
   175     item. For example, we can put a MouseArea in a Rectangle that changes
       
   176     the Rectangle color to red when clicked:
       
   177     \snippet doc/src/snippets/declarative/mouseregion.qml 0
       
   178 
       
   179     Many MouseArea signals pass a \l {MouseEvent}{mouse} parameter that contains
       
   180     additional information about the mouse event, such as the position, button,
       
   181     and any key modifiers.
       
   182 
       
   183     Below we have the previous
       
   184     example extended so as to give a different color when you right click.
       
   185     \snippet doc/src/snippets/declarative/mouseregion.qml 1
       
   186 
       
   187     For basic key handling, see the \l {Keys}{Keys attached property}.
       
   188 
       
   189     MouseArea is an invisible item: it is never painted.
       
   190 
       
   191     \sa MouseEvent
       
   192 */
       
   193 
       
   194 /*!
       
   195     \qmlsignal MouseArea::onEntered()
       
   196 
       
   197     This handler is called when the mouse enters the mouse area.
       
   198 
       
   199     By default the onEntered handler is only called while a button is
       
   200     pressed. Setting hoverEnabled to true enables handling of
       
   201     onEntered when no mouse button is pressed.
       
   202 
       
   203     \sa hoverEnabled
       
   204 */
       
   205 
       
   206 /*!
       
   207     \qmlsignal MouseArea::onExited()
       
   208 
       
   209     This handler is called when the mouse exists the mouse area.
       
   210 
       
   211     By default the onExited handler is only called while a button is
       
   212     pressed. Setting hoverEnabled to true enables handling of
       
   213     onExited when no mouse button is pressed.
       
   214 
       
   215     \sa hoverEnabled
       
   216 */
       
   217 
       
   218 /*!
       
   219     \qmlsignal MouseArea::onPositionChanged(MouseEvent mouse)
       
   220 
       
   221     This handler is called when the mouse position changes.
       
   222 
       
   223     The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
       
   224     position, and any buttons currently pressed.
       
   225 
       
   226     The \e accepted property of the MouseEvent parameter is ignored in this handler.
       
   227 
       
   228     By default the onPositionChanged handler is only called while a button is
       
   229     pressed.  Setting hoverEnabled to true enables handling of
       
   230     onPositionChanged when no mouse button is pressed.
       
   231 */
       
   232 
       
   233 /*!
       
   234     \qmlsignal MouseArea::onClicked(mouse)
       
   235 
       
   236     This handler is called when there is a click. A click is defined as a press followed by a release,
       
   237     both inside the MouseArea (pressing, moving outside the MouseArea, and then moving back inside and
       
   238     releasing is also considered a click).
       
   239 
       
   240     The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
       
   241     position of the release of the click, and whether the click wasHeld.
       
   242 
       
   243     The \e accepted property of the MouseEvent parameter is ignored in this handler.
       
   244 */
       
   245 
       
   246 /*!
       
   247     \qmlsignal MouseArea::onPressed(mouse)
       
   248 
       
   249     This handler is called when there is a press.
       
   250     The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
       
   251     position and which button was pressed.
       
   252 
       
   253     The \e accepted property of the MouseEvent parameter determines whether this MouseArea
       
   254     will handle the press and all future mouse events until release.  The default is to accept
       
   255     the event and not allow other MouseArea beneath this one to handle the event.  If \e accepted
       
   256     is set to false, no further events will be sent to this MouseArea until the button is next
       
   257     pressed.
       
   258 */
       
   259 
       
   260 /*!
       
   261     \qmlsignal MouseArea::onReleased(mouse)
       
   262 
       
   263     This handler is called when there is a release.
       
   264     The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
       
   265     position of the release of the click, and whether the click wasHeld.
       
   266 
       
   267     The \e accepted property of the MouseEvent parameter is ignored in this handler.
       
   268 */
       
   269 
       
   270 /*!
       
   271     \qmlsignal MouseArea::onPressAndHold(mouse)
       
   272 
       
   273     This handler is called when there is a long press (currently 800ms).
       
   274     The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
       
   275     position of the press, and which button is pressed.
       
   276 
       
   277     The \e accepted property of the MouseEvent parameter is ignored in this handler.
       
   278 */
       
   279 
       
   280 /*!
       
   281     \qmlsignal MouseArea::onDoubleClicked(mouse)
       
   282 
       
   283     This handler is called when there is a double-click (a press followed by a release followed by a press).
       
   284     The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
       
   285     position of the release of the click, and whether the click wasHeld.
       
   286 
       
   287     The \e accepted property of the MouseEvent parameter is ignored in this handler.
       
   288 */
       
   289 
       
   290 /*!
       
   291     \qmlsignal MouseArea::onCanceled()
       
   292 
       
   293     This handler is called when the mouse events are canceled, either because the event was not accepted or
       
   294     another element stole the mouse event handling. This signal is for advanced users, it's useful in case there
       
   295     is more than one mouse areas handling input, or when there is a mouse area inside a flickable. In the latter
       
   296     case, if you do some logic on pressed and then start dragging, the flickable will steal the mouse handling
       
   297     from the mouse area. In these cases, to reset the logic when there is no mouse handling anymore, you should
       
   298     use onCanceled, in addition to onReleased.
       
   299 */
       
   300 
       
   301 /*!
       
   302     \internal
       
   303     \class QDeclarativeMouseArea
       
   304     \brief The QDeclarativeMouseArea class provides a simple mouse handling abstraction for use within Qml.
       
   305 
       
   306     All QDeclarativeItem derived classes can do mouse handling but the QDeclarativeMouseArea class exposes mouse
       
   307     handling data as properties and tracks flicking and dragging of the mouse.
       
   308 
       
   309     A QDeclarativeMouseArea object can be instantiated in Qml using the tag \l MouseArea.
       
   310  */
       
   311 QDeclarativeMouseArea::QDeclarativeMouseArea(QDeclarativeItem *parent)
       
   312   : QDeclarativeItem(*(new QDeclarativeMouseAreaPrivate), parent)
       
   313 {
       
   314     Q_D(QDeclarativeMouseArea);
       
   315     d->init();
       
   316 }
       
   317 
       
   318 QDeclarativeMouseArea::~QDeclarativeMouseArea()
       
   319 {
       
   320 }
       
   321 
       
   322 /*!
       
   323     \qmlproperty real MouseArea::mouseX
       
   324     \qmlproperty real MouseArea::mouseY
       
   325     These properties hold the coordinates of the mouse.
       
   326 
       
   327     If the hoverEnabled property is false then these properties will only be valid
       
   328     while a button is pressed, and will remain valid as long as the button is held
       
   329     even if the mouse is moved outside the area.
       
   330 
       
   331     If hoverEnabled is true then these properties will be valid:
       
   332     \list
       
   333         \i when no button is pressed, but the mouse is within the MouseArea (containsMouse is true).
       
   334         \i if a button is pressed and held, even if it has since moved out of the area.
       
   335     \endlist
       
   336 
       
   337     The coordinates are relative to the MouseArea.
       
   338 */
       
   339 qreal QDeclarativeMouseArea::mouseX() const
       
   340 {
       
   341     Q_D(const QDeclarativeMouseArea);
       
   342     return d->lastPos.x();
       
   343 }
       
   344 
       
   345 qreal QDeclarativeMouseArea::mouseY() const
       
   346 {
       
   347     Q_D(const QDeclarativeMouseArea);
       
   348     return d->lastPos.y();
       
   349 }
       
   350 
       
   351 /*!
       
   352     \qmlproperty bool MouseArea::enabled
       
   353     This property holds whether the item accepts mouse events.
       
   354 */
       
   355 bool QDeclarativeMouseArea::isEnabled() const
       
   356 {
       
   357     Q_D(const QDeclarativeMouseArea);
       
   358     return d->absorb;
       
   359 }
       
   360 
       
   361 void QDeclarativeMouseArea::setEnabled(bool a)
       
   362 {
       
   363     Q_D(QDeclarativeMouseArea);
       
   364     if (a != d->absorb) {
       
   365         d->absorb = a;
       
   366         emit enabledChanged();
       
   367     }
       
   368 }
       
   369 /*!
       
   370     \qmlproperty MouseButtons MouseArea::pressedButtons
       
   371     This property holds the mouse buttons currently pressed.
       
   372 
       
   373     It contains a bitwise combination of:
       
   374     \list
       
   375     \o Qt.LeftButton
       
   376     \o Qt.RightButton
       
   377     \o Qt.MiddleButton
       
   378     \endlist
       
   379 
       
   380     The code below displays "right" when the right mouse buttons is pressed:
       
   381     \code
       
   382     Text {
       
   383         text: mr.pressedButtons & Qt.RightButton ? "right" : ""
       
   384         horizontalAlignment: Text.AlignHCenter
       
   385         verticalAlignment: Text.AlignVCenter
       
   386         MouseArea {
       
   387             id: mr
       
   388             acceptedButtons: Qt.LeftButton | Qt.RightButton
       
   389             anchors.fill: parent
       
   390         }
       
   391     }
       
   392     \endcode
       
   393 
       
   394     \sa acceptedButtons
       
   395 */
       
   396 Qt::MouseButtons QDeclarativeMouseArea::pressedButtons() const
       
   397 {
       
   398     Q_D(const QDeclarativeMouseArea);
       
   399     return d->lastButtons;
       
   400 }
       
   401 
       
   402 void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
       
   403 {
       
   404     Q_D(QDeclarativeMouseArea);
       
   405     d->moved = false;
       
   406     if (!d->absorb)
       
   407         QDeclarativeItem::mousePressEvent(event);
       
   408     else {
       
   409         d->longPress = false;
       
   410         d->saveEvent(event);
       
   411         if (d->drag) {
       
   412             d->dragX = drag()->axis() & QDeclarativeDrag::XAxis;
       
   413             d->dragY = drag()->axis() & QDeclarativeDrag::YAxis;
       
   414         }
       
   415         if (d->drag)
       
   416             d->drag->setActive(false);
       
   417         setHovered(true);
       
   418         d->startScene = event->scenePos();
       
   419         // we should only start timer if pressAndHold is connected to.
       
   420         if (d->isConnected("pressAndHold(QDeclarativeMouseEvent*)"))
       
   421             d->pressAndHoldTimer.start(PressAndHoldDelay, this);
       
   422         setKeepMouseGrab(false);
       
   423         event->setAccepted(setPressed(true));
       
   424     }
       
   425 }
       
   426 
       
   427 void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
       
   428 {
       
   429     Q_D(QDeclarativeMouseArea);
       
   430     if (!d->absorb) {
       
   431         QDeclarativeItem::mouseMoveEvent(event);
       
   432         return;
       
   433     }
       
   434 
       
   435     d->saveEvent(event);
       
   436 
       
   437     // ### we should skip this if these signals aren't used
       
   438     // ### can GV handle this for us?
       
   439     bool contains = boundingRect().contains(d->lastPos);
       
   440     if (d->hovered && !contains)
       
   441         setHovered(false);
       
   442     else if (!d->hovered && contains)
       
   443         setHovered(true);
       
   444 
       
   445     if (d->drag && d->drag->target()) {
       
   446         if (!d->moved) {
       
   447             d->startX = drag()->target()->x();
       
   448             d->startY = drag()->target()->y();
       
   449         }
       
   450 
       
   451         QPointF startLocalPos;
       
   452         QPointF curLocalPos;
       
   453         if (drag()->target()->parent()) {
       
   454             startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
       
   455             curLocalPos = drag()->target()->parentItem()->mapFromScene(event->scenePos());
       
   456         } else {
       
   457             startLocalPos = d->startScene;
       
   458             curLocalPos = event->scenePos();
       
   459         }
       
   460 
       
   461         const int dragThreshold = QApplication::startDragDistance();
       
   462         qreal dx = qAbs(curLocalPos.x() - startLocalPos.x());
       
   463         qreal dy = qAbs(curLocalPos.y() - startLocalPos.y());
       
   464         if ((d->dragX && !(dx < dragThreshold)) || (d->dragY && !(dy < dragThreshold)))
       
   465             d->drag->setActive(true);
       
   466         if (!keepMouseGrab()) {
       
   467             if ((!d->dragY && dy < dragThreshold && d->dragX && dx > dragThreshold)
       
   468                 || (!d->dragX && dx < dragThreshold && d->dragY && dy > dragThreshold)
       
   469                 || (d->dragX && d->dragY)) {
       
   470                 setKeepMouseGrab(true);
       
   471             }
       
   472         }
       
   473 
       
   474         if (d->dragX && d->drag->active()) {
       
   475             qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX;
       
   476             if (x < drag()->xmin())
       
   477                 x = drag()->xmin();
       
   478             else if (x > drag()->xmax())
       
   479                 x = drag()->xmax();
       
   480             drag()->target()->setX(x);
       
   481         }
       
   482         if (d->dragY && d->drag->active()) {
       
   483             qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY;
       
   484             if (y < drag()->ymin())
       
   485                 y = drag()->ymin();
       
   486             else if (y > drag()->ymax())
       
   487                 y = drag()->ymax();
       
   488             drag()->target()->setY(y);
       
   489         }
       
   490         d->moved = true;
       
   491     }
       
   492     QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
       
   493     emit mousePositionChanged(&me);
       
   494     me.setX(d->lastPos.x());
       
   495     me.setY(d->lastPos.y());
       
   496     emit positionChanged(&me);
       
   497 }
       
   498 
       
   499 
       
   500 void QDeclarativeMouseArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   501 {
       
   502     Q_D(QDeclarativeMouseArea);
       
   503     if (!d->absorb) {
       
   504         QDeclarativeItem::mouseReleaseEvent(event);
       
   505     } else {
       
   506         d->saveEvent(event);
       
   507         setPressed(false);
       
   508         if (d->drag)
       
   509             d->drag->setActive(false);
       
   510         // If we don't accept hover, we need to reset containsMouse.
       
   511         if (!acceptHoverEvents())
       
   512             setHovered(false);
       
   513         setKeepMouseGrab(false);
       
   514     }
       
   515 }
       
   516 
       
   517 void QDeclarativeMouseArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
       
   518 {
       
   519     Q_D(QDeclarativeMouseArea);
       
   520     if (!d->absorb) {
       
   521         QDeclarativeItem::mouseDoubleClickEvent(event);
       
   522     } else {
       
   523         QDeclarativeItem::mouseDoubleClickEvent(event);
       
   524         if (event->isAccepted()) {
       
   525             // Only deliver the event if we have accepted the press.
       
   526             d->saveEvent(event);
       
   527             QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
       
   528             emit this->doubleClicked(&me);
       
   529         }
       
   530     }
       
   531 }
       
   532 
       
   533 void QDeclarativeMouseArea::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
       
   534 {
       
   535     Q_D(QDeclarativeMouseArea);
       
   536     if (!d->absorb)
       
   537         QDeclarativeItem::hoverEnterEvent(event);
       
   538     else
       
   539         setHovered(true);
       
   540 }
       
   541 
       
   542 void QDeclarativeMouseArea::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
       
   543 {
       
   544     Q_D(QDeclarativeMouseArea);
       
   545     if (!d->absorb) {
       
   546         QDeclarativeItem::hoverEnterEvent(event);
       
   547     } else {
       
   548         d->lastPos = event->pos();
       
   549         QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, d->lastButtons, d->lastModifiers, false, d->longPress);
       
   550         emit mousePositionChanged(&me);
       
   551         me.setX(d->lastPos.x());
       
   552         me.setY(d->lastPos.y());
       
   553         emit positionChanged(&me);
       
   554     }
       
   555 }
       
   556 
       
   557 void QDeclarativeMouseArea::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
       
   558 {
       
   559     Q_D(QDeclarativeMouseArea);
       
   560     if (!d->absorb)
       
   561         QDeclarativeItem::hoverLeaveEvent(event);
       
   562     else
       
   563         setHovered(false);
       
   564 }
       
   565 
       
   566 bool QDeclarativeMouseArea::sceneEvent(QEvent *event)
       
   567 {
       
   568     bool rv = QDeclarativeItem::sceneEvent(event);
       
   569     if (event->type() == QEvent::UngrabMouse) {
       
   570         Q_D(QDeclarativeMouseArea);
       
   571         if (d->pressed) {
       
   572             // if our mouse grab has been removed (probably by Flickable), fix our
       
   573             // state
       
   574             d->pressed = false;
       
   575             setKeepMouseGrab(false);
       
   576             emit canceled();
       
   577             emit pressedChanged();
       
   578             if (d->hovered) {
       
   579                 d->hovered = false;
       
   580                 emit hoveredChanged();
       
   581             }
       
   582         }
       
   583     }
       
   584     return rv;
       
   585 }
       
   586 
       
   587 void QDeclarativeMouseArea::timerEvent(QTimerEvent *event)
       
   588 {
       
   589     Q_D(QDeclarativeMouseArea);
       
   590     if (event->timerId() == d->pressAndHoldTimer.timerId()) {
       
   591         d->pressAndHoldTimer.stop();
       
   592         bool dragged = d->drag && d->drag->active();
       
   593         if (d->pressed && dragged == false && d->hovered == true) {
       
   594             d->longPress = true;
       
   595             QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
       
   596             emit pressAndHold(&me);
       
   597         }
       
   598     }
       
   599 }
       
   600 
       
   601 void QDeclarativeMouseArea::geometryChanged(const QRectF &newGeometry,
       
   602                                             const QRectF &oldGeometry)
       
   603 {
       
   604     Q_D(QDeclarativeMouseArea);
       
   605     QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
       
   606 
       
   607     if (d->lastScenePos.isNull)
       
   608         d->lastScenePos = mapToScene(d->lastPos);
       
   609     else if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y())
       
   610         d->lastPos = mapFromScene(d->lastScenePos);
       
   611 }
       
   612 
       
   613 /*! \internal */
       
   614 QVariant QDeclarativeMouseArea::itemChange(GraphicsItemChange change,
       
   615                                        const QVariant &value)
       
   616 {
       
   617     Q_D(QDeclarativeMouseArea);
       
   618     switch (change) {
       
   619     case ItemVisibleHasChanged:
       
   620         if (acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse()))
       
   621             setHovered(!d->hovered);
       
   622         break;
       
   623     default:
       
   624         break;
       
   625     }
       
   626 
       
   627     return QDeclarativeItem::itemChange(change, value);
       
   628 }
       
   629 
       
   630 /*!
       
   631     \qmlproperty bool MouseArea::hoverEnabled
       
   632     This property holds whether hover events are handled.
       
   633 
       
   634     By default, mouse events are only handled in response to a button event, or when a button is
       
   635     pressed.  Hover enables handling of all mouse events even when no mouse button is
       
   636     pressed.
       
   637 
       
   638     This property affects the containsMouse property and the onEntered, onExited and onPositionChanged signals.
       
   639 */
       
   640 bool QDeclarativeMouseArea::hoverEnabled() const
       
   641 {
       
   642     return acceptHoverEvents();
       
   643 }
       
   644 
       
   645 void QDeclarativeMouseArea::setHoverEnabled(bool h)
       
   646 {
       
   647     Q_D(QDeclarativeMouseArea);
       
   648     if (h == acceptHoverEvents())
       
   649         return;
       
   650 
       
   651     setAcceptHoverEvents(h);
       
   652     emit hoverEnabledChanged();
       
   653     if (d->hovered != isUnderMouse())
       
   654         setHovered(!d->hovered);
       
   655 }
       
   656 
       
   657 /*!
       
   658     \qmlproperty bool MouseArea::containsMouse
       
   659     This property holds whether the mouse is currently inside the mouse area.
       
   660 
       
   661     \warning This property is not updated if the area moves under the mouse: \e containsMouse will not change.
       
   662     In addition, if hoverEnabled is false, containsMouse will only be valid when the mouse is pressed.
       
   663 */
       
   664 bool QDeclarativeMouseArea::hovered() const
       
   665 {
       
   666     Q_D(const QDeclarativeMouseArea);
       
   667     return d->hovered;
       
   668 }
       
   669 
       
   670 /*!
       
   671     \qmlproperty bool MouseArea::pressed
       
   672     This property holds whether the mouse area is currently pressed.
       
   673 */
       
   674 bool QDeclarativeMouseArea::pressed() const
       
   675 {
       
   676     Q_D(const QDeclarativeMouseArea);
       
   677     return d->pressed;
       
   678 }
       
   679 
       
   680 void QDeclarativeMouseArea::setHovered(bool h)
       
   681 {
       
   682     Q_D(QDeclarativeMouseArea);
       
   683     if (d->hovered != h) {
       
   684         d->hovered = h;
       
   685         emit hoveredChanged();
       
   686         d->hovered ? emit entered() : emit exited();
       
   687     }
       
   688 }
       
   689 
       
   690 /*!
       
   691     \qmlproperty Qt::MouseButtons MouseArea::acceptedButtons
       
   692     This property holds the mouse buttons that the mouse area reacts to.
       
   693 
       
   694     The available buttons are:
       
   695     \list
       
   696     \o Qt.LeftButton
       
   697     \o Qt.RightButton
       
   698     \o Qt.MiddleButton
       
   699     \endlist
       
   700 
       
   701     To accept more than one button the flags can be combined with the
       
   702     "|" (or) operator:
       
   703 
       
   704     \code
       
   705     MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton }
       
   706     \endcode
       
   707 
       
   708     The default is to accept the Left button.
       
   709 */
       
   710 Qt::MouseButtons QDeclarativeMouseArea::acceptedButtons() const
       
   711 {
       
   712     return acceptedMouseButtons();
       
   713 }
       
   714 
       
   715 void QDeclarativeMouseArea::setAcceptedButtons(Qt::MouseButtons buttons)
       
   716 {
       
   717     if (buttons != acceptedMouseButtons()) {
       
   718         setAcceptedMouseButtons(buttons);
       
   719         emit acceptedButtonsChanged();
       
   720     }
       
   721 }
       
   722 
       
   723 bool QDeclarativeMouseArea::setPressed(bool p)
       
   724 {
       
   725     Q_D(QDeclarativeMouseArea);
       
   726     bool dragged = d->drag && d->drag->active();
       
   727     bool isclick = d->pressed == true && p == false && dragged == false && d->hovered == true;
       
   728 
       
   729     if (d->pressed != p) {
       
   730         d->pressed = p;
       
   731         QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
       
   732         if (d->pressed) {
       
   733             emit pressed(&me);
       
   734             me.setX(d->lastPos.x());
       
   735             me.setY(d->lastPos.y());
       
   736             emit mousePositionChanged(&me);
       
   737         } else {
       
   738             emit released(&me);
       
   739             me.setX(d->lastPos.x());
       
   740             me.setY(d->lastPos.y());
       
   741             if (isclick && !d->longPress)
       
   742                 emit clicked(&me);
       
   743         }
       
   744 
       
   745         emit pressedChanged();
       
   746         return me.isAccepted();
       
   747     }
       
   748     return false;
       
   749 }
       
   750 
       
   751 QDeclarativeDrag *QDeclarativeMouseArea::drag()
       
   752 {
       
   753     Q_D(QDeclarativeMouseArea);
       
   754     if (!d->drag)
       
   755         d->drag = new QDeclarativeDrag;
       
   756     return d->drag;
       
   757 }
       
   758 
       
   759 /*!
       
   760     \qmlproperty Item MouseArea::drag.target
       
   761     \qmlproperty bool MouseArea::drag.active
       
   762     \qmlproperty enumeration MouseArea::drag.axis
       
   763     \qmlproperty real MouseArea::drag.minimumX
       
   764     \qmlproperty real MouseArea::drag.maximumX
       
   765     \qmlproperty real MouseArea::drag.minimumY
       
   766     \qmlproperty real MouseArea::drag.maximumY
       
   767 
       
   768     drag provides a convenient way to make an item draggable.
       
   769 
       
   770     \list
       
   771     \i \c target specifies the item to drag.
       
   772     \i \c active specifies if the target item is being currently dragged.
       
   773     \i \c axis specifies whether dragging can be done horizontally (Drag.XAxis), vertically (Drag.YAxis), or both (Drag.XandYAxis)
       
   774     \i the minimum and maximum properties limit how far the target can be dragged along the corresponding axes.
       
   775     \endlist
       
   776 
       
   777     The following example uses drag to reduce the opacity of an image as it moves to the right:
       
   778     \snippet doc/src/snippets/declarative/drag.qml 0
       
   779 */
       
   780 
       
   781 QT_END_NAMESPACE