[vlc-commits] [Git][videolan/vlc][master] 14 commits: qml: factorize expandgridview

Pierre Lamot gitlab at videolan.org
Mon May 3 13:12:21 UTC 2021



Pierre Lamot pushed to branch master at VideoLAN / VLC


Commits:
8cece6e7 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: factorize expandgridview

- - - - -
85b3c967 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: not use obsolete variant in ExpandGridView

- - - - -
c3f6b1bf by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: don't relayout on data change in ExpandGridView

- - - - -
f46e14b3 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: cache current range in ExpandGridView

- - - - -
db6cdbe5 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: fix range check in _refreshData of ExpandGridView

- - - - -
7d2cb6a5 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: iteratively update selection in ExpandGridView

- - - - -
7e506392 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: fix expand item's model not updating

- - - - -
f0f2e1ba by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: index children of ExpandGridView in list form

~20% ExpandGridView::layout performance improvement during scrolling

- - - - -
046009ea by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: don't base GridItem on FocusScope

GridItem as a whole holds focus, no need to wrap it inside FocusScope

- - - - -
2be1b9d2 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: load ScanProgressBar on demand

- - - - -
462685b4 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: debounce layout when scrolling in gridview

- - - - -
7a0719ce by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: stop at bounds when scrolling in ExpandGridView

Ref #25591

- - - - -
e2806a13 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: correctly remove selection on left click in ExpandGridView

- - - - -
22268499 by Prince Gupta at 2021-05-03T12:20:37+00:00
qml: stop at bound when scrolling in KeyNavigableListView

- - - - -


5 changed files:

- modules/gui/qt/maininterface/qml/MainDisplay.qml
- modules/gui/qt/widgets/qml/ExpandGridView.qml
- modules/gui/qt/widgets/qml/GridItem.qml
- modules/gui/qt/widgets/qml/KeyNavigableListView.qml
- modules/gui/qt/widgets/qml/ScanProgressBar.qml


Changes:

=====================================
modules/gui/qt/maininterface/qml/MainDisplay.qml
=====================================
@@ -230,7 +230,7 @@ Widgets.NavigableFocusScope {
                                 topMargin: VLCStyle.dp(10, VLCStyle.scale)
                                 bottomMargin: VLCStyle.dp(10, VLCStyle.scale)
                             }
-                            active: !!medialib
+                            active: !!medialib && !medialib.idle
                             source: "qrc:///widgets/ScanProgressBar.qml"
                         }
                     }


=====================================
modules/gui/qt/widgets/qml/ExpandGridView.qml
=====================================
@@ -41,8 +41,8 @@ NavigableFocusScope {
     readonly property int _effectiveCellWidth: cellWidth + horizontalSpacing
     readonly property int _effectiveCellHeight: cellHeight + verticalSpacing
 
-    property variant delegateModel
-    property variant model
+    property var delegateModel
+    property var model
 
     property int currentIndex: 0
     property alias contentHeight: flickable.contentHeight
@@ -84,8 +84,9 @@ NavigableFocusScope {
     signal selectAll()
     signal actionAtIndex(int index)
 
-    property variant _idChildrenMap: ({})
-    property variant _unusedItemList: []
+    property var _idChildrenList: []
+    property var _unusedItemList: []
+    property var _currentRange: [0,0]
 
     Accessible.role: Accessible.Table
 
@@ -172,7 +173,13 @@ NavigableFocusScope {
 
     function leftClickOnItem(modifier, index) {
         delegateModel.updateSelection( modifier , currentIndex, index)
-        currentIndex = index
+        if (delegateModel.isSelected(model.index(index, 0)))
+            currentIndex = index
+        else if (currentIndex === index) {
+            if (root._containsItem(currentIndex))
+                root._getItem(currentIndex).focus = false
+            currentIndex = -1
+        }
         root.forceActiveFocus()
     }
 
@@ -182,13 +189,6 @@ NavigableFocusScope {
         }
     }
 
-    function _updateSelected() {
-        for (var id in _idChildrenMap) {
-            var item = _idChildrenMap[id]
-            item.selected = delegateModel.isSelected(model.index(id, 0))
-        }
-    }
-
     function _initialize() {
         if (root._isInitialised)
             return;
@@ -200,7 +200,7 @@ NavigableFocusScope {
         root._isInitialised = true;
     }
 
-    function _getFirstAndLastInstanciatedItemIds() {
+    function _calculateCurrentRange() {
         var myContentY = flickable.contentY - root.headerHeight - topMargin
 
         var contentYWithoutExpand = myContentY
@@ -227,70 +227,91 @@ NavigableFocusScope {
         return [firstId, lastId]
     }
 
-    function _setupChild(id, ydelta) {
-        var item
-        var pos = root.getItemPos(id)
+    function _getItem(id) {
+        var i = id - root._currentRange[0]
+        return root._idChildrenList[i]
+    }
 
-        if (id in _idChildrenMap) {
-            // re-position
+    function _setItem(id, item) {
+        var i = id - root._currentRange[0]
+        root._idChildrenList[i] = item
+    }
 
-            item = _idChildrenMap[id]
-            if (item === undefined)
-                throw "wrong child: " + id
-            //theses properties are always defined in Item
-            item.focus = (id === root.currentIndex) && (root.expandIndex === -1)
-            item.x = pos[0]
-            item.y = pos[1] + ydelta
+    function _containsItem(id) {
+        var i = id - root._currentRange[0]
+        return i >= 0 && i < root._idChildrenList.length && typeof root._idChildrenList[i] !== "undefined"
+    }
 
-        }  else if (_unusedItemList.length > 0) {
-            //recyle
+    function _repositionItem(id, x, y) {
+        var item = root._getItem(id)
+        if (item === undefined)
+            throw "wrong child: " + id
 
-            item = _unusedItemList.pop()
-            if (item === undefined)
-                throw "wrong toRecycle child " + id + ", len " + toUse.length
+        //theses properties are always defined in Item
+        item.focus = (id === root.currentIndex) && (root.expandIndex === -1)
+        item.x = x
+        item.y = y
+        item.selected = delegateModel.isSelected(model.index(id, 0))
+    }
 
-            item.index = id
-            item.model = model.getDataAt(id)
+    function _recycleItem(id, x, y) {
+        var item = _unusedItemList.pop()
+        if (item === undefined)
+            throw "wrong toRecycle child " + id + ", len " + toUse.length
 
-            item.focus = (id === root.currentIndex) && (root.expandIndex === -1)
-            item.x = pos[0]
-            item.y = pos[1] + ydelta
-            item.visible = true
+        item.index = id
+        item.model = model.getDataAt(id)
+        item.selected = delegateModel.isSelected(model.index(id, 0))
+        item.focus = (id === root.currentIndex) && (root.expandIndex === -1)
+        item.x = x
+        item.y = y
+        item.visible = true
 
-            _idChildrenMap[id] = item
+        root._setItem(id, item)
+    }
+
+    function _createItem(id, x, y) {
+        var item = root.delegate.createObject( flickable.contentItem, {
+                        selected: delegateModel.isSelected(model.index(id, 0)),
+                        index: id,
+                        model: model.getDataAt(id),
+                        focus: (id === root.currentIndex) && (root.expandIndex === -1),
+                        x: x,
+                        y: y,
+                        visible: true
+                    });
+        if (item === undefined)
+            throw "wrong unable to instantiate child " + id
+        root._setItem(id, item)
+    }
 
+    function _setupChild(id, ydelta) {
+        var pos = root.getItemPos(id)
+
+        if (root._containsItem(id)) {
+            _repositionItem(id, pos[0], pos[1] + ydelta)
+        }  else if (_unusedItemList.length > 0) {
+            _recycleItem(id, pos[0], pos[1] + ydelta)
         } else {
-            //instanciate a new item
-
-            item = root.delegate.createObject( flickable.contentItem, {
-                            index: id,
-                            model: model.getDataAt(id),
-                            focus: (id === root.currentIndex) && (root.expandIndex === -1),
-                            x: pos[0],
-                            y: pos[1] + ydelta,
-                            visible: true
-                        });
-            if (item === undefined)
-                throw "wrong unable to instantiate child " + id
-            _idChildrenMap[id] = item
-        }
-        return item
+            _createItem(id, pos[0], pos[1] + ydelta)
+        }
     }
 
     function _refreshData( iMin, iMax ) {
-        var f_l = _getFirstAndLastInstanciatedItemIds()
+        var f_l = root._currentRange
         if (!iMin || iMin < f_l[0])
             iMin = f_l[0]
         if (!iMax || iMax > f_l[1])
             iMax= f_l[1]
 
-        for (var id  = iMin; id <= iMax; id++) {
-            var item = _idChildrenMap[id]
-            if (!item) {
-                continue
-            }
+        for (var id  = iMin; id < iMax; id++) {
+            var item = root._getItem(id)
             item.model = model.getDataAt(id)
         }
+
+        if (root.expandIndex >= iMin && root.expandIndex < iMax) {
+            expandItem.model = model.getDataAt(root.expandIndex)
+        }
     }
 
     function _onModelCountChanged() {
@@ -311,10 +332,9 @@ NavigableFocusScope {
         target: model
         onDataChanged: {
             var iMin = topLeft.row
-            var iMax = bottomRight.row
-            var f_l = _getFirstAndLastInstanciatedItemIds()
-            if (iMin <= f_l[1] && f_l[0] <= iMax) {
-                flickable.layout(true)
+            var iMax = bottomRight.row + 1 // [] => [)
+            var f_l = root._currentRange
+            if (iMin < f_l[1] && f_l[0] < iMax) {
                 _refreshData(iMin, iMax)
             }
         }
@@ -323,6 +343,35 @@ NavigableFocusScope {
         onModelReset: _onModelCountChanged()
     }
 
+    Connections {
+        target: delegateModel
+
+        onSelectionChanged: {
+            var i
+            for (i = 0; i < selected.length; ++i) {
+                _updateSelectedRange(selected[i].topLeft, selected[i].bottomRight, true)
+            }
+
+            for (i = 0; i < deselected.length; ++i) {
+                _updateSelectedRange(deselected[i].topLeft, deselected[i].bottomRight, false)
+            }
+        }
+
+        function _updateSelectedRange(topLeft, bottomRight, select) {
+            var iMin = topLeft.row
+            var iMax = bottomRight.row + 1 // [] => [)
+            if (iMin < root._currentRange[1] && root._currentRange[0] < iMax) {
+                iMin = Math.max(iMin, root._currentRange[0])
+                iMax = Math.min(iMax, root._currentRange[1])
+                for (var j = iMin; j < iMax; j++) {
+                    var item = root._getItem(j)
+                    console.assert(item)
+                    item.selected = select
+                }
+            }
+        }
+    }
+
     onModelChanged: _onModelCountChanged()
 
     Connections {
@@ -335,8 +384,10 @@ NavigableFocusScope {
         id: flickable
 
         clip: true
-
         flickableDirection: Flickable.VerticalFlick
+        boundsBehavior: Flickable.StopAtBounds
+        boundsMovement :Flickable.StopAtBounds
+
         ScrollBar.vertical: ScrollBar {
             id: flickableScrollBar
         }
@@ -397,7 +448,17 @@ NavigableFocusScope {
         anchors.fill: parent
         onWidthChanged: { layout(true) }
         onHeightChanged: { layout(false) }
-        onContentYChanged: { layout(false) }
+        onContentYChanged: { scrollLayoutTimer.start() }
+
+        Timer {
+            id: scrollLayoutTimer
+
+            interval: 1
+            running: false
+            repeat: false
+            triggeredOnStart: false
+            onTriggered: flickable.layout(false)
+        }
 
         function getExpandItemGridId() {
             var ret
@@ -411,6 +472,52 @@ NavigableFocusScope {
             return ret
         }
 
+        function _setupIndexes(force, range, yDelta) {
+            for (var i = range[0]; i < range[1]; i++) {
+                if (!force && root._containsItem(i))
+                    continue
+                _setupChild(i, yDelta)
+            }
+        }
+
+        function _overlappedInterval(i1, i2) {
+            if (i1[0] > i2[0]) return _overlappedInterval(i2, i1)
+            if (i1[1] > i2[0]) return [i2[0], Math.min(i1[1], i2[1])]
+            return [0, 0]
+        }
+
+        function _updateChildrenMap(first, last) {
+            if (first >= last) {
+                root._idChildrenList.forEach(function(item) { item.visible = false; })
+                root._unusedItemList = root._idChildrenList
+                root._idChildrenList = []
+                root._currentRange = [0, 0]
+                return
+            }
+
+            var overlapped = _overlappedInterval([first, last], root._currentRange)
+
+            var i
+            var newList = new Array(last - first)
+
+            for (i = overlapped[0]; i < overlapped[1]; ++i) {
+                newList[i - first] = root._getItem(i)
+                root._setItem(i, undefined)
+            }
+
+            for (i = _currentRange[0]; i < _currentRange[1]; ++i) {
+                var item = root._getItem(i)
+                if (typeof item !== "undefined") {
+                    item.visible = false
+                    _unusedItemList.push(item)
+                    //  root._setItem(i, undefined) // not needed the list will be reset following this loop
+                }
+            }
+
+            _idChildrenList = newList
+            root._currentRange = [first, last]
+        }
+
         function layout(forceRelayout) {
             if (flickable.width === 0 || flickable.height === 0)
                 return
@@ -422,37 +529,22 @@ NavigableFocusScope {
             var i
             var expandItemGridId = getExpandItemGridId()
 
-            var f_l = _getFirstAndLastInstanciatedItemIds()
+            var f_l = _calculateCurrentRange()
             var nbItems = f_l[1] - f_l[0]
             var firstId = f_l[0]
             var lastId = f_l[1]
 
             var topGridEndId = Math.max(Math.min(expandItemGridId, lastId), firstId)
 
-            // Clean the no longer used ids
-            var toKeep = {}
-
-            for (var id in _idChildrenMap) {
-                var val = _idChildrenMap[id]
-
-                if (id >= firstId && id < lastId) {
-                    toKeep[id] = val
-                } else {
-                    _unusedItemList.push(val)
-                    val.visible = false
-                }
-            }
-            _idChildrenMap = toKeep
+            if (!forceRelayout && root._currentRange[0] === firstId && root._currentRange[1] === lastId)
+                return;
 
+            _updateChildrenMap(firstId, lastId)
 
             var item
             var pos
             // Place the delegates before the expandItem
-            for (i = firstId; i < topGridEndId; ++i) {
-                if (!forceRelayout && i in _idChildrenMap)
-                    continue
-                _setupChild(i,  0)
-            }
+            _setupIndexes(forceRelayout, [firstId, topGridEndId], 0)
 
             if (root.expandIndex !== -1) {
                 var expandItemPos = root.getItemPos(expandItemGridId)
@@ -460,19 +552,13 @@ NavigableFocusScope {
             }
 
             // Place the delegates after the expandItem
-            for (i = topGridEndId; i < lastId; ++i) {
-                if (!forceRelayout && i in _idChildrenMap)
-                    continue
-                 _setupChild(i, _expandItemVerticalSpace)
-            }
+            _setupIndexes(forceRelayout, [topGridEndId, lastId], _expandItemVerticalSpace)
 
             // Calculate and set the contentHeight
             var newContentHeight = root.getItemPos(_count - 1)[1] + root._effectiveCellHeight + _expandItemVerticalSpace
             contentHeight = newContentHeight + root.bottomMargin // topMargin is included from root.getItemPos
             contentHeight += footerItemLoader.item ? footerItemLoader.item.height : 0
             contentWidth = root._effectiveCellWidth * root.getNbItemsPerRow() - root.horizontalSpacing
-
-            _updateSelected()
         }
 
         Connections {
@@ -549,8 +635,8 @@ NavigableFocusScope {
             if (expandIndex !== -1)
                 return
             var child
-            if (currentIndex in _idChildrenMap)
-                child = _idChildrenMap[currentIndex]
+            if (root._containsItem(currentIndex))
+                child = root._getItem(currentIndex)
             if (child !== undefined)
                 child.focus = true
         }
@@ -573,7 +659,6 @@ NavigableFocusScope {
         if (expandIndex !== -1)
             retract()
         flickable.setCurrentItemFocus()
-        _updateSelected()
         positionViewAtIndex(root.currentIndex, ItemView.Contain)
     }
 
@@ -615,8 +700,6 @@ NavigableFocusScope {
 
         if (!event.accepted)
             defaultKeyAction(event, currentIndex)
-
-        _updateSelected()
     }
 
     Keys.onReleased: {
@@ -627,7 +710,5 @@ NavigableFocusScope {
             event.accepted = true
             root.actionAtIndex(currentIndex)
         }
-
-        _updateSelected()
     }
 }


=====================================
modules/gui/qt/widgets/qml/GridItem.qml
=====================================
@@ -25,7 +25,7 @@ import org.videolan.vlc 0.1
 import "qrc:///widgets/" as Widgets
 import "qrc:///style/"
 
-FocusScope {
+MouseArea {
     id: root
 
     property alias image: picture.source
@@ -42,7 +42,12 @@ FocusScope {
     property real pictureWidth: VLCStyle.colWidth(1)
     property real pictureHeight: pictureWidth
     property int titleMargin: VLCStyle.margin_xsmall
-    property Item dragItem
+    property Item dragItem: null
+
+    readonly property bool highlighted: root.containsMouse || root.activeFocus
+    readonly property int selectedBorderWidth: VLCStyle.gridItemSelectedBorder
+
+    property int _modifiersOnLastPress: Qt.NoModifier
 
     // if true, texts are horizontally centered, provided it can fit in pictureWidth
     property bool textAlignHCenter: false
@@ -56,20 +61,15 @@ FocusScope {
     signal itemDoubleClicked(Item menuParent, int keys, int modifier)
     signal contextMenuButtonClicked(Item menuParent, var globalMousePos)
 
+    acceptedButtons: Qt.RightButton | Qt.LeftButton
+    hoverEnabled: true
+    implicitWidth: layout.implicitWidth
+    implicitHeight: layout.implicitHeight
     Keys.onMenuPressed: root.contextMenuButtonClicked(picture, root.mapToGlobal(0,0))
 
     Accessible.role: Accessible.Cell
     Accessible.name: title
 
-    implicitWidth: mouseArea.implicitWidth
-    implicitHeight: mouseArea.implicitHeight
-
-    readonly property bool highlighted: mouseArea.containsMouse || root.activeFocus
-
-    readonly property int selectedBorderWidth: VLCStyle.gridItemSelectedBorder
-
-    property int _modifiersOnLastPress: Qt.NoModifier
-
     state: highlighted ? "selected" : "unselected"
     states: [
         State {
@@ -165,130 +165,119 @@ FocusScope {
         }
     ]
 
-    MouseArea {
-        id: mouseArea
-
-        hoverEnabled: true
-        anchors.fill: parent
-        implicitWidth: layout.implicitWidth
-        implicitHeight: layout.implicitHeight
-        drag.target: root.dragItem
-        drag.axis: Drag.XAndYAxis
-        drag.onActiveChanged: {
-            // perform the "click" action because the click action is only executed on mouse release (we are in the pressed state)
-            // but we will need the updated list on drop
-            if (drag.active && !selected) {
-                root.itemClicked(picture, Qt.LeftButton, root._modifiersOnLastPress)
-            } else if (root.dragItem) {
-                root.dragItem.Drag.drop()
-            }
-            root.dragItem.Drag.active = drag.active
+    drag.target: root.dragItem
+    drag.axis: Drag.XAndYAxis
+    drag.onActiveChanged: {
+        // perform the "click" action because the click action is only executed on mouse release (we are in the pressed state)
+        // but we will need the updated list on drop
+        if (drag.active && !selected) {
+            root.itemClicked(picture, Qt.LeftButton, root._modifiersOnLastPress)
+        } else if (root.dragItem) {
+            root.dragItem.Drag.drop()
         }
+        root.dragItem.Drag.active = drag.active
+    }
 
-        acceptedButtons: Qt.RightButton | Qt.LeftButton
-        Keys.onMenuPressed: root.contextMenuButtonClicked(picture, root.mapToGlobal(0,0))
-
-        onClicked: {
-            if (mouse.button === Qt.RightButton)
-                contextMenuButtonClicked(picture, mouseArea.mapToGlobal(mouse.x,mouse.y));
-            else {
-                root.itemClicked(picture, mouse.button, mouse.modifiers);
-            }
+    onClicked: {
+        if (mouse.button === Qt.RightButton)
+            contextMenuButtonClicked(picture, root.mapToGlobal(mouse.x,mouse.y));
+        else {
+            root.itemClicked(picture, mouse.button, mouse.modifiers);
         }
+    }
 
-        onDoubleClicked: {
-            if (mouse.button === Qt.LeftButton)
-                root.itemDoubleClicked(picture,mouse.buttons, mouse.modifiers)
-        }
+    onDoubleClicked: {
+        if (mouse.button === Qt.LeftButton)
+            root.itemDoubleClicked(picture,mouse.buttons, mouse.modifiers)
+    }
 
-        onPressed: _modifiersOnLastPress = mouse.modifiers
+    onPressed: _modifiersOnLastPress = mouse.modifiers
 
-        onPositionChanged: {
-            if (drag.active) {
-                var pos = drag.target.parent.mapFromItem(mouseArea, mouseX, mouseY)
-                drag.target.x = pos.x + 12
-                drag.target.y = pos.y + 12
-            }
+    onPositionChanged: {
+        if (drag.active) {
+            var pos = drag.target.parent.mapFromItem(root, mouseX, mouseY)
+            drag.target.x = pos.x + 12
+            drag.target.y = pos.y + 12
         }
+    }
 
-        /* background visible when selected */
-        Rectangle {
-            id: selectionRect
+    /* background visible when selected */
+    Rectangle {
+        id: selectionRect
 
-            x: - root.selectedBorderWidth
-            y: - root.selectedBorderWidth
-            width: root.width + ( root.selectedBorderWidth * 2 )
-            height:  root.height + ( root.selectedBorderWidth * 2 )
-            color: VLCStyle.colors.bgHover
-            visible: root.selected || root.highlighted
-        }
+        x: - root.selectedBorderWidth
+        y: - root.selectedBorderWidth
+        width: root.width + ( root.selectedBorderWidth * 2 )
+        height:  root.height + ( root.selectedBorderWidth * 2 )
+        color: VLCStyle.colors.bgHover
+        visible: root.selected || root.highlighted
+    }
 
-        Loader {
-            id: unselectedUnderlayLoader
+    Loader {
+        id: unselectedUnderlayLoader
 
-            asynchronous: true
-        }
+        asynchronous: true
+    }
 
-        Loader {
-            id: selectedUnderlayLoader
+    Loader {
+        id: selectedUnderlayLoader
 
-            asynchronous: true
-            active: false
-            visible: false
-            onVisibleChanged: {
-                if (visible && !active)
-                    active = true
-            }
+        asynchronous: true
+        active: false
+        visible: false
+        onVisibleChanged: {
+            if (visible && !active)
+                active = true
         }
+    }
 
-        Column {
-            id: layout
-
-            anchors.centerIn: parent
-
-            Widgets.MediaCover {
-                id: picture
+    Column {
+        id: layout
 
-                width: pictureWidth
-                height: pictureHeight
-                playCoverVisible: root.highlighted
-                onPlayIconClicked: root.playClicked()
-                radius: VLCStyle.gridCover_radius
-            }
+        anchors.centerIn: parent
 
-            Widgets.ScrollingText {
-                id: titleTextRect
+        Widgets.MediaCover {
+            id: picture
 
-                label: titleLabel
-                scroll: highlighted
-                height: titleLabel.height
-                width: titleLabel.width
-                visible: root.title !== ""
+            width: pictureWidth
+            height: pictureHeight
+            playCoverVisible: root.highlighted
+            onPlayIconClicked: root.playClicked()
+            radius: VLCStyle.gridCover_radius
+        }
 
-                Widgets.ListLabel {
-                    id: titleLabel
+        Widgets.ScrollingText {
+            id: titleTextRect
 
-                    elide: titleTextRect.scroll ?  Text.ElideNone : Text.ElideRight
-                    width: pictureWidth
-                    horizontalAlignment: root.textAlignHCenter && titleLabel.contentWidth <= titleLabel.width ? Text.AlignHCenter : Text.AlignLeft
-                    topPadding: root.titleMargin
-                    color: selectionRect.visible ? VLCStyle.colors.bgHoverText : VLCStyle.colors.text
-                }
-            }
+            label: titleLabel
+            scroll: highlighted
+            height: titleLabel.height
+            width: titleLabel.width
+            visible: root.title !== ""
 
-            Widgets.MenuCaption {
-                id: subtitleTxt
+            Widgets.ListLabel {
+                id: titleLabel
 
-                visible: text !== ""
-                text: root.subtitle
+                elide: titleTextRect.scroll ?  Text.ElideNone : Text.ElideRight
                 width: pictureWidth
-                topPadding: VLCStyle.margin_xsmall              
-                elide: Text.ElideRight
-                horizontalAlignment: root.textAlignHCenter && subtitleTxt.contentWidth <= subtitleTxt.width ? Text.AlignHCenter : Text.AlignLeft
-                color: selectionRect.visible
-                       ? VLCStyle.colors.setColorAlpha(VLCStyle.colors.bgHoverText, .6)
-                       : VLCStyle.colors.menuCaption
+                horizontalAlignment: root.textAlignHCenter && titleLabel.contentWidth <= titleLabel.width ? Text.AlignHCenter : Text.AlignLeft
+                topPadding: root.titleMargin
+                color: selectionRect.visible ? VLCStyle.colors.bgHoverText : VLCStyle.colors.text
             }
         }
+
+        Widgets.MenuCaption {
+            id: subtitleTxt
+
+            visible: text !== ""
+            text: root.subtitle
+            width: pictureWidth
+            topPadding: VLCStyle.margin_xsmall              
+            elide: Text.ElideRight
+            horizontalAlignment: root.textAlignHCenter && subtitleTxt.contentWidth <= subtitleTxt.width ? Text.AlignHCenter : Text.AlignLeft
+            color: selectionRect.visible
+                    ? VLCStyle.colors.setColorAlpha(VLCStyle.colors.bgHoverText, .6)
+                    : VLCStyle.colors.menuCaption
+        }
     }
 }


=====================================
modules/gui/qt/widgets/qml/KeyNavigableListView.qml
=====================================
@@ -145,6 +145,9 @@ NavigableFocusScope {
         section.criteria: ViewSection.FullString
         section.delegate: sectionHeading
 
+        boundsBehavior: Flickable.StopAtBounds
+        boundsMovement :Flickable.StopAtBounds
+
         Connections {
             target: view.currentItem
             ignoreUnknownSignals: true


=====================================
modules/gui/qt/widgets/qml/ScanProgressBar.qml
=====================================
@@ -89,6 +89,7 @@ T.ProgressBar {
                     id: loadingAnim
 
                     loops: Animation.Infinite
+                    running: control.indeterminate
 
                     NumberAnimation {
                         from: - 1



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4d13639f939e05c11aea58f2614ef0d222692263...2226849992b43e97e4bf77e307285fe61d7e3c0a

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4d13639f939e05c11aea58f2614ef0d222692263...2226849992b43e97e4bf77e307285fe61d7e3c0a
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list