@ -19,22 +19,21 @@
* /
import QtQuick 2.5
import QtQuick . Controls 2.1 as QQC2
import QtQuick . Window 2.2
import QtGraphicalEffects 1.0
import org . kde . plasma . wallpapers . image 2.0 as Wallpaper
import org . kde . plasma . core 2.0 as PlasmaCore
Item {
QQC2 . StackView {
id: root
readonly property string configuredImage: wallpaper . configuration . Image
readonly property string modelImage: imageWallpaper . wallpaperPath
property Item currentImage: imageB
property Item currentBlurBackground: blurBackgroundB
property Item otherImage: imageA
property Item otherBlurBackground: blurBackgroundA
readonly property string configuredImage: wallpaper . configuration . Image
readonly property int fillMode: wallpaper . configuration . FillMode
property size sourceSize: Qt . size ( root . width * Screen . devicePixelRatio , root . height * Screen . devicePixelRatio )
readonly property string configColor: wallpaper . configuration . Color
readonly property bool blur: wallpaper . configuration . Blur
readonly property size sourceSize: Qt . size ( root . width * Screen . devicePixelRatio , root . height * Screen . devicePixelRatio )
/ / p u b l i c A P I , t h e C + + p a r t w i l l l o o k f o r t h o s e
function setUrl ( url ) {
@ -51,128 +50,10 @@ Item {
}
/ / p r i v a t e
function setupImage ( ) {
currentImage . sourceSize = root . sourceSize ;
currentImage . fillMode = root . fillMode ;
currentImage . source = modelImage ;
}
function fadeWallpaper ( ) {
if ( startupTimer . running ) {
setupImage ( ) ;
return ;
}
fadeAnim . running = false
swapImages ( )
currentImage . source = modelImage
currentImage . sourceSize = root . sourceSize
/ / P r e v e n t s o u r c e s i z e c h a n g e w h e n i m a g e h a s j u s t b e e n s e t u p a n y w a y
sourceSizeTimer . stop ( )
currentImage . opacity = 0
currentBlurBackground . opacity = 0
otherImage . z = 0
currentImage . z = 1
/ / o n l y c r o s s - f a d e i f t h e n e w i m a g e c o u l d b e s m a l l e r t h a n t h e o l d o n e
fadeOtherAnimator . enabled = Qt . binding ( function ( ) {
return currentImage . paintedWidth < otherImage . paintedWidth || currentImage . paintedHeight < otherImage . paintedHeight
} )
/ / A l l e v i a t e s t u t t e r i n g b y w a i t i n g w i t h t h e f a d e a n i m a t i o n u n t i l t h e i m a g e i s l o a d e d ( o r f a i l e d t o )
fadeAnim . running = Qt . binding ( function ( ) {
return currentImage . status !== Image . Loading && otherImage . status !== Image . Loading
} )
}
function fadeFillMode ( ) {
if ( startupTimer . running ) {
setupImage ( ) ;
return ;
}
fadeAnim . running = false
swapImages ( )
currentImage . sourceSize = root . sourceSize
sourceSizeTimer . stop ( )
currentImage . source = modelImage
currentImage . opacity = 0
currentBlurBackground . opacity = 0
otherImage . z = 0
currentImage . fillMode = fillMode
currentImage . z = 1
/ / o n l y c r o s s - f a d e i f t h e n e w i m a g e c o u l d b e s m a l l e r t h a n t h e o l d o n e
fadeOtherAnimator . enabled = Qt . binding ( function ( ) {
return currentImage . paintedWidth < otherImage . paintedWidth || currentImage . paintedHeight < otherImage . paintedHeight
} )
fadeAnim . running = Qt . binding ( function ( ) {
return currentImage . status !== Image . Loading && otherImage . status !== Image . Loading
} )
}
function fadeSourceSize ( ) {
if ( currentImage . sourceSize === root . sourceSize ) {
return
}
if ( startupTimer . running ) {
setupImage ( ) ;
return ;
}
fadeAnim . running = false
swapImages ( )
currentImage . sourceSize = root . sourceSize
currentImage . opacity = 0
currentBlurBackground . opacity = 0
currentImage . source = otherImage . source
otherImage . z = 0
currentImage . z = 1
fadeOtherAnimator . enabled = false / / t h e i m a g e s i z e d i d n ' t c h a n g e , a v o i d c r o s s - d i s s o l v e
fadeAnim . running = Qt . binding ( function ( ) {
return currentImage . status !== Image . Loading && otherImage . status !== Image . Loading
} )
}
function startFadeSourceTimer ( ) {
if ( width > 0 && height > 0 && ( imageA . status !== Image . Null || imageB . status !== Image . Null ) ) {
sourceSizeTimer . restart ( )
}
}
function swapImages ( ) {
if ( currentImage == imageA ) {
currentImage = imageB
currentBlurBackground = blurBackgroundB
otherImage = imageA
otherBlurBackground = blurBackgroundA
} else {
currentImage = imageA
currentBlurBackground = blurBackgroundA
otherImage = imageB
otherBlurBackground = blurBackgroundB
}
}
onWidthChanged: startFadeSourceTimer ( )
onHeightChanged: startFadeSourceTimer ( )
/ / H A C K p r e v e n t f a d e s a n d t r a n s i t i o n s d u r i n g s t a r t u p
Timer {
id: startupTimer
interval: 100
running: true
}
Timer {
id: sourceSizeTimer
interval: 1000 / / a l w a y s d e l a y r e l o a d i n g t h e i m a g e e v e n w h e n a n i m a t i o n s a r e t u r n e d o f f
onTriggered: fadeSourceSize ( )
onConfiguredImageChanged: {
imageWallpaper . addUrl ( configuredImage )
}
Component.onCompleted: {
if ( wallpaper . pluginName == "org.kde.slideshow" ) {
wallpaper . setAction ( "open" , i18n ( "Open Wallpaper Image" ) , "document-open" ) ;
@ -189,130 +70,79 @@ Item {
slideTimer: wallpaper . configuration . SlideInterval
}
onFillModeChanged: {
fadeFillMode ( ) ;
}
onConfiguredImageChanged: {
imageWallpaper . addUrl ( configuredImage )
}
onModelImageChanged: {
fadeWallpaper ( ) ;
onFillModeChanged: Qt . callLater ( loadImage ) ;
onModelImageChanged: Qt . callLater ( loadImage ) ;
onConfigColorChanged: Qt . callLater ( loadImage ) ;
onBlurChanged: Qt . callLater ( loadImage ) ;
onWidthChanged: Qt . callLater ( loadImage ) ;
onHeightChanged: Qt . callLater ( loadImage ) ;
function loadImage ( ) {
var isFirst = ( root . currentItem == undefined ) ;
var pendingImage = baseImage . createObject ( root , { "source" : root . modelImage ,
"fillMode" : root . fillMode ,
"sourceSize" : root . sourceSize ,
"color" : root . configColor ,
"blur" : root . blur ,
"opacity" : isFirst ? 1 : 0 } ) ;
function replaceWhenLoaded ( ) {
if ( pendingImage . status != Image . Loading ) {
root . replace ( pendingImage , { } ,
isFirst ? QQC2.StackView.Immediate : QQC2 . StackView . Transition ) ; / / d o n t ' a n i m a t e f i r s t s h o w
pendingImage . statusChanged . disconnect ( replaceWhenLoaded ) ;
}
}
pendingImage . statusChanged . connect ( replaceWhenLoaded ) ;
replaceWhenLoaded ( ) ;
}
SequentialAnimation {
id: fadeAnim
running: false
Component {
id: baseImage
ParallelAnimation {
OpacityAnimator {
target: currentBlurBackground
from: 0
to: 1
duration: fadeOtherAnimator . duration
}
OpacityAnimator {
target: otherBlurBackground
from: 1
/ / c a n n o t d i s a b l e a n a n i m a t i o n i n d i v i d u a l l y , s o w e j u s t f a d e f r o m 1 t o 1
to: enabled ? 0 : 1
Image {
id: mainImage
/ / u s e c o n f i g u r e d d u r a t i o n i f a n i m a t i o n s a r e e n a b l e d
duration: units . longDuration && wallpaper . configuration . TransitionAnimationDuration
}
OpacityAnimator {
target: currentImage
from: 0
to: 1
duration: fadeOtherAnimator . duration
}
OpacityAnimator {
id: fadeOtherAnimator
property bool enabled: true
target: otherImage
from: 1
/ / c a n n o t d i s a b l e a n a n i m a t i o n i n d i v i d u a l l y , s o w e j u s t f a d e f r o m 1 t o 1
to: enabled ? 0 : 1
property alias color: backgroundColor . color
property alias blur: blurEffect . visible
asynchronous: true
cache: false
autoTransform: true
z: - 1
QQC2.StackView.onRemoved: destroy ( )
/ / u s e c o n f i g u r e d d u r a t i o n i f a n i m a t i o n s a r e e n a b l e d
duration: units . longDuration && wallpaper . configuration . TransitionAnimationDuration
Rectangle {
id: backgroundColor
anchors.fill: parent
visible: mainImage . status === Image . Ready
z: - 2
}
}
ScriptAction {
script: {
otherImage . source = "" ;
otherImage . fillMode = fillMode ;
GaussianBlur {
id: blurEffect
anchors.fill: parent
source: mainImage
radius: 32
samples: 65
z: mainImage . z
}
}
}
Rectangle {
id: backgroundColor
anchors.fill: parent
visible: currentImage . status === Image . Ready || otherImage . status === Image . Ready
color: wallpaper . configuration . Color
Behavior on color {
ColorAnimation { duration: units . longDuration }
enabled: ! startupTimer . running
replaceEnter: Transition {
OpacityAnimator {
from: 0
to: 1
duration: wallpaper . configuration . TransitionAnimationDuration
}
}
Image {
id: blurBackgroundSourceA
visible: wallpaper . configuration . Blur
anchors.fill: parent
asynchronous: true
cache: false
fillMode: Image . PreserveAspectCrop
source: imageA . source
z: - 1
}
GaussianBlur {
id: blurBackgroundA
visible: wallpaper . configuration . Blur
anchors.fill: parent
source: blurBackgroundSourceA
radius: 32
samples: 65
z: imageA . z
}
Image {
id: blurBackgroundSourceB
visible: wallpaper . configuration . Blur
anchors.fill: parent
asynchronous: true
cache: false
fillMode: Image . PreserveAspectCrop
source: imageB . source
z: - 1
}
GaussianBlur {
id: blurBackgroundB
visible: wallpaper . configuration . Blur
anchors.fill: parent
source: blurBackgroundSourceB
radius: 32
samples: 65
z: imageB . z
}
Image {
id: imageA
anchors.fill: parent
asynchronous: true
cache: false
fillMode: wallpaper . configuration . FillMode
autoTransform: true / / n e w A P I i n Q t 5 . 5 , d o n o t b a c k p o r t i n t o P l a s m a 5 . 4 .
}
Image {
id: imageB
anchors.fill: parent
asynchronous: true
cache: false
fillMode: wallpaper . configuration . FillMode
autoTransform: true / / n e w A P I i n Q t 5 . 5 , d o n o t b a c k p o r t i n t o P l a s m a 5 . 4 .
/ / K e e p t h e o l d i m a g e a r o u n d t i l l t h e n e w o n e i s f u l l y f a d e d i n
/ / I f w e f a d e b o t h a t t h e s a m e t i m e y o u c a n s e e t h e b a c k g r o u n d b e h i n d g l i m p s e t h r o u g h
replaceExit: Transition {
PauseAnimation {
duration: wallpaper . configuration . TransitionAnimationDuration
}
}
}