/***************************************************************************** * 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.Templates as T import QtQuick.Layouts import QtQml.Models import org.videolan.vlc 0.1 import "qrc:///widgets/" as Widgets import "qrc:///util/Helpers.js" as Helpers import "qrc:///style/" T.ItemDelegate { id: root // Properties property real pictureWidth: VLCStyle.colWidth(1) property real pictureHeight: pictureWidth property int titleMargin: VLCStyle.margin_xsmall property Item dragItem: null readonly property int selectedBorderWidth: VLCStyle.gridItemSelectedBorder property int _modifiersOnLastPress: Qt.NoModifier // if true, texts are horizontally centered, provided it can fit in pictureWidth property bool textAlignHCenter: false // if the item is selected property bool selected: false // Aliases property alias image: picture.source property alias cacheImage: picture.cacheImage property alias isImageReady: picture.isImageReady property alias fallbackImage: picture.fallbackImageSource property alias title: titleLabel.text property alias subtitle: subtitleTxt.text property alias playCoverBorderWidth: picture.playCoverBorderWidth property alias playCoverShowPlay: picture.playCoverShowPlay property alias playIconSize: picture.playIconSize property alias pictureRadius: picture.radius property alias pictureOverlay: picture.imageOverlay property alias selectedShadow: selectedShadow property alias unselectedShadow: unselectedShadow // Signals signal playClicked signal addToPlaylistClicked signal itemClicked(int modifier) signal itemDoubleClicked(int modifier) signal contextMenuButtonClicked(Item menuParent, point globalMousePos) // Settings implicitWidth: layout.implicitWidth implicitHeight: layout.implicitHeight highlighted: (mouseHoverHandler.hovered || visualFocus) Accessible.role: Accessible.Cell Accessible.name: title Accessible.selected: root.selected Accessible.onPressAction: root.playClicked() Keys.onMenuPressed: root.contextMenuButtonClicked(picture, root.mapToGlobal(0,0)) // States states: [ State { name: "highlighted" when: highlighted PropertyChanges { target: selectedShadow opacity: 1.0 } PropertyChanges { target: unselectedShadow opacity: 0 } PropertyChanges { target: picture playCoverVisible: true playCoverOpacity: 1.0 } } ] transitions: [ Transition { from: "" to: "highlighted" // reversible: true // doesn't work SequentialAnimation { PropertyAction { target: picture properties: "playCoverVisible" } NumberAnimation { properties: "opacity, playCoverOpacity" duration: VLCStyle.duration_long easing.type: Easing.InSine } } }, Transition { from: "highlighted" to: "" SequentialAnimation { PropertyAction { target: picture property: "playCoverVisible" } NumberAnimation { properties: "opacity, playCoverOpacity" duration: VLCStyle.duration_long easing.type: Easing.OutSine } } } ] // Childs readonly property ColorContext colorContext: ColorContext { id: theme colorSet: ColorContext.Item focused: root.visualFocus hovered: root.hovered } background: AnimatedBackground { width: root.width + (selectedBorderWidth * 2) height: root.height + (selectedBorderWidth * 2) x: - selectedBorderWidth y: - selectedBorderWidth enabled: theme.initialized //don't show the backgroud unless selected color: root.selected ? theme.bg.highlight : theme.bg.primary border.color: visualFocus ? theme.visualFocus : "transparent" } contentItem: MouseArea { implicitWidth: layout.implicitWidth implicitHeight: layout.implicitHeight acceptedButtons: Qt.RightButton | Qt.LeftButton drag.target: root.dragItem drag.axis: Drag.XAndYAxis drag.smoothed: false onClicked: (mouse) => { if (mouse.button === Qt.RightButton) contextMenuButtonClicked(picture, root.mapToGlobal(mouse.x,mouse.y)); else if (mouse.button === Qt.LeftButton) { root.itemClicked(mouse.modifiers); } } onDoubleClicked: (mouse) => { if (mouse.button === Qt.LeftButton) root.itemDoubleClicked(mouse.modifiers) } onPressed: (mouse) => { _modifiersOnLastPress = mouse.modifiers } drag.onActiveChanged: { // perform the "click" action because the click action is only executed on mouse release (we are in the pressed state) // but we will need the updated list on drop if (drag.active && !selected) { root.itemClicked(root._modifiersOnLastPress) } else if (root.dragItem) { root.dragItem.Drag.drop() } root.dragItem.Drag.active = drag.active } TapHandler { acceptedDevices: PointerDevice.TouchScreen onTapped: (eventPoint, button) => { root.itemClicked(Qt.NoModifier) root.itemDoubleClicked(Qt.NoModifier) } onLongPressed: { contextMenuButtonClicked(picture, point.scenePosition); } } HoverHandler { id: mouseHoverHandler acceptedDevices: PointerDevice.Mouse } ColumnLayout { id: layout anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter spacing: 0 Widgets.MediaCover { id: picture playCoverVisible: false playCoverOpacity: 0 radius: VLCStyle.gridCover_radius color: theme.bg.secondary Layout.preferredWidth: pictureWidth Layout.preferredHeight: pictureHeight onPlayIconClicked: (mouse) => { // emulate a mouse click before delivering the play signal as to select the item // this helps in updating the selection and restore of initial index in the parent views root.itemClicked(mouse.modifiers) root.playClicked() } DefaultShadow { id: unselectedShadow anchors.centerIn: parent visible: opacity > 0 sourceItem: parent width: viewportWidth height: viewportHeight sourceSize: Qt.size(128, 128) } DoubleShadow { id: selectedShadow anchors.centerIn: parent visible: opacity > 0 opacity: 0 sourceItem: parent width: viewportWidth height: viewportHeight sourceSize: Qt.size(128, 128) primaryVerticalOffset: VLCStyle.dp(6, VLCStyle.scale) primaryBlurRadius: VLCStyle.dp(18, VLCStyle.scale) secondaryVerticalOffset: VLCStyle.dp(32, VLCStyle.scale) secondaryBlurRadius: VLCStyle.dp(72, VLCStyle.scale) } } Widgets.TextAutoScroller { id: titleTextRect label: titleLabel forceScroll: highlighted visible: root.title !== "" clip: scrolling Layout.preferredWidth: Math.min(titleLabel.implicitWidth, pictureWidth) Layout.preferredHeight: titleLabel.height Layout.topMargin: root.titleMargin Layout.alignment: root.textAlignHCenter ? Qt.AlignCenter : Qt.AlignLeft Widgets.ListLabel { id: titleLabel height: implicitHeight color: root.selected ? theme.fg.highlight : theme.fg.primary textFormat: Text.PlainText } } Widgets.MenuCaption { id: subtitleTxt visible: text !== "" text: root.subtitle elide: Text.ElideRight color: root.selected ? theme.fg.highlight : theme.fg.secondary textFormat: Text.PlainText Layout.preferredWidth: Math.min(pictureWidth, implicitWidth) Layout.alignment: root.textAlignHCenter ? Qt.AlignCenter : Qt.AlignLeft Layout.topMargin: VLCStyle.margin_xsmall ToolTip.delay: VLCStyle.delayToolTipAppear ToolTip.text: subtitleTxt.text ToolTip.visible: subtitleTxtMouseHandler.hovered HoverHandler { id: subtitleTxtMouseHandler acceptedDevices: PointerDevice.Mouse } } } } }