part.cpp 129 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
 *   Copyright (C) 2017    Klarälvdalens Datakonsult AB, a KDAB Group      *
 *                         company, info@kdab.com. Work sponsored by the   *
 *                         LiMux project of the city of Munich             *
20 21 22 23 24 25 26
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/

27 28
#include "part.h"

29
// qt/kde includes
30
#include <QApplication>
31 32
#include <QDialog>
#include <QDialogButtonBox>
33
#include <QFile>
34 35 36
#include <QFileDialog>
#include <QIcon>
#include <QInputDialog>
37 38
#include <QLayout>
#include <QLabel>
39
#include <QMenu>
40 41
#include <QTimer>
#include <QTemporaryFile>
42 43 44
#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
45
#include <QScrollBar>
46 47
#include <QSlider>
#include <QSpinBox>
48 49
#include <QStandardPaths>
#include <QWidgetAction>
50
#include <QContextMenuEvent>
51

52 53 54 55
#include <KAboutApplicationDialog>
#include <KActionCollection>
#include <KBookmarkAction>
#include <KBookmarkMenu>
56
#include <Kdelibs4ConfigMigrator>
57 58 59 60 61
#include <Kdelibs4Migration>
#include <KDirWatch>
#include <KFilterBase>
#include <KFilterDev>
#include <KIO/Job>
62
#include <KIO/OpenFileManagerWindowJob>
63
#include <KJobWidgets>
64 65 66
#include <KMessageBox>
#include <KPasswordDialog>
#include <KPluginFactory>
67
#include <KPluginMetaData>
68 69 70 71
#include <KSharedDataCache>
#include <KStandardShortcut>
#include <KToggleAction>
#include <KToggleFullScreenAction>
72
#ifdef WITH_KWALLET
73
#include <KWallet>
74
#endif
75 76 77
#include <KXMLGUIClient>
#include <KXMLGUIFactory>

Kevin Ottens's avatar
Kevin Ottens committed
78 79 80 81 82 83

#if PURPOSE_FOUND
#include <Purpose/AlternativesModel>
#include <PurposeWidgets/Menu>
#endif

84
#if 0
85
#include <knewstuff2/engine.h>
86
#endif
87

88
// local includes
89
#include "aboutdata.h"
90
#include "extensions.h"
91
#include "ui/debug_ui.h"
92
#include "ui/drawingtoolactions.h"
93 94
#include "ui/pageview.h"
#include "ui/toc.h"
95 96 97
#include "ui/searchwidget.h"
#include "ui/thumbnaillist.h"
#include "ui/side_reviews.h"
98
#include "ui/minibar.h"
99
#include "ui/embeddedfilesdialog.h"
100 101
#include "ui/propertiesdialog.h"
#include "ui/presentationwidget.h"
Albert Astals Cid's avatar
Albert Astals Cid committed
102
#include "ui/pagesizelabel.h"
103
#include "ui/bookmarklist.h"
104
#include "ui/findbar.h"
Pino Toscano's avatar
Pino Toscano committed
105
#include "ui/sidebar.h"
106
#include "ui/fileprinterpreview.h"
107
#include "ui/guiutils.h"
108
#include "ui/layers.h"
109
#include "ui/okmenutitle.h"
110
#include "ui/signaturepanel.h"
111
#include "conf/preferencesdialog.h"
112
#include "settings.h"
113
#include "core/action.h"
114
#include "core/annotations.h"
115
#include "core/bookmarkmanager.h"
116
#include "core/document.h"
117
#include "core/document_p.h"
118
#include "core/generator.h"
119
#include "core/page.h"
John Layt's avatar
John Layt committed
120
#include "core/fileprinter.h"
121
#include "core/printoptionswidget.h"
122
#include <memory>
123

124
#ifdef OKULAR_KEEP_FILE_OPEN
125 126 127 128
class FileKeeper
{
    public:
        FileKeeper()
129
            : m_handle( nullptr )
130 131 132 133 134 135 136 137 138 139
        {
        }

        ~FileKeeper()
        {
        }

        void open( const QString & path )
        {
            if ( !m_handle )
Frederik Gladhorn's avatar
Frederik Gladhorn committed
140
                m_handle = std::fopen( QFile::encodeName( path ).constData(), "r" );
141 142 143 144 145 146 147 148
        }

        void close()
        {
            if ( m_handle )
            {
                int ret = std::fclose( m_handle );
                Q_UNUSED( ret )
149
                m_handle = nullptr;
150 151 152
            }
        }

Frederik Gladhorn's avatar
Frederik Gladhorn committed
153
        QTemporaryFile* copyToTemporary() const
154 155
        {
            if ( !m_handle )
156
                return nullptr;
157

Frederik Gladhorn's avatar
Frederik Gladhorn committed
158
            QTemporaryFile * retFile = new QTemporaryFile;
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
            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;
};
180
#endif
181

182 183
K_PLUGIN_FACTORY(OkularPartFactory, registerPlugin<Okular::Part>();)

Laurent Montel's avatar
Laurent Montel committed
184
static QAction* actionForExportFormat( const Okular::ExportFormat& format, QObject *parent = Q_NULLPTR )
185 186 187 188 189 190 191 192 193
{
    QAction *act = new QAction( format.description(), parent );
    if ( !format.icon().isNull() )
    {
        act->setIcon( format.icon() );
    }
    return act;
}

194
static KFilterDev::CompressionType compressionTypeFor( const QString& mime_to_check )
195
{
196 197 198
    // 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
199
    static QHash< QString, KFilterDev::CompressionType > compressedMimeMap;
200 201
    static bool supportBzip = false;
    static bool supportXz = false;
Laurent Montel's avatar
Laurent Montel committed
202 203 204
    const QString app_gzip( QStringLiteral( "application/x-gzip" ) );
    const QString app_bzip( QStringLiteral( "application/x-bzip" ) );
    const QString app_xz( QStringLiteral( "application/x-xz" ) );
205 206
    if ( compressedMimeMap.isEmpty() )
    {
Jan Kundrát's avatar
Jan Kundrát committed
207
        std::unique_ptr< KFilterBase > f;
Laurent Montel's avatar
Laurent Montel committed
208
        compressedMimeMap[ QStringLiteral( "image/x-gzeps" ) ] = KFilterDev::GZip;
209
        // check we can read bzip2-compressed files
210
        f.reset( KCompressionDevice::filterForCompressionType( KCompressionDevice::BZip2 ) );
211 212
        if ( f.get() )
        {
213
            supportBzip = true;
Laurent Montel's avatar
Laurent Montel committed
214 215 216 217
            compressedMimeMap[ QStringLiteral( "application/x-bzpdf" ) ] = KFilterDev::BZip2;
            compressedMimeMap[ QStringLiteral( "application/x-bzpostscript" ) ] = KFilterDev::BZip2;
            compressedMimeMap[ QStringLiteral( "application/x-bzdvi" ) ] = KFilterDev::BZip2;
            compressedMimeMap[ QStringLiteral( "image/x-bzeps" ) ] = KFilterDev::BZip2;
218
        }
219
        // check if we can read XZ-compressed files
220
        f.reset( KCompressionDevice::filterForCompressionType( KCompressionDevice::Xz ) );
221 222
        if ( f.get() )
        {
223
            supportXz = true;
224
        }
225
    }
226
    QHash< QString, KFilterDev::CompressionType >::const_iterator it = compressedMimeMap.constFind( mime_to_check );
Laurent Montel's avatar
Laurent Montel committed
227
    if ( it != compressedMimeMap.constEnd() )
228 229
        return it.value();

Frederik Gladhorn's avatar
Frederik Gladhorn committed
230 231 232
    QMimeDatabase db;
    QMimeType mime = db.mimeTypeForName( mime_to_check );
    if ( mime.isValid() )
233
    {
Frederik Gladhorn's avatar
Frederik Gladhorn committed
234
        if ( mime.inherits( app_gzip ) )
235
            return KFilterDev::GZip;
Frederik Gladhorn's avatar
Frederik Gladhorn committed
236
        else if ( supportBzip && mime.inherits( app_bzip ) )
237
            return KFilterDev::BZip2;
Frederik Gladhorn's avatar
Frederik Gladhorn committed
238
        else if ( supportXz && mime.inherits( app_xz ) )
239
            return KFilterDev::Xz;
240
    }
241

242
    return KFilterDev::None;
243 244
}

245
static Okular::EmbedMode detectEmbedMode( QWidget *parentWidget, QObject *parent, const QVariantList &args )
246 247 248 249
{
    Q_UNUSED( parentWidget );

    if ( parent
Jonathan Doman's avatar
Jonathan Doman committed
250 251
         && ( parent->objectName().startsWith( QLatin1String( "okular::Shell" ) )
              || parent->objectName().startsWith( QLatin1String( "okular/okular__Shell" ) ) ) )
252
        return Okular::NativeShellMode;
253

254 255
    if ( parent
         && ( QByteArray( "KHTMLPart" ) == parent->metaObject()->className() ) )
256
        return Okular::KHTMLPartMode;
257

258 259 260 261
    Q_FOREACH ( const QVariant &arg, args )
    {
        if ( arg.type() == QVariant::String )
        {
Michel Ludwig's avatar
Michel Ludwig committed
262 263
            if ( arg.toString() == QLatin1String( "Print/Preview" ) )
            {
264
                return Okular::PrintPreviewMode;
265
            }
Michel Ludwig's avatar
Michel Ludwig committed
266 267
            else if ( arg.toString() == QLatin1String( "ViewerWidget" ) )
            {
268
                return Okular::ViewerWidgetMode;
269
            }
270 271 272
        }
    }

273
    return Okular::UnknownEmbedMode;
274 275
}

276 277 278 279 280 281 282
static QString detectConfigFileName( const QVariantList &args )
{
    Q_FOREACH ( const QVariant &arg, args )
    {
        if ( arg.type() == QVariant::String )
        {
            QString argString = arg.toString();
Laurent Montel's avatar
Laurent Montel committed
283
            int separatorIndex = argString.indexOf( QStringLiteral("=") );
284 285 286 287 288 289 290
            if ( separatorIndex >= 0 && argString.left( separatorIndex ) == QLatin1String( "ConfigFileName" ) )
            {
                return argString.mid( separatorIndex + 1 );
            }
        }
    }

Michel Ludwig's avatar
Michel Ludwig committed
291
    return QString();
292 293
}

294 295 296 297 298 299 300 301 302 303
#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

304 305
int Okular::Part::numberOfParts = 0;

306 307 308
namespace Okular
{

Albert Astals Cid's avatar
Albert Astals Cid committed
309
Part::Part(QWidget *parentWidget,
310
QObject *parent,
311
const QVariantList &args)
312
: KParts::ReadWritePart(parent),
313
m_tempfile( nullptr ), m_documentOpenWithPassword( false ), m_swapInsteadOfOpening( false ), m_isReloading( false ), m_fileWasRemoved( false ), m_showMenuBarAction( nullptr ), m_showFullScreenAction( nullptr ), m_actionsSearched( false ),
314
m_cliPresentation(false), m_cliPrint(false), m_cliPrintAndExit(false), m_embedMode(detectEmbedMode(parentWidget, parent, args)), m_generatorGuiClient(nullptr), m_keeper( nullptr )
315
{
316 317 318 319
    // make sure that the component name is okular otherwise the XMLGUI .rc files are not found
    // when this part is used in an application other than okular (e.g. unit tests)
    setComponentName(QStringLiteral("okular"), QString());

320 321
    const QLatin1String configFileName("okularpartrc");

322
    // first, we check if a config file name has been specified
323 324 325
    QString configFilePath = detectConfigFileName( args );

    if ( configFilePath.isEmpty() )
326
    {
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
        configFilePath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + configFileName;
    }


    // Migrate old config
    if ( !QFile::exists( configFilePath ) ) {
        qCDebug(OkularUiDebug) << "Did not find a config file, attempting to look for old config";

        // Migrate old config + UI
        Kdelibs4ConfigMigrator configMigrator( componentName() );
        // UI file is handled automatically, we only need to specify config name because we're a part
        configMigrator.setConfigFiles( QStringList( configFileName ) );

        // If there's no old okular config to migrate, look for kpdf
        if ( !configMigrator.migrate() ) {
            qCDebug(OkularUiDebug) << "Did not find an old okular config file, attempting to look for kpdf config";

            // First try the automatic detection, using $KDEHOME etc.
            Kdelibs4Migration migration;
            QString kpdfConfig = migration.locateLocal( "config", QStringLiteral("kpdfpartrc") );

            // Fallback just in case it tried e. g. ~/.kde4
            if ( kpdfConfig.isEmpty() ) {
                kpdfConfig = QDir::homePath() + QStringLiteral("/.kde/share/config/kpdfpartrc");
            }

            if ( QFile::exists( kpdfConfig ) ) {
                qCDebug(OkularUiDebug) << "Found old kpdf config" << kpdfConfig << "copying to" << configFilePath;
                QFile::copy( kpdfConfig, configFilePath );
            } else {
                qCDebug(OkularUiDebug) << "Did not find an old kpdf config file";
            }
        } else {
            qCDebug(OkularUiDebug) << "Migrated old okular config";
        }
362
    }
363 364

    Okular::Settings::instance( configFilePath );
365

366 367
    numberOfParts++;
    if (numberOfParts == 1) {
Albert Astals Cid's avatar
Albert Astals Cid committed
368
        m_registerDbusName = QStringLiteral("/okular");
369
    } else {
Albert Astals Cid's avatar
Albert Astals Cid committed
370
        m_registerDbusName = QStringLiteral("/okular%1").arg(numberOfParts);
371
    }
Albert Astals Cid's avatar
Albert Astals Cid committed
372
    QDBusConnection::sessionBus().registerObject(m_registerDbusName, this, QDBusConnection::ExportScriptableSlots);
373

374 375
    // 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
376
    connect(this, &KParts::ReadOnlyPart::started, this, &Part::slotJobStarted);
377 378 379

    // 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
380
    connect(this, &KParts::ReadOnlyPart::canceled, this, &Part::loadCancelled);
381

382 383
    // create browser extension (for printing when embedded into browser)
    m_bExtension = new BrowserExtension(this);
384 385
    // create live connect extension (for integrating with browser scripting)
    new OkularLiveConnectExtension( this );
386

387
    GuiUtils::addIconLoader( iconLoader() );
388

389 390
    m_sidebar = new Sidebar( parentWidget );
    setWidget( m_sidebar );
Laurent Montel's avatar
Laurent Montel committed
391
    connect( m_sidebar, &Sidebar::urlsDropped, this, &Part::handleDroppedUrls );
Pino Toscano's avatar
Pino Toscano committed
392

393
    // build the document
394
    m_document = new Okular::Document(widget());
Laurent Montel's avatar
Laurent Montel committed
395 396 397 398 399 400 401
    connect( m_document, &Document::linkFind, this, &Part::slotFind );
    connect( m_document, &Document::linkGoToPage, this, &Part::slotGoToPage );
    connect( m_document, &Document::linkPresentation, this, &Part::slotShowPresentation );
    connect( m_document, &Document::linkEndPresentation, this, &Part::slotHidePresentation );
    connect( m_document, &Document::openUrl, this, &Part::openUrlFromDocument );
    connect( m_document->bookmarkManager(), &BookmarkManager::openUrl, this, &Part::openUrlFromBookmarks );
    connect( m_document, &Document::close, this, &Part::close );
402 403 404 405 406 407 408
    connect( m_document, &Document::undoHistoryCleanChanged, this,
            [this](bool clean)
            {
                setModified( !clean );
                setWindowTitleFromDocument();
            }
    );
409

Frederik Gladhorn's avatar
Frederik Gladhorn committed
410
    if ( parent && parent->metaObject()->indexOfSlot( QMetaObject::normalizedSignature( "slotQuit()" ).constData() ) != -1 )
Laurent Montel's avatar
Laurent Montel committed
411
        connect( m_document, SIGNAL(quit()), parent, SLOT(slotQuit()) );
412
    else
Laurent Montel's avatar
Laurent Montel committed
413
        connect( m_document, &Document::quit, this, &Part::cannotQuit );
414 415 416 417 418 419 420 421 422
    // 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 );

    // [left toolbox: Table of Contents] | []
423
    m_toc = new TOC( nullptr, m_document );
Laurent Montel's avatar
Laurent Montel committed
424
    connect( m_toc.data(), &TOC::hasTOC, this, &Part::enableTOC );
425
    connect( m_toc.data(), &TOC::rightClick, this, &Part::slotShowTOCMenu );
426
    m_sidebar->addItem( m_toc, QIcon::fromTheme(QApplication::isLeftToRight() ? QStringLiteral("format-justify-left") : QStringLiteral("format-justify-right")), i18n("Contents") );
427 428
    enableTOC( false );

429
    // [left toolbox: Layers] | []
430
    m_layers = new Layers( nullptr, m_document );
Laurent Montel's avatar
Laurent Montel committed
431
    connect( m_layers.data(), &Layers::hasLayers, this, &Part::enableLayers );
432
    m_sidebar->addItem( m_layers, QIcon::fromTheme( QStringLiteral("format-list-unordered") ), i18n( "Layers" ) );
433 434
    enableLayers( false );

435
    // [left toolbox: Thumbnails and Bookmarks] | []
436
    QWidget * thumbsBox = new ThumbnailsBox( nullptr );
Laurent Montel's avatar
Laurent Montel committed
437
    thumbsBox->layout()->setSpacing( 6 );
438
    m_searchWidget = new SearchWidget( thumbsBox, m_document );
Laurent Montel's avatar
Laurent Montel committed
439
    thumbsBox->layout()->addWidget(m_searchWidget);
440
    m_thumbnailList = new ThumbnailList( thumbsBox, m_document );
Laurent Montel's avatar
Laurent Montel committed
441
    thumbsBox->layout()->addWidget(m_thumbnailList);
442
    //	ThumbnailController * m_tc = new ThumbnailController( thumbsBox, m_thumbnailList );
Laurent Montel's avatar
Laurent Montel committed
443 444
    connect( m_thumbnailList.data(), &ThumbnailList::rightClick, this, &Part::slotShowMenu );
    m_sidebar->addItem( thumbsBox, QIcon::fromTheme( QStringLiteral("view-preview") ), i18n("Thumbnails") );
445 446

    m_sidebar->setCurrentItem( thumbsBox );
447 448

    // [left toolbox: Reviews] | []
449
    m_reviewsWidget = new Reviews( nullptr, m_document );
Laurent Montel's avatar
Laurent Montel committed
450
    m_sidebar->addItem( m_reviewsWidget, QIcon::fromTheme(QStringLiteral("draw-freehand")), i18n("Reviews") );
451
    m_sidebar->setItemEnabled( m_reviewsWidget, false );
452 453

    // [left toolbox: Bookmarks] | []
454
    m_bookmarkList = new BookmarkList( m_document, nullptr );
Laurent Montel's avatar
Laurent Montel committed
455
    m_sidebar->addItem( m_bookmarkList, QIcon::fromTheme(QStringLiteral("bookmarks")), i18n("Bookmarks") );
456
    m_sidebar->setItemEnabled( m_bookmarkList, false );
457

458 459 460 461 462 463
    // [left toolbox: Signature Panel] | []
    m_signaturePanel = new SignaturePanel( m_document, nullptr );
    connect( m_signaturePanel.data(), &SignaturePanel::documentHasSignatures, this, &Part::showSidebarSignaturesItem );
    m_sidebar->addItem( m_signaturePanel, QIcon::fromTheme(QStringLiteral("application-pkcs7-signature")), i18n("Signatures") );
    showSidebarSignaturesItem( false );

464
    // widgets: [../miniBarContainer] | []
465
#ifdef OKULAR_ENABLE_MINIBAR
Pino Toscano's avatar
Pino Toscano committed
466 467
    QWidget * miniBarContainer = new QWidget( 0 );
    m_sidebar->setBottomWidget( miniBarContainer );
468 469 470 471 472 473 474 475 476 477 478 479 480
    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 ) );
481
#endif
482 483

    // widgets: [] | [right 'pageView']
484
    QWidget * rightContainer = new QWidget( nullptr );
Pino Toscano's avatar
Pino Toscano committed
485
    m_sidebar->setMainWidget( rightContainer );
486 487 488 489 490
    QVBoxLayout * rightLayout = new QVBoxLayout( rightContainer );
    rightLayout->setMargin( 0 );
    rightLayout->setSpacing( 0 );
    //	KToolBar * rtb = new KToolBar( rightContainer, "mainToolBarSS" );
    //	rightLayout->addWidget( rtb );
491 492 493 494
    m_migrationMessage = new KMessageWidget( rightContainer );
    m_migrationMessage->setVisible( false );
    m_migrationMessage->setWordWrap( true );
    m_migrationMessage->setMessageType( KMessageWidget::Warning );
495
    m_migrationMessage->setText( i18n( "This document contains annotations or form data that were saved internally by a previous Okular version. Internal storage is <b>no longer supported</b>.<br/>Please save to a file in order to move them if you want to continue to edit the document." ) );
496
    rightLayout->addWidget( m_migrationMessage );
497 498 499 500 501
    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." ) );
Laurent Montel's avatar
Laurent Montel committed
502 503
    m_topMessage->setIcon( QIcon::fromTheme( QStringLiteral("mail-attachment") ) );
    connect( m_topMessage, &KMessageWidget::linkActivated, this, &Part::slotShowEmbeddedFiles );
504
    rightLayout->addWidget( m_topMessage );
505 506 507 508
    m_formsMessage = new KMessageWidget( rightContainer );
    m_formsMessage->setVisible( false );
    m_formsMessage->setWordWrap( true );
    m_formsMessage->setMessageType( KMessageWidget::Information );
509
    rightLayout->addWidget( m_formsMessage );
510 511 512 513 514 515 516
    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 );
Laurent Montel's avatar
Laurent Montel committed
517
    connect( m_infoTimer, &QTimer::timeout, m_infoMessage, &KMessageWidget::animatedHide );
518 519 520 521 522
    m_signatureMessage = new KMessageWidget( rightContainer );
    m_signatureMessage->setVisible( false );
    m_signatureMessage->setWordWrap( true );
    m_signatureMessage->setMessageType( KMessageWidget::Information );
    rightLayout->addWidget( m_signatureMessage );
523
    m_pageView = new PageView( rightContainer, m_document );
524
    QMetaObject::invokeMethod( m_pageView, "setFocus", Qt::QueuedConnection );      //usability setting
Pino Toscano's avatar
Pino Toscano committed
525
//    m_splitter->setFocusProxy(m_pageView);
Laurent Montel's avatar
Laurent Montel committed
526 527 528 529 530 531
    connect( m_pageView.data(), &PageView::rightClick, this, &Part::slotShowMenu );
    connect( m_document, &Document::error, this, &Part::errorMessage );
    connect( m_document, &Document::warning, this, &Part::warningMessage );
    connect( m_document, &Document::notice, this, &Part::noticeMessage );
    connect( m_document, &Document::sourceReferenceActivated, this, &Part::slotHandleActivatedSourceReference );
    connect( m_pageView.data(), &PageView::fitWindowToPage, this, &Part::fitWindowToPage );
532
    rightLayout->addWidget( m_pageView );
533
    m_layers->setPageView( m_pageView );
534
    m_signaturePanel->setPageView( m_pageView );
535 536
    m_findBar = new FindBar( m_document, rightContainer );
    rightLayout->addWidget( m_findBar );
537 538 539
    m_bottomBar = new QWidget( rightContainer );
    QHBoxLayout * bottomBarLayout = new QHBoxLayout( m_bottomBar );
    m_pageSizeLabel = new PageSizeLabel( m_bottomBar, m_document );
540 541 542
    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
543 544
    m_miniBarLogic = new MiniBarLogic( this, m_document );
    m_miniBar = new MiniBar( m_bottomBar, m_miniBarLogic );
545 546
    bottomBarLayout->addWidget( m_miniBar );
    bottomBarLayout->addWidget( m_pageSizeLabel );
547
    rightLayout->addWidget( m_bottomBar );
548

549
    m_pageNumberTool = new MiniBar( nullptr, m_miniBarLogic );
550

Laurent Montel's avatar
Laurent Montel committed
551
    connect( m_findBar, SIGNAL(forwardKeyPressEvent(QKeyEvent*)), m_pageView, SLOT(externalKeyPressEvent(QKeyEvent*)));
552
    connect( m_findBar, SIGNAL(onCloseButtonPressed()), m_pageView, SLOT(setFocus()));
Laurent Montel's avatar
Laurent Montel committed
553
    connect( m_miniBar, SIGNAL(forwardKeyPressEvent(QKeyEvent*)), m_pageView, SLOT(externalKeyPressEvent(QKeyEvent*)));
Laurent Montel's avatar
Laurent Montel committed
554
    connect( m_pageView.data(), &PageView::escPressed, m_findBar, &FindBar::resetSearch );
555
    connect( m_pageNumberTool, SIGNAL(forwardKeyPressEvent(QKeyEvent*)), m_pageView, SLOT(externalKeyPressEvent(QKeyEvent*)));
556

Laurent Montel's avatar
Laurent Montel committed
557 558
    connect( m_reviewsWidget.data(), &Reviews::openAnnotationWindow,
        m_pageView.data(), &PageView::openAnnotationWindow );
559 560 561 562 563

    // add document observers
    m_document->addObserver( this );
    m_document->addObserver( m_thumbnailList );
    m_document->addObserver( m_pageView );
564
    m_document->registerView( m_pageView );
565
    m_document->addObserver( m_toc );
Albert Astals Cid's avatar
Albert Astals Cid committed
566
    m_document->addObserver( m_miniBarLogic );
567
#ifdef OKULAR_ENABLE_MINIBAR
568
    m_document->addObserver( m_progressWidget );
569
#endif
570
    m_document->addObserver( m_reviewsWidget );
571
    m_document->addObserver( m_pageSizeLabel );
572
    m_document->addObserver( m_bookmarkList );
573
    m_document->addObserver( m_signaturePanel );
574

Laurent Montel's avatar
Laurent Montel committed
575 576
    connect( m_document->bookmarkManager(), &BookmarkManager::saved,
        this, &Part::slotRebuildBookmarkMenu );
577

578 579 580 581 582 583
    setupViewerActions();

    if ( m_embedMode != ViewerWidgetMode )
    {
        setupActions();
    }
584 585 586 587
    else
    {
        setViewerShortcuts();
    }
588 589 590

    // document watcher and reloader
    m_watcher = new KDirWatch( this );
Laurent Montel's avatar
Laurent Montel committed
591
    connect( m_watcher, &KDirWatch::dirty, this, &Part::slotFileDirty );
592
    connect( m_watcher, &KDirWatch::created, this, &Part::slotFileDirty );
593
    connect( m_watcher, &KDirWatch::deleted, this, &Part::slotFileDirty );
594 595
    m_dirtyHandler = new QTimer( this );
    m_dirtyHandler->setSingleShot( true );
Albert Astals Cid's avatar
Albert Astals Cid committed
596
    connect( m_dirtyHandler, &QTimer::timeout, this, [this] { slotAttemptReload(); } );
597 598 599

    slotNewConfig();

600
    // keep us informed when the user changes settings
Laurent Montel's avatar
Laurent Montel committed
601
    connect( Okular::Settings::self(), &KCoreConfigSkeleton::configChanged, this, &Part::slotNewConfig );
602

603 604 605
#ifdef HAVE_SPEECH
    // [SPEECH] check for TTS presence and usability
    Okular::Settings::setUseTTS( true );
606
    Okular::Settings::self()->save();
607
#endif
608 609 610 611 612

    rebuildBookmarkMenu( false );

    if ( m_embedMode == ViewerWidgetMode ) {
        // set the XML-UI resource file for the viewer mode
Laurent Montel's avatar
Laurent Montel committed
613
        setXMLFile(QStringLiteral("part-viewermode.rc"));
614 615 616 617
    }
    else
    {
        // set our main XML-UI resource file
Laurent Montel's avatar
Laurent Montel committed
618
        setXMLFile(QStringLiteral("part.rc"));
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
    }

    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();

638 639
    // also update the state of the actions in the page view
    m_pageView->updateActionState( false, false, false );
640 641 642 643 644 645 646 647 648 649 650

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

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

void Part::setupViewerActions()
{
651 652 653 654
    // ACTIONS
    KActionCollection * ac = actionCollection();

    // Page Traversal actions
Laurent Montel's avatar
Laurent Montel committed
655
    m_gotoPage = KStandardAction::gotoPage( this, SLOT(slotGoToPage()), ac );
656
    ac->setDefaultShortcuts(m_gotoPage, KStandardShortcut::gotoLine());
657
    // dirty way to activate gotopage when pressing miniBar's button
Laurent Montel's avatar
Laurent Montel committed
658 659
    connect( m_miniBar.data(), &MiniBar::gotoPage, m_gotoPage, &QAction::trigger );
    connect( m_pageNumberTool.data(), &MiniBar::gotoPage, m_gotoPage, &QAction::trigger );
660 661

    m_prevPage = KStandardAction::prior(this, SLOT(slotPreviousPage()), ac);
662 663
    m_prevPage->setIconText( i18nc( "Previous page", "Previous" ) );
    m_prevPage->setToolTip( i18n( "Go back to the Previous Page" ) );
664
    m_prevPage->setWhatsThis( i18n( "Moves to the previous page of the document" ) );
665
    ac->setDefaultShortcut(m_prevPage, QKeySequence());
666
    // dirty way to activate prev page when pressing miniBar's button
Laurent Montel's avatar
Laurent Montel committed
667 668
    connect( m_miniBar.data(), &MiniBar::prevPage, m_prevPage, &QAction::trigger );
    connect( m_pageNumberTool.data(), &MiniBar::prevPage, m_prevPage, &QAction::trigger );
669
#ifdef OKULAR_ENABLE_MINIBAR
Laurent Montel's avatar
Laurent Montel committed
670
    connect( m_progressWidget, SIGNAL(prevPage()), m_prevPage, SLOT(trigger()) );
671
#endif
672 673

    m_nextPage = KStandardAction::next(this, SLOT(slotNextPage()), ac );
674 675
    m_nextPage->setIconText( i18nc( "Next page", "Next" ) );
    m_nextPage->setToolTip( i18n( "Advance to the Next Page" ) );
676
    m_nextPage->setWhatsThis( i18n( "Moves to the next page of the document" ) );
677
    ac->setDefaultShortcut(m_nextPage, QKeySequence());
678
    // dirty way to activate next page when pressing miniBar's button
Laurent Montel's avatar
Laurent Montel committed
679 680
    connect( m_miniBar.data(), &MiniBar::nextPage, m_nextPage, &QAction::trigger );
    connect( m_pageNumberTool.data(), &MiniBar::nextPage, m_nextPage, &QAction::trigger );
681
#ifdef OKULAR_ENABLE_MINIBAR
Laurent Montel's avatar
Laurent Montel committed
682
    connect( m_progressWidget, SIGNAL(nextPage()), m_nextPage, SLOT(trigger()) );
683
#endif
684

Laurent Montel's avatar
Laurent Montel committed
685
    m_beginningOfDocument = KStandardAction::firstPage( this, SLOT(slotGotoFirst()), ac );
Laurent Montel's avatar
Laurent Montel committed
686
    ac->addAction(QStringLiteral("first_page"), m_beginningOfDocument);
687 688
    m_beginningOfDocument->setText(i18n( "Beginning of the document"));
    m_beginningOfDocument->setWhatsThis( i18n( "Moves to the beginning of the document" ) );
689

Laurent Montel's avatar
Laurent Montel committed
690
    m_endOfDocument = KStandardAction::lastPage( this, SLOT(slotGotoLast()), ac );
Laurent Montel's avatar
Laurent Montel committed
691
    ac->addAction(QStringLiteral("last_page"),m_endOfDocument);
692 693
    m_endOfDocument->setText(i18n( "End of the document"));
    m_endOfDocument->setWhatsThis( i18n( "Moves to the end of the document" ) );
694

Albert Astals Cid's avatar
Albert Astals Cid committed
695
    // we do not want back and next in history in the dummy mode
696 697
    m_historyBack = nullptr;
    m_historyNext = nullptr;
698

Laurent Montel's avatar
Laurent Montel committed
699
    m_addBookmark = KStandardAction::addBookmark( this, SLOT(slotAddBookmark()), ac );
700
    m_addBookmarkText = m_addBookmark->text();
701
    m_addBookmarkIcon = m_addBookmark->icon();
702

Laurent Montel's avatar
Laurent Montel committed
703
    m_renameBookmark = ac->addAction(QStringLiteral("rename_bookmark"));
704
    m_renameBookmark->setText(i18n( "Rename Bookmark" ));
Laurent Montel's avatar
Laurent Montel committed
705
    m_renameBookmark->setIcon(QIcon::fromTheme( QStringLiteral("edit-rename") ));
706
    m_renameBookmark->setWhatsThis( i18n( "Rename the current bookmark" ) );
Laurent Montel's avatar
Laurent Montel committed
707
    connect( m_renameBookmark, &QAction::triggered, this, &Part::slotRenameCurrentViewportBookmark );
708

Laurent Montel's avatar
Laurent Montel committed
709
    m_prevBookmark = ac->addAction(QStringLiteral("previous_bookmark"));
710
    m_prevBookmark->setText(i18n( "Previous Bookmark" ));
Laurent Montel's avatar
Laurent Montel committed
711
    m_prevBookmark->setIcon(QIcon::fromTheme( QStringLiteral("go-up-search") ));
712
    m_prevBookmark->setWhatsThis( i18n( "Go to the previous bookmark" ) );
Laurent Montel's avatar
Laurent Montel committed
713
    connect( m_prevBookmark, &QAction::triggered, this, &Part::slotPreviousBookmark );
714

Laurent Montel's avatar
Laurent Montel committed
715
    m_nextBookmark = ac->addAction(QStringLiteral("next_bookmark"));
716
    m_nextBookmark->setText(i18n( "Next Bookmark" ));
Laurent Montel's avatar
Laurent Montel committed
717
    m_nextBookmark->setIcon(QIcon::fromTheme( QStringLiteral("go-down-search") ));
718
    m_nextBookmark->setWhatsThis( i18n( "Go to the next bookmark" ) );
Laurent Montel's avatar
Laurent Montel committed
719
    connect( m_nextBookmark, &QAction::triggered, this, &Part::slotNextBookmark );
720

721
    m_copy = nullptr;
722

723
    m_selectAll = nullptr;
724
    m_selectCurrentPage = nullptr;
725

726
    // Find and other actions
Laurent Montel's avatar
Laurent Montel committed
727
    m_find = KStandardAction::find( this, SLOT(slotShowFindBar()), ac );
728 729
    QList<QKeySequence> s = m_find->shortcuts();
    s.append( QKeySequence( Qt::Key_Slash ) );
730
    ac->setDefaultShortcuts(m_find, s);
731 732
    m_find->setEnabled( false );

Laurent Montel's avatar
Laurent Montel committed
733
    m_findNext = KStandardAction::findNext( this, SLOT(slotFindNext()), ac);
734 735
    m_findNext->setEnabled( false );

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

739
    m_save = nullptr;
740
    m_saveAs = nullptr;
741
    m_openContainingFolder = nullptr;
Pino Toscano's avatar
Pino Toscano committed
742

Laurent Montel's avatar
Laurent Montel committed
743
    QAction * prefs = KStandardAction::preferences( this, SLOT(slotPreferences()), ac);
744
    if ( m_embedMode == NativeShellMode )
745
    {
746
        prefs->setText( i18n( "Configure Okular..." ) );
747 748 749
    }
    else
    {
Pino Toscano's avatar
Pino Toscano committed
750
        // TODO: improve this message
751 752 753
        prefs->setText( i18n( "Configure Viewer..." ) );
    }

Vishesh Handa's avatar
Vishesh Handa committed
754
    QAction * genPrefs = new QAction( ac );
Laurent Montel's avatar
Laurent Montel committed
755
    ac->addAction(QStringLiteral("options_configure_generators"), genPrefs);
756 757 758 759
    if ( m_embedMode == ViewerWidgetMode )
    {
        genPrefs->setText( i18n( "Configure Viewer Backends..." ) );
    }
Michel Ludwig's avatar
Michel Ludwig committed
760 761
    else
    {
762 763
        genPrefs->setText( i18n( "Configure Backends..." ) );
    }
Laurent Montel's avatar
Laurent Montel committed
764
    genPrefs->setIcon( QIcon::fromTheme( QStringLiteral("configure") ) );
765
    genPrefs->setEnabled( m_document->configurableGenerators() > 0 );
Laurent Montel's avatar
Laurent Montel committed
766
    connect( genPrefs, &QAction::triggered, this, &Part::slotGeneratorPreferences );
767

Laurent Montel's avatar
Laurent Montel committed
768
    m_printPreview = KStandardAction::printPreview( this, SLOT(slotPrintPreview()), ac );
769 770
    m_printPreview->setEnabled( false );

771 772
    m_showLeftPanel = nullptr;
    m_showBottomBar = nullptr;
773
    m_showSignaturePanel = nullptr;
774

Laurent Montel's avatar
Laurent Montel committed
775
    m_showProperties = ac->addAction(QStringLiteral("properties"));
776
    m_showProperties->setText(i18n("&Properties"));
Laurent Montel's avatar
Laurent Montel committed
777 778
    m_showProperties->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
    connect(m_showProperties, &QAction::triggered, this, &Part::slotShowProperties);
779 780
    m_showProperties->setEnabled( false );

781 782
    m_showEmbeddedFiles = nullptr;
    m_showPresentation = nullptr;
783

784 785 786 787
    m_exportAs = nullptr;
    m_exportAsMenu = nullptr;
    m_exportAsText = nullptr;
    m_exportAsDocArchive = nullptr;
Kevin Ottens's avatar
Kevin Ottens committed
788 789 790 791 792 793

#if PURPOSE_FOUND
    m_share = nullptr;
    m_shareMenu = nullptr;
#endif

794
    m_presentationDrawingActions = nullptr;
795

Laurent Montel's avatar
Laurent Montel committed
796
    m_aboutBackend = ac->addAction(QStringLiteral("help_about_backend"));
797 798
    m_aboutBackend->setText(i18n("About Backend"));
    m_aboutBackend->setEnabled( false );
Laurent Montel's avatar
Laurent Montel committed
799
    connect(m_aboutBackend, &QAction::triggered, this, &Part::slotAboutBackend);
800

Laurent Montel's avatar
Laurent Montel committed
801
    QAction *reload = ac->add<QAction>( QStringLiteral("file_reload") );
802
    reload->setText( i18n( "Reloa&d" ) );
Laurent Montel's avatar
Laurent Montel committed
803
    reload->setIcon( QIcon::fromTheme( QStringLiteral("view-refresh") ) );
804
    reload->setWhatsThis( i18n( "Reload the current document from disk." ) );
Laurent Montel's avatar
Laurent Montel committed
805
    connect( reload, &QAction::triggered, this, &Part::slotReload );
806
    ac->setDefaultShortcuts(reload, KStandardShortcut::reload());
807 808
    m_reload = reload;

Laurent Montel's avatar
Laurent Montel committed
809
    m_closeFindBar = ac->addAction( QStringLiteral("close_find_bar"), this, SLOT(slotHideFindBar()) );
Jonathan Doman's avatar
Jonathan Doman committed
810
    m_closeFindBar->setText( i18n("Close &Find Bar") );
811
    ac->setDefaultShortcut(m_closeFindBar, QKeySequence(Qt::Key_Escape));
Jonathan Doman's avatar
Jonathan Doman committed
812
    m_closeFindBar->setEnabled( false );
813

Vishesh Handa's avatar
Vishesh Handa committed
814 815
    QWidgetAction *pageno = new QWidgetAction( ac );
    pageno->setText( i18n( "Page Number" ) );
816
    pageno->setDefaultWidget( m_pageNumberTool );
Laurent Montel's avatar
Laurent Montel committed
817
    ac->addAction( QStringLiteral("page_number"), pageno );
818 819
}

820
void Part::setViewerShortcuts()
821 822 823
{
    KActionCollection * ac = actionCollection();

824 825
    ac->setDefaultShortcut(m_gotoPage, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_G));
    ac->setDefaultShortcut(m_find, QKeySequence());
826

827 828
    ac->setDefaultShortcut(m_findNext, QKeySequence());
    ac->setDefaultShortcut(m_findPrev, QKeySequence());
829

830
    ac->setDefaultShortcut(m_addBookmark, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_B));
831

832 833
    ac->setDefaultShortcut(m_beginningOfDocument, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Home));
    ac->setDefaultShortcut(m_endOfDocument, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_End));
834

Laurent Montel's avatar
Laurent Montel committed
835
    QAction *action = static_cast<QAction*>( ac->action( QStringLiteral("file_reload") ) );
836 837 838
    if (action) {
        ac->setDefaultShortcut(action, QKeySequence(Qt::ALT + Qt::Key_F5));
    }
839 840 841 842 843
}

void Part::setupActions()
{
    KActionCollection * ac = actionCollection();
844 845 846 847 848

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

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

849 850 851 852 853 854
    // Setup select all action for the current page
    m_selectCurrentPage = ac->addAction(QStringLiteral("edit_select_all_current_page"));
    m_selectCurrentPage->setText(i18n("Select All Text on Current Page"));
    connect( m_selectCurrentPage, &QAction::triggered, m_pageView, &PageView::slotSelectPage );
    m_selectCurrentPage->setEnabled( false );

Albert Astals Cid's avatar
Albert Astals Cid committed
855
    m_save = KStandardAction::save( this, [this] { saveFile(); }, ac );
Fabio D'Urso's avatar
Fabio D'Urso committed
856
    m_save->setEnabled( false );
857 858 859

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

Laurent Montel's avatar
Laurent Montel committed
862
    m_showLeftPanel = ac->add<KToggleAction>(QStringLiteral("show_leftpanel"));
863
    m_showLeftPanel->setText(i18n( "Show &Navigation Panel"));
Laurent Montel's avatar
Laurent Montel committed
864 865
    m_showLeftPanel->setIcon(QIcon::fromTheme( QStringLiteral("view-sidetree") ));
    connect( m_showLeftPanel, &QAction::toggled, this, &Part::slotShowLeftPanel );
866
    ac->setDefaultShortcut(m_showLeftPanel, QKeySequence(Qt::Key_F7));
867 868 869
    m_showLeftPanel->setChecked( Okular::Settings::showLeftPanel() );
    slotShowLeftPanel();

Laurent Montel's avatar
Laurent Montel committed
870
    m_showBottomBar = ac->add<KToggleAction>(QStringLiteral("show_bottombar"));
871
    m_showBottomBar->setText(i18n( "Show &Page Bar"));
Laurent Montel's avatar
Laurent Montel committed
872
    connect( m_showBottomBar, &QAction::toggled, this, &Part::slotShowBottomBar );
873 874 875
    m_showBottomBar->setChecked( Okular::Settings::showBottomBar() );
    slotShowBottomBar();

876 877 878 879 880 881 882 883
    m_showSignaturePanel = ac->add<QAction>(QStringLiteral("show_signatures"));
    m_showSignaturePanel->setText(i18n("Show &Signatures Panel"));
    connect( m_showSignaturePanel, &QAction::triggered, this, [this] {
        if ( m_sidebar->currentItem() != m_signaturePanel) {
            m_sidebar->setCurrentItem( m_signaturePanel );
        }
    });

Laurent Montel's avatar
Laurent Montel committed
884
    m_showEmbeddedFiles = ac->addAction(QStringLiteral("embedded_files"));
885
    m_showEmbeddedFiles->setText(i18n("&Embedded Files"));
Laurent Montel's avatar
Laurent Montel committed
886 887
    m_showEmbeddedFiles->setIcon( QIcon::fromTheme( QStringLiteral("mail-attachment") ) );
    connect(m_showEmbeddedFiles, &QAction::triggered, this, &Part::slotShowEmbeddedFiles);
888 889
    m_showEmbeddedFiles->setEnabled( false );

Laurent Montel's avatar
Laurent Montel committed
890
    m_exportAs = ac->addAction(QStringLiteral("file_export_as"));
891
    m_exportAs->setText(i18n("E&xport As"));
Laurent Montel's avatar
Laurent Montel committed
892
    m_exportAs->setIcon( QIcon::fromTheme( QStringLiteral("document-export") ) );
893
    m_exportAsMenu = new QMenu();
Laurent Montel's avatar
Laurent Montel committed
894
    connect(m_exportAsMenu, &QMenu::triggered, this, &Part::slotExportAs);
895 896 897
    m_exportAs->setMenu( m_exportAsMenu );
    m_exportAsText = actionForExportFormat( Okular::ExportFormat::standardFormat( Okular::ExportFormat::PlainText ), m_exportAsMenu );
    m_exportAsMenu->addAction( m_exportAsText );
898
    m_exportAs->setEnabled( false );
899 900
    m_exportAsText->setEnabled( false );

Kevin Ottens's avatar
Kevin Ottens committed
901 902 903 904 905 906 907 908 909 910
#if PURPOSE_FOUND
    m_share = ac->addAction( QStringLiteral("file_share") );
    m_share->setText( i18n("S&hare") );
    m_share->setIcon( QIcon::fromTheme( QStringLiteral("document-share") ) );
    m_share->setEnabled( false );
    m_shareMenu = new Purpose::Menu();
    connect(m_shareMenu, &Purpose::Menu::finished, this, &Part::slotShareActionFinished);
    m_share->setMenu( m_shareMenu );
#endif