Merge lp:~zsombi/ubuntu-ui-toolkit/77-pressandhold into lp:ubuntu-ui-toolkit/staging

Proposed by Zsombor Egri
Status: Merged
Approved by: Tim Peeters
Approved revision: 1383
Merged at revision: 1387
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/77-pressandhold
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 328 lines (+130/-8)
6 files modified
components.api (+1/-0)
modules/Ubuntu/Components/plugin/uclistitem.cpp (+56/-6)
modules/Ubuntu/Components/plugin/uclistitem.h (+2/-0)
modules/Ubuntu/Components/plugin/uclistitem_p.h (+3/-0)
tests/resources/listitems/ListItemTest.qml (+8/-2)
tests/unit_x11/tst_components/tst_listitem.qml (+60/-0)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/77-pressandhold
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Tim Peeters Approve
Review via email: mp+246940@code.launchpad.net

Commit message

Introducing pressAndHold signal into ListItem.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1381. By Zsombor Egri

staging sync

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1382. By Zsombor Egri

staging sync

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

If you press on a list item without actions, and then start dragging, the long-press still takes effect. This was not totally expected for me, but I tested the MouseArea behavior and that is the same. Nice! :)

When I long-press on a list item with actions it works fine (and it doesn't trigger when dragging the actions).

Revision history for this message
Tim Peeters (tpeeters) wrote :

82 + * onPressAndHold: console.log("clicked on ListItem with onPressAndHold implemented")

"clicked" should be "long-pressed" ;)

Revision history for this message
Tim Peeters (tpeeters) wrote :

105 + * The signal is emitted when the list item is long pressed. When a slot is connected,
106 + * no \l clicked signal will be emitted, similarly to MouseArea's pressAndHold.

shouldn't that be "When a slot is triggered,"? Connected seems misleading here.

1383. By Zsombor Egri

review comments applied

Revision history for this message
Tim Peeters (tpeeters) wrote :

great, thanks!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'components.api'
2--- components.api 2015-01-22 06:15:59 +0000
3+++ components.api 2015-01-22 11:34:38 +0000
4@@ -882,6 +882,7 @@
5 Property { name: "style"; type: "QQmlComponent"; isPointer: true }
6 Property { name: "__styleInstance"; type: "QQuickItem"; isReadonly: true; isPointer: true }
7 Signal { name: "clicked" }
8+ Signal { name: "pressAndHold" }
9 Signal { name: "contentMovementStarted" }
10 Signal { name: "contentMovementEnded" }
11 name: "UCListItemActions"
12
13=== modified file 'modules/Ubuntu/Components/plugin/uclistitem.cpp'
14--- modules/Ubuntu/Components/plugin/uclistitem.cpp 2015-01-20 10:24:08 +0000
15+++ modules/Ubuntu/Components/plugin/uclistitem.cpp 2015-01-22 11:34:38 +0000
16@@ -28,6 +28,8 @@
17 #include <QtQuick/private/qquickitem_p.h>
18 #include <QtQuick/private/qquickflickable_p.h>
19 #include <QtQuick/private/qquickpositioners_p.h>
20+#include <QtGui/QGuiApplication>
21+#include <QtGui/QStyleHints>
22 #include <QtQuick/private/qquickanimation_p.h>
23 #include <QtQuick/private/qquickmousearea_p.h>
24 #include "uclistitemstyle.h"
25@@ -395,6 +397,14 @@
26 return QObjectPrivate::get(q)->isSignalConnected(signalIdx);
27 }
28
29+bool UCListItemPrivate::isPressAndHoldConnected()
30+{
31+ Q_Q(UCListItem);
32+ static QMetaMethod method = QMetaMethod::fromSignal(&UCListItem::pressAndHold);
33+ static int signalIdx = QMetaObjectPrivate::signalIndex(method);
34+ return QObjectPrivate::get(q)->isSignalConnected(signalIdx);
35+}
36+
37 void UCListItemPrivate::_q_updateThemedData()
38 {
39 Q_Q(UCListItem);
40@@ -593,7 +603,8 @@
41 // action, leading or trailing actions list or at least an active child component declared
42 QQuickMouseArea *ma = q->findChild<QQuickMouseArea*>();
43 bool activeMouseArea = ma && ma->isEnabled();
44- return !activeComponent && (isClickedConnected() || leadingActions || trailingActions || activeMouseArea);
45+ return !activeComponent && (isClickedConnected() || isPressAndHoldConnected() ||
46+ leadingActions || trailingActions || activeMouseArea);
47 }
48
49 // set highlighted flag and update contentItem
50@@ -604,6 +615,12 @@
51 suppressClick = false;
52 Q_Q(UCListItem);
53 q->update();
54+ if (highlighted) {
55+ // start pressandhold timer
56+ pressAndHoldTimer.start(QGuiApplication::styleHints()->mousePressAndHoldInterval(), q);
57+ } else {
58+ pressAndHoldTimer.stop();
59+ }
60 Q_EMIT q->highlightedChanged();
61 }
62 }
63@@ -697,9 +714,9 @@
64 * properties. The list item is highlighted if there is an action attached to it.
65 * This means that the list item must have an active component declared as child,
66 * at least leading- or trailing actions specified, or to have a slot connected to
67- * \l clicked signal. In any other case the component will not be highlighted, and
68- * \l highlighted property will not be toggled either. Also, there will be no highlight
69- * happening if the click happens on the active component.
70+ * \l clicked or \l pressAndHold signal. In any other case the component will not
71+ * be highlighted, and \l highlighted property will not be toggled either. Also,
72+ * there will be no highlight happening if the click happens on the active component.
73 * \qml
74 * import QtQuick 2.3
75 * import Ubuntu.Components 1.2
76@@ -744,6 +761,12 @@
77 * }
78 * ListItem {
79 * Label {
80+ * text: "onPressAndHold implemented"
81+ * }
82+ * onPressAndHold: console.log("long-pressed on ListItem with onPressAndHold implemented")
83+ * }
84+ * ListItem {
85+ * Label {
86 * text: "No highlight"
87 * }
88 * }
89@@ -825,11 +848,22 @@
90
91 /*!
92 * \qmlsignal ListItem::clicked()
93- *
94 * The signal is emitted when the component gets released while the \l highlighted property
95 * is set. The signal is not emitted if the ListItem content is swiped or when used in
96 * Flickable (or ListView, GridView) and the Flickable gets moved.
97- */
98+ *
99+ * If the ListItem contains a component which contains a MouseArea, the clicked
100+ * signal will be supressed.
101+ */
102+
103+/*!
104+ * \qmlsignal ListItem::pressAndHold()
105+ * The signal is emitted when the list item is long pressed.
106+ *
107+ * If the ListItem contains a component which contains a MouseArea, the pressAndHold
108+ * signal will be supressed.
109+ */
110+
111 UCListItem::UCListItem(QQuickItem *parent)
112 : UCStyledItemBase(*(new UCListItemPrivate), parent)
113 {
114@@ -1073,6 +1107,8 @@
115 d->lastPos = event->localPos();
116
117 if (dx) {
118+ // stop pressAndHold timer as we started to drag
119+ d->pressAndHoldTimer.stop();
120 d->setContentMoving(true);
121 // clamp X into allowed dragging area
122 d->clampAndMoveX(x, dx);
123@@ -1146,6 +1182,20 @@
124 return UCStyledItemBase::eventFilter(target, event);
125 }
126
127+void UCListItem::timerEvent(QTimerEvent *event)
128+{
129+ Q_D(UCListItem);
130+ if (event->timerId() == d->pressAndHoldTimer.timerId() && d->highlighted) {
131+ d->pressAndHoldTimer.stop();
132+ if (isEnabled() && d->isPressAndHoldConnected()) {
133+ d->suppressClick = true;
134+ Q_EMIT pressAndHold();
135+ }
136+ } else {
137+ QQuickItem::timerEvent(event);
138+ }
139+}
140+
141 /*!
142 * \qmlproperty ListItemActions ListItem::leadingActions
143 *
144
145=== modified file 'modules/Ubuntu/Components/plugin/uclistitem.h'
146--- modules/Ubuntu/Components/plugin/uclistitem.h 2015-01-12 15:44:59 +0000
147+++ modules/Ubuntu/Components/plugin/uclistitem.h 2015-01-22 11:34:38 +0000
148@@ -78,6 +78,7 @@
149 void mouseMoveEvent(QMouseEvent *event);
150 bool childMouseEventFilter(QQuickItem *child, QEvent *event);
151 bool eventFilter(QObject *, QEvent *);
152+ void timerEvent(QTimerEvent *event);
153
154 Q_SIGNALS:
155 void leadingActionsChanged();
156@@ -90,6 +91,7 @@
157 void listItemChildrenChanged();
158
159 void clicked();
160+ void pressAndHold();
161
162 void styleChanged();
163 void __styleInstanceChanged();
164
165=== modified file 'modules/Ubuntu/Components/plugin/uclistitem_p.h'
166--- modules/Ubuntu/Components/plugin/uclistitem_p.h 2015-01-12 15:44:59 +0000
167+++ modules/Ubuntu/Components/plugin/uclistitem_p.h 2015-01-22 11:34:38 +0000
168@@ -20,6 +20,7 @@
169 #include "uclistitem.h"
170 #include "ucstyleditembase_p.h"
171 #include <QtCore/QPointer>
172+#include <QtCore/QBasicTimer>
173 #include <QtQuick/private/qquickrectangle_p.h>
174
175 #define MIN(x, y) ((x < y) ? x : y)
176@@ -54,6 +55,7 @@
177 }
178
179 bool isClickedConnected();
180+ bool isPressAndHoldConnected();
181 void _q_updateThemedData();
182 void _q_rebound();
183 void promptRebound();
184@@ -79,6 +81,7 @@
185 bool flicked:1;
186 qreal xAxisMoveThresholdGU;
187 qreal overshoot;
188+ QBasicTimer pressAndHoldTimer;
189 QPointF lastPos;
190 QPointF pressedPos;
191 QColor color;
192
193=== modified file 'tests/resources/listitems/ListItemTest.qml'
194--- tests/resources/listitems/ListItemTest.qml 2015-01-12 07:58:55 +0000
195+++ tests/resources/listitems/ListItemTest.qml 2015-01-22 11:34:38 +0000
196@@ -96,16 +96,21 @@
197 print("click")
198 main.override = !main.override
199 }
200+ onPressAndHold: print("pressAndHold", objectName)
201 Label {
202 anchors.fill: parent
203 text: units.gridUnit + "PX/unit"
204 }
205+ Button {
206+ text: "Press me"
207+ anchors.centerIn: parent
208+ }
209+
210 leadingActions: ListItemActions {
211 objectName: "InlineLeading"
212 actions: [stock]
213 delegate: Column {
214 width: height + units.gu(2)
215- anchors.verticalCenter: parent.verticalCenter
216 Icon {
217 width: units.gu(3)
218 height: width
219@@ -149,12 +154,13 @@
220 clip: true
221 width: parent.width
222 height: units.gu(20)
223- model: 10
224+ model: 25
225 pressDelay: 0
226 delegate: ListItem {
227 objectName: "ListItem" + index
228 id: listItem
229 onClicked: print(" clicked")
230+ onPressAndHold: print("pressAndHold")
231 leadingActions: leading
232 trailingActions: leadingActions
233 Label {
234
235=== modified file 'tests/unit_x11/tst_components/tst_listitem.qml'
236--- tests/unit_x11/tst_components/tst_listitem.qml 2015-01-16 14:08:06 +0000
237+++ tests/unit_x11/tst_components/tst_listitem.qml 2015-01-22 11:34:38 +0000
238@@ -78,6 +78,7 @@
239 ListItem {
240 id: clickedConnected
241 onClicked: {}
242+ onPressAndHold: {}
243 }
244 ListItem {
245 id: testItem
246@@ -174,6 +175,8 @@
247 highlightedSpy.clear();
248 clickSpy.clear();
249 actionSpy.clear();
250+ pressAndHoldSpy.clear();
251+ buttonSpy.clear();
252 interactiveSpy.clear();
253 listView.interactive = true;
254 // make sure we collapse
255@@ -235,10 +238,12 @@
256 }
257
258 function test_clicked_on_mouse() {
259+ clickSpy.target = testItem;
260 mouseClick(testItem, testItem.width / 2, testItem.height / 2);
261 clickSpy.wait();
262 }
263 function test_clicked_on_tap() {
264+ clickSpy.target = testItem;
265 TestExtras.touchClick(0, testItem, centerOf(testItem));
266 clickSpy.wait();
267 }
268@@ -612,5 +617,60 @@
269 compare(highlightedSpy.count, 0, "Should not be highlighted!");
270 }
271 }
272+
273+ SignalSpy {
274+ id: pressAndHoldSpy
275+ signalName: "pressAndHold"
276+ }
277+ SignalSpy {
278+ id: buttonSpy
279+ signalName: "clicked"
280+ target: button
281+ }
282+ function test_pressandhold_suppress_click() {
283+ var center = centerOf(testItem);
284+ pressAndHoldSpy.target = testItem;
285+ clickSpy.target = testItem;
286+ clickSpy.clear();
287+ mouseLongPress(testItem, center.x, center.y);
288+ mouseRelease(testItem, center.x, center.y);
289+ pressAndHoldSpy.wait();
290+ compare(clickSpy.count, 0, "Click must be suppressed when long pressed");
291+ }
292+
293+ function test_pressandhold_not_emitted_when_swiped() {
294+ var center = centerOf(testItem);
295+ pressAndHoldSpy.target = testItem;
296+ // move mouse slowly from left to right, the swipe threshold is 1.5 GU!!!,
297+ // so any value less than that will emit pressAndHold
298+ mouseMoveSlowly(testItem, center.x, center.y, units.gu(2), 0, 10, 100);
299+ mouseRelease(testItem, center.x + units.gu(1), center.y);
300+ compare(pressAndHoldSpy.count, 0, "pressAndHold should not be emitted!");
301+ // make sure we have collapsed item
302+ rebound(testItem);
303+ }
304+
305+ function test_pressandhold_not_emitted_when_pressed_over_active_component() {
306+ var press = centerOf(button);
307+ pressAndHoldSpy.target = controlItem;
308+ mouseLongPress(button, press.x, press.y);
309+ compare(pressAndHoldSpy.count, 0, "")
310+ mouseRelease(button, press.x, press.y);
311+ }
312+
313+ function test_click_on_button_suppresses_listitem_click() {
314+ buttonSpy.target = button;
315+ clickSpy.target = controlItem;
316+ mouseClick(button, centerOf(button).x, centerOf(button).y);
317+ buttonSpy.wait();
318+ compare(clickSpy.count, 0, "ListItem clicked() must be suppressed");
319+ }
320+
321+ function test_pressandhold_connected_causes_highlight() {
322+ highlightedSpy.target = clickedConnected;
323+ mouseLongPress(clickedConnected, centerOf(clickedConnected).x, centerOf(clickedConnected).y);
324+ highlightedSpy.wait();
325+ mouseRelease(clickedConnected, centerOf(clickedConnected).x, centerOf(clickedConnected).y);
326+ }
327 }
328 }

Subscribers

People subscribed via source and target branches