pageview.cpp 210 KB
Newer Older
1
/***************************************************************************
2
 *   Copyright (C) 2004-2005 by Enrico Ros <eros.kde@email.it>             *
Albert Astals Cid's avatar
Albert Astals Cid committed
3
 *   Copyright (C) 2004-2006 by Albert Astals Cid <aacid@kde.org>          *
4
 *                                                                         *
5
 *   With portions of code from kpdf/kpdf_pagewidget.cc by:                *
6 7 8 9 10 11
 *     Copyright (C) 2002 by Wilco Greven <greven@kde.org>                 *
 *     Copyright (C) 2003 by Christophe Devriese                           *
 *                           <Christophe.Devriese@student.kuleuven.ac.be>  *
 *     Copyright (C) 2003 by Laurent Montel <montel@kde.org>               *
 *     Copyright (C) 2003 by Dirk Mueller <mueller@kde.org>                *
 *     Copyright (C) 2004 by James Ots <kde@jamesots.com>                  *
Jiri Baum's avatar
Jiri Baum committed
12
 *     Copyright (C) 2011 by Jiri Baum - NICTA <jiri@baum.com.au>          *
13 14 15 16 17 18 19
 *                                                                         *
 *   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
20 21
#include "pageview.h"

22
// qt/kde includes
23
#include <QtCore/qloggingcategory.h>
24
#include <qcursor.h>
25
#include <qevent.h>
26
#include <qimage.h>
27 28
#include <qpainter.h>
#include <qtimer.h>
29
#include <qset.h>
30
#include <qscrollbar.h>
31
#include <qtooltip.h>
Enrico Ros's avatar
Enrico Ros committed
32 33
#include <qapplication.h>
#include <qclipboard.h>
Vishesh Handa's avatar
Vishesh Handa committed
34
#include <qmenu.h>
35
#include <QInputDialog>
36
#include <qdesktopwidget.h>
37
#include <QDesktopServices>
Laurent Montel's avatar
Laurent Montel committed
38
#include <QMimeDatabase>
Olivier Churlaud's avatar
Olivier Churlaud committed
39
#include <QMimeData>
40
#include <QGestureEvent>
41

Laurent Montel's avatar
Laurent Montel committed
42
#include <qaction.h>
43
#include <kactionmenu.h>
Laurent Montel's avatar
Laurent Montel committed
44
#include <kstandardaction.h>
45
#include <kactioncollection.h>
Lukáš Tinkl's avatar
Lukáš Tinkl committed
46
#include <KLocalizedString>
Albert Astals Cid's avatar
compile  
Albert Astals Cid committed
47 48
#include <kselectaction.h>
#include <ktoggleaction.h>
49
#include <QtCore/QDebug>
50
#include <kmessagebox.h>
Laurent Montel's avatar
Laurent Montel committed
51
#include <QIcon>
52 53 54
#include <kurifilter.h>
#include <kstringhandler.h>
#include <ktoolinvocation.h>
55
#include <krun.h>
Albert Astals Cid's avatar
compile  
Albert Astals Cid committed
56

57
// system includes
58
#include <math.h>
59
#include <stdlib.h>
60

61
// local includes
62
#include "debug_ui.h"
63
#include "formwidgets.h"
64
#include "pageviewutils.h"
65
#include "pagepainter.h"
66
#include "core/annotations.h"
67
#include "annotwindow.h"
Pino Toscano's avatar
Pino Toscano committed
68
#include "guiutils.h"
69
#include "annotationpopup.h"
70
#include "pageviewannotator.h"
71
#include "pageviewmouseannotation.h"
72
#include "priorities.h"
73
#include "toolaction.h"
74
#include "okmenutitle.h"
75 76 77
#ifdef HAVE_SPEECH
#include "tts.h"
#endif
78
#include "videowidget.h"
Pino Toscano's avatar
Pino Toscano committed
79
#include "core/action.h"
80
#include "core/area.h"
81
#include "core/document_p.h"
82
#include "core/form.h"
83
#include "core/page.h"
84
#include "core/misc.h"
85
#include "core/generator.h"
86
#include "core/movie.h"
Jaydeep Solanki's avatar
Jaydeep Solanki committed
87
#include "core/audioplayer.h"
88
#include "core/sourcereference.h"
89
#include "core/tile.h"
90
#include "settings.h"
91
#include "settings_core.h"
92
#include "url_utils.h"
Michal Humpula's avatar
Michal Humpula committed
93
#include "magnifierview.h"
94

95
static const int pageflags = PagePainter::Accessibility | PagePainter::EnhanceLinks |
96
                       PagePainter::EnhanceImages | PagePainter::Highlights |
97
                       PagePainter::TextSelection | PagePainter::Annotations;
98

Tingnan Zhang's avatar
Tingnan Zhang committed
99 100
static const float kZoomValues[] = { 0.12, 0.25, 0.33, 0.50, 0.66, 0.75, 1.00, 1.25, 1.50, 2.00, 4.00, 8.00, 16.00 };

101 102 103 104 105
static inline double normClamp( double value, double def )
{
    return ( value < 0.0 || value > 1.0 ) ? def : value;
}

Jiri Baum's avatar
Jiri Baum committed
106 107 108 109 110
struct TableSelectionPart {
    PageViewItem * item;
    Okular::NormalizedRect rectInItem;
    Okular::NormalizedRect rectInSelection;

111
    TableSelectionPart(PageViewItem * item_p, const Okular::NormalizedRect &rectInItem_p, const Okular::NormalizedRect &rectInSelection_p);
Jiri Baum's avatar
Jiri Baum committed
112 113
};

114
TableSelectionPart::TableSelectionPart(  PageViewItem * item_p, const Okular::NormalizedRect &rectInItem_p, const Okular::NormalizedRect &rectInSelection_p)
Jiri Baum's avatar
Jiri Baum committed
115 116 117 118
    : item ( item_p ), rectInItem (rectInItem_p), rectInSelection (rectInSelection_p)
{
}

119 120 121 122
// structure used internally by PageView for data storage
class PageViewPrivate
{
public:
123 124 125
    PageViewPrivate( PageView *qq );

    FormWidgetsController* formWidgetsController();
126 127 128
#ifdef HAVE_SPEECH
    OkularTTS* tts();
#endif
129
    QString selectedText() const;
130

131
    // the document, pageviewItems and the 'visible cache'
132
    PageView *q;
133
    Okular::Document * document;
134 135
    QVector< PageViewItem * > items;
    QLinkedList< PageViewItem * > visibleItems;
Michal Humpula's avatar
Michal Humpula committed
136
    MagnifierView *magnifierView;
137

138
    // view layout (columns and continuous in Settings), zoom and mouse
139 140 141
    PageView::ZoomMode zoomMode;
    float zoomFactor;
    QPoint mouseGrabPos;
142
    QPoint mousePressPos;
143
    QPoint mouseSelectPos;
144
    int mouseMidLastY;
145
    bool mouseSelecting;
146
    QRect mouseSelectionRect;
147
    QColor mouseSelectionColor;
148
    bool mouseTextSelecting;
149
    QSet< int > pagesWithTextSelection;
150
    bool mouseOnRect;
151
    int mouseMode;
152
    MouseAnnotation * mouseAnnotation;
153

Jiri Baum's avatar
Jiri Baum committed
154 155 156 157
    // table selection
    QList<double> tableSelectionCols;
    QList<double> tableSelectionRows;
    QList<TableSelectionPart> tableSelectionParts;
158
    bool tableDividersGuessed;
Jiri Baum's avatar
Jiri Baum committed
159

Enrico Ros's avatar
Enrico Ros committed
160 161 162 163
    // viewport move
    bool viewportMoveActive;
    QTime viewportMoveTime;
    QPoint viewportMoveDest;
164 165 166
    int lastSourceLocationViewportPageNumber;
    double lastSourceLocationViewportNormalizedX;
    double lastSourceLocationViewportNormalizedY;
Enrico Ros's avatar
Enrico Ros committed
167
    QTimer * viewportMoveTimer;
168
    int controlWheelAccumulatedDelta;
Enrico Ros's avatar
Enrico Ros committed
169
    // auto scroll
170
    int scrollIncrement;
Enrico Ros's avatar
Enrico Ros committed
171
    QTimer * autoScrollTimer;
172
    // annotations
173
    PageViewAnnotator * annotator;
174
    //text annotation dialogs list
175
    QHash< Okular::Annotation *, AnnotWindow * > m_annowindows;
Enrico Ros's avatar
Enrico Ros committed
176
    // other stuff
177
    QTimer * delayResizeEventTimer;
178
    bool dirtyLayout;
Enrico Ros's avatar
Enrico Ros committed
179
    bool blockViewport;                 // prevents changes to viewport
180 181
    bool blockPixmapsRequest;           // prevent pixmap requests
    PageViewMessage * messageWindow;    // in pageviewutils.h
182
    bool m_formsVisible;
183
    FormWidgetsController *formsWidgetController;
184 185 186
#ifdef HAVE_SPEECH
    OkularTTS * m_tts;
#endif
187
    QTimer * refreshTimer;
188
    QSet<int> refreshPages;
189

Jake Linder's avatar
Jake Linder committed
190 191 192
    // bbox state for Trim to Selection mode
    Okular::NormalizedRect trimBoundingBox;

193
    // infinite resizing loop prevention
194
    bool verticalScrollBarVisible;
Thomas Fischer's avatar
Thomas Fischer committed
195
    bool horizontalScrollBarVisible;
196

197 198 199 200
    // drag scroll
    QPoint dragScrollVector;
    QTimer dragScrollTimer;

201 202 203
    // left click depress
    QTimer leftClickTimer;

204
    // actions
Vishesh Handa's avatar
Vishesh Handa committed
205 206 207
    QAction * aRotateClockwise;
    QAction * aRotateCounterClockwise;
    QAction * aRotateOriginal;
208
    KSelectAction * aPageSizes;
Jake Linder's avatar
Jake Linder committed
209
    KActionMenu * aTrimMode;
210
    KToggleAction * aTrimMargins;
Vishesh Handa's avatar
Vishesh Handa committed
211 212 213 214 215
    QAction * aMouseNormal;
    QAction * aMouseSelect;
    QAction * aMouseTextSelect;
    QAction * aMouseTableSelect;
    QAction * aMouseMagnifier;
Jake Linder's avatar
Jake Linder committed
216
    KToggleAction * aTrimToSelection;
217
    KToggleAction * aToggleAnnotator;
218
    KSelectAction * aZoom;
219 220
    QAction * aZoomIn;
    QAction * aZoomOut;
221 222
    KToggleAction * aZoomFitWidth;
    KToggleAction * aZoomFitPage;
Thomas Fischer's avatar
Thomas Fischer committed
223
    KToggleAction * aZoomAutoFit;
224
    KActionMenu * aViewMode;
225
    KToggleAction * aViewContinuous;
Laurent Montel's avatar
Laurent Montel committed
226
    QAction * aPrevAction;
Vishesh Handa's avatar
Vishesh Handa committed
227 228 229 230
    QAction * aToggleForms;
    QAction * aSpeakDoc;
    QAction * aSpeakPage;
    QAction * aSpeakStop;
231
    KActionCollection * actionCollection;
232
    QActionGroup * mouseModeActionGroup;
233
    QAction * aFitWindowToPage;
234

235
    int setting_viewCols;
236
    bool rtl_Mode;
237 238
    // Keep track of whether tablet pen is currently pressed down
    bool penDown;
239 240
};

241 242
PageViewPrivate::PageViewPrivate( PageView *qq )
    : q( qq )
243
#ifdef HAVE_SPEECH
244
    , m_tts( nullptr )
245
#endif
246 247 248 249 250 251 252
{
}

FormWidgetsController* PageViewPrivate::formWidgetsController()
{
    if ( !formsWidgetController )
    {
Jon Mease's avatar
Jon Mease committed
253 254 255 256 257
        formsWidgetController = new FormWidgetsController( document );
        QObject::connect( formsWidgetController, SIGNAL( changed( int ) ),
                          q, SLOT( slotFormChanged( int ) ) );
        QObject::connect( formsWidgetController, SIGNAL( action( Okular::Action* ) ),
                          q, SLOT( slotAction( Okular::Action* ) ) );
258 259 260 261 262
    }

    return formsWidgetController;
}

263 264 265 266 267 268 269 270
#ifdef HAVE_SPEECH
OkularTTS* PageViewPrivate::tts()
{
    if ( !m_tts )
    {
        m_tts = new OkularTTS( q );
        if ( aSpeakStop )
        {
Laurent Montel's avatar
Laurent Montel committed
271 272
            QObject::connect( m_tts, &OkularTTS::isSpeaking,
                              aSpeakStop, &QAction::setEnabled );
273 274
        }
    }
275

276 277 278
    return m_tts;
}
#endif
279

280

281 282 283 284
/* PageView. What's in this file? -> quick overview.
 * Code weight (in rows) and meaning:
 *  160 - constructor and creating actions plus their connected slots (empty stuff)
 *  70  - DocumentObserver inherited methodes (important)
285
 *  550 - events: mouse, keyboard, drag
286
 *  170 - slotRelayoutPages: set contents of the scrollview on continuous/single modes
287
 *  100 - zoom: zooming pages in different ways, keeping update the toolbar actions, etc..
288
 *  other misc functions: only slotRequestVisiblePixmaps and pickItemOnPoint noticeable,
289
 * and many insignificant stuff like this comment :-)
290
 */
291
PageView::PageView( QWidget *parent, Okular::Document *document )
292
    : QAbstractScrollArea( parent )
Laurent Montel's avatar
Laurent Montel committed
293
    , Okular::View( QLatin1String( "PageView" ) )
294 295
{
    // create and initialize private storage structure
296
    d = new PageViewPrivate( this );
297
    d->document = document;
298 299 300 301
    d->aRotateClockwise = nullptr;
    d->aRotateCounterClockwise = nullptr;
    d->aRotateOriginal = nullptr;
    d->aViewMode = nullptr;
302
    d->zoomMode = PageView::ZoomFitWidth;
303
    d->zoomFactor = 1.0;
304
    d->mouseSelecting = false;
305
    d->mouseTextSelecting = false;
306
    d->mouseOnRect = false;
307
    d->mouseMode = Okular::Settings::mouseMode();
308
    d->mouseAnnotation = new MouseAnnotation( this, document );
309
    d->tableDividersGuessed = false;
Enrico Ros's avatar
Enrico Ros committed
310
    d->viewportMoveActive = false;
311 312 313
    d->lastSourceLocationViewportPageNumber = -1;
    d->lastSourceLocationViewportNormalizedX = 0.0;
    d->lastSourceLocationViewportNormalizedY = 0.0;
314
    d->viewportMoveTimer = nullptr;
315
    d->controlWheelAccumulatedDelta = 0;
316
    d->scrollIncrement = 0;
317 318
    d->autoScrollTimer = nullptr;
    d->annotator = nullptr;
319
    d->dirtyLayout = false;
320
    d->blockViewport = false;
321
    d->blockPixmapsRequest = false;
322
    d->messageWindow = new PageViewMessage(this);
323
    d->m_formsVisible = false;
324
    d->formsWidgetController = nullptr;
325
#ifdef HAVE_SPEECH
326
    d->m_tts = nullptr;
327
#endif
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
    d->refreshTimer = nullptr;
    d->aRotateClockwise = nullptr;
    d->aRotateCounterClockwise = nullptr;
    d->aRotateOriginal = nullptr;
    d->aPageSizes = nullptr;
    d->aTrimMode = nullptr;
    d->aTrimMargins = nullptr;
    d->aTrimToSelection = nullptr;
    d->aMouseNormal = nullptr;
    d->aMouseSelect = nullptr;
    d->aMouseTextSelect = nullptr;
    d->aToggleAnnotator = nullptr;
    d->aZoomFitWidth = nullptr;
    d->aZoomFitPage = nullptr;
    d->aZoomAutoFit = nullptr;
    d->aViewMode = nullptr;
    d->aViewContinuous = nullptr;
    d->aPrevAction = nullptr;
    d->aToggleForms = nullptr;
    d->aSpeakDoc = nullptr;
    d->aSpeakPage = nullptr;
    d->aSpeakStop = nullptr;
    d->actionCollection = nullptr;
    d->aPageSizes=nullptr;
352
    d->setting_viewCols = Okular::Settings::viewColumns();
353
    d->rtl_Mode = Okular::Settings::rtlReadingDirection();
354
    d->mouseModeActionGroup = nullptr;
355
    d->penDown = false;
356 357
    d->aMouseMagnifier = nullptr;
    d->aFitWindowToPage = nullptr;
Jake Linder's avatar
Jake Linder committed
358
    d->trimBoundingBox = Okular::NormalizedRect(); // Null box
359

Albert Astals Cid's avatar
Albert Astals Cid committed
360
    switch( Okular::Settings::zoomMode() )
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
    {
        case 0:
        {
            d->zoomFactor = 1;
            d->zoomMode = PageView::ZoomFixed;
            break;
        }
        case 1:
        {
            d->zoomMode = PageView::ZoomFitWidth;
            break;
        }
        case 2:
        {
            d->zoomMode = PageView::ZoomFitPage;
            break;
        }
Thomas Fischer's avatar
Thomas Fischer committed
378 379 380 381 382
        case 3:
        {
            d->zoomMode = PageView::ZoomFitAuto;
            break;
        }
383 384
    }

385 386
    d->delayResizeEventTimer = new QTimer( this );
    d->delayResizeEventTimer->setSingleShot( true );
Laurent Montel's avatar
Laurent Montel committed
387
    connect( d->delayResizeEventTimer, &QTimer::timeout, this, &PageView::delayedResizeEvent );
388

389 390
    setFrameStyle(QFrame::NoFrame);

Pino Toscano's avatar
Pino Toscano committed
391 392
    setAttribute( Qt::WA_StaticContents );

Laurent Montel's avatar
Laurent Montel committed
393
    setObjectName( QStringLiteral( "okular::pageView" ) );
Pino Toscano's avatar
Pino Toscano committed
394

395
    // viewport setup: setup focus, and track mouse
396
    viewport()->setFocusProxy( this );
397
    viewport()->setFocusPolicy( Qt::StrongFocus );
398 399 400
    viewport()->setAttribute( Qt::WA_OpaquePaintEvent );
    viewport()->setAttribute( Qt::WA_NoSystemBackground );
    viewport()->setMouseTracking( true );
401
    viewport()->setAutoFillBackground( false );
402
    // the apparently "magic" value of 20 is the same used internally in QScrollArea
403
    verticalScrollBar()->setCursor( Qt::ArrowCursor );
404
    verticalScrollBar()->setSingleStep( 20 );
405
    horizontalScrollBar()->setCursor( Qt::ArrowCursor );
406
    horizontalScrollBar()->setSingleStep( 20 );
407 408

    // conntect the padding of the viewport to pixmaps requests
Laurent Montel's avatar
Laurent Montel committed
409 410 411
    connect(horizontalScrollBar(), &QAbstractSlider::valueChanged, this, &PageView::slotRequestVisiblePixmaps);
    connect(verticalScrollBar(), &QAbstractSlider::valueChanged, this, &PageView::slotRequestVisiblePixmaps);
    connect( &d->dragScrollTimer, &QTimer::timeout, this, &PageView::slotDragScroll );
412

413
    d->leftClickTimer.setSingleShot( true );
Laurent Montel's avatar
Laurent Montel committed
414
    connect( &d->leftClickTimer, &QTimer::timeout, this, &PageView::slotShowSizeAllCursor );
415

416
    // set a corner button to resize the view to the page size
417 418 419 420
//    QPushButton * resizeButton = new QPushButton( viewport() );
//    resizeButton->setPixmap( SmallIcon("crop") );
//    setCornerWidget( resizeButton );
//    resizeButton->setEnabled( false );
421
    // connect(...);
Tobias Koenig's avatar
Tobias Koenig committed
422
    setAttribute( Qt::WA_InputMethodEnabled, true );
423

424
    // Grab pinch gestures to zoom and rotate the view
425 426
    grabGesture(Qt::PinchGesture);

Michal Humpula's avatar
Michal Humpula committed
427 428
    d->magnifierView = new MagnifierView(document, this);
    d->magnifierView->hide();
429
    d->magnifierView->setGeometry(0, 0, 351, 201); // TODO: more dynamic?
Michal Humpula's avatar
Michal Humpula committed
430

Laurent Montel's avatar
Laurent Montel committed
431 432
    connect(document, &Okular::Document::processMovieAction, this, &PageView::slotProcessMovieAction);
    connect(document, &Okular::Document::processRenditionAction, this, &PageView::slotProcessRenditionAction);
433

434
    // schedule the welcome message
435
    QMetaObject::invokeMethod(this, "slotShowWelcome", Qt::QueuedConnection);
436 437 438 439
}

PageView::~PageView()
{
440 441 442 443
#ifdef HAVE_SPEECH
    if ( d->m_tts )
        d->m_tts->stopAllSpeechs();
#endif
Pino Toscano's avatar
Pino Toscano committed
444

445 446
    delete d->mouseAnnotation;

447
    // delete the local storage structure
448

449 450 451 452 453 454
    // We need to assign it to a different list otherwise slotAnnotationWindowDestroyed
    // will bite us and clear d->m_annowindows
    QHash< Okular::Annotation *, AnnotWindow * > annowindows = d->m_annowindows;
    d->m_annowindows.clear();
    qDeleteAll( annowindows );

455
    // delete all widgets
Laurent Montel's avatar
Laurent Montel committed
456
    QVector< PageViewItem * >::const_iterator dIt = d->items.constBegin(), dEnd = d->items.constEnd();
457 458
    for ( ; dIt != dEnd; ++dIt )
        delete *dIt;
459
    delete d->formsWidgetController;
Albert Astals Cid's avatar
Albert Astals Cid committed
460
    d->document->removeObserver( this );
461 462 463
    delete d;
}

464 465 466 467 468
void PageView::setupBaseActions( KActionCollection * ac )
{
    d->actionCollection = ac;

    // Zoom actions ( higher scales takes lots of memory! )
Laurent Montel's avatar
Laurent Montel committed
469 470
    d->aZoom  = new KSelectAction(QIcon::fromTheme( QStringLiteral("page-zoom") ), i18n("Zoom"), this);
    ac->addAction(QStringLiteral("zoom_to"), d->aZoom );
471
    d->aZoom->setEditable( true );
472
    d->aZoom->setMaxComboViewCount( 14 );
Laurent Montel's avatar
Laurent Montel committed
473
    connect( d->aZoom, SIGNAL(triggered(QAction*)), this, SLOT(slotZoom()) );
474 475
    updateZoomText();

Laurent Montel's avatar
Laurent Montel committed
476
    d->aZoomIn = KStandardAction::zoomIn( this, SLOT(slotZoomIn()), ac );
477

Laurent Montel's avatar
Laurent Montel committed
478
    d->aZoomOut = KStandardAction::zoomOut( this, SLOT(slotZoomOut()), ac );
479 480
}

481
void PageView::setupViewerActions( KActionCollection * ac )
482
{
483 484
    d->actionCollection = ac;

485 486
    ac->setDefaultShortcut(d->aZoomIn, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Plus));
    ac->setDefaultShortcut(d->aZoomOut, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Minus));
487

488
    // orientation menu actions
Laurent Montel's avatar
Laurent Montel committed
489
    d->aRotateClockwise = new QAction( QIcon::fromTheme( QStringLiteral("object-rotate-right") ), i18n( "Rotate &Right" ), this );
490
    d->aRotateClockwise->setIconText( i18nc( "Rotate right", "Right" ) );
Laurent Montel's avatar
Laurent Montel committed
491
    ac->addAction( QStringLiteral("view_orientation_rotate_cw"), d->aRotateClockwise );
492
    d->aRotateClockwise->setEnabled( false );
Laurent Montel's avatar
Laurent Montel committed
493 494
    connect( d->aRotateClockwise, &QAction::triggered, this, &PageView::slotRotateClockwise );
    d->aRotateCounterClockwise = new QAction( QIcon::fromTheme( QStringLiteral("object-rotate-left") ), i18n( "Rotate &Left" ), this );
495
    d->aRotateCounterClockwise->setIconText( i18nc( "Rotate left", "Left" ) );
Laurent Montel's avatar
Laurent Montel committed
496
    ac->addAction( QStringLiteral("view_orientation_rotate_ccw"), d->aRotateCounterClockwise );
497
    d->aRotateCounterClockwise->setEnabled( false );
Laurent Montel's avatar
Laurent Montel committed
498
    connect( d->aRotateCounterClockwise, &QAction::triggered, this, &PageView::slotRotateCounterClockwise );
Vishesh Handa's avatar
Vishesh Handa committed
499
    d->aRotateOriginal = new QAction( i18n( "Original Orientation" ), this );
Laurent Montel's avatar
Laurent Montel committed
500
    ac->addAction( QStringLiteral("view_orientation_original"), d->aRotateOriginal );
501
    d->aRotateOriginal->setEnabled( false );
Laurent Montel's avatar
Laurent Montel committed
502
    connect( d->aRotateOriginal, &QAction::triggered, this, &PageView::slotRotateOriginal );
503

Laurent Montel's avatar
Laurent Montel committed
504
    d->aPageSizes = new KSelectAction(i18n("&Page Size"), this);
Laurent Montel's avatar
Laurent Montel committed
505
    ac->addAction(QStringLiteral("view_pagesizes"), d->aPageSizes);
506
    d->aPageSizes->setEnabled( false );
507

Laurent Montel's avatar
Laurent Montel committed
508 509
    connect( d->aPageSizes , SIGNAL(triggered(int)),
         this, SLOT(slotPageSizes(int)) );
510

Jake Linder's avatar
Jake Linder committed
511 512 513
    // Trim View actions
    d->aTrimMode = new KActionMenu(i18n( "&Trim View" ), this );
    d->aTrimMode->setDelayed( false );
Laurent Montel's avatar
Laurent Montel committed
514
    ac->addAction(QStringLiteral("view_trim_mode"), d->aTrimMode );
Jake Linder's avatar
Jake Linder committed
515 516 517

    d->aTrimMargins  = new KToggleAction( i18n( "&Trim Margins" ), d->aTrimMode->menu() );
    d->aTrimMode->addAction( d->aTrimMargins  );
Laurent Montel's avatar
Laurent Montel committed
518
    ac->addAction( QStringLiteral("view_trim_margins"), d->aTrimMargins  );
Jake Linder's avatar
Jake Linder committed
519
    d->aTrimMargins->setData( qVariantFromValue( (int)Okular::Settings::EnumTrimMode::Margins ) );
Laurent Montel's avatar
Laurent Montel committed
520
    connect( d->aTrimMargins, &QAction::toggled, this, &PageView::slotTrimMarginsToggled );
521
    d->aTrimMargins->setChecked( Okular::Settings::trimMargins() );
522

Jake Linder's avatar
Jake Linder committed
523 524
    d->aTrimToSelection  = new KToggleAction( i18n( "Trim To &Selection" ), d->aTrimMode->menu() );
    d->aTrimMode->addAction( d->aTrimToSelection);
Laurent Montel's avatar
Laurent Montel committed
525
    ac->addAction( QStringLiteral("view_trim_selection"), d->aTrimToSelection);
Jake Linder's avatar
Jake Linder committed
526
    d->aTrimToSelection->setData( qVariantFromValue( (int)Okular::Settings::EnumTrimMode::Selection ) );
Laurent Montel's avatar
Laurent Montel committed
527
    connect( d->aTrimToSelection, &QAction::toggled, this, &PageView::slotTrimToSelectionToggled );
Jake Linder's avatar
Jake Linder committed
528

Laurent Montel's avatar
Laurent Montel committed
529 530 531
    d->aZoomFitWidth  = new KToggleAction(QIcon::fromTheme( QStringLiteral("zoom-fit-width") ), i18n("Fit &Width"), this);
    ac->addAction(QStringLiteral("view_fit_to_width"), d->aZoomFitWidth );
    connect( d->aZoomFitWidth, &QAction::toggled, this, &PageView::slotFitToWidthToggled );
532

Laurent Montel's avatar
Laurent Montel committed
533 534 535
    d->aZoomFitPage  = new KToggleAction(QIcon::fromTheme( QStringLiteral("zoom-fit-best") ), i18n("Fit &Page"), this);
    ac->addAction(QStringLiteral("view_fit_to_page"), d->aZoomFitPage );
    connect( d->aZoomFitPage, &QAction::toggled, this, &PageView::slotFitToPageToggled );
536

Laurent Montel's avatar
Laurent Montel committed
537 538 539
    d->aZoomAutoFit  = new KToggleAction(QIcon::fromTheme( QStringLiteral("zoom-fit-best") ), i18n("&Auto Fit"), this);
    ac->addAction(QStringLiteral("view_auto_fit"), d->aZoomAutoFit );
    connect( d->aZoomAutoFit, &QAction::toggled, this, &PageView::slotAutoFitToggled );
Thomas Fischer's avatar
Thomas Fischer committed
540

Laurent Montel's avatar
Laurent Montel committed
541
    d->aFitWindowToPage = new QAction(QIcon::fromTheme( QStringLiteral("zoom-fit-width") ), i18n("Fit Wi&ndow to Page"), this);
542
    d->aFitWindowToPage->setEnabled( Okular::Settings::viewMode() == (int)Okular::Settings::EnumViewMode::Single );
Laurent Montel's avatar
Laurent Montel committed
543
    ac->setDefaultShortcut(d->aFitWindowToPage, QKeySequence(Qt::CTRL + Qt::Key_J) );
Laurent Montel's avatar
Laurent Montel committed
544 545
    ac->addAction( QStringLiteral("fit_window_to_page"), d->aFitWindowToPage );
    connect( d->aFitWindowToPage, &QAction::triggered, this, &PageView::slotFitWindowToPage );
546

547
    // View-Layout actions
Laurent Montel's avatar
Laurent Montel committed
548
    d->aViewMode = new KActionMenu( QIcon::fromTheme( QStringLiteral("view-split-left-right") ), i18n( "&View Mode" ), this );
549 550 551
    d->aViewMode->setDelayed( false );
#define ADD_VIEWMODE_ACTION( text, name, id ) \
do { \
Vishesh Handa's avatar
Vishesh Handa committed
552
    QAction *vm = new QAction( text, this ); \
553 554 555
    vm->setCheckable( true ); \
    vm->setData( qVariantFromValue( id ) ); \
    d->aViewMode->addAction( vm ); \
556
    ac->addAction( QStringLiteral(name), vm ); \
557 558
    vmGroup->addAction( vm ); \
} while( 0 )
Laurent Montel's avatar
Laurent Montel committed
559
    ac->addAction(QStringLiteral("view_render_mode"), d->aViewMode );
Vishesh Handa's avatar
Vishesh Handa committed
560
    QActionGroup *vmGroup = new QActionGroup( this ); //d->aViewMode->menu() );
561 562
    ADD_VIEWMODE_ACTION( i18n( "Single Page" ), "view_render_mode_single", (int)Okular::Settings::EnumViewMode::Single );
    ADD_VIEWMODE_ACTION( i18n( "Facing Pages" ), "view_render_mode_facing", (int)Okular::Settings::EnumViewMode::Facing );
563
    ADD_VIEWMODE_ACTION( i18n( "Facing Pages (Center First Page)" ), "view_render_mode_facing_center_first", (int)Okular::Settings::EnumViewMode::FacingFirstCentered );
564 565 566 567 568 569 570 571 572
    ADD_VIEWMODE_ACTION( i18n( "Overview" ), "view_render_mode_overview", (int)Okular::Settings::EnumViewMode::Summary );
    const QList<QAction *> viewModeActions = d->aViewMode->menu()->actions();
    foreach(QAction *viewModeAction, viewModeActions)
    {
        if (viewModeAction->data().toInt() == Okular::Settings::viewMode())
        {
            viewModeAction->setChecked( true );
        }
    }
Laurent Montel's avatar
Laurent Montel committed
573
    connect( vmGroup, &QActionGroup::triggered, this, &PageView::slotViewMode );
574
#undef ADD_VIEWMODE_ACTION
575

Laurent Montel's avatar
Laurent Montel committed
576 577 578
    d->aViewContinuous  = new KToggleAction(QIcon::fromTheme( QStringLiteral("view-list-text") ), i18n("&Continuous"), this);
    ac->addAction(QStringLiteral("view_continuous"), d->aViewContinuous );
    connect( d->aViewContinuous, &QAction::toggled, this, &PageView::slotContinuousToggled );
579
    d->aViewContinuous->setChecked( Okular::Settings::viewContinuous() );
580

581 582 583
    // Mouse mode actions for viewer mode
    d->mouseModeActionGroup = new QActionGroup( this );
    d->mouseModeActionGroup->setExclusive( true );
Laurent Montel's avatar
Laurent Montel committed
584 585 586
    d->aMouseNormal  = new QAction( QIcon::fromTheme( QStringLiteral("input-mouse") ), i18n( "&Browse Tool" ), this );
    ac->addAction(QStringLiteral("mouse_drag"), d->aMouseNormal );
    connect( d->aMouseNormal, &QAction::triggered, this, &PageView::slotSetMouseNormal );
Pino Toscano's avatar
Pino Toscano committed
587
    d->aMouseNormal->setIconText( i18nc( "Browse Tool", "Browse" ) );
Pino Toscano's avatar
Pino Toscano committed
588
    d->aMouseNormal->setCheckable( true );
589
    ac->setDefaultShortcut(d->aMouseNormal, QKeySequence(Qt::CTRL + Qt::Key_1));
590
    d->aMouseNormal->setActionGroup( d->mouseModeActionGroup );
591
    d->aMouseNormal->setChecked( Okular::Settings::mouseMode() == Okular::Settings::EnumMouseMode::Browse );
592

Laurent Montel's avatar
Laurent Montel committed
593 594 595
    QAction * mz  = new QAction(QIcon::fromTheme( QStringLiteral("page-zoom") ), i18n("&Zoom Tool"), this);
    ac->addAction(QStringLiteral("mouse_zoom"), mz );
    connect( mz, &QAction::triggered, this, &PageView::slotSetMouseZoom );
Pino Toscano's avatar
Pino Toscano committed
596
    mz->setIconText( i18nc( "Zoom Tool", "Zoom" ) );
Pino Toscano's avatar
Pino Toscano committed
597
    mz->setCheckable( true );
598
    ac->setDefaultShortcut(mz, QKeySequence(Qt::CTRL + Qt::Key_2));
599
    mz->setActionGroup( d->mouseModeActionGroup );
600
    mz->setChecked( Okular::Settings::mouseMode() == Okular::Settings::EnumMouseMode::Zoom );
601

Vishesh Handa's avatar
Vishesh Handa committed
602
    QAction * aToggleChangeColors  = new QAction(i18n("&Toggle Change Colors"), this);
Laurent Montel's avatar
Laurent Montel committed
603 604
    ac->addAction(QStringLiteral("toggle_change_colors"), aToggleChangeColors );
    connect( aToggleChangeColors, &QAction::triggered, this, &PageView::slotToggleChangeColors );
605 606 607 608 609 610 611
}

// WARNING: 'setupViewerActions' must have been called before this method
void PageView::setupActions( KActionCollection * ac )
{
    d->actionCollection = ac;

612 613
    ac->setDefaultShortcuts(d->aZoomIn, KStandardShortcut::zoomIn());
    ac->setDefaultShortcuts(d->aZoomOut, KStandardShortcut::zoomOut());
614 615

    // Mouse-Mode actions
Laurent Montel's avatar
Laurent Montel committed
616 617 618
    d->aMouseSelect  = new QAction(QIcon::fromTheme( QStringLiteral("select-rectangular") ), i18n("&Selection Tool"), this);
    ac->addAction(QStringLiteral("mouse_select"), d->aMouseSelect );
    connect( d->aMouseSelect, &QAction::triggered, this, &PageView::slotSetMouseSelect );
Pino Toscano's avatar
Pino Toscano committed
619
    d->aMouseSelect->setIconText( i18nc( "Select Tool", "Selection" ) );
Pino Toscano's avatar
Pino Toscano committed
620
    d->aMouseSelect->setCheckable( true );
621 622
    ac->setDefaultShortcut(d->aMouseSelect, Qt::CTRL + Qt::Key_3);

623
    d->aMouseSelect->setActionGroup( d->mouseModeActionGroup );
624
    d->aMouseSelect->setChecked( Okular::Settings::mouseMode() == Okular::Settings::EnumMouseMode::RectSelect );
625

Laurent Montel's avatar
Laurent Montel committed
626 627 628
    d->aMouseTextSelect  = new QAction(QIcon::fromTheme( QStringLiteral("draw-text") ), i18n("&Text Selection Tool"), this);
    ac->addAction(QStringLiteral("mouse_textselect"), d->aMouseTextSelect );
    connect( d->aMouseTextSelect, &QAction::triggered, this, &PageView::slotSetMouseTextSelect );
Pino Toscano's avatar
Pino Toscano committed
629
    d->aMouseTextSelect->setIconText( i18nc( "Text Selection Tool", "Text Selection" ) );
630
    d->aMouseTextSelect->setCheckable( true );
631
    ac->setDefaultShortcut(d->aMouseTextSelect, Qt::CTRL + Qt::Key_4);
632
    d->aMouseTextSelect->setActionGroup( d->mouseModeActionGroup );
633
    d->aMouseTextSelect->setChecked( Okular::Settings::mouseMode() == Okular::Settings::EnumMouseMode::TextSelect );
634

Laurent Montel's avatar
Laurent Montel committed
635 636 637
    d->aMouseTableSelect  = new QAction(QIcon::fromTheme( QStringLiteral("table") ), i18n("T&able Selection Tool"), this);
    ac->addAction(QStringLiteral("mouse_tableselect"), d->aMouseTableSelect );
    connect( d->aMouseTableSelect, &QAction::triggered, this, &PageView::slotSetMouseTableSelect );
Jiri Baum's avatar
Jiri Baum committed
638 639
    d->aMouseTableSelect->setIconText( i18nc( "Table Selection Tool", "Table Selection" ) );
    d->aMouseTableSelect->setCheckable( true );
640
    ac->setDefaultShortcut(d->aMouseTableSelect, Qt::CTRL + Qt::Key_5);
641
    d->aMouseTableSelect->setActionGroup( d->mouseModeActionGroup );
642
    d->aMouseTableSelect->setChecked( Okular::Settings::mouseMode() == Okular::Settings::EnumMouseMode::TableSelect );
Jiri Baum's avatar
Jiri Baum committed
643

Laurent Montel's avatar
Laurent Montel committed
644 645 646
    d->aMouseMagnifier = new QAction(QIcon::fromTheme( QStringLiteral("document-preview") ), i18n("&Magnifier"), this);
    ac->addAction(QStringLiteral("mouse_magnifier"), d->aMouseMagnifier );
    connect( d->aMouseMagnifier, &QAction::triggered, this, &PageView::slotSetMouseMagnifier );
Michal Humpula's avatar
Michal Humpula committed
647 648
    d->aMouseMagnifier->setIconText( i18nc( "Magnifier Tool", "Magnifier" ) );
    d->aMouseMagnifier->setCheckable( true );
649
    ac->setDefaultShortcut(d->aMouseMagnifier, Qt::CTRL + Qt::Key_6);
Michal Humpula's avatar
Michal Humpula committed
650 651 652
    d->aMouseMagnifier->setActionGroup( d->mouseModeActionGroup );
    d->aMouseMagnifier->setChecked( Okular::Settings::mouseMode() == Okular::Settings::EnumMouseMode::Magnifier );

Laurent Montel's avatar
Laurent Montel committed
653 654
    d->aToggleAnnotator  = new KToggleAction(QIcon::fromTheme( QStringLiteral("draw-freehand") ), i18n("&Review"), this);
    ac->addAction(QStringLiteral("mouse_toggle_annotate"), d->aToggleAnnotator );
Pino Toscano's avatar
Pino Toscano committed
655
    d->aToggleAnnotator->setCheckable( true );
Laurent Montel's avatar
Laurent Montel committed
656
    connect( d->aToggleAnnotator, &QAction::toggled, this, &PageView::slotToggleAnnotator );
657
    ac->setDefaultShortcut(d->aToggleAnnotator, Qt::Key_F6);
658

659
    ToolAction *ta = new ToolAction( this );
Laurent Montel's avatar
Laurent Montel committed
660
    ac->addAction( QStringLiteral("mouse_selecttools"), ta );
661 662
    ta->addAction( d->aMouseSelect );
    ta->addAction( d->aMouseTextSelect );
663
    ta->addAction( d->aMouseTableSelect );
664

665
    // speak actions
666
#ifdef HAVE_SPEECH
Laurent Montel's avatar
Laurent Montel committed
667 668
    d->aSpeakDoc = new QAction( QIcon::fromTheme( QStringLiteral("text-speak") ), i18n( "Speak Whole Document" ), this );
    ac->addAction( QStringLiteral("speak_document"), d->aSpeakDoc );
669
    d->aSpeakDoc->setEnabled( false );
Laurent Montel's avatar
Laurent Montel committed
670
    connect( d->aSpeakDoc, &QAction::triggered, this, &PageView::slotSpeakDocument );
Olivier Churlaud's avatar
Olivier Churlaud committed
671

Laurent Montel's avatar
Laurent Montel committed
672 673
    d->aSpeakPage = new QAction( QIcon::fromTheme( QStringLiteral("text-speak") ), i18n( "Speak Current Page" ), this );
    ac->addAction( QStringLiteral("speak_current_page"), d->aSpeakPage );
674
    d->aSpeakPage->setEnabled( false );
Laurent Montel's avatar
Laurent Montel committed
675
    connect( d->aSpeakPage, &QAction::triggered, this, &PageView::slotSpeakCurrentPage );
676

Laurent Montel's avatar
Laurent Montel committed
677 678
    d->aSpeakStop = new QAction( QIcon::fromTheme( QStringLiteral("media-playback-stop") ), i18n( "Stop Speaking" ), this );
    ac->addAction( QStringLiteral("speak_stop_all"), d->aSpeakStop );
679
    d->aSpeakStop->setEnabled( false );
Laurent Montel's avatar
Laurent Montel committed
680
    connect( d->aSpeakStop, &QAction::triggered, this, &PageView::slotStopSpeaks );
681 682 683 684 685
#else
    d->aSpeakDoc = 0;
    d->aSpeakPage = 0;
    d->aSpeakStop = 0;
#endif
686

687
    // Other actions
Vishesh Handa's avatar
Vishesh Handa committed
688
    QAction * su  = new QAction(i18n("Scroll Up"), this);
Laurent Montel's avatar
Laurent Montel committed
689 690
    ac->addAction(QStringLiteral("view_scroll_up"), su );
    connect( su, &QAction::triggered, this, &PageView::slotAutoScrollUp );
691
    ac->setDefaultShortcut(su, QKeySequence(Qt::SHIFT + Qt::Key_Up));
Albert Astals Cid's avatar
Albert Astals Cid committed
692
    addAction(su);
693

Vishesh Handa's avatar
Vishesh Handa committed
694
    QAction * sd  = new QAction(i18n("Scroll Down"), this);
Laurent Montel's avatar
Laurent Montel committed
695 696
    ac->addAction(QStringLiteral("view_scroll_down"), sd );
    connect( sd, &QAction::triggered, this, &PageView::slotAutoScrollDown );
697
    ac->setDefaultShortcut(sd, QKeySequence(Qt::