vlc/modules/gui/qt/widgets/qml/TableViewDelegate.qml

262 lines
7.8 KiB
QML

/*****************************************************************************
* Copyright (C) 2021 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.Templates 2.12 as T
import QtQuick.Layouts 1.12
import org.videolan.vlc 0.1
import "qrc:///widgets/" as Widgets
import "qrc:///style/"
T.Control {
id: delegate
// Properties
property var rowModel
property var sortModel
property bool selected: false
readonly property int _index: index
property int _modifiersOnLastPress: Qt.NoModifier
readonly property bool dragActive: hoverArea.drag.active
property var dragItem
property bool acceptDrop: false
signal contextMenuButtonClicked(Item menuParent, var menuModel, point globalMousePos)
signal rightClick(Item menuParent, var menuModel, point globalMousePos)
signal itemDoubleClicked(var index, var model)
signal selectAndFocus(int modifiers, int focusReason)
signal dropEntered(var drag, bool before)
signal dropUpdatePosition(var drag, bool before)
signal dropExited(var drag, bool before)
signal dropEvent(var drag, var drop, bool before)
property Component defaultDelegate: Widgets.ScrollingText {
id: defaultDelId
property var rowModel: parent.rowModel
property var colModel: parent.colModel
readonly property ColorContext colorContext: parent.colorContext
readonly property bool selected: parent.selected
label: text
forceScroll: parent.currentlyFocused
width: parent.width
clip: scrolling
Widgets.ListLabel {
id: text
anchors.verticalCenter: parent.verticalCenter
text: defaultDelId.rowModel
? (defaultDelId.rowModel[defaultDelId.colModel.criteria] || "")
: ""
color: defaultDelId.selected
? defaultDelId.colorContext.fg.highlight
: defaultDelId.colorContext.fg.primary
}
}
// Settings
hoverEnabled: true
ListView.delayRemove: dragActive
Component.onCompleted: {
Keys.menuPressed.connect(contextButton.clicked)
}
// Childs
readonly property ColorContext colorContext: ColorContext {
id: theme
colorSet: ColorContext.Item
focused: delegate.visualFocus
hovered: delegate.hovered
}
background: AnimatedBackground {
animationDuration: VLCStyle.duration_short
enabled: theme.initialized
color: delegate.selected ? theme.bg.highlight : theme.bg.primary
border.color: visualFocus ? theme.visualFocus : "transparent"
MouseArea {
id: hoverArea
// Settings
anchors.fill: parent
hoverEnabled: false
acceptedButtons: Qt.RightButton | Qt.LeftButton
drag.target: delegate.dragItem
drag.axis: Drag.XAndYAxis
drag.smoothed: false
// Events
onPressed: (mouse) => {
_modifiersOnLastPress = mouse.modifiers
}
onClicked: (mouse) => {
if ((mouse.button === Qt.LeftButton) || !delegate.selected) {
delegate.selectAndFocus(mouse.modifiers, Qt.MouseFocusReason)
}
if (mouse.button === Qt.RightButton)
delegate.rightClick(delegate, delegate.rowModel, hoverArea.mapToGlobal(mouse.x, mouse.y))
}
onDoubleClicked: (mouse) => {
if (mouse.button === Qt.LeftButton)
delegate.itemDoubleClicked(delegate._index, delegate.rowModel)
}
drag.onActiveChanged: {
// NOTE: 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 && !delegate.selected) {
delegate.selectAndFocus(_modifiersOnLastPress, index)
} else if (delegate.dragItem) {
delegate.dragItem.Drag.drop()
}
delegate.dragItem.Drag.active = drag.active
}
TapHandler {
acceptedDevices: PointerDevice.TouchScreen
onTapped: {
delegate.selectAndFocus(Qt.NoModifier, Qt.MouseFocusReason)
delegate.itemDoubleClicked(delegate._index, delegate.rowModel)
}
onLongPressed: {
delegate.rightClick(delegate, delegate.rowModel, point.scenePosition)
}
}
}
}
contentItem: Row {
leftPadding: VLCStyle.margin_xxxsmall
rightPadding: VLCStyle.margin_xxxsmall
spacing: VLCStyle.column_spacing
Repeater {
model: delegate.sortModel
Loader{
property var rowModel: delegate.rowModel
property var colModel: modelData.model
readonly property int index: delegate._index
readonly property bool currentlyFocused: delegate.activeFocus
readonly property bool selected: delegate.selected
readonly property bool containsMouse: hoverArea.containsMouse
readonly property ColorContext colorContext: theme
width: (modelData.size) ? VLCStyle.colWidth(modelData.size) : 0
height: parent.height
sourceComponent: colModel.colDelegate || delegate.defaultDelegate
}
}
Item {
width: VLCStyle.icon_normal
height: parent.height
Widgets.IconToolButton {
id: contextButton
anchors.left: parent.left
// NOTE: We want the contextButton to be contained inside the trailing
// column_spacing.
anchors.leftMargin: -width
anchors.verticalCenter: parent.verticalCenter
text: VLCIcons.ellipsis
font.pixelSize: VLCStyle.icon_normal
description: I18n.qtr("Menu")
visible: delegate.hovered
onClicked: {
if (!delegate.selected)
delegate.selectAndFocus(Qt.NoModifier, Qt.MouseFocusReason)
const pos = contextButton.mapToGlobal(VLCStyle.margin_xsmall, contextButton.height / 2 + VLCStyle.fontHeight_normal)
delegate.contextMenuButtonClicked(this, delegate.rowModel, pos)
}
activeFocusOnTab: false
}
}
}
DropArea {
enabled: delegate.acceptDrop
anchors.fill: parent
function isBefore(drag) {
return drag.y < height/2
}
onEntered: (drag) => { delegate.dropEntered(drag, isBefore(drag)) }
onPositionChanged: (drag) => { delegate.dropUpdatePosition(drag, isBefore(drag)) }
onExited:delegate.dropExited(drag, isBefore(drag))
onDropped: (drop) => { delegate.dropEvent(drag, drop, isBefore(drag)) }
}
}