summaryrefslogtreecommitdiffstats
path: root/kuickshow/src
diff options
context:
space:
mode:
Diffstat (limited to 'kuickshow/src')
-rw-r--r--kuickshow/src/Makefile.am31
-rw-r--r--kuickshow/src/aboutwidget.cpp95
-rw-r--r--kuickshow/src/aboutwidget.h43
-rw-r--r--kuickshow/src/defaultswidget.cpp282
-rw-r--r--kuickshow/src/defaultswidget.h73
-rw-r--r--kuickshow/src/filecache.cpp83
-rw-r--r--kuickshow/src/filecache.h47
-rw-r--r--kuickshow/src/filefinder.cpp99
-rw-r--r--kuickshow/src/filefinder.h54
-rw-r--r--kuickshow/src/filewidget.cpp464
-rw-r--r--kuickshow/src/filewidget.h98
-rw-r--r--kuickshow/src/generalwidget.cpp163
-rw-r--r--kuickshow/src/generalwidget.h62
-rw-r--r--kuickshow/src/hi16-app-kuickshow.pngbin0 -> 396 bytes
-rw-r--r--kuickshow/src/hi22-app-kuickshow.pngbin0 -> 1423 bytes
-rw-r--r--kuickshow/src/hi32-app-kuickshow.pngbin0 -> 954 bytes
-rw-r--r--kuickshow/src/imagewindow.cpp1251
-rw-r--r--kuickshow/src/imagewindow.h176
-rw-r--r--kuickshow/src/imdata.cpp92
-rw-r--r--kuickshow/src/imdata.h57
-rw-r--r--kuickshow/src/imlibwidget.cpp715
-rw-r--r--kuickshow/src/imlibwidget.h187
-rw-r--r--kuickshow/src/kuick.cpp4
-rw-r--r--kuickshow/src/kuick.h70
-rw-r--r--kuickshow/src/kuickconfigdlg.cpp99
-rw-r--r--kuickshow/src/kuickconfigdlg.h58
-rw-r--r--kuickshow/src/kuickdata.cpp177
-rw-r--r--kuickshow/src/kuickdata.h86
-rw-r--r--kuickshow/src/kuickfile.cpp194
-rw-r--r--kuickshow/src/kuickfile.h99
-rw-r--r--kuickshow/src/kuickglobals.h33
-rw-r--r--kuickshow/src/kuickimage.cpp527
-rw-r--r--kuickshow/src/kuickimage.h92
-rw-r--r--kuickshow/src/kuickshow.cpp1443
-rw-r--r--kuickshow/src/kuickshow.desktop93
-rw-r--r--kuickshow/src/kuickshow.h178
-rw-r--r--kuickshow/src/kurlwidget.cpp42
-rw-r--r--kuickshow/src/kurlwidget.h36
-rw-r--r--kuickshow/src/main.cpp66
-rw-r--r--kuickshow/src/mainwidget.cpp43
-rw-r--r--kuickshow/src/mainwidget.h47
-rw-r--r--kuickshow/src/printing.cpp338
-rw-r--r--kuickshow/src/printing.h85
-rw-r--r--kuickshow/src/slideshowwidget.cpp80
-rw-r--r--kuickshow/src/slideshowwidget.h44
-rw-r--r--kuickshow/src/version.h3
46 files changed, 8009 insertions, 0 deletions
diff --git a/kuickshow/src/Makefile.am b/kuickshow/src/Makefile.am
new file mode 100644
index 00000000..57c92388
--- /dev/null
+++ b/kuickshow/src/Makefile.am
@@ -0,0 +1,31 @@
+## Makefile.am for kuickshow
+
+bin_PROGRAMS =
+lib_LTLIBRARIES =
+kdeinit_LTLIBRARIES = kuickshow.la
+
+# set the include path for X, qt and KDE
+INCLUDES = $(all_includes)
+KDE_CXXFLAGS = $(IMLIB_CFLAGS)
+METASOURCES = AUTO
+
+kuickshow_la_LDFLAGS = $(all_libraries) -module -avoid-version
+kuickshow_la_LIBADD = $(LIB_KDEPRINT) $(LIB_IMLIB)
+kuickshow_la_SOURCES = kuickshow.cpp \
+ aboutwidget.cpp generalwidget.cpp kuickconfigdlg.cpp main.cpp \
+ defaultswidget.cpp imagewindow.cpp kuickdata.cpp \
+ imdata.cpp filefinder.cpp kurlwidget.cpp filewidget.cpp \
+ kuick.cpp imlibwidget.cpp slideshowwidget.cpp printing.cpp \
+ kuickfile.cpp kuickimage.cpp filecache.cpp
+
+# if you "make distclean", this files get removed. If you want to remove
+# them while "make clean", use CLEANFILES
+DISTCLEANFILES = $(METASOURCES)
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kuickshow.pot
+
+KDE_ICON = kuickshow
+
+ # this is where the kdelnk file will go
+xdg_apps_DATA = kuickshow.desktop
diff --git a/kuickshow/src/aboutwidget.cpp b/kuickshow/src/aboutwidget.cpp
new file mode 100644
index 00000000..2ae41102
--- /dev/null
+++ b/kuickshow/src/aboutwidget.cpp
@@ -0,0 +1,95 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qdatetime.h>
+#include <qevent.h>
+#include <qglobal.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+
+#include <kwin.h>
+#include <kstandarddirs.h>
+
+#include "imlibwidget.h"
+#include "kurlwidget.h"
+#include "version.h"
+
+#include "aboutwidget.h"
+
+AboutWidget::AboutWidget( QWidget *parent, const char *name )
+ : QVBox( parent, name, Qt::WShowModal )
+{
+ KWin::setType( winId(), NET::Override );
+ KWin::setState( winId(), NET::SkipTaskbar );
+
+ setFrameStyle( WinPanel | Raised );
+
+ QGroupBox *gBox = new QGroupBox( 1, Horizontal, this);
+ gBox->setGeometry( 10, 10, width()-20, height()-20 );
+ gBox->setAlignment( AlignHCenter );
+ gBox->installEventFilter( this );
+
+ gBox->setPalette( QPalette( QColor( white ) ) );
+ gBox->setBackgroundMode( PaletteBackground );
+
+ int hour = QTime::currentTime().hour();
+ QString file;
+
+ if ( hour >= 10 && hour < 16 )
+ file = locate("appdata", "pics/kuickshow-day.jpg");
+ else
+ file = locate("appdata", "pics/kuickshow-night.jpg");
+
+ QLabel *authors = new QLabel("Kuickshow " KUICKSHOWVERSION
+ " was brought to you by", gBox);
+ authors->setAlignment( AlignCenter );
+
+ m_homepage = new KURLWidget("Carsten Pfeiffer", gBox);
+ m_homepage->setURL( "http://devel-home.kde.org/~pfeiffer/kuickshow/" );
+ m_homepage->setAlignment( AlignCenter );
+
+ QLabel *copy = new QLabel("(C) 1998-2006", gBox);
+ copy->setAlignment( AlignCenter );
+
+ ImlibWidget *im = new ImlibWidget( 0L, gBox, "KuickShow Logo" );
+ if ( im->loadImage( file ) )
+ im->setFixedSize( im->width(), im->height() );
+ else {
+ delete im;
+ im = 0L;
+ qWarning( "KuickShow: about-image not found/unreadable." );
+ }
+}
+
+AboutWidget::~AboutWidget()
+{
+}
+
+bool AboutWidget::eventFilter( QObject *o, QEvent *e )
+{
+ if ( e->type() == QEvent::MouseButtonPress ) {
+ QMouseEvent *ev = static_cast<QMouseEvent*>( e );
+ if ( !m_homepage->geometry().contains( ev->pos() ) ) {
+ deleteLater();
+ return true;
+ }
+ }
+
+ return QVBox::eventFilter( o, e );
+}
+#include "aboutwidget.moc"
diff --git a/kuickshow/src/aboutwidget.h b/kuickshow/src/aboutwidget.h
new file mode 100644
index 00000000..b9bc79d1
--- /dev/null
+++ b/kuickshow/src/aboutwidget.h
@@ -0,0 +1,43 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ABOUTWIDGET_H
+#define ABOUTWIDGET_H
+
+#include <qevent.h>
+#include <qvbox.h>
+
+class KURLWidget;
+
+class AboutWidget : public QVBox
+{
+ Q_OBJECT
+
+public:
+ AboutWidget(QWidget *parent = 0, const char *name = 0);
+
+protected:
+ ~AboutWidget();
+ bool eventFilter( QObject*, QEvent * );
+
+private:
+ KURLWidget *m_homepage;
+
+};
+
+#endif
diff --git a/kuickshow/src/defaultswidget.cpp b/kuickshow/src/defaultswidget.cpp
new file mode 100644
index 00000000..69807251
--- /dev/null
+++ b/kuickshow/src/defaultswidget.cpp
@@ -0,0 +1,282 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qvgroupbox.h>
+
+#include <kcombobox.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+
+#include "imlibwidget.h"
+#include "defaultswidget.h"
+
+DefaultsWidget::DefaultsWidget( QWidget *parent, const char *name)
+ : QWidget( parent, name )
+{
+ imFiltered = 0L;
+
+ cbEnableMods = new QCheckBox( i18n("Apply default image modifications"), this );
+ connect( cbEnableMods, SIGNAL( toggled(bool) ), SLOT( enableWidgets(bool) ));
+
+ // create all the widgets
+
+ gbScale = new QGroupBox( i18n("Scaling"), this );
+ gbScale->setColumnLayout( 0, Qt::Horizontal );
+
+ cbDownScale = new QCheckBox( i18n("Shrink image to screen size, if larger"),
+ gbScale, "shrinktoscreen" );
+
+ cbUpScale = new QCheckBox( i18n("Scale image to screen size, if smaller, up to factor:"), gbScale, "upscale checkbox" );
+
+ sbMaxUpScaleFactor = new KIntNumInput( gbScale, "upscale factor" );
+ sbMaxUpScaleFactor->setRange( 1, 100, 1, false );
+
+ connect(cbUpScale, SIGNAL( toggled(bool)), sbMaxUpScaleFactor,
+ SLOT( setEnabled(bool) ));
+
+ // --
+
+ gbGeometry = new QGroupBox( i18n("Geometry"), this );
+ gbGeometry->setColumnLayout( 0, Qt::Horizontal );
+
+ cbFlipVertically = new QCheckBox( i18n("Flip vertically"), gbGeometry );
+
+ cbFlipHorizontally = new QCheckBox( i18n("Flip horizontally"), gbGeometry );
+
+ lbRotate = new QLabel( i18n("Rotate image:"), gbGeometry );
+
+ comboRotate = new KComboBox( gbGeometry, "rotate combobox" );
+ comboRotate->insertItem( i18n("0 Degrees") );
+ comboRotate->insertItem( i18n("90 Degrees") );
+ comboRotate->insertItem( i18n("180 Degrees") );
+ comboRotate->insertItem( i18n("270 Degrees") );
+
+ // --
+
+ gbAdjust = new QVGroupBox( i18n("Adjustments"), this );
+
+ sbBrightness = new KIntNumInput( gbAdjust, "brightness spinbox" );
+ sbBrightness->setRange( -256, 256, 1, true );
+ sbBrightness->setLabel( i18n("Brightness:"), AlignVCenter );
+
+ sbContrast = new KIntNumInput( sbBrightness, 0,gbAdjust, 10,
+ "contrast spinbox");
+ sbContrast->setRange( -256, 256, 1, true );
+ sbContrast->setLabel( i18n("Contrast:"), AlignVCenter );
+
+ sbGamma = new KIntNumInput( sbContrast, 0, gbAdjust, 10, "gamma spinbox" );
+ sbGamma->setRange( -256, 256, 1, true );
+ sbGamma->setLabel( i18n("Gamma:"), AlignVCenter );
+
+ // --
+
+ gbPreview = new QGroupBox( i18n("Preview"), this );
+ gbPreview->setAlignment( AlignCenter );
+
+ lbImOrig = new QLabel( i18n("Original"), gbPreview );
+ imOrig = new ImlibWidget( 0L, gbPreview, "original image" );
+
+ lbImFiltered = new QLabel( i18n("Modified"), gbPreview );
+ imFiltered = new ImlibWidget( 0L, imOrig->getImlibData(), gbPreview, "" );
+ connect( imFiltered, SIGNAL( destroyed() ), SLOT( slotNoImage() ));
+
+ ////
+ ////////////////
+
+
+ // layout management
+ QVBoxLayout *mainLayout = new QVBoxLayout( this, 0,
+ KDialog::spacingHint(), "main layout" );
+
+ QVBoxLayout *gbScaleLayout = new QVBoxLayout( gbScale->layout(),
+ KDialog::spacingHint());
+ QVBoxLayout *gbGeometryLayout = new QVBoxLayout(gbGeometry->layout(),
+ KDialog::spacingHint());
+ QGridLayout *gbPreviewLayout = new QGridLayout(gbPreview, 2, 3, 0,
+ KDialog::spacingHint());
+
+ QHBoxLayout *scaleLayout = new QHBoxLayout();
+ QHBoxLayout *rotateLayout = new QHBoxLayout();
+
+ mainLayout->addWidget( cbEnableMods );
+ mainLayout->addWidget( gbScale );
+ QHBoxLayout *hl = new QHBoxLayout();
+ hl->addWidget( gbGeometry );
+ hl->addWidget( gbAdjust );
+ mainLayout->addLayout( hl );
+ mainLayout->addWidget( gbPreview );
+ mainLayout->addStretch();
+
+ // --
+
+ gbScaleLayout->addWidget( cbDownScale );
+ gbScaleLayout->addLayout( scaleLayout );
+
+ scaleLayout->addWidget( cbUpScale );
+ scaleLayout->addWidget( sbMaxUpScaleFactor );
+
+ // --
+
+ gbGeometryLayout->addWidget( cbFlipVertically, 0, AlignLeft );
+ gbGeometryLayout->addWidget( cbFlipHorizontally, 0, AlignLeft );
+ gbGeometryLayout->addLayout( rotateLayout, 0 );
+
+ rotateLayout->addWidget( lbRotate, 0, AlignLeft );
+ rotateLayout->addWidget( comboRotate, 0, AlignLeft );
+
+ // --
+
+ gbPreviewLayout->setMargin( 10 );
+ gbPreviewLayout->setSpacing( KDialog::spacingHint() );
+ gbPreviewLayout->addWidget( lbImOrig, 0, 0, AlignCenter );
+ gbPreviewLayout->addWidget( imOrig, 1, 0, AlignCenter | AlignTop );
+ gbPreviewLayout->addWidget( lbImFiltered, 0, 2, AlignCenter );
+ gbPreviewLayout->addWidget( imFiltered, 1, 2, AlignCenter | AlignTop );
+
+
+ ////
+ ////////////////
+
+ // connect them all to the update slot
+ connect( cbDownScale, SIGNAL( clicked() ), SLOT( updatePreview() ));
+ connect( cbUpScale, SIGNAL( clicked() ), SLOT( updatePreview() ));
+ connect( cbFlipVertically, SIGNAL( clicked() ), SLOT( updatePreview() ));
+ connect( cbFlipHorizontally, SIGNAL( clicked() ), SLOT( updatePreview() ));
+ connect( sbMaxUpScaleFactor, SIGNAL( valueChanged(int) ), SLOT( updatePreview() ));
+ connect( sbBrightness, SIGNAL( valueChanged(int) ), SLOT( updatePreview() ));
+ connect( sbContrast, SIGNAL( valueChanged(int) ), SLOT( updatePreview() ));
+ connect( sbGamma, SIGNAL( valueChanged(int) ), SLOT( updatePreview() ));
+
+ connect( comboRotate, SIGNAL( activated(int) ), SLOT( updatePreview() ));
+
+
+ QString filename = locate( "data", "kuickshow/pics/calibrate.png" );
+ if ( !imOrig->loadImage( filename ) )
+ imOrig = 0L; // FIXME - display some errormessage!
+ if ( !imFiltered->loadImage( filename ) )
+ imFiltered = 0L; // FIXME - display some errormessage!
+
+ loadSettings( *kdata );
+
+ if ( imOrig )
+ imOrig->setFixedSize( imOrig->size() );
+ if ( imFiltered )
+ imFiltered->setFixedSize( imFiltered->size() );
+
+ mainLayout->activate();
+}
+
+
+DefaultsWidget::~DefaultsWidget()
+{
+ // those need to be deleted in the right order, as imFiltered
+ // references ImlibData from imOrig
+ delete imFiltered;
+ delete imOrig;
+}
+
+void DefaultsWidget::loadSettings( const KuickData& data )
+{
+ cbDownScale->setChecked( data.downScale );
+ cbUpScale->setChecked( data.upScale );
+ sbMaxUpScaleFactor->setValue( data.maxUpScale );
+
+ cbFlipVertically->setChecked( data.flipVertically );
+ cbFlipHorizontally->setChecked( data.flipHorizontally );
+
+ comboRotate->setCurrentItem( data.rotation );
+
+ ImData *id = data.idata;
+
+ sbBrightness->setValue( id->brightness );
+ sbContrast->setValue( id->contrast );
+ sbGamma->setValue( id->gamma );
+
+ cbEnableMods->setChecked( data.isModsEnabled );
+ enableWidgets( data.isModsEnabled );
+
+ updatePreview();
+}
+
+void DefaultsWidget::applySettings( KuickData& data )
+{
+ data.isModsEnabled = cbEnableMods->isChecked();
+
+ data.downScale = cbDownScale->isChecked();
+ data.upScale = cbUpScale->isChecked();
+ data.maxUpScale = sbMaxUpScaleFactor->value();
+
+ data.flipVertically = cbFlipVertically->isChecked();
+ data.flipHorizontally = cbFlipHorizontally->isChecked();
+
+ data.rotation = currentRotation();
+
+ ImData *id = data.idata;
+
+ id->brightness = sbBrightness->value();
+ id->contrast = sbContrast->value();
+ id->gamma = sbGamma->value();
+}
+
+void DefaultsWidget::updatePreview()
+{
+ if ( !imFiltered )
+ return;
+
+ imFiltered->setAutoRender( false );
+
+ int flipMode = cbFlipHorizontally->isChecked() ? FlipHorizontal : FlipNone;
+ flipMode |= cbFlipVertically->isChecked() ? FlipVertical : FlipNone;
+ imFiltered->setFlipMode( flipMode );
+
+ Rotation rotation = cbEnableMods->isChecked() ? currentRotation() : ROT_0;
+ imFiltered->setRotation( rotation );
+
+ imFiltered->setBrightness( sbBrightness->value() );
+ imFiltered->setContrast( sbContrast->value() );
+ imFiltered->setGamma( sbGamma->value() );
+
+ imFiltered->updateImage();
+ imFiltered->setAutoRender( true );
+}
+
+
+void DefaultsWidget::enableWidgets( bool enable )
+{
+ gbScale->setEnabled( enable );
+ sbMaxUpScaleFactor->setEnabled( enable & cbUpScale->isChecked() );
+
+ gbGeometry->setEnabled( enable );
+ gbAdjust->setEnabled( enable );
+ gbPreview->setEnabled( enable );
+ updatePreview();
+}
+
+
+Rotation DefaultsWidget::currentRotation() const
+{
+ return (Rotation) comboRotate->currentItem();
+}
+
+#include "defaultswidget.moc"
diff --git a/kuickshow/src/defaultswidget.h b/kuickshow/src/defaultswidget.h
new file mode 100644
index 00000000..3febb098
--- /dev/null
+++ b/kuickshow/src/defaultswidget.h
@@ -0,0 +1,73 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef DEFAULTSWIDGET_H
+#define DEFAULTSWIDGET_H
+
+#include "kuickdata.h"
+
+class ImlibWidget;
+class ImData;
+
+class QCheckBox;
+class QLabel;
+
+class KComboBox;
+class KIntNumInput;
+
+class DefaultsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DefaultsWidget( QWidget *parent, const char *name );
+ ~DefaultsWidget();
+
+ void loadSettings( const KuickData& data );
+ void applySettings( KuickData& data );
+
+private:
+ Rotation currentRotation() const;
+
+ QCheckBox *cbEnableMods;
+
+ QGroupBox *gbScale;
+ QCheckBox *cbUpScale, *cbDownScale;
+ KIntNumInput *sbMaxUpScaleFactor;
+
+ QGroupBox *gbAdjust;
+ KIntNumInput *sbBrightness, *sbContrast, *sbGamma;
+
+ QGroupBox *gbGeometry;
+ QLabel *lbRotate;
+ KComboBox *comboRotate;
+ QCheckBox *cbFlipVertically, *cbFlipHorizontally;
+
+ QGroupBox *gbPreview;
+ QLabel *lbImOrig, *lbImFiltered;
+ ImlibWidget *imOrig, *imFiltered;
+
+
+private slots:
+ void updatePreview();
+ void slotNoImage() { imFiltered = 0L; }
+ void enableWidgets( bool );
+
+};
+
+#endif
diff --git a/kuickshow/src/filecache.cpp b/kuickshow/src/filecache.cpp
new file mode 100644
index 00000000..c1c1affe
--- /dev/null
+++ b/kuickshow/src/filecache.cpp
@@ -0,0 +1,83 @@
+#include <unistd.h>
+
+#include <qstring.h>
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <ktempdir.h>
+
+#include "filecache.h"
+
+FileCache * FileCache::s_self;
+
+FileCache::FileCache()
+ : m_limit( 0 ),
+ m_tempDir( 0L )
+{
+ m_files.setAutoDelete( true );
+ m_files.setMaxCost( 100 ); // good default? ### make configurable?
+}
+
+FileCache::~FileCache()
+{
+ delete m_tempDir;
+}
+
+void FileCache::shutdown()
+{
+ if ( s_self )
+ {
+ delete s_self;
+ s_self = 0L;
+ }
+}
+
+FileCache * FileCache::self()
+{
+ if ( !s_self )
+ s_self = new FileCache();
+ return s_self;
+}
+
+KuickFile * FileCache::getFile( const KURL& url )
+{
+ QString urlString = url.prettyURL();
+ KuickFile *file = m_files.find( urlString );
+ if ( !file ) {
+ file = new KuickFile( url );
+ m_files.insert( urlString, file );
+ }
+
+ return file;
+}
+
+QString FileCache::tempDir()
+{
+ if ( !m_tempDir ) {
+ m_tempDir = createTempDir();
+
+ if ( !m_tempDir ) {
+ kdWarning() << "Unable to create temporary directory for KuickShow" << endl;
+ return QString::null;
+ }
+ }
+
+ return m_tempDir->name();
+}
+
+
+KTempDir * FileCache::createTempDir()
+{
+ QString tmpName = QString::fromLatin1( KGlobal::instance()->instanceName() );
+ tmpName.append( QString::number( getpid() ) );
+ QString dirName = locateLocal( "tmp", tmpName );
+ KTempDir *dir = new KTempDir( dirName );
+ dir->setAutoDelete( true );
+ if ( dir->status() != 0L )
+ {
+ delete dir;
+ return 0L;
+ }
+
+ return dir;
+}
diff --git a/kuickshow/src/filecache.h b/kuickshow/src/filecache.h
new file mode 100644
index 00000000..16e53261
--- /dev/null
+++ b/kuickshow/src/filecache.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+** $Id: .emacs,v 1.3 2006/02/20 15:06:53 gis Exp $
+**
+** Created : 2006
+**
+** Copyright (C) 2006 Carsten Pfeiffer <pfeiffer@kde.org>
+**
+****************************************************************************/
+
+#ifndef FILECACHE_H
+#define FILECACHE_H
+
+#include <qcache.h>
+
+#include "kuickfile.h"
+
+class KTempDir;
+
+class FileCache
+{
+public:
+ static FileCache * self();
+ static void shutdown();
+
+ KuickFile * getFile( const KURL& url );
+ void setLimit( int numFiles );
+ int getLimit() const { return m_limit; }
+
+ /**
+ * @return the temporary directory or QString::null if none available
+ */
+ QString tempDir();
+
+private:
+ static FileCache *s_self;
+ FileCache();
+ ~FileCache();
+
+ KTempDir * createTempDir();
+ QCache<KuickFile> m_files;
+
+ int m_limit;
+ KTempDir *m_tempDir;
+
+};
+
+#endif // FILECACHE_H
diff --git a/kuickshow/src/filefinder.cpp b/kuickshow/src/filefinder.cpp
new file mode 100644
index 00000000..9dda0046
--- /dev/null
+++ b/kuickshow/src/filefinder.cpp
@@ -0,0 +1,99 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qkeycode.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kcompletionbox.h>
+#include <kurlcompletion.h>
+
+#include "filefinder.h"
+
+FileFinder::FileFinder( QWidget *parent, const char *name )
+ : KLineEdit( parent, name )
+{
+ // make this widget just as large, as the font is + 8 Pixels
+ int height = fontMetrics().height() + 8;
+ setFixedSize( 150, height );
+ setFrame( true );
+
+ setHandleSignals( true ); // we want the completionbox signals
+ completionBox()->setTabHandling( true );
+
+ connect( completionBox(), SIGNAL( userCancelled(const QString&) ),
+ SLOT( hide() ));
+ connect( completionBox(), SIGNAL( activated( const QString& ) ),
+ SLOT( slotAccept( const QString& )));
+ connect( this, SIGNAL( returnPressed( const QString& )),
+ SLOT( slotAccept( const QString& ) ));
+
+ KURLCompletion *comp = new KURLCompletion();
+ comp->setReplaceHome( true );
+ comp->setReplaceEnv( true );
+ setCompletionObject( comp, false );
+ setAutoDeleteCompletionObject( true );
+ setFocusPolicy( ClickFocus );
+
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver cs( config, "GeneralConfiguration" );
+ setCompletionMode( (KGlobalSettings::Completion)
+ config->readNumEntry( "FileFinderCompletionMode",
+ KGlobalSettings::completionMode()));
+}
+
+FileFinder::~FileFinder()
+{
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver cs( config, "GeneralConfiguration" );
+ config->writeEntry( "FileFinderCompletionMode", completionMode() );
+}
+
+void FileFinder::focusOutEvent( QFocusEvent *e )
+{
+ if ( e->reason() != QFocusEvent::Popup )
+ hide();
+}
+
+void FileFinder::keyPressEvent( QKeyEvent *e )
+{
+ int key = e->key();
+ if ( key == Key_Escape ) {
+ hide();
+ e->accept();
+ }
+
+ else {
+ KLineEdit::keyPressEvent( e );
+ }
+}
+
+void FileFinder::hide()
+{
+ KLineEdit::hide();
+ parentWidget()->setFocus();
+}
+
+void FileFinder::slotAccept( const QString& dir )
+{
+ hide();
+ emit enterDir( dir );
+}
+
+#include "filefinder.moc"
diff --git a/kuickshow/src/filefinder.h b/kuickshow/src/filefinder.h
new file mode 100644
index 00000000..f75c69a4
--- /dev/null
+++ b/kuickshow/src/filefinder.h
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef FILEFINDER_H
+#define FILEFINDER_H
+
+#include <qevent.h>
+
+#include <klineedit.h>
+
+class KURLCompletion;
+
+class FileFinder : public KLineEdit
+{
+ Q_OBJECT
+
+public:
+ FileFinder( QWidget *parent=0, const char *name=0 );
+ ~FileFinder();
+
+ KURLCompletion *completion() {
+ return static_cast<KURLCompletion*>( completionObject() );
+ }
+
+ virtual void hide();
+
+signals:
+ void enterDir( const QString& );
+
+protected:
+ virtual void focusOutEvent( QFocusEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
+
+private slots:
+ void slotAccept( const QString& );
+
+};
+
+#endif // FILEFINDER_H
diff --git a/kuickshow/src/filewidget.cpp b/kuickshow/src/filewidget.cpp
new file mode 100644
index 00000000..d4b99f0a
--- /dev/null
+++ b/kuickshow/src/filewidget.cpp
@@ -0,0 +1,464 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qkeycode.h>
+
+#include <kdeversion.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kpropertiesdialog.h>
+#include <kurlcompletion.h>
+
+#include "filefinder.h"
+#include "filewidget.h"
+#include "kuickdata.h"
+#include "kuickshow.h"
+
+#ifdef KeyPress
+#undef KeyPress
+#endif
+
+FileWidget::FileWidget( const KURL& url, QWidget *parent, const char *name )
+ : KDirOperator( url, parent, name ),
+ m_validCompletion( false ),
+ m_fileFinder( 0L )
+{
+ setEnableDirHighlighting( true );
+
+#if KDE_VERSION >= 310
+ setViewConfig( KGlobal::config(), "Filebrowser" );
+#endif
+ readConfig( KGlobal::config(), "Filebrowser" );
+ setView( KFile::Default );
+
+ // setOnlyDoubleClickSelectsFiles( true );
+ reloadConfiguration();
+
+ completionObject()->setCompletionMode( KGlobalSettings::CompletionAuto );
+ dirCompletionObject()->setCompletionMode( KGlobalSettings::CompletionAuto);
+
+ slotViewChanged();
+ connect( this, SIGNAL( viewChanged( KFileView * )),
+ SLOT( slotViewChanged() ));
+
+ connect( dirLister(), SIGNAL( clear() ), SLOT( slotItemsCleared() ));
+ connect( dirLister(), SIGNAL( deleteItem( KFileItem * ) ),
+ SLOT( slotItemDeleted( KFileItem *) ));
+
+ connect( this, SIGNAL( fileHighlighted( const KFileItem * )),
+ SLOT( slotHighlighted( const KFileItem * )));
+
+ connect( this, SIGNAL(urlEntered(const KURL&)),
+ SLOT( slotURLEntered( const KURL& )));
+
+ // should actually be KDirOperator's job!
+ connect( this, SIGNAL( finishedLoading() ), SLOT( slotFinishedLoading() ));
+}
+
+FileWidget::~FileWidget()
+{
+ delete m_fileFinder;
+}
+
+void FileWidget::initActions()
+{
+ int index = 0;
+ KActionCollection *coll = actionCollection();
+ KActionSeparator *sep = new KActionSeparator( coll, "kuicksep" );
+ KActionMenu *menu = static_cast<KActionMenu*>( coll->action("popupMenu") );
+
+ menu->insert( coll->action("kuick_showInOtherWindow"), index++ );
+ menu->insert( coll->action("kuick_showInSameWindow"), index++ );
+ menu->insert( coll->action("kuick_showFullscreen"), index++ );
+ menu->insert( sep, index++ );
+
+ // support for older kdelibs, remove somewhen...
+ if ( coll->action("kuick_delete") )
+ menu->insert( coll->action("kuick_delete"), 9 );
+
+ // properties dialog is now in kfile, but not at the right position,
+ // so we move it to the real bottom
+ menu->remove( coll->action( "properties" ) );
+
+ QPopupMenu *pMenu = menu->popupMenu();
+ int lastItemId = pMenu->idAt( pMenu->count() - 1 );
+ QMenuItem *mItem = pMenu->findItem( lastItemId );
+ if ( mItem && !mItem->isSeparator() )
+ menu->insert( sep );
+
+ // those at the bottom
+ menu->insert( coll->action("kuick_print") );
+ menu->insert( sep );
+ menu->insert( coll->action("properties") );
+}
+
+void FileWidget::reloadConfiguration()
+{
+ if ( kdata->fileFilter != nameFilter() ) {
+ // At first, our list must have folders
+ QStringList mimes;
+ mimes.append("inode/directory");
+
+ // Then, all the images!
+ KMimeType::List l = KMimeType::allMimeTypes();
+ for (KMimeType::List::iterator it = l.begin(); it != l.end(); ++it)
+ if ((*it)->name().startsWith( "image/" ))
+ mimes.append( (*it)->name() );
+
+ // Ok, show what we've done
+ setMimeFilter (mimes);
+ updateDir();
+ }
+}
+
+bool FileWidget::hasFiles() const
+{
+ return (numFiles() > 0);
+}
+
+void FileWidget::activatedMenu( const KFileItem *item, const QPoint& pos )
+{
+ bool image = isImage( item );
+ actionCollection()->action("kuick_showInSameWindow")->setEnabled( image );
+ actionCollection()->action("kuick_showInOtherWindow")->setEnabled( image );
+ actionCollection()->action("kuick_showFullscreen")->setEnabled( image );
+ actionCollection()->action("kuick_print")->setEnabled( image );
+ actionCollection()->action("properties")->setEnabled( item );
+
+ bool hasSelection = (item != 0L);
+ if ( actionCollection()->action("kuick_delete") )
+ actionCollection()->action("kuick_delete")->setEnabled( hasSelection );
+
+ KDirOperator::activatedMenu( item, pos );
+}
+
+void FileWidget::findCompletion( const QString& text )
+{
+ if ( text.at(0) == '/' || text.at(0) == '~' ||
+ text.find('/') != -1 ) {
+ QString t = m_fileFinder->completion()->makeCompletion( text );
+
+ if (m_fileFinder->completionMode() == KGlobalSettings::CompletionPopup ||
+ m_fileFinder->completionMode() == KGlobalSettings::CompletionPopupAuto)
+ m_fileFinder->setCompletedItems(
+ m_fileFinder->completion()->allMatches() );
+ else
+ if ( !t.isNull() )
+ m_fileFinder->setCompletedText( t );
+
+ return;
+ }
+
+ QString file = makeDirCompletion( text );
+ if ( file.isNull() )
+ file = makeCompletion( text );
+
+ m_validCompletion = !file.isNull();
+
+ if ( m_validCompletion )
+ KDirOperator::setCurrentItem( file );
+}
+
+bool FileWidget::eventFilter( QObject *o, QEvent *e )
+{
+ if ( e->type() == QEvent::KeyPress ) {
+ QKeyEvent *k = static_cast<QKeyEvent*>( e );
+
+ if ( (k->state() & (ControlButton | AltButton)) == 0 ) {
+ int key = k->key();
+ if ( actionCollection()->action("delete")->shortcut().contains( key ) )
+ {
+ k->accept();
+ KFileItem *item = getCurrentItem( false );
+ if ( item ) {
+ KFileItemList list;
+ list.append( item );
+ del( list, (k->state() & ShiftButton) == 0 );
+ }
+ return true;
+ }
+
+ const QString& text = k->text();
+ if ( !text.isEmpty() && text.unicode()->isPrint() ) {
+ k->accept();
+
+ if ( !m_fileFinder ) {
+ m_fileFinder = new FileFinder( this, "file finder" );
+ connect( m_fileFinder, SIGNAL( completion(const QString&)),
+ SLOT( findCompletion( const QString& )));
+ connect( m_fileFinder,
+ SIGNAL( enterDir( const QString& ) ),
+ SLOT( slotReturnPressed( const QString& )));
+ m_fileFinder->move( width() - m_fileFinder->width(),
+ height() - m_fileFinder->height() );
+ }
+
+ bool first = m_fileFinder->isHidden();
+
+ m_fileFinder->setText( text );
+ m_fileFinder->raise();
+ m_fileFinder->show();
+ m_fileFinder->setFocus();
+ if ( first )
+ findCompletion( text );
+
+ return true;
+ }
+ }
+
+ k->ignore();
+ }
+ return KDirOperator::eventFilter( o, e );
+}
+
+
+// KIO::NetAccess::stat() does NOT give us the right mimetype, while
+// KIO::NetAccess::mimetype() does. So we have this hacklet to tell
+// showImage that the KFileItem is really an image.
+#define IS_IMAGE 5
+#define MY_TYPE 55
+
+bool FileWidget::isImage( const KFileItem *item )
+{
+// return item && !item->isDir();
+ if ( item )
+ {
+ return item->isReadable() && item->mimetype().startsWith( "image/") ||
+ item->extraData( (void*) MY_TYPE ) == (void*) IS_IMAGE;
+ }
+ return false;
+}
+
+void FileWidget::setImage( KFileItem& item, bool enable )
+{
+ if ( enable )
+ item.setExtraData( (void*) MY_TYPE, (void*) IS_IMAGE );
+ else
+ item.removeExtraData( (void*) MY_TYPE );
+}
+
+KFileItem * FileWidget::gotoFirstImage()
+{
+ KFileItemListIterator it( *(fileView()->items()) );
+
+ while ( it.current() ) {
+ if ( isImage( it.current() ) ) {
+ setCurrentItem( it.current() );
+ return it.current();
+ }
+ ++it;
+ }
+
+ return 0L;
+}
+
+KFileItem * FileWidget::gotoLastImage()
+{
+ KFileItemListIterator it( *(fileView()->items()) );
+ it.toLast();
+
+ while ( it.current() ) {
+ if ( isImage( it.current() ) ) {
+ setCurrentItem( it.current() );
+ return it.current();
+ }
+ --it;
+ }
+
+ return 0L;
+}
+
+KFileItem * FileWidget::getNext( bool go )
+{
+ KFileItem *item = getItem( Next, true );
+ if ( item ) {
+ if ( go )
+ setCurrentItem( item );
+ return item;
+ }
+
+ return 0L;
+}
+
+KFileItem * FileWidget::getPrevious( bool go )
+{
+ KFileItem *item = getItem( Previous, true );
+ if ( item ) {
+ if ( go )
+ setCurrentItem( item );
+ return item;
+ }
+
+ return 0L;
+}
+
+// returns 0L when there is no previous/next item/image
+// this sucks! Use KFileView::currentFileItem() when implemented
+KFileItem * FileWidget::getItem( WhichItem which, bool onlyImage ) const
+{
+ KFileItemListIterator it( *(fileView()->items()) );
+
+ while ( it.current() ) { // find the iterator to the current item
+ if ( it.current()->url() == m_currentURL )
+ break;
+
+ ++it;
+ }
+
+ if ( it.current() ) {
+ switch ( which ) {
+ case Previous: {
+ --it;
+ while ( it.current() ) {
+ if ( isImage( it.current() ) || !onlyImage )
+ return it.current();
+ --it;
+ }
+ return 0L; // no previous item / image
+ }
+
+ case Next: {
+ ++it;
+ while ( it.current() ) {
+ if ( isImage( it.current() ) || !onlyImage )
+ return it.current();
+ ++it;
+ }
+ return 0L; // no further item / image
+ }
+
+ case Current:
+ default:
+ return it.current();
+ }
+ }
+
+ return 0L;
+}
+
+void FileWidget::slotViewChanged()
+{
+ fileView()->widget()->installEventFilter( this );
+}
+
+void FileWidget::slotItemsCleared()
+{
+ m_currentURL = QString::null;
+}
+
+void FileWidget::slotItemDeleted( KFileItem *item )
+{
+ KFileItem *current = getCurrentItem( false );
+ if ( item != current ) {
+ return; // all ok, we already have a new current item
+ }
+
+ KFileItem *next = getNext();
+ if ( !next )
+ next = getPrevious();
+
+ if ( next )
+ m_currentURL = next->url().url();
+}
+
+void FileWidget::slotHighlighted( const KFileItem *item )
+{
+ m_currentURL = item->url().url();
+}
+
+void FileWidget::slotReturnPressed( const QString& t )
+{
+ // we need a / at the end, otherwise replacedPath() will cut off the dir,
+ // assuming it is a filename
+ QString text = t;
+ if ( text.at( text.length()-1 ) != '/' )
+ text += '/';
+
+ if ( text.at(0) == '/' || text.at(0) == '~' ) {
+ QString dir = m_fileFinder->completion()->replacedPath( text );
+
+ KURL url;
+ url.setPath( dir );
+ setURL( url, true );
+ }
+
+ else if ( text.find('/') != (int) text.length() -1 ) { // relative path
+ QString dir = m_fileFinder->completion()->replacedPath( text );
+ KURL u( url(), dir );
+ setURL( u, true );
+ }
+
+ else if ( m_validCompletion ) {
+ KFileItem *item = getCurrentItem( true );
+
+ if ( item ) {
+ if ( item->isDir() )
+ setURL( item->url(), true );
+ else
+ emit fileSelected( item );
+ }
+ }
+}
+
+void FileWidget::setCurrentItem( const KFileItem *item )
+{
+ if ( item ) {
+ fileView()->setCurrentItem( item );
+ fileView()->ensureItemVisible( item );
+ }
+}
+
+void FileWidget::setInitialItem( const QString& filename )
+{
+ m_initialName = filename;
+}
+
+void FileWidget::slotURLEntered( const KURL& url )
+{
+ if ( m_fileFinder )
+ m_fileFinder->completion()->setDir( url.path() );
+}
+
+void FileWidget::slotFinishedLoading()
+{
+ KFileItem *current = getCurrentItem( false );
+ if ( !m_initialName.isEmpty() )
+ setCurrentItem( m_initialName );
+ else if ( !current )
+ setCurrentItem( view()->items()->getFirst() );
+
+ m_initialName = QString::null;
+ emit finished();
+}
+
+QSize FileWidget::sizeHint() const
+{
+ return QSize( 300, 300 );
+}
+
+void FileWidget::resizeEvent( QResizeEvent *e )
+{
+ KDirOperator::resizeEvent( e );
+ if ( m_fileFinder )
+ m_fileFinder->move( width() - m_fileFinder->width(),
+ height() - m_fileFinder->height() );
+}
+
+#include "filewidget.moc"
diff --git a/kuickshow/src/filewidget.h b/kuickshow/src/filewidget.h
new file mode 100644
index 00000000..a785fd85
--- /dev/null
+++ b/kuickshow/src/filewidget.h
@@ -0,0 +1,98 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef FILEWIDGET_H
+#define FILEWIDGET_H
+
+#include <qevent.h>
+
+#include <kdiroperator.h>
+
+class FileFinder;
+class KFileItem;
+
+class FileWidget : public KDirOperator
+{
+ Q_OBJECT
+
+public:
+ enum WhichItem { Previous, Next, Current };
+
+ FileWidget( const KURL& url, QWidget *parent = 0L, const char *name = 0L );
+ ~FileWidget();
+
+ bool hasFiles() const;
+ void reloadConfiguration();
+
+ void setInitialItem( const QString& filename );
+
+ KFileItem *getCurrentItem( bool onlyImage ) const {
+ return getItem( Current, onlyImage );
+ }
+
+ void setCurrentItem( const KFileItem * );
+ void setCurrentItem( const QString& filename ) {
+ KDirOperator::setCurrentItem( filename );
+ }
+
+ KFileItem * gotoFirstImage();
+ KFileItem * gotoLastImage();
+ KFileItem * getNext( bool go=true );
+ KFileItem * getPrevious( bool go=true );
+
+
+ KFileItem *getItem( WhichItem which, bool onlyImage ) const;
+
+ static bool isImage( const KFileItem * );
+ static void setImage( KFileItem& item, bool enable );
+
+ void initActions();
+
+signals:
+ void finished();
+
+protected:
+ virtual bool eventFilter( QObject *o, QEvent * );
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void activatedMenu( const KFileItem *, const QPoint& );
+ virtual QSize sizeHint() const;
+
+private slots:
+ void slotReturnPressed( const QString& text );
+ void findCompletion( const QString& );
+ void slotViewChanged();
+
+ void slotItemsCleared();
+ void slotItemDeleted( KFileItem * );
+ void slotHighlighted( const KFileItem * );
+
+ void slotURLEntered( const KURL& url );
+ void slotFinishedLoading();
+
+private:
+ KFileView * fileView() const { return (KFileView*) view(); }
+
+ bool m_validCompletion;
+ FileFinder *m_fileFinder;
+ QString m_currentURL;
+ QString m_initialName;
+
+};
+
+
+#endif // FILEWIDGET_H
diff --git a/kuickshow/src/generalwidget.cpp b/kuickshow/src/generalwidget.cpp
new file mode 100644
index 00000000..3b718d69
--- /dev/null
+++ b/kuickshow/src/generalwidget.cpp
@@ -0,0 +1,163 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qvgroupbox.h>
+
+#include <kapplication.h>
+#include <kcolorbutton.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kurllabel.h>
+
+#include "generalwidget.h"
+
+GeneralWidget::GeneralWidget( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ QVBoxLayout *layout = new QVBoxLayout( this );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ QPixmap pixmap = UserIcon( "logo" );
+ KURLLabel *logo = new KURLLabel( this );
+ logo->setURL( "http://devel-home.kde.org/~pfeiffer/kuickshow/" );
+ logo->setPixmap( pixmap );
+ logo->setFixedSize( pixmap.size() );
+ logo->setTipText( i18n( "Open KuickShow Website" ) );
+ logo->setUseTips( true );
+
+ connect( logo, SIGNAL( leftClickedURL( const QString & ) ),
+ SLOT( slotURLClicked( const QString & ) ) );
+
+ layout->addWidget( logo, 0, AlignRight );
+
+ cbFullscreen = new QCheckBox( i18n("Fullscreen mode"), this, "boscreen" );
+
+ cbPreload = new QCheckBox( i18n("Preload next image"), this, "preload");
+ cbLastdir = new QCheckBox( i18n("Remember last folder"), this, "restart_lastdir");
+
+ QGridLayout *gridLayout = new QGridLayout( 2, 2 );
+ gridLayout->setSpacing( KDialog::spacingHint() );
+ QLabel *l0 = new QLabel( i18n("Background color:"), this );
+ colorButton = new KColorButton( this );
+
+ QLabel *l1 = new QLabel( i18n("Show only files with extension: "), this, "label" );
+ editFilter = new KLineEdit( this, "filteredit" );
+
+ gridLayout->addWidget( l0, 0, 0 );
+ gridLayout->addWidget( colorButton, 0, 1 );
+ gridLayout->addWidget( l1, 1, 0 );
+ gridLayout->addWidget( editFilter, 1, 1 );
+
+ layout->addWidget( cbFullscreen );
+ layout->addWidget( cbPreload );
+ layout->addWidget( cbLastdir );
+ layout->addLayout( gridLayout );
+
+ ////////////////////////////////////////////////////////////////////////
+
+ QVGroupBox *gbox2 = new QVGroupBox( i18n("Quality/Speed"),
+ this, "qualitybox" );
+ layout->addWidget( gbox2 );
+ layout->addStretch();
+
+ cbSmoothScale = new QCheckBox( i18n("Smooth scaling"), gbox2, "smoothscale" );
+ cbFastRender = new QCheckBox( i18n("Fast rendering"), gbox2, "fastrender" );
+ cbDither16bit = new QCheckBox( i18n("Dither in HiColor (15/16bit) modes"),
+ gbox2, "dither16bit" );
+
+ cbDither8bit = new QCheckBox( i18n("Dither in LowColor (<=8bit) modes"),
+ gbox2, "dither8bit" );
+
+ cbOwnPalette = new QCheckBox( i18n("Use own color palette"),
+ gbox2, "pal");
+ connect( cbOwnPalette, SIGNAL( clicked() ), this, SLOT( useOwnPalette() ) );
+
+ cbFastRemap = new QCheckBox( i18n("Fast palette remapping"), gbox2, "remap");
+
+ maxCacheSpinBox = new KIntNumInput( gbox2, "editmaxcache" );
+ maxCacheSpinBox->setLabel( i18n("Maximum cache size: "), AlignVCenter );
+ maxCacheSpinBox->setSuffix( i18n( " MB" ) );
+ maxCacheSpinBox->setSpecialValueText( i18n( "Unlimited" ) );
+ maxCacheSpinBox->setRange( 0, 400, 1 );
+
+ loadSettings( *kdata );
+ cbFullscreen->setFocus();
+}
+
+GeneralWidget::~GeneralWidget()
+{
+}
+
+void GeneralWidget::slotURLClicked( const QString & url )
+{
+ kapp->invokeBrowser( url );
+}
+
+void GeneralWidget::loadSettings( const KuickData& data )
+{
+ ImData *idata = data.idata;
+
+ colorButton->setColor( data.backgroundColor );
+ editFilter->setText( data.fileFilter );
+ cbFullscreen->setChecked( data.fullScreen );
+ cbPreload->setChecked( data.preloadImage );
+ cbLastdir->setChecked( data.startInLastDir );
+ cbFastRemap->setChecked( idata->fastRemap );
+ cbOwnPalette->setChecked( idata->ownPalette );
+ cbSmoothScale->setChecked( idata->smoothScale );
+ cbFastRender->setChecked( idata->fastRender );
+ cbDither16bit->setChecked( idata->dither16bit );
+ cbDither8bit->setChecked( idata->dither8bit );
+ maxCacheSpinBox->setValue( idata->maxCache / 1024 );
+
+ useOwnPalette(); // enable/disable remap-checkbox
+}
+
+void GeneralWidget::applySettings( KuickData& data)
+{
+ ImData *idata = data.idata;
+
+ data.backgroundColor = colorButton->color();
+ data.fileFilter = editFilter->text();
+ data.fullScreen = cbFullscreen->isChecked();
+ data.preloadImage = cbPreload->isChecked();
+ data.startInLastDir = cbLastdir->isChecked();
+
+ idata->smoothScale = cbSmoothScale->isChecked();
+ idata->fastRemap = cbFastRemap->isChecked();
+ idata->ownPalette = cbOwnPalette->isChecked();
+ idata->fastRender = cbFastRender->isChecked();
+ idata->dither16bit = cbDither16bit->isChecked();
+ idata->dither8bit = cbDither8bit->isChecked();
+
+ idata->maxCache = (uint) maxCacheSpinBox->value() * 1024;
+}
+
+void GeneralWidget::useOwnPalette()
+{
+ cbFastRemap->setEnabled( cbOwnPalette->isChecked() );
+}
+
+#include "generalwidget.moc"
diff --git a/kuickshow/src/generalwidget.h b/kuickshow/src/generalwidget.h
new file mode 100644
index 00000000..e39eef18
--- /dev/null
+++ b/kuickshow/src/generalwidget.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef GENERALWIDGET_H
+#define GENERALWIDGET_H
+
+#include <qwidget.h>
+
+#include "kuickdata.h"
+
+class QCheckBox;
+class KColorButton;
+class KLineEdit;
+class KIntNumInput;
+
+
+class GeneralWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ GeneralWidget( QWidget *parent, const char *name );
+ ~GeneralWidget();
+
+ void loadSettings( const KuickData& data );
+ void applySettings( KuickData& data );
+
+private:
+ QCheckBox *cbFullscreen, *cbActiveWindow, *cbPreload, *cbLastdir;
+ QCheckBox *cbSmoothScale, *cbFastRemap, *cbFastRender;
+ QCheckBox *cbDither16bit, *cbDither8bit, *cbOwnPalette;
+
+ KLineEdit *editFilter;
+ KIntNumInput *maxCacheSpinBox;
+
+ KIntNumInput *sbMaxWidth, *sbMaxHeight;
+ KIntNumInput *sbZoomFactor;
+
+ KColorButton *colorButton;
+
+private slots:
+ void useOwnPalette();
+ void slotURLClicked( const QString & );
+
+};
+
+#endif
diff --git a/kuickshow/src/hi16-app-kuickshow.png b/kuickshow/src/hi16-app-kuickshow.png
new file mode 100644
index 00000000..9f764485
--- /dev/null
+++ b/kuickshow/src/hi16-app-kuickshow.png
Binary files differ
diff --git a/kuickshow/src/hi22-app-kuickshow.png b/kuickshow/src/hi22-app-kuickshow.png
new file mode 100644
index 00000000..d8750f31
--- /dev/null
+++ b/kuickshow/src/hi22-app-kuickshow.png
Binary files differ
diff --git a/kuickshow/src/hi32-app-kuickshow.png b/kuickshow/src/hi32-app-kuickshow.png
new file mode 100644
index 00000000..e70e573e
--- /dev/null
+++ b/kuickshow/src/hi32-app-kuickshow.png
Binary files differ
diff --git a/kuickshow/src/imagewindow.cpp b/kuickshow/src/imagewindow.cpp
new file mode 100644
index 00000000..c63a3c67
--- /dev/null
+++ b/kuickshow/src/imagewindow.cpp
@@ -0,0 +1,1251 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2006 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+
+#include <qcheckbox.h>
+#include <qcursor.h>
+#include <qdrawutil.h>
+#include <qfileinfo.h>
+#include <qkeycode.h>
+#include <qpainter.h>
+#include <qpen.h>
+#include <qpopupmenu.h>
+
+#ifdef KDE_USE_FINAL
+#undef GrayScale
+#undef Color
+#endif
+#include <qrect.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#ifdef KDE_USE_FINAL
+#undef Unsorted
+#endif
+#include <kfiledialog.h>
+#include <kiconloader.h>
+#include <kimageeffect.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprinter.h>
+#include <kpropertiesdialog.h>
+#include <kstdaccel.h>
+#include <kstdguiitem.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <ktempfile.h>
+#include <kwin.h>
+#include <netwm.h>
+#include <kurldrag.h>
+#include <kio/netaccess.h>
+
+#include "filecache.h"
+#include "imagewindow.h"
+#include "kuick.h"
+#include "kuickdata.h"
+#include "kuickfile.h"
+#include "kuickimage.h"
+#include "printing.h"
+
+
+#undef GrayScale
+
+QCursor *ImageWindow::s_handCursor = 0L;
+
+ImageWindow::ImageWindow( ImData *_idata, ImlibData *id, QWidget *parent,
+ const char *name )
+ : ImlibWidget( _idata, id, parent, name )
+{
+ init();
+}
+
+ImageWindow::ImageWindow( ImData *_idata, QWidget *parent, const char *name )
+ : ImlibWidget( _idata, parent, name )
+{
+ init();
+}
+
+ImageWindow::~ImageWindow()
+{
+}
+
+
+void ImageWindow::init()
+{
+ setFocusPolicy( QWidget::StrongFocus );
+
+ KCursor::setAutoHideCursor( this, true, true );
+ KCursor::setHideCursorDelay( 1500 );
+
+ // give the image window a different WM_CLASS
+ XClassHint hint;
+ hint.res_name = const_cast<char*>( kapp->name() );
+ hint.res_class = const_cast<char*>( "ImageWindow" );
+ XSetClassHint( x11Display(), winId(), &hint );
+
+ viewerMenu = 0L;
+ gammaMenu = 0L;
+ brightnessMenu = 0L;
+ contrastMenu = 0L;
+
+
+ m_actions = new KActionCollection( this );
+
+ if ( !s_handCursor ) {
+ QString file = locate( "appdata", "pics/handcursor.png" );
+ if ( !file.isEmpty() )
+ s_handCursor = new QCursor( file );
+ else
+ s_handCursor = new QCursor( arrowCursor );
+ }
+
+ setupActions();
+ imageCache->setMaxImages( kdata->maxCachedImages );
+
+ transWidget = 0L;
+ myIsFullscreen = false;
+
+ xpos = 0, ypos = 0;
+ m_numHeads = ScreenCount( x11Display() );
+
+ setAcceptDrops( true );
+ setBackgroundColor( kdata->backgroundColor );
+
+ static QPixmap imageIcon = UserIcon( "imageviewer-medium" );
+ static QPixmap miniImageIcon = UserIcon( "imageviewer-small" );
+ KWin::setIcons( winId(), imageIcon, miniImageIcon );
+}
+
+void ImageWindow::updateActions()
+{
+ m_actions->readShortcutSettings();
+}
+
+void ImageWindow::setupActions()
+{
+ new KAction( i18n("Show Next Image"), KStdAccel::next(),
+ this, SLOT( slotRequestNext() ),
+ m_actions, "next_image" );
+ new KAction( i18n("Show Previous Image"), KStdAccel::prior(),
+ this, SLOT( slotRequestPrevious() ),
+ m_actions, "previous_image" );
+
+ new KAction( i18n("Delete Image"), SHIFT + Key_Delete,
+ this, SLOT( imageDelete() ),
+ m_actions, "delete_image" );
+ new KAction( i18n("Move Image to Trash"), Key_Delete,
+ this, SLOT( imageTrash() ),
+ m_actions, "trash_image" );
+
+ new KAction( i18n("Zoom In"), Key_Plus,
+ this, SLOT( zoomIn() ),
+ m_actions, "zoom_in" );
+ new KAction( i18n("Zoom Out"), Key_Minus,
+ this, SLOT( zoomOut() ),
+ m_actions, "zoom_out" );
+ new KAction( i18n("Restore Original Size"), Key_O,
+ this, SLOT( showImageOriginalSize() ),
+ m_actions, "original_size" );
+ new KAction( i18n("Maximize"), Key_M,
+ this, SLOT( maximize() ),
+ m_actions, "maximize" );
+
+ new KAction( i18n("Rotate 90 Degrees"), Key_9,
+ this, SLOT( rotate90() ),
+ m_actions, "rotate90" );
+ new KAction( i18n("Rotate 180 Degrees"), Key_8,
+ this, SLOT( rotate180() ),
+ m_actions, "rotate180" );
+ new KAction( i18n("Rotate 270 Degrees"), Key_7,
+ this, SLOT( rotate270() ),
+ m_actions, "rotate270" );
+
+ new KAction( i18n("Flip Horizontally"), Key_Asterisk,
+ this, SLOT( flipHoriz() ),
+ m_actions, "flip_horicontally" );
+ new KAction( i18n("Flip Vertically"), Key_Slash,
+ this, SLOT( flipVert() ),
+ m_actions, "flip_vertically" );
+
+ new KAction( i18n("Print Image..."), KStdAccel::print(),
+ this, SLOT( printImage() ),
+ m_actions, "print_image" );
+ KStdAction::saveAs( this, SLOT( saveImage() ),
+ m_actions, "save_image_as" );
+
+ KStdAction::close( this, SLOT( close() ),
+ m_actions, "close_image" );
+ // --------
+ new KAction( i18n("More Brightness"), Key_B,
+ this, SLOT( moreBrightness() ),
+ m_actions, "more_brightness" );
+ new KAction( i18n("Less Brightness"), SHIFT + Key_B,
+ this, SLOT( lessBrightness() ),
+ m_actions, "less_brightness" );
+ new KAction( i18n("More Contrast"), Key_C,
+ this, SLOT( moreContrast() ),
+ m_actions, "more_contrast" );
+ new KAction( i18n("Less Contrast"), SHIFT + Key_C,
+ this, SLOT( lessContrast() ),
+ m_actions, "less_contrast" );
+ new KAction( i18n("More Gamma"), Key_G,
+ this, SLOT( moreGamma() ),
+ m_actions, "more_gamma" );
+ new KAction( i18n("Less Gamma"), SHIFT + Key_G,
+ this, SLOT( lessGamma() ),
+ m_actions, "less_gamma" );
+
+ // --------
+ new KAction( i18n("Scroll Up"), Key_Up,
+ this, SLOT( scrollUp() ),
+ m_actions, "scroll_up" );
+ new KAction( i18n("Scroll Down"), Key_Down,
+ this, SLOT( scrollDown() ),
+ m_actions, "scroll_down" );
+ new KAction( i18n("Scroll Left"), Key_Left,
+ this, SLOT( scrollLeft() ),
+ m_actions, "scroll_left" );
+ new KAction( i18n("Scroll Right"), Key_Right,
+ this, SLOT( scrollRight() ),
+ m_actions, "scroll_right" );
+ // --------
+ new KAction( i18n("Pause Slideshow"), Key_P,
+ this, SLOT( pauseSlideShow() ),
+ m_actions, "kuick_slideshow_pause" );
+
+ KAction *fullscreenAction = KStdAction::fullScreen(this, SLOT( toggleFullscreen() ), m_actions, 0 );
+
+ KAction *reloadAction = new KAction( i18n("Reload Image"), KStdAccel::shortcut(KStdAccel::Reload),
+ this, SLOT( reload() ),
+ m_actions, "reload_image" );
+
+ new KAction( i18n("Properties"), ALT + Key_Return,
+ this, SLOT( slotProperties() ),
+ m_actions, "properties" );
+
+ m_actions->readShortcutSettings();
+
+ // Unfortunately there is no KAction::setShortcutDefault() :-/
+ // so add Key_Return as fullscreen shortcut _after_ readShortcutSettings()
+ addAlternativeShortcut(fullscreenAction, Key_Return);
+ addAlternativeShortcut(reloadAction, Key_Enter);
+}
+
+void ImageWindow::addAlternativeShortcut(KAction *action, int key)
+{
+ KShortcut cut( action->shortcut() );
+ if (cut == action->shortcutDefault()) {
+ cut.append(KKey(key));
+ action->setShortcut(cut);
+ }
+}
+
+void ImageWindow::showWindow()
+{
+ if ( myIsFullscreen )
+ showFullScreen();
+ else
+ showNormal();
+}
+
+void ImageWindow::setFullscreen( bool enable )
+{
+ xpos = 0; ypos = 0;
+
+// if ( enable && !myIsFullscreen ) { // set Fullscreen
+// showFullScreen();
+// }
+// else if ( !enable && myIsFullscreen ) { // go into window mode
+// showNormal();
+// }
+
+ myIsFullscreen = enable;
+// centerImage(); // ### really necessary (multihead!)
+}
+
+
+void ImageWindow::updateGeometry( int imWidth, int imHeight )
+{
+// qDebug("::updateGeometry: %i, %i", imWidth, imHeight);
+ // XMoveWindow( x11Display(), win, 0, 0 );
+ XResizeWindow( x11Display(), win, imWidth, imHeight );
+
+ if ( imWidth != width() || imHeight != height() ) {
+ if ( myIsFullscreen ) {
+ centerImage();
+ }
+ else { // window mode
+ // XMoveWindow( x11Display(), win, 0, 0 );
+ resizeOptimal( imWidth, imHeight ); // also centers the image
+ }
+ }
+ else { // image size == widget size
+ xpos = 0; ypos = 0;
+ XMoveWindow( x11Display(), win, 0, 0 );
+ }
+
+ updateCursor();
+
+ QString caption = i18n( "Filename (Imagewidth x Imageheight)",
+ "%3 (%1 x %2)" );
+ caption = caption.arg( m_kuim->originalWidth() ).
+ arg( m_kuim->originalHeight() ).arg( m_kuim->url().prettyURL() );
+ setCaption( kapp->makeStdCaption( caption ) );
+}
+
+
+void ImageWindow::centerImage()
+{
+ int w, h;
+ if ( myIsFullscreen )
+ {
+ QRect desktopRect = KGlobalSettings::desktopGeometry( this );
+ w = desktopRect.width();
+ h = desktopRect.height();
+ }
+ else
+ {
+ w = width();
+ h = height();
+ }
+
+ xpos = w/2 - imageWidth()/2;
+ ypos = h/2 - imageHeight()/2;
+
+ XMoveWindow( x11Display(), win, xpos, ypos );
+
+ // Modified by Evan for his Multi-Head (2 screens)
+ // This should center on the first head
+// if ( myIsFullscreen && m_numHeads > 1 && ((m_numHeads % 2) == 0) )
+// xpos = ((width()/m_numHeads) / 2) - imageWidth()/2;
+// else
+// xpos = width()/2 - imageWidth()/2;
+
+// ypos = height()/2 - imageHeight()/2;
+// XMoveWindow( x11Display(), win, xpos, ypos );
+}
+
+
+void ImageWindow::scrollImage( int x, int y, bool restrict )
+{
+ xpos += x;
+ ypos += y;
+
+ int cwlocal = width();
+ int chlocal = height();
+
+ int iw = imageWidth();
+ int ih = imageHeight();
+
+ if ( myIsFullscreen || width() > desktopWidth() )
+ cwlocal = desktopWidth();
+
+ if ( myIsFullscreen || height() > desktopHeight() )
+ chlocal = desktopHeight();
+
+ if ( restrict ) { // don't allow scrolling in certain cases
+ if ( x != 0 ) { // restrict x-movement
+ if ( iw <= cwlocal )
+ xpos -= x; // restore previous position
+ else if ( (xpos <= 0) && (xpos + iw <= cwlocal) )
+ xpos = cwlocal - iw;
+ else if ( (xpos + iw >= cwlocal) && xpos >= 0 )
+ xpos = 0;
+ }
+
+ if ( y != 0 ) { // restrict y-movement
+ if ( ih <= chlocal )
+ ypos -= y;
+ else if ( (ypos <= 0) && (ypos + ih <= chlocal) )
+ ypos = chlocal - ih;
+ else if ( (ypos + ih >= chlocal) && ypos >= 0 )
+ ypos = 0;
+ }
+ }
+
+ XMoveWindow( x11Display(), win, xpos, ypos );
+ XClearArea( x11Display(), win, xpos, ypos, iw, ih, false );
+ showImage();
+}
+
+
+// image loading performs:
+// ---------------------
+// loadImageInternal();
+// reset image mods
+// load image from disk / get from cache
+// loaded(); // apply modifications, scale
+// render pixmap
+//
+// updateWidget();
+// XUnmapWindow();
+// XSetWindowBackgroundPixmap()
+// resize window to fit image size, center image
+// XClearWindow(); // repaint
+// XMapWindow(), XSync();
+//
+bool ImageWindow::showNextImage( const KURL& url )
+{
+ KuickFile *file = FileCache::self()->getFile( url );
+ switch ( file->waitForDownload( this ) ) {
+ case KuickFile::ERROR:
+ {
+ QString tmp = i18n("Unable to download the image from %1.").arg(url.prettyURL());
+ emit sigImageError( file, tmp );
+ return false;
+ }
+ case KuickFile::CANCELED:
+ return false; // just abort, no error message
+ default:
+ break; // go on...
+ }
+
+ return showNextImage( file );
+}
+
+bool ImageWindow::showNextImage( KuickFile *file )
+{
+ if ( !loadImage( file ) ) {
+ QString tmp = i18n("Unable to load the image %1.\n"
+ "Perhaps the file format is unsupported or "
+ "your Imlib is not installed properly.").arg(file->url().prettyURL());
+ emit sigImageError( file, tmp );
+ return false;
+ }
+
+ else {
+ // updateWidget( true ); // already called from loadImage()
+ if ( !isVisible() )
+ showWindow();
+
+ showImage();
+ return true;
+ }
+}
+
+void ImageWindow::reload()
+{
+ showNextImage( currentFile() );
+}
+
+void ImageWindow::pauseSlideShow()
+{
+ emit pauseSlideShowSignal();
+}
+
+void ImageWindow::addBrightness( int factor )
+{
+ if ( factor == 0 )
+ return;
+
+ int oldValue = mod.brightness - ImlibOffset;
+ setBrightness( oldValue + (idata->brightnessFactor * (int) factor) );
+}
+
+void ImageWindow::addContrast( int factor )
+{
+ if ( factor == 0 )
+ return;
+
+ int oldValue = mod.contrast - ImlibOffset;
+ setContrast( oldValue + (idata->contrastFactor * (int) factor) );
+}
+
+void ImageWindow::addGamma( int factor )
+{
+ if ( factor == 0 )
+ return;
+
+ int oldValue = mod.gamma - ImlibOffset;
+ setGamma( oldValue + (idata->gammaFactor * (int) factor) );
+}
+
+
+////////////
+////
+// slots for keyboard/popupmenu actions
+
+
+void ImageWindow::scrollUp()
+{
+ scrollImage( 0, 20 * kdata->scrollSteps );
+}
+
+void ImageWindow::scrollDown()
+{
+ scrollImage( 0, - 20 * kdata->scrollSteps );
+}
+
+void ImageWindow::scrollLeft()
+{
+ scrollImage( 20 * kdata->scrollSteps, 0 );
+}
+
+void ImageWindow::scrollRight()
+{
+ scrollImage( - 20 * kdata->scrollSteps, 0 );
+}
+
+///
+
+void ImageWindow::zoomIn()
+{
+ zoomImage( kdata->zoomSteps );
+}
+
+void ImageWindow::zoomOut()
+{
+ Q_ASSERT( kdata->zoomSteps != 0 );
+ zoomImage( 1.0 / kdata->zoomSteps );
+}
+
+///
+
+void ImageWindow::moreBrightness()
+{
+ addBrightness( kdata->brightnessSteps );
+}
+
+void ImageWindow::moreContrast()
+{
+ addContrast( kdata->contrastSteps );
+}
+
+void ImageWindow::moreGamma()
+{
+ addGamma( kdata->gammaSteps );
+}
+
+
+void ImageWindow::lessBrightness()
+{
+ addBrightness( - kdata->brightnessSteps );
+}
+
+void ImageWindow::lessContrast()
+{
+ addContrast( - kdata->contrastSteps );
+}
+
+void ImageWindow::lessGamma()
+{
+ addGamma( - kdata->gammaSteps );
+}
+
+void ImageWindow::imageDelete()
+{
+ emit deleteImage(this);
+}
+
+void ImageWindow::imageTrash()
+{
+ emit trashImage(this);
+}
+
+///
+
+
+
+
+/////////////
+////
+// event handlers
+
+void ImageWindow::wheelEvent( QWheelEvent *e )
+{
+ e->accept();
+ static const int WHEEL_DELTA = 120;
+ int delta = e->delta();
+
+ if ( delta == 0 )
+ return;
+
+ int steps = delta / WHEEL_DELTA;
+ emit requestImage( this, -steps );
+}
+
+void ImageWindow::keyPressEvent( QKeyEvent *e )
+{
+ uint key = e->key();
+
+ if ( key == Key_Shift )
+ updateCursor( ZoomCursor );
+
+ if ( key == Key_Escape || KStdAccel::close().contains( KKey( e ) ) )
+ close( true );
+ else if ( KStdAccel::save().contains( KKey( e ) ) )
+ saveImage();
+
+ else {
+ e->ignore();
+ return;
+ }
+
+ e->accept();
+}
+
+void ImageWindow::keyReleaseEvent( QKeyEvent *e )
+{
+ if ( e->state() & ShiftButton ) { // Shift-key released
+ updateCursor();
+ if ( transWidget ) {
+ delete transWidget;
+ transWidget = 0L;
+ }
+ }
+
+ e->accept();
+}
+
+void ImageWindow::mousePressEvent( QMouseEvent *e )
+{
+ xmove = e->x(); // for moving the image with the mouse
+ ymove = e->y();
+
+ xzoom = xmove; // for zooming with the mouse
+ yzoom = ymove;
+
+ xposPress = xmove;
+ yposPress = ymove;
+
+ if ( e->button() == LeftButton ) {
+ if ( e->state() & ShiftButton )
+ updateCursor( ZoomCursor );
+ else
+ updateCursor( MoveCursor );
+ }
+
+ ImlibWidget::mousePressEvent( e );
+}
+
+void ImageWindow::contextMenuEvent( QContextMenuEvent *e )
+{
+ e->accept();
+
+ if ( !viewerMenu )
+ setPopupMenu();
+
+ viewerMenu->popup( e->globalPos() );
+}
+
+void ImageWindow::updateCursor( KuickCursor cursor )
+{
+ switch ( cursor )
+ {
+ case ZoomCursor:
+ setCursor( arrowCursor ); // need a magnify-cursor
+ break;
+ case MoveCursor:
+ setCursor( *s_handCursor );
+ break;
+ case DefaultCursor:
+ default:
+ if ( isCursorHidden() )
+ return;
+
+ if ( imageWidth() > width() || imageHeight() > height() )
+ setCursor( *s_handCursor );
+ else
+ setCursor( arrowCursor );
+ break;
+ }
+}
+
+void ImageWindow::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( !(e->state() & LeftButton) ) { // only handle LeftButton actions
+ return;
+ }
+
+ if ( e->state() & ShiftButton ) {
+
+ if ( !transWidget ) {
+ transWidget = new QWidget( this );
+ transWidget->setGeometry( 0, 0, width(), height() );
+ transWidget->setBackgroundMode( NoBackground );
+ }
+
+ transWidget->hide();
+ QPainter p( transWidget );
+ // really required?
+ p.eraseRect( transWidget->rect() );
+ transWidget->show();
+ qApp->processOneEvent();
+
+ int width = e->x() - xposPress;
+ int height = e->y() - yposPress;
+
+ if ( width < 0 ) {
+ width = abs( width );
+ xzoom = e->x();
+ }
+
+ if ( height < 0 ) {
+ height = abs( height );
+ yzoom = e->y();
+ }
+
+ QPen pen( Qt::white, 1, DashLine );
+ p.setPen( pen ); // for drawing white dashed line
+ p.drawRect( xzoom, yzoom, width, height );
+ p.setPen( DotLine ); // defaults to black dotted line pen
+ p.drawRect( xzoom, yzoom, width, height );
+ p.flush();
+ }
+
+ else { // move the image
+ // scrolling with mouse
+ uint xtmp = e->x();
+ uint ytmp = e->y();
+ scrollImage( xtmp - xmove, ytmp - ymove );
+ xmove = xtmp;
+ ymove = ytmp;
+ }
+}
+
+void ImageWindow::mouseReleaseEvent( QMouseEvent *e )
+{
+ updateCursor();
+
+ if ( transWidget ) {
+ // destroy the transparent widget, used for showing the rectangle (zoom)
+ delete transWidget;
+ transWidget = 0L;
+ }
+
+ // only proceed if shift-Key is still pressed
+ if ( !(e->button() == LeftButton && e->state() & ShiftButton) )
+ return;
+
+ int neww, newh, topX, topY, botX, botY;
+ float factor, factorx, factory;
+
+ // zoom into the selected area
+ uint x = e->x();
+ uint y = e->y();
+
+ if ( xposPress == x || yposPress == y )
+ return;
+
+ if ( xposPress > x ) {
+ topX = x;
+ botX = xposPress;
+ }
+ else {
+ topX = xposPress;
+ botX = x;
+ }
+
+ if ( yposPress > y ) {
+ topY = y;
+ botY = yposPress;
+ }
+ else {
+ topY = yposPress;
+ botY = y;
+ }
+
+ neww = botX - topX;
+ newh = botY - topY;
+
+ factorx = ((float) width() / (float) neww);
+ factory = ((float) height() / (float) newh);
+
+ if ( factorx < factory ) // use the smaller factor
+ factor = factorx;
+ else factor = factory;
+
+ uint w = 0; // shut up compiler!
+ uint h = 0;
+ w = (uint) ( factor * (float) imageWidth() );
+ h = (uint) ( factor * (float) imageHeight() );
+
+ if ( !canZoomTo( w, h ) )
+ return;
+
+ int xtmp = - (int) (factor * abs(xpos - topX) );
+ int ytmp = - (int) (factor * abs(ypos - topY) );
+
+ // if image has different ratio (width()/height()), center it
+ int xcenter = (width() - (int) (neww * factor)) / 2;
+ int ycenter = (height() - (int) (newh * factor)) / 2;
+
+ xtmp += xcenter;
+ ytmp += ycenter;
+
+ m_kuim->resize( w, h, idata->smoothScale ? KuickImage::SMOOTH : KuickImage::FAST );
+ XResizeWindow( x11Display(), win, w, h );
+ updateWidget( false );
+
+ xpos = xtmp; ypos = ytmp;
+
+ XMoveWindow( x11Display(), win, xpos, ypos );
+ scrollImage( 1, 1, true ); // unrestricted scrolling
+}
+
+
+void ImageWindow::focusInEvent( QFocusEvent *ev )
+{
+ ImlibWidget::focusInEvent( ev );
+ emit sigFocusWindow( this );
+}
+
+
+void ImageWindow::resizeEvent( QResizeEvent *e )
+{
+ ImlibWidget::resizeEvent( e );
+
+ centerImage();
+ updateCursor();
+}
+
+
+void ImageWindow::dragEnterEvent( QDragEnterEvent *e )
+{
+ // if ( e->provides( "image/*" ) ) // can't do this right now with Imlib
+ if ( e->provides( "text/uri-list" ) )
+ e->accept();
+ else
+ e->ignore();
+}
+
+
+void ImageWindow::dropEvent( QDropEvent *e )
+{
+ // FIXME - only preliminary drop-support for now
+ KURL::List list;
+ if ( KURLDrag::decode( e, list ) && !list.isEmpty()) {
+ QString tmpFile;
+ const KURL &url = list.first();
+ if (KIO::NetAccess::download( url, tmpFile, this ) )
+ {
+ loadImage( tmpFile );
+ KIO::NetAccess::removeTempFile( tmpFile );
+ }
+ updateWidget();
+ e->accept();
+ }
+ else
+ e->ignore();
+}
+
+
+////////////////////
+/////////
+// misc stuff
+
+void ImageWindow::setPopupMenu()
+{
+ viewerMenu = new QPopupMenu( this );
+
+ m_actions->action("next_image")->plug( viewerMenu );
+ m_actions->action("previous_image")->plug( viewerMenu );
+ viewerMenu->insertSeparator();
+
+ brightnessMenu = new QPopupMenu( viewerMenu );
+ m_actions->action("more_brightness")->plug(brightnessMenu);
+ m_actions->action("less_brightness")->plug(brightnessMenu);
+
+ contrastMenu = new QPopupMenu( viewerMenu );
+ m_actions->action("more_contrast")->plug(contrastMenu);
+ m_actions->action("less_contrast")->plug(contrastMenu);
+
+ gammaMenu = new QPopupMenu( viewerMenu );
+ m_actions->action("more_gamma")->plug(gammaMenu);
+ m_actions->action("less_gamma")->plug(gammaMenu);
+
+ m_actions->action("zoom_in")->plug( viewerMenu );
+ m_actions->action("zoom_out")->plug( viewerMenu );
+ m_actions->action("original_size")->plug( viewerMenu );
+ m_actions->action("maximize")->plug( viewerMenu );
+
+ viewerMenu->insertSeparator();
+ m_actions->action("rotate90")->plug( viewerMenu );
+ m_actions->action("rotate180")->plug( viewerMenu );
+ m_actions->action("rotate270")->plug( viewerMenu );
+
+ viewerMenu->insertSeparator();
+ m_actions->action("flip_vertically")->plug( viewerMenu );
+ m_actions->action("flip_horicontally")->plug( viewerMenu );
+ viewerMenu->insertSeparator();
+ viewerMenu->insertItem( i18n("Brightness"), brightnessMenu );
+ viewerMenu->insertItem( i18n("Contrast"), contrastMenu );
+ viewerMenu->insertItem( i18n("Gamma"), gammaMenu );
+ viewerMenu->insertSeparator();
+
+ m_actions->action("delete_image")->plug( viewerMenu );
+ m_actions->action("print_image")->plug( viewerMenu );
+ m_actions->action("save_image_as")->plug( viewerMenu );
+ m_actions->action("properties")->plug( viewerMenu );
+
+ viewerMenu->insertSeparator();
+ m_actions->action("close_image")->plug( viewerMenu );
+}
+
+void ImageWindow::printImage()
+{
+ if ( !m_kuim )
+ return;
+
+ if ( !Printing::printImage( *this, this ) )
+ {
+ KMessageBox::sorry( this, i18n("Unable to print the image."),
+ i18n("Printing Failed") );
+ }
+}
+
+void ImageWindow::saveImage()
+{
+ if ( !m_kuim )
+ return;
+
+ KuickData tmp;
+ QCheckBox *keepSize = new QCheckBox( i18n("Keep original image size"), 0L);
+ keepSize->setChecked( true );
+ KFileDialog dlg( m_saveDirectory, tmp.fileFilter, this, "filedialog", true
+#if KDE_VERSION >= 310
+ ,keepSize
+#endif
+ );
+
+ QString selection = m_saveDirectory.isEmpty() ?
+ m_kuim->url().url() :
+ m_kuim->url().fileName();
+ dlg.setOperationMode( KFileDialog::Saving );
+ dlg.setMode( KFile::File );
+ dlg.setSelection( selection );
+ dlg.setCaption( i18n("Save As") );
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ KURL url = dlg.selectedURL();
+ if ( url.isValid() )
+ {
+ if ( !saveImage( url, keepSize->isChecked() ) )
+ {
+ QString tmp = i18n("Couldn't save the file.\n"
+ "Perhaps the disk is full, or you don't "
+ "have write permission to the file.");
+ KMessageBox::sorry( this, tmp, i18n("File Saving Failed"));
+ }
+ else
+ {
+ if ( url.equals( m_kuim->url() )) {
+ Imlib_apply_modifiers_to_rgb( id, m_kuim->imlibImage() );
+ }
+ }
+ }
+ }
+
+ QString lastDir = dlg.baseURL().path(+1);
+ if ( lastDir != m_saveDirectory )
+ m_saveDirectory = lastDir;
+
+#if KDE_VERSION < 310
+ delete keepSize;
+#endif
+}
+
+bool ImageWindow::saveImage( const KURL& dest, bool keepOriginalSize )
+{
+ int w = keepOriginalSize ? m_kuim->originalWidth() : m_kuim->width();
+ int h = keepOriginalSize ? m_kuim->originalHeight() : m_kuim->height();
+ if ( m_kuim->absRotation() == ROT_90 || m_kuim->absRotation() == ROT_270 )
+ qSwap( w, h );
+
+ ImlibImage *saveIm = Imlib_clone_scaled_image( id, m_kuim->imlibImage(),
+ w, h );
+ bool success = false;
+
+ QString saveFile;
+ if ( dest.isLocalFile() )
+ saveFile = dest.path();
+ else
+ {
+ QString extension = QFileInfo( dest.fileName() ).extension();
+ if ( !extension.isEmpty() )
+ extension.prepend( '.' );
+
+ KTempFile tmpFile( QString::null, extension );
+ if ( tmpFile.status() != 0 )
+ return false;
+ tmpFile.close();
+ if ( tmpFile.status() != 0 )
+ return false;
+ saveFile = tmpFile.name();
+ }
+
+ if ( saveIm )
+ {
+ Imlib_apply_modifiers_to_rgb( id, saveIm );
+ success = Imlib_save_image( id, saveIm,
+ QFile::encodeName( saveFile ).data(),
+ NULL );
+ if ( success && !dest.isLocalFile() )
+ {
+ if ( isFullscreen() )
+ toggleFullscreen(); // otherwise upload window would block us invisibly
+ success = KIO::NetAccess::upload( saveFile, dest, const_cast<ImageWindow*>( this ) );
+ }
+
+ Imlib_kill_image( id, saveIm );
+ }
+
+ return success;
+}
+
+void ImageWindow::toggleFullscreen()
+{
+ setFullscreen( !myIsFullscreen );
+ showWindow();
+}
+
+void ImageWindow::loaded( KuickImage *kuim )
+{
+ if ( !kdata->isModsEnabled ) {
+ // ### BUG: should be "restorePreviousSize"
+ kuim->restoreOriginalSize();
+ }
+ else
+ {
+ autoRotate( kuim );
+ autoScale( kuim );
+ }
+}
+
+// upscale/downscale depending on configuration
+void ImageWindow::autoScale( KuickImage *kuim )
+{
+ int newW = kuim->originalWidth();
+ int newH = kuim->originalHeight();
+
+ QSize s = maxImageSize();
+ int mw = s.width();
+ int mh = s.height();
+
+ if ( kuim->absRotation() == ROT_90 || kuim->absRotation() == ROT_270 )
+ qSwap( newW, newH );
+
+ bool doIt = false;
+
+ if ( kdata->upScale )
+ {
+ if ( (newW < mw) && (newH < mh) )
+ {
+ doIt = true;
+
+ float ratio1, ratio2;
+ int maxUpScale = kdata->maxUpScale;
+
+ ratio1 = (float) mw / (float) newW;
+ ratio2 = (float) mh / (float) newH;
+ ratio1 = (ratio1 < ratio2) ? ratio1 : ratio2;
+ if ( maxUpScale > 0 )
+ ratio1 = (ratio1 < maxUpScale) ? ratio1 : maxUpScale;
+ newH = (int) ((float) newH * ratio1);
+ newW = (int) ((float) newW * ratio1);
+ }
+ }
+
+ if ( kdata->downScale )
+ {
+ // eventually set width and height to the best/max possible screen size
+ if ( (newW > mw) || (newH > mh) )
+ {
+ doIt = true;
+
+ if ( newW > mw )
+ {
+ float ratio = (float) newW / (float) newH;
+ newW = mw;
+ newH = (int) ((float) newW / ratio);
+ }
+
+ // the previously calculated "h" might be larger than screen
+ if ( newH > mh ) {
+ float ratio = (float) newW / (float) newH;
+ newH = mh;
+ newW = (int) ((float) newH * ratio);
+ }
+ }
+ }
+
+ if ( doIt )
+ kuim->resize( newW, newH, idata->smoothScale ? KuickImage::SMOOTH : KuickImage::FAST );
+}
+
+// only called when kdata->isModsEnabled is true
+bool ImageWindow::autoRotate( KuickImage *kuim )
+{
+ if ( kdata->autoRotation && ImlibWidget::autoRotate( kuim ) )
+ return true;
+
+ else // rotation by metadata not available or not configured
+ {
+ // only apply default mods to newly loaded images
+
+ // ### actually we should have a dirty flag ("neverManuallyFlipped")
+ if ( kuim->flipMode() == FlipNone )
+ {
+ int flipMode = 0;
+ if ( kdata->flipVertically )
+ flipMode |= FlipVertical;
+ if ( kdata->flipHorizontally )
+ flipMode |= FlipHorizontal;
+
+ kuim->flipAbs( flipMode );
+ }
+
+ if ( kuim->absRotation() == ROT_0 )
+ kuim->rotateAbs( kdata->rotation );
+ }
+
+ return true;
+}
+
+int ImageWindow::desktopWidth( bool totalScreen ) const
+{
+ if ( myIsFullscreen || totalScreen )
+ {
+ return KGlobalSettings::desktopGeometry(topLevelWidget()).width();
+ } else
+ return Kuick::workArea().width();
+}
+
+
+int ImageWindow::desktopHeight( bool totalScreen ) const
+{
+ if ( myIsFullscreen || totalScreen ) {
+ return KGlobalSettings::desktopGeometry(topLevelWidget()).height();
+ } else {
+ return Kuick::workArea().height();
+ }
+}
+
+QSize ImageWindow::maxImageSize() const
+{
+ if ( myIsFullscreen ) {
+ return KGlobalSettings::desktopGeometry(topLevelWidget()).size();
+ }
+ else {
+ return Kuick::workArea().size() - Kuick::frameSize( winId() );
+ }
+}
+
+void ImageWindow::resizeOptimal( int w, int h )
+{
+ QSize s = maxImageSize();
+ int mw = s.width();
+ int mh = s.height();
+ int neww = (w >= mw) ? mw : w;
+ int newh = (h >= mh) ? mh : h;
+
+ if ( neww == width() && newh == height() )
+ centerImage();
+ else
+ resize( neww, newh ); // also centers the image
+}
+
+void ImageWindow::maximize()
+{
+ if ( !m_kuim )
+ return;
+
+ bool oldUpscale = kdata->upScale;
+ bool oldDownscale = kdata->downScale;
+
+ kdata->upScale = true;
+ kdata->downScale = true;
+
+ autoScale( m_kuim );
+ updateWidget( true );
+
+ if ( !myIsFullscreen )
+ resizeOptimal( imageWidth(), imageHeight() );
+
+ kdata->upScale = oldUpscale;
+ kdata->downScale = oldDownscale;
+}
+
+bool ImageWindow::canZoomTo( int newWidth, int newHeight )
+{
+ if ( !ImlibWidget::canZoomTo( newWidth, newHeight ) )
+ return false;
+
+ QSize desktopSize = KGlobalSettings::desktopGeometry(topLevelWidget()).size();
+
+ int desktopArea = desktopSize.width() * desktopSize.height();
+ int imageArea = newWidth * newHeight;
+
+ if ( imageArea > desktopArea * kdata->maxZoomFactor )
+ {
+ return KMessageBox::warningContinueCancel(
+ this,
+ i18n("You are about to view a very large image (%1 x %2 pixels), which can be very resource-consuming and even make your computer hang.\nDo you want to continue?")
+ .arg( newWidth ).arg( newHeight ),
+ QString::null,
+ KStdGuiItem::cont(),
+ "ImageWindow_confirm_very_large_window"
+ ) == KMessageBox::Continue;
+ }
+
+ return true;
+}
+
+void ImageWindow::rotated( KuickImage *kuim, int rotation )
+{
+ if ( !m_kuim )
+ return;
+
+ ImlibWidget::rotated( kuim, rotation );
+
+ if ( rotation == ROT_90 || rotation == ROT_270 )
+ autoScale( kuim ); // ### BUG: only autoScale when configured!
+}
+
+void ImageWindow::slotProperties()
+{
+ (void) new KPropertiesDialog( currentFile()->url(), this, "props dialog", true );
+}
+
+void ImageWindow::setBusyCursor()
+{
+ // avoid busy cursor in fullscreen mode
+ if ( !isFullscreen() )
+ ImlibWidget::setBusyCursor();
+}
+
+void ImageWindow::restoreCursor()
+{
+ // avoid busy cursor in fullscreen mode
+ if ( !isFullscreen() )
+ ImlibWidget::restoreCursor();
+}
+
+bool ImageWindow::isCursorHidden() const
+{
+ return cursor().shape() == Qt::BlankCursor;
+}
+
+#include "imagewindow.moc"
diff --git a/kuickshow/src/imagewindow.h b/kuickshow/src/imagewindow.h
new file mode 100644
index 00000000..4a823a0a
--- /dev/null
+++ b/kuickshow/src/imagewindow.h
@@ -0,0 +1,176 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef IMAGEWINDOW_H
+#define IMAGEWINDOW_H
+
+#include <qevent.h>
+
+#include <kaction.h>
+#include <kurl.h>
+
+#include "imlibwidget.h"
+
+class QCursor;
+class QPopupMenu;
+class QRect;
+class QString;
+class QTimer;
+class QWidget;
+
+class KuickFile;
+
+class ImageWindow : public ImlibWidget
+{
+ Q_OBJECT
+
+public:
+ ImageWindow( ImData *_idata, ImlibData *id, QWidget *parent=0,
+ const char *name=0 );
+ ImageWindow( ImData *_idata=0, QWidget *parent=0, const char *name=0 );
+
+ bool showNextImage( KuickFile * file );
+ bool showNextImage( const KURL& url );
+ void scrollImage( int, int, bool restrict=true );
+ void setFullscreen( bool );
+ bool isFullscreen() const { return myIsFullscreen; }
+
+ void addBrightness( int );
+ void addContrast( int );
+ void addGamma( int );
+
+ void updateActions();
+
+ KActionCollection * actionCollection() const { return m_actions; }
+
+ /**
+ * Resizes image to @p w, @p h, but takes into account the workarea, so
+ * it won't ever get a bigger size than the workarea.
+ */
+ void resizeOptimal( int w, int h );
+ void autoScale( KuickImage *kuim );
+ virtual bool autoRotate( KuickImage *kuim );
+
+ bool saveImage( const KURL& dest, bool keepOriginalSize );
+
+public slots:
+ void zoomIn();
+ void zoomOut();
+ void moreBrightness();
+ void lessBrightness();
+ void moreContrast();
+ void lessContrast();
+ void moreGamma();
+ void lessGamma();
+ void scrollUp();
+ void scrollDown();
+ void scrollLeft();
+ void scrollRight();
+ void printImage();
+ void toggleFullscreen();
+ void maximize();
+ void imageDelete();
+ void imageTrash();
+
+signals:
+ void sigFocusWindow( ImageWindow * );
+ // go advance images back/forth
+ void requestImage( ImageWindow *, int advance );
+ void deleteImage(ImageWindow *viewer);
+ void trashImage(ImageWindow *viewer);
+
+protected:
+ ~ImageWindow(); // deletes itself, just call close( true );
+
+ void init();
+ void centerImage();
+ void addAlternativeShortcut( KAction *action, int key );
+ virtual void updateGeometry( int imWidth, int imHeight );
+ virtual void loaded( KuickImage * );
+ virtual bool canZoomTo( int newWidth, int newHeight );
+ virtual void rotated( KuickImage *kuim, int rotation );
+
+ virtual void wheelEvent( QWheelEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
+ virtual void keyReleaseEvent( QKeyEvent * );
+ virtual void mousePressEvent( QMouseEvent * );
+ virtual void mouseReleaseEvent( QMouseEvent * );
+ virtual void mouseMoveEvent( QMouseEvent * );
+ virtual void focusInEvent( QFocusEvent * );
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void dragEnterEvent( QDragEnterEvent * );
+ virtual void dropEvent( QDropEvent * );
+ virtual void contextMenuEvent( QContextMenuEvent * );
+
+ void showWindow();
+ enum KuickCursor { DefaultCursor = 0, ZoomCursor, MoveCursor };
+ void updateCursor( KuickCursor cursor = DefaultCursor );
+
+ // popupmenu entries
+ uint itemViewerZoomMax, itemViewerZoomOrig, itemViewerZoomIn;
+ uint itemViewerZoomOut, itemViewerFlipH, itemViewerProps;
+ uint itemRotate90, itemRotate180, itemRotate270;
+ uint itemViewerFlipV, itemViewerPrint;
+ uint itemViewerSave, itemViewerClose;
+ uint itemBrightnessPlus, itemBrightnessMinus;
+ uint itemContrastPlus, itemContrastMinus;
+ uint itemGammaPlus, itemGammaMinus;
+
+
+ uint xmove, ymove; // used for scrolling the image with the mouse
+ int xpos, ypos; // top left corner of the image
+ int xzoom, yzoom; // used for zooming the image with the mouse
+ uint xposPress, yposPress;
+
+
+ QPopupMenu *viewerMenu, *gammaMenu, *brightnessMenu, *contrastMenu;
+ QWidget *transWidget;
+
+
+protected slots:
+ void saveImage();
+ void slotRequestNext() { emit requestImage( this, +1 ); }
+ void slotRequestPrevious() { emit requestImage( this, -1 ); }
+ void reload();
+ void slotProperties();
+ void pauseSlideShow();
+ virtual void setBusyCursor();
+ virtual void restoreCursor();
+
+signals:
+ void pauseSlideShowSignal();
+
+private:
+ int desktopWidth( bool totalScreen = false ) const;
+ int desktopHeight( bool totalScreen = false ) const;
+ QSize maxImageSize() const;
+ void setupActions();
+ void setPopupMenu();
+ bool isCursorHidden() const;
+
+ bool myIsFullscreen;
+ int m_numHeads;
+ QString m_saveDirectory;
+
+ KActionCollection *m_actions;
+
+ static QCursor * s_handCursor;
+};
+
+
+#endif // IMAGEWINDOW_H
diff --git a/kuickshow/src/imdata.cpp b/kuickshow/src/imdata.cpp
new file mode 100644
index 00000000..a2e89283
--- /dev/null
+++ b/kuickshow/src/imdata.cpp
@@ -0,0 +1,92 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2001 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+
+#include <kconfig.h>
+
+#include "imdata.h"
+
+
+ImData::ImData()
+{
+ ownPalette = true;
+ fastRemap = true;
+ fastRender = true;
+ dither16bit = false;
+ dither8bit = true;
+ smoothScale = false;
+ maxCache = 10240;
+
+ gamma = 0;
+ brightness = 0;
+ contrast = 0;
+
+ gammaFactor = 10;
+ brightnessFactor = 10;
+ contrastFactor = 10;
+}
+
+
+void ImData::load( KConfig *kc )
+{
+ ImData def;
+
+ kc->setGroup( "ImlibConfiguration" );
+
+ ownPalette = kc->readBoolEntry( "UseOwnPalette", def.ownPalette );
+ fastRemap = kc->readBoolEntry( "FastRemapping", def.fastRemap );
+ fastRender = kc->readBoolEntry( "FastRendering", def.fastRender );
+ dither16bit = kc->readBoolEntry( "Dither16Bit", def.dither16bit );
+ dither8bit = kc->readBoolEntry( "Dither8Bit", def.dither8bit );
+ smoothScale = kc->readBoolEntry( "SmoothScaling", def.smoothScale );
+
+ maxCache = kc->readNumEntry( "MaxCacheSize", 10240 );
+
+ gamma = kc->readNumEntry( "GammaDefault", 0 );
+ brightness = kc->readNumEntry( "BrightnessDefault", 0 );
+ contrast = kc->readNumEntry( "ContrastDefault", 0 );
+
+ gammaFactor = abs( kc->readNumEntry( "GammaFactor", 10 ) );
+ brightnessFactor = abs( kc->readNumEntry( "BrightnessFactor", 10 ) );
+ contrastFactor = abs( kc->readNumEntry( "ContrastFactor", 10 ) );
+}
+
+
+void ImData::save( KConfig *kc )
+{
+ kc->setGroup( "ImlibConfiguration" );
+
+ kc->writeEntry( "UseOwnPalette", ownPalette );
+ kc->writeEntry( "FastRemapping", fastRemap );
+ kc->writeEntry( "FastRendering", fastRender );
+ kc->writeEntry( "Dither16Bit", dither16bit );
+ kc->writeEntry( "Dither8Bit", dither8bit );
+ kc->writeEntry( "MaxCacheSize", maxCache );
+ kc->writeEntry( "SmoothScaling", smoothScale );
+
+ kc->writeEntry( "GammaDefault", gamma );
+ kc->writeEntry( "BrightnessDefault", brightness );
+ kc->writeEntry( "ContrastDefault", contrast );
+
+ kc->writeEntry( "GammaFactor", gammaFactor );
+ kc->writeEntry( "BrightnessFactor", brightnessFactor );
+ kc->writeEntry( "ContrastFactor", contrastFactor );
+
+ kc->sync();
+}
diff --git a/kuickshow/src/imdata.h b/kuickshow/src/imdata.h
new file mode 100644
index 00000000..c6dc6a5c
--- /dev/null
+++ b/kuickshow/src/imdata.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998,1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef IMBLIBCONFIG_H
+#define IMBLIBCONFIG_H
+
+class KConfig;
+class ImData
+{
+public:
+ ImData();
+ ~ImData() {};
+
+ void load( KConfig *kc );
+ void save( KConfig *kc );
+
+ // new stuff..........
+
+ int gamma;
+ int brightness;
+ int contrast;
+
+ // -----------------------
+
+ bool ownPalette :1;
+ bool fastRemap :1;
+ bool fastRender :1;
+ bool dither16bit :1;
+ bool dither8bit :1;
+ bool smoothScale :1;
+
+
+ uint gammaFactor;
+ uint brightnessFactor;
+ uint contrastFactor;
+
+ uint maxCache;
+
+};
+
+
+#endif
diff --git a/kuickshow/src/imlibwidget.cpp b/kuickshow/src/imlibwidget.cpp
new file mode 100644
index 00000000..5b5cb84b
--- /dev/null
+++ b/kuickshow/src/imlibwidget.cpp
@@ -0,0 +1,715 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kuickdata.h"
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <qcolor.h>
+#include <qfile.h>
+#include <qglobal.h>
+#include <qimage.h>
+#include <qobject.h>
+#include <qpalette.h>
+
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kfilemetainfo.h>
+#include <kimageio.h>
+
+#include "filecache.h"
+#include "kuickfile.h"
+#include "kuickimage.h"
+#include "imlibwidget.h"
+
+const int ImlibWidget::ImlibOffset = 256;
+
+ImlibWidget::ImlibWidget( ImData *_idata, QWidget *parent, const char *name ) :
+ QWidget( parent, name, WDestructiveClose )
+{
+ idata = _idata;
+ deleteImData = false;
+ deleteImlibData = true;
+
+ if ( !idata ) { // if no imlib configuration was given, create one ourself
+ idata = new ImData;
+ deleteImData = true;
+ }
+
+ ImlibInitParams par;
+
+ // PARAMS_PALETTEOVERRIDE taken out because of segfault in imlib :o(
+ par.flags = ( PARAMS_REMAP | PARAMS_VISUALID |
+ PARAMS_FASTRENDER | PARAMS_HIQUALITY | PARAMS_DITHER |
+ PARAMS_IMAGECACHESIZE | PARAMS_PIXMAPCACHESIZE );
+
+ Visual* defaultvis = DefaultVisual(x11Display(), x11Screen());
+
+ par.paletteoverride = idata->ownPalette ? 1 : 0;
+ par.remap = idata->fastRemap ? 1 : 0;
+ par.fastrender = idata->fastRender ? 1 : 0;
+ par.hiquality = idata->dither16bit ? 1 : 0;
+ par.dither = idata->dither8bit ? 1 : 0;
+ par.visualid = defaultvis->visualid;
+ uint maxcache = idata->maxCache;
+
+ // 0 == no cache
+ par.imagecachesize = maxcache * 1024;
+ par.pixmapcachesize = maxcache * 1024;
+
+ id = Imlib_init_with_params( x11Display(), &par );
+
+ init();
+}
+
+
+ImlibWidget::ImlibWidget( ImData *_idata, ImlibData *_id, QWidget *parent,
+ const char *name )
+ : QWidget( parent, name, WDestructiveClose )
+{
+ id = _id;
+ idata = _idata;
+ deleteImData = false;
+ deleteImlibData = false;
+
+ if ( !idata ) {
+ idata = new ImData;
+ deleteImData = true;
+ }
+
+ init();
+}
+
+
+void ImlibWidget::init()
+{
+ int w = 1; // > 0 for XCreateWindow
+ int h = 1;
+ myBackgroundColor = Qt::black;
+ m_kuim = 0L;
+ m_kuickFile = 0L;
+
+ if ( !id )
+ qFatal("ImlibWidget: Imlib not initialized, aborting.");
+
+ setAutoRender( true );
+
+ setPalette( QPalette( myBackgroundColor ));
+ setBackgroundMode( PaletteBackground );
+
+ imageCache = new ImageCache( id, 4 ); // cache 4 images (FIXME?)
+ connect( imageCache, SIGNAL( sigBusy() ), SLOT( setBusyCursor() ));
+ connect( imageCache, SIGNAL( sigIdle() ), SLOT( restoreCursor() ));
+
+ win = XCreateSimpleWindow(x11Display(), winId(), 0,0,w,h,0,0,0);
+}
+
+ImlibWidget::~ImlibWidget()
+{
+ delete imageCache;
+ if ( deleteImlibData && id ) free ( id );
+ if ( win ) XDestroyWindow( x11Display(), win );
+ if ( deleteImData ) delete idata;
+}
+
+KURL ImlibWidget::url() const
+{
+ if ( m_kuickFile )
+ return m_kuickFile->url();
+
+ return KURL();
+}
+
+KuickFile * ImlibWidget::currentFile() const
+{
+ return m_kuickFile;
+}
+
+// tries to load "file" and returns the according KuickImage *
+// or 0L if unsuccessful
+// Note that the given file MUST already be downloaded prior to calling this function
+KuickImage * ImlibWidget::loadImageInternal( KuickFile * file )
+{
+ assert( file->isAvailable() );
+
+ // apply default image modifications
+ mod.brightness = idata->brightness + ImlibOffset;
+ mod.contrast = idata->contrast + ImlibOffset;
+ mod.gamma = idata->gamma + ImlibOffset;
+
+ KuickImage *kuim = imageCache->getKuimage( file, mod );
+ if ( !kuim ) {// couldn't load file, maybe corrupt or wrong format
+ kdWarning() << "ImlibWidget: can't load image " << file->url().prettyURL() << endl;
+ return 0L;
+ }
+
+ loaded( kuim ); // maybe upscale/downscale/rotate in subclasses
+
+ return kuim;
+}
+
+// overridden in subclass
+void ImlibWidget::loaded( KuickImage * )
+{
+}
+
+bool ImlibWidget::loadImage( const KURL& url )
+{
+ return loadImage( FileCache::self()->getFile( url ));
+}
+
+bool ImlibWidget::loadImage( KuickFile * file )
+{
+ if ( file->waitForDownload( this ) != KuickFile::OK)
+ return false;
+
+ KuickImage *kuim = loadImageInternal( file );
+ // FIXME - check everywhere if we have a kuim or not!
+
+ if ( kuim ) {
+ m_kuim = kuim;
+ autoUpdate( true ); // -> updateWidget() -> updateGeometry()
+ m_kuickFile = file;
+ return true;
+ }
+
+ return false;
+}
+
+
+bool ImlibWidget::cacheImage( const KURL& url )
+{
+// qDebug("cache image: %s", url.url().latin1());
+ KuickFile *file = FileCache::self()->getFile( url );
+ if ( file->isAvailable() )
+ return cacheImage( file );
+ else {
+ if ( !file->download() ) {
+ return false;
+ }
+ connect( file, SIGNAL( downloaded( KuickFile * )), SLOT( cacheImage( KuickFile * )) );
+ return true; // optimistic
+ }
+}
+
+bool ImlibWidget::cacheImage( KuickFile * file )
+{
+// qDebug("cache image: %s", file->url().url().latin1());
+ KuickImage *kuim = loadImageInternal( file );
+ if ( kuim ) {
+ kuim->renderPixmap();
+ return true;
+ }
+ return false;
+}
+
+
+void ImlibWidget::showImage()
+{
+ XMapWindow( x11Display(), win );
+ XSync( x11Display(), False );
+}
+
+
+// -256..256
+void ImlibWidget::setBrightness( int factor )
+{
+ mod.brightness = factor + ImlibOffset;
+ setImageModifier();
+
+ autoUpdate();
+}
+
+
+// -256..256
+void ImlibWidget::setContrast( int factor )
+{
+ mod.contrast = factor + ImlibOffset;
+ setImageModifier();
+
+ autoUpdate();
+}
+
+
+// -256..256
+void ImlibWidget::setGamma( int factor )
+{
+ mod.gamma = factor + ImlibOffset;
+ setImageModifier();
+
+ autoUpdate();
+}
+
+
+Rotation ImlibWidget::rotation() const
+{
+ return m_kuim ? m_kuim->absRotation() : ROT_0;
+}
+
+FlipMode ImlibWidget::flipMode() const
+{
+ return m_kuim ? m_kuim->flipMode() : FlipNone;
+}
+
+void ImlibWidget::zoomImage( float factor )
+{
+ if ( factor == 1 || factor == 0 || !m_kuim )
+ return;
+
+ int newWidth = (int) (factor * (float) m_kuim->width());
+ int newHeight = (int) (factor * (float) m_kuim->height());
+
+ if ( canZoomTo( newWidth, newHeight ) )
+ {
+ m_kuim->resize( newWidth, newHeight, idata->smoothScale ? KuickImage::SMOOTH : KuickImage::FAST );
+ autoUpdate( true );
+ }
+}
+
+bool ImlibWidget::canZoomTo( int newWidth, int newHeight )
+{
+ if ( newWidth <= 2 || newHeight <= 2 ) // minimum size for an image is 2x2 pixels
+ return false;
+
+ return true;
+}
+
+
+void ImlibWidget::showImageOriginalSize()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->restoreOriginalSize();
+ autoUpdate( true );
+
+ showImage();
+}
+
+bool ImlibWidget::autoRotate( KuickImage *kuim )
+{
+ KFileMetaInfo metadatas( kuim->file().localFile() );
+ if ( !metadatas.isValid() )
+ return false;
+
+ KFileMetaInfoItem metaitem = metadatas.item("Orientation");
+ if ( !metaitem.isValid()
+#if QT_VERSION >= 0x030100
+ || metaitem.value().isNull()
+#endif
+ )
+ return false;
+
+
+ switch ( metaitem.value().toInt() )
+ {
+ // Orientation:
+ // 1: normal
+ // 2: flipped horizontally
+ // 3: ROT 180
+ // 4: flipped vertically
+ // 5: ROT 90 -> flip horizontally
+ // 6: ROT 90
+ // 7: ROT 90 -> flip vertically
+ // 8: ROT 270
+
+ case 1:
+ default:
+ kuim->rotateAbs( ROT_0 );
+ break;
+ case 2:
+ kuim->flipAbs( FlipHorizontal );
+ break;
+ case 3:
+ kuim->rotateAbs( ROT_180 );
+ break;
+ case 4:
+ kuim->flipAbs( FlipVertical );
+ break;
+ case 5:
+ kuim->rotateAbs( ROT_90 );
+ kuim->flipAbs( FlipHorizontal );
+ break;
+ case 6:
+ kuim->rotateAbs( ROT_90 );
+ break;
+ case 7:
+ kuim->rotateAbs( ROT_90 );
+ kuim->flipAbs( FlipVertical );
+ break;
+ case 8:
+ kuim->rotateAbs( ROT_270 );
+ break;
+ }
+
+ return true;
+}
+
+
+void ImlibWidget::setRotation( Rotation rot )
+{
+ if ( m_kuim )
+ {
+ if ( m_kuim->rotateAbs( rot ) )
+ autoUpdate( true );
+ }
+}
+
+
+// slots connected to Accels and popupmenu
+void ImlibWidget::rotate90()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->rotate( ROT_90 );
+ rotated( m_kuim, ROT_90 );
+ autoUpdate( true );
+}
+
+void ImlibWidget::rotate180()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->rotate( ROT_180 );
+ rotated( m_kuim, ROT_180 );
+ autoUpdate();
+}
+
+void ImlibWidget::rotate270()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->rotate( ROT_270 );
+ rotated( m_kuim, ROT_270 );
+ autoUpdate( true );
+}
+
+
+// should this go into a subclass?
+void ImlibWidget::flipHoriz()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->flip( FlipHorizontal );
+ autoUpdate();
+}
+
+void ImlibWidget::flipVert()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->flip( FlipVertical );
+ autoUpdate();
+}
+// end slots
+
+
+void ImlibWidget::setFlipMode( int mode )
+{
+ if ( !m_kuim )
+ return;
+
+ if ( m_kuim->flipAbs( mode ) )
+ autoUpdate();
+}
+
+
+void ImlibWidget::updateWidget( bool geometryUpdate )
+{
+ if ( !m_kuim )
+ return;
+
+// if ( geometryUpdate )
+// XUnmapWindow( x11Display(), win );// remove the old image -> no flicker
+
+ XSetWindowBackgroundPixmap( x11Display(), win, m_kuim->pixmap() );
+
+ if ( geometryUpdate )
+ updateGeometry( m_kuim->width(), m_kuim->height() );
+
+ XClearWindow( x11Display(), win );
+
+ showImage();
+}
+
+
+// here we just use the size of m_kuim, may be overridden in subclass
+void ImlibWidget::updateGeometry( int w, int h )
+{
+ XMoveWindow( x11Display(), win, 0, 0 ); // center?
+ XResizeWindow( x11Display(), win, w, h );
+ resize( w, h );
+}
+
+
+void ImlibWidget::closeEvent( QCloseEvent *e )
+{
+ e->accept();
+ QWidget::closeEvent( e );
+}
+
+
+void ImlibWidget::setBackgroundColor( const QColor& color )
+{
+ myBackgroundColor = color;
+ setPalette( QPalette( myBackgroundColor ));
+ repaint( false); // FIXME - false? necessary at all?
+}
+
+const QColor& ImlibWidget::backgroundColor() const
+{
+ return myBackgroundColor;
+}
+
+
+void ImlibWidget::setImageModifier()
+{
+ if ( !m_kuim )
+ return;
+
+ Imlib_set_image_modifier( id, m_kuim->imlibImage(), &mod );
+ m_kuim->setDirty( true );
+}
+
+int ImlibWidget::imageWidth() const
+{
+ return m_kuim ? m_kuim->width() : 0;
+}
+
+int ImlibWidget::imageHeight() const
+{
+ return m_kuim ? m_kuim->height() : 0;
+}
+
+void ImlibWidget::setBusyCursor()
+{
+ if ( ownCursor() )
+ m_oldCursor = cursor();
+ else
+ m_oldCursor = QCursor();
+
+ setCursor( KCursor::waitCursor() );
+}
+
+void ImlibWidget::restoreCursor()
+{
+ if ( cursor().shape() == KCursor::waitCursor().shape() ) // only if nobody changed the cursor in the meantime!
+ setCursor( m_oldCursor );
+}
+
+// Reparenting a widget in Qt in fact means destroying the old X window of the widget
+// and creating a new one. And since the X window used for the Imlib image is a child
+// of this widget's X window, destroying this widget's X window would mean also
+// destroying the Imlib image X window. Therefore it needs to be temporarily reparented
+// away and reparented back to the new X window.
+// Reparenting may happen e.g. when doing the old-style (non-NETWM) fullscreen changes.
+void ImlibWidget::reparent( QWidget* parent, WFlags f, const QPoint& p, bool showIt )
+{
+ XWindowAttributes attr;
+ XGetWindowAttributes( x11Display(), win, &attr );
+ XUnmapWindow( x11Display(), win );
+ XReparentWindow( x11Display(), win, attr.root, 0, 0 );
+ QWidget::reparent( parent, f, p, showIt );
+ XReparentWindow( x11Display(), win, winId(), attr.x, attr.y );
+ if( attr.map_state != IsUnmapped )
+ XMapWindow( x11Display(), win );
+}
+
+void ImlibWidget::rotated( KuickImage *, int )
+{
+}
+
+//----------
+
+
+// uhh ugly, we have two lists to map from filename to KuickImage :-/
+ImageCache::ImageCache( ImlibData *id, int maxImages )
+{
+ myId = id;
+ idleCount = 0;
+ myMaxImages = maxImages;
+ kuickList.setAutoDelete( true );
+ fileList.clear();
+ kuickList.clear();
+}
+
+
+ImageCache::~ImageCache()
+{
+ kuickList.clear();
+ fileList.clear();
+}
+
+
+void ImageCache::setMaxImages( int maxImages )
+{
+ myMaxImages = maxImages;
+ int count = kuickList.count();
+ while ( count > myMaxImages ) {
+ kuickList.removeLast();
+ fileList.remove( fileList.fromLast() );
+ count--;
+ }
+}
+
+void ImageCache::slotBusy()
+{
+ if ( idleCount == 0 )
+ emit sigBusy();
+
+ idleCount++;
+}
+
+void ImageCache::slotIdle()
+{
+ idleCount--;
+
+ if ( idleCount == 0 )
+ emit sigIdle();
+}
+
+
+KuickImage * ImageCache::getKuimage( KuickFile * file,
+ ImlibColorModifier mod )
+{
+ if ( !file )
+ return 0L;
+
+ assert( file->isAvailable() ); // debug build
+ if ( file->waitForDownload( 0L ) != KuickFile::OK ) // and for users
+ return 0L;
+
+ KuickImage *kuim = 0L;
+ int index = fileList.findIndex( file );
+ if ( index != -1 ) {
+ if ( index == 0 )
+ kuim = kuickList.at( 0 );
+
+ // need to reorder the lists, otherwise we might delete the current
+ // image when a new one is cached and the current one is the last!
+ else {
+ kuim = kuickList.take( index );
+ kuickList.insert( 0, kuim );
+ fileList.remove( file );
+ fileList.prepend( file );
+ }
+
+ return kuim;
+ }
+
+ if ( !kuim ) {
+ slotBusy();
+
+// #ifndef NDEBUG
+// struct timeval tms1, tms2;
+// gettimeofday( &tms1, NULL );
+// #endif
+
+ ImlibImage *im = Imlib_load_image( myId,
+ QFile::encodeName( file->localFile() ).data() );
+
+// #ifndef NDEBUG
+// gettimeofday( &tms2, NULL );
+// qDebug("*** LOADING image: %s, took %ld ms", file.latin1(),
+// (tms2.tv_usec - tms1.tv_usec)/1000);
+// #endif
+
+ slotIdle();
+ if ( !im ) {
+ slotBusy();
+ im = loadImageWithQt( file->localFile() );
+ slotIdle();
+ if ( !im )
+ return 0L;
+ }
+
+ Imlib_set_image_modifier( myId, im, &mod );
+ kuim = new KuickImage( file, im, myId );
+ connect( kuim, SIGNAL( startRendering() ), SLOT( slotBusy() ));
+ connect( kuim, SIGNAL( stoppedRendering() ), SLOT( slotIdle() ));
+
+ kuickList.insert( 0, kuim );
+ fileList.prepend( file );
+ }
+
+ if ( kuickList.count() > (uint) myMaxImages ) {
+// qDebug(":::: now removing from cache: %s", (*fileList.fromLast()).latin1());
+ kuickList.removeLast();
+ fileList.remove( fileList.fromLast() );
+ }
+
+ return kuim;
+}
+
+
+// Note: the returned image's filename will not be the real filename (which it usually
+// isn't anyway, according to Imlib's sources).
+ImlibImage * ImageCache::loadImageWithQt( const QString& fileName ) const
+{
+ kdDebug() << "Trying to load " << fileName << " with KImageIO..." << endl;
+
+ KImageIO::registerFormats();
+
+ QImage image( fileName );
+ if ( image.isNull() )
+ return 0L;
+ if ( image.depth() != 32 ) {
+ image.setAlphaBuffer(false);
+ image = image.convertDepth(32);
+
+ if ( image.isNull() )
+ return 0L;
+ }
+
+ // convert to 24 bpp (discard alpha)
+ int numPixels = image.width() * image.height();
+ const int NUM_BYTES_NEW = 3; // 24 bpp
+ uchar *newImageData = new uchar[numPixels * NUM_BYTES_NEW];
+ uchar *newData = newImageData;
+
+ int w = image.width();
+ int h = image.height();
+
+ for (int y = 0; y < h; y++) {
+ QRgb *scanLine = reinterpret_cast<QRgb *>( image.scanLine(y) );
+ for (int x = 0; x < w; x++) {
+ const QRgb& pixel = scanLine[x];
+ *(newData++) = qRed(pixel);
+ *(newData++) = qGreen(pixel);
+ *(newData++) = qBlue(pixel);
+ }
+ }
+
+ ImlibImage *im = Imlib_create_image_from_data( myId, newImageData, NULL,
+ image.width(), image.height() );
+
+ delete[] newImageData;
+
+ return im;
+}
+
+#include "imlibwidget.moc"
diff --git a/kuickshow/src/imlibwidget.h b/kuickshow/src/imlibwidget.h
new file mode 100644
index 00000000..5f6e89e1
--- /dev/null
+++ b/kuickshow/src/imlibwidget.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+** $Id$
+**
+** ImlibWidget: maps an Xlib window with Imlib's contents on a QWidget
+**
+** Created : 98
+**
+** Copyright (C) 1998-2001 by Carsten Pfeiffer. All rights reserved.
+**
+****************************************************************************/
+
+#ifndef IMLIBWIDGET_H
+#define IMLIBWIDGET_H
+
+#include <qvariant.h>
+
+#include <qcursor.h>
+#include <qevent.h>
+#include <qptrlist.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+#include <kurl.h>
+
+// #include those AFTER Qt-includes!
+#include <Imlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+// #include <X11/extensions/shape.h>
+
+#include "imdata.h"
+#include "kuickdata.h"
+
+class KuickFile;
+class KuickImage;
+
+class ImageCache : public QObject
+{
+ Q_OBJECT
+
+public:
+ ImageCache( ImlibData *id, int maxImages=1 );
+ ~ImageCache();
+
+ void setMaxImages( int maxImages );
+ int maxImages() const { return myMaxImages; }
+
+ KuickImage * getKuimage( KuickFile * file, ImlibColorModifier );
+
+private:
+ ImlibImage * loadImageWithQt( const QString& filename ) const;
+
+ int myMaxImages;
+ QValueList<KuickFile*>fileList;
+ QPtrList<KuickImage> kuickList;
+ // QPtrList<ImlibImage> imList;
+ ImlibData * myId;
+ int idleCount;
+
+private slots:
+ void slotBusy();
+ void slotIdle();
+
+signals:
+ void sigBusy();
+ void sigIdle();
+
+};
+
+
+// ------------------------------------------
+
+class QColor;
+
+class ImlibWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ ImlibWidget( ImData *_idata=0, QWidget *parent=0, const char *name=0 );
+ ImlibWidget( ImData *_idata, ImlibData *id, QWidget *parent=0,
+ const char *name=0 );
+ virtual ~ImlibWidget();
+
+ KURL url() const;
+ KuickFile * currentFile() const;
+ bool loadImage( KuickFile * file );
+ bool loadImage( const KURL& url );
+ bool cacheImage(const KURL& url );
+ void zoomImage( float );
+ void setBrightness( int );
+ void setContrast( int );
+ void setGamma( int );
+ void setRotation( Rotation );
+ void setFlipMode( int mode );
+
+ int brightness() const; // ### no impl!
+ int contrast() const; // ### no impl!
+ int gamma() const; // ### no impl!
+ Rotation rotation() const;
+ FlipMode flipMode() const;
+
+ int imageWidth() const;
+ int imageHeight() const;
+
+ void setAutoRender( bool enable ) { isAutoRendering = enable;}
+ bool isAutoRenderEnabled() const { return isAutoRendering; }
+ void setMaxImageCache( int );
+ int maxImageCache() const { return myMaxImageCache; }
+ const QColor& backgroundColor() const;
+ void setBackgroundColor( const QColor& );
+
+ /**
+ * @return true if auto-rotation is not possible, e.g. because no metadata
+ * about orientation is available
+ */
+ virtual bool autoRotate( KuickImage *kuim );
+
+ ImlibData* getImlibData() const { return id; }
+
+ virtual void reparent( QWidget* parent, WFlags f, const QPoint& p, bool showIt = FALSE );
+
+public slots:
+ void rotate90();
+ void rotate270();
+ void rotate180();
+ void flipHoriz();
+ void flipVert();
+ void showImageOriginalSize();
+ inline void updateImage() { updateWidget( true ); }
+
+
+protected:
+ KuickImage * loadImageInternal( KuickFile * file );
+ void showImage();
+ void setImageModifier();
+ void rotate( int );
+ void updateWidget( bool geometryUpdate=true );
+ virtual void updateGeometry( int width, int height );
+ virtual void loaded( KuickImage * );
+ virtual bool canZoomTo( int newWidth, int newHeight );
+ virtual void rotated( KuickImage *kuim, int rotation );
+
+ void closeEvent( QCloseEvent * );
+
+ inline void autoUpdate( bool geometryUpdate=false ) {
+ if ( isAutoRendering )
+ updateWidget( geometryUpdate );
+ }
+
+ bool stillResizing, deleteImData, deleteImlibData;
+ bool imlibModifierChanged;
+
+ KuickImage *m_kuim;
+ ImageCache *imageCache;
+ ImlibData *id;
+ ImData *idata;
+ Window win;
+ ImlibColorModifier mod;
+
+ KuickFile *m_kuickFile;
+ QCursor m_oldCursor;
+
+ static const int ImlibOffset;
+
+
+private:
+ void init();
+ bool isAutoRendering;
+ int myMaxImageCache;
+ QColor myBackgroundColor;
+
+
+protected slots:
+ bool cacheImage( KuickFile *file );
+ virtual void setBusyCursor();
+ virtual void restoreCursor();
+
+
+signals:
+ void sigImageError( const KuickFile * file, const QString& );
+
+};
+
+
+#endif
diff --git a/kuickshow/src/kuick.cpp b/kuickshow/src/kuick.cpp
new file mode 100644
index 00000000..43eadb50
--- /dev/null
+++ b/kuickshow/src/kuick.cpp
@@ -0,0 +1,4 @@
+#include "kuick.h"
+
+Kuick * Kuick::s_self = 0L;
+QSize Kuick::s_frameSize;
diff --git a/kuickshow/src/kuick.h b/kuickshow/src/kuick.h
new file mode 100644
index 00000000..bc86d5d2
--- /dev/null
+++ b/kuickshow/src/kuick.h
@@ -0,0 +1,70 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000,2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKGLOBALS_H
+#define KUICKGLOBALS_H
+
+#include <qrect.h>
+#include <qsize.h>
+
+#include <kwin.h>
+#include <kwinmodule.h>
+
+class Kuick
+{
+public:
+ static QRect workArea() {
+ return self()->winModule.workArea();
+ }
+
+ static QSize frameSize( WId win = 0L ) {
+ if ( win ) {
+ KWin::WindowInfo info = KWin::windowInfo(win, NET::WMKDEFrameStrut | NET::WMGeometry);
+ int wborder = info.frameGeometry().width() - info.geometry().width();
+ int hborder = info.frameGeometry().height() - info.geometry().height();
+
+ if ( wborder || hborder ) { // we get a 0,0 border when not shown
+ s_frameSize.setWidth( wborder );
+ s_frameSize.setHeight( hborder );
+ }
+ }
+
+ if ( !s_frameSize.isValid() )
+ return QSize( 0, 0 );
+
+ return s_frameSize;
+ }
+
+ static Kuick * self() {
+ if ( !s_self ) {
+ s_self = new Kuick;
+ }
+ return s_self;
+ }
+
+ KWinModule winModule;
+
+private:
+ Kuick() {}
+ static Kuick * s_self;
+
+ static QSize s_frameSize;
+};
+
+
+#endif // KUICKGLOBALS_H
diff --git a/kuickshow/src/kuickconfigdlg.cpp b/kuickshow/src/kuickconfigdlg.cpp
new file mode 100644
index 00000000..6ece8883
--- /dev/null
+++ b/kuickshow/src/kuickconfigdlg.cpp
@@ -0,0 +1,99 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifdef index
+#undef index
+#endif
+#include "kuickconfigdlg.h"
+
+#include <qkeycode.h>
+#include <qvbox.h>
+
+#include <kaccel.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include "imagewindow.h"
+#include "defaultswidget.h"
+#include "generalwidget.h"
+#include "slideshowwidget.h"
+
+#include "kuickdata.h"
+
+
+KuickConfigDialog::KuickConfigDialog( KActionCollection *_coll, QWidget *parent,
+ const char *name, bool modal )
+ : KDialogBase( Tabbed, i18n("Configure"),
+ Help | Default | Ok | Apply | Cancel, Ok,
+ parent, name, modal )
+{
+ coll = _coll;
+ QVBox *box = addVBoxPage( i18n("&General") );
+ generalWidget = new GeneralWidget( box, "general widget" );
+
+ box = addVBoxPage( i18n("&Modifications") );
+ defaultsWidget = new DefaultsWidget( box, "defaults widget" );
+
+ box = addVBoxPage( i18n("&Slideshow") );
+ slideshowWidget = new SlideShowWidget( box, "slideshow widget" );
+
+ box = addVBoxPage( i18n("&Viewer Shortcuts") );
+
+ imageWindow = new ImageWindow(); // just to get the accel...
+ imageWindow->hide();
+
+ imageKeyChooser = new KKeyChooser( imageWindow->actionCollection(), box );
+
+ box = addVBoxPage( i18n("Bro&wser Shortcuts") );
+ browserKeyChooser = new KKeyChooser( coll, box );
+
+ connect( this, SIGNAL( defaultClicked() ), SLOT( resetDefaults() ));
+}
+
+KuickConfigDialog::~KuickConfigDialog()
+{
+ imageWindow->close( true );
+}
+
+void KuickConfigDialog::applyConfig()
+{
+ generalWidget->applySettings( *kdata );
+ defaultsWidget->applySettings( *kdata );
+ slideshowWidget->applySettings( *kdata );
+
+ imageKeyChooser->save();
+ browserKeyChooser->save();
+
+ KGlobal::config()->sync();
+}
+
+
+void KuickConfigDialog::resetDefaults()
+{
+ KuickData data;
+ generalWidget->loadSettings( data );
+ defaultsWidget->loadSettings( data );
+ slideshowWidget->loadSettings( data );
+
+ imageKeyChooser->allDefault();
+ browserKeyChooser->allDefault();
+}
+
+#include "kuickconfigdlg.moc"
diff --git a/kuickshow/src/kuickconfigdlg.h b/kuickshow/src/kuickconfigdlg.h
new file mode 100644
index 00000000..884d91dc
--- /dev/null
+++ b/kuickshow/src/kuickconfigdlg.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKCONFIGDLG_H
+#define KUICKCONFIGDLG_H
+
+#include <qevent.h>
+
+#include <kkeydialog.h>
+
+#include <kdialogbase.h>
+
+class GeneralWidget;
+class DefaultsWidget;
+class SlideShowWidget;
+class ImageWindow;
+
+class KuickConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KuickConfigDialog( KActionCollection *coll, QWidget *parent=0,
+ const char *name=0, bool modal=true);
+ ~KuickConfigDialog();
+
+ void applyConfig();
+
+private slots:
+ void resetDefaults();
+
+private:
+ DefaultsWidget *defaultsWidget;
+ GeneralWidget *generalWidget;
+ SlideShowWidget *slideshowWidget;
+ KKeyChooser *imageKeyChooser, *browserKeyChooser;
+ KActionCollection *coll;
+
+ ImageWindow *imageWindow;
+
+};
+
+#endif
diff --git a/kuickshow/src/kuickdata.cpp b/kuickshow/src/kuickdata.cpp
new file mode 100644
index 00000000..c6aa47c2
--- /dev/null
+++ b/kuickshow/src/kuickdata.cpp
@@ -0,0 +1,177 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+
+#include <qcolor.h>
+#include <kconfig.h>
+#include <kglobal.h>
+
+#include "kuickdata.h"
+
+
+KuickData::KuickData()
+{
+ fileFilter = "*.jpeg *.jpg *.gif *.xpm *.ppm *.pgm *.pbm *.pnm *.png *.bmp *.psd *.eim *.tif *.tiff *.xcf";// *.mng";
+ slideDelay = 3000;
+ slideshowCycles = 1;
+ slideshowFullscreen = true;
+ slideshowStartAtFirst = true;
+
+ preloadImage = true;
+
+ isModsEnabled = true;
+ fullScreen = false;
+ autoRotation = true;
+ downScale = true;
+ upScale = false;
+ flipVertically = false;
+ flipHorizontally = false;
+
+ maxUpScale = 3;
+ rotation = ROT_0;
+
+ brightnessSteps = 1;
+ contrastSteps = 1;
+ gammaSteps = 1;
+ scrollSteps = 1;
+ zoomSteps = 1.5;
+
+ maxZoomFactor = 4.0;
+
+ maxCachedImages = 4;
+ backgroundColor = Qt::black;
+
+ startInLastDir = true;
+
+ idata = new ImData;
+}
+
+KuickData::~KuickData()
+{
+ delete idata;
+}
+
+
+void KuickData::load()
+{
+ KConfig *kc = KGlobal::config();
+
+ KuickData def;
+
+ kc->setGroup( "GeneralConfiguration" );
+ fileFilter = kc->readEntry( "FileFilter", def.fileFilter );
+ slideDelay = kc->readNumEntry( "SlideShowDelay", def.slideDelay );
+ slideshowCycles = kc->readUnsignedNumEntry( "SlideshowCycles", 1 );
+ slideshowFullscreen = kc->readBoolEntry( "SlideshowFullscreen", true );
+ slideshowStartAtFirst = kc->readBoolEntry("SlideshowStartAtFirst", true );
+
+ preloadImage = kc->readBoolEntry( "PreloadNextImage", def.preloadImage );
+
+ fullScreen = kc->readBoolEntry( "Fullscreen", def.fullScreen);
+ autoRotation = kc->readBoolEntry( "AutoRotation", def.autoRotation);
+ downScale = kc->readBoolEntry( "ShrinkToScreenSize", def.downScale );
+ upScale = kc->readBoolEntry( "ZoomToScreenSize", def.upScale );
+ flipVertically = kc->readBoolEntry( "FlipVertically", def.flipVertically );
+ flipHorizontally = kc->readBoolEntry( "FlipHorizontally",
+ def.flipHorizontally );
+ maxUpScale = kc->readNumEntry( "MaxUpscale Factor", def.maxUpScale );
+ rotation = (Rotation) kc->readNumEntry( "Rotation", def.rotation );
+
+ isModsEnabled = kc->readBoolEntry( "ApplyDefaultModifications",
+ def.isModsEnabled );
+
+ brightnessSteps = kc->readNumEntry("BrightnessStepSize",def.brightnessSteps);
+ contrastSteps = kc->readNumEntry("ContrastStepSize", def.contrastSteps);
+ gammaSteps = kc->readNumEntry("GammaStepSize", def.gammaSteps);
+ scrollSteps = kc->readNumEntry("ScrollingStepSize", def.scrollSteps);
+ zoomSteps = kc->readDoubleNumEntry("ZoomStepSize", def.zoomSteps);
+
+ maxZoomFactor = kc->readDoubleNumEntry( "MaximumZoomFactorByDesktop", def.maxZoomFactor );
+
+ maxCachedImages = kc->readUnsignedNumEntry( "MaxCachedImages",
+ def.maxCachedImages );
+ backgroundColor = kc->readColorEntry( "BackgroundColor", &Qt::black );
+
+ startInLastDir = kc->readBoolEntry( "StartInLastDir", true);
+
+ idata->load( kc );
+
+ // compatibility with KuickShow <= 0.8.3
+ switch ( rotation )
+ {
+ case 90:
+ rotation = ROT_90;
+ break;
+ case 180:
+ rotation = ROT_180;
+ break;
+ case 270:
+ rotation = ROT_270;
+ break;
+ default:
+ if ( (rotation < ROT_0) || (rotation > ROT_270) )
+ rotation = ROT_0;
+ break;
+ }
+}
+
+
+void KuickData::save()
+{
+ KConfig *kc = KGlobal::config();
+ kc->setGroup( "GeneralConfiguration" );
+
+ kc->writeEntry( "FileFilter", fileFilter );
+ kc->writeEntry( "SlideShowDelay", slideDelay );
+ kc->writeEntry( "SlideshowCycles", slideshowCycles );
+ kc->writeEntry( "SlideshowFullscreen", slideshowFullscreen );
+ kc->writeEntry( "SlideshowStartAtFirst", slideshowStartAtFirst );
+
+ kc->writeEntry( "PreloadNextImage", preloadImage );
+
+ kc->writeEntry( "Fullscreen", fullScreen );
+ kc->writeEntry( "AutoRotation", autoRotation );
+ kc->writeEntry( "ShrinkToScreenSize", downScale );
+ kc->writeEntry( "ZoomToScreenSize", upScale );
+ kc->writeEntry( "FlipVertically", flipVertically );
+ kc->writeEntry( "FlipHorizontally", flipHorizontally );
+ kc->writeEntry( "MaxUpscale Factor", maxUpScale );
+ kc->writeEntry( "Rotation", rotation );
+
+ kc->writeEntry( "ApplyDefaultModifications", isModsEnabled );
+
+
+ kc->writeEntry( "BrightnessStepSize", brightnessSteps );
+ kc->writeEntry( "ContrastStepSize", contrastSteps );
+ kc->writeEntry( "GammaStepSize", gammaSteps );
+
+ kc->writeEntry( "ScrollingStepSize", scrollSteps );
+ kc->writeEntry( "ZoomStepSize", zoomSteps );
+
+ kc->writeEntry( "MaximumZoomFactorByDesktop", maxZoomFactor );
+
+ kc->writeEntry( "MaxCachedImages", maxCachedImages );
+ kc->writeEntry( "BackgroundColor", backgroundColor );
+
+ kc->writeEntry( "StartInLastDir", startInLastDir );
+
+ idata->save( kc );
+
+ kc->sync();
+}
diff --git a/kuickshow/src/kuickdata.h b/kuickshow/src/kuickdata.h
new file mode 100644
index 00000000..d05b3e99
--- /dev/null
+++ b/kuickshow/src/kuickdata.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKDATA_H
+#define KUICKDATA_H
+
+#include <qcolor.h>
+#include <qstring.h>
+
+#include "imdata.h"
+
+class KConfig;
+
+// values are also used as combobox index defaultswidget.*
+enum Rotation { ROT_0=0, ROT_90=1, ROT_180=2, ROT_270=3 };
+
+// hmm, global declaration for now
+enum FlipMode { FlipNone = 0, FlipHorizontal = 1, FlipVertical = 2 };
+
+class KuickData
+{
+public:
+ KuickData();
+ ~KuickData();
+
+ void load();
+ void save();
+
+
+ ImData *idata;
+
+ QString fileFilter;
+ uint slideDelay;
+ uint slideshowCycles;
+ bool slideshowFullscreen :1;
+ bool slideshowStartAtFirst :1;
+
+ int brightnessSteps;
+ int contrastSteps;
+ int gammaSteps;
+
+ int scrollSteps;
+ float zoomSteps;
+
+ bool startInLastDir :1;
+
+ bool preloadImage :1;
+ bool autoRotation :1;
+ bool fullScreen :1;
+
+ // default image modifications
+ bool isModsEnabled :1;
+
+ bool flipVertically :1;
+ bool flipHorizontally :1;
+ bool downScale :1;
+ bool upScale :1;
+ int maxUpScale;
+ float maxZoomFactor;
+ uint maxCachedImages;
+ Rotation rotation;
+
+ QColor backgroundColor;
+
+
+};
+
+
+extern KuickData* kdata;
+
+#endif
diff --git a/kuickshow/src/kuickfile.cpp b/kuickshow/src/kuickfile.cpp
new file mode 100644
index 00000000..1dd259d6
--- /dev/null
+++ b/kuickshow/src/kuickfile.cpp
@@ -0,0 +1,194 @@
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kinstance.h>
+#include <klocale.h>
+#include <kprogress.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <ktempfile.h>
+
+#include "filecache.h"
+#include "kuickfile.h"
+
+KuickFile::KuickFile(const KURL& url)
+ : QObject(),
+ m_url( url ),
+ m_job( 0L ),
+ m_progress( 0L ),
+ m_currentProgress( 0 )
+{
+ if ( m_url.isLocalFile())
+ m_localFile = m_url.path();
+ else {
+ const KURL& mostLocal = KIO::NetAccess::mostLocalURL( m_url, 0L );
+ if ( mostLocal.isValid() && mostLocal.isLocalFile() )
+ m_localFile = mostLocal.path();
+ }
+}
+
+KuickFile::~KuickFile()
+{
+ delete m_job;
+
+ if ( hasDownloaded() )
+ QFile::remove( m_localFile );
+}
+
+QString KuickFile::localFile() const
+{
+ // Note: never call isAvailable() from here, directly or indirectly
+
+ if ( isDownloading() )
+ return QString::null;
+
+ return m_localFile;
+}
+
+bool KuickFile::hasDownloaded() const
+{
+ return !m_url.isLocalFile() && isAvailable() && m_job != 0L;
+}
+
+// ### need an API for refreshing the file?
+bool KuickFile::download()
+{
+ if ( m_url.isLocalFile() || isAvailable() )
+ return true;
+
+ if ( isDownloading() )
+ return true;
+
+ // reinitialize
+ m_localFile = QString::null;
+ m_currentProgress = 0;
+
+
+ QString ext;
+ QString fileName = m_url.fileName();
+ int extIndex = fileName.findRev('.');
+ if ( extIndex > 0 )
+ ext = fileName.mid( extIndex + 1 );
+
+ QString tempDir = FileCache::self()->tempDir();
+ KTempFile tempFile( tempDir, ext );
+ tempFile.setAutoDelete( tempDir.isNull() ); // in case there is no proper tempdir, make sure to delete those files!
+ if ( tempFile.status() != 0 )
+ return false;
+
+ tempFile.close();
+ if ( tempFile.status() != 0 )
+ return false;
+
+ KURL destURL;
+ destURL.setPath( tempFile.name() );
+
+ m_job = KIO::file_copy( m_url, destURL, -1, true, false, false ); // handling progress ourselves
+ m_job->setAutoErrorHandlingEnabled( true );
+ connect( m_job, SIGNAL( result( KIO::Job * )), SLOT( slotResult( KIO::Job * ) ));
+ connect( m_job, SIGNAL( percent( KIO::Job *, unsigned long )), SLOT( slotProgress( KIO::Job *, unsigned long ) ));
+
+ // TODO: generify background/foreground downloading?
+
+ return m_job != 0L;
+}
+
+KuickFile::DownloadStatus KuickFile::waitForDownload( QWidget *parent )
+{
+ if ( isAvailable() )
+ return OK;
+
+ if ( !isDownloading() ) {
+ if ( !download() )
+ return ERROR;
+ }
+
+ KProgressDialog *dialog = new KProgressDialog( parent );
+ dialog->setModal( true );
+ dialog->setCaption( i18n("Downloading %1...").arg( m_url.fileName() ) );
+ dialog->setLabel( i18n("Please wait while downloading\n%1").arg( m_url.prettyURL() ));
+ dialog->setAllowCancel( true );
+ dialog->setAutoClose( true );
+
+ m_progress = dialog->progressBar();
+ m_progress->setTotalSteps( 100 ); // percent
+ m_progress->setProgress( m_currentProgress );
+ dialog->exec();
+ bool canceled = dialog->wasCancelled();
+ delete dialog;
+ m_progress = 0L;
+
+ if ( canceled && m_job ) {
+ m_job->kill();
+ m_job = 0L;
+ m_currentProgress = 0;
+ }
+ // ### when aborted, remove KuickImage from FileCache?
+
+ if ( canceled )
+ return CANCELED;
+
+ if ( !isAvailable() )
+ return ERROR;
+
+ // ### use custom progress dialog with OK, SKIP, CANCEL?
+ return OK;
+}
+
+void KuickFile::slotResult( KIO::Job *job )
+{
+ if (job != m_job) { // huh?
+ return;
+ }
+
+ m_job = 0L;
+
+ if ( job->error() != 0 ) {
+ m_currentProgress = 0;
+
+ if ( job->error() != KIO::ERR_USER_CANCELED )
+ kdWarning() << "ERROR: KuickFile::slotResult: " << job->errorString() << endl;
+
+ QString canceledFile = static_cast<KIO::FileCopyJob*>(job)->destURL().path();
+ QFile::remove( canceledFile );
+ m_progress->topLevelWidget()->hide();
+ }
+ else {
+ m_localFile = static_cast<KIO::FileCopyJob*>(job)->destURL().path();
+ emit downloaded( this ); // before closing the progress dialog
+
+ if ( m_progress ) {
+ m_progress->setProgress( 100 );
+#define BUGGY_VERSION KDE_MAKE_VERSION(3,5,2)
+ if ( KDE::version() <= BUGGY_VERSION ) {
+ m_progress->topLevelWidget()->hide(); // ### workaround broken KProgressDialog
+ }
+ }
+ }
+}
+
+void KuickFile::slotProgress( KIO::Job *job, unsigned long percent )
+{
+ if (job != m_job) { // huh?
+ return;
+ }
+
+ m_currentProgress = percent;
+
+ if ( !m_progress )
+ return;
+
+ // only set 100% in slotResult. Otherwise, the progress dialog would be closed
+ // before slotResult() is called.
+ if ( percent >= 100 )
+ percent = 99;
+
+ m_progress->setProgress( (int) percent );
+}
+
+bool operator==( const KuickFile& first, const KuickFile& second ) {
+ return first.url().equals( second.url() );
+}
+
+#include "kuickfile.moc"
diff --git a/kuickshow/src/kuickfile.h b/kuickshow/src/kuickfile.h
new file mode 100644
index 00000000..957db6ee
--- /dev/null
+++ b/kuickshow/src/kuickfile.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+** $Id: .emacs,v 1.3 2002/02/20 15:06:53 gis Exp $
+**
+** Created : 2006
+**
+** Copyright (C) 2006 Carsten Pfeiffer <pfeiffer@kde.org>
+**
+****************************************************************************/
+
+#ifndef KUICKFILE_H
+#define KUICKFILE_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+#include <kurl.h>
+#include <kprogress.h>
+
+namespace KIO {
+ class Job;
+ class FileCopyJob;
+}
+
+class KuickFile : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum DownloadStatus
+ {
+ OK = 1,
+ CANCELED,
+ ERROR
+ };
+
+ KuickFile(const KURL& url);
+
+ /**
+ * Cleans up resources and removes any temporary file, if available.
+ */
+ ~KuickFile();
+
+ const KURL& url() const { return m_url; }
+
+
+ QString localFile() const;
+
+ bool download();
+
+ /**
+ * @return true if download is in progress
+ */
+ bool isDownloading() const { return m_job != 0L; }
+
+ /**
+ * @return true if a local file is available, that is,
+ * @ref #localFile will return a non-empty name
+ * ### HERE ADD mostlylocal thing!
+ */
+ bool isAvailable() const { return !localFile().isEmpty(); }
+
+ /**
+ * @return true if @ref #isAvailable() returns true AND @ref #url() is a remote URL,
+ * i.e. the file really has been downloaded.
+ */
+ bool hasDownloaded() const;
+
+ /**
+ * Opens a modal dialog window, blocking user interaction until the download
+ * has finished. If the file is already available, this function will return true
+ * immediately.
+ * @return true when the download has finished or false when the user aborted the dialog
+ */
+ KuickFile::DownloadStatus waitForDownload( QWidget *parent );
+
+// bool needsDownload();
+
+signals:
+ /**
+ * Signals that download has finished for that file. Will only be emitted for non-local files!
+ */
+ void downloaded( KuickFile * );
+
+private slots:
+ void slotResult( KIO::Job *job );
+ void slotProgress( KIO::Job *job, unsigned long percent );
+
+private:
+ KURL m_url;
+ QString m_localFile;
+ KIO::FileCopyJob *m_job;
+ KProgress *m_progress;
+ int m_currentProgress;
+
+};
+
+bool operator==( const KuickFile& first, const KuickFile& second );
+
+#endif // KUICKFILE_H
diff --git a/kuickshow/src/kuickglobals.h b/kuickshow/src/kuickglobals.h
new file mode 100644
index 00000000..4ea2ff3c
--- /dev/null
+++ b/kuickshow/src/kuickglobals.h
@@ -0,0 +1,33 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKGLOBALS_H
+#define KUICKGLOBALS_H
+
+#include <kwinmodule.h>
+
+class KuickGlobals
+{
+public:
+ KWinModule winModule;
+
+
+};
+
+
+#endif // KUICKGLOBALS_H
diff --git a/kuickshow/src/kuickimage.cpp b/kuickshow/src/kuickimage.cpp
new file mode 100644
index 00000000..29e5de1c
--- /dev/null
+++ b/kuickshow/src/kuickimage.cpp
@@ -0,0 +1,527 @@
+#include "kuickimage.h"
+
+KuickImage::KuickImage( const KuickFile * file, ImlibImage *im, ImlibData *id)
+ : QObject( 0L, 0L )
+{
+ myFile = file;
+ myOrigIm = 0L;
+ myIm = im;
+ myId = id;
+ myPixmap = 0L;
+ myWidth = im->rgb_width;
+ myHeight = im->rgb_height;
+ myIsDirty = true;
+
+ myOrigWidth = myWidth;
+ myOrigHeight = myHeight;
+ myRotation = ROT_0;
+ myFlipMode = FlipNone;
+}
+
+KuickImage::~KuickImage()
+{
+ if ( myPixmap )
+ Imlib_free_pixmap( myId, myPixmap );
+
+ if ( myOrigIm )
+ {
+ Imlib_destroy_image( myId, myOrigIm );
+ Imlib_kill_image( myId, myIm ); // kill scaled image (### really? analyze!)
+ }
+ else
+ Imlib_destroy_image( myId, myIm );
+}
+
+
+Pixmap& KuickImage::pixmap()
+{
+ if ( myIsDirty )
+ renderPixmap();
+
+ return myPixmap;
+}
+
+
+void KuickImage::renderPixmap()
+{
+ if ( !myIsDirty )
+ return;
+
+// qDebug("### rendering: %s", myFilename.latin1());
+
+ if ( myPixmap )
+ Imlib_free_pixmap( myId, myPixmap );
+
+ emit startRendering();
+
+// #ifndef NDEBUG
+// struct timeval tms1, tms2;
+// gettimeofday( &tms1, NULL );
+// #endif
+
+ Imlib_render( myId, myIm, myWidth, myHeight );
+ myPixmap = Imlib_move_image( myId, myIm );
+
+// #ifndef NDEBUG
+// gettimeofday( &tms2, NULL );
+// qDebug("*** rendering image: %s, took %ld ms", myFilename.latin1(),
+// (tms2.tv_usec - tms1.tv_usec)/1000);
+// #endif
+
+ emit stoppedRendering();
+
+ myIsDirty = false;
+}
+
+
+void KuickImage::rotate( Rotation rot )
+{
+ if ( rot == ROT_180 ) { // rotate 180 degrees
+ Imlib_flip_image_horizontal( myId, myIm );
+ Imlib_flip_image_vertical( myId, myIm );
+ }
+
+ else if ( rot == ROT_90 || rot == ROT_270 ) {
+ qSwap( myWidth, myHeight );
+ Imlib_rotate_image( myId, myIm, -1 );
+
+ if ( rot == ROT_90 ) // rotate 90 degrees
+ Imlib_flip_image_horizontal( myId, myIm );
+ else if ( rot == ROT_270 ) // rotate 270 degrees
+ Imlib_flip_image_vertical( myId, myIm );
+ }
+
+ myRotation = (Rotation) ((myRotation + rot) % 4);
+ myIsDirty = true;
+}
+
+
+bool KuickImage::rotateAbs( Rotation rot )
+{
+ if ( myRotation == rot )
+ return false;
+
+ int diff = rot - myRotation;
+ bool clockWise = (diff > 0);
+
+ switch( abs(diff) ) {
+ case ROT_90:
+ rotate( clockWise ? ROT_90 : ROT_270 );
+ break;
+ case ROT_180:
+ rotate( ROT_180 );
+ break;
+ case ROT_270:
+ rotate( clockWise ? ROT_270 : ROT_90 );
+ break;
+ }
+
+ return true;
+}
+
+void KuickImage::flip( FlipMode flipMode )
+{
+ if ( flipMode & FlipHorizontal )
+ Imlib_flip_image_horizontal( myId, myIm );
+ if ( flipMode & FlipVertical )
+ Imlib_flip_image_vertical( myId, myIm );
+
+ myFlipMode = (FlipMode) (myFlipMode ^ flipMode);
+ myIsDirty = true;
+}
+
+bool KuickImage::flipAbs( int mode )
+{
+ if ( myFlipMode == mode )
+ return false;
+
+ bool changed = false;
+
+ if ( ((myFlipMode & FlipHorizontal) && !(mode & FlipHorizontal)) ||
+ (!(myFlipMode & FlipHorizontal) && (mode & FlipHorizontal)) ) {
+ Imlib_flip_image_horizontal( myId, myIm );
+ changed = true;
+ }
+
+ if ( ((myFlipMode & FlipVertical) && !(mode & FlipVertical)) ||
+ (!(myFlipMode & FlipVertical) && (mode & FlipVertical)) ) {
+ Imlib_flip_image_vertical( myId, myIm );
+ changed = true;
+ }
+
+ if ( changed ) {
+ myFlipMode = (FlipMode) mode;
+ myIsDirty = true;
+ return true;
+ }
+
+ return false;
+}
+
+
+void KuickImage::restoreOriginalSize()
+{
+ if (myWidth == myOrigWidth && myHeight == myOrigHeight)
+ return;
+
+// qDebug("-- restoreOriginalSize");
+
+ if ( myOrigIm != 0L )
+ {
+ Imlib_destroy_image( myId, myIm );
+ myIm = myOrigIm;
+ myOrigIm = 0L;
+ }
+
+ myWidth = myOrigWidth;
+ myHeight = myOrigHeight;
+ myIsDirty = true;
+
+ if ( myRotation == ROT_90 || myRotation == ROT_270 )
+ qSwap( myWidth, myHeight );
+}
+
+void KuickImage::resize( int width, int height, KuickImage::ResizeMode mode )
+{
+ if ( myWidth == width && myHeight == height )
+ return;
+
+ if ( mode == KuickImage::SMOOTH )
+ {
+ if ( !smoothResize( width, height ) )
+ fastResize( width, height );
+ }
+ else
+ {
+ fastResize( width, height );
+ }
+}
+
+
+void KuickImage::fastResize( int width, int height )
+{
+// qDebug("-- fastResize: %i x %i", width, height );
+
+ // lazy resizing (only done when rendering pixmap)
+ myWidth = width;
+ myHeight = height;
+ myIsDirty = true;
+}
+
+bool KuickImage::smoothResize( int newWidth, int newHeight )
+{
+// qDebug("-- smoothResize: %i x %i", newWidth, newHeight);
+
+ QImage *image = newQImage();
+ // Note: QImage::ScaleMin seems to have a bug (off-by-one, sometimes results in width being 1 pixel too small)
+ QImage scaledImage = image->smoothScale(newWidth, newHeight, QImage::ScaleFree);
+
+ delete image;
+
+
+ ImlibImage *newIm = toImage( myId, scaledImage );
+ if ( newIm )
+ {
+ if ( myOrigIm == 0 )
+ myOrigIm = myIm;
+
+ myIm = newIm;
+ myWidth = newWidth;
+ myHeight = newHeight;
+ myIsDirty = true;
+ return true;
+ }
+
+ return false;
+}
+
+QImage * KuickImage::newQImage() const
+{
+ ImlibImage *im;
+
+// qDebug("-- newQImage");
+
+ if ( myOrigIm != 0L && myRotation == ROT_0 && myFlipMode == FlipNone )
+ {
+ // use original image if no other modifications have been applied
+ // ### use orig image always and reapply mods?
+ im = myOrigIm;
+ }
+ else
+ {
+ im = myIm;
+ }
+
+ int w = im->rgb_width;
+ int h = im->rgb_height;
+
+ QImage *image = new QImage( w, h, 32 );
+ uchar *rgb = im->rgb_data;
+ QRgb **destImageData = reinterpret_cast<QRgb**>( image->jumpTable() );
+
+
+ int byteIndex = 0;
+ int destLineIndex = 0;
+ int destByteIndex = 0;
+ for ( int pixel = 0; pixel < (w * h); pixel++ )
+ {
+ if ( pixel != 0 && (pixel % w) == 0 )
+ {
+ destLineIndex++;
+ destByteIndex = 0;
+ }
+
+ uchar r = rgb[byteIndex++];
+ uchar g = rgb[byteIndex++];
+ uchar b = rgb[byteIndex++];
+
+ QRgb rgbPixel = qRgb( r, g, b );
+ destImageData[destLineIndex][destByteIndex++] = rgbPixel;
+ }
+
+ return image;
+}
+
+ImlibImage * KuickImage::toImage( ImlibData *id, QImage& image )
+{
+ if ( image.isNull() )
+ return 0L;
+
+ if ( image.depth() != 32 )
+ {
+ image.setAlphaBuffer(false);
+ image = image.convertDepth(32);
+
+ if ( image.isNull() )
+ return 0L;
+ }
+
+ // convert to 24 bpp (discard alpha)
+ int numPixels = image.width() * image.height();
+ const int NUM_BYTES_NEW = 3; // 24 bpp
+ uchar *newImageData = new uchar[numPixels * NUM_BYTES_NEW];
+ uchar *newData = newImageData;
+
+ int w = image.width();
+ int h = image.height();
+
+ for (int y = 0; y < h; y++) {
+ QRgb *scanLine = reinterpret_cast<QRgb *>( image.scanLine(y) );
+ for (int x = 0; x < w; x++) {
+ const QRgb& pixel = scanLine[x];
+ *(newData++) = qRed(pixel);
+ *(newData++) = qGreen(pixel);
+ *(newData++) = qBlue(pixel);
+ }
+ }
+
+ ImlibImage *im = Imlib_create_image_from_data( id, newImageData, NULL,
+ image.width(), image.height() );
+
+ delete [] newImageData;
+
+ return im;
+}
+
+
+#if 0
+bool KuickImage::smoothResize( int newWidth, int newHeight )
+{
+ int numPixels = newWidth * newHeight;
+ const int NUM_BYTES_NEW = 3; // 24 bpp
+ uchar *newImageData = new uchar[numPixels * NUM_BYTES_NEW];
+
+ // ### endianness
+ // myIm : old image, old size
+
+
+ /////////////////////////////////////////////////
+// int w = myOrigWidth; //myViewport.width();
+ //int h = myOrigHeight; //myViewport.height();
+
+ //QImage dst(w, h, myIm->depth(), myIm->numColors(), myIm->bitOrder());
+
+ //QRgb *scanline;
+
+ int basis_ox, basis_oy, basis_xx, basis_yy;
+
+ // ### we only scale with a fixed factor for x and y anyway
+ double scalex = newWidth / (double) myOrigWidth;
+ double scaley = newHeight / (double) myOrigHeight;
+
+// basis_ox=(int) (myViewport.left() * 4096.0 / scalex);
+// basis_oy=(int) (myViewport.top() * 4096.0 / scaley);
+ basis_ox = 0;
+ basis_oy = 0;
+ basis_xx = (int) (4096.0 / scalex);
+ basis_yy = (int) (4096.0 / scaley);
+
+ //qDebug("Basis: (%d, %d), (%d, 0), (0, %d)", basis_ox, basis_oy, basis_xx, basis_yy);
+
+ int x2, y2;
+
+ int max_x2 = (myOrigWidth << 12);
+ int max_y2 = (myOrigHeight << 12);
+
+// QRgb background = idata->backgroundColor.rgb();
+
+// QRgb **imdata = (QRgb **) myIm->jumpTable();
+// QRgb *imdata = reinterpret_cast<QRgb*>( myIm->rgb_data );
+ uchar *imdata = myIm->rgb_data;
+
+
+ int y = 0;
+
+
+// for (;;) //fill the top of the target pixmap with the background color
+// {
+// y2 = basis_oy + y * basis_yy;
+//
+// if ((y2 >= 0 && (y2 >> 12) < myIm->height()) || y >= h)
+// break;
+//
+// scanline = (QRgb*) dst.scanLine(y);
+// for (int i = 0; i < w; i++)
+// *(scanline++) = background; //qRgb(0,255,0);
+// y++;
+// }
+
+ for (; y < newHeight; y++)
+ {
+// scanline = (QRgb*) dst.scanLine(y);
+
+ x2 = basis_ox;
+ y2 = basis_oy + y * basis_yy;
+
+ if (y2 >= max_y2)
+ break;
+
+ int x = 0;
+
+// while ((x2 < 0 || (x2 >> 12) >= myIm->width()) && x < w) //fill the left of the target pixmap with the background color
+// {
+// *(scanline++) = background; //qRgb(0,0,255);
+// x2 += basis_xx;
+// x++;
+// }
+
+ int top = y2 >> 12;
+ int bottom = top + 1;
+ if (bottom >= myOrigHeight)
+ bottom--;
+
+// for (; x < w; x++)
+ for (; x < newWidth; x++) // ### myOrigWidth orig
+ {
+ int left = x2 >> 12;
+ int right = left + 1;
+
+ if (right >= myOrigWidth)
+ right = myOrigWidth - 1;
+
+ unsigned int wx = x2 & 0xfff; //12 bits of precision for reasons which will become clear
+ unsigned int wy = y2 & 0xfff; //12 bits of precision
+
+ unsigned int iwx = 0xfff - wx;
+ unsigned int iwy = 0xfff - wy;
+
+ QRgb tl = 0, tr = 0, bl = 0, br = 0;
+ int ind = 0;
+ ind = (left + top * myOrigWidth) * 3;
+ tl = (imdata[ind] << 16);
+ tl |= (imdata[ind + 1] << 8);
+ tl |= (imdata[ind + 2] << 0);
+ int bar = imdata[ind + 2] << 8;
+ bar = qBlue(bar);
+
+ ind = (right + top * myOrigWidth) * 3;
+ tr = (imdata[ind] << 16);
+ tr |= (imdata[ind + 1] << 8);
+ tr |= (imdata[ind + 2] << 0);
+ bar = imdata[ind + 2] << 8;
+
+ ind = (left + bottom * myOrigWidth) * 3;
+ bl = (imdata[ind] << 16);
+ bl |= (imdata[ind + 1] << 8);
+ bl |= (imdata[ind + 2] << 0);
+ bar = imdata[ind + 2] << 8;
+
+ ind = (right + bottom * myOrigWidth) * 3;
+ br = (imdata[ind] << 16);
+ br |= (imdata[ind + 1] << 8);
+ br |= (imdata[ind + 2] << 0);
+// tl=imdata[top][left];
+// tr=imdata[top][right];
+// bl=imdata[bottom][left];
+// br=imdata[bottom][right];
+
+ /*
+ tl=getValidPixel(myIm, left, top, x, y); //these calls are expensive
+ tr=getValidPixel(myIm, right, top, x, y); //use them to debug segfaults in this function
+ bl=getValidPixel(myIm, left, bottom, x, y);
+ br=getValidPixel(myIm, right, bottom, x, y);
+ */
+
+ unsigned int r = (unsigned int) (qRed(tl) * iwx * iwy + qRed(tr) * wx* iwy + qRed(bl) * iwx * wy + qRed(br) * wx * wy); // NB 12+12+8 == 32
+ unsigned int g = (unsigned int) (qGreen(tl) * iwx * iwy + qGreen(tr) * wx * iwy + qGreen(bl) * iwx * wy + qGreen(br) * wx * wy);
+ unsigned int b = (unsigned int) (qBlue(tl) * iwx * iwy + qBlue(tr) * wx * iwy + qBlue(bl) * iwx * wy + qBlue(br) * wx * wy);
+
+ // ### endianness
+ //we're actually off by one in 255 here! (254 instead of 255)
+ int foo = r >> 24;
+ foo = g >> 24;
+ foo = b >> 24;
+ newImageData[(y * newWidth * 3) + (x * 3) + 0] = (r >> 24);
+ newImageData[(y * newWidth * 3) + (x * 3) + 1] = (g >> 24);
+ newImageData[(y * newWidth * 3) + (x * 3) + 2] = (b >> 24);
+// *(scanline++) = qRgb(r >> 24, g >> 24, b >> 24); //we're actually off by one in 255 here
+
+ x2 += basis_xx;
+
+ if (x2 > max_x2)
+ {
+ x++;
+ break;
+ }
+
+ }
+
+// while (x < w) //fill the right of each scanline with the background colour
+// {
+// *(scanline++) = background; //qRgb(255,0,0);
+// x++;
+// }
+ }
+
+// for (;;) //fill the bottom of the target pixmap with the background color
+// {
+// y2 = basis_oy + y * basis_yy;
+//
+// if (y >= h)
+// break;
+//
+// scanline = (QRgb*) dst.scanLine(y);
+// for (int i = 0; i < w; i++)
+// *(scanline++) = background; //qRgb(255,255,0);
+// y++;
+// }
+
+ // ### keep orig image somewhere but delete all scaled images!
+ ImlibImage *newIm = Imlib_create_image_from_data( myId, newImageData, NULL,
+ newWidth, newHeight );
+ delete[] newImageData;
+
+ if ( newIm )
+ {
+ myScaledIm = newIm;
+ myIsDirty = true;
+ myWidth = newWidth;
+ myHeight = newHeight;
+ }
+
+ return myIm != 0L;
+// return dst.copy();
+}
+#endif
+
+#include "kuickimage.moc"
diff --git a/kuickshow/src/kuickimage.h b/kuickshow/src/kuickimage.h
new file mode 100644
index 00000000..745facf4
--- /dev/null
+++ b/kuickshow/src/kuickimage.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+** $Id: .emacs,v 1.3 2002/02/20 15:06:53 gis Exp $
+**
+** Created : 2002
+**
+** Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+**
+****************************************************************************/
+
+#ifndef KUICKIMAGE_H
+#define KUICKIMAGE_H
+
+#include <qimage.h>
+#include <qobject.h>
+
+#include <kurl.h>
+
+#include "kuickdata.h"
+#include "kuickfile.h"
+
+// #include those AFTER Qt-includes!
+#include <Imlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+// #include <X11/extensions/shape.h>
+
+
+class KuickImage : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum ResizeMode { FAST, SMOOTH };
+
+ KuickImage( const KuickFile * file, ImlibImage *im, ImlibData *id );
+ ~KuickImage();
+
+ int width() const { return myWidth; }
+ int height() const { return myHeight; }
+ int originalWidth() const { return myOrigWidth; }
+ int originalHeight() const { return myOrigHeight; }
+
+ void resize( int width, int height, KuickImage::ResizeMode mode );
+ void restoreOriginalSize();
+ void rotate( Rotation rot );
+ bool rotateAbs( Rotation rot );
+ void flip( FlipMode flipMode );
+ bool flipAbs( int mode );
+ ImlibImage * imlibImage() const { return myIm; }
+ Pixmap& pixmap();
+ void renderPixmap();
+// const QString& filename() const { return myFilename;}
+ const KuickFile& file() const { return *myFile; }
+ const KURL& url() const { return myFile->url(); }
+
+ void setDirty( bool d ) { myIsDirty = d; }
+ bool isDirty() const { return myIsDirty; }
+ Rotation absRotation() const { return myRotation; }
+ FlipMode flipMode() const { return myFlipMode; }
+
+ static ImlibImage * toImage( ImlibData *id, QImage& image );
+
+private:
+ void fastResize( int newWidth, int newHeight );
+ bool smoothResize( int width, int height );
+ /**
+ * Note: caller must delete it!
+ */
+ QImage * newQImage() const;
+
+ const KuickFile * myFile;
+
+ int myWidth;
+ int myHeight;
+ ImlibImage * myOrigIm;
+ ImlibImage * myIm;
+ ImlibData * myId;
+ Pixmap myPixmap;
+ bool myIsDirty;
+
+ int myOrigWidth;
+ int myOrigHeight;
+ Rotation myRotation;
+ FlipMode myFlipMode;
+
+signals:
+ void startRendering();
+ void stoppedRendering();
+};
+
+
+#endif // KUICKIMAGE_H
diff --git a/kuickshow/src/kuickshow.cpp b/kuickshow/src/kuickshow.cpp
new file mode 100644
index 00000000..7e8718fb
--- /dev/null
+++ b/kuickshow/src/kuickshow.cpp
@@ -0,0 +1,1443 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2006 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <qdir.h>
+#include <qdesktopwidget.h>
+#include <qdialog.h>
+#include <qglobal.h>
+#include <qkeycode.h>
+#include <qlayout.h>
+#include <qsize.h>
+#include <qstring.h>
+
+#include <kaboutdata.h>
+#include <kaccel.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdeversion.h>
+#include <kfiledialog.h>
+#include <kfilemetainfo.h>
+#include <kglobal.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmenubar.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kprotocolinfo.h>
+#include <kpropertiesdialog.h>
+#include <kprotocolinfo.h>
+#include <kstatusbar.h>
+#include <kstdaction.h>
+#include <kstandarddirs.h>
+#include <kstartupinfo.h>
+#include <ktoolbar.h>
+#include <kurlcombobox.h>
+#include <kurlcompletion.h>
+#include <kurldrag.h>
+#include <kwin.h>
+#include <kstdguiitem.h>
+
+#include <kdebug.h>
+
+#include "aboutwidget.h"
+#include "filewidget.h"
+#include "filecache.h"
+#include "imdata.h"
+#include "imagewindow.h"
+#include "imlibwidget.h"
+#include "kuick.h"
+#include "kuickfile.h"
+
+#ifdef index
+#undef index
+#endif
+
+#include "kuickconfigdlg.h"
+#include "kuickdata.h"
+#include "kuickshow.h"
+#include "version.h"
+
+#ifdef KeyPress
+#undef KeyPress
+#endif
+
+KuickData* kdata;
+
+static const int URL_ITEM = 0;
+static const int META_ITEM = 1;
+
+QValueList<ImageWindow*> KuickShow::s_viewers;
+
+KuickShow::KuickShow( const char *name )
+ : KMainWindow( 0L, name ),
+ m_slideshowCycle( 1 ),
+ fileWidget( 0L ),
+ dialog( 0L ),
+ id( 0L ),
+ m_viewer( 0L ),
+ oneWindowAction( 0L ),
+ m_accel( 0L ),
+ m_delayedRepeatItem( 0L ),
+ m_slideShowStopped(false)
+{
+ aboutWidget = 0L;
+ kdata = new KuickData;
+ kdata->load();
+
+ initImlib();
+ resize( 400, 500 );
+
+ m_slideTimer = new QTimer( this );
+ connect( m_slideTimer, SIGNAL( timeout() ), SLOT( nextSlide() ));
+
+
+ KConfig *kc = KGlobal::config();
+
+ bool isDir = false; // true if we get a directory on the commandline
+
+ // parse commandline options
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ // files to display
+ // either a directory to display, an absolute path, a relative path, or a URL
+ KURL startDir;
+ startDir.setPath( QDir::currentDirPath() + '/' );
+
+ int numArgs = args->count();
+ if ( numArgs >= 10 )
+ {
+ // Even though the 1st i18n string will never be used, it needs to exist for plural handling - mhunter
+ if ( KMessageBox::warningYesNo(
+ this,
+ i18n("Do you really want to display this 1 image at the same time? This might be quite resource intensive and could overload your computer.<br>If you choose %1, only the first image will be shown.",
+ "Do you really want to display these %n images at the same time? This might be quite resource intensive and could overload your computer.<br>If you choose %1, only the first image will be shown.", numArgs).arg(KStdGuiItem::no().plainText()),
+ i18n("Display Multiple Images?"))
+ != KMessageBox::Yes )
+ {
+ numArgs = 1;
+ }
+ }
+
+ for ( int i = 0; i < numArgs; i++ ) {
+ KURL url = args->url( i );
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, url, false );
+
+ // for remote URLs, we don't know if it's a file or directory, but
+ // FileWidget::isImage() should correct in most cases.
+ // For non-local non-images, we just assume directory.
+
+ if ( FileWidget::isImage( &item ) )
+ {
+ showImage( &item, true, false, true ); // show in new window, not fullscreen-forced and move to 0,0
+// showImage( &item, true, false, false ); // show in new window, not fullscreen-forced and not moving to 0,0
+ }
+ else if ( item.isDir() )
+ {
+ startDir = url;
+ isDir = true;
+ }
+
+ // need to check remote files
+ else if ( !url.isLocalFile() )
+ {
+ KMimeType::Ptr mime = KMimeType::findByURL( url );
+ QString name = mime->name();
+ if ( name == "application/octet-stream" ) // unknown -> stat()
+ name = KIO::NetAccess::mimetype( url, this );
+
+ // text/* is a hack for bugs.kde.org-attached-images urls.
+ // The real problem here is that NetAccess::mimetype does a HTTP HEAD, which doesn't
+ // always return the right mimetype. The rest of KDE start a get() instead....
+ if ( name.startsWith( "image/" ) || name.startsWith( "text/" ) )
+ {
+ FileWidget::setImage( item, true );
+ showImage( &item, true, false, true );
+ }
+ else // assume directory, KDirLister will tell us if we can't list
+ {
+ startDir = url;
+ isDir = true;
+ }
+ }
+ // else // we don't handle local non-images
+ }
+
+ if ( (kdata->startInLastDir && args->count() == 0) || args->isSet( "lastfolder" )) {
+ kc->setGroup( "SessionSettings");
+ startDir = kc->readPathEntry( "CurrentDirectory", startDir.url() );
+ }
+
+ if ( s_viewers.isEmpty() || isDir ) {
+ initGUI( startDir );
+ if (!kapp->isRestored()) // during session management, readProperties() will show()
+ show();
+ }
+
+ else { // don't show browser, when image on commandline
+ hide();
+ KStartupInfo::appStarted();
+ }
+}
+
+
+KuickShow::~KuickShow()
+{
+ saveSettings();
+
+ if ( m_viewer )
+ m_viewer->close( true );
+
+ FileCache::shutdown();
+ free( id );
+ kapp->quit();
+
+ delete kdata;
+}
+
+// TODO convert to use xmlui file
+void KuickShow::initGUI( const KURL& startDir )
+{
+ KURL startURL( startDir );
+ if ( !KProtocolInfo::supportsListing( startURL ) )
+ startURL = KURL();
+
+ fileWidget = new FileWidget( startURL, this, "MainWidget" );
+ setFocusProxy( fileWidget );
+
+ KActionCollection *coll = fileWidget->actionCollection();
+
+ redirectDeleteAndTrashActions(coll);
+
+ connect( fileWidget, SIGNAL( fileSelected( const KFileItem * ) ),
+ this, SLOT( slotSelected( const KFileItem * ) ));
+
+ connect( fileWidget, SIGNAL( fileHighlighted( const KFileItem * )),
+ this, SLOT( slotHighlighted( const KFileItem * ) ));
+
+ connect( fileWidget, SIGNAL( urlEntered( const KURL& )),
+ this, SLOT( dirSelected( const KURL& )) );
+
+
+ fileWidget->setAcceptDrops(true);
+ connect( fileWidget, SIGNAL( dropped( const KFileItem *, QDropEvent *, const KURL::List & )),
+ this, SLOT( slotDropped( const KFileItem *, QDropEvent *, const KURL::List &)) );
+
+ // setup actions
+ KAction *open = KStdAction::open( this, SLOT( slotOpenURL() ),
+ coll, "openURL" );
+
+ KAction *print = KStdAction::print( this, SLOT( slotPrint() ),
+ coll, "kuick_print" );
+ print->setText( i18n("Print Image...") );
+
+ KAction *configure = new KAction( i18n("Configure %1...").arg( KGlobal::instance()->aboutData()->programName() ), "configure",
+ KShortcut(),
+ this, SLOT( configuration() ),
+ coll, "kuick_configure" );
+ KAction *slide = new KAction( i18n("Start Slideshow" ), "ksslide",
+ KShortcut( Key_F2 ),
+ this, SLOT( startSlideShow() ),
+ coll, "kuick_slideshow" );
+ KAction *about = new KAction( i18n( "About KuickShow" ), "about",
+ KShortcut(),
+ this, SLOT( about() ), coll, "about" );
+
+ oneWindowAction = new KToggleAction( i18n("Open Only One Image Window"),
+ "window_new",
+ KShortcut( CTRL+Key_N ), coll,
+ "kuick_one window" );
+
+ m_toggleBrowserAction = new KToggleAction( i18n("Show File Browser"), KShortcut( Key_Space ), coll, "toggleBrowser" );
+ m_toggleBrowserAction->setCheckedState(i18n("Hide File Browser"));
+ connect( m_toggleBrowserAction, SIGNAL( toggled( bool ) ),
+ SLOT( toggleBrowser() ));
+
+ KAction *showInOther = new KAction( i18n("Show Image"), KShortcut(),
+ this, SLOT( slotShowInOtherWindow() ),
+ coll, "kuick_showInOtherWindow" );
+ KAction *showInSame = new KAction( i18n("Show Image in Active Window"),
+ KShortcut(),
+ this, SLOT( slotShowInSameWindow() ),
+ coll, "kuick_showInSameWindow" );
+ KAction *showFullscreen = new KAction( i18n("Show Image in Fullscreen Mode"),
+ KShortcut(), this, SLOT( slotShowFullscreen() ),
+ coll, "kuick_showFullscreen" );
+
+ KAction *quit = KStdAction::quit( this, SLOT(slotQuit()), coll, "quit");
+
+ // remove QString::null parameter -- ellis
+ coll->readShortcutSettings( QString::null );
+ m_accel = coll->accel();
+
+ // menubar
+ KMenuBar *mBar = menuBar();
+ QPopupMenu *fileMenu = new QPopupMenu( mBar, "file" );
+ open->plug( fileMenu );
+ showInOther->plug( fileMenu );
+ showInSame->plug( fileMenu );
+ showFullscreen->plug( fileMenu );
+ fileMenu->insertSeparator();
+ slide->plug( fileMenu );
+ print->plug( fileMenu );
+ fileMenu->insertSeparator();
+ quit->plug( fileMenu );
+
+ QPopupMenu *editMenu = new QPopupMenu( mBar, "edit" );
+ coll->action("mkdir")->plug( editMenu );
+ coll->action("delete")->plug( editMenu );
+ editMenu->insertSeparator();
+ coll->action("properties")->plug( editMenu );
+
+
+ // remove the Sorting submenu (and the separator below)
+ // from the main contextmenu
+ KActionMenu *sortingMenu = static_cast<KActionMenu*>( coll->action("sorting menu"));
+ KActionMenu *mainActionMenu = static_cast<KActionMenu*>( coll->action("popupMenu"));
+ QPopupMenu *mainPopup = mainActionMenu->popupMenu();
+ int sortingIndex = mainPopup->indexOf( sortingMenu->itemId( 0 ) );
+ int separatorId = mainPopup->idAt( sortingIndex + 1 );
+ QMenuItem *separatorItem = mainPopup->findItem( separatorId );
+ if ( separatorItem && separatorItem->isSeparator() )
+ mainPopup->removeItem( separatorId );
+ mainActionMenu->remove( sortingMenu );
+
+ // add the sorting menu and a separator into the View menu
+ KActionMenu *viewActionMenu = static_cast<KActionMenu*>( coll->action("view menu"));
+ viewActionMenu->popupMenu()->insertSeparator( 0 );
+ sortingMenu->plug( viewActionMenu->popupMenu(), 0 ); // on top of the menu
+
+
+ QPopupMenu *settingsMenu = new QPopupMenu( mBar, "settings" );
+ configure->plug( settingsMenu );
+
+ mBar->insertItem( i18n("&File"), fileMenu );
+ mBar->insertItem( i18n("&Edit"), editMenu );
+ viewActionMenu->plug( mBar );
+ mBar->insertItem( i18n("&Settings"), settingsMenu );
+
+ // toolbar
+ KToolBar *tBar = toolBar();
+ tBar->setText( i18n( "Main Toolbar" ) );
+
+ coll->action("up")->plug( tBar );
+ coll->action("back")->plug( tBar );
+ coll->action("forward")->plug( tBar );
+ coll->action("home")->plug( tBar );
+ coll->action("reload")->plug( tBar );
+
+ tBar->insertSeparator();
+
+ coll->action( "short view" )->plug( tBar );
+ coll->action( "detailed view" )->plug( tBar );
+ coll->action( "preview")->plug( tBar );
+
+ tBar->insertSeparator();
+ configure->plug( tBar );
+ slide->plug( tBar );
+ tBar->insertSeparator();
+ oneWindowAction->plug( tBar );
+ print->plug( tBar );
+ tBar->insertSeparator();
+ about->plug( tBar );
+
+ QPopupMenu *help = helpMenu( QString::null, false );
+ mBar->insertItem( KStdGuiItem::help().text() , help );
+
+
+ KStatusBar* sBar = statusBar();
+ sBar->insertItem( " ", URL_ITEM, 10 );
+ sBar->insertItem( " ", META_ITEM, 2 );
+ sBar->setItemAlignment(URL_ITEM, QLabel::AlignVCenter | QLabel::AlignLeft);
+
+ fileWidget->setFocus();
+
+ KConfig *kc = KGlobal::config();
+ kc->setGroup("SessionSettings");
+ bool oneWindow = kc->readBoolEntry("OpenImagesInActiveWindow", true );
+ oneWindowAction->setChecked( oneWindow );
+
+ tBar->show();
+
+ // Address box in address tool bar
+ KToolBar *addressToolBar = toolBar( "address_bar" );
+ const int ID_ADDRESSBAR = 1;
+
+ cmbPath = new KURLComboBox( KURLComboBox::Directories,
+ true, addressToolBar, "address_combo_box" );
+ KURLCompletion *cmpl = new KURLCompletion( KURLCompletion::DirCompletion );
+ cmbPath->setCompletionObject( cmpl );
+ cmbPath->setAutoDeleteCompletionObject( true );
+
+ addressToolBar->insertWidget( ID_ADDRESSBAR, 1, cmbPath);
+ addressToolBar->setItemAutoSized( ID_ADDRESSBAR );
+
+ connect( cmbPath, SIGNAL( urlActivated( const KURL& )),
+ this, SLOT( slotSetURL( const KURL& )));
+ connect( cmbPath, SIGNAL( returnPressed()),
+ this, SLOT( slotURLComboReturnPressed()));
+
+
+ fileWidget->initActions();
+ fileWidget->clearHistory();
+ dirSelected( fileWidget->url() );
+
+ setCentralWidget( fileWidget );
+ setupGUI( KMainWindow::Save );
+
+ coll->action( "reload" )->setShortcut( KStdAccel::reload() );
+ coll->action( "short view" )->setShortcut(Key_F6);
+ coll->action( "detailed view" )->setShortcut(Key_F7);
+ coll->action( "show hidden" )->setShortcut(Key_F8);
+ coll->action( "mkdir" )->setShortcut(Key_F10);
+ coll->action( "preview" )->setShortcut(Key_F11);
+ coll->action( "separate dirs" )->setShortcut(Key_F12);
+}
+
+void KuickShow::redirectDeleteAndTrashActions(KActionCollection *coll)
+{
+ KAction *action = coll->action("delete");
+ if (action)
+ {
+ action->disconnect(fileWidget);
+ connect(action, SIGNAL(activated()), this, SLOT(slotDeleteCurrentImage()));
+ }
+
+ action = coll->action("trash");
+ if (action)
+ {
+ action->disconnect(fileWidget);
+ connect(action, SIGNAL(activated()), this, SLOT(slotTrashCurrentImage()));
+ }
+}
+
+void KuickShow::slotSetURL( const KURL& url )
+{
+ fileWidget->setURL( url, true );
+}
+
+void KuickShow::slotURLComboReturnPressed()
+{
+ KURL where = KURL::fromPathOrURL( cmbPath->currentText() );
+ slotSetURL( where );
+}
+
+void KuickShow::viewerDeleted()
+{
+ ImageWindow *viewer = (ImageWindow*) sender();
+ s_viewers.remove( viewer );
+ if ( viewer == m_viewer )
+ m_viewer = 0L;
+
+ if ( !haveBrowser() && s_viewers.isEmpty() ) {
+ saveSettings();
+ FileCache::shutdown();
+ ::exit(0);
+ }
+
+ else if ( haveBrowser() ) {
+ setActiveWindow();
+ // This setFocus() call causes problems in the combiview (always the
+ // directory view on the left gets the focus, which is not desired)
+ // fileWidget->setFocus();
+ }
+
+ if ( fileWidget )
+ // maybe a slideshow was stopped --> enable the action again
+ fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
+
+ m_slideTimer->stop();
+}
+
+
+void KuickShow::slotHighlighted( const KFileItem *fi )
+{
+ KFileItem *item = const_cast<KFileItem *>( fi );
+ statusBar()->changeItem( item->getStatusBarInfo(), URL_ITEM );
+ bool image = FileWidget::isImage( fi );
+
+ QString meta;
+ if ( image )
+ {
+ KFileMetaInfo info = item->metaInfo();
+ if ( info.isValid() )
+ {
+ meta = info.item( KFileMimeTypeInfo::Size ).string();
+ KFileMetaInfoGroup group = info.group( "Technical" );
+ if ( group.isValid() )
+ {
+ QString bpp = group.item( "BitDepth" ).string();
+ if ( !bpp.isEmpty() )
+ meta.append( ", " ).append( bpp );
+ }
+ }
+ }
+ statusBar()->changeItem( meta, META_ITEM );
+
+ fileWidget->actionCollection()->action("kuick_print")->setEnabled( image );
+ fileWidget->actionCollection()->action("kuick_showInSameWindow")->setEnabled( image );
+ fileWidget->actionCollection()->action("kuick_showInOtherWindow")->setEnabled( image );
+ fileWidget->actionCollection()->action("kuick_showFullscreen")->setEnabled( image );
+}
+
+void KuickShow::dirSelected( const KURL& url )
+{
+ if ( url.isLocalFile() )
+ setCaption( url.path() );
+ else
+ setCaption( url.prettyURL() );
+
+ cmbPath->setURL( url );
+ statusBar()->changeItem( url.prettyURL(), URL_ITEM );
+}
+
+void KuickShow::slotSelected( const KFileItem *item )
+{
+ showImage( item, !oneWindowAction->isChecked() );
+}
+
+// downloads item if necessary
+void KuickShow::showFileItem( ImageWindow * /*view*/,
+ const KFileItem * /*item*/ )
+{
+
+}
+
+bool KuickShow::showImage( const KFileItem *fi,
+ bool newWindow, bool fullscreen, bool moveToTopLeft )
+{
+ newWindow |= !m_viewer;
+ fullscreen |= (newWindow && kdata->fullScreen);
+ if ( FileWidget::isImage( fi ) ) {
+
+ if ( newWindow ) {
+ m_viewer = new ImageWindow( kdata->idata, id, 0L, "image window" );
+ m_viewer->setFullscreen( fullscreen );
+ s_viewers.append( m_viewer );
+
+ connect( m_viewer, SIGNAL( destroyed() ), SLOT( viewerDeleted() ));
+ connect( m_viewer, SIGNAL( sigFocusWindow( ImageWindow *) ),
+ this, SLOT( slotSetActiveViewer( ImageWindow * ) ));
+ connect( m_viewer, SIGNAL( sigImageError(const KuickFile *, const QString& ) ),
+ this, SLOT( messageCantLoadImage(const KuickFile *, const QString &) ));
+ connect( m_viewer, SIGNAL( requestImage( ImageWindow *, int )),
+ this, SLOT( slotAdvanceImage( ImageWindow *, int )));
+ connect( m_viewer, SIGNAL( pauseSlideShowSignal() ),
+ this, SLOT( pauseSlideShow() ) );
+ connect( m_viewer, SIGNAL (deleteImage (ImageWindow *)),
+ this, SLOT (slotDeleteCurrentImage (ImageWindow *)));
+ connect( m_viewer, SIGNAL (trashImage (ImageWindow *)),
+ this, SLOT (slotTrashCurrentImage (ImageWindow *)));
+ if ( s_viewers.count() == 1 && moveToTopLeft ) {
+ // we have to move to 0x0 before showing _and_
+ // after showing, otherwise we get some bogus geometry()
+ m_viewer->move( Kuick::workArea().topLeft() );
+ }
+
+ m_viewer->installEventFilter( this );
+ }
+
+ // for some strange reason, m_viewer sometimes changes during the
+ // next few lines of code, so as a workaround, we use safeViewer here.
+ // This happens when calling KuickShow with two or more remote-url
+ // arguments on the commandline, where the first one is loaded properly
+ // and the second isn't (e.g. because it is a pdf or something else,
+ // Imlib can't load).
+ ImageWindow *safeViewer = m_viewer;
+
+// file->waitForDownload( this );
+// QString filename;
+// KIO::NetAccess::download(fi->url(), filename, this);
+
+ if ( !safeViewer->showNextImage( fi->url() ) ) {
+ m_viewer = safeViewer;
+ safeViewer->close( true ); // couldn't load image, close window
+ }
+ else {
+// safeViewer->setFullscreen( fullscreen );
+
+ if ( newWindow ) {
+// safeViewer->show();
+
+ if ( !fullscreen && s_viewers.count() == 1 && moveToTopLeft ) {
+ // the WM might have moved us after showing -> strike back!
+ // move the first image to 0x0 workarea coord
+ safeViewer->move( Kuick::workArea().topLeft() );
+ }
+ }
+
+ if ( kdata->preloadImage && fileWidget ) {
+ KFileItem *item = 0L; // don't move cursor
+ item = fileWidget->getItem( FileWidget::Next, true );
+ if ( item )
+ safeViewer->cacheImage( item->url() );
+ }
+
+ m_viewer = safeViewer;
+ return true;
+ } // m_viewer created successfully
+ } // isImage
+
+ return false;
+}
+
+void KuickShow::slotDeleteCurrentImage()
+{
+ performDeleteCurrentImage(fileWidget);
+}
+
+void KuickShow::slotTrashCurrentImage()
+{
+ performTrashCurrentImage(fileWidget);
+}
+
+void KuickShow::slotDeleteCurrentImage(ImageWindow *viewer)
+{
+ if (!fileWidget) {
+ delayAction(new DelayedRepeatEvent(viewer, DelayedRepeatEvent::DeleteCurrentFile, 0L));
+ return;
+ }
+ performDeleteCurrentImage(viewer);
+}
+
+void KuickShow::slotTrashCurrentImage(ImageWindow *viewer)
+{
+ if (!fileWidget) {
+ delayAction(new DelayedRepeatEvent(viewer, DelayedRepeatEvent::TrashCurrentFile, 0L));
+ return;
+ }
+ performTrashCurrentImage(viewer);
+}
+
+void KuickShow::performDeleteCurrentImage(QWidget *parent)
+{
+ assert(fileWidget != 0L);
+
+ KFileItemList list;
+ KFileItem *item = fileWidget->getCurrentItem(false);
+ list.append (item);
+
+ if (KMessageBox::warningContinueCancel(
+ parent,
+ i18n("<qt>Do you really want to delete\n <b>'%1'</b>?</qt>").arg(item->url().pathOrURL()),
+ i18n("Delete File"),
+ KStdGuiItem::del(),
+ "Kuick_delete_current_image")
+ != KMessageBox::Continue)
+ {
+ return;
+ }
+
+ tryShowNextImage();
+ fileWidget->del(list, false, false);
+}
+
+void KuickShow::performTrashCurrentImage(QWidget *parent)
+{
+ assert(fileWidget != 0L);
+
+ KFileItemList list;
+ KFileItem *item = fileWidget->getCurrentItem(false);
+ if (!item) return;
+
+ list.append (item);
+
+ if (KMessageBox::warningContinueCancel(
+ parent,
+ i18n("<qt>Do you really want to trash\n <b>'%1'</b>?</qt>").arg(item->url().pathOrURL()),
+ i18n("Trash File"),
+ KGuiItem(i18n("to trash", "&Trash"),"edittrash"),
+ "Kuick_trash_current_image")
+ != KMessageBox::Continue)
+ {
+ return;
+ }
+
+ tryShowNextImage();
+ fileWidget->trash(list, parent, false, false);
+}
+
+void KuickShow::tryShowNextImage()
+{
+ // move to next file item even if we have no viewer
+ KFileItem *next = fileWidget->getNext(true);
+ if (!next)
+ next = fileWidget->getPrevious(true);
+
+ // ### why is this necessary at all? Why does KDirOperator suddenly re-read the
+ // entire directory after a file was deleted/trashed!? (KDirNotify is the reason)
+ if (!m_viewer)
+ return;
+
+ if (next)
+ showImage(next, false);
+ else
+ {
+ if (!haveBrowser())
+ {
+ // ### when simply calling toggleBrowser(), this main window is completely messed up
+ QTimer::singleShot(0, this, SLOT(toggleBrowser()));
+ }
+ m_viewer->deleteLater();
+ }
+}
+
+void KuickShow::startSlideShow()
+{
+ KFileItem *item = kdata->slideshowStartAtFirst ?
+ fileWidget->gotoFirstImage() :
+ fileWidget->getCurrentItem(false);
+
+ if ( item ) {
+ m_slideshowCycle = 1;
+ fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( false );
+ showImage( item, !oneWindowAction->isChecked(),
+ kdata->slideshowFullscreen );
+ if(kdata->slideDelay)
+ m_slideTimer->start( kdata->slideDelay );
+ }
+}
+
+void KuickShow::pauseSlideShow()
+{
+ if(m_slideShowStopped) {
+ if(kdata->slideDelay)
+ m_slideTimer->start( kdata->slideDelay );
+ m_slideShowStopped = false;
+ }
+ else {
+ m_slideTimer->stop();
+ m_slideShowStopped = true;
+ }
+}
+
+void KuickShow::nextSlide()
+{
+ if ( !m_viewer ) {
+ m_slideshowCycle = 1;
+ fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
+ return;
+ }
+
+ KFileItem *item = fileWidget->getNext( true );
+ if ( !item ) { // last image
+ if ( m_slideshowCycle < kdata->slideshowCycles
+ || kdata->slideshowCycles == 0 ) {
+ item = fileWidget->gotoFirstImage();
+ if ( item ) {
+ nextSlide( item );
+ m_slideshowCycle++;
+ return;
+ }
+ }
+
+ m_viewer->close( true );
+ fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
+ return;
+ }
+
+ nextSlide( item );
+}
+
+void KuickShow::nextSlide( KFileItem *item )
+{
+ m_viewer->showNextImage( item->url() );
+ if(kdata->slideDelay)
+ m_slideTimer->start( kdata->slideDelay );
+}
+
+
+// prints the selected files in the filebrowser
+void KuickShow::slotPrint()
+{
+ const KFileItemList *items = fileWidget->selectedItems();
+ if ( !items )
+ return;
+
+ KFileItemListIterator it( *items );
+
+ // don't show the image, just print
+ ImageWindow *iw = new ImageWindow( 0, id, this, "printing image" );
+ KFileItem *item;
+ while ( (item = it.current()) ) {
+ if (FileWidget::isImage( item ) && iw->loadImage( item->url() ))
+ iw->printImage();
+ ++it;
+ }
+
+ iw->close( true );
+}
+
+void KuickShow::slotShowInOtherWindow()
+{
+ showImage( fileWidget->getCurrentItem( false ), true );
+}
+
+void KuickShow::slotShowInSameWindow()
+{
+ showImage( fileWidget->getCurrentItem( false ), false );
+}
+
+void KuickShow::slotShowFullscreen()
+{
+ showImage( fileWidget->getCurrentItem( false ), false, true );
+}
+
+void KuickShow::slotDropped( const KFileItem *, QDropEvent *, const KURL::List &urls)
+{
+ KURL::List::ConstIterator it = urls.begin();
+ for ( ; it != urls.end(); ++it )
+ {
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, *it );
+ if ( FileWidget::isImage( &item ) )
+ showImage( &item, true );
+ else
+ fileWidget->setURL( *it, true );
+ }
+}
+
+// try to init the WM border as it is 0,0 when the window is not shown yet.
+void KuickShow::show()
+{
+ KMainWindow::show();
+ (void) Kuick::frameSize( winId() );
+}
+
+void KuickShow::slotAdvanceImage( ImageWindow *view, int steps )
+{
+ KFileItem *item = 0L; // to be shown
+ KFileItem *item_next = 0L; // to be cached
+
+ if ( steps == 0 )
+ return;
+
+ // the viewer might not be available yet. Factor this out somewhen.
+ if ( !fileWidget ) {
+ if ( m_delayedRepeatItem )
+ return;
+
+ delayAction(new DelayedRepeatEvent( view, DelayedRepeatEvent::AdvanceViewer, new int(steps) ));
+ return;
+ }
+
+ if ( steps > 0 ) {
+ for ( int i = 0; i < steps; i++ )
+ item = fileWidget->getNext( true );
+ item_next = fileWidget->getNext( false );
+ }
+
+ else if ( steps < 0 ) {
+ for ( int i = steps; i < 0; i++ )
+ item = fileWidget->getPrevious( true );
+ item_next = fileWidget->getPrevious( false );
+ }
+
+ if ( FileWidget::isImage( item ) ) {
+// QString filename;
+// KIO::NetAccess::download(item->url(), filename, this);
+ view->showNextImage( item->url() );
+ if (m_slideTimer->isActive() && kdata->slideDelay)
+ m_slideTimer->start( kdata->slideDelay );
+
+ if ( kdata->preloadImage && item_next ) { // preload next image
+ if ( FileWidget::isImage( item_next ) )
+ view->cacheImage( item_next->url() );
+ }
+
+ }
+}
+
+bool KuickShow::eventFilter( QObject *o, QEvent *e )
+{
+ if ( m_delayedRepeatItem ) // we probably need to install an eventFilter over
+ {
+ return true; // kapp, to make it really safe
+ }
+
+ bool ret = false;
+ int eventType = e->type();
+ QKeyEvent *k = 0L;
+ if ( eventType == QEvent::KeyPress )
+ k = static_cast<QKeyEvent *>( e );
+
+ if ( k ) {
+ if ( KStdAccel::quit().contains( KKey( k ) ) ) {
+ saveSettings();
+ deleteAllViewers();
+ FileCache::shutdown();
+ ::exit(0);
+ }
+ else if ( KStdAccel::help().contains( KKey( k ) ) ) {
+ appHelpActivated();
+ return true;
+ }
+ }
+
+
+ ImageWindow *window = dynamic_cast<ImageWindow*>( o );
+
+ if ( window ) {
+ // The XWindow used to display Imlib's image is being resized when
+ // switching images, causing enter- and leaveevents for this
+ // ImageWindow, leading to the cursor being unhidden. So we simply
+ // don't pass those events to KCursor to prevent that.
+ if ( eventType != QEvent::Leave && eventType != QEvent::Enter )
+ KCursor::autoHideEventFilter( o, e );
+
+ m_viewer = window;
+ QString img;
+ KFileItem *item = 0L; // the image to be shown
+ KFileItem *item_next = 0L; // the image to be cached
+
+ if ( k ) { // keypress
+ ret = true;
+ int key = k->key();
+
+ // Key_Shift shouldn't load the browser in nobrowser mode, it
+ // is used for zooming in the imagewindow
+ // Key_Alt shouldn't either - otherwise Alt+F4 doesn't work, the
+ // F4 gets eaten (by NetAccess' modal dialog maybe?)
+
+ if ( !fileWidget )
+ {
+ if ( key != Key_Escape && key != Key_Shift && key != Key_Alt )
+ {
+ KuickFile *file = m_viewer->currentFile();
+// QFileInfo fi( m_viewer->filename() );
+// start.setPath( fi.dirPath( true ) );
+ initGUI( file->url().upURL() );
+
+ // the fileBrowser will list the start-directory
+ // asynchronously so we can't immediately continue. There
+ // is no current-item and no next-item (actually no item
+ // at all). So we tell the browser the initial
+ // current-item and wait for it to tell us when it's ready.
+ // Then we will replay this KeyEvent.
+ delayedRepeatEvent( m_viewer, k );
+
+ // OK, once again, we have a problem with the now async and
+ // sync KDirLister :( If the startDir is already cached by
+ // KDirLister, we won't ever get that finished() signal
+ // because it is emitted before we can connect(). So if
+ // our dirlister has a rootFileItem, we assume the
+ // directory is read already and simply call
+ // slotReplayEvent() without the need for the finished()
+ // signal.
+
+ // see slotAdvanceImage() for similar code
+ if ( fileWidget->dirLister()->isFinished() )
+ {
+ if ( fileWidget->dirLister()->rootItem() )
+ {
+ fileWidget->setCurrentItem( file->url().fileName() );
+ QTimer::singleShot( 0, this, SLOT( slotReplayEvent()));
+ }
+ else // finished, but no root-item -- probably an error, kill repeat-item!
+ {
+ abortDelayedEvent();
+ }
+ }
+ else // not finished yet
+ {
+ fileWidget->setInitialItem( file->url().fileName() );
+ connect( fileWidget, SIGNAL( finished() ),
+ SLOT( slotReplayEvent() ));
+ }
+
+ return true;
+ }
+
+ return KMainWindow::eventFilter( o, e );
+ }
+
+ // we definitely have a fileWidget here!
+
+ KKey kkey( k );
+ if ( key == Key_Home || KStdAccel::home().contains( kkey ) )
+ {
+ item = fileWidget->gotoFirstImage();
+ item_next = fileWidget->getNext( false );
+ }
+
+ else if ( key == Key_End || KStdAccel::end().contains( kkey ) )
+ {
+ item = fileWidget->gotoLastImage();
+ item_next = fileWidget->getPrevious( false );
+ }
+
+ else if ( fileWidget->actionCollection()->action("delete")->shortcut().contains( key ))
+ {
+ kdDebug() << "WOW, deletion happens here!" << endl;
+// KFileItem *cur = fileWidget->getCurrentItem( false );
+ (void) fileWidget->getCurrentItem( false );
+ item = fileWidget->getNext( false ); // don't move
+ if ( !item )
+ item = fileWidget->getPrevious( false );
+ KFileItem it( KFileItem::Unknown, KFileItem::Unknown,
+ m_viewer->url() );
+ KFileItemList list;
+ list.append( &it );
+ if ( fileWidget->del(list, window,
+ (k->state() & ShiftButton) == 0) == 0L )
+ return true; // aborted deletion
+
+ // ### check failure asynchronously and restore old item?
+ fileWidget->setCurrentItem( item );
+ }
+
+ else if ( m_toggleBrowserAction->shortcut().contains( key ) )
+ {
+ toggleBrowser();
+ return true; // don't pass keyEvent
+ }
+
+ else
+ ret = false;
+
+
+ if ( FileWidget::isImage( item ) ) {
+// QString filename;
+// KIO::NetAccess::download(item->url(), filename, this);
+ m_viewer->showNextImage( item->url() );
+
+ if ( kdata->preloadImage && item_next ) { // preload next image
+ if ( FileWidget::isImage( item_next ) )
+ m_viewer->cacheImage( item_next->url() );
+ }
+
+ ret = true; // don't pass keyEvent
+ }
+ } // keyPressEvent on ImageWindow
+
+
+ // doubleclick closes image window
+ // and shows browser when last window closed via doubleclick
+ else if ( eventType == QEvent::MouseButtonDblClick )
+ {
+ QMouseEvent *ev = static_cast<QMouseEvent*>( e );
+ if ( ev->button() == LeftButton )
+ {
+ if ( s_viewers.count() == 1 )
+ {
+ if ( !fileWidget )
+ {
+// KURL start;
+// QFileInfo fi( window->filename() );
+// start.setPath( fi.dirPath( true ) );
+ initGUI( window->currentFile()->url().fileName() );
+ }
+ show();
+ raise();
+ }
+
+ window->close( true );
+
+ ev->accept();
+ ret = true;
+ }
+ }
+
+ } // isA ImageWindow
+
+
+ if ( ret )
+ return true;
+
+ return KMainWindow::eventFilter( o, e );
+}
+
+void KuickShow::configuration()
+{
+ if ( !m_accel ) {
+ KURL start;
+ start.setPath( QDir::homeDirPath() );
+ initGUI( KURL::fromPathOrURL( QDir::homeDirPath() ) );
+ }
+
+ dialog = new KuickConfigDialog( fileWidget->actionCollection(), 0L,
+ "dialog", false );
+ dialog->resize( 540, 510 );
+ dialog->setIcon( kapp->miniIcon() );
+
+ connect( dialog, SIGNAL( okClicked() ),
+ this, SLOT( slotConfigApplied() ) );
+ connect( dialog, SIGNAL( applyClicked() ),
+ this, SLOT( slotConfigApplied() ) );
+ connect( dialog, SIGNAL( finished() ),
+ this, SLOT( slotConfigClosed() ) );
+
+ fileWidget->actionCollection()->action( "kuick_configure" )->setEnabled( false );
+ dialog->show();
+}
+
+
+void KuickShow::slotConfigApplied()
+{
+ dialog->applyConfig();
+
+ initImlib();
+ kdata->save();
+
+ ImageWindow *viewer;
+ QValueListIterator<ImageWindow*> it = s_viewers.begin();
+ while ( it != s_viewers.end() ) {
+ viewer = *it;
+ viewer->updateActions();
+ ++it;
+ }
+
+ fileWidget->reloadConfiguration();
+}
+
+
+void KuickShow::slotConfigClosed()
+{
+ dialog->delayedDestruct();
+ fileWidget->actionCollection()->action( "kuick_configure" )->setEnabled( true );
+}
+
+void KuickShow::about()
+{
+ if ( !aboutWidget )
+ aboutWidget = new AboutWidget( 0L, "about" );
+
+ aboutWidget->adjustSize();
+
+#if KDE_VERSION >= 310
+ KDialog::centerOnScreen( aboutWidget );
+#else
+// Not fixed because it must be dead code now.
+ QDesktopWidget *desktop = QApplication::desktop();
+ int screen = desktop->screenNumber( aboutWidget );
+ if ( screen == -1 )
+ screen = desktop->primaryScreen();
+
+ QRect r = desktop->screenGeometry( screen );
+ aboutWidget->move( r.center().x() - aboutWidget->width()/2,
+ r.center().y() - aboutWidget->height()/2 );
+#endif
+
+ aboutWidget->show();
+}
+
+// ------ sessionmanagement - load / save current directory -----
+void KuickShow::readProperties( KConfig *kc )
+{
+ assert( fileWidget ); // from SM, we should always have initGUI on startup
+ QString dir = kc->readPathEntry( "CurrentDirectory" );
+ if ( !dir.isEmpty() ) {
+ fileWidget->setURL( KURL::fromPathOrURL( dir ), true );
+ fileWidget->clearHistory();
+ }
+
+ const KURL& listedURL = fileWidget->url();
+ QStringList images = kc->readPathListEntry( "Images shown" );
+ QStringList::Iterator it;
+ bool hasCurrentURL = false;
+
+ for ( it = images.begin(); it != images.end(); ++it ) {
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, KURL::fromPathOrURL( *it ), false );
+ if ( item.isReadable() )
+ if ( showImage( &item, true ) ) {
+ // Set the current URL in the file widget, if possible
+ if ( !hasCurrentURL && listedURL.isParentOf( item.url() ))
+ fileWidget->setInitialItem( item.url().fileName() );
+ hasCurrentURL = true;
+ }
+ }
+
+ bool visible = kc->readBoolEntry( "Browser visible", false );
+ if ( visible || s_viewers.isEmpty() )
+ show();
+}
+
+void KuickShow::saveProperties( KConfig *kc )
+{
+ kc->writeEntry( "Browser visible", fileWidget && fileWidget->isVisible() );
+ if (fileWidget)
+ kc->writePathEntry( "CurrentDirectory", fileWidget->url().url() );
+
+ QStringList urls;
+ QValueListIterator<ImageWindow*> it;
+ for ( it = s_viewers.begin(); it != s_viewers.end(); ++it )
+ {
+ const KURL& url = (*it)->currentFile()->url();
+ if ( url.isLocalFile() )
+ urls.append( url.path() );
+ else
+ urls.append( url.prettyURL() ); // ### check if writePathEntry( prettyURL ) works!
+ }
+
+ kc->writePathEntry( "Images shown", urls );
+}
+
+// --------------------------------------------------------------
+
+void KuickShow::saveSettings()
+{
+ KConfig *kc = KGlobal::config();
+
+ kc->setGroup("SessionSettings");
+ if ( oneWindowAction )
+ kc->writeEntry( "OpenImagesInActiveWindow", oneWindowAction->isChecked() );
+
+ if ( fileWidget ) {
+ kc->writePathEntry( "CurrentDirectory", fileWidget->url().prettyURL() ); // ### was url().url()
+ fileWidget->writeConfig( kc, "Filebrowser" );
+ }
+
+ kc->sync();
+}
+
+
+void KuickShow::messageCantLoadImage( const KuickFile *, const QString& message )
+{
+ m_viewer->clearFocus();
+ KMessageBox::information( m_viewer, message, i18n("Error"), "kuick_cant_load_image" );
+}
+
+void KuickShow::initImlib()
+{
+ ImData *idata = kdata->idata;
+ ImlibInitParams par;
+ initImlibParams( idata, &par );
+
+ id = Imlib_init_with_params( x11Display(), &par );
+ if ( !id ) {
+ initImlibParams( idata, &par );
+
+ qWarning("*** KuickShow: Whoops, can't initialize imlib, trying my own palettefile now.");
+ QString paletteFile = locate( "data", "kuickshow/im_palette.pal" );
+ // ### - does the qstrdup() cure the segfault in imlib eventually?
+ char *file = qstrdup( paletteFile.local8Bit() );
+ par.palettefile = file;
+ par.flags |= PARAMS_PALETTEFILE;
+
+ qWarning("Palettefile: %s", par.palettefile );
+
+ id = Imlib_init_with_params( x11Display(), &par );
+
+ if ( !id ) {
+ QString tmp = i18n("Unable to initialize \"Imlib\".\n"
+ "Start kuickshow from the command line "
+ "and look for error messages.\n"
+ "The program will now quit.");
+ KMessageBox::error( this, tmp, i18n("Fatal Imlib Error") );
+
+ FileCache::shutdown();
+ ::exit(1);
+ }
+ }
+}
+
+
+void KuickShow::initImlibParams( ImData *idata, ImlibInitParams *par )
+{
+ par->flags = ( PARAMS_REMAP | PARAMS_VISUALID | PARAMS_SHAREDMEM | PARAMS_SHAREDPIXMAPS |
+ PARAMS_FASTRENDER | PARAMS_HIQUALITY | PARAMS_DITHER |
+ PARAMS_IMAGECACHESIZE | PARAMS_PIXMAPCACHESIZE );
+
+ Visual* defaultvis = DefaultVisual(x11Display(), x11Screen());
+
+ par->paletteoverride = idata->ownPalette ? 1 : 0;
+ par->remap = idata->fastRemap ? 1 : 0;
+ par->fastrender = idata->fastRender ? 1 : 0;
+ par->hiquality = idata->dither16bit ? 1 : 0;
+ par->dither = idata->dither8bit ? 1 : 0;
+ par->sharedmem = 1;
+ par->sharedpixmaps = 1;
+ par->visualid = defaultvis->visualid;
+ uint maxcache = idata->maxCache;
+
+ // 0 == no cache
+ par->imagecachesize = maxcache * 1024;
+ par->pixmapcachesize = maxcache * 1024;
+}
+
+bool KuickShow::haveBrowser() const
+{
+ return fileWidget && fileWidget->isVisible();
+}
+
+void KuickShow::delayedRepeatEvent( ImageWindow *w, QKeyEvent *e )
+{
+ m_delayedRepeatItem = new DelayedRepeatEvent( w, new QKeyEvent( *e ) );
+}
+
+void KuickShow::abortDelayedEvent()
+{
+ delete m_delayedRepeatItem;
+ m_delayedRepeatItem = 0L;
+}
+
+void KuickShow::slotReplayEvent()
+{
+ disconnect( fileWidget, SIGNAL( finished() ),
+ this, SLOT( slotReplayEvent() ));
+
+ DelayedRepeatEvent *e = m_delayedRepeatItem;
+ m_delayedRepeatItem = 0L; // otherwise, eventFilter aborts
+
+ eventFilter( e->viewer, e->event );
+ delete e;
+
+ // ### WORKAROUND for QIconView bug in Qt <= 3.0.3 at least
+ if ( fileWidget && fileWidget->view() ) {
+ QWidget *widget = fileWidget->view()->widget();
+ if ( widget->inherits( "QIconView" ) || widget->child(0, "QIconView" ) ){
+ fileWidget->setSorting( fileWidget->sorting() );
+ }
+ }
+ // --------------------------------------------------------------
+}
+
+void KuickShow::replayAdvance(DelayedRepeatEvent *event)
+{
+ // ### WORKAROUND for QIconView bug in Qt <= 3.0.3 at least
+ // Sigh. According to qt-bugs, they won't fix this bug ever. So you can't
+ // rely on sorting to be correct before the QIconView has been show()n.
+ if ( fileWidget && fileWidget->view() ) {
+ QWidget *widget = fileWidget->view()->widget();
+ if ( widget->inherits( "QIconView" ) || widget->child(0, "QIconView" ) ){
+ fileWidget->setSorting( fileWidget->sorting() );
+ }
+ }
+ // --------------------------------------------------------------
+
+ slotAdvanceImage( event->viewer, *(int *) (event->data) );
+}
+
+void KuickShow::delayAction(DelayedRepeatEvent *event)
+{
+ if (m_delayedRepeatItem)
+ return;
+
+ m_delayedRepeatItem = event;
+
+ KURL url = event->viewer->currentFile()->url();
+// QFileInfo fi( event->viewer->filename() );
+// start.setPath( fi.dirPath( true ) );
+ initGUI( url.upURL() );
+
+ // see eventFilter() for explanation and similar code
+ if ( fileWidget->dirLister()->isFinished() &&
+ fileWidget->dirLister()->rootItem() )
+ {
+ fileWidget->setCurrentItem( url.fileName() );
+ QTimer::singleShot( 0, this, SLOT( doReplay()));
+ }
+ else
+ {
+ fileWidget->setInitialItem( url.fileName() );
+ connect( fileWidget, SIGNAL( finished() ),
+ SLOT( doReplay() ));
+ }
+}
+
+void KuickShow::doReplay()
+{
+ if (!m_delayedRepeatItem)
+ return;
+
+ disconnect( fileWidget, SIGNAL( finished() ),
+ this, SLOT( doReplay() ));
+
+ switch (m_delayedRepeatItem->action)
+ {
+ case DelayedRepeatEvent::DeleteCurrentFile:
+ performDeleteCurrentImage((QWidget *) m_delayedRepeatItem->data);
+ break;
+ case DelayedRepeatEvent::TrashCurrentFile:
+ performTrashCurrentImage((QWidget *) m_delayedRepeatItem->data);
+ break;
+ case DelayedRepeatEvent::AdvanceViewer:
+ replayAdvance(m_delayedRepeatItem);
+ break;
+ default:
+ kdWarning() << "doReplay: unknown action -- ignoring: " << m_delayedRepeatItem->action << endl;
+ break;
+ }
+
+ delete m_delayedRepeatItem;
+ m_delayedRepeatItem = 0L;
+}
+
+void KuickShow::toggleBrowser()
+{
+ if ( !haveBrowser() ) {
+ if ( m_viewer && m_viewer->isFullscreen() )
+ m_viewer->setFullscreen( false );
+ fileWidget->resize( size() ); // ### somehow fileWidget isn't resized!?
+ show();
+ raise();
+ KWin::activateWindow( winId() ); // ### this should not be necessary
+// setFocus();
+ }
+ else if ( !s_viewers.isEmpty() )
+ hide();
+}
+
+void KuickShow::slotOpenURL()
+{
+ KFileDialog dlg(QString::null, kdata->fileFilter, this, "filedialog", true);
+ dlg.setMode( KFile::Files | KFile::Directory );
+ dlg.setCaption( i18n("Select Files or Folder to Open") );
+
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ KURL::List urls = dlg.selectedURLs();
+ KURL::List::ConstIterator it = urls.begin();
+ for ( ; it != urls.end(); ++it )
+ {
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, *it );
+ if ( FileWidget::isImage( &item ) )
+ showImage( &item, true );
+ else
+ fileWidget->setURL( *it, true );
+ }
+ }
+}
+
+void KuickShow::deleteAllViewers()
+{
+ QValueListIterator<ImageWindow*> it = s_viewers.begin();
+ for ( ; it != s_viewers.end(); ++it ) {
+ (*it)->disconnect( SIGNAL( destroyed() ), this, SLOT( viewerDeleted() ));
+ (*it)->close( true );
+ }
+
+ s_viewers.clear();
+ m_viewer = 0L;
+}
+
+KActionCollection * KuickShow::actionCollection() const
+{
+ if ( fileWidget )
+ return fileWidget->actionCollection();
+
+ return KMainWindow::actionCollection();
+}
+
+#include "kuickshow.moc"
diff --git a/kuickshow/src/kuickshow.desktop b/kuickshow/src/kuickshow.desktop
new file mode 100644
index 00000000..b2e2ee37
--- /dev/null
+++ b/kuickshow/src/kuickshow.desktop
@@ -0,0 +1,93 @@
+[Desktop Entry]
+Name=Kuickshow
+Name[af]=Vinnig-vertoon
+Name[ar]=عرض سريع
+Name[eo]=Rapidmontrilo
+Name[fr]=KuickShow
+Name[hi]=क्विक-शो
+Name[it]=KuickShow
+Name[ko]=K퀵쇼
+Name[ne]=क्विकशो
+Name[pt_BR]=KRápida Exibição
+Name[ta]=விரைவுகாட்சி
+Name[th]=ดูภาพด่วน - K
+Name[ven]=Musumbedzo wa kuick
+Name[zh_TW]=Kuickshow 快秀
+Name[zu]=I Kuickshow
+Exec=kuickshow %i %m -caption "%c" %U
+Icon=kuickshow
+Type=Application
+MimeType=image/gif;image/x-xpm;image/x-xbm;image/jpeg;image/png;image/tiff;image/x-bmp;image/x-psd;image/x-eim;image/x-portable-bitmap;image/x-portable-pixmap;image/x-portable-greymap;
+DocPath=kuickshow/index.html
+Terminal=false
+InitialPreference=6
+
+GenericName=Image Viewer
+GenericName[af]=Beeld Aansig
+GenericName[ar]=عارض صور
+GenericName[bg]=Преглед на изображения
+GenericName[br]=Gweler ar skeudennoù
+GenericName[bs]=Preglednik slika
+GenericName[ca]=Visualitzador d'imatges
+GenericName[cs]=Prohlížeč obrázků
+GenericName[cy]=Gwelydd Delweddau
+GenericName[da]=Billedfremviser
+GenericName[de]=Bildbetrachter
+GenericName[el]=Προβολέας εικόνων
+GenericName[eo]=Bildorigardilo
+GenericName[es]=Visor de imágenes
+GenericName[et]=Pildifailide näitaja
+GenericName[eu]=Irudi ikustailua
+GenericName[fa]=مشاهده‌گر تصویر
+GenericName[fi]=Kuvannäytin
+GenericName[fr]=Afficheur d'images
+GenericName[ga]=Amharcán Íomhánna
+GenericName[gl]=Visor de imaxes
+GenericName[he]=מציג תמונות
+GenericName[hi]=छवि प्रदर्शक
+GenericName[hr]=Preglednik slika
+GenericName[hu]=Képnézegető
+GenericName[is]=Myndaskoðari
+GenericName[it]=Visore di immagini
+GenericName[ja]=画像ビューア
+GenericName[kk]=Кескіндерді қарау
+GenericName[km]=កម្មវិធី​មើល​រូបភាព
+GenericName[lt]=Paveikslėlių žiūriklis
+GenericName[lv]=Attēlu Skatītājs
+GenericName[ms]=Paparan Imej
+GenericName[mt]=Werrej tal-istampi
+GenericName[nb]=Bildefremviser
+GenericName[nds]=Bildkieker
+GenericName[ne]=छवि दर्शक
+GenericName[nl]=Afbeeldingenweergaveprogramma
+GenericName[nn]=Biletvisar
+GenericName[nso]=Molebeledi wa Ponagalo
+GenericName[pa]=ਚਿੱਤਰ ਦਰਸ਼ਕ
+GenericName[pl]=Przeglądarka obrazków
+GenericName[pt]=Visualizador de Imagens
+GenericName[pt_BR]=Visualizador de Imagens
+GenericName[ro]=Vizualizor de imagini
+GenericName[ru]=Просмотр изображений
+GenericName[rw]=Mugaraza Shusho
+GenericName[se]=Govvačájeheaddji
+GenericName[sk]=Prehliadač obrázkov
+GenericName[sl]=Pregledovalnik slik
+GenericName[sr]=Приказивач слика
+GenericName[sr@Latn]=Prikazivač slika
+GenericName[sv]=Bildvisare
+GenericName[ta]=பிம்ப காட்சி
+GenericName[tg]=Намоиши тасвирот
+GenericName[th]=เครื่องมือแสดงภาพ
+GenericName[tr]=Resim Göstericisi
+GenericName[uk]=Переглядач зображень
+GenericName[uz]=Rasm koʻruvchi
+GenericName[uz@cyrillic]=Расм кўрувчи
+GenericName[ven]=Tshivhoni tsha Mutaleli
+GenericName[wa]=Håyneu d' imådjes
+GenericName[xh]=Umboniseli Womfanekiso
+GenericName[zh_CN]=图片查看程序
+GenericName[zh_HK]=圖像檢視器
+GenericName[zh_TW]=影像檢視程式
+GenericName[zu]=Umbonisi Womfanekiso
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Graphics;
diff --git a/kuickshow/src/kuickshow.h b/kuickshow/src/kuickshow.h
new file mode 100644
index 00000000..d6239b64
--- /dev/null
+++ b/kuickshow/src/kuickshow.h
@@ -0,0 +1,178 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2006 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKSHOW_H
+#define KUICKSHOW_H
+
+#include <qevent.h>
+#include <qguardedptr.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <kfileitem.h>
+#include <kmainwindow.h>
+#include <kurl.h>
+
+#include <Imlib.h>
+
+#include "aboutwidget.h"
+
+class FileWidget;
+class ImageWindow;
+class ImData;
+class KuickConfigDialog;
+
+class KAccel;
+class KConfig;
+class KToggleAction;
+class AboutWidget;
+
+class KURL;
+class KURLComboBox;
+
+class KuickFile;
+
+class DelayedRepeatEvent
+{
+public:
+ DelayedRepeatEvent( ImageWindow *view, QKeyEvent *ev ) {
+ viewer = view;
+ event = ev;
+ }
+ DelayedRepeatEvent( ImageWindow *view, int action, void *data ) {
+ this->viewer = view;
+ this->action = action;
+ this->data = data;
+ this->event = 0L;
+ }
+
+ ~DelayedRepeatEvent() {
+ delete event;
+ }
+
+ enum Action
+ {
+ DeleteCurrentFile,
+ TrashCurrentFile,
+ AdvanceViewer
+ };
+
+ ImageWindow *viewer;
+ QKeyEvent *event;
+ int action;
+ void *data;
+};
+
+
+class KuickShow : public KMainWindow
+{
+ Q_OBJECT
+
+public:
+ KuickShow( const char *name=0 );
+ ~KuickShow();
+
+ virtual void show();
+ static QValueList<ImageWindow*> s_viewers;
+
+ // overridden to make KDCOPActionProxy work -- all our actions are not
+ // in the mainwindow's collection, but in the filewidget's.
+ virtual KActionCollection* actionCollection() const;
+
+
+protected:
+ virtual void readProperties( KConfig * );
+ void initImlibParams( ImData *, ImlibInitParams * );
+ void tryShowNextImage();
+
+private slots:
+ void toggleBrowser();
+ void slotQuit() { delete this; }
+ void slotPrint();
+ void slotConfigApplied();
+ void slotConfigClosed();
+ void messageCantLoadImage( const KuickFile * file, const QString& message);
+ bool showImage(const KFileItem *, bool newWindow = false,
+ bool fullscreen = false, bool moveToTopLeft = true );
+ void showFileItem( ImageWindow *, const KFileItem * );
+ void slotHighlighted( const KFileItem * );
+ void slotSelected( const KFileItem * );
+ void dirSelected( const KURL& );
+ void configuration();
+ void about();
+ void startSlideShow();
+ void pauseSlideShow();
+ void nextSlide();
+ void nextSlide( KFileItem *item );
+ void viewerDeleted();
+ void slotDropped( const KFileItem *, QDropEvent *, const KURL::List &);
+ void slotSetActiveViewer( ImageWindow *i ) { m_viewer = i; }
+ void slotAdvanceImage( ImageWindow *, int steps );
+
+ void slotShowInSameWindow();
+ void slotShowInOtherWindow();
+ void slotShowFullscreen();
+
+ void slotReplayEvent();
+ void slotOpenURL();
+ void slotSetURL( const KURL& );
+ void slotURLComboReturnPressed();
+// void invalidateImages( const KFileItemList& items );
+ void slotDeleteCurrentImage(ImageWindow *viewer);
+ void slotTrashCurrentImage(ImageWindow *viewer);
+ void slotDeleteCurrentImage();
+ void slotTrashCurrentImage();
+
+ void doReplay();
+
+private:
+ void initGUI( const KURL& startDir );
+ bool eventFilter( QObject *, QEvent * );
+ void initImlib();
+ void saveProperties( KConfig * );
+ void saveSettings();
+ bool haveBrowser() const;
+ void delayedRepeatEvent( ImageWindow *, QKeyEvent * );
+ void abortDelayedEvent();
+ void deleteAllViewers();
+ void redirectDeleteAndTrashActions(KActionCollection *coll);
+
+ void delayAction(DelayedRepeatEvent *event);
+ void replayAdvance(DelayedRepeatEvent *event);
+
+ void performDeleteCurrentImage(QWidget *parent);
+ void performTrashCurrentImage(QWidget *parent);
+
+ uint viewItem, renameItem, deleteItem, printItem;
+ uint m_slideshowCycle;
+
+ FileWidget *fileWidget;
+ KURLComboBox *cmbPath;
+ KuickConfigDialog *dialog;
+ ImlibData *id;
+ ImageWindow *m_viewer;
+ KToggleAction *oneWindowAction;
+ KAccel *m_accel;
+ DelayedRepeatEvent *m_delayedRepeatItem;
+ QTimer *m_slideTimer;
+ bool m_slideShowStopped;
+ KToggleAction *m_toggleBrowserAction;
+ QGuardedPtr<AboutWidget> aboutWidget;
+};
+
+#endif
diff --git a/kuickshow/src/kurlwidget.cpp b/kuickshow/src/kurlwidget.cpp
new file mode 100644
index 00000000..0a23fa3a
--- /dev/null
+++ b/kuickshow/src/kurlwidget.cpp
@@ -0,0 +1,42 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998,1999,2000 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qtooltip.h>
+
+#include <kurl.h>
+#include <krun.h>
+
+#include "kurlwidget.h"
+
+KURLWidget::KURLWidget(const QString& text, QWidget *parent, const char *name)
+ : KURLLabel( parent, name )
+{
+ setText( text );
+ connect( this, SIGNAL( leftClickedURL() ), SLOT( run() ));
+ setUseTips( true );
+}
+
+void KURLWidget::run()
+{
+ KURL ku( url() );
+ if ( ku.isValid() ) {
+ (void) new KRun( ku, this );
+ }
+}
+
+#include "kurlwidget.moc"
diff --git a/kuickshow/src/kurlwidget.h b/kuickshow/src/kurlwidget.h
new file mode 100644
index 00000000..2f35e009
--- /dev/null
+++ b/kuickshow/src/kurlwidget.h
@@ -0,0 +1,36 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998,1999,2000 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KURLWIDGET_H
+#define KURLWIDGET_H
+
+#include <kurllabel.h>
+
+class KURLWidget : public KURLLabel
+{
+ Q_OBJECT
+
+public:
+ KURLWidget( const QString& text, QWidget *, const char *name=0 );
+
+protected slots:
+ virtual void run();
+
+};
+
+#endif
diff --git a/kuickshow/src/main.cpp b/kuickshow/src/main.cpp
new file mode 100644
index 00000000..dfb462f0
--- /dev/null
+++ b/kuickshow/src/main.cpp
@@ -0,0 +1,66 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qstring.h>
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "kuickshow.h"
+#include "version.h"
+
+static KCmdLineOptions options[] =
+{
+ { "lastfolder", I18N_NOOP("Start in the last visited folder, not the "
+ "current working folder."), 0 },
+ { "d", 0, 0 }, // short option for --lastdir
+ { "+[files]", I18N_NOOP("Optional image filenames/urls to show"), 0 },
+ KCmdLineLastOption
+};
+
+extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
+{
+ KAboutData about(
+ "kuickshow", I18N_NOOP( "KuickShow" ), KUICKSHOWVERSION,
+ I18N_NOOP("A fast and versatile image viewer" ),
+ KAboutData::License_GPL, "(c) 1998-2006, Carsten Pfeiffer",
+ 0 /*text*/, "http://devel-home.kde.org/~pfeiffer/" );
+
+ about.addAuthor( "Carsten Pfeiffer", 0, "pfeiffer@kde.org",
+ "http://devel-home.kde.org/~pfeiffer/" );
+ about.addCredit( "Rober Hamberger", 0, "rh474@bingo-ev.de" );
+ about.addCredit( "Thorsten Scheuermann", 0, "uddn@rz.uni-karlsruhe.de" );
+
+ KCmdLineArgs::init( argc, argv, &about );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+
+ if ( app.isRestored() ) {
+ (new KuickShow())->restore( 1, false ); // don't show automatically
+ }
+ else {
+ KuickShow *k = new KuickShow( "kuickshow" );
+ app.setMainWidget( k );
+ }
+
+ return app.exec();
+}
diff --git a/kuickshow/src/mainwidget.cpp b/kuickshow/src/mainwidget.cpp
new file mode 100644
index 00000000..caa6700c
--- /dev/null
+++ b/kuickshow/src/mainwidget.cpp
@@ -0,0 +1,43 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998,1999 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "fileview.h"
+#include "kuickdata.h"
+#include "mainwidget.h"
+
+
+MainWidget::MainWidget( QString startDir, QWidget *parent,
+ const char *name ) : QWidget ( parent, name )
+{
+ box = new FileView( startDir, true, (QDir::Dirs | QDir::Files),
+ this, "fileview" );
+}
+
+
+MainWidget::~MainWidget()
+{
+
+}
+
+
+// for now, no layout managers
+void MainWidget::resizeEvent( QResizeEvent * )
+{
+ box->resize( width(), height() );
+}
+#include "mainwidget.moc"
diff --git a/kuickshow/src/mainwidget.h b/kuickshow/src/mainwidget.h
new file mode 100644
index 00000000..36285dd8
--- /dev/null
+++ b/kuickshow/src/mainwidget.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef MAINWIDGET_H
+#define MAINWIDGET_H
+
+#include <qevent.h>
+#include <qstring.h>
+#include <qwidget.h>
+
+class FileView;
+
+class MainWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ MainWidget( QString, QWidget *parent, const char *name=0L);
+ ~MainWidget();
+
+ FileView* getFileBox() { return box; }
+
+protected:
+ virtual void resizeEvent( QResizeEvent * );
+
+private:
+ FileView *box;
+
+};
+
+
+#endif
diff --git a/kuickshow/src/printing.cpp b/kuickshow/src/printing.cpp
new file mode 100644
index 00000000..be57ca7f
--- /dev/null
+++ b/kuickshow/src/printing.cpp
@@ -0,0 +1,338 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qgrid.h>
+#include <qhbox.h>
+#include <qlayout.h>
+#include <qimage.h>
+#include <kimageeffect.h>
+#include <qpaintdevicemetrics.h>
+#include <qpainter.h>
+#include <qradiobutton.h>
+#include <qvbuttongroup.h>
+#include <qcolor.h>
+
+#include <kcombobox.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kglobalsettings.h>
+#include <knuminput.h>
+#include <kprinter.h>
+#include <ktempfile.h>
+
+#include "imagewindow.h"
+#include "printing.h"
+#include "version.h"
+
+bool Printing::printImage( ImageWindow& imageWin, QWidget *parent )
+{
+ QString imageURL = imageWin.url().prettyURL();
+ KPrinter printer;
+ printer.setDocName( imageURL );
+ printer.setCreator( "KuickShow-" KUICKSHOWVERSION );
+
+ KPrinter::addDialogPage( new KuickPrintDialogPage( parent, "kuick page"));
+
+ if ( printer.setup( parent, i18n("Print %1").arg(printer.docName().section('/', -1)) ) )
+ {
+ KTempFile tmpFile( QString::null, ".png" );
+ if ( tmpFile.status() == 0 )
+ {
+ tmpFile.setAutoDelete( true );
+ if ( imageWin.saveImage( tmpFile.name(), true ) )
+ return printImageWithQt( tmpFile.name(), printer,
+ imageURL );
+ }
+
+ return false;
+ }
+
+ return true; // user aborted
+}
+
+bool Printing::printImageWithQt( const QString& filename, KPrinter& printer,
+ const QString& originalFileName )
+{
+ QImage image( filename );
+ if ( image.isNull() ) {
+ kdWarning() << "Can't load image: " << filename << " for printing.\n";
+ return false;
+ }
+
+ QPainter p;
+ p.begin( &printer );
+
+ QPaintDeviceMetrics metrics( &printer );
+ p.setFont( KGlobalSettings::generalFont() );
+ QFontMetrics fm = p.fontMetrics();
+
+ int w = metrics.width();
+ int h = metrics.height();
+
+ QString t = "true";
+ QString f = "false";
+
+ // Black & white print?
+ if ( printer.option( "app-kuickshow-blackwhite" ) != f) {
+ image = image.convertDepth( 1, Qt::MonoOnly | Qt::ThresholdDither | Qt::AvoidDither );
+ }
+
+ int filenameOffset = 0;
+ bool printFilename = printer.option( "app-kuickshow-printFilename" ) != f;
+ if ( printFilename ) {
+ filenameOffset = fm.lineSpacing() + 14;
+ h -= filenameOffset; // filename goes into one line!
+ }
+
+ //
+ // shrink image to pagesize, if necessary
+ //
+ bool shrinkToFit = (printer.option( "app-kuickshow-shrinkToFit" ) != f);
+ QSize imagesize = image.size();
+ if ( shrinkToFit && (image.width() > w || image.height() > h) ) {
+ imagesize.scale( w, h, QSize::ScaleMin );
+ }
+
+
+ //
+ // align image
+ //
+ bool ok = false;
+ int alignment = printer.option("app-kuickshow-alignment").toInt( &ok );
+ if ( !ok )
+ alignment = Qt::AlignCenter; // default
+
+ int x = 0;
+ int y = 0;
+
+ // ### need a GUI for this in KuickPrintDialogPage!
+ // x - alignment
+ if ( alignment & Qt::AlignHCenter )
+ x = (w - imagesize.width())/2;
+ else if ( alignment & Qt::AlignLeft )
+ x = 0;
+ else if ( alignment & Qt::AlignRight )
+ x = w - imagesize.width();
+
+ // y - alignment
+ if ( alignment & Qt::AlignVCenter )
+ y = (h - imagesize.height())/2;
+ else if ( alignment & Qt::AlignTop )
+ y = 0;
+ else if ( alignment & Qt::AlignBottom )
+ y = h - imagesize.height();
+
+ //
+ // perform the actual drawing
+ //
+ p.drawImage( QRect( x, y, imagesize.width(), imagesize.height()), image );
+
+ if ( printFilename )
+ {
+ QString fname = minimizeString( originalFileName, fm, w );
+ if ( !fname.isEmpty() )
+ {
+ int fw = fm.width( fname );
+ int x = (w - fw)/2;
+ int y = metrics.height() - filenameOffset/2;
+ p.drawText( x, y, fname );
+ }
+ }
+
+ p.end();
+
+ return true;
+}
+
+QString Printing::minimizeString( QString text, const QFontMetrics&
+ metrics, int maxWidth )
+{
+ if ( text.length() <= 5 )
+ return QString::null; // no sense to cut that tiny little string
+
+ bool changed = false;
+ while ( metrics.width( text ) > maxWidth )
+ {
+ int mid = text.length() / 2;
+ text.remove( mid, 2 ); // remove 2 characters in the middle
+ changed = true;
+ }
+
+ if ( changed ) // add "..." in the middle
+ {
+ int mid = text.length() / 2;
+ if ( mid <= 5 ) // sanity check
+ return QString::null;
+
+ text.replace( mid - 1, 3, "..." );
+ }
+
+ return text;
+}
+
+
+///////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
+
+
+KuickPrintDialogPage::KuickPrintDialogPage( QWidget *parent, const char *name )
+ : KPrintDialogPage( parent, name )
+{
+ setTitle( i18n("Image Settings") );
+
+ QVBoxLayout *layout = new QVBoxLayout( this );
+ layout->setMargin( KDialog::marginHint() );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ m_addFileName = new QCheckBox( i18n("Print fi&lename below image"), this);
+ m_addFileName->setChecked( true );
+ layout->addWidget( m_addFileName );
+
+ m_blackwhite = new QCheckBox ( i18n("Print image in &black and white"), this);
+ m_blackwhite->setChecked( false );
+ layout->addWidget (m_blackwhite );
+
+ QVButtonGroup *group = new QVButtonGroup( i18n("Scaling"), this );
+ group->setRadioButtonExclusive( true );
+ layout->addWidget( group );
+ // m_shrinkToFit = new QRadioButton( i18n("Shrink image to &fit, if necessary"), group );
+ m_shrinkToFit = new QCheckBox( i18n("Shrink image to &fit, if necessary"), group );
+ m_shrinkToFit->setChecked( true );
+
+ QWidget *widget = new QWidget( group );
+ QGridLayout *grid = new QGridLayout( widget, 3, 3 );
+ grid->addColSpacing( 0, 30 );
+ grid->setColStretch( 0, 0 );
+ grid->setColStretch( 1, 1 );
+ grid->setColStretch( 2, 10 );
+
+ m_scale = new QRadioButton( i18n("Print e&xact size: "), widget );
+ m_scale->setEnabled( false ); // ###
+ grid->addMultiCellWidget( m_scale, 0, 0, 0, 1 );
+ group->insert( m_scale );
+ connect( m_scale, SIGNAL( toggled( bool )), SLOT( toggleScaling( bool )));
+
+ m_units = new KComboBox( false, widget, "unit combobox" );
+ grid->addWidget( m_units, 0, 2, AlignLeft );
+ m_units->insertItem( i18n("Millimeters") );
+ m_units->insertItem( i18n("Centimeters") );
+ m_units->insertItem( i18n("Inches") );
+
+ m_width = new KIntNumInput( widget, "exact width" );
+ grid->addWidget( m_width, 1, 1 );
+ m_width->setLabel( i18n("&Width:" ) );
+ m_width->setMinValue( 1 );
+
+ m_height = new KIntNumInput( widget, "exact height" );
+ grid->addWidget( m_height, 2, 1 );
+ m_height->setLabel( i18n("&Height:" ) );
+ m_height->setMinValue( 1 );
+}
+
+KuickPrintDialogPage::~KuickPrintDialogPage()
+{
+}
+
+void KuickPrintDialogPage::getOptions( QMap<QString,QString>& opts,
+ bool /*incldef*/ )
+{
+ QString t = "true";
+ QString f = "false";
+
+// ### opts["app-kuickshow-alignment"] = ;
+ opts["app-kuickshow-printFilename"] = m_addFileName->isChecked() ? t : f;
+ opts["app-kuickshow-blackwhite"] = m_blackwhite->isChecked() ? t : f;
+ opts["app-kuickshow-shrinkToFit"] = m_shrinkToFit->isChecked() ? t : f;
+ opts["app-kuickshow-scale"] = m_scale->isChecked() ? t : f;
+ opts["app-kuickshow-scale-unit"] = m_units->currentText();
+ opts["app-kuickshow-scale-width-pixels"] = QString::number( scaleWidth() );
+ opts["app-kuickshow-scale-height-pixels"] = QString::number( scaleHeight() );
+}
+
+void KuickPrintDialogPage::setOptions( const QMap<QString,QString>& opts )
+{
+ QString t = "true";
+ QString f = "false";
+
+ m_addFileName->setChecked( opts["app-kuickshow-printFilename"] != f );
+ // This sound strange, but if I copy the code on the line above, the checkbox
+ // was always checked. And this isn't the wanted behavior. So, with this works.
+ // KPrint magic ;-)
+ m_blackwhite->setChecked ( false );
+ m_shrinkToFit->setChecked( opts["app-kuickshow-shrinkToFit"] != f );
+ m_scale->setChecked( opts["app-kuickshow-scale"] == t );
+
+ m_units->setCurrentItem( opts["app-kuickshow-scale-unit"] );
+
+ bool ok;
+ int val = opts["app-kuickshow-scale-width-pixels"].toInt( &ok );
+ if ( ok )
+ setScaleWidth( val );
+ val = opts["app-kuickshow-scale-height-pixels"].toInt( &ok );
+ if ( ok )
+ setScaleHeight( val );
+
+ if ( m_scale->isChecked() == m_shrinkToFit->isChecked() )
+ m_shrinkToFit->setChecked( !m_scale->isChecked() );
+
+ // ### re-enable when implementednn
+ toggleScaling( false && m_scale->isChecked() );
+}
+
+void KuickPrintDialogPage::toggleScaling( bool enable )
+{
+ m_width->setEnabled( enable );
+ m_height->setEnabled( enable );
+ m_units->setEnabled( enable );
+}
+
+int KuickPrintDialogPage::scaleWidth() const
+{
+ return fromUnitToPixels( m_width->value() );
+}
+
+int KuickPrintDialogPage::scaleHeight() const
+{
+ return fromUnitToPixels( m_height->value() );
+}
+
+void KuickPrintDialogPage::setScaleWidth( int pixels )
+{
+ m_width->setValue( (int) pixelsToUnit( pixels ) );
+}
+
+void KuickPrintDialogPage::setScaleHeight( int pixels )
+{
+ m_width->setValue( (int) pixelsToUnit( pixels ) );
+}
+
+int KuickPrintDialogPage::fromUnitToPixels( float /*value*/ ) const
+{
+ return 1; // ###
+}
+
+float KuickPrintDialogPage::pixelsToUnit( int /*pixels*/ ) const
+{
+ return 1.0; // ###
+}
+
+#include "printing.moc"
diff --git a/kuickshow/src/printing.h b/kuickshow/src/printing.h
new file mode 100644
index 00000000..eb679f7e
--- /dev/null
+++ b/kuickshow/src/printing.h
@@ -0,0 +1,85 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PRINTING_H
+#define PRINTING_H
+
+#include <qfontmetrics.h>
+#include <qstring.h>
+
+#include <kdeprint/kprintdialogpage.h>
+
+class QCheckBox;
+class QRadioButton;
+class KComboBox;
+class KPrinter;
+class KIntNumInput;
+
+class ImageWindow;
+
+
+class Printing
+{
+public:
+ static bool printImage( ImageWindow& imageWin, QWidget *parent = 0L);
+ static bool printImageWithQt( const QString& filename, KPrinter& printer,
+ const QString& originalFileName );
+
+private:
+ static void addConfigPages();
+ static QString minimizeString( QString text, const QFontMetrics& metrics,
+ int maxWidth );
+
+};
+
+class KuickPrintDialogPage : public KPrintDialogPage
+{
+ Q_OBJECT
+
+public:
+ KuickPrintDialogPage( QWidget *parent = 0L, const char *name = 0 );
+ ~KuickPrintDialogPage();
+
+ virtual void getOptions(QMap<QString,QString>& opts, bool incldef = false);
+ virtual void setOptions(const QMap<QString,QString>& opts);
+
+private slots:
+ void toggleScaling( bool enable );
+
+private:
+ // return values in pixels!
+ int scaleWidth() const;
+ int scaleHeight() const;
+
+ void setScaleWidth( int pixels );
+ void setScaleHeight( int pixels );
+
+ int fromUnitToPixels( float val ) const;
+ float pixelsToUnit( int pixels ) const;
+
+ QCheckBox *m_shrinkToFit;
+ QRadioButton *m_scale;
+ KIntNumInput *m_width;
+ KIntNumInput *m_height;
+ KComboBox *m_units;
+ QCheckBox *m_addFileName;
+ QCheckBox *m_blackwhite;
+
+};
+
+#endif // PRINTING_H
diff --git a/kuickshow/src/slideshowwidget.cpp b/kuickshow/src/slideshowwidget.cpp
new file mode 100644
index 00000000..447b996e
--- /dev/null
+++ b/kuickshow/src/slideshowwidget.cpp
@@ -0,0 +1,80 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "slideshowwidget.h"
+
+
+SlideShowWidget::SlideShowWidget( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+// setTitle( i18n("Slideshow") );
+
+ QVBoxLayout *layout = new QVBoxLayout( this );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ m_fullScreen = new QCheckBox( i18n("Switch to &full-screen"), this );
+ m_startWithCurrent = new QCheckBox( i18n("S&tart with current image"), this);
+
+ m_delayTime = new KIntNumInput( this, "delay time" );
+ m_delayTime->setLabel( i18n("De&lay between slides:") );
+ m_delayTime->setSuffix( i18n(" sec") );
+ m_delayTime->setRange( 0, 60 * 60 ); // 1 hour
+ m_delayTime->setSpecialValueText( i18n("Wait for key") );
+
+ m_cycles = new KIntNumInput( m_delayTime, 1, this );
+ m_cycles->setLabel( i18n("&Iterations (0 = infinite):") );
+ m_cycles->setSpecialValueText( i18n("infinite") );
+ m_cycles->setRange( 0, 500 );
+
+ layout->addWidget( m_fullScreen );
+ layout->addWidget( m_startWithCurrent );
+ layout->addWidget( m_delayTime );
+ layout->addWidget( m_cycles );
+ layout->addStretch( 1 );
+
+ loadSettings( *kdata );
+}
+
+SlideShowWidget::~SlideShowWidget()
+{
+}
+
+void SlideShowWidget::loadSettings( const KuickData& data )
+{
+ m_delayTime->setValue( data.slideDelay / 1000 );
+ m_cycles->setValue( data.slideshowCycles );
+ m_fullScreen->setChecked( data.slideshowFullscreen );
+ m_startWithCurrent->setChecked( !data.slideshowStartAtFirst );
+}
+
+void SlideShowWidget::applySettings( KuickData& data )
+{
+ data.slideDelay = m_delayTime->value() * 1000;
+ data.slideshowCycles = m_cycles->value();
+ data.slideshowFullscreen = m_fullScreen->isChecked();
+ data.slideshowStartAtFirst = !m_startWithCurrent->isChecked();
+}
+
+#include "slideshowwidget.moc"
diff --git a/kuickshow/src/slideshowwidget.h b/kuickshow/src/slideshowwidget.h
new file mode 100644
index 00000000..c651103d
--- /dev/null
+++ b/kuickshow/src/slideshowwidget.h
@@ -0,0 +1,44 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ 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, version 2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SLIDESHOWWIDGET_H
+#define SLIDESHOWWIDGET_H
+
+#include "kuickdata.h"
+
+class QCheckBox;
+class KIntNumInput;
+
+class SlideShowWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ SlideShowWidget( QWidget *parent, const char *name );
+ ~SlideShowWidget();
+
+ virtual void loadSettings( const KuickData& data );
+ virtual void applySettings( KuickData& data );
+
+private:
+ KIntNumInput *m_delayTime;
+ KIntNumInput *m_cycles;
+ QCheckBox *m_fullScreen;
+ QCheckBox *m_startWithCurrent;
+};
+
+#endif // SLIDESHOWWIDGET_H
diff --git a/kuickshow/src/version.h b/kuickshow/src/version.h
new file mode 100644
index 00000000..2465967f
--- /dev/null
+++ b/kuickshow/src/version.h
@@ -0,0 +1,3 @@
+#ifndef KUICKSHOWVERSION
+#define KUICKSHOWVERSION "0.8.13"
+#endif