Merge lp:~ahayzen/music-app/bottom-edge-implementation-001 into lp:music-app/trusty

Proposed by Andrew Hayzen
Status: Rejected
Rejected by: Victor Thompson
Proposed branch: lp:~ahayzen/music-app/bottom-edge-implementation-001
Merge into: lp:music-app/trusty
Diff against target: 2815 lines (+1586/-904)
10 files modified
MusicNowPlaying.qml (+15/-4)
MusicToolbar.qml (+1026/-889)
Player.qml (+4/-1)
common/AlbumsPage.qml (+0/-1)
common/MusicPage.qml (+7/-1)
common/PageWithBottomEdge.qml (+512/-0)
common/SongsPage.qml (+1/-1)
music-app.qml (+7/-7)
tests/autopilot/music_app/__init__.py (+6/-0)
tests/autopilot/music_app/tests/test_music.py (+8/-0)
To merge this branch: bzr merge lp:~ahayzen/music-app/bottom-edge-implementation-001
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Needs Fixing
Victor Thompson Needs Fixing
Review via email: mp+230303@code.launchpad.net

Commit message

* Add bottom edge support for now playing page across all MusicPages
* Reparent the same now playing page for all bottom edges

Description of the change

* Add bottom edge support for now playing page across all MusicPages
* Reparent the same now playing page for all bottom edges

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
536. By Andrew Hayzen

* Fix for console errors
* Improvements for ap tests

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
537. By Andrew Hayzen

* Fixes for ap

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
538. By Andrew Hayzen

* Add wait for isReady

539. By Andrew Hayzen

* Remove unneeded property alias

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
540. By Andrew Hayzen

* Sync with upstream bottom edge

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
541. By Andrew Hayzen

* Fix for panel state dragging

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Victor Thompson (vthompson) wrote :

One small thing I just noticed is that sometimes the toolbar can not be exposed by simply swiping from the bottom. However, when this happens you can swipe up if you manage to precisely swipe up the hidden hint for the bottom edge.

To reproduce: 1) Click a view that pops a page onto the stack (select an album), 2) try to swipe up from the bottom.

I assume this has something to do with the pagestack.

review: Needs Fixing
542. By Andrew Hayzen

* Fix for margin on stacked pages

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Victor Thompson (vthompson) wrote :

Comments:

1. I think we should start putting upstream code in a directory other than "common". I suggest we adopt the same name as the Clock reboot, which uses "upstreamcomponents".
2. I see the following error in the logs, not sure if it was introudced here:

file:///opt/click.ubuntu.com/com.ubuntu.music/1.3.542/music-app.qml:963:9: QML M
usicNowPlaying: Cannot anchor to an item that isn't a parent or sibling.

I also added a few inline comments.

review: Needs Fixing
543. By Andrew Hayzen

* Fixes for some inline diff comments

544. By Andrew Hayzen

* Merge of trunk

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
545. By Andrew Hayzen

* Merge of trunk

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Victor Thompson (vthompson) wrote :

Setting this to WIP, as we have decided to wait until the 'remix' of the app and implement this feature in the new design, if appropriate.

Unmerged revisions

545. By Andrew Hayzen

* Merge of trunk

544. By Andrew Hayzen

* Merge of trunk

543. By Andrew Hayzen

* Fixes for some inline diff comments

542. By Andrew Hayzen

* Fix for margin on stacked pages

541. By Andrew Hayzen

* Fix for panel state dragging

540. By Andrew Hayzen

* Sync with upstream bottom edge

539. By Andrew Hayzen

* Remove unneeded property alias

538. By Andrew Hayzen

* Add wait for isReady

537. By Andrew Hayzen

* Fixes for ap

536. By Andrew Hayzen

* Fix for console errors
* Improvements for ap tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'MusicNowPlaying.qml'
2--- MusicNowPlaying.qml 2014-08-17 23:58:29 +0000
3+++ MusicNowPlaying.qml 2014-08-21 20:46:47 +0000
4@@ -31,9 +31,12 @@
5 id: nowPlaying
6 objectName: "nowplayingpage"
7 title: i18n.tr("Now Playing")
8- visible: false
9+ visible: true
10
11 property int ensureVisibleIndex: 0 // ensure first index is visible at startup
12+ property var parentCache // cache of parent for reparent()
13+
14+ bottomEdgeEnabled: false
15
16 Rectangle {
17 anchors.fill: parent
18@@ -80,6 +83,14 @@
19 queuelist.contentY -= header.height;
20 }
21
22+ function reparent(newParent) {
23+ if (parentCache !== newParent) {
24+ nowPlaying.parent = newParent
25+ nowPlaying.anchors.fill = newParent
26+ parentCache = newParent
27+ }
28+ }
29+
30 ListView {
31 id: queuelist
32 objectName: "queuelist"
33@@ -348,10 +359,10 @@
34 }
35
36 onRunningChanged: {
37- if (running === false && ensureVisibleIndex != -1)
38+ if (running === false && nowPlaying.ensureVisibleIndex != -1)
39 {
40- queuelist.positionViewAtIndex(ensureVisibleIndex, ListView.Beginning);
41- ensureVisibleIndex = -1;
42+ queuelist.positionViewAtIndex(nowPlaying.ensureVisibleIndex, ListView.Beginning);
43+ nowPlaying.ensureVisibleIndex = -1;
44 }
45 }
46 }
47
48=== modified file 'MusicToolbar.qml'
49--- MusicToolbar.qml 2014-08-18 00:02:37 +0000
50+++ MusicToolbar.qml 2014-08-21 20:46:47 +0000
51@@ -24,12 +24,15 @@
52 import Ubuntu.Components.Popups 0.1
53 import "settings.js" as Settings
54
55-Item {
56- anchors {
57- bottom: parent.bottom
58- left: parent.left
59- right: parent.right
60- }
61+Panel {
62+ id: musicToolbarPanel
63+ align: Qt.AlignCenter
64+ height: currentMode === "full" ? fullHeight : expandedHeight
65+ locked: true
66+ width: parent.width
67+ x: 0
68+ y: currentPage === null ? 0 : currentPage.height
69+ z: 200
70
71 // Properties storing the current page info
72 property var currentPage: null
73@@ -43,13 +46,63 @@
74 property int transitionDuration: 100
75
76 property alias currentHeight: musicToolbarPanel.height
77- property alias minimizedHeight: musicToolbarPanel.minimizedHeight
78- property alias expandedHeight: musicToolbarPanel.expandedHeight
79- property alias fullHeight: musicToolbarPanel.fullHeight
80 property alias mouseAreaOffset: musicToolbarPanel.hintSize
81
82- property alias animating: musicToolbarPanel.animating
83- property alias opened: musicToolbarPanel.opened
84+ // The current mode of the controls
85+ property string currentMode: wideAspect || isNowPlaying(currentPage)
86+ ? "full" : "expanded"
87+
88+ // Properties for the different heights
89+ property int minimizedHeight: units.gu(0.5)
90+ property int expandedHeight: units.gu(8)
91+ property int fullHeight: units.gu(11)
92+
93+ onCurrentModeChanged: {
94+ musicToolbarFullProgressMouseArea.enabled = currentMode === "full"
95+ }
96+
97+ onHeightChanged: {
98+ if (currentPage !== null && !currentPage.floating) {
99+ if (shown) {
100+ y = currentPage.height - height
101+ } else {
102+ y = currentPage.height
103+ }
104+ }
105+ }
106+
107+ onOpenedChanged: {
108+ onToolbarShownChanged(opened, currentPage, currentTab);
109+
110+ if (opened) {
111+ startAutoHideTimer();
112+ }
113+ }
114+
115+ onShownChanged: {
116+ onToolbarShownChanged(shown, currentPage, currentTab);
117+
118+ if (shown) {
119+ startAutoHideTimer();
120+ }
121+ }
122+
123+ onYChanged: {
124+ if (currentPage !== null) {
125+ if (y <= currentPage.height - height) {
126+ shown = true
127+ } else {
128+ shown = false
129+ }
130+ }
131+ }
132+
133+ Behavior on y {
134+ // don't animate if the bottomedge is being dragged
135+ enabled: !currentPage.floating
136+ UbuntuNumberAnimation {
137+ }
138+ }
139
140 Connections {
141 id: pageStackConn
142@@ -59,14 +112,27 @@
143 previousPage = currentPage;
144
145 // If going back from nowPlaying jump back to tabs
146- if (previousPage === nowPlaying && mainPageStack.currentPage !== nowPlaying) {
147+ if (isNowPlaying(previousPage) && !isNowPlaying(mainPageStack.currentPage)) {
148+ tabs.selectedTab.page.forceExpandedStateNoAnimation() // ensure main tab bottom edge state will animate
149+
150 while (mainPageStack.depth > 1) {
151- mainPageStack.pop(mainPageStack.currentPage)
152+ mainPageStack.currentPage.bottomEdgeState = "collapsed" // ensure bottom edge state is reset
153+ mainPageStack.pop()
154 }
155 }
156 }
157 }
158
159+ Connections {
160+ target: mainView
161+ onWideAspectChanged: {
162+ // Force toolbar to show if in wideAspect
163+ if (wideAspect && !shown) {
164+ showToolbar();
165+ }
166+ }
167+ }
168+
169 /* Helper functions */
170
171 // Disable the toolbar for this page/view (eg a dialog)
172@@ -103,10 +169,15 @@
173 function hideToolbar()
174 {
175 if (!wideAspect) {
176- musicToolbarPanel.close();
177+ y = currentPage.height
178 }
179
180- toolbarAutoHideTimer.stop(); // cancel any autohide
181+ stopAutoHideTimer(); // cancel any autohide
182+ }
183+
184+ // Return true if the page is now playing
185+ function isNowPlaying(page) {
186+ return page === nowPlaying
187 }
188
189 // Remove sheet as it has been closed
190@@ -135,161 +206,132 @@
191 // Show the toolbar
192 function showToolbar()
193 {
194- startAutohideTimer(); // always attempt to autohide toolbar
195+ startAutoHideTimer(); // always attempt to autohide toolbar
196
197- if (!musicToolbarPanel.opened) {
198- musicToolbarPanel.open();
199- }
200+ y = currentPage.height - height
201 }
202
203 // Start the autohidetimer
204- function startAutohideTimer()
205+ function startAutoHideTimer()
206 {
207 toolbarAutoHideTimer.restart();
208 }
209
210- Connections {
211- target: mainView
212- onWideAspectChanged: {
213- // Force toolbar to show if in wideAspect
214- if (wideAspect && !opened) {
215- showToolbar();
216- }
217- }
218+ function stopAutoHideTimer()
219+ {
220+ toolbarAutoHideTimer.stop()
221 }
222
223- Panel {
224- id: musicToolbarPanel
225+ /* Full toolbar */
226+ Rectangle {
227+ id: musicToolbarFullContainer
228 anchors {
229- left: parent.left
230- right: parent.right
231- bottom: parent.bottom
232- }
233- height: currentMode === "full" ? fullHeight : expandedHeight
234- locked: wideAspect
235-
236- __closeOnContentsClicks: false // TODO: fix bug 1295720
237-
238- // The current mode of the controls
239- property string currentMode: wideAspect || (currentPage === nowPlaying)
240- ? "full" : "expanded"
241-
242- // Properties for the different heights
243- property int minimizedHeight: units.gu(0.5)
244- property int expandedHeight: units.gu(8)
245- property int fullHeight: units.gu(11)
246-
247- onCurrentModeChanged: {
248- musicToolbarFullProgressMouseArea.enabled = currentMode === "full"
249- }
250-
251- onOpenedChanged: {
252- onToolbarShownChanged(opened, currentPage, currentTab);
253-
254- if (opened) {
255- startAutohideTimer();
256- }
257- }
258-
259- /* Full toolbar */
260+ fill: parent
261+ }
262+ color: styleMusic.toolbar.fullBackgroundColor
263+ visible: musicToolbarPanel.currentMode === "full"
264+
265+ /* Buttons component */
266 Rectangle {
267- id: musicToolbarFullContainer
268- anchors {
269- fill: parent
270- }
271- color: styleMusic.toolbar.fullBackgroundColor
272- visible: musicToolbarPanel.currentMode === "full"
273-
274- /* Buttons component */
275- Rectangle {
276- id: musicToolbarFullButtonsContainer
277- anchors.left: parent.left
278- anchors.top: musicToolbarFullProgressContainer.bottom
279- color: "transparent"
280- height: parent.height - musicToolbarFullProgressContainer.height
281- width: parent.width
282-
283- /* Column for labels in wideAspect */
284- Column {
285- id: nowPlayingWideAspectLabels
286- anchors {
287- left: parent.left
288- leftMargin: units.gu(1)
289- right: nowPlayingRepeatButton.left
290- rightMargin: units.gu(1)
291- verticalCenter: parent.verticalCenter
292- }
293- visible: wideAspect
294-
295- /* Clicking in the area shows the queue */
296- function trigger() {
297- if (trackQueue.model.count !== 0 && currentPage !== nowPlaying) {
298- tabs.pushNowPlaying();
299- }
300- else if (currentPage === nowPlaying) {
301- musicToolbar.goBack();
302- }
303- }
304-
305- /* Title of track */
306- Label {
307- id: nowPlayingWideAspectTitle
308- anchors {
309- left: parent.left
310- leftMargin: units.gu(1)
311- right: parent.right
312- rightMargin: units.gu(1)
313- }
314- color: styleMusic.playerControls.labelColor
315- elide: Text.ElideRight
316- fontSize: "medium"
317- objectName: "playercontroltitle"
318- text: trackQueue.model.count === 0 ? "" : player.currentMetaTitle === "" ? player.currentMetaFile : player.currentMetaTitle
319- }
320-
321- /* Artist of track */
322- Label {
323- id: nowPlayingWideAspectArtist
324- anchors {
325- left: parent.left
326- leftMargin: units.gu(1)
327- right: parent.right
328- rightMargin: units.gu(1)
329- }
330- color: styleMusic.playerControls.labelColor
331- elide: Text.ElideRight
332- fontSize: "small"
333- text: trackQueue.model.count === 0 ? "" : player.currentMetaArtist
334- }
335-
336- /* Album of track */
337- Label {
338- id: nowPlayingWideAspectAlbum
339- anchors {
340- left: parent.left
341- leftMargin: units.gu(1)
342- right: parent.right
343- rightMargin: units.gu(1)
344- }
345- color: styleMusic.playerControls.labelColor
346- elide: Text.ElideRight
347- fontSize: "small"
348- text: trackQueue.model.count === 0 ? "" : player.currentMetaAlbum
349- }
350- }
351-
352- /* Repeat button */
353- Item {
354- id: nowPlayingRepeatButton
355- objectName: "repeatShape"
356- anchors.right: nowPlayingPreviousButton.left
357- anchors.rightMargin: units.gu(1)
358- anchors.verticalCenter: parent.verticalCenter
359- height: units.gu(6)
360- opacity: player.repeat && !emptyPage.noMusic ? 1 : .4
361- width: height
362-
363- function trigger() {
364+ id: musicToolbarFullButtonsContainer
365+ anchors.left: parent.left
366+ anchors.top: musicToolbarFullProgressContainer.bottom
367+ color: "transparent"
368+ height: parent.height - musicToolbarFullProgressContainer.height
369+ width: parent.width
370+
371+ /* Column for labels in wideAspect */
372+ Column {
373+ id: nowPlayingWideAspectLabels
374+ anchors {
375+ left: parent.left
376+ leftMargin: units.gu(1)
377+ right: nowPlayingRepeatButton.left
378+ rightMargin: units.gu(1)
379+ }
380+ visible: wideAspect
381+
382+ /* Title of track */
383+ Label {
384+ id: nowPlayingWideAspectTitle
385+ anchors {
386+ left: parent.left
387+ leftMargin: units.gu(1)
388+ right: parent.right
389+ rightMargin: units.gu(1)
390+ }
391+ color: styleMusic.playerControls.labelColor
392+ elide: Text.ElideRight
393+ fontSize: "medium"
394+ objectName: "playercontroltitle"
395+ text: player.currentMetaTitle === "" ? player.currentMetaFile : player.currentMetaTitle
396+ }
397+
398+ /* Artist of track */
399+ Label {
400+ id: nowPlayingWideAspectArtist
401+ anchors {
402+ left: parent.left
403+ leftMargin: units.gu(1)
404+ right: parent.right
405+ rightMargin: units.gu(1)
406+ }
407+ color: styleMusic.playerControls.labelColor
408+ elide: Text.ElideRight
409+ fontSize: "small"
410+ text: player.currentMetaArtist
411+ }
412+
413+ /* Album of track */
414+ Label {
415+ id: nowPlayingWideAspectAlbum
416+ anchors {
417+ left: parent.left
418+ leftMargin: units.gu(1)
419+ right: parent.right
420+ rightMargin: units.gu(1)
421+ }
422+ color: styleMusic.playerControls.labelColor
423+ elide: Text.ElideRight
424+ fontSize: "small"
425+ text: player.currentMetaAlbum
426+ }
427+ }
428+
429+ /* Clicking in the area shows the queue */
430+ MouseArea {
431+ anchors {
432+ bottom: parent.bottom
433+ left: parent.left
434+ right: nowPlayingRepeatButton.left
435+ top: parent.top
436+ }
437+ onClicked: {
438+ if (trackQueue.model.count !== 0 && currentPage !== nowPlaying) {
439+ tabs.pushNowPlaying();
440+ }
441+ else if (currentPage === nowPlaying) {
442+ musicToolbar.goBack();
443+ }
444+ }
445+ }
446+
447+ /* Repeat button */
448+ Item {
449+ id: nowPlayingRepeatButton
450+ objectName: "repeatShape"
451+ anchors.right: nowPlayingPreviousButton.left
452+ anchors.rightMargin: units.gu(1)
453+ anchors.verticalCenter: parent.verticalCenter
454+ height: units.gu(6)
455+ opacity: player.repeat && !emptyPage.noMusic ? 1 : .4
456+ width: height
457+
458+ MouseArea {
459+ anchors {
460+ fill: parent
461+ }
462+ onClicked: {
463 if (emptyPage.noMusic) {
464 return;
465 }
466@@ -297,114 +339,124 @@
467 // Invert repeat settings
468 player.repeat = !player.repeat
469 }
470-
471- Image {
472- id: repeatIcon
473- height: units.gu(3)
474- width: height
475- anchors.verticalCenter: parent.verticalCenter
476- anchors.horizontalCenter: parent.horizontalCenter
477- source: Qt.resolvedUrl("images/media-playlist-repeat.svg")
478- verticalAlignment: Text.AlignVCenter
479- opacity: player.repeat && !emptyPage.noMusic ? 1 : .4
480- }
481 }
482
483- /* Previous button */
484- Item {
485- id: nowPlayingPreviousButton
486- anchors.right: nowPlayingPlayButton.left
487- anchors.rightMargin: units.gu(1)
488+ Image {
489+ id: repeatIcon
490+ height: units.gu(3)
491+ width: height
492 anchors.verticalCenter: parent.verticalCenter
493- height: units.gu(6)
494- objectName: "previousshape"
495- opacity: trackQueue.model.count === 0 ? .4 : 1
496- width: height
497-
498- function trigger() {
499+ anchors.horizontalCenter: parent.horizontalCenter
500+ source: Qt.resolvedUrl("images/media-playlist-repeat.svg")
501+ verticalAlignment: Text.AlignVCenter
502+ opacity: player.repeat && !emptyPage.noMusic ? 1 : .4
503+ }
504+ }
505+
506+ /* Previous button */
507+ Item {
508+ id: nowPlayingPreviousButton
509+ anchors.right: nowPlayingPlayButton.left
510+ anchors.rightMargin: units.gu(1)
511+ anchors.verticalCenter: parent.verticalCenter
512+ height: units.gu(6)
513+ objectName: "previousshape"
514+ opacity: trackQueue.model.count === 0 ? .4 : 1
515+ width: height
516+
517+ MouseArea {
518+ anchors {
519+ fill: parent
520+ }
521+ onClicked: {
522 if (trackQueue.model.count === 0) {
523 return;
524 }
525
526 player.previousSong()
527 }
528-
529- Image {
530- id: nowPlayingPreviousIndicator
531- height: units.gu(3)
532- width: height
533- anchors.horizontalCenter: parent.horizontalCenter
534- anchors.verticalCenter: parent.verticalCenter
535- source: Qt.resolvedUrl("images/media-skip-backward.svg")
536- opacity: 1
537- }
538 }
539
540- /* Play/Pause button */
541- Rectangle {
542- id: nowPlayingPlayButton
543+ Image {
544+ id: nowPlayingPreviousIndicator
545+ height: units.gu(3)
546+ width: height
547 anchors.horizontalCenter: parent.horizontalCenter
548 anchors.verticalCenter: parent.verticalCenter
549+ source: Qt.resolvedUrl("images/media-skip-backward.svg")
550+ opacity: 1
551+ }
552+ }
553+
554+ /* Play/Pause button */
555+ Rectangle {
556+ id: nowPlayingPlayButton
557+ anchors.horizontalCenter: parent.horizontalCenter
558+ anchors.verticalCenter: parent.verticalCenter
559+ antialiasing: true
560+ color: styleMusic.toolbar.fullOuterPlayCircleColor
561+ height: units.gu(12)
562+ radius: height / 2
563+ width: height
564+
565+ // draws the outter shadow/highlight
566+ Rectangle {
567+ id: sourceOutterFull
568+ anchors { fill: parent; margins: -units.gu(0.1) }
569+ radius: (width / 2)
570 antialiasing: true
571- color: styleMusic.toolbar.fullOuterPlayCircleColor
572- height: units.gu(12)
573- radius: height / 2
574- width: height
575+ gradient: Gradient {
576+ GradientStop { position: 0.0; color: "black" }
577+ GradientStop { position: 0.5; color: "transparent" }
578+ GradientStop { position: 1.0; color: UbuntuColors.warmGrey }
579+ }
580
581- // draws the outter shadow/highlight
582 Rectangle {
583- id: sourceOutterFull
584- anchors { fill: parent; margins: -units.gu(0.1) }
585- radius: (width / 2)
586+ anchors.horizontalCenter: parent.horizontalCenter
587+ anchors.verticalCenter: parent.verticalCenter
588 antialiasing: true
589- gradient: Gradient {
590- GradientStop { position: 0.0; color: "black" }
591- GradientStop { position: 0.5; color: "transparent" }
592- GradientStop { position: 1.0; color: UbuntuColors.warmGrey }
593- }
594+ color: styleMusic.toolbar.fullOuterPlayCircleColor
595+ height: nowPlayingPlayButton.height - units.gu(.1)
596+ radius: height / 2
597+ width: height
598
599 Rectangle {
600+ id: nowPlayingPlayButtonInner
601 anchors.horizontalCenter: parent.horizontalCenter
602 anchors.verticalCenter: parent.verticalCenter
603 antialiasing: true
604- color: styleMusic.toolbar.fullOuterPlayCircleColor
605- height: nowPlayingPlayButton.height - units.gu(.1)
606+ color: styleMusic.toolbar.fullInnerPlayCircleColor
607+ height: units.gu(7)
608 radius: height / 2
609 width: height
610
611+ // draws the inner shadow/highlight
612 Rectangle {
613- id: nowPlayingPlayButtonInner
614- anchors.horizontalCenter: parent.horizontalCenter
615- anchors.verticalCenter: parent.verticalCenter
616+ id: sourceInnerFull
617+ anchors { fill: parent; margins: -units.gu(0.1) }
618+ radius: (width / 2)
619 antialiasing: true
620- color: styleMusic.toolbar.fullInnerPlayCircleColor
621- height: units.gu(7)
622- radius: height / 2
623- width: height
624+ gradient: Gradient {
625+ GradientStop { position: 0.0; color: UbuntuColors.warmGrey }
626+ GradientStop { position: 0.5; color: "transparent" }
627+ GradientStop { position: 1.0; color: "black" }
628+ }
629
630- // draws the inner shadow/highlight
631 Rectangle {
632- id: sourceInnerFull
633- anchors { fill: parent; margins: -units.gu(0.1) }
634- radius: (width / 2)
635+ anchors.horizontalCenter: parent.horizontalCenter
636+ anchors.verticalCenter: parent.verticalCenter
637 antialiasing: true
638- gradient: Gradient {
639- GradientStop { position: 0.0; color: UbuntuColors.warmGrey }
640- GradientStop { position: 0.5; color: "transparent" }
641- GradientStop { position: 1.0; color: "black" }
642- }
643-
644- Rectangle {
645- anchors.horizontalCenter: parent.horizontalCenter
646- anchors.verticalCenter: parent.verticalCenter
647- antialiasing: true
648- color: styleMusic.toolbar.fullInnerPlayCircleColor
649- height: nowPlayingPlayButtonInner.height - units.gu(.1)
650- objectName: "nowPlayingPlayShape"
651- radius: height / 2
652- width: height
653-
654- function trigger() {
655+ color: styleMusic.toolbar.fullInnerPlayCircleColor
656+ height: nowPlayingPlayButtonInner.height - units.gu(.1)
657+ objectName: "nowPlayingPlayShape"
658+ radius: height / 2
659+ width: height
660+
661+ MouseArea {
662+ anchors {
663+ fill: parent
664+ }
665+ onClicked: {
666 if (emptyPage.noMusic) {
667 return;
668 }
669@@ -416,66 +468,76 @@
670 player.toggle();
671 }
672 }
673+ }
674
675- Image {
676- id: nowPlayingPlayIndicator
677- height: units.gu(6)
678- width: height
679- anchors.horizontalCenter: parent.horizontalCenter
680- anchors.verticalCenter: parent.verticalCenter
681- opacity: emptyPage.noMusic ? .4 : 1
682- source: player.playbackState === MediaPlayer.PlayingState ?
683- Qt.resolvedUrl("images/media-playback-pause.svg") : Qt.resolvedUrl("images/media-playback-start.svg")
684- }
685+ Image {
686+ id: nowPlayingPlayIndicator
687+ height: units.gu(6)
688+ width: height
689+ anchors.horizontalCenter: parent.horizontalCenter
690+ anchors.verticalCenter: parent.verticalCenter
691+ opacity: emptyPage.noMusic ? .4 : 1
692+ source: player.playbackState === MediaPlayer.PlayingState ?
693+ Qt.resolvedUrl("images/media-playback-pause.svg") : Qt.resolvedUrl("images/media-playback-start.svg")
694 }
695 }
696 }
697 }
698 }
699 }
700-
701- /* Next button */
702- Item {
703- id: nowPlayingNextButton
704- anchors.left: nowPlayingPlayButton.right
705- anchors.leftMargin: units.gu(1)
706- anchors.verticalCenter: parent.verticalCenter
707- height: units.gu(6)
708- objectName: "forwardshape"
709- opacity: trackQueue.model.count === 0 ? .4 : 1
710- width: height
711-
712- function trigger() {
713+ }
714+
715+ /* Next button */
716+ Item {
717+ id: nowPlayingNextButton
718+ anchors.left: nowPlayingPlayButton.right
719+ anchors.leftMargin: units.gu(1)
720+ anchors.verticalCenter: parent.verticalCenter
721+ height: units.gu(6)
722+ objectName: "forwardshape"
723+ opacity: trackQueue.model.count === 0 ? .4 : 1
724+ width: height
725+
726+ MouseArea {
727+ anchors {
728+ fill: parent
729+ }
730+ onClicked: {
731 if (trackQueue.model.count === 0 || emptyPage.noMusic) {
732 return;
733 }
734
735 player.nextSong()
736 }
737-
738- Image {
739- id: nowPlayingNextIndicator
740- height: units.gu(3)
741- width: height
742- anchors.horizontalCenter: parent.horizontalCenter
743- anchors.verticalCenter: parent.verticalCenter
744- source: Qt.resolvedUrl("images/media-skip-forward.svg")
745- opacity: 1
746- }
747 }
748
749- /* Shuffle button */
750- Item {
751- id: nowPlayingShuffleButton
752- objectName: "shuffleShape"
753- anchors.left: nowPlayingNextButton.right
754- anchors.leftMargin: units.gu(1)
755+ Image {
756+ id: nowPlayingNextIndicator
757+ height: units.gu(3)
758+ width: height
759+ anchors.horizontalCenter: parent.horizontalCenter
760 anchors.verticalCenter: parent.verticalCenter
761- height: units.gu(6)
762- opacity: player.shuffle && !emptyPage.noMusic ? 1 : .4
763- width: height
764-
765- function trigger() {
766+ source: Qt.resolvedUrl("images/media-skip-forward.svg")
767+ opacity: 1
768+ }
769+ }
770+
771+ /* Shuffle button */
772+ Item {
773+ id: nowPlayingShuffleButton
774+ objectName: "shuffleShape"
775+ anchors.left: nowPlayingNextButton.right
776+ anchors.leftMargin: units.gu(1)
777+ anchors.verticalCenter: parent.verticalCenter
778+ height: units.gu(6)
779+ opacity: player.shuffle && !emptyPage.noMusic ? 1 : .4
780+ width: height
781+
782+ MouseArea {
783+ anchors {
784+ fill: parent
785+ }
786+ onClicked: {
787 if (emptyPage.noMusic) {
788 return;
789 }
790@@ -483,33 +545,38 @@
791 // Invert shuffle settings
792 player.shuffle = !player.shuffle
793 }
794-
795- Image {
796- id: shuffleIcon
797- height: units.gu(3)
798- width: height
799- anchors.verticalCenter: parent.verticalCenter
800- anchors.horizontalCenter: parent.horizontalCenter
801- source: Qt.resolvedUrl("images/media-playlist-shuffle.svg")
802- opacity: player.shuffle && !emptyPage.noMusic ? 1 : .4
803- }
804- }
805-
806- /* Search button in wideAspect */
807- Item {
808- id: nowPlayingSearchButton
809- objectName: "searchShape"
810+ }
811+
812+ Image {
813+ id: shuffleIcon
814+ height: units.gu(3)
815+ width: height
816+ anchors.verticalCenter: parent.verticalCenter
817+ anchors.horizontalCenter: parent.horizontalCenter
818+ source: Qt.resolvedUrl("images/media-playlist-shuffle.svg")
819+ opacity: player.shuffle && !emptyPage.noMusic ? 1 : .4
820+ }
821+ }
822+
823+ /* Search button in wideAspect */
824+ Item {
825+ id: nowPlayingSearchButton
826+ objectName: "searchShape"
827+ anchors {
828+ right: parent.right
829+ rightMargin: units.gu(1)
830+ verticalCenter: parent.verticalCenter
831+ }
832+ height: units.gu(6)
833+ opacity: !emptyPage.noMusic ? 1 : .4
834+ width: height
835+ visible: wideAspect
836+
837+ MouseArea {
838 anchors {
839- right: parent.right
840- rightMargin: units.gu(1)
841- verticalCenter: parent.verticalCenter
842+ fill: parent
843 }
844- height: units.gu(6)
845- opacity: !emptyPage.noMusic ? 1 : .4
846- width: height
847- visible: wideAspect
848-
849- function trigger() {
850+ onClicked: {
851 if (emptyPage.noMusic) {
852 return;
853 }
854@@ -519,620 +586,690 @@
855 mainView, { title: i18n.tr("Search")} )
856 }
857 }
858+ }
859
860- Image {
861- id: searchIcon
862- anchors {
863- horizontalCenter: parent.horizontalCenter
864- verticalCenter: parent.verticalCenter
865- }
866- height: units.gu(3)
867- opacity: !emptyPage.noMusic ? 1 : .4
868- source: Qt.resolvedUrl("images/search.svg")
869- width: height
870+ Image {
871+ id: searchIcon
872+ anchors {
873+ horizontalCenter: parent.horizontalCenter
874+ verticalCenter: parent.verticalCenter
875 }
876+ height: units.gu(3)
877+ opacity: !emptyPage.noMusic ? 1 : .4
878+ source: Qt.resolvedUrl("images/search.svg")
879+ width: height
880 }
881 }
882-
883- /* Progress bar component */
884- Rectangle {
885- id: musicToolbarFullProgressContainer
886+ }
887+
888+ /* Progress bar component */
889+ Rectangle {
890+ id: musicToolbarFullProgressContainer
891+ anchors.left: parent.left
892+ anchors.top: parent.top
893+ color: styleMusic.toolbar.fullBackgroundColor
894+ height: units.gu(3)
895+ width: parent.width
896+
897+ /* Position label */
898+ Label {
899+ id: musicToolbarFullPositionLabel
900 anchors.left: parent.left
901+ anchors.leftMargin: units.gu(2)
902 anchors.top: parent.top
903- color: styleMusic.toolbar.fullBackgroundColor
904- height: units.gu(3)
905- width: parent.width
906-
907- /* Position label */
908- Label {
909- id: musicToolbarFullPositionLabel
910- anchors.left: parent.left
911- anchors.leftMargin: units.gu(2)
912- anchors.top: parent.top
913- color: styleMusic.nowPlaying.labelColor
914- fontSize: "x-small"
915- height: parent.height
916- horizontalAlignment: Text.AlignHCenter
917- text: durationToString(player.position)
918- verticalAlignment: Text.AlignVCenter
919- width: units.gu(3)
920- }
921-
922- /* Progress bar */
923- Rectangle {
924- id: musicToolbarFullProgressBarContainer
925- objectName: "progressBarShape"
926- anchors.left: musicToolbarFullPositionLabel.right
927- anchors.leftMargin: units.gu(2)
928- anchors.right: musicToolbarFullDurationLabel.left
929- anchors.rightMargin: units.gu(2)
930- anchors.verticalCenter: parent.verticalCenter
931- color: "transparent"
932- height: units.gu(1);
933- state: trackQueue.model.count === 0 ? "disabled" : "enabled"
934-
935- states: [
936- State {
937- name: "disabled"
938- PropertyChanges {
939- target: musicToolbarFullProgressMouseArea
940- enabled: false
941- }
942- PropertyChanges {
943- target: musicToolbarFullProgressTrough
944- visible: false
945- }
946- PropertyChanges {
947- target: musicToolbarFullProgressHandle
948- visible: false
949- }
950- },
951- State {
952- name: "enabled"
953- PropertyChanges {
954- target: musicToolbarFullProgressMouseArea
955- enabled: true
956- }
957- PropertyChanges {
958- target: musicToolbarFullProgressTrough
959- visible: true
960- }
961- PropertyChanges {
962- target: musicToolbarFullProgressHandle
963- visible: true
964- }
965- }
966- ]
967-
968- property bool seeking: false
969-
970- onSeekingChanged: {
971- if (seeking === false) {
972- musicToolbarFullPositionLabel.text = durationToString(player.position)
973- }
974- }
975-
976- Connections {
977- target: player
978- onDurationChanged: {
979- console.debug("Duration changed: " + player.duration)
980- musicToolbarFullDurationLabel.text = durationToString(player.duration)
981- }
982- onPositionChanged: {
983- if (musicToolbarFullProgressBarContainer.seeking === false)
984- {
985- musicToolbarFullPositionLabel.text = durationToString(player.position)
986- musicToolbarFullDurationLabel.text = durationToString(player.duration)
987- musicToolbarFullProgressHandle.x = (player.position / player.duration) * musicToolbarFullProgressBarContainer.width
988- - musicToolbarFullProgressHandle.width / 2;
989- }
990- }
991- onStopped: {
992- musicToolbarFullProgressHandle.x = -musicToolbarFullProgressHandle.width / 2;
993-
994- musicToolbarFullPositionLabel.text = durationToString(0);
995- musicToolbarFullDurationLabel.text = durationToString(0);
996- }
997- }
998-
999- // Black background behind the progress bar
1000- Rectangle {
1001- id: musicToolbarFullProgressBackground
1002- anchors.verticalCenter: parent.verticalCenter;
1003- color: styleMusic.toolbar.fullProgressBackgroundColor;
1004- height: parent.height;
1005- radius: units.gu(0.5)
1006- width: parent.width;
1007- }
1008-
1009- // The orange fill of the progress bar
1010- Rectangle {
1011- id: musicToolbarFullProgressTrough
1012- anchors.verticalCenter: parent.verticalCenter;
1013- antialiasing: true
1014- color: styleMusic.toolbar.fullProgressTroughColor;
1015- height: parent.height;
1016- radius: units.gu(0.5)
1017- width: musicToolbarFullProgressHandle.x + (height / 2); // +radius
1018- }
1019-
1020- // The current position (handle) of the progress bar
1021- Rectangle {
1022- id: musicToolbarFullProgressHandle
1023- anchors.verticalCenter: musicToolbarFullProgressBackground.verticalCenter
1024- antialiasing: true
1025- color: styleMusic.nowPlaying.progressHandleColor
1026- height: units.gu(1.5)
1027- radius: height / 2
1028- width: height
1029-
1030- // On X change update the position string
1031- onXChanged: {
1032- if (musicToolbarFullProgressBarContainer.seeking) {
1033- var fraction = (x + (width / 2)) / parent.width;
1034- musicToolbarFullPositionLabel.text = durationToString(fraction * player.duration)
1035- }
1036- }
1037- }
1038- }
1039-
1040- /* Duration label */
1041- Label {
1042- id: musicToolbarFullDurationLabel
1043- anchors.right: parent.right
1044- anchors.rightMargin: units.gu(2)
1045- anchors.top: parent.top
1046- color: styleMusic.nowPlaying.labelColor
1047- fontSize: "x-small"
1048- height: parent.height
1049- horizontalAlignment: Text.AlignHCenter
1050- text: durationToString(player.duration)
1051- verticalAlignment: Text.AlignVCenter
1052- width: units.gu(3)
1053- }
1054-
1055- /* Border at the bottom */
1056- Rectangle {
1057- anchors.bottom: parent.bottom
1058- anchors.left: parent.left
1059- anchors.right: parent.right
1060- color: styleMusic.common.white
1061- height: units.gu(0.1)
1062- opacity: 0.1
1063- }
1064- }
1065- }
1066-
1067- /* Expanded toolbar */
1068- Rectangle {
1069- id: musicToolbarExpandedContainer
1070- anchors {
1071- fill: parent
1072- }
1073- color: "transparent"
1074- visible: musicToolbarPanel.currentMode === "expanded"
1075-
1076+ color: styleMusic.nowPlaying.labelColor
1077+ fontSize: "x-small"
1078+ height: parent.height
1079+ horizontalAlignment: Text.AlignHCenter
1080+ text: durationToString(player.position)
1081+ verticalAlignment: Text.AlignVCenter
1082+ width: units.gu(3)
1083+ }
1084+
1085+ /* Progress bar */
1086 Rectangle {
1087- id: musicToolbarPlayerControls
1088- anchors.fill: parent
1089- color: styleMusic.playerControls.backgroundColor
1090+ id: musicToolbarFullProgressBarContainer
1091+ objectName: "progressBarShape"
1092+ anchors.left: musicToolbarFullPositionLabel.right
1093+ anchors.leftMargin: units.gu(2)
1094+ anchors.right: musicToolbarFullDurationLabel.left
1095+ anchors.rightMargin: units.gu(2)
1096+ anchors.verticalCenter: parent.verticalCenter
1097+ color: "transparent"
1098+ height: units.gu(1);
1099 state: trackQueue.model.count === 0 ? "disabled" : "enabled"
1100+
1101 states: [
1102 State {
1103 name: "disabled"
1104 PropertyChanges {
1105- target: disabledPlayerControlsGroup
1106- visible: true
1107- }
1108- PropertyChanges {
1109- target: enabledPlayerControlsGroup
1110+ target: musicToolbarFullProgressMouseArea
1111+ enabled: false
1112+ }
1113+ PropertyChanges {
1114+ target: musicToolbarFullProgressTrough
1115+ visible: false
1116+ }
1117+ PropertyChanges {
1118+ target: musicToolbarFullProgressHandle
1119 visible: false
1120 }
1121 },
1122 State {
1123 name: "enabled"
1124 PropertyChanges {
1125- target: disabledPlayerControlsGroup
1126- visible: false
1127- }
1128- PropertyChanges {
1129- target: enabledPlayerControlsGroup
1130+ target: musicToolbarFullProgressMouseArea
1131+ enabled: true
1132+ }
1133+ PropertyChanges {
1134+ target: musicToolbarFullProgressTrough
1135+ visible: true
1136+ }
1137+ PropertyChanges {
1138+ target: musicToolbarFullProgressHandle
1139 visible: true
1140 }
1141 }
1142 ]
1143
1144- Rectangle {
1145- id: disabledPlayerControlsGroup
1146- anchors.fill: parent
1147- color: "transparent"
1148- visible: trackQueue.model.count === 0
1149-
1150- Label {
1151- id: noSongsInQueueLabel
1152- anchors {
1153- left: parent.left
1154- right: disabledPlayerControlsPlayButton.left
1155- margins: units.gu(1)
1156- top: parent.top
1157- }
1158- color: styleMusic.playerControls.labelColor
1159- text: i18n.tr("Tap play to shuffle music")
1160- fontSize: "large"
1161- wrapMode: Text.WordWrap
1162- maximumLineCount: 2
1163- }
1164-
1165- Rectangle {
1166- id: disabledPlayerControlsPlayButton
1167- anchors.right: parent.right
1168- anchors.rightMargin: units.gu(1)
1169- anchors.verticalCenter: parent.verticalCenter
1170- antialiasing: true
1171- color: "#444"
1172- height: units.gu(7)
1173- radius: height / 2
1174- width: height
1175-
1176- function trigger() {
1177- if (emptyPage.noMusic) {
1178- return;
1179- }
1180-
1181- if (trackQueue.model.count === 0) {
1182- playRandomSong();
1183- }
1184- else {
1185- player.toggle();
1186- }
1187- }
1188-
1189- // draws the outer shadow/highlight
1190- Rectangle {
1191- id: disabledSourceOutter
1192- anchors { fill: parent; margins: -units.gu(0.1) }
1193- radius: (width / 2)
1194- antialiasing: true
1195- gradient: Gradient {
1196- GradientStop { position: 0.0; color: "black" }
1197- GradientStop { position: 0.5; color: "transparent" }
1198- GradientStop { position: 1.0; color: UbuntuColors.warmGrey }
1199- }
1200-
1201- Rectangle {
1202- anchors.verticalCenter: parent.verticalCenter
1203- anchors.horizontalCenter: parent.horizontalCenter
1204- antialiasing: true
1205- color: "#444"
1206- height: playerControlsPlayButton.height - units.gu(.1)
1207- radius: height / 2
1208- width: height
1209-
1210- Rectangle {
1211- id: disabledPlayerControlsPlayInnerCircle
1212- anchors.horizontalCenter: parent.horizontalCenter
1213- anchors.verticalCenter: parent.verticalCenter
1214- antialiasing: true
1215- height: units.gu(4.5)
1216- radius: height / 2
1217- width: height
1218- color: styleMusic.toolbar.fullInnerPlayCircleColor
1219-
1220- // draws the inner shadow/highlight
1221- Rectangle {
1222- id: disabledSourceInner
1223- anchors { fill: parent; margins: -units.gu(0.1) }
1224- radius: (width / 2)
1225- antialiasing: true
1226- gradient: Gradient {
1227- GradientStop { position: 0.0; color: UbuntuColors.warmGrey }
1228- GradientStop { position: 0.5; color: "transparent" }
1229- GradientStop { position: 1.0; color: "black" }
1230- }
1231-
1232- Rectangle {
1233- anchors.verticalCenter: parent.verticalCenter
1234- anchors.horizontalCenter: parent.horizontalCenter
1235- antialiasing: true
1236- height: playerControlsPlayInnerCircle.height - units.gu(.1)
1237- radius: height / 2
1238- width: height
1239- color: styleMusic.toolbar.fullInnerPlayCircleColor
1240-
1241- Image {
1242- id: disabledPlayIndicator
1243- height: units.gu(4)
1244- width: height
1245- anchors.horizontalCenter: parent.horizontalCenter
1246- anchors.verticalCenter: parent.verticalCenter
1247- opacity: emptyPage.noMusic ? .4 : 1
1248- source: player.playbackState === MediaPlayer.PlayingState ?
1249- Qt.resolvedUrl("images/media-playback-pause.svg") : Qt.resolvedUrl("images/media-playback-start.svg")
1250- }
1251- }
1252- }
1253- }
1254- }
1255- }
1256- }
1257- }
1258-
1259- Rectangle {
1260- id: enabledPlayerControlsGroup
1261- anchors.fill: parent
1262- color: "transparent"
1263- visible: trackQueue.model.count !== 0
1264-
1265- /* Settings button */
1266- // TODO: Enable settings when it is practical
1267- /* Rectangle {
1268- id: playerControlsSettings
1269- anchors.right: parent.right
1270- anchors.verticalCenter: parent.verticalCenter
1271- width: units.gu(6)
1272- height: width
1273- color: "transparent"
1274-
1275- Image {
1276- anchors.horizontalCenter: parent.horizontalCenter
1277- anchors.verticalCenter: parent.verticalCenter
1278- height: units.gu(3)
1279- source: Qt.resolvedUrl("images/settings.png")
1280- width: height
1281- }
1282-
1283- MouseArea {
1284- anchors.fill: parent
1285- onClicked: {
1286- console.debug('Debug: Show settings')
1287- PopupUtils.open(Qt.resolvedUrl("MusicSettings.qml"), mainView,
1288- {
1289- title: i18n.tr("Settings")
1290- } )
1291- }
1292- }
1293- } */
1294-
1295- /* Play/Pause button TODO: image and colours needs updating */
1296- Rectangle {
1297- id: playerControlsPlayButton
1298- anchors.right: parent.right
1299- anchors.rightMargin: units.gu(1)
1300- anchors.verticalCenter: parent.verticalCenter
1301- antialiasing: true
1302- color: "#444"
1303- height: units.gu(7)
1304- objectName: "playshape"
1305- radius: height / 2
1306- width: height
1307-
1308- function trigger() {
1309- if (emptyPage.noMusic) {
1310- return;
1311- }
1312-
1313- if (trackQueue.model.count === 0) {
1314- playRandomSong();
1315- }
1316- else {
1317- player.toggle();
1318- }
1319- }
1320-
1321- // draws the outer shadow/highlight
1322- Rectangle {
1323- id: sourceOutter
1324- anchors { fill: parent; margins: -units.gu(0.1) }
1325- radius: (width / 2)
1326- antialiasing: true
1327- gradient: Gradient {
1328- GradientStop { position: 0.0; color: "black" }
1329- GradientStop { position: 0.5; color: "transparent" }
1330- GradientStop { position: 1.0; color: UbuntuColors.warmGrey }
1331- }
1332-
1333- Rectangle {
1334- anchors.verticalCenter: parent.verticalCenter
1335- anchors.horizontalCenter: parent.horizontalCenter
1336- antialiasing: true
1337- color: "#444"
1338- height: playerControlsPlayButton.height - units.gu(.1)
1339- radius: height / 2
1340- width: height
1341-
1342- Rectangle {
1343- id: playerControlsPlayInnerCircle
1344- anchors.horizontalCenter: parent.horizontalCenter
1345- anchors.verticalCenter: parent.verticalCenter
1346- antialiasing: true
1347- height: units.gu(4.5)
1348- radius: height / 2
1349- width: height
1350- color: styleMusic.toolbar.fullInnerPlayCircleColor
1351-
1352- // draws the inner shadow/highlight
1353- Rectangle {
1354- id: sourceInner
1355- anchors { fill: parent; margins: -units.gu(0.1) }
1356- radius: (width / 2)
1357- antialiasing: true
1358- gradient: Gradient {
1359- GradientStop { position: 0.0; color: UbuntuColors.warmGrey }
1360- GradientStop { position: 0.5; color: "transparent" }
1361- GradientStop { position: 1.0; color: "black" }
1362- }
1363-
1364- Rectangle {
1365- anchors.verticalCenter: parent.verticalCenter
1366- anchors.horizontalCenter: parent.horizontalCenter
1367- antialiasing: true
1368- height: playerControlsPlayInnerCircle.height - units.gu(.1)
1369- radius: height / 2
1370- width: height
1371- color: styleMusic.toolbar.fullInnerPlayCircleColor
1372-
1373- Image {
1374- id: playindicator
1375- height: units.gu(4)
1376- width: height
1377- anchors.horizontalCenter: parent.horizontalCenter
1378- anchors.verticalCenter: parent.verticalCenter
1379- opacity: emptyPage.noMusic ? .4 : 1
1380- source: player.playbackState === MediaPlayer.PlayingState ?
1381- Qt.resolvedUrl("images/media-playback-pause.svg") : Qt.resolvedUrl("images/media-playback-start.svg")
1382- }
1383- }
1384- }
1385- }
1386- }
1387- }
1388- }
1389-
1390- /* Container holding the labels for the toolbar */
1391- Rectangle {
1392- id: playerControlLabelContainer
1393- anchors.bottom: parent.bottom
1394- anchors.left: parent.left
1395- anchors.right: playerControlsPlayButton.left
1396- anchors.top: parent.top
1397- color: "transparent"
1398-
1399- /* Title of track */
1400- Label {
1401- id: playerControlsTitle
1402- anchors.left: parent.left
1403- anchors.leftMargin: units.gu(1)
1404- anchors.right: parent.right
1405- anchors.rightMargin: units.gu(1)
1406- anchors.top: parent.top
1407- anchors.topMargin: units.gu(1)
1408- color: styleMusic.playerControls.labelColor
1409- elide: Text.ElideRight
1410- fontSize: "medium"
1411- objectName: "playercontroltitle"
1412- text: player.currentMetaTitle === ""
1413- ? player.source : player.currentMetaTitle
1414- }
1415-
1416- /* Artist of track */
1417- Label {
1418- id: playerControlsArtist
1419- anchors.left: parent.left
1420- anchors.leftMargin: units.gu(1)
1421- anchors.right: parent.right
1422- anchors.rightMargin: units.gu(1)
1423- anchors.top: playerControlsTitle.bottom
1424- color: styleMusic.playerControls.labelColor
1425- elide: Text.ElideRight
1426- fontSize: "small"
1427- text: player.currentMetaArtist
1428- }
1429-
1430- /* Album of track */
1431- Label {
1432- id: playerControlsAlbum
1433- anchors.left: parent.left
1434- anchors.leftMargin: units.gu(1)
1435- anchors.right: parent.right
1436- anchors.rightMargin: units.gu(1)
1437- anchors.top: playerControlsArtist.bottom
1438- color: styleMusic.playerControls.labelColor
1439- elide: Text.ElideRight
1440- fontSize: "small"
1441- text: player.currentMetaAlbum
1442- }
1443- }
1444-
1445- Rectangle {
1446- anchors.fill: playerControlLabelContainer
1447- color: "transparent"
1448- function trigger() {
1449- tabs.pushNowPlaying();
1450- }
1451- }
1452- }
1453- }
1454- }
1455-
1456- /* Object which provides the progress bar when toolbar is minimized */
1457- Rectangle {
1458- id: musicToolbarSmallProgressBackground
1459- anchors {
1460- bottom: parent.top
1461- left: parent.left
1462- right: parent.right
1463- }
1464- color: styleMusic.common.black
1465- height: musicToolbarPanel.minimizedHeight
1466- visible: (!musicToolbarPanel.animating &&
1467- !musicToolbarPanel.opened)
1468- || musicToolbarPanel.currentMode == "expanded"
1469-
1470- Rectangle {
1471- id: musicToolbarSmallProgressHint
1472- anchors.left: parent.left
1473- anchors.top: parent.top
1474- color: styleMusic.nowPlaying.progressForegroundColor
1475- height: parent.height
1476- width: 0
1477+ property bool seeking: false
1478+
1479+ onSeekingChanged: {
1480+ if (seeking === false) {
1481+ musicToolbarFullPositionLabel.text = durationToString(player.position)
1482+ }
1483+ }
1484
1485 Connections {
1486 target: player
1487+ onDurationChanged: {
1488+ console.debug("Duration changed: " + player.duration)
1489+ musicToolbarFullDurationLabel.text = durationToString(player.duration)
1490+ }
1491 onPositionChanged: {
1492- musicToolbarSmallProgressHint.width = (player.position / player.duration) * musicToolbarSmallProgressBackground.width
1493+ if (musicToolbarFullProgressBarContainer.seeking === false)
1494+ {
1495+ musicToolbarFullPositionLabel.text = durationToString(player.position)
1496+ musicToolbarFullDurationLabel.text = durationToString(player.duration)
1497+ musicToolbarFullProgressHandle.x = (player.position / player.duration) * musicToolbarFullProgressBarContainer.width
1498+ - musicToolbarFullProgressHandle.width / 2;
1499+ }
1500 }
1501 onStopped: {
1502- musicToolbarSmallProgressHint.width = 0;
1503- }
1504- }
1505- }
1506- }
1507-
1508- /* Mouse events for the progress bar
1509- is after musicToolbarMouseArea so that it captures mouse events for dragging */
1510- MouseArea {
1511- id: musicToolbarFullProgressMouseArea
1512- height: units.gu(2)
1513- width: musicToolbarFullProgressBarContainer.width
1514- x: musicToolbarFullProgressBarContainer.x
1515- y: musicToolbarFullProgressBarContainer.y
1516-
1517- drag.axis: Drag.XAxis
1518- drag.minimumX: -(musicToolbarFullProgressHandle.width / 2)
1519- drag.maximumX: musicToolbarFullProgressBarContainer.width - (musicToolbarFullProgressHandle.width / 2)
1520- drag.target: musicToolbarFullProgressHandle
1521-
1522- onPressed: {
1523- musicToolbarFullProgressBarContainer.seeking = true;
1524-
1525- // Jump the handle to the current mouse position
1526- musicToolbarFullProgressHandle.x = mouse.x - (musicToolbarFullProgressHandle.width / 2);
1527- }
1528-
1529- onReleased: {
1530- var fraction = mouse.x / musicToolbarFullProgressBarContainer.width;
1531-
1532- // Limit the bounds of the fraction
1533- fraction = fraction < 0 ? 0 : fraction
1534- fraction = fraction > 1 ? 1 : fraction
1535-
1536- player.seek((fraction) * player.duration);
1537- musicToolbarFullProgressBarContainer.seeking = false;
1538- }
1539- }
1540-
1541- // Timer for autohide
1542- Timer {
1543- id: toolbarAutoHideTimer
1544- interval: 5000
1545- repeat: false
1546- running: false
1547- onTriggered: {
1548- if (currentPage !== nowPlaying) { // don't autohide on now playing
1549- hideToolbar();
1550- }
1551+ musicToolbarFullProgressHandle.x = -musicToolbarFullProgressHandle.width / 2;
1552+
1553+ musicToolbarFullPositionLabel.text = durationToString(0);
1554+ musicToolbarFullDurationLabel.text = durationToString(0);
1555+ }
1556+ }
1557+
1558+ // Black background behind the progress bar
1559+ Rectangle {
1560+ id: musicToolbarFullProgressBackground
1561+ anchors.verticalCenter: parent.verticalCenter;
1562+ color: styleMusic.toolbar.fullProgressBackgroundColor;
1563+ height: parent.height;
1564+ radius: units.gu(0.5)
1565+ width: parent.width;
1566+ }
1567+
1568+ // The orange fill of the progress bar
1569+ Rectangle {
1570+ id: musicToolbarFullProgressTrough
1571+ anchors.verticalCenter: parent.verticalCenter;
1572+ antialiasing: true
1573+ color: styleMusic.toolbar.fullProgressTroughColor;
1574+ height: parent.height;
1575+ radius: units.gu(0.5)
1576+ width: musicToolbarFullProgressHandle.x + (height / 2); // +radius
1577+ }
1578+
1579+ // The current position (handle) of the progress bar
1580+ Rectangle {
1581+ id: musicToolbarFullProgressHandle
1582+ anchors.verticalCenter: musicToolbarFullProgressBackground.verticalCenter
1583+ antialiasing: true
1584+ color: styleMusic.nowPlaying.progressHandleColor
1585+ height: units.gu(1.5)
1586+ radius: height / 2
1587+ width: height
1588+
1589+ // On X change update the position string
1590+ onXChanged: {
1591+ if (musicToolbarFullProgressBarContainer.seeking) {
1592+ var fraction = (x + (width / 2)) / parent.width;
1593+ musicToolbarFullPositionLabel.text = durationToString(fraction * player.duration)
1594+ }
1595+ }
1596+ }
1597+ }
1598+
1599+ /* Duration label */
1600+ Label {
1601+ id: musicToolbarFullDurationLabel
1602+ anchors.right: parent.right
1603+ anchors.rightMargin: units.gu(2)
1604+ anchors.top: parent.top
1605+ color: styleMusic.nowPlaying.labelColor
1606+ fontSize: "x-small"
1607+ height: parent.height
1608+ horizontalAlignment: Text.AlignHCenter
1609+ text: durationToString(player.duration)
1610+ verticalAlignment: Text.AlignVCenter
1611+ width: units.gu(3)
1612+ }
1613+
1614+ /* Border at the bottom */
1615+ Rectangle {
1616+ anchors.bottom: parent.bottom
1617+ anchors.left: parent.left
1618+ anchors.right: parent.right
1619+ color: styleMusic.common.white
1620+ height: units.gu(0.1)
1621+ opacity: 0.1
1622+ }
1623+ }
1624+ }
1625+
1626+ /* Expanded toolbar */
1627+ Rectangle {
1628+ id: musicToolbarExpandedContainer
1629+ anchors {
1630+ fill: parent
1631+ }
1632+ color: "transparent"
1633+ visible: musicToolbarPanel.currentMode === "expanded"
1634+
1635+ Rectangle {
1636+ id: musicToolbarPlayerControls
1637+ anchors.fill: parent
1638+ color: styleMusic.playerControls.backgroundColor
1639+ state: trackQueue.model.count === 0 ? "disabled" : "enabled"
1640+ states: [
1641+ State {
1642+ name: "disabled"
1643+ PropertyChanges {
1644+ target: disabledPlayerControlsGroup
1645+ visible: true
1646+ }
1647+ PropertyChanges {
1648+ target: enabledPlayerControlsGroup
1649+ visible: false
1650+ }
1651+ },
1652+ State {
1653+ name: "enabled"
1654+ PropertyChanges {
1655+ target: disabledPlayerControlsGroup
1656+ visible: false
1657+ }
1658+ PropertyChanges {
1659+ target: enabledPlayerControlsGroup
1660+ visible: true
1661+ }
1662+ }
1663+ ]
1664+
1665+ Rectangle {
1666+ id: disabledPlayerControlsGroup
1667+ anchors.fill: parent
1668+ color: "transparent"
1669+ visible: trackQueue.model.count === 0
1670+
1671+ Label {
1672+ id: noSongsInQueueLabel
1673+ anchors {
1674+ left: parent.left
1675+ right: disabledPlayerControlsPlayButton.left
1676+ margins: units.gu(1)
1677+ top: parent.top
1678+ }
1679+ color: styleMusic.playerControls.labelColor
1680+ text: i18n.tr("Tap play to shuffle music")
1681+ fontSize: "large"
1682+ wrapMode: Text.WordWrap
1683+ maximumLineCount: 2
1684+ }
1685+
1686+ Rectangle {
1687+ id: disabledPlayerControlsPlayButton
1688+ anchors.right: parent.right
1689+ anchors.rightMargin: units.gu(1)
1690+ anchors.verticalCenter: parent.verticalCenter
1691+ antialiasing: true
1692+ color: "#444"
1693+ height: units.gu(7)
1694+ radius: height / 2
1695+ width: height
1696+
1697+ MouseArea {
1698+ anchors {
1699+ fill: parent
1700+ }
1701+ onClicked: {
1702+ if (emptyPage.noMusic) {
1703+ return;
1704+ }
1705+
1706+ if (trackQueue.model.count === 0) {
1707+ playRandomSong();
1708+ }
1709+ else {
1710+ player.toggle();
1711+ }
1712+ }
1713+ }
1714+
1715+ // draws the outer shadow/highlight
1716+ Rectangle {
1717+ id: disabledSourceOutter
1718+ anchors { fill: parent; margins: -units.gu(0.1) }
1719+ radius: (width / 2)
1720+ antialiasing: true
1721+ gradient: Gradient {
1722+ GradientStop { position: 0.0; color: "black" }
1723+ GradientStop { position: 0.5; color: "transparent" }
1724+ GradientStop { position: 1.0; color: UbuntuColors.warmGrey }
1725+ }
1726+
1727+ Rectangle {
1728+ anchors.verticalCenter: parent.verticalCenter
1729+ anchors.horizontalCenter: parent.horizontalCenter
1730+ antialiasing: true
1731+ color: "#444"
1732+ height: playerControlsPlayButton.height - units.gu(.1)
1733+ radius: height / 2
1734+ width: height
1735+
1736+ Rectangle {
1737+ id: disabledPlayerControlsPlayInnerCircle
1738+ anchors.horizontalCenter: parent.horizontalCenter
1739+ anchors.verticalCenter: parent.verticalCenter
1740+ antialiasing: true
1741+ height: units.gu(4.5)
1742+ radius: height / 2
1743+ width: height
1744+ color: styleMusic.toolbar.fullInnerPlayCircleColor
1745+
1746+ // draws the inner shadow/highlight
1747+ Rectangle {
1748+ id: disabledSourceInner
1749+ anchors { fill: parent; margins: -units.gu(0.1) }
1750+ radius: (width / 2)
1751+ antialiasing: true
1752+ gradient: Gradient {
1753+ GradientStop { position: 0.0; color: UbuntuColors.warmGrey }
1754+ GradientStop { position: 0.5; color: "transparent" }
1755+ GradientStop { position: 1.0; color: "black" }
1756+ }
1757+
1758+ Rectangle {
1759+ anchors.verticalCenter: parent.verticalCenter
1760+ anchors.horizontalCenter: parent.horizontalCenter
1761+ antialiasing: true
1762+ height: playerControlsPlayInnerCircle.height - units.gu(.1)
1763+ radius: height / 2
1764+ width: height
1765+ color: styleMusic.toolbar.fullInnerPlayCircleColor
1766+
1767+ Image {
1768+ id: disabledPlayIndicator
1769+ height: units.gu(4)
1770+ width: height
1771+ anchors.horizontalCenter: parent.horizontalCenter
1772+ anchors.verticalCenter: parent.verticalCenter
1773+ opacity: emptyPage.noMusic ? .4 : 1
1774+ source: player.playbackState === MediaPlayer.PlayingState ?
1775+ Qt.resolvedUrl("images/media-playback-pause.svg") : Qt.resolvedUrl("images/media-playback-start.svg")
1776+ }
1777+ }
1778+ }
1779+ }
1780+ }
1781+ }
1782+ }
1783+ }
1784+
1785+ Rectangle {
1786+ id: enabledPlayerControlsGroup
1787+ anchors.fill: parent
1788+ color: "transparent"
1789+ visible: trackQueue.model.count !== 0
1790+
1791+ /* Settings button */
1792+ // TODO: Enable settings when it is practical
1793+ /* Rectangle {
1794+ id: playerControlsSettings
1795+ anchors.right: parent.right
1796+ anchors.verticalCenter: parent.verticalCenter
1797+ width: units.gu(6)
1798+ height: width
1799+ color: "transparent"
1800+
1801+ Image {
1802+ anchors.horizontalCenter: parent.horizontalCenter
1803+ anchors.verticalCenter: parent.verticalCenter
1804+ height: units.gu(3)
1805+ source: Qt.resolvedUrl("images/settings.png")
1806+ width: height
1807+ }
1808+
1809+ MouseArea {
1810+ anchors.fill: parent
1811+ onClicked: {
1812+ console.debug('Debug: Show settings')
1813+ PopupUtils.open(Qt.resolvedUrl("MusicSettings.qml"), mainView,
1814+ {
1815+ title: i18n.tr("Settings")
1816+ } )
1817+ }
1818+ }
1819+ } */
1820+
1821+ /* Play/Pause button TODO: image and colours needs updating */
1822+ Rectangle {
1823+ id: playerControlsPlayButton
1824+ anchors.right: parent.right
1825+ anchors.rightMargin: units.gu(1)
1826+ anchors.verticalCenter: parent.verticalCenter
1827+ antialiasing: true
1828+ color: "#444"
1829+ height: units.gu(7)
1830+ objectName: "playshape"
1831+ radius: height / 2
1832+ width: height
1833+
1834+ MouseArea {
1835+ anchors {
1836+ fill: parent
1837+ }
1838+ onClicked: {
1839+ if (emptyPage.noMusic) {
1840+ return;
1841+ }
1842+
1843+ if (trackQueue.model.count === 0) {
1844+ playRandomSong();
1845+ }
1846+ else {
1847+ player.toggle();
1848+ }
1849+ }
1850+ }
1851+
1852+ // draws the outer shadow/highlight
1853+ Rectangle {
1854+ id: sourceOutter
1855+ anchors { fill: parent; margins: -units.gu(0.1) }
1856+ radius: (width / 2)
1857+ antialiasing: true
1858+ gradient: Gradient {
1859+ GradientStop { position: 0.0; color: "black" }
1860+ GradientStop { position: 0.5; color: "transparent" }
1861+ GradientStop { position: 1.0; color: UbuntuColors.warmGrey }
1862+ }
1863+
1864+ Rectangle {
1865+ anchors.verticalCenter: parent.verticalCenter
1866+ anchors.horizontalCenter: parent.horizontalCenter
1867+ antialiasing: true
1868+ color: "#444"
1869+ height: playerControlsPlayButton.height - units.gu(.1)
1870+ radius: height / 2
1871+ width: height
1872+
1873+ Rectangle {
1874+ id: playerControlsPlayInnerCircle
1875+ anchors.horizontalCenter: parent.horizontalCenter
1876+ anchors.verticalCenter: parent.verticalCenter
1877+ antialiasing: true
1878+ height: units.gu(4.5)
1879+ radius: height / 2
1880+ width: height
1881+ color: styleMusic.toolbar.fullInnerPlayCircleColor
1882+
1883+ // draws the inner shadow/highlight
1884+ Rectangle {
1885+ id: sourceInner
1886+ anchors { fill: parent; margins: -units.gu(0.1) }
1887+ radius: (width / 2)
1888+ antialiasing: true
1889+ gradient: Gradient {
1890+ GradientStop { position: 0.0; color: UbuntuColors.warmGrey }
1891+ GradientStop { position: 0.5; color: "transparent" }
1892+ GradientStop { position: 1.0; color: "black" }
1893+ }
1894+
1895+ Rectangle {
1896+ anchors.verticalCenter: parent.verticalCenter
1897+ anchors.horizontalCenter: parent.horizontalCenter
1898+ antialiasing: true
1899+ height: playerControlsPlayInnerCircle.height - units.gu(.1)
1900+ radius: height / 2
1901+ width: height
1902+ color: styleMusic.toolbar.fullInnerPlayCircleColor
1903+
1904+ Image {
1905+ id: playindicator
1906+ height: units.gu(4)
1907+ width: height
1908+ anchors.horizontalCenter: parent.horizontalCenter
1909+ anchors.verticalCenter: parent.verticalCenter
1910+ opacity: emptyPage.noMusic ? .4 : 1
1911+ source: player.playbackState === MediaPlayer.PlayingState ?
1912+ Qt.resolvedUrl("images/media-playback-pause.svg") : Qt.resolvedUrl("images/media-playback-start.svg")
1913+ }
1914+ }
1915+ }
1916+ }
1917+ }
1918+ }
1919+ }
1920+
1921+ /* Container holding the labels for the toolbar */
1922+ Rectangle {
1923+ id: playerControlLabelContainer
1924+ anchors.bottom: parent.bottom
1925+ anchors.left: parent.left
1926+ anchors.right: playerControlsPlayButton.left
1927+ anchors.top: parent.top
1928+ color: "transparent"
1929+
1930+ /* Title of track */
1931+ Label {
1932+ id: playerControlsTitle
1933+ anchors.left: parent.left
1934+ anchors.leftMargin: units.gu(1)
1935+ anchors.right: parent.right
1936+ anchors.rightMargin: units.gu(1)
1937+ anchors.top: parent.top
1938+ anchors.topMargin: units.gu(1)
1939+ color: styleMusic.playerControls.labelColor
1940+ elide: Text.ElideRight
1941+ fontSize: "medium"
1942+ objectName: "playercontroltitle"
1943+ text: player.currentMetaTitle === ""
1944+ ? player.source : player.currentMetaTitle
1945+ }
1946+
1947+ /* Artist of track */
1948+ Label {
1949+ id: playerControlsArtist
1950+ anchors.left: parent.left
1951+ anchors.leftMargin: units.gu(1)
1952+ anchors.right: parent.right
1953+ anchors.rightMargin: units.gu(1)
1954+ anchors.top: playerControlsTitle.bottom
1955+ color: styleMusic.playerControls.labelColor
1956+ elide: Text.ElideRight
1957+ fontSize: "small"
1958+ text: player.currentMetaArtist
1959+ }
1960+
1961+ /* Album of track */
1962+ Label {
1963+ id: playerControlsAlbum
1964+ anchors.left: parent.left
1965+ anchors.leftMargin: units.gu(1)
1966+ anchors.right: parent.right
1967+ anchors.rightMargin: units.gu(1)
1968+ anchors.top: playerControlsArtist.bottom
1969+ color: styleMusic.playerControls.labelColor
1970+ elide: Text.ElideRight
1971+ fontSize: "small"
1972+ text: player.currentMetaAlbum
1973+ }
1974+ }
1975+
1976+ Rectangle {
1977+ anchors.fill: playerControlLabelContainer
1978+ color: "transparent"
1979+
1980+ MouseArea {
1981+ anchors {
1982+ fill: parent
1983+ }
1984+ onClicked: tabs.pushNowPlaying();
1985+ }
1986+ }
1987+ }
1988+ }
1989+ }
1990+
1991+ /* Object which provides the progress bar when toolbar is minimized */
1992+ Rectangle {
1993+ id: musicToolbarSmallProgressBackground
1994+ anchors {
1995+ bottom: parent.top
1996+ left: parent.left
1997+ right: parent.right
1998+ }
1999+ color: styleMusic.common.black
2000+ height: musicToolbarPanel.minimizedHeight
2001+ visible: (!musicToolbarPanel.animating &&
2002+ !musicToolbarPanel.shown)
2003+ || musicToolbarPanel.currentMode === "expanded"
2004+
2005+ Rectangle {
2006+ id: musicToolbarSmallProgressHint
2007+ anchors.left: parent.left
2008+ anchors.top: parent.top
2009+ color: styleMusic.nowPlaying.progressForegroundColor
2010+ height: parent.height
2011+ width: 0
2012+
2013+ Connections {
2014+ target: player
2015+ onPositionChanged: {
2016+ musicToolbarSmallProgressHint.width = (player.position / player.duration) * musicToolbarSmallProgressBackground.width
2017+ }
2018+ onStopped: {
2019+ musicToolbarSmallProgressHint.width = 0;
2020+ }
2021+ }
2022+ }
2023+ }
2024+
2025+ /* Mouse events for dragging the toolbar down */
2026+ MouseArea {
2027+ anchors {
2028+ fill: parent
2029+ }
2030+ drag {
2031+ axis: Drag.YAxis
2032+ minimumY: currentPage === null ? -musicToolbarPanel.height : currentPage.height - musicToolbarPanel.height
2033+ maximumY: currentPage === null ? 0 : currentPage.height
2034+ target: musicToolbarPanel
2035+ }
2036+ enabled: !wideAspect
2037+ propagateComposedEvents: true
2038+
2039+ property bool changed: false
2040+
2041+ onClicked: mouse.accepted = changed
2042+ onMouseYChanged: {
2043+ mouse.accepted = true
2044+ changed = true
2045+ }
2046+ onPressed: mouse.accepted = false
2047+ onReleased: {
2048+ mouse.accepted = changed
2049+ changed = false
2050+
2051+ if (musicToolbarPanel.y < currentPage.height - (musicToolbarPanel.height / 2)) {
2052+ showToolbar()
2053+ } else {
2054+ hideToolbar()
2055+ }
2056+ }
2057+ }
2058+
2059+ /* Mouse events for showing the toolbar when hidden and bottom edge is expanded */
2060+ MouseArea {
2061+ enabled: isNowPlaying(currentPage) && !wideAspect
2062+ height: units.gu(2)
2063+ width: parent.width
2064+ x: 0
2065+ y: currentPage === null ? 0 : -height
2066+ drag {
2067+ axis: Drag.YAxis
2068+ minimumY: currentPage === null ? -musicToolbarPanel.height : currentPage.height - musicToolbarPanel.height
2069+ maximumY: currentPage === null ? 0 : currentPage.height
2070+ target: musicToolbarPanel
2071+ }
2072+
2073+ onReleased: {
2074+ if (musicToolbarPanel.y < currentPage.height - (musicToolbarPanel.height / 2)) {
2075+ showToolbar()
2076+ } else {
2077+ hideToolbar()
2078+ }
2079+ }
2080+ }
2081+
2082+ /* Mouse events for the progress bar
2083+ is after musicToolbarMouseArea so that it captures mouse events for dragging */
2084+ MouseArea {
2085+ id: musicToolbarFullProgressMouseArea
2086+ height: units.gu(2)
2087+ width: musicToolbarFullProgressBarContainer.width
2088+ x: musicToolbarFullProgressBarContainer.x
2089+ y: musicToolbarFullProgressBarContainer.y
2090+
2091+ drag.axis: Drag.XAxis
2092+ drag.minimumX: -(musicToolbarFullProgressHandle.width / 2)
2093+ drag.maximumX: musicToolbarFullProgressBarContainer.width - (musicToolbarFullProgressHandle.width / 2)
2094+ drag.target: musicToolbarFullProgressHandle
2095+
2096+ onPressed: {
2097+ musicToolbarFullProgressBarContainer.seeking = true;
2098+
2099+ // Jump the handle to the current mouse position
2100+ musicToolbarFullProgressHandle.x = mouse.x - (musicToolbarFullProgressHandle.width / 2);
2101+ }
2102+
2103+ onReleased: {
2104+ var fraction = mouse.x / musicToolbarFullProgressBarContainer.width;
2105+
2106+ // Limit the bounds of the fraction
2107+ fraction = fraction < 0 ? 0 : fraction
2108+ fraction = fraction > 1 ? 1 : fraction
2109+
2110+ player.seek((fraction) * player.duration);
2111+ musicToolbarFullProgressBarContainer.seeking = false;
2112+ }
2113+ }
2114+
2115+ // Timer for autohide
2116+ Timer {
2117+ id: toolbarAutoHideTimer
2118+ interval: 5000
2119+ repeat: false
2120+ running: false
2121+ onTriggered: {
2122+ if (!isNowPlaying(currentPage) && !currentPage.floating) { // don't autohide on now playing
2123+ hideToolbar();
2124 }
2125 }
2126 }
2127 }
2128-
2129
2130=== modified file 'Player.qml'
2131--- Player.qml 2014-08-13 23:57:39 +0000
2132+++ Player.qml 2014-08-21 20:46:47 +0000
2133@@ -65,7 +65,10 @@
2134 player.currentIndex = 0;
2135 player.source = Qt.resolvedUrl(trackQueue.model.get(0).filename)
2136 } else if (trackQueue.model.count === 0) {
2137- currentMetaFile = ""
2138+ currentMetaAlbum = "";
2139+ currentMetaArtist = "";
2140+ currentMetaFile = "";
2141+ currentMetaTitle = "";
2142 }
2143 }
2144 }
2145
2146=== modified file 'common/AlbumsPage.qml'
2147--- common/AlbumsPage.qml 2014-08-21 17:28:54 +0000
2148+++ common/AlbumsPage.qml 2014-08-21 20:46:47 +0000
2149@@ -28,7 +28,6 @@
2150
2151 MusicPage {
2152 id: albumStackPage
2153- anchors.bottomMargin: units.gu(.5)
2154 visible: false
2155
2156 property string artist: ""
2157
2158=== modified file 'common/MusicPage.qml'
2159--- common/MusicPage.qml 2014-07-02 12:27:30 +0000
2160+++ common/MusicPage.qml 2014-08-21 20:46:47 +0000
2161@@ -17,13 +17,19 @@
2162 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2163 */
2164
2165+import QtQuick 2.0
2166 import Ubuntu.Components 0.1
2167
2168
2169 // generic page for music, could be useful for bottomedge implementation
2170-Page {
2171+PageWithBottomEdge {
2172 id: thisPage
2173
2174+ bottomEdgeEnabled: true
2175+ //bottomEdgePageComponent: nowPlayingComponent
2176+ bottomEdgeTitle: i18n.tr("Now Playing") + " (" + trackQueue.model.count.toString() + ")"
2177+ reloadBottomEdgePage: false
2178+
2179 onVisibleChanged: {
2180 if (visible) {
2181 musicToolbar.setPage(thisPage);
2182
2183=== added file 'common/PageWithBottomEdge.qml'
2184--- common/PageWithBottomEdge.qml 1970-01-01 00:00:00 +0000
2185+++ common/PageWithBottomEdge.qml 2014-08-21 20:46:47 +0000
2186@@ -0,0 +1,512 @@
2187+/*
2188+ * Copyright (C) 2014 Canonical, Ltd.
2189+ *
2190+ * This program is free software; you can redistribute it and/or modify
2191+ * it under the terms of the GNU General Public License as published by
2192+ * the Free Software Foundation; version 3.
2193+ *
2194+ * This program is distributed in the hope that it will be useful,
2195+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2196+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2197+ * GNU General Public License for more details.
2198+ *
2199+ * You should have received a copy of the GNU General Public License
2200+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2201+ */
2202+
2203+/*
2204+ Example:
2205+
2206+ MainView {
2207+ objectName: "mainView"
2208+
2209+ applicationName: "com.ubuntu.developer.boiko.bottomedge"
2210+
2211+ width: units.gu(100)
2212+ height: units.gu(75)
2213+
2214+ Component {
2215+ id: pageComponent
2216+
2217+ PageWithBottomEdge {
2218+ id: mainPage
2219+ title: i18n.tr("Main Page")
2220+
2221+ Rectangle {
2222+ anchors.fill: parent
2223+ color: "white"
2224+ }
2225+
2226+ bottomEdgePageComponent: Page {
2227+ title: "Contents"
2228+ anchors.fill: parent
2229+ //anchors.topMargin: contentsPage.flickable.contentY
2230+
2231+ ListView {
2232+ anchors.fill: parent
2233+ model: 50
2234+ delegate: ListItems.Standard {
2235+ text: "One Content Item: " + index
2236+ }
2237+ }
2238+ }
2239+ bottomEdgeTitle: i18n.tr("Bottom edge action")
2240+ }
2241+ }
2242+
2243+ PageStack {
2244+ id: stack
2245+ Component.onCompleted: stack.push(pageComponent)
2246+ }
2247+ }
2248+
2249+*/
2250+
2251+import QtQuick 2.0
2252+import Ubuntu.Components 0.1
2253+
2254+Page {
2255+ id: page
2256+
2257+ property alias bottomEdgePageComponent: edgeLoader.sourceComponent
2258+ property alias bottomEdgePageSource: edgeLoader.source
2259+ property alias bottomEdgeTitle: tipLabel.text
2260+ property alias bottomEdgeEnabled: bottomEdge.visible
2261+ property int bottomEdgeExpandThreshold: page.height * 0.2
2262+ property int bottomEdgeExposedArea: bottomEdge.state !== "expanded" ? (page.height - bottomEdge.y - bottomEdge.tipHeight) : _areaWhenExpanded
2263+ property bool reloadBottomEdgePage: true
2264+
2265+ readonly property alias bottomEdgePage: edgeLoader.item
2266+ readonly property bool isReady: (bottomEdge.y === 0) // CUSTOM, no edgeLoader && bottomEdgePageLoaded && edgeLoader.item.active)
2267+ readonly property bool isCollapsed: (bottomEdge.y === page.height)
2268+ readonly property bool bottomEdgePageLoaded: (edgeLoader.status == Loader.Ready)
2269+
2270+ property bool _showEdgePageWhenReady: false
2271+ property int _areaWhenExpanded: 0
2272+
2273+ property bool floating: bottomEdge.state === "floating" // CUSTOM
2274+ property alias bottomEdgeState: bottomEdge.state // CUSTOM expose state for toolbar and pushNowPlaying()
2275+
2276+ signal bottomEdgeReleased()
2277+ signal bottomEdgeDismissed()
2278+
2279+
2280+ function showBottomEdgePage(source, properties)
2281+ {
2282+ edgeLoader.setSource(source, properties)
2283+ _showEdgePageWhenReady = true
2284+ }
2285+
2286+ function setBottomEdgePage(source, properties)
2287+ {
2288+ edgeLoader.setSource(source, properties)
2289+ }
2290+
2291+ function _pushPage()
2292+ {
2293+ /* CUSTOM
2294+ if (edgeLoader.status === Loader.Ready) {
2295+ edgeLoader.item.active = true
2296+ page.pageStack.push(edgeLoader.item)
2297+ if (edgeLoader.item.flickable) {
2298+ edgeLoader.item.flickable.contentY = -page.header.height
2299+ edgeLoader.item.flickable.returnToBounds()
2300+ }
2301+ if (edgeLoader.item.ready)
2302+ edgeLoader.item.ready()
2303+ }
2304+ */
2305+
2306+ nowPlaying.reparent(mainPageStack) // CUSTOM
2307+ mainPageStack.push(nowPlaying) // CUSTOM
2308+ }
2309+
2310+
2311+ function forceExpandedStateNoAnimation() // CUSTOM, used by toolbar to restore state
2312+ {
2313+ bottomEdge.forceStateNoAnimation = true
2314+ bottomEdge.state = "expanded"
2315+ bottomEdge.forceStateNoAnimation = false
2316+ }
2317+
2318+
2319+ Component.onCompleted: {
2320+ // avoid a binding on the expanded height value
2321+ var expandedHeight = height;
2322+ _areaWhenExpanded = expandedHeight;
2323+ }
2324+
2325+ onActiveChanged: {
2326+ if (active) {
2327+ bottomEdge.state = "collapsed"
2328+ }
2329+ }
2330+
2331+ onBottomEdgePageLoadedChanged: {
2332+ if (_showEdgePageWhenReady && bottomEdgePageLoaded) {
2333+ bottomEdge.state = "expanded"
2334+ _showEdgePageWhenReady = false
2335+ }
2336+ }
2337+
2338+ onVisibleChanged: { // CUSTOM, reparent now playing to this page
2339+ if (visible) {
2340+ nowPlaying.reparent(customLoader)
2341+ }
2342+ }
2343+
2344+ Rectangle {
2345+ id: bgVisual
2346+
2347+ color: "black"
2348+ anchors.fill: page
2349+ opacity: 0.7 * ((page.height - bottomEdge.y) / page.height)
2350+ z: 1
2351+ }
2352+
2353+ Timer {
2354+ id: hideIndicator
2355+
2356+ interval: 3000
2357+ running: true
2358+ repeat: false
2359+ onTriggered: tip.hidden = true
2360+ }
2361+
2362+
2363+ Rectangle {
2364+ id: bottomEdge
2365+ objectName: "bottomEdge"
2366+
2367+ readonly property int tipHeight: units.gu(4) // CUSTOM increase tip height due to progress bar overlay units.gu(3)
2368+ readonly property int pageStartY: 0
2369+
2370+ property bool forceStateNoAnimation: false // CUSTOM, used to force the state without animation
2371+
2372+ z: 1
2373+ color: Theme.palette.normal.background // FIXME: causes non transparent bg
2374+ parent: page
2375+ anchors {
2376+ left: parent.left
2377+ right: parent.right
2378+ }
2379+ height: page.height
2380+ y: height
2381+
2382+ Connections { // custom
2383+ target: musicToolbar
2384+
2385+ onYChanged: {
2386+ // Lock the bottom edge y to the toolbar y if not in expanded mode
2387+ if (!floating && bottomEdge.state === "panel") {
2388+ bottomEdge.y = musicToolbar.y
2389+ }
2390+ }
2391+ }
2392+
2393+
2394+ UbuntuShape {
2395+ id: tip
2396+ objectName: "bottomEdgeTip"
2397+
2398+ property bool hidden: false
2399+
2400+ //readonly property double visiblePosition: (page.height - bottomEdge.y) < units.gu(1) ? -bottomEdge.tipHeight + (page.height - bottomEdge.y) : 0
2401+ //readonly property double invisiblePosition: (page.height - bottomEdge.y) < units.gu(1) ? -units.gu(1) : 0
2402+ // CUSTOM, due to panel state position needs to be different
2403+ readonly property double visiblePosition: bottomEdge.y < page.height - musicToolbar.height - units.gu(1) ? 0 : -bottomEdge.tipHeight
2404+ readonly property double invisiblePosition: bottomEdge.state === "panel" || bottomEdge.state === "collapsed" ? -units.gu(1) : 0
2405+
2406+ z: -1
2407+ anchors.horizontalCenter: parent.horizontalCenter
2408+ y: hidden ? invisiblePosition : visiblePosition
2409+
2410+ width: tipLabel.paintedWidth + units.gu(6)
2411+ height: bottomEdge.tipHeight + units.gu(1)
2412+ color: Theme.palette.normal.overlay
2413+ Label {
2414+ id: tipLabel
2415+
2416+ anchors {
2417+ top: parent.top
2418+ left: parent.left
2419+ right: parent.right
2420+ }
2421+ color: styleMusic.common.black // CUSTOM use black text so it is readable
2422+ height: bottomEdge.tipHeight
2423+ verticalAlignment: Text.AlignVCenter
2424+ horizontalAlignment: Text.AlignHCenter
2425+ opacity: tip.hidden ? 0.0 : 1.0
2426+ Behavior on opacity {
2427+ UbuntuNumberAnimation {
2428+ duration: UbuntuAnimation.SnapDuration
2429+ }
2430+ }
2431+ }
2432+ Behavior on y {
2433+ UbuntuNumberAnimation {
2434+ duration: UbuntuAnimation.SnapDuration
2435+ }
2436+ }
2437+ }
2438+
2439+
2440+ Rectangle {
2441+ id: shadow
2442+
2443+ anchors {
2444+ left: parent.left
2445+ right: parent.right
2446+ }
2447+ height: units.gu(1)
2448+ y: -height
2449+ z: -2
2450+ opacity: 0.0
2451+ gradient: Gradient {
2452+ GradientStop { position: 0.0; color: "transparent" }
2453+ GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.2) }
2454+ }
2455+ }
2456+
2457+ MouseArea {
2458+ id: mouseArea
2459+
2460+ preventStealing: true
2461+ drag {
2462+ axis: Drag.YAxis
2463+ target: bottomEdge
2464+ minimumY: bottomEdge.pageStartY
2465+ maximumY: page.height
2466+ threshold: 100
2467+ }
2468+
2469+ anchors {
2470+ left: parent.left
2471+ right: parent.right
2472+ }
2473+ height: bottomEdge.tipHeight
2474+ y: -height
2475+
2476+ onReleased: {
2477+ page.bottomEdgeReleased()
2478+ if (bottomEdge.y < (page.height - bottomEdgeExpandThreshold * 2 - bottomEdge.tipHeight)) {
2479+ bottomEdge.state = "expanded"
2480+ }
2481+ // Release case for panel state
2482+ else if (bottomEdge.y < (page.height - musicToolbar.height * 0.5)) {
2483+ bottomEdge.state = "panel" // CUSTOM, custom panel state
2484+ }
2485+ else {
2486+ bottomEdge.state = "collapsed"
2487+ bottomEdge.y = bottomEdge.height
2488+ }
2489+ }
2490+
2491+ onClicked: {
2492+ tip.hidden = false
2493+ hideIndicator.restart()
2494+ }
2495+
2496+ // custom
2497+ // update the Y position of the musicToolbar as the bottom edge is dragged
2498+ // do not move the toolbar 'higher' than its height
2499+ onMouseYChanged: musicToolbar.y = bottomEdge.y < page.height - musicToolbar.height ? page.height - musicToolbar.height : bottomEdge.y
2500+ }
2501+
2502+ state: "collapsed"
2503+ states: [
2504+ State {
2505+ name: "collapsed"
2506+ PropertyChanges {
2507+ target: bottomEdge
2508+ y: bottomEdge.height - (wideAspect ? musicToolbar.height : 0) // custom, in wideAspect toolbar does not hide
2509+ }
2510+ PropertyChanges {
2511+ target: tip
2512+ opacity: 1.0
2513+ }
2514+ PropertyChanges {
2515+ target: hideIndicator
2516+ running: true
2517+ }
2518+ PropertyChanges { // custom
2519+ // Set the music toolbar to be offscreen unless in wideaspect
2520+ target: musicToolbar
2521+ y: bottomEdge.height - (wideAspect ? musicToolbar.height : 0) // in wideAspect toolbar does not hide
2522+ }
2523+ },
2524+ State { // custom
2525+ name: "panel" // state for when Panel is shown
2526+ PropertyChanges {
2527+ target: bottomEdge
2528+ y: bottomEdge.height - musicToolbar.height
2529+ }
2530+ PropertyChanges {
2531+ target: hideIndicator
2532+ running: true
2533+ }
2534+ PropertyChanges {
2535+ target: tip
2536+ hidden: false
2537+ }
2538+ PropertyChanges {
2539+ target: musicToolbar
2540+ y: bottomEdge.height - musicToolbar.height
2541+ }
2542+ },
2543+ State {
2544+ name: "expanded"
2545+ PropertyChanges {
2546+ target: bottomEdge
2547+ y: bottomEdge.pageStartY
2548+ }
2549+ PropertyChanges {
2550+ target: hideIndicator
2551+ running: false
2552+ }
2553+ PropertyChanges { // custom
2554+ // Ensure that the musicToolbar is shown as the bottom edge is shown
2555+ target: musicToolbar
2556+ y: bottomEdge.height - musicToolbar.height
2557+ }
2558+ },
2559+ State {
2560+ name: "floating"
2561+ when: mouseArea.drag.active
2562+ PropertyChanges { // CUSTOM, otherwise if drag starts from panel Y gets reset
2563+ target: bottomEdge
2564+ y: bottomEdge.y
2565+ }
2566+ PropertyChanges {
2567+ target: shadow
2568+ opacity: 1.0
2569+ }
2570+ PropertyChanges {
2571+ target: hideIndicator
2572+ running: false
2573+ }
2574+ PropertyChanges {
2575+ target: tip
2576+ hidden: false
2577+ }
2578+ }
2579+ ]
2580+
2581+ transitions: [
2582+ Transition {
2583+ to: "expanded"
2584+ enabled: !bottomEdge.forceStateNoAnimation // CUSTOM, only animate if required
2585+ SequentialAnimation {
2586+ UbuntuNumberAnimation {
2587+ targets: bottomEdge
2588+ properties: "y"
2589+ duration: UbuntuAnimation.SlowDuration
2590+ }
2591+ ScriptAction {
2592+ script: page._pushPage()
2593+ }
2594+ }
2595+ },
2596+ Transition {
2597+ from: "expanded"
2598+ to: "collapsed"
2599+ SequentialAnimation {
2600+ ScriptAction {
2601+ script: {
2602+ nowPlaying.reparent(customLoader) // CUSTOM, rebind the now playing to the bottom edge
2603+
2604+ /* CUSTOM.
2605+ Qt.inputMethod.hide()
2606+ edgeLoader.item.parent = edgeLoader
2607+ edgeLoader.item.anchors.fill = edgeLoader
2608+ edgeLoader.item.active = false
2609+ */
2610+ }
2611+ }
2612+ UbuntuNumberAnimation {
2613+ targets: bottomEdge
2614+ properties: "y"
2615+ duration: UbuntuAnimation.SlowDuration
2616+ }
2617+ ScriptAction {
2618+ script: {
2619+ // destroy current bottom page
2620+ if (page.reloadBottomEdgePage) {
2621+ edgeLoader.active = false
2622+ }
2623+
2624+ // notify
2625+ page.bottomEdgeDismissed()
2626+
2627+ edgeLoader.active = true
2628+ tip.hidden = false
2629+ hideIndicator.restart()
2630+
2631+ // CUSTOM, collapse toolbar when going to collapsed mode
2632+ musicToolbar.hideToolbar()
2633+ }
2634+ }
2635+ }
2636+ },
2637+ Transition {
2638+ from: "floating"
2639+ to: "collapsed"
2640+ UbuntuNumberAnimation {
2641+ targets: bottomEdge
2642+ properties: "y"
2643+ }
2644+ },
2645+ Transition { // custom
2646+ to: "panel"
2647+ ScriptAction {
2648+ // Start autohide timer when going to panel
2649+ script: musicToolbar.startAutoHideTimer()
2650+ }
2651+ },
2652+ Transition { // custom
2653+ from: "panel"
2654+ ScriptAction {
2655+ // Stop any autohide timers when moving away from panel
2656+ script: musicToolbar.stopAutoHideTimer()
2657+ }
2658+ }
2659+ ]
2660+
2661+
2662+ Item {
2663+ anchors.fill: parent
2664+ clip: true
2665+
2666+ Item { // CUSTOM, item which will contain the bottom edge component
2667+ id: customLoader
2668+ anchors {
2669+ fill: parent
2670+ }
2671+ z: 1
2672+ }
2673+
2674+ Loader {
2675+ id: edgeLoader
2676+
2677+ z: 1
2678+ active: true
2679+ asynchronous: true
2680+ anchors.fill: parent
2681+
2682+ //WORKAROUND: The SDK move the page contents down to allocate space for the header we need to avoid that during the page dragging
2683+ Binding {
2684+ target: edgeLoader.status === Loader.Ready ? edgeLoader : null
2685+ property: "anchors.topMargin"
2686+ value: edgeLoader.item && edgeLoader.item.flickable ? edgeLoader.item.flickable.contentY : 0
2687+ when: !page.isReady
2688+ }
2689+
2690+ onLoaded: {
2691+ if (page.isReady && edgeLoader.item.active !== true) {
2692+ page._pushPage()
2693+ }
2694+ }
2695+ }
2696+ }
2697+ }
2698+}
2699
2700=== modified file 'common/SongsPage.qml'
2701--- common/SongsPage.qml 2014-08-16 13:38:36 +0000
2702+++ common/SongsPage.qml 2014-08-21 20:46:47 +0000
2703@@ -29,7 +29,7 @@
2704
2705 MusicPage {
2706 id: songStackPage
2707- anchors.bottomMargin: units.gu(.5)
2708+ objectName: "songStackPage"
2709 visible: false
2710
2711 property string line1: ""
2712
2713=== modified file 'music-app.qml'
2714--- music-app.qml 2014-08-21 18:54:06 +0000
2715+++ music-app.qml 2014-08-21 20:46:47 +0000
2716@@ -35,7 +35,6 @@
2717 import "scrobble.js" as Scrobble
2718 import "playlists.js" as Playlists
2719 import "common"
2720-
2721 MainView {
2722 objectName: "music"
2723 applicationName: "com.ubuntu.music"
2724@@ -598,7 +597,7 @@
2725 // Show toolbar and start timer if there is music
2726 if (!emptyPage.noMusic) {
2727 musicToolbar.showToolbar();
2728- musicToolbar.startAutohideTimer();
2729+ musicToolbar.startAutoHideTimer();
2730 }
2731 }
2732
2733@@ -990,7 +989,6 @@
2734 MusicToolbar {
2735 id: musicToolbar
2736 objectName: "musicToolbarObject"
2737- z: 200 // put on top of everything else
2738 }
2739
2740 PageStack {
2741@@ -999,7 +997,7 @@
2742 Tabs {
2743 id: tabs
2744 anchors {
2745- bottomMargin: wideAspect ? musicToolbar.fullHeight : undefined
2746+ //bottomMargin: wideAspect ? musicToolbar.fullHeight : undefined
2747 fill: parent
2748 }
2749
2750@@ -1123,8 +1121,9 @@
2751 function pushNowPlaying()
2752 {
2753 // only push if on a different page
2754- if (mainPageStack.currentPage !== nowPlaying) {
2755- mainPageStack.push(nowPlaying);
2756+ if (!musicToolbar.isNowPlaying(musicToolbar.currentPage)) {
2757+ // Emulate dragging the bottom edge up
2758+ musicToolbar.currentPage.bottomEdgeState = "expanded"
2759 }
2760 }
2761
2762@@ -1161,8 +1160,9 @@
2763 }
2764 }
2765
2766- Page {
2767+ MusicPage {
2768 id: emptyPage
2769+ bottomEdgeEnabled: false
2770 title: i18n.tr("Music")
2771 visible: noMusic
2772
2773
2774=== modified file 'tests/autopilot/music_app/__init__.py'
2775--- tests/autopilot/music_app/__init__.py 2014-08-21 17:59:15 +0000
2776+++ tests/autopilot/music_app/__init__.py 2014-08-21 20:46:47 +0000
2777@@ -257,6 +257,12 @@
2778 if item.text == trackTitle:
2779 return item
2780
2781+ def get_song_stack_page(self):
2782+ return self.select_single("*", objectName="songStackPage")
2783+
2784+ def get_tracks_page(self):
2785+ return self.select_single("*", objectName="tracksPage")
2786+
2787 def get_songs_page_listview_tracktitle(self, trackTitle):
2788 tracktitles = self.select_many_retry(
2789 "Label", objectName="songspage-tracktitle")
2790
2791=== modified file 'tests/autopilot/music_app/tests/test_music.py'
2792--- tests/autopilot/music_app/tests/test_music.py 2014-08-19 23:30:26 +0000
2793+++ tests/autopilot/music_app/tests/test_music.py 2014-08-21 20:46:47 +0000
2794@@ -41,6 +41,10 @@
2795 def pointing_device(self):
2796 return self.app.app.pointing_device
2797
2798+ # wait for animations to complete
2799+ page = self.main_view.get_tracks_page()
2800+ page.isReady.wait_for(True)
2801+
2802 def turn_shuffle_off(self):
2803 if self.player.shuffle:
2804 shufflebutton = self.main_view.get_shuffle_button()
2805@@ -527,6 +531,10 @@
2806 self.trackTitle)
2807 self.pointing_device.click_object(track)
2808
2809+ # wait for animations to complete
2810+ page = self.main_view.get_song_stack_page()
2811+ page.isReady.wait_for(True)
2812+
2813 # verify track queue has added all songs to initial value
2814 endtracksCount = self.main_view.get_queue_track_count()
2815 self.assertThat(endtracksCount, Equals(initialtracksCount + 2))

Subscribers

People subscribed via source and target branches

to status/vote changes: