Add a hidden XandYAxis enum value
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickmousearea.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickmousearea_p.h"
43 #include "qquickmousearea_p_p.h"
44 #include "qquickwindow.h"
45 #include "qquickevents_p_p.h"
46 #include "qquickdrag_p.h"
47
48 #include <private/qqmldata_p.h>
49
50 #include <QtGui/private/qguiapplication_p.h>
51
52 #include <QtGui/qevent.h>
53 #include <QtGui/qguiapplication.h>
54 #include <QtGui/qstylehints.h>
55
56 #include <float.h>
57
58 QT_BEGIN_NAMESPACE
59
60 DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
61
62 static const int PressAndHoldDelay = 800;
63
64 #ifndef QT_NO_DRAGANDDROP
65
66 QQuickDrag::QQuickDrag(QObject *parent)
67 : QObject(parent), _target(0), _axis(XAndYAxis), _xmin(-FLT_MAX),
68 _xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX), _active(false), _filterChildren(false)
69 {
70 }
71
72 QQuickDrag::~QQuickDrag()
73 {
74 }
75
76 QQuickItem *QQuickDrag::target() const
77 {
78     return _target;
79 }
80
81 void QQuickDrag::setTarget(QQuickItem *t)
82 {
83     if (_target == t)
84         return;
85     _target = t;
86     emit targetChanged();
87 }
88
89 void QQuickDrag::resetTarget()
90 {
91     if (_target == 0)
92         return;
93     _target = 0;
94     emit targetChanged();
95 }
96
97 QQuickDrag::Axis QQuickDrag::axis() const
98 {
99     return _axis;
100 }
101
102 void QQuickDrag::setAxis(QQuickDrag::Axis a)
103 {
104     if (_axis == a)
105         return;
106     _axis = a;
107     emit axisChanged();
108 }
109
110 qreal QQuickDrag::xmin() const
111 {
112     return _xmin;
113 }
114
115 void QQuickDrag::setXmin(qreal m)
116 {
117     if (_xmin == m)
118         return;
119     _xmin = m;
120     emit minimumXChanged();
121 }
122
123 qreal QQuickDrag::xmax() const
124 {
125     return _xmax;
126 }
127
128 void QQuickDrag::setXmax(qreal m)
129 {
130     if (_xmax == m)
131         return;
132     _xmax = m;
133     emit maximumXChanged();
134 }
135
136 qreal QQuickDrag::ymin() const
137 {
138     return _ymin;
139 }
140
141 void QQuickDrag::setYmin(qreal m)
142 {
143     if (_ymin == m)
144         return;
145     _ymin = m;
146     emit minimumYChanged();
147 }
148
149 qreal QQuickDrag::ymax() const
150 {
151     return _ymax;
152 }
153
154 void QQuickDrag::setYmax(qreal m)
155 {
156     if (_ymax == m)
157         return;
158     _ymax = m;
159     emit maximumYChanged();
160 }
161
162 bool QQuickDrag::active() const
163 {
164     return _active;
165 }
166
167 void QQuickDrag::setActive(bool drag)
168 {
169     if (_active == drag)
170         return;
171     _active = drag;
172     emit activeChanged();
173 }
174
175 bool QQuickDrag::filterChildren() const
176 {
177     return _filterChildren;
178 }
179
180 void QQuickDrag::setFilterChildren(bool filter)
181 {
182     if (_filterChildren == filter)
183         return;
184     _filterChildren = filter;
185     emit filterChildrenChanged();
186 }
187
188 QQuickDragAttached *QQuickDrag::qmlAttachedProperties(QObject *obj)
189 {
190     return new QQuickDragAttached(obj);
191 }
192
193 #endif // QT_NO_DRAGANDDROP
194
195 QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
196 : enabled(true), hovered(false), longPress(false),
197   moved(false), stealMouse(false), doubleClick(false), preventStealing(false),
198   propagateComposedEvents(false), pressed(0)
199 #ifndef QT_NO_DRAGANDDROP
200   , drag(0)
201 #endif
202 #ifndef QT_NO_CURSOR
203   , cursor(0)
204 #endif
205 {
206 }
207
208 QQuickMouseAreaPrivate::~QQuickMouseAreaPrivate()
209 {
210 #ifndef QT_NO_DRAGANDDROP
211     delete drag;
212 #endif
213 #ifndef QT_NO_CURSOR
214     delete cursor;
215 #endif
216 }
217
218 void QQuickMouseAreaPrivate::init()
219 {
220     Q_Q(QQuickMouseArea);
221     q->setAcceptedMouseButtons(Qt::LeftButton);
222     q->setFiltersChildMouseEvents(true);
223     if (qmlVisualTouchDebugging()) {
224         q->setFlag(QQuickItem::ItemHasContents);
225     }
226 }
227
228 void QQuickMouseAreaPrivate::saveEvent(QMouseEvent *event)
229 {
230     lastPos = event->localPos();
231     lastScenePos = event->windowPos();
232     lastButton = event->button();
233     lastButtons = event->buttons();
234     lastModifiers = event->modifiers();
235 }
236
237 bool QQuickMouseAreaPrivate::isPressAndHoldConnected()
238 {
239     Q_Q(QQuickMouseArea);
240     IS_SIGNAL_CONNECTED(q, QQuickMouseArea, pressAndHold, (QQuickMouseEvent *));
241 }
242
243 bool QQuickMouseAreaPrivate::isDoubleClickConnected()
244 {
245     Q_Q(QQuickMouseArea);
246     IS_SIGNAL_CONNECTED(q, QQuickMouseArea, doubleClicked, (QQuickMouseEvent *));
247 }
248
249 bool QQuickMouseAreaPrivate::isClickConnected()
250 {
251     Q_Q(QQuickMouseArea);
252     IS_SIGNAL_CONNECTED(q, QQuickMouseArea, clicked, (QQuickMouseEvent *));
253 }
254
255 bool QQuickMouseAreaPrivate::isWheelConnected()
256 {
257     Q_Q(QQuickMouseArea);
258     IS_SIGNAL_CONNECTED(q, QQuickMouseArea, wheel, (QQuickWheelEvent *));
259 }
260
261 void QQuickMouseAreaPrivate::propagate(QQuickMouseEvent* event, PropagateType t)
262 {
263     Q_Q(QQuickMouseArea);
264     if (!propagateComposedEvents)
265         return;
266     QPointF scenePos = q->mapToScene(QPointF(event->x(), event->y()));
267     propagateHelper(event, window->contentItem(), scenePos, t);
268 }
269
270 bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *item,const QPointF &sp, PropagateType sig)
271 {
272     //Based off of QQuickWindow::deliverInitialMousePressEvent
273     //But specific to MouseArea, so doesn't belong in window
274     Q_Q(const QQuickMouseArea);
275     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
276
277     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
278         QPointF p = item->mapFromScene(sp);
279         if (!item->contains(p))
280             return false;
281     }
282
283     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
284     for (int ii = children.count() - 1; ii >= 0; --ii) {
285         QQuickItem *child = children.at(ii);
286         if (!child->isVisible() || !child->isEnabled())
287             continue;
288         if (propagateHelper(ev, child, sp, sig))
289             return true;
290     }
291
292     QQuickMouseArea* ma = qobject_cast<QQuickMouseArea*>(item);
293     if (ma && ma != q && itemPrivate->acceptedMouseButtons() & ev->button()) {
294         switch (sig) {
295         case Click:
296             if (!ma->d_func()->isClickConnected())
297                 return false;
298             break;
299         case DoubleClick:
300             if (!ma->d_func()->isDoubleClickConnected())
301                 return false;
302             break;
303         case PressAndHold:
304             if (!ma->d_func()->isPressAndHoldConnected())
305                 return false;
306             break;
307         }
308         QPointF p = item->mapFromScene(sp);
309         if (item->contains(p)) {
310             ev->setX(p.x());
311             ev->setY(p.y());
312             ev->setAccepted(true);//It is connected, they have to explicitly ignore to let it slide
313             switch (sig) {
314             case Click: emit ma->clicked(ev); break;
315             case DoubleClick: emit ma->doubleClicked(ev); break;
316             case PressAndHold: emit ma->pressAndHold(ev); break;
317             }
318             if (ev->isAccepted())
319                 return true;
320         }
321     }
322     return false;
323
324 }
325
326 /*!
327     \qmltype MouseArea
328     \instantiates QQuickMouseArea
329     \inqmlmodule QtQuick 2
330     \ingroup qtquick-input
331     \brief Enables simple mouse handling
332     \inherits Item
333
334     A MouseArea is an invisible item that is typically used in conjunction with
335     a visible item in order to provide mouse handling for that item.
336     By effectively acting as a proxy, the logic for mouse handling can be
337     contained within a MouseArea item.
338
339     The \l enabled property is used to enable and disable mouse handling for
340     the proxied item. When disabled, the mouse area becomes transparent to
341     mouse events.
342
343     The \l pressed read-only property indicates whether or not the user is
344     holding down a mouse button over the mouse area. This property is often
345     used in bindings between properties in a user interface. The containsMouse
346     read-only property indicates the presence of the mouse cursor over the
347     mouse area but, by default, only when a mouse button is held down; see
348     the containsMouse documentation for details.
349
350     Information about the mouse position and button clicks are provided via
351     signals for which event handler properties are defined. The most commonly
352     used involved handling mouse presses and clicks: onClicked, onDoubleClicked,
353     onPressed, onReleased and onPressAndHold. It's also possible to handle mouse
354     wheel events via the onWheel signal.
355
356     If a MouseArea overlaps with the area of other MouseArea items, you can choose
357     to propagate \c clicked, \c doubleClicked and \c pressAndHold events to these
358     other items by setting propagateComposedEvents to true and rejecting events
359     that should be propagated. See the propagateComposedEvents documentation for
360     details.
361
362     By default, MouseArea items only report mouse clicks and not changes to the
363     position of the mouse cursor. Setting the hoverEnabled property ensures that
364     handlers defined for onPositionChanged, onEntered and onExited are used and
365     that the containsMouse property is updated even when no mouse buttons are
366     pressed.
367
368     \section1 Example Usage
369
370     \div {class="float-right"}
371     \inlineimage qml-mousearea-snippet.png
372     \enddiv
373
374     The following example uses a MouseArea in a \l Rectangle that changes
375     the \l Rectangle color to red when clicked:
376
377     \snippet qml/mousearea/mousearea.qml import
378     \codeline
379     \snippet qml/mousearea/mousearea.qml intro
380
381     \clearfloat
382     Many MouseArea signals pass a \l{MouseEvent}{mouse} parameter that contains
383     additional information about the mouse event, such as the position, button,
384     and any key modifiers.
385
386     Here is an extension of the previous example that produces a different
387     color when the area is right clicked:
388
389     \snippet qml/mousearea/mousearea.qml intro-extended
390
391     \sa MouseEvent, {declarative/touchinteraction/mousearea}{MouseArea example},
392     {Important Concepts In Qt Quick - User Input}
393 */
394
395 /*!
396     \qmlsignal QtQuick2::MouseArea::onEntered()
397
398     This handler is called when the mouse enters the mouse area.
399
400     By default the onEntered handler is only called while a button is
401     pressed. Setting hoverEnabled to true enables handling of
402     onEntered when no mouse button is pressed.
403
404     \sa hoverEnabled
405 */
406
407 /*!
408     \qmlsignal QtQuick2::MouseArea::onExited()
409
410     This handler is called when the mouse exits the mouse area.
411
412     By default the onExited handler is only called while a button is
413     pressed. Setting hoverEnabled to true enables handling of
414     onExited when no mouse button is pressed.
415
416     The example below shows a fairly typical relationship between
417     two MouseAreas, with \c mouseArea2 on top of \c mouseArea1. Moving the
418     mouse into \c mouseArea2 from \c mouseArea1 will cause \c onExited
419     to be called for \c mouseArea1.
420     \qml
421     Rectangle {
422         width: 400; height: 400
423         MouseArea {
424             id: mouseArea1
425             anchors.fill: parent
426             hoverEnabled: true
427         }
428         MouseArea {
429             id: mouseArea2
430             width: 100; height: 100
431             anchors.centerIn: parent
432             hoverEnabled: true
433         }
434     }
435     \endqml
436
437     If instead you give the two mouseAreas a parent-child relationship,
438     moving the mouse into \c mouseArea2 from \c mouseArea1 will \b not
439     cause \c onExited to be called for \c mouseArea1. Instead, they will
440     both be considered to be simultaneously hovered.
441
442     \sa hoverEnabled
443 */
444
445 /*!
446     \qmlsignal QtQuick2::MouseArea::onPositionChanged(MouseEvent mouse)
447
448     This handler is called when the mouse position changes.
449
450     The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
451     position, and any buttons currently pressed.
452
453     The \e accepted property of the MouseEvent parameter is ignored in this handler.
454
455     By default the onPositionChanged handler is only called while a button is
456     pressed.  Setting hoverEnabled to true enables handling of
457     onPositionChanged when no mouse button is pressed.
458 */
459
460 /*!
461     \qmlsignal QtQuick2::MouseArea::onClicked(MouseEvent mouse)
462
463     This handler is called when there is a click. A click is defined as a press followed by a release,
464     both inside the MouseArea (pressing, moving outside the MouseArea, and then moving back inside and
465     releasing is also considered a click).
466
467     The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
468     position of the release of the click, and whether the click was held.
469
470     The \e accepted property of the MouseEvent parameter is ignored in this handler.
471 */
472
473 /*!
474     \qmlsignal QtQuick2::MouseArea::onPressed(MouseEvent mouse)
475
476     This handler is called when there is a press.
477     The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
478     position and which button was pressed.
479
480     The \e accepted property of the MouseEvent parameter determines whether this MouseArea
481     will handle the press and all future mouse events until release.  The default is to accept
482     the event and not allow other MouseArea beneath this one to handle the event.  If \e accepted
483     is set to false, no further events will be sent to this MouseArea until the button is next
484     pressed.
485 */
486
487 /*!
488     \qmlsignal QtQuick2::MouseArea::onReleased(MouseEvent mouse)
489
490     This handler is called when there is a release.
491     The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
492     position of the release of the click, and whether the click was held.
493
494     The \e accepted property of the MouseEvent parameter is ignored in this handler.
495
496     \sa onCanceled
497 */
498
499 /*!
500     \qmlsignal QtQuick2::MouseArea::onPressAndHold(MouseEvent mouse)
501
502     This handler is called when there is a long press (currently 800ms).
503     The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
504     position of the press, and which button is pressed.
505
506     The \e accepted property of the MouseEvent parameter is ignored in this handler.
507 */
508
509 /*!
510     \qmlsignal QtQuick2::MouseArea::onDoubleClicked(MouseEvent mouse)
511
512     This handler is called when there is a double-click (a press followed by a release followed by a press).
513     The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
514     position of the release of the click, and whether the click was held.
515
516     If the \e accepted property of the \l {MouseEvent}{mouse} parameter is set to false
517     in the handler, the onPressed/onReleased/onClicked handlers will be called for the second
518     click; otherwise they are suppressed.  The accepted property defaults to true.
519 */
520
521 /*!
522     \qmlsignal QtQuick2::MouseArea::onCanceled()
523
524     This handler is called when mouse events have been canceled, either because an event was not accepted, or
525     because another item stole the mouse event handling.
526
527     This signal is for advanced use: it is useful when there is more than one MouseArea
528     that is handling input, or when there is a MouseArea inside a \l Flickable. In the latter
529     case, if you execute some logic on the pressed signal and then start dragging, the
530     \l Flickable will steal the mouse handling from the MouseArea. In these cases, to reset
531     the logic when the MouseArea has lost the mouse handling to the \l Flickable,
532     \c onCanceled should be used in addition to onReleased.
533 */
534
535 /*!
536     \qmlsignal QtQuick2::MouseArea::onWheel(WheelEvent wheel)
537
538     This handler is called in response to both mouse wheel and trackpad scroll gestures.
539
540     The \l {WheelEvent}{wheel} parameter provides information about the event, including the x and y
541     position, any buttons currently pressed, and information about the wheel movement, including
542     angleDelta and pixelDelta.
543 */
544
545 QQuickMouseArea::QQuickMouseArea(QQuickItem *parent)
546   : QQuickItem(*(new QQuickMouseAreaPrivate), parent)
547 {
548     Q_D(QQuickMouseArea);
549     d->init();
550 }
551
552 QQuickMouseArea::~QQuickMouseArea()
553 {
554 }
555
556 /*!
557     \qmlproperty real QtQuick2::MouseArea::mouseX
558     \qmlproperty real QtQuick2::MouseArea::mouseY
559     These properties hold the coordinates of the mouse cursor.
560
561     If the hoverEnabled property is false then these properties will only be valid
562     while a button is pressed, and will remain valid as long as the button is held
563     down even if the mouse is moved outside the area.
564
565     By default, this property is false.
566
567     If hoverEnabled is true then these properties will be valid when:
568     \list
569         \li no button is pressed, but the mouse is within the MouseArea (containsMouse is true).
570         \li a button is pressed and held, even if it has since moved out of the area.
571     \endlist
572
573     The coordinates are relative to the MouseArea.
574 */
575 qreal QQuickMouseArea::mouseX() const
576 {
577     Q_D(const QQuickMouseArea);
578     return d->lastPos.x();
579 }
580
581 qreal QQuickMouseArea::mouseY() const
582 {
583     Q_D(const QQuickMouseArea);
584     return d->lastPos.y();
585 }
586
587 /*!
588     \qmlproperty bool QtQuick2::MouseArea::enabled
589     This property holds whether the item accepts mouse events.
590
591     By default, this property is true.
592 */
593 bool QQuickMouseArea::isEnabled() const
594 {
595     Q_D(const QQuickMouseArea);
596     return d->enabled;
597 }
598
599 void QQuickMouseArea::setEnabled(bool a)
600 {
601     Q_D(QQuickMouseArea);
602     if (a != d->enabled) {
603         d->enabled = a;
604         emit enabledChanged();
605     }
606 }
607
608 /*!
609     \qmlproperty bool QtQuick2::MouseArea::preventStealing
610     This property holds whether the mouse events may be stolen from this
611     MouseArea.
612
613     If a MouseArea is placed within an item that filters child mouse
614     events, such as Flickable, the mouse
615     events may be stolen from the MouseArea if a gesture is recognized
616     by the parent item, e.g. a flick gesture.  If preventStealing is
617     set to true, no item will steal the mouse events.
618
619     Note that setting preventStealing to true once an item has started
620     stealing events will have no effect until the next press event.
621
622     By default this property is false.
623 */
624 bool QQuickMouseArea::preventStealing() const
625 {
626     Q_D(const QQuickMouseArea);
627     return d->preventStealing;
628 }
629
630 void QQuickMouseArea::setPreventStealing(bool prevent)
631 {
632     Q_D(QQuickMouseArea);
633     if (prevent != d->preventStealing) {
634         d->preventStealing = prevent;
635         setKeepMouseGrab(d->preventStealing && d->enabled);
636         emit preventStealingChanged();
637     }
638 }
639
640
641 /*!
642     \qmlproperty bool QtQuick2::MouseArea::propagateComposedEvents
643     This property holds whether composed mouse events will automatically propagate to
644     other MouseAreas that overlap with this MouseArea but are lower in the visual stacking order.
645     By default, this property is false.
646
647     MouseArea contains several composed events: \c clicked, \c doubleClicked and \c pressAndHold.
648     These are composed of basic mouse events, like \c pressed, and can be propagated differently
649     in comparison to basic events.
650
651     If propagateComposedEvents is set to true, then composed events will be automatically
652     propagated to other MouseAreas in the same location in the scene. Each event is propagated
653     to the next \l enabled MouseArea beneath it in the stacking order, propagating down this visual
654     hierarchy until a MouseArea accepts the event. Unlike \c pressed events, composed events will
655     not be automatically accepted if no handler is present.
656
657     For example, below is a yellow \l Rectangle that contains a blue \l Rectangle. The blue
658     rectangle is the top-most item in the hierarchy of the visual stacking order; it will
659     visually rendered above the yellow rectangle. Since the blue rectangle sets
660     propagateComposedEvents to true, and also sets \l MouseEvent::accepted to false for all
661     received \c clicked events, any \c clicked events it receives are propagated to the
662     MouseArea of the yellow rectangle beneath it.
663
664     \qml
665     import QtQuick 2.0
666
667     Rectangle {
668         color: "yellow"
669         width: 100; height: 100
670
671         MouseArea {
672             anchors.fill: parent
673             onClicked: console.log("clicked yellow")
674         }
675
676         Rectangle {
677             color: "blue"
678             width: 50; height: 50
679
680             MouseArea {
681                 anchors.fill: parent
682                 propagateComposedEvents: true
683                 onClicked: {
684                     console.log("clicked blue")
685                     mouse.accepted = false
686                 }
687             }
688         }
689     }
690     \endqml
691
692     Clicking on the blue rectangle will cause the \c onClicked handler of its child MouseArea to
693     be invoked; the event will then be propagated to the MouseArea of the yellow rectangle, causing
694     its own \c onClicked handler to be invoked.
695
696     This property greatly simplifies the usecase of when you want to have overlapping MouseAreas
697     handling the composed events together. For example: if you want one MouseArea to handle \c clicked
698     signals and the other to handle \c pressAndHold, or if you want one MouseArea to handle \c clicked most
699     of the time, but pass it through when certain conditions are met.
700 */
701 bool QQuickMouseArea::propagateComposedEvents() const
702 {
703     Q_D(const QQuickMouseArea);
704     return d->propagateComposedEvents;
705 }
706
707 void QQuickMouseArea::setPropagateComposedEvents(bool prevent)
708 {
709     Q_D(QQuickMouseArea);
710     if (prevent != d->propagateComposedEvents) {
711         d->propagateComposedEvents = prevent;
712         setKeepMouseGrab(d->propagateComposedEvents && d->enabled);
713         emit propagateComposedEventsChanged();
714     }
715 }
716
717 /*!
718     \qmlproperty MouseButtons QtQuick2::MouseArea::pressedButtons
719     This property holds the mouse buttons currently pressed.
720
721     It contains a bitwise combination of:
722     \list
723     \li Qt.LeftButton
724     \li Qt.RightButton
725     \li Qt.MiddleButton
726     \endlist
727
728     The code below displays "right" when the right mouse buttons is pressed:
729
730     \snippet qml/mousearea/mousearea.qml mousebuttons
731
732     \note this property only handles buttons specified in \l acceptedButtons.
733
734     \sa acceptedButtons
735 */
736 Qt::MouseButtons QQuickMouseArea::pressedButtons() const
737 {
738     Q_D(const QQuickMouseArea);
739     return d->pressed;
740 }
741
742 void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
743 {
744     Q_D(QQuickMouseArea);
745     d->moved = false;
746     d->stealMouse = d->preventStealing;
747     if (!d->enabled || !(event->button() & acceptedMouseButtons())) {
748         QQuickItem::mousePressEvent(event);
749     } else {
750         d->longPress = false;
751         d->saveEvent(event);
752 #ifndef QT_NO_DRAGANDDROP
753         if (d->drag)
754             d->drag->setActive(false);
755 #endif
756         setHovered(true);
757         d->startScene = event->windowPos();
758         d->pressAndHoldTimer.start(PressAndHoldDelay, this);
759         setKeepMouseGrab(d->stealMouse);
760         event->setAccepted(setPressed(event->button(), true));
761     }
762 }
763
764 void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
765 {
766     Q_D(QQuickMouseArea);
767     if (!d->enabled && !d->pressed) {
768         QQuickItem::mouseMoveEvent(event);
769         return;
770     }
771
772     d->saveEvent(event);
773
774     // ### we should skip this if these signals aren't used
775     // ### can GV handle this for us?
776     const bool isInside = contains(d->lastPos);
777     if (d->hovered && !isInside)
778         setHovered(false);
779     else if (!d->hovered && isInside)
780         setHovered(true);
781
782 #ifndef QT_NO_DRAGANDDROP
783     if (d->drag && d->drag->target()) {
784         if (!d->moved) {
785             d->targetStartPos = d->drag->target()->parentItem()
786                     ? d->drag->target()->parentItem()->mapToScene(d->drag->target()->position())
787                     : d->drag->target()->position();
788         }
789
790         QPointF startLocalPos;
791         QPointF curLocalPos;
792         if (drag()->target()->parentItem()) {
793             startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
794             curLocalPos = drag()->target()->parentItem()->mapFromScene(event->windowPos());
795         } else {
796             startLocalPos = d->startScene;
797             curLocalPos = event->windowPos();
798         }
799
800         qreal dx = qAbs(curLocalPos.x() - startLocalPos.x());
801         qreal dy = qAbs(curLocalPos.y() - startLocalPos.y());
802
803         if (keepMouseGrab() && d->stealMouse && !d->drag->active())
804             d->drag->setActive(true);
805
806         QPointF startPos = d->drag->target()->parentItem()
807                 ? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos)
808                 : d->targetStartPos;
809
810         QPointF dragPos = d->drag->target()->position();
811
812         bool dragX = drag()->axis() & QQuickDrag::XAxis;
813         bool dragY = drag()->axis() & QQuickDrag::YAxis;
814
815         if (dragX && d->drag->active()) {
816             qreal x = (curLocalPos.x() - startLocalPos.x()) + startPos.x();
817             if (x < drag()->xmin())
818                 x = drag()->xmin();
819             else if (x > drag()->xmax())
820                 x = drag()->xmax();
821             dragPos.setX(x);
822         }
823         if (dragY && d->drag->active()) {
824             qreal y = (curLocalPos.y() - startLocalPos.y()) + startPos.y();
825             if (y < drag()->ymin())
826                 y = drag()->ymin();
827             else if (y > drag()->ymax())
828                 y = drag()->ymax();
829             dragPos.setY(y);
830         }
831         d->drag->target()->setPosition(dragPos);
832
833         if (!keepMouseGrab()) {
834             bool xDragged = QQuickWindowPrivate::dragOverThreshold(dx, Qt::XAxis, event);
835             bool yDragged = QQuickWindowPrivate::dragOverThreshold(dy, Qt::YAxis, event);
836             if ((!dragY && !yDragged && dragX && xDragged)
837                 || (!dragX && !xDragged && dragY && yDragged)
838                 || (dragX && dragY && (xDragged || yDragged))) {
839                 setKeepMouseGrab(true);
840                 d->stealMouse = true;
841             }
842         }
843
844         d->moved = true;
845     }
846 #endif
847
848     QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
849     emit mouseXChanged(&me);
850     me.setPosition(d->lastPos);
851     emit mouseYChanged(&me);
852     me.setPosition(d->lastPos);
853     emit positionChanged(&me);
854 }
855
856 void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event)
857 {
858     Q_D(QQuickMouseArea);
859     d->stealMouse = false;
860     if (!d->enabled && !d->pressed) {
861         QQuickItem::mouseReleaseEvent(event);
862     } else {
863         d->saveEvent(event);
864         setPressed(event->button(), false);
865         if (!d->pressed) {
866             // no other buttons are pressed
867 #ifndef QT_NO_DRAGANDDROP
868             if (d->drag)
869                 d->drag->setActive(false);
870 #endif
871             // If we don't accept hover, we need to reset containsMouse.
872             if (!acceptHoverEvents())
873                 setHovered(false);
874             QQuickWindow *w = window();
875             if (w && w->mouseGrabberItem() == this)
876                 ungrabMouse();
877             setKeepMouseGrab(false);
878         }
879     }
880     d->doubleClick = false;
881 }
882
883 void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
884 {
885     Q_D(QQuickMouseArea);
886     if (d->enabled) {
887         d->saveEvent(event);
888         QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
889         me.setAccepted(d->isDoubleClickConnected());
890         emit this->doubleClicked(&me);
891         if (!me.isAccepted())
892             d->propagate(&me, QQuickMouseAreaPrivate::DoubleClick);
893         d->doubleClick = d->isDoubleClickConnected() || me.isAccepted();
894     }
895     QQuickItem::mouseDoubleClickEvent(event);
896 }
897
898 void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
899 {
900     Q_D(QQuickMouseArea);
901     if (!d->enabled && !d->pressed) {
902         QQuickItem::hoverEnterEvent(event);
903     } else {
904         d->lastPos = event->posF();
905         d->lastModifiers = event->modifiers();
906         setHovered(true);
907         QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
908         emit mouseXChanged(&me);
909         me.setPosition(d->lastPos);
910         emit mouseYChanged(&me);
911         me.setPosition(d->lastPos);
912     }
913 }
914
915 void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
916 {
917     Q_D(QQuickMouseArea);
918     if (!d->enabled && !d->pressed) {
919         QQuickItem::hoverMoveEvent(event);
920     } else {
921         d->lastPos = event->posF();
922         d->lastModifiers = event->modifiers();
923         QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
924         emit mouseXChanged(&me);
925         me.setPosition(d->lastPos);
926         emit mouseYChanged(&me);
927         me.setPosition(d->lastPos);
928         emit positionChanged(&me);
929     }
930 }
931
932 void QQuickMouseArea::hoverLeaveEvent(QHoverEvent *event)
933 {
934     Q_D(QQuickMouseArea);
935     if (!d->enabled && !d->pressed)
936         QQuickItem::hoverLeaveEvent(event);
937     else
938         setHovered(false);
939 }
940
941 void QQuickMouseArea::wheelEvent(QWheelEvent *event)
942 {
943     Q_D(QQuickMouseArea);
944     if (!d->enabled) {
945         QQuickItem::wheelEvent(event);
946         return;
947     }
948
949     QQuickWheelEvent we(event->posF().x(), event->posF().y(), event->angleDelta(),
950                         event->pixelDelta(), event->buttons(), event->modifiers());
951     we.setAccepted(d->isWheelConnected());
952     emit wheel(&we);
953     if (!we.isAccepted())
954         QQuickItem::wheelEvent(event);
955 }
956
957 void QQuickMouseArea::ungrabMouse()
958 {
959     Q_D(QQuickMouseArea);
960     if (d->pressed) {
961         // if our mouse grab has been removed (probably by Flickable), fix our
962         // state
963         d->pressed = 0;
964         d->stealMouse = false;
965         setKeepMouseGrab(false);
966         emit canceled();
967         emit pressedChanged();
968         emit pressedButtonsChanged();
969         if (d->hovered) {
970             d->hovered = false;
971             emit hoveredChanged();
972         }
973     }
974 }
975
976 void QQuickMouseArea::mouseUngrabEvent()
977 {
978     ungrabMouse();
979 }
980
981 bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
982 {
983     Q_D(QQuickMouseArea);
984     QPointF localPos = mapFromScene(event->windowPos());
985
986     QQuickWindow *c = window();
987     QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
988     bool stealThisEvent = d->stealMouse;
989     if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
990         QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(),
991                                event->button(), event->buttons(), event->modifiers());
992         mouseEvent.setAccepted(false);
993
994         switch (event->type()) {
995         case QEvent::MouseMove:
996             mouseMoveEvent(&mouseEvent);
997             break;
998         case QEvent::MouseButtonPress:
999             mousePressEvent(&mouseEvent);
1000             break;
1001         case QEvent::MouseButtonRelease:
1002             mouseReleaseEvent(&mouseEvent);
1003             break;
1004         default:
1005             break;
1006         }
1007         grabber = c->mouseGrabberItem();
1008         if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
1009             grabMouse();
1010
1011         return stealThisEvent;
1012     }
1013     if (event->type() == QEvent::MouseButtonRelease) {
1014         if (d->pressed) {
1015             d->pressed &= ~event->button();
1016             emit pressedButtonsChanged();
1017             if (!d->pressed) {
1018                 // no other buttons are pressed
1019                 d->stealMouse = false;
1020                 if (c && c->mouseGrabberItem() == this)
1021                     ungrabMouse();
1022                 emit canceled();
1023                 emit pressedChanged();
1024                 if (d->hovered) {
1025                     d->hovered = false;
1026                     emit hoveredChanged();
1027                 }
1028             }
1029         }
1030     }
1031     return false;
1032 }
1033
1034 bool QQuickMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
1035 {
1036     Q_D(QQuickMouseArea);
1037     if (!d->pressed &&
1038             (!d->enabled || !isVisible()
1039 #ifndef QT_NO_DRAGANDDROP
1040              || !d->drag || !d->drag->filterChildren()
1041 #endif
1042             )
1043        )
1044         return QQuickItem::childMouseEventFilter(i, e);
1045     switch (e->type()) {
1046     case QEvent::MouseButtonPress:
1047     case QEvent::MouseMove:
1048     case QEvent::MouseButtonRelease:
1049         return sendMouseEvent(static_cast<QMouseEvent *>(e));
1050     default:
1051         break;
1052     }
1053
1054     return QQuickItem::childMouseEventFilter(i, e);
1055 }
1056
1057 void QQuickMouseArea::timerEvent(QTimerEvent *event)
1058 {
1059     Q_D(QQuickMouseArea);
1060     if (event->timerId() == d->pressAndHoldTimer.timerId()) {
1061         d->pressAndHoldTimer.stop();
1062 #ifndef QT_NO_DRAGANDDROP
1063         bool dragged = d->drag && d->drag->active();
1064 #else
1065         bool dragged = false;
1066 #endif
1067         if (d->pressed && dragged == false && d->hovered == true) {
1068             d->longPress = true;
1069             QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
1070             me.setAccepted(d->isPressAndHoldConnected());
1071             emit pressAndHold(&me);
1072             if (!me.isAccepted())
1073                 d->propagate(&me, QQuickMouseAreaPrivate::PressAndHold);
1074             if (!me.isAccepted()) // no one handled the long press - allow click
1075                 d->longPress = false;
1076         }
1077     }
1078 }
1079
1080 void QQuickMouseArea::windowDeactivateEvent()
1081 {
1082     ungrabMouse();
1083     QQuickItem::windowDeactivateEvent();
1084 }
1085
1086 void QQuickMouseArea::geometryChanged(const QRectF &newGeometry,
1087                                             const QRectF &oldGeometry)
1088 {
1089     Q_D(QQuickMouseArea);
1090     QQuickItem::geometryChanged(newGeometry, oldGeometry);
1091
1092     if (d->lastScenePos.isNull)
1093         d->lastScenePos = mapToScene(d->lastPos);
1094     else if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y())
1095         d->lastPos = mapFromScene(d->lastScenePos);
1096 }
1097
1098 void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
1099 {
1100     Q_D(QQuickMouseArea);
1101     switch (change) {
1102     case ItemVisibleHasChanged:
1103         if (acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse())) {
1104             if (!d->hovered) {
1105                 QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition;
1106                 d->lastScenePos = d->window->mapFromGlobal(cursorPos.toPoint());
1107                 d->lastPos = mapFromScene(d->lastScenePos);
1108             }
1109             setHovered(!d->hovered);
1110         }
1111         break;
1112     default:
1113         break;
1114     }
1115
1116     QQuickItem::itemChange(change, value);
1117 }
1118
1119 /*!
1120     \qmlproperty bool QtQuick2::MouseArea::hoverEnabled
1121     This property holds whether hover events are handled.
1122
1123     By default, mouse events are only handled in response to a button event, or when a button is
1124     pressed.  Hover enables handling of all mouse events even when no mouse button is
1125     pressed.
1126
1127     This property affects the containsMouse property and the onEntered, onExited and
1128     onPositionChanged signals.
1129 */
1130 bool QQuickMouseArea::hoverEnabled() const
1131 {
1132     return acceptHoverEvents();
1133 }
1134
1135 void QQuickMouseArea::setHoverEnabled(bool h)
1136 {
1137     if (h == acceptHoverEvents())
1138         return;
1139
1140     setAcceptHoverEvents(h);
1141     emit hoverEnabledChanged();
1142 }
1143
1144
1145 /*!
1146     \qmlproperty bool QtQuick2::MouseArea::containsMouse
1147     This property holds whether the mouse is currently inside the mouse area.
1148
1149     \warning This property is not updated if the area moves under the mouse: \e containsMouse will not change.
1150     In addition, if hoverEnabled is false, containsMouse will only be valid when the mouse is pressed.
1151 */
1152 bool QQuickMouseArea::hovered() const
1153 {
1154     Q_D(const QQuickMouseArea);
1155     return d->hovered;
1156 }
1157
1158 /*!
1159     \qmlproperty bool QtQuick2::MouseArea::pressed
1160     This property holds whether any of the \l acceptedButtons are currently pressed.
1161 */
1162 bool QQuickMouseArea::pressed() const
1163 {
1164     Q_D(const QQuickMouseArea);
1165     return d->pressed;
1166 }
1167
1168 void QQuickMouseArea::setHovered(bool h)
1169 {
1170     Q_D(QQuickMouseArea);
1171     if (d->hovered != h) {
1172         d->hovered = h;
1173         emit hoveredChanged();
1174         d->hovered ? emit entered() : emit exited();
1175     }
1176 }
1177
1178 /*!
1179     \qmlproperty Qt::MouseButtons QtQuick2::MouseArea::acceptedButtons
1180     This property holds the mouse buttons that the mouse area reacts to.
1181
1182     To specify that the MouseArea will react to multiple buttons,
1183     Qt::MouseButtons flag values are combined using the "|" (or) operator:
1184
1185     \code
1186     MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton }
1187     \endcode
1188
1189     To indicate that all possible mouse buttons are to be accepted,
1190     the special value 'Qt.AllButtons' may be used:
1191
1192     \code
1193     MouseArea { acceptedButtons: Qt.AllButtons }
1194     \endcode
1195
1196     The default value is \c Qt.LeftButton.
1197 */
1198 Qt::MouseButtons QQuickMouseArea::acceptedButtons() const
1199 {
1200     return acceptedMouseButtons();
1201 }
1202
1203 void QQuickMouseArea::setAcceptedButtons(Qt::MouseButtons buttons)
1204 {
1205     if (buttons != acceptedMouseButtons()) {
1206         setAcceptedMouseButtons(buttons);
1207         emit acceptedButtonsChanged();
1208     }
1209 }
1210
1211 bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p)
1212 {
1213     Q_D(QQuickMouseArea);
1214
1215 #ifndef QT_NO_DRAGANDDROP
1216     bool dragged = d->drag && d->drag->active();
1217 #else
1218     bool dragged = false;
1219 #endif
1220     bool wasPressed = d->pressed & button;
1221     bool isclick = wasPressed && p == false && dragged == false && d->hovered == true;
1222     Qt::MouseButtons oldPressed = d->pressed;
1223
1224     if (wasPressed != p) {
1225         QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
1226         if (p) {
1227             d->pressed |= button;
1228             if (!d->doubleClick)
1229                 emit pressed(&me);
1230             me.setPosition(d->lastPos);
1231             emit mouseXChanged(&me);
1232             me.setPosition(d->lastPos);
1233             emit mouseYChanged(&me);
1234             if (!oldPressed)
1235                 emit pressedChanged();
1236             emit pressedButtonsChanged();
1237         } else {
1238             d->pressed &= ~button;
1239             emit released(&me);
1240             me.setPosition(d->lastPos);
1241             if (!d->pressed)
1242                 emit pressedChanged();
1243             emit pressedButtonsChanged();
1244             if (isclick && !d->longPress && !d->doubleClick){
1245                 me.setAccepted(d->isClickConnected());
1246                 emit clicked(&me);
1247                 if (!me.isAccepted())
1248                     d->propagate(&me, QQuickMouseAreaPrivate::Click);
1249             }
1250         }
1251
1252         return me.isAccepted();
1253     }
1254     return false;
1255 }
1256
1257
1258 /*!
1259     \qmlproperty Qt::CursorShape QtQuick2::MouseArea::cursorShape
1260     This property holds the cursor shape for this mouse area.
1261     Note that on platforms that do not display a mouse cursor this may have
1262     no effect.
1263
1264     The available cursor shapes are:
1265     \list
1266     \li Qt.ArrowCursor
1267     \li Qt.UpArrowCursor
1268     \li Qt.CrossCursor
1269     \li Qt.WaitCursor
1270     \li Qt.IBeamCursor
1271     \li Qt.SizeVerCursor
1272     \li Qt.SizeHorCursor
1273     \li Qt.SizeBDiagCursor
1274     \li Qt.SizeFDiagCursor
1275     \li Qt.SizeAllCursor
1276     \li Qt.BlankCursor
1277     \li Qt.SplitVCursor
1278     \li Qt.SplitHCursor
1279     \li Qt.PointingHandCursor
1280     \li Qt.ForbiddenCursor
1281     \li Qt.WhatsThisCursor
1282     \li Qt.BusyCursor
1283     \li Qt.OpenHandCursor
1284     \li Qt.ClosedHandCursor
1285     \li Qt.DragCopyCursor
1286     \li Qt.DragMoveCursor
1287     \li Qt.DragLinkCursor
1288     \endlist
1289
1290     In order to only set a mouse cursor shape for a region without reacting
1291     to mouse events set the acceptedButtons to none:
1292
1293     \code
1294     MouseArea { cursorShape: Qt.IBeamCursor; acceptedButtons: Qt.NoButton }
1295     \endcode
1296
1297     The default value is \c Qt.ArrowCursor.
1298     \sa Qt::CursorShape
1299 */
1300
1301 #ifndef QT_NO_CURSOR
1302 Qt::CursorShape QQuickMouseArea::cursorShape() const
1303 {
1304     return cursor().shape();
1305 }
1306
1307 void QQuickMouseArea::setCursorShape(Qt::CursorShape shape)
1308 {
1309     if (cursor().shape() == shape)
1310         return;
1311
1312     setCursor(shape);
1313
1314     emit cursorShapeChanged();
1315 }
1316
1317 #endif
1318
1319 /*!
1320     \qmlproperty Item QtQuick2::MouseArea::drag.target
1321     \qmlproperty bool QtQuick2::MouseArea::drag.active
1322     \qmlproperty enumeration QtQuick2::MouseArea::drag.axis
1323     \qmlproperty real QtQuick2::MouseArea::drag.minimumX
1324     \qmlproperty real QtQuick2::MouseArea::drag.maximumX
1325     \qmlproperty real QtQuick2::MouseArea::drag.minimumY
1326     \qmlproperty real QtQuick2::MouseArea::drag.maximumY
1327     \qmlproperty bool QtQuick2::MouseArea::drag.filterChildren
1328
1329     \c drag provides a convenient way to make an item draggable.
1330
1331     \list
1332     \li \c drag.target specifies the id of the item to drag.
1333     \li \c drag.active specifies if the target item is currently being dragged.
1334     \li \c drag.axis specifies whether dragging can be done horizontally (\c Drag.XAxis), vertically (\c Drag.YAxis), or both (\c Drag.XAndYAxis)
1335     \li \c drag.minimum and \c drag.maximum limit how far the target can be dragged along the corresponding axes.
1336     \endlist
1337
1338     The following example displays a \l Rectangle that can be dragged along the X-axis. The opacity
1339     of the rectangle is reduced when it is dragged to the right.
1340
1341     \snippet qml/mousearea/mousearea.qml drag
1342
1343     \note Items cannot be dragged if they are anchored for the requested
1344     \c drag.axis. For example, if \c anchors.left or \c anchors.right was set
1345     for \c rect in the above example, it cannot be dragged along the X-axis.
1346     This can be avoided by settng the anchor value to \c undefined in
1347     an \l onPressed handler.
1348
1349     If \c drag.filterChildren is set to true, a drag can override descendant MouseAreas.  This
1350     enables a parent MouseArea to handle drags, for example, while descendants handle clicks:
1351
1352     \snippet qml/mousearea/mouseareadragfilter.qml dragfilter
1353
1354 */
1355
1356 #ifndef QT_NO_DRAGANDDROP
1357 QQuickDrag *QQuickMouseArea::drag()
1358 {
1359     Q_D(QQuickMouseArea);
1360     if (!d->drag)
1361         d->drag = new QQuickDrag;
1362     return d->drag;
1363 }
1364 #endif
1365
1366 QSGNode *QQuickMouseArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1367 {
1368     Q_UNUSED(data);
1369     Q_D(QQuickMouseArea);
1370
1371     if (!qmlVisualTouchDebugging())
1372         return 0;
1373
1374     QSGRectangleNode *rectangle = static_cast<QSGRectangleNode *>(oldNode);
1375     if (!rectangle) rectangle = d->sceneGraphContext()->createRectangleNode();
1376
1377     rectangle->setRect(QRectF(0, 0, width(), height()));
1378     rectangle->setColor(QColor(255, 0, 0, 50));
1379     rectangle->update();
1380     return rectangle;
1381 }
1382
1383 QT_END_NAMESPACE