compile
[kdegraphics.git] / okular / part.cpp
blob26d7c1b7946058987bdb049149f2b6ec85607acd
1 /***************************************************************************
2 * Copyright (C) 2002 by Wilco Greven <greven@kde.org> *
3 * Copyright (C) 2002 by Chris Cheney <ccheney@cheney.cx> *
4 * Copyright (C) 2002 by Malcolm Hunter <malcolm.hunter@gmx.co.uk> *
5 * Copyright (C) 2003-2004 by Christophe Devriese *
6 * <Christophe.Devriese@student.kuleuven.ac.be> *
7 * Copyright (C) 2003 by Daniel Molkentin <molkentin@kde.org> *
8 * Copyright (C) 2003 by Andy Goossens <andygoossens@telenet.be> *
9 * Copyright (C) 2003 by Dirk Mueller <mueller@kde.org> *
10 * Copyright (C) 2003 by Laurent Montel <montel@kde.org> *
11 * Copyright (C) 2004 by Dominique Devriese <devriese@kde.org> *
12 * Copyright (C) 2004 by Christoph Cullmann <crossfire@babylon2k.de> *
13 * Copyright (C) 2004 by Henrique Pinto <stampede@coltec.ufmg.br> *
14 * Copyright (C) 2004 by Waldo Bastian <bastian@kde.org> *
15 * Copyright (C) 2004-2008 by Albert Astals Cid <aacid@kde.org> *
16 * Copyright (C) 2004 by Antti Markus <antti.markus@starman.ee> *
17 * *
18 * This program is free software; you can redistribute it and/or modify *
19 * it under the terms of the GNU General Public License as published by *
20 * the Free Software Foundation; either version 2 of the License, or *
21 * (at your option) any later version. *
22 ***************************************************************************/
24 #include "part.h"
26 // qt/kde includes
27 #include <qapplication.h>
28 #include <qfile.h>
29 #include <qlayout.h>
30 #include <qlabel.h>
31 #include <qtimer.h>
32 #include <QtGui/QPrinter>
33 #include <QtGui/QPrintDialog>
35 #include <kvbox.h>
36 #include <kaboutapplicationdialog.h>
37 #include <kaction.h>
38 #include <kactioncollection.h>
39 #include <kdirwatch.h>
40 #include <kstandardaction.h>
41 #include <kparts/genericfactory.h>
42 #include <kfiledialog.h>
43 #include <kmessagebox.h>
44 #include <knuminput.h>
45 #include <kio/netaccess.h>
46 #include <kmenu.h>
47 #include <kxmlguiclient.h>
48 #include <kxmlguifactory.h>
49 #include <kservicetypetrader.h>
50 #include <kstandarddirs.h>
51 #include <kstandardshortcut.h>
52 #include <ktemporaryfile.h>
53 #include <ktoggleaction.h>
54 #include <ktogglefullscreenaction.h>
55 #include <kio/job.h>
56 #include <kicon.h>
57 #include <kfilterdev.h>
58 #include <knewstuff2/engine.h>
59 #include <kdeprintdialog.h>
60 #include <kprintpreview.h>
62 // local includes
63 #include "aboutdata.h"
64 #include "extensions.h"
65 #include "ui/pageview.h"
66 #include "ui/toc.h"
67 #include "ui/searchwidget.h"
68 #include "ui/thumbnaillist.h"
69 #include "ui/side_reviews.h"
70 #include "ui/minibar.h"
71 #include "ui/embeddedfilesdialog.h"
72 #include "ui/propertiesdialog.h"
73 #include "ui/presentationwidget.h"
74 #include "ui/pagesizelabel.h"
75 #include "ui/bookmarklist.h"
76 #include "ui/findbar.h"
77 #include "ui/sidebar.h"
78 #include "ui/fileprinterpreview.h"
79 #include "ui/guiutils.h"
80 #include "conf/preferencesdialog.h"
81 #include "settings.h"
82 #include "core/bookmarkmanager.h"
83 #include "core/document.h"
84 #include "core/generator.h"
85 #include "core/page.h"
86 #include "core/fileprinter.h"
88 #include <cstdio>
90 class FileKeeper
92 public:
93 FileKeeper()
94 : m_handle( NULL )
98 ~FileKeeper()
102 void open( const QString & path )
104 if ( !m_handle )
105 m_handle = std::fopen( QFile::encodeName( path ), "r" );
108 void close()
110 if ( m_handle )
112 int ret = std::fclose( m_handle );
113 Q_UNUSED( ret )
114 m_handle = NULL;
118 KTemporaryFile* copyToTemporary() const
120 if ( !m_handle )
121 return 0;
123 KTemporaryFile * retFile = new KTemporaryFile;
124 retFile->open();
126 std::rewind( m_handle );
127 int c = -1;
130 c = std::fgetc( m_handle );
131 if ( c == EOF )
132 break;
133 if ( !retFile->putChar( (char)c ) )
134 break;
135 } while ( !feof( m_handle ) );
137 retFile->flush();
139 return retFile;
142 private:
143 std::FILE * m_handle;
146 K_PLUGIN_FACTORY( okularPartFactory, registerPlugin< Part >(); )
147 K_EXPORT_PLUGIN( okularPartFactory( okularAboutData( "okular", I18N_NOOP( "Okular" ) ) ) )
149 static QAction* actionForExportFormat( const Okular::ExportFormat& format, QObject *parent = 0 )
151 QAction *act = new QAction( format.description(), parent );
152 if ( !format.icon().isNull() )
154 act->setIcon( format.icon() );
156 return act;
159 static QString compressedMimeFor( const QString& mime_to_check )
161 static QHash< QString, QString > compressedMimeMap;
162 if ( compressedMimeMap.isEmpty() )
164 compressedMimeMap[ QString::fromLatin1( "application/x-gzip" ) ] =
165 QString::fromLatin1( "application/x-gzip" );
166 compressedMimeMap[ QString::fromLatin1( "application/x-bzip" ) ] =
167 QString::fromLatin1( "application/x-bzip" );
168 compressedMimeMap[ QString::fromLatin1( "application/x-bzpdf" ) ] =
169 QString::fromLatin1( "application/x-bzip" );
170 compressedMimeMap[ QString::fromLatin1( "application/x-bzpostscript" ) ] =
171 QString::fromLatin1( "application/x-bzip" );
172 compressedMimeMap[ QString::fromLatin1( "application/x-bzdvi" ) ] =
173 QString::fromLatin1( "application/x-bzip" );
174 compressedMimeMap[ QString::fromLatin1( "image/x-gzeps" ) ] =
175 QString::fromLatin1( "application/x-gzip" );
176 compressedMimeMap[ QString::fromLatin1( "image/x-bzeps" ) ] =
177 QString::fromLatin1( "application/x-bzip" );
179 QHash< QString, QString >::const_iterator it = compressedMimeMap.constFind( mime_to_check );
180 if ( it != compressedMimeMap.constEnd() )
181 return it.value();
183 return QString();
186 #undef OKULAR_KEEP_FILE_OPEN
188 #ifdef OKULAR_KEEP_FILE_OPEN
189 static bool keepFileOpen()
191 static bool keep_file_open = !qgetenv("OKULAR_NO_KEEP_FILE_OPEN").toInt();
192 return keep_file_open;
194 #endif
196 Part::Part(QWidget *parentWidget,
197 QObject *parent,
198 const QVariantList &args )
199 : KParts::ReadOnlyPart(parent),
200 m_tempfile( 0 ), m_fileWasRemoved( false ), m_showMenuBarAction( 0 ), m_showFullScreenAction( 0 ), m_actionsSearched( false ),
201 m_cliPresentation(false), m_generatorGuiClient(0), m_keeper( 0 )
203 // first necessary step: copy the configuration from kpdf, if available
204 QString newokularconffile = KStandardDirs::locateLocal( "config", "okularpartrc" );
205 if ( !QFile::exists( newokularconffile ) )
207 QString oldkpdfconffile = KStandardDirs::locateLocal( "config", "kpdfpartrc" );
208 if ( QFile::exists( oldkpdfconffile ) )
209 QFile::copy( oldkpdfconffile, newokularconffile );
212 QDBusConnection::sessionBus().registerObject("/okular", this, QDBusConnection::ExportScriptableSlots);
214 // connect the started signal to tell the job the mimetypes we like
215 connect(this, SIGNAL(started(KIO::Job *)), this, SLOT(setMimeTypes(KIO::Job *)));
217 // connect the completed signal so we can put the window caption when loading remote files
218 connect(this, SIGNAL(completed()), this, SLOT(setWindowTitleFromDocument()));
219 connect(this, SIGNAL(canceled(const QString &)), this, SLOT(loadCancelled(const QString &)));
221 // create browser extension (for printing when embedded into browser)
222 m_bExtension = new BrowserExtension(this);
223 // create live connect extension (for integrating with browser scripting)
224 new OkularLiveConnectExtension( this );
226 // we need an instance
227 setComponentData(okularPartFactory::componentData());
229 GuiUtils::setIconLoader( iconLoader() );
231 m_sidebar = new Sidebar( parentWidget );
232 setWidget( m_sidebar );
234 // build the document
235 m_document = new Okular::Document(widget());
236 connect( m_document, SIGNAL( linkFind() ), this, SLOT( slotFind() ) );
237 connect( m_document, SIGNAL( linkGoToPage() ), this, SLOT( slotGoToPage() ) );
238 connect( m_document, SIGNAL( linkPresentation() ), this, SLOT( slotShowPresentation() ) );
239 connect( m_document, SIGNAL( linkEndPresentation() ), this, SLOT( slotHidePresentation() ) );
240 connect( m_document, SIGNAL( openUrl(const KUrl &) ), this, SLOT( openUrlFromDocument(const KUrl &) ) );
241 connect( m_document->bookmarkManager(), SIGNAL( openUrl(const KUrl &) ), this, SLOT( openUrlFromBookmarks(const KUrl &) ) );
242 connect( m_document, SIGNAL( close() ), this, SLOT( close() ) );
244 if ( parent && parent->metaObject()->indexOfSlot( QMetaObject::normalizedSignature( "slotQuit()" ) ) != -1 )
245 connect( m_document, SIGNAL( quit() ), parent, SLOT( slotQuit() ) );
246 else
247 connect( m_document, SIGNAL( quit() ), this, SLOT( cannotQuit() ) );
248 // widgets: ^searchbar (toolbar containing label and SearchWidget)
249 // m_searchToolBar = new KToolBar( parentWidget, "searchBar" );
250 // m_searchToolBar->boxLayout()->setSpacing( KDialog::spacingHint() );
251 // QLabel * sLabel = new QLabel( i18n( "&Search:" ), m_searchToolBar, "kde toolbar widget" );
252 // m_searchWidget = new SearchWidget( m_searchToolBar, m_document );
253 // sLabel->setBuddy( m_searchWidget );
254 // m_searchToolBar->setStretchableWidget( m_searchWidget );
256 int tbIndex;
257 // [left toolbox: Table of Contents] | []
258 m_toc = new TOC( 0, m_document );
259 connect( m_toc, SIGNAL( hasTOC( bool ) ), this, SLOT( enableTOC( bool ) ) );
260 tbIndex = m_sidebar->addItem( m_toc, KIcon(QApplication::isLeftToRight() ? "format-justify-left" : "format-justify-right"), i18n("Contents") );
261 enableTOC( false );
263 // [left toolbox: Thumbnails and Bookmarks] | []
264 KVBox * thumbsBox = new ThumbnailsBox( 0 );
265 thumbsBox->setSpacing( 6 );
266 m_searchWidget = new SearchWidget( thumbsBox, m_document );
267 m_thumbnailList = new ThumbnailList( thumbsBox, m_document );
268 // ThumbnailController * m_tc = new ThumbnailController( thumbsBox, m_thumbnailList );
269 connect( m_thumbnailList, SIGNAL( urlDropped( const KUrl& ) ), SLOT( openUrlFromDocument( const KUrl & )) );
270 connect( m_thumbnailList, SIGNAL( rightClick(const Okular::Page *, const QPoint &) ), this, SLOT( slotShowMenu(const Okular::Page *, const QPoint &) ) );
271 tbIndex = m_sidebar->addItem( thumbsBox, KIcon( "view-preview" ), i18n("Thumbnails") );
272 m_sidebar->setCurrentIndex( tbIndex );
274 // [left toolbox: Reviews] | []
275 m_reviewsWidget = new Reviews( 0, m_document );
276 m_sidebar->addItem( m_reviewsWidget, KIcon("draw-freehand"), i18n("Reviews") );
277 m_sidebar->setItemEnabled( 2, false );
279 // [left toolbox: Bookmarks] | []
280 m_bookmarkList = new BookmarkList( m_document, 0 );
281 m_sidebar->addItem( m_bookmarkList, KIcon("bookmarks"), i18n("Bookmarks") );
282 m_sidebar->setItemEnabled( 3, false );
284 // widgets: [../miniBarContainer] | []
285 #ifdef OKULAR_ENABLE_MINIBAR
286 QWidget * miniBarContainer = new QWidget( 0 );
287 m_sidebar->setBottomWidget( miniBarContainer );
288 QVBoxLayout * miniBarLayout = new QVBoxLayout( miniBarContainer );
289 miniBarLayout->setMargin( 0 );
290 // widgets: [../[spacer/..]] | []
291 miniBarLayout->addItem( new QSpacerItem( 6, 6, QSizePolicy::Fixed, QSizePolicy::Fixed ) );
292 // widgets: [../[../MiniBar]] | []
293 QFrame * bevelContainer = new QFrame( miniBarContainer );
294 bevelContainer->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
295 QVBoxLayout * bevelContainerLayout = new QVBoxLayout( bevelContainer );
296 bevelContainerLayout->setMargin( 4 );
297 m_progressWidget = new ProgressWidget( bevelContainer, m_document );
298 bevelContainerLayout->addWidget( m_progressWidget );
299 miniBarLayout->addWidget( bevelContainer );
300 miniBarLayout->addItem( new QSpacerItem( 6, 6, QSizePolicy::Fixed, QSizePolicy::Fixed ) );
301 #endif
303 // widgets: [] | [right 'pageView']
304 QWidget * rightContainer = new QWidget( 0 );
305 m_sidebar->setMainWidget( rightContainer );
306 QVBoxLayout * rightLayout = new QVBoxLayout( rightContainer );
307 rightLayout->setMargin( 0 );
308 rightLayout->setSpacing( 0 );
309 // KToolBar * rtb = new KToolBar( rightContainer, "mainToolBarSS" );
310 // rightLayout->addWidget( rtb );
311 m_topMessage = new PageViewTopMessage( rightContainer );
312 m_topMessage->setup( i18n( "This document has embedded files. <a href=\"okular:/embeddedfiles\">Click here to see them</a> or go to File -> Embedded Files." ), KIcon( "mail-attachment" ) );
313 connect( m_topMessage, SIGNAL( action() ), this, SLOT( slotShowEmbeddedFiles() ) );
314 rightLayout->addWidget( m_topMessage );
315 m_formsMessage = new PageViewTopMessage( rightContainer );
316 m_formsMessage->setup( i18n( "This document has forms. Click on the button to interact with them, or use View -> Show Forms." ) );
317 rightLayout->addWidget( m_formsMessage );
318 m_pageView = new PageView( rightContainer, m_document );
319 m_pageView->setFocus(); //usability setting
320 // m_splitter->setFocusProxy(m_pageView);
321 connect( m_pageView, SIGNAL( urlDropped( const KUrl& ) ), SLOT( openUrlFromDocument( const KUrl & )));
322 connect( m_pageView, SIGNAL( rightClick(const Okular::Page *, const QPoint &) ), this, SLOT( slotShowMenu(const Okular::Page *, const QPoint &) ) );
323 connect( m_document, SIGNAL( error( const QString&, int ) ), m_pageView, SLOT( errorMessage( const QString&, int ) ) );
324 connect( m_document, SIGNAL( warning( const QString&, int ) ), m_pageView, SLOT( warningMessage( const QString&, int ) ) );
325 connect( m_document, SIGNAL( notice( const QString&, int ) ), m_pageView, SLOT( noticeMessage( const QString&, int ) ) );
326 rightLayout->addWidget( m_pageView );
327 m_findBar = new FindBar( m_document, rightContainer );
328 rightLayout->addWidget( m_findBar );
329 QWidget * bottomBar = new QWidget( rightContainer );
330 QHBoxLayout * bottomBarLayout = new QHBoxLayout( bottomBar );
331 m_pageSizeLabel = new PageSizeLabel( bottomBar, m_document );
332 bottomBarLayout->setMargin( 0 );
333 bottomBarLayout->setSpacing( 0 );
334 bottomBarLayout->addWidget( m_pageSizeLabel->antiWidget() );
335 bottomBarLayout->addItem( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
336 m_miniBar = new MiniBar( bottomBar, m_document );
337 bottomBarLayout->addWidget( m_miniBar );
338 bottomBarLayout->addItem( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
339 bottomBarLayout->addWidget( m_pageSizeLabel );
340 rightLayout->addWidget( bottomBar );
342 connect( m_reviewsWidget, SIGNAL( setAnnotationWindow( Okular::Annotation* ) ),
343 m_pageView, SLOT( setAnnotationWindow( Okular::Annotation* ) ) );
344 connect( m_reviewsWidget, SIGNAL( removeAnnotationWindow( Okular::Annotation* ) ),
345 m_pageView, SLOT( removeAnnotationWindow( Okular::Annotation* ) ) );
347 // add document observers
348 m_document->addObserver( this );
349 m_document->addObserver( m_thumbnailList );
350 m_document->addObserver( m_pageView );
351 m_document->registerView( m_pageView );
352 m_document->addObserver( m_toc );
353 m_document->addObserver( m_miniBar );
354 #ifdef OKULAR_ENABLE_MINIBAR
355 m_document->addObserver( m_progressWidget );
356 #endif
357 m_document->addObserver( m_reviewsWidget );
358 m_document->addObserver( m_pageSizeLabel );
359 m_document->addObserver( m_bookmarkList );
361 connect( m_document->bookmarkManager(), SIGNAL( saved() ),
362 this, SLOT( slotRebuildBookmarkMenu() ) );
364 // ACTIONS
365 KActionCollection * ac = actionCollection();
367 // Page Traversal actions
368 m_gotoPage = KStandardAction::gotoPage( this, SLOT( slotGoToPage() ), ac );
369 m_gotoPage->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_G) );
370 // dirty way to activate gotopage when pressing miniBar's button
371 connect( m_miniBar, SIGNAL( gotoPage() ), m_gotoPage, SLOT( trigger() ) );
373 m_prevPage = KStandardAction::prior(this, SLOT(slotPreviousPage()), ac);
374 m_prevPage->setIconText( i18nc( "Previous page", "Previous" ) );
375 m_prevPage->setToolTip( i18n( "Go back to the Previous Page" ) );
376 m_prevPage->setWhatsThis( i18n( "Moves to the previous page of the document" ) );
377 m_prevPage->setShortcut( 0 );
378 // dirty way to activate prev page when pressing miniBar's button
379 connect( m_miniBar, SIGNAL( prevPage() ), m_prevPage, SLOT( trigger() ) );
380 #ifdef OKULAR_ENABLE_MINIBAR
381 connect( m_progressWidget, SIGNAL( prevPage() ), m_prevPage, SLOT( trigger() ) );
382 #endif
384 m_nextPage = KStandardAction::next(this, SLOT(slotNextPage()), ac );
385 m_nextPage->setIconText( i18nc( "Next page", "Next" ) );
386 m_nextPage->setToolTip( i18n( "Advance to the Next Page" ) );
387 m_nextPage->setWhatsThis( i18n( "Moves to the next page of the document" ) );
388 m_nextPage->setShortcut( 0 );
389 // dirty way to activate next page when pressing miniBar's button
390 connect( m_miniBar, SIGNAL( nextPage() ), m_nextPage, SLOT( trigger() ) );
391 #ifdef OKULAR_ENABLE_MINIBAR
392 connect( m_progressWidget, SIGNAL( nextPage() ), m_nextPage, SLOT( trigger() ) );
393 #endif
395 m_firstPage = KStandardAction::firstPage( this, SLOT( slotGotoFirst() ), ac );
396 ac->addAction("first_page", m_firstPage);
397 m_firstPage->setWhatsThis( i18n( "Moves to the first page of the document" ) );
399 m_lastPage = KStandardAction::lastPage( this, SLOT( slotGotoLast() ), ac );
400 ac->addAction("last_page",m_lastPage);
401 m_lastPage->setWhatsThis( i18n( "Moves to the last page of the document" ) );
403 // we do not want back and next in history in the dummy mode
404 m_historyBack = 0;
405 m_historyNext = 0;
407 m_addBookmark = KStandardAction::addBookmark( this, SLOT( slotAddBookmark() ), ac );
408 m_addBookmarkText = m_addBookmark->text();
409 m_addBookmarkIcon = m_addBookmark->icon();
411 m_prevBookmark = ac->addAction("previous_bookmark");
412 m_prevBookmark->setText(i18n( "Previous Bookmark" ));
413 m_prevBookmark->setIcon(KIcon( "go-up-search" ));
414 m_prevBookmark->setWhatsThis( i18n( "Go to the previous bookmarked page" ) );
415 connect( m_prevBookmark, SIGNAL( triggered() ), this, SLOT( slotPreviousBookmark() ) );
417 m_nextBookmark = ac->addAction("next_bookmark");
418 m_nextBookmark->setText(i18n( "Next Bookmark" ));
419 m_nextBookmark->setIcon(KIcon( "go-down-search" ));
420 m_nextBookmark->setWhatsThis( i18n( "Go to the next bookmarked page" ) );
421 connect( m_nextBookmark, SIGNAL( triggered() ), this, SLOT( slotNextBookmark() ) );
423 m_copy = KStandardAction::create( KStandardAction::Copy, m_pageView, SLOT( copyTextSelection() ), ac );
425 m_selectAll = KStandardAction::selectAll( m_pageView, SLOT( selectAll() ), ac );
427 // Find and other actions
428 m_find = KStandardAction::find( this, SLOT( slotShowFindBar() ), ac );
429 QList<QKeySequence> s = m_find->shortcuts();
430 s.append( QKeySequence( Qt::Key_Slash ) );
431 m_find->setShortcuts( s );
432 m_find->setEnabled( false );
434 m_findNext = KStandardAction::findNext( this, SLOT( slotFindNext() ), ac);
435 m_findNext->setEnabled( false );
437 m_findPrev = KStandardAction::findPrev( this, SLOT( slotFindPrev() ), ac );
438 m_findPrev->setEnabled( false );
440 m_saveCopyAs = KStandardAction::saveAs( this, SLOT( slotSaveCopyAs() ), ac );
441 m_saveCopyAs->setText( i18n( "Save &Copy As..." ) );
442 ac->addAction( "file_save_copy", m_saveCopyAs );
443 m_saveCopyAs->setEnabled( false );
445 m_saveAs = KStandardAction::saveAs( this, SLOT( slotSaveFileAs() ), ac );
446 m_saveAs->setEnabled( false );
448 QAction * prefs = KStandardAction::preferences( this, SLOT( slotPreferences() ), ac);
449 if ( parent && ( parent->objectName() == QLatin1String( "okular::Shell" ) ) )
451 prefs->setText( i18n( "Configure Okular..." ) );
453 else
455 // TODO: improve this message
456 prefs->setText( i18n( "Configure Viewer..." ) );
459 KAction * genPrefs = new KAction( ac );
460 ac->addAction("options_configure_generators", genPrefs);
461 genPrefs->setText( i18n( "Configure Backends..." ) );
462 genPrefs->setIcon( KIcon( "configure" ) );
463 genPrefs->setEnabled( m_document->configurableGenerators() > 0 );
464 connect( genPrefs, SIGNAL( triggered( bool ) ), this, SLOT( slotGeneratorPreferences() ) );
466 m_printPreview = KStandardAction::printPreview( this, SLOT( slotPrintPreview() ), ac );
467 m_printPreview->setEnabled( false );
469 m_showLeftPanel = ac->add<KToggleAction>("show_leftpanel");
470 m_showLeftPanel->setText(i18n( "Show &Navigation Panel"));
471 m_showLeftPanel->setIcon(KIcon( "view-sidetree" ));
472 connect( m_showLeftPanel, SIGNAL( toggled( bool ) ), this, SLOT( slotShowLeftPanel() ) );
473 m_showLeftPanel->setShortcut( Qt::Key_F7 );
474 m_showLeftPanel->setChecked( Okular::Settings::showLeftPanel() );
475 slotShowLeftPanel();
477 QAction * importPS = ac->addAction("import_ps");
478 importPS->setText(i18n("&Import PostScript as PDF..."));
479 importPS->setIcon(KIcon("document-import"));
480 connect(importPS, SIGNAL(triggered()), this, SLOT(slotImportPSFile()));
481 #if 0
482 QAction * ghns = ac->addAction("get_new_stuff");
483 ghns->setText(i18n("&Get Books From Internet..."));
484 ghns->setIcon(KIcon("get-hot-new-stuff"));
485 connect(ghns, SIGNAL(triggered()), this, SLOT(slotGetNewStuff()));
486 // TEMP, REMOVE ME!
487 ghns->setShortcut( Qt::Key_G );
488 #endif
490 m_showProperties = ac->addAction("properties");
491 m_showProperties->setText(i18n("&Properties"));
492 m_showProperties->setIcon(KIcon("document-properties"));
493 connect(m_showProperties, SIGNAL(triggered()), this, SLOT(slotShowProperties()));
494 m_showProperties->setEnabled( false );
496 m_showEmbeddedFiles = ac->addAction("embedded_files");
497 m_showEmbeddedFiles->setText(i18n("&Embedded Files"));
498 m_showEmbeddedFiles->setIcon( KIcon( "mail-attachment" ) );
499 connect(m_showEmbeddedFiles, SIGNAL(triggered()), this, SLOT(slotShowEmbeddedFiles()));
500 m_showEmbeddedFiles->setEnabled( false );
502 m_showPresentation = ac->addAction("presentation");
503 m_showPresentation->setText(i18n("P&resentation"));
504 m_showPresentation->setIcon( KIcon( "view-presentation" ) );
505 connect(m_showPresentation, SIGNAL(triggered()), this, SLOT(slotShowPresentation()));
506 m_showPresentation->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_P ) );
507 m_showPresentation->setEnabled( false );
509 m_exportAs = ac->addAction("file_export_as");
510 m_exportAs->setText(i18n("E&xport As"));
511 m_exportAs->setIcon( KIcon( "document-export" ) );
512 m_exportAsMenu = new QMenu();
513 connect(m_exportAsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotExportAs(QAction *)));
514 m_exportAs->setMenu( m_exportAsMenu );
515 m_exportAsText = actionForExportFormat( Okular::ExportFormat::standardFormat( Okular::ExportFormat::PlainText ), m_exportAsMenu );
516 m_exportAsMenu->addAction( m_exportAsText );
517 m_exportAs->setEnabled( false );
518 m_exportAsText->setEnabled( false );
519 m_exportAsDocArchive = actionForExportFormat( Okular::ExportFormat(
520 i18nc( "A document format, Okular-specific", "Document Archive" ),
521 KMimeType::mimeType( "application/vnd.kde.okular-archive" ) ), m_exportAsMenu );
522 m_exportAsMenu->addAction( m_exportAsDocArchive );
523 m_exportAsDocArchive->setEnabled( false );
525 m_aboutBackend = ac->addAction("help_about_backend");
526 m_aboutBackend->setText(i18n("About Backend"));
527 m_aboutBackend->setEnabled( false );
528 connect(m_aboutBackend, SIGNAL(triggered()), this, SLOT(slotAboutBackend()));
530 KAction *reload = ac->add<KAction>( "file_reload" );
531 reload->setText( i18n( "Reloa&d" ) );
532 reload->setIcon( KIcon( "view-refresh" ) );
533 reload->setWhatsThis( i18n( "Reload the current document from disk." ) );
534 connect( reload, SIGNAL(triggered()), this, SLOT(slotReload()) );
535 reload->setShortcut( KStandardShortcut::reload() );
536 m_reload = reload;
538 KAction *closeFindBar = new KAction( i18n( "Close &Find Bar" ), ac );
539 ac->addAction("close_find_bar", closeFindBar);
540 connect(closeFindBar, SIGNAL(triggered()), this, SLOT(slotHideFindBar()));
541 closeFindBar->setShortcut( QKeySequence( Qt::Key_Escape ) );
542 widget()->addAction(closeFindBar);
544 KToggleAction *blackscreenAction = new KToggleAction( i18n( "Switch Blackscreen Mode" ), ac );
545 ac->addAction( "switch_blackscreen_mode", blackscreenAction );
546 blackscreenAction->setShortcut( QKeySequence( Qt::Key_B ) );
547 blackscreenAction->setIcon( KIcon( "view-presentation" ) );
549 KToggleAction *drawingAction = new KToggleAction( i18n( "Toggle Drawing Mode" ), ac );
550 ac->addAction( "presentation_drawing_mode", drawingAction );
551 drawingAction->setIcon( KIcon( "draw-freehand" ) );
553 KAction *eraseDrawingAction = new KAction( i18n( "Erase Drawings" ), ac );
554 ac->addAction( "presentation_erase_drawings", eraseDrawingAction );
555 eraseDrawingAction->setIcon( KIcon( "draw-eraser" ) );
557 // document watcher and reloader
558 m_watcher = new KDirWatch( this );
559 connect( m_watcher, SIGNAL( dirty( const QString& ) ), this, SLOT( slotFileDirty( const QString& ) ) );
560 m_dirtyHandler = new QTimer( this );
561 m_dirtyHandler->setSingleShot( true );
562 connect( m_dirtyHandler, SIGNAL( timeout() ),this, SLOT( slotDoFileDirty() ) );
564 slotNewConfig();
566 // [SPEECH] check for KTTSD presence and usability
567 KService::List offers = KServiceTypeTrader::self()->query("DBUS/Text-to-Speech", "Name == 'KTTSD'");
568 Okular::Settings::setUseKTTSD( !offers.isEmpty() );
569 Okular::Settings::self()->writeConfig();
571 rebuildBookmarkMenu( false );
573 // set our XML-UI resource file
574 setXMLFile("part.rc");
576 m_pageView->setupBaseActions( actionCollection() );
578 // ensure history actions are in the correct state
579 updateViewActions();
581 m_dummyMode = true;
582 m_sidebar->setSidebarVisibility( false );
583 if ( !args.contains( QVariant( "Print/Preview" ) ) ) unsetDummyMode();
585 #ifdef OKULAR_KEEP_FILE_OPEN
586 m_keeper = new FileKeeper();
587 #endif
591 Part::~Part()
593 m_document->removeObserver( this );
595 if ( m_document->isOpened() )
596 Part::closeUrl();
598 delete m_toc;
599 delete m_pageView;
600 delete m_thumbnailList;
601 delete m_miniBar;
602 #ifdef OKULAR_ENABLE_MINIBAR
603 delete m_progressWidget;
604 #endif
605 delete m_pageSizeLabel;
606 delete m_reviewsWidget;
607 delete m_bookmarkList;
609 delete m_document;
611 delete m_tempfile;
613 qDeleteAll( m_bookmarkActions );
615 delete m_exportAsMenu;
617 #ifdef OKULAR_KEEP_FILE_OPEN
618 delete m_keeper;
619 #endif
623 bool Part::openDocument(const KUrl& url, uint page)
625 Okular::DocumentViewport vp( page - 1 );
626 vp.rePos.enabled = true;
627 vp.rePos.normalizedX = 0;
628 vp.rePos.normalizedY = 0;
629 vp.rePos.pos = Okular::DocumentViewport::TopLeft;
630 if ( vp.isValid() )
631 m_document->setNextDocumentViewport( vp );
632 return openUrl( url );
636 void Part::startPresentation()
638 m_cliPresentation = true;
642 QStringList Part::supportedMimeTypes() const
644 return m_document->supportedMimeTypes();
648 KUrl Part::realUrl() const
650 if ( !m_realUrl.isEmpty() )
651 return m_realUrl;
653 return url();
657 void Part::openUrlFromDocument(const KUrl &url)
659 if (m_dummyMode) return;
661 m_bExtension->openUrlNotify();
662 m_bExtension->setLocationBarUrl(url.prettyUrl());
663 openUrl(url);
666 void Part::openUrlFromBookmarks(const KUrl &_url)
668 KUrl url = _url;
669 Okular::DocumentViewport vp( _url.htmlRef() );
670 if ( vp.isValid() )
671 m_document->setNextDocumentViewport( vp );
672 url.setHTMLRef( QString() );
673 if ( m_document->currentDocument() == url )
675 if ( vp.isValid() )
676 m_document->setViewport( vp );
678 else
679 openUrl( url );
682 void Part::setMimeTypes(KIO::Job *job)
684 if (job)
686 QStringList supportedMimeTypes = m_document->supportedMimeTypes();
687 job->addMetaData("accept", supportedMimeTypes.join(", ") + ", */*;q=0.5");
691 void Part::loadCancelled(const QString &reason)
693 emit setWindowCaption( QString() );
695 // when m_viewportDirty.pageNumber != -1 we come from slotDoFileDirty
696 // so we don't want to show an ugly messagebox just because the document is
697 // taking more than usual to be recreated
698 if (m_viewportDirty.pageNumber == -1)
700 if (!reason.isEmpty())
702 KMessageBox::error( widget(), i18n("Could not open %1. Reason: %2", url().prettyUrl(), reason ) );
704 else
706 KMessageBox::error( widget(), i18n("Could not open %1", url().prettyUrl() ) );
711 void Part::setWindowTitleFromDocument()
713 // If 'DocumentTitle' should be used, check if the document has one. If
714 // either case is false, use the file name.
715 QString title = realUrl().fileName();
717 if ( Okular::Settings::displayDocumentTitle() )
719 const QString docTitle = m_document->metaData( "DocumentTitle" ).toString();
720 if ( !docTitle.isEmpty() && !docTitle.trimmed().isEmpty() )
722 title = docTitle;
726 emit setWindowCaption( title );
729 void Part::slotGeneratorPreferences( )
731 // an instance the dialog could be already created and could be cached,
732 // in which case you want to display the cached dialog
733 if ( KConfigDialog::showDialog( "generator_prefs" ) )
734 return;
736 // we didn't find an instance of this dialog, so lets create it
737 KConfigDialog * dialog = new KConfigDialog( m_pageView, "generator_prefs", Okular::Settings::self() );
738 dialog->setCaption( i18n( "Configure Backends" ) );
740 m_document->fillConfigDialog( dialog );
742 // keep us informed when the user changes settings
743 connect( dialog, SIGNAL( settingsChanged( const QString& ) ), this, SLOT( slotNewGeneratorConfig() ) );
744 dialog->show();
748 void Part::notifySetup( const QVector< Okular::Page * > & /*pages*/, int setupFlags )
750 if ( !( setupFlags & Okular::DocumentObserver::DocumentChanged ) )
751 return;
753 rebuildBookmarkMenu();
754 updateAboutBackendAction();
755 m_searchWidget->setEnabled( m_document->supportsSearching() );
758 void Part::notifyViewportChanged( bool /*smoothMove*/ )
760 // update actions if the page is changed
761 static int lastPage = -1;
762 int viewportPage = m_document->viewport().pageNumber;
763 if ( viewportPage != lastPage )
765 updateViewActions();
766 lastPage = viewportPage;
770 void Part::notifyPageChanged( int page, int flags )
772 if ( !(flags & Okular::DocumentObserver::Bookmark ) )
773 return;
775 rebuildBookmarkMenu();
776 if ( page == m_document->viewport().pageNumber )
777 updateBookmarksActions();
781 void Part::goToPage(uint i)
783 if ( i <= m_document->pages() )
784 m_document->setViewportPage( i - 1 );
788 void Part::openDocument( const QString &doc )
790 openUrl( KUrl( doc ) );
794 uint Part::pages()
796 return m_document->pages();
800 uint Part::currentPage()
802 return m_document->pages() ? m_document->currentPage() + 1 : 0;
806 QString Part::currentDocument()
808 return m_document->currentDocument().pathOrUrl();
812 bool Part::slotImportPSFile()
814 QString app = KStandardDirs::findExe( "ps2pdf" );
815 if ( app.isEmpty() )
817 // TODO point the user to their distro packages?
818 KMessageBox::error( widget(), i18n( "The program \"ps2pdf\" was not found, so Okular can not import PS files using it." ), i18n("ps2pdf not found") );
819 return false;
822 KUrl url = KFileDialog::getOpenUrl( KUrl(), "application/postscript", this->widget() );
823 if ( url.isLocalFile() )
825 KTemporaryFile tf;
826 tf.setSuffix( ".pdf" );
827 tf.setAutoRemove( false );
828 if ( !tf.open() )
829 return false;
830 m_temporaryLocalFile = tf.fileName();
831 tf.close();
833 setLocalFilePath( url.path() );
834 QStringList args;
835 QProcess *p = new QProcess();
836 args << url.toLocalFile() << m_temporaryLocalFile;
837 m_pageView->displayMessage(i18n("Importing PS file as PDF (this may take a while)..."));
838 connect(p, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(psTransformEnded(int, QProcess::ExitStatus)));
839 p->start(app, args);
840 return true;
843 m_temporaryLocalFile.clear();
844 return false;
848 bool Part::openFile()
850 KMimeType::Ptr mime;
851 if ( !arguments().mimeType().isEmpty() )
853 mime = KMimeType::mimeType( arguments().mimeType() );
855 if ( !mime )
857 mime = KMimeType::findByPath( localFilePath() );
859 bool isCompressedFile = false;
860 bool uncompressOk = true;
861 QString fileNameToOpen = localFilePath();
862 QString compressedMime = compressedMimeFor( mime->name() );
863 if ( compressedMime.isEmpty() )
864 compressedMime = compressedMimeFor( mime->parentMimeType() );
865 if ( !compressedMime.isEmpty() )
867 isCompressedFile = true;
868 uncompressOk = handleCompressed( fileNameToOpen, localFilePath(), compressedMime );
869 mime = KMimeType::findByPath( fileNameToOpen );
871 bool ok = false;
872 if ( uncompressOk )
874 if ( mime->is( "application/vnd.kde.okular-archive" ) )
875 ok = m_document->openDocumentArchive( fileNameToOpen, url() );
876 else
877 ok = m_document->openDocument( fileNameToOpen, url(), mime );
879 bool canSearch = m_document->supportsSearching();
881 // update one-time actions
882 m_find->setEnabled( ok && canSearch );
883 m_findNext->setEnabled( ok && canSearch );
884 m_findPrev->setEnabled( ok && canSearch );
885 m_saveAs->setEnabled( ok && m_document->canSaveChanges() );
886 m_saveCopyAs->setEnabled( ok );
887 emit enablePrintAction( ok && m_document->printingSupport() != Okular::Document::NoPrinting );
888 m_printPreview->setEnabled( ok && m_document->printingSupport() != Okular::Document::NoPrinting );
889 m_showProperties->setEnabled( ok );
890 bool hasEmbeddedFiles = ok && m_document->embeddedFiles() && m_document->embeddedFiles()->count() > 0;
891 m_showEmbeddedFiles->setEnabled( hasEmbeddedFiles );
892 m_topMessage->setVisible( hasEmbeddedFiles );
893 // m_pageView->toggleFormsAction() may be null on dummy mode
894 m_formsMessage->setVisible( ok && m_pageView->toggleFormsAction() && m_pageView->toggleFormsAction()->isEnabled() );
895 m_showPresentation->setEnabled( ok );
896 if ( ok )
898 m_exportFormats = m_document->exportFormats();
899 QList<Okular::ExportFormat>::ConstIterator it = m_exportFormats.constBegin();
900 QList<Okular::ExportFormat>::ConstIterator itEnd = m_exportFormats.constEnd();
901 QMenu *menu = m_exportAs->menu();
902 for ( ; it != itEnd; ++it )
904 menu->addAction( actionForExportFormat( *it ) );
906 if ( isCompressedFile )
908 m_realUrl = url();
910 #ifdef OKULAR_KEEP_FILE_OPEN
911 if ( keepFileOpen() )
912 m_keeper->open( fileNameToOpen );
913 #endif
915 m_exportAsText->setEnabled( ok && m_document->canExportToText() );
916 m_exportAsDocArchive->setEnabled( ok );
917 m_exportAs->setEnabled( ok );
919 // update viewing actions
920 updateViewActions();
922 m_fileWasRemoved = false;
924 if ( !ok )
926 // if can't open document, update windows so they display blank contents
927 m_pageView->widget()->update();
928 m_thumbnailList->update();
929 return false;
932 // set the file to the fileWatcher
933 if ( url().isLocalFile() )
935 if ( !m_watcher->contains( localFilePath() ) ) m_watcher->addFile(localFilePath());
936 QFileInfo fi(localFilePath());
937 if ( !m_watcher->contains( fi.absolutePath() ) ) m_watcher->addDir(fi.absolutePath());
940 // if the 'OpenTOC' flag is set, open the TOC
941 if ( m_document->metaData( "OpenTOC" ).toBool() && m_sidebar->isItemEnabled( 0 ) )
943 m_sidebar->setCurrentIndex( 0 );
945 // if the 'StartFullScreen' flag is set, or the command line flag was
946 // specified, start presentation
947 if ( m_document->metaData( "StartFullScreen" ).toBool() || m_cliPresentation )
949 bool goAheadWithPresentationMode = true;
950 if ( !m_cliPresentation )
952 const QString text = i18n( "The document requested to be launched in presentation mode.\n"
953 "Do you want to allow it?" );
954 const QString caption = i18n( "Presentation Mode" );
955 const KGuiItem yesItem = KGuiItem( i18n( "Allow" ), "dialog-ok", i18n( "Allow the presentation mode" ) );
956 const KGuiItem noItem = KGuiItem( i18n( "Do Not Allow" ), "process-stop", i18n( "Do not allow the presentation mode" ) );
957 const int result = KMessageBox::questionYesNo( widget(), text, caption, yesItem, noItem );
958 if ( result == KMessageBox::No )
959 goAheadWithPresentationMode = false;
961 m_cliPresentation = false;
962 if ( goAheadWithPresentationMode )
963 QMetaObject::invokeMethod( this, "slotShowPresentation", Qt::QueuedConnection );
965 m_generatorGuiClient = factory() ? m_document->guiClient() : 0;
966 if ( m_generatorGuiClient )
967 factory()->addClient( m_generatorGuiClient );
968 return true;
971 bool Part::openUrl(const KUrl &url)
973 // this calls in sequence the 'closeUrl' and 'openFile' methods
974 bool openOk = KParts::ReadOnlyPart::openUrl( url );
976 if ( openOk )
978 m_viewportDirty.pageNumber = -1;
980 setWindowTitleFromDocument();
983 return openOk;
987 bool Part::closeUrl()
989 if (!m_temporaryLocalFile.isNull() && m_temporaryLocalFile != localFilePath())
991 QFile::remove( m_temporaryLocalFile );
992 m_temporaryLocalFile.clear();
995 slotHidePresentation();
996 m_find->setEnabled( false );
997 m_findNext->setEnabled( false );
998 m_findPrev->setEnabled( false );
999 m_saveAs->setEnabled( false );
1000 m_saveCopyAs->setEnabled( false );
1001 m_printPreview->setEnabled( false );
1002 m_showProperties->setEnabled( false );
1003 m_showEmbeddedFiles->setEnabled( false );
1004 m_exportAs->setEnabled( false );
1005 m_exportAsText->setEnabled( false );
1006 m_exportAsDocArchive->setEnabled( false );
1007 m_exportFormats.clear();
1008 QMenu *menu = m_exportAs->menu();
1009 QList<QAction*> acts = menu->actions();
1010 int num = acts.count();
1011 for ( int i = 2; i < num; ++i )
1013 menu->removeAction( acts.at(i) );
1014 delete acts.at(i);
1016 m_showPresentation->setEnabled( false );
1017 emit setWindowCaption("");
1018 emit enablePrintAction(false);
1019 m_realUrl = KUrl();
1020 if ( url().isLocalFile() )
1022 m_watcher->removeFile( localFilePath() );
1023 QFileInfo fi(localFilePath());
1024 m_watcher->removeDir( fi.absolutePath() );
1026 m_fileWasRemoved = false;
1027 if ( m_generatorGuiClient )
1028 factory()->removeClient( m_generatorGuiClient );
1029 m_generatorGuiClient = 0;
1030 m_document->closeDocument();
1031 updateViewActions();
1032 delete m_tempfile;
1033 m_tempfile = 0;
1034 if ( widget() )
1036 m_searchWidget->clearText();
1037 m_topMessage->setVisible( false );
1038 m_formsMessage->setVisible( false );
1040 #ifdef OKULAR_KEEP_FILE_OPEN
1041 m_keeper->close();
1042 #endif
1043 return KParts::ReadOnlyPart::closeUrl();
1047 void Part::close()
1049 if (parent()
1050 && (parent()->objectName() == QLatin1String("okular::Shell")
1051 || parent()->objectName() == QLatin1String("okular/okular__Shell")))
1053 closeUrl();
1055 else KMessageBox::information( widget(), i18n( "This link points to a close document action that does not work when using the embedded viewer." ), QString(), "warnNoCloseIfNotInOkular" );
1059 void Part::cannotQuit()
1061 KMessageBox::information( widget(), i18n( "This link points to a quit application action that does not work when using the embedded viewer." ), QString(), "warnNoQuitIfNotInOkular" );
1065 void Part::slotShowLeftPanel()
1067 bool showLeft = m_showLeftPanel->isChecked();
1068 Okular::Settings::setShowLeftPanel( showLeft );
1069 Okular::Settings::self()->writeConfig();
1070 // show/hide left panel
1071 m_sidebar->setSidebarVisibility( showLeft );
1075 void Part::slotFileDirty( const QString& path )
1077 // The beauty of this is that each start cancels the previous one.
1078 // This means that timeout() is only fired when there have
1079 // no changes to the file for the last 750 milisecs.
1080 // This ensures that we don't update on every other byte that gets
1081 // written to the file.
1082 if ( path == localFilePath() )
1084 m_dirtyHandler->start( 750 );
1086 else
1088 QFileInfo fi(localFilePath());
1089 if ( fi.absolutePath() == path )
1091 // Our parent has been dirtified
1092 if (!QFile::exists(localFilePath()))
1094 m_fileWasRemoved = true;
1096 else if (m_fileWasRemoved && QFile::exists(localFilePath()))
1098 // we need to watch the new file
1099 m_watcher->removeFile(localFilePath());
1100 m_watcher->addFile(localFilePath());
1101 m_dirtyHandler->start( 750 );
1108 void Part::slotDoFileDirty()
1110 // do the following the first time the file is reloaded
1111 if ( m_viewportDirty.pageNumber == -1 )
1113 // store the current viewport
1114 m_viewportDirty = m_document->viewport();
1116 // store the current toolbox pane
1117 m_dirtyToolboxIndex = m_sidebar->currentIndex();
1118 m_wasSidebarVisible = m_sidebar->isSidebarVisible();
1120 // store if presentation view was open
1121 m_wasPresentationOpen = ((PresentationWidget*)m_presentationWidget != 0);
1123 // inform the user about the operation in progress
1124 m_pageView->displayMessage( i18n("Reloading the document...") );
1127 // close and (try to) reopen the document
1128 if ( KParts::ReadOnlyPart::openUrl( url() ) )
1130 // on successful opening, restore the previous viewport
1131 if ( m_viewportDirty.pageNumber >= (int) m_document->pages() )
1132 m_viewportDirty.pageNumber = (int) m_document->pages() - 1;
1133 m_document->setViewport( m_viewportDirty );
1134 m_viewportDirty.pageNumber = -1;
1135 if ( m_sidebar->currentIndex() != m_dirtyToolboxIndex && m_sidebar->isItemEnabled( m_dirtyToolboxIndex ) )
1137 m_sidebar->setCurrentIndex( m_dirtyToolboxIndex );
1139 if ( m_sidebar->isSidebarVisible() != m_wasSidebarVisible )
1141 m_sidebar->setCurrentIndex( m_sidebar->currentIndex() );
1143 if (m_wasPresentationOpen) slotShowPresentation();
1144 emit enablePrintAction(true && m_document->printingSupport() != Okular::Document::NoPrinting);
1146 else
1148 // start watching the file again (since we dropped it on close)
1149 m_watcher->addFile(localFilePath());
1150 m_dirtyHandler->start( 750 );
1155 void Part::updateViewActions()
1157 bool opened = m_document->pages() > 0;
1158 if ( opened )
1160 bool atBegin = m_document->currentPage() < 1;
1161 bool atEnd = m_document->currentPage() >= (m_document->pages() - 1);
1162 m_gotoPage->setEnabled( m_document->pages() > 1 );
1163 m_firstPage->setEnabled( !atBegin );
1164 m_prevPage->setEnabled( !atBegin );
1165 m_lastPage->setEnabled( !atEnd );
1166 m_nextPage->setEnabled( !atEnd );
1167 if (m_historyBack) m_historyBack->setEnabled( !m_document->historyAtBegin() );
1168 if (m_historyNext) m_historyNext->setEnabled( !m_document->historyAtEnd() );
1169 m_reload->setEnabled( true );
1170 m_copy->setEnabled( true );
1171 m_selectAll->setEnabled( true );
1173 else
1175 m_gotoPage->setEnabled( false );
1176 m_firstPage->setEnabled( false );
1177 m_lastPage->setEnabled( false );
1178 m_prevPage->setEnabled( false );
1179 m_nextPage->setEnabled( false );
1180 if (m_historyBack) m_historyBack->setEnabled( false );
1181 if (m_historyNext) m_historyNext->setEnabled( false );
1182 m_reload->setEnabled( false );
1183 m_copy->setEnabled( false );
1184 m_selectAll->setEnabled( false );
1186 updateBookmarksActions();
1190 void Part::updateBookmarksActions()
1192 bool opened = m_document->pages() > 0;
1193 if ( opened )
1195 m_addBookmark->setEnabled( true );
1196 if ( m_document->bookmarkManager()->isBookmarked( m_document->currentPage() ) )
1198 m_addBookmark->setText( i18n( "Remove Bookmark" ) );
1199 m_addBookmark->setIcon( KIcon( "edit-delete-bookmark" ) );
1201 else
1203 m_addBookmark->setText( m_addBookmarkText );
1204 m_addBookmark->setIcon( m_addBookmarkIcon );
1207 else
1209 m_addBookmark->setEnabled( false );
1210 m_addBookmark->setText( m_addBookmarkText );
1211 m_addBookmark->setIcon( m_addBookmarkIcon );
1216 void Part::enableTOC(bool enable)
1218 m_sidebar->setItemEnabled(0, enable);
1221 void Part::slotRebuildBookmarkMenu()
1223 rebuildBookmarkMenu();
1226 void Part::slotShowFindBar()
1228 m_findBar->show();
1229 m_findBar->focusAndSetCursor();
1232 void Part::slotHideFindBar()
1234 m_findBar->hide();
1235 m_pageView->setFocus();
1238 //BEGIN go to page dialog
1239 class GotoPageDialog : public KDialog
1241 public:
1242 GotoPageDialog(QWidget *p, int current, int max) : KDialog(p)
1244 setCaption(i18n("Go to Page"));
1245 setButtons(Ok | Cancel);
1246 setDefaultButton(Ok);
1248 QWidget *w = new QWidget(this);
1249 setMainWidget(w);
1251 QVBoxLayout *topLayout = new QVBoxLayout(w);
1252 topLayout->setMargin(0);
1253 topLayout->setSpacing(spacingHint());
1254 e1 = new KIntNumInput(current, w);
1255 e1->setRange(1, max);
1256 e1->setEditFocus(true);
1257 e1->setSliderEnabled(true);
1259 QLabel *label = new QLabel(i18n("&Page:"), w);
1260 label->setBuddy(e1);
1261 topLayout->addWidget(label);
1262 topLayout->addWidget(e1);
1263 // A little bit extra space
1264 topLayout->addSpacing(spacingHint());
1265 topLayout->addStretch(10);
1266 e1->setFocus();
1269 int getPage() const
1271 return e1->value();
1274 protected:
1275 KIntNumInput *e1;
1277 //END go to page dialog
1279 void Part::slotGoToPage()
1281 GotoPageDialog pageDialog( m_pageView, m_document->currentPage() + 1, m_document->pages() );
1282 if ( pageDialog.exec() == QDialog::Accepted )
1283 m_document->setViewportPage( pageDialog.getPage() - 1 );
1287 void Part::slotPreviousPage()
1289 if ( m_document->isOpened() && !(m_document->currentPage() < 1) )
1290 m_document->setViewportPage( m_document->currentPage() - 1 );
1294 void Part::slotNextPage()
1296 if ( m_document->isOpened() && m_document->currentPage() < (m_document->pages() - 1) )
1297 m_document->setViewportPage( m_document->currentPage() + 1 );
1301 void Part::slotGotoFirst()
1303 if ( m_document->isOpened() )
1304 m_document->setViewportPage( 0 );
1308 void Part::slotGotoLast()
1310 if ( m_document->isOpened() )
1311 m_document->setViewportPage( m_document->pages() - 1 );
1315 void Part::slotHistoryBack()
1317 m_document->setPrevViewport();
1321 void Part::slotHistoryNext()
1323 m_document->setNextViewport();
1327 void Part::slotAddBookmark()
1329 uint current = m_document->currentPage();
1330 if ( m_document->bookmarkManager()->isBookmarked( current ) )
1332 m_document->bookmarkManager()->removeBookmark( current );
1334 else
1336 m_document->bookmarkManager()->addBookmark( current );
1341 void Part::slotPreviousBookmark()
1343 uint current = m_document->currentPage();
1344 // we are at the first page
1345 if ( current == 0 )
1346 return;
1348 for ( int i = current - 1; i >= 0; --i )
1350 if ( m_document->bookmarkManager()->isBookmarked( i ) )
1352 m_document->setViewportPage( i );
1353 break;
1359 void Part::slotNextBookmark()
1361 uint current = m_document->currentPage();
1362 uint pages = m_document->pages();
1363 // we are at the last page
1364 if ( current == pages )
1365 return;
1367 for ( uint i = current + 1; i < pages; ++i )
1369 if ( m_document->bookmarkManager()->isBookmarked( i ) )
1371 m_document->setViewportPage( i );
1372 break;
1378 void Part::slotFind()
1380 // when in presentation mode, there's already a search bar, taking care of
1381 // the 'find' requests
1382 if ( (PresentationWidget*)m_presentationWidget != 0 )
1384 m_presentationWidget->slotFind();
1386 else
1388 slotShowFindBar();
1393 void Part::slotFindNext()
1395 if (m_findBar->isHidden())
1396 slotShowFindBar();
1397 else
1398 m_findBar->findNext();
1402 void Part::slotFindPrev()
1404 if (m_findBar->isHidden())
1405 slotShowFindBar();
1406 else
1407 m_findBar->findPrev();
1411 void Part::slotSaveFileAs()
1413 if (m_dummyMode) return;
1415 KUrl saveUrl = KFileDialog::getSaveUrl( url().isLocalFile() ? url().url() : url().fileName(), QString(), widget() );
1416 if ( !saveUrl.isValid() || saveUrl.isEmpty() )
1417 return;
1419 if ( saveUrl.isLocalFile() )
1421 const QString fileName = saveUrl.toLocalFile();
1422 if ( QFile::exists( fileName ) )
1424 if (KMessageBox::warningContinueCancel( widget(), i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?", saveUrl.fileName()), QString(), KGuiItem(i18n("Overwrite"))) != KMessageBox::Continue)
1425 return;
1428 if ( !m_document->saveChanges( fileName ) )
1430 KMessageBox::information( widget(), i18n("File could not be saved in '%1'. Try to save it to another location.", fileName ) );
1431 return;
1434 else
1436 if ( KIO::NetAccess::exists( saveUrl, KIO::NetAccess::DestinationSide, widget() ) )
1438 if (KMessageBox::warningContinueCancel( widget(), i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?", saveUrl.fileName()), QString(), KGuiItem(i18n("Overwrite"))) != KMessageBox::Continue)
1439 return;
1442 KTemporaryFile tf;
1443 QString fileName;
1444 if ( !tf.open() )
1446 KMessageBox::information( widget(), i18n("Could not open the temporary file for saving." ) );
1447 return;
1449 fileName = tf.fileName();
1450 tf.close();
1452 if ( !m_document->saveChanges( fileName ) )
1454 KMessageBox::information( widget(), i18n("File could not be saved in '%1'. Try to save it to another location.", fileName ) );
1455 return;
1458 KIO::Job *copyJob = KIO::file_copy( fileName, saveUrl, -1, KIO::Overwrite );
1459 if ( !KIO::NetAccess::synchronousRun( copyJob, widget() ) )
1460 KMessageBox::information( widget(), i18n("File could not be saved in '%1'. Try to save it to another location.", saveUrl.prettyUrl() ) );
1465 void Part::slotSaveCopyAs()
1467 if (m_dummyMode) return;
1469 KUrl saveUrl = KFileDialog::getSaveUrl( url().isLocalFile() ? url().url() : url().fileName(), QString(), widget() );
1470 if ( saveUrl.isValid() && !saveUrl.isEmpty() )
1472 if ( KIO::NetAccess::exists( saveUrl, KIO::NetAccess::DestinationSide, widget() ) )
1474 if (KMessageBox::warningContinueCancel( widget(), i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?", saveUrl.fileName()), QString(), KGuiItem(i18n("Overwrite"))) != KMessageBox::Continue)
1475 return;
1478 // make use of the already downloaded (in case of remote URLs) file,
1479 // no point in downloading that again
1480 KUrl srcUrl = KUrl::fromPath( localFilePath() );
1481 KTemporaryFile * tempFile = 0;
1482 // duh, our local file disappeared...
1483 if ( !QFile::exists( localFilePath() ) )
1485 if ( url().isLocalFile() )
1487 #ifdef OKULAR_KEEP_FILE_OPEN
1488 // local file: try to get it back from the open handle on it
1489 if ( ( tempFile = m_keeper->copyToTemporary() ) )
1490 srcUrl = KUrl::fromPath( tempFile->fileName() );
1491 #else
1492 const QString msg = i18n( "Okular cannot copy %1 to the specified location.\n\nThe document does not exist anymore.", localFilePath() );
1493 KMessageBox::sorry( widget(), msg );
1494 return;
1495 #endif
1497 else
1499 // we still have the original remote URL of the document,
1500 // so copy the document from there
1501 srcUrl = url();
1505 KIO::Job *copyJob = KIO::file_copy( srcUrl, saveUrl, -1, KIO::Overwrite );
1506 if ( !KIO::NetAccess::synchronousRun( copyJob, widget() ) )
1507 KMessageBox::information( widget(), i18n("File could not be saved in '%1'. Try to save it to another location.", saveUrl.prettyUrl() ) );
1509 delete tempFile;
1514 void Part::slotGetNewStuff()
1516 KNS::Engine engine(widget());
1517 engine.init( "okular.knsrc" );
1518 // show the modal dialog over pageview and execute it
1519 KNS::Entry::List entries = engine.downloadDialogModal( m_pageView );
1520 Q_UNUSED( entries )
1524 void Part::slotPreferences()
1526 // an instance the dialog could be already created and could be cached,
1527 // in which case you want to display the cached dialog
1528 if ( PreferencesDialog::showDialog( "preferences" ) )
1529 return;
1531 // we didn't find an instance of this dialog, so lets create it
1532 PreferencesDialog * dialog = new PreferencesDialog( m_pageView, Okular::Settings::self() );
1533 // keep us informed when the user changes settings
1534 connect( dialog, SIGNAL( settingsChanged( const QString & ) ), this, SLOT( slotNewConfig() ) );
1536 dialog->show();
1540 void Part::slotNewConfig()
1542 // Apply settings here. A good policy is to check whether the setting has
1543 // changed before applying changes.
1545 // Watch File
1546 bool watchFile = Okular::Settings::watchFile();
1547 if ( watchFile && m_watcher->isStopped() )
1548 m_watcher->startScan();
1549 if ( !watchFile && !m_watcher->isStopped() )
1551 m_dirtyHandler->stop();
1552 m_watcher->stopScan();
1555 // Main View (pageView)
1556 m_pageView->reparseConfig();
1558 // update document settings
1559 m_document->reparseConfig();
1561 // update TOC settings
1562 if ( m_sidebar->isItemEnabled(0) )
1563 m_toc->reparseConfig();
1565 // update ThumbnailList contents
1566 if ( Okular::Settings::showLeftPanel() && !m_thumbnailList->isHidden() )
1567 m_thumbnailList->updateWidgets();
1571 void Part::slotNewGeneratorConfig()
1573 // Apply settings here. A good policy is to check whether the setting has
1574 // changed before applying changes.
1576 // NOTE: it's not needed to reload the configuration of the Document,
1577 // the Document itself will take care of that
1579 // Main View (pageView)
1580 m_pageView->reparseConfig();
1582 // update TOC settings
1583 if ( m_sidebar->isItemEnabled(0) )
1584 m_toc->reparseConfig();
1586 // update ThumbnailList contents
1587 if ( Okular::Settings::showLeftPanel() && !m_thumbnailList->isHidden() )
1588 m_thumbnailList->updateWidgets();
1592 void Part::slotPrintPreview()
1594 if (m_document->pages() == 0) return;
1596 QPrinter printer;
1598 // Native printing supports KPrintPreview, Postscript needs to use FilePrinterPreview
1599 if ( m_document->printingSupport() == Okular::Document::NativePrinting )
1601 KPrintPreview previewdlg( &printer, widget() );
1602 setupPrint( printer );
1603 doPrint( printer );
1604 previewdlg.exec();
1606 else
1608 // Generate a temp filename for Print to File, then release the file so generator can write to it
1609 KTemporaryFile tf;
1610 tf.setAutoRemove( true );
1611 tf.setSuffix( ".ps" );
1612 tf.open();
1613 printer.setOutputFileName( tf.fileName() );
1614 tf.close();
1615 setupPrint( printer );
1616 doPrint( printer );
1617 if ( QFile::exists( printer.outputFileName() ) )
1619 Okular::FilePrinterPreview previewdlg( printer.outputFileName(), widget() );
1620 previewdlg.exec();
1626 void Part::slotShowMenu(const Okular::Page *page, const QPoint &point)
1628 if (m_dummyMode) return;
1630 bool reallyShow = false;
1631 if (!m_actionsSearched)
1633 // the quest for options_show_menubar
1634 KActionCollection *ac;
1635 QAction *act;
1637 if (factory())
1639 QList<KXMLGUIClient*> clients(factory()->clients());
1640 for(int i = 0 ; (!m_showMenuBarAction || !m_showFullScreenAction) && i < clients.size(); ++i)
1642 ac = clients.at(i)->actionCollection();
1643 // show_menubar
1644 act = ac->action("options_show_menubar");
1645 if (act && qobject_cast<KToggleAction*>(act))
1646 m_showMenuBarAction = qobject_cast<KToggleAction*>(act);
1647 // fullscreen
1648 act = ac->action("fullscreen");
1649 if (act && qobject_cast<KToggleFullScreenAction*>(act))
1650 m_showFullScreenAction = qobject_cast<KToggleFullScreenAction*>(act);
1653 m_actionsSearched = true;
1656 KMenu *popup = new KMenu( widget() );
1657 QAction *addBookmark = 0;
1658 QAction *removeBookmark = 0;
1659 QAction *fitPageWidth = 0;
1660 if (page)
1662 popup->addTitle( i18n( "Page %1", page->number() + 1 ) );
1663 if ( m_document->bookmarkManager()->isBookmarked( page->number() ) )
1664 removeBookmark = popup->addAction( KIcon("edit-delete-bookmark"), i18n("Remove Bookmark") );
1665 else
1666 addBookmark = popup->addAction( KIcon("bookmark-new"), i18n("Add Bookmark") );
1667 if ( m_pageView->canFitPageWidth() )
1668 fitPageWidth = popup->addAction( KIcon("zoom-fit-best"), i18n("Fit Width") );
1669 popup->addAction( m_prevBookmark );
1670 popup->addAction( m_nextBookmark );
1671 reallyShow = true;
1674 //Albert says: I have not ported this as i don't see it does anything
1675 if ( d->mouseOnRect ) // and rect->objectType() == ObjectRect::Image ...
1677 m_popup->insertItem( SmallIcon("document-save"), i18n("Save Image..."), 4 );
1678 m_popup->setItemEnabled( 4, false );
1681 if ((m_showMenuBarAction && !m_showMenuBarAction->isChecked()) || (m_showFullScreenAction && m_showFullScreenAction->isChecked()))
1683 popup->addTitle( i18n( "Tools" ) );
1684 if (m_showMenuBarAction && !m_showMenuBarAction->isChecked()) popup->addAction(m_showMenuBarAction);
1685 if (m_showFullScreenAction && m_showFullScreenAction->isChecked()) popup->addAction(m_showFullScreenAction);
1686 reallyShow = true;
1690 if (reallyShow)
1692 QAction *res = popup->exec(point);
1693 if (res)
1695 if (res == addBookmark) m_document->bookmarkManager()->addBookmark( page->number() );
1696 else if (res == removeBookmark) m_document->bookmarkManager()->removeBookmark( page->number() );
1697 else if (res == fitPageWidth) m_pageView->fitPageWidth( page->number() );
1700 delete popup;
1704 void Part::slotShowProperties()
1706 PropertiesDialog *d = new PropertiesDialog(widget(), m_document);
1707 d->exec();
1708 delete d;
1712 void Part::slotShowEmbeddedFiles()
1714 EmbeddedFilesDialog *d = new EmbeddedFilesDialog(widget(), m_document);
1715 d->exec();
1716 delete d;
1720 void Part::slotShowPresentation()
1722 if ( !m_presentationWidget )
1724 m_presentationWidget = new PresentationWidget( widget(), m_document, actionCollection() );
1729 void Part::slotHidePresentation()
1731 if ( m_presentationWidget )
1732 delete (PresentationWidget*) m_presentationWidget;
1736 void Part::slotTogglePresentation()
1738 if ( m_document->isOpened() )
1740 if ( !m_presentationWidget )
1741 m_presentationWidget = new PresentationWidget( widget(), m_document, actionCollection() );
1742 else delete (PresentationWidget*) m_presentationWidget;
1747 void Part::reload()
1749 if ( m_document->isOpened() )
1751 slotReload();
1756 void Part::slotAboutBackend()
1758 const KComponentData *data = m_document->componentData();
1759 if ( !data )
1760 return;
1762 KAboutApplicationDialog dlg( data->aboutData(), widget() );
1763 dlg.exec();
1767 void Part::slotExportAs(QAction * act)
1769 QList<QAction*> acts = m_exportAs->menu() ? m_exportAs->menu()->actions() : QList<QAction*>();
1770 int id = acts.indexOf( act );
1771 if ( ( id < 0 ) || ( id >= acts.count() ) )
1772 return;
1774 QString filter;
1775 switch ( id )
1777 case 0:
1778 filter = "text/plain";
1779 break;
1780 case 1:
1781 filter = "application/vnd.kde.okular-archive";
1782 break;
1783 default:
1784 filter = m_exportFormats.at( id - 2 ).mimeType()->name();
1785 break;
1787 QString fileName = KFileDialog::getSaveFileName( url().isLocalFile() ? url().directory() : QString(), filter, widget() );
1788 if ( !fileName.isEmpty() )
1790 bool saved = false;
1791 switch ( id )
1793 case 0:
1794 saved = m_document->exportToText( fileName );
1795 break;
1796 case 1:
1797 saved = m_document->saveDocumentArchive( fileName );
1798 break;
1799 default:
1800 saved = m_document->exportTo( fileName, m_exportFormats.at( id - 2 ) );
1801 break;
1803 if ( !saved )
1804 KMessageBox::information( widget(), i18n("File could not be saved in '%1'. Try to save it to another location.", fileName ) );
1809 void Part::slotReload()
1811 // stop the dirty handler timer, otherwise we may conflict with the
1812 // auto-refresh system
1813 m_dirtyHandler->stop();
1815 slotDoFileDirty();
1819 void Part::slotPrint()
1821 if (m_document->pages() == 0) return;
1823 QPrinter printer;
1824 QPrintDialog *printDialog = 0;
1825 QWidget *printConfigWidget = 0;
1827 // Must do certain QPrinter setup before creating QPrintDialog
1828 setupPrint( printer );
1830 // Create the Print Dialog with extra config widgets if required
1831 if ( m_document->canConfigurePrinter() )
1833 printConfigWidget = m_document->printConfigurationWidget();
1835 if ( printConfigWidget )
1837 printDialog = KdePrint::createPrintDialog( &printer, QList<QWidget*>() << printConfigWidget, widget() );
1839 else
1841 printDialog = KdePrint::createPrintDialog( &printer, widget() );
1844 if ( printDialog )
1847 // Set the available Print Range
1848 printDialog->setMinMax( 1, m_document->pages() );
1849 printDialog->setFromTo( 1, m_document->pages() );
1851 // If the user has bookmarked pages for printing, then enable Selection
1852 if ( !m_document->bookmarkedPageRange().isEmpty() )
1854 printDialog->addEnabledOption( QAbstractPrintDialog::PrintSelection );
1857 // If the Document type doesn't support print to both PS & PDF then disable the Print Dialog option
1858 if ( printDialog->isOptionEnabled( QAbstractPrintDialog::PrintToFile ) &&
1859 !m_document->supportsPrintToFile() )
1861 printDialog->setEnabledOptions( printDialog->enabledOptions() ^ QAbstractPrintDialog::PrintToFile );
1864 if ( printDialog->exec() )
1865 doPrint( printer );
1866 delete printDialog;
1871 void Part::setupPrint( QPrinter &printer )
1873 double width, height;
1874 int landscape, portrait;
1875 const Okular::Page *page;
1877 // if some pages are landscape and others are not the most common win as QPrinter does
1878 // not accept a per page setting
1879 landscape = 0;
1880 portrait = 0;
1881 for (uint i = 0; i < m_document->pages(); i++)
1883 page = m_document->page(i);
1884 width = page->width();
1885 height = page->height();
1886 if (page->orientation() == Okular::Rotation90 || page->orientation() == Okular::Rotation270) qSwap(width, height);
1887 if (width > height) landscape++;
1888 else portrait++;
1890 if (landscape > portrait) printer.setOrientation(QPrinter::Landscape);
1892 // title
1893 QString title = m_document->metaData( "DocumentTitle" ).toString();
1894 if ( title.isEmpty() )
1896 title = m_document->currentDocument().fileName();
1898 if ( !title.isEmpty() )
1900 printer.setDocName( title );
1905 void Part::doPrint(QPrinter &printer)
1907 if (!m_document->isAllowed(Okular::AllowPrint))
1909 KMessageBox::error(widget(), i18n("Printing this document is not allowed."));
1910 return;
1913 if (!m_document->print(printer))
1915 KMessageBox::error(widget(), i18n("Could not print the document. Please report to bugs.kde.org"));
1920 void Part::restoreDocument(const KConfigGroup &group)
1922 KUrl url ( group.readPathEntry( "URL", QString() ) );
1923 if ( url.isValid() )
1925 QString viewport = group.readEntry( "Viewport" );
1926 if (!viewport.isEmpty()) m_document->setNextDocumentViewport( Okular::DocumentViewport( viewport ) );
1927 openUrl( url );
1932 void Part::saveDocumentRestoreInfo(KConfigGroup &group)
1934 group.writePathEntry( "URL", url().url() );
1935 group.writeEntry( "Viewport", m_document->viewport().toString() );
1939 void Part::psTransformEnded(int exit, QProcess::ExitStatus status)
1941 Q_UNUSED( exit )
1942 if ( status != QProcess::NormalExit )
1943 return;
1945 QProcess *senderobj = sender() ? qobject_cast< QProcess * >( sender() ) : 0;
1946 if ( senderobj )
1948 senderobj->close();
1949 senderobj->deleteLater();
1952 setLocalFilePath( m_temporaryLocalFile );
1953 openUrl( m_temporaryLocalFile );
1954 m_temporaryLocalFile.clear();
1958 void Part::unsetDummyMode()
1960 if (!m_dummyMode) return;
1962 m_dummyMode = false;
1964 m_sidebar->setItemEnabled( 2, true );
1965 m_sidebar->setItemEnabled( 3, true );
1966 m_sidebar->setSidebarVisibility( Okular::Settings::showLeftPanel() );
1968 // add back and next in history
1969 m_historyBack = KStandardAction::documentBack( this, SLOT( slotHistoryBack() ), actionCollection() );
1970 m_historyBack->setWhatsThis( i18n( "Go to the place you were before" ) );
1972 m_historyNext = KStandardAction::documentForward( this, SLOT( slotHistoryNext() ), actionCollection());
1973 m_historyNext->setWhatsThis( i18n( "Go to the place you were after" ) );
1975 m_pageView->setupActions( actionCollection() );
1977 // attach the actions of the children widgets too
1978 m_formsMessage->setActionButton( m_pageView->toggleFormsAction() );
1980 // ensure history actions are in the correct state
1981 updateViewActions();
1985 bool Part::handleCompressed( QString &destpath, const QString &path, const QString &compressedMimetype )
1987 m_tempfile = 0;
1989 // we are working with a compressed file, decompressing
1990 // temporary file for decompressing
1991 KTemporaryFile *newtempfile = new KTemporaryFile();
1992 newtempfile->setAutoRemove(true);
1994 if ( !newtempfile->open() )
1996 KMessageBox::error( widget(),
1997 i18n("<qt><strong>File Error!</strong> Could not create temporary file "
1998 "<nobr><strong>%1</strong></nobr>.</qt>",
1999 strerror(newtempfile->error())));
2000 delete newtempfile;
2001 return false;
2004 // decompression filer
2005 QIODevice* filterDev = KFilterDev::deviceForFile( path, compressedMimetype );
2006 if (!filterDev)
2008 delete newtempfile;
2009 return false;
2012 if ( !filterDev->open(QIODevice::ReadOnly) )
2014 KMessageBox::detailedError( widget(),
2015 i18n("<qt><strong>File Error!</strong> Could not open the file "
2016 "<nobr><strong>%1</strong></nobr> for uncompression. "
2017 "The file will not be loaded.</qt>", path),
2018 i18n("<qt>This error typically occurs if you do "
2019 "not have enough permissions to read the file. "
2020 "You can check ownership and permissions if you "
2021 "right-click on the file in the Dolphin "
2022 "file manager and then choose the 'Properties' tab.</qt>"));
2024 delete filterDev;
2025 delete newtempfile;
2026 return false;
2029 QByteArray buf(1024, '\0');
2030 int read = 0, wrtn = 0;
2032 while ((read = filterDev->read(buf.data(), buf.size())) > 0)
2034 wrtn = newtempfile->write(buf.data(), read);
2035 if ( read != wrtn )
2036 break;
2038 delete filterDev;
2039 if ((read != 0) || (newtempfile->size() == 0))
2041 KMessageBox::detailedError(widget(),
2042 i18n("<qt><strong>File Error!</strong> Could not uncompress "
2043 "the file <nobr><strong>%1</strong></nobr>. "
2044 "The file will not be loaded.</qt>", path ),
2045 i18n("<qt>This error typically occurs if the file is corrupt. "
2046 "If you want to be sure, try to decompress the file manually "
2047 "using command-line tools.</qt>"));
2048 delete newtempfile;
2049 return false;
2051 m_tempfile = newtempfile;
2052 destpath = m_tempfile->fileName();
2053 return true;
2056 void Part::rebuildBookmarkMenu( bool unplugActions )
2058 if ( unplugActions )
2060 unplugActionList( "bookmarks_currentdocument" );
2061 qDeleteAll( m_bookmarkActions );
2062 m_bookmarkActions.clear();
2064 KUrl u = m_document->currentDocument();
2065 if ( u.isValid() )
2067 m_bookmarkActions = m_document->bookmarkManager()->actionsForUrl( u );
2069 bool havebookmarks = true;
2070 if ( m_bookmarkActions.isEmpty() )
2072 havebookmarks = false;
2073 QAction * a = new QAction( 0 );
2074 a->setText( i18n( "No Bookmarks" ) );
2075 a->setEnabled( false );
2076 m_bookmarkActions.append( a );
2078 for ( int i = 0; i < m_bookmarkActions.count(); ++i )
2080 actionCollection()->addAction( QString( "bookmark_action_%1" ).arg( i ), m_bookmarkActions.at(i) );
2082 plugActionList( "bookmarks_currentdocument", m_bookmarkActions );
2084 m_prevBookmark->setEnabled( havebookmarks );
2085 m_nextBookmark->setEnabled( havebookmarks );
2088 void Part::updateAboutBackendAction()
2090 const KComponentData *data = m_document->componentData();
2091 if ( data )
2093 m_aboutBackend->setEnabled( true );
2095 else
2097 m_aboutBackend->setEnabled( false );
2102 #include "part.moc"
2104 /* kate: replace-tabs on; indent-width 4; */