Verified Commit 6e43d469 authored by Fushan Wen's avatar Fushan Wen 💬
Browse files

wallpapers/image: add animated image support

FEATURE: 454984
FIXED-IN: 5.26
parent 013ad033
Pipeline #192198 passed with stage
in 11 minutes and 43 seconds
......@@ -97,14 +97,36 @@ QQC2.StackView {
onConfigColorChanged: Qt.callLater(loadImage);
onBlurChanged: Qt.callLater(loadImage);
property Component staticImageComponent
property Component animatedImageComponent
function createBackgroundComponent() {
switch (mediaProxy.backgroundType) {
case Wallpaper.BackgroundType.Image: {
if (!staticImageComponent) {
staticImageComponent = Qt.createComponent("mediacomponent/StaticImageComponent.qml");
}
return staticImageComponent;
}
case Wallpaper.BackgroundType.AnimatedImage: {
if (!animatedImageComponent) {
animatedImageComponent = Qt.createComponent("mediacomponent/AnimatedImageComponent.qml");
}
return animatedImageComponent;
}
}
}
function loadImageImmediately() {
loadImage(true);
}
function loadImage(skipAnimation) {
const _skipAnimation = root.currentItem == undefined || !!skipAnimation;
const baseImage = Qt.createComponent("mediacomponent/ImageComponent.qml");
var pendingImage = baseImage.createObject(root, { "source": root.modelImage,
const baseImage = createBackgroundComponent();
var pendingImage = baseImage.createObject(root, {
// Use mediaProxy instead of root because colorSchemeChanged needs immediately update the wallpaper
"source": mediaProxy.modelImage,
"fillMode": root.fillMode,
"sourceSize": root.sourceSize,
"color": root.configColor,
......
/*
SPDX-FileCopyrightText: 2022 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Window 2.15
import org.kde.plasma.wallpapers.image 2.0 as PlasmaWallpaper
import org.kde.kwindowsystem 1.0
BaseMediaComponent {
id: animatedImageComponent
readonly property rect desktopRect: Qt.rect(Window.window.x, Window.window.y, Window.window.width, Window.window.height)
readonly property alias status: mainImage.status
blurSource: blurLoader.item
KWindowSystem {
id: kwindowsystem
}
PlasmaWallpaper.MaximizedWindowMonitor {
id: activeWindowMonitor
targetRect: animatedImageComponent.desktopRect
}
AnimatedImage {
id: mainImage
anchors.fill: parent
asynchronous: true
cache: false
autoTransform: true
fillMode: animatedImageComponent.fillMode
source: animatedImageComponent.source
// sourceSize is read-only
// https://github.com/qt/qtdeclarative/blob/23b4ab24007f489ac7c2b9ceabe72fa625a51f3d/src/quick/items/qquickanimatedimage_p.h#L39
paused: activeWindowMonitor.count > 0 && !kwindowsystem.showingDesktop
}
Loader {
id: blurLoader
anchors.fill: parent
active: animatedImageComponent.blurEnabled
sourceComponent: Image {
asynchronous: true
cache: false
autoTransform: true
fillMode: Image.PreserveAspectCrop
source: mainImage.source
sourceSize: animatedImageComponent.sourceSize
visible: false // will be rendered by the blur
}
}
}
/*
SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
SPDX-FileCopyrightText: 2014 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2014 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import QtGraphicalEffects 1.15
Rectangle {
id: backgroundColor
color: "black"
z: -2
property bool blur: false
required property url source
property int fillMode
required property size sourceSize
/**
* This defines the item that will be blurred and used in the background
*/
property var blurSource
readonly property bool blurEnabled: backgroundColor.blur
&& (backgroundColor.fillMode === Image.PreserveAspectFit || backgroundColor.fillMode === Image.Pad)
Loader {
anchors.fill: parent
active: blurEnabled
visible: active
z: 0
sourceComponent: GaussianBlur {
source: backgroundColor.blurSource
radius: 32
samples: 65
}
}
}
......@@ -7,58 +7,39 @@
*/
import QtQuick 2.15
import QtGraphicalEffects 1.15
Rectangle {
id: backgroundColor
BaseMediaComponent {
id: staticImageComponent
color: "black"
z: -2
readonly property alias status: mainImage.status
property bool blur: false
property alias mainImage: mainImage
property alias source: mainImage.source
property alias fillMode: mainImage.fillMode
property alias sourceSize: mainImage.sourceSize
property alias status: mainImage.status
blurSource: blurLoader.item
Image {
id: mainImage
anchors.fill: parent
asynchronous: true
cache: false
autoTransform: true
z: 0
fillMode: staticImageComponent.fillMode
source: staticImageComponent.source
sourceSize: staticImageComponent.sourceSize
}
Loader {
id: blurLoader
anchors.fill: parent
z: -1
active: backgroundColor.blur && (mainImage.fillMode === Image.PreserveAspectFit || mainImage.fillMode === Image.Pad)
visible: active
sourceComponent: Item {
Image {
id: blurSource
anchors.fill: parent
asynchronous: true
cache: false
autoTransform: true
fillMode: Image.PreserveAspectCrop
source: mainImage.source
sourceSize: mainImage.sourceSize
visible: false // will be rendered by the blur
}
GaussianBlur {
id: blurEffect
anchors.fill: parent
source: blurSource
radius: 32
samples: 65
visible: blurSource.status === Image.Ready
}
z: 0
active: blurEnabled
sourceComponent: Image {
asynchronous: true
cache: false
autoTransform: true
fillMode: Image.PreserveAspectCrop
source: mainImage.source
sourceSize: mainImage.sourceSize
visible: false // will be rendered by the blur
}
}
}
......@@ -16,6 +16,7 @@ set(image_SRCS
model/imageproxymodel.cpp
provider/packageimageprovider.cpp
provider/providertype.h
utils/backgroundtype.h
utils/maximizedwindowmonitor.cpp
utils/mediaproxy.cpp
)
......
......@@ -37,5 +37,7 @@ void ImagePlugin::registerTypes(const char *uri)
qmlRegisterType<MaximizedWindowMonitor>(uri, 2, 0, "MaximizedWindowMonitor");
qmlRegisterAnonymousType<QAbstractItemModel>("QAbstractItemModel", 1);
qmlRegisterUncreatableType<BackgroundType>(uri, 2, 0, "BackgroundType", QStringLiteral("error: only enums"));
qmlRegisterUncreatableType<SortingMode>(uri, 2, 0, "SortingMode", QStringLiteral("error: only enums"));
}
/*
SPDX-FileCopyrightText: 2022 Fushan Wen <qydwhotmail@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
class BackgroundType
{
Q_GADGET
public:
enum class Type {
Unknown,
Image,
AnimatedImage, /**< AnimatedImage doesn't support \QQuickImageProvider , @see https://bugreports.qt.io/browse/QTBUG-30524 */
};
Q_ENUM(Type)
};
......@@ -8,6 +8,8 @@
#include <QFileInfo>
#include <QGuiApplication>
#include <QMimeDatabase>
#include <QMovie>
#include <QScreen>
#include <QUrlQuery>
......@@ -54,7 +56,8 @@ QString MediaProxy::source() const
void MediaProxy::setSource(const QString &url)
{
if (m_source.toString() == url) {
// New desktop has empty url
if (url.isEmpty() || m_source.toString() == url) {
return;
}
......@@ -63,6 +66,8 @@ void MediaProxy::setSource(const QString &url)
Q_EMIT sourceChanged();
determineProviderType();
determineBackgroundType();
updateModelImage();
}
......@@ -172,6 +177,7 @@ void MediaProxy::useSingleImageDefaults()
Q_EMIT sourceChanged();
determineProviderType();
determineBackgroundType();
updateModelImage();
}
......@@ -199,6 +205,11 @@ void MediaProxy::slotSystemPaletteChanged(const QPalette &palette)
}
m_isDarkColorScheme = dark;
if (m_providerType == Provider::Type::Package) {
updateModelImageWithoutSignal();
}
Q_EMIT colorSchemeChanged();
}
......@@ -211,6 +222,30 @@ bool MediaProxy::isDarkColorScheme(const QPalette &palette) const noexcept
return qGray(palette.window().color().rgb()) < 192;
}
void MediaProxy::determineBackgroundType()
{
QString filePath;
if (m_providerType == Provider::Type::Package) {
filePath = findPreferredImageInPackage().toLocalFile();
} else {
filePath = m_formattedSource.toLocalFile();
}
QMimeDatabase db;
const QString type = db.mimeTypeForFile(filePath).name();
if (QMovie::supportedFormats().contains(QFileInfo(filePath).suffix().toLower().toLatin1())) {
// Derived from the suffix
m_backgroundType = BackgroundType::Type::AnimatedImage;
} else if (type.startsWith(QLatin1String("image/"))) {
m_backgroundType = BackgroundType::Type::Image;
} else {
m_backgroundType = BackgroundType::Type::Unknown;
}
Q_EMIT backgroundTypeChanged();
}
void MediaProxy::determineProviderType()
{
QFileInfo info(m_formattedSource.toLocalFile());
......@@ -249,7 +284,7 @@ QUrl MediaProxy::findPreferredImageInPackage()
return url;
}
void MediaProxy::updateModelImage()
void MediaProxy::updateModelImage(bool doesBlockSignal)
{
if (!m_ready) {
return;
......@@ -264,6 +299,12 @@ void MediaProxy::updateModelImage()
}
case Provider::Type::Package: {
if (m_backgroundType == BackgroundType::Type::AnimatedImage) {
// Is an animated image
newRealSource = findPreferredImageInPackage();
break;
}
// Use a custom image provider
QUrl composedUrl(QStringLiteral("image://package/get"));
......@@ -288,5 +329,12 @@ void MediaProxy::updateModelImage()
}
m_modelImage = newRealSource;
Q_EMIT modelImageChanged();
if (!doesBlockSignal) {
Q_EMIT modelImageChanged();
}
}
void MediaProxy::updateModelImageWithoutSignal()
{
updateModelImage(true);
}
......@@ -14,6 +14,7 @@
#include <QUrl>
#include "../provider/providertype.h"
#include "backgroundtype.h"
/**
* A proxy class that converts a provider url to a real resource url.
......@@ -36,6 +37,11 @@ class MediaProxy : public QObject, public QQmlParserStatus, public Provider
*/
Q_PROPERTY(QUrl modelImage READ modelImage NOTIFY modelImageChanged)
/**
* Type of the current wallpaper
*/
Q_PROPERTY(BackgroundType::Type backgroundType MEMBER m_backgroundType NOTIFY backgroundTypeChanged)
Q_PROPERTY(QSize targetSize READ targetSize WRITE setTargetSize NOTIFY targetSizeChanged)
public:
......@@ -63,6 +69,12 @@ public:
Q_SIGNALS:
void sourceChanged();
void modelImageChanged();
/**
* Emitted when the type of the current wallpaper changes.
*/
void backgroundTypeChanged();
void targetSizeChanged(const QSize &size);
/**
......@@ -83,16 +95,19 @@ private Q_SLOTS:
private:
inline bool isDarkColorScheme(const QPalette &palette = {}) const noexcept;
void determineBackgroundType();
void determineProviderType();
QUrl findPreferredImageInPackage();
void updateModelImage();
void updateModelImage(bool doesBlockSignal = false);
void updateModelImageWithoutSignal();
bool m_ready = false;
QUrl m_source;
QUrl m_formattedSource;
QUrl m_modelImage;
BackgroundType::Type m_backgroundType = BackgroundType::Type::Unknown;
Provider::Type m_providerType = Provider::Type::Unknown;
QSize m_targetSize;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment