plasma-wallpaper-plugin-potd/contents/ui/WallpaperDelegate.qml
2025-08-21 11:36:02 +02:00

260 lines
8.8 KiB
QML

/*
SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
SPDX-FileCopyrightText: 2022 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import Qt5Compat.GraphicalEffects as GE
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15
import org.kde.kirigami as Kirigami
FocusScope {
// FocusScope can pass Tab to inline buttons
id: delegate
readonly property int shadowOffset: thumbnail.shadow.size - thumbnail.shadow.yOffset
readonly property bool isNull: wallpaperImage.status !== Image.Ready
/**
* The background color of the preview area when the image is loaded
*/
property color backgroundColor
/**
* The local path of the wallpaper
*/
property url localUrl
/**
* The website of the wallpaper
*/
property url infoUrl
/**
* The title of the wallpaper
*/
property string title
/**
* The author of the wallpaper
*/
property string author
/**
* Set it to true when a thumbnail is actually available: when false,
* only an icon ("edit-none") will be shown instead of the actual thumbnail.
*/
property bool thumbnailAvailable: false
/**
* Set it to true when a thumbnail is still being loaded: when false,
* the BusyIndicator will be shown.
*/
property bool thumbnailLoading: false
/**
* A list of extra actions for the thumbnails. They will be shown as
* icons on the bottom-right corner of the thumbnail on mouse over
*/
property list<QtObject> actions
ActionContextMenu {
id: contextMenu
showAllActions: thumbnailAvailable
actions: delegate.actions
}
Keys.onMenuPressed: contextMenu.popup(delegate, thumbnail.x, thumbnail.y + thumbnail.height)
Keys.onSpacePressed: contextMenu.popup(delegate, thumbnail.x, thumbnail.y + thumbnail.height)
onThumbnailLoadingChanged: {
if (!thumbnailLoading) {
if (wallpaperImage.source === Qt.resolvedUrl(delegate.localUrl)) {
wallpaperImage.source = "";
}
wallpaperImage.source = delegate.localUrl;
} else {
wallpaperImage.source = delegate.localUrl;
}
}
TapHandler {
acceptedButtons: Qt.RightButton
onTapped: contextMenu.popup()
}
TapHandler {
id: openUrlTapHandler
enabled: hoverHandler.enabled
acceptedButtons: Qt.LeftButton
onTapped: Qt.openUrlExternally(delegate.infoUrl)
}
HoverHandler {
id: hoverHandler
enabled: delegate.thumbnailAvailable && delegate.infoUrl.toString().length > 0
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
}
QQC2.ToolTip {
text: delegate.infoUrl.toString()
visible: hoverHandler.enabled && !contextMenu.opened
&& (hoverHandler.hovered
|| thumbnailArea.activeFocus
|| (Kirigami.Settings.isMobile && openUrlTapHandler.pressed))
}
// From kdeclarative/src/qmlcontrols/kcmcontrols/qml/GridDelegate.qml
Kirigami.ShadowedRectangle {
id: thumbnail
anchors.fill: parent
radius: Kirigami.Units.cornerRadius
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.View
shadow.xOffset: 0
shadow.yOffset: 2
shadow.size: 10
shadow.color: Qt.rgba(0, 0, 0, 0.3)
color: thumbnailArea.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor
Rectangle {
id: thumbnailArea
radius: Math.round(Kirigami.Units.cornerRadius / 2)
anchors {
fill: parent
margins: Kirigami.Units.smallSpacing
}
color: !delegate.thumbnailAvailable || delegate.thumbnailLoading ? Kirigami.Theme.backgroundColor : delegate.backgroundColor
activeFocusOnTab: true
Accessible.name: delegate.thumbnailAvailable ? i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis", "Today's picture")
: delegate.thumbnailLoading ? i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis", "Loading")
: i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis", "Unavailable")
Accessible.description: delegate.thumbnailAvailable ? i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis for an image %1 title %2 author", "%1 Author: %2. Right-click on the image to see more actions.", delegate.title, delegate.author)
: delegate.thumbnailLoading ? i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis", "The wallpaper is being fetched from the Internet.")
: i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis", "Failed to fetch the wallpaper from the Internet.")
Image {
id: wallpaperImage
anchors.fill: parent
autoTransform: false
cache: false
fillMode: cfg_FillMode || Image.PreserveAspectCrop
smooth: true
Drag.dragType: Drag.Automatic
Drag.supportedActions: Qt.CopyAction
Drag.mimeData: {
"text/uri-list" : [delegate.localUrl],
"text/plain": delegate.title,
}
DragHandler {
id: dragHandler
onActiveChanged: if (active) {
parent.grabToImage((result) => {
parent.Drag.imageSource = result.url;
parent.Drag.active = dragHandler.active;
});
} else {
parent.Drag.active = false;
parent.Drag.imageSource = "";
}
}
// CachedProvider will load the image from cache, but we would like to show the real loading status.
layer.enabled: delegate.thumbnailLoading
layer.effect: GE.HueSaturation {
cached: true
lightness: 0.5
saturation: 0.9
layer.enabled: true
layer.effect: GE.GaussianBlur {
cached: true
radius: 128
deviation: 12
samples: 63
transparentBorder: false
}
}
}
Loader {
active: delegate.thumbnailLoading || !delegate.thumbnailAvailable
anchors.centerIn: parent
opacity: 0.5
visible: active
width: Kirigami.Units.iconSizes.large
height: width
sourceComponent: delegate.thumbnailLoading ? busyIndicator : fallbackIcon
Component {
id: busyIndicator
QQC2.BusyIndicator {
anchors.fill: parent
}
}
// "None/There's nothing here" indicator
Component {
id: fallbackIcon
Kirigami.Icon {
anchors.fill: parent
source: "edit-none"
}
}
}
RowLayout {
anchors {
right: parent.right
rightMargin: Kirigami.Units.smallSpacing
bottom: parent.bottom
bottomMargin: Kirigami.Units.smallSpacing
}
// Always show above thumbnail content
z: 9999
Repeater {
model: delegate.actions
delegate: QQC2.Button {
icon.name: modelData.icon.name
activeFocusOnTab: visible
onClicked: modelData.trigger()
enabled: modelData.enabled
visible: modelData.visible
Accessible.name: modelData.tooltip
Accessible.description: modelData.Accessible.description
QQC2.ToolTip {
visible: modelData.tooltip.length > 0
&& ((Kirigami.Settings.isMobile ? parent.pressed : parent.hovered)
|| (parent.activeFocus && (parent.focusReason === Qt.TabFocusReason || parent.focusReason === Qt.BacktabFocusReason)))
text: modelData.tooltip
}
}
}
}
}
}
}