diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -226,6 +226,7 @@ qml/ContextView.qml qml/ContentView.qml qml/ViewSelector.qml + qml/ViewManager.qml qml/MediaPlayListView.qml qml/MediaTrackDelegate.qml diff --git a/src/qml/ContentView.qml b/src/qml/ContentView.qml --- a/src/qml/ContentView.qml +++ b/src/qml/ContentView.qml @@ -30,16 +30,78 @@ signal toggleSearch() function goBack() { - localAlbums.goBack() - localArtists.goBack() + viewManager.goBack() + } + + ViewManager { + id: viewManager + + onSwitchAllAlbumsView: { + listViews.currentIndex = 1 + localArtistsLoader.opacity = 0 + localTracksLoader.opacity = 0 + localAlbumsLoader.opacity = 1 + } + + onSwitchOneAlbumView: { + elisa.singleAlbumProxyModel.loadAlbumData(databaseId) + currentStackView.push(albumView, { + mainTitle: mainTitle, + secondaryTitle: secondaryTitle, + image: imageUrl, + stackView: currentStackView, + }) + oneAlbumViewIsLoaded() + } + + onSwitchAllArtistsView: { + listViews.currentIndex = 2 + localArtistsLoader.opacity = 1 + localTracksLoader.opacity = 0 + localAlbumsLoader.opacity = 0 + } + + onSwitchOneArtistView: { + elisa.singleArtistProxyModel.setArtistFilterText(mainTitle) + currentStackView.push(innerAlbumView, { + mainTitle: mainTitle, + secondaryTitle: secondaryTitle, + image: imageUrl, + stackView: currentStackView, + }) + oneArtistViewIsLoaded() + } + + onSwitchAllTracksView: { + listViews.currentIndex = 3 + localArtistsLoader.opacity = 0 + localTracksLoader.opacity = 1 + localAlbumsLoader.opacity = 0 + } + + onSwitchOffAllViews: { + localArtistsLoader.opacity = 0 + localTracksLoader.opacity = 0 + localAlbumsLoader.opacity = 0 + } } ViewSelector { id: listViews Layout.fillHeight: true Layout.preferredWidth: mainWindow.width * 0.11 Layout.maximumWidth: mainWindow.width * 0.11 + + onSwitchView: if (index === 1) { + viewManager.openAllAlbums() + } else if (index === 2) { + viewManager.openAllArtists() + } else if (index === 3) { + viewManager.openAllTracks() + } else { + viewManager.closeAllViews() + } } Rectangle { @@ -150,6 +212,8 @@ anchors.fill: parent + onLoaded: viewManager.allAlbumsViewIsLoaded(item.stackView) + sourceComponent: MediaBrowser { id: localAlbums @@ -173,16 +237,10 @@ mainTitle: i18nc("Title of the view of all albums", "Albums") onOpen: { - elisa.singleAlbumProxyModel.loadAlbumData(databaseId) - localAlbums.stackView.push(albumView, { - mainTitle: innerMainTitle, - secondaryTitle: innerSecondaryTitle, - image: innerImage, - stackView: localAlbums.stackView, - }) + viewManager.openOneAlbum(localAlbums.stackView, innerMainTitle, innerSecondaryTitle, innerImage, databaseId) } - onGoBack: localAlbums.stackView.pop() + onGoBack: viewManager.goBack() Binding { target: allAlbumsView @@ -193,6 +251,13 @@ onFilterViewChanged: persistentSettings.expandedFilterView = expandedFilterView } } + + Behavior on opacity { + NumberAnimation { + easing.type: Easing.InOutQuad + duration: 300 + } + } } Loader { @@ -202,8 +267,12 @@ visible: opacity > 0 + opacity: 0 + anchors.fill: parent + onLoaded: viewManager.allArtistsViewIsLoaded(item.stackView) + sourceComponent: MediaBrowser { id: localArtists @@ -229,16 +298,10 @@ mainTitle: i18nc("Title of the view of all artists", "Artists") onOpen: { - elisa.singleArtistProxyModel.setArtistFilterText(innerMainTitle) - localArtists.stackView.push(innerAlbumView, { - mainTitle: innerMainTitle, - secondaryTitle: innerSecondaryTitle, - image: innerImage, - }) - + viewManager.openOneArtist(localArtists.stackView, innerMainTitle, innerImage, 0) } - onGoBack: localArtists.stackView.pop() + onGoBack: viewManager.goBack() Binding { target: allArtistsView @@ -249,6 +312,13 @@ onFilterViewChanged: persistentSettings.expandedFilterView = expandedFilterView } } + + Behavior on opacity { + NumberAnimation { + easing.type: Easing.InOutQuad + duration: 300 + } + } } Loader { @@ -258,8 +328,12 @@ visible: opacity > 0 + opacity: 0 + anchors.fill: parent + onLoaded: viewManager.allTracksViewIsLoaded(item) + sourceComponent: MediaBrowser { id: localTracks @@ -311,6 +385,13 @@ onFilterViewChanged: persistentSettings.expandedFilterView = expandedFilterView } } + + Behavior on opacity { + NumberAnimation { + easing.type: Easing.InOutQuad + duration: 300 + } + } } Behavior on border.color { @@ -401,7 +482,7 @@ states: [ State { - name: 'full' + name: 'playList' when: listViews.currentIndex === 0 PropertyChanges { target: mainContentView @@ -434,28 +515,10 @@ Layout.maximumWidth: contentZone.width / 2 Layout.preferredWidth: contentZone.width / 2 } - PropertyChanges { - target: localAlbumsLoader - opacity: 0 - } - PropertyChanges { - target: localArtistsLoader - opacity: 0 - } - PropertyChanges { - target: localTracksLoader - opacity: 0 - } }, State { - name: 'allAlbums' - when: listViews.currentIndex === 1 - StateChangeScript { - script: { - if (localAlbumsLoader.localAlbums) - localAlbumsLoader.localAlbums.stackView.pop({item: null, immediate: true}) - } - } + name: 'browsingViews' + when: listViews.currentIndex !== 0 PropertyChanges { target: mainContentView Layout.fillWidth: true @@ -487,118 +550,6 @@ Layout.maximumWidth: 0 Layout.preferredWidth: 0 } - PropertyChanges { - target: localAlbumsLoader - opacity: 1 - } - PropertyChanges { - target: localArtistsLoader - opacity: 0 - } - PropertyChanges { - target: localTracksLoader - opacity: 0 - } - }, - State { - name: 'allArtists' - when: listViews.currentIndex === 2 - StateChangeScript { - script: { - if (localArtistsLoader.localArtists) - localArtistsLoader.localArtists.stackView.pop({item: null, immediate: true}) - } - } - PropertyChanges { - target: mainContentView - Layout.fillWidth: true - Layout.minimumWidth: contentZone.width * 0.66 - Layout.maximumWidth: contentZone.width * 0.68 - Layout.preferredWidth: contentZone.width * 0.68 - } - PropertyChanges { - target: firstViewSeparatorItem - Layout.minimumWidth: 1 - Layout.maximumWidth: 1 - Layout.preferredWidth: 1 - } - PropertyChanges { - target: playList - Layout.minimumWidth: contentZone.width * 0.33 - Layout.maximumWidth: contentZone.width * 0.33 - Layout.preferredWidth: contentZone.width * 0.33 - } - PropertyChanges { - target: viewSeparatorItem - Layout.minimumWidth: 0 - Layout.maximumWidth: 0 - Layout.preferredWidth: 0 - } - PropertyChanges { - target: albumContext - Layout.minimumWidth: 0 - Layout.maximumWidth: 0 - Layout.preferredWidth: 0 - } - PropertyChanges { - target: localAlbumsLoader - opacity: 0 - } - PropertyChanges { - target: localArtistsLoader - opacity: 1 - } - PropertyChanges { - target: localTracksLoader - opacity: 0 - } - }, - State { - name: 'allTracks' - when: listViews.currentIndex === 3 - PropertyChanges { - target: mainContentView - Layout.fillWidth: true - Layout.minimumWidth: contentZone.width * 0.66 - Layout.maximumWidth: contentZone.width * 0.68 - Layout.preferredWidth: contentZone.width * 0.68 - } - PropertyChanges { - target: firstViewSeparatorItem - Layout.minimumWidth: 1 - Layout.maximumWidth: 1 - Layout.preferredWidth: 1 - } - PropertyChanges { - target: playList - Layout.minimumWidth: contentZone.width * 0.33 - Layout.maximumWidth: contentZone.width * 0.33 - Layout.preferredWidth: contentZone.width * 0.33 - } - PropertyChanges { - target: viewSeparatorItem - Layout.minimumWidth: 0 - Layout.maximumWidth: 0 - Layout.preferredWidth: 0 - } - PropertyChanges { - target: albumContext - Layout.minimumWidth: 0 - Layout.maximumWidth: 0 - Layout.preferredWidth: 0 - } - PropertyChanges { - target: localAlbumsLoader - opacity: 0 - } - PropertyChanges { - target: localArtistsLoader - opacity: 0 - } - PropertyChanges { - target: localTracksLoader - opacity: 1 - } } ] transitions: Transition { @@ -622,16 +573,10 @@ isSubPage: true onOpen: { - elisa.singleAlbumProxyModel.loadAlbumData(databaseId) - localArtists.stackView.push(albumView, { - mainTitle: innerMainTitle, - secondaryTitle: innerSecondaryTitle, - image: innerImage, - stackView: localArtists.stackView, - }) + viewManager.openOneAlbumFromArtist(stackView, innerMainTitle, innerSecondaryTitle, innerImage, databaseId) } - onGoBack: localArtists.stackView.pop() + onGoBack: viewManager.goBack() Binding { target: innerAlbumGridView @@ -648,7 +593,6 @@ ListBrowserView { id: albumGridView - property var stackView contentModel: elisa.singleAlbumProxyModel @@ -680,22 +624,10 @@ allowArtistNavigation: true onShowArtist: { - listViews.currentIndex = 2 - if (localArtists.stackView.depth === 3) { - localArtists.stackView.pop() - } - if (localArtists.stackView.depth === 2) { - var artistPage = localArtists.stackView.get(1) - if (artistPage.mainTitle === name) { - return - } else { - localArtists.stackView.pop() - } - } - allArtistsView.open(name, name, elisaTheme.defaultArtistImage, '') + viewManager.openOneArtist(stackView, name, elisaTheme.artistIcon, 0) } - onGoBack: stackView.pop() + onGoBack: viewManager.goBack() expandedFilterView: true diff --git a/src/qml/GridBrowserView.qml b/src/qml/GridBrowserView.qml --- a/src/qml/GridBrowserView.qml +++ b/src/qml/GridBrowserView.qml @@ -37,6 +37,7 @@ property alias showRating: navigationBar.showRating property bool delegateDisplaySecondaryText: true property alias expandedFilterView: navigationBar.expandedFilterView + property var stackView signal open(var innerMainTitle, var innerSecondaryTitle, var innerImage, var databaseId) signal goBack() diff --git a/src/qml/ListBrowserView.qml b/src/qml/ListBrowserView.qml --- a/src/qml/ListBrowserView.qml +++ b/src/qml/ListBrowserView.qml @@ -39,6 +39,7 @@ property alias showRating: navigationBar.showRating property alias allowArtistNavigation: navigationBar.allowArtistNavigation property var delegateWidth: scrollBar.visible ? contentDirectoryView.width - scrollBar.width : contentDirectoryView.width + property var stackView signal goBack() signal showArtist(var name) diff --git a/src/qml/ViewManager.qml b/src/qml/ViewManager.qml new file mode 100644 --- /dev/null +++ b/src/qml/ViewManager.qml @@ -0,0 +1,197 @@ +/* + * Copyright 2016-2017 Matthieu Gallien + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.7 + +QtObject { + + enum ViewsType { + NoViews, + AllAlbums, + OneAlbum, + AllArtists, + OneArtist, + OneAlbumFromArtist, + AllTracks + } + + property int currentView + property string currentAlbumTitle + property string currentAlbumAuthor + property string currentArtistName + property var currentStackView + + property int targetView + property string targetAlbumTitle + property string targetAlbumAuthor + property string targetArtistName + property url targetImageUrl + property int targetDatabaseId + + signal switchAllAlbumsView() + signal switchOneAlbumView(var currentStackView, string mainTitle, string imageUrl, string secondaryTitle, int databaseId) + signal switchAllArtistsView() + signal switchOneArtistView(var currentStackView, string mainTitle, string imageUrl, string secondaryTitle, int databaseId) + signal switchAllTracksView() + signal switchOffAllViews() + + function closeAllViews() + { + currentView = ViewManager.ViewsType.NoViews + targetView = ViewManager.ViewsType.NoViews + switchOffAllViews() + } + + function openAllAlbums() + { + targetView = ViewManager.ViewsType.AllAlbums + + if (currentView != targetView) { + switchAllAlbumsView() + } + } + + function openOneAlbum(stackView, albumTitle, albumAuthor, albumCover, albumDatabaseId) + { + targetAlbumTitle = albumTitle + targetAlbumAuthor = albumAuthor + targetDatabaseId = albumDatabaseId + targetImageUrl = albumCover + currentStackView = stackView + + targetView = ViewManager.ViewsType.OneAlbum + + if (currentView == ViewManager.ViewsType.AllAlbums) { + switchOneAlbumView(currentStackView, targetAlbumTitle, targetImageUrl, targetAlbumAuthor, targetDatabaseId) + } else { + switchAllAlbumsView() + } + } + + function openAllArtists() + { + targetView = ViewManager.ViewsType.AllArtists + + if (currentView != targetView) { + switchAllArtistsView() + } + } + + function openOneArtist(stackView, artistName, artistImageUrl, artistDatabaseId) + { + targetArtistName = artistName + targetDatabaseId = artistDatabaseId + targetImageUrl = artistImageUrl + currentStackView = stackView + + targetView = ViewManager.ViewsType.OneArtist + + if (currentView == ViewManager.ViewsType.AllArtists) { + switchOneArtistView(currentStackView, targetArtistName, targetImageUrl, '', targetDatabaseId) + } else if (currentView == ViewManager.ViewsType.OneArtist && currentArtistName != targetArtistName) { + currentStackView.pop() + switchOneArtistView(currentStackView, targetArtistName, targetImageUrl, '', targetDatabaseId) + } else if (currentView == ViewManager.ViewsType.OneAlbumFromArtist && currentArtistName != targetArtistName) { + currentStackView.pop() + currentStackView.pop() + switchOneArtistView(currentStackView, targetArtistName, targetImageUrl, '', targetDatabaseId) + } else { + switchAllArtistsView() + } + } + + function openOneAlbumFromArtist(stackView, albumTitle, albumAuthor, albumCover, albumDatabaseId) + { + targetAlbumTitle = albumTitle + targetAlbumAuthor = albumAuthor + targetDatabaseId = albumDatabaseId + targetImageUrl = albumCover + currentStackView = stackView + + targetView = ViewManager.ViewsType.OneAlbumFromArtist + + if (currentView == ViewManager.ViewsType.OneArtist) { + switchOneAlbumView(currentStackView, targetAlbumTitle, targetImageUrl, targetAlbumAuthor, targetDatabaseId) + } else { + switchAllAlbumsView() + } + } + + function openAllTracks() + { + targetView = ViewManager.ViewsType.AllTracks + if (currentView != targetView) { + switchAllTracksView() + } + } + + function allAlbumsViewIsLoaded(stackView) + { + currentStackView = stackView + currentView = ViewManager.ViewsType.AllAlbums + if (targetView == ViewManager.ViewsType.OneAlbum) { + switchOneAlbumView(currentStackView, targetAlbumTitle, targetImageUrl, targetArtistName, targetDatabaseId) + } + } + + function oneAlbumViewIsLoaded() + { + currentAlbumTitle = targetAlbumTitle + currentAlbumAuthor = targetAlbumAuthor + + if (targetView == ViewManager.ViewsType.OneAlbum) { + currentView = ViewManager.ViewsType.OneAlbum + } else { + currentView = ViewManager.ViewsType.OneAlbumFromArtist + } + } + + function allArtistsViewIsLoaded(stackView) + { + currentStackView = stackView + currentView = ViewManager.ViewsType.AllArtists + if (targetView == ViewManager.ViewsType.OneArtist) { + switchOneArtistView(currentStackView, targetArtistName, targetImageUrl, '', targetDatabaseId) + } + } + + function oneArtistViewIsLoaded() + { + currentArtistName = targetArtistName + currentView = ViewManager.ViewsType.OneArtist + } + + function allTracksViewIsLoaded(allTracksView) + { + currentView = ViewManager.ViewsType.AllTracks + } + + function goBack() + { + currentStackView.pop() + + if (currentView == ViewManager.ViewsType.OneAlbum) { + currentView = ViewManager.ViewsType.AllAlbums + } else if (currentView == ViewManager.ViewsType.OneArtist) { + currentView = ViewManager.ViewsType.AllArtists + } else if (currentView == ViewManager.ViewsType.OneAlbumFromArtist) { + currentView = ViewManager.ViewsType.OneArtist + } + } +} diff --git a/src/qml/ViewSelector.qml b/src/qml/ViewSelector.qml --- a/src/qml/ViewSelector.qml +++ b/src/qml/ViewSelector.qml @@ -24,8 +24,11 @@ FocusScope { id: rootFocusScope + property alias currentIndex: viewModeView.currentIndex + signal switchView(int index) + Rectangle { anchors.fill: parent @@ -145,6 +148,7 @@ { viewModeView.currentIndex = index rootFocusScope.focus = true + switchView(index) } } diff --git a/src/resources.qrc b/src/resources.qrc --- a/src/resources.qrc +++ b/src/resources.qrc @@ -28,6 +28,7 @@ qml/ListBrowserView.qml qtquickcontrols2.conf background.png + qml/ViewManager.qml windows/WindowsTheme.qml