Merge lp:~ahayzen/music-app/bottom-edge-implementation-001 into lp:music-app/trusty
- bottom-edge-implementation-001
- Merge into trusty
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 |
Related bugs: |
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
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
- 536. By Andrew Hayzen
-
* Fix for console errors
* Improvements for ap tests
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:536
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 537. By Andrew Hayzen
-
* Fixes for ap
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:537
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 538. By Andrew Hayzen
-
* Add wait for isReady
- 539. By Andrew Hayzen
-
* Remove unneeded property alias
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:539
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 540. By Andrew Hayzen
-
* Sync with upstream bottom edge
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:540
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 541. By Andrew Hayzen
-
* Fix for panel state dragging
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:541
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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.
- 542. By Andrew Hayzen
-
* Fix for margin on stacked pages
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:542
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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 "upstreamcompon
2. I see the following error in the logs, not sure if it was introudced here:
file://
usicNowPlaying: Cannot anchor to an item that isn't a parent or sibling.
I also added a few inline comments.
- 543. By Andrew Hayzen
-
* Fixes for some inline diff comments
- 544. By Andrew Hayzen
-
* Merge of trunk
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:544
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 545. By Andrew Hayzen
-
* Merge of trunk
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:545
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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
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)) |
FAILED: Continuous integration, rev:535 91.189. 93.70:8080/ job/music- app-ci/ 995/ 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 1468 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 1468/artifact/ work/output/ *zip*/output. zip 91.189. 93.70:8080/ job/music- app-utopic- amd64-ci/ 219
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/music- app-ci/ 995/rebuild
http://