Warning, /plasma/plasma-workspace/wallpapers/image/imagepackage/contents/ui/ImageStackView.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
0003 SPDX-FileCopyrightText: 2014 Sebastian Kügler <sebas@kde.org>
0004 SPDX-FileCopyrightText: 2014 Kai Uwe Broulik <kde@privat.broulik.de>
0005
0006 SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008
0009 import QtQuick
0010 import QtQuick.Controls as QQC2
0011 import org.kde.plasma.wallpapers.image as Wallpaper
0012 import org.kde.kirigami as Kirigami
0013
0014 QQC2.StackView {
0015 id: view
0016
0017 required property int fillMode
0018 required property string configColor
0019 required property bool blur
0020 property alias source: mediaProxy.source
0021 required property size sourceSize
0022 required property QtObject wallpaperInterface
0023
0024 readonly property alias mediaProxy: mediaProxy
0025 readonly property url modelImage: mediaProxy.modelImage
0026
0027 /**
0028 * Stores pending image here to avoid the default image overriding the true image.
0029 *
0030 * @see BUG 456189
0031 */
0032 property Item pendingImage
0033
0034 property bool doesSkipAnimation: true
0035
0036 property Component staticImageComponent
0037 property Component animatedImageComponent
0038
0039 onFillModeChanged: Qt.callLater(loadImage);
0040 onModelImageChanged: Qt.callLater(loadImage);
0041 onConfigColorChanged: Qt.callLater(loadImage);
0042 onBlurChanged: Qt.callLater(loadImage);
0043
0044 function createBackgroundComponent() {
0045 switch (mediaProxy.backgroundType) {
0046 case Wallpaper.BackgroundType.Image: {
0047 if (!staticImageComponent) {
0048 staticImageComponent = Qt.createComponent("mediacomponent/StaticImageComponent.qml");
0049 }
0050 return staticImageComponent;
0051 }
0052 case Wallpaper.BackgroundType.AnimatedImage: {
0053 if (!animatedImageComponent) {
0054 animatedImageComponent = Qt.createComponent("mediacomponent/AnimatedImageComponent.qml");
0055 }
0056 return animatedImageComponent;
0057 }
0058 }
0059 }
0060
0061 function loadImageImmediately() {
0062 loadImage(true);
0063 }
0064
0065 function loadImage(skipAnimation) {
0066 if (pendingImage) {
0067 pendingImage.statusChanged.disconnect(replaceWhenLoaded);
0068 pendingImage.destroy();
0069 pendingImage = null;
0070 }
0071
0072 if (mediaProxy.providerType == Wallpaper.Provider.Unknown) {
0073 console.error("The backend got an unknown wallpaper provider type. The wallpaper will now fall back to the default. Please check your wallpaper configuration!");
0074 mediaProxy.useSingleImageDefaults();
0075 return;
0076 }
0077
0078 doesSkipAnimation = view.currentItem == undefined || view.currentItem.sourceSize !== view.sourceSize || !!skipAnimation;
0079 const baseImage = createBackgroundComponent();
0080 pendingImage = baseImage.createObject(view, {
0081 // Use mediaProxy instead of view because colorSchemeChanged needs immediately update the wallpaper
0082 "source": mediaProxy.modelImage,
0083 "fillMode": view.fillMode,
0084 "sourceSize": view.sourceSize,
0085 "color": view.configColor,
0086 "blur": view.blur,
0087 "opacity": 0,
0088 "width": view.width,
0089 "height": view.height,
0090 });
0091
0092 pendingImage.statusChanged.connect(replaceWhenLoaded);
0093 replaceWhenLoaded();
0094 }
0095
0096 function replaceWhenLoaded() {
0097 if (pendingImage.status === Image.Loading) {
0098 return;
0099 }
0100
0101 pendingImage.statusChanged.disconnect(replaceWhenLoaded);
0102 // BUG 454908: Update accent color
0103 pendingImage.QQC2.StackView.onActivated.connect(() => {
0104 if (Qt.colorEqual(mediaProxy.customColor, "transparent") && Qt.colorEqual(wallpaperInterface.accentColor, "transparent")) {
0105 wallpaperInterface.accentColorChanged();
0106 } else {
0107 wallpaperInterface.accentColor = mediaProxy.customColor;
0108 }
0109 });
0110
0111 // onRemoved only fires when all transitions end. If a user switches wallpaper quickly this adds up
0112 // Given it's such a heavy item, try to cleanup as early as possible
0113 pendingImage.QQC2.StackView.onDeactivated.connect(pendingImage.destroy);
0114 pendingImage.QQC2.StackView.onRemoved.connect(pendingImage.destroy);
0115 view.replace(pendingImage, {}, QQC2.StackView.Transition);
0116
0117 wallpaperInterface.loading = false;
0118
0119 if (pendingImage.status !== Image.Ready) {
0120 mediaProxy.useSingleImageDefaults();
0121 }
0122
0123 pendingImage = null;
0124 }
0125
0126 replaceEnter: Transition {
0127 OpacityAnimator {
0128 id: replaceEnterOpacityAnimator
0129 from: 0
0130 to: 1
0131 // The value is to keep compatible with the old feeling defined by "TransitionAnimationDuration" (default: 1000)
0132 // 1 is HACK for https://bugreports.qt.io/browse/QTBUG-106797 to avoid flickering
0133 duration: view.doesSkipAnimation ? 1 : Math.round(Kirigami.Units.veryLongDuration * 2.5)
0134 }
0135 }
0136 // Keep the old image around till the new one is fully faded in
0137 // If we fade both at the same time you can see the background behind glimpse through
0138 replaceExit: Transition{
0139 PauseAnimation {
0140 // 500: The exit transition starts first and can be completed earlier than the enter transition
0141 duration: replaceEnterOpacityAnimator.duration + 500
0142 }
0143 }
0144
0145 Wallpaper.MediaProxy {
0146 id: mediaProxy
0147
0148 targetSize: view.sourceSize
0149
0150 onActualSizeChanged: Qt.callLater(loadImageImmediately);
0151 onColorSchemeChanged: loadImageImmediately();
0152 onSourceFileUpdated: loadImageImmediately()
0153 }
0154 }