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> *
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 ***************************************************************************/
27 #include <qapplication.h>
32 #include <QtGui/QPrinter>
33 #include <QtGui/QPrintDialog>
36 #include <kaboutapplicationdialog.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>
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>
57 #include <kfilterdev.h>
58 #include <knewstuff2/engine.h>
59 #include <kdeprintdialog.h>
60 #include <kprintpreview.h>
63 #include "aboutdata.h"
64 #include "extensions.h"
65 #include "ui/pageview.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"
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"
102 void open( const QString
& path
)
105 m_handle
= std::fopen( QFile::encodeName( path
), "r" );
112 int ret
= std::fclose( m_handle
);
118 KTemporaryFile
* copyToTemporary() const
123 KTemporaryFile
* retFile
= new KTemporaryFile
;
126 std::rewind( m_handle
);
130 c
= std::fgetc( m_handle
);
133 if ( !retFile
->putChar( (char)c
) )
135 } while ( !feof( m_handle
) );
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() );
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() )
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
;
196 Part::Part(QWidget
*parentWidget
,
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() ) );
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 );
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") );
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
) );
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
);
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() ) );
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() ) );
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() ) );
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
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..." ) );
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() );
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()));
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()));
487 ghns
->setShortcut( Qt::Key_G
);
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() );
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() ) );
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
582 m_sidebar
->setSidebarVisibility( false );
583 if ( !args
.contains( QVariant( "Print/Preview" ) ) ) unsetDummyMode();
585 #ifdef OKULAR_KEEP_FILE_OPEN
586 m_keeper
= new FileKeeper();
593 m_document
->removeObserver( this );
595 if ( m_document
->isOpened() )
600 delete m_thumbnailList
;
602 #ifdef OKULAR_ENABLE_MINIBAR
603 delete m_progressWidget
;
605 delete m_pageSizeLabel
;
606 delete m_reviewsWidget
;
607 delete m_bookmarkList
;
613 qDeleteAll( m_bookmarkActions
);
615 delete m_exportAsMenu
;
617 #ifdef OKULAR_KEEP_FILE_OPEN
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
;
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() )
657 void Part::openUrlFromDocument(const KUrl
&url
)
659 if (m_dummyMode
) return;
661 m_bExtension
->openUrlNotify();
662 m_bExtension
->setLocationBarUrl(url
.prettyUrl());
666 void Part::openUrlFromBookmarks(const KUrl
&_url
)
669 Okular::DocumentViewport
vp( _url
.htmlRef() );
671 m_document
->setNextDocumentViewport( vp
);
672 url
.setHTMLRef( QString() );
673 if ( m_document
->currentDocument() == url
)
676 m_document
->setViewport( vp
);
682 void Part::setMimeTypes(KIO::Job
*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
) );
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() )
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" ) )
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() ) );
748 void Part::notifySetup( const QVector
< Okular::Page
* > & /*pages*/, int setupFlags
)
750 if ( !( setupFlags
& Okular::DocumentObserver::DocumentChanged
) )
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
)
766 lastPage
= viewportPage
;
770 void Part::notifyPageChanged( int page
, int flags
)
772 if ( !(flags
& Okular::DocumentObserver::Bookmark
) )
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
) );
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" );
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") );
822 KUrl url
= KFileDialog::getOpenUrl( KUrl(), "application/postscript", this->widget() );
823 if ( url
.isLocalFile() )
826 tf
.setSuffix( ".pdf" );
827 tf
.setAutoRemove( false );
830 m_temporaryLocalFile
= tf
.fileName();
833 setLocalFilePath( url
.path() );
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
)));
843 m_temporaryLocalFile
.clear();
848 bool Part::openFile()
851 if ( !arguments().mimeType().isEmpty() )
853 mime
= KMimeType::mimeType( arguments().mimeType() );
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
);
874 if ( mime
->is( "application/vnd.kde.okular-archive" ) )
875 ok
= m_document
->openDocumentArchive( fileNameToOpen
, url() );
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
);
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
)
910 #ifdef OKULAR_KEEP_FILE_OPEN
911 if ( keepFileOpen() )
912 m_keeper
->open( fileNameToOpen
);
915 m_exportAsText
->setEnabled( ok
&& m_document
->canExportToText() );
916 m_exportAsDocArchive
->setEnabled( ok
);
917 m_exportAs
->setEnabled( ok
);
919 // update viewing actions
922 m_fileWasRemoved
= false;
926 // if can't open document, update windows so they display blank contents
927 m_pageView
->widget()->update();
928 m_thumbnailList
->update();
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
);
971 bool Part::openUrl(const KUrl
&url
)
973 // this calls in sequence the 'closeUrl' and 'openFile' methods
974 bool openOk
= KParts::ReadOnlyPart::openUrl( url
);
978 m_viewportDirty
.pageNumber
= -1;
980 setWindowTitleFromDocument();
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
) );
1016 m_showPresentation
->setEnabled( false );
1017 emit
setWindowCaption("");
1018 emit
enablePrintAction(false);
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();
1036 m_searchWidget
->clearText();
1037 m_topMessage
->setVisible( false );
1038 m_formsMessage
->setVisible( false );
1040 #ifdef OKULAR_KEEP_FILE_OPEN
1043 return KParts::ReadOnlyPart::closeUrl();
1050 && (parent()->objectName() == QLatin1String("okular::Shell")
1051 || parent()->objectName() == QLatin1String("okular/okular__Shell")))
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 );
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
);
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;
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 );
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;
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" ) );
1203 m_addBookmark
->setText( m_addBookmarkText
);
1204 m_addBookmark
->setIcon( m_addBookmarkIcon
);
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()
1229 m_findBar
->focusAndSetCursor();
1232 void Part::slotHideFindBar()
1235 m_pageView
->setFocus();
1238 //BEGIN go to page dialog
1239 class GotoPageDialog
: public KDialog
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);
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);
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
);
1336 m_document
->bookmarkManager()->addBookmark( current
);
1341 void Part::slotPreviousBookmark()
1343 uint current
= m_document
->currentPage();
1344 // we are at the first page
1348 for ( int i
= current
- 1; i
>= 0; --i
)
1350 if ( m_document
->bookmarkManager()->isBookmarked( i
) )
1352 m_document
->setViewportPage( i
);
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
)
1367 for ( uint i
= current
+ 1; i
< pages
; ++i
)
1369 if ( m_document
->bookmarkManager()->isBookmarked( i
) )
1371 m_document
->setViewportPage( i
);
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();
1393 void Part::slotFindNext()
1395 if (m_findBar
->isHidden())
1398 m_findBar
->findNext();
1402 void Part::slotFindPrev()
1404 if (m_findBar
->isHidden())
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() )
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
)
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
) );
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
)
1446 KMessageBox::information( widget(), i18n("Could not open the temporary file for saving." ) );
1449 fileName
= tf
.fileName();
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
) );
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
)
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() );
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
);
1499 // we still have the original remote URL of the document,
1500 // so copy the document from there
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() ) );
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
);
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" ) )
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() ) );
1540 void Part::slotNewConfig()
1542 // Apply settings here. A good policy is to check whether the setting has
1543 // changed before applying changes.
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;
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
);
1608 // Generate a temp filename for Print to File, then release the file so generator can write to it
1610 tf
.setAutoRemove( true );
1611 tf
.setSuffix( ".ps" );
1613 printer
.setOutputFileName( tf
.fileName() );
1615 setupPrint( printer
);
1617 if ( QFile::exists( printer
.outputFileName() ) )
1619 Okular::FilePrinterPreview
previewdlg( printer
.outputFileName(), widget() );
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
;
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();
1644 act
= ac
->action("options_show_menubar");
1645 if (act
&& qobject_cast
<KToggleAction
*>(act
))
1646 m_showMenuBarAction
= qobject_cast
<KToggleAction
*>(act
);
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;
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") );
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
);
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
);
1692 QAction
*res
= popup
->exec(point
);
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() );
1704 void Part::slotShowProperties()
1706 PropertiesDialog
*d
= new PropertiesDialog(widget(), m_document
);
1712 void Part::slotShowEmbeddedFiles()
1714 EmbeddedFilesDialog
*d
= new EmbeddedFilesDialog(widget(), m_document
);
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
;
1749 if ( m_document
->isOpened() )
1756 void Part::slotAboutBackend()
1758 const KComponentData
*data
= m_document
->componentData();
1762 KAboutApplicationDialog
dlg( data
->aboutData(), widget() );
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() ) )
1778 filter
= "text/plain";
1781 filter
= "application/vnd.kde.okular-archive";
1784 filter
= m_exportFormats
.at( id
- 2 ).mimeType()->name();
1787 QString fileName
= KFileDialog::getSaveFileName( url().isLocalFile() ? url().directory() : QString(), filter
, widget() );
1788 if ( !fileName
.isEmpty() )
1794 saved
= m_document
->exportToText( fileName
);
1797 saved
= m_document
->saveDocumentArchive( fileName
);
1800 saved
= m_document
->exportTo( fileName
, m_exportFormats
.at( id
- 2 ) );
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();
1819 void Part::slotPrint()
1821 if (m_document
->pages() == 0) return;
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() );
1841 printDialog
= KdePrint::createPrintDialog( &printer
, widget() );
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() )
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
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
++;
1890 if (landscape
> portrait
) printer
.setOrientation(QPrinter::Landscape
);
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."));
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
) );
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
)
1942 if ( status
!= QProcess::NormalExit
)
1945 QProcess
*senderobj
= sender() ? qobject_cast
< QProcess
* >( sender() ) : 0;
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
)
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())));
2004 // decompression filer
2005 QIODevice
* filterDev
= KFilterDev::deviceForFile( path
, compressedMimetype
);
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>"));
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
);
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>"));
2051 m_tempfile
= newtempfile
;
2052 destpath
= m_tempfile
->fileName();
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();
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();
2093 m_aboutBackend
->setEnabled( true );
2097 m_aboutBackend
->setEnabled( false );
2104 /* kate: replace-tabs on; indent-width 4; */