Merge lp:~ahayzen/music-app/remix-queue-split into lp:music-app/remix

Proposed by Andrew Hayzen
Status: Work in progress
Proposed branch: lp:~ahayzen/music-app/remix-queue-split
Merge into: lp:music-app/remix
Diff against target: 978 lines (+449/-383)
4 files modified
MusicNowPlaying.qml (+25/-344)
MusicQueue.qml (+368/-0)
tests/autopilot/music_app/__init__.py (+19/-33)
tests/autopilot/music_app/tests/test_music.py (+37/-6)
To merge this branch: bzr merge lp:~ahayzen/music-app/remix-queue-split
Reviewer Review Type Date Requested Status
Victor Thompson Needs Fixing
Ubuntu Phone Apps Jenkins Bot continuous-integration Needs Fixing
Review via email: mp+241884@code.launchpad.net

Commit message

* Split the MusicQueue and MusicNowPlaying into two pages (still act like toggles though)

Description of the change

* Split the MusicQueue and MusicNowPlaying into two pages (still act like toggles though)

Note this is in prep for bottom edge development.

Please test both pages in great detail, remember things like header actions/multiselect etc :)

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)
Revision history for this message
Victor Thompson (vthompson) wrote :

When clicking on the toolbar while in Queue view the following error is produced:

file:///home/victor/Development/remix-queue-split/music-app.qml:1047: Error: Cannot assign to non-existent property "isListView"

review: Needs Fixing
Revision history for this message
Victor Thompson (vthompson) wrote :

This also causes the Queue to be rebuilt each time it is shown. Currently it is fairly distracting when it is doing so. Do we need to rebuild it each time?

Unmerged revisions

741. By Andrew Hayzen

* Split the MusicQueue and MusicNowPlaying into two pages (still act like toggles though)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'MusicNowPlaying.qml'
--- MusicNowPlaying.qml 2014-11-07 22:51:16 +0000
+++ MusicNowPlaying.qml 2014-11-15 22:18:22 +0000
@@ -17,181 +17,42 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */18 */
1919
20import QtMultimedia 5.0
21import QtQuick 2.320import QtQuick 2.3
22import QtQuick.LocalStorage 2.0
23import Ubuntu.Components 1.121import Ubuntu.Components 1.1
24import Ubuntu.Thumbnailer 0.122import Ubuntu.Thumbnailer 0.1
25import "common"23import "common"
26import "common/ListItemActions"24
27import "meta-database.js" as Library
28import "playlists.js" as Playlists
2925
30MusicPage {26MusicPage {
31 id: nowPlaying27 id: nowPlaying
32 flickable: isListView ? queueListLoader.item : null // Ensures that the header is shown in fullview
33 objectName: "nowPlayingPage"28 objectName: "nowPlayingPage"
34 title: isListView ? i18n.tr("Queue") : i18n.tr("Now playing")29 title: i18n.tr("Now playing")
35 visible: false30
3631 head {
37 property bool isListView: false32 actions: [
3833 Action {
39 onIsListViewChanged: {34 objectName: "toggleView"
40 if (isListView) { // When changing to the queue positionAt the currentIndex35 iconName: "media-playlist"
41 // ensure the loader and listview is ready36 onTriggered: {
42 if (queueListLoader.status === Loader.Ready) {37 var comp = Qt.createComponent("MusicQueue.qml")
43 ensureListViewLoaded()38 var queue = comp.createObject(mainPageStack, {});
44 } else {39
45 queueListLoader.onStatusChanged.connect(function() {40 if (queue == null) { // Error Handling
46 if (queueListLoader.status === Loader.Ready) {41 console.log("Error creating object");
47 ensureListViewLoaded()42 }
48 }43
49 })44 mainPageStack.pop();
50 }45 mainPageStack.push(queue);
51 }46
52 }47 queue.positionAtWhenReady(); // runs positionAt once queue is loaded
5348 }
54 // Ensure that the listview has loaded before attempting to positionAt49 }
55 function ensureListViewLoaded() {50 ]
56 if (queueListLoader.item.count === trackQueue.model.count) {51 }
57 positionAt(player.currentIndex);
58 } else {
59 queueListLoader.item.onCountChanged.connect(function() {
60 if (queueListLoader.item.count === trackQueue.model.count) {
61 positionAt(player.currentIndex);
62 }
63 })
64 }
65 }
66
67 // Position the view at the index
68 function positionAt(index) {
69 queueListLoader.item.positionViewAtIndex(index, ListView.Center);
70 }
71
72 state: isListView && queueListLoader.item.state === "multiselectable" ? "selection" : "default"
73 states: [
74 PageHeadState {
75 id: defaultState
76
77 name: "default"
78 actions: [
79 Action {
80 objectName: "toggleView"
81 iconName: "media-playlist"
82 onTriggered: {
83 isListView = !isListView
84 }
85 },
86 Action {
87 enabled: trackQueue.model.count > 0
88 iconName: "add-to-playlist"
89 text: i18n.tr("Add to playlist")
90 visible: isListView
91 onTriggered: {
92 var items = []
93
94 for (var i=0; i < trackQueue.model.count; i++) {
95 items.push(makeDict(trackQueue.model.get(i)));
96 }
97
98 var comp = Qt.createComponent("MusicaddtoPlaylist.qml")
99 var addToPlaylist = comp.createObject(mainPageStack, {"chosenElements": items});
100
101 if (addToPlaylist == null) { // Error Handling
102 console.log("Error creating object");
103 }
104
105 mainPageStack.push(addToPlaylist)
106 }
107 },
108 Action {
109 enabled: trackQueue.model.count > 0
110 iconName: "delete"
111 objectName: "clearQueue"
112 text: i18n.tr("Clear queue")
113 visible: isListView
114 onTriggered: {
115 pageStack.pop()
116 trackQueue.clear()
117 }
118 }
119 ]
120 PropertyChanges {
121 target: nowPlaying.head
122 backAction: defaultState.backAction
123 actions: defaultState.actions
124 }
125 },
126 PageHeadState {
127 id: selectionState
128
129 name: "selection"
130 backAction: Action {
131 text: i18n.tr("Cancel selection")
132 iconName: "back"
133 onTriggered: queueListLoader.item.state = "normal"
134 }
135 actions: [
136 Action {
137 text: i18n.tr("Select All")
138 iconName: "select"
139 onTriggered: {
140 if (queueListLoader.item.selectedItems.length === trackQueue.model.count) {
141 queueListLoader.item.clearSelection()
142 } else {
143 queueListLoader.item.selectAll()
144 }
145 }
146 },
147 Action {
148 enabled: queueListLoader.item.selectedItems.length > 0
149 iconName: "add-to-playlist"
150 text: i18n.tr("Add to playlist")
151 onTriggered: {
152 var items = []
153
154 for (var i=0; i < queueListLoader.item.selectedItems.length; i++) {
155 items.push(makeDict(trackQueue.model.get(queueListLoader.item.selectedItems[i])));
156 }
157
158 var comp = Qt.createComponent("MusicaddtoPlaylist.qml")
159 var addToPlaylist = comp.createObject(mainPageStack, {"chosenElements": items});
160
161 if (addToPlaylist == null) { // Error Handling
162 console.log("Error creating object");
163 }
164
165 mainPageStack.push(addToPlaylist)
166
167 queueListLoader.item.closeSelection()
168 }
169 },
170 Action {
171 enabled: queueListLoader.item.selectedItems.length > 0
172 iconName: "delete"
173 text: i18n.tr("Delete")
174 onTriggered: {
175 for (var i=0; i < queueListLoader.item.selectedItems.length; i++) {
176 removeQueue(queueListLoader.item.selectedItems[i])
177 }
178
179 queueListLoader.item.closeSelection()
180 }
181 }
182 ]
183 PropertyChanges {
184 target: nowPlaying.head
185 backAction: selectionState.backAction
186 actions: selectionState.actions
187 }
188 }
189 ]
19052
191 Item {53 Item {
192 id: fullview54 id: fullview
193 anchors.fill: parent55 anchors.fill: parent
194 visible: !isListView
19556
196 BlurredBackground {57 BlurredBackground {
197 id: blurredBackground58 id: blurredBackground
@@ -430,7 +291,7 @@
430 anchors.horizontalCenter: parent.horizontalCenter291 anchors.horizontalCenter: parent.horizontalCenter
431 opacity: emptyPage.noMusic ? .4 : 1292 opacity: emptyPage.noMusic ? .4 : 1
432 color: "white"293 color: "white"
433 name: player.playbackState === MediaPlayer.PlayingState ? "media-playback-pause" : "media-playback-start"294 name: player.isPlaying ? "media-playback-pause" : "media-playback-start"
434 objectName: "playShape"295 objectName: "playShape"
435 }296 }
436 }297 }
@@ -484,184 +345,4 @@
484 }345 }
485 }346 }
486 }347 }
487
488 function removeQueue(index)
489 {
490 var removedIndex = index
491
492 if (trackQueue.model.count === 1) {
493 player.stop()
494 musicToolbar.goBack()
495 } else if (index === player.currentIndex) {
496 player.nextSong(player.isPlaying);
497 }
498
499 trackQueue.model.remove(index);
500 Library.removeQueueItem(removedIndex);
501
502 if (removedIndex < player.currentIndex) {
503 // update index as the old has been removed
504 player.currentIndex -= 1;
505 queueIndex -= 1;
506 }
507 }
508
509 Loader {
510 id: queueListLoader
511 anchors {
512 fill: parent
513 }
514 asynchronous: true
515 sourceComponent: ListView {
516 id: queueList
517 anchors {
518 bottomMargin: units.gu(2)
519 fill: parent
520 topMargin: units.gu(2)
521 }
522 delegate: queueDelegate
523 footer: Item {
524 height: mainView.height - (styleMusic.common.expandHeight + queueList.currentHeight) + units.gu(8)
525 }
526 model: trackQueue.model
527 objectName: "nowPlayingqueueList"
528
529 property int normalHeight: units.gu(6)
530 property int transitionDuration: 250 // transition length of animations
531
532 onCountChanged: {
533 customdebug("Queue: Now has: " + queueList.count + " tracks")
534 }
535
536 // Requirements for ListItemWithActions
537 property var selectedItems: []
538
539 signal clearSelection()
540 signal closeSelection()
541 signal selectAll()
542
543 onClearSelection: selectedItems = []
544 onCloseSelection: {
545 clearSelection()
546 state = "normal"
547 }
548 onSelectAll: {
549 var tmp = selectedItems
550
551 for (var i=0; i < model.count; i++) {
552 if (tmp.indexOf(i) === -1) {
553 tmp.push(i)
554 }
555 }
556
557 selectedItems = tmp
558 }
559 onVisibleChanged: {
560 if (!visible) {
561 clearSelection(true)
562 }
563 }
564
565 Component.onCompleted: {
566 // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition
567 // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration
568 var scaleFactor = units.gridUnit / 8;
569 maximumFlickVelocity = maximumFlickVelocity * scaleFactor;
570 flickDeceleration = flickDeceleration * scaleFactor;
571 }
572
573 Component {
574 id: queueDelegate
575 ListItemWithActions {
576 id: queueListItem
577 color: player.currentIndex === index ? "#2c2c34" : "transparent"
578 height: queueList.normalHeight
579 objectName: "nowPlayingListItem" + index
580 state: ""
581
582 leftSideAction: Remove {
583 onTriggered: removeQueue(index)
584 }
585 multiselectable: true
586 reorderable: true
587 rightSideActions: [
588 AddToPlaylist{
589
590 }
591 ]
592
593 onItemClicked: {
594 customdebug("File: " + model.filename) // debugger
595 trackQueueClick(index); // toggle track state
596 }
597 onReorder: {
598 console.debug("Move: ", from, to);
599
600 trackQueue.model.move(from, to, 1);
601 Library.moveQueueItem(from, to);
602
603 // Maintain currentIndex with current song
604 if (from === player.currentIndex) {
605 player.currentIndex = to;
606 }
607 else if (from < player.currentIndex && to >= player.currentIndex) {
608 player.currentIndex -= 1;
609 }
610 else if (from > player.currentIndex && to <= player.currentIndex) {
611 player.currentIndex += 1;
612 }
613
614 queueIndex = player.currentIndex
615 }
616
617 Item {
618 id: trackContainer;
619 anchors {
620 fill: parent
621 }
622
623 NumberAnimation {
624 id: trackContainerReorderAnimation
625 target: trackContainer;
626 property: "anchors.leftMargin";
627 duration: queueList.transitionDuration;
628 to: units.gu(2)
629 }
630
631 NumberAnimation {
632 id: trackContainerResetAnimation
633 target: trackContainer;
634 property: "anchors.leftMargin";
635 duration: queueList.transitionDuration;
636 to: units.gu(0.5)
637 }
638
639 MusicRow {
640 id: musicRow
641 height: parent.height
642 column: Column {
643 Label {
644 id: trackTitle
645 color: player.currentIndex === index ? UbuntuColors.blue
646 : styleMusic.common.music
647 fontSize: "small"
648 objectName: "titleLabel"
649 text: model.title
650 }
651
652 Label {
653 id: trackArtist
654 color: styleMusic.common.subtitle
655 fontSize: "x-small"
656 objectName: "artistLabel"
657 text: model.author
658 }
659 }
660 }
661 }
662 }
663 }
664 }
665 visible: isListView
666 }
667}348}
668349
=== added file 'MusicQueue.qml'
--- MusicQueue.qml 1970-01-01 00:00:00 +0000
+++ MusicQueue.qml 2014-11-15 22:18:22 +0000
@@ -0,0 +1,368 @@
1/*
2 * Copyright (C) 2013, 2014
3 * Andrew Hayzen <ahayzen@gmail.com>
4 * Daniel Holm <d.holmen@gmail.com>
5 * Victor Thompson <victor.thompson@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20import QtQuick 2.3
21import Ubuntu.Components 1.1
22import "common"
23import "common/ListItemActions"
24import "meta-database.js" as Library
25import "playlists.js" as Playlists
26
27
28MusicPage {
29 id: queuePage
30 flickable: queueListLoader.item
31 objectName: "queuePage"
32 title: i18n.tr("Queue")
33 state: queueListLoader.item.state === "multiselectable" ? "selection" : "default"
34 states: [
35 PageHeadState {
36 id: defaultState
37
38 name: "default"
39 actions: [
40 Action {
41 objectName: "toggleView"
42 iconName: "media-playlist"
43 onTriggered: {
44 var comp = Qt.createComponent("MusicNowPlaying.qml")
45 var nowPlaying = comp.createObject(mainPageStack, {});
46
47 if (nowPlaying == null) { // Error Handling
48 console.log("Error creating object");
49 }
50
51 mainPageStack.pop();
52 mainPageStack.push(nowPlaying);
53 }
54 },
55 Action {
56 enabled: trackQueue.model.count > 0
57 iconName: "add-to-playlist"
58 text: i18n.tr("Add to playlist")
59 onTriggered: {
60 var items = []
61
62 for (var i=0; i < trackQueue.model.count; i++) {
63 items.push(makeDict(trackQueue.model.get(i)));
64 }
65
66 var comp = Qt.createComponent("MusicaddtoPlaylist.qml")
67 var addToPlaylist = comp.createObject(mainPageStack, {"chosenElements": items});
68
69 if (addToPlaylist == null) { // Error Handling
70 console.log("Error creating object");
71 }
72
73 mainPageStack.push(addToPlaylist)
74 }
75 },
76 Action {
77 enabled: trackQueue.model.count > 0
78 iconName: "delete"
79 objectName: "clearQueue"
80 text: i18n.tr("Clear queue")
81 onTriggered: {
82 pageStack.pop()
83 trackQueue.clear()
84 }
85 }
86 ]
87 PropertyChanges {
88 target: queuePage.head
89 backAction: defaultState.backAction
90 actions: defaultState.actions
91 }
92 },
93 PageHeadState {
94 id: selectionState
95
96 name: "selection"
97 backAction: Action {
98 text: i18n.tr("Cancel selection")
99 iconName: "back"
100 onTriggered: queueListLoader.item.state = "normal"
101 }
102 actions: [
103 Action {
104 text: i18n.tr("Select All")
105 iconName: "select"
106 onTriggered: {
107 if (queueListLoader.item.selectedItems.length === trackQueue.model.count) {
108 queueListLoader.item.clearSelection()
109 } else {
110 queueListLoader.item.selectAll()
111 }
112 }
113 },
114 Action {
115 enabled: queueListLoader.item.selectedItems.length > 0
116 iconName: "add-to-playlist"
117 text: i18n.tr("Add to playlist")
118 onTriggered: {
119 var items = []
120
121 for (var i=0; i < queueListLoader.item.selectedItems.length; i++) {
122 items.push(makeDict(trackQueue.model.get(queueListLoader.item.selectedItems[i])));
123 }
124
125 var comp = Qt.createComponent("MusicaddtoPlaylist.qml")
126 var addToPlaylist = comp.createObject(mainPageStack, {"chosenElements": items});
127
128 if (addToPlaylist == null) { // Error Handling
129 console.log("Error creating object");
130 }
131
132 mainPageStack.push(addToPlaylist)
133
134 queueListLoader.item.closeSelection()
135 }
136 },
137 Action {
138 enabled: queueListLoader.item.selectedItems.length > 0
139 iconName: "delete"
140 text: i18n.tr("Delete")
141 onTriggered: {
142 for (var i=0; i < queueListLoader.item.selectedItems.length; i++) {
143 removeQueue(queueListLoader.item.selectedItems[i])
144 }
145
146 queueListLoader.item.closeSelection()
147 }
148 }
149 ]
150 PropertyChanges {
151 target: queuePage.head
152 backAction: selectionState.backAction
153 actions: selectionState.actions
154 }
155 }
156 ]
157
158 // Ensure that the listview has loaded before attempting to positionAt
159 function ensureListViewLoaded() {
160 if (queueListLoader.item.count === trackQueue.model.count) {
161 positionAt(player.currentIndex);
162 } else {
163 queueListLoader.item.onCountChanged.connect(function() {
164 if (queueListLoader.item.count === trackQueue.model.count) {
165 positionAt(player.currentIndex);
166 }
167 })
168 }
169 }
170
171 function removeQueue(index)
172 {
173 var removedIndex = index
174
175 if (trackQueue.model.count === 1) {
176 player.stop()
177 musicToolbar.goBack()
178 } else if (index === player.currentIndex) {
179 player.nextSong(player.isPlaying);
180 }
181
182 trackQueue.model.remove(index);
183 Library.removeQueueItem(removedIndex);
184
185 if (removedIndex < player.currentIndex) {
186 // update index as the old has been removed
187 player.currentIndex -= 1;
188 queueIndex -= 1;
189 }
190 }
191
192 // Position the view at the index
193 function positionAt(index) {
194 queueListLoader.item.positionViewAtIndex(index, ListView.Center);
195 }
196
197 // Ensure the loader is ready and the list is ready before positioning at
198 function positionAtWhenReady() {
199 // ensure the loader and listview is ready
200 if (queueListLoader.status === Loader.Ready) {
201 ensureListViewLoaded()
202 } else {
203 queueListLoader.onStatusChanged.connect(function() {
204 if (queueListLoader.status === Loader.Ready) {
205 ensureListViewLoaded()
206 }
207 })
208 }
209 }
210
211 Loader {
212 id: queueListLoader
213 anchors {
214 fill: parent
215 }
216 asynchronous: true
217 sourceComponent: ListView {
218 id: queueList
219 anchors {
220 bottomMargin: units.gu(2)
221 fill: parent
222 topMargin: units.gu(2)
223 }
224 delegate: queueDelegate
225 footer: Item {
226 height: mainView.height - (styleMusic.common.expandHeight + queueList.currentHeight) + units.gu(8)
227 }
228 model: trackQueue.model
229 objectName: "queueListView"
230
231 property int normalHeight: units.gu(6)
232 property int transitionDuration: 250 // transition length of animations
233
234 onCountChanged: {
235 customdebug("Queue: Now has: " + queueList.count + " tracks")
236 }
237
238 // Requirements for ListItemWithActions
239 property var selectedItems: []
240
241 signal clearSelection()
242 signal closeSelection()
243 signal selectAll()
244
245 onClearSelection: selectedItems = []
246 onCloseSelection: {
247 clearSelection()
248 state = "normal"
249 }
250 onSelectAll: {
251 var tmp = selectedItems
252
253 for (var i=0; i < model.count; i++) {
254 if (tmp.indexOf(i) === -1) {
255 tmp.push(i)
256 }
257 }
258
259 selectedItems = tmp
260 }
261 onVisibleChanged: {
262 if (!visible) {
263 clearSelection(true)
264 }
265 }
266
267 Component.onCompleted: {
268 // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition
269 // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration
270 var scaleFactor = units.gridUnit / 8;
271 maximumFlickVelocity = maximumFlickVelocity * scaleFactor;
272 flickDeceleration = flickDeceleration * scaleFactor;
273 }
274
275 Component {
276 id: queueDelegate
277 ListItemWithActions {
278 id: queueListItem
279 color: player.currentIndex === index ? "#2c2c34" : "transparent"
280 height: queueList.normalHeight
281 objectName: "queueListItem" + index
282 state: ""
283
284 leftSideAction: Remove {
285 onTriggered: removeQueue(index)
286 }
287 multiselectable: true
288 reorderable: true
289 rightSideActions: [
290 AddToPlaylist{
291
292 }
293 ]
294
295 onItemClicked: {
296 customdebug("File: " + model.filename) // debugger
297 trackQueueClick(index); // toggle track state
298 }
299 onReorder: {
300 console.debug("Move: ", from, to);
301
302 trackQueue.model.move(from, to, 1);
303 Library.moveQueueItem(from, to);
304
305 // Maintain currentIndex with current song
306 if (from === player.currentIndex) {
307 player.currentIndex = to;
308 }
309 else if (from < player.currentIndex && to >= player.currentIndex) {
310 player.currentIndex -= 1;
311 }
312 else if (from > player.currentIndex && to <= player.currentIndex) {
313 player.currentIndex += 1;
314 }
315
316 queueIndex = player.currentIndex
317 }
318
319 Item {
320 id: trackContainer;
321 anchors {
322 fill: parent
323 }
324
325 NumberAnimation {
326 id: trackContainerReorderAnimation
327 target: trackContainer;
328 property: "anchors.leftMargin";
329 duration: queueList.transitionDuration;
330 to: units.gu(2)
331 }
332
333 NumberAnimation {
334 id: trackContainerResetAnimation
335 target: trackContainer;
336 property: "anchors.leftMargin";
337 duration: queueList.transitionDuration;
338 to: units.gu(0.5)
339 }
340
341 MusicRow {
342 id: musicRow
343 height: parent.height
344 column: Column {
345 Label {
346 id: trackTitle
347 color: player.currentIndex === index ? UbuntuColors.blue
348 : styleMusic.common.music
349 fontSize: "small"
350 objectName: "titleLabel"
351 text: model.title
352 }
353
354 Label {
355 id: trackArtist
356 color: styleMusic.common.subtitle
357 fontSize: "x-small"
358 objectName: "artistLabel"
359 text: model.author
360 }
361 }
362 }
363 }
364 }
365 }
366 }
367 }
368}
0369
=== modified file 'tests/autopilot/music_app/__init__.py'
--- tests/autopilot/music_app/__init__.py 2014-11-07 22:54:20 +0000
+++ tests/autopilot/music_app/__init__.py 2014-11-15 22:18:22 +0000
@@ -21,28 +21,6 @@
21 return func_wrapper21 return func_wrapper
2222
2323
24def ensure_now_playing_full(func):
25 """Wrapper which ensures the now playing is full before clicking"""
26 def func_wrapper(self, *args, **kwargs):
27 if self.isListView:
28 self.click_toggle_view()
29
30 return func(self, *args, **kwargs)
31
32 return func_wrapper
33
34
35def ensure_now_playing_list(func):
36 """Wrapper which ensures the now playing is list before clicking"""
37 def func_wrapper(self, *args, **kwargs):
38 if not self.isListView:
39 self.click_toggle_view()
40
41 return func(self, *args, **kwargs)
42
43 return func_wrapper
44
45
46class MusicApp(object):24class MusicApp(object):
47 """Autopilot helper object for the Music application."""25 """Autopilot helper object for the Music application."""
4826
@@ -89,6 +67,10 @@
89 return self.main_view.select_single("LibraryListModel",67 return self.main_view.select_single("LibraryListModel",
90 objectName="trackQueue").count68 objectName="trackQueue").count
9169
70 def get_queue_page(self):
71 return self.app.wait_select_single(MusicQueue,
72 objectName="queuePage")
73
92 def get_songs_page(self):74 def get_songs_page(self):
93 return self.app.wait_select_single(SongsPage, objectName="songsPage")75 return self.app.wait_select_single(SongsPage, objectName="songsPage")
9476
@@ -242,27 +224,22 @@
242224
243 self.visible.wait_for(True)225 self.visible.wait_for(True)
244226
245 @ensure_now_playing_full
246 @click_object227 @click_object
247 def click_forward_button(self):228 def click_forward_button(self):
248 return self.wait_select_single("*", objectName="forwardShape")229 return self.wait_select_single("*", objectName="forwardShape")
249230
250 @ensure_now_playing_full
251 @click_object231 @click_object
252 def click_play_button(self):232 def click_play_button(self):
253 return self.wait_select_single("*", objectName="playShape")233 return self.wait_select_single("*", objectName="playShape")
254234
255 @ensure_now_playing_full
256 @click_object235 @click_object
257 def click_previous_button(self):236 def click_previous_button(self):
258 return self.wait_select_single("*", objectName="previousShape")237 return self.wait_select_single("*", objectName="previousShape")
259238
260 @ensure_now_playing_full
261 @click_object239 @click_object
262 def click_repeat_button(self):240 def click_repeat_button(self):
263 return self.wait_select_single("*", objectName="repeatShape")241 return self.wait_select_single("*", objectName="repeatShape")
264242
265 @ensure_now_playing_full
266 @click_object243 @click_object
267 def click_shuffle_button(self):244 def click_shuffle_button(self):
268 return self.wait_select_single("*", objectName="shuffleShape")245 return self.wait_select_single("*", objectName="shuffleShape")
@@ -270,12 +247,6 @@
270 def click_toggle_view(self):247 def click_toggle_view(self):
271 self.main_view.get_header().click_action_button("toggleView")248 self.main_view.get_header().click_action_button("toggleView")
272249
273 @ensure_now_playing_list
274 def get_track(self, i):
275 return (self.wait_select_single(ListItemWithActions,
276 objectName="nowPlayingListItem" + str(i)))
277
278 @ensure_now_playing_full
279 def seek_to(self, percentage):250 def seek_to(self, percentage):
280 progress_bar = self.wait_select_single(251 progress_bar = self.wait_select_single(
281 "*", objectName="progressSliderShape")252 "*", objectName="progressSliderShape")
@@ -300,6 +271,21 @@
300 self.player.shuffle.wait_for(state)271 self.player.shuffle.wait_for(state)
301272
302273
274class MusicQueue(MusicPage):
275 """ Autopilot helper for queue page """
276 def __init__(self, *args):
277 super(MusicPage, self).__init__(*args)
278
279 self.visible.wait_for(True)
280
281 def click_toggle_view(self):
282 self.main_view.get_header().click_action_button("toggleView")
283
284 def get_track(self, i):
285 return (self.wait_select_single(ListItemWithActions,
286 objectName="queueListItem" + str(i)))
287
288
303class AlbumsPage(MusicPage):289class AlbumsPage(MusicPage):
304 """ Autopilot helper for the albums page """290 """ Autopilot helper for the albums page """
305 def __init__(self, *args):291 def __init__(self, *args):
306292
=== modified file 'tests/autopilot/music_app/tests/test_music.py'
--- tests/autopilot/music_app/tests/test_music.py 2014-11-07 23:08:29 +0000
+++ tests/autopilot/music_app/tests/test_music.py 2014-11-15 22:18:22 +0000
@@ -95,8 +95,13 @@
95 # Re get now playing page as it has changed95 # Re get now playing page as it has changed
96 now_playing_page = self.app.get_now_playing_page()96 now_playing_page = self.app.get_now_playing_page()
9797
98 # Switch to the queue
99 now_playing_page.click_toggle_view()
100
98 # verify song's metadata matches the item added to the Now Playing view101 # verify song's metadata matches the item added to the Now Playing view
99 current_track = now_playing_page.get_track(self.player.currentIndex)102 queue_page = self.app.get_queue_page()
103
104 current_track = queue_page.get_track(self.player.currentIndex)
100105
101 self.assertThat(current_track.get_label_text("artistLabel"),106 self.assertThat(current_track.get_label_text("artistLabel"),
102 Equals(self.tracks[0]["artist"]))107 Equals(self.tracks[0]["artist"]))
@@ -350,8 +355,13 @@
350 # Re get now playing page as it has changed355 # Re get now playing page as it has changed
351 now_playing_page = self.app.get_now_playing_page()356 now_playing_page = self.app.get_now_playing_page()
352357
358 # Switch to the queue
359 now_playing_page.click_toggle_view()
360
353 # verify song's metadata matches the item added to the Now Playing view361 # verify song's metadata matches the item added to the Now Playing view
354 current_track = now_playing_page.get_track(self.player.currentIndex)362 queue_page = self.app.get_queue_page()
363
364 current_track = queue_page.get_track(self.player.currentIndex)
355365
356 self.assertThat(current_track.get_label_text("artistLabel"),366 self.assertThat(current_track.get_label_text("artistLabel"),
357 Equals(tracks[0]["artist"]))367 Equals(tracks[0]["artist"]))
@@ -385,8 +395,13 @@
385 Eventually(NotEquals(self.app.get_queue_count())))395 Eventually(NotEquals(self.app.get_queue_count())))
386 self.assertThat(self.player.isPlaying, Eventually(Equals(True)))396 self.assertThat(self.player.isPlaying, Eventually(Equals(True)))
387397
398 # Switch to the queue
399 now_playing_page.click_toggle_view()
400
388 # verify song's metadata matches the item added to the Now Playing view401 # verify song's metadata matches the item added to the Now Playing view
389 current_track = now_playing_page.get_track(self.player.currentIndex)402 queue_page = self.app.get_queue_page()
403
404 current_track = queue_page.get_track(self.player.currentIndex)
390405
391 self.assertThat(current_track.get_label_text("artistLabel"),406 self.assertThat(current_track.get_label_text("artistLabel"),
392 Equals(self.tracks[0]["artist"]))407 Equals(self.tracks[0]["artist"]))
@@ -425,8 +440,13 @@
425 # Re get now playing page as it has changed440 # Re get now playing page as it has changed
426 now_playing_page = self.app.get_now_playing_page()441 now_playing_page = self.app.get_now_playing_page()
427442
443 # Switch to the queue
444 now_playing_page.click_toggle_view()
445
428 # verify song's metadata matches the item added to the Now Playing view446 # verify song's metadata matches the item added to the Now Playing view
429 current_track = now_playing_page.get_track(self.player.currentIndex)447 queue_page = self.app.get_queue_page()
448
449 current_track = queue_page.get_track(self.player.currentIndex)
430450
431 self.assertThat(current_track.get_label_text("artistLabel"),451 self.assertThat(current_track.get_label_text("artistLabel"),
432 Equals(self.tracks[0]["artist"]))452 Equals(self.tracks[0]["artist"]))
@@ -527,8 +547,13 @@
527 Eventually(NotEquals(self.app.get_queue_count())))547 Eventually(NotEquals(self.app.get_queue_count())))
528 self.assertThat(self.player.isPlaying, Eventually(Equals(True)))548 self.assertThat(self.player.isPlaying, Eventually(Equals(True)))
529549
550 # Switch to the queue
551 now_playing_page.click_toggle_view()
552
530 # verify song's metadata matches the item added to the Now Playing view553 # verify song's metadata matches the item added to the Now Playing view
531 current_track = now_playing_page.get_track(self.player.currentIndex)554 queue_page = self.app.get_queue_page()
555
556 current_track = queue_page.get_track(self.player.currentIndex)
532557
533 self.assertThat(current_track.get_label_text("artistLabel"),558 self.assertThat(current_track.get_label_text("artistLabel"),
534 Equals(tracks[0]["artist"]))559 Equals(tracks[0]["artist"]))
@@ -546,8 +571,14 @@
546 # get initial queue count571 # get initial queue count
547 initial_queue_count = self.app.get_queue_count()572 initial_queue_count = self.app.get_queue_count()
548573
574 # Switch to the queue
575 now_playing_page.click_toggle_view()
576
577 # verify song's metadata matches the item added to the Now Playing view
578 queue_page = self.app.get_queue_page()
579
549 # get track row and swipe to reveal swipe to delete580 # get track row and swipe to reveal swipe to delete
550 track = now_playing_page.get_track(0)581 track = queue_page.get_track(0)
551 track.swipe_to_delete()582 track.swipe_to_delete()
552583
553 track.confirm_removal() # confirm delete584 track.confirm_removal() # confirm delete

Subscribers

People subscribed via source and target branches