1 /* 2 This is part of TeXworks, an environment for working with TeX documents 3 Copyright (C) 2007-2010 Jonathan Kew 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 For links to further information, or to contact the author, 19 see <http://texworks.org/>. 20 */ 21 22 #ifndef Header_PDF_Document 23 #define Header_PDF_Document 24 25 #ifndef NO_POPPLER_PREVIEW 26 27 28 #include "mostQtHeaders.h" 29 30 #include <QGestureEvent> 31 #include <QPinchGesture> 32 #include <QTapGesture> 33 #include <QPainterPath> 34 #include <QProgressDialog> 35 #include <QPainterPath> 36 #if QT_VERSION_MAJOR>5 37 #include "poppler-qt6.h" 38 #else 39 #include "poppler-qt5.h" 40 #endif 41 #include "poppler-version.h" 42 #include "qsynctex.h" 43 44 #include "pdfrendermanager.h" 45 46 47 const int kPDFWindowStateVersion = 1; 48 49 class QAction; 50 class QMenu; 51 class QToolBar; 52 class QScrollArea; 53 class QShortcut; 54 class QFileSystemWatcher; 55 class ConfigManagerInterface; 56 class PDFDocument; 57 class PDFWidget; 58 59 class TitledPanel; 60 class PDFAnnotations; 61 class PDFAnnotation; 62 class PDFAnnotationTableView; 63 class MessageFrame; 64 65 66 class PDFMagnifier : public QLabel 67 { 68 Q_OBJECT 69 70 public: 71 PDFMagnifier(QWidget *parent, qreal inDpi); 72 void setPage(int p, qreal scale, const QRect &visibleRect); 73 void reshape(); 74 75 public slots: 76 void setImage(const QPixmap &img, int pageNr); 77 78 protected: 79 virtual void paintEvent(QPaintEvent *event); 80 QPixmap &getConvertedImage(); 81 82 private: 83 int oldshape; 84 int page; 85 qreal overScale; 86 qreal scaleFactor; 87 qreal parentDpi; 88 QPixmap image; 89 QPixmap convertedImage; 90 bool convertedImageIsGrayscale; 91 bool convertedImageIsColorInverted; 92 93 QPoint mouseTranslate; 94 95 QPoint imageLoc, mouseOffset; 96 QSize imageSize; 97 qreal imageDpi; 98 int imagePage; 99 }; 100 101 #ifdef PHONON 102 #include <phonon/VideoPlayer> 103 104 class PDFMovie: public Phonon::VideoPlayer 105 { 106 Q_OBJECT 107 public: 108 PDFMovie(PDFWidget *parent, QSharedPointer<Poppler::MovieAnnotation> annot, int page); 109 void place(); 110 protected: 111 void contextMenuEvent(QContextMenuEvent *); 112 void mouseReleaseEvent(QMouseEvent *e); 113 public slots: 114 void realPlay(); 115 void setVolumeDialog(); 116 void seekDialog(); 117 private: 118 QMenu *popup; 119 QRectF boundary; 120 int page; 121 }; 122 #endif 123 124 typedef enum { 125 kFixedMag, 126 kFitWidth, 127 kFitWindow, 128 kFitTextWidth 129 } autoScaleOption; 130 131 struct PDFPageHistoryItem{ 132 int page; 133 double x, y; PDFPageHistoryItemPDFPageHistoryItem134 PDFPageHistoryItem():page(0),x(0),y(0){} PDFPageHistoryItemPDFPageHistoryItem135 PDFPageHistoryItem(int page, double x, double y):page(page),x(x),y(y){} 136 }; 137 138 class PDFScrollArea; 139 class PDFWidget : public QLabel 140 { 141 Q_OBJECT 142 143 public: 144 explicit PDFWidget(bool embedded = false); 145 virtual ~PDFWidget(); 146 147 void setDocument(const QSharedPointer<Poppler::Document> &doc); 148 void setPDFDocument(PDFDocument *docu); 149 150 void saveState(); // used when toggling full screen mode 151 void restoreState(); 152 void setResolution(int res); 153 void resetMagnifier(); 154 Q_INVOKABLE int normalizedPageIndex(int pageIndex); 155 Q_INVOKABLE void goToPageDirect(int pageIndex, bool sync); 156 Q_INVOKABLE void setHighlightPath(const int pageIndex, const QPainterPath &path, const bool dontRemove=false); 157 Q_INVOKABLE int getHighlightPage() const; 158 Q_INVOKABLE void goToDestination(const QString &destName); 159 Q_INVOKABLE void goToPageRelativePosition(int page, double xinpage, double yinpage); 160 Q_INVOKABLE int getPageIndex(); 161 Q_INVOKABLE void reloadPage(bool sync = true); 162 void updateStatusBar(); 163 void setGridSize(int gx, int gy, bool setAsDefault = false); 164 Q_INVOKABLE int visiblePages() const; 165 Q_INVOKABLE int pseudoNumPages() const; 166 Q_INVOKABLE int realNumPages() const; 167 Q_INVOKABLE int pageStep(); 168 Q_INVOKABLE int gridCols() const; 169 Q_INVOKABLE int gridRowHeight() const; 170 Q_INVOKABLE int gridBorder() const; 171 Q_INVOKABLE PDFDocument *getPDFDocument(); 172 Q_INVOKABLE int getPageOffset() const; getScaleOption()173 autoScaleOption getScaleOption() { return scaleOption; } 174 double totalScaleFactor() const; 175 176 int currentPageHistoryIndex() const; 177 const QList<PDFPageHistoryItem> currentPageHistory() const; 178 void updateCurrentPageHistoryOffset(); 179 180 QPoint gridPagePosition(int pageIndex) const; 181 QRect gridPageRect(int pageIndex) const; 182 int gridPageIndex(const QPoint &position) const; 183 void mapToScaledPosition(const QPoint &position, int &page, QPointF &scaledPos) const; 184 QPoint mapFromScaledPosition(int page, const QPointF &scaledPos) const; 185 int pageFromPos(const QPoint &pos) const; 186 QRect pageRect(int page) const; 187 QSizeF maxPageSizeF() const; 188 QSizeF maxPageSizeFDpiAdjusted() const; 189 QRectF horizontalTextRangeF(); 190 191 Q_INVOKABLE void zoom(qreal scale); 192 193 virtual void wheelEvent(QWheelEvent *event); 194 195 protected slots: //not private, so scripts have access 196 void goFirst(); 197 void goPrev(); 198 void goNext(); 199 void goLast(); 200 void goForward(); 201 void goBack(); 202 void doPageDialog(); 203 204 void fitWidth(bool checked = true); 205 void fitTextWidth(bool checked = true); 206 void zoomIn(); 207 void zoomOut(); 208 void jumpToSource(); 209 210 void upOrPrev(); 211 void leftOrPrev(); 212 void pageUpOrPrev(); 213 214 void downOrNext(); 215 void rightOrNext(); 216 void pageDownOrNext(); 217 218 void clearHighlight(); 219 void openAnnotationDialog(const PDFAnnotation *annon); 220 221 public slots: 222 void setSinglePageStep(bool step); 223 void windowResized(); 224 void fitWindow(bool checked = true); 225 void setTool(int tool); 226 void syncWindowClick(const QPoint &p, bool activate); 227 void syncCurrentPage(bool activate); 228 void fixedScale(qreal scale = 1.0); 229 void setImage(QPixmap img, int pageNr); 230 void delayedUpdate(); 231 232 signals: 233 void changedPage(int, bool); 234 void changedZoom(qreal); 235 void changedScaleOption(autoScaleOption); 236 void syncClick(int, const QPointF &, bool activate); //page position in page coordinates 237 238 protected: 239 virtual void paintEvent(QPaintEvent *event); 240 241 virtual void mousePressEvent(QMouseEvent *event); 242 virtual void mouseReleaseEvent(QMouseEvent *event); 243 virtual void mouseDoubleClickEvent(QMouseEvent *event); 244 virtual void mouseMoveEvent(QMouseEvent *event); 245 246 virtual void keyPressEvent(QKeyEvent *event); 247 virtual void keyReleaseEvent(QKeyEvent *event); 248 249 virtual void focusInEvent(QFocusEvent *event); 250 251 virtual void contextMenuEvent(QContextMenuEvent *event); 252 253 virtual bool event(QEvent *event); 254 255 bool gestureEvent(QGestureEvent *event); 256 void pinchEvent(QPinchGesture *gesture); 257 void tapEvent(QTapGesture *gesture); 258 259 private: 260 friend class PDFMagnifier; 261 262 void init(); 263 void adjustSize(); 264 void updateCursor(); 265 void updateCursor(const QPoint &pos); 266 QRect mapPopplerRectToWidget(QRectF rect, const QSizeF &pageSize) const; 267 void useMagnifier(const QMouseEvent *inEvent); 268 void goToDestination(const Poppler::LinkDestination &dest); 269 void doLink(const QSharedPointer<Poppler::Link> link); 270 void annotationClicked(QSharedPointer<Poppler::Annotation> annotation, int page); 271 void doZoom(const QPoint &clickPos, int dir, qreal newScaleFactor = 1.0); 272 void doZoom(const QPointF &clickPos, int dir, qreal newScaleFactor = 1.0); 273 274 PDFScrollArea *getScrollArea() const; 275 276 QSharedPointer<Poppler::Document> document; 277 QMutex textwidthCalculationMutex; 278 279 //QList<int> pages; 280 QSharedPointer<Poppler::Link> clickedLink; 281 QSharedPointer<Poppler::Annotation> clickedAnnotation; 282 283 int realPageIndex, oldRealPageIndex; 284 QList<int> pages; 285 qreal scaleFactor; 286 qreal dpi; 287 autoScaleOption scaleOption; 288 289 bool inhibitNextContextMenuEvent; 290 double summedWheelDegrees; 291 292 int docPages; 293 qreal saveScaleFactor; 294 autoScaleOption saveScaleOption; 295 296 QAction *ctxZoomInAction; 297 QAction *ctxZoomOutAction; 298 QShortcut *shortcutUp; 299 QShortcut *shortcutLeft; 300 QShortcut *shortcutDown; 301 QShortcut *shortcutRight; 302 303 QPixmap image; 304 QRect imageRect; 305 qreal imageDpi; 306 int imagePage; 307 308 PDFMagnifier *magnifier; 309 #ifdef PHONON 310 PDFMovie *movie; 311 #endif 312 int currentTool; // the current tool selected in the toolbar 313 int usingTool; // the tool actually being used in an ongoing mouse drag 314 bool singlePageStep; 315 316 int gridx, gridy; 317 318 bool forceUpdate; 319 320 QPainterPath highlightPath; 321 int highlightPage; 322 QTimer highlightRemover; 323 324 static QCursor *magnifierCursor; 325 static QCursor *zoomInCursor; 326 static QCursor *zoomOutCursor; 327 328 mutable QSizeF maxPageSize; //cache pageSize 329 mutable QRectF horizontalTextRange; 330 331 QList<PDFPageHistoryItem> pageHistory; 332 int pageHistoryIndex; 333 334 PDFDocument *pdfdocument; 335 }; 336 337 class PDFSearchResult 338 { 339 public: 340 explicit PDFSearchResult(const PDFDocument *pdfdoc = nullptr, int page = -1, QRectF rect = QRectF()) doc(pdfdoc)341 : doc(pdfdoc), pageIdx(page), selRect(rect) 342 { } 343 344 const PDFDocument *doc; 345 int pageIdx; 346 QRectF selRect; 347 }; 348 349 350 351 struct PDFDocumentConfig; 352 class PDFDock; 353 class PDFSearchDock; 354 class PDFScrollArea; 355 class PDFDocument : public QMainWindow 356 { 357 Q_OBJECT 358 359 Q_PROPERTY(QString fileName READ fileName) 360 361 public: 362 explicit PDFDocument(PDFDocumentConfig *const pdfConfig, bool embedded = false); 363 virtual ~PDFDocument(); 364 365 enum DisplayFlagsEnum { 366 NoDisplayFlags = 0x0000, 367 FocusEmbedded = 0x0001, 368 FocusWindowed = 0x0010, 369 Raise = 0x0100, 370 371 // window state independent combinations 372 Focus = FocusEmbedded | FocusWindowed, 373 // filter 374 FilterEmbedded = 0xFF0F, 375 FilterWindowed = 0xFFF0, 376 }; 377 Q_DECLARE_FLAGS(DisplayFlags, DisplayFlagsEnum) 378 379 static PDFDocument *findDocument(const QString &fileName); documentList()380 static QList<PDFDocument *> documentList() { return docList; } 381 fileName()382 Q_INVOKABLE QString fileName() const { return curFile; } getMasterFile()383 Q_INVOKABLE QFileInfo getMasterFile() const { return masterFile; } 384 385 void saveGeometryToConfig(); 386 387 Q_INVOKABLE void zoomToRight(QWidget *otherWindow); 388 void showScale(qreal scale); 389 Q_INVOKABLE void showPage(int page); 390 Q_INVOKABLE void setResolution(int res); 391 void resetMagnifier(); 392 Q_INVOKABLE void goToDestination(const QString &destName); 393 Q_INVOKABLE void goToPage(const int page); 394 Q_INVOKABLE void focus(); hasSyncData()395 bool hasSyncData() { return scanner.isValid(); } 396 popplerDoc()397 const QSharedPointer<Poppler::Document> &popplerDoc() const { return document; } 398 widget()399 Q_INVOKABLE PDFWidget *widget() { return pdfWidget; } widget()400 const PDFWidget *widget() const { return pdfWidget; } 401 402 bool followCursor() const; 403 bool ignoreSynchronization() const; 404 PDFRenderManager *renderManager; 405 406 static bool isCompiling, isMaybeCompiling; 407 bool embeddedMode; 408 bool autoClose; 409 410 void setStateEnlarged(bool state); 411 412 protected: 413 virtual void changeEvent(QEvent *event); 414 virtual void closeEvent(QCloseEvent *event); 415 virtual void dragEnterEvent(QDragEnterEvent *event); 416 virtual void dropEvent(QDropEvent *event); 417 virtual void enterEvent(QEvent *event); 418 virtual void leaveEvent(QEvent *event); 419 virtual void mouseMoveEvent(QMouseEvent *event); 420 void setToolbarsVisible(bool visible); 421 void shortcutOnlyIfFocused(const QList<QAction *> &actions); 422 423 public slots: 424 void reloadSettings(); 425 void loadCurrentFile(bool fillCache = true); 426 void fillRenderCache(int pg = -1); 427 void sideBySide(); 428 void doFindDialog(const QString command = ""); 429 void doFindAgain(); 430 void goToSource(); 431 void toggleFullScreen(const bool fullscreen); 432 int syncFromSource(const QString &sourceFile, int lineNo, int column, PDFDocument::DisplayFlags displayFlags); // lineNo, column are 0-based 433 void syncFromView(const QString &pdfFile, const QFileInfo &masterFile, int page); 434 void loadFile(const QString &fileName, QFileInfo masterFile = QFileInfo(), PDFDocument::DisplayFlags displayFlags = DisplayFlagsEnum(Raise | Focus)); 435 void printPDF(); 436 void setAutoHideToolbars(bool enabled); 437 void hideToolbars(); 438 void showToolbars(); 439 void showToolbarsDelayed(); 440 void setToolbarIconSize(int sz); 441 void showMessage(const QString &text); 442 443 void splitMergeTool(); 444 private slots: 445 void fileOpen(); 446 447 void enablePageActions(int, bool); 448 void enableZoomActions(qreal); 449 void adjustScaleActions(autoScaleOption); 450 void syncClick(int page, const QPointF &pos, bool activate); 451 void stopReloadTimer(); 452 void reloadWhenIdle(); 453 void idleReload(); 454 455 void runExternalViewer(); 456 void runInternalViewer(); 457 void toggleEmbedded(); 458 void toggleAutoHideToolbars(); 459 void runQuickBuild(); 460 461 void setGrid(); 462 463 public slots: 464 bool closeElement(); 465 private slots: 466 void tileWindows(); 467 void stackWindows(); 468 void unminimize(); 469 void updateDisplayState(PDFDocument::DisplayFlags displayFlags); 470 void arrangeWindows(bool tile); 471 void updateToolBarForOrientation(Qt::Orientation orientation); 472 473 void jumpToPage(); 474 475 void search(bool backward, bool incremental); 476 void clearHightlight(bool visible); 477 public: 478 void search(const QString &searchText, bool backward, bool incremental, bool caseSensitive, bool wholeWords, bool sync); 479 void search(); 480 static QString debugSyncTeX(const QString &filename); 481 private slots: 482 void gotoAnnotation(const PDFAnnotation *ann); 483 484 void zoomFromAction(); 485 void zoomSliderChange(int pos = 0); 486 void enlarge(); 487 void shrink(); 488 signals: 489 void documentClosed(); 490 void documentLoaded(); 491 void syncSource(const QString &sourceFile, int line, bool activate, const QString &guessedWord); //view -> source 492 void syncView(const QString &pdfFile, const QFileInfo &masterFile, int page); //view -> other view 493 void focusEditor(); 494 void fileDropped(const QUrl &url); 495 496 void runCommand(const QString &command, const QFileInfo &masterFile, const QFileInfo ¤tFile, int linenr); 497 498 void triggeredAbout(); 499 void triggeredManual(); 500 void triggeredQuit(); 501 void triggeredPlaceOnLeft(); 502 void triggeredConfigure(); 503 void triggeredEnlarge(); 504 void triggeredShrink(); 505 506 void triggeredClone(); 507 508 private: 509 void init(bool embedded = false); 510 void setupMenus(bool embedded); 511 void setupToolBar(); 512 void setCurrentFile(const QString &fileName); 513 void loadSyncData(); 514 515 qreal zoomSliderPosToScale(int pos); 516 int scaleToZoomSliderPos(qreal scale); 517 518 QString curFile, curFileUnnormalized; 519 qint64 curFileSize; 520 QDateTime curFileLastModified; 521 QFileInfo masterFile; 522 QSynctex::TeXSyncPoint lastSyncPoint; 523 524 QSharedPointer<Poppler::Document> document; 525 526 PDFWidget *pdfWidget; 527 PDFScrollArea *scrollArea; 528 MessageFrame *messageFrame; 529 TitledPanel *annotationPanel; 530 PDFAnnotations *annotations; 531 PDFAnnotationTableView *annotationTable; 532 533 QMenuBar *menubar; 534 QMenu *menuroot; 535 QMenu *menuHelp; 536 QMenu *menuFile; 537 QMenu *menuEdit; 538 QMenu *menuView; 539 QMenu *menuGrid; 540 QMenu *menuWindow; 541 QList<QMenu *>menus; 542 543 QAction *actionAbout_TW; 544 QAction *actionFirst_Page; 545 QAction *actionPrevious_Page; 546 QAction *actionNext_Page; 547 QAction *actionLast_Page; 548 QAction *actionGo_to_Page; 549 QAction *actionZoom_In; 550 QAction *actionZoom_Out; 551 QAction *actionFit_to_Window; 552 QAction *actionActual_Size; 553 QAction *actionFit_to_Width; 554 QAction *actionNew; 555 QAction *actionOpen; 556 QAction *actionOpen_Recent; 557 QAction *actionClose; 558 QAction *actionUndo; 559 QAction *actionRedo; 560 QAction *actionCut; 561 QAction *actionCopy; 562 QAction *actionPaste; 563 QAction *actionClear; 564 QAction *actionTypeset; 565 QAction *actionExternalViewer; 566 QAction *actionPreferences; 567 QAction *actionStack; 568 QAction *actionTile; 569 QAction *actionGo_to_Source; 570 QAction *actionNew_from_Template; 571 QAction *actionFull_Screen; 572 QAction *actionMagnify; 573 QAction *actionScroll; 574 QAction *actionSelect_Text; 575 QAction *actionSelect_Image; 576 QAction *actionUserManual; 577 QAction *actionWriteToMailingList; 578 QAction *actionSide_by_Side; 579 QAction *actionPlace_on_Left; 580 QAction *actionPlace_on_Right; 581 QAction *actionQuit_TeXworks; 582 QAction *actionFind; 583 QAction *actionFind_Again; 584 QAction *actionUpdate_Scripts; 585 QAction *actionManage_Scripts; 586 QAction *actionShow_Scripts_Folder; 587 QAction *actionAbout_Scripts; 588 QAction *actionS; 589 QAction *actionCloseElement; 590 QAction *actionScrolling_follows_cursor; 591 QAction *actionCursor_follows_scrolling; 592 QAction *actionFind_2; 593 QAction *actionFind_again; 594 QAction *actionNew_Window; 595 QAction *actionGrid11; 596 QAction *actionGrid21; 597 QAction *actionGrid12; 598 QAction *actionGrid22; 599 QAction *actionGrid23; 600 QAction *actionGrid33; 601 QAction *actionCustom; 602 QAction *actionSinglePageStep; 603 QAction *actionSynchronize_multiple_views, *actionNoSynchronization; 604 QAction *actionPresentation; 605 QAction *actionContinuous; 606 QAction *action_Print; 607 QAction *actionFileOpen; 608 QAction *actionBack; 609 QAction *actionForward; 610 QAction *actionToggleEmbedded; 611 QAction *actionEnlargeViewer; 612 QAction *actionShrinkViewer; 613 QAction *actionAutoHideToolbars; 614 QAction *actionInvertColors; 615 QAction *actionFocus_Editor; 616 QAction *actionFit_to_Text_Width; 617 QAction *actionGrayscale; 618 QAction *actionSplitMerge; 619 620 QStatusBar *statusbar; 621 QToolBar *toolBar; 622 QTimer *toolBarTimer; 623 public: 624 QMenu *menuShow; 625 private: 626 QMenu *menuEdit_2; 627 628 QAction *actionPage_Up; 629 QAction *actionPage_Down; 630 631 QButtonGroup *toolButtonGroup; 632 QToolButton *comboZoom; 633 QLineEdit *leCurrentPage; 634 QLabel *pageCountSeparator; 635 QLabel *pageCountLabel; 636 QIntValidator *leCurrentPageValidator; 637 638 QLabel *pageLabel; 639 QToolButton *scaleButton; 640 QSlider *zoomSlider; 641 QList<QAction *> recentFileActions; 642 QShortcut *exitFullscreen; 643 644 QFileSystemWatcher *watcher; 645 QTimer *reloadTimer; 646 647 QSynctex::Scanner scanner; 648 649 static QList<PDFDocument *> docList; 650 651 PDFDock *dwClock, *dwOutline, *dwFonts, *dwInfo, *dwOverview; 652 bool dwVisOutline, dwVisFonts, dwVisInfo, dwVisSearch, dwVisOverview; 653 bool wasContinuous; 654 PDFSearchDock *dwSearch; 655 656 PDFSearchResult lastSearchResult; 657 // stores the page idx a search was started on 658 // after wrapping the search will continue only up to this page 659 int firstSearchPage; 660 661 bool wasMaximized; 662 bool syncFromSourceBlocked; //temporary disable sync from source 663 bool syncToSourceBlocked; //temporary disable sync to source (only for continuous scrolling) 664 }; 665 Q_DECLARE_OPERATORS_FOR_FLAGS(PDFDocument::DisplayFlags) 666 667 #endif 668 669 #endif 670