diff options
author | Yoann Lopes <yoann.lopes@nokia.com> | 2012-05-18 02:15:44 +0200 |
---|---|---|
committer | Yoann Lopes <yoann.lopes@nokia.com> | 2012-05-18 02:15:44 +0200 |
commit | f932a86631105b6dff7c48708f0f62ca4417a43d (patch) | |
tree | 4c8ec4b028a809a56f52b1f32b8f6f0e751e4da7 /qml | |
parent | ad5e96ea6b7e8b75972babe870338ceda00349fc (diff) |
Added folder support.
Diffstat (limited to 'qml')
-rw-r--r-- | qml/FolderPage.qml | 211 | ||||
-rw-r--r-- | qml/MainPage.qml | 16 | ||||
-rw-r--r-- | qml/PlaylistMenu.qml | 64 | ||||
-rw-r--r-- | qml/PlaylistPage.qml | 41 | ||||
-rw-r--r-- | qml/SettingsPage.qml | 8 |
5 files changed, 304 insertions, 36 deletions
diff --git a/qml/FolderPage.qml b/qml/FolderPage.qml new file mode 100644 index 0000000..95faaf1 --- /dev/null +++ b/qml/FolderPage.qml @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Yoann Lopes (yoann.lopes@nokia.com) +** +** This file is part of the MeeSpot project. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the names of its +** contributors may be used to endorse or promote products derived from +** this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +import QtQuick 1.1 +import com.nokia.meego 1.0 +import QtSpotify 1.0 +import "UIConstants.js" as UI + +Page { + id: folderPage + orientationLock: PageOrientation.LockPortrait + anchors.rightMargin: UI.MARGIN_XLARGE + anchors.leftMargin: UI.MARGIN_XLARGE + + property variant folder + property bool folderDeleted: false + + function folderNotDeleted(page) { + if (page.folderDeleted == undefined) { + return true; + } + return !page.folderDeleted; + } + + Connections { + target: folder + onPlaylistDestroyed: { + folderPage.folderDeleted = true + var foundPage = playlistsTab.find(folderNotDeleted); + if (foundPage !== playlistsTab.currentPage) + playlistsTab.pop(foundPage, true); + } + } + + PlaylistMenu { + id: menu + } + +// PlaylistNameSheet { +// id: newPlaylistSheet +// title: "Playlist name" +// onAccepted: { spotifySession.user.createPlaylistInFolder(newPlaylistSheet.playlistName, folderPage.folder); } +// } + + ListView { + id: playlists + anchors.fill: parent + + cacheBuffer: 3000 + model: folder.playlists + + Component.onCompleted: positionViewAtBeginning() + + delegate: PlaylistDelegate { + title: (modelData.type === SpotifyPlaylist.Playlist || modelData.type === SpotifyPlaylist.Folder ? modelData.name + : (modelData.type === SpotifyPlaylist.Starred ? "Starred" + : "Inbox")) + subtitle: if (modelData.type == SpotifyPlaylist.Folder) { + modelData.playlistCount + " playlist" + (modelData.playlistCount > 1 ? "s" : "") + } else { + modelData.trackCount + " song" + (modelData.trackCount > 1 ? "s" : "") + + ((spotifySession.user ? spotifySession.user.ownsPlaylist(modelData) : false) ? "" : " | by " + modelData.owner) + } + extraText: modelData.type === SpotifyPlaylist.Folder ? "" : spotifySession.formatDuration(modelData.totalDuration) + icon: modelData.collaborative ? "images/icon-m-collaborative-playlist.png" : staticIcon + offlineStatus: modelData.offlineStatus + availableOffline: modelData.availableOffline + downloadProgress: modelData.offlineDownloadProgress + unseens: modelData.unseenCount + enabled: opacity == 1.0 + opacity: !spotifySession.offlineMode || modelData.availableOffline || modelData.type === SpotifyPlaylist.Folder ? 1.0 : 0.3 + + onClicked: { + if (modelData.trackCount > 0) { + var component = Qt.createComponent("TracklistPage.qml"); + if (component.status === Component.Ready) { + var playlistPage = component.createObject(playlistsTab, { playlist: modelData }); + playlistsTab.push(playlistPage); + } + } else if (modelData.type === SpotifyPlaylist.Folder) { + var component2 = Qt.createComponent("FolderPage.qml"); + if (component2.status === Component.Ready) { + var folderPage = component2.createObject(playlistsTab, { folder: modelData }); + playlistsTab.push(folderPage); + } + } + } + onPressAndHold: { menu.playlist = modelData; menu.open(); } + + property string staticIcon + Component.onCompleted: { + if (modelData.type === SpotifyPlaylist.Playlist) + staticIcon = "image://theme/icon-m-music-video-all-songs"; + else if (modelData.type === SpotifyPlaylist.Starred) + staticIcon = "image://theme/icon-m-common-favorite-mark-inverse"; + else if (modelData.type === SpotifyPlaylist.Inbox) + staticIcon = "image://theme/icon-m-toolbar-directory-move-to-white-selected"; + else if (modelData.type === SpotifyPlaylist.Folder) + staticIcon = "image://theme/icon-m-toolbar-directory-selected" + } + } + + header: ViewHeader { + text: folder.name + } + +// footer: Item { +// height: visible ? (UI.LIST_ITEM_HEIGHT + separator.height) : 0 +// width: parent.width +// visible: !spotifySession.offlineMode + +// Separator { +// id: separator +// anchors.left: parent.left +// anchors.right: parent.right +// anchors.top: parent.top +// } + +// Rectangle { +// id: background +// anchors.fill: row +// // Fill page porders +// anchors.leftMargin: -UI.MARGIN_XLARGE +// anchors.rightMargin: -UI.MARGIN_XLARGE +// opacity: mouseArea.pressed ? 1.0 : 0.0 +// color: "#22FFFFFF" +// } + +// Row { +// id: row +// width: parent.width +// anchors.top: separator.bottom +// anchors.bottom: parent.bottom +// spacing: UI.LIST_ITEM_SPACING + +// Item { +// id: iconItem +// anchors.verticalCenter: parent.verticalCenter +// visible: iconImage.source !== "" ? true : false +// width: 40 +// height: 40 + +// Image { +// id: iconImage +// anchors.centerIn: parent +// source: theme.inverted ? "image://theme/icon-m-input-add" : "image://theme/icon-m-common-add" +// opacity: 0.4 +// } +// } + +// Label { +// anchors.verticalCenter: parent.verticalCenter +// font.family: UI.FONT_FAMILY_BOLD +// font.weight: Font.Bold +// font.pixelSize: UI.LIST_TILE_SIZE +// color: theme.inverted ? UI.LIST_TITLE_COLOR_INVERTED : UI.LIST_TITLE_COLOR +// opacity: 0.4 +// text: "New playlist" +// } +// } + +// MouseArea { +// id: mouseArea; +// anchors.fill: parent +// onClicked: { +// newPlaylistSheet.playlistName = ""; +// newPlaylistSheet.open(); +// } +// } +// } + } + + Scrollbar { listView: playlists } +} diff --git a/qml/MainPage.qml b/qml/MainPage.qml index 828ba38..1fb0fb0 100644 --- a/qml/MainPage.qml +++ b/qml/MainPage.qml @@ -79,7 +79,7 @@ Page { } } - property variant playlists: spotifySession.user ? spotifySession.user.playlists : null + property variant playlists: spotifySession.user ? spotifySession.user.playlistsFlat : null Connections { target: spotifySession.user onPlaylistsNameChanged: updatePlaylistDialog() @@ -93,18 +93,18 @@ Page { if (playlists === null) return; + playlistSelectionDialog.model.append({"name": "New playlist" }); + for (var i in mainPage.playlists) { - if (mainPage.playlists[i].type == SpotifyPlaylist.Playlist && spotifySession.user.canModifyPlaylist(mainPage.playlists[i])) + if (mainPage.playlists[i].type === SpotifyPlaylist.Playlist && spotifySession.user.canModifyPlaylist(mainPage.playlists[i])) playlistSelectionDialog.model.append({"name": mainPage.playlists[i].name, "object": mainPage.playlists[i] }) } - - playlistSelectionDialog.model.append({"name": "New playlist" }); } Connections { target: spotifySession onConnectionErrorChanged: { - if (spotifySession.connectionError != SpotifySession.Ok) { + if (spotifySession.connectionError !== SpotifySession.Ok) { errorBanner.text = spotifySession.connectionErrorMessage; errorBanner.show(); } @@ -132,7 +132,7 @@ Page { TabGroup { id: tabGroup enabled: !currentTab.busy - y: player.hidden ? 0 : screen.currentOrientation == Screen.Portrait ? UI.HEADER_DEFAULT_HEIGHT_PORTRAIT + y: player.hidden ? 0 : screen.currentOrientation === Screen.Portrait ? UI.HEADER_DEFAULT_HEIGHT_PORTRAIT : UI.HEADER_DEFAULT_HEIGHT_LANDSCAPE height: parent.height - y Behavior on y { NumberAnimation { easing.type: Easing.OutQuart; duration: 500 } } @@ -200,7 +200,7 @@ Page { onPressedChanged: { if (pressed) - isCurrentTab = (tabGroup.currentTab == searchTab); + isCurrentTab = (tabGroup.currentTab === searchTab); } onClicked: { @@ -218,7 +218,7 @@ Page { onPressedChanged: { if (pressed) - isCurrentTab = (tabGroup.currentTab == toplistTab); + isCurrentTab = (tabGroup.currentTab === toplistTab); } onClicked: { diff --git a/qml/PlaylistMenu.qml b/qml/PlaylistMenu.qml index bbe1380..6fd697d 100644 --- a/qml/PlaylistMenu.qml +++ b/qml/PlaylistMenu.qml @@ -5,22 +5,22 @@ ** Contact: Yoann Lopes (yoann.lopes@nokia.com) ** ** This file is part of the MeeSpot project. -** +** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: -** +** ** Redistributions of source code must retain the above copyright notice, ** this list of conditions and the following disclaimer. -** +** ** Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. -** +** ** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the names of its ** contributors may be used to endorse or promote products derived from ** this software without specific prior written permission. -** +** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -65,12 +65,19 @@ MyMenu { QueryDialog { id: confirmDeleteDialog + property bool deleteFolderContent: false parent: playlistMenu.parent - titleText: userOwnsPlaylist ? "Delete playlist?" : "Unsubscribe from playlist?" message: playlist ? playlist.name : "" acceptButtonText: "Yes" rejectButtonText: "No" - onAccepted: { playlist.removeFromContainer() } + onAccepted: { + if (deleteFolderContent) + playlist.deleteFolderContent(); + else + playlist.removeFromContainer() + deleteFolderContent = false; + } + onRejected: deleteFolderContent = false; } MyMenuLayout { @@ -84,7 +91,7 @@ MyMenu { MyMenuItem { text: "Add to queue"; onClicked: { playlist.enqueue() } - visible: (playlist && playlist.trackCount > 0) ? true : false + visible: (playlist && (playlist.trackCount > 0 || playlist.type === SpotifyPlaylist.Folder)) ? true : false } MyMenuItem { text: "Rename" @@ -100,12 +107,43 @@ MyMenu { } MyMenuItem { id: offlineItem + visible: (playlist && playlist.type !== SpotifyPlaylist.Folder) ? true : false onClicked: { playlist.availableOffline = !playlist.availableOffline } } MyMenuItem { + id: setFolderOfflineItem + visible: ((playlist && playlist.type === SpotifyPlaylist.Folder) ? true : false) && !spotifySession.offlineMode + text: "Set offline mode for content" + onClicked: { playlist.availableOffline = true } + } + MyMenuItem { + id: unsetFolderOfflineItem + visible: (playlist && playlist.type === SpotifyPlaylist.Folder) ? true : false + text: "Unset offline mode for content" + onClicked: { playlist.availableOffline = false } + } + MyMenuItem { id: deleteItem - onClicked: { confirmDeleteDialog.open(); } - visible: ((playlist && playlist.type == SpotifyPlaylist.Playlist) ? true : false) + onClicked: { + if (playlist.type === SpotifyPlaylist.Folder) { + confirmDeleteDialog.titleText = "Delete folder?"; + } else { + confirmDeleteDialog.titleText = userOwnsPlaylist ? "Delete playlist?" : "Unsubscribe from playlist?"; + } + confirmDeleteDialog.open(); + } + visible: ((playlist && (playlist.type == SpotifyPlaylist.Playlist || playlist.type == SpotifyPlaylist.Folder)) ? true : false) + && !spotifySession.offlineMode + } + MyMenuItem { + id: deleteFolderContentItem + text: "Delete folder and content" + onClicked: { + confirmDeleteDialog.deleteFolderContent = true; + confirmDeleteDialog.titleText = "Delete folder and its content?"; + confirmDeleteDialog.open(); + } + visible: ((playlist && playlist.type == SpotifyPlaylist.Folder) ? true : false) && !spotifySession.offlineMode } } @@ -113,8 +151,12 @@ MyMenu { onStatusChanged: { if (status == DialogStatus.Opening && playlist) { collabItem.text = (playlist.collaborative ? "Unset" : "Set") + " collaborative"; - deleteItem.text = userOwnsPlaylist ? "Delete" : "Unsubscribe"; offlineItem.text = (playlist.availableOffline ? "Unset" : "Set") + " offline mode" + if (playlist.type === SpotifyPlaylist.Folder) { + deleteItem.text = "Delete"; + } else { + deleteItem.text = userOwnsPlaylist ? "Delete" : "Unsubscribe"; + } } } } diff --git a/qml/PlaylistPage.qml b/qml/PlaylistPage.qml index 90a85a6..23a11bd 100644 --- a/qml/PlaylistPage.qml +++ b/qml/PlaylistPage.qml @@ -83,40 +83,55 @@ Page { Component.onCompleted: positionViewAtBeginning() delegate: PlaylistDelegate { - title: (modelData.type == SpotifyPlaylist.Playlist ? modelData.name - : (modelData.type == SpotifyPlaylist.Starred ? "Starred" - : "Inbox")) - subtitle: modelData.trackCount + " song" + (modelData.trackCount > 1 ? "s" : "") - + ((spotifySession.user ? spotifySession.user.ownsPlaylist(modelData) : false) ? "" : " | by " + modelData.owner) - extraText: spotifySession.formatDuration(modelData.totalDuration) - visible: modelData.isLoaded + title: !modelData.isLoaded ? "Loading..." : (modelData.type === SpotifyPlaylist.Playlist || modelData.type === SpotifyPlaylist.Folder ? modelData.name + : (modelData.type === SpotifyPlaylist.Starred ? "Starred" + : "Inbox")) + subtitle: if (!modelData.isLoaded) { + ""; + } else { + if (modelData.type === SpotifyPlaylist.Folder) { + modelData.playlistCount + " playlist" + (modelData.playlistCount > 1 ? "s" : "") + } else { + modelData.trackCount + " song" + (modelData.trackCount > 1 ? "s" : "") + + ((spotifySession.user ? spotifySession.user.ownsPlaylist(modelData) : false) ? "" : " | by " + modelData.owner) + } + } + extraText: modelData.type === SpotifyPlaylist.Folder || !modelData.isLoaded ? "" : spotifySession.formatDuration(modelData.totalDuration) icon: modelData.collaborative ? "images/icon-m-collaborative-playlist.png" : staticIcon offlineStatus: modelData.offlineStatus availableOffline: modelData.availableOffline downloadProgress: modelData.offlineDownloadProgress unseens: modelData.unseenCount enabled: opacity == 1.0 - opacity: !spotifySession.offlineMode || modelData.availableOffline ? 1.0 : 0.3 + opacity: (!spotifySession.offlineMode || modelData.availableOffline || modelData.type === SpotifyPlaylist.Folder) && modelData.isLoaded ? 1.0 : 0.3 onClicked: { if (modelData.trackCount > 0) { var component = Qt.createComponent("TracklistPage.qml"); - if (component.status == Component.Ready) { + if (component.status === Component.Ready) { var playlistPage = component.createObject(pageStack, { playlist: modelData }); pageStack.push(playlistPage); } + } else if (modelData.type === SpotifyPlaylist.Folder) { + var component2 = Qt.createComponent("FolderPage.qml"); + if (component2.status === Component.Ready) { + var folderPage = component2.createObject(pageStack, { folder: modelData }); + pageStack.push(folderPage); + } } } onPressAndHold: { menu.playlist = modelData; menu.open(); } property string staticIcon Component.onCompleted: { - if (modelData.type == SpotifyPlaylist.Playlist) + if (modelData.type === SpotifyPlaylist.Playlist) staticIcon = "image://theme/icon-m-music-video-all-songs"; - else if (modelData.type == SpotifyPlaylist.Starred) + else if (modelData.type === SpotifyPlaylist.Starred) staticIcon = "image://theme/icon-m-common-favorite-mark-inverse"; - else if (modelData.type == SpotifyPlaylist.Inbox) + else if (modelData.type === SpotifyPlaylist.Inbox) staticIcon = "image://theme/icon-m-toolbar-directory-move-to-white-selected"; + else if (modelData.type === SpotifyPlaylist.Folder) + staticIcon = "image://theme/icon-m-toolbar-directory-selected" } } @@ -194,7 +209,7 @@ Page { section.delegate: Separator { anchors.left: parent.left anchors.right: parent.right - visible: section == "p" + visible: section === "p" } } diff --git a/qml/SettingsPage.qml b/qml/SettingsPage.qml index ad21fb9..dcd0e2d 100644 --- a/qml/SettingsPage.qml +++ b/qml/SettingsPage.qml @@ -127,8 +127,8 @@ Page { ListElement { name: "Normal quality (160kbps)"; value: SpotifySession.HighQuality } ListElement { name: "High quality (320kbps)"; value: SpotifySession.UltraQuality } } - selectedIndex: spotifySession.streamingQuality == SpotifySession.LowQuality ? 0 - : spotifySession.streamingQuality == SpotifySession.HighQuality ? 1 : 2 + selectedIndex: spotifySession.streamingQuality === SpotifySession.LowQuality ? 0 + : spotifySession.streamingQuality === SpotifySession.HighQuality ? 1 : 2 onSelectedIndexChanged: spotifySession.streamingQuality = model.get(selectedIndex).value } @@ -139,8 +139,8 @@ Page { ListElement { name: "Normal quality (160kbps)"; value: SpotifySession.HighQuality } ListElement { name: "High quality (320kbps)"; value: SpotifySession.UltraQuality } } - selectedIndex: spotifySession.syncQuality == SpotifySession.LowQuality ? 0 - : spotifySession.syncQuality == SpotifySession.HighQuality ? 1 : 2 + selectedIndex: spotifySession.syncQuality === SpotifySession.LowQuality ? 0 + : spotifySession.syncQuality === SpotifySession.HighQuality ? 1 : 2 onSelectedIndexChanged: spotifySession.syncQuality = model.get(selectedIndex).value } |