[vlc-devel] [RFC 72/82] qml: provide a widget to display the play queue
Pierre Lamot
pierre at videolabs.io
Fri Feb 1 14:02:16 CET 2019
this support key navigation and edition
---
modules/gui/qt/Makefile.am | 4 +
modules/gui/qt/qml/playlist/PLItem.qml | 158 +++++++++++
modules/gui/qt/qml/playlist/PLItemFooter.qml | 55 ++++
.../gui/qt/qml/playlist/PlaylistListView.qml | 263 ++++++++++++++++++
modules/gui/qt/qml/playlist/PlaylistMenu.qml | 249 +++++++++++++++++
modules/gui/qt/vlc.qrc | 6 +
6 files changed, 735 insertions(+)
create mode 100644 modules/gui/qt/qml/playlist/PLItem.qml
create mode 100644 modules/gui/qt/qml/playlist/PLItemFooter.qml
create mode 100644 modules/gui/qt/qml/playlist/PlaylistListView.qml
create mode 100644 modules/gui/qt/qml/playlist/PlaylistMenu.qml
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index aecc08abcf..bd4905ba91 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -545,6 +545,10 @@ libqt_plugin_la_RES = \
gui/qt/qml/utils/SelectableDelegateModel.qml \
gui/qt/qml/utils/ComboBoxExt.qml \
gui/qt/qml/utils/StackViewExt.qml \
+ gui/qt/qml/playlist/PlaylistListView.qml \
+ gui/qt/qml/playlist/PLItem.qml \
+ gui/qt/qml/playlist/PLItemFooter.qml \
+ gui/qt/qml/playlist/PlaylistMenu.qml \
gui/qt/qml/style/qmldir \
gui/qt/qml/style/VLCIcons.qml \
gui/qt/qml/style/VLCStyle.qml \
diff --git a/modules/gui/qt/qml/playlist/PLItem.qml b/modules/gui/qt/qml/playlist/PLItem.qml
new file mode 100644
index 0000000000..8d139bcd58
--- /dev/null
+++ b/modules/gui/qt/qml/playlist/PLItem.qml
@@ -0,0 +1,158 @@
+/*****************************************************************************
+ * 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 2.11
+import QtQuick.Controls 2.4
+import QtQuick.Layouts 1.3
+
+
+import "qrc:///utils/" as Utils
+import "qrc:///style/"
+
+
+Rectangle {
+ id: root
+
+ signal itemClicked(int keys, int modifier)
+ signal itemDoubleClicked(int keys, int modifier)
+ property alias hovered: mouse.containsMouse
+
+ property var dragitem: null
+ signal dropedMovedAt(int target, var drop)
+
+
+ // Should the cover be displayed
+ //property alias showCover: cover.visible
+
+ // This item will become the parent of the dragged item during the drag operation
+ //property alias draggedItemParent: draggable_item.draggedItemParent
+
+ height: Math.max( VLCStyle.fontHeight_normal, VLCStyle.icon_normal )
+
+ property bool dropVisible: false
+
+
+ Rectangle {
+ width: parent.width
+ height: 2
+ anchors.top: parent.top
+ antialiasing: true
+ visible: dropVisible
+ color: VLCStyle.colors.accent
+ }
+
+ MouseArea {
+ id: mouse
+ anchors.fill: parent
+ hoverEnabled: true
+
+
+ onClicked:{
+ root.itemClicked(mouse.buttons, mouse.modifiers);
+ }
+ onDoubleClicked: root.itemDoubleClicked(mouse.buttons, mouse.modifiers);
+
+ drag.target: dragItem
+
+ property bool hold: false
+ onPositionChanged: {
+ if (hold)
+ dragItem.visible = true
+ }
+ onPressed: {
+ hold = true
+ var pos = this.mapToGlobal( mouseX, mouseY)
+ dragItem.updatePos(pos.x, pos.y)
+ }
+ onReleased: {
+ if (dragItem.visible)
+ dragItem.Drag.drop()
+ dragItem.visible = false
+ hold = false
+ }
+
+ RowLayout {
+ id: content
+ anchors.fill: parent
+
+ /* Cover of the associated album */
+ Image {
+ id: cover
+
+ Layout.preferredHeight: VLCStyle.icon_normal
+ Layout.preferredWidth: VLCStyle.icon_normal
+
+ fillMode: Image.PreserveAspectFit
+ source: (model.artwork && model.artwork.toString()) ? model.artwork : VLCStyle.noArtCover
+ }
+
+ Image {
+ id: isVisible
+ visible: model.isCurrent
+ Layout.preferredHeight: VLCStyle.icon_small
+ Layout.preferredWidth: VLCStyle.icon_small
+ source: "qrc:///toolbar/play_b.svg"
+ }
+
+ Rectangle {
+ id: bg
+
+ Layout.fillWidth: true
+ Layout.alignment: Layout.verticalCenter | Layout.left
+
+ height: VLCStyle.fontHeight_normal
+
+ color: "transparent"
+
+ /* Title/name of the item */
+ Text {
+ id: textInfo
+
+ x: VLCStyle.margin_small
+ font.pixelSize: VLCStyle.fontSize_normal
+
+ text: model.title
+ color: VLCStyle.colors.text
+ }
+
+ Text {
+ id: textDuration
+
+ anchors.right: parent.right
+ font.pixelSize: VLCStyle.fontSize_normal
+
+ text: model.duration
+ color: VLCStyle.colors.text
+ }
+ }
+ }
+
+ DropArea {
+ anchors { fill: parent }
+ onEntered: {
+ dropVisible = true
+ return true
+ }
+ onExited: dropVisible = false
+ onDropped: {
+ root.dropedMovedAt(model.index, drop)
+ dropVisible = false
+ }
+ }
+ }
+}
diff --git a/modules/gui/qt/qml/playlist/PLItemFooter.qml b/modules/gui/qt/qml/playlist/PLItemFooter.qml
new file mode 100644
index 0000000000..f4f89a84d4
--- /dev/null
+++ b/modules/gui/qt/qml/playlist/PLItemFooter.qml
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * 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 2.11
+
+import "qrc:///style/"
+
+Item {
+ id: foot
+ property bool _dropVisible: false
+
+ width: parent.width
+ height: Math.max(VLCStyle.icon_normal, view.height - y)
+
+ Rectangle {
+ width: parent.width
+ anchors.top: parent.top
+ antialiasing: true
+ height: 2
+ visible: foot._dropVisible
+ color: VLCStyle.colors.accent
+ }
+
+ DropArea {
+ anchors { fill: parent }
+ onEntered: {
+ foot._dropVisible = true
+ return true
+ }
+ onExited: foot._dropVisible = false
+ onDropped: {
+ if (drop.hasUrls) {
+ console.log("add urls", drop.urls)
+ delegateModel.onDropUrlAtEnd(drop.urls)
+ } else {
+ delegateModel.onDropMovedAtEnd()
+ }
+ foot._dropVisible = false
+ }
+ }
+}
diff --git a/modules/gui/qt/qml/playlist/PlaylistListView.qml b/modules/gui/qt/qml/playlist/PlaylistListView.qml
new file mode 100644
index 0000000000..799b2072f3
--- /dev/null
+++ b/modules/gui/qt/qml/playlist/PlaylistListView.qml
@@ -0,0 +1,263 @@
+/*****************************************************************************
+ * 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 2.11
+import QtQuick.Controls 2.4
+import QtQml.Models 2.2
+
+import org.videolan.medialib 0.1
+import org.videolan.vlc 0.1
+
+import "qrc:///utils/" as Utils
+import "qrc:///style/"
+
+Utils.NavigableFocusScope {
+ id: root
+
+ property var plmodel: PlaylistListModel {
+ playlistId: mainctx.playlist
+ }
+
+
+ PlaylistControlerModel {
+ id: plControler
+ playlistPtr: mainctx.playlist
+ }
+
+ //label for DnD
+ Utils.DNDLabel {
+ id: dragItem
+ text: qsTr("%1 tracks selected").arg(delegateModel.selectedGroup.count)
+ }
+
+
+ /* popup side menu allowing to perform group action */
+ PlaylistMenu {
+ id: overlay
+
+ anchors.verticalCenter: root.verticalCenter
+ anchors.right: view.right
+ z: 2
+
+ onMenuExit:{
+ delegateModel.mode = "normal"
+ view.focus = true
+ }
+ onClear: delegateModel.onDelete()
+ onPlay: delegateModel.onPlay()
+ onSelectionMode: {
+ delegateModel.mode = selectionMode ? "select" : "normal"
+ view.focus = true
+ }
+ onMoveMode: {
+ delegateModel.mode = moveMode ? "move" : "normal"
+ view.focus = true
+ }
+ }
+
+ //model
+
+ Utils.SelectableDelegateModel {
+ id: delegateModel
+ model: root.plmodel
+
+ property string mode: "normal"
+
+ delegate: Package {
+ id: element
+
+ PLItem {
+ id: plitem
+ Package.name: "list"
+ width: root.width
+ color: VLCStyle.colors.getBgColor(element.DelegateModel.inSelected, plitem.hovered, plitem.activeFocus)
+
+ dragitem: dragItem
+
+ onItemClicked : {
+ view.forceActiveFocus()
+ if (delegateModel.mode == "move") {
+ delegateModel.onMoveSelectionAtPos(index)
+ view.currentIndex = index
+ } else if ( delegateModel.mode == "select" ) {
+ } else {
+ delegateModel.onUpdateIndex( modifier , view.currentIndex, index)
+ view.currentIndex = index
+ }
+ }
+ onItemDoubleClicked: delegateModel.onAction(index, true)
+
+ onDropedMovedAt: {
+ if (drop.hasUrls) {
+ delegateModel.onDropUrlAtPos(drop.urls, target)
+ } else {
+ delegateModel.onMoveSelectionAtPos(target)
+ }
+ }
+ }
+ }
+
+ function onMoveSelectionAtPos(target) {
+ var list = []
+ for (var i = 0; i < delegateModel.selectedGroup.count; i++ ) {
+ list.push(delegateModel.selectedGroup.get(i).itemsIndex)
+ }
+ root.plmodel.moveItems(list, target)
+ }
+
+ function onDropMovedAtEnd() {
+ onMoveSelectionAtPos(items.count)
+ }
+
+ function onDropUrlAtPos(urls, target) {
+ var list = []
+ for (var i = 0; i < urls.length; i++){
+ list.push(urls[i])
+ }
+ plControler.insert(target, list)
+ }
+
+ function onDropUrlAtEnd(urls) {
+ var list = []
+ for (var i = 0; i < urls.length; i++){
+ list.push(urls[i])
+ }
+ plControler.append(list)
+ }
+
+ function onDelete() {
+ var list = []
+ for (var i = 0; i < delegateModel.selectedGroup.count; i++ ) {
+ list.push(delegateModel.selectedGroup.get(i).itemsIndex)
+ }
+ root.plmodel.removeItems(list)
+ }
+
+ function onPlay() {
+ if (delegateModel.selectedGroup.count > 0)
+ plControler.goTo(delegateModel.selectedGroup.get(0).itemsIndex, true)
+ }
+
+ function onAction(index) {
+ if (mode === "select")
+ updateSelection( Qt.ControlModifier, index, view.currentIndex )
+ else //normal
+ onPlay()
+ }
+
+ function onUpdateIndex( keyModifiers, oldIndex, newIndex )
+ {
+ if (delegateModel.mode === "select") {
+ console.log("update selection select")
+ } else if (delegateModel.mode === "move") {
+ if (delegateModel.selectedGroup.count === 0)
+ return
+
+ var list = []
+ for (var i = 0; i < delegateModel.selectedGroup.count; i++ ) {
+ list.push(delegateModel.selectedGroup.get(i).itemsIndex)
+ }
+ var minIndex= delegateModel.selectedGroup.get(0).itemsIndex
+ var maxIndex= delegateModel.selectedGroup.get(delegateModel.selectedGroup.count - 1).itemsIndex
+
+ if (newIndex > oldIndex) {
+ //after the next item
+ newIndex = Math.min(maxIndex + 2, delegateModel.items.count)
+ view.currentIndex = Math.min(maxIndex, delegateModel.items.count)
+ } else if (newIndex < oldIndex) {
+ //before the previous item
+ view.currentIndex = Math.max(minIndex, 0)
+ newIndex = Math.max(minIndex - 1, 0)
+ }
+
+ root.plmodel.moveItems(list, newIndex)
+
+ } else { //normal
+ updateSelection( keyModifiers, oldIndex, newIndex )
+ }
+ }
+ }
+
+ Utils.KeyNavigableListView {
+ id: view
+
+ anchors.fill: parent
+ focus: true
+
+ model: delegateModel.parts.list
+ modelCount: delegateModel.items.count
+
+ footer: PLItemFooter {}
+
+ onSelectAll: delegateModel.selectAll()
+ onSelectionUpdated: delegateModel.onUpdateIndex( keyModifiers, oldIndex, newIndex )
+ Keys.onDeletePressed: delegateModel.onDelete()
+ onActionAtIndex: delegateModel.onAction(index)
+ onActionRight: {
+ overlay.state = "normal"
+ overlay.focus = true
+ }
+ onActionLeft: this.onCancel(index, root.actionLeft)
+ onActionCancel: this.onCancel(index, root.actionCancel)
+ onActionUp: root.actionUp(index)
+ onActionDown: root.actionDown(index)
+
+ function onCancel(index, fct) {
+ if (delegateModel.mode === "select" || delegateModel.mode === "move")
+ {
+ overlay.state = "hidden"
+ delegateModel.mode = "normal"
+ }
+ else
+ {
+ fct(index)
+ }
+ }
+
+ Connections {
+ target: root.plmodel
+ onCurrentIndexChanged: {
+ var plIndex = root.plmodel.currentIndex
+ if (view.currentIndex === -1 && plIndex >= 0) {
+ delegateModel.items.get(plIndex).inSelected = true
+ view.currentIndex = plIndex
+ }
+ }
+ }
+ Connections {
+ target: delegateModel.items
+ onCountChanged: {
+ if (view.currentIndex === -1 && delegateModel.items.count > 0) {
+ delegateModel.items.get(0).inSelected = true
+ view.currentIndex = 0
+ }
+ }
+ }
+ }
+
+ Label {
+ anchors.centerIn: parent
+ visible: delegateModel.items.count === 0
+ font.pixelSize: VLCStyle.fontHeight_xxlarge
+ color: root.activeFocus ? VLCStyle.colors.accent : VLCStyle.colors.text
+ text: qsTr("playlist is empty")
+ }
+
+ Keys.priority: Keys.AfterItem
+ Keys.forwardTo: view
+ Keys.onPressed: defaultKeyAction(event, 0)
+}
diff --git a/modules/gui/qt/qml/playlist/PlaylistMenu.qml b/modules/gui/qt/qml/playlist/PlaylistMenu.qml
new file mode 100644
index 0000000000..5bfb282ca4
--- /dev/null
+++ b/modules/gui/qt/qml/playlist/PlaylistMenu.qml
@@ -0,0 +1,249 @@
+/*****************************************************************************
+ * 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 2.11
+import QtQuick.Controls 2.4
+import QtQuick.Layouts 1.3
+
+import "qrc:///style/"
+
+FocusScope{
+ id: root
+
+ signal menuExit()
+ signal play()
+ signal clear()
+ signal selectionMode()
+ signal moveMode()
+
+ Keys.onPressed: {
+ if (event.matches(StandardKey.MoveToPreviousChar) //left
+ || event.matches(StandardKey.MoveToNextChar) //right
+ || event.matches(StandardKey.Back)
+ || event.matches(StandardKey.Cancel) //esc
+ ) {
+ _exitMenu();
+ event.accepted = true
+ return;
+ }
+ }
+
+ width: VLCStyle.icon_large
+ height: VLCStyle.icon_large * 5
+ property int _hiddentX: VLCStyle.icon_large
+
+ function _exitMenu() {
+ root.state = "hidden"
+ menuExit()
+ }
+
+ Item {
+ id: overlay
+ anchors.fill: parent
+
+ Column {
+ anchors.right: parent.right
+ spacing: VLCStyle.margin_xsmall
+
+ RoundButton {
+ id: playButton
+
+ height: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ width: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ x: root._hiddentX
+
+ KeyNavigation.down: clearButton
+ icon.source: "qrc:///toolbar/play_b.svg"
+ icon.width: VLCStyle.icon_normal
+ icon.height: VLCStyle.icon_normal
+ onClicked: {
+ play()
+ _exitMenu()
+ }
+ focus: true
+ background: Rectangle {
+ radius: parent.radius
+ implicitHeight: parent.width
+ implicitWidth: parent.height
+ color: "palegreen"
+ }
+ }
+ RoundButton {
+ id: clearButton
+
+ height: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ width: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ x: root._hiddentX
+
+ KeyNavigation.down: selectButton
+ icon.source: "qrc:///toolbar/clear.svg"
+ icon.width: VLCStyle.icon_normal
+ icon.height: VLCStyle.icon_normal
+ onClicked: {
+ clear()
+ _exitMenu()
+ }
+ background: Rectangle {
+ radius: parent.radius
+ implicitHeight: parent.width
+ implicitWidth: parent.height
+ color: "pink"
+ }
+ }
+ RoundButton {
+ id: selectButton
+
+ height: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ width: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ x: root._hiddentX
+
+ KeyNavigation.down: moveButton
+ icon.source: "qrc:///toolbar/playlist.svg"
+ icon.width: VLCStyle.icon_normal
+ icon.height: VLCStyle.icon_normal
+
+ checkable: true
+ checked: false
+ onClicked: root.state = checked ? "select" : "normal"
+ onCheckedChanged: selectionMode(checked)
+ background: Rectangle {
+ radius: parent.radius
+ implicitHeight: parent.width
+ implicitWidth: parent.height
+ color: "lightblue"
+ }
+ }
+ RoundButton {
+ id: moveButton
+
+ height: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ width: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ x: root._hiddentX
+
+ KeyNavigation.down: backButton
+ icon.source: "qrc:///toolbar/space.svg"
+ icon.width: VLCStyle.icon_normal
+ icon.height: VLCStyle.icon_normal
+
+ checkable: true
+ checked: false
+ onClicked: root.state = checked ? "move" : "normal"
+ onCheckedChanged: moveMode(checked)
+ background: Rectangle {
+ radius: parent.radius
+ implicitHeight: parent.width
+ implicitWidth: parent.height
+ color: "lightyellow"
+ }
+ }
+ RoundButton {
+ id: backButton
+ height: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ width: activeFocus ? VLCStyle.icon_normal * 1.3 : VLCStyle.icon_normal
+ x: root._hiddentX
+
+ icon.source: "qrc:///menu/exit.svg"
+ icon.width: VLCStyle.icon_normal
+ icon.height: VLCStyle.icon_normal
+
+ onClicked: _exitMenu()
+
+ background: Rectangle {
+ radius: parent.radius
+ implicitHeight: parent.width
+ implicitWidth: parent.height
+ color: "lightgrey"
+ }
+ }
+ }
+ }
+
+ state: "hidden"
+ states: [
+ State {
+ name: "hidden"
+ PropertyChanges { target: selectButton; checked: false }
+ PropertyChanges { target: moveButton; checked: false }
+ },
+ State {
+ name: "normal"
+ PropertyChanges { target: moveButton; checked: false }
+ PropertyChanges { target: selectButton; checked: false }
+ },
+ State {
+ name: "select"
+ PropertyChanges { target: selectButton; checked: true }
+ PropertyChanges { target: moveButton; checked: false }
+ },
+ State {
+ name: "move"
+ PropertyChanges { target: selectButton; checked: false }
+ PropertyChanges { target: moveButton; checked: true }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "hidden"; to: "*"
+ ParallelAnimation {
+ SequentialAnimation {
+ NumberAnimation { target: playButton; properties: "x"; duration: 200; from: _hiddentX; to: 0 }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 25 }
+ NumberAnimation { target: clearButton; properties: "x"; duration: 200; from: _hiddentX; to: 0 }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 75 }
+ NumberAnimation { target: selectButton; properties: "x"; duration: 200; from: _hiddentX; to: 0 }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 50 }
+ NumberAnimation { target: moveButton; properties: "x"; duration: 200; from: _hiddentX; to: 0 }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 100 }
+ NumberAnimation { target: backButton; properties: "x"; duration: 200; from: _hiddentX; to: 0 }
+ }
+ }
+ },
+ Transition {
+ from: "*"; to: "hidden"
+ ParallelAnimation {
+ SequentialAnimation {
+ PauseAnimation { duration: 100 }
+ NumberAnimation { target: playButton; properties: "x"; duration: 200; from: 0; to: _hiddentX }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 75 }
+ NumberAnimation { target: clearButton; properties: "x"; duration: 200; from: 0; to: _hiddentX }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 50 }
+ NumberAnimation { target: selectButton; properties: "x"; duration: 200; from: 0; to: _hiddentX }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 25 }
+ NumberAnimation { target: moveButton; properties: "x"; duration: 200; from: 0; to: _hiddentX }
+ }
+ SequentialAnimation {
+ NumberAnimation { target: backButton; properties: "x"; duration: 200; from: 0; to: _hiddentX }
+ }
+ }
+ }
+ ]
+}
diff --git a/modules/gui/qt/vlc.qrc b/modules/gui/qt/vlc.qrc
index 530e1c1aa5..de7bac2321 100644
--- a/modules/gui/qt/vlc.qrc
+++ b/modules/gui/qt/vlc.qrc
@@ -185,6 +185,12 @@
<file alias="VLCColors.qml">qml/style/VLCColors.qml</file>
<file alias="VLCIcons.qml">qml/style/VLCIcons.qml</file>
</qresource>
+ <qresource prefix="/playlist">
+ <file alias="PLItem.qml">qml/playlist/PLItem.qml</file>
+ <file alias="PlaylistListView.qml">qml/playlist/PlaylistListView.qml</file>
+ <file alias="PlaylistMenu.qml">qml/playlist/PlaylistMenu.qml</file>
+ <file alias="PLItemFooter.qml">qml/playlist/PLItemFooter.qml</file>
+ </qresource>
<qresource prefix="/about">
<file alias="About.qml">qml/about/About.qml</file>
</qresource>
--
2.19.1
More information about the vlc-devel
mailing list