Merge lp:~cimi/unity8/shadow-ubuntu-store-icon into lp:unity8

Proposed by Andrea Cimitan on 2015-11-20
Status: Merged
Approved by: MichaƂ Sawicz on 2015-12-08
Approved revision: 1849
Merged at revision: 2085
Proposed branch: lp:~cimi/unity8/shadow-ubuntu-store-icon
Merge into: lp:unity8
Prerequisite: lp:~cimi/unity8/new-shadows-1.3
Diff against target: 1444 lines (+732/-128)
31 files modified
debian/control (+2/-2)
plugins/Dash/AudioProgressBar.qml (+53/-0)
plugins/Dash/CMakeLists.txt (+3/-0)
plugins/Dash/CardAudioProgress.qml (+59/-0)
plugins/Dash/CardCreator.js (+116/-2)
plugins/Dash/DashAudioPlayer.qml (+96/-0)
plugins/Dash/plugin.cpp (+35/-0)
plugins/Dash/qmldir (+3/-0)
qml/Dash/CardGrid.qml (+2/-0)
qml/Dash/GenericScopeView.qml (+15/-9)
qml/Dash/Previews/PreviewAudioPlayback.qml (+16/-76)
tests/mocks/QtMultimedia/CMakeLists.txt (+1/-0)
tests/mocks/QtMultimedia/audio.cpp (+23/-21)
tests/mocks/QtMultimedia/audio.h (+8/-6)
tests/mocks/QtMultimedia/declarativeplaylist.cpp (+73/-0)
tests/mocks/QtMultimedia/declarativeplaylist.h (+54/-0)
tests/mocks/QtMultimedia/plugin.cpp (+2/-0)
tests/mocks/Unity/CMakeLists.txt (+1/-1)
tests/plugins/Dash/cardcreator/1.res (+1/-0)
tests/plugins/Dash/cardcreator/2.res (+9/-0)
tests/plugins/Dash/cardcreator/3.res (+1/-0)
tests/plugins/Dash/cardcreator/4.res (+1/-0)
tests/plugins/Dash/cardcreator/5.res (+1/-0)
tests/plugins/Dash/cardcreator/6.res (+9/-0)
tests/plugins/Dash/cardcreator/7.res (+9/-0)
tests/plugins/Dash/cardcreator/8.res (+9/-0)
tests/plugins/Dash/cardcreator/9.res (+113/-0)
tests/plugins/Dash/cardcreator/9.tst (+3/-0)
tests/qmltests/Dash/CardHelpers.js (+1/-1)
tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml (+5/-9)
tests/qmltests/Dash/tst_Card.qml (+8/-1)
To merge this branch: bzr merge lp:~cimi/unity8/shadow-ubuntu-store-icon
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing on 2015-11-23
Albert Astals Cid (community) 2015-11-20 Approve on 2015-11-23
Review via email: mp+278172@code.launchpad.net

Commit Message

Add shadows to ubuntu store icon

Description of the Change

 * Are there any related MPs required for this MP to build/function as expected? Please list.
n
 * Did you perform an exploratory manual test run of your code change and any related functionality?
y
 * Did you make sure that your branch does not contain spurious tags?
y
 * 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?
noy yet

To post a comment you must log in.
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1848
http://jenkins.qa.ubuntu.com/job/unity8-ci/6761/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5301
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/176/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1474/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/176
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1368
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1369
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/175
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/175
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4206
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5321
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5321/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25348
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/48/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/176
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/176/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25347

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

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

The code looks good, tested it and works fine, the CI failure seems unrelated..

I've retriggered another CI run though, will wait for it to top approve

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes

 * Did CI run pass?
Waiting for re-run

 * Did you make sure that the branch does not contain spurious tags?
Yes

review: Approve
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1848
http://jenkins.qa.ubuntu.com/job/unity8-ci/6769/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5314
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/184/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1482
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/184
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1376
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1377
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/183
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/183
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4219
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5334
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5334/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25397
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/55/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/184
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/184/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25399

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

review: Needs Fixing (continuous-integration)
1849. By Andrea Cimitan on 2015-12-08

merged trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2015-11-26 13:51:24 +0000
3+++ debian/control 2015-12-04 12:30:34 +0000
4@@ -29,7 +29,7 @@
5 libqt5xmlpatterns5-dev,
6 libsystemsettings-dev,
7 libudev-dev,
8- libunity-api-dev (>= 7.103),
9+ libunity-api-dev (>= 7.104),
10 libusermetricsoutput1-dev,
11 libxcb1-dev,
12 pkg-config,
13@@ -131,7 +131,7 @@
14 unity-application-impl-11,
15 unity-notifications-impl-3,
16 unity-plugin-scopes | unity-scopes-impl,
17- unity-scopes-impl-7,
18+ unity-scopes-impl-9,
19 unity8-fake-env | unity-application-impl,
20 ${misc:Depends},
21 Breaks: unity8 (<< 7.86),
22
23=== added file 'plugins/Dash/AudioProgressBar.qml'
24--- plugins/Dash/AudioProgressBar.qml 1970-01-01 00:00:00 +0000
25+++ plugins/Dash/AudioProgressBar.qml 2015-12-04 12:30:34 +0000
26@@ -0,0 +1,53 @@
27+/*
28+ * Copyright 2015 Canonical Ltd.
29+ *
30+ * This program is free software; you can redistribute it and/or modify
31+ * it under the terms of the GNU General Public License as published by
32+ * the Free Software Foundation; version 3.
33+ *
34+ * This program is distributed in the hope that it will be useful,
35+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37+ * GNU General Public License for more details.
38+ *
39+ * You should have received a copy of the GNU General Public License
40+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
41+ */
42+
43+import QtQuick 2.4
44+import Ubuntu.Components 1.3
45+import Dash 0.1
46+
47+Item {
48+ id: root
49+
50+ implicitHeight: progressBarImage.height
51+
52+ property url source
53+ readonly property double progress: AudioUrlComparer.compare(source, DashAudioPlayer.currentSource) ? DashAudioPlayer.progress : 0
54+
55+ Image {
56+ id: progressBarImage
57+ anchors { left: parent.left; right: parent.right }
58+ height: units.dp(6)
59+ source: "graphics/music_progress_bg.png"
60+ sourceSize.width: width
61+ sourceSize.height: height
62+ }
63+
64+ UbuntuShape {
65+ id: progressBarFill
66+ objectName: "progressBarFill"
67+
68+ readonly property int maxWidth: progressBarImage.width
69+
70+ anchors {
71+ left: progressBarImage.left
72+ right: progressBarImage.right
73+ verticalCenter: progressBarImage.verticalCenter
74+ rightMargin: maxWidth - (maxWidth * root.progress)
75+ }
76+ height: units.dp(2)
77+ backgroundColor: UbuntuColors.orange
78+ }
79+}
80
81=== modified file 'plugins/Dash/CMakeLists.txt'
82--- plugins/Dash/CMakeLists.txt 2015-08-26 15:47:28 +0000
83+++ plugins/Dash/CMakeLists.txt 2015-12-04 12:30:34 +0000
84@@ -38,3 +38,6 @@
85 qt5_use_modules(Dash-qml Qml Quick Concurrent)
86
87 add_unity8_plugin(Dash 0.1 Dash TARGETS Dash-qml)
88+
89+install(FILES graphics/music_progress_bg.png DESTINATION ${SHELL_INSTALL_QML}/Dash/graphics/)
90+file(COPY graphics/music_progress_bg.png DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/graphics/)
91
92=== added file 'plugins/Dash/CardAudioProgress.qml'
93--- plugins/Dash/CardAudioProgress.qml 1970-01-01 00:00:00 +0000
94+++ plugins/Dash/CardAudioProgress.qml 2015-12-04 12:30:34 +0000
95@@ -0,0 +1,59 @@
96+/*
97+ * Copyright 2015 Canonical Ltd.
98+ *
99+ * This program is free software; you can redistribute it and/or modify
100+ * it under the terms of the GNU General Public License as published by
101+ * the Free Software Foundation; version 3.
102+ *
103+ * This program is distributed in the hope that it will be useful,
104+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
105+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
106+ * GNU General Public License for more details.
107+ *
108+ * You should have received a copy of the GNU General Public License
109+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
110+ */
111+
112+import QtQuick 2.4
113+import Ubuntu.Components 1.3
114+import Dash 0.1
115+
116+Item {
117+ id: root
118+
119+ implicitHeight: positionLabel.y + positionLabel.height
120+ visible: AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)
121+
122+ property int duration: 0
123+ property alias source: progress.source
124+ property color color: theme.palette.normal.baseText
125+ readonly property int position: root.visible ? DashAudioPlayer.position / 1000 : 0
126+
127+ AudioProgressBar {
128+ id: progress
129+ anchors { left: parent.left; right: parent.right }
130+ }
131+
132+ Label {
133+ id: positionLabel
134+ anchors {
135+ left: parent.left
136+ top: progress.bottom
137+ }
138+ verticalAlignment: Text.AlignBottom
139+ fontSize: "x-small"
140+ text: DashAudioPlayer.lengthToString(root.position)
141+ color: root.color
142+ }
143+
144+ Label {
145+ anchors {
146+ right: parent.right
147+ top: progress.bottom
148+ }
149+ verticalAlignment: Text.AlignBottom
150+ fontSize: "x-small"
151+ text: DashAudioPlayer.lengthToString(duration)
152+ color: root.color
153+ }
154+}
155
156=== modified file 'plugins/Dash/CardCreator.js'
157--- plugins/Dash/CardCreator.js 2015-11-19 16:55:31 +0000
158+++ plugins/Dash/CardCreator.js 2015-12-04 12:30:34 +0000
159@@ -28,6 +28,14 @@
160 sourceComponent: UbuntuShape { \n\
161 objectName: "background"; \n\
162 radius: "medium"; \n\
163+ aspect: { \n\
164+ switch (root.backgroundShapeStyle) { \n\
165+ case "inset": return UbuntuShape.Inset; \n\
166+ case "shadow": return UbuntuShape.DropShadow; \n\
167+ default: \n\
168+ case "flat": return UbuntuShape.Flat; \n\
169+ } \n\
170+ } \n\
171 backgroundColor: getColor(0) || "white"; \n\
172 secondaryBackgroundColor: getColor(1) || backgroundColor; \n\
173 backgroundMode: UbuntuShape.VerticalGradient; \n\
174@@ -128,6 +136,43 @@
175 } \n\
176 }\n';
177
178+// %1 is anchors.fill
179+// %2 is width
180+// %3 is height
181+var kAudioButtonCode = 'AbstractButton { \n\
182+ id: audioButton; \n\
183+ anchors.fill: %1; \n\
184+ width: %2; \n\
185+ height: %3; \n\
186+ readonly property url source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || ""; \n\
187+ UbuntuShape { \n\
188+ anchors.fill: parent; \n\
189+ visible: parent.pressed; \n\
190+ radius: "medium"; \n\
191+ } \n\
192+ Icon { \n\
193+ anchors.fill: parent; \n\
194+ anchors.margins: parent.height > units.gu(5) ? units.gu(2) : 0; \n\
195+ opacity: 0.9; \n\
196+ name: DashAudioPlayer.playing && AudioUrlComparer.compare(parent.source, DashAudioPlayer.currentSource) ? "media-playback-pause" : "media-playback-start"; \n\
197+ } \n\
198+ onClicked: { \n\
199+ if (AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)) { \n\
200+ if (DashAudioPlayer.playing) { \n\
201+ DashAudioPlayer.pause(); \n\
202+ } else { \n\
203+ DashAudioPlayer.play(); \n\
204+ } \n\
205+ } else { \n\
206+ var playlist = (cardData["quickPreviewData"] && cardData["quickPreviewData"]["playlist"]) || null; \n\
207+ DashAudioPlayer.playSource(source, playlist); \n\
208+ } \n\
209+ } \n\
210+ onPressAndHold: { \n\
211+ root.pressAndHold(); \n\
212+ } \n\
213+ }';
214+
215 var kOverlayLoaderCode = 'Loader { \n\
216 id: overlayLoader; \n\
217 readonly property real overlayHeight: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
218@@ -308,6 +353,22 @@
219 color: %3; \n\
220 }\n';
221
222+// %1 is used as bottom anchor of audio progress bar
223+// %2 is used as left anchor of audio progress bar
224+// %3 is used as text color
225+var kAudioProgressBarCode = 'CardAudioProgress { \n\
226+ id: audioProgressBar; \n\
227+ duration: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["duration"]) || 0; \n\
228+ source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || ""; \n\
229+ anchors { \n\
230+ bottom: %1; \n\
231+ left: %2; \n\
232+ right: parent.right; \n\
233+ margins: units.gu(1); \n\
234+ } \n\
235+ color: %3; \n\
236+ }';
237+
238 function cardString(template, components) {
239 var code;
240
241@@ -318,6 +379,7 @@
242 property var components; \n\
243 property var cardData; \n\
244 property string artShapeStyle: "inset"; \n\
245+ property string backgroundShapeStyle: "inset"; \n\
246 property real fontScale: 1.0; \n\
247 property var scopeStyle: null; \n\
248 property int titleAlignment: Text.AlignLeft; \n\
249@@ -342,7 +404,20 @@
250 var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
251 var hasSubtitle = hasTitle && components["subtitle"] || false;
252 var hasHeaderRow = hasMascot && hasTitle;
253- var hasAttributes = hasTitle && components["attributes"]["field"] || false;
254+ var hasAttributes = hasTitle && components["attributes"] && components["attributes"]["field"] || false;
255+ var isAudio = template["quick-preview-type"] === "audio";
256+
257+ if (isAudio) {
258+ // For now we only support audio cards with [optional] art, title, subtitle
259+ // in horizontal mode
260+ // Anything else makes it behave not like an audio card
261+ if (hasSummary) isAudio = false;
262+ if (!isHorizontal) isAudio = false;
263+ if (hasMascot) isAudio = false;
264+ if (hasEmblem) isAudio = false;
265+ if (headerAsOverlay) isAudio = false;
266+ if (hasAttributes) isAudio = false;
267+ }
268
269 if (hasBackground) {
270 var templateCardBackground = (template && typeof template["card-background"] === "string") ? template["card-background"] : "";
271@@ -412,17 +487,22 @@
272 topMargin: units.gu(1);\n';
273 }
274 }
275+
276 var headerLeftAnchor;
277 var headerLeftAnchorHasMargin = false;
278 if (isHorizontal && hasArt) {
279 headerLeftAnchor = 'left: artShapeHolder.right; \n\
280 leftMargin: units.gu(1);\n';
281 headerLeftAnchorHasMargin = true;
282+ } else if (isHorizontal && isAudio) {
283+ headerLeftAnchor = 'left: audioButton.right; \n\
284+ leftMargin: units.gu(1);\n';
285+ headerLeftAnchorHasMargin = true;
286 } else {
287 headerLeftAnchor = 'left: parent.left;\n';
288 }
289
290- var touchdownOnArtShape = !hasBackground && hasArt && !hasMascot && !hasSummary;
291+ var touchdownOnArtShape = !hasBackground && hasArt && !hasMascot && !hasSummary && !isAudio;
292
293 if (hasHeaderRow) {
294 code += 'readonly property int headerHeight: row.height;\n'
295@@ -436,6 +516,14 @@
296 } else {
297 code += 'readonly property int headerHeight: attributesRow.height;\n'
298 }
299+ } else if (isAudio) {
300+ if (hasSubtitle) {
301+ code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + audioProgressBar.height + audioProgressBar.anchors.topMargin;\n'
302+ } else if (hasTitle) {
303+ code += 'readonly property int headerHeight: titleLabel.height + audioProgressBar.height + audioProgressBar.anchors.topMargin;\n'
304+ } else {
305+ code += 'readonly property int headerHeight: audioProgressBar.height;\n'
306+ }
307 } else if (hasSubtitle) {
308 code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
309 } else if (hasTitle) {
310@@ -623,6 +711,30 @@
311 code += mascotShapeCode + mascotCode + titleSubtitleCode;
312 }
313
314+ if (isAudio) {
315+ var audioProgressBarLeftAnchor = 'audioButton.right';
316+ var audioProgressBarBottomAnchor = 'audioButton.bottom';
317+ var audioProgressBarTextColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
318+
319+ code += kAudioProgressBarCode.arg(audioProgressBarBottomAnchor)
320+ .arg(audioProgressBarLeftAnchor)
321+ .arg(audioProgressBarTextColor);
322+
323+ var audioButtonAnchorsFill;
324+ var audioButtonWidth;
325+ var audioButtonHeight;
326+ if (hasArt) {
327+ audioButtonAnchorsFill = 'artShapeHolder';
328+ audioButtonWidth = 'undefined';
329+ audioButtonHeight = 'undefined';
330+ } else {
331+ audioButtonAnchorsFill = 'undefined';
332+ audioButtonWidth = 'height';
333+ audioButtonHeight = '(root.fixedHeaderHeight > 0 ? root.fixedHeaderHeight : headerHeight) + 2 * units.gu(1)';
334+ }
335+ code += kAudioButtonCode.arg(audioButtonAnchorsFill).arg(audioButtonWidth).arg(audioButtonHeight);
336+ }
337+
338 if (hasSummary) {
339 var summaryTopAnchor;
340 if (isHorizontal && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
341@@ -661,6 +773,8 @@
342 var implicitHeight = 'implicitHeight: ';
343 if (hasSummary) {
344 implicitHeight += 'summary.y + summary.height + units.gu(1);\n';
345+ } else if (isAudio) {
346+ implicitHeight += 'audioButton.height;\n';
347 } else if (headerAsOverlay) {
348 implicitHeight += 'artShapeHolder.height;\n';
349 } else if (hasHeaderRow) {
350
351=== added file 'plugins/Dash/DashAudioPlayer.qml'
352--- plugins/Dash/DashAudioPlayer.qml 1970-01-01 00:00:00 +0000
353+++ plugins/Dash/DashAudioPlayer.qml 2015-12-04 12:30:34 +0000
354@@ -0,0 +1,96 @@
355+/*
356+ * Copyright (C) 2015 Canonical, Ltd.
357+ *
358+ * This program is free software; you can redistribute it and/or modify
359+ * it under the terms of the GNU General Public License as published by
360+ * the Free Software Foundation; version 3.
361+ *
362+ * This program is distributed in the hope that it will be useful,
363+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
364+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
365+ * GNU General Public License for more details.
366+ *
367+ * You should have received a copy of the GNU General Public License
368+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
369+ */
370+
371+pragma Singleton
372+import QtQuick 2.4
373+import QtMultimedia 5.4
374+import Dash 0.1
375+
376+QtObject {
377+ readonly property real progress: audio.position / audio.duration
378+ readonly property bool playing: audio.playbackState === Audio.PlayingState
379+ readonly property bool paused: audio.playbackState === Audio.PausedState
380+ readonly property bool stopped: audio.playbackState === Audio.StoppedState
381+ readonly property alias position: audio.position
382+ readonly property url currentSource: audio.playlist.currentItemSource
383+
384+ function playSource(newSource, newPlaylist) {
385+ stop();
386+ audio.playlist.clear();
387+ if (newPlaylist) {
388+ // Look for newSource in newPlaylist
389+ var sourceIndex = -1;
390+ for (var i in newPlaylist) {
391+ if (AudioUrlComparer.compare(newSource, newPlaylist[i])) {
392+ sourceIndex = i;
393+ break;
394+ }
395+ }
396+ var urls = [];
397+ if (sourceIndex === -1 && newSource != "") {
398+ // If the playing song is not in the playlist, add it
399+ urls.push(newSource);
400+ sourceIndex = 0;
401+ }
402+ for (var i in newPlaylist) {
403+ urls.push(newPlaylist[i]);
404+ }
405+ audio.playlist.addItems(urls);
406+ audio.playlist.currentIndex = sourceIndex;
407+ } else {
408+ audio.playlist.addItem(newSource);
409+ audio.playlist.currentIndex = 0;
410+ }
411+ play();
412+ }
413+
414+ function stop() {
415+ audio.stop();
416+ }
417+
418+ function play() {
419+ audio.play();
420+ }
421+
422+ function pause() {
423+ audio.pause();
424+ }
425+
426+ property QtObject audio: Audio {
427+ id: audio
428+ objectName: "audio"
429+ playlist: Playlist {
430+ objectName: "playlist"
431+ }
432+
433+ onErrorStringChanged: console.warn("Dash Audio player error:", errorString)
434+ }
435+
436+ function lengthToString(s) {
437+ if (typeof(s) !== "number" || s < 0) return "";
438+
439+ var sec = "" + s % 60;
440+ if (sec.length == 1) sec = "0" + sec;
441+ var hour = Math.floor(s / 3600);
442+ if (hour < 1) {
443+ return Math.floor(s / 60) + ":" + sec;
444+ } else {
445+ var min = "" + Math.floor(s / 60) % 60;
446+ if (min.length == 1) min = "0" + min;
447+ return hour + ":" + min + ":" + sec;
448+ }
449+ }
450+}
451
452=== added directory 'plugins/Dash/graphics'
453=== renamed file 'qml/Dash/Previews/graphics/music_progress_bg.png' => 'plugins/Dash/graphics/music_progress_bg.png'
454Binary files qml/Dash/Previews/graphics/music_progress_bg.png 2013-11-13 14:40:58 +0000 and plugins/Dash/graphics/music_progress_bg.png 2015-12-04 12:30:34 +0000 differ
455=== modified file 'plugins/Dash/plugin.cpp'
456--- plugins/Dash/plugin.cpp 2015-08-26 15:47:28 +0000
457+++ plugins/Dash/plugin.cpp 2015-12-04 12:30:34 +0000
458@@ -23,6 +23,38 @@
459 #include "verticaljournal.h"
460
461 #include <QAbstractItemModel>
462+#include <QUrlQuery>
463+
464+static QUrl oauthCleanedUrl(QUrl u)
465+{
466+ QUrlQuery q(u);
467+ q.removeQueryItem("oauth_nonce");
468+ q.removeQueryItem("oauth_timestamp");
469+ q.removeQueryItem("oauth_consumer_key");
470+ q.removeQueryItem("oauth_signature_method");
471+ q.removeQueryItem("oauth_version");
472+ q.removeQueryItem("oauth_signature");
473+ u.setQuery(q);
474+ return u;
475+}
476+
477+class AudioComparer : public QObject
478+{
479+ Q_OBJECT
480+public:
481+ Q_INVOKABLE bool compare(const QUrl &url1, const QUrl &url2)
482+ {
483+ return oauthCleanedUrl(url1) == oauthCleanedUrl(url2);
484+ }
485+};
486+
487+static QObject *audio_comparer_singleton_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
488+{
489+ Q_UNUSED(engine)
490+ Q_UNUSED(scriptEngine)
491+
492+ return new AudioComparer();
493+}
494
495 void DashPlugin::registerTypes(const char *uri)
496 {
497@@ -32,4 +64,7 @@
498 qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
499 qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
500 qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
501+ qmlRegisterSingletonType<AudioComparer>(uri, 0, 1, "AudioUrlComparer", audio_comparer_singleton_provider);
502 }
503+
504+#include "plugin.moc"
505
506=== modified file 'plugins/Dash/qmldir'
507--- plugins/Dash/qmldir 2014-08-25 08:25:54 +0000
508+++ plugins/Dash/qmldir 2015-12-04 12:30:34 +0000
509@@ -2,6 +2,9 @@
510 plugin Dash-qml
511 typeinfo Dash.qmltypes
512 singleton CardCreatorCache 0.1 CardCreatorCache.qml
513+singleton DashAudioPlayer 0.1 DashAudioPlayer.qml
514 ScopeStyle 0.1 ScopeStyle.qml
515 CardAttributes 0.1 CardAttributes.qml
516 CroppedImageMinimumSourceSize 0.1 CroppedImageMinimumSourceSize.qml
517+AudioProgressBar 0.1 AudioProgressBar.qml
518+CardAudioProgress 0.1 CardAudioProgress.qml
519
520=== modified file 'qml/Dash/CardGrid.qml'
521--- qml/Dash/CardGrid.qml 2015-11-20 15:36:42 +0000
522+++ qml/Dash/CardGrid.qml 2015-12-04 12:30:34 +0000
523@@ -25,6 +25,7 @@
524 return cardTool.template["collapsed-rows"];
525 }
526 property string artShapeStyle: "inset";
527+ property string backgroundShapeStyle: "inset";
528
529 expandedHeight: grid.totalContentHeight
530 collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows, grid.cellHeight), expandedHeight)
531@@ -71,6 +72,7 @@
532 item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
533 item.scopeStyle = root.scopeStyle;
534 item.artShapeStyle = root.artShapeStyle;
535+ item.backgroundShapeStyle = root.backgroundShapeStyle;
536 }
537 Connections {
538 target: loader.item
539
540=== modified file 'qml/Dash/GenericScopeView.qml'
541--- qml/Dash/GenericScopeView.qml 2015-11-20 15:36:42 +0000
542+++ qml/Dash/GenericScopeView.qml 2015-12-04 12:30:34 +0000
543@@ -360,17 +360,23 @@
544 baseItem.expand(shouldExpand, false /*animate*/);
545 }
546 updateRanges();
547- if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
548- // Yeah, hackish :/
549- if (scopeView.width > units.gu(45)) {
550- if (scopeView.width >= units.gu(70)) {
551- cardTool.cardWidth = units.gu(9);
552- } else {
553- cardTool.cardWidth = units.gu(10);
554+ if (scope && scope.id === "clickscope") {
555+ if (categoryId === "predefined" || categoryId === "local") {
556+ // Yeah, hackish :/
557+ if (scopeView.width > units.gu(45)) {
558+ if (scopeView.width >= units.gu(70)) {
559+ cardTool.cardWidth = units.gu(9);
560+ } else {
561+ cardTool.cardWidth = units.gu(10);
562+ }
563 }
564+ cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
565+ item.artShapeStyle = "icon";
566+ } else {
567+ // Should be ubuntu store icon
568+ item.artShapeStyle = "flat";
569+ item.backgroundShapeStyle = "shadow";
570 }
571- cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
572- item.artShapeStyle = "icon";
573 }
574 item.cardTool = cardTool;
575 }
576
577=== modified file 'qml/Dash/Previews/PreviewAudioPlayback.qml'
578--- qml/Dash/Previews/PreviewAudioPlayback.qml 2015-11-04 14:57:13 +0000
579+++ qml/Dash/Previews/PreviewAudioPlayback.qml 2015-12-04 12:30:34 +0000
580@@ -15,8 +15,8 @@
581 */
582
583 import QtQuick 2.4
584-import QtMultimedia 5.0
585 import Ubuntu.Components 1.3
586+import Dash 0.1
587
588 /*! \brief Preview widget for audio tracks.
589
590@@ -36,38 +36,6 @@
591 id: root
592 implicitHeight: childrenRect.height
593
594- onIsCurrentPreviewChanged: if (!isCurrentPreview) audio.stop()
595-
596- Audio {
597- id: audio
598- objectName: "audio"
599-
600- property real progress: audio.position / audio.duration
601- property Item playingItem
602-
603- Component.onDestruction: {
604- // destroying the component doesn't automatically send stop to the media service, probably a bug in QtMultimedia
605- audio.stop();
606- }
607-
608- onErrorStringChanged: console.warn("Audio player error:", errorString)
609-
610- function lengthToString(s) {
611- if (typeof(s) !== "number" || s <= 0) return "";
612-
613- var sec = "" + s % 60;
614- if (sec.length == 1) sec = "0" + sec;
615- var hour = Math.floor(s / 3600);
616- if (hour < 1) {
617- return Math.floor(s / 60) + ":" + sec;
618- } else {
619- var min = "" + Math.floor(s / 60) % 60;
620- if (min.length == 1) min = "0" + min;
621- return hour + ":" + min + ":" + sec;
622- }
623- }
624- }
625-
626 Column {
627 anchors { left: parent.left; right: parent.right }
628 visible: trackRepeater.count > 0
629@@ -77,20 +45,12 @@
630 objectName: "trackRepeater"
631 model: root.widgetData["tracks"]
632
633- function play(item, source) {
634- audio.stop();
635- // Make sure we change the source, even if two items point to the same uri location
636- audio.source = "";
637- audio.source = source;
638- audio.playingItem = item;
639- audio.play();
640- }
641-
642 delegate: Item {
643 id: trackItem
644 objectName: "trackItem" + index
645
646- property bool isPlayingItem: audio.playingItem == trackItem
647+ readonly property url sourceUrl: modelData["source"]
648+ readonly property bool isPlayingItem: AudioUrlComparer.compare(sourceUrl, DashAudioPlayer.currentSource)
649
650 anchors { left: parent.left; right: parent.right }
651 height: units.gu(5)
652@@ -98,9 +58,9 @@
653 Row {
654 id: trackRow
655
656- property int column1Width: units.gu(3)
657- property int column2Width: width - (2 * spacing) - column1Width - column3Width
658- property int column3Width: units.gu(4)
659+ readonly property int column1Width: units.gu(3)
660+ readonly property int column2Width: width - (2 * spacing) - column1Width - column3Width
661+ readonly property int column3Width: units.gu(4)
662
663 anchors.verticalCenter: parent.verticalCenter
664 width: parent.width
665@@ -110,7 +70,7 @@
666 objectName: "playButton"
667 width: trackRow.column1Width
668 height: width
669- iconSource: audio.playbackState == Audio.PlayingState && trackItem.isPlayingItem ? "image://theme/media-playback-pause" : "image://theme/media-playback-start"
670+ iconSource: DashAudioPlayer.playing && trackItem.isPlayingItem ? "image://theme/media-playback-pause" : "image://theme/media-playback-start"
671
672 // Can't be "transparent" or "#00xxxxxx" as the button optimizes away the surrounding shape
673 // FIXME when this is resolved: https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1251685
674@@ -118,13 +78,13 @@
675
676 onClicked: {
677 if (trackItem.isPlayingItem) {
678- if (audio.playbackState == Audio.PlayingState) {
679- audio.pause();
680- } else if (audio.playbackState == Audio.PausedState) {
681- audio.play();
682+ if (DashAudioPlayer.playing) {
683+ DashAudioPlayer.pause();
684+ } else if (DashAudioPlayer.paused) {
685+ DashAudioPlayer.play();
686 }
687 } else {
688- trackRepeater.play(trackItem, modelData["source"]);
689+ DashAudioPlayer.playSource(sourceUrl);
690 }
691 }
692 }
693@@ -160,30 +120,10 @@
694 elide: Text.ElideRight
695 }
696
697- UbuntuShape {
698- id: progressBarFill
699- objectName: "progressBarFill"
700-
701- property int maxWidth: progressBarImage.width - units.dp(4)
702-
703- anchors {
704- left: progressBarImage.left
705- right: progressBarImage.right
706- verticalCenter: progressBarImage.verticalCenter
707- margins: units.dp(2)
708- rightMargin: maxWidth - (maxWidth * audio.progress) + units.dp(2)
709- }
710- height: units.dp(2)
711- visible: progressBarImage.visible
712- backgroundColor: UbuntuColors.orange
713- }
714-
715- Image {
716- id: progressBarImage
717+ AudioProgressBar {
718 anchors { left: parent.left; top: parent.bottom; right: parent.right }
719- height: units.dp(6)
720- visible: audio.playbackState != Audio.StoppedState && trackItem.isPlayingItem && modelData["length"] > 0
721- source: "graphics/music_progress_bg.png"
722+ visible: !DashAudioPlayer.stopped && trackItem.isPlayingItem && modelData["length"] > 0
723+ source: sourceUrl
724 }
725 }
726
727@@ -196,7 +136,7 @@
728 color: scopeStyle ? scopeStyle.foreground : theme.palette.normal.baseText
729 fontSize: "small"
730 horizontalAlignment: Text.AlignRight
731- text: audio.lengthToString(modelData["length"])
732+ text: DashAudioPlayer.lengthToString(modelData["length"])
733 }
734 }
735 }
736
737=== modified file 'tests/mocks/QtMultimedia/CMakeLists.txt'
738--- tests/mocks/QtMultimedia/CMakeLists.txt 2014-05-02 22:57:21 +0000
739+++ tests/mocks/QtMultimedia/CMakeLists.txt 2015-12-04 12:30:34 +0000
740@@ -1,6 +1,7 @@
741 add_library(QtMultimedia-qml MODULE
742 plugin.cpp
743 audio.cpp
744+ declarativeplaylist.cpp
745 )
746
747 qt5_use_modules(QtMultimedia-qml Qml)
748
749=== modified file 'tests/mocks/QtMultimedia/audio.cpp'
750--- tests/mocks/QtMultimedia/audio.cpp 2015-08-19 13:56:21 +0000
751+++ tests/mocks/QtMultimedia/audio.cpp 2015-12-04 12:30:34 +0000
752@@ -1,5 +1,5 @@
753 /*
754- * Copyright (C) 2013 Canonical, Ltd.
755+ * Copyright (C) 2013, 2015 Canonical, Ltd.
756 *
757 * This program is free software; you can redistribute it and/or modify
758 * it under the terms of the GNU General Public License as published by
759@@ -20,30 +20,18 @@
760
761 Audio::Audio(QObject* parent):
762 QObject(parent),
763- m_playbackState(StoppedState)
764+ m_playbackState(StoppedState),
765+ m_playlist(0)
766 {
767 qsrand(time(nullptr));
768 m_timer.setInterval(1000);
769 connect(&m_timer, &QTimer::timeout, this, &Audio::timerEvent);
770-}
771-
772-QUrl Audio::source() const
773-{
774- return m_source;
775-}
776-
777-void Audio::setSource(const QUrl &source)
778-{
779- if (m_source != source) {
780- m_source = source;
781- Q_EMIT sourceChanged(source);
782-
783- m_position = 0;
784- Q_EMIT positionChanged(m_position);
785-
786- m_duration = (qrand() % 20000) + 10000;
787- Q_EMIT durationChanged(m_duration);
788- }
789+
790+ m_position = 0;
791+ Q_EMIT positionChanged(m_position);
792+
793+ m_duration = (qrand() % 20000) + 10000;
794+ Q_EMIT durationChanged(m_duration);
795 }
796
797 Audio::PlaybackState Audio::playbackState() const
798@@ -115,3 +103,17 @@
799 {
800 Q_UNUSED(audioRole);
801 }
802+
803+DeclarativePlaylist *Audio::playlist() const
804+{
805+ return m_playlist;
806+}
807+
808+void Audio::setPlaylist(DeclarativePlaylist *playlist)
809+{
810+ if (playlist == m_playlist)
811+ return;
812+
813+ m_playlist = playlist;
814+ Q_EMIT playlistChanged();
815+}
816
817=== modified file 'tests/mocks/QtMultimedia/audio.h'
818--- tests/mocks/QtMultimedia/audio.h 2015-06-08 11:37:27 +0000
819+++ tests/mocks/QtMultimedia/audio.h 2015-12-04 12:30:34 +0000
820@@ -1,5 +1,5 @@
821 /*
822- * Copyright (C) 2012,2013 Canonical, Ltd.
823+ * Copyright (C) 2012, 2013, 2015 Canonical, Ltd.
824 *
825 * This program is free software; you can redistribute it and/or modify
826 * it under the terms of the GNU General Public License as published by
827@@ -13,7 +13,6 @@
828 * You should have received a copy of the GNU General Public License
829 * along with this program. If not, see <http://www.gnu.org/licenses/>.
830 *
831- * Authors: Michael Zanetti <michael.zanetti@canonical.com>
832 */
833
834 #ifndef MOCK_AUDIO_H
835@@ -23,17 +22,19 @@
836 #include <QUrl>
837 #include <QTimer>
838
839+class DeclarativePlaylist;
840+
841 class Audio: public QObject
842 {
843 Q_OBJECT
844 Q_ENUMS(PlaybackState)
845 Q_ENUMS(AudioRole)
846- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
847 Q_PROPERTY(PlaybackState playbackState READ playbackState NOTIFY playbackStateChanged)
848 Q_PROPERTY(int position READ position NOTIFY positionChanged)
849 Q_PROPERTY(int duration READ duration NOTIFY durationChanged)
850 Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged)
851 Q_PROPERTY(AudioRole audioRole READ audioRole WRITE setAudioRole)
852+ Q_PROPERTY(DeclarativePlaylist *playlist READ playlist WRITE setPlaylist NOTIFY playlistChanged)
853 public:
854 enum PlaybackState {
855 PlayingState,
856@@ -50,8 +51,8 @@
857
858 explicit Audio(QObject *parent = 0);
859
860- QUrl source() const;
861- void setSource(const QUrl &source);
862+ DeclarativePlaylist *playlist() const;
863+ void setPlaylist(DeclarativePlaylist *playlist);
864
865 PlaybackState playbackState() const;
866
867@@ -70,6 +71,7 @@
868 void stop();
869
870 Q_SIGNALS:
871+ void playlistChanged();
872 void sourceChanged(const QUrl &source);
873 void playbackStateChanged(PlaybackState playbackState);
874 void positionChanged(int position);
875@@ -80,11 +82,11 @@
876 void timerEvent();
877
878 private:
879- QUrl m_source;
880 PlaybackState m_playbackState;
881 QTimer m_timer;
882 int m_position;
883 int m_duration;
884+ DeclarativePlaylist *m_playlist;
885 };
886
887 #endif
888
889=== added file 'tests/mocks/QtMultimedia/declarativeplaylist.cpp'
890--- tests/mocks/QtMultimedia/declarativeplaylist.cpp 1970-01-01 00:00:00 +0000
891+++ tests/mocks/QtMultimedia/declarativeplaylist.cpp 2015-12-04 12:30:34 +0000
892@@ -0,0 +1,73 @@
893+/*
894+ * Copyright (C) 2015 Canonical, Ltd.
895+ *
896+ * This program is free software; you can redistribute it and/or modify
897+ * it under the terms of the GNU General Public License as published by
898+ * the Free Software Foundation; version 3.
899+ *
900+ * This program is distributed in the hope that it will be useful,
901+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
902+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
903+ * GNU General Public License for more details.
904+ *
905+ * You should have received a copy of the GNU General Public License
906+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
907+ *
908+ */
909+
910+#include "declarativeplaylist.h"
911+
912+DeclarativePlaylist::DeclarativePlaylist(QObject *parent)
913+ : QObject(parent)
914+ , m_currentIndex(-1)
915+{
916+}
917+
918+QUrl DeclarativePlaylist::currentItemSource() const
919+{
920+ return itemSource(currentIndex());
921+}
922+
923+int DeclarativePlaylist::currentIndex() const
924+{
925+ return m_currentIndex;
926+}
927+
928+void DeclarativePlaylist::setCurrentIndex(int index)
929+{
930+ if (currentIndex() == index)
931+ return;
932+
933+ m_currentIndex = index;
934+ Q_EMIT currentIndexChanged();
935+ Q_EMIT currentItemSourceChanged();
936+}
937+
938+QUrl DeclarativePlaylist::itemSource(int index) const
939+{
940+ if (index < 0 || index >= m_medias.count())
941+ return QUrl();
942+ return m_medias[index];
943+}
944+
945+bool DeclarativePlaylist::addItem(const QUrl &source)
946+{
947+ m_medias << source;
948+ setCurrentIndex(0);
949+ return true;
950+}
951+
952+bool DeclarativePlaylist::addItems(const QList<QUrl> &sources)
953+{
954+ m_medias << sources;
955+ if (!sources.isEmpty())
956+ setCurrentIndex(0);
957+ return true;
958+}
959+
960+bool DeclarativePlaylist::clear()
961+{
962+ m_medias.clear();
963+ setCurrentIndex(-1);
964+ return true;
965+}
966
967=== added file 'tests/mocks/QtMultimedia/declarativeplaylist.h'
968--- tests/mocks/QtMultimedia/declarativeplaylist.h 1970-01-01 00:00:00 +0000
969+++ tests/mocks/QtMultimedia/declarativeplaylist.h 2015-12-04 12:30:34 +0000
970@@ -0,0 +1,54 @@
971+/*
972+ * Copyright (C) 2015 Canonical, Ltd.
973+ *
974+ * This program is free software; you can redistribute it and/or modify
975+ * it under the terms of the GNU General Public License as published by
976+ * the Free Software Foundation; version 3.
977+ *
978+ * This program is distributed in the hope that it will be useful,
979+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
980+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
981+ * GNU General Public License for more details.
982+ *
983+ * You should have received a copy of the GNU General Public License
984+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
985+ *
986+ */
987+
988+#ifndef DECLARATIVEPLAYLIST_H
989+#define DECLARATIVEPLAYLIST_H
990+
991+#include <QObject>
992+#include <QUrl>
993+
994+class DeclarativePlaylist : public QObject
995+{
996+ Q_OBJECT
997+ Q_PROPERTY(QUrl currentItemSource READ currentItemSource NOTIFY currentItemSourceChanged)
998+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
999+
1000+public:
1001+ DeclarativePlaylist(QObject *parent = 0);
1002+
1003+ QUrl currentItemSource() const;
1004+ int currentIndex() const;
1005+ void setCurrentIndex(int currentIndex);
1006+
1007+public Q_SLOTS:
1008+ QUrl itemSource(int index) const;
1009+ bool addItem(const QUrl &source);
1010+ bool addItems(const QList<QUrl> &sources);
1011+ bool clear();
1012+
1013+Q_SIGNALS:
1014+ void currentItemSourceChanged();
1015+ void currentIndexChanged();
1016+
1017+private:
1018+ Q_DISABLE_COPY(DeclarativePlaylist)
1019+
1020+ int m_currentIndex;
1021+ QList<QUrl> m_medias;
1022+};
1023+
1024+#endif
1025
1026=== modified file 'tests/mocks/QtMultimedia/plugin.cpp'
1027--- tests/mocks/QtMultimedia/plugin.cpp 2015-06-08 11:37:27 +0000
1028+++ tests/mocks/QtMultimedia/plugin.cpp 2015-12-04 12:30:34 +0000
1029@@ -18,6 +18,7 @@
1030
1031 #include "plugin.h"
1032 #include "audio.h"
1033+#include "declarativeplaylist.h"
1034
1035 #include <QtQml/qqml.h>
1036
1037@@ -26,4 +27,5 @@
1038 Q_ASSERT(uri == QLatin1String("QtMultimedia"));
1039 qmlRegisterType<Audio>(uri, 5, 0, "Audio");
1040 qmlRegisterType<Audio>(uri, 5, 0, "MediaPlayer");
1041+ qmlRegisterType<DeclarativePlaylist>(uri, 5, 4, "Playlist");
1042 }
1043
1044=== modified file 'tests/mocks/Unity/CMakeLists.txt'
1045--- tests/mocks/Unity/CMakeLists.txt 2015-10-14 09:23:16 +0000
1046+++ tests/mocks/Unity/CMakeLists.txt 2015-12-04 12:30:34 +0000
1047@@ -7,7 +7,7 @@
1048 add_subdirectory(DashCommunicator)
1049
1050 pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
1051-pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=8)
1052+pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=9)
1053
1054 include_directories(
1055 ${CMAKE_CURRENT_BINARY_DIR}
1056
1057=== modified file 'tests/plugins/Dash/cardcreator/1.res'
1058--- tests/plugins/Dash/cardcreator/1.res 2015-10-23 10:16:09 +0000
1059+++ tests/plugins/Dash/cardcreator/1.res 2015-12-04 12:30:34 +0000
1060@@ -3,6 +3,7 @@
1061 property var components;
1062 property var cardData;
1063 property string artShapeStyle: "inset";
1064+ property string backgroundShapeStyle: "inset";
1065 property real fontScale: 1.0;
1066 property var scopeStyle: null;
1067 property int titleAlignment: Text.AlignLeft;
1068
1069=== modified file 'tests/plugins/Dash/cardcreator/2.res'
1070--- tests/plugins/Dash/cardcreator/2.res 2015-08-24 15:00:19 +0000
1071+++ tests/plugins/Dash/cardcreator/2.res 2015-12-04 12:30:34 +0000
1072@@ -3,6 +3,7 @@
1073 property var components;
1074 property var cardData;
1075 property string artShapeStyle: "inset";
1076+ property string backgroundShapeStyle: "inset";
1077 property real fontScale: 1.0;
1078 property var scopeStyle: null;
1079 property int titleAlignment: Text.AlignLeft;
1080@@ -23,6 +24,14 @@
1081 sourceComponent: UbuntuShape {
1082 objectName: "background";
1083 radius: "medium";
1084+ aspect: {
1085+ switch (root.backgroundShapeStyle) {
1086+ case "inset": return UbuntuShape.Inset;
1087+ case "shadow": return UbuntuShape.DropShadow;
1088+ default:
1089+ case "flat": return UbuntuShape.Flat;
1090+ }
1091+ }
1092 backgroundColor: getColor(0) || "white";
1093 secondaryBackgroundColor: getColor(1) || backgroundColor;
1094 backgroundMode: UbuntuShape.VerticalGradient;
1095
1096=== modified file 'tests/plugins/Dash/cardcreator/3.res'
1097--- tests/plugins/Dash/cardcreator/3.res 2015-10-23 10:16:09 +0000
1098+++ tests/plugins/Dash/cardcreator/3.res 2015-12-04 12:30:34 +0000
1099@@ -3,6 +3,7 @@
1100 property var components;
1101 property var cardData;
1102 property string artShapeStyle: "inset";
1103+ property string backgroundShapeStyle: "inset";
1104 property real fontScale: 1.0;
1105 property var scopeStyle: null;
1106 property int titleAlignment: Text.AlignLeft;
1107
1108=== modified file 'tests/plugins/Dash/cardcreator/4.res'
1109--- tests/plugins/Dash/cardcreator/4.res 2015-10-23 10:16:09 +0000
1110+++ tests/plugins/Dash/cardcreator/4.res 2015-12-04 12:30:34 +0000
1111@@ -3,6 +3,7 @@
1112 property var components;
1113 property var cardData;
1114 property string artShapeStyle: "inset";
1115+ property string backgroundShapeStyle: "inset";
1116 property real fontScale: 1.0;
1117 property var scopeStyle: null;
1118 property int titleAlignment: Text.AlignLeft;
1119
1120=== modified file 'tests/plugins/Dash/cardcreator/5.res'
1121--- tests/plugins/Dash/cardcreator/5.res 2015-10-23 10:16:09 +0000
1122+++ tests/plugins/Dash/cardcreator/5.res 2015-12-04 12:30:34 +0000
1123@@ -3,6 +3,7 @@
1124 property var components;
1125 property var cardData;
1126 property string artShapeStyle: "inset";
1127+ property string backgroundShapeStyle: "inset";
1128 property real fontScale: 1.0;
1129 property var scopeStyle: null;
1130 property int titleAlignment: Text.AlignLeft;
1131
1132=== modified file 'tests/plugins/Dash/cardcreator/6.res'
1133--- tests/plugins/Dash/cardcreator/6.res 2015-08-24 15:00:19 +0000
1134+++ tests/plugins/Dash/cardcreator/6.res 2015-12-04 12:30:34 +0000
1135@@ -3,6 +3,7 @@
1136 property var components;
1137 property var cardData;
1138 property string artShapeStyle: "inset";
1139+ property string backgroundShapeStyle: "inset";
1140 property real fontScale: 1.0;
1141 property var scopeStyle: null;
1142 property int titleAlignment: Text.AlignLeft;
1143@@ -23,6 +24,14 @@
1144 sourceComponent: UbuntuShape {
1145 objectName: "background";
1146 radius: "medium";
1147+ aspect: {
1148+ switch (root.backgroundShapeStyle) {
1149+ case "inset": return UbuntuShape.Inset;
1150+ case "shadow": return UbuntuShape.DropShadow;
1151+ default:
1152+ case "flat": return UbuntuShape.Flat;
1153+ }
1154+ }
1155 backgroundColor: getColor(0) || "white";
1156 secondaryBackgroundColor: getColor(1) || backgroundColor;
1157 backgroundMode: UbuntuShape.VerticalGradient;
1158
1159=== modified file 'tests/plugins/Dash/cardcreator/7.res'
1160--- tests/plugins/Dash/cardcreator/7.res 2015-08-24 15:00:19 +0000
1161+++ tests/plugins/Dash/cardcreator/7.res 2015-12-04 12:30:34 +0000
1162@@ -3,6 +3,7 @@
1163 property var components;
1164 property var cardData;
1165 property string artShapeStyle: "inset";
1166+ property string backgroundShapeStyle: "inset";
1167 property real fontScale: 1.0;
1168 property var scopeStyle: null;
1169 property int titleAlignment: Text.AlignLeft;
1170@@ -23,6 +24,14 @@
1171 sourceComponent: UbuntuShape {
1172 objectName: "background";
1173 radius: "medium";
1174+ aspect: {
1175+ switch (root.backgroundShapeStyle) {
1176+ case "inset": return UbuntuShape.Inset;
1177+ case "shadow": return UbuntuShape.DropShadow;
1178+ default:
1179+ case "flat": return UbuntuShape.Flat;
1180+ }
1181+ }
1182 backgroundColor: getColor(0) || "white";
1183 secondaryBackgroundColor: getColor(1) || backgroundColor;
1184 backgroundMode: UbuntuShape.VerticalGradient;
1185
1186=== modified file 'tests/plugins/Dash/cardcreator/8.res'
1187--- tests/plugins/Dash/cardcreator/8.res 2015-08-24 15:00:19 +0000
1188+++ tests/plugins/Dash/cardcreator/8.res 2015-12-04 12:30:34 +0000
1189@@ -3,6 +3,7 @@
1190 property var components;
1191 property var cardData;
1192 property string artShapeStyle: "inset";
1193+ property string backgroundShapeStyle: "inset";
1194 property real fontScale: 1.0;
1195 property var scopeStyle: null;
1196 property int titleAlignment: Text.AlignLeft;
1197@@ -23,6 +24,14 @@
1198 sourceComponent: UbuntuShape {
1199 objectName: "background";
1200 radius: "medium";
1201+ aspect: {
1202+ switch (root.backgroundShapeStyle) {
1203+ case "inset": return UbuntuShape.Inset;
1204+ case "shadow": return UbuntuShape.DropShadow;
1205+ default:
1206+ case "flat": return UbuntuShape.Flat;
1207+ }
1208+ }
1209 backgroundColor: getColor(0) || "white";
1210 secondaryBackgroundColor: getColor(1) || backgroundColor;
1211 backgroundMode: UbuntuShape.VerticalGradient;
1212
1213=== added file 'tests/plugins/Dash/cardcreator/9.res'
1214--- tests/plugins/Dash/cardcreator/9.res 1970-01-01 00:00:00 +0000
1215+++ tests/plugins/Dash/cardcreator/9.res 2015-12-04 12:30:34 +0000
1216@@ -0,0 +1,113 @@
1217+AbstractButton {
1218+ id: root;
1219+ property var components;
1220+ property var cardData;
1221+ property string artShapeStyle: "inset";
1222+ property string backgroundShapeStyle: "inset";
1223+ property real fontScale: 1.0;
1224+ property var scopeStyle: null;
1225+ property int titleAlignment: Text.AlignLeft;
1226+ property int fixedHeaderHeight: -1;
1227+ property size fixedArtShapeSize: Qt.size(-1, -1);
1228+ readonly property string title: cardData && cardData["title"] || "";
1229+ property bool asynchronous: true;
1230+ property bool showHeader: true;
1231+ implicitWidth: childrenRect.width;
1232+ enabled: true;
1233+
1234+readonly property size artShapeSize: Qt.size(-1, -1);
1235+readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + audioProgressBar.height + audioProgressBar.anchors.topMargin;
1236+Label {
1237+ id: titleLabel;
1238+ objectName: "titleLabel";
1239+ anchors { right: parent.right;
1240+rightMargin: units.gu(1);
1241+left: audioButton.right;
1242+ leftMargin: units.gu(1);
1243+top: parent.top;
1244+ topMargin: units.gu(1);
1245+ }
1246+ elide: Text.ElideRight;
1247+ fontSize: "small";
1248+ wrapMode: Text.Wrap;
1249+ maximumLineCount: 2;
1250+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1251+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
1252+ visible: showHeader ;
1253+ width: undefined;
1254+ text: root.title;
1255+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
1256+ horizontalAlignment: root.titleAlignment;
1257+ }
1258+Label {
1259+ id: subtitleLabel;
1260+ objectName: "subtitleLabel";
1261+ anchors { left: titleLabel.left;
1262+ leftMargin: titleLabel.leftMargin;
1263+rightMargin: units.gu(1);
1264+right: titleLabel.right;
1265+top: titleLabel.bottom;
1266+ }
1267+ anchors.topMargin: units.dp(2);
1268+ elide: Text.ElideRight;
1269+ maximumLineCount: 1;
1270+ fontSize: "x-small";
1271+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1272+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
1273+ visible: titleLabel.visible && titleLabel.text;
1274+ text: cardData && cardData["subtitle"] || "";
1275+ font.weight: Font.Light;
1276+ }
1277+CardAudioProgress {
1278+ id: audioProgressBar;
1279+ duration: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["duration"]) || 0;
1280+ source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || "";
1281+ anchors {
1282+ bottom: audioButton.bottom;
1283+ left: audioButton.right;
1284+ right: parent.right;
1285+ margins: units.gu(1);
1286+ }
1287+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
1288+ }AbstractButton {
1289+ id: audioButton;
1290+ anchors.fill: undefined;
1291+ width: height;
1292+ height: (root.fixedHeaderHeight > 0 ? root.fixedHeaderHeight : headerHeight) + 2 * units.gu(1);
1293+ readonly property url source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || "";
1294+ UbuntuShape {
1295+ anchors.fill: parent;
1296+ visible: parent.pressed;
1297+ radius: "medium";
1298+ }
1299+ Icon {
1300+ anchors.fill: parent;
1301+ anchors.margins: parent.height > units.gu(5) ? units.gu(2) : 0;
1302+ opacity: 0.9;
1303+ name: DashAudioPlayer.playing && AudioUrlComparer.compare(parent.source, DashAudioPlayer.currentSource) ? "media-playback-pause" : "media-playback-start";
1304+ }
1305+ onClicked: {
1306+ if (AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)) {
1307+ if (DashAudioPlayer.playing) {
1308+ DashAudioPlayer.pause();
1309+ } else {
1310+ DashAudioPlayer.play();
1311+ }
1312+ } else {
1313+ var playlist = (cardData["quickPreviewData"] && cardData["quickPreviewData"]["playlist"]) || null;
1314+ DashAudioPlayer.playSource(source, playlist);
1315+ }
1316+ }
1317+ onPressAndHold: {
1318+ root.pressAndHold();
1319+ }
1320+ }UbuntuShape {
1321+ id: touchdown;
1322+ objectName: "touchdown";
1323+ anchors { fill: root }
1324+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
1325+ radius: "medium";
1326+ borderSource: "radius_pressed.sci"
1327+ }
1328+implicitHeight: audioButton.height;
1329+}
1330
1331=== added file 'tests/plugins/Dash/cardcreator/9.tst'
1332--- tests/plugins/Dash/cardcreator/9.tst 1970-01-01 00:00:00 +0000
1333+++ tests/plugins/Dash/cardcreator/9.tst 2015-12-04 12:30:34 +0000
1334@@ -0,0 +1,3 @@
1335+template: {"card-layout":"horizontal","card-size":"medium","category-layout":"grid","collapsed-rows":2,"quick-preview-type": "audio"}
1336+components: {"art":{"aspect-ratio":1},"subtitle":{"field":"author"},"title":{"field":"title"}, "quickPreviewData": "quickPreviewData"}
1337+result: 9.res
1338
1339=== modified file 'tests/qmltests/Dash/CardHelpers.js'
1340--- tests/qmltests/Dash/CardHelpers.js 2014-09-05 07:27:00 +0000
1341+++ tests/qmltests/Dash/CardHelpers.js 2015-12-04 12:30:34 +0000
1342@@ -16,7 +16,7 @@
1343
1344 .pragma library
1345
1346-var components = ["title", "art", "subtitle", "mascot", "emblem", "summary", "attributes", "overlayColor"]
1347+var components = ["title", "art", "subtitle", "mascot", "emblem", "summary", "attributes", "overlayColor", "quickPreviewData"]
1348
1349 var defaultLayout = ' \
1350 { \
1351
1352=== modified file 'tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml'
1353--- tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml 2015-07-15 15:07:19 +0000
1354+++ tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml 2015-12-04 12:30:34 +0000
1355@@ -18,6 +18,7 @@
1356 import QtTest 1.0
1357 import Ubuntu.Components 1.3
1358 import "../../../../qml/Dash/Previews"
1359+import Dash 0.1
1360 import Unity.Test 0.1 as UT
1361 import QtMultimedia 5.0
1362
1363@@ -58,8 +59,8 @@
1364 function test_time_formatter_data() {
1365 return [
1366 { tag: "NaN", value: "not a number", result: "" },
1367- { tag: "0", value: 0, result: "" },
1368 { tag: "-1", value: -1, result: "" },
1369+ { tag: "0", value: 0, result: "0:00" },
1370 { tag: "30", value: 30, result: "0:30" },
1371 { tag: "60", value: 60, result: "1:00" },
1372 { tag: "3600", value: 3600, result: "1:00:00" }
1373@@ -67,8 +68,7 @@
1374 }
1375
1376 function test_time_formatter(data) {
1377- var audio = findInvisibleChild(previewAudioPlayback, "audio");
1378- compare(audio.lengthToString(data.value), data.result)
1379+ compare(DashAudioPlayer.lengthToString(data.value), data.result)
1380 }
1381
1382 function test_tracks_data() {
1383@@ -102,7 +102,7 @@
1384
1385 function checkPlayerSource(index) {
1386 var modelFilename = previewAudioPlayback.widgetData["tracks"][index]["source"].replace(/^.*[\\\/]/, '');
1387- var playerFilename = findInvisibleChild(previewAudioPlayback, "audio").source.toString().replace(/^.*[\\\/]/, '');
1388+ var playerFilename = DashAudioPlayer.currentSource.toString().replace(/^.*[\\\/]/, '');
1389
1390 compare(modelFilename, playerFilename, "Player source is not set correctly.");
1391 }
1392@@ -123,7 +123,7 @@
1393 var track1PlayButton = findChild(track1Item, "playButton");
1394 var track2PlayButton = findChild(track2Item, "playButton");
1395
1396- var audio = findInvisibleChild(previewAudioPlayback, "audio");
1397+ var audio = DashAudioPlayer.audio;
1398
1399 // All progress bars must be hidden in the beginning
1400 compare(track0ProgressBar.visible, false);
1401@@ -170,10 +170,6 @@
1402 tryCompare(track0ProgressBar, "visible", false);
1403 tryCompare(track1ProgressBar, "visible", false);
1404 tryCompare(track2ProgressBar, "visible", true);
1405-
1406- // Changing preview should make all players shut up!
1407- previewAudioPlayback.isCurrentPreview = false
1408- tryCompare(audio, "playbackState", Audio.StoppedState);
1409 }
1410 }
1411 }
1412
1413=== modified file 'tests/qmltests/Dash/tst_Card.qml'
1414--- tests/qmltests/Dash/tst_Card.qml 2015-11-04 14:57:13 +0000
1415+++ tests/qmltests/Dash/tst_Card.qml 2015-12-04 12:30:34 +0000
1416@@ -35,7 +35,8 @@
1417 "title": "foo",
1418 "subtitle": "bar",
1419 "summary": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
1420- "attributes": [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}]
1421+ "attributes": [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}],
1422+ "quickPreviewData": {"uri": "/some/file", "duration": "14"}
1423 }'
1424
1425 property var cardsModel: [
1426@@ -106,6 +107,11 @@
1427 "layout": { "template": { "card-layout": "horizontal" },
1428 "components": JSON.parse(Helpers.fullMapping) }
1429 },
1430+ {
1431+ "name": "Art, title, subtitle - Audio",
1432+ "layout": { "template": { "card-layout": "horizontal", "quick-preview-type": "audio" },
1433+ "components": { "art": "art", "title": "title", "subtitle": "subtitle", "quickPreviewData": "quickPreviewData" } }
1434+ },
1435 ]
1436
1437 CardTool {
1438@@ -129,6 +135,7 @@
1439 item.width = Qt.binding(function() { return cardTool.cardWidth || item.implicitWidth; });
1440 item.height = Qt.binding(function() { return cardTool.cardHeight || item.implicitHeight; });
1441 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
1442+ item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
1443 }
1444 }
1445

Subscribers

People subscribed via source and target branches