1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
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 The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qquickpresshandler_p_p.h"
38
39#include <QtCore/private/qobject_p.h>
40#include <QtGui/qguiapplication.h>
41#include <QtGui/qstylehints.h>
42#include <QtQuick/qquickitem.h>
43#include <QtQuick/private/qquickevents_p_p.h>
44#include <QtQuickTemplates2/private/qquicktextarea_p.h>
45#include <QtQuickTemplates2/private/qquicktextfield_p.h>
46
47QT_BEGIN_NAMESPACE
48
49void QQuickPressHandler::mousePressEvent(QMouseEvent *event)
50{
51 longPress = false;
52 pressPos = event->localPos();
53 if (Qt::LeftButton == (event->buttons() & Qt::LeftButton)) {
54 timer.start(msec: QGuiApplication::styleHints()->mousePressAndHoldInterval(), obj: control);
55 delayedMousePressEvent = new QMouseEvent(event->type(), event->pos(), event->button(), event->buttons(), event->modifiers());
56 } else {
57 timer.stop();
58 }
59
60 if (isSignalConnected(item: control, signalName: "pressed(QQuickMouseEvent*)", signalIndex&: pressedSignalIndex)) {
61 QQuickMouseEvent mev;
62 mev.reset(x: pressPos.x(), y: pressPos.y(), button: event->button(), buttons: event->buttons(),
63 modifiers: QGuiApplication::keyboardModifiers(), isClick: false/*isClick*/, wasHeld: false/*wasHeld*/);
64 mev.setAccepted(true);
65 QQuickMouseEvent *mevPtr = &mev;
66 void *args[] = { nullptr, &mevPtr };
67 QMetaObject::metacall(control, QMetaObject::InvokeMetaMethod, pressedSignalIndex, args);
68 event->setAccepted(mev.isAccepted());
69 }
70}
71
72void QQuickPressHandler::mouseMoveEvent(QMouseEvent *event)
73{
74 if (qAbs(t: int(event->localPos().x() - pressPos.x())) > QGuiApplication::styleHints()->startDragDistance())
75 timer.stop();
76}
77
78void QQuickPressHandler::mouseReleaseEvent(QMouseEvent *event)
79{
80 if (!longPress) {
81 timer.stop();
82
83 if (isSignalConnected(item: control, signalName: "released(QQuickMouseEvent*)", signalIndex&: releasedSignalIndex)) {
84 QQuickMouseEvent mev;
85 mev.reset(x: pressPos.x(), y: pressPos.y(), button: event->button(), buttons: event->buttons(),
86 modifiers: QGuiApplication::keyboardModifiers(), isClick: false/*isClick*/, wasHeld: false/*wasHeld*/);
87 mev.setAccepted(true);
88 QQuickMouseEvent *mevPtr = &mev;
89 void *args[] = { nullptr, &mevPtr };
90 QMetaObject::metacall(control, QMetaObject::InvokeMetaMethod, releasedSignalIndex, args);
91 event->setAccepted(mev.isAccepted());
92 }
93 }
94}
95
96void QQuickPressHandler::timerEvent(QTimerEvent *)
97{
98 timer.stop();
99 clearDelayedMouseEvent();
100
101 longPress = isSignalConnected(item: control, signalName: "pressAndHold(QQuickMouseEvent*)", signalIndex&: pressAndHoldSignalIndex);
102 if (longPress) {
103 QQuickMouseEvent mev;
104 mev.reset(x: pressPos.x(), y: pressPos.y(), button: Qt::LeftButton, buttons: Qt::LeftButton,
105 modifiers: QGuiApplication::keyboardModifiers(), isClick: false/*isClick*/, wasHeld: true/*wasHeld*/);
106 mev.setAccepted(true);
107 // Use fast signal invocation since we already got its index
108 QQuickMouseEvent *mevPtr = &mev;
109 void *args[] = { nullptr, &mevPtr };
110 QMetaObject::metacall(control, QMetaObject::InvokeMetaMethod, pressAndHoldSignalIndex, args);
111 if (!mev.isAccepted())
112 longPress = false;
113 }
114}
115
116void QQuickPressHandler::clearDelayedMouseEvent()
117{
118 if (delayedMousePressEvent) {
119 delete delayedMousePressEvent;
120 delayedMousePressEvent = 0;
121 }
122}
123
124bool QQuickPressHandler::isActive()
125{
126 return !(timer.isActive() || longPress);
127}
128
129bool QQuickPressHandler::isSignalConnected(QQuickItem *item, const char *signalName, int &signalIndex)
130{
131 if (signalIndex == -1)
132 signalIndex = item->metaObject()->indexOfSignal(signal: signalName);
133 Q_ASSERT(signalIndex != -1);
134 const auto signalMetaMethod = item->metaObject()->method(index: signalIndex);
135 if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea*>(object: item)) {
136 return textArea->isSignalConnected(signal: signalMetaMethod);
137 } else if (QQuickTextField *textField = qobject_cast<QQuickTextField*>(object: item)) {
138 return textField->isSignalConnected(signal: signalMetaMethod);
139 }
140 qFatal(msg: "Unhandled control type for signal name: %s", signalName);
141 return false;
142}
143
144QT_END_NAMESPACE
145

source code of qtquickcontrols2/src/quicktemplates2/qquickpresshandler.cpp