[vlc-commits] [Git][videolan/vlc][master] 7 commits: qml: expose the view in `PlaylistPane`
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Fri Oct 2 15:57:52 UTC 2026
Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
671c7221 by Fatih Uzunoglu at 2026-10-02T17:46:15+02:00
qml: expose the view in `PlaylistPane`
- - - - -
4c5e19ba by Fatih Uzunoglu at 2026-10-02T17:46:15+02:00
qml: introduce exported component `PlaylistToggleButton` in `PlaylistPane`
- - - - -
c85bc32f by Fatih Uzunoglu at 2026-10-02T17:46:15+02:00
qml: use `PlaylistToggleButton` in `LocalTopbar`
- - - - -
45817987 by Fatih Uzunoglu at 2026-10-02T17:46:15+02:00
qml: use `PlaylistToggleButton` in `TopBar`
- - - - -
2d1bdb36 by Fatih Uzunoglu at 2026-10-02T17:46:15+02:00
qml: enable d&d functionality in playlist button in `TopBar`
This was already enabled in main display's top bar, but now
we can do the same in player's top bar without duplication
since we reuse the exported component in both places now.
- - - - -
7db59655 by Fatih Uzunoglu at 2026-10-02T17:46:15+02:00
qml: get rid of playlist tool bar in `PlaylistPane`
We retain these two buttons in the playlist pane:
- Sort button
- Search/filter button
These buttons are available in default profile
of player control bar:
- Shuffle toggle button.
- Loop toggle button.
This button is removed, its function is
solely delegated to the context menu now:
- Clear button.
- - - - -
b5eb7538 by Fatih Uzunoglu at 2026-10-02T17:46:15+02:00
qml: get rid of obsolete `PlaylistToolbar`
- - - - -
9 changed files:
- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/qml/LocalTopbar.qml
- modules/gui/qt/maininterface/qml/MainDisplay.qml
- modules/gui/qt/meson.build
- modules/gui/qt/player/qml/Player.qml
- modules/gui/qt/player/qml/TopBar.qml
- modules/gui/qt/playlist/qml/PlaylistPane.qml
- − modules/gui/qt/playlist/qml/PlaylistToolbar.qml
- po/POTFILES.in
Changes:
=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -1257,7 +1257,6 @@ libqml_module_playlist_a_CPPFLAGS = $(libqt_plugin_la_CPPFLAGS)
libqml_module_playlist_a_QML = \
playlist/qml/PlaylistDelegate.qml \
playlist/qml/PlaylistPane.qml \
- playlist/qml/PlaylistToolbar.qml \
playlist/qml/PlaylistDetachedWindow.qml
libqml_module_playlist_a_Singleton_QML =
libqml_module_playlist_a_SOURCES = $(QML_MODULE_playlist_SRC)
=====================================
modules/gui/qt/maininterface/qml/LocalTopbar.qml
=====================================
@@ -184,72 +184,16 @@ T.ToolBar {
Navigation.parentItem: root
Navigation.leftItem: navigationButtons
- Widgets.IconToolButton {
+ PlaylistPane.PlaylistToggleButton {
id: playlistBtn
- font.pixelSize: VLCStyle.icon_banner
- text: VLCIcons.playlist
- description: qsTr("Playlist")
-
- AccessibleCompat.id: "playqueueToggle"
-
- width: VLCStyle.bannerButton_width
- height: VLCStyle.bannerButton_height
- //highlighted: MainCtx.playlistVisible
+ plListView: root.plListView
Navigation.parentItem: playqueueButtonsTop
Navigation.rightItem: menuBtn
Navigation.leftItem: historyBack
onClicked: root.togglePlayqueueVisibility()
-
- DropArea {
- anchors.fill: parent
-
- onContainsDragChanged: {
- if (containsDrag) {
- _timer.restart()
-
- if (plListView)
- MainCtx.setCursor(Qt.DragCopyCursor)
- } else {
- _timer.stop()
-
- if (plListView)
- MainCtx.restoreCursor()
- }
- }
-
- onEntered: (drag) => {
- if (root.plListView) {
- console.assert(root.plListView.isDropAcceptableFunc)
- console.assert(root.plListView.model)
- if (root.plListView.isDropAcceptableFunc(drag, root.plListView.model.count)) {
- drag.accept()
- } else {
- drag.accepted = false
- }
- } else {
- drag.accepted = false
- }
- }
-
- onDropped: (drop) => {
- if (root.plListView) {
- console.assert(plListView.acceptDropFunc)
- root.plListView.acceptDropFunc(root.plListView.model.count, drop)
- }
- }
-
- Timer {
- id: _timer
- interval: VLCStyle.duration_humanMoment
-
- onTriggered: {
- MainCtx.playqueuePanel.visible = true
- }
- }
- }
}
Widgets.IconToolButton {
=====================================
modules/gui/qt/maininterface/qml/MainDisplay.qml
=====================================
@@ -757,11 +757,13 @@ FocusScope {
leftPadding: playqueueResizeHandle.visualBorder.width
rightPadding: VLCStyle.applicationHorizontalMargin
- bottomPadding: VLCStyle.margin_normal + Math.max(VLCStyle.applicationVerticalMargin - g_mainDisplay.displayMargin, 0)
+ bottomPadding: Math.max(VLCStyle.applicationVerticalMargin - g_mainDisplay.displayMargin, 0)
topPadding: VLCStyle.layoutTitle_top_padding
useAcrylic: !VLCStyle.isScreenSmall
+ view.fadingEdge.pixelAlignedForDPR: !miniPlayer.visible
+
Navigation.parentItem: g_mainDisplay
Navigation.upItem: localTopbar
Navigation.downItem: loaderUpdatePane
=====================================
modules/gui/qt/meson.build
=====================================
@@ -820,7 +820,6 @@ qml_modules += {
'sources': files(
'playlist/qml/PlaylistDelegate.qml',
'playlist/qml/PlaylistPane.qml',
- 'playlist/qml/PlaylistToolbar.qml',
'playlist/qml/PlaylistDetachedWindow.qml',
),
}
=====================================
modules/gui/qt/player/qml/Player.qml
=====================================
@@ -963,6 +963,15 @@ FocusScope {
showToolbar: MainCtx.hasToolbarMenu && (MainCtx.intfMainWindow.visibility !== Window.FullScreen)
playlistVisible: playlistVisibility.isPlaylistVisible
+ plListView: {
+ if (playlistpopup.active)
+ return playlistpopup.item
+ else if (playlistWindowLoader?.status === Loader.Ready)
+ return playlistWindowLoader.item.playlistView
+ else
+ return null
+ }
+
Navigation.parentItem: rootPlayer
Navigation.downItem: {
if (playlistVisibility.isPlaylistVisible)
@@ -1108,11 +1117,14 @@ FocusScope {
// NOTE: We increase the padding accordingly to avoid overlapping the TopBar.
return topBar.reservedHeight
}
+ bottomPadding: 0
background: Rectangle {
color: windowTheme.bg.primary.alpha(0.8)
}
+ view.fadingEdge.pixelAlignedForDPR: !controlBar.visible
+
Navigation.parentItem: rootPlayer
Navigation.upItem: topBar
Navigation.downItem: Player.isInteractive ? toggleControlBarButton : controlBar
=====================================
modules/gui/qt/player/qml/TopBar.qml
=====================================
@@ -26,6 +26,7 @@ import QtQuick.Window
import VLC.MainInterface
import VLC.Style
import VLC.PlayerControls
+import VLC.Playlist
import VLC.Widgets as Widgets
import VLC.Menus as Menus
import VLC.Util
@@ -37,6 +38,10 @@ FocusScope{
required property int textWidth
+ // For now, used for d&d functionality
+ // Not strictly necessary to set
+ property Item plListView
+
property int reservedHeight: 0
property int topMargin: 0
@@ -475,7 +480,7 @@ FocusScope{
}
}
- Widgets.IconToolButton {
+ PlaylistPane.PlaylistToggleButton {
id: playlistButton
anchors.verticalCenter: parent.verticalCenter
@@ -491,6 +496,8 @@ FocusScope{
width: VLCStyle.bannerButton_width
height: VLCStyle.bannerButton_height
+ plListView: root.plListView
+
Navigation.parentItem: root
Navigation.leftItem: menuSelector.visible ? menuSelector : backBtn
=====================================
modules/gui/qt/playlist/qml/PlaylistPane.qml
=====================================
@@ -16,6 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
import QtQuick
+import QtQuick.Window
import QtQuick.Controls
import QtQuick.Templates as T
import QtQuick.Layouts
@@ -52,6 +53,8 @@ T.Pane {
property alias isDropAcceptableFunc: listView.isDropAcceptableFunc
property alias acceptDropFunc: listView.acceptDropFunc
+ property alias view: listView
+
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
@@ -113,22 +116,115 @@ T.Pane {
contentItem: ColumnLayout {
spacing: VLCStyle.margin_xxsmall
- Layout.minimumWidth: noContentInfoColumn.implicitWidth
+ Layout.minimumWidth: Math.min(Math.max(noContentInfoColumn.implicitWidth,
+ titleRowLayout.implicitWidth ),
+ /* Minimum width should not be too large, we rely on elision otherwise: */
+ Window.width / 3) + (headerColumn.Layout.leftMargin + headerColumn.Layout.rightMargin)
readonly property ListView listView: listView
Column {
+ id: headerColumn
+
Layout.fillHeight: false
Layout.fillWidth: true
Layout.leftMargin: VLCStyle.margin_normal
+ Layout.rightMargin: VLCStyle.margin_normal
spacing: VLCStyle.margin_xxxsmall
- Widgets.SubtitleLabel {
- text: qsTr("Play Queue")
- color: theme.fg.primary
- font.weight: Font.Bold
- font.pixelSize: VLCStyle.dp(24, VLCStyle.scale)
+ RowLayout {
+ id: titleRowLayout
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ spacing: VLCStyle.margin_normal
+
+ Widgets.SubtitleLabel {
+ id: titleLabel
+
+ Layout.fillWidth: true
+
+ text: qsTr("Play Queue")
+ color: theme.fg.primary
+ font.weight: Font.Bold
+ font.pixelSize: VLCStyle.dp(24, VLCStyle.scale)
+ }
+
+ Widgets.SortControl {
+ id: sort
+
+ font.pixelSize: VLCStyle.icon_banner
+
+ description : qsTr("Sort")
+
+ AccessibleCompat.id: "playqueueSort"
+
+ enabled: MainPlaylistController.count > 1
+
+ checked: MainPlaylistController.sortKey !== PlaylistController.SORT_KEY_NONE
+
+ popupAbove: false
+
+ model: MainPlaylistController.sortKeyTitleList
+
+ onSortSelected: key => {
+ MainPlaylistController.sortKey = key
+ }
+
+ onSortOrderSelected: type => {
+ if (type === Qt.AscendingOrder)
+ MainPlaylistController.sortOrder = PlaylistController.SORT_ORDER_ASC
+ else if (type === Qt.DescendingOrder)
+ MainPlaylistController.sortOrder = PlaylistController.SORT_ORDER_DESC
+
+ MainPlaylistController.sort()
+ }
+
+ sortOrder: {
+ if (MainPlaylistController.sortOrder === PlaylistController.SORT_ORDER_ASC) {
+ Qt.AscendingOrder
+ }
+ else if (MainPlaylistController.sortOrder === PlaylistController.SORT_ORDER_DESC) {
+ Qt.DescendingOrder
+ }
+ }
+
+ sortKey: MainPlaylistController.sortKey
+
+ Navigation.parentItem: root
+ Navigation.rightItem: searchBox
+ Navigation.downItem: listView
+ }
+
+ Widgets.SearchBox {
+ id: searchBox
+
+ enabled: MainPlaylistController.count > 1
+
+ toggleButton.font.pixelSize: VLCStyle.icon_banner
+
+ popBelow: true
+
+ displayRegexToggleButton: true
+ displayCaseSensitiveToggleButton: true
+
+ popup.width: Math.max(popup.implicitWidth, root.contentItem?.width * 0.6)
+ popup.topPadding: VLCStyle.margin_xxsmall
+
+ Navigation.parentItem: root
+ Navigation.leftItem: sort
+ Navigation.downItem: listView
+
+ Connections {
+ target: contextMenu
+
+ function onDiscardedFilteredOutItems() {
+ searchBox.retract()
+ }
+ }
+ }
}
Widgets.CaptionLabel {
@@ -246,9 +342,9 @@ T.Pane {
model: proxyModel ?? root.model
onWidthChanged: {
- if (toolbar.searchBox.expanded) {
- if (width < toolbar.searchBox.textField.width)
- toolbar.searchBox.retract()
+ if (searchBox.expanded) {
+ if (width < searchBox.textField.width)
+ searchBox.retract()
}
}
@@ -261,10 +357,10 @@ T.Pane {
proxyModel = proxyModelComponent.createObject(listView)
}
- if (toolbar.searchBox.regexButtonToggled)
- proxyModel.setFilterRegularExpression(toolbar.searchBox.searchPattern)
+ if (searchBox.regexButtonToggled)
+ proxyModel.setFilterRegularExpression(searchBox.searchPattern)
else
- proxyModel.setFilterFixedString(toolbar.searchBox.searchPattern)
+ proxyModel.setFilterFixedString(searchBox.searchPattern)
}
Component {
@@ -275,8 +371,8 @@ T.Pane {
sourceModel: root.model
- filterCaseSensitivity: toolbar.searchBox.caseSensitiveButtonToggled ? Qt.CaseSensitive
- : Qt.CaseInsensitive
+ filterCaseSensitivity: searchBox.caseSensitiveButtonToggled ? Qt.CaseSensitive
+ : Qt.CaseInsensitive
}
}
@@ -384,8 +480,8 @@ T.Pane {
}
})
- toolbar.searchBox.searchPatternChanged.connect(listView, listView.adjustFiltering)
- toolbar.searchBox.regexButtonToggledChanged.connect(listView, listView.adjustFiltering)
+ searchBox.searchPatternChanged.connect(listView, listView.adjustFiltering)
+ searchBox.regexButtonToggledChanged.connect(listView, listView.adjustFiltering)
}
Connections {
@@ -444,6 +540,7 @@ T.Pane {
}
Navigation.parentItem: root
+ Navigation.upItem: sort
onActionAtIndex: (index) => {
if (index < 0)
@@ -516,30 +613,77 @@ T.Pane {
}
}
}
+ }
- PlaylistToolbar {
- id: toolbar
+ Keys.priority: Keys.AfterItem
+ Keys.forwardTo: listView
+ Keys.onPressed: (event) => root.Navigation.defaultKeyAction(event)
- Layout.preferredHeight: VLCStyle.heightBar_normal
- Layout.fillHeight: false
- Layout.fillWidth: true
- Layout.leftMargin: VLCStyle.margin_normal
- Layout.rightMargin: VLCStyle.margin_normal
+ component PlaylistToggleButton : Widgets.IconToolButton {
+ id: playlistBtn
- searchBox.displayRegexToggleButton: true
- searchBox.displayCaseSensitiveToggleButton: true
+ focus: true
- Connections {
- target: contextMenu
+ font.pixelSize: VLCStyle.icon_banner
+ text: VLCIcons.playlist
+ description: qsTr("Play queue")
+
+ AccessibleCompat.id: "playqueueToggle"
+
+ width: VLCStyle.bannerButton_width
+ height: VLCStyle.bannerButton_height
+ //highlighted: MainCtx.playlistVisible
- function onDiscardedFilteredOutItems() {
- toolbar.searchBox.retract()
+ property Item plListView
+
+ DropArea {
+ anchors.fill: parent
+
+ onContainsDragChanged: {
+ if (containsDrag) {
+ _timer.restart()
+
+ if (playlistBtn.plListView)
+ MainCtx.setCursor(Qt.DragCopyCursor)
+ } else {
+ _timer.stop()
+
+ if (playlistBtn.plListView)
+ MainCtx.restoreCursor()
+ }
+ }
+
+ onEntered: (drag) => {
+ const plListView = playlistBtn.plListView
+ if (plListView) {
+ console.assert(plListView.isDropAcceptableFunc)
+ console.assert(plListView.model)
+ if (plListView.isDropAcceptableFunc(drag, plListView.model.count)) {
+ drag.accept()
+ } else {
+ drag.accepted = false
+ }
+ } else {
+ drag.accepted = false
+ }
+ }
+
+ onDropped: (drop) => {
+ const plListView = playlistBtn.plListView
+ if (plListView) {
+ console.assert(plListView.acceptDropFunc)
+ plListView.acceptDropFunc(plListView.model.count, drop)
+ }
+ }
+
+ Timer {
+ id: _timer
+ interval: VLCStyle.duration_humanMoment
+
+ onTriggered: {
+ MainCtx.playqueuePanel.visible = true
}
}
}
}
-
- Keys.priority: Keys.AfterItem
- Keys.forwardTo: listView
- Keys.onPressed: (event) => root.Navigation.defaultKeyAction(event)
}
=====================================
modules/gui/qt/playlist/qml/PlaylistToolbar.qml deleted
=====================================
@@ -1,190 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2019 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
-import QtQuick.Controls
-import QtQuick.Layouts
-
-
-import VLC.Widgets as Widgets
-import VLC.Style
-import VLC.Playlist
-import VLC.Util
-
-RowLayout {
- id: rowLayout
-
- readonly property ColorContext colorContext: ColorContext {
- colorSet: ColorContext.Window
- }
-
- spacing: VLCStyle.margin_normal
-
- property alias searchBox: searchBox
-
- Accessible.role: Accessible.ToolBar
-
- Item {
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- implicitWidth: loop.implicitWidth
- implicitHeight: loop.implicitHeight
-
- Widgets.IconToolButton {
- id: loop
-
- anchors.centerIn: parent
-
- font.pixelSize: VLCStyle.icon_playlist
-
- description: qsTr("Loop")
-
- AccessibleCompat.id: "playqueueLoop"
-
- text: (MainPlaylistController.repeatMode === PlaylistController.PLAYBACK_REPEAT_CURRENT)
- ? VLCIcons.repeat_one
- : VLCIcons.repeat_all
- checked: MainPlaylistController.repeatMode !== PlaylistController.PLAYBACK_REPEAT_NONE
- onClicked: MainPlaylistController.toggleRepeatMode()
- }
- }
-
-
- Item {
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- implicitWidth: shuffle.implicitWidth
- implicitHeight: shuffle.implicitHeight
-
- Widgets.IconToolButton {
- id: shuffle
-
- anchors.centerIn: parent
-
- checked: MainPlaylistController.random
- font.pixelSize: VLCStyle.icon_playlist
-
- description: qsTr("Shuffle")
-
- AccessibleCompat.id: "playqueueShuffle"
-
- text: VLCIcons.shuffle
- onClicked: MainPlaylistController.toggleRandom()
- }
- }
-
- Item {
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- implicitWidth: sort.implicitWidth
- implicitHeight: sort.implicitHeight
-
- Widgets.SortControl {
- id: sort
-
- anchors.centerIn: parent
-
- font.pixelSize: VLCStyle.icon_playlist
-
- description : qsTr("Sort")
-
- AccessibleCompat.id: "playqueueSort"
-
- enabled: MainPlaylistController.count > 1
-
- checked: MainPlaylistController.sortKey !== PlaylistController.SORT_KEY_NONE
-
- popupAbove: true
-
- model: MainPlaylistController.sortKeyTitleList
-
- onSortSelected: key => {
- MainPlaylistController.sortKey = key
- }
-
- onSortOrderSelected: type => {
- if (type === Qt.AscendingOrder)
- MainPlaylistController.sortOrder = PlaylistController.SORT_ORDER_ASC
- else if (type === Qt.DescendingOrder)
- MainPlaylistController.sortOrder = PlaylistController.SORT_ORDER_DESC
-
- MainPlaylistController.sort()
- }
-
- sortOrder: {
- if (MainPlaylistController.sortOrder === PlaylistController.SORT_ORDER_ASC) {
- Qt.AscendingOrder
- }
- else if (MainPlaylistController.sortOrder === PlaylistController.SORT_ORDER_DESC) {
- Qt.DescendingOrder
- }
- }
-
- sortKey: MainPlaylistController.sortKey
- }
- }
-
- Item {
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- implicitWidth: clear.implicitWidth
- implicitHeight: clear.implicitHeight
-
- Widgets.IconToolButton {
- id: clear
-
- anchors.centerIn: parent
-
- font.pixelSize: VLCStyle.icon_playlist
- enabled: !MainPlaylistController.empty
-
- description: qsTr("Clear play queue")
-
- AccessibleCompat.id: "playqueueClearPlayqueue"
-
- text: VLCIcons.playlist_clear
- onClicked: MainPlaylistController.clear()
- }
- }
-
- Item {
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- implicitWidth: searchBox.implicitWidth
- implicitHeight: searchBox.implicitHeight
-
- Widgets.SearchBox {
- id: searchBox
-
- anchors.centerIn: parent
-
- enabled: MainPlaylistController.count > 1
-
- toggleButton.font.pixelSize: VLCStyle.icon_playlist
-
- popBelow: false
-
- popup.width: Math.max(popup.implicitWidth, rowLayout.width * 0.6)
- popup.bottomPadding: VLCStyle.margin_xxsmall
- }
- }
-}
=====================================
po/POTFILES.in
=====================================
@@ -886,7 +886,6 @@ modules/gui/qt/player/qml/controlbarcontrols/VolumeWidget.qml
modules/gui/qt/playlist/qml/PlaylistDelegate.qml
modules/gui/qt/playlist/qml/PlaylistDetachedWindow.qml
modules/gui/qt/playlist/qml/PlaylistPane.qml
-modules/gui/qt/playlist/qml/PlaylistToolbar.qml
modules/gui/qt/qt.cpp
modules/gui/qt/qt.hpp
modules/gui/qt/util/color_scheme_model.cpp
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/5cb59f573667fc7f5f5e69117ce316b9d8562676...b5eb753828de2bbec9a80bfee829b5d124e99043
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/5cb59f573667fc7f5f5e69117ce316b9d8562676...b5eb753828de2bbec9a80bfee829b5d124e99043
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list