[vlc-commits] [Git][videolan/vlc][master] 10 commits: Revert "qml/PlayerControlLayout: Update the 'layoutSpacing' property"
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Sun Nov 26 16:08:50 UTC 2023
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
70732cf3 by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
Revert "qml/PlayerControlLayout: Update the 'layoutSpacing' property"
This reverts commit 72c34ac178d835a549920ece08a0e4edefe12351.
- - - - -
848b6e21 by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
Revert "qml/PlayerControlLayout: Update resize and collpasing behavior"
This reverts commit a1f2bda77b7446d6a71f79f1a82311f3db18bd3f.
- - - - -
2bcc6e63 by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
Revert "qml/ArtworkInfoWidget: Add the 'preferredWidth' property"
This reverts commit aec938f083e269bcc69de2b8f9b4307a0336584b.
- - - - -
979681c2 by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
Revert "qml/ControlLayout: Add the 'preferredWidth' support"
This reverts commit 3efc5ce68fd39b6d0aebd80a6fa626473e2098ad.
- - - - -
4af07aea by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
Revert "qml/ControlLayout: Update the 'implicitWidth' property"
This reverts commit 44bc4d84b507b9d4e817fb97a844fb8ae6ce1c54.
- - - - -
92ffca9b by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
Revert "qml/ControlLayout: Add the 'count' alias"
This reverts commit 96e3f57302d95f08dad13068389e1f38804e6e9b.
- - - - -
55099e40 by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
Revert "qml/ControlLayout: Add the 'alignment' property"
This reverts commit a421045fd7d6a31bc85887bf797327a3f8ba9753.
- - - - -
c2803be3 by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
Revert "qml/ControlLayout: Add the 'contentWidth' property"
This reverts commit 9bea3945b16ad336e323543065667054274f615a.
- - - - -
3be2ea83 by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
qml: major overhaul for player control layout
- Support dynamic width when center is not
available.
- Proper support for height adjustment
- Declarative approach
- - - - -
d4d2c619 by Fatih Uzunoglu at 2023-11-26T15:53:44+00:00
qml: enable delayed bindings when the component is completed
- - - - -
11 changed files:
- modules/gui/qt/Makefile.am
- modules/gui/qt/dialogs/toolbar/qml/EditorDNDDelegate.qml
- modules/gui/qt/dialogs/toolbar/qml/EditorDNDView.qml
- modules/gui/qt/player/qml/ControlBar.qml
- modules/gui/qt/player/qml/ControlLayout.qml
- + modules/gui/qt/player/qml/ControlRepeater.qml
- modules/gui/qt/player/qml/PlayerControlLayout.qml
- modules/gui/qt/player/qml/controlbarcontrols/ArtworkInfoWidget.qml
- modules/gui/qt/player/qml/controlbarcontrols/ExpandingSpacerWidget.qml
- modules/gui/qt/player/qml/controlbarcontrols/PlayButton.qml
- modules/gui/qt/vlc.qrc
Changes:
=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -930,6 +930,7 @@ libqt_plugin_la_QML = \
gui/qt/player/qml/TracksPageSubtitle.qml \
gui/qt/player/qml/TracksListPage.qml \
gui/qt/player/qml/ControlLayout.qml \
+ gui/qt/player/qml/ControlRepeater.qml \
gui/qt/player/qml/controlbarcontrols/HighResolutionTimeWidget.qml \
gui/qt/player/qml/controlbarcontrols/ArtworkInfoWidget.qml \
gui/qt/player/qml/controlbarcontrols/AspectRatioWidget.qml \
=====================================
modules/gui/qt/dialogs/toolbar/qml/EditorDNDDelegate.qml
=====================================
@@ -18,6 +18,7 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
import QtQml.Models 2.12
import org.videolan.vlc 0.1
@@ -35,7 +36,7 @@ Control {
readonly property int controlId: model.id
property ListView dndView: null
- readonly property bool dragActive: loader.Drag.active
+ readonly property bool dragActive: contentItem.target.Drag.active
property alias dropArea: dropArea
property alias containsMouse: mouseArea.containsMouse
@@ -78,9 +79,9 @@ Control {
}
onPressed: {
- const pos = mapToItem(loader.parent, mouseX, mouseY)
- loader.y = pos.y + VLCStyle.dragDelta
- loader.x = pos.x + VLCStyle.dragDelta
+ const pos = mapToItem(control.contentItem.target.parent, mouseX, mouseY)
+ control.contentItem.target.y = pos.y + VLCStyle.dragDelta
+ control.contentItem.target.x = pos.x + VLCStyle.dragDelta
}
}
@@ -132,8 +133,6 @@ Control {
}
background: Rectangle {
- opacity: Drag.active ? 0.75 : 1.0
-
color: "transparent"
border.width: VLCStyle.dp(1, VLCStyle.scale)
@@ -145,13 +144,14 @@ Control {
implicitHeight: loader.implicitHeight
implicitWidth: loader.implicitWidth
+ readonly property Item target: loader
+
Loader {
id: loader
parent: Drag.active ? root : control.contentItem
- anchors.horizontalCenter: Drag.active ? undefined : parent.horizontalCenter
- anchors.verticalCenter: Drag.active ? undefined : parent.verticalCenter
+ anchors.fill: (parent === control.contentItem) ? parent : undefined
source: PlayerControlbarControls.control(model.id).source
@@ -160,10 +160,6 @@ Control {
onLoaded: {
item.paintOnly = true
item.enabled = false
-
- if (!extraWidthAvailable && item.minimumWidth !== undefined) {
- item.width = item.minimumWidth
- }
}
}
}
=====================================
modules/gui/qt/dialogs/toolbar/qml/EditorDNDView.qml
=====================================
@@ -161,8 +161,9 @@ ListView {
}
delegate: EditorDNDDelegate {
- anchors.verticalCenter: (!!parent) ? parent.verticalCenter : undefined
+ height: Math.min((contentItem.implicitHeight > 0) ? contentItem.implicitHeight : Number.MAX_VALUE, VLCStyle.controlLayoutHeight)
+ anchors.verticalCenter: parent ? parent.verticalCenter : undefined
dndView: playerBtnDND
BindingCompat {
=====================================
modules/gui/qt/player/qml/ControlBar.qml
=====================================
@@ -243,6 +243,9 @@ T.Pane {
Layout.rightMargin: VLCStyle.margin_large
identifier: root.identifier
+
+ implicitHeight: MainCtx.pinVideoControls ? VLCStyle.controlLayoutHeightPinned
+ : VLCStyle.controlLayoutHeight
Navigation.upItem: trackPositionSlider.enabled ? trackPositionSlider : root.Navigation.upItem
=====================================
modules/gui/qt/player/qml/ControlLayout.qml
=====================================
@@ -32,9 +32,55 @@ FocusScope {
// Properties
- property int contentWidth: 0
+ // These delayed bindings are necessary
+ // because the size of the items
+ // may not be ready immediately.
+ // The wise thing to do would be to not
+ // delay if the sizes are ready.
+
+ BindingCompat on Layout.minimumWidth {
+ delayed: true
+ when: controlLayout._componentCompleted
+ value: {
+ const count = repeater.count
+
+ if (count === 0)
+ return 0
+
+ let size = 0
+
+ for (let i = 0; i < count; ++i) {
+ const item = repeater.itemAt(i)
+
+ if (item.Layout.minimumWidth < 0)
+ size += item.implicitWidth
+ else
+ size += item.Layout.minimumWidth
+ }
+
+ return size + ((count - 1 + ((controlLayout.alignment & (Qt.AlignLeft | Qt.AlignRight)) ? 1 : 0)) * playerControlLayout.spacing)
+ }
+ }
+
+ BindingCompat on Layout.maximumWidth {
+ delayed: true
+ when: controlLayout._componentCompleted
+ value: {
+ let maximumWidth = 0
+ const count = repeater.count
- property int alignment: 0
+ for (let i = 0; i < count; ++i) {
+ const item = repeater.itemAt(i)
+ maximumWidth += item.implicitWidth
+ }
+
+ maximumWidth += ((count - 1 + ((alignment & (Qt.AlignLeft | Qt.AlignRight)) ? 1 : 0)) * playerControlLayout.spacing)
+
+ return maximumWidth
+ }
+ }
+
+ property alias alignment: repeater.alignment
property var altFocusAction: Navigation.defaultNavigationUp
@@ -43,9 +89,9 @@ FocusScope {
colorSet: ColorContext.Window
}
- // Aliases
+ property bool _componentCompleted: false
- property alias count: repeater.count
+ // Aliases
property alias model: repeater.model
@@ -57,23 +103,7 @@ FocusScope {
// Settings
- implicitWidth: {
- if (count === 0)
- return 0
-
- let size = 0
-
- for (let i = 0; i < count; ++i) {
- size += repeater.itemAt(i).preferredWidth
- }
-
- if (alignment)
- // NOTE: We provision the spacing induced by the alignment item.
- return size + count * rowLayout.spacing
- else
- return size + (count - 1) * rowLayout.spacing
- }
-
+ implicitWidth: Layout.maximumWidth
implicitHeight: rowLayout.implicitHeight
Navigation.navigable: {
@@ -92,6 +122,8 @@ FocusScope {
Component.onCompleted: {
visibleChanged.connect(_handleFocus)
activeFocusChanged.connect(_handleFocus)
+
+ _componentCompleted = true
}
// Functions
@@ -104,28 +136,6 @@ FocusScope {
altFocusAction()
}
- function _updateContentWidth() {
- let size = 0
-
- for (let i = 0; i < count; i++) {
-
- const item = repeater.itemAt(i)
-
- if (item === null || item.isActive === false)
- continue
-
- const width = item.width
-
- if (width)
- size += width + spacing
- }
-
- if (size)
- contentWidth = size - spacing
- else
- contentWidth = size
- }
-
// Children
RowLayout {
@@ -136,249 +146,25 @@ FocusScope {
spacing: playerControlLayout.spacing
Item {
- Layout.fillWidth: (controlLayout.alignment === Qt.AlignRight)
+ Layout.fillWidth: visible
+ visible: (controlLayout.alignment & Qt.AlignRight)
}
- Repeater {
+ ControlRepeater {
id: repeater
- // NOTE: We apply the 'navigation chain' after adding the item.
- onItemAdded: {
- item.applyNavigation()
-
- controlLayout._updateContentWidth()
- }
-
- onItemRemoved: {
- // NOTE: We update the 'navigation chain' after removing the item.
- item.removeNavigation()
-
- item.recoverFocus(index)
-
- controlLayout._updateContentWidth()
- }
-
- delegate: Loader {
- id: loader
-
- // Properties
-
- // NOTE: This is required for contentWidth because the visible property is delayed.
- property bool isActive: (x + minimumWidth <= rowLayout.width)
+ Navigation.parentItem: controlLayout
- property int minimumWidth: {
- if (expandable)
- return item.minimumWidth
- else if (item)
- return item.implicitWidth
- else
- return 0
- }
+ availableWidth: rowLayout.width
+ availableHeight: rowLayout.height
- property int preferredWidth: (item && item.preferredWidth) ? item.preferredWidth
- : minimumWidth
-
- readonly property bool expandable: (item && item.minimumWidth !== undefined)
-
- // Settings
-
- source: PlayerControlbarControls.control(model.id).source
-
- focus: (index === 0)
-
- Layout.fillWidth: expandable
-
- Layout.minimumWidth: minimumWidth
-
- Layout.preferredWidth: preferredWidth
-
- Layout.maximumWidth: preferredWidth
-
- Layout.alignment: (Qt.AlignVCenter | controlLayout.alignment)
-
- BindingCompat {
- delayed: true // this is important
- target: loader
- property: "visible"
- value: isActive
- }
-
- // Events
-
- Component.onCompleted: repeater.countChanged.connect(controlLayout._handleFocus)
-
- onIsActiveChanged: controlLayout._updateContentWidth()
-
- onWidthChanged: controlLayout._updateContentWidth()
-
- onActiveFocusChanged: {
- if (activeFocus && (!!item && !item.focus)) {
- recoverFocus()
- }
- }
-
- onLoaded: {
- // control should not request focus if they are not enabled:
- item.focus = Qt.binding(function() { return item.enabled && item.visible })
-
- // navigation parent of control is always controlLayout
- // so it can be set here unlike leftItem and rightItem:
- item.Navigation.parentItem = controlLayout
-
- if (item instanceof Control || item instanceof T.Control)
- item.activeFocusOnTab = true
-
- // FIXME: Do we really need to enforce a defaultSize ?
- if (item.size !== undefined)
- item.size = Qt.binding(function() { return defaultSize; })
-
- item.width = Qt.binding(function() { return loader.width } )
-
- if (item.maximumHeight !== undefined)
- item.maximumHeight = Qt.binding(function() { return rowLayout.height })
-
- item.visible = Qt.binding(function() { return loader.visible })
-
- if (item.requestLockUnlockAutoHide) {
- item.requestLockUnlockAutoHide.connect(function(lock) {
- controlLayout.requestLockUnlockAutoHide(lock)
- })
- }
-
- if (item.menuOpened) {
- item.menuOpened.connect(function(menu) {
- controlLayout.menuOpened(menu)
- })
- }
- }
-
- // Connections
-
- Connections {
- target: item
-
- enabled: loader.status === Loader.Ready
-
- onEnabledChanged: {
- if (activeFocus && !item.enabled) // Loader has focus but item is not enabled
- recoverFocus()
- }
-
- onVisibleChanged: {
- if (activeFocus && !item.visible)
- recoverFocus()
- }
- }
-
- // Functions
-
- function applyNavigation() {
- if (item == null) return
-
- const itemLeft = repeater.itemAt(index - 1)
- const itemRight = repeater.itemAt(index + 1)
-
- if (itemLeft) {
- const componentLeft = itemLeft.item
-
- if (componentLeft)
- {
- item.Navigation.leftItem = componentLeft
-
- componentLeft.Navigation.rightItem = item
- }
- }
-
- if (itemRight) {
- const componentRight = itemRight.item
-
- if (componentRight)
- {
- item.Navigation.rightItem = componentRight
-
- componentRight.Navigation.leftItem = item
- }
- }
- }
-
- function removeNavigation() {
- if (item == null) return
-
- const itemLeft = repeater.itemAt(index - 1)
-
- // NOTE: The current item was removed from the repeater so we test against the
- // same index.
- const itemRight = repeater.itemAt(index)
-
- if (itemLeft) {
- if (itemRight) {
- itemLeft.item.Navigation.rightItem = itemRight.item
- itemRight.item.Navigation.leftItem = itemLeft.item
- }
- else
- itemLeft.item.Navigation.rightItem = null
- }
- else if (itemRight) {
- itemRight.item.Navigation.leftItem = null
- }
- }
-
- function recoverFocus(_index) {
- if (item == null) return
-
- if (!controlLayout.visible)
- return
-
- if (_index === undefined)
- _index = index
-
- for (let i = 1; i <= Math.max(_index, repeater.count - (_index + 1)); ++i) {
- if (i <= _index) {
- const leftItem = repeater.itemAt(_index - i)
-
- if (_focusIfFocusable(leftItem))
- return
- }
-
- if (_index + i <= repeater.count - 1) {
- const rightItem = repeater.itemAt(_index + i)
-
- if (_focusIfFocusable(rightItem))
- return
- }
- }
-
- // focus to other alignment if focusable control
- // in the same alignment is not found:
- if (!!controlLayout.Navigation.rightItem) {
- controlLayout.Navigation.defaultNavigationRight()
- } else if (!!controlLayout.Navigation.leftItem) {
- controlLayout.Navigation.defaultNavigationLeft()
- } else {
- controlLayout.altFocusAction()
- }
- }
-
- // Private
-
- function _focusIfFocusable(_loader) {
- if (!!_loader && !!_loader.item && _loader.item.focus) {
- if (item.focusReason !== undefined)
- _loader.item.forceActiveFocus(item.focusReason)
- else {
- console.warn("focusReason is not available in %1!".arg(item))
- _loader.item.forceActiveFocus()
- }
- return true
- } else {
- return false
- }
- }
- }
+ requestLockUnlockAutoHide: controlLayout.requestLockUnlockAutoHide
+ menuOpened: controlLayout.menuOpened
}
Item {
- Layout.fillWidth: (controlLayout.alignment === Qt.AlignLeft)
+ Layout.fillWidth: visible
+ visible: (controlLayout.alignment & Qt.AlignLeft)
}
}
}
=====================================
modules/gui/qt/player/qml/ControlRepeater.qml
=====================================
@@ -0,0 +1,227 @@
+/*****************************************************************************
+ * Copyright (C) 2023 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+
+import org.videolan.vlc 0.1
+import org.videolan.compat 0.1
+
+Repeater {
+ id: repeater
+
+ property int alignment: Qt.AlignVCenter
+
+ property real availableWidth: Number.MAX_VALUE
+ property real availableHeight: Number.MAX_VALUE
+
+ property var menuOpened
+ property var requestLockUnlockAutoHide
+
+ // NOTE: We apply the 'navigation chain' after adding the item.
+ onItemAdded: item.applyNavigation()
+
+ onItemRemoved: {
+ // NOTE: We update the 'navigation chain' after removing the item.
+ item.removeNavigation()
+
+ item.recoverFocus(index)
+ }
+
+ delegate: Loader {
+ id: loader
+
+ // Settings
+
+ source: PlayerControlbarControls.control(model.id).source
+
+ focus: (index === 0)
+
+ Layout.fillWidth: (item && item.Layout.minimumWidth > 0)
+ Layout.minimumWidth: Layout.fillWidth ? item.Layout.minimumWidth : (item ? item.implicitWidth : -1)
+ Layout.maximumWidth: Layout.fillWidth ? (item ? item.implicitWidth : -1) : -1
+
+ Layout.minimumHeight: 0
+ Layout.maximumHeight: Math.min((item && item.implicitHeight <= 0) ? Number.MAX_VALUE : item.implicitHeight, repeater.availableHeight)
+ Layout.fillHeight: true
+
+ Layout.alignment: repeater.alignment
+
+ BindingCompat on visible {
+ delayed: true // this is important
+ value: (loader.x + loader.Layout.minimumWidth <= repeater.availableWidth)
+ }
+
+ // Events
+
+ onActiveFocusChanged: {
+ if (activeFocus && (!!item && !item.focus)) {
+ recoverFocus()
+ }
+ }
+
+ onLoaded: {
+ // control should not request focus if they are not enabled:
+ item.focus = Qt.binding(function() { return item.enabled && item.visible })
+
+ // navigation parent of control is always controlLayout
+ // so it can be set here unlike leftItem and rightItem:
+ item.Navigation.parentItem = repeater
+
+ if (typeof item.activeFocusOnTab === "boolean")
+ item.activeFocusOnTab = true
+
+ // FIXME: Do we really need to enforce a defaultSize ?
+ if (item.size !== undefined)
+ item.size = Qt.binding(function() { return defaultSize; })
+
+ item.visible = Qt.binding(function() { return loader.visible })
+
+ if (item.requestLockUnlockAutoHide)
+ item.requestLockUnlockAutoHide.connect(repeater.requestLockUnlockAutoHide)
+
+ if (item.menuOpened)
+ item.menuOpened.connect(repeater.menuOpened)
+ }
+
+ // Connections
+
+ Connections {
+ target: item
+
+ enabled: loader.status === Loader.Ready
+
+ onEnabledChanged: {
+ if (activeFocus && !item.enabled) // Loader has focus but item is not enabled
+ recoverFocus()
+ }
+
+ onVisibleChanged: {
+ if (activeFocus && !item.visible)
+ recoverFocus()
+ }
+ }
+
+ // Functions
+
+ function applyNavigation() {
+ if (item === null) return
+
+ const itemLeft = repeater.itemAt(index - 1)
+ const itemRight = repeater.itemAt(index + 1)
+
+ if (itemLeft) {
+ const componentLeft = itemLeft.item
+
+ if (componentLeft)
+ {
+ item.Navigation.leftItem = componentLeft
+
+ componentLeft.Navigation.rightItem = item
+ }
+ }
+
+ if (itemRight) {
+ const componentRight = itemRight.item
+
+ if (componentRight)
+ {
+ item.Navigation.rightItem = componentRight
+
+ componentRight.Navigation.leftItem = item
+ }
+ }
+ }
+
+ function removeNavigation() {
+ if (item === null) return
+
+ const itemLeft = repeater.itemAt(index - 1)
+
+ // NOTE: The current item was removed from the repeater so we test against the
+ // same index.
+ const itemRight = repeater.itemAt(index)
+
+ if (itemLeft) {
+ if (itemRight) {
+ itemLeft.item.Navigation.rightItem = itemRight.item
+ itemRight.item.Navigation.leftItem = itemLeft.item
+ }
+ else
+ itemLeft.item.Navigation.rightItem = null
+ }
+ else if (itemRight) {
+ itemRight.item.Navigation.leftItem = null
+ }
+ }
+
+ function recoverFocus(_index) {
+ if (item === null) return
+
+ const controlLayout = repeater.Navigation.parentItem
+
+ if (!controlLayout || !controlLayout.visible)
+ return
+
+ if (_index === undefined)
+ _index = index
+
+ for (let i = 1; i <= Math.max(_index, repeater.count - (_index + 1)); ++i) {
+ if (i <= _index) {
+ const leftItem = repeater.itemAt(_index - i)
+
+ if (_focusIfFocusable(leftItem))
+ return
+ }
+
+ if (_index + i <= repeater.count - 1) {
+ const rightItem = repeater.itemAt(_index + i)
+
+ if (_focusIfFocusable(rightItem))
+ return
+ }
+ }
+
+ // focus to other alignment if focusable control
+ // in the same alignment is not found:
+ if (!!controlLayout.Navigation.rightItem) {
+ controlLayout.Navigation.defaultNavigationRight()
+ } else if (!!controlLayout.Navigation.leftItem) {
+ controlLayout.Navigation.defaultNavigationLeft()
+ } else if (controlLayout.altFocusAction) {
+ controlLayout.altFocusAction()
+ }
+ }
+
+ // Private
+
+ function _focusIfFocusable(_loader) {
+ if (!!_loader && !!_loader.item && _loader.item.focus) {
+ if (item.focusReason !== undefined)
+ _loader.item.forceActiveFocus(item.focusReason)
+ else {
+ console.warn("focusReason is not available in %1!".arg(item))
+ _loader.item.forceActiveFocus()
+ }
+ return true
+ } else {
+ return false
+ }
+ }
+ }
+}
=====================================
modules/gui/qt/player/qml/PlayerControlLayout.qml
=====================================
@@ -17,8 +17,10 @@
*****************************************************************************/
import QtQuick 2.12
+import QtQuick.Layouts 1.12
import org.videolan.vlc 0.1
+import org.videolan.compat 0.1
import "qrc:///style/"
import "qrc:///widgets/" as Widgets
@@ -33,7 +35,7 @@ FocusScope {
property real spacing: VLCStyle.margin_normal // spacing between controls
- property real layoutSpacing: VLCStyle.margin_xlarge // spacing between layouts (left, center, and right)
+ property real layoutSpacing: VLCStyle.margin_xxlarge // spacing between layouts (left, center, and right)
property int identifier: -1
@@ -49,10 +51,6 @@ FocusScope {
colorSet: ColorContext.Window
}
- // Private
-
- property int _minimumSpacing: layoutSpacing - spacing
-
// Signals
signal requestLockUnlockAutoHide(bool lock)
@@ -61,102 +59,120 @@ FocusScope {
// Settings
- // NOTE: We want a smaller ControlBar when the controls are pinned.
- implicitHeight: (MainCtx.pinVideoControls) ? VLCStyle.controlLayoutHeightPinned
- : VLCStyle.controlLayoutHeight
-
- // Events
-
- Component.onCompleted: {
- console.assert(identifier >= 0)
+ implicitWidth: loaderLeftRight.active ? loaderLeftRight.implicitWidth
+ : (loaderLeft.implicitWidth + loaderCenter.implicitWidth + loaderRight.implicitWidth)
- _updateLayout()
- }
+ implicitHeight: Math.max(loaderLeft.implicitHeight, loaderCenter.implicitHeight, loaderRight.implicitHeight)
- onWidthChanged: _updateLayout()
-
- // Functions
+ // Events
- function _updateLayout() {
- let item = loaderCenter.item
+ Component.onCompleted: console.assert(identifier >= 0)
- // NOTE: Sometimes this gets called before the item is loaded.
- if (item === null)
- return
+ // Children
- if (item.count) {
+ Loader {
+ id: loaderLeftRight
- loaderCenter.width = Math.min(loaderCenter.implicitWidth, width)
+ anchors.fill: parent
- loaderLeft.width = loaderCenter.x - _minimumSpacing
+ active: !loaderCenter.active &&
+ playerControlLayout.model &&
+ ((playerControlLayout.model.left && (playerControlLayout.model.left.count > 0)) ||
+ (playerControlLayout.model.right && (playerControlLayout.model.right.count > 0)))
- loaderRight.width = width - loaderCenter.x - loaderCenter.width - _minimumSpacing
+ focus: active
- } else if (loaderRight.item.count) {
+ sourceComponent: RowLayout {
+ spacing: playerControlLayout.spacing
- const implicitLeft = loaderLeft.implicitWidth
- const implicitRight = loaderRight.implicitWidth
+ focus: true
- const total = implicitLeft + implicitRight
+ // TODO: Qt >= 5.13 Use QConcatenateTablesProxyModel
+ // instead of multiple repeaters
- let size = total + _minimumSpacing
+ ControlRepeater {
+ id: leftRepeater
+ model: ControlListFilter {
+ sourceModel: playerControlLayout.model.left
- if (size > width) {
- size = width - _minimumSpacing
+ player: Player
+ ctx: MainCtx
+ }
- // NOTE: When both sizes are equals we expand on the left.
- if (implicitLeft >= implicitRight) {
+ Navigation.parentItem: playerControlLayout
+ Navigation.rightAction: function() {
+ const item = rightRepeater.itemAt(0)
+ if (item)
+ item.forceActiveFocus(Qt.TabFocusReason)
+ else
+ return false
+ }
- loaderRight.width = Math.round(size * (implicitRight / total))
+ availableWidth: loaderLeftRight.width
+ availableHeight: loaderLeftRight.height
+ }
- item = loaderRight.item
+ Item {
+ function containsVisibleItem(repeater) {
+ for (let i = 0; i < repeater.count; ++i) {
+ const item = repeater.itemAt(i)
- if (item === null)
- return
+ if (item && item.visible)
+ return true
+ }
- const contentWidth = item.contentWidth
+ return false
+ }
- // NOTE: We assign the remaining width based on the contentWidth.
- if (contentWidth)
- loaderLeft.width = width - contentWidth - _minimumSpacing
- else
- loaderLeft.width = width
- } else {
- loaderLeft.width = Math.round(size * (implicitLeft / total))
+ Layout.minimumWidth: (containsVisibleItem(leftRepeater) && containsVisibleItem(rightRepeater)) ? playerControlLayout.layoutSpacing
+ : 0
- item = loaderLeft.item
+ Layout.fillWidth: true
+ visible: true
+ }
- if (item === null)
- return
+ ControlRepeater {
+ id: rightRepeater
+ model: ControlListFilter {
+ sourceModel: playerControlLayout.model.right
- const contentWidth = item.contentWidth
+ player: Player
+ ctx: MainCtx
+ }
- // NOTE: We assign the remaining width based on the contentWidth.
- if (contentWidth)
- loaderRight.width = width - contentWidth - _minimumSpacing
+ Navigation.parentItem: playerControlLayout
+ Navigation.leftAction: function() {
+ const item = leftRepeater.itemAt(leftRepeater.count - 1)
+ if (item)
+ item.forceActiveFocus(Qt.BacktabFocusReason)
else
- loaderRight.width = width
+ return false
}
- } else {
- loaderLeft.width = implicitLeft
- loaderRight.width = implicitRight
+
+ availableWidth: loaderLeftRight.width
+ availableHeight: loaderLeftRight.height
}
- } else
- loaderLeft.width = width
+ }
}
- // Children
Loader {
id: loaderLeft
- anchors.left: parent.left
- anchors.top: parent.top
- anchors.bottom: parent.bottom
+ anchors {
+ right: loaderCenter.left
+ left: parent.left
+ top: parent.top
+ bottom: parent.bottom
+
+ // Spacing for the filler item acts as padding
+ rightMargin: layoutSpacing - spacing
+ }
- active: !!playerControlLayout.model && !!playerControlLayout.model.left
+ active: !!playerControlLayout.model && !!playerControlLayout.model.left && (playerControlLayout.model.left.count > 0) &&
+ !loaderLeftRight.active
- focus: true
+ focus: active
sourceComponent: ControlLayout {
model: ControlListFilter {
@@ -166,7 +182,7 @@ FocusScope {
ctx: MainCtx
}
- alignment: Qt.AlignLeft
+ alignment: (Qt.AlignVCenter | Qt.AlignLeft)
focus: true
@@ -175,10 +191,6 @@ FocusScope {
Navigation.parentItem: playerControlLayout
Navigation.rightItem: loaderCenter.item
- onImplicitWidthChanged: playerControlLayout._updateLayout()
-
- onCountChanged: playerControlLayout._updateLayout()
-
onRequestLockUnlockAutoHide: playerControlLayout.requestLockUnlockAutoHide(lock)
onMenuOpened: playerControlLayout.menuOpened(menu)
@@ -188,12 +200,37 @@ FocusScope {
Loader {
id: loaderCenter
- anchors.top: parent.top
- anchors.bottom: parent.bottom
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ top: parent.top
+ bottom: parent.bottom
+ }
- anchors.horizontalCenter: parent.horizontalCenter
+ // TODO: "ControlListFilter"'s count......
+ active: !!playerControlLayout.model && !!playerControlLayout.model.center && (playerControlLayout.model.center.count > 0)
- active: !!playerControlLayout.model && !!playerControlLayout.model.center
+ BindingCompat on width {
+ delayed: true
+ when: loaderCenter._componentCompleted
+ value: {
+ const item = loaderCenter.item
+
+ const minimumWidth = (item && item.Layout.minimumWidth > 0) ? item.Layout.minimumWidth : implicitWidth
+ const maximumWidth = (item && item.Layout.maximumWidth > 0) ? item.Layout.maximumWidth : implicitWidth
+
+ if ((loaderLeft.active && (loaderLeft.width > 0)) || (loaderRight.active && (loaderRight.width > 0))) {
+ return minimumWidth
+ } else {
+ return Math.min(loaderCenter.parent.width, maximumWidth)
+ }
+ }
+ }
+
+ property bool _componentCompleted: false
+
+ Component.onCompleted: {
+ _componentCompleted = true
+ }
sourceComponent: ControlLayout {
model: ControlListFilter {
@@ -211,10 +248,6 @@ FocusScope {
Navigation.leftItem: loaderLeft.item
Navigation.rightItem: loaderRight.item
- onImplicitWidthChanged: playerControlLayout._updateLayout()
-
- onCountChanged: playerControlLayout._updateLayout()
-
onRequestLockUnlockAutoHide: playerControlLayout.requestLockUnlockAutoHide(lock)
onMenuOpened: playerControlLayout.menuOpened(menu)
@@ -224,11 +257,18 @@ FocusScope {
Loader {
id: loaderRight
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.bottom: parent.bottom
+ anchors {
+ left: loaderCenter.right
+ right: parent.right
+ top: parent.top
+ bottom: parent.bottom
+
+ // Spacing for the filler item acts as padding
+ leftMargin: layoutSpacing - spacing
+ }
- active: !!playerControlLayout.model && !!playerControlLayout.model.right
+ active: !!playerControlLayout.model && !!playerControlLayout.model.right && (playerControlLayout.model.right.count > 0) &&
+ !loaderLeftRight.active
sourceComponent: ControlLayout {
model: ControlListFilter {
@@ -238,7 +278,7 @@ FocusScope {
ctx: MainCtx
}
- alignment: Qt.AlignRight
+ alignment: (Qt.AlignVCenter | Qt.AlignRight)
focus: true
@@ -247,10 +287,6 @@ FocusScope {
Navigation.parentItem: playerControlLayout
Navigation.leftItem: loaderCenter.item
- onImplicitWidthChanged: playerControlLayout._updateLayout()
-
- onCountChanged: playerControlLayout._updateLayout()
-
onRequestLockUnlockAutoHide: playerControlLayout.requestLockUnlockAutoHide(lock)
onMenuOpened: playerControlLayout.menuOpened(menu)
=====================================
modules/gui/qt/player/qml/controlbarcontrols/ArtworkInfoWidget.qml
=====================================
@@ -21,6 +21,7 @@ import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import org.videolan.vlc 0.1
+import org.videolan.compat 0.1
import "qrc:///widgets/" as Widgets
import "qrc:///style/"
@@ -32,16 +33,11 @@ AbstractButton {
property bool paintOnly: false
- readonly property real minimumWidth: coverRect.implicitWidth +
- + (leftPadding + rightPadding)
+ Layout.minimumWidth: height
- property int maximumHeight: _preferredHeight
+ implicitHeight: 0
- readonly property int preferredWidth: minimumWidth + contentItem.spacing * 2
- +
- Math.max(titleLabel.implicitWidth,
- artistLabel.implicitWidth,
- progressIndicator.implicitWidth)
+ property bool _keyPressed: false
readonly property ColorContext colorContext: ColorContext {
id: theme
@@ -52,10 +48,6 @@ AbstractButton {
hovered: root.hovered
}
- property int _preferredHeight: VLCStyle.dp(60, VLCStyle.scale)
-
- property bool _keyPressed: false
-
// Settings
text: I18n.qtr("Open player")
@@ -102,57 +94,51 @@ AbstractButton {
// Children
contentItem: RowLayout {
- spacing: infoColumn.visible ? VLCStyle.margin_xsmall : 0
+ spacing: VLCStyle.margin_xsmall
- Rectangle {
- id: coverRect
+ Image {
+ id: coverImage
- implicitWidth: implicitHeight
+ Layout.fillHeight: true
+ Layout.preferredWidth: root.height
- implicitHeight: Math.min(root._preferredHeight, root.maximumHeight)
+ sourceSize.width: root.height
- color: theme.bg.primary
-
- Widgets.DoubleShadow {
- anchors.centerIn: cover
- width: cover.paintedWidth
- height: cover.paintedHeight
- z: -1
+ source: {
+ if (!paintOnly && Player.artwork && Player.artwork.toString())
+ return Player.artwork
+ else
+ return VLCStyle.noArtAlbumCover
+ }
- primaryBlurRadius: VLCStyle.dp(3, VLCStyle.scale)
- primaryVerticalOffset: VLCStyle.dp(1, VLCStyle.scale)
+ fillMode: Image.PreserveAspectFit
- secondaryBlurRadius: VLCStyle.dp(14, VLCStyle.scale)
- secondaryVerticalOffset: VLCStyle.dp(6, VLCStyle.scale)
- }
+ asynchronous: true
- Widgets.ScaledImage {
- id: cover
+ Accessible.role: Accessible.Graphic
+ Accessible.name: I18n.qtr("Cover")
- anchors.fill: parent
+ ToolTip.visible: infoColumn.width < infoColumn.implicitWidth
+ && (root.hovered || root.visualFocus)
+ ToolTip.delay: VLCStyle.delayToolTipAppear
+ ToolTip.text: I18n.qtr("%1\n%2\n%3").arg(titleLabel.text)
+ .arg(artistLabel.text)
+ .arg(progressIndicator.text)
- source: {
- if (!paintOnly
- && Player.artwork
- && Player.artwork.toString())
- Player.artwork
- else
- VLCStyle.noArtAlbumCover
- }
+ Widgets.DoubleShadow {
+ anchors.centerIn: coverImage
+ anchors.alignWhenCentered: false
- fillMode: Image.PreserveAspectFit
+ implicitWidth: coverImage.paintedWidth
+ implicitHeight: coverImage.paintedHeight
- asynchronous: true
+ z: -1
- Accessible.role: Accessible.Graphic
- Accessible.name: I18n.qtr("Cover")
+ primaryBlurRadius: VLCStyle.dp(3, VLCStyle.scale)
+ primaryVerticalOffset: VLCStyle.dp(1, VLCStyle.scale)
- ToolTip.visible: infoColumn.width < infoColumn.implicitWidth
- && (root.hovered || root.visualFocus)
- ToolTip.delay: VLCStyle.delayToolTipAppear
- ToolTip.text: I18n.qtr("%1\n%2\n%3").arg(titleLabel.text)
- .arg(artistLabel.text)
- .arg(progressIndicator.text)
+ secondaryBlurRadius: VLCStyle.dp(14, VLCStyle.scale)
+ secondaryVerticalOffset: VLCStyle.dp(6, VLCStyle.scale)
}
}
@@ -160,15 +146,19 @@ AbstractButton {
id: infoColumn
Layout.fillWidth: true
- Layout.preferredHeight: coverRect.height
+ Layout.fillHeight: true
Layout.minimumWidth: 0.1 // FIXME: Qt layout bug
+ spacing: 0
+
Widgets.MenuLabel {
id: titleLabel
Layout.fillWidth: true
Layout.fillHeight: true
+ visible: text.length > 0
+
text: {
if (paintOnly)
I18n.qtr("Title")
@@ -184,12 +174,18 @@ AbstractButton {
Layout.fillWidth: true
Layout.fillHeight: true
+ BindingCompat on visible {
+ delayed: (MainCtx.qtVersion() < MainCtx.qtVersionCheck(5, 15, 8))
+ value: (infoColumn.height > infoColumn.implicitHeight) && (artistLabel.text.length > 0)
+ }
+
text: {
if (paintOnly)
I18n.qtr("Artist")
else
Player.artist
}
+
color: theme.fg.secondary
}
@@ -199,7 +195,7 @@ AbstractButton {
Layout.fillWidth: true
Layout.fillHeight: true
- visible: (infoColumn.height >= root._preferredHeight)
+ visible: text.length > 0
text: {
if (paintOnly)
=====================================
modules/gui/qt/player/qml/controlbarcontrols/ExpandingSpacerWidget.qml
=====================================
@@ -17,6 +17,7 @@
*****************************************************************************/
import QtQuick 2.12
import QtQuick.Templates 2.12 as T
+import QtQuick.Layouts 1.12
import org.videolan.vlc 0.1
@@ -27,13 +28,13 @@ import "qrc:///style/"
Item {
enabled: false
- implicitWidth: paintOnly ? VLCStyle.widthExtendedSpacer : Number.MAX_VALUE
+ implicitWidth: VLCStyle.widthExtendedSpacer
implicitHeight: VLCStyle.icon_toolbar
property bool paintOnly: false
property alias spacetextExt: spacetext
- readonly property real minimumWidth: 0
+ Layout.minimumWidth: 1
readonly property ColorContext colorContext: ColorContext {
id: theme
=====================================
modules/gui/qt/player/qml/controlbarcontrols/PlayButton.qml
=====================================
@@ -30,8 +30,6 @@ T.Control {
// Properties
- property int maximumHeight: VLCStyle.icon_medium
-
property bool paintOnly: false
readonly property ColorContext colorContext: ColorContext {
@@ -53,9 +51,8 @@ T.Control {
// Settings
- implicitWidth: implicitHeight
-
- implicitHeight: Math.min(VLCStyle.icon_medium, maximumHeight)
+ implicitWidth: implicitBackgroundWidth + leftInset + rightInset
+ implicitHeight: implicitBackgroundHeight + topInset + bottomInset
scale: (_keyOkPressed || (mouseArea.pressed && cursorInside)) ? 0.95
: 1.00
@@ -230,6 +227,9 @@ T.Control {
}
background: Item {
+ implicitWidth: height
+ implicitHeight: VLCStyle.icon_medium
+
// TODO: Qt >= 5.15 use inline component for the drop shadows
Widgets.DropShadowImage {
id: hoverShadow
=====================================
modules/gui/qt/vlc.qrc
=====================================
@@ -318,6 +318,7 @@
<file alias="PIPPlayer.qml">player/qml/PIPPlayer.qml</file>
<file alias="PlayerControlLayout.qml">player/qml/PlayerControlLayout.qml</file>
<file alias="ControlLayout.qml">player/qml/ControlLayout.qml</file>
+ <file alias="ControlRepeater.qml">player/qml/ControlRepeater.qml</file>
<file alias="PlaybackSpeed.qml">player/qml/PlaybackSpeed.qml</file>
<file alias="PlayerPlaylistVisibilityFSM.qml">player/qml/PlayerPlaylistVisibilityFSM.qml</file>
<file alias="PlayerBlurredBackground.qml">player/qml/PlayerBlurredBackground.qml</file>
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/10a4528c1ef62d3703172c94415eff760acd7584...d4d2c619c0da284fb272b3fc5a57ab3c965b25a4
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/10a4528c1ef62d3703172c94415eff760acd7584...d4d2c619c0da284fb272b3fc5a57ab3c965b25a4
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list