Merge lp:~unity-team/unity8/action_preview_widget into lp:unity8

Proposed by Michał Sawicz
Status: Merged
Approved by: Michał Sawicz
Approved revision: no longer in the source branch.
Merged at revision: 693
Proposed branch: lp:~unity-team/unity8/action_preview_widget
Merge into: lp:unity8
Prerequisite: lp:~aacid/unity8/image_gallery_preview_widget
Diff against target: 487 lines (+344/-25)
8 files modified
qml/Dash/Previews/PreviewActionButton.qml (+30/-0)
qml/Dash/Previews/PreviewActionCombo.qml (+66/-0)
qml/Dash/Previews/PreviewActions.qml (+64/-0)
qml/Dash/Previews/PreviewAudioPlayback.qml (+22/-23)
qml/Dash/Previews/PreviewWidget.qml (+12/-2)
tests/qmltests/CMakeLists.txt (+1/-0)
tests/qmltests/Dash/Previews/tst_PreviewActions.qml (+148/-0)
tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml (+1/-0)
To merge this branch: bzr merge lp:~unity-team/unity8/action_preview_widget
Reviewer Review Type Date Requested Status
Michał Sawicz Approve
PS Jenkins bot continuous-integration Pending
Review via email: mp+205232@code.launchpad.net

This proposal supersedes a proposal from 2014-02-05.

Commit message

Actions Preview Widget

Description of the change

 * Are there any related MPs required for this MP to build/function as expected?
It's listed in the prerequisite field

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes, the tests work, it's not hooked into the rest of the app yet

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A

 * If you changed the UI, has there been a design review?
No, it's not hooked into the rest of the app yet, will get a whole review when we do that.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:680
http://jenkins.qa.ubuntu.com/job/unity8-ci/2245/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/2950
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/2686
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/1116
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/767
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/769
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/769/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/767
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/2589
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/2952
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/2952/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/2687
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/2687/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/5111
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/3682

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/2245/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal

27 + property var data: null

33 + onClicked: triggeredAction(data)

164 + root.triggered(root.widgetId, data.id, data);

306 + compare(spy.signalArguments[0][2], target.widgetData["actions"][buttonNumber]);

Those actions should not submit any data. Only actions triggered by data-generating widgets (rating-input, progress) will actually send any data.

Can we override the clicked() signal to send just the action id?

=====

62 + width: childrenRect.width
63 + height: childrenRect.height

I've a feeling this should be implicitWidth, but the buttons should be divided in two if the widget is wider.

Remember a single button should be right-aligned, too.

=====

81 + id: c

More name, please.

=====

92 + delegate: Button {

Why not PreviewActionButton?

=====

77 + width: c.maxWidth

82 + property real maxWidth: -1

98 + width: implicitWidth < parent.width ? parent.width : implicitWidth

100 + Component.onCompleted: {
101 + c.maxWidth = Math.max(c.maxWidth, implicitWidth);
102 + }

I don't think that's necessary, see above about widths.

=====

83 + anchors.top: moreButton.bottom
84 + anchors.topMargin: spacing

Compress into { } please.

=====

84 + anchors.topMargin: spacing

86 + spacing: height > 0 ? units.gu(1) : 0

Shouldn't the topMargin have that condition instead?

=====

97 + height: moreButton.expanded ? implicitHeight : 0

99 + visible: height > 0

Shouldn't that be on the Column instead?

=====

Animate the Column height please.

=====

142 + width: childrenRect.width

Should be parent-driven.

=====

144 + readonly property var actions: root.widgetData ? root.widgetData["actions"] : null

Move lower in the hierarchy, please, so it's not exposed.

=====

158 + item.model = actions.slice(1)

Smart! ++; please.

=====

174 +

--\n, please.

=====

185 + //! The id of the widget

ETOOMANYTHES, "The widget identifier"?

=====

301 + spy.clear();

→ cleanup()?

=====

303 + compare(spy.count, 1);

spy.wait();

review: Needs Fixing
Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 27 + property var data: null
>
> 33 + onClicked: triggeredAction(data)
>
> 164 + root.triggered(root.widgetId, data.id, data);
>
> 306 + compare(spy.signalArguments[0][2],
> target.widgetData["actions"][buttonNumber]);
>
> Those actions should not submit any data. Only actions triggered by data-
> generating widgets (rating-input, progress) will actually send any data.

Done

> Can we override the clicked() signal to send just the action id?

No, it complains about duplicate signals

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> =====
>
> 81 + id: c
>
> More name, please.

done

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 92 + delegate: Button {
>
> Why not PreviewActionButton?

Done.

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 158 + item.model = actions.slice(1)
>
> Smart! ++; please.

Done

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

>
>
> 174 +
>
> --\n, please.

Really? Done

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> =====
>
> 185 + //! The id of the widget
>
> ETOOMANYTHES, "The widget identifier"?

Done.

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 301 + spy.clear();
>
> → cleanup()?

Object SignalSpy_QMLTYPE_3(0x15abe60) has no method 'cleanup'

So no :D

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 303 + compare(spy.count, 1);
>
> spy.wait();

Why? It should trigger immediately and only once, spy.wait() seems a worse check than spy.count == 1

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 144 + readonly property var actions: root.widgetData ?
> root.widgetData["actions"] : null
>
> Move lower in the hierarchy, please, so it's not exposed.

Done

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 62 + width: childrenRect.width
> 63 + height: childrenRect.height
>
> I've a feeling this should be implicitWidth, but the buttons should be divided
> in two if the widget is wider.
>
> Remember a single button should be right-aligned, too.

I made it implicitWidth and right-aligned the buttons.

I did not understand the "buttons should be divided in two if the widget is wider" part.

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 77 + width: c.maxWidth
>
> 82 + property real maxWidth: -1
>
> 98 + width: implicitWidth < parent.width ? parent.width : implicitWidth
>
> 100 + Component.onCompleted: {
> 101 + c.maxWidth = Math.max(c.maxWidth, implicitWidth);
> 102 + }
>
> I don't think that's necessary, see above about widths.

Well, this makes sure all the buttons in the "combo button column" have the same width, otherwise the thing looked ultra ugly to me. Why do you think it's not necessary?

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

>
> 84 + anchors.topMargin: spacing
>
> 86 + spacing: height > 0 ? units.gu(1) : 0
>
> Shouldn't the topMargin have that condition instead?

Makes sense, done.

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> 83 + anchors.top: moreButton.bottom
> 84 + anchors.topMargin: spacing
>
> Compress into { } please.

Done

Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

> =====
>
> 97 + height: moreButton.expanded ? implicitHeight : 0
>
> 99 + visible: height > 0
>
> Shouldn't that be on the Column instead?
>
> =====
>
> Animate the Column height please.
>

Done both, it was part of a failed animation experiment from yesterday after another one failed and another one failed (yeah it was late on the day :D)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:686
http://jenkins.qa.ubuntu.com/job/unity8-ci/2249/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/2959
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/2693
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/1120
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/771
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/773
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/773/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/771
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/2598
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/2961
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/2961/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/2694
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/2694/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/5118
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/3692

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/2249/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal

74 + gradient: UbuntuColors.orangeGradient

No gradient, please - use color: Theme.palette.selected.foreground

=====

76 + width: parent.width

86 + width: parent.width

I'd use anchors, but your call.

=====

129 +/*! This preview widget shows a either one button, two buttons or one button

"shows either"

=====

137 + implicitHeight: row.height
138 + implicitWidth: row.width

Please make it height:, and drop the implicitWidth I think?

=====

158 + item.width = Qt.binding(function() { return (root.width - units.gu(1)) / 2; });

Just make Loader.width ↑, the loaded item will be sized to that.

review: Needs Fixing
Revision history for this message
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

Done everything expect the "width: parent.width" -> anchors thing. If you want that it'll have to wait until tomorrow, i have to run now :D

Revision history for this message
Michał Sawicz (saviq) wrote :

Only a merge on top of the superseded proposal.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:693
http://jenkins.qa.ubuntu.com/job/unity8-ci/2251/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/2966
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/2700
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/1122
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/773
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/775
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/775/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/773
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/2605
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/2968
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/2968/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/2701
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/2701/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/5124
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/3700

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/2251/rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'qml/Dash/Previews/PreviewActionButton.qml'
2--- qml/Dash/Previews/PreviewActionButton.qml 1970-01-01 00:00:00 +0000
3+++ qml/Dash/Previews/PreviewActionButton.qml 2014-02-06 18:10:34 +0000
4@@ -0,0 +1,30 @@
5+/*
6+ * Copyright (C) 2014 Canonical, Ltd.
7+ *
8+ * This program is free software; you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License as published by
10+ * the Free Software Foundation; version 3.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ */
20+
21+import QtQuick 2.0
22+import Ubuntu.Components 0.1
23+
24+Button {
25+ signal triggeredAction(string id)
26+
27+ property var data: null
28+ objectName: "button" + (data && data.id || "")
29+ color: Theme.palette.selected.foreground
30+ text: data && data.label || ""
31+ iconSource: data && data.icon || ""
32+ iconPosition: "left"
33+ onClicked: triggeredAction(data.id)
34+}
35
36=== added file 'qml/Dash/Previews/PreviewActionCombo.qml'
37--- qml/Dash/Previews/PreviewActionCombo.qml 1970-01-01 00:00:00 +0000
38+++ qml/Dash/Previews/PreviewActionCombo.qml 2014-02-06 18:10:34 +0000
39@@ -0,0 +1,66 @@
40+/*
41+ * Copyright (C) 2014 Canonical, Ltd.
42+ *
43+ * This program is free software; you can redistribute it and/or modify
44+ * it under the terms of the GNU General Public License as published by
45+ * the Free Software Foundation; version 3.
46+ *
47+ * This program is distributed in the hope that it will be useful,
48+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
49+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50+ * GNU General Public License for more details.
51+ *
52+ * You should have received a copy of the GNU General Public License
53+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
54+ */
55+
56+import QtQuick 2.0
57+import Ubuntu.Components 0.1
58+
59+Item {
60+ id: root
61+
62+ implicitHeight: childrenRect.height
63+
64+ signal triggeredAction(string id)
65+
66+ property alias model: actionRepeater.model
67+
68+ Button {
69+ id: moreButton
70+ property bool expanded: false
71+
72+ objectName: "moreLessButton"
73+ text: !expanded ? i18n.tr("More...") : i18n.tr("Less...")
74+ color: Theme.palette.selected.foreground
75+ onClicked: expanded = !expanded
76+ width: parent.width
77+ }
78+
79+ Column {
80+ anchors {
81+ top: moreButton.bottom
82+ topMargin: height > 0 ? spacing : 0
83+ }
84+ objectName: "buttonColumn"
85+ spacing: units.gu(1)
86+ width: parent.width
87+ height: moreButton.expanded ? implicitHeight : 0
88+ clip: true
89+ Behavior on height {
90+ UbuntuNumberAnimation {
91+ duration: UbuntuAnimation.SnapDuration
92+ }
93+ }
94+
95+ Repeater {
96+ id: actionRepeater
97+
98+ delegate: PreviewActionButton {
99+ data: modelData
100+ width: implicitWidth < parent.width ? parent.width : implicitWidth
101+ onClicked: root.triggeredAction(modelData.id)
102+ }
103+ }
104+ }
105+}
106
107=== added file 'qml/Dash/Previews/PreviewActions.qml'
108--- qml/Dash/Previews/PreviewActions.qml 1970-01-01 00:00:00 +0000
109+++ qml/Dash/Previews/PreviewActions.qml 2014-02-06 18:10:34 +0000
110@@ -0,0 +1,64 @@
111+/*
112+ * Copyright (C) 2014 Canonical, Ltd.
113+ *
114+ * This program is free software; you can redistribute it and/or modify
115+ * it under the terms of the GNU General Public License as published by
116+ * the Free Software Foundation; version 3.
117+ *
118+ * This program is distributed in the hope that it will be useful,
119+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
120+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
121+ * GNU General Public License for more details.
122+ *
123+ * You should have received a copy of the GNU General Public License
124+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
125+ */
126+
127+import QtQuick 2.1
128+
129+/*! This preview widget shows either one button, two buttons or one button
130+ * and a combo button depending on the number of items in widgetData["actions"].
131+ * For each of the items we recognize the fields "label", "icon" and "id".
132+ */
133+
134+PreviewWidget {
135+ id: root
136+
137+ height: row.height
138+
139+ Row {
140+ id: row
141+ readonly property var actions: root.widgetData ? root.widgetData["actions"] : null
142+ anchors.right: parent.right
143+
144+ spacing: units.gu(1)
145+
146+ Loader {
147+ id: loader
148+ readonly property bool button: row.actions && row.actions.length == 2
149+ readonly property bool combo: row.actions && row.actions.length > 2
150+ source: button ? "PreviewActionButton.qml" : (combo ? "PreviewActionCombo.qml" : "")
151+ width: (root.width - units.gu(1)) / 2
152+ onLoaded: {
153+ if (button) {
154+ item.data = row.actions[1];
155+ } else if (combo) {
156+ item.model = row.actions.slice(1);
157+ }
158+ }
159+ Connections {
160+ target: loader.item
161+ onTriggeredAction: {
162+ root.triggered(root.widgetId, id, null);
163+ }
164+ }
165+ }
166+
167+ PreviewActionButton {
168+ data: visible ? row.actions[0] : null
169+ visible: row.actions && row.actions.length > 0
170+ onTriggeredAction: root.triggered(root.widgetId, id, null)
171+ width: (root.width - units.gu(1)) / 2
172+ }
173+ }
174+}
175
176=== modified file 'qml/Dash/Previews/PreviewAudioPlayback.qml'
177--- qml/Dash/Previews/PreviewAudioPlayback.qml 2014-02-06 18:10:33 +0000
178+++ qml/Dash/Previews/PreviewAudioPlayback.qml 2014-02-06 18:10:34 +0000
179@@ -17,7 +17,6 @@
180 import QtQuick 2.0
181 import QtMultimedia 5.0
182 import Ubuntu.Components 0.1
183-import Ubuntu.Components.ListItems 0.1
184
185 /*! \brief Preview widget for audio tracks.
186
187@@ -35,7 +34,7 @@
188
189 PreviewWidget {
190 id: root
191- implicitHeight: childrenRect.height
192+ height: childrenRect.height
193
194 onIsCurrentPreviewChanged: if (!isCurrentPreview) audio.stop()
195
196@@ -47,24 +46,24 @@
197 property Item playingItem
198
199 Component.onDestruction: {
200- // destructing the component doesn't automatically send stop to the media service, probably a bug in QtMultimedia
201+ // destroying the component doesn't automatically send stop to the media service, probably a bug in QtMultimedia
202 audio.stop();
203 }
204
205 onErrorStringChanged: console.warn("Audio player error:", errorString)
206
207 function lengthToString(s) {
208- if (s <= 0 || s === undefined) return ""
209+ if (typeof(s) !== "number" || s <= 0) return "";
210
211- var sec = "" + s % 60
212- if (sec.length == 1) sec = "0" + sec
213- var hour = Math.floor(s / 3600)
214+ var sec = "" + s % 60;
215+ if (sec.length == 1) sec = "0" + sec;
216+ var hour = Math.floor(s / 3600);
217 if (hour < 1) {
218- return Math.floor(s / 60) + ":" + sec
219+ return Math.floor(s / 60) + ":" + sec;
220 } else {
221- var min = "" + Math.floor(s / 60) % 60
222- if (min.length == 1) min = "0" + min
223- return hour + ":" + min + ":" + sec
224+ var min = "" + Math.floor(s / 60) % 60;
225+ if (min.length == 1) min = "0" + min;
226+ return hour + ":" + min + ":" + sec;
227 }
228 }
229 }
230@@ -78,6 +77,15 @@
231 objectName: "trackRepeater"
232 model: root.widgetData["tracks"]
233
234+ function play(item, source) {
235+ audio.stop();
236+ // Make sure we change the source, even if two items point to the same uri location
237+ audio.source = "";
238+ audio.source = source;
239+ audio.playingItem = item;
240+ audio.play();
241+ }
242+
243 delegate: Item {
244 id: trackItem
245 objectName: "trackItem" + index
246@@ -87,15 +95,6 @@
247 anchors { left: parent.left; right: parent.right }
248 height: units.gu(5)
249
250- function play() {
251- audio.stop();
252- // Make sure we change the source, even if two items point to the same uri location
253- audio.source = "";
254- audio.source = modelData["source"];
255- audio.playingItem = trackItem;
256- audio.play();
257- }
258-
259 Row {
260 id: trackRow
261
262@@ -121,11 +120,11 @@
263 if (trackItem.isPlayingItem) {
264 if (audio.playbackState == Audio.PlayingState) {
265 audio.pause();
266- } else if (audio.playbackState == Audio.PausedState){
267+ } else if (audio.playbackState == Audio.PausedState) {
268 audio.play();
269 }
270 } else {
271- trackItem.play();
272+ trackRepeater.play(trackItem, modelData["source"]);
273 }
274 }
275 }
276@@ -156,7 +155,7 @@
277 color: Theme.palette.selected.backgroundText
278 fontSize: "small"
279 horizontalAlignment: Text.AlignLeft
280- text: modelData["subtitle"] !== undefined ? modelData["subtitle"] : ""
281+ text: modelData["subtitle"] || ""
282 elide: Text.ElideRight
283 }
284
285
286=== modified file 'qml/Dash/Previews/PreviewWidget.qml'
287--- qml/Dash/Previews/PreviewWidget.qml 2014-02-06 18:10:33 +0000
288+++ qml/Dash/Previews/PreviewWidget.qml 2014-02-06 18:10:34 +0000
289@@ -19,9 +19,19 @@
290 /*! Interface for preview widgets. */
291
292 Item {
293- /// type:bool Specifies the preview widget being currently used or not
294+ //! Specifies the preview widget being currently used or not
295 property bool isCurrentPreview: true
296
297- /// Variable used to contain widget's data
298+ //! The widget identifier
299+ property string widgetId
300+
301+ //! Variable used to contain widget's data
302 property var widgetData
303+
304+ /*! \brief This signal should be emitted when a preview action was triggered.
305+ *
306+ * \param widgetId,actionId Respective identifiers from widgetData.
307+ * \param data Optional widget-specific data sent to the scope.
308+ */
309+ signal triggered(string widgetId, string actionId, var data)
310 }
311
312=== modified file 'tests/qmltests/CMakeLists.txt'
313--- tests/qmltests/CMakeLists.txt 2014-02-06 18:10:33 +0000
314+++ tests/qmltests/CMakeLists.txt 2014-02-06 18:10:34 +0000
315@@ -55,6 +55,7 @@
316 add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
317 add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
318 add_qml_test(Dash/Music MusicPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
319+add_qml_test(Dash/Previews PreviewActions IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
320 add_qml_test(Dash/Previews PreviewAudioPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
321 add_qml_test(Dash/Previews PreviewImageGallery IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
322 add_qml_test(Dash/Previews PreviewTextSummary IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
323
324=== added file 'tests/qmltests/Dash/Previews/tst_PreviewActions.qml'
325--- tests/qmltests/Dash/Previews/tst_PreviewActions.qml 1970-01-01 00:00:00 +0000
326+++ tests/qmltests/Dash/Previews/tst_PreviewActions.qml 2014-02-06 18:10:34 +0000
327@@ -0,0 +1,148 @@
328+/*
329+ * Copyright 2014 Canonical Ltd.
330+ *
331+ * This program is free software; you can redistribute it and/or modify
332+ * it under the terms of the GNU General Public License as published by
333+ * the Free Software Foundation; version 3.
334+ *
335+ * This program is distributed in the hope that it will be useful,
336+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
337+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
338+ * GNU General Public License for more details.
339+ *
340+ * You should have received a copy of the GNU General Public License
341+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
342+ */
343+
344+import QtQuick 2.0
345+import QtTest 1.0
346+import "../../../../qml/Dash/Previews"
347+import Unity.Test 0.1 as UT
348+import Ubuntu.Components 0.1
349+
350+
351+Rectangle {
352+ id: root
353+ width: units.gu(60)
354+ height: units.gu(80)
355+
356+ property var actionDataOneAction: {
357+ "actions": [{"label": "Some Label", "icon": "../graphics/play_button.png", "id": "someid"}]
358+ }
359+
360+ property var actionDataTwoActions: {
361+ "actions": [{"label": "Some Label A", "icon": "../graphics/icon_clear.png", "id": "someid1"},
362+ {"label": "Some Label B", "icon": "../graphics/play_button.png", "id": "someid2"}
363+ ]
364+ }
365+
366+ property var actionDataFiveActions: {
367+ "actions": [{"label": "Some Label C", "icon": "../graphics/play_button.png", "id": "someid3"},
368+ {"label": "Some Label D", "icon": "../graphics/icon_clear.png", "id": "someid4"},
369+ {"label": "Some Label E", "icon": "../graphics/play_button.png", "id": "someid5"},
370+ {"label": "Some Label F", "icon": "../graphics/icon_clear.png", "id": "someid6"},
371+ {"label": "Some Label G", "icon": "../graphics/play_button.png", "id": "someid7"}
372+ ]
373+ }
374+
375+ SignalSpy {
376+ id: spy
377+ signalName: "triggered"
378+ }
379+
380+ Column {
381+ spacing: units.gu(1)
382+
383+ PreviewActions {
384+ id: oneAction
385+ widgetId: "button"
386+ widgetData: actionDataOneAction
387+ onTriggered: console.log("triggered", widgetId, actionId);
388+ width: units.gu(50)
389+
390+ Rectangle {
391+ anchors.fill: parent
392+ color: "red"
393+ opacity: 0.1
394+ }
395+ }
396+
397+ PreviewActions {
398+ id: buttonAndCombo
399+ widgetId: "buttonAndCombo"
400+ widgetData: actionDataFiveActions
401+ onTriggered: console.log("triggered", widgetId, actionId);
402+ width: units.gu(40)
403+
404+ Rectangle {
405+ anchors.fill: parent
406+ color: "red"
407+ opacity: 0.1
408+ }
409+ }
410+
411+ PreviewActions {
412+ id: twoActions
413+ widgetId: "2buttons"
414+ widgetData: actionDataTwoActions
415+ onTriggered: console.log("triggered", widgetId, actionId);
416+ width: units.gu(60)
417+ }
418+ }
419+
420+ UT.UnityTestCase {
421+ name: "PreviewActionTest"
422+ when: windowShown
423+
424+ function cleanup()
425+ {
426+ spy.clear();
427+ }
428+
429+ function checkButtonPressSignal(target, id)
430+ {
431+ var button = findChild(root, "button" + id);
432+ verify(button != null);
433+ spy.target = target;
434+ mouseClick(button, button.width / 2, button.height / 2);
435+ compare(spy.count, 1);
436+ compare(spy.signalArguments[0][0], target.widgetId);
437+ compare(spy.signalArguments[0][1], id);
438+ }
439+
440+ function test_checkButtons_data() {
441+ return [
442+ {tag: "oneActionButton", target: oneAction, id: "someid" },
443+ {tag: "twobuttonsButton0", target: twoActions, id: "someid1" },
444+ {tag: "twobuttonsButton1", target: twoActions, id: "someid2" },
445+ {tag: "buttonAndComboButton0", target: buttonAndCombo, id: "someid3" }
446+ ]
447+ }
448+
449+ function test_checkButtons(data) {
450+ checkButtonPressSignal(data.target, data.id, data.buttonNumber)
451+ }
452+
453+ function test_comboButton_data() {
454+ return [
455+ {tag: "button1", id: "someid4" },
456+ {tag: "button2", id: "someid5" },
457+ {tag: "button3", id: "someid6" },
458+ {tag: "button4", id: "someid7" }
459+ ]
460+ }
461+
462+ function test_comboButton(data) {
463+ var button = findChild(root, "moreLessButton");
464+ var buttonColumn = findChild(root, "buttonColumn");
465+ verify(button != null);
466+ var twoActionsY = twoActions.y
467+ mouseClick(button, button.width / 2, button.height / 2);
468+ tryCompareFunction(function () { return twoActions.y <= twoActionsY; }, false);
469+ tryCompare(buttonColumn, "height", buttonColumn.implicitHeight);
470+ checkButtonPressSignal(buttonAndCombo, data.id, data.buttonNumber);
471+ mouseClick(button, button.width / 2, button.height / 2);
472+ tryCompare(twoActions, "y", twoActionsY);
473+ }
474+ }
475+}
476
477=== modified file 'tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml'
478--- tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml 2014-02-06 18:10:33 +0000
479+++ tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml 2014-02-06 18:10:34 +0000
480@@ -57,6 +57,7 @@
481
482 function test_time_formatter_data() {
483 return [
484+ { tag: "NaN", value: "not a number", result: "" },
485 { tag: "0", value: 0, result: "" },
486 { tag: "-1", value: -1, result: "" },
487 { tag: "30", value: 30, result: "0:30" },

Subscribers

People subscribed via source and target branches