// SPDX-FileCopyrightText: 2020 George Florea Bănuș // SPDX-FileCopyrightText: 2026 Tri Vo Khac // SPDX-License-Identifier: GPL-3.0-or-later import QtQuick import QtQuick.Controls import QtQuick.Layouts import org.kde.ki18n import org.kde.kirigami as Kirigami // One row of the playlist: row number, playing icon and file name. Item { id: root required property int index required property url url required property string name required property bool isPlaying required property PlaylistModel playlist required property MpvItem mpv property real alpha: QtPotatoSettings.playlistOverlayVideo ? 0.6 : 1 readonly property bool hovered: hoverHandler.hovered readonly property real fontSize: Kirigami.Theme.defaultFont.pointSize activeFocusOnTab: true function activate() { root.playlist.play(root.index) } function showContextMenu() { contextMenu.popup() } Keys.onReturnPressed: root.activate() Keys.onEnterPressed: root.activate() Keys.onMenuPressed: root.showContextMenu() Keys.onPressed: event => { if (event.key === Qt.Key_F10 && (event.modifiers & Qt.ShiftModifier)) { root.showContextMenu() event.accepted = true } } function labelColor(): color { if (root.isPlaying && !root.hovered) { return Kirigami.Theme.highlightedTextColor } return Kirigami.Theme.textColor } implicitWidth: ListView.view.width implicitHeight: fontSize * 3 HoverHandler { id: hoverHandler } TapHandler { acceptedButtons: Qt.LeftButton onTapped: root.forceActiveFocus(Qt.MouseFocusReason) onDoubleTapped: root.playlist.play(root.index) } TapHandler { acceptedButtons: Qt.RightButton onTapped: contextMenu.popup() } Rectangle { anchors.fill: parent Kirigami.Theme.colorSet: Kirigami.Theme.View color: { if (root.isPlaying && !root.hovered) { return Qt.alpha(Kirigami.Theme.highlightColor, root.alpha) } if (root.hovered) { return Qt.alpha(Kirigami.Theme.hoverColor, root.alpha) } return Qt.alpha(Kirigami.Theme.backgroundColor, root.alpha) } border.width: root.activeFocus ? 2 : 0 border.color: Kirigami.Theme.focusColor RowLayout { anchors.fill: parent spacing: Kirigami.Units.largeSpacing Label { text: root.index + 1 color: root.labelColor() visible: QtPotatoSettings.playlistShowRowNumber font.pointSize: root.fontSize font.features: { "tnum": 1 } horizontalAlignment: Qt.AlignHCenter Layout.leftMargin: Kirigami.Units.largeSpacing Layout.preferredWidth: rowNumberMetrics.width } TextMetrics { id: rowNumberMetrics font.pointSize: root.fontSize text: String(root.playlist.count).replace(/./g, "0") } Rectangle { color: Qt.alpha(Kirigami.Theme.textColor, 0.2) visible: QtPotatoSettings.playlistShowRowNumber Layout.preferredWidth: 1 Layout.fillHeight: true Layout.topMargin: Kirigami.Units.smallSpacing Layout.bottomMargin: Kirigami.Units.smallSpacing } Kirigami.Icon { source: "media-playback-start" color: root.labelColor() visible: root.isPlaying Layout.leftMargin: QtPotatoSettings.playlistShowRowNumber ? 0 : Kirigami.Units.largeSpacing Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium } LabelWithTooltip { text: root.name toolTipText: root.url.toString().startsWith("file://") ? decodeURIComponent(root.url.toString().substring(7)) : root.url color: root.labelColor() elide: Text.ElideRight font.pointSize: root.fontSize font.bold: root.isPlaying verticalAlignment: Qt.AlignVCenter Layout.fillWidth: true Layout.leftMargin: !QtPotatoSettings.playlistShowRowNumber && !root.isPlaying ? Kirigami.Units.largeSpacing : 0 Layout.rightMargin: Kirigami.Units.largeSpacing } Button { text: KI18n.i18nc("@action:button remove playlist item", "Remove") icon.name: "list-remove" display: AbstractButton.IconOnly flat: true Accessible.name: text ToolTip.text: text ToolTip.visible: hovered ToolTip.delay: Kirigami.Units.toolTipDelay Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium + Kirigami.Units.smallSpacing * 2 Layout.rightMargin: Kirigami.Units.smallSpacing onClicked: root.playlist.remove(root.index) } } } AppMenu { id: contextMenu AppMenuItem { text: KI18n.i18nc("@action:inmenu", "Play") icon.name: "media-playback-start" onTriggered: root.playlist.play(root.index) } AppMenuItem { text: KI18n.i18nc("@action:inmenu", "Open Containing Folder") icon.name: "folder-open" enabled: root.url.toString().startsWith("file://") onTriggered: { const path = root.url.toString() Qt.openUrlExternally(path.substring(0, path.lastIndexOf("/"))) } } MenuSeparator {} AppMenuItem { text: KI18n.i18nc("@action:inmenu", "Move Up") icon.name: "go-up" enabled: root.index > 0 onTriggered: root.playlist.move(root.index, root.index - 1) } AppMenuItem { text: KI18n.i18nc("@action:inmenu", "Move Down") icon.name: "go-down" enabled: root.index < root.playlist.count - 1 onTriggered: root.playlist.move(root.index, root.index + 1) } AppMenuItem { text: KI18n.i18nc("@action:inmenu", "Remove from Playlist") icon.name: "list-remove" onTriggered: root.playlist.remove(root.index) } } }