1/* 2 * Copyright (C) 2016, 2017 3 * Jean-Luc Barriere <jlbarriere68@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; version 3. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18import QtQuick 2.9 19import QtQuick.Controls 2.2 20import QtQuick.Layouts 1.3 21import NosonApp 1.0 22import "components" 23import "components/Delegates" 24import "components/Flickables" 25import "components/Dialog" 26 27MusicPage { 28 id: playlistsPage 29 objectName: "playlistsPage" 30 pageTitle: qsTr("Playlists") 31 pageFlickable: playlistsGrid 32 searchable: true 33 addVisible: true 34 35 property bool changed: false 36 property bool childrenChanged: false 37 38 onSearchClicked: filter.visible = true 39 40 header: MusicFilter { 41 id: filter 42 visible: false 43 } 44 45 SortFilterModel { 46 id: playlistsModelFilter 47 model: AllPlaylistsModel 48 sort.property: "title" 49 sort.order: Qt.AscendingOrder 50 sortCaseSensitivity: Qt.CaseInsensitive 51 filter.property: "normalized" 52 filter.pattern: new RegExp(normalizedInput(filter.displayText), "i") 53 filterCaseSensitivity: Qt.CaseInsensitive 54 } 55 56 MusicGridView { 57 id: playlistsGrid 58 itemWidth: units.gu(15) 59 heightOffset: units.gu(7) 60 61 model: playlistsModelFilter 62 63 delegate: Card { 64 id: playlistCard 65 height: playlistsGrid.cellHeight 66 width: playlistsGrid.cellWidth 67 primaryText: model.title 68 secondaryTextVisible: false 69 70 isFavorite: (AllFavoritesModel.findFavorite(model.payload).length > 0) 71 72 // check favorite on data loaded 73 Connections { 74 target: AllFavoritesModel 75 function onLoaded(succeeded) { 76 isFavorite = (AllFavoritesModel.findFavorite(model.payload).length > 0) 77 } 78 } 79 80 coverSources: allCovers() 81 82 function allCovers() { 83 var cs = []; 84 var arts = model.arts; 85 for (var i = 0; i < arts.length; ++i) cs.push({art: arts[i]}); 86 return cs; 87 } 88 89 coverFlow: 4 90 91 onClicked: { 92 stackView.push("qrc:/controls2/SongsView.qml", 93 { 94 "containerItem": makeContainerItem(model), 95 "songSearch": model.id, 96 "album": undefined, 97 "coverFlow": 4, 98 "covers": coverSources, 99 "isPlaylist": true, 100 "genre": undefined, 101 "page": playlistsPage, 102 "pageTitle": qsTr("Playlist"), 103 "line1": "", 104 "line2": model.title, 105 }) 106 } 107 onPressAndHold: { 108 if (isFavorite && removeFromFavorites(model.payload)) 109 isFavorite = false 110 else if (!isFavorite && addItemToFavorites(model, qsTr("Playlist"), imageSource)) 111 isFavorite = true 112 } 113 } 114 } 115 116 // Overlay to show when no playlists are on the device 117 Loader { 118 anchors.fill: parent 119 active: AllPlaylistsModel.count === 0 && !infoLoadedIndex 120 asynchronous: true 121 source: "qrc:/controls2/components/PlaylistsEmptyState.qml" 122 visible: active 123 } 124 125 DialogNewPlaylist { 126 id: dialogNewPlaylist 127 } 128 129 onAddClicked: dialogNewPlaylist.open() 130 131 // Overlay to show when load failed 132 Loader { 133 anchors.fill: parent 134 active: AllPlaylistsModel.failure 135 asynchronous: true 136 sourceComponent: Component { 137 DataFailureState { 138 onReloadClicked: AllPlaylistsModel.asyncLoad(); 139 } 140 } 141 visible: active 142 } 143} 144