1 /* Slide Show Screen Saver
2 * (C) 1999 Stefan Taferner <taferner@kde.org>
3 * (C) 2001 Martin R. Jones <mjones@kde.org>
4 * (C) 2003 Chris Howells <howells@kde.org>
5 * (C) 2003 Sven Leiber <s.leiber@web.de>
7 * This code is under GPL
9 * 2001/03/04 Converted to libkscreensaver by Martin R. Jones.
18 #include <q3paintdevicemetrics.h>
19 #include <qcheckbox.h>
20 #include <qcombobox.h>
27 #include <QVBoxLayout>
32 #include <kapplication.h>
34 #include <kmessagebox.h>
36 #include <kfiledialog.h>
37 #include <kstandarddirs.h>
38 #include <kurlrequester.h>
39 #include <kaboutdata.h>
40 #include <kaboutapplication.h>
48 #include "slideshow.h"
49 #include "slideshow.moc"
52 #define SLIDESHOW_VERSION "2.3.0"
53 static const char version
[] = SLIDESHOW_VERSION
;
54 static const char description
[] = I18N_NOOP("KSlideshow");
56 static KAboutData
* s_aboutData
= 0;
58 // libkscreensaver interface
59 class KSlideShowSaverInterface
: public KScreenSaverInterface
62 virtual KAboutData
* aboutData() {
66 virtual KScreenSaver
* create( WId id
)
68 return new kSlideShowSaver( id
);
71 virtual QDialog
* setup()
73 return new kSlideShowSetup();
77 int main( int argc
, char *argv
[] )
79 s_aboutData
= new KAboutData( "kslideshow.kss", I18N_NOOP("SlideShow"),
80 version
, description
, KAboutData::License_GPL
,
81 "(c) 1999-2003, The KDE Team" );
82 s_aboutData
->addAuthor("Stefan Taferner", 0, "taferner@kde.org");
83 s_aboutData
->addAuthor("Chris Howells", 0, "howells@kde.org");
84 s_aboutData
->addAuthor("Sven Leiber", 0, "s.leiber@web.de");
86 KSlideShowSaverInterface kss
;
87 return kScreenSaverMain( argc
, argv
, kss
);
91 //=============================================================================
92 // Class kSlideShowSaver
93 //=============================================================================
94 kSlideShowSaver::kSlideShowSaver( WId id
): KScreenSaver(id
)
99 srand((unsigned int)t
);
113 mEffectRunning
= false;
117 mTimer
.start(10, true);
118 connect(&mTimer
, SIGNAL(timeout()), SLOT(slotTimeout()));
122 //----------------------------------------------------------------------------
123 kSlideShowSaver::~kSlideShowSaver()
126 delete [] mEffectList
;
129 if (mPainter
.isActive()) mPainter
.end();
133 //-----------------------------------------------------------------------------
134 void kSlideShowSaver::initNextScreen()
140 mNextScreen
= QPixmap(w
, h
);
144 //-----------------------------------------------------------------------------
145 void kSlideShowSaver::readConfig()
147 KConfig
*config
= KGlobal::config();
148 config
->setGroup("Settings");
149 mShowRandom
= config
->readEntry("ShowRandom", true);
150 mZoomImages
= config
->readEntry("ZoomImages", false);
151 mPrintName
= config
->readEntry("PrintName", true);
152 mDirectory
= config
->readPathEntry("Directory", KGlobal::dirs()->findDirs("wallpaper", "").last());
153 mDelay
= config
->readEntry("Delay", 10) * 1000;
154 mSubdirectory
= config
->readEntry("SubDirectory", false);
155 mRandomPosition
= config
->readEntry("RandomPosition", false);
161 //----------------------------------------------------------------------------
162 void kSlideShowSaver::registerEffects()
166 mEffectList
= new EffectMethod
[64];
167 mEffectList
[i
++] = &kSlideShowSaver::effectChessboard
;
168 mEffectList
[i
++] = &kSlideShowSaver::effectMultiCircleOut
;
169 mEffectList
[i
++] = &kSlideShowSaver::effectSpiralIn
;
170 mEffectList
[i
++] = &kSlideShowSaver::effectSweep
;
171 mEffectList
[i
++] = &kSlideShowSaver::effectMeltdown
;
172 mEffectList
[i
++] = &kSlideShowSaver::effectCircleOut
;
173 mEffectList
[i
++] = &kSlideShowSaver::effectBlobs
;
174 mEffectList
[i
++] = &kSlideShowSaver::effectHorizLines
;
175 mEffectList
[i
++] = &kSlideShowSaver::effectVertLines
;
176 mEffectList
[i
++] = &kSlideShowSaver::effectRandom
;
177 mEffectList
[i
++] = &kSlideShowSaver::effectGrowing
;
178 mEffectList
[i
++] = &kSlideShowSaver::effectIncomingEdges
;
181 // mNumEffects = 1; //...for testing
185 //----------------------------------------------------------------------------
186 int kSlideShowSaver::effectMultiCircleOut(bool aInit
)
190 static QPolygon
pa(4);
199 pa
.setPoint(0, mw
>>1, mh
>>1);
200 pa
.setPoint(3, mw
>>1, mh
>>1);
201 mfy
= sqrt((double)mw
*mw
+ mh
*mh
) / 2;
206 mfx
= M_PI
/32; // divisor must be powers of 8
216 for (alpha
=mAlpha
, i
=mi
; i
>=0; i
--, alpha
+=mfd
)
218 x
= (mw
>>1) + (int)(mfy
* cos(-alpha
));
219 y
= (mh
>>1) + (int)(mfy
* sin(-alpha
));
221 mx
= (mw
>>1) + (int)(mfy
* cos(-alpha
+ mfx
));
222 my
= (mh
>>1) + (int)(mfy
* sin(-alpha
+ mfx
));
224 pa
.setPoint(1, x
, y
);
225 pa
.setPoint(2, mx
, my
);
227 mPainter
.drawPolygon(pa
);
235 //----------------------------------------------------------------------------
236 int kSlideShowSaver::effectSpiralIn(bool aInit
)
257 if (mi
==0 && mx0
>=mx1
)
264 if (mi
==0 && mx
>=mx1
) // switch to: down on right side
271 else if (mi
==1 && my
>=my1
) // switch to: right to left on bottom side
278 else if (mi
==2 && mx
<=mx0
) // switch to: up on left side
285 else if (mi
==3 && my
<=my0
) // switch to: left to right on top side
293 bitBlt(this, mx
, my
, &mNextScreen
, mx
, my
, mix
, miy
);
303 //----------------------------------------------------------------------------
304 int kSlideShowSaver::effectMeltdown(bool aInit
)
317 mIntArray
= new int[mix
];
318 for (i
=mix
-1; i
>=0; i
--)
323 for (i
=0,x
=0; i
<mix
; i
++,x
+=mdx
)
326 if (y
>= mh
) continue;
328 if ((rand()&15) < 6) continue;
329 bitBlt(this, x
, y
+mdy
, this, x
, y
, mdx
, mh
-y
-mdy
);
330 bitBlt(this, x
, y
, &mNextScreen
, x
, y
, mdx
, mdy
);
345 //----------------------------------------------------------------------------
346 int kSlideShowSaver::effectCircleOut(bool aInit
)
349 static QPolygon
pa(4);
359 pa
.setPoint(0, mw
>>1, mh
>>1);
360 pa
.setPoint(3, mw
>>1, mh
>>1);
361 mfx
= M_PI
/16; // divisor must be powers of 8
362 mfy
= sqrt((double)mw
*mw
+ mh
*mh
) / 2;
374 mx
= (mw
>>1) + (int)(mfy
* cos(mAlpha
));
375 my
= (mh
>>1) + (int)(mfy
* sin(mAlpha
));
378 pa
.setPoint(1, x
, y
);
379 pa
.setPoint(2, mx
, my
);
381 mPainter
.drawPolygon(pa
);
387 //----------------------------------------------------------------------------
388 int kSlideShowSaver::effectSweep(bool aInit
)
394 // subtype: 0=sweep right to left, 1=sweep left to right
395 // 2=sweep bottom to top, 3=sweep top to bottom
396 mSubType
= rand() % 4;
399 mdx
= (mSubType
==1 ? 16 : -16);
400 mdy
= (mSubType
==3 ? 16 : -16);
401 mx
= (mSubType
==1 ? 0 : mw
);
402 my
= (mSubType
==3 ? 0 : mh
);
405 if (mSubType
==0 || mSubType
==1)
408 if ((mSubType
==0 && mx
< -64) ||
409 (mSubType
==1 && mx
> mw
+64))
413 for (w
=2,i
=4,x
=mx
; i
>0; i
--, w
<<=1, x
-=mdx
)
415 bitBlt(this, x
, 0, &mNextScreen
, x
, 0, w
, mh
);
422 if ((mSubType
==2 && my
< -64) ||
423 (mSubType
==3 && my
> mh
+64))
427 for (h
=2,i
=4,y
=my
; i
>0; i
--, h
<<=1, y
-=mdy
)
429 bitBlt(this, 0, y
, &mNextScreen
, 0, y
, mw
, h
);
438 //----------------------------------------------------------------------------
439 int kSlideShowSaver::effectBlobs(bool aInit
)
461 r
= (rand() % 200) + 50;
463 mPainter
.drawEllipse(mx
-r
, my
-r
, r
, r
);
470 //----------------------------------------------------------------------------
471 int kSlideShowSaver::effectRandom(bool /*aInit*/)
473 int x
, y
, i
, w
, h
, fact
, sz
;
475 fact
= (rand() % 3) + 1;
478 h
= height() >> fact
;
481 for (i
= (w
*h
)<<1; i
> 0; i
--)
483 x
= (rand() % w
) << fact
;
484 y
= (rand() % h
) << fact
;
485 bitBlt(this, x
, y
, &mNextScreen
, x
, y
, sz
, sz
);
493 //----------------------------------------------------------------------------
494 int kSlideShowSaver::effectGrowing(bool aInit
)
507 mx
= (mw
>>1) - (int)(mi
* mfx
);
508 my
= (mh
>>1) - (int)(mi
* mfy
);
517 bitBlt(this, mx
, my
, &mNextScreen
, mx
, my
,
518 mw
- (mx
<<1), mh
- (my
<<1));
524 //----------------------------------------------------------------------------
525 int kSlideShowSaver::effectChessboard(bool aInit
)
533 mdx
= 8; // width of one tile
534 mdy
= 8; // height of one tile
535 mj
= (mw
+mdx
-1)/mdx
; // number of tiles
536 mx
= mj
*mdx
; // shrinking x-offset from screen border
537 mix
= 0; // growing x-offset from screen border
538 miy
= 0; // 0 or mdy for growing tiling effect
539 my
= mj
&1 ? 0 : mdy
; // 0 or mdy for shrinking tiling effect
540 mwait
= 800 / mj
; // timeout between effects
554 for (y
=0; y
<mw
; y
+=(mdy
<<1))
556 bitBlt(this, mix
, y
+miy
, &mNextScreen
, mix
, y
+miy
,
558 bitBlt(this, mx
, y
+my
, &mNextScreen
, mx
, y
+my
,
566 //----------------------------------------------------------------------------
567 int kSlideShowSaver::effectIncomingEdges(bool aInit
)
580 mSubType
= rand() & 1;
583 mx
= (int)(mfx
* mi
);
584 my
= (int)(mfy
* mi
);
586 if (mx
>mix
|| my
>miy
)
598 // moving image edges
599 bitBlt(this, 0, 0, &mNextScreen
, mix
-mx
, miy
-my
, mx
, my
);
600 bitBlt(this, x1
, 0, &mNextScreen
, mix
, miy
-my
, mx
, my
);
601 bitBlt(this, 0, y1
, &mNextScreen
, mix
-mx
, miy
, mx
, my
);
602 bitBlt(this, x1
, y1
, &mNextScreen
, mix
, miy
, mx
, my
);
607 bitBlt(this, 0, 0, &mNextScreen
, 0, 0, mx
, my
);
608 bitBlt(this, x1
, 0, &mNextScreen
, x1
, 0, mx
, my
);
609 bitBlt(this, 0, y1
, &mNextScreen
, 0, y1
, mx
, my
);
610 bitBlt(this, x1
, y1
, &mNextScreen
, x1
, y1
, mx
, my
);
616 //----------------------------------------------------------------------------
617 int kSlideShowSaver::effectHorizLines(bool aInit
)
619 static int iyPos
[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
629 if (iyPos
[mi
] < 0) return -1;
631 for (y
=iyPos
[mi
]; y
<mh
; y
+=8)
633 bitBlt(this, 0, y
, &mNextScreen
, 0, y
, mw
, 1);
637 if (iyPos
[mi
] >= 0) return 160;
642 //----------------------------------------------------------------------------
643 int kSlideShowSaver::effectVertLines(bool aInit
)
645 static int ixPos
[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
655 if (ixPos
[mi
] < 0) return -1;
657 for (x
=ixPos
[mi
]; x
<mw
; x
+=8)
659 bitBlt(this, x
, 0, &mNextScreen
, x
, 0, 1, mh
);
663 if (ixPos
[mi
] >= 0) return 160;
668 //-----------------------------------------------------------------------------
669 void kSlideShowSaver::startPainter(Qt::PenStyle aPen
)
672 brush
.setPixmap(mNextScreen
);
673 if (mPainter
.isActive()) mPainter
.end();
674 mPainter
.begin(this);
675 mPainter
.setBrush(brush
);
676 mPainter
.setPen(aPen
);
680 //-----------------------------------------------------------------------------
681 void kSlideShowSaver::restart()
683 mEffectRunning
= false;
690 //-----------------------------------------------------------------------------
691 void kSlideShowSaver::slotTimeout()
698 tmout
= (this->*mEffect
)(false);
705 if (mNumEffects
> 1) i
= rand() % mNumEffects
;
708 mEffect
= mEffectList
[i
];
709 mEffectRunning
= true;
710 tmout
= (this->*mEffect
)(true);
715 mEffectRunning
= false;
717 mTimer
.start(tmout
, true);
721 //----------------------------------------------------------------------------
722 void kSlideShowSaver::showNextScreen()
724 bitBlt(this, 0, 0, &mNextScreen
, 0, 0,
725 mNextScreen
.width(), mNextScreen
.height());
729 //----------------------------------------------------------------------------
730 void kSlideShowSaver::createNextScreen()
733 int ww
, wh
, iw
, ih
, x
, y
;
736 if (mNextScreen
.size() != size())
737 mNextScreen
.resize(size());
739 mNextScreen
.fill(Qt::black
);
741 ww
= mNextScreen
.width();
742 wh
= mNextScreen
.height();
744 ih
= mImage
.height();
746 p
.begin(&mNextScreen
);
748 if (mFileList
.isEmpty())
750 p
.setPen(QColor("white"));
751 p
.drawText(20 + (rand() % (ww
>>1)), 20 + (rand() % (wh
>>1)),
752 i18n("No images found"));
758 fx
= (double)ww
/ iw
;
759 fy
= (double)wh
/ ih
;
760 if (fx
> fy
) fx
= fy
;
764 QImage scaledImg
= mImage
.smoothScale(iw
, ih
);
769 p
.drawImage(x
, y
, scaledImg
);
773 if(iw
> ww
|| ih
> wh
)
775 fx
= (double)ww
/ iw
;
776 fy
= (double)wh
/ ih
;
777 if (fx
> fy
) fx
= fy
;
781 QImage scaledImg
= mImage
.smoothScale(iw
, ih
);
786 p
.drawImage(x
, y
, scaledImg
);
792 x
= rand() % (ww
- iw
);
793 y
= rand() % (wh
- ih
);
801 // bitBlt(&mNextScreen, x, y, &mImage, 0, 0, iw, ih);
802 p
.drawImage(x
, y
, mImage
);
808 p
.setPen(QColor("black"));
809 for (x
=9; x
<=11; x
++)
810 for (y
=21; y
>=19; y
--)
811 p
.drawText(x
, wh
-y
, mImageName
);
812 p
.setPen(QColor("white"));
813 p
.drawText(10, wh
-20, mImageName
);
821 //----------------------------------------------------------------------------
822 void kSlideShowSaver::loadNextImage()
827 num
= mFileList
.count();
828 if (num
<= 0) //no files in the directory
835 mFileIdx
= rand() % num
;
836 fname
= mFileList
[mFileIdx
];
837 mFileList
.remove(fname
);
838 if (num
== 1) //we're about to run out of images
840 mFileList
= mRandomList
;
845 if (mFileIdx
>= num
) mFileIdx
= 0;
846 fname
= mFileList
[mFileIdx
];
849 if (!mImage
.load(fname
))
851 kDebug() << "Failed to load image " << fname
<< endl
;
852 mFileList
.remove(fname
);
853 mRandomList
.remove(fname
);
854 if (!mFileList
.isEmpty())
861 i
= fname
.findRev('.');
862 if (i
< 0) i
= 32767;
863 j
= fname
.findRev('/') + 1;
865 mImageName
= fname
.mid(j
, i
-j
);
869 //----------------------------------------------------------------------------
870 void kSlideShowSaver::loadDirectory()
874 traverseDirectory(mDirectory
);
875 mRandomList
= mFileList
;
878 void kSlideShowSaver::traverseDirectory(const QString
&dirName
)
885 dir
.setFilter(QDir::Dirs
| QDir::Files
);
887 QFileInfoList fileinfolist
= dir
.entryInfoList();
888 QFileInfoListIterator it
= fileinfolist
.begin();
889 while ( it
!= fileinfolist
.end())
891 if (it
->fileName() == "." || it
->fileName() == "..")
896 if (it
->isDir() && it
->isReadable() && mSubdirectory
)
898 traverseDirectory(it
->filePath());
904 mFileList
.append(it
->filePath());
912 //-----------------------------------------------------------------------------
913 void kSlideShowSaver::blank()
919 //=============================================================================
920 // Class kSlideShowSetup
921 //=============================================================================
922 kSlideShowSetup::kSlideShowSetup(QWidget
*aParent
, const char *aName
)
925 setCaption(i18n( "Setup Slide Show Screen Saver" ));
926 setButtons(Ok
|Cancel
|Help
);
927 setDefaultButton(Ok
);
929 setButtonText( Help
, i18n( "A&bout" ) );
931 QWidget
*main
= new QWidget(this);
933 cfg
= new SlideShowCfg();
934 cfg
->setupUi( main
);
936 cfg
->mPreview
->setFixedSize(220, 170);
937 cfg
->mPreview
->setBackgroundColor(Qt::black
);
938 cfg
->mPreview
->show(); // otherwise saver does not get correct size
939 mSaver
= new kSlideShowSaver(cfg
->mPreview
->winId());
941 cfg
->mDirChooser
->setMode(KFile::Directory
| KFile::ExistingOnly
);
942 connect(cfg
->mDirChooser
, SIGNAL(returnPressed(const QString
&)),
943 SLOT(slotDirSelected(const QString
&)));
944 connect(cfg
->mDirChooser
, SIGNAL(urlSelected(const KUrl
&)),
945 SLOT(slotDirSelected(const KUrl
&)));
946 connect(this,SIGNAL(okClicked()),this,SLOT(slotOk()));
947 connect(this,SIGNAL(helpClicked()),this,SLOT(slotHelp()));
951 kSlideShowSetup::~kSlideShowSetup()
956 //-----------------------------------------------------------------------------
957 void kSlideShowSetup::readSettings()
959 KConfig
*config
= KGlobal::config();
961 config
->setGroup("Settings");
962 cfg
->mCbxRandom
->setChecked(config
->readEntry("ShowRandom", true));
963 cfg
->mCbxZoom
->setChecked(config
->readEntry("ZoomImages", false));
964 cfg
->mCbxShowName
->setChecked(config
->readEntry("PrintName", true));
965 cfg
->mDelay
->setValue(config
->readEntry("Delay", 20));
966 cfg
->mDirChooser
->setPath(config
->readPathEntry("Directory"));
967 cfg
->mCbxSubdirectory
->setChecked(config
->readEntry("SubDirectory", false));
968 cfg
->mCbxRandomPosition
->setChecked(config
->readEntry("RandomPosition", false));
972 //-----------------------------------------------------------------------------
973 void kSlideShowSetup::writeSettings()
975 KConfig
*config
= KGlobal::config();
977 config
->setGroup("Settings");
978 config
->writeEntry("ShowRandom", cfg
->mCbxRandom
->isChecked());
979 config
->writeEntry("ZoomImages", cfg
->mCbxZoom
->isChecked());
980 config
->writeEntry("PrintName", cfg
->mCbxShowName
->isChecked());
981 config
->writeEntry("Delay", cfg
->mDelay
->value());
982 config
->writePathEntry("Directory", cfg
->mDirChooser
->url().path());
983 config
->writeEntry("SubDirectory", cfg
->mCbxSubdirectory
->isChecked());
984 config
->writeEntry("RandomPosition", cfg
->mCbxRandomPosition
->isChecked());
990 mSaver
->readConfig();
996 //-----------------------------------------------------------------------------
998 void kSlideShowSetup::slotDirSelected(const KUrl
&)
1003 void kSlideShowSetup::slotDirSelected(const QString
&)
1009 //-----------------------------------------------------------------------------
1010 void kSlideShowSetup::slotOk()
1017 //-----------------------------------------------------------------------------
1018 void kSlideShowSetup::slotHelp()
1020 KAboutApplication
mAbout(s_aboutData
, this, 0);