2 * kate: space-indent on; tab-width 8; indent-width 4; indent-mode cstyle;
4 * This file is part of the KDE project, module kdesktop.
5 * Copyright (C) 1999 Geert Jansen <g.t.jansen@stud.tue.nl>
7 * You can Freely distribute this program under the GNU Library General
8 * Public License. See the file "COPYING.LIB" for the exact licensing terms.
13 #include <config-workspace.h>
24 #include <QDesktopWidget>
25 #include <QPaintEngine>
30 #include <kapplication.h>
33 #include <kstandarddirs.h>
34 #include <qimageblitz.h>
35 #include <ktemporaryfile.h>
37 #include <kfilemetainfo.h>
39 #include <kconfiggroup.h>
40 #include <ksvgrenderer.h>
41 #include <kmacroexpander.h>
43 #include "bgdefaults.h"
49 /**** KBackgroundRenderer ****/
52 KBackgroundRenderer::KBackgroundRenderer(int screen
, bool drawBackgroundPerScreen
, const KSharedConfigPtr
&config
)
53 : KBackgroundSettings(screen
, drawBackgroundPerScreen
, config
)
56 m_isBusyCursor
= false;
57 m_enableBusyCursor
= false;
58 m_pDirs
= KGlobal::dirs();
59 m_rSize
= m_Size
= drawBackgroundPerScreen
?
60 QApplication::desktop()->screenGeometry(screen
).size() : QApplication::desktop()->size();
65 m_TilingEnabled
= false;
67 m_pTimer
= new QTimer(this);
68 m_pTimer
->setSingleShot(true);
69 connect(m_pTimer
, SIGNAL(timeout()), SLOT(render()));
73 KBackgroundRenderer::~KBackgroundRenderer()
81 void KBackgroundRenderer::setSize(const QSize
&size
)
83 m_rSize
= m_Size
= size
;
87 * Re-configure because the desktop has been resized.
89 void KBackgroundRenderer::desktopResized()
92 m_rSize
= drawBackgroundPerScreen() ?
93 QApplication::desktop()->screenGeometry(screen()).size() : QApplication::desktop()->size();
99 void KBackgroundRenderer::tile(QImage
& dest
, const QRect
&_rect
, const QImage
& src
)
105 int h
= rect
.height(), w
= rect
.width();
106 int offx
= rect
.x(), offy
= rect
.y();
107 int sw
= src
.width(), sh
= src
.height();
109 for (y
=offy
; y
<offy
+h
; y
++)
110 for (x
=offx
; x
<offx
+w
; x
++)
111 dest
.setPixel(x
, y
, src
.pixel(x
%sw
, y
%sh
));
116 * Build a command line to run the program.
119 QString
KBackgroundRenderer::buildCommand()
123 cmd
= previewCommand();
130 QHash
<QChar
, QString
> map
;
131 map
.insert('f', m_Tempfile
->fileName());
132 map
.insert('x', QString::number(m_Size
.width()));
133 map
.insert('y', QString::number(m_Size
.height()));
134 return KMacroExpander::expandMacrosShellQuote(cmd
, map
);
139 * Create a background tile. If the background mode is `Program',
140 * this is asynchronous.
142 int KBackgroundRenderer::doBackground(bool quit
)
144 if (m_State
& BackgroundDone
)
146 int bgmode
= backgroundMode();
152 if (bgmode
== Program
&& m_pProc
)
153 m_pProc
->terminate();
160 static unsigned int tileWidth
= 0;
161 static unsigned int tileHeight
= 0;
164 int tile_val
= QPixmap::defaultDepth() >= 24 ? 1 : 2;
165 // some dithering may be needed even with bpb==15/16, so don't use tileWidth==1
167 // with tileWidth>2, repainting the desktop causes nasty effect (XFree86 4.1.0 )
168 if( XQueryBestTile( QX11Info::display(), QX11Info::appRootWindow(), tile_val
, tile_val
,
169 &tileWidth
, &tileHeight
) != Success
)
170 tileWidth
= tileHeight
= tile_val
; // some defaults
175 // this can be tiled correctly without problems
176 m_Background
= QImage( tileWidth
, tileHeight
, QImage::Format_RGB32
);
177 m_Background
.fill(colorA().rgb());
182 if (pattern().isEmpty())
184 file
= m_pDirs
->findResource("dtop_pattern", pattern());
188 m_Background
.load(file
);
189 if (m_Background
.isNull())
191 int w
= m_Background
.width();
192 int h
= m_Background
.height();
193 if ((w
> m_Size
.width()) || (h
> m_Size
.height())) {
194 w
= qMin(w
, m_Size
.width());
195 h
= qMin(h
, m_Size
.height());
196 m_Background
= m_Background
.copy(0, 0, w
, h
);
198 Blitz::flatten(m_Background
, colorA(), colorB());
202 if (m_State
& BackgroundStarted
)
204 m_State
|= BackgroundStarted
;
207 file
= buildCommand();
212 m_pProc
= new KProcess
;
213 m_pProc
->setShellCommand(file
);
215 SIGNAL(finished(int, QProcess::ExitStatus
)),
216 SLOT(slotBackgroundDone(int, QProcess::ExitStatus
)));
221 case HorizontalGradient
:
224 // on <16bpp displays the gradient sucks when tiled because of dithering
226 size
.setHeight( tileHeight
);
227 m_Background
= Blitz::gradient(size
, colorA(), colorB(),
228 Blitz::HorizontalGradient
);
231 case VerticalGradient
:
234 // on <16bpp displays the gradient sucks when tiled because of dithering
236 size
.setWidth( tileWidth
);
237 m_Background
= Blitz::gradient(size
, colorA(), colorB(),
238 Blitz::VerticalGradient
);
241 case PyramidGradient
:
242 m_Background
= Blitz::gradient(m_Size
, colorA(), colorB(),
243 Blitz::PyramidGradient
);
246 case PipeCrossGradient
:
247 m_Background
= Blitz::gradient(m_Size
, colorA(), colorB(),
248 Blitz::PipeCrossGradient
);
251 case EllipticGradient
:
252 m_Background
= Blitz::gradient(m_Size
, colorA(), colorB(),
253 Blitz::EllipticGradient
);
258 m_State
|= BackgroundDone
;
264 int KBackgroundRenderer::doWallpaper(bool quit
)
266 if (m_State
& WallpaperDone
)
270 // currently no asynch. wallpapers
273 int wpmode
= enabled()?wallpaperMode():NoWallpaper
;
275 m_Wallpaper
= QImage();
276 if (wpmode
!= NoWallpaper
) {
278 if (currentWallpaper().isEmpty()) {
279 wpmode
= NoWallpaper
;
282 QString file
= m_pDirs
->findResource("wallpaper", currentWallpaper());
283 if (file
.isEmpty()) {
284 wpmode
= NoWallpaper
;
288 // _Don't_ use KMimeType, as it relies on ksycoca which we really
289 // don't want in krootimage (kdm context).
290 //if ( KMimeType::findByPath( file )->is( "image/svg+xml" ) ) {
291 if (file
.endsWith(".svg") || file
.endsWith(".svgz")) {
293 // Special stuff for SVG icons
296 //ksvgiconloader doesn't seem to let us find out the
297 //ratio of width to height so for the most part we just
298 //assume it's a square
305 svgHeight
= (int)(m_Size
.height() * 0.8);
306 svgWidth
= svgHeight
;
310 svgHeight
= (int)(m_Size
.height() * 0.5);
311 svgWidth
= svgHeight
;
314 svgHeight
= m_Size
.height();
315 svgWidth
= m_Size
.width();
320 svgHeight
= m_Size
.height();
321 svgWidth
= svgHeight
;
325 kWarning() << "unknown diagram type" ;
326 svgHeight
= m_Size
.height();
327 svgWidth
= svgHeight
;
330 //FIXME hack due to strangeness with
331 //background control modules
332 if ( svgHeight
< 200 ) {
337 KSvgRenderer
renderer(file
);
338 if (renderer
.isValid()) {
339 m_Wallpaper
= QImage(svgWidth
, svgHeight
, QImage::Format_ARGB32_Premultiplied
);
341 QPainter
p(&m_Wallpaper
);
345 m_Wallpaper
.load(file
);
347 if (m_Wallpaper
.isNull()) {
348 kWarning() << "failed to load wallpaper " << file
;
349 if (discardCurrentWallpaper())
351 wpmode
= NoWallpaper
;
354 m_Wallpaper
= m_Wallpaper
.convertToFormat(QImage::Format_ARGB32_Premultiplied
, Qt::DiffuseAlphaDither
);
356 // If we're previewing, scale the wallpaper down to make the preview
357 // look more like the real desktop.
359 int xs
= m_Wallpaper
.width() * m_Size
.width() / m_rSize
.width();
360 int ys
= m_Wallpaper
.height() * m_Size
.height() / m_rSize
.height();
361 if ((xs
< 1) || (ys
< 1))
365 if( m_WallpaperRect
.size() != QSize( xs
, ys
))
366 m_Wallpaper
= m_Wallpaper
.scaled(xs
, ys
, Qt::IgnoreAspectRatio
, Qt::SmoothTransformation
);
370 // HACK: Use KFileMetaInfo only when we have a KApplication
371 // KFileMetaInfo needs ksycoca and so on, but this code is
372 // used also in krootimage (which in turn is used by kdm).
374 KFileMetaInfo
metaInfo(file
);
375 if (metaInfo
.isValid() && metaInfo
.item("Orientation").isValid()) {
376 switch (metaInfo
.item("Orientation").value().toInt()) {
378 // Flipped horizontally
379 m_Wallpaper
.mirrored(true, false);
382 // Rotated 180 degrees
383 m_Wallpaper
= m_Wallpaper
.transformed(QMatrix().rotate(180));
386 // Flipped vertically
387 m_Wallpaper
= m_Wallpaper
.mirrored(false, true);
390 // Rotated 90 degrees & flipped horizontally
391 m_Wallpaper
= m_Wallpaper
.transformed(QMatrix().rotate(90)).mirrored(true, false);
394 // Rotated 90 degrees
395 m_Wallpaper
= m_Wallpaper
.transformed(QMatrix().rotate(90));
398 // Rotated 90 degrees & flipped vertically
399 m_Wallpaper
= m_Wallpaper
.transformed(QMatrix().rotate(90)).mirrored(false, true);
402 // Rotated 270 degrees
403 m_Wallpaper
= m_Wallpaper
.transformed(QMatrix().rotate(270));
407 // Normal or invalid orientation
416 if (m_Background
.isNull()) {
417 m_Background
= QImage(8, 8, QImage::Format_RGB32
);
418 m_Background
.fill(colorA().rgb());
423 // desktop width/height
424 int w
= m_Size
.width();
425 int h
= m_Size
.height();
427 // wallpaper width/height
428 int ww
= m_Wallpaper
.width();
429 int wh
= m_Wallpaper
.height();
431 // to be filled destination rectangle; may exceed desktop!
432 m_WallpaperRect
= QRect();
439 m_WallpaperRect
.setRect((w
- ww
) / 2, (h
- wh
) / 2, ww
, wh
);
442 m_WallpaperRect
.setRect(0, 0, w
, h
);
445 m_WallpaperRect
.setCoords(-ww
+ ((w
- ww
) / 2) % ww
, -wh
+ ((h
- wh
) / 2) % wh
, w
-1, h
-1);
450 if( m_WallpaperRect
.size() != QSize( w
, h
))
451 m_Wallpaper
= m_Wallpaper
.scaled( w
, h
, Qt::IgnoreAspectRatio
, Qt::SmoothTransformation
);
452 m_WallpaperRect
.setRect(0, 0, w
, h
);
455 if( ww
<= w
&& wh
<= h
) {
456 m_WallpaperRect
.setRect((w
- ww
) / 2, (h
- wh
) / 2, ww
, wh
); // like Centred
462 double sx
= (double) w
/ ww
;
463 double sy
= (double) h
/ wh
;
471 if( m_WallpaperRect
.size() != QSize( ww
, wh
))
472 m_Wallpaper
= m_Wallpaper
.scaled(ww
, wh
, Qt::IgnoreAspectRatio
, Qt::SmoothTransformation
);
473 m_WallpaperRect
.setRect((w
- ww
) / 2, (h
- wh
) / 2, ww
, wh
);
478 double sx
= (double) w
/ ww
;
479 double sy
= (double) h
/ wh
;
487 if( m_WallpaperRect
.size() != QSize( ww
, wh
))
488 m_Wallpaper
= m_Wallpaper
.scaled(ww
, wh
, Qt::IgnoreAspectRatio
, Qt::SmoothTransformation
);
489 m_WallpaperRect
.setRect(0, 0, w
, h
);
494 double sx
= (double) w
/ ww
;
495 double sy
= (double) h
/ wh
;
497 //Case 1: x needs bigger scaling. Lets increase x and leave part of y offscreen
501 //Case 2: y needs bigger scaling. Lets increase y and leave part of x offscreen
505 if( m_WallpaperRect
.size() != QSize( ww
, wh
))
506 m_Wallpaper
= m_Wallpaper
.scaled(ww
, wh
, Qt::IgnoreAspectRatio
, Qt::SmoothTransformation
);
507 m_WallpaperRect
.setRect((w
- ww
) / 2, (h
- wh
) / 2,w
, h
);
515 m_State
|= WallpaperDone
;
520 bool KBackgroundRenderer::canTile() const
522 return m_TilingEnabled
&& optimize();
525 void KBackgroundRenderer::wallpaperBlend()
527 if( !enabled() || wallpaperMode() == NoWallpaper
528 || (blendMode() == NoBlending
&&
529 ( QApplication::desktop()->paintEngine()->hasFeature(QPaintEngine::Antialiasing
)
530 || !m_Wallpaper
.hasAlphaChannel()))) {
531 fastWallpaperBlend();
534 fullWallpaperBlend();
538 // works only for NoBlending and no alpha in wallpaper
539 // but is much faster than QImage fidling
540 void KBackgroundRenderer::fastWallpaperBlend()
543 // copy background to m_pPixmap
544 if( !enabled() || (wallpaperMode() == NoWallpaper
&& canTile())) {
545 // if there's no wallpaper, no need to tile the pixmap to the size of desktop, as X does
546 // that automatically and using a smaller pixmap should save some memory
547 m_Pixmap
= QPixmap::fromImage( m_Background
);
550 else if( wallpaperMode() == Tiled
&& !m_Wallpaper
.hasAlphaChannel() && canTile() && !m_bPreview
) {
551 // tiles will be tiled by X automatically
552 m_Pixmap
= QPixmap::fromImage( m_Wallpaper
);
555 else if( m_WallpaperRect
.contains( QRect( QPoint( 0, 0 ), m_Size
))
556 && !m_Wallpaper
.hasAlphaChannel()) // wallpaper covers all and no blending
557 m_Pixmap
= QPixmap( m_Size
);
558 else if (m_Background
.size() == m_Size
)
559 m_Pixmap
= QPixmap::fromImage( m_Background
);
561 m_Pixmap
= QPixmap( m_Size
);
562 QPainter
p( &m_Pixmap
);
563 QPixmap pm
= QPixmap::fromImage( m_Background
);
564 p
.drawTiledPixmap( 0, 0, m_Size
.width(), m_Size
.height(), pm
);
567 // paint/alpha-blend wallpaper to destination rectangle of m_pPixmap
568 if (m_WallpaperRect
.isValid()) {
569 QPixmap wp_pixmap
= QPixmap::fromImage( m_Wallpaper
);
570 QPainter
pa( &m_Pixmap
);
571 int ww
= m_Wallpaper
.width();
572 int wh
= m_Wallpaper
.height();
573 for (int y
= m_WallpaperRect
.top(); y
< m_WallpaperRect
.bottom(); y
+= wh
) {
574 for (int x
= m_WallpaperRect
.left(); x
< m_WallpaperRect
.right(); x
+= ww
) {
575 pa
.drawPixmap( x
, y
, wp_pixmap
);
582 void KBackgroundRenderer::fullWallpaperBlend()
584 m_Pixmap
= QPixmap();
586 // desktop width/height
587 int w
= m_Size
.width();
588 int h
= m_Size
.height();
590 // copy background to m_pImage
591 if (m_Background
.size() == m_Size
) {
592 m_Image
= m_Background
.copy();
594 if (m_Image
.depth() < 32) {
595 m_Image
= m_Image
.convertToFormat(QImage::Format_ARGB32_Premultiplied
, Qt::DiffuseAlphaDither
);
598 m_Image
= QImage(w
, h
, QImage::Format_RGB32
);
599 tile(m_Image
, QRect(0, 0, w
, h
), m_Background
);
602 // blend wallpaper to destination rectangle of m_pImage
603 if (m_WallpaperRect
.isValid())
605 int blendFactor
= 100;
606 if (blendMode() == FlatBlending
)
607 blendFactor
= (blendBalance()+200)/4;
608 int ww
= m_Wallpaper
.width();
609 int wh
= m_Wallpaper
.height();
610 for (int y
= m_WallpaperRect
.top(); y
< m_WallpaperRect
.bottom(); y
+= wh
) {
611 for (int x
= m_WallpaperRect
.left(); x
< m_WallpaperRect
.right(); x
+= ww
) {
612 blend(m_Image
, QRect(x
, y
, ww
, wh
), m_Wallpaper
,
613 QPoint(-qMin(x
, 0), -qMin(y
, 0)), blendFactor
);
619 // blend whole desktop
620 if ( wallpaperMode() != NoWallpaper
) {
621 int bal
= blendBalance();
623 switch( blendMode() ) {
624 /* TODO disabled for now
625 case HorizontalBlending:
626 Blitz::blend( m_Image, m_Background,
627 Blitz::HorizontalGradient,
631 case VerticalBlending:
632 Blitz::blend( m_Image, m_Background,
633 Blitz::VerticalGradient,
637 case PyramidBlending:
638 Blitz::blend( m_Image, m_Background,
639 Blitz::PyramidGradient,
643 case PipeCrossBlending:
644 Blitz::blend( m_Image, m_Background,
645 Blitz::PipeCrossGradient,
649 case EllipticBlending:
650 Blitz::blend( m_Image, m_Background,
651 Blitz::EllipticGradient,
656 case IntensityBlending
:
657 Blitz::modulate( m_Image
, m_Background
, reverseBlending(),
658 Blitz::Intensity
, bal
, Blitz::All
);
661 case SaturateBlending
:
662 Blitz::modulate( m_Image
, m_Background
, reverseBlending(),
663 Blitz::Saturation
, bal
, Blitz::Brightness
);
666 case ContrastBlending
:
667 Blitz::modulate( m_Image
, m_Background
, reverseBlending(),
668 Blitz::Contrast
, bal
, Blitz::All
);
671 case HueShiftBlending
:
672 Blitz::modulate( m_Image
, m_Background
, reverseBlending(),
673 Blitz::HueShift
, bal
, Blitz::Brightness
);
683 /* Alpha blend an area from <src> with offset <soffs> to rectangle <dr> of <dst>
684 * Default offset is QPoint(0, 0).
685 * blendfactor = [0, 100%]
687 void KBackgroundRenderer::blend(QImage
& dst
, const QRect
&_dr
, const QImage
& src
, const QPoint
&soffs
, int blendFactor
)
693 for (y
= 0; y
< dr
.height(); y
++) {
694 if (dst
.scanLine(dr
.y() + y
) && src
.scanLine(soffs
.y() + y
)) {
697 for (x
= 0; x
< dr
.width(); x
++) {
698 b
= reinterpret_cast<QRgb
*>(dst
.scanLine(dr
.y() + y
)
699 + (dr
.x() + x
) * sizeof(QRgb
));
700 d
= reinterpret_cast<const QRgb
*>(src
.scanLine(soffs
.y() + y
)
701 + (soffs
.x() + x
) * sizeof(QRgb
));
702 a
= (qAlpha(*d
) * blendFactor
) / 100;
703 *b
= qRgb(qRed(*b
) - (((qRed(*b
) - qRed(*d
)) * a
) >> 8),
704 qGreen(*b
) - (((qGreen(*b
) - qGreen(*d
)) * a
) >> 8),
705 qBlue(*b
) - (((qBlue(*b
) - qBlue(*d
)) * a
) >> 8));
713 void KBackgroundRenderer::slotBackgroundDone(int exitCode
, QProcess::ExitStatus exitStatus
)
715 m_State
|= BackgroundDone
;
717 if (exitStatus
== QProcess::NormalExit
&& !exitCode
) {
718 m_Background
.load(m_Tempfile
->fileName());
719 m_State
|= BackgroundDone
;
722 delete m_Tempfile
; m_Tempfile
= 0;
724 setBusyCursor(false);
730 * Starts the rendering process.
732 void KBackgroundRenderer::start(bool enableBusyCursor
)
734 m_enableBusyCursor
= enableBusyCursor
;
745 * This slot is connected to a timer event. It is called repeatedly until
746 * the rendering is done.
748 void KBackgroundRenderer::render()
751 if (!(m_State
& Rendering
))
754 if( !(m_State
& InitCheck
)) {
755 QString f
= cacheFileName();
756 if( useCacheFile()) {
757 QString w
= m_pDirs
->findResource("wallpaper", currentWallpaper());
760 if( wi
.lastModified().isValid() && fi
.lastModified().isValid()
761 && wi
.lastModified() < fi
.lastModified()) {
763 if( im
.load( f
, "PNG" )) {
765 m_Pixmap
= QPixmap::fromImage( m_Image
);
767 m_State
|= InitCheck
| BackgroundDone
| WallpaperDone
;
772 m_State
|= InitCheck
;
778 if (!(m_State
& BackgroundDone
)) {
779 ret
= doBackground();
785 // No async wallpaper
789 setBusyCursor(false);
794 * Rendering is finished.
796 void KBackgroundRenderer::done()
798 setBusyCursor(false);
800 emit
imageDone(screen());
801 if(backgroundMode() == Program
&& m_pProc
&&
802 m_pProc
->exitStatus() != QProcess::NormalExit
) {
803 emit
programFailure(-1);
804 } else if(backgroundMode() == Program
&& m_pProc
&&
805 m_pProc
->exitCode()) {
806 emit
programFailure(m_pProc
->exitStatus());
807 } else if(backgroundMode() == Program
) {
808 emit
programSuccess();
813 * This function toggles a busy cursor on and off, for use in rendering.
814 * It is useful because of the ASYNC nature of the rendering - it is hard
815 * to make sure we don't set the busy cursor twice, but only restore
818 void KBackgroundRenderer::setBusyCursor(bool isBusy
) {
819 if(m_isBusyCursor
== isBusy
)
821 if (isBusy
&& !m_enableBusyCursor
)
823 m_isBusyCursor
= isBusy
;
825 QApplication::setOverrideCursor( QCursor(Qt::BusyCursor
) );
827 QApplication::restoreOverrideCursor();
831 * Stop the rendering.
833 void KBackgroundRenderer::stop()
835 if (!(m_State
& Rendering
))
845 * Cleanup after rendering.
847 void KBackgroundRenderer::cleanup()
849 setBusyCursor(false);
850 m_Background
= QImage();
852 m_Pixmap
= QPixmap();
853 m_Wallpaper
= QImage();
854 delete m_pProc
; m_pProc
= 0L;
856 m_WallpaperRect
= QRect();
861 void KBackgroundRenderer::setPreview(const QSize
&size
)
872 QPixmap
KBackgroundRenderer::pixmap()
874 if (m_State
& AllDone
) {
875 if( m_Pixmap
.isNull())
876 m_Pixmap
= QPixmap::fromImage( m_Image
);
882 QImage
KBackgroundRenderer::image()
884 if (m_State
& AllDone
) {
885 if( m_Image
.isNull())
886 fullWallpaperBlend(); // create from m_Pixmap
893 void KBackgroundRenderer::load(int screen
, bool drawBackgroundPerScreen
, bool reparseConfig
)
895 if (m_State
& Rendering
)
902 KBackgroundSettings::load(screen
, drawBackgroundPerScreen
, reparseConfig
);
905 void KBackgroundRenderer::createTempFile()
908 m_Tempfile
= new KTemporaryFile();
913 QString
KBackgroundRenderer::cacheFileName()
915 QString f
= fingerprint();
916 f
.replace ( ':', '_' ); // avoid characters that shouldn't be in filenames
917 f
.replace ( '/', '#' );
918 f
= KStandardDirs::locateLocal( "cache", QString( "background/%1x%2_%3.png" )
919 .arg( m_Size
.width()).arg( m_Size
.height()).arg( f
));
923 bool KBackgroundRenderer::useCacheFile() const
927 if( backgroundMode() == Program
)
928 return false; // don't cache these at all
929 if( wallpaperMode() == NoWallpaper
)
930 return false; // generating only background patterns should be always faster
931 QString file
= currentWallpaper();
932 if( file
.endsWith(".svg") || file
.endsWith(".svgz"))
933 return true; // cache these, they can be bloody slow
934 switch( backgroundMode())
940 return false; // these don't need scaling
951 void KBackgroundRenderer::saveCacheFile()
953 if( !( m_State
& AllDone
))
957 if( m_Image
.isNull())
958 fullWallpaperBlend(); // generate from m_Pixmap
959 QString f
= cacheFileName();
960 if( KStandardDirs::exists( f
) || m_Cached
)
961 utime( QFile::encodeName( f
), NULL
);
963 m_Image
.save( f
, "PNG" );
964 // remove old entries from the cache
965 QDir
dir( KStandardDirs::locateLocal( "cache", "background/" ));
966 const QFileInfoList list
= dir
.entryInfoList( QStringList() << "*.png", QDir::Files
, QDir::Time
| QDir::Reversed
);
967 if( !list
.isEmpty()) {
969 Q_FOREACH( const QFileInfo
& info
, list
)
971 Q_FOREACH( const QFileInfo
& info
, list
) {
972 if( size
< 8 * 1024 * 1024 )
974 // keep everything newer than 10 minutes if the total size is less than 50M (just in case)
975 if( size
< 50 * 1024 * 1024
976 && ( time_t ) info
.lastModified().toTime_t() >= time( NULL
) - 10 * 60 )
979 QFile::remove( info
.absoluteFilePath());
985 #include "bgrender.moc"