Merge lp:~zsombi/ubuntu-ui-toolkit/haptics-feedback-singleton into lp:ubuntu-ui-toolkit/rtm
- haptics-feedback-singleton
- Merge into rtm
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Zoltan Balogh | ||||
Approved revision: | 1143 | ||||
Merged at revision: | 1143 | ||||
Proposed branch: | lp:~zsombi/ubuntu-ui-toolkit/haptics-feedback-singleton | ||||
Merge into: | lp:ubuntu-ui-toolkit/rtm | ||||
Prerequisite: | lp:~zsombi/ubuntu-ui-toolkit/other-vibrations | ||||
Diff against target: | 497 lines (+339/-19) 9 files modified components.api (+78/-0) modules/Ubuntu/Components/11/Haptics.qml (+181/-0) modules/Ubuntu/Components/AbstractButton.qml (+6/-12) modules/Ubuntu/Components/plugin/adapters/dbuspropertywatcher_p.cpp (+3/-3) modules/Ubuntu/Components/plugin/ucserviceproperties.cpp (+14/-4) modules/Ubuntu/Components/plugin/ucserviceproperties_p.h (+1/-0) modules/Ubuntu/Components/qmldir (+3/-0) tests/unit/runtest.sh (+1/-0) tests/unit/tst_components/tst_haptics.qml (+52/-0) | ||||
To merge this branch: | bzr merge lp:~zsombi/ubuntu-ui-toolkit/haptics-feedback-singleton | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cris Dywan | Approve | ||
Review via email: |
Commit message
Haptics singleton component to provide toolkit wide default and custom feedback functionaity controlled by system settings.
Description of the change
*** MUST BE LANDED TOGETHER OR AFTER GSETTINGS BRANCH BELOW IS LANDED ***
https:/

Tim Peeters (tpeeters) wrote : | # |

Zsombor Egri (zsombi) wrote : | # |
The Haptics singleton has to be added to 0.1 and 1.0 versions, otherwise apps made with 0.1 and 1.0 will no longer work. At least UITK gallery doesn't load anymore.

Cris Dywan (kalikiana) wrote : | # |
224 + function playCustomEffec
How about making this an optional argument to play(), without the extra function? So no argument would just mean defaults.
153 + onClicked: Haptics.play()
I wonder, should/ can we do anything here to be prepared for the future where a theme may want to use the name of the component playing the effect to change it?
Can we somehow get the name of the component from the function call? Or would we need to pass "Button" everywhere?

Cris Dywan (kalikiana) wrote : | # |
Nice. As discussed, and reflected in the FIXME, this will be supported by theming in a follow-up change.

Zsombor Egri (zsombi) wrote : | # |
> 224 + function playCustomEffec
>
> How about making this an optional argument to play(), without the extra
> function? So no argument would just mean defaults.
Hmm, not bad.
>
> 153 + onClicked: Haptics.play()
>
> I wonder, should/ can we do anything here to be prepared for the future where
> a theme may want to use the name of the component playing the effect to change
> it?
>
> Can we somehow get the name of the component from the function call? Or would
> we need to pass "Button" everywhere?
As discussed, we should move this into teh style and have styleHint driving it.

Cris Dywan (kalikiana) wrote : | # |
A way to overcome the testing dependency on the real service:
- 1141. By Zsombor Egri
-
rtm merge
- 1142. By Zsombor Egri
-
small typo fix
- 1143. By Zsombor Egri
-
suppress ServiceProperties element warnings if SUPPRESS_
SERVICEPROPERTI ES_WARNINGS is set to '1' or 'yes' - 1144. By Zsombor Egri
-
RTM sync
- 1145. By Zsombor Egri
-
prereq merge
- 1146. By Zsombor Egri
-
guard crashing if ServiceProperties cannot connect to the DBus on CI
- 1147. By Zsombor Egri
-
no need to wait for service readyness which is behind the scene
- 1148. By Zsombor Egri
-
initialize Haptics singleton early enough so its settings are synched when the singleton is invoked
Preview Diff
1 | === modified file 'components.api' |
2 | --- components.api 2015-02-09 12:55:39 +0000 |
3 | +++ components.api 2015-02-09 12:55:39 +0000 |
4 | @@ -62,6 +62,11 @@ |
5 | property string fadeStyle |
6 | readonly property bool running |
7 | readonly property int status |
8 | +Haptics 0.1 1.0 |
9 | +Object |
10 | + readonly property bool enabled |
11 | + property HapticsEffect effect |
12 | + function play(customEffect) |
13 | Header 0.1 1.0 |
14 | AppHeader |
15 | property string _for_autopilot |
16 | @@ -701,6 +706,64 @@ |
17 | name: "QAbstractProxyModel" |
18 | prototype: "QAbstractItemModel" |
19 | Property { name: "sourceModel"; type: "QAbstractItemModel"; isPointer: true } |
20 | + name: "QDeclarativeFeedbackActuator" |
21 | + prototype: "QObject" |
22 | + exports: ["QtFeedback/Actuator 5.0"] |
23 | + name: "Capability" |
24 | + name: "State" |
25 | + Property { name: "actuatorId"; type: "int"; isReadonly: true } |
26 | + Property { name: "name"; type: "string"; isReadonly: true } |
27 | + Property { name: "state"; type: "State"; isReadonly: true } |
28 | + Property { name: "valid"; type: "bool"; isReadonly: true } |
29 | + Property { name: "enabled"; type: "bool" } |
30 | + Method { |
31 | + name: "isCapabilitySupported" |
32 | + Parameter { name: "capability"; type: "Capability" } |
33 | + name: "QDeclarativeFeedbackEffect" |
34 | + prototype: "QObject" |
35 | + exports: ["QtFeedback/Feedback 5.0", "QtFeedback/FeedbackEffect 5.0"] |
36 | + name: "Duration" |
37 | + name: "State" |
38 | + name: "ErrorType" |
39 | + Property { name: "running"; type: "bool" } |
40 | + Property { name: "paused"; type: "bool" } |
41 | + Property { name: "duration"; type: "int" } |
42 | + Property { name: "state"; type: "State" } |
43 | + Property { name: "error"; type: "ErrorType"; isReadonly: true } |
44 | + Method { name: "updateState" } |
45 | + Method { name: "start" } |
46 | + Method { name: "stop" } |
47 | + Method { name: "pause" } |
48 | + name: "QDeclarativeFileEffect" |
49 | + prototype: "QDeclarativeFeedbackEffect" |
50 | + exports: ["QtFeedback/FileEffect 5.0"] |
51 | + Property { name: "loaded"; type: "bool" } |
52 | + Property { name: "source"; type: "QUrl" } |
53 | + Property { name: "supportedMimeTypes"; type: "QStringList"; isReadonly: true } |
54 | + Method { name: "load" } |
55 | + Method { name: "unload" } |
56 | + name: "QDeclarativeHapticsEffect" |
57 | + prototype: "QDeclarativeFeedbackEffect" |
58 | + exports: ["QtFeedback/HapticsEffect 5.0"] |
59 | + Property { |
60 | + name: "availableActuators" |
61 | + Property { name: "intensity"; type: "double" } |
62 | + Property { name: "attackTime"; type: "int" } |
63 | + Property { name: "attackIntensity"; type: "double" } |
64 | + Property { name: "fadeTime"; type: "int" } |
65 | + Property { name: "fadeIntensity"; type: "double" } |
66 | + Property { name: "period"; type: "int" } |
67 | + Property { name: "actuator"; type: "QDeclarativeFeedbackActuator"; isPointer: true } |
68 | + name: "QDeclarativeThemeEffect" |
69 | + prototype: "QObject" |
70 | + exports: ["QtFeedback/EffectPlayer 5.0", "QtFeedback/ThemeEffect 5.0"] |
71 | + name: "Effect" |
72 | + Property { name: "supported"; type: "bool"; isReadonly: true } |
73 | + Property { name: "effect"; type: "Effect" } |
74 | + Method { name: "play" } |
75 | + Method { |
76 | + name: "play" |
77 | + Parameter { name: "effect"; type: "Effect" } |
78 | name: "QSortFilterProxyModel" |
79 | prototype: "QAbstractProxyModel" |
80 | Property { name: "filterRegExp"; type: "QRegExp" } |
81 | @@ -995,6 +1058,21 @@ |
82 | Parameter { name: "singular"; type: "string" } |
83 | Parameter { name: "plural"; type: "string" } |
84 | Parameter { name: "n"; type: "int" } |
85 | + prototype: "QObject" |
86 | + name: "Haptics" |
87 | + exports: ["Haptics -1.-1"] |
88 | + Property { name: "enabled"; type: "bool"; isReadonly: true } |
89 | + Property { name: "effect"; type: "QDeclarativeHapticsEffect"; isReadonly: true; isPointer: true } |
90 | + Method { |
91 | + name: "play" |
92 | + Parameter { name: "customEffect"; type: "QVariant" } |
93 | + Property { name: "__defaultPropertyFix"; type: "QObject"; isList: true; isReadonly: true } |
94 | + Property { name: "children"; type: "QObject"; isList: true; isReadonly: true } |
95 | + prototype: "QObject" |
96 | + name: "Object" |
97 | + exports: ["Object -1.-1"] |
98 | + Property { name: "__defaultPropertyFix"; type: "QObject"; isList: true; isReadonly: true } |
99 | + Property { name: "children"; type: "QObject"; isList: true; isReadonly: true } |
100 | name: "ULConditionalLayout" |
101 | prototype: "QObject" |
102 | exports: ["ConditionalLayout 0.1", "ConditionalLayout 1.0"] |
103 | |
104 | === added file 'modules/Ubuntu/Components/11/Haptics.qml' |
105 | --- modules/Ubuntu/Components/11/Haptics.qml 1970-01-01 00:00:00 +0000 |
106 | +++ modules/Ubuntu/Components/11/Haptics.qml 2015-02-09 12:55:39 +0000 |
107 | @@ -0,0 +1,181 @@ |
108 | +/* |
109 | + * Copyright 2014 Canonical Ltd. |
110 | + * |
111 | + * This program is free software; you can redistribute it and/or modify |
112 | + * it under the terms of the GNU Lesser General Public License as published by |
113 | + * the Free Software Foundation; version 3. |
114 | + * |
115 | + * This program is distributed in the hope that it will be useful, |
116 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
117 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
118 | + * GNU Lesser General Public License for more details. |
119 | + * |
120 | + * You should have received a copy of the GNU Lesser General Public License |
121 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
122 | + */ |
123 | + |
124 | +pragma Singleton |
125 | +import QtQuick 2.0 |
126 | +import QtFeedback 5.0 |
127 | +import Ubuntu.Components 1.1 |
128 | + |
129 | +/*! |
130 | + \qmltype Haptics |
131 | + \inqmlmodule Ubuntu.Components 1.1 |
132 | + \ingroup ubuntu-services |
133 | + \brief Singleton defining the haptics feedback used in components, where execution |
134 | + of the feedback is controlled by the system settings. |
135 | + |
136 | + Supports global feedback as well as custom feedback. Global feedback can be |
137 | + configured through its properties, and \l play function will play the default |
138 | + configuration, or a custom one if parameter is given. |
139 | + |
140 | + Example of using Haptics: |
141 | + \qml |
142 | + import QtQuick 2.3 |
143 | + import Ubuntu.Components 1.1 |
144 | + |
145 | + Item { |
146 | + implicitWidth: units.gu(20) |
147 | + implicitHeight: units.gu(5) |
148 | + |
149 | + Label { |
150 | + text: "Press me" |
151 | + anchors.fill: parent |
152 | + horizontalAlignment: Text.AlignHCenter |
153 | + verticalAlignment: Text.AlignVCenter |
154 | + } |
155 | + MouseArea { |
156 | + anchors.fill: parent |
157 | + onClicked: Haptics.play() |
158 | + } |
159 | + } |
160 | + \endqml |
161 | + |
162 | + Custom effects can be played as follows: |
163 | + \qml |
164 | + import QtQuick 2.3 |
165 | + import Ubuntu.Components 1.1 |
166 | + |
167 | + Item { |
168 | + implicitWidth: units.gu(20) |
169 | + implicitHeight: units.gu(5) |
170 | + |
171 | + Label { |
172 | + text: "Press me" |
173 | + anchors.fill: parent |
174 | + horizontalAlignment: Text.AlignHCenter |
175 | + verticalAlignment: Text.AlignVCenter |
176 | + } |
177 | + MouseArea { |
178 | + anchors.fill: parent |
179 | + onClicked: Haptics.play({duration: 25, attackIntensity: 0.7}) |
180 | + } |
181 | + } |
182 | + \endqml |
183 | + |
184 | + \note Though the \l effect property exposes \c start, \c stop and \c pause |
185 | + functions, use those only if you want to have feedback independent on what the |
186 | + system setting is. |
187 | + */ |
188 | +Object { |
189 | + |
190 | + /*! |
191 | + \qmlproperty bool enabled |
192 | + \readonly |
193 | + The property specifies whether the haptics feedback is enabled or not by the system. |
194 | + */ |
195 | + readonly property alias enabled: vibra.otherVibrate |
196 | + |
197 | + /*! |
198 | + \qmlproperty HapticsEffect effect |
199 | + The property defines the settings of the haptics effect used by the component. |
200 | + The default setting is a haptics effect with a duration of 10 milliseconds |
201 | + with an intensity of 1.0, having fading time of 50 millisecods and fading |
202 | + intensity 0.0, and attack time of 50 milliseconds and with an intensity of |
203 | + 0.0. |
204 | + */ |
205 | + property alias effect: effect |
206 | + |
207 | + /*! |
208 | + \qmlmethod play([customEffect]) |
209 | + The function plays the feedback with the configuration specified in \l effect |
210 | + if no parameter is given. Custom effect can be played by specifying the effect |
211 | + properties in a JSON object in \c customEffect. |
212 | + |
213 | + The function will exit unconditionaly if playing the effects is blocked by |
214 | + system settings. |
215 | + |
216 | + The function will not stop any ongoing haptics effect played, if that one |
217 | + was a default haptics effect. In case of custom effects, the previous effect |
218 | + will be stopped, and settings will be restored before the new haptics will |
219 | + be played. The custom settings properties (the ones which are required to |
220 | + be different from the ones defined in the \l effect) must be specified in |
221 | + the parameter in a JSON object. |
222 | + */ |
223 | + function play(customEffect) { |
224 | + if (!vibra.otherVibrate) { |
225 | + return; |
226 | + } |
227 | + if (effectData.data) { |
228 | + // we have a custom effect playing, stop it |
229 | + effect.stop(); |
230 | + } |
231 | + if (effect.running) { |
232 | + // this is a global effect, leave |
233 | + return; |
234 | + } |
235 | + if (customEffect) { |
236 | + effectData.backup(customEffect); |
237 | + } |
238 | + effect.start(); |
239 | + } |
240 | + |
241 | + QtObject { |
242 | + id: effectData |
243 | + property var data |
244 | + |
245 | + function backup(customEffect) { |
246 | + data = customEffect; |
247 | + for (var p in data) { |
248 | + var value = data[p]; |
249 | + data[p] = effect[p]; |
250 | + effect[p] = value; |
251 | + } |
252 | + } |
253 | + function restore() { |
254 | + for (var p in data) { |
255 | + effect[p] = data[p]; |
256 | + } |
257 | + data = undefined; |
258 | + } |
259 | + } |
260 | + |
261 | + // local feedback component used to play feedback |
262 | + HapticsEffect { |
263 | + id: effect |
264 | + attackIntensity: 0.0 |
265 | + attackTime: 50 |
266 | + intensity: 1.0 |
267 | + duration: 10 |
268 | + fadeTime: 50 |
269 | + fadeIntensity: 0.0 |
270 | + |
271 | + onStateChanged: { |
272 | + if (state == HapticsEffect.Stopped) { |
273 | + effectData.restore(); |
274 | + } |
275 | + } |
276 | + } |
277 | + |
278 | + // watch system settings for otherVibrate |
279 | + ServiceProperties { |
280 | + objectName: "system_effect_settings" |
281 | + id: vibra |
282 | + service: "org.freedesktop.Accounts" |
283 | + serviceInterface: "org.freedesktop.Accounts" |
284 | + path: "/org/freedesktop/Accounts" |
285 | + adaptorInterface: "com.ubuntu.touch.AccountsService.Sound" |
286 | + property bool otherVibrate: true |
287 | + } |
288 | +} |
289 | |
290 | === modified file 'modules/Ubuntu/Components/AbstractButton.qml' |
291 | --- modules/Ubuntu/Components/AbstractButton.qml 2015-02-09 12:55:39 +0000 |
292 | +++ modules/Ubuntu/Components/AbstractButton.qml 2015-02-09 12:55:39 +0000 |
293 | @@ -15,7 +15,6 @@ |
294 | */ |
295 | |
296 | import QtQuick 2.0 |
297 | -import QtFeedback 5.0 |
298 | import Ubuntu.Components 1.1 |
299 | |
300 | /*! |
301 | @@ -85,16 +84,6 @@ |
302 | |
303 | activeFocusOnPress: true |
304 | |
305 | - HapticsEffect { |
306 | - id: pressEffect |
307 | - attackIntensity: 0.0 |
308 | - attackTime: 50 |
309 | - intensity: 1.0 |
310 | - duration: 10 |
311 | - fadeTime: 50 |
312 | - fadeIntensity: 0.0 |
313 | - } |
314 | - |
315 | MouseArea { |
316 | id: mouseArea |
317 | anchors.fill: parent |
318 | @@ -102,9 +91,14 @@ |
319 | // as it might occlude the newly assigned mouse area. |
320 | hoverEnabled: true |
321 | |
322 | + // invoke Haptics singleton earlier than we press the button, |
323 | + // so we give some time for the singleton to sync settings with the service |
324 | + property bool hapticsEnabled: Haptics.enabled |
325 | + |
326 | onClicked: { |
327 | if (button.__acceptEvents) { |
328 | - pressEffect.start(); |
329 | + // FIXME (Vivid) call this in the style rather than from AbstractButton |
330 | + Haptics.play(); |
331 | button.clicked() |
332 | } |
333 | } |
334 | |
335 | === modified file 'modules/Ubuntu/Components/plugin/adapters/dbuspropertywatcher_p.cpp' |
336 | --- modules/Ubuntu/Components/plugin/adapters/dbuspropertywatcher_p.cpp 2015-02-09 12:55:39 +0000 |
337 | +++ modules/Ubuntu/Components/plugin/adapters/dbuspropertywatcher_p.cpp 2015-02-09 12:55:39 +0000 |
338 | @@ -133,13 +133,13 @@ |
339 | if (!readIFace.isValid()) { |
340 | // report invalid interface only if the property's first letter was with capital one! |
341 | if (property[0].isUpper()) { |
342 | - qmlInfo(q) << readIFace.lastError().message(); |
343 | + warning(readIFace.lastError().message()); |
344 | } |
345 | return false; |
346 | } |
347 | QDBusPendingCall pending = readIFace.asyncCall("Get", adaptor, property); |
348 | if (pending.isError()) { |
349 | - qmlInfo(q) << pending.error().message(); |
350 | + warning(pending.error().message()); |
351 | return false; |
352 | } |
353 | QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(pending, q); |
354 | @@ -182,7 +182,7 @@ |
355 | properties.removeAll(property); |
356 | if (property[0].isUpper()) { |
357 | // report error! |
358 | - qmlInfo(q) << reply.error().message(); |
359 | + warning(reply.error().message()); |
360 | } |
361 | } else { |
362 | // update watched property value |
363 | |
364 | === modified file 'modules/Ubuntu/Components/plugin/ucserviceproperties.cpp' |
365 | --- modules/Ubuntu/Components/plugin/ucserviceproperties.cpp 2015-02-09 12:55:39 +0000 |
366 | +++ modules/Ubuntu/Components/plugin/ucserviceproperties.cpp 2015-02-09 12:55:39 +0000 |
367 | @@ -39,6 +39,15 @@ |
368 | return service->d_func(); |
369 | } |
370 | |
371 | +void UCServicePropertiesPrivate::warning(const QString &message) |
372 | +{ |
373 | + QByteArray suppressWarnings = qgetenv("SUPPRESS_SERVICEPROPERTIES_WARNINGS"); |
374 | + if ((suppressWarnings == "yes") || (suppressWarnings == "1")) { |
375 | + return; |
376 | + } |
377 | + qmlInfo(q_ptr) << message; |
378 | +} |
379 | + |
380 | void UCServicePropertiesPrivate::setError(const QString &msg) |
381 | { |
382 | if (error == msg) { |
383 | @@ -59,7 +68,8 @@ |
384 | |
385 | void printLocked(UCServiceProperties *owner) |
386 | { |
387 | - qmlInfo(owner) << UbuntuI18n::instance().tr("Changing connection parameters forbidden."); |
388 | + UCServicePropertiesPrivate::get(owner)-> |
389 | + warning(UbuntuI18n::instance().tr("Changing connection parameters forbidden.")); |
390 | } |
391 | |
392 | /*! |
393 | @@ -141,9 +151,9 @@ |
394 | // check the binding on the property and warn if there is one. |
395 | QQmlProperty qmlProperty(this, property); |
396 | if (QQmlPropertyPrivate::binding(qmlProperty)) { |
397 | - qmlInfo(this) << UbuntuI18n::instance(). |
398 | - tr("Binding detected on property '%1' will be removed by the service updates."). |
399 | - arg(property); |
400 | + d->warning(UbuntuI18n::instance(). |
401 | + tr("Binding detected on property '%1' will be removed by the service updates."). |
402 | + arg(property)); |
403 | } |
404 | // insert both the declared and capitalized first character properties |
405 | d->properties << property; |
406 | |
407 | === modified file 'modules/Ubuntu/Components/plugin/ucserviceproperties_p.h' |
408 | --- modules/Ubuntu/Components/plugin/ucserviceproperties_p.h 2015-02-09 12:55:39 +0000 |
409 | +++ modules/Ubuntu/Components/plugin/ucserviceproperties_p.h 2015-02-09 12:55:39 +0000 |
410 | @@ -27,6 +27,7 @@ |
411 | virtual ~UCServicePropertiesPrivate(); |
412 | |
413 | static UCServicePropertiesPrivate *get(UCServiceProperties *service); |
414 | + void warning(const QString &message); |
415 | void setError(const QString &msg); |
416 | void setStatus(UCServiceProperties::Status status); |
417 | |
418 | |
419 | === modified file 'modules/Ubuntu/Components/qmldir' |
420 | --- modules/Ubuntu/Components/qmldir 2014-09-07 16:42:47 +0000 |
421 | +++ modules/Ubuntu/Components/qmldir 2015-02-09 12:55:39 +0000 |
422 | @@ -104,3 +104,6 @@ |
423 | Icon 1.1 Icon11.qml |
424 | StyledItem 1.1 StyledItem.qml |
425 | singleton UbuntuColors 1.1 11/UbuntuColors.qml |
426 | + |
427 | +singleton Haptics 0.1 11/Haptics.qml |
428 | +singleton Haptics 1.0 11/Haptics.qml |
429 | |
430 | === modified file 'tests/unit/runtest.sh' |
431 | --- tests/unit/runtest.sh 2015-02-09 12:55:39 +0000 |
432 | +++ tests/unit/runtest.sh 2015-02-09 12:55:39 +0000 |
433 | @@ -46,6 +46,7 @@ |
434 | # https://bugreports.qt-project.org/browse/QTBUG-36243 |
435 | QML2_IMPORT_PATH=../../../modules:$QML2_IMPORT_PATH UBUNTU_UI_TOOLKIT_THEMES_PATH=../../../modules \ |
436 | ALARM_BACKEND=memory \ |
437 | + SUPPRESS_SERVICEPROPERTIES_WARNINGS=yes \ |
438 | $_CMD $_ARGS 2>&1 | grep -v 'QFontDatabase: Cannot find font directory' |
439 | # Note: Get first command before the pipe, $? would be ambiguous |
440 | RESULT=${PIPESTATUS[0]} |
441 | |
442 | === added file 'tests/unit/tst_components/tst_haptics.qml' |
443 | --- tests/unit/tst_components/tst_haptics.qml 1970-01-01 00:00:00 +0000 |
444 | +++ tests/unit/tst_components/tst_haptics.qml 2015-02-09 12:55:39 +0000 |
445 | @@ -0,0 +1,52 @@ |
446 | +/* |
447 | + * Copyright 2014 Canonical Ltd. |
448 | + * |
449 | + * This program is free software; you can redistribute it and/or modify |
450 | + * it under the terms of the GNU Lesser General Public License as published by |
451 | + * the Free Software Foundation; version 3. |
452 | + * |
453 | + * This program is distributed in the hope that it will be useful, |
454 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
455 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
456 | + * GNU Lesser General Public License for more details. |
457 | + * |
458 | + * You should have received a copy of the GNU Lesser General Public License |
459 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
460 | + */ |
461 | + |
462 | +import QtQuick 2.3 |
463 | +import QtTest 1.0 |
464 | +import Ubuntu.Components 1.1 |
465 | +import Ubuntu.Test 1.0 |
466 | +import QtFeedback 5.0 |
467 | + |
468 | +UbuntuTestCase { |
469 | + name: "HapticsAPI" |
470 | + |
471 | + function waitForHapticsCompleted() { |
472 | + tryCompareFunction(function() { return Haptics.effect.state; }, HapticsEffect.Stopped, 1000); |
473 | + } |
474 | + |
475 | + function test_0_defaults() { |
476 | + verify(Haptics.hasOwnProperty("enabled"), "missing property 'enabled'"); |
477 | + verify(Haptics.hasOwnProperty("effect"), "missing property 'effect'"); |
478 | + verify(Haptics.hasOwnProperty("play"), "missing function 'play'"); |
479 | + } |
480 | + |
481 | + function test_play() { |
482 | + Haptics.play(); |
483 | + if (Haptics.enabled) { |
484 | + waitForHapticsCompleted(); |
485 | + } |
486 | + } |
487 | + |
488 | + function test_custom_play() { |
489 | + Haptics.play({attackTime: 10, attackIntensity: 0.5, duration: 1200}); |
490 | + if (Haptics.enabled && Haptics.effect.running) { |
491 | + compare(Haptics.effect.attackTime, 10, "attack time not modified"); |
492 | + compare(Haptics.effect.attackIntensity, 0.5, "attack intensity not modified"); |
493 | + compare(Haptics.effect.duration, 400, "duration not modified"); |
494 | + waitForHapticsCompleted(); |
495 | + } |
496 | + } |
497 | +} |
why do we have so much stuff added to components.api here? Only Haptics should be added.