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 }