[vlc-devel] [RFC 67/82] qml: provide common class to serve as delegate for list and grid view

Pierre Lamot pierre at videolabs.io
Fri Feb 1 14:02:11 CET 2019


---
 modules/gui/qt/Makefile.am            |   2 +
 modules/gui/qt/qml/utils/GridItem.qml | 240 ++++++++++++++++++++++++++
 modules/gui/qt/qml/utils/ListItem.qml | 173 +++++++++++++++++++
 modules/gui/qt/vlc.qrc                |   2 +
 4 files changed, 417 insertions(+)
 create mode 100644 modules/gui/qt/qml/utils/GridItem.qml
 create mode 100644 modules/gui/qt/qml/utils/ListItem.qml

diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 36e2699f86..0e8124c19a 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -525,11 +525,13 @@ libqt_plugin_la_RES = \
 	gui/qt/qml/utils/DNDLabel.qml \
 	gui/qt/qml/utils/ToolTipArea.qml \
 	gui/qt/qml/utils/ExpandGridView.qml \
+	gui/qt/qml/utils/GridItem.qml \
 	gui/qt/qml/utils/IconToolButton.qml \
 	gui/qt/qml/utils/ImageToolButton.qml \
 	gui/qt/qml/utils/TextToolButton.qml \
 	gui/qt/qml/utils/MenuExt.qml \
 	gui/qt/qml/utils/MenuItemExt.qml \
+	gui/qt/qml/utils/ListItem.qml \
 	gui/qt/qml/utils/MultiCoverPreview.qml \
 	gui/qt/qml/utils/NavigableFocusScope.qml \
 	gui/qt/qml/utils/KeyNavigableGridView.qml \
diff --git a/modules/gui/qt/qml/utils/GridItem.qml b/modules/gui/qt/qml/utils/GridItem.qml
new file mode 100644
index 0000000000..4421abba25
--- /dev/null
+++ b/modules/gui/qt/qml/utils/GridItem.qml
@@ -0,0 +1,240 @@
+/*****************************************************************************
+ * 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 QtQml.Models 2.2
+import QtGraphicalEffects 1.0
+import org.videolan.medialib 0.1
+
+
+import "qrc:///utils/" as Utils
+import "qrc:///style/"
+
+Item {
+    id: root
+    width: VLCStyle.cover_normal
+    height: VLCStyle.cover_normal
+            + VLCStyle.fontHeight_normal
+            + VLCStyle.fontHeight_small
+            + VLCStyle.margin_xsmall
+
+    property url image: VLCStyle.noArtCover
+    property string title: ""
+    property string subtitle: ""
+    property bool selected: false
+    property int shiftX: 0
+    property bool noActionButtons: false
+
+    signal playClicked
+    signal addToPlaylistClicked
+    signal itemClicked(int keys, int modifier)
+    signal itemDoubleClicked(int keys, int modifier)
+
+    Item {
+        x: shiftX
+        width: parent.width
+        height: parent.height
+
+        MouseArea {
+
+            id: mouseArea
+            anchors.fill: parent
+            hoverEnabled: true
+            onClicked:  root.itemClicked(mouse.buttons, mouse.modifiers)
+            onDoubleClicked: root.itemDoubleClicked(mouse.buttons, mouse.modifiers);
+
+            ColumnLayout {
+                anchors.fill: parent
+                Item {
+                    id: picture
+                    width: VLCStyle.cover_normal
+                    height: VLCStyle.cover_normal
+                    property bool highlighted: selected || mouseArea.containsMouse
+
+                    RectangularGlow {
+                        visible: picture.highlighted
+                        anchors.fill: coverPlaceHolder
+                        cornerRadius: 25
+                        spread: 0.2
+                        glowRadius: VLCStyle.margin_xsmall
+                        color: VLCStyle.colors.getBgColor( selected, mouseArea.containsMouse, root.activeFocus )
+                    }
+
+                    Item {
+                        id: coverPlaceHolder
+                        x: cover.x + (cover.width - cover.paintedWidth) / 2
+                        y: cover.y +(cover.height - cover.paintedHeight) / 2
+                        width: cover.paintedWidth
+                        height: cover.paintedHeight
+                    }
+
+                    Image {
+                        id: cover
+                        width: VLCStyle.cover_small
+                        height: VLCStyle.cover_small
+                        Behavior on width  { SmoothedAnimation { velocity: 100 } }
+                        Behavior on height { SmoothedAnimation { velocity: 100 } }
+                        anchors.centerIn: parent
+                        source: image
+                        fillMode: Image.PreserveAspectFit
+
+                        Rectangle {
+                            id: overlay
+                            anchors.fill: parent
+                            visible: mouseArea.containsMouse
+                            color: "black" //darken the image below
+
+                            RowLayout {
+                                anchors.fill: parent
+                                visible: !noActionButtons
+                                Item {
+                                    Layout.fillHeight: true
+                                    Layout.fillWidth: true
+                                    /* A addToPlaylist button visible when hovered */
+                                    Text {
+                                        property int iconSize: VLCStyle.icon_large
+                                        Behavior on iconSize  { SmoothedAnimation { velocity: 100 } }
+                                        Binding on iconSize {
+                                            value: VLCStyle.icon_large * 1.2
+                                            when: mouseAreaAdd.containsMouse
+                                        }
+
+                                        //Layout.alignment: Qt.AlignCenter
+                                        anchors.centerIn: parent
+                                        text: VLCIcons.add
+                                        font.family: VLCIcons.fontFamily
+                                        horizontalAlignment: Text.AlignHCenter
+                                        color: mouseAreaAdd.containsMouse ? "white" : "lightgray"
+                                        font.pixelSize: iconSize
+
+                                        MouseArea {
+                                            id: mouseAreaAdd
+                                            anchors.fill: parent
+                                            hoverEnabled: true
+                                            propagateComposedEvents: true
+                                            onClicked: root.addToPlaylistClicked()
+                                        }
+                                    }
+                                }
+
+                                /* A play button visible when hovered */
+                                Item {
+                                    Layout.fillHeight: true
+                                    Layout.fillWidth: true
+
+                                    Text {
+                                        property int iconSize: VLCStyle.icon_large
+                                        Behavior on iconSize  {
+                                            SmoothedAnimation { velocity: 100 }
+                                        }
+                                        Binding on iconSize {
+                                            value: VLCStyle.icon_large * 1.2
+                                            when: mouseAreaPlay.containsMouse
+                                        }
+
+                                        anchors.centerIn: parent
+                                        text: VLCIcons.play
+                                        font.family: VLCIcons.fontFamily
+                                        horizontalAlignment: Text.AlignHCenter
+                                        color: mouseAreaPlay.containsMouse ? "white" : "lightgray"
+                                        font.pixelSize: iconSize
+
+                                        MouseArea {
+                                            id: mouseAreaPlay
+                                            anchors.fill: parent
+                                            hoverEnabled: true
+                                            onClicked: root.playClicked()
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        states: [
+                            State {
+                                name: "visible"
+                                PropertyChanges { target: overlay; visible: true }
+                                when: mouseArea.containsMouse
+                            },
+                            State {
+                                name: "hidden"
+                                PropertyChanges { target: overlay; visible: false }
+                                when: !mouseArea.containsMouse
+                            }
+                        ]
+                        transitions: [
+                            Transition {
+                                from: "hidden";  to: "visible"
+                                NumberAnimation  {
+                                    target: overlay
+                                    properties: "opacity"
+                                    from: 0; to: 0.8; duration: 300
+                                }
+                            }
+                        ]
+                    }
+
+                    states: [
+                        State {
+                            name: "big"
+                            when: picture.highlighted
+                            PropertyChanges {
+                                target: cover
+                                width:  VLCStyle.cover_normal - 2 * VLCStyle.margin_xsmall
+                                height: VLCStyle.cover_normal - 2 * VLCStyle.margin_xsmall
+                            }
+                        },
+                        State {
+                            name: "small"
+                            when: !picture.highlighted
+                            PropertyChanges {
+                                target: cover
+                                width:  VLCStyle.cover_normal - 2 * VLCStyle.margin_small
+                                height: VLCStyle.cover_normal - 2 * VLCStyle.margin_small
+                            }
+                        }
+                    ]
+                }
+                Text {
+                    Layout.fillWidth: true
+                    Layout.leftMargin: VLCStyle.margin_small
+                    Layout.rightMargin: VLCStyle.margin_small
+
+                    text: root.title
+
+                    elide: Text.ElideRight
+                    font.pixelSize: VLCStyle.fontSize_normal
+                    font.bold: true
+                    color: VLCStyle.colors.text
+                }
+                Text {
+                    Layout.fillWidth: true
+                    Layout.leftMargin: VLCStyle.margin_small
+                    Layout.rightMargin: VLCStyle.margin_small
+
+                    text : root.subtitle
+
+                    elide: Text.ElideRight
+                    font.pixelSize: VLCStyle.fontSize_small
+                    color: VLCStyle.colors.text
+                }
+            }
+        }
+    }
+}
diff --git a/modules/gui/qt/qml/utils/ListItem.qml b/modules/gui/qt/qml/utils/ListItem.qml
new file mode 100644
index 0000000000..39863544f8
--- /dev/null
+++ b/modules/gui/qt/qml/utils/ListItem.qml
@@ -0,0 +1,173 @@
+/*****************************************************************************
+ * 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/"
+
+NavigableFocusScope {
+    id: root
+    signal playClicked
+    signal addToPlaylistClicked
+    signal itemClicked(int keys, int modifier)
+    signal itemDoubleClicked(int keys, int modifier)
+
+    property alias hovered: mouse.containsMouse
+
+    property Component cover: Item {}
+    property alias line1: line1_text.text
+    property alias line2: line2_text.text
+
+    property alias color: linerect.color
+
+    Component {
+        id: actionAdd
+        IconToolButton {
+            size: VLCStyle.icon_normal
+            text: VLCIcons.add
+
+            focus: true
+
+            highlightColor: activeFocus ? VLCStyle.colors.buttonText : "transparent"
+
+            //visible: mouse.containsMouse || root.activeFocus
+            onClicked: root.addToPlaylistClicked()
+        }
+    }
+
+
+    Component {
+        id: actionPlay
+        IconToolButton {
+            id: add_and_play_icon
+            size: VLCStyle.icon_normal
+            //visible: mouse.containsMouse  || root.activeFocus
+            text: VLCIcons.play
+
+            focus: true
+
+            highlightColor: add_and_play_icon.activeFocus ? VLCStyle.colors.buttonText : "transparent"
+            onClicked: root.playClicked()
+        }
+    }
+
+    property var actionButtons: [ actionAdd, actionPlay ]
+
+    Rectangle {
+        id: linerect
+        anchors.fill: parent
+        color: "transparent"
+
+        MouseArea {
+            id: mouse
+            anchors.fill: parent
+            hoverEnabled: true
+            onClicked: {
+                root.itemClicked(mouse.buttons, mouse.modifiers);
+            }
+            onDoubleClicked: {
+                root.itemDoubleClicked(mouse.buttons, mouse.modifiers);
+            }
+        }
+
+        RowLayout {
+            anchors.fill: parent
+
+            Loader {
+                Layout.preferredWidth: VLCStyle.icon_normal
+                Layout.preferredHeight: VLCStyle.icon_normal
+                sourceComponent: root.cover
+            }
+            FocusScope {
+                id: presentation
+                Layout.fillHeight: true
+                Layout.fillWidth: true
+                focus: true
+
+                Column {
+                    anchors.fill: parent
+
+                    Text{
+                        id: line1_text
+                        font.bold: true
+                        width: parent.width
+                        elide: Text.ElideRight
+                        color: VLCStyle.colors.text
+                        font.pixelSize: VLCStyle.fontSize_normal
+                        enabled: text !== ""
+                    }
+                    Text{
+                        id: line2_text
+                        width: parent.width
+                        text: ""
+                        elide: Text.ElideRight
+                        color: VLCStyle.colors.text
+                        font.pixelSize: VLCStyle.fontSize_xsmall
+                        enabled: text !== ""
+                    }
+                }
+
+                Keys.onRightPressed: {
+                    if (actionButtons.length === 0)
+                        root.actionRight(0)
+                    else
+                        toolButtons.focus = true
+                }
+                Keys.onLeftPressed: {
+                    root.actionLeft(0)
+                }
+            }
+
+            FocusScope {
+                id: toolButtons
+                Layout.preferredHeight: VLCStyle.icon_normal
+                Layout.preferredWidth: toolButtonsRow.implicitWidth
+                Layout.alignment: Qt.AlignVCenter
+                visible: mouse.containsMouse || root.activeFocus
+                property int focusIndex: 0
+                Row {
+                    id: toolButtonsRow
+                    anchors.fill: parent
+                    Repeater {
+                        id: buttons
+                        model: actionButtons
+                        delegate: Loader {
+                            sourceComponent: modelData
+                            focus: index === toolButtons.focusIndex
+                        }
+                    }
+                }
+                Keys.onLeftPressed: {
+                    if (focusIndex === 0)
+                        presentation.focus = true
+                    else {
+                        focusIndex -= 1
+                    }
+                }
+                Keys.onRightPressed: {
+                    if (focusIndex === actionButtons.length - 1)
+                        root.actionRight(0)
+                    else {
+                        focusIndex += 1
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/modules/gui/qt/vlc.qrc b/modules/gui/qt/vlc.qrc
index e7b5110013..1a12e86b13 100644
--- a/modules/gui/qt/vlc.qrc
+++ b/modules/gui/qt/vlc.qrc
@@ -160,6 +160,8 @@
     </qresource>
     <qresource prefix="/utils">
         <file alias="MultiCoverPreview.qml">qml/utils/MultiCoverPreview.qml</file>
+        <file alias="GridItem.qml">qml/utils/GridItem.qml</file>
+        <file alias="ListItem.qml">qml/utils/ListItem.qml</file>
         <file alias="SelectableDelegateModel.qml">qml/utils/SelectableDelegateModel.qml</file>
         <file alias="KeyNavigableGridView.qml">qml/utils/KeyNavigableGridView.qml</file>
         <file alias="KeyNavigableListView.qml">qml/utils/KeyNavigableListView.qml</file>
-- 
2.19.1



More information about the vlc-devel mailing list