Commit c952167b authored by Matthieu Gallien's avatar Matthieu Gallien 🎵

add SortMenu to handle feature rich sorting in the views

able to sort by different roles and in ascending and descending orders
parent b87e04db
......@@ -392,6 +392,7 @@ if (Qt5Quick_FOUND AND Qt5Widgets_FOUND)
qml/HeaderBar.qml
qml/NavigationActionBar.qml
qml/SortMenu.qml
qml/MediaPlayerControl.qml
qml/ContextView.qml
qml/ContentView.qml
......
......@@ -66,6 +66,11 @@ RowLayout {
isSubPage: (browseStackView.depth >= 2),
haveTreeModel: configurationData.isTreeModel,
stackView: configurationData.browseStackView,
sortRole: Qt.DisplayRole,
sortRoles: [Qt.DisplayRole],
sortRoleNames: [''],
sortOrderNames: ['A-Z', 'Z-A'],
sortOrder: Qt.AscendingOrder,
opacity: 1,
}, StackView.Immediate)
}
......@@ -94,9 +99,14 @@ RowLayout {
stackView: browseStackView,
displaySingleAlbum: configurationData.displaySingleAlbum,
showSection: configurationData.showDiscHeaders,
opacity: 1,
radioCase: configurationData.radioCase,
haveTreeModel: configurationData.isTreeModel,
sortRole: Qt.DisplayRole,
sortRoles: [Qt.DisplayRole],
sortRoleNames: [''],
sortOrderNames: ['A-Z', 'Z-A'],
sortOrder: Qt.AscendingOrder,
opacity: 1,
}, StackView.Immediate)
}
......
......@@ -26,6 +26,11 @@ FocusScope {
property alias expandedFilterView: gridView.expandedFilterView
property alias haveTreeModel: gridView.haveTreeModel
property var filter
property alias sortRole: gridView.sortRole
property alias sortRoles: gridView.sortRoles
property alias sortRoleNames: gridView.sortRoleNames
property alias sortOrderNames: gridView.sortOrderNames
property alias sortOrder: gridView.sortOrder
property bool modelIsInitialized: false
focus: true
......@@ -56,6 +61,8 @@ FocusScope {
proxyModel.playList = ElisaApplication.mediaPlayListProxyModel
gridView.contentModel = proxyModel
proxyModel.sortModel(sortOrder)
realModel.initializeByData(ElisaApplication.musicManager, ElisaApplication.musicManager.viewDatabase,
modelType, filterType, filter)
......
......@@ -24,7 +24,11 @@ FocusScope {
property var modelType
property AbstractItemModel realModel
property AbstractProxyModel proxyModel
property int sortRole
property alias sortRole: listView.sortRole
property alias sortRoles: listView.sortRoles
property alias sortRoleNames: listView.sortRoleNames
property alias sortOrderNames: listView.sortOrderNames
property alias sortOrder: listView.sortOrder
property var sortAscending
property bool displaySingleAlbum: false
property alias radioCase: listView.showCreateRadioButton
......@@ -84,7 +88,7 @@ FocusScope {
listView.contentModel = proxyModel
if (!displaySingleAlbum) {
proxyModel.sortModel(sortAscending)
proxyModel.sortModel(sortOrder)
}
realModel.initializeByData(ElisaApplication.musicManager, ElisaApplication.musicManager.viewDatabase,
......
......@@ -25,6 +25,11 @@ FocusScope {
property bool delegateDisplaySecondaryText: true
property alias expandedFilterView: navigationBar.expandedFilterView
property bool haveTreeModel: false
property alias sortRole: navigationBar.sortRole
property alias sortRoles: navigationBar.sortRoles
property alias sortRoleNames: navigationBar.sortRoleNames
property alias sortOrderNames: navigationBar.sortOrderNames
property alias sortOrder: navigationBar.sortOrder
property var stackView
property url defaultIcon
property int depth: 1
......@@ -54,7 +59,6 @@ FocusScope {
secondaryTitle: gridView.secondaryTitle
image: gridView.image
enableGoBack: gridView.isSubPage || depth > 1
sortOrder: if (gridView.contentModel) {gridView.contentModel.sortedAscending} else true
Layout.fillWidth: true
......@@ -80,6 +84,17 @@ FocusScope {
}
}
Loader {
active: gridView.contentModel && navigationBar.enableSorting
sourceComponent: Binding {
target: gridView.contentModel
property: 'sortRole'
when: gridView.contentModel && navigationBar.enableSorting
value: navigationBar.sortRole
}
}
onEnqueue: contentModel.enqueueToPlayList(delegateModel.rootIndex)
onReplaceAndPlay:contentModel.replaceAndPlayOfPlayList(delegateModel.rootIndex)
......@@ -88,7 +103,16 @@ FocusScope {
gridView.goToBack()
}
onSort: contentModel.sortModel(order)
onSortOrderChanged: {
if (!contentModel || !navigationBar.enableSorting) {
return
}
if ((contentModel.sortedAscending && sortOrder !== Qt.AscendingOrder) ||
(!contentModel.sortedAscending && sortOrder !== Qt.DescendingOrder)) {
contentModel.sortModel(sortOrder)
}
}
}
DelegateModel {
......
......@@ -31,6 +31,11 @@ FocusScope {
property var delegateWidth: scrollBar.visible ? contentDirectoryView.width - scrollBar.width : contentDirectoryView.width
property alias currentIndex: contentDirectoryView.currentIndex
property alias enableSorting: navigationBar.enableSorting
property alias sortRole: navigationBar.sortRole
property alias sortRoles: navigationBar.sortRoles
property alias sortRoleNames: navigationBar.sortRoleNames
property alias sortOrderNames: navigationBar.sortOrderNames
property alias sortOrder: navigationBar.sortOrder
property var stackView
property alias showEnqueueButton: navigationBar.showEnqueueButton
property alias showCreateRadioButton: navigationBar.showCreateRadioButton
......@@ -72,7 +77,6 @@ FocusScope {
id: navigationBar
enableGoBack: listView.isSubPage || depth > 1
sortOrder: contentModel.sortedAscending
Layout.fillWidth: true
......@@ -98,6 +102,17 @@ FocusScope {
}
}
Loader {
active: listView.contentModel && navigationBar.enableSorting
sourceComponent: Binding {
target: listView.contentModel
property: 'sortRole'
when: listView.contentModel && navigationBar.enableSorting
value: navigationBar.sortRole
}
}
onEnqueue: contentModel.enqueueToPlayList(delegateModel.rootIndex)
onReplaceAndPlay: contentModel.replaceAndPlayOfPlayList(delegateModel.rootIndex)
......@@ -108,7 +123,16 @@ FocusScope {
onShowArtist: listView.showArtist(listView.contentModel.sourceModel.author)
onSort: contentModel.sortModel(order)
onSortOrderChanged: {
if (!contentModel || !navigationBar.enableSorting) {
return
}
if ((contentModel.sortedAscending && sortOrder !== Qt.AscendingOrder) ||
(!contentModel.sortedAscending && sortOrder !== Qt.DescendingOrder)) {
contentModel.sortModel(sortOrder)
}
}
}
Rectangle {
......
......@@ -29,15 +29,17 @@ ColumnLayout {
property bool enableGoBack: true
property bool expandedFilterView
property bool enableSorting: true
property bool sortOrder
property alias sortRole: sortMenu.sortRole
property var sortOrder
property alias sortRoles: sortMenu.sortRoles
property alias sortRoleNames: sortMenu.sortRoleNames
property alias sortOrderNames: sortMenu.sortOrderNames
signal enqueue();
signal replaceAndPlay();
signal createRadio();
signal goBack();
signal showArtist();
signal sort(var order);
HeaderFooterToolbar {
toolbarType: filterRow.visible ? HeaderFooterToolbar.ToolbarType.Other
......@@ -132,11 +134,20 @@ ColumnLayout {
onClicked: showArtist()
},
FlatButtonWithToolTip {
objectName: 'sortAscendingButton'
objectName: 'sortMenuButton'
visible: enableSorting && !showCreateRadioButton
text: i18nc("Toggle between ascending and descending order", "Toggle sort order")
icon.name: sortOrder ? "view-sort-ascending" : "view-sort-descending"
onClicked: sortOrder ? sort(Qt.DescendingOrder) : sort(Qt.AscendingOrder)
text: i18nc("Sort By Menu", "Sort By")
icon.name: "view-sort"
onClicked: {
sortMenu.sortOrder = navigationBar.sortOrder
sortMenu.open()
}
SortMenu {
id: sortMenu
onSortOrderChanged: navigationBar.sortOrder = sortOrder
}
},
FlatButtonWithToolTip {
objectName: 'showFilterButton'
......
/*
SPDX-FileCopyrightText: 2020 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>
SPDX-License-Identifier: LGPL-3.0-or-later
*/
import QtQuick 2.12
import QtQuick.Controls 2.5
Menu {
id: sortMenu
property int sortRole
property var sortRoles
property var sortRoleNames
property var sortOrder
property var sortOrderNames
title: i18nc("Sort By Menu", "Sort By")
function refreshSortOrderNames() {
if (!sortMenu.sortOrderNames) {
return
}
for (let i = 0; i < sortRoleNames.length; ++i) {
if (sortRoles[i] === sortMenu.sortRole && sortMenu.sortOrderNames.length >= (i * 2 + 1)) {
ascendingSortOrder.text = sortMenu.sortOrderNames[i * 2]
descendingSortOrder.text = sortMenu.sortOrderNames[i * 2 + 1]
}
}
}
ButtonGroup {
id: rolesButtonGroup
}
Repeater {
id: rolesRepeater
model: sortRoleNames.length > 1 ? sortRoleNames : []
delegate: MenuItem {
text: modelData
checkable: true
checked: sortRoles[index] === sortMenu.sortRole
onToggled: {
sortMenu.sortRole = sortRoles[index]
checked = (sortRoles[index] === sortMenu.sortRole)
}
ButtonGroup.group: rolesButtonGroup
}
}
MenuSeparator {
visible: sortRoleNames.length > 1
}
ButtonGroup {
id: orderButtonGroup
}
MenuItem {
id: ascendingSortOrder
checkable: true
checked: sortOrder === Qt.AscendingOrder
onToggled: sortOrder = Qt.AscendingOrder
ButtonGroup.group: orderButtonGroup
}
MenuItem {
id: descendingSortOrder
checkable: true
checked: sortOrder === Qt.DescendingOrder
onToggled: sortOrder = Qt.DescendingOrder
ButtonGroup.group: orderButtonGroup
}
onSortRoleChanged: refreshSortOrderNames()
onSortOrderNamesChanged: refreshSortOrderNames()
}
......@@ -43,6 +43,7 @@
<file>qml/ElisaConfigurationDialog.qml</file>
<file>qml/FileScanningConfiguration.qml</file>
<file>qml/GeneralConfiguration.qml</file>
<file>qml/SortMenu.qml</file>
</qresource>
<qresource prefix="/qml/+windows">
<file alias="Theme.qml">windows/WindowsTheme.qml</file>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment