source: trunk/src/declarative/graphicsitems/qdeclarativemousearea.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 28.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
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#include <float.h>
50
51QT_BEGIN_NAMESPACE
52static const int PressAndHoldDelay = 800;
53
54QDeclarativeDrag::QDeclarativeDrag(QObject *parent)
55: QObject(parent), _target(0), _axis(XandYAxis), _xmin(-FLT_MAX), _xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX),
56_active(false), _filterChildren(false)
57{
58}
59
60QDeclarativeDrag::~QDeclarativeDrag()
61{
62}
63
64QGraphicsObject *QDeclarativeDrag::target() const
65{
66 return _target;
67}
68
69void QDeclarativeDrag::setTarget(QGraphicsObject *t)
70{
71 if (_target == t)
72 return;
73 _target = t;
74 emit targetChanged();
75}
76
77void QDeclarativeDrag::resetTarget()
78{
79 if (!_target)
80 return;
81 _target = 0;
82 emit targetChanged();
83}
84
85QDeclarativeDrag::Axis QDeclarativeDrag::axis() const
86{
87 return _axis;
88}
89
90void QDeclarativeDrag::setAxis(QDeclarativeDrag::Axis a)
91{
92 if (_axis == a)
93 return;
94 _axis = a;
95 emit axisChanged();
96}
97
98qreal QDeclarativeDrag::xmin() const
99{
100 return _xmin;
101}
102
103void QDeclarativeDrag::setXmin(qreal m)
104{
105 if (_xmin == m)
106 return;
107 _xmin = m;
108 emit minimumXChanged();
109}
110
111qreal QDeclarativeDrag::xmax() const
112{
113 return _xmax;
114}
115
116void QDeclarativeDrag::setXmax(qreal m)
117{
118 if (_xmax == m)
119 return;
120 _xmax = m;
121 emit maximumXChanged();
122}
123
124qreal QDeclarativeDrag::ymin() const
125{
126 return _ymin;
127}
128
129void QDeclarativeDrag::setYmin(qreal m)
130{
131 if (_ymin == m)
132 return;
133 _ymin = m;
134 emit minimumYChanged();
135}
136
137qreal QDeclarativeDrag::ymax() const
138{
139 return _ymax;
140}
141
142void QDeclarativeDrag::setYmax(qreal m)
143{
144 if (_ymax == m)
145 return;
146 _ymax = m;
147 emit maximumYChanged();
148}
149
150bool QDeclarativeDrag::active() const
151{
152 return _active;
153}
154
155void QDeclarativeDrag::setActive(bool drag)
156{
157 if (_active == drag)
158 return;
159 _active = drag;
160 emit activeChanged();
161}
162
163bool QDeclarativeDrag::filterChildren() const
164{
165 return _filterChildren;
166}
167
168void QDeclarativeDrag::setFilterChildren(bool filter)
169{
170 if (_filterChildren == filter)
171 return;
172 _filterChildren = filter;
173 emit filterChildrenChanged();
174}
175
176QDeclarativeMouseAreaPrivate::~QDeclarativeMouseAreaPrivate()
177{
178 delete drag;
179}
180
181/*!
182 \qmlclass MouseArea QDeclarativeMouseArea
183 \ingroup qml-basic-interaction-elements
184 \since 4.7
185 \brief The MouseArea item enables simple mouse handling.
186 \inherits Item
187
188 A MouseArea is an invisible item that is typically used in conjunction with
189 a visible item in order to provide mouse handling for that item.
190 By effectively acting as a proxy, the logic for mouse handling can be
191 contained within a MouseArea item.
192
193 For basic key handling, see the \l{Keys}{Keys attached property}.
194
195 The \l enabled property is used to enable and disable mouse handling for
196 the proxied item. When disabled, the mouse area becomes transparent to
197 mouse events.
198
199 The \l pressed read-only property indicates whether or not the user is
200 holding down a mouse button over the mouse area. This property is often
201 used in bindings between properties in a user interface. The containsMouse
202 read-only property indicates the presence of the mouse cursor over the
203 mouse area but, by default, only when a mouse button is held down; see below
204 for further details.
205
206 Information about the mouse position and button clicks are provided via
207 signals for which event handler properties are defined. The most commonly
208 used involved handling mouse presses and clicks: onClicked, onDoubleClicked,
209 onPressed, onReleased and onPressAndHold.
210
211 By default, MouseArea items only report mouse clicks and not changes to the
212 position of the mouse cursor. Setting the hoverEnabled property ensures that
213 handlers defined for onPositionChanged, onEntered and onExited are used and
214 that the containsMouse property is updated even when no mouse buttons are
215 pressed.
216
217 \section1 Example Usage
218
219 \beginfloatright
220 \inlineimage qml-mousearea-snippet.png
221 \endfloat
222
223 The following example uses a MouseArea in a \l Rectangle that changes
224 the \l Rectangle color to red when clicked:
225
226 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml import
227 \codeline
228 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro
229
230 \clearfloat
231 Many MouseArea signals pass a \l{MouseEvent}{mouse} parameter that contains
232 additional information about the mouse event, such as the position, button,
233 and any key modifiers.
234
235 Here is an extension of the previous example that produces a different
236 color when the area is right clicked:
237
238 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro-extended
239
240 \sa MouseEvent, {declarative/touchinteraction/mousearea}{MouseArea example}
241*/
242
243/*!
244 \qmlsignal MouseArea::onEntered()
245
246 This handler is called when the mouse enters the mouse area.
247
248 By default the onEntered handler is only called while a button is
249 pressed. Setting hoverEnabled to true enables handling of
250 onEntered when no mouse button is pressed.
251
252 \sa hoverEnabled
253*/
254
255/*!
256 \qmlsignal MouseArea::onExited()
257
258 This handler is called when the mouse exists the mouse area.
259
260 By default the onExited handler is only called while a button is
261 pressed. Setting hoverEnabled to true enables handling of
262 onExited when no mouse button is pressed.
263
264 \sa hoverEnabled
265*/
266
267/*!
268 \qmlsignal MouseArea::onPositionChanged(MouseEvent mouse)
269
270 This handler is called when the mouse position changes.
271
272 The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
273 position, and any buttons currently pressed.
274
275 The \e accepted property of the MouseEvent parameter is ignored in this handler.
276
277 By default the onPositionChanged handler is only called while a button is
278 pressed. Setting hoverEnabled to true enables handling of
279 onPositionChanged when no mouse button is pressed.
280*/
281
282/*!
283 \qmlsignal MouseArea::onClicked(MouseEvent mouse)
284
285 This handler is called when there is a click. A click is defined as a press followed by a release,
286 both inside the MouseArea (pressing, moving outside the MouseArea, and then moving back inside and
287 releasing is also considered a click).
288
289 The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
290 position of the release of the click, and whether the click was held.
291
292 The \e accepted property of the MouseEvent parameter is ignored in this handler.
293*/
294
295/*!
296 \qmlsignal MouseArea::onPressed(MouseEvent mouse)
297
298 This handler is called when there is a press.
299 The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
300 position and which button was pressed.
301
302 The \e accepted property of the MouseEvent parameter determines whether this MouseArea
303 will handle the press and all future mouse events until release. The default is to accept
304 the event and not allow other MouseArea beneath this one to handle the event. If \e accepted
305 is set to false, no further events will be sent to this MouseArea until the button is next
306 pressed.
307*/
308
309/*!
310 \qmlsignal MouseArea::onReleased(MouseEvent mouse)
311
312 This handler is called when there is a release.
313 The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
314 position of the release of the click, and whether the click was held.
315
316 The \e accepted property of the MouseEvent parameter is ignored in this handler.
317*/
318
319/*!
320 \qmlsignal MouseArea::onPressAndHold(MouseEvent mouse)
321
322 This handler is called when there is a long press (currently 800ms).
323 The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
324 position of the press, and which button is pressed.
325
326 The \e accepted property of the MouseEvent parameter is ignored in this handler.
327*/
328
329/*!
330 \qmlsignal MouseArea::onDoubleClicked(MouseEvent mouse)
331
332 This handler is called when there is a double-click (a press followed by a release followed by a press).
333 The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
334 position of the release of the click, and whether the click was held.
335
336 If the \e accepted property of the \l {MouseEvent}{mouse} parameter is set to false
337 in the handler, the onPressed/onReleased/onClicked handlers will be called for the second
338 click; otherwise they are suppressed. The accepted property defaults to true.
339*/
340
341/*!
342 \qmlsignal MouseArea::onCanceled()
343
344 This handler is called when mouse events have been canceled, either because an event was not accepted, or
345 because another element stole the mouse event handling.
346
347 This signal is for advanced use: it is useful when there is more than one MouseArea
348 that is handling input, or when there is a MouseArea inside a \l Flickable. In the latter
349 case, if you execute some logic on the pressed signal and then start dragging, the
350 \l Flickable will steal the mouse handling from the MouseArea. In these cases, to reset
351 the logic when the MouseArea has lost the mouse handling to the \l Flickable,
352 \c onCanceled should be used in addition to onReleased.
353*/
354
355QDeclarativeMouseArea::QDeclarativeMouseArea(QDeclarativeItem *parent)
356 : QDeclarativeItem(*(new QDeclarativeMouseAreaPrivate), parent)
357{
358 Q_D(QDeclarativeMouseArea);
359 d->init();
360}
361
362QDeclarativeMouseArea::~QDeclarativeMouseArea()
363{
364}
365
366/*!
367 \qmlproperty real MouseArea::mouseX
368 \qmlproperty real MouseArea::mouseY
369 These properties hold the coordinates of the mouse cursor.
370
371 If the hoverEnabled property is false then these properties will only be valid
372 while a button is pressed, and will remain valid as long as the button is held
373 down even if the mouse is moved outside the area.
374
375 By default, this property is false.
376
377 If hoverEnabled is true then these properties will be valid when:
378 \list
379 \i no button is pressed, but the mouse is within the MouseArea (containsMouse is true).
380 \i a button is pressed and held, even if it has since moved out of the area.
381 \endlist
382
383 The coordinates are relative to the MouseArea.
384*/
385qreal QDeclarativeMouseArea::mouseX() const
386{
387 Q_D(const QDeclarativeMouseArea);
388 return d->lastPos.x();
389}
390
391qreal QDeclarativeMouseArea::mouseY() const
392{
393 Q_D(const QDeclarativeMouseArea);
394 return d->lastPos.y();
395}
396
397/*!
398 \qmlproperty bool MouseArea::enabled
399 This property holds whether the item accepts mouse events.
400
401 By default, this property is true.
402*/
403bool QDeclarativeMouseArea::isEnabled() const
404{
405 Q_D(const QDeclarativeMouseArea);
406 return d->absorb;
407}
408
409void QDeclarativeMouseArea::setEnabled(bool a)
410{
411 Q_D(QDeclarativeMouseArea);
412 if (a != d->absorb) {
413 d->absorb = a;
414 emit enabledChanged();
415 }
416}
417/*!
418 \qmlproperty MouseButtons MouseArea::pressedButtons
419 This property holds the mouse buttons currently pressed.
420
421 It contains a bitwise combination of:
422 \list
423 \o Qt.LeftButton
424 \o Qt.RightButton
425 \o Qt.MiddleButton
426 \endlist
427
428 The code below displays "right" when the right mouse buttons is pressed:
429
430 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml mousebuttons
431
432 \sa acceptedButtons
433*/
434Qt::MouseButtons QDeclarativeMouseArea::pressedButtons() const
435{
436 Q_D(const QDeclarativeMouseArea);
437 return d->lastButtons;
438}
439
440void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
441{
442 Q_D(QDeclarativeMouseArea);
443 d->moved = false;
444 d->stealMouse = false;
445 if (!d->absorb)
446 QDeclarativeItem::mousePressEvent(event);
447 else {
448 d->longPress = false;
449 d->saveEvent(event);
450 if (d->drag) {
451 d->dragX = drag()->axis() & QDeclarativeDrag::XAxis;
452 d->dragY = drag()->axis() & QDeclarativeDrag::YAxis;
453 }
454 if (d->drag)
455 d->drag->setActive(false);
456 setHovered(true);
457 d->startScene = event->scenePos();
458 // we should only start timer if pressAndHold is connected to.
459 if (d->isPressAndHoldConnected())
460 d->pressAndHoldTimer.start(PressAndHoldDelay, this);
461 setKeepMouseGrab(false);
462 event->setAccepted(setPressed(true));
463 }
464}
465
466void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
467{
468 Q_D(QDeclarativeMouseArea);
469 if (!d->absorb) {
470 QDeclarativeItem::mouseMoveEvent(event);
471 return;
472 }
473
474 d->saveEvent(event);
475
476 // ### we should skip this if these signals aren't used
477 // ### can GV handle this for us?
478 bool contains = boundingRect().contains(d->lastPos);
479 if (d->hovered && !contains)
480 setHovered(false);
481 else if (!d->hovered && contains)
482 setHovered(true);
483
484 if (d->drag && d->drag->target()) {
485 if (!d->moved) {
486 d->startX = drag()->target()->x();
487 d->startY = drag()->target()->y();
488 }
489
490 QPointF startLocalPos;
491 QPointF curLocalPos;
492 if (drag()->target()->parentItem()) {
493 startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
494 curLocalPos = drag()->target()->parentItem()->mapFromScene(event->scenePos());
495 } else {
496 startLocalPos = d->startScene;
497 curLocalPos = event->scenePos();
498 }
499
500 const int dragThreshold = QApplication::startDragDistance();
501 qreal dx = qAbs(curLocalPos.x() - startLocalPos.x());
502 qreal dy = qAbs(curLocalPos.y() - startLocalPos.y());
503
504 if (keepMouseGrab() && d->stealMouse)
505 d->drag->setActive(true);
506
507 if (d->dragX && d->drag->active()) {
508 qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX;
509 if (x < drag()->xmin())
510 x = drag()->xmin();
511 else if (x > drag()->xmax())
512 x = drag()->xmax();
513 drag()->target()->setX(x);
514 }
515 if (d->dragY && d->drag->active()) {
516 qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY;
517 if (y < drag()->ymin())
518 y = drag()->ymin();
519 else if (y > drag()->ymax())
520 y = drag()->ymax();
521 drag()->target()->setY(y);
522 }
523
524 if (!keepMouseGrab()) {
525 if ((!d->dragY && dy < dragThreshold && d->dragX && dx > dragThreshold)
526 || (!d->dragX && dx < dragThreshold && d->dragY && dy > dragThreshold)
527 || (d->dragX && d->dragY && (dx > dragThreshold || dy > dragThreshold))) {
528 setKeepMouseGrab(true);
529 d->stealMouse = true;
530 }
531 }
532
533 d->moved = true;
534 }
535 QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
536 emit mousePositionChanged(&me);
537 me.setX(d->lastPos.x());
538 me.setY(d->lastPos.y());
539 emit positionChanged(&me);
540}
541
542
543void QDeclarativeMouseArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
544{
545 Q_D(QDeclarativeMouseArea);
546 d->stealMouse = false;
547 if (!d->absorb) {
548 QDeclarativeItem::mouseReleaseEvent(event);
549 } else {
550 d->saveEvent(event);
551 setPressed(false);
552 if (d->drag)
553 d->drag->setActive(false);
554 // If we don't accept hover, we need to reset containsMouse.
555 if (!acceptHoverEvents())
556 setHovered(false);
557 QGraphicsScene *s = scene();
558 if (s && s->mouseGrabberItem() == this)
559 ungrabMouse();
560 setKeepMouseGrab(false);
561 }
562 d->doubleClick = false;
563}
564
565void QDeclarativeMouseArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
566{
567 Q_D(QDeclarativeMouseArea);
568 if (!d->absorb) {
569 QDeclarativeItem::mouseDoubleClickEvent(event);
570 } else {
571 if (d->isDoubleClickConnected())
572 d->doubleClick = true;
573 d->saveEvent(event);
574 QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
575 me.setAccepted(d->isDoubleClickConnected());
576 emit this->doubleClicked(&me);
577 QDeclarativeItem::mouseDoubleClickEvent(event);
578 }
579}
580
581void QDeclarativeMouseArea::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
582{
583 Q_D(QDeclarativeMouseArea);
584 if (!d->absorb)
585 QDeclarativeItem::hoverEnterEvent(event);
586 else
587 setHovered(true);
588}
589
590void QDeclarativeMouseArea::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
591{
592 Q_D(QDeclarativeMouseArea);
593 if (!d->absorb) {
594 QDeclarativeItem::hoverEnterEvent(event);
595 } else {
596 d->lastPos = event->pos();
597 QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, d->lastButtons, d->lastModifiers, false, d->longPress);
598 emit mousePositionChanged(&me);
599 me.setX(d->lastPos.x());
600 me.setY(d->lastPos.y());
601 emit positionChanged(&me);
602 }
603}
604
605void QDeclarativeMouseArea::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
606{
607 Q_D(QDeclarativeMouseArea);
608 if (!d->absorb)
609 QDeclarativeItem::hoverLeaveEvent(event);
610 else
611 setHovered(false);
612}
613
614bool QDeclarativeMouseArea::sceneEvent(QEvent *event)
615{
616 bool rv = QDeclarativeItem::sceneEvent(event);
617 if (event->type() == QEvent::UngrabMouse) {
618 Q_D(QDeclarativeMouseArea);
619 if (d->pressed) {
620 // if our mouse grab has been removed (probably by Flickable), fix our
621 // state
622 d->pressed = false;
623 d->stealMouse = false;
624 setKeepMouseGrab(false);
625 emit canceled();
626 emit pressedChanged();
627 if (d->hovered) {
628 d->hovered = false;
629 emit hoveredChanged();
630 }
631 }
632 }
633 return rv;
634}
635
636bool QDeclarativeMouseArea::sendMouseEvent(QGraphicsSceneMouseEvent *event)
637{
638 Q_D(QDeclarativeMouseArea);
639 QGraphicsSceneMouseEvent mouseEvent(event->type());
640 QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
641
642 QGraphicsScene *s = scene();
643 QDeclarativeItem *grabber = s ? qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()) : 0;
644 bool stealThisEvent = d->stealMouse;
645 if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
646 mouseEvent.setAccepted(false);
647 for (int i = 0x1; i <= 0x10; i <<= 1) {
648 if (event->buttons() & i) {
649 Qt::MouseButton button = Qt::MouseButton(i);
650 mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
651 }
652 }
653 mouseEvent.setScenePos(event->scenePos());
654 mouseEvent.setLastScenePos(event->lastScenePos());
655 mouseEvent.setPos(mapFromScene(event->scenePos()));
656 mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
657
658 switch(mouseEvent.type()) {
659 case QEvent::GraphicsSceneMouseMove:
660 mouseMoveEvent(&mouseEvent);
661 break;
662 case QEvent::GraphicsSceneMousePress:
663 mousePressEvent(&mouseEvent);
664 break;
665 case QEvent::GraphicsSceneMouseRelease:
666 mouseReleaseEvent(&mouseEvent);
667 break;
668 default:
669 break;
670 }
671 grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
672 if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
673 grabMouse();
674
675 return stealThisEvent;
676 }
677 if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
678 if (d->pressed) {
679 d->pressed = false;
680 d->stealMouse = false;
681 if (s && s->mouseGrabberItem() == this)
682 ungrabMouse();
683 emit canceled();
684 emit pressedChanged();
685 if (d->hovered) {
686 d->hovered = false;
687 emit hoveredChanged();
688 }
689 }
690 }
691 return false;
692}
693
694bool QDeclarativeMouseArea::sceneEventFilter(QGraphicsItem *i, QEvent *e)
695{
696 Q_D(QDeclarativeMouseArea);
697 if (!d->absorb || !isVisible() || !d->drag || !d->drag->filterChildren())
698 return QDeclarativeItem::sceneEventFilter(i, e);
699 switch (e->type()) {
700 case QEvent::GraphicsSceneMousePress:
701 case QEvent::GraphicsSceneMouseMove:
702 case QEvent::GraphicsSceneMouseRelease:
703 return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
704 default:
705 break;
706 }
707
708 return QDeclarativeItem::sceneEventFilter(i, e);
709}
710
711void QDeclarativeMouseArea::timerEvent(QTimerEvent *event)
712{
713 Q_D(QDeclarativeMouseArea);
714 if (event->timerId() == d->pressAndHoldTimer.timerId()) {
715 d->pressAndHoldTimer.stop();
716 bool dragged = d->drag && d->drag->active();
717 if (d->pressed && dragged == false && d->hovered == true) {
718 d->longPress = true;
719 QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
720 emit pressAndHold(&me);
721 }
722 }
723}
724
725void QDeclarativeMouseArea::geometryChanged(const QRectF &newGeometry,
726 const QRectF &oldGeometry)
727{
728 Q_D(QDeclarativeMouseArea);
729 QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
730
731 if (d->lastScenePos.isNull)
732 d->lastScenePos = mapToScene(d->lastPos);
733 else if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y())
734 d->lastPos = mapFromScene(d->lastScenePos);
735}
736
737QVariant QDeclarativeMouseArea::itemChange(GraphicsItemChange change,
738 const QVariant &value)
739{
740 Q_D(QDeclarativeMouseArea);
741 switch (change) {
742 case ItemVisibleHasChanged:
743 if (acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse()))
744 setHovered(!d->hovered);
745 break;
746 default:
747 break;
748 }
749
750 return QDeclarativeItem::itemChange(change, value);
751}
752
753/*!
754 \qmlproperty bool MouseArea::hoverEnabled
755 This property holds whether hover events are handled.
756
757 By default, mouse events are only handled in response to a button event, or when a button is
758 pressed. Hover enables handling of all mouse events even when no mouse button is
759 pressed.
760
761 This property affects the containsMouse property and the onEntered, onExited and
762 onPositionChanged signals.
763*/
764bool QDeclarativeMouseArea::hoverEnabled() const
765{
766 return acceptHoverEvents();
767}
768
769void QDeclarativeMouseArea::setHoverEnabled(bool h)
770{
771 Q_D(QDeclarativeMouseArea);
772 if (h == acceptHoverEvents())
773 return;
774
775 setAcceptHoverEvents(h);
776 emit hoverEnabledChanged();
777 if (d->hovered != isUnderMouse())
778 setHovered(!d->hovered);
779}
780
781/*!
782 \qmlproperty bool MouseArea::containsMouse
783 This property holds whether the mouse is currently inside the mouse area.
784
785 \warning This property is not updated if the area moves under the mouse: \e containsMouse will not change.
786 In addition, if hoverEnabled is false, containsMouse will only be valid when the mouse is pressed.
787*/
788bool QDeclarativeMouseArea::hovered() const
789{
790 Q_D(const QDeclarativeMouseArea);
791 return d->hovered;
792}
793
794/*!
795 \qmlproperty bool MouseArea::pressed
796 This property holds whether the mouse area is currently pressed.
797*/
798bool QDeclarativeMouseArea::pressed() const
799{
800 Q_D(const QDeclarativeMouseArea);
801 return d->pressed;
802}
803
804void QDeclarativeMouseArea::setHovered(bool h)
805{
806 Q_D(QDeclarativeMouseArea);
807 if (d->hovered != h) {
808 d->hovered = h;
809 emit hoveredChanged();
810 d->hovered ? emit entered() : emit exited();
811 }
812}
813
814/*!
815 \qmlproperty Qt::MouseButtons MouseArea::acceptedButtons
816 This property holds the mouse buttons that the mouse area reacts to.
817
818 The available buttons are:
819 \list
820 \o Qt.LeftButton
821 \o Qt.RightButton
822 \o Qt.MiddleButton
823 \endlist
824
825 To accept more than one button the flags can be combined with the
826 "|" (or) operator:
827
828 \code
829 MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton }
830 \endcode
831
832 The default value is \c Qt.LeftButton.
833*/
834Qt::MouseButtons QDeclarativeMouseArea::acceptedButtons() const
835{
836 return acceptedMouseButtons();
837}
838
839void QDeclarativeMouseArea::setAcceptedButtons(Qt::MouseButtons buttons)
840{
841 if (buttons != acceptedMouseButtons()) {
842 setAcceptedMouseButtons(buttons);
843 emit acceptedButtonsChanged();
844 }
845}
846
847bool QDeclarativeMouseArea::setPressed(bool p)
848{
849 Q_D(QDeclarativeMouseArea);
850 bool dragged = d->drag && d->drag->active();
851 bool isclick = d->pressed == true && p == false && dragged == false && d->hovered == true;
852
853 if (d->pressed != p) {
854 d->pressed = p;
855 QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
856 if (d->pressed) {
857 if (!d->doubleClick)
858 emit pressed(&me);
859 me.setX(d->lastPos.x());
860 me.setY(d->lastPos.y());
861 emit mousePositionChanged(&me);
862 } else {
863 emit released(&me);
864 me.setX(d->lastPos.x());
865 me.setY(d->lastPos.y());
866 if (isclick && !d->longPress && !d->doubleClick)
867 emit clicked(&me);
868 }
869
870 emit pressedChanged();
871 return me.isAccepted();
872 }
873 return false;
874}
875
876QDeclarativeDrag *QDeclarativeMouseArea::drag()
877{
878 Q_D(QDeclarativeMouseArea);
879 if (!d->drag)
880 d->drag = new QDeclarativeDrag;
881 return d->drag;
882}
883
884/*!
885 \qmlproperty Item MouseArea::drag.target
886 \qmlproperty bool MouseArea::drag.active
887 \qmlproperty enumeration MouseArea::drag.axis
888 \qmlproperty real MouseArea::drag.minimumX
889 \qmlproperty real MouseArea::drag.maximumX
890 \qmlproperty real MouseArea::drag.minimumY
891 \qmlproperty real MouseArea::drag.maximumY
892 \qmlproperty bool MouseArea::drag.filterChildren
893
894 \c drag provides a convenient way to make an item draggable.
895
896 \list
897 \i \c drag.target specifies the id of the item to drag.
898 \i \c drag.active specifies if the target item is currently being dragged.
899 \i \c drag.axis specifies whether dragging can be done horizontally (\c Drag.XAxis), vertically (\c Drag.YAxis), or both (\c Drag.XandYAxis)
900 \i \c drag.minimum and \c drag.maximum limit how far the target can be dragged along the corresponding axes.
901 \endlist
902
903 The following example displays a \l Rectangle that can be dragged along the X-axis. The opacity
904 of the rectangle is reduced when it is dragged to the right.
905
906 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml drag
907
908 \note Items cannot be dragged if they are anchored for the requested
909 \c drag.axis. For example, if \c anchors.left or \c anchors.right was set
910 for \c rect in the above example, it cannot be dragged along the X-axis.
911 This can be avoided by settng the anchor value to \c undefined in
912 an \l onPressed handler.
913
914 If \c drag.filterChildren is set to true, a drag can override descendant MouseAreas. This
915 enables a parent MouseArea to handle drags, for example, while descendants handle clicks:
916
917 \snippet doc/src/snippets/declarative/mousearea/mouseareadragfilter.qml dragfilter
918
919*/
920
921QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.