summaryrefslogtreecommitdiffstats
path: root/kipi-plugins/slideshow
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-19 18:22:05 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-19 18:22:05 +0000
commit57e10fedbcb8c3e8c6590ff0935dbf017ce5587f (patch)
tree3000a7649ca4e40e43f9e7feed963236a0b0f56b /kipi-plugins/slideshow
downloadkipi-plugins-57e10fedbcb8c3e8c6590ff0935dbf017ce5587f.tar.gz
kipi-plugins-57e10fedbcb8c3e8c6590ff0935dbf017ce5587f.zip
Import abandoned KDE3 version of kipi plugins
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/kipi-plugins@1077221 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kipi-plugins/slideshow')
-rw-r--r--kipi-plugins/slideshow/Makefile.am30
-rw-r--r--kipi-plugins/slideshow/hi22-action-slideshow.pngbin0 -> 710 bytes
-rw-r--r--kipi-plugins/slideshow/imageloadthread.cpp180
-rw-r--r--kipi-plugins/slideshow/imageloadthread.h88
-rw-r--r--kipi-plugins/slideshow/kbeffect.cpp192
-rw-r--r--kipi-plugins/slideshow/kbeffect.h101
-rw-r--r--kipi-plugins/slideshow/kipiplugin_slideshow.desktop60
-rw-r--r--kipi-plugins/slideshow/listimageitems.cpp87
-rw-r--r--kipi-plugins/slideshow/listimageitems.h84
-rw-r--r--kipi-plugins/slideshow/plugin_slideshow.cpp267
-rw-r--r--kipi-plugins/slideshow/plugin_slideshow.h69
-rw-r--r--kipi-plugins/slideshow/screenproperties.cpp105
-rw-r--r--kipi-plugins/slideshow/screenproperties.h49
-rw-r--r--kipi-plugins/slideshow/slideshow.cpp1214
-rw-r--r--kipi-plugins/slideshow/slideshow.h189
-rw-r--r--kipi-plugins/slideshow/slideshowconfig.cpp785
-rw-r--r--kipi-plugins/slideshow/slideshowconfig.h121
-rw-r--r--kipi-plugins/slideshow/slideshowconfigbase.ui1522
-rw-r--r--kipi-plugins/slideshow/slideshowgl.cpp1508
-rw-r--r--kipi-plugins/slideshow/slideshowgl.h172
-rw-r--r--kipi-plugins/slideshow/slideshowkb.cpp578
-rw-r--r--kipi-plugins/slideshow/slideshowkb.h190
-rw-r--r--kipi-plugins/slideshow/slideshowloader.cpp219
-rw-r--r--kipi-plugins/slideshow/slideshowloader.h109
-rw-r--r--kipi-plugins/slideshow/toolbar.cpp192
-rw-r--r--kipi-plugins/slideshow/toolbar.h84
26 files changed, 8195 insertions, 0 deletions
diff --git a/kipi-plugins/slideshow/Makefile.am b/kipi-plugins/slideshow/Makefile.am
new file mode 100644
index 0000000..9982df4
--- /dev/null
+++ b/kipi-plugins/slideshow/Makefile.am
@@ -0,0 +1,30 @@
+METASOURCES = AUTO
+
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) \
+ $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_slideshow.la
+
+kipiplugin_slideshow_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+
+kipiplugin_slideshow_la_SOURCES = listimageitems.cpp plugin_slideshow.cpp \
+ slideshow.cpp slideshowconfig.cpp slideshowconfigbase.ui slideshowgl.cpp \
+ slideshowloader.cpp toolbar.cpp imageloadthread.cpp kbeffect.cpp screenproperties.cpp \
+ slideshowkb.cpp
+
+#kipiplugin_slideshow_la_LIBADD = -lkdefx $(GL_LIBS) $(LIBKIPI_LIBS) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+kipiplugin_slideshow_la_LIBADD = -lkdefx -lXrandr $(GL_LIBS) $(LIBKIPI_LIBS) $(LIBKDCRAW_LIBS) \
+ $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_KIO) $(LIB_QT)
+
+kipiplugin_slideshow_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+kde_services_DATA = kipiplugin_slideshow.desktop
+
+kipiplugin_slideshowicondir = $(kde_datadir)/kipiplugin_slideshow/icons
+kipiplugin_slideshowicon_ICON = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_slideshow.pot
+
+
diff --git a/kipi-plugins/slideshow/hi22-action-slideshow.png b/kipi-plugins/slideshow/hi22-action-slideshow.png
new file mode 100644
index 0000000..73a0952
--- /dev/null
+++ b/kipi-plugins/slideshow/hi22-action-slideshow.png
Binary files differ
diff --git a/kipi-plugins/slideshow/imageloadthread.cpp b/kipi-plugins/slideshow/imageloadthread.cpp
new file mode 100644
index 0000000..36f40c8
--- /dev/null
+++ b/kipi-plugins/slideshow/imageloadthread.cpp
@@ -0,0 +1,180 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qdir.h>
+#include <qvaluevector.h>
+#include <qdeepcopy.h>
+#include <qwmatrix.h>
+#include <qobject.h>
+
+// KDE includes.
+
+#include <klocale.h>
+
+// Local includes.
+
+#include "slideshowkb.h"
+#include "imageloadthread.h"
+#include "imageloadthread.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+ImageLoadThread::ImageLoadThread(QValueList<QPair<QString, int> >& fileList,
+ int width, int height)
+{
+
+ m_initialized = false;
+ m_needImage = true;
+ m_haveImages = false;
+ m_quitRequested = false;
+
+ m_fileIndex = 0;
+ m_fileList = fileList;
+
+ m_width = width;
+ m_height = height;
+}
+
+void ImageLoadThread::quit() {
+
+ QMutexLocker locker(&m_condLock);
+
+ m_quitRequested = true;
+ m_imageRequest.wakeOne();
+}
+
+void ImageLoadThread::requestNewImage() {
+
+ QMutexLocker locker(&m_condLock);
+
+ if ( !m_needImage) {
+ m_needImage = true;
+ m_imageRequest.wakeOne();
+ }
+}
+
+void ImageLoadThread::run() {
+
+ QMutexLocker locker(&m_condLock);
+
+ // we enter the loop with m_needImage==true, so we will immediatly
+ // try to load an image
+
+ while (true) {
+
+ if (m_quitRequested)
+ break;
+
+ if (m_needImage) {
+
+ if ( m_fileIndex == (int)m_fileList.count() )
+ {
+ m_needImage = false;
+ emit(endOfShow());
+ continue;
+ }
+
+ m_needImage = false;
+ m_condLock.unlock();
+
+ bool ok;
+ do {
+ ok = loadImage();
+ if ( !ok)
+ invalidateCurrentImageName();
+ } while ( !ok && m_fileIndex < (int)m_fileList.count());
+
+ if ( m_fileIndex == (int)m_fileList.count() )
+ {
+
+ emit(endOfShow());
+ m_condLock.lock();
+ continue;
+ }
+
+ if ( !ok) {
+ // generate a black dummy image
+ m_texture = QImage(128, 128, 32);
+ m_texture.fill(Qt::black.rgb());
+ }
+
+ m_condLock.lock();
+
+ m_fileIndex++;
+
+ if ( !m_initialized) {
+ m_haveImages = ok;
+ m_initialized = true;
+ }
+
+ } else {
+ // wait for new requests from the consumer
+ m_imageRequest.wait(&m_condLock);
+ }
+ }
+}
+
+bool ImageLoadThread::loadImage() {
+
+ QPair<QString, int> fileAngle = m_fileList[m_fileIndex];
+ QString path(fileAngle.first);
+ int angle(fileAngle.second);
+ QImage image(path);
+ if (angle != 0)
+ {
+ QWMatrix wm;
+ wm.rotate(angle);
+ image = image.xForm(wm);
+ }
+
+ if (image.isNull()) {
+ return false;
+ }
+
+ float aspect = (float)image.width() / (float)image.height();
+
+ image = image.smoothScale(m_width, m_height, QImage::ScaleMin);
+
+ m_imageLock.lock();
+
+ // this is the critical moment, when we make the new texture and
+ // aspect available to the consumer
+ m_textureAspect = aspect;
+ m_texture = QGLWidget::convertToGLFormat(image);
+
+ m_imageLock.unlock();
+
+ return true;
+}
+
+void ImageLoadThread::invalidateCurrentImageName() {
+ m_fileList.remove(m_fileList[m_fileIndex]);
+ m_fileIndex++;
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/imageloadthread.h b/kipi-plugins/slideshow/imageloadthread.h
new file mode 100644
index 0000000..41c5386
--- /dev/null
+++ b/kipi-plugins/slideshow/imageloadthread.h
@@ -0,0 +1,88 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGELOADTHREAD_H
+#define IMAGELOADTHREAD_H
+
+// QT includes.
+
+#include <qimage.h>
+#include <qthread.h>
+#include <qwaitcondition.h>
+#include <qmutex.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qstring.h>
+#include <qobject.h>
+
+namespace KIPISlideShowPlugin
+{
+
+class ImageLoadThread : public QObject, public QThread
+{
+
+Q_OBJECT
+
+public:
+
+ ImageLoadThread(QValueList<QPair<QString, int> >& fileList, int width, int height);
+
+ void quit();
+ void requestNewImage();
+ bool grabImage() { m_imageLock.lock(); return m_haveImages; };
+ void ungrabImage() { m_imageLock.unlock(); };
+ bool ready() { return m_initialized; };
+ const QImage &image() { return m_texture; };
+ float imageAspect() { return m_textureAspect; };
+
+signals:
+
+ void endOfShow();
+
+protected:
+
+ void run();
+
+ bool loadImage();
+ void invalidateCurrentImageName();
+
+private:
+
+ int m_fileIndex;
+ QValueList<QPair<QString, int> > m_fileList;
+
+ int m_width, m_height;
+
+ QWaitCondition m_imageRequest;
+ QMutex m_condLock, m_imageLock;
+ bool m_initialized, m_needImage, m_haveImages, m_quitRequested, m_scanSubdirectories;
+
+ float m_textureAspect;
+ QImage m_texture;
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // IMAGELOADTHREAD_H
diff --git a/kipi-plugins/slideshow/kbeffect.cpp b/kipi-plugins/slideshow/kbeffect.cpp
new file mode 100644
index 0000000..891a6fe
--- /dev/null
+++ b/kipi-plugins/slideshow/kbeffect.cpp
@@ -0,0 +1,192 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <assert.h>
+
+// Qt includes.
+
+#include <qdatetime.h>
+
+// KDE includes.
+
+#include "kbeffect.h"
+
+// Local includes.
+
+#include "slideshowkb.h"
+
+namespace KIPISlideShowPlugin
+{
+
+// -------------------------------------------------------------------------
+
+int KBEffect::m_numKBEffectRepeated = 0;
+
+// -------------------------------------------------------------------------
+
+KBEffect::KBEffect(SlideShowKB *parent, bool needFadeIn) {
+
+ this->slideWidget = parent;
+ this->m_needFadeIn = needFadeIn;
+}
+
+
+KBEffect::~KBEffect() {
+
+}
+
+
+void KBEffect::setupNewImage(int img) {
+
+ slideWidget->setupNewImage(img);
+}
+
+
+void KBEffect::swapImages() {
+
+ slideWidget->swapImages();
+}
+
+
+Image *KBEffect::image(int img) {
+
+ assert(img >= 0 && img < 2);
+ return slideWidget->m_image[img];
+}
+
+
+KBEffect::Type KBEffect::chooseKBEffect(KBEffect::Type oldType) {
+
+ KBEffect::Type type;
+
+ do {
+ type = (rand() < RAND_MAX / 2) ? KBEffect::Fade : KBEffect::Blend;
+ } while (type == oldType && m_numKBEffectRepeated >= 1);
+
+ if (type == oldType)
+ m_numKBEffectRepeated++;
+ else
+ m_numKBEffectRepeated = 0;
+
+ return type;
+}
+
+
+
+// -------------------------------------------------------------------------
+
+FadeKBEffect::FadeKBEffect(SlideShowKB *parent, bool needFadeIn):
+ KBEffect(parent, needFadeIn)
+{
+ m_img[0] = image(0);
+}
+
+
+FadeKBEffect::~FadeKBEffect() {
+
+}
+
+
+bool FadeKBEffect::done() {
+
+ if (m_img[0]->m_pos >= 1.0) {
+ setupNewImage(0);
+ return true;
+ }
+
+ return false;
+}
+
+
+void FadeKBEffect::advanceTime(float step) {
+
+ m_img[0]->m_pos += step;
+ if (m_img[0]->m_pos >= 1.0)
+ m_img[0]->m_pos = 1.0;
+
+ if (m_needFadeIn && m_img[0]->m_pos < 0.1)
+ m_img[0]->m_opacity = m_img[0]->m_pos * 10;
+ else if (m_img[0]->m_pos > 0.9)
+ m_img[0]->m_opacity = (1.0 - m_img[0]->m_pos) * 10;
+ else
+ m_img[0]->m_opacity = 1.0;
+}
+
+// -------------------------------------------------------------------------
+
+BlendKBEffect::BlendKBEffect(SlideShowKB *parent, bool needFadeIn):
+ KBEffect(parent, needFadeIn)
+{
+ m_img[0] = image(0);
+ m_img[1] = 0;
+}
+
+
+BlendKBEffect::~BlendKBEffect() {
+
+}
+
+
+bool BlendKBEffect::done() {
+
+ if (m_img[0]->m_pos >= 1.0) {
+ m_img[0]->m_paint = false;
+ swapImages();
+ return true;
+ }
+
+ return false;
+}
+
+
+void BlendKBEffect::advanceTime(float step) {
+
+ m_img[0]->m_pos += step;
+ if (m_img[0]->m_pos >= 1.0)
+ m_img[0]->m_pos = 1.0;
+
+ if (m_img[1])
+ m_img[1]->m_pos += step;
+
+ if (m_needFadeIn && m_img[0]->m_pos < 0.1)
+ m_img[0]->m_opacity = m_img[0]->m_pos * 10;
+
+ else if (m_img[0]->m_pos > 0.9) {
+
+ m_img[0]->m_opacity = (1.0 - m_img[0]->m_pos) * 10;
+
+ if (m_img[1] == 0) {
+ setupNewImage(1);
+ m_img[1] = image(1);
+ m_img[1]->m_opacity = 1.0;
+ }
+
+ } else
+ m_img[0]->m_opacity = 1.0;
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/kbeffect.h b/kipi-plugins/slideshow/kbeffect.h
new file mode 100644
index 0000000..029efb5
--- /dev/null
+++ b/kipi-plugins/slideshow/kbeffect.h
@@ -0,0 +1,101 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef KBEFFECT_H
+#define KBEFFECT_H
+
+namespace KIPISlideShowPlugin
+{
+
+class Image;
+class SlideShowKB;
+
+class KBEffect
+{
+
+public:
+
+ typedef enum { Fade, Blend } Type;
+
+ KBEffect(SlideShowKB *parent, bool m_needFadeIn = true);
+ virtual ~KBEffect();
+
+ virtual void advanceTime(float step) = 0;
+ virtual Type type() = 0;
+ virtual bool done() = 0;
+ virtual bool fadeIn() const { return m_needFadeIn; };
+
+ static Type chooseKBEffect(Type oldType);
+
+protected:
+
+ void setupNewImage(int img);
+ void swapImages();
+ Image *image(int img);
+
+protected:
+
+ static int m_numKBEffectRepeated;
+ bool m_needFadeIn;
+ Image *m_img[2];
+
+private:
+
+ SlideShowKB *slideWidget;
+};
+
+// -------------------------------------------------------------------------
+
+class FadeKBEffect: public KBEffect
+{
+
+public:
+
+ FadeKBEffect(SlideShowKB *parent, bool m_needFadeIn = true);
+ virtual ~FadeKBEffect();
+
+ virtual void advanceTime(float step);
+ virtual Type type() { return Fade; };
+ virtual bool done();
+};
+
+// -------------------------------------------------------------------------
+
+class BlendKBEffect: public KBEffect
+{
+
+public:
+
+ BlendKBEffect(SlideShowKB *parent, bool m_needFadeIn = true);
+ virtual ~BlendKBEffect();
+
+ virtual void advanceTime(float step);
+ virtual Type type() { return Blend; };
+ virtual bool done();
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // KBEFFECT_H
diff --git a/kipi-plugins/slideshow/kipiplugin_slideshow.desktop b/kipi-plugins/slideshow/kipiplugin_slideshow.desktop
new file mode 100644
index 0000000..23a3a8c
--- /dev/null
+++ b/kipi-plugins/slideshow/kipiplugin_slideshow.desktop
@@ -0,0 +1,60 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=SlideShow
+Name[br]=Diskouezadur skeudennoù
+Name[ca]=Passi de dispositives
+Name[cs]=Prezentace
+Name[cy]=Sioe Tryloywderau
+Name[da]=Lysbilledshow
+Name[de]=Diashow
+Name[el]=ΠροβολήΣλάιντ
+Name[es]=Presentación
+Name[et]=Slaidiseanss
+Name[fi]=Kuvasarja
+Name[gl]=Apresentazón
+Name[it]=Presentazione
+Name[nds]=Diaschau
+Name[nl]=Diavoorstelling
+Name[pa]=ਸਲਾਇਡਸ਼ੋ
+Name[pl]=Pokaz slajdów
+Name[pt]=Apresentação
+Name[sr]=Слајд шоу
+Name[sr@Latn]=Slajd šou
+Name[sv]=Bildspel
+Name[tg]=НамоишиСлайд
+Name[th]=นำเสนอภาพ
+Name[tr]=SlaytGösterisi
+Name[xx]=xxSlideShowxx
+Name[zh_CN]=幻灯片
+Comment=KIPI SlideShow Plugin
+Comment[br]=Lugent diskouezadur skeudennoù KIPI
+Comment[ca]=Connector del KIPI de passi de diapositives
+Comment[cs]=KIPI modul prezentace
+Comment[da]=KIPI-plugin: Lysbilledshow
+Comment[de]=Ein KIPI-Modul zur Erstellung von Bildschirmpräsentationen
+Comment[el]=Πρόσθετο του KIPI για προβολή σλάιντ
+Comment[es]=Complemento de KIPI para presentaciones
+Comment[et]=KIPI slaidiseansi plugin
+Comment[fi]=Kipi-liitännäinen kuvasarjojen esityksiä varten
+Comment[fr]=Module externe KIPI pour faire un diaporama
+Comment[gl]=Plugin de KIPI para Apresentazóns
+Comment[it]=Plugin di presentazione di KIPI
+Comment[ja]=Kipi スライドショープラグイン
+Comment[nds]=KIPI-Moduul för Diaschauen
+Comment[nl]=KIPI-plugin voor diavoorstellingen
+Comment[pa]=KIPI ਸਲਾਇਡਸ਼ੋ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Pokaz slajdów
+Comment[pt]='Plugin' do KIPI para Apresentações
+Comment[pt_BR]=Plugin de Show de Slides do KIPI
+Comment[sr]=KIPI прикључак за слајд шоу
+Comment[sr@Latn]=KIPI priključak za slajd šou
+Comment[sv]=KIPI-insticksprogram: Bildspel
+Comment[tg]=Модули KIPI барои НамоишиСлайд
+Comment[tr]=KIPI Slayt Gösterisi Eklentisi
+Comment[xx]=xxKIPI SlideShow Pluginxx
+Comment[zh_CN]=KIPI 幻灯片插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_slideshow
+X-KIPI-MergeMenu=true
+author=Renchi Raju, renchi@pooh.tam.uiuc.edu
diff --git a/kipi-plugins/slideshow/listimageitems.cpp b/kipi-plugins/slideshow/listimageitems.cpp
new file mode 100644
index 0000000..7202b8f
--- /dev/null
+++ b/kipi-plugins/slideshow/listimageitems.cpp
@@ -0,0 +1,87 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-21
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2003-2007 Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes
+
+#include <qstring.h>
+#include <qwidget.h>
+#include <qevent.h>
+#include <qstrlist.h>
+#include <qdragobject.h>
+#include <qfileinfo.h>
+#include <qlistbox.h>
+
+// KDE includes
+
+#include <klistbox.h>
+#include <kurl.h>
+
+// Local includes
+
+#include "listimageitems.h"
+#include "listimageitems.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+ListImageItems::ListImageItems(QWidget *parent, const char *name)
+ : KListBox(parent, name)
+{
+ setSelectionMode (QListBox::Extended);
+ setAcceptDrops(true);
+}
+
+void ListImageItems::dragEnterEvent(QDragEnterEvent *e)
+{
+ e->accept(QUriDrag::canDecode(e));
+}
+
+void ListImageItems::dropEvent(QDropEvent *e)
+{
+ QStrList strList;
+ KURL::List filesUrl;
+
+ if ( !QUriDrag::decode(e, strList) ) return;
+
+ QStrList stringList;
+ QStrListIterator it(strList);
+ char *str;
+
+ while ( (str = it.current()) != 0 )
+ {
+ QString filePath = QUriDrag::uriToLocalFile(str);
+ QFileInfo fileInfo(filePath);
+
+ if (fileInfo.isFile() && fileInfo.exists())
+ {
+ KURL url(fileInfo.filePath());
+ filesUrl.append(url);
+ }
+
+ ++it;
+ }
+
+ if (filesUrl.isEmpty() == false)
+ emit addedDropItems(filesUrl);
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/listimageitems.h b/kipi-plugins/slideshow/listimageitems.h
new file mode 100644
index 0000000..16e575d
--- /dev/null
+++ b/kipi-plugins/slideshow/listimageitems.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-21
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2003-2007 Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef LISTIMAGEITEM_H
+#define LISTIMAGEITEM_H
+
+// QT includes
+
+#include <qevent.h>
+#include <qwidget.h>
+#include <qstring.h>
+
+// KDE includes
+
+#include <klistbox.h>
+#include <kurl.h>
+
+namespace KIPISlideShowPlugin
+{
+
+class ImageItem : public QListBoxText
+{
+
+public:
+
+ ImageItem(QListBox * parent, QString const & name, QString const & comments, QString const & path,
+ QString const & album)
+ : QListBoxText(parent), _name(name), _comments(comments), _path(path), _album(album)
+ {}
+
+ QString comments() { return _comments; }
+ QString name() { return _name; }
+ QString path() { return _path; }
+ QString album() { return _album; }
+ void setName(const QString &newName) { setText(newName); }
+
+private:
+
+ QString _name;
+ QString _comments;
+ QString _path;
+ QString _album;
+};
+
+class ListImageItems : public KListBox
+{
+ Q_OBJECT
+
+ public:
+
+ ListImageItems(QWidget *parent=0, const char *name=0);
+
+ signals:
+
+ void addedDropItems(KURL::List filesUrl);
+
+ protected:
+
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dropEvent(QDropEvent *e);
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif /* LISTIMAGEITEM_H */
diff --git a/kipi-plugins/slideshow/plugin_slideshow.cpp b/kipi-plugins/slideshow/plugin_slideshow.cpp
new file mode 100644
index 0000000..3043893
--- /dev/null
+++ b/kipi-plugins/slideshow/plugin_slideshow.cpp
@@ -0,0 +1,267 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-01-31
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/time.h>
+}
+
+// C++ includes.
+
+#include <ctime>
+#include <cstdlib>
+
+// Qt includes.
+
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qstringlist.h>
+
+ // KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+// Lib KIPI includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imagecollection.h>
+
+// Local includes.
+
+#include "slideshow.h"
+#include "slideshowgl.h"
+#include "slideshowkb.h"
+#include "slideshowconfig.h"
+#include "plugin_slideshow.h"
+#include "plugin_slideshow.moc"
+
+typedef KGenericFactory<Plugin_SlideShow> Factory;
+
+K_EXPORT_COMPONENT_FACTORY(kipiplugin_slideshow, Factory("kipiplugin_slideshow"));
+
+Plugin_SlideShow::Plugin_SlideShow(QObject *parent, const char*,
+ const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "SlideShow")
+{
+ kdDebug( 51001 ) << "Plugin_SlideShow plugin loaded"
+ << endl;
+}
+
+void Plugin_SlideShow::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_actionSlideShow = new KAction (i18n("Advanced SlideShow..."),
+ "slideshow",
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "slideshow");
+
+ m_interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ m_urlList = new KURL::List();
+
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi m_interface is null!" << endl;
+ return;
+ }
+
+ m_actionSlideShow->setEnabled( false );
+
+ connect( m_interface, SIGNAL( currentAlbumChanged( bool ) ),
+ SLOT( slotAlbumChanged( bool ) ) );
+
+ addAction( m_actionSlideShow );
+}
+
+Plugin_SlideShow::~Plugin_SlideShow()
+{
+ if (m_urlList)
+ delete m_urlList;
+}
+
+void Plugin_SlideShow::slotActivate()
+{
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi m_interface is null!" << endl;
+ return;
+ }
+
+ bool allowSelectedOnly = true;
+
+ KIPI::ImageCollection currSel = m_interface->currentSelection();
+ if ( !currSel.isValid() || currSel.images().isEmpty() )
+ {
+ allowSelectedOnly = false;
+ }
+
+ m_imagesHasComments = m_interface->hasFeature(KIPI::ImagesHasComments);
+
+ KIPISlideShowPlugin::SlideShowConfig *slideShowConfig
+ = new KIPISlideShowPlugin::SlideShowConfig( allowSelectedOnly, m_interface,kapp->activeWindow(),
+ i18n("Slide Show").ascii(), m_imagesHasComments,
+ m_urlList);
+
+ connect(slideShowConfig, SIGNAL(buttonStartClicked()),
+ this, SLOT(slotSlideShow()));
+
+ slideShowConfig->show();
+}
+
+void Plugin_SlideShow::slotAlbumChanged(bool anyAlbum)
+{
+ if (!anyAlbum)
+ {
+ m_actionSlideShow->setEnabled( false );
+ return;
+ }
+
+ KIPI::Interface* m_interface = dynamic_cast<KIPI::Interface*>( parent() );
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi m_interface is null!" << endl;
+ m_actionSlideShow->setEnabled( false );
+ return;
+ }
+
+ KIPI::ImageCollection currAlbum = m_interface->currentAlbum();
+ if ( !currAlbum.isValid() )
+ {
+ kdError( 51000 ) << "Current image collection is not valid." << endl;
+ m_actionSlideShow->setEnabled( false );
+ return;
+ }
+
+ m_actionSlideShow->setEnabled(true);
+}
+
+void Plugin_SlideShow::slotSlideShow()
+{
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi m_interface is null!" << endl;
+ return;
+ }
+
+ KConfig config("kipirc");
+
+ bool opengl;
+ bool shuffle;
+ bool wantKB;
+
+ config.setGroup("SlideShow Settings");
+ opengl = config.readBoolEntry("OpenGL");
+ shuffle = config.readBoolEntry("Shuffle");
+ wantKB = config.readEntry("Effect Name (OpenGL)") == QString("Ken Burns");
+
+ if ( m_urlList->isEmpty() )
+ {
+ KMessageBox::sorry(kapp->activeWindow(), i18n("There are no images to show."));
+ return;
+ }
+
+ typedef QPair<QString, int> FileAnglePair;
+ typedef QValueList<FileAnglePair > FileList;
+ FileList fileList;
+ QStringList commentsList;
+
+ for( KURL::List::Iterator urlIt = m_urlList->begin(); urlIt != m_urlList->end(); ++urlIt )
+ {
+ KIPI::ImageInfo info = m_interface->info( *urlIt );
+ fileList.append( FileAnglePair((*urlIt).path(), info.angle()) );
+ commentsList.append(info.description());
+ }
+
+ m_urlList->clear();
+
+ if (shuffle)
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ srand(tv.tv_sec);
+
+ FileList::iterator it = fileList.begin();
+ FileList::iterator it1;
+
+ QStringList::iterator itcom = commentsList.begin();
+ QStringList::iterator itcom1;
+
+ for (uint i=0; i<fileList.size(); i++)
+ {
+ int inc = (int) (float(fileList.count())*rand()/(RAND_MAX+1.0));
+
+ it1 = fileList.begin();
+ it1 += inc;
+
+ itcom1 = commentsList.begin();
+ itcom1 += inc;
+
+ qSwap(*(it++), *(it1));
+ qSwap(*(itcom++), *(itcom1));
+ }
+ }
+
+ if (!opengl) {
+ KIPISlideShowPlugin::SlideShow* slideShow = new KIPISlideShowPlugin::SlideShow(fileList, commentsList, m_imagesHasComments);
+ slideShow->show();
+ }
+ else {
+ if (!QGLFormat::hasOpenGL())
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Sorry. OpenGL support not available on your system"));
+ else {
+ if (wantKB) {
+ KIPISlideShowPlugin::SlideShowKB* slideShow =
+ new KIPISlideShowPlugin::SlideShowKB(fileList, commentsList, m_imagesHasComments);
+ slideShow->show();
+ }
+ else {
+ KIPISlideShowPlugin::SlideShowGL * slideShow =
+ new KIPISlideShowPlugin::SlideShowGL(fileList, commentsList, m_imagesHasComments);
+ slideShow->show();
+ }
+ }
+ }
+}
+
+KIPI::Category Plugin_SlideShow::category( KAction* action ) const
+{
+ if ( action == m_actionSlideShow )
+ return KIPI::TOOLSPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::TOOLSPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/slideshow/plugin_slideshow.h b/kipi-plugins/slideshow/plugin_slideshow.h
new file mode 100644
index 0000000..4195556
--- /dev/null
+++ b/kipi-plugins/slideshow/plugin_slideshow.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-01-31
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef PLUGIN_SLIDESHOW_H
+#define PLUGIN_SLIDESHOW_H
+
+// KDE includes
+
+#include <kurl.h>
+
+// libKIPI includes.
+
+#include <libkipi/plugin.h>
+#include <libkipi/interface.h>
+
+class KAction;
+
+class Plugin_SlideShow : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_SlideShow(QObject *parent, const char* name,
+ const QStringList &args);
+ ~Plugin_SlideShow();
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+public slots:
+
+ void slotActivate();
+
+private slots:
+
+ void slotAlbumChanged(bool anyAlbum);
+ void slotSlideShow();
+
+private:
+
+ KAction* m_actionSlideShow;
+ KIPI::Interface* m_interface;
+ KURL::List* m_urlList;
+
+ bool m_imagesHasComments;
+};
+
+#endif // PLUGIN_SLIDESHOW_H
diff --git a/kipi-plugins/slideshow/screenproperties.cpp b/kipi-plugins/slideshow/screenproperties.cpp
new file mode 100644
index 0000000..55f1e91
--- /dev/null
+++ b/kipi-plugins/slideshow/screenproperties.cpp
@@ -0,0 +1,105 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qapplication.h>
+
+// X11 includes.
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+
+// Local includes.
+
+#include "screenproperties.h"
+
+namespace KIPISlideShowPlugin
+{
+
+ ScreenProperties::ScreenProperties(QWidget *mainWidget) {
+
+ activeScreen = QApplication::desktop()->screenNumber(mainWidget);
+ }
+
+ unsigned ScreenProperties::suggestFrameRate() {
+
+ int eventBase, errorBase;
+ if ( !XRRQueryExtension(qt_xdisplay(), &eventBase, &errorBase)) {
+ // No information, make a lucky guess on based on that ;)
+ return 25;
+ }
+
+ // ask X11 for the refresh rate of the current screen
+ XRRScreenConfiguration* config;
+ int screenRate;
+
+ config = XRRGetScreenInfo(qt_xdisplay(), RootWindow(qt_xdisplay(),
+ activeScreen));
+ screenRate = XRRConfigCurrentRate(config);
+ XRRFreeScreenConfigInfo(config);
+ //qDebug("monitor refresh rate %d Hz", screenRate);
+
+ // Find the frame rate, that matches the monitor's refresh rate best.
+ // We will choose between 25, 28 and 30 Hz, to get smooth animations.
+ // The following frame rate will be chosen according to the monitor's
+ // refresh rate:
+ //
+ // Frame rate: Monitor refresh rate
+ // 25 Hz (50), 75, 100 Hz (PAL compliant setups)
+ // 28 Hz 85 Hz, 110 Hz (seems to work ok)
+ // 30 Hz 60, 90, 120 Hz (NTSC compliant setups)
+ //
+ // However, this will only work, if the kernel can schedule the
+ // screensaver at the right time (a 2.6.x kernel should work fine,
+ // because of the high HZ value).
+ int candidateRate[3] = { 30, 25, 28 };
+ int bestRate = candidateRate[0];
+ int smallestError = 1000, i = 0;
+ do {
+ int r = candidateRate[i];
+ int error = QMIN(screenRate % r, (screenRate + r) % r);
+
+ if (error < smallestError) {
+ smallestError = error;
+ bestRate = r;
+ }
+ } while (++i < 3);
+
+ //qDebug("using %d Hz as framerate for effects", bestRate);
+ return bestRate;
+ }
+
+ bool ScreenProperties::enableVSync() {
+
+ // currently only supported on NVidia hardware using the
+ // proprietary driver
+
+ // For NVidia graphics cards: always use sync-to-vblank
+ // return (setenv("__GL_SYNC_TO_VBLANK", "1", 1) == 0);
+ return false;
+ }
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/screenproperties.h b/kipi-plugins/slideshow/screenproperties.h
new file mode 100644
index 0000000..3a94237
--- /dev/null
+++ b/kipi-plugins/slideshow/screenproperties.h
@@ -0,0 +1,49 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SCREEN_H
+#define SCREEN_H
+
+namespace KIPISlideShowPlugin
+{
+
+ class ScreenProperties {
+
+ public:
+
+ ScreenProperties(QWidget *mainWidget);
+ virtual ~ScreenProperties() { };
+
+ virtual unsigned suggestFrameRate();
+ virtual bool enableVSync();
+
+ protected:
+
+ unsigned activeScreen;
+ };
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // SCREEN_H
diff --git a/kipi-plugins/slideshow/slideshow.cpp b/kipi-plugins/slideshow/slideshow.cpp
new file mode 100644
index 0000000..8cc87c2
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshow.cpp
@@ -0,0 +1,1214 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-02-16
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdlib>
+#include <cassert>
+#include <cmath>
+#include <ctime>
+
+// Qt includes.
+
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qevent.h>
+#include <qcursor.h>
+#include <qfont.h>
+#include <qwmatrix.h>
+#include <qtextcodec.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdeversion.h>
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <kurl.h>
+
+// Local includes.
+
+#include "toolbar.h"
+#include "slideshow.h"
+#include "slideshow.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+SlideShow::SlideShow(const FileList& fileList, const QStringList& commentsList, bool ImagesHasComments)
+ : QWidget(0, 0, WStyle_StaysOnTop | WType_Popup | WX11BypassWM | WDestructiveClose)
+{
+#if KDE_IS_VERSION(3,2,0)
+ QRect deskRect = KGlobalSettings::desktopGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+#else
+ QRect deskRect = QApplication::desktop()->screenGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+#endif
+
+ move(m_deskX, m_deskY);
+ resize(m_deskWidth, m_deskHeight);
+ setPaletteBackgroundColor(black);
+
+ m_toolBar = new ToolBar(this);
+ m_toolBar->hide();
+ if (!m_loop)
+ {
+ m_toolBar->setEnabledPrev(false);
+ }
+ connect(m_toolBar, SIGNAL(signalPause()),
+ this, SLOT(slotPause()));
+
+ connect(m_toolBar, SIGNAL(signalPlay()),
+ this, SLOT(slotPlay()));
+
+ connect(m_toolBar, SIGNAL(signalNext()),
+ this, SLOT(slotNext()));
+
+ connect(m_toolBar, SIGNAL(signalPrev()),
+ this, SLOT(slotPrev()));
+
+ connect(m_toolBar, SIGNAL(signalClose()),
+ this, SLOT(slotClose()));
+
+ // ---------------------------------------------------------------
+
+ m_currImage = 0;
+ m_fileIndex = -1; // start with -1
+ m_effect = 0;
+ m_effectRunning = false;
+ m_intArray = 0;
+ m_endOfShow = false;
+
+ m_timer = new QTimer();
+ connect(m_timer, SIGNAL(timeout()),
+ this, SLOT(slotTimeOut()));
+
+ // --------------------------------------------------
+
+ m_fileList = fileList;
+ m_commentsList = commentsList;
+ m_ImagesHasComments = ImagesHasComments;
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("SlideShow Settings");
+
+ readSettings();
+
+ m_imageLoader = new SlideShowLoader(m_fileList, m_cacheSize, width(), height(), m_fileIndex);
+
+ // --------------------------------------------------
+
+ registerEffects();
+
+ if (m_effectName == "Random")
+ m_effect = getRandomEffect();
+ else
+ {
+ m_effect = Effects[m_effectName];
+ if (!m_effect)
+ {
+ m_effect = Effects["None"];
+ }
+ }
+
+ m_timer->start(10, true);
+
+ // -- hide cursor when not moved --------------------
+
+ m_mouseMoveTimer = new QTimer;
+ connect(m_mouseMoveTimer, SIGNAL(timeout()),
+ SLOT(slotMouseMoveTimeOut()));
+
+ setMouseTracking(true);
+ slotMouseMoveTimeOut();
+
+}
+
+SlideShow::~SlideShow()
+{
+ m_timer->stop();
+ delete m_timer;
+ m_mouseMoveTimer->stop();
+ delete m_mouseMoveTimer;
+
+ if (m_painter.isActive())
+ m_painter.end();
+
+ if (m_intArray)
+ delete [] m_intArray;
+
+ if (m_currImage)
+ delete m_currImage;
+
+ if (m_imageLoader)
+ delete m_imageLoader;
+
+ if (m_config)
+ delete m_config;
+}
+
+void SlideShow::readSettings()
+{
+ m_delay = m_config->readNumEntry("Delay", 1500);
+ m_printName = m_config->readBoolEntry("Print Filename", true);
+ m_printProgress = m_config->readBoolEntry("Print Progress Indicator", true);
+ m_printComments = m_config->readBoolEntry("Print Comments", false);
+ m_loop = m_config->readBoolEntry("Loop", false);
+
+ m_effectName = m_config->readEntry("Effect Name", "Random");
+
+ m_enableMouseWheel = m_config->readBoolEntry("Enable Mouse Wheel", true);
+
+ // Comments tab settings
+
+ m_commentsFont = new QFont();
+ m_commentsFont->setFamily(m_config->readEntry("Comments Font Family"));
+ m_commentsFont->setPointSize(m_config->readNumEntry("Comments Font Size", 10 ));
+ m_commentsFont->setBold(m_config->readBoolEntry("Comments Font Bold", false));
+ m_commentsFont->setItalic(m_config->readBoolEntry("Comments Font Italic", false));
+ m_commentsFont->setUnderline(m_config->readBoolEntry("Comments Font Underline", false));
+ m_commentsFont->setOverline(m_config->readBoolEntry("Comments Font Overline", false));
+ m_commentsFont->setStrikeOut(m_config->readBoolEntry("Comments Font StrikeOut", false));
+ m_commentsFont->setFixedPitch(m_config->readBoolEntry("Comments Font FixedPitch", false));
+
+ m_commentsFontColor = m_config->readUnsignedNumEntry("Comments Font Color", 0xffffff);
+ m_commentsBgColor = m_config->readUnsignedNumEntry("Comments Bg Color", 0x000000);
+
+ m_commentsLinesLength = m_config->readNumEntry("Comments Lines Length", 72);
+
+ // Advanced settings
+ bool enableCache = m_config->readBoolEntry("Enable Cache", false);
+ if (enableCache)
+ m_cacheSize = m_config->readNumEntry("Cache Size", 1);
+ else
+ m_cacheSize = 1;
+}
+
+void SlideShow::registerEffects()
+{
+ Effects.insert("None", &SlideShow::effectNone);
+ Effects.insert("Chess Board", &SlideShow::effectChessboard);
+ Effects.insert("Melt Down", &SlideShow::effectMeltdown);
+ Effects.insert("Sweep", &SlideShow::effectSweep);
+ Effects.insert("Noise", &SlideShow::effectRandom);
+ Effects.insert("Growing", &SlideShow::effectGrowing);
+ Effects.insert("Incom_ing Edges", &SlideShow::effectIncom_ingEdges);
+ Effects.insert("Horizontal Lines", &SlideShow::effectHorizLines);
+ Effects.insert("Vertical Lines", &SlideShow::effectVertLines);
+ Effects.insert("Circle Out", &SlideShow::effectCircleOut);
+ Effects.insert("MultiCircle Out", &SlideShow::effectMultiCircleOut);
+ Effects.insert("Spiral In", &SlideShow::effectSpiralIn);
+ Effects.insert("Blobs", &SlideShow::effectBlobs);
+}
+
+QStringList SlideShow::effectNames()
+{
+ QStringList effects;
+
+ effects.append("None");
+ effects.append("Chess Board");
+ effects.append("Melt Down");
+ effects.append("Sweep");
+ effects.append("Noise");
+ effects.append("Growing");
+ effects.append("Incom_ing Edges");
+ effects.append("Horizontal Lines");
+ effects.append("Vertical Lines");
+ effects.append("Circle Out");
+ effects.append("MultiCircle Out");
+ effects.append("Spiral In");
+ effects.append("Blobs");
+ effects.append("Random");
+
+ return effects;
+}
+
+QMap<QString,QString> SlideShow::effectNamesI18N()
+{
+ QMap<QString,QString> effects;
+
+ effects["None"] = i18n("None");
+ effects["Chess Board"] = i18n("Chess Board");
+ effects["Melt Down"] = i18n("Melt Down");
+ effects["Sweep"] = i18n("Sweep");
+ effects["Noise"] = i18n("Noise");
+ effects["Growing"] = i18n("Growing");
+ effects["Incom_ing Edges"] = i18n("Incom_ing Edges");
+ effects["Horizontal Lines"] = i18n("Horizontal Lines");
+ effects["Vertical Lines"] = i18n("Vertical Lines");
+ effects["Circle Out"] = i18n("Circle Out");
+ effects["MultiCircle Out"] = i18n("MultiCircle Out");
+ effects["Spiral In"] = i18n("Spiral In");
+ effects["Blobs"] = i18n("Blobs");
+ effects["Random"] = i18n("Random");
+
+ return effects;
+}
+
+void SlideShow::slotTimeOut()
+{
+ if (!m_effect) return; // No effect -> bye !
+
+ int tmout = -1;
+
+ if (m_effectRunning) // Effect under progress ?
+ {
+ tmout = (this->*m_effect)(false);
+ }
+ else
+ {
+ loadNextImage();
+
+ if (!m_currImage || m_fileList.isEmpty()) // End of slideshow ?
+ {
+ showEndOfShow();
+ return;
+ }
+
+ if (m_effectName == "Random") // Take a random effect.
+ {
+ m_effect = getRandomEffect();
+ if (!m_effect) return;
+ }
+
+ m_effectRunning = true;
+ tmout = (this->*m_effect)(true);
+ }
+
+ if (tmout <= 0) // Effect finished -> delay.
+ {
+ tmout = m_delay;
+ m_effectRunning = false;
+ }
+
+ m_timer->start(tmout, true);
+}
+
+void SlideShow::loadNextImage()
+{
+ if (m_currImage)
+ delete m_currImage;
+ m_currImage = 0;
+
+ m_fileIndex++;
+ m_imageLoader->next();
+ int num = m_fileList.count();
+ if (m_fileIndex >= num)
+ {
+ if (m_loop)
+ {
+ m_fileIndex = 0;
+ }
+ else
+ {
+ m_fileIndex = num-1;
+ return;
+ }
+ }
+
+ if (!m_loop)
+ {
+ m_toolBar->setEnabledPrev(m_fileIndex > 0);
+ m_toolBar->setEnabledNext(m_fileIndex < num-1);
+ }
+
+ QPixmap* oldPixmap = m_currImage;
+ QPixmap* newPixmap = new QPixmap(m_imageLoader->getCurrent());
+
+ QPixmap pixmap(width(),height());
+ pixmap.fill(Qt::black);
+
+ QPainter p(&pixmap);
+ p.drawPixmap((width()-newPixmap->width())/2,
+ (height()-newPixmap->height())/2, *newPixmap,
+ 0, 0, newPixmap->width(), newPixmap->height());
+
+ delete newPixmap;
+ m_currImage = new QPixmap(pixmap);
+ delete oldPixmap;
+
+ if (m_printName)
+ printFilename();
+
+ if (m_printProgress)
+ printProgress();
+
+ if (m_printComments && m_ImagesHasComments)
+ printComments();
+}
+
+void SlideShow::loadPrevImage()
+{
+ if (m_currImage)
+ delete m_currImage;
+ m_currImage = 0;
+
+ m_fileIndex--;
+ m_imageLoader->prev();
+ int num = m_fileList.count();
+ if (m_fileIndex < 0)
+ {
+ if (m_loop)
+ {
+ m_fileIndex = num-1;
+ }
+ else
+ {
+ m_fileIndex = -1; // set this to -1.
+ return;
+ }
+ }
+
+ if (!m_loop)
+ {
+ m_toolBar->setEnabledPrev(m_fileIndex > 0);
+ m_toolBar->setEnabledNext(m_fileIndex < num-1);
+ }
+
+ QPixmap* oldPixmap = m_currImage;
+ QPixmap* newPixmap = new QPixmap(m_imageLoader->getCurrent());
+
+ QPixmap pixmap(width(),height());
+ pixmap.fill(Qt::black);
+
+ QPainter p(&pixmap);
+ p.drawPixmap((width()-newPixmap->width())/2,
+ (height()-newPixmap->height())/2, *newPixmap,
+ 0, 0, newPixmap->width(), newPixmap->height());
+
+ delete newPixmap;
+ m_currImage = new QPixmap(pixmap);
+ delete oldPixmap;
+
+ if (m_printName)
+ printFilename();
+
+ if (m_printProgress)
+ printProgress();
+
+ if (m_printComments)
+ printComments();
+}
+
+void SlideShow::showCurrentImage()
+{
+ if (!m_currImage)
+ return;
+
+ bitBlt(this, 0, 0, m_currImage,
+ 0, 0, m_currImage->width(),
+ m_currImage->height(), Qt::CopyROP, true);
+}
+
+void SlideShow::printFilename()
+{
+ if (!m_currImage) return;
+
+ QPainter p;
+ p.begin(m_currImage);
+
+ p.setPen(QColor("black"));
+ for (int x=9; x<=11; x++)
+ for (int y=31; y>=29; y--)
+ p.drawText(x, height()-y, m_imageLoader->currFileName());
+
+ p.setPen(QColor("white"));
+ p.drawText(10, height()-30, m_imageLoader->currFileName());
+}
+
+void SlideShow::printComments()
+{
+ if (!m_currImage) return;
+
+ QString comments = m_commentsList[m_fileIndex];
+
+ int yPos = 30; // Text Y coordinate
+ if (m_printName) yPos = 50;
+
+ QStringList commentsByLines;
+
+ uint commentsIndex = 0; // Comments QString index
+
+ while (commentsIndex < comments.length())
+ {
+ QString newLine;
+ bool breakLine = FALSE; // End Of Line found
+ uint currIndex; // Comments QString current index
+
+ // Check minimal lines dimension
+
+ uint commentsLinesLengthLocal = m_commentsLinesLength;
+
+ for ( currIndex = commentsIndex; currIndex < comments.length() && !breakLine; currIndex++ )
+ if( comments[currIndex] == QChar('\n') || comments[currIndex].isSpace() ) breakLine = TRUE;
+
+ if (commentsLinesLengthLocal <= (currIndex - commentsIndex))
+ commentsLinesLengthLocal = (currIndex - commentsIndex);
+
+ breakLine = FALSE;
+
+ for ( currIndex = commentsIndex; currIndex <= commentsIndex + commentsLinesLengthLocal &&
+ currIndex < comments.length() &&
+ !breakLine; currIndex++ )
+ {
+ breakLine = (comments[currIndex] == QChar('\n')) ? TRUE : FALSE;
+
+ if (breakLine)
+ newLine.append( ' ' );
+ else
+ newLine.append( comments[currIndex] );
+ }
+
+ commentsIndex = currIndex; // The line is ended
+
+ if ( commentsIndex != comments.length() )
+ while ( !newLine.endsWith(" ") )
+ {
+ newLine.truncate(newLine.length() - 1);
+ commentsIndex--;
+ }
+
+ commentsByLines.prepend(newLine.stripWhiteSpace());
+ }
+
+ QPainter p;
+ p.begin(m_currImage);
+ p.setFont(*m_commentsFont);
+
+ for ( int lineNumber = 0; lineNumber < (int)commentsByLines.count(); lineNumber++ ) {
+
+ p.setPen(QColor(m_commentsBgColor));
+
+ // coefficient 1.5 is used to maintain distance between different lines
+
+ for (int x=9; x<=11; x++)
+ for (int y = (int)(yPos + lineNumber * 1.5 * m_commentsFont->pointSize() + 1);
+ y >= (int)(yPos + lineNumber* 1.5 * m_commentsFont->pointSize() - 1); y--)
+ p.drawText(x, height()-y, commentsByLines[lineNumber]);
+
+ p.setPen(QColor(m_commentsFontColor));
+
+ p.drawText(10, height()-(int)(lineNumber * 1.5 * m_commentsFont->pointSize() + yPos), commentsByLines[lineNumber]);
+ }
+}
+
+void SlideShow::printProgress()
+{
+ if (!m_currImage) return;
+
+ QPainter p;
+ p.begin(m_currImage);
+
+ QString progress(QString::number(m_fileIndex+1) + "/" + QString::number(m_fileList.count()));
+
+ int stringLenght = p.fontMetrics().width(progress) * progress.length();
+
+ p.setPen(QColor("black"));
+ for (int x=9; x<=11; x++)
+ for (int y=21; y>=19; y--)
+ p.drawText(x, height()-y, progress);
+
+ p.setPen(QColor("white"));
+ p.drawText(width() - stringLenght - 10, 20, progress);
+}
+
+EffectMethod SlideShow::getRandomEffect()
+{
+ QStringList effs = Effects.keys();
+ effs.remove("None");
+
+ int count = effs.count();
+
+ int i = rand() % count;
+ QString key = effs[i];
+
+ return Effects[key];
+}
+
+void SlideShow::showEndOfShow()
+{
+ QPainter p;
+ p.begin(this);
+ p.fillRect(0, 0, width(), height(), Qt::black);
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize()+10);
+ fn.setBold(true);
+
+ p.setFont(fn);
+ p.setPen(Qt::white);
+ p.drawText(100, 100, i18n("SlideShow Completed."));
+ p.drawText(100, 150, i18n("Click To Exit..."));
+ p.end();
+
+ m_endOfShow = true;
+ m_toolBar->setEnabledPlay(false);
+ m_toolBar->setEnabledNext(false);
+ m_toolBar->setEnabledPrev(false);
+}
+
+void SlideShow::keyPressEvent(QKeyEvent *event)
+{
+ if (!event)
+ return;
+
+ m_toolBar->keyPressEvent(event);
+}
+
+void SlideShow::mousePressEvent(QMouseEvent *e)
+{
+ if (m_endOfShow)
+ slotClose();
+
+ if (e->button() == Qt::LeftButton)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotNext();
+ }
+ else if (e->button() == Qt::RightButton && m_fileIndex-1 >= 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotPrev();
+ }
+}
+
+void SlideShow::mouseMoveEvent(QMouseEvent *e)
+{
+ setCursor(QCursor(Qt::ArrowCursor));
+ m_mouseMoveTimer->start(1000, true);
+
+ if (!m_toolBar->canHide())
+ return;
+
+ QPoint pos(e->pos());
+
+ if ((pos.y() > (m_deskY+20)) &&
+ (pos.y() < (m_deskY+m_deskHeight-20-1)))
+ {
+ if (m_toolBar->isHidden())
+ return;
+ else
+ m_toolBar->hide();
+ return;
+ }
+
+ int w = m_toolBar->width();
+ int h = m_toolBar->height();
+
+ if (pos.y() < (m_deskY+20))
+ {
+ if (pos.x() <= (m_deskX+m_deskWidth/2))
+ // position top left
+ m_toolBar->move(m_deskX, m_deskY);
+ else
+ // position top right
+ m_toolBar->move(m_deskX+m_deskWidth-w-1, m_deskY);
+ }
+ else
+ {
+ if (pos.x() <= (m_deskX+m_deskWidth/2))
+ // position bot left
+ m_toolBar->move(m_deskX, m_deskY+m_deskHeight-h-1);
+ else
+ // position bot right
+ m_toolBar->move(m_deskX+m_deskWidth-w-1, m_deskY+m_deskHeight-h-1);
+ }
+ m_toolBar->show();
+}
+
+void SlideShow::wheelEvent(QWheelEvent *e)
+{
+ if (!m_enableMouseWheel) return;
+
+ if (m_endOfShow)
+ slotClose();
+
+ int delta = e->delta();
+
+ if (delta < 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotNext();
+ }
+ else if (delta > 0 && m_fileIndex-1 >= 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotPrev();
+ }
+}
+
+void SlideShow::slotMouseMoveTimeOut()
+{
+ QPoint pos(QCursor::pos());
+ if ((pos.y() < (m_deskY+20)) ||
+ (pos.y() > (m_deskY+m_deskHeight-20-1)))
+ return;
+
+ setCursor(QCursor(Qt::BlankCursor));
+}
+
+int SlideShow::effectNone(bool /* aInit */)
+{
+ showCurrentImage();
+ return -1;
+}
+
+
+int SlideShow::effectChessboard(bool aInit)
+{
+ int y;
+
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_dx = 8; // width of one tile
+ m_dy = 8; // height of one tile
+ m_j = (m_w+m_dx-1)/m_dx; // number of tiles
+ m_x = m_j*m_dx; // shrinking x-offset from screen border
+ m_ix = 0; // growing x-offset from screen border
+ m_iy = 0; // 0 or m_dy for growing tiling effect
+ m_y = m_j&1 ? 0 : m_dy; // 0 or m_dy for shrinking tiling effect
+ m_wait = 800 / m_j; // timeout between effects
+ }
+
+ if (m_ix >= m_w)
+ {
+ showCurrentImage();
+ return -1;
+ }
+
+ m_ix += m_dx;
+ m_x -= m_dx;
+ m_iy = m_iy ? 0 : m_dy;
+ m_y = m_y ? 0 : m_dy;
+
+ for (y=0; y<m_w; y+=(m_dy<<1))
+ {
+ bitBlt(this, m_ix, y+m_iy, m_currImage, m_ix, y+m_iy,
+ m_dx, m_dy, CopyROP, true);
+ bitBlt(this, m_x, y+m_y, m_currImage, m_x, y+m_y,
+ m_dx, m_dy, CopyROP, true);
+ }
+
+ return m_wait;
+}
+
+int SlideShow::effectMeltdown(bool aInit)
+{
+ int i, x, y;
+ bool done;
+
+ if (aInit)
+ {
+ delete [] m_intArray;
+ m_w = width();
+ m_h = height();
+ m_dx = 4;
+ m_dy = 16;
+ m_ix = m_w / m_dx;
+ m_intArray = new int[m_ix];
+ for (i=m_ix-1; i>=0; i--)
+ m_intArray[i] = 0;
+ }
+
+ done = true;
+ for (i=0,x=0; i<m_ix; i++,x+=m_dx)
+ {
+ y = m_intArray[i];
+ if (y >= m_h) continue;
+ done = false;
+ if ((rand()&15) < 6) continue;
+ bitBlt(this, x, y+m_dy, this, x, y, m_dx, m_h-y-m_dy, CopyROP, true);
+ bitBlt(this, x, y, m_currImage, x, y, m_dx, m_dy, CopyROP, true);
+ m_intArray[i] += m_dy;
+ }
+
+ if (done)
+ {
+ delete [] m_intArray;
+ m_intArray = NULL;
+ return -1;
+ }
+
+ return 15;
+}
+
+int SlideShow::effectSweep(bool aInit)
+{
+ int w, h, x, y, i;
+
+ if (aInit)
+ {
+ // subtype: 0=sweep right to left, 1=sweep left to right
+ // 2=sweep bottom to top, 3=sweep top to bottom
+ m_subType = rand() % 4;
+ m_w = width();
+ m_h = height();
+ m_dx = (m_subType==1 ? 16 : -16);
+ m_dy = (m_subType==3 ? 16 : -16);
+ m_x = (m_subType==1 ? 0 : m_w);
+ m_y = (m_subType==3 ? 0 : m_h);
+ }
+
+ if (m_subType==0 || m_subType==1)
+ {
+ // horizontal sweep
+ if ((m_subType==0 && m_x < -64) ||
+ (m_subType==1 && m_x > m_w+64))
+ {
+ return -1;
+ }
+ for (w=2,i=4,x=m_x; i>0; i--, w<<=1, x-=m_dx)
+ {
+ bitBlt(this, x, 0, m_currImage, x, 0, w, m_h, CopyROP, true);
+ }
+ m_x += m_dx;
+ }
+ else
+ {
+ // vertical sweep
+ if ((m_subType==2 && m_y < -64) ||
+ (m_subType==3 && m_y > m_h+64))
+ {
+ return -1;
+ }
+ for (h=2,i=4,y=m_y; i>0; i--, h<<=1, y-=m_dy)
+ {
+ bitBlt(this, 0, y, m_currImage, 0, y, m_w, h, CopyROP, true);
+ }
+ m_y += m_dy;
+ }
+
+ return 20;
+}
+
+int SlideShow::effectRandom(bool /*aInit*/)
+{
+ int x, y, i, w, h, fact, sz;
+
+ fact = (rand() % 3) + 1;
+
+ w = width() >> fact;
+ h = height() >> fact;
+ sz = 1 << fact;
+
+ for (i = (w*h)<<1; i > 0; i--)
+ {
+ x = (rand() % w) << fact;
+ y = (rand() % h) << fact;
+ bitBlt(this, x, y, m_currImage, x, y, sz, sz, CopyROP, true);
+ }
+
+ showCurrentImage();
+
+ return -1;
+}
+
+int SlideShow::effectGrowing(bool aInit)
+{
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_x = m_w >> 1;
+ m_y = m_h >> 1;
+ m_i = 0;
+ m_fx = m_x / 100.0;
+ m_fy = m_y / 100.0;
+ }
+
+ m_x = (m_w>>1) - (int)(m_i * m_fx);
+ m_y = (m_h>>1) - (int)(m_i * m_fy);
+ m_i++;
+
+ if (m_x<0 || m_y<0)
+ {
+ showCurrentImage();
+ return -1;
+ }
+
+ bitBlt(this, m_x, m_y, m_currImage, m_x, m_y,
+ m_w - (m_x<<1), m_h - (m_y<<1), CopyROP, true);
+
+ return 20;
+}
+
+int SlideShow::effectIncom_ingEdges(bool aInit)
+{
+ int x1, y1;
+
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_ix = m_w >> 1;
+ m_iy = m_h >> 1;
+ m_fx = m_ix / 100.0;
+ m_fy = m_iy / 100.0;
+ m_i = 0;
+ m_subType = rand() & 1;
+ }
+
+ m_x = (int)(m_fx * m_i);
+ m_y = (int)(m_fy * m_i);
+
+ if (m_x>m_ix || m_y>m_iy)
+ {
+ showCurrentImage();
+ return -1;
+ }
+
+ x1 = m_w - m_x;
+ y1 = m_h - m_y;
+ m_i++;
+
+ if (m_subType)
+ {
+ // moving image edges
+ bitBlt(this, 0, 0, m_currImage, m_ix-m_x, m_iy-m_y, m_x, m_y, CopyROP, true);
+ bitBlt(this, x1, 0, m_currImage, m_ix, m_iy-m_y, m_x, m_y, CopyROP, true);
+ bitBlt(this, 0, y1, m_currImage, m_ix-m_x, m_iy, m_x, m_y, CopyROP, true);
+ bitBlt(this, x1, y1, m_currImage, m_ix, m_iy, m_x, m_y, CopyROP, true);
+ }
+ else
+ {
+ // fixed image edges
+ bitBlt(this, 0, 0, m_currImage, 0, 0, m_x, m_y, CopyROP, true);
+ bitBlt(this, x1, 0, m_currImage, x1, 0, m_x, m_y, CopyROP, true);
+ bitBlt(this, 0, y1, m_currImage, 0, y1, m_x, m_y, CopyROP, true);
+ bitBlt(this, x1, y1, m_currImage, x1, y1, m_x, m_y, CopyROP, true);
+ }
+ return 20;
+}
+
+int SlideShow::effectHorizLines(bool aInit)
+{
+ static int iyPos[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
+ int y;
+
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_i = 0;
+ }
+
+ if (iyPos[m_i] < 0) return -1;
+
+ for (y=iyPos[m_i]; y<m_h; y+=8)
+ {
+ bitBlt(this, 0, y, m_currImage, 0, y, m_w, 1, CopyROP, true);
+ }
+
+ m_i++;
+ if (iyPos[m_i] >= 0) return 160;
+ return -1;
+}
+
+int SlideShow::effectVertLines(bool aInit)
+{
+ static int ixPos[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
+ int x;
+
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_i = 0;
+ }
+
+ if (ixPos[m_i] < 0) return -1;
+
+ for (x=ixPos[m_i]; x<m_w; x+=8)
+ {
+ bitBlt(this, x, 0, m_currImage, x, 0, 1, m_h, CopyROP, true);
+ }
+
+ m_i++;
+ if (ixPos[m_i] >= 0) return 160;
+ return -1;
+}
+
+int SlideShow::effectMultiCircleOut(bool aInit)
+{
+ int x, y, i;
+ double alpha;
+ static QPointArray pa(4);
+
+ if (aInit)
+ {
+ startPainter();
+ m_w = width();
+ m_h = height();
+ m_x = m_w;
+ m_y = m_h>>1;
+ pa.setPoint(0, m_w>>1, m_h>>1);
+ pa.setPoint(3, m_w>>1, m_h>>1);
+ m_fy = sqrt((double)m_w*m_w + m_h*m_h) / 2;
+ m_i = rand()%15 + 2;
+ m_fd = M_PI*2/m_i;
+ m_alpha = m_fd;
+ m_wait = 10 * m_i;
+ m_fx = M_PI/32; // divisor must be powers of 8
+ }
+
+ if (m_alpha < 0)
+ {
+ m_painter.end();
+ showCurrentImage();
+ return -1;
+ }
+
+ for (alpha=m_alpha, i=m_i; i>=0; i--, alpha+=m_fd)
+ {
+ x = (m_w>>1) + (int)(m_fy * cos(-alpha));
+ y = (m_h>>1) + (int)(m_fy * sin(-alpha));
+
+ m_x = (m_w>>1) + (int)(m_fy * cos(-alpha + m_fx));
+ m_y = (m_h>>1) + (int)(m_fy * sin(-alpha + m_fx));
+
+ pa.setPoint(1, x, y);
+ pa.setPoint(2, m_x, m_y);
+
+ m_painter.drawPolygon(pa);
+ }
+
+ m_alpha -= m_fx;
+
+ return m_wait;
+}
+
+int SlideShow::effectSpiralIn(bool aInit)
+{
+ if (aInit)
+ {
+ startPainter();
+ m_w = width();
+ m_h = height();
+ m_ix = m_w / 8;
+ m_iy = m_h / 8;
+ m_x0 = 0;
+ m_x1 = m_w - m_ix;
+ m_y0 = m_iy;
+ m_y1 = m_h - m_iy;
+ m_dx = m_ix;
+ m_dy = 0;
+ m_i = 0;
+ m_j = 16 * 16;
+ m_x = 0;
+ m_y = 0;
+ }
+
+ if (m_i==0 && m_x0>=m_x1)
+ {
+ m_painter.end();
+ showCurrentImage();
+ return -1;
+ }
+
+ if (m_i==0 && m_x>=m_x1) // switch to: down on right side
+ {
+ m_i = 1;
+ m_dx = 0;
+ m_dy = m_iy;
+ m_x1 -= m_ix;
+ }
+ else if (m_i==1 && m_y>=m_y1) // switch to: right to left on bottom side
+ {
+ m_i = 2;
+ m_dx = -m_ix;
+ m_dy = 0;
+ m_y1 -= m_iy;
+ }
+ else if (m_i==2 && m_x<=m_x0) // switch to: up on left side
+ {
+ m_i = 3;
+ m_dx = 0;
+ m_dy = -m_iy;
+ m_x0 += m_ix;
+ }
+ else if (m_i==3 && m_y<=m_y0) // switch to: left to right on top side
+ {
+ m_i = 0;
+ m_dx = m_ix;
+ m_dy = 0;
+ m_y0 += m_iy;
+ }
+
+ bitBlt(this, m_x, m_y, m_currImage, m_x, m_y, m_ix, m_iy, CopyROP, true);
+
+ m_x += m_dx;
+ m_y += m_dy;
+ m_j--;
+
+ return 8;
+}
+
+int SlideShow::effectCircleOut(bool aInit)
+{
+ int x, y;
+ static QPointArray pa(4);
+
+ if (aInit)
+ {
+ startPainter();
+ m_w = width();
+ m_h = height();
+ m_x = m_w;
+ m_y = m_h>>1;
+ m_alpha = 2*M_PI;
+ pa.setPoint(0, m_w>>1, m_h>>1);
+ pa.setPoint(3, m_w>>1, m_h>>1);
+ m_fx = M_PI/16; // divisor must be powers of 8
+ m_fy = sqrt((double)m_w*m_w + m_h*m_h) / 2;
+ }
+
+ if (m_alpha < 0)
+ {
+ m_painter.end();
+ showCurrentImage();
+ return -1;
+ }
+
+ x = m_x;
+ y = m_y;
+ m_x = (m_w>>1) + (int)(m_fy * cos(m_alpha));
+ m_y = (m_h>>1) + (int)(m_fy * sin(m_alpha));
+ m_alpha -= m_fx;
+
+ pa.setPoint(1, x, y);
+ pa.setPoint(2, m_x, m_y);
+
+ m_painter.drawPolygon(pa);
+
+ return 20;
+}
+
+
+int SlideShow::effectBlobs(bool aInit)
+{
+ int r;
+
+ if (aInit)
+ {
+ startPainter();
+ m_alpha = M_PI * 2;
+ m_w = width();
+ m_h = height();
+ m_i = 150;
+ }
+
+ if (m_i <= 0)
+ {
+ m_painter.end();
+ showCurrentImage();
+ return -1;
+ }
+
+ m_x = rand() % m_w;
+ m_y = rand() % m_h;
+ r = (rand() % 200) + 50;
+
+ m_painter.drawEllipse(m_x-r, m_y-r, r, r);
+ m_i--;
+
+ return 10;
+}
+
+void SlideShow::startPainter(Qt::PenStyle aPen)
+{
+ QBrush brush;
+ brush.setPixmap(*(m_currImage));
+
+ if (m_painter.isActive())
+ m_painter.end();
+
+ m_painter.begin(this);
+ m_painter.setBrush(brush);
+ m_painter.setPen(aPen);
+}
+
+void SlideShow::slotPause()
+{
+ m_timer->stop();
+
+ if (m_toolBar->isHidden())
+ {
+ int w = m_toolBar->width();
+ m_toolBar->move(m_deskWidth-w-1,0);
+ m_toolBar->show();
+ }
+}
+
+void SlideShow::slotPlay()
+{
+ m_toolBar->hide();
+ slotTimeOut();
+}
+
+void SlideShow::slotPrev()
+{
+ loadPrevImage();
+ if (!m_currImage || m_fileList.isEmpty())
+ {
+ showEndOfShow();
+ return;
+ }
+ m_effectRunning = false;
+ showCurrentImage();
+}
+
+void SlideShow::slotNext()
+{
+ loadNextImage();
+ if (!m_currImage || m_fileList.isEmpty())
+ {
+ showEndOfShow();
+ return;
+ }
+ m_effectRunning = false;
+ showCurrentImage();
+}
+
+void SlideShow::slotClose()
+{
+ close();
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/slideshow.h b/kipi-plugins/slideshow/slideshow.h
new file mode 100644
index 0000000..4214ce9
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshow.h
@@ -0,0 +1,189 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-02-16
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SLIDESHOW_H
+#define SLIDESHOW_H
+
+// QT includes.
+
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include <qpair.h>
+#include <qstring.h>
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qmap.h>
+#include <qfont.h>
+#include <qstring.h>
+
+// KDE includes.
+
+#include <kconfig.h>
+#include <kurl.h>
+
+// Libkipi includes.
+
+#include <libkipi/imagecollection.h>
+#include <libkipi/interface.h>
+
+// Local includes.
+
+#include "slideshowloader.h"
+
+class QTimer;
+
+typedef QPair<QString, int> FileAnglePair;
+typedef QValueList<FileAnglePair > FileList;
+
+namespace KIPISlideShowPlugin
+{
+
+class ToolBar;
+
+class SlideShow;
+
+typedef int (SlideShow::*EffectMethod)(bool);
+
+class SlideShow : public QWidget
+{
+
+ Q_OBJECT
+
+public:
+
+ SlideShow(const FileList& fileList, const QStringList& commentsList, bool ImagesHasComments);
+ ~SlideShow();
+
+ void registerEffects();
+
+ static QStringList effectNames();
+ static QMap<QString,QString> effectNamesI18N();
+
+protected:
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *);
+ void wheelEvent(QWheelEvent *);
+ void keyPressEvent(QKeyEvent *event);
+
+ int effectNone(bool);
+ int effectChessboard(bool doInit);
+ int effectMeltdown(bool doInit);
+ int effectSweep(bool doInit);
+ int effectRandom(bool doInit);
+ int effectGrowing(bool doInit);
+ int effectIncom_ingEdges(bool doInit);
+ int effectHorizLines(bool doInit);
+ int effectVertLines(bool doInit);
+ int effectMultiCircleOut(bool doInit);
+ int effectSpiralIn(bool doInit);
+ int effectCircleOut(bool doInit);
+ int effectBlobs(bool doInit);
+
+ void startPainter(Qt::PenStyle penStyle=NoPen);
+
+private slots:
+
+ void slotTimeOut();
+ void slotMouseMoveTimeOut();
+
+ void slotPause();
+ void slotPlay();
+ void slotPrev();
+ void slotNext();
+ void slotClose();
+
+private:
+
+ void loadNextImage();
+ void loadPrevImage();
+ void showCurrentImage();
+ void printFilename();
+ void printComments();
+ void printProgress();
+ EffectMethod getRandomEffect();
+ void showEndOfShow();
+
+ void readSettings();
+
+private:
+
+ // config ------------------
+
+ KConfig* m_config;
+
+ int m_delay;
+ bool m_printName;
+ bool m_printComments;
+ bool m_printProgress;
+ QString m_effectName;
+ bool m_loop;
+
+ bool m_ImagesHasComments;
+
+ QFont* m_commentsFont;
+ uint m_commentsFontColor;
+ uint m_commentsBgColor;
+ int m_commentsLinesLength;
+
+ bool m_enableMouseWheel;
+
+ uint m_cacheSize;
+ // -------------------------
+
+ QMap<QString, EffectMethod> Effects;
+
+ SlideShowLoader* m_imageLoader;
+ QPixmap* m_currImage;
+
+ FileList m_fileList;
+ QStringList m_commentsList;
+ QTimer* m_timer;
+ int m_fileIndex;
+
+ EffectMethod m_effect;
+ bool m_effectRunning;
+
+ int m_commentsLinesLenght;
+
+ // values for state of various effects:
+ int m_x, m_y, m_w, m_h, m_dx, m_dy, m_ix, m_iy, m_i, m_j, m_subType;
+ int m_x0, m_y0, m_x1, m_y1, m_wait;
+ double m_fx, m_fy, m_alpha, m_fd;
+ int* m_intArray;
+ QPainter m_painter;
+
+ ToolBar* m_toolBar;
+ QTimer* m_mouseMoveTimer;
+ bool m_endOfShow;
+
+ int m_deskX;
+ int m_deskY;
+ int m_deskWidth;
+ int m_deskHeight;
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif /* SLIDESHOW_H */
diff --git a/kipi-plugins/slideshow/slideshowconfig.cpp b/kipi-plugins/slideshow/slideshowconfig.cpp
new file mode 100644
index 0000000..033fafa
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowconfig.cpp
@@ -0,0 +1,785 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-02-17
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qmap.h>
+#include <qframe.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qcolor.h>
+#include <qnamespace.h>
+#include <qlistbox.h>
+#include <qfileinfo.h>
+
+// Kde includes.
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kfontdialog.h>
+#include <kcolorbutton.h>
+#include <kio/previewjob.h>
+#include <kurl.h>
+
+// libkipi includes
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "listimageitems.h"
+#include "slideshow.h"
+#include "slideshowgl.h"
+#include "slideshowkb.h"
+#include "slideshowconfig.h"
+#include "slideshowconfig.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+SlideShowConfig::SlideShowConfig(bool allowSelectedOnly, KIPI::Interface * interface,
+ QWidget *parent, const char* name, bool ImagesHasComments,
+ KURL::List *urlList)
+ : SlideShowConfigBase(parent, name)
+{
+ // About data and help button.
+
+ KIPIPlugins::KPAboutData * about = new KIPIPlugins::KPAboutData(I18N_NOOP("Slide Show"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for image slideshow"),
+ "(c) 2003-2004, Renchi Raju\n(c) 2007, Valerio Fuoglio");
+
+ about->addAuthor("Renchi Raju", I18N_NOOP("Author"),
+ "renchi@pooh.tam.uiuc.edu");
+ about->addAuthor("Valerio Fuoglio", I18N_NOOP("Author and maintainer"),
+ "valerio.fuoglio@gmail.com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ // Switch to selected files only (it depends on allowSelectedOnly)
+
+ m_selectedFilesButton->setEnabled( allowSelectedOnly );
+
+ m_delayMsMaxValue = 100000;
+ m_delayMsMinValue = 100;
+ m_delayMsLineStep = 10;
+
+ m_delaySpinBox->setMinValue(m_delayMsMinValue);
+ m_delaySpinBox->setMaxValue(m_delayMsMaxValue);
+ m_delaySpinBox->setLineStep(m_delayMsLineStep);
+
+ m_interface = interface;
+
+ // Signal to Slot connections
+
+ connect(m_openglCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotOpenGLToggled()));
+ connect(m_buttonStart, SIGNAL(clicked()), this, SLOT(slotStartClicked()));
+ connect(m_printCommentsCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotPrintCommentsToggled()));
+ connect(m_commentsFontColor, SIGNAL(changed(const QColor &)), this, SLOT(slotCommentsFontColorChanged()));
+ connect(m_commentsBgColor, SIGNAL(changed(const QColor &)), this, SLOT(slotCommentsBgColorChanged()));
+ connect(m_useMillisecondsCheckBox, SIGNAL(toggled(bool)), SLOT(slotUseMillisecondsToggled()));
+ connect(m_delaySpinBox, SIGNAL(valueChanged(int)), this, SLOT(slotDelayChanged()));
+ connect(m_effectsComboBox, SIGNAL(activated(int)), this, SLOT(slotEffectChanged()));
+
+ connect(m_fileSrcButtonGroup, SIGNAL(clicked(int)), this, SLOT(slotSelection()));
+
+ connect( m_ImagesFilesListBox, SIGNAL( currentChanged( QListBoxItem * ) ),
+ this, SLOT( slotImagesFilesSelected(QListBoxItem *) ) );
+ connect(m_ImagesFilesListBox, SIGNAL( addedDropItems(KURL::List) ),
+ this, SLOT( slotAddDropItems(KURL::List)));
+ connect( m_ImagesFilesButtonAdd, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonAdd() ) );
+ connect( m_ImagesFilesButtonDelete, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonDelete() ) );
+ connect( m_ImagesFilesButtonUp, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonUp() ) );
+ connect( m_ImagesFilesButtonDown, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonDown() ) );
+
+ connect(m_cacheCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotCacheToggled()));
+
+ m_thumbJob = 0L;
+
+ // Configuration file management
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("SlideShow Settings");
+
+ readSettings();
+
+ slotUseMillisecondsToggled();
+
+ // Comments tab management
+
+ m_commentsFontChooser->setSampleText(
+ i18n("Slideshow is part of KIPI-Plugins (http://www.kipi-plugins.org)"));
+
+ // Host application images has comments
+ if ( ! ImagesHasComments ) {
+ m_printCommentsCheckBox->setEnabled(FALSE);
+ m_tabWidget->setTabEnabled(commentsTab, FALSE);
+ }
+
+ m_urlList = urlList;
+
+ slotSelection();
+ slotEffectChanged();
+}
+
+SlideShowConfig::~SlideShowConfig()
+{
+ if ( m_thumbJob ) delete m_thumbJob;
+ if ( m_config ) delete m_config;
+}
+
+void SlideShowConfig::loadEffectNames()
+{
+ m_effectsComboBox->clear();
+
+ QMap<QString,QString> effectNames = SlideShow::effectNamesI18N();
+ QStringList effects;
+
+ QMap<QString,QString>::Iterator it;
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.append(it.data());
+
+ m_effectsComboBox->insertStringList(effects);
+
+ for (int i=0; i<m_effectsComboBox->count(); i++) {
+ if (effectNames[m_effectName] == m_effectsComboBox->text(i)) {
+ m_effectsComboBox->setCurrentItem(i);
+ break;
+ }
+ }
+}
+
+void SlideShowConfig::loadEffectNamesGL()
+{
+ m_effectsComboBox->clear();
+
+ QStringList effects;
+ QMap<QString,QString> effectNames;
+ QMap<QString,QString>::Iterator it;
+
+ // Load slideshowgl effects
+ effectNames = SlideShowGL::effectNamesI18N();
+
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.append(it.data());
+
+ // Load Ken Burns effect
+ effectNames = SlideShowKB::effectNamesI18N();
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.append(it.data());
+
+ // Update GUI
+
+ effects.sort();
+ m_effectsComboBox->insertStringList(effects);
+
+ for (int i=0; i<m_effectsComboBox->count(); i++) {
+ if (effectNames[m_effectNameGL] == m_effectsComboBox->text(i)) {
+ m_effectsComboBox->setCurrentItem(i);
+ break;
+ }
+ }
+}
+
+
+void SlideShowConfig::readSettings()
+{
+ bool opengl;
+ int delay;
+ bool printFileName;
+ bool printProgress;
+ bool printFileComments;
+ bool loop;
+ bool shuffle;
+ bool showSelectedFilesOnly;
+ bool useMilliseconds;
+ bool enableMouseWheel;
+
+ opengl = m_config->readBoolEntry("OpenGL", false);
+ delay = m_config->readNumEntry("Delay", 1500);
+ printFileName = m_config->readBoolEntry("Print Filename", true);
+ printProgress = m_config->readBoolEntry("Print Progress Inticator", true);
+ printFileComments = m_config->readBoolEntry("Print Comments", false);
+ loop = m_config->readBoolEntry("Loop", false);
+ shuffle = m_config->readBoolEntry("Shuffle", false);
+ showSelectedFilesOnly = m_config->readBoolEntry("Show Selected Files Only", false);
+ m_effectName = m_config->readEntry("Effect Name", "Random");
+ m_effectNameGL = m_config->readEntry("Effect Name (OpenGL)", "Random");
+
+ useMilliseconds = m_config->readBoolEntry("Use Milliseconds", false);
+ enableMouseWheel = m_config->readNumEntry("Enable Mouse Wheel", true);
+
+
+ // Comments tab settings
+ uint commentsFontColor;
+ uint commentsBgColor;
+ int commentsLinesLength;
+
+ QFont *savedFont = new QFont();
+ savedFont->setFamily(m_config->readEntry("Comments Font Family"));
+ savedFont->setPointSize(m_config->readNumEntry("Comments Font Size", 10 ));
+ savedFont->setBold(m_config->readBoolEntry("Comments Font Bold", false));
+ savedFont->setItalic(m_config->readBoolEntry("Comments Font Italic", false));
+ savedFont->setUnderline(m_config->readBoolEntry("Comments Font Underline", false));
+ savedFont->setOverline(m_config->readBoolEntry("Comments Font Overline", false));
+ savedFont->setStrikeOut(m_config->readBoolEntry("Comments Font StrikeOut", false));
+ savedFont->setFixedPitch(m_config->readBoolEntry("Comments Font FixedPitch", false));
+
+ commentsFontColor = m_config->readUnsignedNumEntry("Comments Font Color", 0xffffff);
+ commentsBgColor = m_config->readUnsignedNumEntry("Comments Bg Color", 0x000000);
+
+ commentsLinesLength = m_config->readNumEntry("Comments Lines Length", 72);
+
+ // Advanced tab
+ bool enableCache, kbDisableFadeInOut, kbDisableCrossFade;
+
+ kbDisableFadeInOut = m_config->readBoolEntry("KB Disable FadeInOut", false);
+ kbDisableCrossFade = m_config->readBoolEntry("KB Disable Crossfade", false);
+
+ enableCache = m_config->readBoolEntry("Enable Cache", false);
+ m_cacheSize = m_config->readNumEntry("Cache Size", 5);
+
+
+ // -- Apply Settings to widgets ------------------------------
+
+ m_openglCheckBox->setChecked(opengl);
+
+ m_delaySpinBox->setValue(delay);
+
+ m_printNameCheckBox->setChecked(printFileName);
+
+ m_printProgressCheckBox->setChecked(printProgress);
+
+ m_printCommentsCheckBox->setChecked(printFileComments);
+
+ m_loopCheckBox->setChecked(loop);
+
+ m_shuffleCheckBox->setChecked(shuffle);
+
+ m_enableMouseWheelCheckBox->setChecked(enableMouseWheel);
+ m_useMillisecondsCheckBox->setChecked(useMilliseconds);
+
+ if (showSelectedFilesOnly && m_selectedFilesButton->isEnabled() )
+ m_selectedFilesButton->setChecked(true);
+ else
+ m_allFilesButton->setChecked(true);
+
+ m_commentsLinesLengthSpinBox->setValue(commentsLinesLength);
+ m_commentsFontColor->setColor(QColor(commentsFontColor));
+ m_commentsBgColor->setColor(QColor(commentsBgColor));
+ m_commentsFontChooser->setFont(*savedFont);
+ delete savedFont;
+
+ m_kbDisableFadeCheckBox->setChecked(kbDisableFadeInOut);
+ m_kbDisableCrossfadeCheckBox->setChecked(kbDisableCrossFade);
+
+ m_cacheCheckBox->setChecked(enableCache);
+
+ slotOpenGLToggled();
+ slotCacheToggled();
+}
+
+void SlideShowConfig::saveSettings()
+{
+ if (!m_config) return;
+
+ m_config->writeEntry("OpenGL", m_openglCheckBox->isChecked());
+
+ // Delay will be always saved as millisecond value, to keep compatibility
+ if ( m_useMillisecondsCheckBox->isChecked() )
+ m_config->writeEntry("Delay", m_delaySpinBox->value());
+ else
+ m_config->writeEntry("Delay", m_delaySpinBox->value()*1000);
+
+ m_config->writeEntry("Print Filename", m_printNameCheckBox->isChecked());
+ m_config->writeEntry("Print Progress Indicator", m_printProgressCheckBox->isChecked());
+ m_config->writeEntry("Print Comments", m_printCommentsCheckBox->isChecked());
+ m_config->writeEntry("Loop", m_loopCheckBox->isChecked());
+ m_config->writeEntry("Shuffle", m_shuffleCheckBox->isChecked());
+ m_config->writeEntry("Show Selected Files Only", m_selectedFilesButton->isChecked());
+
+ m_config->writeEntry("Use Milliseconds", m_useMillisecondsCheckBox->isChecked());
+ m_config->writeEntry("Enable Mouse Wheel", m_enableMouseWheelCheckBox->isChecked());
+
+ // Comments tab settings
+ QFont* commentsFont = new QFont(m_commentsFontChooser->font());
+ m_config->writeEntry("Comments Font Family", commentsFont->family());
+ m_config->writeEntry("Comments Font Size", commentsFont->pointSize());
+ m_config->writeEntry("Comments Font Bold", commentsFont->bold());
+ m_config->writeEntry("Comments Font Italic", commentsFont->italic());
+ m_config->writeEntry("Comments Font Underline", commentsFont->underline());
+ m_config->writeEntry("Comments Font Overline", commentsFont->overline());
+ m_config->writeEntry("Comments Font StrikeOut", commentsFont->strikeOut());
+ m_config->writeEntry("Comments Font FixedPitch", commentsFont->fixedPitch());
+ delete commentsFont;
+
+ QColor* fontColor = new QColor(m_commentsFontColor->color());
+ uint commentsFontColorRGB = fontColor->rgb();
+ delete fontColor;
+ m_config->writeEntry("Comments Font Color", commentsFontColorRGB);
+
+ QColor* bgColor = new QColor(m_commentsBgColor->color());
+ uint commentsBgColorRGB = bgColor->rgb();
+ delete bgColor;
+ m_config->writeEntry("Comments Bg Color", commentsBgColorRGB);
+
+ m_config->writeEntry("Comments Lines Length", m_commentsLinesLengthSpinBox->value());
+
+ if (!m_openglCheckBox->isChecked()) {
+
+ QString effect;
+ QMap<QString,QString> effectNames = SlideShow::effectNamesI18N();
+ QMap<QString,QString>::Iterator it;
+
+ for (it = effectNames.begin(); it != effectNames.end(); ++it) {
+ if (it.data() == m_effectsComboBox->currentText()) {
+ effect = it.key();
+ break;
+ }
+ }
+
+ m_config->writeEntry("Effect Name", effect);
+
+ }
+ else
+ {
+ QMap<QString,QString> effects;
+ QMap<QString,QString> effectNames;
+ QMap<QString,QString>::Iterator it;
+
+ // Load slideshowgl effects
+ effectNames = SlideShowGL::effectNamesI18N();
+
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.insert(it.key(),it.data());
+
+ // Load Ken Burns effect
+ effectNames = SlideShowKB::effectNamesI18N();
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.insert(it.key(),it.data());
+
+ QString effect;
+
+ for (it = effects.begin(); it != effects.end(); ++it) {
+ if ( it.data() == m_effectsComboBox->currentText()) {
+ effect = it.key();
+ break;
+ }
+ }
+
+ m_config->writeEntry("Effect Name (OpenGL)", effect);
+ }
+
+ // Advanced settings
+ m_config->writeEntry("KB Disable FadeInOut", m_kbDisableFadeCheckBox->isChecked());
+ m_config->writeEntry("KB Disable Crossfade", m_kbDisableCrossfadeCheckBox->isChecked());
+
+ m_config->writeEntry("Enable Cache", m_cacheCheckBox->isChecked());
+ m_config->writeEntry("Cache Size", m_cacheSizeSpinBox->value());
+
+ m_config->sync();
+}
+
+void SlideShowConfig::addItems(const KURL::List& fileList)
+{
+ if (fileList.isEmpty()) return;
+ KURL::List Files = fileList;
+
+ for ( KURL::List::Iterator it = Files.begin() ; it != Files.end() ; ++it )
+ {
+ KURL currentFile = *it;
+
+ QFileInfo fi(currentFile.path());
+ QString Temp = fi.dirPath();
+ QString albumName = Temp.section('/', -1);
+
+ KIPI::ImageInfo info = m_interface->info(currentFile);
+ QString comments = info.description();
+
+ ImageItem *item = new ImageItem( m_ImagesFilesListBox,
+ currentFile.path().section('/', -1 ), // File name with extension.
+ comments, // Image comments.
+ currentFile.path().section('/', 0, -1), // Complete path with file name.
+ albumName // Album name.
+ );
+
+ item->setName( currentFile.path().section('/', -1) );
+ }
+
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+ m_ImagesFilesListBox->setCurrentItem( m_ImagesFilesListBox->count()-1) ;
+ slotImagesFilesSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()));
+ m_ImagesFilesListBox->centerCurrentItem();
+}
+
+void SlideShowConfig::slotCommentsBgColorChanged()
+{
+ m_commentsFontChooser->setBackgroundColor(m_commentsBgColor->color());
+}
+
+void SlideShowConfig::slotCommentsFontColorChanged()
+{
+ m_commentsFontChooser->setColor(m_commentsFontColor->color());
+}
+
+void SlideShowConfig::slotPrintCommentsToggled()
+{
+ m_tabWidget->setTabEnabled(commentsTab, m_printCommentsCheckBox->isChecked());
+}
+
+void SlideShowConfig::slotUseMillisecondsToggled()
+{
+
+ int delayValue = m_delaySpinBox->value();
+
+ m_delaySpinBox->setValue(0);
+
+ if ( m_useMillisecondsCheckBox -> isChecked() ) {
+ m_delayLabel->setText(QString("Delay between images (ms):"));
+
+ m_delaySpinBox->setMinValue(m_delayMsMinValue);
+ m_delaySpinBox->setMaxValue(m_delayMsMaxValue);
+ m_delaySpinBox->setLineStep(m_delayMsLineStep);
+
+ m_delaySpinBox->setValue(delayValue*1000);
+ }
+ else {
+ m_delayLabel->setText(QString("Delay between images (s):"));
+
+ m_delaySpinBox->setMinValue(m_delayMsMinValue/1000);
+ m_delaySpinBox->setMaxValue(m_delayMsMaxValue/100);
+ m_delaySpinBox->setLineStep(m_delayMsLineStep/10);
+
+ m_delaySpinBox->setValue(delayValue/1000);
+ }
+}
+
+void SlideShowConfig::slotEffectChanged()
+{
+ bool isKB = m_effectsComboBox->currentText() == i18n("Ken Burns");
+
+ m_printNameCheckBox->setEnabled(!isKB);
+ m_printProgressCheckBox->setEnabled(!isKB);
+ m_printCommentsCheckBox->setEnabled(!isKB);
+
+ m_cacheButtonGroup->setEnabled(!isKB);
+}
+
+void SlideShowConfig::slotCacheToggled()
+{
+ bool isEnabled = m_cacheCheckBox->isChecked();
+
+ m_cacheSizeLabel1->setEnabled(isEnabled);
+ m_cacheSizeLabel2->setEnabled(isEnabled);
+ m_cacheSizeSpinBox->setEnabled(isEnabled);
+}
+
+void SlideShowConfig::slotOpenGLToggled()
+{
+ if (m_openglCheckBox->isChecked()) {
+ loadEffectNamesGL();
+ }
+ else {
+ loadEffectNames();
+ }
+
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+
+// slotEffectChanged();
+}
+
+void SlideShowConfig::slotDelayChanged()
+{
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+}
+
+void SlideShowConfig::slotSelection()
+{
+ KURL::List urlList;
+ if (m_selectedFilesButton->isChecked())
+ {
+ urlList = m_interface->currentSelection().images();
+
+ m_ImagesFilesButtonAdd->setEnabled(FALSE);
+ m_ImagesFilesButtonDelete->setEnabled(FALSE);
+ m_ImagesFilesButtonUp->setEnabled(FALSE);
+ m_ImagesFilesButtonDown->setEnabled(FALSE);
+ }
+ else
+ if (m_allFilesButton->isChecked())
+ {
+ KURL currentPath = m_interface->currentAlbum().path();
+ QValueList<KIPI::ImageCollection> albumList;
+ albumList = m_interface->allAlbums();
+ QValueList<KIPI::ImageCollection>::iterator it;
+
+ urlList = m_interface->currentAlbum().images();
+ for ( it = albumList.begin(); it != albumList.end(); ++it )
+ if (currentPath.isParentOf((*it).path()) && !((*it).path() == currentPath))
+ urlList += (*it).images();
+
+ m_ImagesFilesButtonAdd->setEnabled(FALSE);
+ m_ImagesFilesButtonDelete->setEnabled(FALSE);
+ m_ImagesFilesButtonUp->setEnabled(FALSE);
+ m_ImagesFilesButtonDown->setEnabled(FALSE);
+ }
+
+ if ( m_customButton->isChecked() ) // Custom selected
+ {
+ m_ImagesFilesButtonAdd->setEnabled(TRUE);
+ m_ImagesFilesButtonDelete->setEnabled(TRUE);
+ m_ImagesFilesButtonUp->setEnabled(TRUE);
+ m_ImagesFilesButtonDown->setEnabled(TRUE);
+ }
+ else
+ {
+ if (!urlList.isEmpty())
+ {
+ m_ImagesFilesListBox->clear();
+ addItems(urlList);
+ }
+ }
+}
+
+void SlideShowConfig::slotImagesFilesSelected( QListBoxItem *item )
+{
+
+ if ( !item || m_ImagesFilesListBox->count() == 0 )
+ {
+ m_label7->setText("");
+ m_ImageLabel->clear();
+ return;
+ }
+
+ ImageItem *pitem = static_cast<ImageItem*>( item );
+
+ if ( !pitem ) return;
+
+ KURL url;
+ url.setPath(pitem->path());
+
+ m_ImageLabel->clear();
+
+ if ( m_thumbJob ) delete m_thumbJob;
+
+ m_thumbJob = KIO::filePreview( url, m_ImageLabel->width() );
+
+ connect(m_thumbJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ SLOT(slotGotPreview(const KFileItem*, const QPixmap&)));
+ connect(m_thumbJob, SIGNAL(failed(const KFileItem*)),
+ SLOT(slotFailedPreview(const KFileItem*)));
+
+ int index = m_ImagesFilesListBox->index ( item );
+ m_label7->setText(i18n("Image no. %1").arg(index + 1));
+}
+
+void SlideShowConfig::slotAddDropItems(KURL::List filesUrl)
+{
+ addItems(filesUrl);
+}
+
+void SlideShowConfig::slotImagesFilesButtonAdd( void )
+{
+ KURL::List ImageFilesList =
+ KIPI::ImageDialog::getImageURLs( this, m_interface );
+ if ( !ImageFilesList.isEmpty() )
+ addItems( ImageFilesList );
+}
+
+void SlideShowConfig::slotImagesFilesButtonDelete( void )
+{
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ {
+ if (m_ImagesFilesListBox->isSelected(i))
+ {
+ m_ImagesFilesListBox->removeItem(i);
+ m_ImagesFilesListBox->setCurrentItem(i);
+ --i;
+ }
+ }
+
+ m_ImagesFilesListBox->setSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()), true);
+ slotImagesFilesSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()));
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+}
+
+void SlideShowConfig::slotImagesFilesButtonUp( void )
+{
+ int Cpt = 0;
+
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ if (m_ImagesFilesListBox->isSelected(i))
+ ++Cpt;
+
+ if (Cpt == 0)
+ return;
+
+ if (Cpt > 1)
+ {
+ KMessageBox::error(this, i18n("You can only move up one image file at once."));
+ return;
+ }
+
+ unsigned int Index = m_ImagesFilesListBox->currentItem();
+
+ if (Index == 0)
+ return;
+
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(Index) );
+ QString path(pitem->path());
+ QString comment(pitem->comments());
+ QString name(pitem->name());
+ QString album(pitem->album());
+ m_ImagesFilesListBox->removeItem(Index);
+ ImageItem *item = new ImageItem( 0, name, comment, path, album );
+ item->setName( name );
+ m_ImagesFilesListBox->insertItem(item, Index-1);
+ m_ImagesFilesListBox->setSelected(Index-1, true);
+ m_ImagesFilesListBox->setCurrentItem(Index-1);
+}
+
+void SlideShowConfig::slotImagesFilesButtonDown( void )
+{
+ int Cpt = 0;
+
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ if (m_ImagesFilesListBox->isSelected(i))
+ ++Cpt;
+
+ if (Cpt == 0)
+ return;
+
+ if (Cpt > 1)
+ {
+ KMessageBox::error(this, i18n("You can only move down one image file at once."));
+ return;
+ }
+
+ unsigned int Index = m_ImagesFilesListBox->currentItem();
+
+ if (Index == m_ImagesFilesListBox->count())
+ return;
+
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(Index) );
+ QString path(pitem->path());
+ QString comment(pitem->comments());
+ QString name(pitem->name());
+ QString album(pitem->name());
+ m_ImagesFilesListBox->removeItem(Index);
+ ImageItem *item = new ImageItem( 0, name, comment, path, album );
+ item->setName( name );
+ m_ImagesFilesListBox->insertItem(item, Index+1);
+ m_ImagesFilesListBox->setSelected(Index+1, true);
+ m_ImagesFilesListBox->setCurrentItem(Index+1);
+}
+
+void SlideShowConfig::ShowNumberImages( int Number )
+{
+ QTime TotalDuration (0, 0, 0);
+
+ int TransitionDuration = 2000;
+
+ if ( m_openglCheckBox->isChecked() )
+ TransitionDuration += 500;
+
+ if ( m_useMillisecondsCheckBox->isChecked() )
+ TotalDuration = TotalDuration.addMSecs(Number * m_delaySpinBox->text().toInt());
+ else
+ TotalDuration = TotalDuration.addSecs(Number * m_delaySpinBox->text().toInt());
+
+ TotalDuration = TotalDuration.addMSecs((Number-1)*TransitionDuration);
+
+ if ( Number < 2)
+ m_label6->setText(i18n("%1 image [%2]").arg(Number).arg(TotalDuration.toString()));
+ else
+ m_label6->setText(i18n("%1 images [%2]").arg(Number).arg(TotalDuration.toString()));
+}
+
+void SlideShowConfig::slotGotPreview(const KFileItem*, const QPixmap &pixmap)
+{
+ m_ImageLabel->setPixmap(pixmap);
+ m_thumbJob = 0L;
+}
+
+void SlideShowConfig::slotFailedPreview(const KFileItem*)
+{
+ m_thumbJob = 0L;
+}
+
+void SlideShowConfig::SlotPortfolioDurationChanged ( int )
+{
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+}
+
+void SlideShowConfig::slotStartClicked()
+{
+ saveSettings();
+
+ for (uint i=0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ {
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(i) );
+ if (!QFile::exists(pitem->path()))
+ {
+ KMessageBox::error(this,
+ i18n("Cannot access to file %1, please check the path is right.").arg(pitem->path()));
+ return;
+ }
+ m_urlList->append(pitem->path()); // Input images files.
+ }
+
+ emit buttonStartClicked();
+}
+
+
+void SlideShowConfig::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("slideshow",
+ "kipi-plugins");
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/slideshowconfig.h b/kipi-plugins/slideshow/slideshowconfig.h
new file mode 100644
index 0000000..b3c2ca9
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowconfig.h
@@ -0,0 +1,121 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-02-17
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SLIDESHOWCONFIG_H
+#define SLIDESHOWCONFIG_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qlistbox.h>
+
+// KDE includes
+
+#include <kconfig.h>
+#include <kio/previewjob.h>
+#include <kurl.h>
+
+// libkipi includes
+
+#include <libkipi/imagedialog.h>
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "slideshowconfigbase.h"
+
+namespace KIPISlideShowPlugin
+{
+
+class SlideShowConfig : public SlideShowConfigBase
+{
+ Q_OBJECT
+
+public:
+
+ SlideShowConfig(bool allowSelectedOnly, KIPI::Interface* interface,
+ QWidget *parent, const char* name, bool ImagesHasComments,
+ KURL::List* urlList);
+ ~SlideShowConfig();
+
+private slots:
+
+ void slotStartClicked();
+ void slotHelp();
+ void slotOpenGLToggled();
+ void slotEffectChanged();
+ void slotDelayChanged();
+ void slotUseMillisecondsToggled();
+ void slotPrintCommentsToggled();
+ void slotCommentsFontColorChanged();
+ void slotCommentsBgColorChanged();
+
+ void slotSelection();
+ void slotCacheToggled();
+
+ void SlotPortfolioDurationChanged ( int );
+ void slotImagesFilesSelected( QListBoxItem *item );
+ void slotAddDropItems(KURL::List filesUrl);
+ void slotImagesFilesButtonAdd( void );
+ void slotImagesFilesButtonDelete( void );
+ void slotImagesFilesButtonUp( void );
+ void slotImagesFilesButtonDown( void );
+ void slotGotPreview(const KFileItem* , const QPixmap &pixmap);
+ void slotFailedPreview(const KFileItem*);
+
+signals:
+
+ void buttonStartClicked(); // Signal needed by plugin_slideshow class
+
+private:
+
+ void loadEffectNames();
+ void loadEffectNamesGL();
+ void readSettings();
+ void saveSettings();
+
+ void ShowNumberImages( int Number );
+ void addItems(const KURL::List& fileList);
+
+private:
+
+ int m_delayMsMaxValue;
+ int m_delayMsMinValue;
+ int m_delayMsLineStep;
+
+ uint m_cacheSize;
+
+ KConfig* m_config;
+
+ QString m_effectName;
+ QString m_effectNameGL;
+
+ KIO::PreviewJob* m_thumbJob;
+ KURL::List* m_urlList;
+
+ KIPI::Interface* m_interface;
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // SLIDESHOWCONFIG_H
diff --git a/kipi-plugins/slideshow/slideshowconfigbase.ui b/kipi-plugins/slideshow/slideshowconfigbase.ui
new file mode 100644
index 0000000..4c18fb1
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowconfigbase.ui
@@ -0,0 +1,1522 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KIPISlideShowPlugin::SlideShowConfigBase</class>
+<widget class="KDialog">
+ <property name="name">
+ <cstring>SlideShowConfigBase</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>678</width>
+ <height>640</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Slideshow</string>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="modal">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>m_tabWidget</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mainTab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Main</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_fileSrcButtonGroup</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_allFilesButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Show all images in current al&amp;bum</string>
+ </property>
+ <property name="accel">
+ <string>Alt+B</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_selectedFilesButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Show onl&amp;y selected images</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Y</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_customButton</cstring>
+ </property>
+ <property name="text">
+ <string>Custom</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_ImagesFilesGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Image Files in slideshow</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Preview the currently selected image.</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIPISlideShowPlugin::ListImageItems">
+ <property name="name">
+ <cstring>m_ImagesFilesListBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the list of the image files for your portfolio.
+The portfolio's first image is on the top; the last image is on the bottom.
+If you want to add some images, click on the 'Add' button or use the drag-and-drop.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_label6</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>None</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Total number of images in the portfolio and sequence duration.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonAdd</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Add...</string>
+ </property>
+ <property name="accel">
+ <string>Alt+A</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Add some image files to the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonDelete</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ <property name="accel">
+ <string>Alt+D</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Remove some image files from the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonUp</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Image &amp;Up</string>
+ </property>
+ <property name="accel">
+ <string>Alt+U</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Moving the current image up on the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonDown</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Image D&amp;own</string>
+ </property>
+ <property name="accel">
+ <string>Alt+O</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Moving the current image down on the portfolio list.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_ImageLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>128</width>
+ <height>128</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Preview the currently selected image.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_label7</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>None</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Currently selected image in the portfolio list.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout50</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout47</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Video options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_openglCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>238</width>
+ <height>33</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Use Open&amp;GL slideshow transitions</string>
+ </property>
+ <property name="accel">
+ <string>Alt+G</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer59</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>2</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Content options</string>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_printNameCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>P&amp;rint filename</string>
+ </property>
+ <property name="accel">
+ <string>Alt+R</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_printProgressCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Progress indicator</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_printCommentsCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Pr&amp;int captions </string>
+ </property>
+ <property name="accel">
+ <string>Alt+I</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer58</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Playback options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_loopCheckBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Loop</string>
+ </property>
+ <property name="accel">
+ <string>Alt+L</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_shuffleCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Shuffle images</string>
+ </property>
+ <property name="accel">
+ <string>Alt+S</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout48</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_delayLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Delay between images (s):</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_delaySpinBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="maxValue">
+ <number>100000</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="lineStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout49</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Transition effect:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>m_effectsComboBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="currentItem">
+ <number>0</number>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer57</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>2</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>commentsTab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Comments</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KFontChooser">
+ <property name="name">
+ <cstring>m_commentsFontChooser</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout57</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox7</cstring>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout52</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Font color :</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer62</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>15</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_commentsFontColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="defaultColor">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout51</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer61</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>15</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_commentsBgColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer66</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>81</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout55</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Line length (in characters) :</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer65</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>15</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_commentsLinesLengthSpinBox</cstring>
+ </property>
+ <property name="buttonSymbols">
+ <enum>UpDownArrows</enum>
+ </property>
+ <property name="maxValue">
+ <number>500</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>72</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Advanced</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox5</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Interface</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_useMillisecondsCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Use milliseconds instead of seconds</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox8</cstring>
+ </property>
+ <property name="title">
+ <string>Controls</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_enableMouseWheelCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Enable mouse wheel (move between images)</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup3</cstring>
+ </property>
+ <property name="title">
+ <string>Ken Burns effect</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_kbDisableFadeCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Disable fade-in / fade-out</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_kbDisableCrossfadeCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Disable crossfade</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_cacheButtonGroup</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>Others</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_cacheCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Enable cache</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_cacheSizeLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Cache size:</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14_4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_cacheSizeSpinBox</cstring>
+ </property>
+ <property name="maxValue">
+ <number>20</number>
+ </property>
+ <property name="minValue">
+ <number>5</number>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_cacheSizeLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>images</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_KBCacheLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Notice&lt;/b&gt;:
+Ken Burns effect doesn't use this cache mechanism.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer10_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>90</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>50</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="0" column="3">
+ <property name="name">
+ <cstring>m_buttonExit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Exit</string>
+ </property>
+ <property name="accel">
+ <string>Alt+E</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>m_buttonStart</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Start Slideshow</string>
+ </property>
+ <property name="accel">
+ <string>Alt+S</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>m_helpButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Help</string>
+ </property>
+ <property name="accel">
+ <string>F1</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KIPISlideShowPlugin::ListImageItems</class>
+ <header location="local">listimageitems.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image1</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="13969">89504e470d0a1a0a0000000d4948445200000080000000800806000000c33e61cb0000200049444154789ced9d77785cc5b9ff3fa7ecaeb4eabd59cd1d775cc102dc30d52114d10288d0434202f64d4808218d7b93c0bd84248484104288136ac0178c31bd1830dd185cb071b7254b966c6955b6ef39677e7f9cddd5566955b0b93ffc7d9ef39c3667e69cf9bef3ce3b33efcc91388a94b162e9b27c4992a6e49665970b43741b86d1e577073aceb8fdd79b8ff4bb0d16d2917e812f33562c5d9667b35baf43e23a9fcb5f4d92fc921559a467a7b5dbd22d9f671566bc5836b6f83fcbeb1ac4617edd41e1a80024c08aa5cb0a54abfaa8e6d7160fe679d5aa88bcf29cf74a47172d1d73e675ef0ff7fb0d278e0a400c56fdf887dfd6fcfaef0cddb0445ecfabaaa478cc18b24af249cbcc40b5d9f0bbba71b61da2f3401b8ec603380f1e421846f8195991c9afc8d99a57967df9e48b6efce0b07f4c0a382a001158f9a39b7fa7f9b41b43e7b2aa3276e10246cf3b094bba1d8440204004370422e258f3ba68dfb98d1d6f7fc0a15dfbc2f12a1685a2eabc753925d9674cacbfa1ed087c5a521c15802056fef0073fd4fcfa6f42e7c563c732fda20b49cfcd352ff4437eecfd80d74dd3c7ebd8fcc2eb189a0e80cd6e350a2a73ff5932b2f0dada53aef61f81cf8cc3510100562c5d361f783d743eeaa4139972f6d9bd01844008237c6c926f441c03c2202c0811421170f7b0fd8d37d9f9eefa6078b0e7a67baa26955d39e1bc1b1e3b3c5f981c5f790158b17499a258941d7a40af012839663cc75f7d359214cc9a21901fa911bcdd5d6c787a156d3bf60220c9124535f91f1755e79f3ceeaceb1d87f9b3c3908f54c25f16c88a7c6d88fcf4bc5c6637340c3bf908812d2b8b59975ec88cf34f435615842168dbd53e7dcffaa6d68f97fff69ac3ffe526bed21a60c5d26559b222371bba910930e78a2b289f3cc9bc398ce487cf837b6f673beb573c4747632b00b2225131bee4d98a634aebcbeb1a0eab6df095d600b2227f2b447ed198d126f942803082e4f71e87c90f911d3c17b1e48b24e487c31ad872f29873f9c51cb3681600862e68dc7ce06b3b3f6adcb7efb507c71fce3cf8ca6a80154b97c98a4569d6037a8924cb2c58b694ecb2328829ad91e4c6113ae0b0bd1ac50c6be0d8bb9b754fbe48c0e30320bb384bab9a5476ced8af7d6bd5e1c887afb20638550fe82500d573669be447a8f894c91703203f2aac799e5b59cd89d75c44de886200badb7ad41d1fec5db9e9893ffce47064c257560054ab720b80a4281c73eaa908c38852dfb1c7890935ab09113a8eaa2e82e71810653bf49e87d2b0666432fb1be7523dc3d4fe5ea74fdaf951e3edeb1ebaebb1e6b5cbbf502dfd951480154b97156a7ebd0ea062ca14ac191908c308d687d11d3c894b768850620cc3e41d4342248837326e4962fca2794c387926007a4067df86e60b9bb7b5bdd5bc76b9ed8bca8bafa40020712ec16faf9d7b7c906448484c42f283a163c927494b80e8f8e204251c06461c7b2c934f9b832449082168dcd852d7b2e3e0a75f94107c250540b5aa5703e4545490575585d075a448f58c11b6d823557b587593a855d047f591e81e912d88882a01289b34892967cc41924d21d8f769f3b8966d6d1f36af5d9e36dc79f1956b05ac58baac006803e469f5f554ce980e4220ab520431906a1bdfdbb985271efc25bb0f2a14955410f0b938d4ba97f6d6dda8aa4a6141018b4f3e9919732f464e2f4ca0058c60d4a1348c703a07b76d65c3eaf73174034992a89c5cf649f9d8e239c3d957a00e5744ff6720712e02d9929646f994c908219024064cbef3c047ac7aea8f94574fe0bc4b6fc0220790f46e64dd89e4cca463c72e9adbbdb47434b27ecd035c7ff31f38767c2e0b4e98c9c5d7fe1e53f9864a3ec4928f10148d1ecb94d3fc7cbafae35075300d78b779edf2e3caeb1a02c3931d5f31acfce1cdef697e6d4ecd9c394cfafa5908c3405165242975f23f597d33ba7d0cb38e9f876c3841eb3137dd055a37b876205a9f8b4ad7ed3378e4352f7f5deda1ba3c9bdffcea2eca6b8f4b4a7eb88a3074f67fbc8ead6f6d35239260e48caa778b6af3eb2ae60eddebe82b6503ac58ba2c5f0b68b3002a674c47e83a2082f57f0409c9ea6dc3cfaa07afa672e242e6d42d44161ed0dca07b4cf27517e86e107a4cca02bb4de2ead3d379edbff350848b53cfbb8a375ff80b10b23112a729215131752a23269487a262efa7fb8f771e74fd6c38f2e42b2500c03908e4ecb232b2cbcac2ea3f69074f5433d0e05ffff335e69c720d2515e37ac9365ca03941f782e63205424416cce8429a9126f18f9bb329cd93f98f5fdc8ba36d6fdfcd4704c80aa3e64e27bb3013309b888d9b5b6e6b7af3a121771b7fa50440b5aad741b0f40b81300c64594a817cc1e637ff884f29a6acb4c4245a0f12afb9c0f080ee3405427783e10ba69858435b15899f5d9a49578fc69dbf5e16df248c7b1f03353d8363164c41b12800741f74ca2ddb0e3edfbc76f990ecb8af8c00ac58baac44f36b332d6969544c9d6a76fcc890acdd1ed501a47bb9f3ee3f70e925df30c936426adf1d3c764554036e44c04132f24397678db32049f0bfaf6d47d3b4089bc388233ff43ef6a23246cea80947b57f6b6b8dbbdb7beb50f265d85b01f5f5f569c02460e230c43f64232784669f7754b92d4daa9a350bc562411802459523323b79efdeba57efa5bd4b909157132ce9bd64a305052174aebb2090c0bf23e64bac168124491886a0b3d341417e3ed1fd01f11d479224513e691c6dbbdae86aebc1d00d9ab7b6feb879edf27bcbeb1a0e0d265f864d00eaebeb47003703d7025f58d7e560e1d4b503b2aa523d6736c230335696a5947af7366dfc98821cb9b7d4c794f8decd83d05de08fe1224e8c051f7eae6118e68d4ec7410af273fb243f742c5bd2187ddc38d63dfb110838d4e8b01654e6dd035c3c987c191601a8afaf3f1d7802c8cccfcda5acb8989cec6c4c0babd7aa0ee543a4c52b42e7e68de86ba11299e89960f86471879e75bbdd34b7b6a2084a2ba64cc16acf4008034595a24a7ec22a20782c2b36d66ded46efda8c925668aa79cd851412022da8fa75a759fa75576fe64491df7bf2e7551e00f273ed5455d7c6373b230521e6fd324b4ac82fcfa5637f270868d9d67661f3dae53f2baf6bd83650ee862c00f5f5f517008fa9aacaf44993185156164598882129d97506183ed5b0465010244932fbfd0d1d21048a62494c7ee479703f79fa3c5cdee778fce1fbf8c6e5df05c3876444ab7da105fb003c8dbd999384fc475ff7b27693d99977d629c7615194b8929e8c7c1048b24af5b1a3e8d8bf0e80ee834ea9a3b9eb6ee0cc81f2372423b0bebebe0ef857467a3aa7ce9b277dd9c80f5d0728a8a9253d373748be045282cc4d40be1082a9732f62dab87c6eb9773b2f3cfe6be85a0fde9660c9ef41f80f82771fb87680d0cccc4942fe9b1b03fcf25fa6865055858b2ebc2e45f27b8d418420bbb484dcd29c70bc1dfbbb4e6d5ebb3c77a01c0e5a03d4d7d7e7032f288aa2cc9d354bb259ad83261f20dd6ec766b361b5d968debfbfcf78422365a90a0a40e9f871849a7e4aba2565f243c70ffc7d35679db5806bfea785d2bf3dc6826956164db372c2642bf6588b2701f95ebfe02fcf79f8ed536e84008b45e19e3b7e1156fffd916f1e87f2cb0049a27ada483a5f580f40c7fe4ec537a1f46ae07f06c2e350aa80ef0399d3274d222b2363c0e4cf98338731e3c79366b361b15aa322bef777bf0b3b68248a67e1e2c54c9e3a95e6fdfbd9b7772f7bf7eca1a9a9092d104898268062b522741dc522234182cc36c2192ca25a05022120b7a09855abdfe2e69b2ee69577b6f3e8eb1e1e7ddd832c49cc1aa7525ea0509a27539a27539227539c2bd3ead0693c68b0eb80ce136b7c61a34f9615eef8f92d9c74d229096c8e50b5440cf9f1f6494e592199f919383b5c189a417b53e7520e8700d4d7d7170337e664658911e5e5d2604a7e56561659595909e3ef2b9ec953a7326dfa74002aabaaa8acaaa2eec413d1759dc67dfbd8bd6b176fbff5569c00844857adca80c90f91929595cb9fffb69add3b3673cfdd3fe5a5b7b7e2f3fb797f6b0008c494fc0490244e9831869b6eba8509e32712f2118c233ff8ce7d910f026485aac9957cb6c61c27686f749407078ade4b95cbc16a809b01fb3163c6843f60306a3f1992c553565ecea2534e49f88ca228d4d4d6b2fee38fe3d2045300144bc8e41938f99142533bf218eebae7091082a6a6263e5df70a9fae7f8f4d5b77a2697af039f3f990119a694f63d9d2db9834694a449d3e78f243c7f95525586c3b08f8345c9d1e1c2d5d3f06ce4a95c8010b407d7d7d19f09ddcec6c515652220d86fcf07112248a27232383b3ce3d174551923eb7e68d37d8b86143620190242c568578f243c7c490df876116713ea2a29c8af2cb3863c9a571cff5868df401ec238db8e7e28f7b05d5dc64d54a6e590e07f7b403d0b1bfebf4e6b5cb73caeb1aba52e173301ae00740da84b1630755f2c3a4f4a10562e3916599b3ce3d97cccccca4cf6cdab89135afbf9ef05d0014e146ef3980303484a183a143f058080d9091240521c948b20c928c242b0842c7b2794f52a2fa3708698d505a41c253263492fc0402d717f92101ceaf2cea1580a64e75c484d22b81bb5321734002505f5f2f031767666488e2c2c2f8d21fcc84d163c7929199c9fa8f3e4a487e7f1a209499a16dd129a7505e5191346ce3be7dac7cfae9c482180cf3ec1f6ee44dfffea8e7168f8402fb4072009024d28f399dac13bf879a5f7dc4c94708724b7a5b7fba66d0d5daf3c50800701c505a515a9ab4e44f9a368d59c71d0740654d0dafbdf4129d0e479c00f485c870e3c68f67cab46949c33a1c0e1e7ff45102a11640024d04a05528f82d6ab0be87cc341871aa8c640873d38080b9179a40d20504005d849f4198b378dcdb9ec7bbfd350acebf0f6be5cc08bbe68b22df88681544930f028bdd863d371d77a7d9bbe8eef18e6d5ebb5c29af6b88754c88c3403b82ce05282b2e4e5cf2c78d0b930f50545ccc79175dc4ece38f27dd6e475155264e999272e9cfccca62f1e9a7270da7691a8ffceb5fb85cae3eab21003907e44205b94046c997a99c28a356c8a865326a898c5a2c612991514b24ac2512d62289b402415a31a495405a29a495817d0414cc16a8693e3a56dc80eeeda4d7713401f92211a149c80f911d477eafed104b7ee8fbf22bf2c3f9e27678ac988371fd62a01ae05c7b7abac8ceca921265762235adaa2ac7ce9cc9b133672284c0300c367cf2499f5a2074eff4254b484b4bee08fbfc73cf71e8e0c1bec98f4a478412c06e939104511b4220456cc92029903d51d0febe0bcfc69564ccb824258b3dec001a476e50cbc46890beaa80a87304b96539346d36ab3897c38da11bc7031b927e4410296b80fafafa69406d59717142f28510bcb7762d1e8f2779c605a75da75205cc9c3d9bea9a9aa461366fdac4c7ebd6f54b7e282d2998c95230699b353a334df28952f77d41b68092a6a0b5ef3ee2e40b21c82ac84292cdfcd535839e7657e2f6720c06a201be0e501a52ff31992d84c0ed72b1e6d557396dc9928411b85c2e5e7be9a50425331a8545459c387f7ed2fb0e87836757ae4c89fc702a91eeaf02fc3e7a89360061762f4bc17329d0b704183ed03d1a96b28983235fe8ec7efd9f6cdbb31f455550550baaaaa02a2a16ab85a9d36721178e0bbe6edfe423049222634bb7e07599834cee2eef9c3e3f20888108c05c4551446e76769f3d7f7b77efe6b38d1b99307972d4c3fbf6ece1e5175e60cef1c7b36bc78e3e0bd892af7f3d697b5fd7759efaf7bff17a3c29911fab01429bd345d479dcd60fbcad8024631b75524c09edbb83470ab8f868f5df59fbc62ba886871cbb8da2aab118c28fcfe360f781831ce83178e4f127e9f149d45414336bda24662f389dcca29a84e48340022c5102e0296f5ebb3cabbcaea1a7afef484900eaebeb2560764e569644e4404c82128810ac5db38611555564e798a355cd4d4dbcf9da6b5c74d965f47477f75b0514141626bdf7daabafd2d4d89832f9bd6989703d8f10b477082423a2156000e1e3bedfcfb517dcfbc03ef56ce4b49c18f2a389e9255fb071e5ef59b1f279ae3bdece4f2e998b54bb10b2cac1d70dfe1e445723e2d3e584245037e0f9cf1dfcf5e957f8d9df5e62e985759cddf03db34f2241b563b3dbe8c11c6974393c12300378a3af6f4955038c0672737372fa253f64e8c9b2695e747775f1e2ead57ced9c73d8b7670fafbcf0422a052c29f6eed93320f24302a06fd6f007b470e93e00ec6f136459217c312c2b12c1d183decb912f2d0419b32e23ebc41b239a677d906ff879e12fb7221fdcc45d3fbc028e39170c0dfc3de0eb01cd8308b8c37184a0c8b064bc9525e3adbcba23c04d8fbfcd932f7fc87fdf7e0b65b5137ac9377484a163b1f56a4d7797075d3366334c02300b20272bab5ff285104c9c3285cce040cf9bafbfce717575b41e38c0cbcf3f9fa064c643d3345435f1ab9d7bde79dc7bcf3df863dafdc9c80fa573d2c233a8ca33e31498f4e6e7d849b75906249002b0148fc33a627a30ddbebb7685b79b7b7e720d8baa7dccbdfea7503d0fe1eb41d23c10f040c08df0bbcde3d8f904112fb668b48567afc8e6d407bab8e9d63bf8e7437f41956584a185ed294b5ad4da96683eadb4bfef49550066430201209e7c4992387696b9f489a3a3834e8783a2e2621ef9c73f52221fe0ed37df64fec28509efe51714b068f162563ff75c4ae487d21a39bf8171636a139214abaa7bdbdc84ebf1e461632cf6c87885e0897b7f4e555a3773affb1be48d848013026ef0bb107e2752c00d0157f0ba076415742de1b7d7e449dcb2209d9fbde4e61ff7fe0f577e7b69d47d6b7a8c0004f4bc3e339ad49b81b32d168b919696169fb911c7aaaab2f88c33c27df69fac5bc7e469d3f8e8fdf7d1753d4e7892e1bd77dee1c0810349ef1f3f772e232a2b53261f4092e17093dfd3f829cfbdf529972c39010ac622026e84cf85a4b920e0420ab81181e06492902024a4a437ee85a3cd32fbc0f31be30a52ac06d0037abf1e42a90ac0949cac2c3936738b4a4a983c6d1af34e3e99b3cf3f9f6b6eb88151c1216280fd4d4d545557f3f9962d09ebeb64d0759d679f79062362dddd484892c4b9e79d8712f4a54b467e5843011252827a3a62ea7714f9a1e3a1f5ee3df8a7df715cb58a3af51208b891348fa9fafd26e12244badf650a80cf097ae49c4f81889c360614d8252409029a4167b7332a5f544b74cb49d7f4ecfe88ed570082ce1f19e931a5df66b371ee051730f7a4933866e244ca627a018510b85c2e7c3e5f7ce9efa70a1040f3fefdbcf7eebb49c3141717b370e1c27ec90fa524857c00c37576ec387f30a3fbea7c49a441e21c4bcd6561843058b7ed00e579e9c1d2ef4204891661f2dd613b00bf1b3c1d043b25c2c4c7e2ddbd5ab8ec74767646ddd302d15587ae89c41e37114845038c048815002589911682d3e9242323c36cf69180a43e9e0d8579ed95577038922fa2397fe142aaaaaa92931f216c1221377048e4e411579a1334b3e28ffbe9dd93243e6e0a80bf0729e03155bedf89140896f8282170219c2d7d1610dd803fbd6b4e3b2bc8b631a2a23ceabee68b36220d5d4f3e7e1e44ea02909e3ea0be1229326c2431293c1b0aef0f0458f9f4d3c9d390242eb9ec32323233a3e34f50d548e156dd61221f83638fa9e1f9cd4e3ab6bf6b121c70236911aa3fe002bf13e1eb41781c084f6782afecc57deff958d764927cf682e958d46895aff9a33580a18b7e07bb531680580330e0f7f7a9caed1919389d4eb212351dfbb10122c36ddfbe9d0fde4ffecf859c9c1c2ebdf4d2684fe104d58d04bdea3a499d1e4bbe08139ec87688a84ee2dcb74cf57dc9d5df0549e294ebee64cfee5d41a32f6803f8dd087fb05af074203a7691ac6808017f79cfc7dd6f790148b32a9c73ee7971e102710260f42b00a934034d0d60b34565aac7e3e1ef7ff90b452525141416925f504071490979f9f94892842ccbd8ed762c160baaaae2f7fbe3b44132c4aaf155cf3e4bc588115424710a19357a34672e59c233cf3c93b4aa31c7a19295e6484d10ef959b3c6c020d1211b6b0bc96fb7efd7daebbe52e4e6af82927d5cd664e6d3693cb542697409e7110e171803bf1b43e21e0bd7d1af7beebe3eddd26b9b99956eefdd50f29298eef2d8dad02148be28a0b14835404a0c6a2aa862ccb71ad0097cb8573e74eb36f3f782d333b9b6baebf1e805163c6b067f76e468e1ecd96cf3e1b9406104210080478f89fffe4bb37de487a7a7ac267e62f58c09e3d7b58bf7e7d9c2d00200735c4e1223fa441a61d379f979f9ac8f2fbef61f90b1fb2e62db3652349509c29519e2d539c29539c2951922993972ed1dc6db0a3dde08d5d017c118d8282ec34eefbef9f50533522611ec4560136bb6567dfd4a6260039aaaac6b97f4102c34e08babbba686b6da5b8a484c953a6f0f8238f70de0517b063c70e7c5e6fd4f3c990c868ece8e8e089c71fa7e1f2cb7b57f38ec1c5dff806cdcdcdb4b4b444910f20741fc2e74408dd5c19c4d041e8611f41499240921192123c36cfcdadd7993465f2858eee73a1fbdda4a9826bbf7d03977cd3cd138f3cccc79fed64fdce43b4f668b4f6e840df8e3bb999362e3b6b1ee79f5f4f7a9a3569b880375a00ecd9e9fdfa03a42200998aa2a42c0002d8ba650bc52525e4e4e652535bcb8eeddb597cca293c1ba9a2fb4830364e4992c8cdcb63f3a64dbcb9660df3920c15abaacac44993686e89b7a61ffd493d697a7754f8f9b5509058a1c423281092a2621bb318fbaccb91338be285c2d0d0bd4ef480274ecb65d8ed5c71f5355c113cdfbbbf8dcf37ae63efbe460cc308ca4e306f8339644f4fe3924b1bb058faa7caddddeb8b61b1a958d32dfdfece2e1501c8521425be051052b1b19b10ecddb327fcf0490b16f08f071fe4f433cf64f4d8b16cfbfcf338f20dc3a0a3a30387c381a3a323981966fc16ab9599336670f0d0215c4e27cfad5a45555515b52347026677f3e6cd9bd9b46913dbb66f376d8d182105708f90d164353c2268b749542c964c6f20a3d70750d240e8024913a011e11328001d43d3f16c7d0edf8ed7c85972274ac9044020f400bab707ddef0de550bfa8ae28a6ba22b9cbdb40e0f704a234802dd306b0a3bfe752d300b21c572ac30290400be4e7f7faa7a5a5a5f18d4b2f65f9430f71d6d96733a2b292375e7b8d0f3ff8800fde7f1f87c34177708838762b2e2961d6ac596cdcb081abafbd96a6c646fefca73ff1c0030fb060c1023efef863f647ce238c789f58c8c5b2e963101cfaadaa014bad8ca499644b41875034732f0540f625ee89b457083a3778e85efd63722e5e8ea16be87e770a59f9c5c1d519ed89959669851404209566a05d0e75b946929f6403386eeedca808b2b2b3b9e4b2cb58bd6a155e8f87ebaebf1e5996d9b7776f42f2b373723873c912468f1ecda64d9bf8e6955762b55a19396a14a79f79266eb79b55ab56a54c3e10525bc16341469a34789f40157226090c5f0fee0d2b8e38f940d823388434bb2d0034f7f75c9f1aa0bebe3e1d5062350009323db4cd9c3327a143476e5e1e575e730defbef30e0ffeed6f4c9a3c9925679d85c7e361f7ae5d288a426e6e2e1e8f87d6d656d6ac59435d5d1dd77ffbdb51f12c5cb8105992a8a9ade5d1471ea1b9b9b97ff20139d80b18ed1348541fc0807c02ada0d8648caea6be031e26b83aa385d092ae1e48e5efa5fd55019900722201209efcc2c242e62d589034328bc5c249f3e631e7b8e3d8ba650b2fbff4121d1d1d6163c962b5525850c0e4a9533973c992a4d6fefc601a575e751577dc71073e9fafdf964514a302fc7e7a891e8c4fa01f74af8e9a57dd4fba8707b15540469e3da53f96a62400093500f102b060f1e2a48e1cefbdf30ec74c98404e6e2e369b8da9d3a631b58f091fa9a0a4a48433cf3c93a79e7a2ab507224ab7cb197d3ea07e6ec0db0648126ac5f4c1bcfab042f3ebf85cbdcb07dbec5632f3ec2b537936350d10d10a8088763ad179b6f1d34f19396a5454045d5d5d3cfaf0c3b43437b37af56a66cc9cc949f3e6919797dc57211008b079d326b66fdfcefbefbf4f4e6e2e8b162d62ce9c3971cea27b225a1c8910d20c9230a27c023b1c83f70974379a7e816af55ca4b49c3ec31e0e74b644376fb38b3221e23f887d61c05540940148b416d8b47123e9763ba79c761a604ed85cb572259e90072f84adfffa0b2ee0d8638f8d4bd0300c6ebbf55673aa5730fef6438778fcb1c778fbadb768b8fc724a8353d31e7bec31d6ad5b97ca7712586ffacd858cc166a0a50332ad44947a296a1f6a9147ee10207403cb9845d8a65f96343d49d7d8f0bf66215454054555515515c562eef3f2b2c9983c2dd4473d247434474f04ceccb7b796d735a4649cf427003e206a3cbf2f011042f0febbefe2743a5114257aae7e4cd8d5ab563175ead4b0f36808870e1e8c223f726b6c6ce457bffa15679c71068d8d8dac5fbf3ed53ce2e4f98bb1abf4722c203dcf4e7a9a6a9a20a15f05ea7ab013c7e8bd08114449c879d5a8e589ab2fbdb989971ffe37ef7df239858585548c1a4b5e5131c2e741eb6963e307efd2e63368f30bac8acc98f2428e9d389aa9c7cfa060f2149007365bcfd00dba5aa335405661c6aba93edf9f006c050cb7db2da72a000212ced18f0ddbd3d3c3eeddbb19155365b4b6b626ed5f1080a1ebac5c9952f516858967dd44a63d9da45db78646c0e540f73949be0241727876efe499fb97a33adab978511d975ff00d28ab018f0bdcdde6ded383e1fa0c34b3be16c09af66efef9dabbdcf2efb7985992c92d4bbfc9885933534eb7abcd89aef5f657a465dab0e7a43f9beaf37d8adb934f3ee9063e7074760abfdfdf3ff9c9b624611b1b1be3d26c89e8c64d16c76010fa1f5022f2356f0fbecefde83e67df912441e38b2ff0b75fdec5158b4ee486fb1f23ffd2ff40aa1c0b3e2ff8dce00fee7d1eb0f4f6e54bc0fc0295bf4dc9e09313b3a9c0c7f9b7fc913fffe897783b3a524adb11a3feb3cc05a5df48f5dd53d137ff650821ed899c8c3140a293856ddebf3f2eb18402c0d0c88790434834f986e6c7d7d542c0790891c4ffb0cf38758d37eefe03ef3cf33cb7df731f39177e0f6c7624af1bbc2ef07b4cd2839bf0ba4149ac74b35589bb27d8f96e8d8dbf7fb88babaeb915771fde50000870b4c4084081bda9bcae21b9476d0cfa1580279f7c7215f04c6757178da14e1712b702a208ebefba10ecdcb913b7db8dd7ebc5ebf5e276bbd9bd7b777cf821901f6e059827e6b961107075e0ebdc8f11f00e2a5e8057eebe87773fdac88dbffd338c9c84f079103e37047c089f07bcee0801f09afb24378f76a20000164c494441540210c28d35699c536a615ba7873b6ebbabcfb0dd879c51fdff8a2a93579ef3e040be21d579011703efb71e3c38d9edf1505d5969f60d90bcae4ee57a576727b7dd7a6b4ae1870ad3234c60047cf8bb5b11fad0feb8d2f3d926fef1d626567def62a89988e47182df6b0a419078e1f32005054184aa8014705d958d1507023cbfa5896fed69a4aca63261b8d69dd18e247915b9c2625307240029999c4f3ef9a407980b3cd1e374f2d9d6ada2a9b9196fb0076e30e43380f0c3014902cddd89af73ff90c94708fe78d75f39bfd48275ded9617243c4874abe14ac0244443580b75f271dc6d895b04fe5aead89c773fc9e001dfba3d57f7e45cefaf2ba86bd03f9949467073ff9e4934ee0c2f3ebeb1fc954d5c7da1d8eb47687839cec6cac562b1655c562b1600d2efa986ca14723746e1883223f1581880c139a5b10e86e450effc86168300eece799bd5d9c373d074a6b903c3d08af1bc9ef41f83da6d1e7f7823796fca041d80fb6b9f470b783e3506263b075e7a1a8efb46558c92bcbfec340bf65c0ab845d5c59e505d20ef97c6cf37ad8e774269dc0f1658211f0202bc3f37f8c832d6de8029c86045e67b8b40b8f0bbc1ed3e20fd7ffeea031e846b43787c73dfac2b36dbd1aca921ddfd368e806adbbdaa3ae1556e5f925497a72a0df32600150adcacf35bf4ea1cdc6ac050b183173061ddd0eda1ded1c686be3406b1bba6eba5849f4ae0a2249a66fbe149c781b3a0ede25ec85150c2c91f89c88ebbdf782bf7e233a9ce137bd7025091479f87e9056386a24aa044f36ba387dd3bb4895634df51f6aee79dd26e191ad008f0bbadafb8dfba32e8dbfec3335559eddc6fcd3e6c58539b4cf11e7ff975f91fb6c795d43fff54b0c0624002b962e9ba4f9f5f02a50c563c7a2aa2a35b523a8a9ade8ed5409b5b763dbdca1e388fb51e789c246dc37c3c6afa8191bd6d0fcf8bb5a31b4e151f9b1507272f9fa84113cb5b9893ffffe6eaeffc18fc16a3389f67bcd5680df1bb4fcbde0ee4134ed483ae93384169fc1351bdd68c14f3b77e14c6c564b5cb8033ba28dbfeca24c3272d3ff38a86f1948e06f9c74c26f84218e05c82a2ea66ad64c2c36c55c82f54b42bee6e9c6d7652e08f94562ca8c49ac79f94d56edeb66cf076b48777752ac68a83e0f04fcd0e300471be2d07e68de65ae07d0079e6e0d70d506375d41f6a7d694f2c39fde8835c617d0d1dcc5811d07a3ae554c2c6d1a73e675370ee63b52d68b2b962e9314556ed735230f60e409275039fd58d2b36d31ffde192cb982212dba280c7cdd6de8de3e57441956b437b7b0ec0777f2d901b3c3460246d965e6e6a99c90af52619329b2c9145b1367f3019fc1eab600ffdb1a60634faf67f0dc63aab9e3ae5b49b3457b000b43f0e9cb5bf1f6f46a367b4e1a93178dbbb8e2c4cb1f1bcc370ca40a981e221fcc7a5008611a567d1213128cfe17478e132212909f409b0843c3d7d932a44e9dc1a0a0bc8c7f3c7c372faf58cdfd8f3dcf9ef61e76b80d76b8fd2cdfdf3b3e2f01f91689629b4c8145a2d56fb0db6d84557d088a2273f9e973b9f6c62b51120c0ab5ee3a14453e40d998e22649969e18ec37a42c00b2229f67e82689b2aa62cbca4256a4debf6ef6477eb079174f7e02c20740be11f0e1eb6a197adb7e08587cee192c3ef70c3edfba93ed9f6c62db961d6cd9d3c296d64e7c010d01b40704ed81c4feff19360bf50b6771d1951752989fd8bf400be8347dd61a75cd9e93466155decde5750d836e86a52c008a2a2f0a09405a561618c2fcf152927ada1c4f8f243f816d9080dca48210577d18e83e17beaed6b07639d218377e14e3c6478f6eeededd445bf301821912d678e1bd21987de22cd43e564107d8bfa535cef20f96fec787f2ce290b80a11be12f4bcbcec6fcf3964cbf46da17447ec0e520e0ecbf5975a4515b3b82dadac453b95285d7e58b33fc86a3f4438a02b062e9b20c5d33c2cefeb6ac2cf3cf9bc111b678f2fb217128e40b1d7f771bda301a7b02c18b6deff1abbf3f8ee3800b599150541959955014194595c9ceb2b368f654ce9fb1801a5bd9b0a59d0a76ad6b0cfeebb017c351fa21750d504b448bc19a918130823f5e3e8ce40b2330ecc6decbad1ff0fb179fe2a0a7938a53f2b974e23728cdae20dd6aa753ebe0e56dcfb06bf74edc87ba7972c31aeefbfdcb648fb632ffb8c9fce2f42bc8563386ed5d12a16d773bdd6dd17e0a9979760aabf36f1c6ae987d40520aa82d2037e7ad7d58927374e1806d2c687601cd16d7c43f3e173ec37fdfa86015ee1e382bfff9c565f07b32e9fc0b7aabecb31b9c7e2d1dcb835276edd49a69e415e7936d999bdd9547a968db697fdac7c741d2bffb58e0baf389e5f9d76edb0bc53dc3b3a7decfd34da674292252aa794bf517142c38ae14823550188d23f7e971ba11b18ba8ea2ca29901b2294a87abcaf367e645cbadf83bfb339287443c721ad934bfefe9fa4cd94b8fdb4ff645afe5c5c811ebcba3b6e93a5e8e698629728fbba8dd2afd9d8f367378ffce91d366dd9c7d337de6efe897c98208460c707fba2dcbd004a4717fa728a32937ba30e10a90a40d45bf8dd2e843030340359918695fcc79fd670743ab059156c5605ab1c40357a484fb371fc342f8a2c180a1a7dad5cfc87ffa2ec3c3bb79f7c1f85b6125c5a0f3edd835b77e2d1dd780d375edd834773232719319764a8fdb61dc3e762c3eb4d7ca7f877fcf992a509c30e06fbb7b4e2ec88eeda4fcbb45131bee487a97afca682540520cadc0eb83d08c340f30750ad664b20be8307c2e447d6eb4904e58db53adfffd9d3ec6bfa08f3ff3d3624ac8005dd3880aeef44c24a7eee2cc68f1cc99d3f984455c5c0dafe02c1657ffc35b6591ab7ccff6f8a6ca5b834a759da83a4fb740f5edd13d600823e044e82ea6bec6cfe410fcf3ff1291f9df83933abc60de89d12c1d9e166ff96d6b8ebd553ca37a956f59e212710819404e0dcbb7fdbf2f4f7bfef34742313c0ef72210c81cfed272dd33a24f2b76c177cf7476fb06d672e1919cbf8e63773a8aa92282a0287c3e0edb70d3efcc0acf70da39340e07ddefde437d45dbc9cda11a7f2e06f1630ba2a35bbe0895dafd2d1e9e4a245a75393390e8feec26798847b747790fc5ef5ef333c7d0b00a06649e4cdb170e8753f77af7c8a876ff8714aef920c7a4067fbfb7b7a9bd24114d5e4eb79e539170c87e117895407c8559fa185d54ec0ebc579e810018f1f43d763c88f50fbb1d67d0cf92fbeeee794fa076969bd9c73ce69e09e7bf239e71c85f1e325ac564156a6447ec4042259cec5663b9582fc57c8cafc257b9b3f66e1653fe6fe27dafafd001d9ddf3ffc0cc5a7d898577a265edd8d477385c9f6682e73d3cd6b1edd1d3608fb435a85998d4d4da979f22683a10bb6aedd1535cd0bcc1540474c28bdb3bcae61cb901248805404200398d7e2706c8dbc7870c7760cc3c0dde52125f263ba7657bee0e59a9b9e62e2c4dff0d707f2b9ea2a858c0c81db656e1e37b893ceba56484b3b9fbcdc6790e591dcfec7dff3b77ff7dd29b4b66d03cd1ff590556ba336737c9878b7e6c21d26dd8527782d74ee0c74f7192f80ee364babab7b68cdd39d1feda3e75074bd2f4912b5d347ecb4d9ad3f1f52e449d09f006401f300fb4beb3f7d39f28663ef5e74bf1f57a71b438ffed191e8a35d2f84e085d75c5cf71f7f62e1c29f72efbd99646682cb257039cdbdd32970b9c0e90a5527495e5ece2337e721c0ca6feeff174e7772edb861df6ef38372324c834f73e18e29f1bd75bf69007a74174ead7f0170ed30ab209f6bf043d08d9b5a686f8c77031f31a1b43bbf3ce7a4f2ba067f82c7868cbe04c0069c085801567ff2c91e5d16e16a400f68b4efd98311d0e939e48c57f351e7bd1a41d3e03b37ff9551236fe3c7b766e0f1083c1ecc92ef3670b983e7c1bdd64f9eca720119f6ebf17a5bf8fe1d9b9286b32b361070706b37dd0147c2269f272c082e3cba932e7f07817efc08dd7b757a369b2f396e7c799f6193e1e09e0ef66f8d37fa0a2a738d8a634a4e2baf6be877a187c1229900c8985ec0514b287db863e7a391e72d9b36e3f7b87139dc78ba3dfd74f098d7eefb7b1b2eb795af9f3d8a40c024dae534707b4c95ef719b5ac0ed36efe929983c56eb7c005e7a2bf994b1136ba682042dabdd7cea782faeb967967e531b9855828783de96be1316b0efef9ef032ff0d0b17f7ffb231e839e462d7baf8195219b9e9d44cadb8b1bcae21f982c9c38064023001288abdf8bbe756bf8e2a853be175bf9fa68fd7230c03474b17016f80687b20fa9fb9866ef0bbbf3c4e76f6059c78a28cdb0d2e17b8dce00aaafd48f25d2e70f6f4dfee5714d36f3ea039e97626361cc6e48d60f4ac623ad705f8c743cb69f53406897747d5ff1ecd85577373c0d388bf9fd2bfef210fee5d26fb59d9699c392ba5ff3485d1d9dac396b776c659fcaa5565e48cca47aa175d352837af81209100a403c7240aecd734e3950d1b7f1d79ada7b5958ebd7b317483f6c60e0ccd88273f58fa77ed95e970bc4a5ddd3854d524d9ed1678dc02b7877075e0f19842e0f1081c7d2f9f0b80ae076b2601073b9293f6a7ebbe8b2d5b65d7f24e7ebdecb7bcf9c69b3439f6d215e8c0abb9e9f277d0e66d66b7f3735c5af2c126c327d8f50737875e37ab658b45e18f3ffc7642278e64e8d8dfc5e76b7761c4a83849921839a37273469efd8a248f0e2b12f5034c0e5e4fd8b8fed38b2f7d78dcf8b1ef64cad6f04a5007366fc69699812d2b8bf646070555b9718e2220f8ecf37640273fdf86cb65e072054bba1b530882eadfd40ae6beabb37f0d10d0826b0448e0f525371ac61655f2d0ed4bb9fae7bfa7fd432f4f7df82ac890395a21e7580bf61a85ac096a524739df4183f637fcb4bfe927d065be972c4bfcd74d0dcc9b3ca5dff70ce1d03e073b3fdc1757f20146ceac74e657e42cfea28cbe58c40a800cd4f4f7d0cf1f7de2d7775ddef084d08c7430a76ceffde0432a674cc7d0b2d0760628aace0b77138704a1acc4fc0b6867e7263ceef9410d40781f52ff2e97c01dac0ebabafa160021bcb8dd0f00909d59c884d1c9ff3806707ced445ebfe74e7ef08ffb79ebb52d18bac0b94dc7b92d28ef12a4572ac836506c12729a84bfddc077d04077c6a86a55e127dfb9900b4e9cd75f9685d1b6ab9d5deb1b49d4bf5435b9bcbda83a7f46795d433fc6c7f021d60da5141883f97a493787cbe5cbcdcad830a6a4f4544468216e03675b1b19f97920645c9d6ed2336da61004b5405181c4effffa3a9d9dbba93be19c20c944b402a285e0e041414f3fc3fe6ecf9ff0fb5e0160f109f358b2a0a6df8fceb0a571ce9c3abebef07802197e1c9e1e9c9dde30275a9720d021f0b519789b0d029d0211511e154566f1a2a93c72db8fa89b90d22f7a01736877d7c7f1061f40e5a4b28e8af12533063ab56ba8885576d3804998eabfdfed17179fbf687259e54f23a559b158289b3c095b4606920cc535f9a465da10868eaf733f57defc212fbef908679f7d1bb3e75c69aafb50bb3f62dfd525686a12f435e92810f888ceae2b40f8902478ee81654c1e5b3ca88ce876ba59bf7b071fefddce9e03ad18c20877690b41b84b5842e2a7f5975252d0efff98c21002f66dd84fcbf68309ef574e2eeba8185732a3bcae61cfa05e7e08881580e330ff1198920000fa3dd75e79494546eef551914a12f935356497962284813d5b253bc70742c3e7379875de3fe9eafe9c69c79ecc8ce9e7601813f07a47e00c76041d386096febec8f7781fc3e9fc05081d24b8b1e15cbe7ff5ec61ca96e183a1196cff606fdc420e21544e2a73548c2f997e24c88778013809a862000200e8f77de7dacb8b6d99df8aadd7ec7979a4e7e6d0b1672f695936464eaf24ab3083e6362f5fbffe090eb47d06405a9a8d8ccc52a09e406034aa321e4589ff3780aeefc1ef5f83dbb31c436f0c7fc1e9279dc4fdff79c6b064c87022e00db075ed6e5c8ec44dd3ca89658e8a634a6694d735ec3eccaf1646ac00cc06c632400100f4df5e75f9d76af30a6f15bae8b32d543cb280aa49e5c8aacccffef0190faf7c8a40203e8324c98e24e7997bc986a67d46acf7af2cc379a79dc65d3f9a977451c92385ce03ddecfca831d837120d5996a83976444b716dc19cf2ba86c446c16142ac11980594d38f1198687b71fda75b6aca8a3faa2e2c3a5d1822a98fb3cbe1e1e09e0e1455e66ba755f3cdf3e6a0c8151cea9470badb22d47e00217a10460786d14694d92c41cd88513cf89b4bb8e2bc295f2af2f580ceeef54decdbd08ca1c5d761d6740ba36657bf54589957575ed770c4dd9a6373ae00389d416880d076d6ec9945d79cb2e8c1802b9078598b0858d32c948f2fa6b8b6005991d1749dcf77b5f0e6875d341de821e4082b823e06a1767355b9cc0d971ed747cc4706dd6d4eb67fb03761a907c82cc81023a78ff82f7b4efa4f5359c7f7702051d15982a909062d048a2c1bfffcfef796d90de54a4317fd16cf5841f8bf0697c34de3a6163a5b93b7598b6b0b7c5593caceab5a78e57387f1d5fa4522552d03650ca21a086d4208e3a9b5efbdad29e2d13993c7cd0b7802f9f1c9f442d70c3a0ff4d0b6bb1dcdaf61cbb4a25a07bc74c16187a7dbcbee8f9bd8fbe97ebcaec41d77922c513db97c7fd5e4f2d923e67d33a5059c0f2712954e05b31ab033042d10b93df4fd1bce294acffca9cfe9eff75fb621e41467513cb280fcf21ca461f4b61d320474b6f5d0baf350d2a65d08b60c2bd5532b1ecc2fcfb9aebcaee18b9daf3e4824cbd952cc26e1b00800a05b54d578f4969bae4bd395fff07b02fdfecf2e04599129aec927af2297eca28c2366f0f9dd01daf6b473704f073e77dfddf492245132aad0593eaef8b29a93af4afee7cb2f01facacd69c02886510800bd223f9ffb6fbaee36ddad5fa3f9b4e4bfc04a00c5a2905392455e5936b9a5d9586c5f5c352184c0d9e1a6abb587ced61e5c1dee848337b148cf4aa37272d973f9e5399796d735a430967964d1970048983d83250cb31000faec31a3955f5c76c103de2edfd784d177df413264e4a563cfe9dd32f2d2e3fea09d12843901d3d3ed3537a78f43fb1c71f3f1fa82244914d5e6f7544e2c5b52bdf0ca3707fe124706fde95319a80372f9028400d0e74f9a28df76f9f9cb3477e07a57a7a764a81f644db760cf49475165148b62ee5505c5aa606806baa6a30774f48041c0af11f06ae6efd606d928535499c2ea7c47514dfeed9979f67b0fd730ee7021950a55068ee50bd204115b60cd6f6fafd3fcda9dce0ed7717ac0f852b70755ab42514d415b5175fe4fec39690f96d735e847fa9d06838158541381117c8102104ae8b53b7e9e25abf2afdc9d9e06afd3973d84ef1b76641566889ce2ac8d65638bef5354f9be2f4b87ce60315093ba08d35d4ce10b148048bcf3c75fd56901fd3b5e977f81bbd35362e8c6616d06489244666186915d98b131b724fbfeacc28c7f95d735f4ef2bfe7f0483c94c0ba6100cb75dd0ef44bf0ffe7aa73de0d3bee5f7042ef47b0213dc9d9ecce15a4b38045991c9c84d17b64ceb81b44cdba6d25145ffab5a9507caeb1a8edc22445f2086529af231ddc7ac1c26018845f3dae56acbf683c707bc81f99a5f9b11f0e9e302de4099a18b74433714c33064a10b49d78cb0f3a56a5351ad0aaa450928aae29355d9ad58e4ceb44cdbcef4acb4d7f3ca7356cbb2b465b8e7e07d593154752a01c5982388128759005241cbdae592806c2043d78c4c45950f95d7350c6d12dfff4718aefa54c6d408f90c5e23fc7fa962bfec18ccff911241006ecc75049c988265616083485f0995fb65c317d197ea0e6e0a41d5cbf0699aa318660c970648040178816e4cf52e05d33baa01be4438dc2553c2d43a2abdd3d28eda004710475a354b440bc2511cc5511cc5511cc5511cc5511cc5517cd1f87fdfa54b2570e59fed0000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>m_buttonExit</sender>
+ <signal>clicked()</signal>
+ <receiver>SlideShowConfigBase</receiver>
+ <slot>close()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>m_buttonExit</tabstop>
+ <tabstop>m_buttonStart</tabstop>
+ <tabstop>m_helpButton</tabstop>
+ <tabstop>m_delaySpinBox</tabstop>
+ <tabstop>m_shuffleCheckBox</tabstop>
+ <tabstop>m_loopCheckBox</tabstop>
+ <tabstop>m_openglCheckBox</tabstop>
+ <tabstop>m_printNameCheckBox</tabstop>
+ <tabstop>m_effectsComboBox</tabstop>
+ <tabstop>m_allFilesButton</tabstop>
+ <tabstop>m_selectedFilesButton</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">klineedit.h</include>
+ <include location="global" impldecl="in declaration">libkipi/interface.h</include>
+ <include location="global" impldecl="in declaration">kprocess.h</include>
+ <include location="global" impldecl="in declaration">kio/previewjob.h</include>
+ <include location="global" impldecl="in declaration">klistbox.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">libkipi/interface.h</include>
+ <include location="global" impldecl="in implementation">kprocess.h</include>
+ <include location="global" impldecl="in implementation">kio/previewjob.h</include>
+ <include location="global" impldecl="in implementation">klistbox.h</include>
+</includes>
+<slots>
+ <slot access="protected">slotOpenGLToggled()</slot>
+ <slot access="protected">slotStartClicked()</slot>
+ <slot access="protected">slotHelp()</slot>
+ <slot access="protected">slotUseMillisecondsToggled()</slot>
+ <slot specifier="non virtual">SlotPortfolioDurationChanged( int )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonUp( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonAdd( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonDown()</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonDelete( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesSelected( QListBoxItem * item )</slot>
+ <slot specifier="non virtual">slotGotPreview( const KFileItem *, const QPixmap &amp; pixmap )</slot>
+ <slot specifier="non virtual">slotFailedPreview( const KFileItem * )</slot>
+ <slot specifier="non virtual">slotAddDropItems( KURL::List filesUrl )</slot>
+ <slot access="protected">slotCacheToggled()</slot>
+</slots>
+<functions>
+ <function access="protected">loadEffectNames()</function>
+ <function access="protected">loadEffectNamesGL()</function>
+ <function access="protected">readSettings()</function>
+ <function access="protected">saveSettings()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kdialog.h</includehint>
+ <includehint>listimageitems.h</includehint>
+ <includehint>kfontdialog.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/slideshow/slideshowgl.cpp b/kipi-plugins/slideshow/slideshowgl.cpp
new file mode 100644
index 0000000..ba49931
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowgl.cpp
@@ -0,0 +1,1508 @@
+/* ============================================================
+ * File : slideshowgl.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-01-19
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2007 by Valerio Fuoglio <valerio.fuoglio@gmail.com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kglobalsettings.h>
+#include <kimageeffect.h>
+
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qapplication.h>
+#include <qevent.h>
+#include <qcursor.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <qfileinfo.h>
+#include <qfontmetrics.h>
+#include <qwmatrix.h>
+
+#include <math.h>
+#include <cstdlib>
+
+#include "slideshowgl.h"
+#include "toolbar.h"
+
+namespace KIPISlideShowPlugin
+{
+
+SlideShowGL::SlideShowGL(const QValueList<QPair<QString, int> >& fileList,
+ const QStringList& commentsList, bool ImagesHasComments)
+ : QGLWidget(0, 0, 0, WStyle_StaysOnTop | WType_Popup |
+ WX11BypassWM | WDestructiveClose)
+{
+#if KDE_IS_VERSION(3,2,0)
+ QRect deskRect = KGlobalSettings::desktopGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+#else
+ QRect deskRect = QApplication::desktop()->screenGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+#endif
+
+ move(m_deskX, m_deskY);
+ resize(m_deskWidth, m_deskHeight);
+
+ m_toolBar = new ToolBar(this);
+ m_toolBar->hide();
+ if (!m_loop)
+ {
+ m_toolBar->setEnabledPrev(false);
+ }
+ connect(m_toolBar, SIGNAL(signalPause()),
+ SLOT(slotPause()));
+ connect(m_toolBar, SIGNAL(signalPlay()),
+ SLOT(slotPlay()));
+ connect(m_toolBar, SIGNAL(signalNext()),
+ SLOT(slotNext()));
+ connect(m_toolBar, SIGNAL(signalPrev()),
+ SLOT(slotPrev()));
+ connect(m_toolBar, SIGNAL(signalClose()),
+ SLOT(slotClose()));
+
+ // -- Minimal texture size (opengl specs) --------------
+
+ m_width = 64;
+ m_height = 64;
+
+ // --------------------------------------------------
+
+ m_fileList = fileList;
+ m_commentsList = commentsList;
+
+ m_imagesHasComments = ImagesHasComments;
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("SlideShow Settings");
+
+ readSettings();
+
+ // ------------------------------------------------------------------
+
+ m_fileIndex = 0;
+
+ m_texture[0] = 0;
+ m_texture[1] = 0;
+ m_curr = 0;
+ m_tex1First = true;
+ m_timeout = m_delay;
+ m_effectRunning = false;
+ m_endOfShow = false;
+
+ m_imageLoader = new SlideShowLoader(m_fileList, m_cacheSize, width(), height());
+
+ // --------------------------------------------------
+
+ registerEffects();
+
+ if (m_effectName == "Random") {
+ m_effect = getRandomEffect();
+ m_random = true;
+ }
+ else {
+ m_effect = m_effects[m_effectName];
+ if (!m_effect)
+ m_effect = m_effects["None"];
+ m_random = false;
+ }
+
+ // --------------------------------------------------
+
+ m_timer = new QTimer();
+ connect(m_timer, SIGNAL(timeout()),
+ SLOT(slotTimeOut()));
+ m_timer->start(m_timeout, true);
+
+ // -- hide cursor when not moved --------------------
+
+ m_mouseMoveTimer = new QTimer;
+ connect(m_mouseMoveTimer, SIGNAL(timeout()),
+ SLOT(slotMouseMoveTimeOut()));
+
+ setMouseTracking(true);
+ slotMouseMoveTimeOut();
+}
+
+SlideShowGL::~SlideShowGL()
+{
+ delete m_timer;
+ delete m_mouseMoveTimer;
+
+ if (m_texture[0])
+ glDeleteTextures(1, &m_texture[0]);
+ if (m_texture[1])
+ glDeleteTextures(1, &m_texture[1]);
+
+ if (m_imageLoader)
+ delete m_imageLoader;
+
+ if (m_config)
+ delete m_config;
+}
+
+void SlideShowGL::readSettings()
+{
+ m_delay = m_config->readNumEntry("Delay", 1500);
+ m_printName = m_config->readBoolEntry("Print Filename", true);
+ m_printProgress = m_config->readBoolEntry("Print Progress Indicator", true);
+ m_printComments = m_config->readBoolEntry("Print Comments", false);
+ m_loop = m_config->readBoolEntry("Loop", false);
+
+ m_effectName = m_config->readEntry("Effect Name (OpenGL)", "Random");
+
+ m_enableMouseWheel = m_config->readBoolEntry("Enable Mouse Wheel", true);
+
+ // Comments tab settings
+
+ m_commentsFont = new QFont();
+ m_commentsFont->setFamily(m_config->readEntry("Comments Font Family"));
+ m_commentsFont->setPointSize(m_config->readNumEntry("Comments Font Size", 10 ));
+ m_commentsFont->setBold(m_config->readBoolEntry("Comments Font Bold", false));
+ m_commentsFont->setItalic(m_config->readBoolEntry("Comments Font Italic", false));
+ m_commentsFont->setUnderline(m_config->readBoolEntry("Comments Font Underline", false));
+ m_commentsFont->setOverline(m_config->readBoolEntry("Comments Font Overline", false));
+ m_commentsFont->setStrikeOut(m_config->readBoolEntry("Comments Font StrikeOut", false));
+ m_commentsFont->setFixedPitch(m_config->readBoolEntry("Comments Font FixedPitch", false));
+
+ m_commentsFontColor = m_config->readUnsignedNumEntry("Comments Font Color", 0xffffff);
+ m_commentsBgColor = m_config->readUnsignedNumEntry("Comments Bg Color", 0x000000);
+
+ m_commentsLinesLength = m_config->readNumEntry("Comments Lines Length", 72);
+
+ // Advanced settings
+ bool enableCache = m_config->readBoolEntry("Enable Cache", false);
+ if (enableCache)
+ m_cacheSize = m_config->readNumEntry("Cache Size", 1);
+ else
+ m_cacheSize = 1;
+}
+
+void SlideShowGL::initializeGL()
+{
+ // Enable Texture Mapping
+ glEnable(GL_TEXTURE_2D);
+ // Clear The Background Color
+ glClearColor(0.0, 0.0, 0.0, 1.0f);
+
+ // Turn Blending On
+ glEnable(GL_BLEND);
+ // Blending Function For Translucency Based On Source Alpha Value
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+ // Enable perspective vision
+ glClearDepth(1.0f);
+
+ // get the maximum texture value.
+ GLint maxTexVal;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexVal);
+
+ // allow only maximum texture value of 1024. anything bigger and things slow down
+ maxTexVal = QMIN(1024, maxTexVal);
+
+ m_width = QApplication::desktop()->width();
+ m_height = QApplication::desktop()->height();
+
+ m_width = 1 << (int)ceil(log((float)m_width)/log((float)2)) ;
+ m_height = 1 << (int)ceil(log((float)m_height)/log((float)2));
+
+ m_width = QMIN( maxTexVal, m_width );
+ m_height = QMIN( maxTexVal, m_height );
+
+ // load the first image
+
+ loadImage();
+}
+
+void SlideShowGL::paintGL()
+{
+ glDisable(GL_DEPTH_TEST);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ if (m_endOfShow)
+ showEndOfShow();
+ else {
+ if (m_effectRunning && m_effect)
+ (this->*m_effect)();
+ else
+ paintTexture();
+ }
+}
+
+void SlideShowGL::resizeGL(int w, int h)
+{
+ // Reset The Current Viewport And Perspective Transformation
+ glViewport(0, 0, (GLint)w, (GLint)h);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+}
+
+void SlideShowGL::keyPressEvent(QKeyEvent *event)
+{
+ if(!event)
+ return;
+
+ m_toolBar->keyPressEvent(event);
+}
+
+void SlideShowGL::mousePressEvent(QMouseEvent *e)
+{
+ if (m_endOfShow)
+ slotClose();
+
+ if (e->button() == Qt::LeftButton)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotNext();
+ }
+ else if (e->button() == Qt::RightButton && m_fileIndex-1 >= 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotPrev();
+ }
+}
+
+void SlideShowGL::mouseMoveEvent(QMouseEvent *e)
+{
+ setCursor(QCursor(Qt::ArrowCursor));
+ m_mouseMoveTimer->start(1000, true);
+
+ if (!m_toolBar->canHide())
+ return;
+
+ QPoint pos(e->pos());
+
+ if ((pos.y() > (m_deskY+20)) &&
+ (pos.y() < (m_deskY+m_deskHeight-20-1)))
+ {
+ if (m_toolBar->isHidden())
+ return;
+ else
+ m_toolBar->hide();
+ return;
+ }
+
+ int w = m_toolBar->width();
+ int h = m_toolBar->height();
+
+ if (pos.y() < (m_deskY+20))
+ {
+ if (pos.x() <= (m_deskX+m_deskWidth/2))
+ // position top left
+ m_toolBar->move(m_deskX, m_deskY);
+ else
+ // position top right
+ m_toolBar->move(m_deskX+m_deskWidth-w-1, m_deskY);
+ }
+ else
+ {
+ if (pos.x() <= (m_deskX+m_deskWidth/2))
+ // position bot left
+ m_toolBar->move(m_deskX, m_deskY+m_deskHeight-h-1);
+ else
+ // position bot right
+ m_toolBar->move(m_deskX+m_deskWidth-w-1, m_deskY+m_deskHeight-h-1);
+ }
+ m_toolBar->show();
+}
+
+void SlideShowGL::wheelEvent(QWheelEvent *e)
+{
+ if (!m_enableMouseWheel) return;
+
+ if (m_endOfShow)
+ slotClose();
+
+ int delta = e->delta();
+
+ if (delta < 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotNext();
+ }
+ else if (delta > 0 && m_fileIndex-1 >= 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotPrev();
+ }
+}
+
+void SlideShowGL::registerEffects()
+{
+ m_effects.insert("None", &SlideShowGL::effectNone);
+ m_effects.insert("Blend", &SlideShowGL::effectBlend);
+ m_effects.insert("Fade", &SlideShowGL::effectFade);
+ m_effects.insert("Rotate", &SlideShowGL::effectRotate);
+ m_effects.insert("Bend", &SlideShowGL::effectBend);
+ m_effects.insert("In Out", &SlideShowGL::effectInOut);
+ m_effects.insert("Slide", &SlideShowGL::effectSlide);
+ m_effects.insert("Flutter", &SlideShowGL::effectFlutter);
+ m_effects.insert("Cube", &SlideShowGL::effectCube);
+}
+
+QStringList SlideShowGL::effectNames()
+{
+ QStringList effects;
+
+ effects.append("None");
+ effects.append("Bend");
+ effects.append("Blend");
+ effects.append("Cube");
+ effects.append("Fade");
+ effects.append("Flutter");
+ effects.append("In Out");
+ effects.append("Rotate");
+ effects.append("Slide");
+ effects.append("Random");
+
+ return effects;
+}
+
+QMap<QString,QString> SlideShowGL::effectNamesI18N()
+{
+ QMap<QString,QString> effects;
+
+ effects["None"] = i18n("None");
+ effects["Bend"] = i18n("Bend");
+ effects["Blend"] = i18n("Blend");
+ effects["Cube"] = i18n("Cube");
+ effects["Fade"] = i18n("Fade");
+ effects["Flutter"] = i18n("Flutter");
+ effects["In Out"] = i18n("In Out");
+ effects["Rotate"] = i18n("Rotate");
+ effects["Slide"] = i18n("Slide");
+ effects["Random"] = i18n("Random");
+
+ return effects;
+}
+
+SlideShowGL::EffectMethod SlideShowGL::getRandomEffect()
+{
+ QMap<QString,EffectMethod> tmpMap(m_effects);
+
+ tmpMap.remove("None");
+ QStringList t = tmpMap.keys();
+
+ int count = t.count();
+
+ int i = (int)((float)(count)*rand()/(RAND_MAX+1.0));
+ QString key = t[i];
+
+ return tmpMap[key];
+}
+
+void SlideShowGL::advanceFrame()
+{
+ m_fileIndex++;
+ m_imageLoader->next();
+ int num = m_fileList.count();
+ if (m_fileIndex >= num) {
+ if (m_loop)
+ {
+ m_fileIndex = 0;
+ }
+ else
+ {
+ m_fileIndex = num-1;
+ m_endOfShow = true;
+ m_toolBar->setEnabledPlay(false);
+ m_toolBar->setEnabledNext(false);
+ m_toolBar->setEnabledPrev(false);
+ }
+ }
+
+ if (!m_loop && !m_endOfShow)
+ {
+ m_toolBar->setEnabledPrev(m_fileIndex > 0);
+ m_toolBar->setEnabledNext(m_fileIndex < num-1);
+ }
+
+ m_tex1First = !m_tex1First;
+ m_curr = (m_curr == 0) ? 1 : 0;
+}
+
+void SlideShowGL::previousFrame()
+{
+ m_fileIndex--;
+ m_imageLoader->prev();
+ int num = m_fileList.count();
+ if (m_fileIndex < 0) {
+ if (m_loop)
+ {
+ m_fileIndex = num-1;
+ }
+ else
+ {
+ m_fileIndex = 0;
+ m_endOfShow = true;
+ m_toolBar->setEnabledPlay(false);
+ m_toolBar->setEnabledNext(false);
+ m_toolBar->setEnabledPrev(false);
+ }
+ }
+
+ if (!m_loop && !m_endOfShow)
+ {
+ m_toolBar->setEnabledPrev(m_fileIndex > 0);
+ m_toolBar->setEnabledNext(m_fileIndex < num-1);
+ }
+
+ m_tex1First = !m_tex1First;
+ m_curr = (m_curr == 0) ? 1 : 0;
+}
+
+void SlideShowGL::loadImage()
+{
+
+ QImage image = m_imageLoader->getCurrent();
+
+ if (!image.isNull()) {
+
+ int a = m_tex1First ? 0 : 1;
+ GLuint& tex = m_texture[a];
+
+ if (tex)
+ glDeleteTextures(1, &tex);
+
+ QImage black(width(), height(), 32);
+ black.fill(Qt::black.rgb());
+
+/* image = image.smoothScale(width(), height(),
+ QImage::ScaleMin);*/
+ montage(image, black);
+
+ black = black.smoothScale(m_width, m_height);
+
+ if (m_printName)
+ printFilename(black);
+
+ if (m_printProgress)
+ printProgress(black);
+
+ if (m_printComments && m_imagesHasComments)
+ printComments(black);
+
+ QImage t = convertToGLFormat(black);
+
+ /* create the texture */
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ /* actually generate the texture */
+ glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
+ /* enable linear filtering */
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+
+ }
+
+}
+
+void SlideShowGL::montage(QImage& top, QImage& bot)
+{
+ int tw = top.width(); int th = top.height();
+ int bw = bot.width(); int bh = bot.height();
+
+ if (tw > bw || th > bh)
+ qFatal("Top Image should be smaller or same size as Bottom Image");
+
+ if (top.depth() != 32) top = top.convertDepth(32);
+ if (bot.depth() != 32) bot = bot.convertDepth(32);
+
+ int sw = bw/2 - tw/2; //int ew = bw/2 + tw/2;
+ int sh = bh/2 - th/2; int eh = bh/2 + th/2;
+
+
+ unsigned int *tdata = (unsigned int*) top.scanLine(0);
+ unsigned int *bdata = 0;
+
+ for (int y = sh; y < eh; y++) {
+
+ bdata = (unsigned int*) bot.scanLine(y) + sw;
+ for (int x = 0; x < tw; x++) {
+ *(bdata++) = *(tdata++);
+ }
+
+ }
+}
+
+void SlideShowGL::printFilename(QImage& layer)
+{
+ QFileInfo fileinfo(m_fileList[m_fileIndex].first);
+ QString filename = fileinfo.fileName();
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize());
+ fn.setBold(true);
+
+ QFontMetrics fm(fn);
+ QRect rect=fm.boundingRect(filename);
+ rect.addCoords( 0, 0, 2, 2 );
+
+ QPixmap pix(rect.width(),rect.height());
+ pix.fill(Qt::black);
+
+ QPainter p(&pix);
+ p.setPen(Qt::white);
+ p.setFont(fn);
+ p.drawText(1,fn.pointSize()+1 , filename);
+ p.end();
+
+ QImage textimage(pix.convertToImage());
+ KImageEffect::blendOnLower(0,m_height-rect.height(),textimage,layer);
+}
+
+void SlideShowGL::printProgress(QImage& layer)
+{
+ QString progress(QString::number(m_fileIndex + 1) + "/" + QString::number(m_fileList.count()));
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize());
+ fn.setBold(true);
+
+ QFontMetrics fm(fn);
+ QRect rect=fm.boundingRect(progress);
+ rect.addCoords( 0, 0, 2, 2 );
+
+ QPixmap pix(rect.width(),rect.height());
+ pix.fill(Qt::black);
+
+ QPainter p(&pix);
+
+ int stringLenght = p.fontMetrics().width(progress) * progress.length();
+
+ p.setPen(Qt::white);
+ p.setFont(fn);
+ p.drawText(1,fn.pointSize()+1 , progress);
+ p.end();
+
+ QImage textimage(pix.convertToImage());
+ KImageEffect::blendOnLower(m_width - stringLenght - 10,
+ 20,textimage,layer);
+}
+
+void SlideShowGL::printComments(QImage& layer)
+{
+ QString comments = m_commentsList[m_fileIndex];
+
+ int yPos = 5; // Text Y coordinate
+ if (m_printName) yPos += 20;
+
+ QStringList commentsByLines;
+
+ uint commentsIndex = 0; // Comments QString index
+
+ while (commentsIndex < comments.length())
+ {
+ QString newLine;
+ bool breakLine = FALSE; // End Of Line found
+ uint currIndex; // Comments QString current index
+
+ // Check miminal lines dimension
+
+ int commentsLinesLengthLocal = m_commentsLinesLength;
+
+ for ( currIndex = commentsIndex; currIndex < comments.length() && !breakLine; currIndex++ )
+ if( comments[currIndex] == QChar('\n') || comments[currIndex].isSpace() ) breakLine = TRUE;
+
+ if (commentsLinesLengthLocal <= (int)((currIndex - commentsIndex)))
+ commentsLinesLengthLocal = (currIndex - commentsIndex);
+
+ breakLine = FALSE;
+
+ for ( currIndex = commentsIndex; currIndex <= commentsIndex + commentsLinesLengthLocal &&
+ currIndex < comments.length() &&
+ !breakLine; currIndex++ )
+ {
+ breakLine = (comments[currIndex] == QChar('\n')) ? TRUE : FALSE;
+
+ if (breakLine)
+ newLine.append( ' ' );
+ else
+ newLine.append( comments[currIndex] );
+ }
+
+ commentsIndex = currIndex; // The line is ended
+
+ if ( commentsIndex != comments.length() )
+ while ( !newLine.endsWith(" ") )
+ {
+ newLine.truncate(newLine.length() - 1);
+ commentsIndex--;
+ }
+
+ commentsByLines.prepend(newLine.stripWhiteSpace());
+ }
+
+ QFontMetrics fm(*m_commentsFont);
+
+ for ( int lineNumber = 0; lineNumber < (int)commentsByLines.count(); lineNumber++ ) {
+
+ yPos += int(1.5 * m_commentsFont->pointSize());
+
+ QRect rect=fm.boundingRect(commentsByLines[lineNumber]);
+ rect.addCoords( 0, 0, 2, 2 );
+
+ QPixmap pix(rect.width(),rect.height());
+ pix.fill(QColor(m_commentsBgColor));
+
+ QPainter p(&pix);
+ p.setPen(QColor(m_commentsFontColor));
+ p.setFont(*m_commentsFont);
+ p.drawText(1,m_commentsFont->pointSize()+0 , commentsByLines[lineNumber]);
+ p.end();
+
+ QImage textimage(pix.convertToImage());
+ KImageEffect::blendOnLower(0,m_height-rect.height()-yPos,textimage,layer);
+ }
+}
+
+void SlideShowGL::showEndOfShow()
+{
+ QPixmap pix(512,512);
+ pix.fill(Qt::black);
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize()+10);
+ fn.setBold(true);
+
+ QPainter p(&pix);
+ p.setPen(Qt::white);
+ p.setFont(fn);
+ p.drawText(20, 50, i18n("SlideShow Completed."));
+ p.drawText(20, 100, i18n("Click To Exit..."));
+ p.end();
+
+ QImage image(pix.convertToImage());
+ QImage t = convertToGLFormat(image);
+
+ GLuint tex;
+
+ /* create the texture */
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ /* actually generate the texture */
+ glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
+ /* enable linear filtering */
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ /* paint the texture */
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0, -1.0, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0, -1.0, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0, 1.0, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0, 1.0, 0);
+ }
+ glEnd();
+
+}
+
+void SlideShowGL::slotTimeOut()
+{
+ if (!m_effect) {
+ kdWarning( 51000 ) << "SlideShowGL: No transition method"
+ << endl;
+ m_effect = &SlideShowGL::effectNone;
+ }
+
+ if (m_effectRunning) {
+ m_timeout = 10;
+ }
+ else {
+ if (m_timeout == -1) {
+ // effect was running and is complete now
+ // run timer while showing current image
+ m_timeout = m_delay;
+ m_i = 0;
+ }
+ else {
+
+ // timed out after showing current image
+ // load next image and start effect
+ if (m_random)
+ m_effect = getRandomEffect();
+
+ advanceFrame();
+ if (m_endOfShow) {
+ updateGL();
+ return;
+ }
+
+ loadImage();
+ m_timeout = 10;
+ m_effectRunning = true;
+ m_i = 0;
+
+ }
+ }
+
+ updateGL();
+ m_timer->start(m_timeout, true);
+}
+
+void SlideShowGL::slotMouseMoveTimeOut()
+{
+ QPoint pos(QCursor::pos());
+ if ((pos.y() < (m_deskY+20)) ||
+ (pos.y() > (m_deskY+m_deskHeight-20-1)))
+ return;
+
+ setCursor(QCursor(Qt::BlankCursor));
+}
+
+void SlideShowGL::paintTexture()
+{
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ GLuint& tex = m_texture[m_curr];
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0, -1.0, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0, -1.0, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0, 1.0, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0, 1.0, 0);
+ }
+ glEnd();
+}
+
+void SlideShowGL::effectNone()
+{
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+}
+
+void SlideShowGL::effectBlend()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0/(100.0)*(float)m_i);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ m_i++;
+}
+
+void SlideShowGL::effectFade()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ int a;
+ float opacity;
+ if (m_i <= 50) {
+ a = (m_curr == 0) ? 1 : 0;
+ opacity = 1.0 - 1.0/50.0*(float)(m_i);
+ }
+ else {
+ opacity = 1.0/50.0*(float)(m_i-50.0);
+ a = m_curr;
+ }
+
+ GLuint& ta = m_texture[a];
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, opacity);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+
+ m_i++;
+}
+
+void SlideShowGL::effectRotate()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ if (m_i == 0)
+ m_dir = (int)((2.0*rand()/(RAND_MAX+1.0)));
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ float rotate = 360.0/100.0*(float)m_i;
+ glRotatef( ((m_dir == 0) ? -1 : 1) * rotate,
+ 0.0, 0.0, 1.0);
+ float scale = 1.0/100.0*(100.0-(float)(m_i));
+ glScalef(scale,scale,1.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ m_i++;
+}
+
+void SlideShowGL::effectBend()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ if (m_i == 0)
+ m_dir = (int)((2.0*rand()/(RAND_MAX+1.0)));
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glRotatef(90.0/100.0*(float)m_i,
+ (m_dir == 0) ? 1.0 : 0.0,
+ (m_dir == 1) ? 1.0 : 0.0,
+ 0.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ m_i++;
+}
+
+void SlideShowGL::effectInOut()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ if (m_i == 0) {
+ m_dir = 1 + (int)((4.0*rand()/(RAND_MAX+1.0)));
+ }
+
+ int a;
+ bool out;
+ if (m_i <= 50) {
+ a = (m_curr == 0) ? 1 : 0;
+ out = 1;
+ }
+ else {
+ a = m_curr;
+ out = 0;
+ }
+
+ GLuint& ta = m_texture[a];
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ float t = out ? 1.0/50.0*(50.0-m_i) : 1.0/50.0*(m_i-50.0);
+ glScalef(t, t, 1.0);
+ t = 1.0 - t;
+ glTranslatef((m_dir % 2 == 0) ? ((m_dir == 2)? 1 : -1) * t : 0.0,
+ (m_dir % 2 == 1) ? ((m_dir == 1)? 1 : -1) * t : 0.0,
+ 0.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+
+ m_i++;
+}
+
+void SlideShowGL::effectSlide()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ if (m_i == 0)
+ m_dir = 1 + (int)((4.0*rand()/(RAND_MAX+1.0)));
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ float trans = 2.0/100.0*(float)m_i;
+ glTranslatef((m_dir % 2 == 0) ? ((m_dir == 2)? 1 : -1) * trans : 0.0,
+ (m_dir % 2 == 1) ? ((m_dir == 1)? 1 : -1) * trans : 0.0,
+ 0.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ m_i++;
+}
+
+void SlideShowGL::effectFlutter()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ if (m_i == 0) {
+ for (int x = 0; x<40; x++) {
+ for (int y = 0; y < 40; y++) {
+ m_points[x][y][0] = (float) (x / 20.0f - 1.0f);
+ m_points[x][y][1] = (float) (y / 20.0f - 1.0f);
+ m_points[x][y][2] = (float) sin((x / 20.0f - 1.0f) *
+ 3.141592654*2.0f)/5.0;
+ }
+ }
+ }
+
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ float rotate = 60.0/100.0*(float)m_i;
+ glRotatef(rotate, 1.0f, 0.0f, 0.0f);
+ float scale = 1.0/100.0*(100.0-(float)m_i);
+ glScalef(scale, scale, scale);
+ glTranslatef(1.0/100.0*(float)m_i, 1.0/100.0*(float)m_i, 0.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ float float_x, float_y, float_xb, float_yb;
+ int x, y;
+
+ for (x = 0; x < 39; x++)
+ {
+ for (y = 0; y < 39; y++)
+ {
+ float_x = (float) x / 40.0f;
+ float_y = (float) y / 40.0f;
+ float_xb = (float) (x + 1) / 40.0f;
+ float_yb = (float) (y + 1) / 40.0f;
+ glTexCoord2f(float_x, float_y);
+ glVertex3f(m_points[x][y][0], m_points[x][y][1], m_points[x][y][2]);
+ glTexCoord2f(float_x, float_yb);
+ glVertex3f(m_points[x][y + 1][0], m_points[x][y + 1][1],
+ m_points[x][y + 1][2]);
+ glTexCoord2f(float_xb, float_yb);
+ glVertex3f(m_points[x + 1][y + 1][0], m_points[x + 1][y + 1][1],
+ m_points[x + 1][y + 1][2]);
+ glTexCoord2f(float_xb, float_y);
+ glVertex3f(m_points[x + 1][y][0], m_points[x + 1][y][1],
+ m_points[x + 1][y][2]);
+ }
+ }
+ }
+ glEnd();
+
+ // wave every two iterations
+ if (m_i%2 == 0) {
+
+ float hold;
+ int x, y;
+ for (y = 0; y < 40; y++)
+ {
+ hold = m_points[0][y][2];
+ for (x = 0; x < 39; x++)
+ {
+ m_points[x][y][2] = m_points[x + 1][y][2];
+ }
+ m_points[39][y][2] = hold;
+ }
+ }
+ m_i++;
+}
+
+void SlideShowGL::effectCube()
+{
+ int tot = 200;
+ int rotStart = 50;
+
+ if (m_i > tot) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ // Enable perspective vision
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ float PI = 4.0 * atan(1.0);
+ float znear = 3.0;
+ float theta = 2.0 * atan2((float)2.0/(float)2.0, (float)znear);
+ theta = theta * 180.0/PI;
+
+ glFrustum(-1.0,1.0,-1.0,1.0, znear-0.01,10.0);
+
+
+ static float xrot;
+ static float yrot;
+ static float zrot;
+
+ if (m_i == 0) {
+ xrot = 0.0;
+ yrot = 0.0;
+ zrot = 0.0;
+ }
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ float trans = 5.0 * (float)((m_i <= tot/2) ? m_i : tot-m_i)/(float)tot;
+ glTranslatef(0.0,0.0, -znear - 1.0 - trans);
+
+ glRotatef(xrot, 1.0f, 0.0f, 0.0f);
+ glRotatef(yrot, 0.0f, 1.0f, 0.0f);
+
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+
+ /* Front Face */
+ glVertex3f( -1.00f, -1.00f, 0.99f );
+ glVertex3f( 1.00f, -1.00f, 0.99f );
+ glVertex3f( 1.00f, 1.00f, 0.99f );
+ glVertex3f( -1.00f, 1.00f, 0.99f );
+
+ /* Back Face */
+ glVertex3f( -1.00f, -1.00f, -0.99f );
+ glVertex3f( -1.00f, 1.00f, -0.99f );
+ glVertex3f( 1.00f, 1.00f, -0.99f );
+ glVertex3f( 1.00f, -1.00f, -0.99f );
+
+ /* Top Face */
+ glVertex3f( -1.00f, 0.99f, -1.00f );
+ glVertex3f( -1.00f, 0.99f, 1.00f );
+ glVertex3f( 1.00f, 0.99f, 1.00f );
+ glVertex3f( 1.00f, 0.99f, -1.00f );
+
+ /* Bottom Face */
+ glVertex3f( -1.00f, -0.99f, -1.00f );
+ glVertex3f( 1.00f, -0.99f, -1.00f );
+ glVertex3f( 1.00f, -0.99f, 1.00f );
+ glVertex3f( -1.00f, -0.99f, 1.00f );
+
+ /* Right face */
+ glVertex3f( 0.99f, -1.00f, -1.00f );
+ glVertex3f( 0.99f, 1.00f, -1.00f );
+ glVertex3f( 0.99f, 1.00f, 1.00f );
+ glVertex3f( 0.99f, -1.00f, 1.00f );
+
+ /* Left Face */
+ glVertex3f( -0.99f, -1.00f, -1.00f );
+ glVertex3f( -0.99f, -1.00f, 1.00f );
+ glVertex3f( -0.99f, 1.00f, 1.00f );
+ glVertex3f( -0.99f, 1.00f, -1.00f );
+
+ }
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4d(1.0, 1.0, 1.0, 1.0);
+
+ // Front Face
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 1.00f );
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, 1.00f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, 1.00f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, 1.00f );
+
+
+ // Top Face
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f, 1.00f, -1.0f );
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f, 1.00f, 1.0f );
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f, 1.00f, 1.0f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.00f, -1.0f );
+
+ // Bottom Face
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, -1.00f, -1.0f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, -1.00f, -1.0f );
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.00f, 1.0f );
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.00f, 1.0f );
+
+ // Right face
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.00f, -1.0f, -1.0f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.00f, -1.0f, 1.0f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.00f, 1.0f, 1.0f );
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.00f, 1.0f, -1.0f );
+
+ // Left Face
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.00f, -1.0f, -1.0f );
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.00f, 1.0f, -1.0f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.00f, 1.0f, 1.0f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.00f, -1.0f, 1.0f );
+
+ }
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4d(1.0, 1.0, 1.0, 1.0);
+
+ // Back Face
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, -1.00f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, -1.00f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, -1.00f );
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, -1.00f );
+ }
+ glEnd();
+
+ if (m_i >= rotStart && m_i < (tot-rotStart)) {
+ xrot += 360.0f/(float)(tot-2*rotStart);
+ yrot += 180.0f/(float)(tot-2*rotStart);
+ }
+
+ m_i++;
+}
+
+void SlideShowGL::slotPause()
+{
+ m_timer->stop();
+
+ if (m_toolBar->isHidden())
+ {
+ int w = m_toolBar->width();
+ m_toolBar->move(m_deskWidth-w-1,0);
+ m_toolBar->show();
+ }
+}
+
+void SlideShowGL::slotPlay()
+{
+ m_toolBar->hide();
+ slotTimeOut();
+}
+
+void SlideShowGL::slotPrev()
+{
+ previousFrame();
+ if (m_endOfShow) {
+ updateGL();
+ return;
+ }
+
+ m_effectRunning = false;
+ loadImage();
+ updateGL();
+}
+
+void SlideShowGL::slotNext()
+{
+ advanceFrame();
+ if (m_endOfShow) {
+ updateGL();
+ return;
+ }
+
+ m_effectRunning = false;
+ loadImage();
+ updateGL();
+}
+
+void SlideShowGL::slotClose()
+{
+ close();
+}
+
+} // NameSpace KIPISlideShowPlugin
+
+#include "slideshowgl.moc"
diff --git a/kipi-plugins/slideshow/slideshowgl.h b/kipi-plugins/slideshow/slideshowgl.h
new file mode 100644
index 0000000..bb1bc8e
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowgl.h
@@ -0,0 +1,172 @@
+/* ============================================================
+ * File : slideshowgl.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-01-19
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2007 by Valerio Fuoglio <valerio.fuoglio@gmail.com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SLIDESHOWGL_H
+#define SLIDESHOWGL_H
+
+// KDE includes
+#include <kconfig.h>
+
+// QT includes
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include <qpair.h>
+#include <qstring.h>
+#include <qmap.h>
+#include <qgl.h>
+
+// Local includes
+#include "slideshowloader.h"
+
+class QTimer;
+
+namespace KIPISlideShowPlugin
+{
+ class SlideShowGL;
+ class ToolBar;
+
+ class SlideShowGL : public QGLWidget
+ {
+ Q_OBJECT
+
+ public:
+
+ SlideShowGL(const QValueList<QPair<QString, int> >& fileList,
+ const QStringList& commentsList, bool ImagesHasComments);
+ ~SlideShowGL();
+
+ void registerEffects();
+
+ static QStringList effectNames();
+ static QMap<QString,QString> effectNamesI18N();
+
+ protected:
+
+ void initializeGL();
+ void paintGL();
+ void resizeGL(int w, int h);
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *);
+ void wheelEvent(QWheelEvent *e);
+ void keyPressEvent(QKeyEvent *event);
+
+ private:
+
+ // config ------------------
+
+ KConfig* m_config;
+
+ int m_delay;
+ QString m_effectName;
+ bool m_loop;
+ bool m_printName;
+ bool m_printProgress;
+ bool m_printComments;
+
+ bool m_imagesHasComments;
+
+ QFont* m_commentsFont;
+ uint m_commentsFontColor;
+ uint m_commentsBgColor;
+ int m_commentsLinesLength;
+
+ bool m_enableMouseWheel;
+
+ uint m_cacheSize;
+ // -------------------------
+
+ typedef void (SlideShowGL::*EffectMethod)();
+ QMap<QString, EffectMethod> m_effects;
+
+ QValueList<QPair<QString, int> > m_fileList;
+ QStringList m_commentsList;
+ QTimer* m_timer;
+ int m_fileIndex;
+
+ SlideShowLoader* m_imageLoader;
+ GLuint m_texture[2];
+ bool m_tex1First;
+ int m_curr;
+
+ int m_width;
+ int m_height;
+
+ EffectMethod m_effect;
+ bool m_effectRunning;
+ int m_timeout;
+ bool m_random;
+ bool m_endOfShow;
+
+ int m_i;
+ int m_dir;
+ float m_points[40][40][3];
+
+ ToolBar* m_toolBar;
+ QTimer* m_mouseMoveTimer;
+
+ int m_deskX;
+ int m_deskY;
+ int m_deskWidth;
+ int m_deskHeight;
+
+ private:
+
+ void paintTexture();
+ void advanceFrame();
+ void previousFrame();
+ void loadImage();
+ void montage(QImage& top, QImage& bot);
+ EffectMethod getRandomEffect();
+ void showEndOfShow();
+ void printFilename(QImage& layer);
+ void printProgress(QImage& layer);
+ void printComments(QImage& layer);
+
+ void readSettings();
+
+ void effectNone();
+ void effectBlend();
+ void effectFade();
+ void effectRotate();
+ void effectBend();
+ void effectInOut();
+ void effectSlide();
+ void effectFlutter();
+ void effectCube();
+
+
+ private slots:
+
+ void slotTimeOut();
+ void slotMouseMoveTimeOut();
+
+ void slotPause();
+ void slotPlay();
+ void slotPrev();
+ void slotNext();
+ void slotClose();
+ };
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif /* SLIDESHOWGL_H */
diff --git a/kipi-plugins/slideshow/slideshowkb.cpp b/kipi-plugins/slideshow/slideshowkb.cpp
new file mode 100644
index 0000000..2f08205
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowkb.cpp
@@ -0,0 +1,578 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de> and slideshowgl.{cpp|h} by Renchi Raju
+ * <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cassert>
+#include <cmath>
+
+// Qt includes.
+
+#include <qapplication.h>
+#include <qimage.h>
+#include <qdatetime.h>
+#include <qpainter.h>
+#include <qobject.h>
+#include <qfont.h>
+#include <qcursor.h>
+
+// KDE includes.
+
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdeversion.h>
+#include <kglobalsettings.h>
+
+// Local includes.
+
+#include "slideshowkb.h"
+#include "imageloadthread.h"
+#include "slideshowkb.moc"
+
+namespace KIPISlideShowPlugin
+{
+ // -------------------------------------------------------------------------
+
+ ViewTrans::ViewTrans(bool zoomIn, float relAspect) {
+
+ int i;
+
+ // randomly select sizes of start end end viewport
+ double s[2];
+ i = 0;
+ do {
+ s[0] = 0.3 * rnd() + 1.0;
+ s[1] = 0.3 * rnd() + 1.0;
+ } while (fabs(s[0] - s[1]) < 0.15 && ++i < 10);
+
+ if (zoomIn xor s[0] > s[1]) {
+ double tmp = s[0];
+ s[0] = s[1];
+ s[1] = tmp;
+ }
+
+ m_deltaScale = s[1] / s[0] - 1.0;
+ m_baseScale = s[0];
+
+ // additional scale factors to ensure proper m_aspect of the displayed image
+ double x[2], y[2], xMargin[2], yMargin[2], bestDist;
+ double sx, sy;
+ if (relAspect > 1.0) {
+ sx = 1.0;
+ sy = relAspect;
+ } else {
+ sx = 1.0 / relAspect;
+ sy = 1.0;
+ }
+ m_xScale = sx;
+ m_yScale = sy;
+
+ // calculate path
+ xMargin[0] = (s[0] * sx - 1.0) / 2.0;
+ yMargin[0] = (s[0] * sy - 1.0) / 2.0;
+ xMargin[1] = (s[1] * sx - 1.0) / 2.0;
+ yMargin[1] = (s[1] * sy - 1.0) / 2.0;
+
+ i = 0;
+ bestDist = 0.0;
+ do {
+ double sign = rndSign();
+ x[0] = xMargin[0] * (0.2 * rnd() + 0.8) * sign;
+ y[0] = yMargin[0] * (0.2 * rnd() + 0.8) * -sign;
+ x[1] = xMargin[1] * (0.2 * rnd() + 0.8) * -sign;
+ y[1] = yMargin[1] * (0.2 * rnd() + 0.8) * sign;
+
+ if (fabs(x[1] - x[0]) + fabs(y[1] - y[0]) > bestDist) {
+ m_baseX = x[0];
+ m_baseY = y[0];
+ m_deltaX = x[1] - x[0];
+ m_deltaY = y[1] - y[0];
+ bestDist = fabs(m_deltaX) + fabs(m_deltaY);
+ }
+
+ } while (bestDist < 0.3 && ++i < 10);
+ }
+
+ // -------------------------------------------------------------------------
+
+ Image::Image(ViewTrans *viewTrans, float aspect) {
+
+ this->m_viewTrans = viewTrans;
+ this->m_aspect = aspect;
+ this->m_pos = 0.0;
+ this->m_opacity = 0.0;
+ this->m_paint = (m_viewTrans) ? true : false;
+ this->m_texture = 0;
+ }
+
+ Image::~Image() {
+
+ delete m_viewTrans;
+ if (glIsTexture(m_texture))
+ glDeleteTextures(1, &m_texture);
+ }
+
+ // -------------------------------------------------------------------------
+ SlideShowKB::SlideShowKB(const QValueList<QPair<QString, int> >& fileList,
+ const QStringList& commentsList, bool ImagesHasComments)
+ : QGLWidget(0, 0, 0, WStyle_StaysOnTop | WType_Popup |
+ WX11BypassWM | WDestructiveClose)
+ {
+ #if KDE_IS_VERSION(3,2,0)
+ QRect deskRect = KGlobalSettings::desktopGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+ #else
+ QRect deskRect = QApplication::desktop()->screenGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+ #endif
+
+ move(m_deskX, m_deskY);
+ resize(m_deskWidth, m_deskHeight);
+
+ // =======================================================
+ // Avoid boring compile time "unused parameter" warning :P
+ // These parameters could be useful for future implementations
+ m_commentsList = commentsList;
+ m_imagesHasComments = ImagesHasComments;
+ // =======================================================
+
+ srand(QTime::currentTime().msec());
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("SlideShow Settings");
+ readSettings();
+
+ m_screen = new ScreenProperties(this);
+ m_screen->enableVSync();
+
+ unsigned frameRate;
+ if (m_forceFrameRate == 0)
+ frameRate = m_screen->suggestFrameRate() * 2;
+ else
+ frameRate = m_forceFrameRate;
+
+ m_image[0] = new Image(0);
+ m_image[1] = new Image(0);
+ m_effect = 0;
+ m_step = 1.0 / ((float) (m_delay * frameRate));
+ m_zoomIn = rand() < RAND_MAX / 2;
+ m_initialized = false;
+ m_haveImages = true;
+
+ QValueList<QPair<QString, int> > m_fileList = fileList;
+
+ m_imageLoadThread = new ImageLoadThread(m_fileList, width(), height());
+ m_timer = new QTimer(this);
+
+ m_endOfShow = false;
+ m_showingEnd = false;
+
+ connect(m_timer, SIGNAL(timeout(void)), this, SLOT(moveSlot()));
+ connect(m_imageLoadThread, SIGNAL(endOfShow(void)), this, SLOT(slotEndOfShow()));
+
+ // -- hide cursor when not moved --------------------
+
+ m_mouseMoveTimer = new QTimer;
+ connect(m_mouseMoveTimer, SIGNAL(timeout()),
+ SLOT(slotMouseMoveTimeOut()));
+
+ setMouseTracking(true);
+ slotMouseMoveTimeOut();
+
+ m_imageLoadThread->start();
+ m_timer->start(1000 / frameRate);
+ }
+
+ SlideShowKB::~SlideShowKB() {
+
+ delete m_effect;
+ delete m_image[0];
+ delete m_image[1];
+
+ m_imageLoadThread->quit();
+ bool terminated = m_imageLoadThread->wait(10000);
+
+ if ( !terminated) {
+ m_imageLoadThread->terminate();
+ terminated = m_imageLoadThread->wait(3000);
+ }
+
+ if (terminated)
+ delete m_imageLoadThread;
+
+ delete m_mouseMoveTimer;
+ delete m_timer;
+ delete m_screen;
+ }
+
+
+ void SlideShowKB::setNewKBEffect() {
+
+ KBEffect::Type type;
+ bool needFadeIn = (m_effect == 0 || m_effect->type() == KBEffect::Fade);
+
+ // we currently only have two effects
+ if (m_disableFadeInOut)
+ type = KBEffect::Blend;
+ else if (m_disableCrossFade)
+ type = KBEffect::Fade;
+ else
+ type = KBEffect::chooseKBEffect((m_effect) ? m_effect->type() : KBEffect::Fade);
+
+ delete m_effect;
+ switch (type) {
+ case KBEffect::Fade:
+ m_effect = new FadeKBEffect(this, needFadeIn);
+ break;
+ case KBEffect::Blend:
+ m_effect = new BlendKBEffect(this, needFadeIn);
+ break;
+ default:
+ qDebug("Unknown transition effect, falling back to crossfade");
+ m_effect = new BlendKBEffect(this, needFadeIn);
+ }
+ }
+
+
+ void SlideShowKB::moveSlot() {
+
+ if (m_initialized) {
+
+ if (m_effect->done()) {
+ setNewKBEffect();
+ m_imageLoadThread->requestNewImage();
+ }
+ m_effect->advanceTime(m_step);
+ }
+
+ updateGL();
+ }
+
+
+ bool SlideShowKB::setupNewImage(int idx) {
+
+ assert(idx >= 0 && idx < 2);
+
+ if ( !m_haveImages)
+ return false;
+
+ bool ok = false;
+ m_zoomIn = !m_zoomIn;
+
+ if (m_imageLoadThread->grabImage()) {
+
+ delete m_image[idx];
+
+ // we have the image lock and there is an image
+ float imageAspect = m_imageLoadThread->imageAspect();
+ ViewTrans *viewTrans = new ViewTrans(m_zoomIn, aspect() / imageAspect);
+ m_image[idx] = new Image(viewTrans, imageAspect);
+
+ applyTexture(m_image[idx], m_imageLoadThread->image());
+ ok = true;
+
+ }
+ else {
+ m_haveImages = false;
+ }
+
+ // don't forget to release the lock on the copy of the image
+ // owned by the image loader thread
+ m_imageLoadThread->ungrabImage();
+
+ return ok;
+ }
+
+ void SlideShowKB::startSlideShowOnce() {
+ // when the image loader thread is ready, it will already have loaded
+ // the first image
+ if (m_initialized == false && m_imageLoadThread->ready()) {
+
+ setupNewImage(0); // setup the first image and
+ m_imageLoadThread->requestNewImage(); // load the next one in background
+ setNewKBEffect(); // set the initial effect
+
+ m_initialized = true;
+ }
+ }
+
+
+ void SlideShowKB::swapImages() {
+
+ Image *tmp = m_image[0];
+ m_image[0] = m_image[1];
+ m_image[1] = tmp;
+ }
+
+
+ void SlideShowKB::initializeGL() {
+
+ // Enable Texture Mapping
+ glEnable(GL_TEXTURE_2D);
+
+ // Clear The Background Color
+ glClearColor(0.0, 0.0, 0.0, 1.0f);
+
+ glEnable (GL_TEXTURE_2D);
+ glShadeModel (GL_SMOOTH);
+
+ // Turn Blending On
+ glEnable(GL_BLEND);
+ // Blending Function For Translucency Based On Source Alpha Value
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ // Enable perspective vision
+ glClearDepth(1.0f);
+ }
+
+
+ void SlideShowKB::paintGL() {
+
+ startSlideShowOnce();
+
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+
+ // only clear the color buffer, if none of the active images is fully opaque
+ if ( !((m_image[0]->m_paint && m_image[0]->m_opacity == 1.0) ||
+ (m_image[1]->m_paint && m_image[1]->m_opacity == 1.0)) )
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ if (m_endOfShow && m_image[0]->m_paint && m_image[1]->m_paint)
+ {
+ endOfShow();
+ m_timer->stop();
+ }
+ else
+ {
+ if (m_image[1]->m_paint)
+ paintTexture(m_image[1]);
+ if (m_image[0]->m_paint)
+ paintTexture(m_image[0]);
+ }
+ glFlush();
+ }
+
+
+ void SlideShowKB::resizeGL(int w, int h) {
+ glViewport(0, 0, (GLint) w, (GLint) h);
+ }
+
+
+
+ void SlideShowKB::applyTexture(Image *img, const QImage &texture) {
+
+ /* create the texture */
+ glGenTextures(1, &img->m_texture);
+ glBindTexture(GL_TEXTURE_2D, img->m_texture);
+
+ /* actually generate the texture */
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, texture.width(), texture.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture.bits());
+ /* enable linear filtering */
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ }
+
+
+ void SlideShowKB::paintTexture(Image *img) {
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ float sx = img->m_viewTrans->m_xScaleCorrect();
+ float sy = img->m_viewTrans->m_yScaleCorrect();
+
+ glTranslatef(img->m_viewTrans->transX(img->m_pos) * 2.0,
+ img->m_viewTrans->transY(img->m_pos) * 2.0, 0.0);
+ glScalef(img->m_viewTrans->scale(img->m_pos),
+ img->m_viewTrans->scale(img->m_pos), 0.0);
+
+ GLuint& tex = img->m_texture;
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, img->m_opacity);
+ glTexCoord2f(0, 0);
+ glVertex3f(-sx, -sy, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(sx, -sy, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(sx, sy, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-sx, sy, 0);
+ }
+ glEnd();
+
+ }
+
+
+ void SlideShowKB::readSettings() {
+ m_delay = m_config->readUnsignedNumEntry("Delay", 8000)/1000;
+ m_disableFadeInOut = m_config->readBoolEntry("KB Disable FadeInOut", false);
+ m_disableCrossFade = m_config->readBoolEntry("KB Disable Crossfade", false);
+ m_forceFrameRate = m_config->readUnsignedNumEntry("KB Force Framerate", 0);
+
+ if (m_delay < 5) m_delay = 5;
+// if (m_delay > 20) m_delay = 20;
+ if (m_forceFrameRate > 120) m_forceFrameRate = 120;
+ }
+
+ void SlideShowKB::endOfShow()
+ {
+ QPixmap pix(512,512);
+ pix.fill(Qt::black);
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize()+10);
+ fn.setBold(true);
+
+ QPainter p(&pix);
+ p.setPen(Qt::white);
+ p.setFont(fn);
+ p.drawText(20, 50, i18n("SlideShow Completed."));
+ p.drawText(20, 100, i18n("Click To Exit..."));
+ p.end();
+
+ QImage image(pix.convertToImage());
+ QImage t = convertToGLFormat(image);
+
+ GLuint tex;
+
+ /* create the texture */
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ /* actually generate the texture */
+ glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
+ /* enable linear filtering */
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ /* paint the texture */
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0, -1.0, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0, -1.0, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0, 1.0, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0, 1.0, 0);
+ }
+ glEnd();
+
+ m_showingEnd = true;
+ }
+
+ QStringList SlideShowKB::effectNames()
+ {
+ QStringList effects;
+
+ effects.append("Ken Burns");
+ return effects;
+ }
+
+ QMap<QString,QString> SlideShowKB::effectNamesI18N()
+ {
+ QMap<QString,QString> effects;
+
+ effects["Ken Burns"] = i18n("Ken Burns");
+
+ return effects;
+ }
+
+ void SlideShowKB::mousePressEvent(QMouseEvent *e)
+ {
+ // =======================================================
+ // Avoid boring compile time "unused parameter" warning :P
+ // This parameter could be useful for future implementations
+ if ( !e ) { /* TODO */ }
+ // =======================================================
+
+ if (m_endOfShow && m_showingEnd)
+ slotClose();
+ }
+
+ void SlideShowKB::mouseMoveEvent(QMouseEvent *e)
+ {
+ setCursor(QCursor(Qt::ArrowCursor));
+ m_mouseMoveTimer->start(1000, true);
+
+ QPoint pos(e->pos());
+ }
+
+ void SlideShowKB::slotEndOfShow()
+ {
+ m_endOfShow = true;
+ }
+
+ void SlideShowKB::slotMouseMoveTimeOut()
+ {
+ QPoint pos(QCursor::pos());
+ if ((pos.y() < (m_deskY+20)) ||
+ (pos.y() > (m_deskY+m_deskHeight-20-1)))
+ return;
+
+ setCursor(QCursor(Qt::BlankCursor));
+ }
+
+ void SlideShowKB::slotClose()
+ {
+ close();
+ }
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/slideshowkb.h b/kipi-plugins/slideshow/slideshowkb.h
new file mode 100644
index 0000000..58c2ce8
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowkb.h
@@ -0,0 +1,190 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de> and slideshowgl.{cpp|h} by Renchi Raju
+ * <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SLIDESHOWKB_H
+#define SLIDESHOWKB_H
+
+// C++ includes.
+
+#include <cstdlib>
+
+// Qt includes.
+
+#include <qgl.h>
+#include <qtimer.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qmap.h>
+
+// KDE includes.
+
+#include <kconfig.h>
+
+// Local includes.
+
+#include "kbeffect.h"
+#include "screenproperties.h"
+
+namespace KIPISlideShowPlugin
+{
+ class SmoothSlideSaver;
+ class ImageLoadThread;
+
+ // -------------------------------------------------------------------------
+
+ class ViewTrans
+ {
+
+ public:
+
+ ViewTrans(bool m_zoomIn, float relAspect);
+
+ float transX(float pos) const { return m_baseX + m_deltaX * pos; };
+ float transY(float pos) const { return m_baseY + m_deltaY * pos; };
+ float scale (float pos) const { return m_baseScale * (1.0 + m_deltaScale * pos); };
+ float m_xScaleCorrect() { return m_xScale; };
+ float m_yScaleCorrect() { return m_yScale; };
+
+ private:
+
+ double rnd() const { return (double)rand() / (double)RAND_MAX; };
+ double rndSign() const { return (rand() < RAND_MAX / 2) ? 1.0 : -1.0; };
+
+ private:
+
+ // delta and scale values (begin to end) and the needed offsets
+ double m_deltaX, m_deltaY, m_deltaScale;
+ double m_baseScale, m_baseX, m_baseY;
+ float m_xScale, m_yScale;
+ };
+
+ // -------------------------------------------------------------------------
+
+ class Image
+ {
+
+ public:
+
+ Image(ViewTrans *viewTrans, float aspect = 1.0);
+ ~Image();
+
+ ViewTrans* m_viewTrans;
+ float m_aspect;
+ float m_pos;
+ float m_opacity;
+ bool m_paint;
+ GLuint m_texture;
+ };
+
+ // -------------------------------------------------------------------------
+
+ class SlideShowKB : public QGLWidget
+ {
+
+ Q_OBJECT
+
+ public:
+
+ SlideShowKB(const QValueList<QPair<QString, int> >& fileList,
+ const QStringList& commentsList, bool ImagesHasComments);
+
+ ~SlideShowKB();
+
+ static QStringList effectNames();
+ static QMap<QString,QString> effectNamesI18N();
+
+ private:
+
+ float aspect() { return (float)width() / (float)height(); };
+ bool setupNewImage(int imageIndex);
+ void startSlideShowOnce();
+ void swapImages();
+ void setNewKBEffect();
+ void endOfShow();
+
+ void initializeGL();
+ void paintGL();
+ void resizeGL(int w, int h);
+ void applyTexture(Image *img, const QImage &image);
+ void paintTexture(Image *img);
+ unsigned suggestFrameRate(unsigned forceRate);
+
+ void readSettings();
+
+ protected:
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *);
+
+ private slots:
+
+ void moveSlot();
+ void slotEndOfShow();
+ void slotMouseMoveTimeOut();
+ void slotClose();
+
+ private:
+
+ int m_deskX;
+ int m_deskY;
+ int m_deskWidth;
+ int m_deskHeight;
+
+ KConfig* m_config;
+
+ bool m_imagesHasComments;
+ QStringList m_commentsList;
+
+ ScreenProperties* m_screen;
+ QTimer *m_timer;
+ QTimer *m_mouseMoveTimer;
+ ImageLoadThread *m_imageLoadThread;
+ bool m_haveImages;
+
+ Image *m_image[2];
+ KBEffect *m_effect;
+ int m_numKBEffectRepeated;
+ bool m_zoomIn, m_initialized;
+ float m_step;
+
+ bool m_endOfShow;
+ bool m_showingEnd;
+
+ // settings from config file
+ int m_delay;
+ bool m_disableFadeInOut;
+ bool m_disableCrossFade;
+ unsigned m_forceFrameRate;
+
+ friend class KBEffect;
+ };
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // SLIDESHOWKB_H
diff --git a/kipi-plugins/slideshow/slideshowloader.cpp b/kipi-plugins/slideshow/slideshowloader.cpp
new file mode 100644
index 0000000..b208783
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowloader.cpp
@@ -0,0 +1,219 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-11
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes
+
+#include <qimage.h>
+#include <qwmatrix.h>
+#include <qpainter.h>
+#include <qvaluelist.h>
+
+// KDE includes
+
+#include <kdebug.h>
+
+// Local includes
+
+#include "slideshowloader.h"
+
+namespace KIPISlideShowPlugin
+{
+
+ LoadThread::LoadThread(LoadedImages* loadedImages, QMutex* imageLock, const KURL path,
+ const int angle, int width, int height) {
+
+ m_path = path;
+ m_angle = angle;
+ m_swidth = width;
+ m_sheight = height;
+ m_imageLock = imageLock;
+ m_loadedImages = loadedImages;
+ }
+
+ LoadThread::~LoadThread() {
+ }
+
+ void LoadThread::run() {
+
+ QImage newImage(m_path.path());
+ // Rotate according to angle
+ if ( m_angle != 0 )
+ {
+ QWMatrix matrix;
+ matrix.rotate((double)m_angle);
+ newImage.xForm( matrix );
+ }
+
+
+ newImage = QImage(newImage.smoothScale(m_swidth, m_sheight, QImage::ScaleMin));
+
+ m_imageLock->lock();
+ m_loadedImages->insert(m_path, newImage);
+ m_imageLock->unlock();
+ }
+
+ // -----------------------------------------------------------------------------------------
+
+ SlideShowLoader::SlideShowLoader(FileList &pathList, uint cacheSize, int width, int height, int beginAtIndex) {
+
+ m_currIndex = beginAtIndex;
+ m_cacheSize = cacheSize;
+ m_pathList = pathList;
+ m_swidth = width;
+ m_sheight = height;
+ m_loadingThreads = new LoadingThreads();
+ m_loadedImages = new LoadedImages();
+ m_imageLock = new QMutex();
+ m_threadLock = new QMutex();
+
+ for ( uint i = 0; i < uint(m_cacheSize/2) && i < uint(m_pathList.count()); i++ ) {
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[i].first),
+ m_pathList[i].second, m_swidth, m_sheight);
+ m_threadLock->lock();
+ m_loadingThreads->insert(m_pathList[i].first, newThread);
+ newThread->start();
+ m_threadLock->unlock();
+ }
+ for ( uint i = 0; i < ( m_cacheSize%2 == 0? (m_cacheSize%2) : uint(m_cacheSize/2)+1); i++ ) {
+ int toLoad = (m_currIndex - i)%m_pathList.count();
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[toLoad].first),
+ m_pathList[toLoad].second, m_swidth, m_sheight);
+ m_threadLock->lock();
+ m_loadingThreads->insert(m_pathList[toLoad].first, newThread);
+ newThread->start();
+ m_threadLock->unlock();
+ }
+
+ }
+
+ SlideShowLoader::~SlideShowLoader() {
+
+ m_threadLock->lock();
+ LoadingThreads::Iterator it;
+ for ( it = m_loadingThreads->begin(); it != m_loadingThreads->end(); ++it ) {
+ it.data()->wait();
+ delete it.data();
+ m_loadingThreads->remove(it);
+ }
+ m_threadLock->unlock();
+
+
+ delete(m_loadingThreads);
+ delete(m_loadedImages);
+
+ delete(m_imageLock);
+ delete(m_threadLock);
+ }
+
+ void SlideShowLoader::next() {
+ int victim = (m_currIndex - ( m_cacheSize%2 == 0 ? (m_cacheSize/2)-1 : int(m_cacheSize/2))) % m_pathList.count();
+ int newBorn = (m_currIndex + int(m_cacheSize/2) + 1) % m_pathList.count();
+
+ if ( victim == newBorn ) return;
+
+ m_threadLock->lock();
+ m_imageLock->lock();
+ m_loadingThreads->remove(m_pathList[victim].first);
+ m_loadedImages->remove(m_pathList[victim].first);
+ m_imageLock->unlock();
+ m_threadLock->unlock();
+
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[newBorn].first),
+ m_pathList[newBorn].second, m_swidth, m_sheight);
+
+ m_threadLock->lock();
+ m_loadingThreads->insert(m_pathList[newBorn].first, newThread);
+ newThread->start();
+ m_threadLock->unlock();
+
+ m_currIndex = (m_currIndex + 1) % m_pathList.count();
+ }
+
+ void SlideShowLoader::prev() {
+ int victim = (m_currIndex + int(m_currIndex/2)) % m_pathList.count();
+ int newBorn = (m_currIndex - ( m_cacheSize&2 == 0 ? (m_cacheSize/2) : int(m_cacheSize/2)+1)) % m_pathList.count();
+
+ if ( victim == newBorn ) return;
+
+ m_threadLock->lock();
+ m_imageLock->lock();
+ m_loadingThreads->remove(m_pathList[victim].first);
+ m_loadedImages->remove(m_pathList[victim].first);
+ m_imageLock->unlock();
+ m_threadLock->unlock();
+
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[newBorn].first),
+ m_pathList[newBorn].second, m_swidth, m_sheight);
+
+
+ m_threadLock->lock();
+ m_loadingThreads->insert(m_pathList[newBorn].first, newThread);
+ newThread->start();
+ m_threadLock->unlock();
+
+ m_currIndex = (m_currIndex - 1) % m_pathList.count();
+
+ }
+
+ QImage SlideShowLoader::getCurrent() {
+ checkIsIn(m_currIndex);
+
+ m_imageLock->lock();
+ QImage returned = (*m_loadedImages)[m_pathList[m_currIndex].first];
+ m_imageLock->unlock();
+
+
+ return returned;
+ }
+
+ QString SlideShowLoader::currFileName()
+ {
+ return KURL(m_pathList[m_currIndex].first).fileName();
+ }
+
+ KURL SlideShowLoader::currPath()
+ {
+ return m_pathList[m_currIndex].first;
+ }
+
+ void SlideShowLoader::checkIsIn(int index)
+ {
+ m_threadLock->lock();
+ if (m_loadingThreads->contains(m_pathList[index].first))
+ {
+ if ( (*m_loadingThreads)[m_pathList[index].first]->running() )
+ (*m_loadingThreads)[m_pathList[index].first]->wait();
+ m_threadLock->unlock();
+ }
+ else
+ {
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[index].first),
+ m_pathList[index].second, m_swidth, m_sheight);
+
+ m_loadingThreads->insert(m_pathList[index].first,newThread);
+ newThread->start();
+ (*m_loadingThreads)[m_pathList[index].first]->wait();
+ m_threadLock->unlock();
+ }
+ }
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/slideshowloader.h b/kipi-plugins/slideshow/slideshowloader.h
new file mode 100644
index 0000000..165fe60
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowloader.h
@@ -0,0 +1,109 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-11
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SLIDESHOWLOADER_H
+#define SLIDESHOWLOADER_H
+
+// QT includes
+
+#include <qmap.h>
+#include <qmutex.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qthread.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+
+// KDE includes
+
+#include <kurl.h>
+
+typedef QPair<QString, int> FileAnglePair;
+typedef QValueList<FileAnglePair> FileList;
+
+namespace KIPISlideShowPlugin
+{
+
+ typedef QMap<KURL, QImage> LoadedImages;
+
+ class LoadThread : public QThread
+ {
+
+ public:
+
+ LoadThread(LoadedImages* loadedImages, QMutex* imageLock, const KURL path,
+ const int angle, int width, int height);
+ ~LoadThread();
+
+ protected:
+
+ void run();
+
+ private:
+
+ QMutex* m_imageLock;
+ LoadedImages* m_loadedImages;
+
+ KURL m_path;
+ QString m_filename;
+ int m_angle;
+ int m_swidth;
+ int m_sheight;
+ };
+
+ typedef QMap<KURL, LoadThread*> LoadingThreads;
+
+ class SlideShowLoader
+ {
+
+ public:
+
+ SlideShowLoader(FileList &pathList, uint cacheSize, int width, int height, int beginAtIndex=0);
+ ~SlideShowLoader();
+
+ void next();
+ void prev();
+
+ QImage getCurrent();
+ QString currFileName();
+ KURL currPath();
+
+ private:
+
+ void checkIsIn(int index);
+
+ LoadingThreads* m_loadingThreads;
+ LoadedImages* m_loadedImages;
+ FileList m_pathList;
+
+ QMutex* m_imageLock;
+ QMutex* m_threadLock;
+
+ uint m_cacheSize;
+ int m_currIndex;
+ int m_swidth;
+ int m_sheight;
+ };
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // SLIDESHOWLOADER_H
diff --git a/kipi-plugins/slideshow/toolbar.cpp b/kipi-plugins/slideshow/toolbar.cpp
new file mode 100644
index 0000000..35d0896
--- /dev/null
+++ b/kipi-plugins/slideshow/toolbar.cpp
@@ -0,0 +1,192 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-05
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qtoolbutton.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+
+// KDE includes.
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+// Local includes.
+
+#include "toolbar.h"
+#include "toolbar.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+ToolBar::ToolBar(QWidget* parent)
+ : QWidget(parent)
+{
+ QHBoxLayout* lay = new QHBoxLayout(this);
+ m_playBtn = new QToolButton(this);
+ m_prevBtn = new QToolButton(this);
+ m_nextBtn = new QToolButton(this);
+ m_stopBtn = new QToolButton(this);
+ m_playBtn->setToggleButton(true);
+
+ KIconLoader* loader = kapp->iconLoader();
+ m_playBtn->setIconSet(loader->loadIcon("player_pause", KIcon::NoGroup, 22));
+ m_prevBtn->setIconSet(loader->loadIcon("back", KIcon::NoGroup, 22));
+ m_nextBtn->setIconSet(loader->loadIcon("forward", KIcon::NoGroup, 22));
+ m_stopBtn->setIconSet(loader->loadIcon("stop", KIcon::NoGroup, 22));
+
+ lay->addWidget(m_playBtn);
+ lay->addWidget(m_prevBtn);
+ lay->addWidget(m_nextBtn);
+ lay->addWidget(m_stopBtn);
+
+ adjustSize();
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ m_canHide = true;
+
+ connect(m_playBtn, SIGNAL(toggled(bool)),
+ this, SLOT(slotPlayBtnToggled()));
+
+ connect(m_nextBtn, SIGNAL(clicked()),
+ this, SLOT(slotNexPrevClicked()));
+
+ connect(m_prevBtn, SIGNAL(clicked()),
+ this, SLOT(slotNexPrevClicked()));
+
+ connect(m_nextBtn, SIGNAL(clicked()),
+ this, SIGNAL(signalNext()));
+
+ connect(m_prevBtn, SIGNAL(clicked()),
+ this, SIGNAL(signalPrev()));
+
+ connect(m_stopBtn, SIGNAL(clicked()),
+ this, SIGNAL(signalClose()));
+}
+
+ToolBar::~ToolBar()
+{
+}
+
+bool ToolBar::canHide() const
+{
+ return m_canHide;
+}
+
+bool ToolBar::isPaused() const
+{
+ return m_playBtn->isOn();
+}
+
+void ToolBar::setPaused(bool val)
+{
+ if (val == isPaused())
+ return;
+
+ m_playBtn->setOn(val);
+ slotPlayBtnToggled();
+}
+
+void ToolBar::setEnabledPlay(bool val)
+{
+ m_playBtn->setEnabled(val);
+}
+
+void ToolBar::setEnabledNext(bool val)
+{
+ m_nextBtn->setEnabled(val);
+}
+
+void ToolBar::setEnabledPrev(bool val)
+{
+ m_prevBtn->setEnabled(val);
+}
+
+void ToolBar::slotPlayBtnToggled()
+{
+ if (m_playBtn->isOn())
+ {
+ m_canHide = false;
+ KIconLoader* loader = kapp->iconLoader();
+ m_playBtn->setIconSet(loader->loadIcon("player_play", KIcon::NoGroup, 22));
+ emit signalPause();
+ }
+ else
+ {
+ m_canHide = true;
+ KIconLoader* loader = kapp->iconLoader();
+ m_playBtn->setIconSet(loader->loadIcon("player_pause", KIcon::NoGroup, 22));
+ emit signalPlay();
+ }
+}
+
+void ToolBar::slotNexPrevClicked()
+{
+ if (!m_playBtn->isOn())
+ {
+ m_playBtn->setOn(true);
+ m_canHide = false;
+ KIconLoader* loader = kapp->iconLoader();
+ m_playBtn->setIconSet(loader->loadIcon("player_play", KIcon::NoGroup, 22));
+ emit signalPause();
+ }
+}
+
+void ToolBar::keyPressEvent(QKeyEvent *event)
+{
+ switch(event->key())
+ {
+ case(Qt::Key_Space):
+ {
+ if (m_playBtn->isEnabled())
+ m_playBtn->animateClick();
+ break;
+ }
+ case(Qt::Key_Prior):
+ {
+ if (m_prevBtn->isEnabled())
+ m_prevBtn->animateClick();
+ break;
+ }
+ case(Qt::Key_Next):
+ {
+ if (m_nextBtn->isEnabled())
+ m_nextBtn->animateClick();
+ break;
+ }
+ case(Qt::Key_Escape):
+ {
+ if (m_stopBtn->isEnabled())
+ m_stopBtn->animateClick();
+ break;
+ }
+ default:
+ break;
+ }
+
+ event->accept();
+}
+
+} // namespace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/toolbar.h b/kipi-plugins/slideshow/toolbar.h
new file mode 100644
index 0000000..776a249
--- /dev/null
+++ b/kipi-plugins/slideshow/toolbar.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-05
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef TOOLBAR_H
+#define TOOLBAR_H
+
+// Qt includes.
+
+#include <qwidget.h>
+
+class QToolButton;
+
+namespace KIPISlideShowPlugin
+{
+
+class ToolBar : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ ToolBar(QWidget* parent);
+ ~ToolBar();
+
+ bool canHide() const;
+ bool isPaused() const;
+ void setPaused(bool val);
+
+ void setEnabledPlay(bool val);
+ void setEnabledNext(bool val);
+ void setEnabledPrev(bool val);
+
+signals:
+
+ void signalNext();
+ void signalPrev();
+ void signalClose();
+ void signalPlay();
+ void signalPause();
+
+protected:
+
+ void keyPressEvent(QKeyEvent *event);
+
+private slots:
+
+ void slotPlayBtnToggled();
+ void slotNexPrevClicked();
+
+private:
+
+ QToolButton* m_playBtn;
+ QToolButton* m_stopBtn;
+ QToolButton* m_nextBtn;
+ QToolButton* m_prevBtn;
+ bool m_canHide;
+
+ friend class SlideShow;
+ friend class SlideShowGL;
+};
+
+} // namespace KIPISlideShowPlugin
+
+#endif /* TOOLBAR_H */