File indexing completed on 2024-05-05 16:39:04

0001 /* This file is part of the KDE project
0002    Copyright (C) 1998-2006 Carsten Pfeiffer <pfeiffer@kde.org>
0003 
0004    This program is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU General Public
0006    License as published by the Free Software Foundation, version 2.
0007 
0008    This program is distributed in the hope that it will be useful,
0009    but WITHOUT ANY WARRANTY; without even the implied warranty of
0010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0011    General Public License for more details.
0012 
0013    You should have received a copy of the GNU General Public License
0014    along with this program; see the file COPYING.  If not, write to
0015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0016    Boston, MA 02110-1301, USA.
0017 */
0018 
0019 #include "kuickshow.h"
0020 
0021 #include <KAboutData>
0022 #include <KActionCollection>
0023 #include <KActionMenu>
0024 #include <KConfigGroup>
0025 #include <KCursor>
0026 #include <KHelpMenu>
0027 #include <KIconLoader>
0028 #include <KIO/MimetypeJob>
0029 #include <KJobWidgets>
0030 #include <KLocalizedString>
0031 #include <KMessageBox>
0032 #include <KProtocolManager>
0033 #include <KSharedConfig>
0034 #include <KStandardAction>
0035 #include <KStandardGuiItem>
0036 #include <KStandardShortcut>
0037 #include <KStartupInfo>
0038 #include <KToolBar>
0039 #include <KUrlComboBox>
0040 #include <KUrlCompletion>
0041 #include <KWindowSystem>
0042 
0043 #include <QAbstractItemView>
0044 #include <QApplication>
0045 #include <QCommandLineParser>
0046 #include <QDesktopWidget>
0047 #include <QDialog>
0048 #include <QDir>
0049 #include <QDropEvent>
0050 #include <QEvent>
0051 #include <QKeyEvent>
0052 #include <QLabel>
0053 #include <QLayout>
0054 #include <QMenu>
0055 #include <QMenuBar>
0056 #include <QMimeDatabase>
0057 #include <QMouseEvent>
0058 #include <QSize>
0059 #include <QStandardPaths>
0060 #include <QStatusBar>
0061 #include <QString>
0062 #include <QScreen>
0063 #include <QTextStream>
0064 #include <QTimer>
0065 #include <QUrl>
0066 #include <QtGlobal>
0067 
0068 #include <assert.h>
0069 #include <stdio.h>
0070 
0071 #include "aboutwidget.h"
0072 #include "filecache.h"
0073 #include "filewidget.h"
0074 #include "imagewindow.h"
0075 #include "imdata.h"
0076 #include "imlibwidget.h"
0077 #include "kuick.h"
0078 #include "kuickconfigdlg.h"
0079 #include "kuickdata.h"
0080 #include "kuickfile.h"
0081 #include "kuickshow_debug.h"
0082 #include "openfilesanddirsdialog.h"
0083 
0084 
0085 KuickData* kdata;
0086 
0087 QList<ImageWindow*> KuickShow::s_viewers;
0088 
0089 KuickShow::KuickShow( const char *name )
0090     : KXmlGuiWindow( 0L ),
0091       m_slideshowCycle( 1 ),
0092       fileWidget( 0L ),
0093       dialog( 0L ),
0094       id( 0L ),
0095       m_viewer( 0L ),
0096       oneWindowAction( 0L ),
0097       m_delayedRepeatItem( 0L ),
0098       m_slideShowStopped(false)
0099 {
0100     setObjectName(name);
0101     aboutWidget = 0L;
0102     kdata = new KuickData;
0103     kdata->load();
0104 
0105     initImlib();
0106     resize( 400, 500 );
0107 
0108     m_slideTimer = new QTimer( this );
0109     connect( m_slideTimer, SIGNAL( timeout() ), SLOT( nextSlide() ));
0110 
0111 
0112     KSharedConfig::Ptr kc = KSharedConfig::openConfig();
0113 
0114     bool isDir = false; // true if we get a directory on the commandline
0115 
0116     // parse commandline options
0117     QCommandLineParser *parser = static_cast<QCommandLineParser *>(qApp->property("cmdlineParser").value<void *>());
0118 
0119     // files to display
0120     // either a directory to display, an absolute path, a relative path, or a URL
0121     QUrl startDir = QUrl::fromLocalFile(QDir::currentPath() + '/');
0122 
0123     QStringList args = parser->positionalArguments();
0124     int numArgs = args.count();
0125     if ( numArgs >= 10 )
0126     {
0127         // Even though the 1st i18n string will never be used, it needs to exist for plural handling - mhunter
0128         if ( KMessageBox::warningYesNo(
0129                  this,
0130                  i18np("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.",
0131                       "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(KStandardGuiItem::no().plainText()),
0132                  i18n("Display Multiple Images?"))
0133              != KMessageBox::Yes )
0134         {
0135             numArgs = 1;
0136         }
0137     }
0138 
0139     QMimeDatabase mimedb;
0140     for ( int i = 0; i < numArgs; i++ ) {
0141         QUrl url = QUrl::fromUserInput(args.value(i), QDir::currentPath(), QUrl::AssumeLocalFile);
0142         KFileItem item( url );
0143 
0144         // for remote URLs, we don't know if it's a file or directory, but
0145         // FileWidget::isImage() should correct in most cases.
0146         // For non-local non-images, we just assume directory.
0147 
0148         if ( FileWidget::isImage( item ) )
0149         {
0150             showImage( item, true, false, true ); // show in new window, not fullscreen-forced and move to 0,0
0151 //    showImage( &item, true, false, false ); // show in new window, not fullscreen-forced and not moving to 0,0
0152         }
0153         else if ( item.isDir() )
0154         {
0155             startDir = url;
0156             isDir = true;
0157         }
0158 
0159         // need to check remote files
0160         else if ( !url.isLocalFile() )
0161         {
0162             QMimeType mime = mimedb.mimeTypeForUrl( url );
0163             QString name = mime.name();
0164             if ( name == "application/octet-stream" ) { // unknown -> stat()
0165                 KIO::MimetypeJob* job = KIO::mimetype(url);
0166                 KJobWidgets::setWindow(job, this);
0167                 connect(job, &KIO::MimetypeJob::result, [job, &name]() {
0168                     if(!job->error()) name = job->mimetype();
0169                 });
0170                 job->exec();
0171             }
0172 
0173         // text/* is a hack for bugs.kde.org-attached-images urls.
0174         // The real problem here is that NetAccess::mimetype does a HTTP HEAD, which doesn't
0175         // always return the right mimetype. The rest of KDE start a get() instead....
0176             if ( name.startsWith( "image/" ) || name.startsWith( "text/" ) )
0177             {
0178                 showImage( item, true, false, true, true );
0179             }
0180             else // assume directory, KDirLister will tell us if we can't list
0181             {
0182                 startDir = url;
0183                 isDir = true;
0184             }
0185         }
0186         // else // we don't handle local non-images
0187     }
0188 
0189     if ( (kdata->startInLastDir && args.count() == 0) || parser->isSet( "lastfolder" )) {
0190         KConfigGroup sessGroup(kc, "SessionSettings");
0191         startDir = QUrl(sessGroup.readPathEntry( "CurrentDirectory", startDir.url() ));
0192     }
0193 
0194     if ( s_viewers.isEmpty() || isDir ) {
0195         initGUI( startDir );
0196     if (!qApp->isSessionRestored()) // during session management, readProperties() will show()
0197         show();
0198     }
0199 
0200     else { // don't show browser, when image on commandline
0201         hide();
0202         KStartupInfo::appStarted();
0203     }
0204 }
0205 
0206 
0207 KuickShow::~KuickShow()
0208 {
0209     saveSettings();
0210 
0211     delete m_viewer;
0212 
0213     FileCache::shutdown();
0214     free( id );
0215     qApp->quit();
0216 
0217     delete kdata;
0218 }
0219 
0220 // TODO convert to use xmlui file
0221 void KuickShow::initGUI( const QUrl& startDir )
0222 {
0223     QUrl startURL( startDir );
0224     if ( !KProtocolManager::supportsListing( startURL ) )
0225         startURL = QUrl();
0226 
0227     fileWidget = new FileWidget( startDir, this );
0228     fileWidget->setObjectName( QString::fromLatin1( "MainWidget" ) );
0229     setFocusProxy( fileWidget );
0230 
0231     KActionCollection *coll = fileWidget->actionCollection();
0232 
0233     redirectDeleteAndTrashActions(coll);
0234 
0235     connect( fileWidget, SIGNAL( fileSelected( const KFileItem& ) ),
0236              this, SLOT( slotSelected( const KFileItem& ) ));
0237 
0238     connect( fileWidget, SIGNAL( fileHighlighted( const KFileItem& )),
0239              this, SLOT( slotHighlighted( const KFileItem& ) ));
0240 
0241     connect( fileWidget, SIGNAL( urlEntered( const QUrl&  )),
0242              this, SLOT( dirSelected( const QUrl& )) );
0243 
0244 
0245     fileWidget->setAcceptDrops(true);
0246     connect( fileWidget, SIGNAL( dropped( const KFileItem&, QDropEvent *, const QList<QUrl> & )),
0247              this, SLOT( slotDropped( const KFileItem&, QDropEvent *, const QList<QUrl> &)) );
0248 
0249     // setup actions
0250     QAction *open = KStandardAction::open( this, SLOT( slotOpenURL() ),
0251                                       coll );
0252     coll->addAction( "openURL", open );
0253 
0254     QAction *print = KStandardAction::print( this, SLOT( slotPrint() ),
0255                                         coll );
0256     coll->addAction( "kuick_print", print );
0257     print->setText( i18n("Print Image...") );
0258 
0259     QAction *configure = coll->addAction( "kuick_configure" );
0260     configure->setText( i18n("Configure %1...", QApplication::applicationDisplayName() ) );
0261     configure->setIcon( QIcon::fromTheme( "configure" ) );
0262     connect( configure, SIGNAL( triggered() ), this, SLOT( configuration() ) );
0263 
0264     QAction *slide = coll->addAction( "kuick_slideshow" );
0265     slide->setText( i18n("Start Slideshow" ) );
0266     slide->setIcon( QIcon::fromTheme("ksslide" ));
0267     coll->setDefaultShortcut(slide, Qt::Key_F2);
0268     connect( slide, SIGNAL( triggered() ), this, SLOT( startSlideShow() ));
0269 
0270     QAction *about = coll->addAction( "about" );
0271     about->setText( i18n( "About KuickShow" ) );
0272     about->setIcon( QIcon::fromTheme("about") );
0273     connect( about, SIGNAL( triggered() ), this, SLOT( about() ) );
0274 
0275     oneWindowAction = coll->add<KToggleAction>( "kuick_one window" );
0276     oneWindowAction->setText( i18n("Open Only One Image Window") );
0277     oneWindowAction->setIcon( QIcon::fromTheme( "window-new" ) );
0278     coll->setDefaultShortcut(oneWindowAction, Qt::CTRL+Qt::Key_N);
0279 
0280     m_toggleBrowserAction = coll->add<KToggleAction>( "toggleBrowser" );
0281     m_toggleBrowserAction->setText( i18n("Show File Browser") );
0282     coll->setDefaultShortcut(m_toggleBrowserAction, Qt::Key_Space);
0283     m_toggleBrowserAction->setCheckedState(KGuiItem(i18n("Hide File Browser")));
0284     connect( m_toggleBrowserAction, SIGNAL( toggled( bool ) ),
0285              SLOT( toggleBrowser() ));
0286 
0287     QAction *showInOther = coll->addAction( "kuick_showInOtherWindow" );
0288     showInOther->setText( i18n("Show Image") );
0289     connect( showInOther, SIGNAL( triggered() ), SLOT( slotShowInOtherWindow() ));
0290 
0291     QAction *showInSame = coll->addAction( "kuick_showInSameWindow" );
0292     showInSame->setText( i18n("Show Image in Active Window") );
0293     connect( showInSame, SIGNAL( triggered() ), this, SLOT( slotShowInSameWindow() ) );
0294 
0295     QAction *showFullscreen = coll->addAction( "kuick_showFullscreen" );
0296     showFullscreen->setText( i18n("Show Image in Fullscreen Mode") );
0297     connect( showFullscreen, SIGNAL( triggered() ), this, SLOT( slotShowFullscreen() ) );
0298 
0299     QAction *defaultInlinePreview = coll->action( "inline preview" );
0300     KToggleAction *inlinePreviewAction = coll->add<KToggleAction>( "kuick_inlinePreview" );
0301     inlinePreviewAction->setText( defaultInlinePreview->text() );
0302     inlinePreviewAction->setIcon( defaultInlinePreview->icon() );
0303     connect( inlinePreviewAction, SIGNAL( toggled(bool) ), this, SLOT( slotToggleInlinePreview(bool) ) );
0304 
0305     QAction *quit = KStandardAction::quit( this, SLOT(slotQuit()), coll);
0306     coll->addAction( "quit", quit );
0307 
0308     // menubar
0309     QMenuBar *mBar = menuBar();
0310     QMenu *fileMenu = new QMenu( i18n("&File"), mBar );
0311     fileMenu->setObjectName( QString::fromLatin1( "file" ) );
0312     fileMenu->addAction(open);
0313     fileMenu->addAction(showInOther);
0314     fileMenu->addAction(showInSame);
0315     fileMenu->addAction(showFullscreen);
0316     fileMenu->addSeparator();
0317     fileMenu->addAction(slide);
0318     fileMenu->addAction(print);
0319     fileMenu->addSeparator();
0320     fileMenu->addAction(quit);
0321 
0322     QMenu *editMenu = new QMenu( i18n("&Edit"), mBar );
0323     editMenu->setObjectName( QString::fromLatin1( "edit" ) );
0324     editMenu->addAction(coll->action("mkdir"));
0325     editMenu->addAction(coll->action("trash"));
0326     editMenu->addSeparator();
0327     editMenu->addAction(coll->action("properties"));
0328 
0329     KActionMenu *viewActionMenu = static_cast<KActionMenu *>(coll->action("view menu"));
0330 
0331     QMenu *settingsMenu = new QMenu( i18n("&Settings"), mBar );
0332     settingsMenu->setObjectName( QString::fromLatin1( "settings" ) );
0333     settingsMenu->addAction(configure);
0334 
0335     mBar->addMenu( fileMenu );
0336     mBar->addMenu( editMenu );
0337     mBar->addAction( viewActionMenu );
0338     mBar->addMenu( settingsMenu );
0339 
0340     // toolbar
0341     KToolBar *tBar = toolBar(i18n("Main Toolbar"));
0342 
0343     tBar->addAction(coll->action("up"));
0344     tBar->addAction(coll->action("back"));
0345     tBar->addAction(coll->action("forward"));
0346     tBar->addAction(coll->action("home"));
0347     tBar->addAction(coll->action("reload"));
0348 
0349     tBar->addSeparator();
0350 
0351     // Address box in address tool bar
0352     KToolBar *addressToolBar = toolBar( "address_bar" );
0353 
0354     cmbPath = new KUrlComboBox( KUrlComboBox::Directories,
0355                                 true, addressToolBar );
0356     KUrlCompletion *cmpl = new KUrlCompletion( KUrlCompletion::DirCompletion );
0357     cmbPath->setCompletionObject( cmpl );
0358     cmbPath->setAutoDeleteCompletionObject( true );
0359 
0360     addressToolBar->addWidget( cmbPath );
0361 
0362     connect( cmbPath, SIGNAL( urlActivated( const QUrl& )),
0363              this, SLOT( slotSetURL( const QUrl& )));
0364     connect( cmbPath, SIGNAL( returnPressed()),
0365              this, SLOT( slotURLComboReturnPressed()));
0366 
0367     tBar->addSeparator();
0368 
0369     tBar->addAction(coll->action( "short view" ));
0370     tBar->addAction(coll->action( "detailed view" ));
0371 
0372 
0373     tBar->addAction(inlinePreviewAction);
0374     tBar->addAction(coll->action( "preview"));
0375 
0376     tBar->addSeparator();
0377     tBar->addAction(slide);
0378     tBar->addSeparator();
0379     tBar->addAction(oneWindowAction);
0380     tBar->addAction(print);
0381     tBar->addSeparator();
0382     tBar->addAction(about);
0383 
0384     mBar->addSeparator();
0385     KHelpMenu* help = new KHelpMenu(this, QString(), false);
0386     mBar->addMenu(help->menu());
0387 
0388     sblblUrlInfo = createStatusBarLabel(10);
0389     sblblMetaInfo = createStatusBarLabel(2);
0390 
0391     fileWidget->setFocus();
0392 
0393     KConfigGroup kc(KSharedConfig::openConfig(), "SessionSettings");
0394     bool oneWindow = kc.readEntry("OpenImagesInActiveWindow", true );
0395     oneWindowAction->setChecked( oneWindow );
0396 
0397     tBar->show();
0398 
0399     fileWidget->initActions();
0400     fileWidget->clearHistory();
0401     dirSelected( fileWidget->url() );
0402 
0403     setCentralWidget( fileWidget );
0404 
0405     setupGUI( KXmlGuiWindow::Save );
0406 
0407     coll->setDefaultShortcuts(coll->action( "reload" ), KStandardShortcut::reload());
0408     coll->setDefaultShortcut(coll->action( "short view" ), Qt::Key_F6);
0409     coll->setDefaultShortcut(coll->action( "detailed view" ), Qt::Key_F7);
0410     //coll->setDefaultShortcut(coll->action( "show hidden" ), Qt::Key_F8);
0411     coll->setDefaultShortcut(coll->action( "mkdir" ), Qt::Key_F10);
0412     coll->setDefaultShortcut(coll->action( "preview" ), Qt::Key_F11);
0413     //coll->setDefaultShortcut(coll->action( "separate dirs" ), Qt::Key_F12);
0414 }
0415 
0416 QLabel* KuickShow::createStatusBarLabel(int stretch)
0417 {
0418     QLabel* label = new QLabel(this);
0419     label->setFixedHeight(fontMetrics().height() + 2);  // copied from KStatusBar::insertItem
0420     statusBar()->addWidget(label, stretch);
0421     return label;
0422 }
0423 
0424 void KuickShow::redirectDeleteAndTrashActions(KActionCollection *coll)
0425 {
0426     QAction *action = coll->action("delete");
0427     if (action)
0428     {
0429         action->disconnect(fileWidget);
0430         connect(action, SIGNAL(triggered()), this, SLOT(slotDeleteCurrentImage()));
0431     }
0432 
0433     action = coll->action("trash");
0434     if (action)
0435     {
0436         action->disconnect(fileWidget);
0437         connect(action, SIGNAL(triggered()), this, SLOT(slotTrashCurrentImage()));
0438     }
0439 }
0440 
0441 void KuickShow::slotSetURL( const QUrl& url )
0442 {
0443     fileWidget->setUrl( url, true );
0444 }
0445 
0446 void KuickShow::slotURLComboReturnPressed()
0447 {
0448     QUrl where = QUrl::fromUserInput( cmbPath->currentText(), QString(), QUrl::AssumeLocalFile );
0449     slotSetURL( where );
0450 }
0451 
0452 void KuickShow::viewerDeleted()
0453 {
0454     ImageWindow *viewer = (ImageWindow*) sender();
0455     s_viewers.removeAll( viewer );
0456     if ( viewer == m_viewer )
0457         m_viewer = 0L;
0458 
0459     if ( !haveBrowser() && s_viewers.isEmpty() ) {
0460         saveSettings();
0461         FileCache::shutdown();
0462         ::exit(0);
0463     }
0464 
0465     else if ( haveBrowser() ) {
0466         activateWindow();
0467         // This setFocus() call causes problems in the combiview (always the
0468         // directory view on the left gets the focus, which is not desired)
0469         // fileWidget->setFocus();
0470     }
0471 
0472     if ( fileWidget )
0473         // maybe a slideshow was stopped --> enable the action again
0474         fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
0475 
0476     m_slideTimer->stop();
0477 }
0478 
0479 
0480 void KuickShow::slotHighlighted( const KFileItem& item )
0481 {
0482     QString statusBarInfo = item.isNull() ? QString() : item.getStatusBarInfo();
0483 
0484     sblblUrlInfo->setText(statusBarInfo);
0485     bool image = FileWidget::isImage( item );
0486 
0487     QString meta;
0488     if ( image )
0489     {
0490         /* KFileMetaInfo disappered in KF5.
0491          * TODO: find alternative to KFileMetaInfo
0492 
0493         KFileMetaInfo info;
0494         // code snippet copied from KFileItem::metaInfo (KDE4)
0495         if(item.isRegularFile() || item.isDir()) {
0496             bool isLocalUrl;
0497             QUrl url(item.mostLocalUrl(&isLocalUrl));
0498             info = KFileMetaInfo(url.toLocalFile(), item.mimetype(), KFileMetaInfo::ContentInfo | KFileMetaInfo::TechnicalInfo);
0499         }
0500         if ( info.isValid() )
0501         {
0502             meta = info.item("sizeurl").value().toString();
0503             const QString bpp = info.item( "BitDepth" ).value().toString();
0504             if ( !bpp.isEmpty() )
0505                 meta.append( ", " ).append( bpp );
0506         }
0507         */
0508     }
0509     sblblMetaInfo->setText(meta);
0510 
0511     fileWidget->actionCollection()->action("kuick_print")->setEnabled( image );
0512     fileWidget->actionCollection()->action("kuick_showInSameWindow")->setEnabled( image );
0513     fileWidget->actionCollection()->action("kuick_showInOtherWindow")->setEnabled( image );
0514     fileWidget->actionCollection()->action("kuick_showFullscreen")->setEnabled( image );
0515 }
0516 
0517 void KuickShow::dirSelected( const QUrl& url )
0518 {
0519     if ( url.isLocalFile() )
0520         setCaption( url.path() );
0521     else
0522         setCaption( url.toDisplayString() );
0523 
0524     cmbPath->setUrl( url );
0525     sblblUrlInfo->setText(url.toDisplayString());
0526 }
0527 
0528 void KuickShow::slotSelected( const KFileItem& item )
0529 {
0530     showImage( item, !oneWindowAction->isChecked() );
0531 }
0532 
0533 // downloads item if necessary
0534 void KuickShow::showFileItem( ImageWindow * /*view*/,
0535                               const KFileItem * /*item*/ )
0536 {
0537 
0538 }
0539 
0540 bool KuickShow::showImage( const KFileItem& fi,
0541                            bool newWindow, bool fullscreen, bool moveToTopLeft, bool ignoreFileType )
0542 {
0543     newWindow  |= !m_viewer;
0544     fullscreen |= (newWindow && kdata->fullScreen);
0545     if ( ignoreFileType || FileWidget::isImage( fi ) ) {
0546 
0547         if ( newWindow ) {
0548             m_viewer = new ImageWindow( kdata->idata, id, 0L );
0549             m_viewer->setObjectName( QString::fromLatin1("image window") );
0550             m_viewer->setFullscreen( fullscreen );
0551             s_viewers.append( m_viewer );
0552 
0553         connect( m_viewer, SIGNAL( nextSlideRequested() ), this, SLOT( nextSlide() ));
0554             connect( m_viewer, SIGNAL( destroyed() ), SLOT( viewerDeleted() ));
0555             connect( m_viewer, SIGNAL( sigFocusWindow( ImageWindow *) ),
0556                      this, SLOT( slotSetActiveViewer( ImageWindow * ) ));
0557             connect( m_viewer, SIGNAL( sigImageError(const KuickFile *, const QString& ) ),
0558                      this, SLOT( messageCantLoadImage(const KuickFile *, const QString &) ));
0559             connect( m_viewer, SIGNAL( requestImage( ImageWindow *, int )),
0560                      this, SLOT( slotAdvanceImage( ImageWindow *, int )));
0561         connect( m_viewer, SIGNAL( pauseSlideShowSignal() ),
0562              this, SLOT( pauseSlideShow() ) );
0563         connect( m_viewer, SIGNAL (deleteImage (ImageWindow *)),
0564                  this, SLOT (slotDeleteCurrentImage (ImageWindow *)));
0565         connect( m_viewer, SIGNAL (trashImage (ImageWindow *)),
0566                  this, SLOT (slotTrashCurrentImage (ImageWindow *)));
0567             if ( s_viewers.count() == 1 && moveToTopLeft ) {
0568                 // we have to move to 0x0 before showing _and_
0569                 // after showing, otherwise we get some bogus geometry()
0570                 m_viewer->move( Kuick::workArea().topLeft() );
0571             }
0572 
0573             m_viewer->installEventFilter( this );
0574         }
0575 
0576         // for some strange reason, m_viewer sometimes changes during the
0577         // next few lines of code, so as a workaround, we use safeViewer here.
0578         // This happens when calling KuickShow with two or more remote-url
0579         // arguments on the commandline, where the first one is loaded properly
0580         // and the second isn't (e.g. because it is a pdf or something else,
0581         // Imlib can't load).
0582         ImageWindow *safeViewer = m_viewer;
0583         if ( !safeViewer->showNextImage( fi.url() ) ) {
0584             m_viewer = safeViewer;
0585             safeViewer->deleteLater(); // couldn't load image, close window
0586         }
0587         else {
0588             // safeViewer->setFullscreen( fullscreen );
0589 
0590             if ( newWindow ) {
0591 //                safeViewer->show();
0592 
0593                 if ( !fullscreen && s_viewers.count() == 1 && moveToTopLeft ) {
0594                     // the WM might have moved us after showing -> strike back!
0595                     // move the first image to 0x0 workarea coord
0596                     safeViewer->move( Kuick::workArea().topLeft() );
0597                 }
0598             }
0599 
0600             if ( kdata->preloadImage && fileWidget ) {
0601                 // don't move cursor
0602                 KFileItem item = fileWidget->getItem( FileWidget::Next, true );
0603                 if ( !item.isNull() )
0604                     safeViewer->cacheImage( item.url() );
0605             }
0606 
0607             m_viewer = safeViewer;
0608             return true;
0609         } // m_viewer created successfully
0610     } // isImage
0611 
0612     return false;
0613 }
0614 
0615 void KuickShow::slotDeleteCurrentImage()
0616 {
0617     performDeleteCurrentImage(fileWidget);
0618 }
0619 
0620 void KuickShow::slotTrashCurrentImage()
0621 {
0622     performTrashCurrentImage(fileWidget);
0623 }
0624 
0625 void KuickShow::slotDeleteCurrentImage(ImageWindow *viewer)
0626 {
0627     if (!fileWidget) {
0628         delayAction(new DelayedRepeatEvent(viewer, DelayedRepeatEvent::DeleteCurrentFile, 0L));
0629         return;
0630     }
0631     performDeleteCurrentImage(viewer);
0632 }
0633 
0634 void KuickShow::slotTrashCurrentImage(ImageWindow *viewer)
0635 {
0636     if (!fileWidget) {
0637         delayAction(new DelayedRepeatEvent(viewer, DelayedRepeatEvent::TrashCurrentFile, 0L));
0638         return;
0639     }
0640     performTrashCurrentImage(viewer);
0641 }
0642 
0643 void KuickShow::performDeleteCurrentImage(QWidget *parent)
0644 {
0645     assert(fileWidget != 0L);
0646 
0647     KFileItemList list;
0648     const KFileItem &item = fileWidget->getCurrentItem(false);
0649     list.append (item);
0650 
0651     if (KMessageBox::warningContinueCancel(
0652             parent,
0653             i18n("<qt>Do you really want to delete\n <b>'%1'</b>?</qt>", item.url().toDisplayString(QUrl::PreferLocalFile)),
0654             i18n("Delete File"),
0655             KStandardGuiItem::del(),
0656             KStandardGuiItem::cancel(),
0657             "Kuick_delete_current_image")
0658         != KMessageBox::Continue)
0659     {
0660         return;
0661     }
0662 
0663     tryShowNextImage();
0664     fileWidget->del(list, 0, false);
0665 }
0666 
0667 void KuickShow::performTrashCurrentImage(QWidget *parent)
0668 {
0669     assert(fileWidget != 0L);
0670 
0671     KFileItemList list;
0672     const KFileItem& item = fileWidget->getCurrentItem(false);
0673     if (item.isNull()) return;
0674 
0675     list.append (item);
0676 
0677     if (KMessageBox::warningContinueCancel(
0678             parent,
0679             i18n("<qt>Do you really want to trash\n <b>'%1'</b>?</qt>", item.url().toDisplayString(QUrl::PreferLocalFile)),
0680             i18n("Trash File"),
0681             KGuiItem(i18nc("to trash", "&Trash"),"edittrash"),
0682             KStandardGuiItem::cancel(),
0683             "Kuick_trash_current_image")
0684         != KMessageBox::Continue)
0685     {
0686         return;
0687     }
0688 
0689     tryShowNextImage();
0690     fileWidget->trash(list, parent, false, false);
0691 }
0692 
0693 void KuickShow::tryShowNextImage()
0694 {
0695     // move to next file item even if we have no viewer
0696     KFileItem next = fileWidget->getNext(true);
0697     if (next.isNull())
0698         next = fileWidget->getPrevious(true);
0699 
0700     // ### why is this necessary at all? Why does KDirOperator suddenly re-read the
0701     // entire directory after a file was deleted/trashed!? (KDirNotify is the reason)
0702     if (!m_viewer)
0703         return;
0704 
0705     if (!next.isNull())
0706         showImage(next, false);
0707     else
0708     {
0709         if (!haveBrowser())
0710         {
0711             // ### when simply calling toggleBrowser(), this main window is completely messed up
0712             QTimer::singleShot(0, this, SLOT(toggleBrowser()));
0713         }
0714         m_viewer->deleteLater();
0715     }
0716 }
0717 
0718 void KuickShow::startSlideShow()
0719 {
0720     KFileItem item = kdata->slideshowStartAtFirst ?
0721                       fileWidget->gotoFirstImage() :
0722                       fileWidget->getCurrentItem(false);
0723 
0724     if ( !item.isNull() ) {
0725         m_slideshowCycle = 1;
0726         fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( false );
0727         showImage( item, !oneWindowAction->isChecked(),
0728                    kdata->slideshowFullscreen );
0729     if(kdata->slideDelay)
0730             m_slideTimer->start( kdata->slideDelay );
0731     }
0732 }
0733 
0734 void KuickShow::pauseSlideShow()
0735 {
0736     if(m_slideShowStopped) {
0737     if(kdata->slideDelay)
0738         m_slideTimer->start( kdata->slideDelay );
0739     m_slideShowStopped = false;
0740     }
0741     else {
0742     m_slideTimer->stop();
0743     m_slideShowStopped = true;
0744     }
0745 }
0746 
0747 void KuickShow::nextSlide()
0748 {
0749     if ( !m_viewer ) {
0750         m_slideshowCycle = 1;
0751         fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
0752         return;
0753     }
0754 
0755     KFileItem item = fileWidget->getNext( true );
0756     if ( item.isNull() ) { // last image
0757         if ( m_slideshowCycle < kdata->slideshowCycles
0758              || kdata->slideshowCycles == 0 ) {
0759             item = fileWidget->gotoFirstImage();
0760             if ( !item.isNull() ) {
0761                 nextSlide( item );
0762                 m_slideshowCycle++;
0763                 return;
0764             }
0765         }
0766 
0767         delete m_viewer;
0768         fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
0769         return;
0770     }
0771 
0772     nextSlide( item );
0773 }
0774 
0775 void KuickShow::nextSlide( const KFileItem& item )
0776 {
0777     m_viewer->showNextImage( item.url() );
0778     if(kdata->slideDelay)
0779         m_slideTimer->start( kdata->slideDelay );
0780 }
0781 
0782 
0783 // prints the selected files in the filebrowser
0784 void KuickShow::slotPrint()
0785 {
0786     const KFileItemList items = fileWidget->selectedItems();
0787     if ( items.isEmpty() )
0788         return;
0789 
0790     KFileItemList::const_iterator it = items.constBegin();
0791     const KFileItemList::const_iterator end = items.constEnd();
0792 
0793     // don't show the image, just print
0794     ImageWindow *iw = new ImageWindow( 0, id, this );
0795     iw->setObjectName( QString::fromLatin1("printing image"));
0796     KFileItem item;
0797     for ( ; it != end; ++it ) {
0798         item = (*it);
0799         if (FileWidget::isImage( item ) && iw->loadImage( item.url()))
0800             iw->printImage();
0801     }
0802 
0803     delete iw;
0804 }
0805 
0806 void KuickShow::slotShowInOtherWindow()
0807 {
0808     showImage( fileWidget->getCurrentItem( false ), true );
0809 }
0810 
0811 void KuickShow::slotShowInSameWindow()
0812 {
0813     showImage( fileWidget->getCurrentItem( false ), false );
0814 }
0815 
0816 void KuickShow::slotShowFullscreen()
0817 {
0818     showImage( fileWidget->getCurrentItem( false ), false, true );
0819 }
0820 
0821 void KuickShow::slotDropped( const KFileItem&, QDropEvent *, const QList<QUrl> &urls)
0822 {
0823     QList<QUrl>::ConstIterator it = urls.constBegin();
0824     for ( ; it != urls.constEnd(); ++it )
0825     {
0826         KFileItem item( *it );
0827         if ( FileWidget::isImage( item ) )
0828             showImage( item, true );
0829         else
0830             fileWidget->setUrl( *it, true );
0831     }
0832 }
0833 
0834 // try to init the WM border as it is 0,0 when the window is not shown yet.
0835 void KuickShow::show()
0836 {
0837     KXmlGuiWindow::show();
0838     (void) Kuick::frameSize( winId() );
0839 }
0840 
0841 void KuickShow::slotAdvanceImage( ImageWindow *view, int steps )
0842 {
0843     KFileItem item; // to be shown
0844     KFileItem item_next; // to be cached
0845 
0846     if ( steps == 0 )
0847         return;
0848 
0849     // the viewer might not be available yet. Factor this out somewhen.
0850     if ( !fileWidget ) {
0851         if ( m_delayedRepeatItem )
0852             return;
0853 
0854         delayAction(new DelayedRepeatEvent( view, DelayedRepeatEvent::AdvanceViewer, new int(steps) ));
0855         return;
0856     }
0857 
0858     if ( steps > 0 ) {
0859         for ( int i = 0; i < steps; i++ )
0860             item = fileWidget->getNext( true );
0861         item_next = fileWidget->getNext( false );
0862     }
0863 
0864     else if ( steps < 0 ) {
0865         for ( int i = steps; i < 0; i++ )
0866             item = fileWidget->getPrevious( true );
0867         item_next = fileWidget->getPrevious( false );
0868     }
0869 
0870     if ( FileWidget::isImage( item ) ) {
0871 //        QString filename;
0872 //        KIO::NetAccess::download(item->url(), filename, this);
0873         view->showNextImage( item.url() );
0874         if (m_slideTimer->isActive() && kdata->slideDelay)
0875             m_slideTimer->start( kdata->slideDelay );
0876 
0877         if ( kdata->preloadImage && !item_next.isNull() ) // preload next image
0878             if ( FileWidget::isImage( item_next ) )
0879                 view->cacheImage( item_next.url() );
0880     }
0881 }
0882 
0883 bool KuickShow::eventFilter( QObject *o, QEvent *e )
0884 {
0885     if ( m_delayedRepeatItem ) // we probably need to install an eventFilter over
0886         return true;    // kapp, to make it really safe
0887 
0888     bool ret = false;
0889     int eventType = e->type();
0890     QKeyEvent *k = 0L;
0891     if ( eventType == QEvent::KeyPress )
0892         k = static_cast<QKeyEvent *>( e );
0893 
0894     if ( k ) {
0895         if ( KStandardShortcut::quit().contains( k->key() ) ) {
0896             saveSettings();
0897             deleteAllViewers();
0898             FileCache::shutdown();
0899             ::exit(0);
0900         }
0901         else if ( KStandardShortcut::help().contains( k->key() ) ) {
0902             appHelpActivated();
0903             return true;
0904         }
0905     }
0906 
0907 
0908     ImageWindow *window = dynamic_cast<ImageWindow*>( o );
0909 
0910     if ( window ) {
0911         // The XWindow used to display Imlib's image is being resized when
0912         // switching images, causing enter- and leaveevents for this
0913         // ImageWindow, leading to the cursor being unhidden. So we simply
0914         // don't pass those events to KCursor to prevent that.
0915         if ( eventType != QEvent::Leave && eventType != QEvent::Enter )
0916             KCursor::autoHideEventFilter( o, e );
0917 
0918         m_viewer = window;
0919         QString img;
0920         KFileItem item;      // the image to be shown
0921         KFileItem item_next; // the image to be cached
0922 
0923         if ( k ) { // keypress
0924             ret = true;
0925             int key = k->key();
0926 
0927             // Qt::Key_Shift shouldn't load the browser in nobrowser mode, it
0928             // is used for zooming in the imagewindow
0929             // Qt::Key_Alt shouldn't either - otherwise Alt+F4 doesn't work, the
0930             // F4 gets eaten (by NetAccess' modal dialog maybe?)
0931             if ( !fileWidget )
0932             {
0933                 if ( key != Qt::Key_Escape && key != Qt::Key_Shift && key != Qt::Key_Alt )
0934                 {
0935                     KuickFile *file = m_viewer->currentFile();
0936                     initGUI( KIO::upUrl(file->url()) );
0937 
0938                     // the fileBrowser will list the start-directory
0939                     // asynchronously so we can't immediately continue. There
0940                     // is no current-item and no next-item (actually no item
0941                     // at all). So we tell the browser the initial
0942                     // current-item and wait for it to tell us when it's ready.
0943                     // Then we will replay this KeyEvent.
0944                     delayedRepeatEvent( m_viewer, k );
0945 
0946                     // OK, once again, we have a problem with the now async and
0947                     // sync KDirLister :( If the startDir is already cached by
0948                     // KDirLister, we won't ever get that finished() signal
0949                     // because it is emitted before we can connect(). So if
0950                     // our dirlister has a rootFileItem, we assume the
0951                     // directory is read already and simply call
0952                     // slotReplayEvent() without the need for the finished()
0953                     // signal.
0954 
0955                     // see slotAdvanceImage() for similar code
0956                     if ( fileWidget->dirLister()->isFinished() )
0957                     {
0958                         if ( !fileWidget->dirLister()->rootItem().isNull() )
0959                         {
0960                             fileWidget->setCurrentItem( file->url() );
0961                             QTimer::singleShot( 0, this, SLOT( slotReplayEvent()));
0962                         }
0963                         else // finished, but no root-item -- probably an error, kill repeat-item!
0964                         {
0965                             abortDelayedEvent();
0966                         }
0967                 }
0968                 else // not finished yet
0969                 {
0970                         fileWidget->setInitialItem( file->url() );
0971                         connect( fileWidget, SIGNAL( finished() ),
0972                                  SLOT( slotReplayEvent() ));
0973                     }
0974 
0975                     return true;
0976                 }
0977 
0978                 return KXmlGuiWindow::eventFilter( o, e );
0979             }
0980 
0981             // we definitely have a fileWidget here!
0982 
0983             if ( key == Qt::Key_Home || KStandardShortcut::begin().contains( k->key() ) )
0984             {
0985                 item = fileWidget->gotoFirstImage();
0986                 item_next = fileWidget->getNext( false );
0987             }
0988 
0989             else if ( key == Qt::Key_End || KStandardShortcut::end().contains( k->key() ) )
0990             {
0991                 item = fileWidget->gotoLastImage();
0992                 item_next = fileWidget->getPrevious( false );
0993             }
0994 
0995             else if ( fileWidget->actionCollection()->action("delete")->shortcuts().contains( key ))
0996             {
0997 //      KFileItem *cur = fileWidget->getCurrentItem( false );
0998                 (void) fileWidget->getCurrentItem( false );
0999                 item = fileWidget->getNext( false ); // don't move
1000                 if ( item.isNull() )
1001                     item = fileWidget->getPrevious( false );
1002                 KFileItem it( m_viewer->url() );
1003                 KFileItemList list;
1004                 list.append( it );
1005                 if ( fileWidget->del(list, window,
1006                                      (k->modifiers() & Qt::ShiftModifier) == 0) == 0L )
1007                     return true; // aborted deletion
1008 
1009                 // ### check failure asynchronously and restore old item?
1010                 fileWidget->setCurrentItem( item );
1011             }
1012 
1013             else if ( m_toggleBrowserAction->shortcuts().contains( key ) )
1014             {
1015                 toggleBrowser();
1016                 return true; // don't pass keyEvent
1017             }
1018             else
1019             {
1020                 ret = false;
1021             }
1022 
1023             if ( FileWidget::isImage( item ) ) {
1024                 m_viewer->showNextImage( item.url() );
1025 
1026                 if ( kdata->preloadImage && !item_next.isNull() ) // preload next image
1027                     if ( FileWidget::isImage( item_next ) )
1028                         m_viewer->cacheImage( item_next.url() );
1029 
1030                 ret = true; // don't pass keyEvent
1031             }
1032 
1033         } // keyPressEvent on ImageWindow
1034 
1035 
1036         // doubleclick closes image window
1037         // and shows browser when last window closed via doubleclick
1038         else if ( eventType == QEvent::MouseButtonDblClick )
1039         {
1040             QMouseEvent *ev = static_cast<QMouseEvent*>( e );
1041             if ( ev->button() == Qt::LeftButton )
1042             {
1043                 if ( s_viewers.count() == 1 )
1044                 {
1045                     if ( !fileWidget )
1046                     {
1047                         initGUI( window->currentFile()->url() );
1048                     }
1049                     show();
1050                     raise();
1051                 }
1052 
1053                 delete window;
1054 
1055                 ev->accept();
1056                 ret = true;
1057             }
1058         }
1059 
1060     } // isA ImageWindow
1061 
1062 
1063     if ( ret )
1064         return true;
1065 
1066     return KXmlGuiWindow::eventFilter( o, e );
1067 }
1068 
1069 void KuickShow::configuration()
1070 {
1071     if ( !fileWidget ) {
1072         initGUI( QUrl::fromLocalFile(QDir::homePath()) );
1073     }
1074 
1075     dialog = new KuickConfigDialog( fileWidget->actionCollection(), 0L, false );
1076     dialog->setObjectName(QString::fromLatin1("dialog"));
1077     dialog->setWindowIcon( qApp->windowIcon() );
1078 
1079     connect( dialog, SIGNAL( okClicked() ),
1080              this, SLOT( slotConfigApplied() ) );
1081     connect( dialog, SIGNAL( applyClicked() ),
1082              this, SLOT( slotConfigApplied() ) );
1083     connect( dialog, SIGNAL( finished(int) ),
1084              this, SLOT( slotConfigClosed() ) );
1085 
1086     fileWidget->actionCollection()->action( "kuick_configure" )->setEnabled( false );
1087     dialog->show();
1088 }
1089 
1090 
1091 void KuickShow::slotConfigApplied()
1092 {
1093     dialog->applyConfig();
1094 
1095     initImlib();
1096     kdata->save();
1097 
1098     ImageWindow *viewer;
1099     QList<ImageWindow*>::ConstIterator it = s_viewers.constBegin();
1100     while ( it != s_viewers.constEnd() ) {
1101         viewer = *it;
1102         viewer->updateActions();
1103         ++it;
1104     }
1105 
1106     fileWidget->reloadConfiguration();
1107 }
1108 
1109 
1110 void KuickShow::slotConfigClosed()
1111 {
1112     dialog->deleteLater();
1113     fileWidget->actionCollection()->action( "kuick_configure" )->setEnabled( true );
1114 }
1115 
1116 void KuickShow::about()
1117 {
1118     if ( !aboutWidget ) {
1119         aboutWidget = new AboutWidget( 0L );
1120         aboutWidget->setObjectName( QString::fromLatin1( "about" ) );
1121     }
1122 
1123     aboutWidget->adjustSize();
1124 
1125     QScreen *screen = windowHandle()->screen();
1126     const QRect screenRect = screen->geometry();
1127     aboutWidget->move(screenRect.center().x() - aboutWidget->width() / 2, screenRect.center().y() - aboutWidget->height() / 2);
1128 
1129     aboutWidget->show();
1130 }
1131 
1132 // ------ sessionmanagement - load / save current directory -----
1133 void KuickShow::readProperties( const KConfigGroup& kc )
1134 {
1135     assert( fileWidget ); // from SM, we should always have initGUI on startup
1136     QString dir = kc.readPathEntry( "CurrentDirectory", QString() );
1137     if ( !dir.isEmpty() ) {
1138         fileWidget->setUrl( QUrl( dir ), true );
1139         fileWidget->clearHistory();
1140     }
1141 
1142     QUrl listedURL = fileWidget->url();
1143     const QStringList images = kc.readPathEntry( "Images shown", QStringList() );
1144     QStringList::const_iterator it;
1145     bool hasCurrentURL = false;
1146 
1147     for ( it = images.constBegin(); it != images.constEnd(); ++it ) {
1148         KFileItem item( (QUrl( *it )) );
1149         if ( item.isReadable() ) {
1150             if (showImage( item, true )) {
1151                 // Set the current URL in the file widget, if possible
1152                 if ( !hasCurrentURL && listedURL.isParentOf( item.url() )) {
1153                     fileWidget->setInitialItem( item.url() );
1154                     hasCurrentURL = true;
1155                 }
1156             }
1157         }
1158     }
1159 
1160     if ( !s_viewers.isEmpty() ) {
1161         bool visible = kc.readEntry( "Browser visible", true );
1162         if ( !visible )
1163             hide();
1164     }
1165 }
1166 
1167 void KuickShow::saveProperties( KConfigGroup& kc )
1168 {
1169     kc.writeEntry( "Browser visible", fileWidget && fileWidget->isVisible() );
1170     if (fileWidget)
1171     kc.writePathEntry( "CurrentDirectory", fileWidget->url().url() );
1172 
1173     QStringList urls;
1174     QList<ImageWindow*>::ConstIterator it;
1175     for ( it = s_viewers.constBegin(); it != s_viewers.constEnd(); ++it ) {
1176         const QUrl url = (*it)->url();          // checks currentFile() internally
1177         if (!url.isValid()) continue;           // no current file, ignore
1178         if ( url.isLocalFile() )
1179             urls.append( url.path() );
1180         else
1181             urls.append( url.toDisplayString() ); // ### check if writePathEntry( prettyUrl ) works!
1182     }
1183 
1184     kc.writePathEntry( "Images shown", urls );
1185 }
1186 
1187 // --------------------------------------------------------------
1188 
1189 void KuickShow::saveSettings()
1190 {
1191     KSharedConfig::Ptr kc = KSharedConfig::openConfig();
1192     KConfigGroup sessGroup(kc, "SessionSettings");
1193     if ( oneWindowAction )
1194         sessGroup.writeEntry( "OpenImagesInActiveWindow", oneWindowAction->isChecked() );
1195 
1196     if ( fileWidget ) {
1197         sessGroup.writePathEntry( "CurrentDirectory", fileWidget->url().toDisplayString() );
1198         KConfigGroup group( kc, "Filebrowser" );
1199         fileWidget->writeConfig( group);
1200     }
1201 
1202     kc->sync();
1203 }
1204 
1205 
1206 void KuickShow::messageCantLoadImage( const KuickFile *, const QString& message )
1207 {
1208     m_viewer->clearFocus();
1209     KMessageBox::error( m_viewer, message, i18n("Image Error") );
1210 }
1211 
1212 void KuickShow::initImlib()
1213 {
1214     ImData *idata = kdata->idata;
1215     ImlibInitParams par;
1216     initImlibParams( idata, &par );
1217 
1218     id = Imlib_init_with_params( getX11Display(), &par );
1219     if ( !id ) {
1220         initImlibParams( idata, &par );
1221 
1222         qWarning("*** KuickShow: Whoops, can't initialize imlib, trying my own palettefile now.");
1223         QString paletteFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kuickshow/im_palette.pal");
1224         // FIXME - does the qstrdup() cure the segfault in imlib eventually?
1225         char *file = qstrdup( paletteFile.toLocal8Bit() );
1226         par.palettefile = file;
1227         par.flags |= PARAMS_PALETTEFILE;
1228 
1229         qWarning("Palettefile: %s", par.palettefile );
1230 
1231         id = Imlib_init_with_params( getX11Display(), &par );
1232 
1233         if ( !id ) {
1234             QString tmp = i18n("Unable to initialize \"Imlib\".\n"
1235                                "Start kuickshow from the command line "
1236                                "and look for error messages.\n"
1237                                "The program will now quit.");
1238             KMessageBox::error( this, tmp, i18n("Fatal Imlib Error") );
1239 
1240             FileCache::shutdown();
1241             ::exit(1);
1242         }
1243     }
1244 }
1245 
1246 
1247 void KuickShow::initImlibParams( ImData *idata, ImlibInitParams *par )
1248 {
1249     par->flags = ( PARAMS_REMAP | PARAMS_VISUALID | PARAMS_SHAREDMEM | PARAMS_SHAREDPIXMAPS |
1250                    PARAMS_FASTRENDER | PARAMS_HIQUALITY | PARAMS_DITHER |
1251                    PARAMS_IMAGECACHESIZE | PARAMS_PIXMAPCACHESIZE );
1252 
1253     Visual* defaultvis = DefaultVisual(getX11Display(), getX11Screen());
1254 
1255     par->paletteoverride = idata->ownPalette  ? 1 : 0;
1256     par->remap           = idata->fastRemap   ? 1 : 0;
1257     par->fastrender      = idata->fastRender  ? 1 : 0;
1258     par->hiquality       = idata->dither16bit ? 1 : 0;
1259     par->dither          = idata->dither8bit  ? 1 : 0;
1260     par->sharedmem       = 1;
1261     par->sharedpixmaps   = 1;
1262     par->visualid    = defaultvis->visualid;
1263     uint maxcache        = idata->maxCache;
1264 
1265     // 0 == no cache
1266     par->imagecachesize  = maxcache * 1024;
1267     par->pixmapcachesize = maxcache * 1024;
1268 }
1269 
1270 bool KuickShow::haveBrowser() const
1271 {
1272     return fileWidget && fileWidget->isVisible();
1273 }
1274 
1275 void KuickShow::delayedRepeatEvent( ImageWindow *w, QKeyEvent *e )
1276 {
1277     m_delayedRepeatItem = new DelayedRepeatEvent( w, new QKeyEvent( *e ) );
1278 }
1279 
1280 void KuickShow::abortDelayedEvent()
1281 {
1282     delete m_delayedRepeatItem;
1283     m_delayedRepeatItem = 0L;
1284 }
1285 
1286 void KuickShow::slotReplayEvent()
1287 {
1288     disconnect( fileWidget, SIGNAL( finished() ),
1289                 this, SLOT( slotReplayEvent() ));
1290 
1291     DelayedRepeatEvent *e = m_delayedRepeatItem;
1292     m_delayedRepeatItem = 0L; // otherwise, eventFilter aborts
1293 
1294     eventFilter( e->viewer, e->event );
1295     delete e;
1296     // --------------------------------------------------------------
1297 }
1298 
1299 void KuickShow::replayAdvance(DelayedRepeatEvent *event)
1300 {
1301 #if 0
1302     // ### WORKAROUND for QIconView bug in Qt <= 3.0.3 at least
1303     // Sigh. According to qt-bugs, they won't fix this bug ever. So you can't
1304     // rely on sorting to be correct before the QIconView has been show()n.
1305     if ( fileWidget && fileWidget->view() ) {
1306         QWidget *widget = fileWidget->view()->widget();
1307         if ( widget->inherits( "QIconView" ) || widget->child(0, "QIconView" ) ){
1308             fileWidget->setSorting( fileWidget->sorting() );
1309         }
1310     }
1311 #endif
1312     // --------------------------------------------------------------
1313     slotAdvanceImage( event->viewer, *(int *) (event->data) );
1314 }
1315 
1316 void KuickShow::delayAction(DelayedRepeatEvent *event)
1317 {
1318     if (m_delayedRepeatItem)
1319         return;
1320 
1321     m_delayedRepeatItem = event;
1322 
1323     QUrl url = event->viewer->currentFile()->url();
1324 //    QFileInfo fi( event->viewer->filename() );
1325 //    start.setPath( fi.dirPath( true ) );
1326     initGUI( KIO::upUrl(url) );
1327 
1328     // see eventFilter() for explanation and similar code
1329     if ( fileWidget->dirLister()->isFinished() &&
1330          !fileWidget->dirLister()->rootItem().isNull() )
1331     {
1332         fileWidget->setCurrentItem( url );
1333         QTimer::singleShot( 0, this, SLOT( doReplay()));
1334     }
1335     else
1336     {
1337         fileWidget->setInitialItem( url );
1338         connect( fileWidget, SIGNAL( finished() ),
1339                  SLOT( doReplay() ));
1340     }
1341 }
1342 
1343 void KuickShow::doReplay()
1344 {
1345     if (!m_delayedRepeatItem)
1346         return;
1347 
1348     disconnect( fileWidget, SIGNAL( finished() ),
1349                 this, SLOT( doReplay() ));
1350 
1351     switch (m_delayedRepeatItem->action)
1352     {
1353         case DelayedRepeatEvent::DeleteCurrentFile:
1354             performDeleteCurrentImage((QWidget *) m_delayedRepeatItem->data);
1355             break;
1356         case DelayedRepeatEvent::TrashCurrentFile:
1357             performTrashCurrentImage((QWidget *) m_delayedRepeatItem->data);
1358             break;
1359         case DelayedRepeatEvent::AdvanceViewer:
1360             replayAdvance(m_delayedRepeatItem);
1361             break;
1362         default:
1363             qWarning("doReplay: unknown action -- ignoring: %d", m_delayedRepeatItem->action);
1364             break;
1365     }
1366 
1367     delete m_delayedRepeatItem;
1368     m_delayedRepeatItem = 0L;
1369 }
1370 
1371 void KuickShow::toggleBrowser()
1372 {
1373     if ( !haveBrowser() ) {
1374         if ( m_viewer && m_viewer->isFullscreen() )
1375             m_viewer->setFullscreen( false );
1376         fileWidget->resize( size() ); // ### somehow fileWidget isn't resized!?
1377         show();
1378         raise();
1379         KWindowSystem::activateWindow( winId() ); // ### this should not be necessary
1380 //         setFocus();
1381     }
1382     else if ( !s_viewers.isEmpty() )
1383         hide();
1384 }
1385 
1386 void KuickShow::slotOpenURL()
1387 {
1388     OpenFilesAndDirsDialog dlg(this, i18n("Select Files or Folder to Open"));
1389     dlg.setNameFilter(i18n("Image Files (%1)").arg(kdata->fileFilter));
1390     if(dlg.exec() != QDialog::Accepted) return;
1391 
1392     QList<QUrl> urls = dlg.selectedUrls();
1393     if(urls.isEmpty()) return;
1394 
1395     for( auto url : urls ) {
1396         KFileItem item( url );
1397         if ( FileWidget::isImage( item ) )
1398             showImage( item, true );
1399         else
1400             fileWidget->setUrl( url, true );
1401     }
1402 }
1403 
1404 void KuickShow::slotToggleInlinePreview(bool on)
1405 {
1406     int iconSize;
1407     if (on) {
1408         iconSize = KIconLoader::SizeEnormous;
1409     } else {
1410         iconSize = KIconLoader::SizeSmall;
1411     }
1412     fileWidget->setIconSize( iconSize );
1413     fileWidget->setInlinePreviewShown(on);
1414     QAction *defaultInlinePreview = fileWidget->actionCollection()->action( "inline preview" );
1415     defaultInlinePreview->setChecked(on);
1416 //  fileWidget->actionCollection("short view")
1417 }
1418 
1419 void KuickShow::deleteAllViewers()
1420 {
1421     QList<ImageWindow*>::Iterator it = s_viewers.begin();
1422     for ( ; it != s_viewers.end(); ++it ) {
1423         (*it)->disconnect( SIGNAL( destroyed() ), this, SLOT( viewerDeleted() ));
1424         delete (*it);
1425     }
1426 
1427     s_viewers.clear();
1428     m_viewer = 0L;
1429 }
1430 
1431 KActionCollection * KuickShow::actionCollection() const
1432 {
1433     if ( fileWidget )
1434         return fileWidget->actionCollection();
1435 
1436     return KXmlGuiWindow::actionCollection();
1437 }
1438 
1439 
1440 int KuickShow::getX11Screen() const
1441 {
1442     return QApplication::desktop()->screenNumber(this);
1443 }