~zsombi/ubuntu-ui-toolkit/listitemSelectModeBugs

« back to all changes in this revision

Viewing changes to src/Ubuntu/Components/plugin/privates/gesturedetector.cpp

  • Committer: Zsombor Egri
  • Date: 2015-11-20 16:37:59 UTC
  • mfrom: (1662.2.62 staging)
  • Revision ID: zsombor.egri@canonical.com-20151120163759-8p94jar0o53nbu95
staging sync

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2015 Canonical Ltd.
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify
5
 
 * it under the terms of the GNU Lesser General Public License as published by
6
 
 * the Free Software Foundation; version 3.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful,
9
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
 * GNU Lesser General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU Lesser General Public License
14
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 *
16
 
 * Authors: Zsombor Egri <zsombor.egri@canonical.com>
17
 
 */
18
 
 
19
 
#include "gesturedetector.h"
20
 
#include "ucunits.h"
21
 
#include <QtCore/QEvent>
22
 
#include <QtCore/QRectF>
23
 
#include <QtGui/QTouchEvent>
24
 
#include <QtQuick/QQuickItem>
25
 
#include <QtGui/QGuiApplication>
26
 
#include <QtGui/QStyleHints>
27
 
 
28
 
#define DETECTION_AREA_THICKNESS_GU 1.2
29
 
 
30
 
GestureDetector::GestureDetector(QObject *parent)
31
 
    : QObject(parent)
32
 
    , m_owner(qobject_cast<QQuickItem*>(parent))
33
 
    , m_status(Ready)
34
 
    , m_bottomUpSwipeDetected(false)
35
 
{
36
 
    Q_ASSERT(m_owner);
37
 
}
38
 
GestureDetector::~GestureDetector()
39
 
{
40
 
    Q_FOREACH(QObject *object, m_filteredItems) {
41
 
        object->removeEventFilter(this);
42
 
    }
43
 
    m_filteredItems.clear();
44
 
}
45
 
 
46
 
void GestureDetector::onFilteredItemDeleted(QObject *object)
47
 
{
48
 
    if (object) {
49
 
        object->removeEventFilter(this);
50
 
        m_filteredItems.removeAll(object);
51
 
    }
52
 
}
53
 
 
54
 
void GestureDetector::setStatus(Status status)
55
 
{
56
 
    if (status == m_status) {
57
 
        return;
58
 
    }
59
 
    m_status = status;
60
 
    Q_EMIT statusChanged(m_status);
61
 
}
62
 
 
63
 
bool GestureDetector::isDetecting()
64
 
{
65
 
    return (m_status > Ready && m_status < Completed);
66
 
}
67
 
 
68
 
void GestureDetector::setItemFilter(QObject *item)
69
 
{
70
 
    m_filteredItems.append(item);
71
 
    item->installEventFilter(this);
72
 
    connect(item, &QObject::destroyed, this, &GestureDetector::onFilteredItemDeleted);
73
 
}
74
 
 
75
 
void GestureDetector::removeItemFilter(QObject *item)
76
 
{
77
 
    m_filteredItems.removeAll(item);
78
 
    item->removeEventFilter(this);
79
 
    disconnect(item, &QObject::destroyed, this, &GestureDetector::onFilteredItemDeleted);
80
 
}
81
 
 
82
 
bool GestureDetector::handleTouchEvent(QObject *target, QTouchEvent *event)
83
 
{
84
 
    switch (event->type()) {
85
 
    case QEvent::TouchBegin: {
86
 
        setStatus(Ready);
87
 
        QPointF itemPoint = m_owner->mapFromScene(event->touchPoints()[0].scenePos());
88
 
        qreal thickness = UCUnits::instance().gu(DETECTION_AREA_THICKNESS_GU);
89
 
        QRectF detectionArea(0.0, m_owner->height() - thickness, m_owner->width(), thickness);
90
 
        if (detectionArea.contains(itemPoint)) {
91
 
            m_startPoint = itemPoint;
92
 
            setStatus(Started);
93
 
            if (target == parent()) {
94
 
                event->accept();
95
 
                return true;
96
 
            }
97
 
        }
98
 
        return false;
99
 
    }
100
 
    case QEvent::TouchEnd:
101
 
    {
102
 
        m_startPoint = QPointF();
103
 
        setStatus(Completed);
104
 
        return false;
105
 
    }
106
 
    case QEvent::TouchCancel: {
107
 
        m_startPoint = QPointF();
108
 
        setStatus(Ready);
109
 
        return false;
110
 
    }
111
 
    case QEvent::TouchUpdate: {
112
 
        if (m_status == Started) {
113
 
            QPointF itemPoint = m_owner->mapFromScene(event->touchPoints()[0].scenePos());
114
 
            if (abs(m_startPoint.y() - itemPoint.y()) >= qApp->styleHints()->startDragDistance()) {
115
 
                setStatus(Detected);
116
 
                Q_EMIT bottomUpSwipeDetected();
117
 
            }
118
 
        }
119
 
        return false;
120
 
    }
121
 
    default: return false;
122
 
    }
123
 
}
124
 
 
125
 
bool GestureDetector::eventFilter(QObject *target, QEvent *event)
126
 
{
127
 
    if (m_filteredItems.contains(target)) {
128
 
        QEvent::Type type = event->type();
129
 
        if (type == QEvent::TouchBegin
130
 
                || type == QEvent::TouchUpdate
131
 
                || type == QEvent::TouchEnd
132
 
                || type == QEvent::TouchCancel) {
133
 
            QTouchEvent *touch = static_cast<QTouchEvent*>(event);
134
 
            return handleTouchEvent(target, touch);
135
 
        } else {
136
 
            // pass it on
137
 
            return false;
138
 
        }
139
 
    } else {
140
 
        return QObject::eventFilter(target, event);
141
 
    }
142
 
}