init
This commit is contained in:
commit
87872cb4fa
7 changed files with 756 additions and 0 deletions
27
contents/config/main.xml
Normal file
27
contents/config/main.xml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||||
|
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||||
|
<kcfgfile name=""/>
|
||||||
|
|
||||||
|
<group name="General">
|
||||||
|
<entry name="Provider" type="String">
|
||||||
|
<label>Provider of Picture of the Day</label>
|
||||||
|
<default>apod</default>
|
||||||
|
</entry>
|
||||||
|
<entry name="FillMode" type="int">
|
||||||
|
<label>Sizing, cropping and positioning of the wallpaper image</label>
|
||||||
|
<default>0</default>
|
||||||
|
</entry>
|
||||||
|
<entry name="Color" type="Color">
|
||||||
|
<label>Color of the wallpaper</label>
|
||||||
|
<default>#000000</default>
|
||||||
|
</entry>
|
||||||
|
<entry name="UpdateOverMeteredConnection" type="Int">
|
||||||
|
<label>Update wallpaper over metered connection. 0 - False, 1 - True, 2 - True when data usage is below limit (not implemented)</label>
|
||||||
|
<default>0</default>
|
||||||
|
</entry>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</kcfg>
|
37
contents/ui/ActionContextMenu.qml
Normal file
37
contents/ui/ActionContextMenu.qml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Fushan Wen <qydwhotmail@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15 as QQC2
|
||||||
|
|
||||||
|
QQC2.Menu {
|
||||||
|
id: contextMenu
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always show all actions regardless of visible property
|
||||||
|
*/
|
||||||
|
property bool showAllActions: false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of extra actions in the context menu.
|
||||||
|
*/
|
||||||
|
property list<QtObject> actions
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: contextMenu.actions
|
||||||
|
delegate: QQC2.MenuItem {
|
||||||
|
text: modelData.text || modelData.tooltip
|
||||||
|
icon.name: modelData.iconName
|
||||||
|
onTriggered: modelData.trigger()
|
||||||
|
enabled: modelData.enabled
|
||||||
|
visible: modelData.visible || contextMenu.showAllActions
|
||||||
|
|
||||||
|
Accessible.description: modelData.Accessible.description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClosed: if (parent) parent.forceActiveFocus()
|
||||||
|
}
|
260
contents/ui/WallpaperDelegate.qml
Normal file
260
contents/ui/WallpaperDelegate.qml
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
contents/ui/WallpaperPreview.qml
Normal file
64
contents/ui/WallpaperPreview.qml
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2022 Fushan Wen <qydwhotmail@gmail.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.12 as Kirigami // For Action and Units
|
||||||
|
|
||||||
|
import org.kde.plasma.wallpapers.potd 1.0
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: wallpaperPreview
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The background color of the preview area when the image is loaded
|
||||||
|
*/
|
||||||
|
property alias backgroundColor: delegate.backgroundColor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shadow height needs to be considered in the padding.
|
||||||
|
*/
|
||||||
|
property alias shadowOffset: delegate.shadowOffset
|
||||||
|
|
||||||
|
// Wallpaper preview (including save button)
|
||||||
|
WallpaperDelegate {
|
||||||
|
id: delegate
|
||||||
|
|
||||||
|
width: Math.round(root.screenSize.width / 10 + Kirigami.Units.smallSpacing * 2) * Screen.devicePixelRatio
|
||||||
|
height: Math.round(root.screenSize.height / 10 + Kirigami.Units.smallSpacing * 2) * Screen.devicePixelRatio
|
||||||
|
|
||||||
|
localUrl: backend.localUrl
|
||||||
|
infoUrl: backend.infoUrl
|
||||||
|
title: backend.title
|
||||||
|
author: backend.author
|
||||||
|
|
||||||
|
thumbnailAvailable: !delegate.isNull
|
||||||
|
thumbnailLoading: backend.loading
|
||||||
|
|
||||||
|
actions: [
|
||||||
|
Kirigami.Action {
|
||||||
|
icon.name: "document-save"
|
||||||
|
enabled: backend.localUrl.length > 0
|
||||||
|
visible: enabled
|
||||||
|
tooltip: i18ndc("plasma_wallpaper_org.kde.potd", "@action:inmenu wallpaper preview menu", "Save Image as…")
|
||||||
|
onTriggered: backend.saveImage()
|
||||||
|
|
||||||
|
Accessible.description: i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis for a button and a menu item", "Save today's picture to local disk")
|
||||||
|
},
|
||||||
|
Kirigami.Action {
|
||||||
|
icon.name: "internet-services"
|
||||||
|
enabled: backend.infoUrl.toString().length > 0
|
||||||
|
visible: false
|
||||||
|
tooltip: i18ndc("plasma_wallpaper_org.kde.potd", "@action:inmenu wallpaper preview menu, will open the website of the wallpaper", "Open Link in Browser…")
|
||||||
|
onTriggered: Qt.openUrlExternally(backend.infoUrl)
|
||||||
|
|
||||||
|
Accessible.description: i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis for a menu item", "Open the website of today's picture in the default browser")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
218
contents/ui/config.qml
Normal file
218
contents/ui/config.qml
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016 Weng Xuetian <wengxt@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls 2.8 as QQC2
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.kquickcontrols 2.0 as KQC2
|
||||||
|
import org.kde.kirigami 2.20 as Kirigami
|
||||||
|
|
||||||
|
import org.kde.plasma.wallpapers.potd 1.0
|
||||||
|
|
||||||
|
Kirigami.FormLayout {
|
||||||
|
id: root
|
||||||
|
twinFormLayouts: parentLayout
|
||||||
|
|
||||||
|
property string cfg_Provider
|
||||||
|
property int cfg_FillMode
|
||||||
|
property alias cfg_Color: colorButton.color
|
||||||
|
property int cfg_UpdateOverMeteredConnection
|
||||||
|
property alias formLayout: root
|
||||||
|
|
||||||
|
readonly property size screenSize: Qt.size(Screen.width, Screen.height)
|
||||||
|
|
||||||
|
PotdBackend {
|
||||||
|
id: backend
|
||||||
|
identifier: cfg_Provider
|
||||||
|
arguments: {
|
||||||
|
if (identifier === "bing") {
|
||||||
|
// Bing supports 1366/1920/UHD resolutions
|
||||||
|
const w = screenSize.width * Screen.devicePixelRatio > 1920 ? 3840 : 1920;
|
||||||
|
const h = screenSize.height * Screen.devicePixelRatio > 1080 ? 2160 : 1080;
|
||||||
|
return [w, h];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
updateOverMeteredConnection: cfg_UpdateOverMeteredConnection
|
||||||
|
}
|
||||||
|
|
||||||
|
onCfg_FillModeChanged: {
|
||||||
|
resizeComboBox.setMethod()
|
||||||
|
}
|
||||||
|
|
||||||
|
QQC2.ComboBox {
|
||||||
|
id: resizeComboBox
|
||||||
|
Kirigami.FormData.label: i18ndc("plasma_wallpaper_org.kde.potd", "@label:listbox", "Positioning:")
|
||||||
|
model: [
|
||||||
|
{
|
||||||
|
'label': i18ndc("plasma_wallpaper_org.kde.potd", "@item:inlistbox", "Scaled and cropped"),
|
||||||
|
'fillMode': Image.PreserveAspectCrop
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': i18ndc("plasma_wallpaper_org.kde.potd", "@item:inlistbox", "Scaled"),
|
||||||
|
'fillMode': Image.Stretch
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': i18ndc("plasma_wallpaper_org.kde.potd", "@item:inlistbox", "Scaled, keep proportions"),
|
||||||
|
'fillMode': Image.PreserveAspectFit
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': i18ndc("plasma_wallpaper_org.kde.potd", "@item:inlistbox", "Centered"),
|
||||||
|
'fillMode': Image.Pad
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': i18ndc("plasma_wallpaper_org.kde.potd", "@item:inlistbox", "Tiled"),
|
||||||
|
'fillMode': Image.Tile
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
textRole: "label"
|
||||||
|
onActivated: cfg_FillMode = model[currentIndex]["fillMode"]
|
||||||
|
Component.onCompleted: setMethod();
|
||||||
|
|
||||||
|
function setMethod() {
|
||||||
|
for (var i = 0; i < model.length; i++) {
|
||||||
|
if (model[i]["fillMode"] === cfg_FillMode) {
|
||||||
|
resizeComboBox.currentIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KQC2.ColorButton {
|
||||||
|
id: colorButton
|
||||||
|
Kirigami.FormData.label: i18ndc("plasma_wallpaper_org.kde.potd", "@label:chooser", "Background color:")
|
||||||
|
dialogTitle: i18ndc("plasma_wallpaper_org.kde.potd", "@title:window", "Select Background Color")
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
Kirigami.FormData.label: i18ndc("plasma_wallpaper_org.kde.potd", "@label:listbox", "Provider:")
|
||||||
|
|
||||||
|
QQC2.ComboBox {
|
||||||
|
id: providerComboBox
|
||||||
|
model: PotdProviderModel { }
|
||||||
|
currentIndex: model.indexOf(cfg_Provider)
|
||||||
|
textRole: "display"
|
||||||
|
valueRole: "id"
|
||||||
|
onCurrentValueChanged: {
|
||||||
|
if (currentIndex < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cfg_Provider = currentValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.ContextualHelpButton {
|
||||||
|
anchors.verticalCenter: providerComboBox.verticalCenter
|
||||||
|
visible: providerComboBox.model.isNSFW(providerComboBox.currentIndex)
|
||||||
|
toolTipText: i18ndc("plasma_wallpaper_org.kde.potd", "@info:tooltip", "This wallpaper provider does not filter out images that may be sensitive or objectionable. Use caution if these images will be displayed in public.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QQC2.CheckBox {
|
||||||
|
id: updateOverMeteredConnectionCheckBox
|
||||||
|
|
||||||
|
checked: cfg_UpdateOverMeteredConnection === 1
|
||||||
|
visible: backend.networkInformationAvailable
|
||||||
|
text: i18ndc("plasma_wallpaper_org.kde.potd", "@option:check", "Update when using metered network connection")
|
||||||
|
|
||||||
|
onToggled: {
|
||||||
|
cfg_UpdateOverMeteredConnection = checked ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Separator {
|
||||||
|
id: previewSeparator
|
||||||
|
Kirigami.FormData.isSection: true
|
||||||
|
visible: wallpaperPreview.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
WallpaperPreview {
|
||||||
|
id: wallpaperPreview
|
||||||
|
Kirigami.FormData.label: i18ndc("plasma_wallpaper_org.kde.potd", "@label", "Today's picture:")
|
||||||
|
backgroundColor: cfg_Color
|
||||||
|
visible: !!cfg_Provider // provider is not empty
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: wallpaperPreview.implicitWidth
|
||||||
|
height: wallpaperPreview.shadowOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Kirigami.FormData.isSection: false
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.SelectableLabel {
|
||||||
|
id: titleLabel
|
||||||
|
Kirigami.FormData.label: i18ndc("plasma_wallpaper_org.kde.potd", "@label", "Title:")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: wallpaperPreview.implicitWidth * 1.5
|
||||||
|
visible: wallpaperPreview.visible && backend.title.length > 0
|
||||||
|
font.bold: true
|
||||||
|
text: backend.title
|
||||||
|
Accessible.name: titleLabel.Kirigami.FormData.label
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Kirigami.FormData.isSection: false
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.SelectableLabel {
|
||||||
|
id: authorLabel
|
||||||
|
Kirigami.FormData.label: i18ndc("plasma_wallpaper_org.kde.potd", "@label", "Author:")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: wallpaperPreview.implicitWidth * 1.5
|
||||||
|
visible: wallpaperPreview.visible && backend.author.length > 0
|
||||||
|
text: backend.author
|
||||||
|
Accessible.name: authorLabel.Kirigami.FormData.label
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.InlineMessage {
|
||||||
|
id: saveMessage
|
||||||
|
|
||||||
|
Kirigami.FormData.isSection: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
showCloseButton: true
|
||||||
|
|
||||||
|
actions: [
|
||||||
|
Kirigami.Action {
|
||||||
|
icon.name: "document-open-folder"
|
||||||
|
text: i18ndc("plasma_wallpaper_org.kde.potd", "@action:button", "Open Containing Folder")
|
||||||
|
visible: backend.saveStatus === PotdBackend.Successful
|
||||||
|
onTriggered: Qt.openUrlExternally(backend.savedFolder)
|
||||||
|
|
||||||
|
Accessible.description: i18ndc("plasma_wallpaper_org.kde.potd", "@info:whatsthis for a button", "Open the destination folder where the wallpaper image was saved.")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
onLinkActivated: Qt.openUrlExternally(backend.savedUrl)
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: backend
|
||||||
|
|
||||||
|
function onSaveStatusChanged() {
|
||||||
|
switch (backend.saveStatus) {
|
||||||
|
case PotdBackend.Successful:
|
||||||
|
saveMessage.text = backend.saveStatusMessage;
|
||||||
|
saveMessage.type = Kirigami.MessageType.Positive;
|
||||||
|
break;
|
||||||
|
case PotdBackend.Failed:
|
||||||
|
saveMessage.text = backend.saveStatusMessage;
|
||||||
|
saveMessage.type = Kirigami.MessageType.Error;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveMessage.visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
131
contents/ui/main.qml
Normal file
131
contents/ui/main.qml
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016 Weng Xuetian <wengxt@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15 as QQC2
|
||||||
|
import QtQuick.Window 2.15
|
||||||
|
|
||||||
|
import org.kde.plasma.core as PlasmaCore
|
||||||
|
import org.kde.kirigami 2.20 as Kirigami
|
||||||
|
|
||||||
|
import org.kde.plasma.wallpapers.potd 1.0
|
||||||
|
import org.kde.plasma.plasmoid 2.0
|
||||||
|
|
||||||
|
WallpaperItem {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
contextualActions: [
|
||||||
|
PlasmaCore.Action {
|
||||||
|
text: i18nd("plasma_wallpaper_org.kde.potd", "Open Wallpaper Image")
|
||||||
|
icon.name: "document-open"
|
||||||
|
onTriggered: Qt.openUrlExternally(backend.localUrl);
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
QQC2.StackView {
|
||||||
|
id: imageView
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
readonly property int fillMode: root.configuration.FillMode
|
||||||
|
readonly property size sourceSize: Qt.size(imageView.width * Screen.devicePixelRatio, imageView.height * Screen.devicePixelRatio)
|
||||||
|
property Item pendingImage
|
||||||
|
property bool doesSkipAnimation: true
|
||||||
|
|
||||||
|
onFillModeChanged: Qt.callLater(imageView.loadImage)
|
||||||
|
onSourceSizeChanged: Qt.callLater(imageView.loadImage)
|
||||||
|
|
||||||
|
function loadImage() {
|
||||||
|
if (backend.localUrl.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (imageView.pendingImage) {
|
||||||
|
imageView.pendingImage.statusChanged.disconnect(replaceWhenLoaded);
|
||||||
|
imageView.pendingImage.destroy();
|
||||||
|
imageView.pendingImage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageView.doesSkipAnimation = imageView.empty || sourceSize !== imageView.currentItem.sourceSize;
|
||||||
|
imageView.pendingImage = imageComponent.createObject(imageView, {
|
||||||
|
"source": backend.localUrl,
|
||||||
|
"fillMode": imageView.fillMode,
|
||||||
|
"opacity": imageView.doesSkipAnimation ? 1 : 0,
|
||||||
|
"sourceSize": imageView.sourceSize,
|
||||||
|
"width": imageView.width,
|
||||||
|
"height": imageView.height,
|
||||||
|
});
|
||||||
|
imageView.pendingImage.statusChanged.connect(imageView.replaceWhenLoaded);
|
||||||
|
imageView.replaceWhenLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceWhenLoaded() {
|
||||||
|
if (imageView.pendingImage.status === Image.Loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
imageView.pendingImage.statusChanged.disconnect(imageView.replaceWhenLoaded);
|
||||||
|
imageView.replace(imageView.pendingImage, {}, imageView.doesSkipAnimation ? QQC2.StackView.Immediate : QQC2.StackView.Transition);
|
||||||
|
imageView.pendingImage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PotdBackend {
|
||||||
|
id: backend
|
||||||
|
identifier: root.configuration.Provider
|
||||||
|
arguments: {
|
||||||
|
if (identifier === "bing") {
|
||||||
|
// Bing supports 1366/1920/UHD resolutions
|
||||||
|
const w = imageView.sourceSize.width > 1920 ? 3840 : 1920;
|
||||||
|
const h = imageView.sourceSize.height > 1080 ? 2160 : 1080;
|
||||||
|
return [w, h];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
updateOverMeteredConnection: root.configuration.UpdateOverMeteredConnection
|
||||||
|
|
||||||
|
onImageChanged: Qt.callLater(imageView.loadImage)
|
||||||
|
onLocalUrlChanged: Qt.callLater(imageView.loadImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: imageComponent
|
||||||
|
|
||||||
|
Image {
|
||||||
|
asynchronous: true
|
||||||
|
cache: false
|
||||||
|
autoTransform: true
|
||||||
|
smooth: true
|
||||||
|
|
||||||
|
QQC2.StackView.onActivated: root.accentColorChanged()
|
||||||
|
QQC2.StackView.onDeactivated: destroy()
|
||||||
|
QQC2.StackView.onRemoved: destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: backgroundColor
|
||||||
|
anchors.fill: parent
|
||||||
|
color: root.configuration.Color
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Kirigami.Units.longDuration }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceEnter: Transition {
|
||||||
|
OpacityAnimator {
|
||||||
|
id: replaceEnterOpacityAnimator
|
||||||
|
to: 1
|
||||||
|
// As the wallpaper is updated once a day, the transition should be longer.
|
||||||
|
duration: Math.round(Kirigami.Units.veryLongDuration * 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Keep the old image around till the new one is fully faded in
|
||||||
|
// If we fade both at the same time you can see the background behind glimpse through
|
||||||
|
replaceExit: Transition {
|
||||||
|
PauseAnimation {
|
||||||
|
// 500: The exit transition starts first and can be completed earlier than the enter transition
|
||||||
|
duration: replaceEnterOpacityAnimator.duration + 500
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
metadata.json
Normal file
19
metadata.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"KPackageStructure": "Plasma/Wallpaper",
|
||||||
|
"KPlugin": {
|
||||||
|
"Authors": [
|
||||||
|
{
|
||||||
|
"Email": "potd@johnbotr.is",
|
||||||
|
"Name": "John Botris"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"BugReportUrl": "https://google.com",
|
||||||
|
"Description": "A new picture from the Internet each day",
|
||||||
|
"EnabledByDefault": true,
|
||||||
|
"Icon": "office-calendar",
|
||||||
|
"Id": "botris.dev.potd",
|
||||||
|
"License": "LGPL-2.1",
|
||||||
|
"Name": "My Picture of the day",
|
||||||
|
"Website": "https://kde.org/"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue