[vlc-devel] [PATCH 12/55] qml: refactor SortControl

Fatih Uzunoglu fuzun54 at outlook.com
Thu Jan 7 21:36:25 UTC 2021


+ uncouple SortControl and Playlist SortKey / SortOrder enums.
---
 .../qt/maininterface/qml/BannerSources.qml    |   8 +-
 .../gui/qt/playlist/qml/PlaylistToolbar.qml   |  22 ++-
 modules/gui/qt/widgets/qml/SortControl.qml    | 162 +++++++++---------
 3 files changed, 102 insertions(+), 90 deletions(-)

diff --git a/modules/gui/qt/maininterface/qml/BannerSources.qml b/modules/gui/qt/maininterface/qml/BannerSources.qml
index ec77ab7a15..3279dcdac3 100644
--- a/modules/gui/qt/maininterface/qml/BannerSources.qml
+++ b/modules/gui/qt/maininterface/qml/BannerSources.qml
@@ -224,9 +224,9 @@ Widgets.NavigableFocusScope {
 
                             textRole: "text"
                             criteriaRole: "criteria"
-                            listWidth: VLCStyle.widthSortBox
+
                             height: localToolbar.height
-                            size: VLCStyle.banner_icon_size
+                            iconSize: VLCStyle.banner_icon_size
 
                             popupAlignment: Qt.AlignLeft | Qt.AlignBottom
 
@@ -235,13 +235,13 @@ Widgets.NavigableFocusScope {
 
                             onSortSelected: {
                                 if (contentModel !== undefined) {
-                                    contentModel.sortCriteria = modelData[criteriaRole]
+                                    contentModel.sortCriteria = type
                                 }
                             }
 
                             onSortOrderSelected: {
                                 if (contentModel !== undefined) {
-                                    contentModel.sortOrder = order
+                                    contentModel.sortOrder = type
                                 }
                             }
 
diff --git a/modules/gui/qt/playlist/qml/PlaylistToolbar.qml b/modules/gui/qt/playlist/qml/PlaylistToolbar.qml
index f1a1f44a2f..9d7ca00c20 100644
--- a/modules/gui/qt/playlist/qml/PlaylistToolbar.qml
+++ b/modules/gui/qt/playlist/qml/PlaylistToolbar.qml
@@ -90,14 +90,30 @@ Widgets.NavigableFocusScope {
                 textRole: "title"
                 criteriaRole: "key"
 
-                listWidth: VLCStyle.widthSortBox
                 onSortSelected: {
-                    mainPlaylistController.sort(modelData.key)
+                    mainPlaylistController.sortKey = type
+                }
+
+                onSortOrderSelected: {
+                    if (type === Qt.AscendingOrder)
+                        mainPlaylistController.sortOrder = PlaylistControllerModel.SORT_ORDER_ASC
+                    else if (type === Qt.DescendingOrder)
+                        mainPlaylistController.sortOrder = PlaylistControllerModel.SORT_ORDER_DESC
+
+                    mainPlaylistController.sort()
                 }
 
                 colors: playlistToolbar.colors
 
-                sortOrder: mainPlaylistController.sortOrder
+                sortOrder: {
+                    if (mainPlaylistController.sortOrder === PlaylistControllerModel.SORT_ORDER_ASC) {
+                        Qt.AscendingOrder
+                    }
+                    else if (mainPlaylistController.sortOrder === PlaylistControllerModel.SORT_ORDER_DESC) {
+                        Qt.DescendingOrder
+                    }
+                }
+
                 sortKey: mainPlaylistController.sortKey
             }
 
diff --git a/modules/gui/qt/widgets/qml/SortControl.qml b/modules/gui/qt/widgets/qml/SortControl.qml
index 55c1a1d0b5..03cb1d22d3 100644
--- a/modules/gui/qt/widgets/qml/SortControl.qml
+++ b/modules/gui/qt/widgets/qml/SortControl.qml
@@ -35,36 +35,38 @@ Widgets.NavigableFocusScope {
     implicitWidth: button.implicitWidth
     implicitHeight: button.implicitHeight
 
-    property alias model: list.model
+    property alias model: listView.model
     property string textRole
     property string criteriaRole
+    // provided for convenience:
+    property alias titleRole: root.textRole
+    property alias keyRole: root.criteriaRole
 
     property int popupAlignment: Qt.AlignRight | Qt.AlignBottom
-    property int listWidth
-    property alias currentIndex: list.currentIndex
+    property real listWidth: VLCStyle.widthSortBox
     property alias focusPolicy: button.focusPolicy
+    property alias iconSize: button.size
 
     property VLCColors colors: VLCStyle.colors
 
     // properties that should be handled by parent
-    // if they are not updated, SortControl will behave as before
-    property var sortKey : PlaylistControllerModel.SORT_KEY_NONE
-    property var sortOrder : undefined
+    // if they are not updated, tick mark and order mark will not be shown
+    property var sortKey: undefined
+    property var sortOrder: undefined
 
-    property bool _intSortOrder : false
+    // sortSelected is triggered with new sorting key when a different sorting key is selected
+    // sortOrderSelected is triggered with Qt.AscendingOrder when different sorting key is selected
+    // sortOrderSelected is triggered with Qt.AscendingOrder or Qt.DescendingOrder when the same sorting key is selected
+    signal sortSelected(var type)
+    signal sortOrderSelected(var type)
 
-    property alias size: button.size
-
-    signal sortSelected(var modelData)
-    signal sortOrderSelected(var order)
-
-    onFocusChanged: {
-        if (!focus)
+    onVisibleChanged: {
+        if (!visible)
             popup.close()
     }
 
-    onVisibleChanged: {
-        if (!visible)
+    onEnabledChanged: {
+        if (!enabled)
             popup.close()
     }
 
@@ -82,36 +84,33 @@ Widgets.NavigableFocusScope {
 
         focus: true
 
-        color: colors.buttonText
-        colorDisabled: colors.textInactive
-
         onClicked: {
-            if (popup.opened)
+            if (popup.visible)
                 popup.close()
             else
                 popup.open()
         }
-
     }
 
     Popup {
         id: popup
 
-        y: (popupAlignment & Qt.AlignBottom) ? (root.height + 1) : - (implicitHeight + 1)
-        x: (popupAlignment & Qt.AlignRight) ? (button.width - width) :  0
-        width: root.listWidth
-        implicitHeight: contentItem.implicitHeight + padding * 2
-        padding: 1
+        y: (popupAlignment & Qt.AlignBottom) ? (root.height) : -(height)
+        x: (popupAlignment & Qt.AlignRight) ? (button.width - width) : 0
+
+        width: listWidth
+
+        padding: bgRect.border.width
+
+        clip: true
 
         onOpened: {
-            button.KeyNavigation.down = list
             button.highlighted = true
 
-            list.forceActiveFocus()
+            listView.forceActiveFocus()
         }
 
         onClosed: {
-            button.KeyNavigation.down = null
             button.highlighted = false
 
             if (button.focusPolicy !== Qt.NoFocus)
@@ -119,50 +118,65 @@ Widgets.NavigableFocusScope {
         }
 
         contentItem: ListView {
-            id: list
+            id: listView
 
-            clip: true
             implicitHeight: contentHeight
-            spacing: 0
+
+            onActiveFocusChanged: {
+                // since Popup.CloseOnReleaseOutside closePolicy is limited to
+                // modal popups, this is an alternative way of closing the popup
+                // when the focus is lost
+                if (!activeFocus && !button.activeFocus)
+                    popup.close()
+            }
 
             ScrollIndicator.vertical: ScrollIndicator { }
 
-            highlight: Rectangle {
-                color: colors.accent
-                opacity: 0.8
-            }
+            property bool containsMouse: false
 
             delegate: ItemDelegate {
                 id: itemDelegate
 
-                anchors.left: parent.left
-                anchors.right: parent.right
-                padding: 0
+                width: parent.width
+
+                readonly property var delegateSortKey: modelData[root.criteriaRole]
+
+                readonly property bool isActive: (delegateSortKey === sortKey)
+
+                background: Rectangle {
+                    color: colors.accent
+                    visible: itemDelegate.hovered || (!listView.containsMouse && itemDelegate.activeFocus)
+                    opacity: 0.8
+                }
+
+                onHoveredChanged: {
+                    listView.containsMouse = hovered
+                    itemDelegate.forceActiveFocus()
+                }
 
-                background: Item {}
                 contentItem: Item {
-                    implicitHeight: itemRow.implicitHeight
+                    implicitHeight: itemRow.height
                     width: itemDelegate.width
 
-                    Rectangle {
-                        anchors.fill: parent
-                        color: colors.accent
-                        visible: mouseArea.containsMouse
-                        opacity: 0.8
-                    }
-
                     RowLayout {
                         id: itemRow
-                        anchors.fill: parent
+
+                        anchors.left: parent.left
+                        anchors.right: parent.right
+
+                        anchors {
+                            leftMargin: VLCStyle.margin_xxsmall
+                            rightMargin: VLCStyle.margin_xxsmall
+                        }
 
                         MenuCaption {
-                            id: isActiveText
                             Layout.preferredHeight: itemText.implicitHeight
                             Layout.preferredWidth: tickMetric.width
-                            Layout.leftMargin: VLCStyle.margin_xsmall
 
-                            text: root.criteriaRole ? (Array.isArray(root.model) ? (modelData[root.criteriaRole] === sortKey ? "✓" : "")
-                                                                                 : (model[root.criteriaRole] === sortKey ? "✓" : "")) : ""
+                            horizontalAlignment: Text.AlignHCenter
+
+                            text: isActive ? tickMetric.text : ""
+
                             color: colors.buttonText
 
                             TextMetrics {
@@ -173,52 +187,32 @@ Widgets.NavigableFocusScope {
 
                         MenuCaption {
                             Layout.fillWidth: true
-                            Layout.topMargin: VLCStyle.margin_xxsmall
-                            Layout.bottomMargin: VLCStyle.margin_xxsmall
-                            Layout.leftMargin: VLCStyle.margin_xsmall
+                            Layout.leftMargin: VLCStyle.margin_xxsmall
 
                             id: itemText
-                            text: root.textRole ? (Array.isArray(root.model) ? modelData[root.textRole] : model[root.textRole]) : modelData
+                            text: modelData[root.textRole]
 
                             color: colors.buttonText
                         }
 
                         MenuCaption {
                             Layout.preferredHeight: itemText.implicitHeight
-                            Layout.rightMargin: VLCStyle.margin_xsmall
 
-                            text: (isActiveText.text === "" ? "" : (sortOrder === PlaylistControllerModel.SORT_ORDER_ASC ? "↓" : "↑"))
+                            text: (sortOrder === Qt.AscendingOrder ? "↓" : "↑")
+                            visible: isActive
 
                             color: colors.buttonText
                         }
                     }
-
-                    MouseArea {
-                        id: mouseArea
-                        anchors.fill: parent
-                        hoverEnabled: true
-                        onClicked: itemDelegate.clicked(mouse)
-                    }
                 }
 
                 onClicked: {
-                    root.currentIndex = index
-
-                    if (root.sortOrder !== undefined) {
-                        var _sortOrder = root.sortOrder
-                        var _sortKey = root.sortKey
+                    if (root.sortKey !== delegateSortKey) {
+                        root.sortSelected(delegateSortKey)
+                        root.sortOrderSelected(Qt.AscendingOrder)
                     }
-
-                    root.sortSelected(Array.isArray(root.model) ? modelData : model)
-
-                    if (root.sortOrder !== undefined) {
-                        if (root.sortKey !== _sortKey)
-                            root._intSortOrder = false
-
-                        if (root.sortOrder === _sortOrder) {
-                            root.sortOrderSelected(root._intSortOrder ? PlaylistControllerModel.SORT_ORDER_DESC : PlaylistControllerModel.SORT_ORDER_ASC)
-                            root._intSortOrder = !root._intSortOrder
-                        }
+                    else {
+                        root.sortOrderSelected(root.sortOrder === Qt.AscendingOrder ? Qt.DescendingOrder : Qt.AscendingOrder)
                     }
 
                     popup.close()
@@ -227,6 +221,8 @@ Widgets.NavigableFocusScope {
         }
 
         background: Rectangle {
+            id: bgRect
+
             border.width: VLCStyle.dp(1)
             border.color: colors.accent
 
@@ -246,7 +242,7 @@ Widgets.NavigableFocusScope {
 
                         // since Popup is not an Item, we can not directly map its position
                         // to the source item. Instead, we can use root because popup's
-                        // position is relative to its position.
+                        // position is relative to root's position.
                         // This method unfortunately causes issues when source item is resized.
                         // But in that case, we reload the effectLoader to redraw the effect.
                         property point popupMappedPos: g_root.mapFromItem(root, popup.x, popup.y)
-- 
2.27.0



More information about the vlc-devel mailing list