part.cpp 96.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/***************************************************************************
 *   Copyright (C) 2002 by Wilco Greven <greven@kde.org>                   *
 *   Copyright (C) 2002 by Chris Cheney <ccheney@cheney.cx>                *
 *   Copyright (C) 2002 by Malcolm Hunter <malcolm.hunter@gmx.co.uk>       *
 *   Copyright (C) 2003-2004 by Christophe Devriese                        *
 *                         <Christophe.Devriese@student.kuleuven.ac.be>    *
 *   Copyright (C) 2003 by Daniel Molkentin <molkentin@kde.org>            *
 *   Copyright (C) 2003 by Andy Goossens <andygoossens@telenet.be>         *
 *   Copyright (C) 2003 by Dirk Mueller <mueller@kde.org>                  *
 *   Copyright (C) 2003 by Laurent Montel <montel@kde.org>                 *
 *   Copyright (C) 2004 by Dominique Devriese <devriese@kde.org>           *
 *   Copyright (C) 2004 by Christoph Cullmann <crossfire@babylon2k.de>     *
 *   Copyright (C) 2004 by Henrique Pinto <stampede@coltec.ufmg.br>        *
 *   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
19
20
21
22
23
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

Albert Astals Cid's avatar
Albert Astals Cid committed
24
25
#include "part.h"

26
// qt/kde includes
27
#include <qapplication.h>
28
#include <qfile.h>
29
30
#include <qlayout.h>
#include <qlabel.h>
Christian Ehrlicher's avatar
Christian Ehrlicher committed
31
#include <qtimer.h>
Frederik Gladhorn's avatar
Frederik Gladhorn committed
32
#include <QtPrintSupport/QPrinter>
Frederik Gladhorn's avatar
Frederik Gladhorn committed
33
#include <QtPrintSupport/QPrintDialog>
34
#include <QScrollBar>
35

Pino Toscano's avatar
porting    
Pino Toscano committed
36
#include <kvbox.h>
37
#include <kaboutapplicationdialog.h>
38
#include <kaction.h>
39
#include <kactioncollection.h>
40
#include <kbookmarkaction.h>
Albert Astals Cid's avatar
Albert Astals Cid committed
41
#include <kdirwatch.h>
Laurent Montel's avatar
Laurent Montel committed
42
#include <kstandardaction.h>
43
#include <kpluginfactory.h>
44
#include <kfiledialog.h>
45
#include <kinputdialog.h>
Albert Astals Cid's avatar
Albert Astals Cid committed
46
#include <kmessagebox.h>
47
#include <knuminput.h>
48
#include <kio/netaccess.h>
49
#include <kmenu.h>
50
51
#include <kxmlguiclient.h>
#include <kxmlguifactory.h>
52
#include <kservicetypetrader.h>
53
#include <kstandarddirs.h>
54
#include <kstandardshortcut.h>
55
#include <ktemporaryfile.h>
Albert Astals Cid's avatar
compile    
Albert Astals Cid committed
56
#include <ktoggleaction.h>
57
#include <ktogglefullscreenaction.h>
Piotr Szymanski's avatar
Piotr Szymanski committed
58
#include <kio/job.h>
Laurent Montel's avatar
Laurent Montel committed
59
#include <kicon.h>
60
#include <kfilterdev.h>
61
#include <kfilterbase.h>
62
#if 0
63
#include <knewstuff2/engine.h>
64
#endif
65
#include <kdeprintdialog.h>
66
#include <kprintpreview.h>
67
#include <kbookmarkmenu.h>
68
69
#include <kpassworddialog.h>
#include <kwallet.h>
Frederik Gladhorn's avatar
Frederik Gladhorn committed
70
#include <kdeversion.h>
71

72
// local includes
73
#include "aboutdata.h"
74
#include "extensions.h"
75
76
#include "ui/pageview.h"
#include "ui/toc.h"
77
78
79
#include "ui/searchwidget.h"
#include "ui/thumbnaillist.h"
#include "ui/side_reviews.h"
80
#include "ui/minibar.h"
81
#include "ui/embeddedfilesdialog.h"
82
83
#include "ui/propertiesdialog.h"
#include "ui/presentationwidget.h"
Albert Astals Cid's avatar
Albert Astals Cid committed
84
#include "ui/pagesizelabel.h"
85
#include "ui/bookmarklist.h"
86
#include "ui/findbar.h"
Pino Toscano's avatar
Pino Toscano committed
87
#include "ui/sidebar.h"
88
#include "ui/fileprinterpreview.h"
89
#include "ui/guiutils.h"
90
#include "conf/preferencesdialog.h"
91
#include "settings.h"
92
#include "core/action.h"
93
#include "core/annotations.h"
94
#include "core/bookmarkmanager.h"
95
#include "core/document.h"
96
#include "core/generator.h"
97
#include "core/page.h"
John Layt's avatar
John Layt committed
98
#include "core/fileprinter.h"
Christophe Devriese's avatar
Christophe Devriese committed
99

100
#include <cstdio>
101
#include <memory>
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

class FileKeeper
{
    public:
        FileKeeper()
            : m_handle( NULL )
        {
        }

        ~FileKeeper()
        {
        }

        void open( const QString & path )
        {
            if ( !m_handle )
Frederik Gladhorn's avatar
Frederik Gladhorn committed
118
                m_handle = std::fopen( QFile::encodeName( path ).constData(), "r" );
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
        }

        void close()
        {
            if ( m_handle )
            {
                int ret = std::fclose( m_handle );
                Q_UNUSED( ret )
                m_handle = NULL;
            }
        }

        KTemporaryFile* copyToTemporary() const
        {
            if ( !m_handle )
                return 0;

            KTemporaryFile * retFile = new KTemporaryFile;
            retFile->open();

            std::rewind( m_handle );
            int c = -1;
            do
            {
                c = std::fgetc( m_handle );
                if ( c == EOF )
                    break;
                if ( !retFile->putChar( (char)c ) )
                    break;
            } while ( !feof( m_handle ) );

            retFile->flush();

            return retFile;
        }

    private:
        std::FILE * m_handle;
};

Frederik Gladhorn's avatar
Frederik Gladhorn committed
159
160
K_PLUGIN_FACTORY(OkularPartFactory, registerPlugin<Okular::Part>();)

161
162
163
164
165
166
167
168
169
170
171
172
Okular::PartFactory::PartFactory()
{
}

Okular::PartFactory::~PartFactory()
{
}

QObject *Okular::PartFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword)
{
    Q_UNUSED ( keyword );

173
    Okular::Part *object = new Okular::Part( parentWidget, parent, args );
174
175
176
177
    object->setReadWrite( QLatin1String(iface) == QLatin1String("KParts::ReadWritePart") );
    return object;
}

178
179
180
181
182
183
184
185
186
187
static QAction* actionForExportFormat( const Okular::ExportFormat& format, QObject *parent = 0 )
{
    QAction *act = new QAction( format.description(), parent );
    if ( !format.icon().isNull() )
    {
        act->setIcon( format.icon() );
    }
    return act;
}

188
189
static QString compressedMimeFor( const QString& mime_to_check )
{
190
191
192
    // The compressedMimeMap is here in case you have a very old shared mime database
    // that doesn't have inheritance info for things like gzeps, etc
    // Otherwise the "is()" calls below are just good enough
193
    static QHash< QString, QString > compressedMimeMap;
194
195
196
197
198
    static bool supportBzip = false;
    static bool supportXz = false;
    const QString app_gzip( QString::fromLatin1( "application/x-gzip" ) );
    const QString app_bzip( QString::fromLatin1( "application/x-bzip" ) );
    const QString app_xz( QString::fromLatin1( "application/x-xz" ) );
199
200
    if ( compressedMimeMap.isEmpty() )
    {
201
        std::auto_ptr< KFilterBase > f;
202
        compressedMimeMap[ QString::fromLatin1( "image/x-gzeps" ) ] = app_gzip;
203
        // check we can read bzip2-compressed files
204
        f.reset( KCompressionDevice::filterForCompressionType( KCompressionDevice::BZip2 ) );
205
206
        if ( f.get() )
        {
207
            supportBzip = true;
208
209
210
211
212
            compressedMimeMap[ QString::fromLatin1( "application/x-bzpdf" ) ] = app_bzip;
            compressedMimeMap[ QString::fromLatin1( "application/x-bzpostscript" ) ] = app_bzip;
            compressedMimeMap[ QString::fromLatin1( "application/x-bzdvi" ) ] = app_bzip;
            compressedMimeMap[ QString::fromLatin1( "image/x-bzeps" ) ] = app_bzip;
        }
213
        // check if we can read XZ-compressed files
214
        f.reset( KCompressionDevice::filterForCompressionType( KCompressionDevice::Xz ) );
215
216
        if ( f.get() )
        {
217
            supportXz = true;
218
        }
219
    }
Laurent Montel's avatar
Laurent Montel committed
220
221
    QHash< QString, QString >::const_iterator it = compressedMimeMap.constFind( mime_to_check );
    if ( it != compressedMimeMap.constEnd() )
222
223
        return it.value();

224
    KMimeType::Ptr mime = KMimeType::mimeType( mime_to_check );
225
226
227
228
229
230
231
232
233
    if ( mime )
    {
        if ( mime->is( app_gzip ) )
            return app_gzip;
        else if ( supportBzip && mime->is( app_bzip ) )
            return app_bzip;
        else if ( supportXz && mime->is( app_xz ) )
            return app_xz;
    }
234

235
236
237
    return QString();
}

238
static Okular::EmbedMode detectEmbedMode( QWidget *parentWidget, QObject *parent, const QVariantList &args )
239
240
241
242
243
244
{
    Q_UNUSED( parentWidget );

    if ( parent
         && ( parent->objectName() == QLatin1String( "okular::Shell" )
              || parent->objectName() == QLatin1String( "okular/okular__Shell" ) ) )
245
        return Okular::NativeShellMode;
246

247
248
    if ( parent
         && ( QByteArray( "KHTMLPart" ) == parent->metaObject()->className() ) )
249
        return Okular::KHTMLPartMode;
250

251
252
253
254
    Q_FOREACH ( const QVariant &arg, args )
    {
        if ( arg.type() == QVariant::String )
        {
Michel Ludwig's avatar
Michel Ludwig committed
255
256
            if ( arg.toString() == QLatin1String( "Print/Preview" ) )
            {
257
                return Okular::PrintPreviewMode;
258
            }
Michel Ludwig's avatar
Michel Ludwig committed
259
260
            else if ( arg.toString() == QLatin1String( "ViewerWidget" ) )
            {
261
                return Okular::ViewerWidgetMode;
262
            }
263
264
265
        }
    }

266
    return Okular::UnknownEmbedMode;
267
268
}

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
static QString detectConfigFileName( const QVariantList &args )
{
    Q_FOREACH ( const QVariant &arg, args )
    {
        if ( arg.type() == QVariant::String )
        {
            QString argString = arg.toString();
            int separatorIndex = argString.indexOf( "=" );
            if ( separatorIndex >= 0 && argString.left( separatorIndex ) == QLatin1String( "ConfigFileName" ) )
            {
                return argString.mid( separatorIndex + 1 );
            }
        }
    }

Michel Ludwig's avatar
Michel Ludwig committed
284
    return QString();
285
286
}

287
288
289
290
291
292
293
294
295
296
#undef OKULAR_KEEP_FILE_OPEN

#ifdef OKULAR_KEEP_FILE_OPEN
static bool keepFileOpen()
{
    static bool keep_file_open = !qgetenv("OKULAR_NO_KEEP_FILE_OPEN").toInt();
    return keep_file_open;
}
#endif

297
298
int Okular::Part::numberOfParts = 0;

299
300
301
namespace Okular
{

Albert Astals Cid's avatar
compile    
Albert Astals Cid committed
302
Part::Part(QWidget *parentWidget,
303
QObject *parent,
304
const QVariantList &args)
305
: KParts::ReadWritePart(parent),
306
m_tempfile( 0 ), m_fileWasRemoved( false ), m_showMenuBarAction( 0 ), m_showFullScreenAction( 0 ), m_actionsSearched( false ),
307
m_cliPresentation(false), m_cliPrint(false), m_embedMode(detectEmbedMode(parentWidget, parent, args)), m_generatorGuiClient(0), m_keeper( 0 )
308
{
309
310
    // first, we check if a config file name has been specified
    QString configFileName = detectConfigFileName( args );
Michel Ludwig's avatar
Michel Ludwig committed
311
    if ( configFileName.isEmpty() )
312
    {
313
314
315
316
317
318
319
320
        configFileName = KStandardDirs::locateLocal( "config", "okularpartrc" );
        // first necessary step: copy the configuration from kpdf, if available
        if ( !QFile::exists( configFileName ) )
        {
            QString oldkpdfconffile = KStandardDirs::locateLocal( "config", "kpdfpartrc" );
            if ( QFile::exists( oldkpdfconffile ) )
                QFile::copy( oldkpdfconffile, configFileName );
        }
321
    }
322
    Okular::Settings::instance( configFileName );
323
324
325
326
327
328
329
    
    numberOfParts++;
    if (numberOfParts == 1) {
        QDBusConnection::sessionBus().registerObject("/okular", this, QDBusConnection::ExportScriptableSlots);
    } else {
        QDBusConnection::sessionBus().registerObject(QString("/okular%1").arg(numberOfParts), this, QDBusConnection::ExportScriptableSlots);
    }
330

331
332
    // connect the started signal to tell the job the mimetypes we like,
    // and get some more information from it
Laurent Montel's avatar
Laurent Montel committed
333
    connect(this, SIGNAL(started(KIO::Job*)), this, SLOT(slotJobStarted(KIO::Job*)));
334
335
336

    // connect the completed signal so we can put the window caption when loading remote files
    connect(this, SIGNAL(completed()), this, SLOT(setWindowTitleFromDocument()));
Laurent Montel's avatar
Laurent Montel committed
337
    connect(this, SIGNAL(canceled(QString)), this, SLOT(loadCancelled(QString)));
338

339
340
    // create browser extension (for printing when embedded into browser)
    m_bExtension = new BrowserExtension(this);
341
342
    // create live connect extension (for integrating with browser scripting)
    new OkularLiveConnectExtension( this );
343
344

    // we need an instance
345
346
#pragma message("KF5 figure out if component data is needed here")
//    setComponentData( componentData );
347

348
    GuiUtils::addIconLoader( iconLoader() );
349

350
351
    m_sidebar = new Sidebar( parentWidget );
    setWidget( m_sidebar );
352
    connect( m_sidebar, SIGNAL(urlsDropped(KUrl::List)), SLOT(handleDroppedUrls(KUrl::List)) );
Pino Toscano's avatar
Pino Toscano committed
353

354
    // build the document
355
    m_document = new Okular::Document(widget());
Laurent Montel's avatar
Laurent Montel committed
356
357
358
359
360
361
362
    connect( m_document, SIGNAL(linkFind()), this, SLOT(slotFind()) );
    connect( m_document, SIGNAL(linkGoToPage()), this, SLOT(slotGoToPage()) );
    connect( m_document, SIGNAL(linkPresentation()), this, SLOT(slotShowPresentation()) );
    connect( m_document, SIGNAL(linkEndPresentation()), this, SLOT(slotHidePresentation()) );
    connect( m_document, SIGNAL(openUrl(KUrl)), this, SLOT(openUrlFromDocument(KUrl)) );
    connect( m_document->bookmarkManager(), SIGNAL(openUrl(KUrl)), this, SLOT(openUrlFromBookmarks(KUrl)) );
    connect( m_document, SIGNAL(close()), this, SLOT(close()) );
363

Frederik Gladhorn's avatar
Frederik Gladhorn committed
364
    if ( parent && parent->metaObject()->indexOfSlot( QMetaObject::normalizedSignature( "slotQuit()" ).constData() ) != -1 )
Laurent Montel's avatar
Laurent Montel committed
365
        connect( m_document, SIGNAL(quit()), parent, SLOT(slotQuit()) );
366
    else
Laurent Montel's avatar
Laurent Montel committed
367
        connect( m_document, SIGNAL(quit()), this, SLOT(cannotQuit()) );
368
369
370
371
372
373
374
375
376
377
    // widgets: ^searchbar (toolbar containing label and SearchWidget)
    //      m_searchToolBar = new KToolBar( parentWidget, "searchBar" );
    //      m_searchToolBar->boxLayout()->setSpacing( KDialog::spacingHint() );
    //      QLabel * sLabel = new QLabel( i18n( "&Search:" ), m_searchToolBar, "kde toolbar widget" );
    //      m_searchWidget = new SearchWidget( m_searchToolBar, m_document );
    //      sLabel->setBuddy( m_searchWidget );
    //      m_searchToolBar->setStretchableWidget( m_searchWidget );

    int tbIndex;
    // [left toolbox: Table of Contents] | []
Pino Toscano's avatar
Pino Toscano committed
378
    m_toc = new TOC( 0, m_document );
Laurent Montel's avatar
Laurent Montel committed
379
    connect( m_toc, SIGNAL(hasTOC(bool)), this, SLOT(enableTOC(bool)) );
380
    tbIndex = m_sidebar->addItem( m_toc, KIcon(QApplication::isLeftToRight() ? "format-justify-left" : "format-justify-right"), i18n("Contents") );
381
382
383
    enableTOC( false );

    // [left toolbox: Thumbnails and Bookmarks] | []
Pino Toscano's avatar
Pino Toscano committed
384
    KVBox * thumbsBox = new ThumbnailsBox( 0 );
385
    thumbsBox->setSpacing( 6 );
386
387
388
    m_searchWidget = new SearchWidget( thumbsBox, m_document );
    m_thumbnailList = new ThumbnailList( thumbsBox, m_document );
    //	ThumbnailController * m_tc = new ThumbnailController( thumbsBox, m_thumbnailList );
Laurent Montel's avatar
Laurent Montel committed
389
    connect( m_thumbnailList, SIGNAL(rightClick(const Okular::Page*,QPoint)), this, SLOT(slotShowMenu(const Okular::Page*,QPoint)) );
Pino Toscano's avatar
Pino Toscano committed
390
    tbIndex = m_sidebar->addItem( thumbsBox, KIcon( "view-preview" ), i18n("Thumbnails") );
Pino Toscano's avatar
Pino Toscano committed
391
    m_sidebar->setCurrentIndex( tbIndex );
392
393

    // [left toolbox: Reviews] | []
394
395
    m_reviewsWidget = new Reviews( 0, m_document );
    m_sidebar->addItem( m_reviewsWidget, KIcon("draw-freehand"), i18n("Reviews") );
396
    m_sidebar->setItemEnabled( 2, false );
397
398

    // [left toolbox: Bookmarks] | []
399
400
    m_bookmarkList = new BookmarkList( m_document, 0 );
    m_sidebar->addItem( m_bookmarkList, KIcon("bookmarks"), i18n("Bookmarks") );
401
    m_sidebar->setItemEnabled( 3, false );
402
403

    // widgets: [../miniBarContainer] | []
404
#ifdef OKULAR_ENABLE_MINIBAR
Pino Toscano's avatar
Pino Toscano committed
405
406
    QWidget * miniBarContainer = new QWidget( 0 );
    m_sidebar->setBottomWidget( miniBarContainer );
407
408
409
410
411
412
413
414
415
416
417
418
419
    QVBoxLayout * miniBarLayout = new QVBoxLayout( miniBarContainer );
    miniBarLayout->setMargin( 0 );
    // widgets: [../[spacer/..]] | []
    miniBarLayout->addItem( new QSpacerItem( 6, 6, QSizePolicy::Fixed, QSizePolicy::Fixed ) );
    // widgets: [../[../MiniBar]] | []
    QFrame * bevelContainer = new QFrame( miniBarContainer );
    bevelContainer->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
    QVBoxLayout * bevelContainerLayout = new QVBoxLayout( bevelContainer );
    bevelContainerLayout->setMargin( 4 );
    m_progressWidget = new ProgressWidget( bevelContainer, m_document );
    bevelContainerLayout->addWidget( m_progressWidget );
    miniBarLayout->addWidget( bevelContainer );
    miniBarLayout->addItem( new QSpacerItem( 6, 6, QSizePolicy::Fixed, QSizePolicy::Fixed ) );
420
#endif
421
422

    // widgets: [] | [right 'pageView']
Pino Toscano's avatar
Pino Toscano committed
423
424
    QWidget * rightContainer = new QWidget( 0 );
    m_sidebar->setMainWidget( rightContainer );
425
426
427
428
429
    QVBoxLayout * rightLayout = new QVBoxLayout( rightContainer );
    rightLayout->setMargin( 0 );
    rightLayout->setSpacing( 0 );
    //	KToolBar * rtb = new KToolBar( rightContainer, "mainToolBarSS" );
    //	rightLayout->addWidget( rtb );
430
431
432
433
434
435
436
    m_topMessage = new KMessageWidget( rightContainer );
    m_topMessage->setVisible( false );
    m_topMessage->setWordWrap( true );
    m_topMessage->setMessageType( KMessageWidget::Information );
    m_topMessage->setText( i18n( "This document has embedded files. <a href=\"okular:/embeddedfiles\">Click here to see them</a> or go to File -> Embedded Files." ) );
    m_topMessage->setIcon( KIcon( "mail-attachment" ) );
    connect( m_topMessage, SIGNAL(linkActivated(QString)), this, SLOT(slotShowEmbeddedFiles()) );
437
    rightLayout->addWidget( m_topMessage );
438
439
440
441
    m_formsMessage = new KMessageWidget( rightContainer );
    m_formsMessage->setVisible( false );
    m_formsMessage->setWordWrap( true );
    m_formsMessage->setMessageType( KMessageWidget::Information );
442
    rightLayout->addWidget( m_formsMessage );
443
444
445
446
447
448
449
450
    m_infoMessage = new KMessageWidget( rightContainer );
    m_infoMessage->setVisible( false );
    m_infoMessage->setWordWrap( true );
    m_infoMessage->setMessageType( KMessageWidget::Information );
    rightLayout->addWidget( m_infoMessage );
    m_infoTimer = new QTimer();
    m_infoTimer->setSingleShot( true );
    connect( m_infoTimer, SIGNAL(timeout()), m_infoMessage, SLOT(animatedHide()) );
451
    m_pageView = new PageView( rightContainer, m_document );
452
    QMetaObject::invokeMethod( m_pageView, "setFocus", Qt::QueuedConnection );      //usability setting
Pino Toscano's avatar
Pino Toscano committed
453
//    m_splitter->setFocusProxy(m_pageView);
Laurent Montel's avatar
Laurent Montel committed
454
    connect( m_pageView, SIGNAL(rightClick(const Okular::Page*,QPoint)), this, SLOT(slotShowMenu(const Okular::Page*,QPoint)) );
455
456
457
    connect( m_document, SIGNAL(error(QString,int)), this, SLOT(errorMessage(QString,int)) );
    connect( m_document, SIGNAL(warning(QString,int)), this, SLOT(warningMessage(QString,int)) );
    connect( m_document, SIGNAL(notice(QString,int)), this, SLOT(noticeMessage(QString,int)) );
Michel Ludwig's avatar
Michel Ludwig committed
458
    connect( m_document, SIGNAL(sourceReferenceActivated(const QString&,int,int,bool*)), this, SLOT(slotHandleActivatedSourceReference(const QString&,int,int,bool*)) );
459
    rightLayout->addWidget( m_pageView );
460
461
    m_findBar = new FindBar( m_document, rightContainer );
    rightLayout->addWidget( m_findBar );
462
463
464
    m_bottomBar = new QWidget( rightContainer );
    QHBoxLayout * bottomBarLayout = new QHBoxLayout( m_bottomBar );
    m_pageSizeLabel = new PageSizeLabel( m_bottomBar, m_document );
465
466
467
    bottomBarLayout->setMargin( 0 );
    bottomBarLayout->setSpacing( 0 );
    bottomBarLayout->addItem( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
Albert Astals Cid's avatar
Albert Astals Cid committed
468
469
    m_miniBarLogic = new MiniBarLogic( this, m_document );
    m_miniBar = new MiniBar( m_bottomBar, m_miniBarLogic );
470
471
    bottomBarLayout->addWidget( m_miniBar );
    bottomBarLayout->addWidget( m_pageSizeLabel );
472
    rightLayout->addWidget( m_bottomBar );
473

Albert Astals Cid's avatar
Albert Astals Cid committed
474
    m_pageNumberTool = new MiniBar( 0, m_miniBarLogic );
475

Laurent Montel's avatar
Laurent Montel committed
476
477
    connect( m_findBar, SIGNAL(forwardKeyPressEvent(QKeyEvent*)), m_pageView, SLOT(externalKeyPressEvent(QKeyEvent*)));
    connect( m_miniBar, SIGNAL(forwardKeyPressEvent(QKeyEvent*)), m_pageView, SLOT(externalKeyPressEvent(QKeyEvent*)));
478
    connect( m_pageView, SIGNAL(escPressed()), m_findBar, SLOT(resetSearch()) );
479
    connect( m_pageNumberTool, SIGNAL(forwardKeyPressEvent(QKeyEvent*)), m_pageView, SLOT(externalKeyPressEvent(QKeyEvent*)));
480

481
482
    connect( m_reviewsWidget, SIGNAL(openAnnotationWindow(Okular::Annotation*,int)),
        m_pageView, SLOT(openAnnotationWindow(Okular::Annotation*,int)) );
483
484
485
486
487

    // add document observers
    m_document->addObserver( this );
    m_document->addObserver( m_thumbnailList );
    m_document->addObserver( m_pageView );
488
    m_document->registerView( m_pageView );
489
    m_document->addObserver( m_toc );
Albert Astals Cid's avatar
Albert Astals Cid committed
490
    m_document->addObserver( m_miniBarLogic );
491
#ifdef OKULAR_ENABLE_MINIBAR
492
    m_document->addObserver( m_progressWidget );
493
#endif
494
    m_document->addObserver( m_reviewsWidget );
495
    m_document->addObserver( m_pageSizeLabel );
496
    m_document->addObserver( m_bookmarkList );
497

Laurent Montel's avatar
Laurent Montel committed
498
499
    connect( m_document->bookmarkManager(), SIGNAL(saved()),
        this, SLOT(slotRebuildBookmarkMenu()) );
500

501
502
503
504
505
506
    setupViewerActions();

    if ( m_embedMode != ViewerWidgetMode )
    {
        setupActions();
    }
507
508
509
510
    else
    {
        setViewerShortcuts();
    }
511
512
513
514
515
516
517
518
519
520

    // document watcher and reloader
    m_watcher = new KDirWatch( this );
    connect( m_watcher, SIGNAL(dirty(QString)), this, SLOT(slotFileDirty(QString)) );
    m_dirtyHandler = new QTimer( this );
    m_dirtyHandler->setSingleShot( true );
    connect( m_dirtyHandler, SIGNAL(timeout()),this, SLOT(slotDoFileDirty()) );

    slotNewConfig();

521
522
523
    // keep us informed when the user changes settings
    connect( Okular::Settings::self(), SIGNAL(configChanged()), this, SLOT(slotNewConfig()) );

524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
    // [SPEECH] check for KTTSD presence and usability
    const KService::Ptr kttsd = KService::serviceByDesktopName("kttsd");
    Okular::Settings::setUseKTTSD( kttsd );
    Okular::Settings::self()->writeConfig();

    rebuildBookmarkMenu( false );

    if ( m_embedMode == ViewerWidgetMode ) {
        // set the XML-UI resource file for the viewer mode
        setXMLFile("part-viewermode.rc");
    }
    else
    {
        // set our main XML-UI resource file
        setXMLFile("part.rc");
    }

    m_pageView->setupBaseActions( actionCollection() );

    m_sidebar->setSidebarVisibility( false );
    if ( m_embedMode != PrintPreviewMode )
    {
        // now set up actions that are required for all remaining modes
        m_pageView->setupViewerActions( actionCollection() );
        // and if we are not in viewer mode, we want the full GUI
        if ( m_embedMode != ViewerWidgetMode )
        {
            unsetDummyMode();
        }
    }

    // ensure history actions are in the correct state
    updateViewActions();

558
559
    // also update the state of the actions in the page view
    m_pageView->updateActionState( false, false, false );
560
561
562
563
564
565
566
567
568
569
570

    if ( m_embedMode == NativeShellMode )
        m_sidebar->setAutoFillBackground( false );

#ifdef OKULAR_KEEP_FILE_OPEN
    m_keeper = new FileKeeper();
#endif
}

void Part::setupViewerActions()
{
571
572
573
574
    // ACTIONS
    KActionCollection * ac = actionCollection();

    // Page Traversal actions
Laurent Montel's avatar
Laurent Montel committed
575
    m_gotoPage = KStandardAction::gotoPage( this, SLOT(slotGoToPage()), ac );
576
    m_gotoPage->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_G) );
577
    // dirty way to activate gotopage when pressing miniBar's button
Laurent Montel's avatar
Laurent Montel committed
578
    connect( m_miniBar, SIGNAL(gotoPage()), m_gotoPage, SLOT(trigger()) );
579
    connect( m_pageNumberTool, SIGNAL(gotoPage()), m_gotoPage, SLOT(trigger()) );
580
581

    m_prevPage = KStandardAction::prior(this, SLOT(slotPreviousPage()), ac);
Pino Toscano's avatar
Pino Toscano committed
582
583
    m_prevPage->setIconText( i18nc( "Previous page", "Previous" ) );
    m_prevPage->setToolTip( i18n( "Go back to the Previous Page" ) );
584
585
586
    m_prevPage->setWhatsThis( i18n( "Moves to the previous page of the document" ) );
    m_prevPage->setShortcut( 0 );
    // dirty way to activate prev page when pressing miniBar's button
Laurent Montel's avatar
Laurent Montel committed
587
    connect( m_miniBar, SIGNAL(prevPage()), m_prevPage, SLOT(trigger()) );
588
    connect( m_pageNumberTool, SIGNAL(prevPage()), m_prevPage, SLOT(trigger()) );
589
#ifdef OKULAR_ENABLE_MINIBAR
Laurent Montel's avatar
Laurent Montel committed
590
    connect( m_progressWidget, SIGNAL(prevPage()), m_prevPage, SLOT(trigger()) );
591
#endif
592
593

    m_nextPage = KStandardAction::next(this, SLOT(slotNextPage()), ac );
Pino Toscano's avatar
Pino Toscano committed
594
595
    m_nextPage->setIconText( i18nc( "Next page", "Next" ) );
    m_nextPage->setToolTip( i18n( "Advance to the Next Page" ) );
596
597
598
    m_nextPage->setWhatsThis( i18n( "Moves to the next page of the document" ) );
    m_nextPage->setShortcut( 0 );
    // dirty way to activate next page when pressing miniBar's button
Laurent Montel's avatar
Laurent Montel committed
599
    connect( m_miniBar, SIGNAL(nextPage()), m_nextPage, SLOT(trigger()) );
600
    connect( m_pageNumberTool, SIGNAL(nextPage()), m_nextPage, SLOT(trigger()) );
601
#ifdef OKULAR_ENABLE_MINIBAR
Laurent Montel's avatar
Laurent Montel committed
602
    connect( m_progressWidget, SIGNAL(nextPage()), m_nextPage, SLOT(trigger()) );
603
#endif
604

Laurent Montel's avatar
Laurent Montel committed
605
    m_beginningOfDocument = KStandardAction::firstPage( this, SLOT(slotGotoFirst()), ac );
606
607
608
    ac->addAction("first_page", m_beginningOfDocument);
    m_beginningOfDocument->setText(i18n( "Beginning of the document"));
    m_beginningOfDocument->setWhatsThis( i18n( "Moves to the beginning of the document" ) );
609

Laurent Montel's avatar
Laurent Montel committed
610
    m_endOfDocument = KStandardAction::lastPage( this, SLOT(slotGotoLast()), ac );
611
612
613
    ac->addAction("last_page",m_endOfDocument);
    m_endOfDocument->setText(i18n( "End of the document"));
    m_endOfDocument->setWhatsThis( i18n( "Moves to the end of the document" ) );
614

Albert Astals Cid's avatar
Albert Astals Cid committed
615
616
617
    // we do not want back and next in history in the dummy mode
    m_historyBack = 0;
    m_historyNext = 0;
618

Laurent Montel's avatar
Laurent Montel committed
619
    m_addBookmark = KStandardAction::addBookmark( this, SLOT(slotAddBookmark()), ac );
620
    m_addBookmarkText = m_addBookmark->text();
621
    m_addBookmarkIcon = m_addBookmark->icon();
622

623
624
625
    m_renameBookmark = ac->addAction("rename_bookmark");
    m_renameBookmark->setText(i18n( "Rename Bookmark" ));
    m_renameBookmark->setIcon(KIcon( "edit-rename" ));
626
627
    m_renameBookmark->setWhatsThis( i18n( "Rename the current bookmark" ) );
    connect( m_renameBookmark, SIGNAL(triggered()), this, SLOT(slotRenameCurrentViewportBookmark()) );
628

629
630
    m_prevBookmark = ac->addAction("previous_bookmark");
    m_prevBookmark->setText(i18n( "Previous Bookmark" ));
631
    m_prevBookmark->setIcon(KIcon( "go-up-search" ));
632
    m_prevBookmark->setWhatsThis( i18n( "Go to the previous bookmark" ) );
Laurent Montel's avatar
Laurent Montel committed
633
    connect( m_prevBookmark, SIGNAL(triggered()), this, SLOT(slotPreviousBookmark()) );
634
635
636

    m_nextBookmark = ac->addAction("next_bookmark");
    m_nextBookmark->setText(i18n( "Next Bookmark" ));
637
    m_nextBookmark->setIcon(KIcon( "go-down-search" ));
638
    m_nextBookmark->setWhatsThis( i18n( "Go to the next bookmark" ) );
Laurent Montel's avatar
Laurent Montel committed
639
    connect( m_nextBookmark, SIGNAL(triggered()), this, SLOT(slotNextBookmark()) );
640

Michel Ludwig's avatar
Michel Ludwig committed
641
    m_copy = 0;
642

Michel Ludwig's avatar
Michel Ludwig committed
643
    m_selectAll = 0;
644

645
    // Find and other actions
Laurent Montel's avatar
Laurent Montel committed
646
    m_find = KStandardAction::find( this, SLOT(slotShowFindBar()), ac );
647
648
649
    QList<QKeySequence> s = m_find->shortcuts();
    s.append( QKeySequence( Qt::Key_Slash ) );
    m_find->setShortcuts( s );
650
651
    m_find->setEnabled( false );

Laurent Montel's avatar
Laurent Montel committed
652
    m_findNext = KStandardAction::findNext( this, SLOT(slotFindNext()), ac);
653
654
    m_findNext->setEnabled( false );

Laurent Montel's avatar
Laurent Montel committed
655
    m_findPrev = KStandardAction::findPrev( this, SLOT(slotFindPrev()), ac );
Pino Toscano's avatar
Pino Toscano committed
656
657
    m_findPrev->setEnabled( false );

Michel Ludwig's avatar
Michel Ludwig committed
658
659
    m_saveCopyAs = 0;
    m_saveAs = 0;
Pino Toscano's avatar
Pino Toscano committed
660

Laurent Montel's avatar
Laurent Montel committed
661
    QAction * prefs = KStandardAction::preferences( this, SLOT(slotPreferences()), ac);
662
    if ( m_embedMode == NativeShellMode )
663
    {
Pino Toscano's avatar
Pino Toscano committed
664
        prefs->setText( i18n( "Configure Okular..." ) );
665
666
667
    }
    else
    {
Pino Toscano's avatar
Pino Toscano committed
668
        // TODO: improve this message
669
670
671
        prefs->setText( i18n( "Configure Viewer..." ) );
    }

Pino Toscano's avatar
Pino Toscano committed
672
673
    KAction * genPrefs = new KAction( ac );
    ac->addAction("options_configure_generators", genPrefs);
674
675
676
677
    if ( m_embedMode == ViewerWidgetMode )
    {
        genPrefs->setText( i18n( "Configure Viewer Backends..." ) );
    }
Michel Ludwig's avatar
Michel Ludwig committed
678
679
    else
    {
680
681
        genPrefs->setText( i18n( "Configure Backends..." ) );
    }
Pino Toscano's avatar
Pino Toscano committed
682
    genPrefs->setIcon( KIcon( "configure" ) );
683
    genPrefs->setEnabled( m_document->configurableGenerators() > 0 );
Laurent Montel's avatar
Laurent Montel committed
684
    connect( genPrefs, SIGNAL(triggered(bool)), this, SLOT(slotGeneratorPreferences()) );
685

Laurent Montel's avatar
Laurent Montel committed
686
    m_printPreview = KStandardAction::printPreview( this, SLOT(slotPrintPreview()), ac );
687
688
    m_printPreview->setEnabled( false );

Michel Ludwig's avatar
Michel Ludwig committed
689
690
    m_showLeftPanel = 0;
    m_showBottomBar = 0;
691
692
693
694
695
696
697

    m_showProperties = ac->addAction("properties");
    m_showProperties->setText(i18n("&Properties"));
    m_showProperties->setIcon(KIcon("document-properties"));
    connect(m_showProperties, SIGNAL(triggered()), this, SLOT(slotShowProperties()));
    m_showProperties->setEnabled( false );

Michel Ludwig's avatar
Michel Ludwig committed
698
699
    m_showEmbeddedFiles = 0;
    m_showPresentation = 0;
700

Michel Ludwig's avatar
Michel Ludwig committed
701
702
703
704
    m_exportAs = 0;
    m_exportAsMenu = 0;
    m_exportAsText = 0;
    m_exportAsDocArchive = 0;
705
706
707
708
709
710
711
712
713
714
715

    m_aboutBackend = ac->addAction("help_about_backend");
    m_aboutBackend->setText(i18n("About Backend"));
    m_aboutBackend->setEnabled( false );
    connect(m_aboutBackend, SIGNAL(triggered()), this, SLOT(slotAboutBackend()));

    KAction *reload = ac->add<KAction>( "file_reload" );
    reload->setText( i18n( "Reloa&d" ) );
    reload->setIcon( KIcon( "view-refresh" ) );
    reload->setWhatsThis( i18n( "Reload the current document from disk." ) );
    connect( reload, SIGNAL(triggered()), this, SLOT(slotReload()) );
716
    reload->setShortcut( QKeySequence(QKeySequence::Refresh) );
717
718
    m_reload = reload;

Jonathan Doman's avatar
Jonathan Doman committed
719
720
721
722
    m_closeFindBar = ac->addAction( "close_find_bar", this, SLOT(slotHideFindBar()) );
    m_closeFindBar->setText( i18n("Close &Find Bar") );
    m_closeFindBar->setShortcut( QKeySequence(Qt::Key_Escape) );
    m_closeFindBar->setEnabled( false );
723
724
725
726

    KAction *pageno = new KAction( i18n( "Page Number" ), ac );
    pageno->setDefaultWidget( m_pageNumberTool );
    ac->addAction( "page_number", pageno );
727
728
}

729
void Part::setViewerShortcuts()
730
731
732
{
    KActionCollection * ac = actionCollection();

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
    m_gotoPage->setShortcut( QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_G) );
    m_find->setShortcuts( QList<QKeySequence>() );

    m_findNext->setShortcut( QKeySequence() );
    m_findPrev->setShortcut( QKeySequence() );

    m_addBookmark->setShortcut( QKeySequence( Qt::CTRL + Qt::ALT + Qt::Key_B ) );

    m_beginningOfDocument->setShortcut( QKeySequence( Qt::CTRL + Qt::ALT + Qt::Key_Home ) );
    m_endOfDocument->setShortcut( QKeySequence( Qt::CTRL + Qt::ALT + Qt::Key_End ) );

    KAction *action = static_cast<KAction*>( ac->action( "file_reload" ) );
    if( action )  action->setShortcuts( QList<QKeySequence>() << QKeySequence( Qt::ALT + Qt::Key_F5 ) );
}

void Part::setupActions()
{
    KActionCollection * ac = actionCollection();
751
752
753
754
755
756
757

    m_copy = KStandardAction::create( KStandardAction::Copy, m_pageView, SLOT(copyTextSelection()), ac );

    m_selectAll = KStandardAction::selectAll( m_pageView, SLOT(selectAll()), ac );

    m_saveCopyAs = KStandardAction::saveAs( this, SLOT(slotSaveCopyAs()), ac );
    m_saveCopyAs->setText( i18n( "Save &Copy As..." ) );
758
    m_saveCopyAs->setShortcut( QKeySequence(QKeySequence::SaveAs) );
759
760
761
762
763
764
    ac->addAction( "file_save_copy", m_saveCopyAs );
    m_saveCopyAs->setEnabled( false );

    m_saveAs = KStandardAction::saveAs( this, SLOT(slotSaveFileAs()), ac );
    m_saveAs->setEnabled( false );

765
766
    m_showLeftPanel = ac->add<KToggleAction>("show_leftpanel");
    m_showLeftPanel->setText(i18n( "Show &Navigation Panel"));
767
    m_showLeftPanel->setIcon(KIcon( "view-sidetree" ));
Laurent Montel's avatar
Laurent Montel committed
768
    connect( m_showLeftPanel, SIGNAL(toggled(bool)), this, SLOT(slotShowLeftPanel()) );
769
    m_showLeftPanel->setShortcut( Qt::Key_F7 );
770
771
772
    m_showLeftPanel->setChecked( Okular::Settings::showLeftPanel() );
    slotShowLeftPanel();

773
774
    m_showBottomBar = ac->add<KToggleAction>("show_bottombar");
    m_showBottomBar->setText(i18n( "Show &Page Bar"));
Laurent Montel's avatar
Laurent Montel committed
775
    connect( m_showBottomBar, SIGNAL(toggled(bool)), this, SLOT(slotShowBottomBar()) );
776
777
778
    m_showBottomBar->setChecked( Okular::Settings::showBottomBar() );
    slotShowBottomBar();

779
780
    m_showEmbeddedFiles = ac->addAction("embedded_files");
    m_showEmbeddedFiles->setText(i18n("&Embedded Files"));
Pino Toscano's avatar
Pino Toscano committed
781
    m_showEmbeddedFiles->setIcon( KIcon( "mail-attachment" ) );
782
783
784
785
786
    connect(m_showEmbeddedFiles, SIGNAL(triggered()), this, SLOT(slotShowEmbeddedFiles()));
    m_showEmbeddedFiles->setEnabled( false );

    m_exportAs = ac->addAction("file_export_as");
    m_exportAs->setText(i18n("E&xport As"));
Pino Toscano's avatar
Pino Toscano committed
787
    m_exportAs->setIcon( KIcon( "document-export" ) );
788
    m_exportAsMenu = new QMenu();
Laurent Montel's avatar
Laurent Montel committed
789
    connect(m_exportAsMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotExportAs(QAction*)));
790
791
792
    m_exportAs->setMenu( m_exportAsMenu );
    m_exportAsText = actionForExportFormat( Okular::ExportFormat::standardFormat( Okular::ExportFormat::PlainText ), m_exportAsMenu );
    m_exportAsMenu->addAction( m_exportAsText );
793
    m_exportAs->setEnabled( false );
794
    m_exportAsText->setEnabled( false );
795
796
797
798
799
    m_exportAsDocArchive = actionForExportFormat( Okular::ExportFormat(
            i18nc( "A document format, Okular-specific", "Document Archive" ),
            KMimeType::mimeType( "application/vnd.kde.okular-archive" ) ), m_exportAsMenu );
    m_exportAsMenu->addAction( m_exportAsDocArchive );
    m_exportAsDocArchive->setEnabled( false );
800

801
802
803
804
805
806
    m_showPresentation = ac->addAction("presentation");
    m_showPresentation->setText(i18n("P&resentation"));
    m_showPresentation->setIcon( KIcon( "view-presentation" ) );
    connect(m_showPresentation, SIGNAL(triggered()), this, SLOT(slotShowPresentation()));
    m_showPresentation->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_P ) );
    m_showPresentation->setEnabled( false );
807

808
809
810
811
812
813
814
815
816
817
818
819
    QAction * importPS = ac->addAction("import_ps");
    importPS->setText(i18n("&Import PostScript as PDF..."));
    importPS->setIcon(KIcon("document-import"));
    connect(importPS, SIGNAL(triggered()), this, SLOT(slotImportPSFile()));
#if 0
    QAction * ghns = ac->addAction("get_new_stuff");
    ghns->setText(i18n("&Get Books From Internet..."));
    ghns->setIcon(KIcon("get-hot-new-stuff"));
    connect(ghns, SIGNAL(triggered()), this, SLOT(slotGetNewStuff()));
    // TEMP, REMOVE ME!
    ghns->setShortcut( Qt::Key_G );
#endif
820

821
822
823
824
    KToggleAction *blackscreenAction = new KToggleAction( i18n( "Switch Blackscreen Mode" ), ac );
    ac->addAction( "switch_blackscreen_mode", blackscreenAction );
    blackscreenAction->setShortcut( QKeySequence( Qt::Key_B ) );
    blackscreenAction->setIcon( KIcon( "view-presentation" ) );
825
    blackscreenAction->setEnabled( false );
826

827
828
829
    KToggleAction *drawingAction = new KToggleAction( i18n( "Toggle Drawing Mode" ), ac );
    ac->addAction( "presentation_drawing_mode", drawingAction );
    drawingAction->setIcon( KIcon( "draw-freehand" ) );
830
    drawingAction->setEnabled( false );
831
832
833
834

    KAction *eraseDrawingAction = new KAction( i18n( "Erase Drawings" ), ac );
    ac->addAction( "presentation_erase_drawings", eraseDrawingAction );
    eraseDrawingAction->setIcon( KIcon( "draw-eraser" ) );
835
    eraseDrawingAction->setEnabled( false );
836
837
838
839
840

    KAction *configureAnnotations = new KAction( i18n( "Configure Annotations..." ), ac );
    ac->addAction( "options_configure_annotations", configureAnnotations );
    configureAnnotations->setIcon( KIcon( "configure" ) );
    connect(configureAnnotations, SIGNAL(triggered()), this, SLOT(slotAnnotationPreferences()));
841
842

    KAction *playPauseAction = new KAction( i18n( "Play/Pause Presentation" ), ac );
843
844
    ac->addAction( "presentation_play_pause", playPauseAction );
    playPauseAction->setEnabled( false );
845
846
}

847
Part::~Part()
Laurent Montel's avatar
Laurent Montel committed
848
{
849
    GuiUtils::removeIconLoader( iconLoader() );
850
851
    m_document->removeObserver( this );

852
    if ( m_document->isOpened() )
853
        Part::closeUrl( false );
854

Albert Astals Cid's avatar
Albert Astals Cid committed
855
856
857
858
    delete m_toc;
    delete m_pageView;
    delete m_thumbnailList;
    delete m_miniBar;
859
    delete m_pageNumberTool;
Albert Astals Cid's avatar
Albert Astals Cid committed
860
    delete m_miniBarLogic;
861
    delete m_bottomBar;
862
#ifdef OKULAR_ENABLE_MINIBAR
863
    delete m_progressWidget;
864
#endif
Albert Astals Cid's avatar
Albert Astals Cid committed
865
    delete m_pageSizeLabel;
866
867
    delete m_reviewsWidget;
    delete m_bookmarkList;
868
    delete m_infoTimer;
Albert Astals Cid's avatar
Albert Astals Cid committed
869

870
    delete m_document;
Leandro Emanuel López's avatar
Leandro Emanuel López committed
871
872

    delete m_tempfile;
873
874

    qDeleteAll( m_bookmarkActions );
875

876
877
    delete m_exportAsMenu;

878
879
880
#ifdef OKULAR_KEEP_FILE_OPEN
    delete m_keeper;
#endif
Laurent Montel's avatar
Laurent Montel committed
881
882
}

883

884
885
886
bool Part::openDocument(const KUrl& url, uint page)
{
    Okular::DocumentViewport vp( page - 1 );
887
888
889
890
    vp.rePos.enabled = true;
    vp.rePos.normalizedX = 0;
    vp.rePos.normalizedY = 0;
    vp.rePos.pos = Okular::DocumentViewport::TopLeft;
891
892
893
894
895
    if ( vp.isValid() )
        m_document->setNextDocumentViewport( vp );
    return openUrl( url );
}

896

897
898
899
900
901
void Part::startPresentation()
{
    m_cliPresentation = true;
}

902

903
904
905
906
907
908
QStringList Part::supportedMimeTypes() const
{
    return m_document->supportedMimeTypes();
}


909
910
911
912
913
914
915
916
KUrl Part::realUrl() const
{
    if ( !m_realUrl.isEmpty() )
        return m_realUrl;

    return url();
}

917
918
// ViewerInterface

919
void Part::showSourceLocation(const QString& fileName, int line, int column, bool showGraphically)
920
{
921
    const QString u = QString( "src:%1 %2" ).arg( line + 1 ).arg( fileName );
922
923
    GotoAction action( QString(), u );
    m_document->processAction( &action );
924
925
926
927
928
929
930
931
932
    if( showGraphically )
    {
        m_pageView->setLastSourceLocationViewport( m_document->viewport() );
    }
}

void Part::clearLastShownSourceLocation()
{
    m_pageView->clearLastSourceLocationViewport();
933
934
}

935
936
937
938
939
bool Part::isWatchFileModeEnabled() const
{
    return !m_watcher->isStopped();
}

940
void Part::setWatchFileModeEnabled(bool enabled)
941
{
942
943
    if ( enabled && m_watcher->isStopped() )
    {
944
945
        m_watcher->startScan();
    }
946
    else if( !enabled && !m_watcher->isStopped() )
947
948
949
950
951
952
    {
        m_dirtyHandler->stop();
        m_watcher->stopScan();
    }
}

953
954
bool Part::areSourceLocationsShownGraphically() const
{
955
    return m_pageView->areSourceLocationsShownGraphically();
956
957
}

958
void Part::setShowSourceLocationsGraphically(bool show)