1 /** 2 * Copyright (C) 2011-2012 Charlie Sharpsteen, Stefan Löffler 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the Free 6 * Software Foundation; either version 2, or (at your option) any later 7 * version. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 */ 14 #ifndef PDFDocumentView_H 15 #define PDFDocumentView_H 16 17 #if QT_VERSION_MAJOR < 5 18 #include <QtGui/QtGui> 19 #else 20 #include <QtWidgets> 21 #endif 22 23 #include <PDFBackend.h> 24 #include <PDFDocumentTools.h> 25 26 namespace QtPDF { 27 28 // Forward declare classes defined in this header. 29 class PDFDocumentScene; 30 class PDFPageGraphicsItem; 31 class PDFLinkGraphicsItem; 32 class PDFDocumentMagnifierView; 33 class PDFActionEvent; 34 class PDFDocumentView; 35 36 37 const int TILE_SIZE=1024; 38 39 class PDFDocumentView : public QGraphicsView { 40 Q_OBJECT 41 typedef QGraphicsView Super; 42 43 QSharedPointer<PDFDocumentScene> _pdf_scene; 44 45 qreal _zoomLevel; 46 int _currentPage, _lastPage; 47 48 QString _searchString; 49 QList<QGraphicsItem *> _searchResults; 50 QFutureWatcher< QList<Backend::SearchResult> > _searchResultWatcher; 51 int _currentSearchResult; 52 QBrush _searchResultHighlightBrush; 53 QBrush _currentSearchResultHighlightBrush; 54 bool _useGrayScale; 55 56 friend class DocumentTool::AbstractTool; 57 58 public: 59 enum PageMode { PageMode_SinglePage, PageMode_OneColumnContinuous, PageMode_TwoColumnContinuous, PageMode_Presentation }; 60 enum MouseMode { MouseMode_MagnifyingGlass, MouseMode_Move, MouseMode_MarqueeZoom, MouseMode_Measure, MouseMode_Select }; 61 enum Dock { Dock_TableOfContents, Dock_MetaData, Dock_Fonts, Dock_Permissions, Dock_Annotations }; 62 63 PDFDocumentView(QWidget *parent = 0); 64 ~PDFDocumentView(); 65 void setScene(QSharedPointer<PDFDocumentScene> a_scene); 66 int currentPage(); 67 int lastPage(); pageMode()68 PageMode pageMode() const { return _pageMode; } zoomLevel()69 qreal zoomLevel() const { return _zoomLevel; } useGrayScale()70 bool useGrayScale() const { return _useGrayScale; } 71 void fitInView(const QRectF & rect, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio); 72 73 // The ownership of the returned pointers is transferred to the caller (i.e., 74 // he has to destroy them, unless the `parent` widget does that automatically) 75 // They are fully wired to this PDFDocumentView (e.g., clicking on entries in 76 // the table of contents will change this view) 77 QDockWidget * dockWidget(const Dock type, QWidget * parent = NULL); 78 armedTool()79 DocumentTool::AbstractTool * armedTool() const { return _armedTool; } triggerContextClick(const int page,const QPointF pos)80 void triggerContextClick(const int page, const QPointF pos) { emit contextClick(page, pos); } 81 82 QGraphicsPathItem * addHighlightPath(const unsigned int page, const QPainterPath & path, const QBrush & brush, const QPen & pen = Qt::NoPen); 83 QGraphicsPathItem * addHighlightPath(const unsigned int page, const QRectF & rect, const QBrush & brush, const QPen & pen = Qt::NoPen) { 84 QPainterPath p; 85 p.addRect(rect); 86 return addHighlightPath(page, p, brush, pen); 87 } 88 QGraphicsPathItem * addHighlightPath(const unsigned int page, const QPainterPath & path, const QColor color, const QPen & pen = Qt::NoPen) { 89 return addHighlightPath(page, path, QBrush(color), pen); 90 } 91 searchResultHighlightBrush()92 QBrush searchResultHighlightBrush() const { return _searchResultHighlightBrush; } 93 void setSearchResultHighlightBrush(const QBrush & brush); 94 currentSearchResultHighlightBrush()95 QBrush currentSearchResultHighlightBrush() const { return _currentSearchResultHighlightBrush; } 96 void setCurrentSearchResultHighlightBrush(const QBrush & brush); 97 canGoPrevViewRects()98 bool canGoPrevViewRects() const { return !_oldViewRects.empty(); } 99 100 public slots: 101 void goPrev(); 102 void goNext(); 103 void goFirst(); 104 void goLast(); 105 void goPrevViewRect(); 106 // `alignment` can be (a combination of) 0, Qt::AlignLeft, Qt::AlignRight, 107 // Qt::AlignHCenter, Qt::AlignTop, Qt::AlignBottom, Qt::AlignVCenter. 108 // 0 corresponds to no alignment, i.e., the view will change so that the 109 // rectangle of page pageNum closest to the original viewport rect is visible. 110 void goToPage(const int pageNum, const int alignment = Qt::AlignLeft | Qt::AlignTop); 111 // Similar to the one above, but view is aligned at `anchor`. Note that the 112 // default alignment is centering here, which is also used if `alignment` == 0. 113 // `anchor` must be given in item coordinates 114 void goToPage(const int pageNum, const QPointF anchor, const int alignment = Qt::AlignHCenter | Qt::AlignVCenter); 115 void goToPDFDestination(const PDFDestination & dest, bool saveOldViewRect = true); 116 void setPageMode(const PageMode pageMode, const bool forceRelayout = false); setSinglePageMode()117 void setSinglePageMode() { setPageMode(PageMode_SinglePage); } setOneColContPageMode()118 void setOneColContPageMode() { setPageMode(PageMode_OneColumnContinuous); } setTwoColContPageMode()119 void setTwoColContPageMode() { setPageMode(PageMode_TwoColumnContinuous); } setPresentationMode()120 void setPresentationMode() { setPageMode(PageMode_Presentation); } 121 void setMouseMode(const MouseMode newMode); setMouseModeMagnifyingGlass()122 void setMouseModeMagnifyingGlass() { setMouseMode(MouseMode_MagnifyingGlass); } setMouseModeMove()123 void setMouseModeMove() { setMouseMode(MouseMode_Move); } setMouseModeMarqueeZoom()124 void setMouseModeMarqueeZoom() { setMouseMode(MouseMode_MarqueeZoom); } setMouseModeMeasure()125 void setMouseModeMeasure() { setMouseMode(MouseMode_Measure); } setMouseModeSelect()126 void setMouseModeSelect() { setMouseMode(MouseMode_Select); } 127 void setMagnifierShape(const DocumentTool::MagnifyingGlass::MagnifierShape shape); 128 void setMagnifierSize(const int size); 129 void setUseGrayScale(const bool grayScale = true) { _useGrayScale = grayScale; } 130 131 void zoomBy(const qreal zoomFactor, const QGraphicsView::ViewportAnchor anchor = QGraphicsView::AnchorViewCenter); 132 void zoomIn(const QGraphicsView::ViewportAnchor anchor = QGraphicsView::AnchorViewCenter); 133 void zoomOut(const QGraphicsView::ViewportAnchor anchor = QGraphicsView::AnchorViewCenter); 134 void zoomToRect(QRectF a_rect); 135 void zoomFitWindow(); 136 void zoomFitWidth(); 137 void zoom100(); 138 void setZoomLevel(const qreal zoomLevel, const QGraphicsView::ViewportAnchor anchor = QGraphicsView::AnchorViewCenter); 139 140 void search(QString searchText, Backend::SearchFlags flags = Backend::Search_CaseInsensitive); 141 void nextSearchResult(); 142 void previousSearchResult(); 143 void clearSearchResults(); 144 145 signals: 146 void changedPage(int pageNum); 147 void changedZoom(qreal zoomLevel); 148 void changedPageMode(QtPDF::PDFDocumentView::PageMode newMode); 149 // emitted, e.g., if a new document was loaded, or if the existing document 150 // has changed (e.g., if it was unlocked) 151 void changedDocument(const QWeakPointer<QtPDF::Backend::Document> newDoc); 152 153 void searchProgressChanged(int percent, int occurrences); 154 void searchResultHighlighted(const int pageNum, const QList<QPolygonF> region); 155 156 void requestOpenUrl(const QUrl url); 157 void requestExecuteCommand(QString command); 158 void requestOpenPdf(QString filename, QtPDF::PDFDestination destination, bool newWindow); 159 void contextClick(const int page, const QPointF pos); 160 161 protected: 162 // Keep track of the current page by overloading the widget paint event. 163 void paintEvent(QPaintEvent *event); 164 void keyPressEvent(QKeyEvent *event); 165 void keyReleaseEvent(QKeyEvent *event); 166 void mousePressEvent(QMouseEvent * event); 167 void mouseMoveEvent(QMouseEvent * event); 168 void mouseReleaseEvent(QMouseEvent * event); 169 void wheelEvent(QWheelEvent * event); 170 void changeEvent(QEvent * event); 171 172 // Maybe this will become public later on 173 // Ownership of tool is transferred to PDFDocumentView 174 void registerTool(DocumentTool::AbstractTool * tool); 175 176 DocumentTool::AbstractTool * getToolByType(const DocumentTool::AbstractTool::Type type); 177 178 void armTool(const DocumentTool::AbstractTool::Type toolType); 179 void armTool(DocumentTool::AbstractTool * tool); 180 void disarmTool(); 181 182 protected slots: 183 void maybeUpdateSceneRect(); 184 void maybeArmTool(uint modifiers); 185 void pdfActionTriggered(const QtPDF::PDFAction * action); 186 // Note: view specifies which part of the page should be visible and must 187 // therefore be given in page coordinates 188 void goToPage(const PDFPageGraphicsItem * page, const QRectF view, const bool mayZoom = false); 189 void goToPage(const PDFPageGraphicsItem * page, const int alignment = Qt::AlignLeft | Qt::AlignTop); 190 void goToPage(const PDFPageGraphicsItem * page, const QPointF anchor, const int alignment = Qt::AlignHCenter | Qt::AlignVCenter); 191 void searchResultReady(int index); 192 void searchProgressValueChanged(int progressValue); 193 void switchInterfaceLocale(const QLocale & newLocale); 194 void reinitializeFromScene(); 195 196 private: 197 PageMode _pageMode; 198 MouseMode _mouseMode; 199 QCursor _hiddenCursor; 200 QVector<DocumentTool::AbstractTool*> _tools; 201 DocumentTool::AbstractTool * _armedTool; 202 QMap<uint, DocumentTool::AbstractTool*> _toolAccessors; 203 204 QStack<PDFDestination> _oldViewRects; 205 206 static QTranslator * _translator; 207 static QString _translatorLanguage; 208 209 // Never try to set a vanilla QGraphicsScene, always use a PDFGraphicsScene. 210 void setScene(QGraphicsScene *scene); 211 // Parent class has no copy constructor. 212 Q_DISABLE_COPY(PDFDocumentView) 213 }; 214 215 class PDFDocumentMagnifierView : public QGraphicsView { 216 Q_OBJECT 217 typedef QGraphicsView Super; 218 219 PDFDocumentView * _parent_view; 220 qreal _zoomLevel, _zoomFactor; 221 222 DocumentTool::MagnifyingGlass::MagnifierShape _shape; 223 int _size; 224 225 public: 226 PDFDocumentMagnifierView(PDFDocumentView *parent = 0); 227 // the zoom factor multiplies the parent view's _zoomLevel 228 void setZoomFactor(const qreal zoomFactor); 229 void setPosition(const QPoint pos); setShape(const DocumentTool::MagnifyingGlass::MagnifierShape shape)230 void setShape(const DocumentTool::MagnifyingGlass::MagnifierShape shape) { setSizeAndShape(_size, shape); } setSize(const int size)231 void setSize(const int size) { setSizeAndShape(size, _shape); } 232 void setSizeAndShape(const int size, const DocumentTool::MagnifyingGlass::MagnifierShape shape); 233 // ensures all settings are in sync with the parent view 234 // make sure you call it before calling show()! 235 // Note: we cannot override show() because prepareToShow() usually needs to be 236 // called before setPosition as well (as it adjusts the region accessible in 237 // setPosition()) 238 void prepareToShow(); 239 240 QPixmap& dropShadow(); 241 242 protected: wheelEvent(QWheelEvent * event)243 void wheelEvent(QWheelEvent * event) { event->ignore(); } 244 void paintEvent(QPaintEvent * event); 245 246 QPixmap _dropShadow; 247 }; 248 249 250 class PDFDocumentInfoWidget : public QWidget 251 { 252 Q_OBJECT 253 friend class PDFDocumentView; 254 public: QWidget(parent)255 PDFDocumentInfoWidget(QWidget * parent = NULL, const QString & title = QString(), const QString & objectName = QString()) : QWidget(parent) { setObjectName(objectName); setWindowTitle(title); } ~PDFDocumentInfoWidget()256 virtual ~PDFDocumentInfoWidget() { } 257 // If the widget has a fixed size, it should not be resized (it can, e.g., be 258 // put into a QScrollArea instead). 259 public slots: 260 void setWindowTitle(const QString & windowTitle); 261 signals: 262 void windowTitleChanged(const QString &); 263 protected slots: initFromDocument(const QWeakPointer<QtPDF::Backend::Document> doc)264 virtual void initFromDocument(const QWeakPointer<QtPDF::Backend::Document> doc) { _doc = doc; } retranslateUi()265 virtual void retranslateUi() { }; 266 virtual void clear() = 0; 267 protected: 268 virtual void changeEvent(QEvent * event); 269 // we need to keep a reference to the document to allow dynamic lookup of data 270 // (e.g., when retranslating the widget) 271 QWeakPointer<QtPDF::Backend::Document> _doc; 272 }; 273 274 class PDFToCInfoWidget : public PDFDocumentInfoWidget 275 { 276 Q_OBJECT 277 public: 278 PDFToCInfoWidget(QWidget * parent); 279 virtual ~PDFToCInfoWidget(); 280 281 protected slots: 282 void initFromDocument(const QWeakPointer<QtPDF::Backend::Document> newDoc); 283 void clear(); 284 virtual void retranslateUi(); 285 signals: 286 void actionTriggered(const QtPDF::PDFAction*); 287 private slots: 288 void itemSelectionChanged(); 289 private: 290 static void recursiveAddTreeItems(const QList<Backend::PDFToCItem> & tocItems, QTreeWidgetItem * parentTreeItem); 291 static void recursiveClearTreeItems(QTreeWidgetItem * parent); 292 QTreeWidget * _tree; 293 }; 294 295 class PDFMetaDataInfoWidget : public PDFDocumentInfoWidget 296 { 297 Q_OBJECT 298 public: 299 PDFMetaDataInfoWidget(QWidget * parent); ~PDFMetaDataInfoWidget()300 virtual ~PDFMetaDataInfoWidget() { } 301 302 protected slots: 303 void initFromDocument(const QWeakPointer<QtPDF::Backend::Document> doc); 304 void clear(); 305 virtual void retranslateUi(); 306 void reload(); 307 private: 308 QGroupBox * _documentGroup; 309 QLabel * _title, * _titleLabel; 310 QLabel * _author, * _authorLabel; 311 QLabel * _subject, * _subjectLabel; 312 QLabel * _keywords, * _keywordsLabel; 313 QGroupBox * _processingGroup; 314 QLabel * _creator, * _creatorLabel; 315 QLabel * _producer, * _producerLabel; 316 QLabel * _creationDate, * _creationDateLabel; 317 QLabel * _modDate, * _modDateLabel; 318 QLabel * _trapped, * _trappedLabel; 319 QGroupBox * _otherGroup; 320 }; 321 322 class PDFFontsInfoWidget : public PDFDocumentInfoWidget 323 { 324 Q_OBJECT 325 public: 326 PDFFontsInfoWidget(QWidget * parent); ~PDFFontsInfoWidget()327 virtual ~PDFFontsInfoWidget() { } 328 329 protected slots: 330 void initFromDocument(const QWeakPointer<QtPDF::Backend::Document> doc); 331 void clear(); 332 virtual void retranslateUi(); 333 void reload(); 334 protected: showEvent(QShowEvent * event)335 virtual void showEvent(QShowEvent * event) { initFromDocument(_doc); } 336 private: 337 QTableWidget * _table; 338 }; 339 340 class PDFPermissionsInfoWidget : public PDFDocumentInfoWidget 341 { 342 Q_OBJECT 343 public: 344 PDFPermissionsInfoWidget(QWidget * parent); ~PDFPermissionsInfoWidget()345 virtual ~PDFPermissionsInfoWidget() { } 346 347 protected slots: 348 void initFromDocument(const QWeakPointer<QtPDF::Backend::Document> doc); 349 void clear(); 350 virtual void retranslateUi(); 351 void reload(); 352 private: 353 QLabel * _print, * _printLabel; 354 QLabel * _modify, * _modifyLabel; 355 QLabel * _extract, * _extractLabel; 356 QLabel * _addNotes, * _addNotesLabel; 357 QLabel * _form, * _formLabel; 358 }; 359 360 class PDFAnnotationsInfoWidget : public PDFDocumentInfoWidget 361 { 362 Q_OBJECT 363 364 QFutureWatcher< QList< QSharedPointer<Annotation::AbstractAnnotation> > > _annotWatcher; 365 QTableWidget * _table; 366 367 static QList< QSharedPointer<Annotation::AbstractAnnotation> > loadAnnotations(QWeakPointer<Backend::Page> thePage); 368 369 public: 370 PDFAnnotationsInfoWidget(QWidget * parent); ~PDFAnnotationsInfoWidget()371 virtual ~PDFAnnotationsInfoWidget() { } 372 373 protected slots: 374 void initFromDocument(const QWeakPointer<QtPDF::Backend::Document> newDoc); 375 void clear(); 376 virtual void retranslateUi(); 377 void annotationsReady(int index); 378 }; 379 380 // Cannot use QGraphicsGridLayout and similar classes for pages because it only 381 // works for QGraphicsLayoutItem (i.e., QGraphicsWidget) 382 class PDFPageLayout : public QObject { 383 Q_OBJECT 384 struct LayoutItem { 385 PDFPageGraphicsItem * page; 386 int row; 387 int col; 388 }; 389 390 QList<LayoutItem> _layoutItems; 391 int _numCols; 392 int _firstCol; 393 qreal _xSpacing; // spacing in pixel @ zoom=1 394 qreal _ySpacing; 395 bool _isContinuous; 396 397 public: 398 PDFPageLayout(); ~PDFPageLayout()399 virtual ~PDFPageLayout() { } columnCount()400 int columnCount() const { return _numCols; } firstColumn()401 int firstColumn() const { return _firstCol; } xSpacing()402 qreal xSpacing() const { return _xSpacing; } ySpacing()403 qreal ySpacing() const { return _ySpacing; } isContinuous()404 bool isContinuous() const { return _isContinuous; } 405 void setContinuous(const bool continuous = true); 406 407 void setColumnCount(const int numCols); 408 void setColumnCount(const int numCols, const int firstCol); 409 void setFirstColumn(const int firstCol); 410 void setXSpacing(const qreal xSpacing); 411 void setYSpacing(const qreal ySpacing); 412 int rowCount() const; 413 414 void addPage(PDFPageGraphicsItem * page); 415 void removePage(PDFPageGraphicsItem * page); 416 void insertPage(PDFPageGraphicsItem * page, PDFPageGraphicsItem * before = NULL); clearPages()417 void clearPages() { _layoutItems.clear(); } 418 419 public slots: 420 void relayout(); 421 422 signals: 423 void layoutChanged(const QRectF sceneRect); 424 425 private: 426 void rearrange(); 427 void continuousModeRelayout(); 428 void singlePageModeRelayout(); 429 }; 430 431 432 class PDFDocumentScene : public QGraphicsScene 433 { 434 Q_OBJECT 435 typedef QGraphicsScene Super; 436 437 const QSharedPointer<Backend::Document> _doc; 438 439 // This may change to a `QSet` in the future 440 QList<QGraphicsItem*> _pages; 441 int _lastPage; 442 PDFPageLayout _pageLayout; 443 QFileSystemWatcher _fileWatcher; 444 QTimer _reloadTimer; 445 double _dpiX, _dpiY; 446 447 void handleActionEvent(const PDFActionEvent * action_event); 448 449 public: 450 PDFDocumentScene(QSharedPointer<Backend::Document> a_doc, QObject *parent = 0, const double dpiX = -1, const double dpiY = -1); 451 452 QWeakPointer<Backend::Document> document(); 453 QList<QGraphicsItem*> pages(); 454 QList<QGraphicsItem*> pages(const QPolygonF &polygon); 455 QGraphicsItem* pageAt(const int idx); 456 QGraphicsItem* pageAt(const QPointF &pt); 457 int pageNumAt(const QPolygonF &polygon); 458 int pageNumAt(const QPointF &pt); 459 int pageNumFor(const PDFPageGraphicsItem * const graphicsItem) const; pageLayout()460 PDFPageLayout& pageLayout() { return _pageLayout; } 461 462 void showOnePage(const int pageIdx); 463 void showOnePage(const PDFPageGraphicsItem * page); 464 void showAllPages(); 465 watchForDocumentChangesOnDisk()466 bool watchForDocumentChangesOnDisk() const { return _fileWatcher.files().size() > 0; } 467 void setWatchForDocumentChangesOnDisk(const bool doWatch = true); 468 469 int lastPage(); 470 document()471 const QWeakPointer<Backend::Document> document() const { return _doc.toWeakRef(); } 472 473 void setResolution(const double dpiX, const double dpiY); 474 475 signals: 476 void pageChangeRequested(int pageNum); 477 void pageLayoutChanged(); 478 void pdfActionTriggered(const QtPDF::PDFAction * action); 479 void documentChanged(const QWeakPointer<QtPDF::Backend::Document> doc); 480 481 public slots: 482 void doUnlockDialog(); 483 void retranslateUi(); 484 void reloadDocument(); 485 486 protected slots: 487 void pageLayoutChanged(const QRectF& sceneRect); 488 void reinitializeScene(); 489 void finishUnlock(); 490 491 protected: 492 // Used in non-continuous mode to keep track of currently shown page across 493 // reloads. -2 is used in continuous mode. -1 indicates an invalid value. 494 int _shownPageIdx; 495 bool event(QEvent* event); 496 497 QWidget * _unlockWidget; 498 QLabel * _unlockWidgetLockText, * _unlockWidgetLockIcon; 499 QPushButton * _unlockWidgetUnlockButton; 500 501 private: 502 // Parent has no copy constructor, so this class shouldn't either. Also, we 503 // hold some information in an `auto_ptr` which does interesting things on 504 // copy that C++ newbies may not expect. 505 Q_DISABLE_COPY(PDFDocumentScene) 506 }; 507 508 509 // Inherits from `QGraphicsOject` instead of `QGraphicsItem` in order to 510 // support SIGNALS/SLOTS used by threaded rendering. 511 // 512 // NOTE: __`QGraphicsObject` was added in Qt 4.6__ 513 class PDFPageGraphicsItem : public QGraphicsObject 514 { 515 Q_OBJECT 516 typedef QGraphicsObject Super; 517 518 QWeakPointer<Backend::Page> _page; 519 520 double _dpiX; 521 double _dpiY; 522 // the nominal (i.e., unmagnified) page size in pixel 523 QSizeF _pageSize; 524 int _pageNum; 525 526 bool _linksLoaded; 527 bool _annotationsLoaded; 528 529 QTransform _pageScale, _pointScale; 530 qreal _zoomLevel; 531 532 friend class PageProcessingRenderPageRequest; 533 friend class PageProcessingLoadLinksRequest; 534 // friend class PDFPageLayout; 535 536 static void imageToGrayScale(QImage & img); 537 538 public: 539 PDFPageGraphicsItem(QWeakPointer<Backend::Page> a_page, const double dpiX, const double dpiY, QGraphicsItem *parent = 0); 540 541 // This seems fragile as it assumes no other code declaring a custom graphics 542 // item will choose the same ID for it's object types. Unfortunately, there 543 // appears to be no equivalent of `registerEventType` for `QGraphicsItem` 544 // subclasses. 545 enum { Type = UserType + 1 }; 546 int type() const; 547 548 void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 549 550 virtual QRectF boundingRect() const; 551 page()552 QWeakPointer<Backend::Page> page() const { return _page; } 553 554 // Maps the point _point_ from the page's coordinate system (in pt) to this 555 // item's coordinate system - chain with mapToScene and related methods to get 556 // coordinates in other systems 557 QPointF mapFromPage(const QPointF & point) const; 558 // Maps the point _point_ from the item's coordinate system to the page's 559 // coordinate system (in pt) - chain with mapFromScene and related methods to 560 // convert from coordinates in other systems 561 QPointF mapToPage(const QPointF & point) const; 562 pageScale()563 QTransform pageScale() { return _pageScale; } pointScale()564 QTransform pointScale() { return _pointScale; } 565 566 // get the nominal (i.e., unmagnified) page size in pixel pageSizeF()567 QSizeF pageSizeF() const { return _pageSize; } pageNum()568 int pageNum() const { return _pageNum; } 569 570 protected: 571 bool event(QEvent *event); 572 573 private: 574 // Parent has no copy constructor. 575 Q_DISABLE_COPY(PDFPageGraphicsItem) 576 577 private slots: 578 void addLinks(QList< QSharedPointer<Annotation::Link> > links); 579 void addAnnotations(QList< QSharedPointer<Annotation::AbstractAnnotation> > annotations); 580 }; 581 582 // TODO: Should be turned into a QGraphicsPolygonItem 583 class PDFLinkGraphicsItem : public QGraphicsRectItem { 584 typedef QGraphicsRectItem Super; 585 586 QSharedPointer<Annotation::Link> _link; 587 bool _activated; 588 589 public: 590 PDFLinkGraphicsItem(QSharedPointer<Annotation::Link> a_link, QGraphicsItem *parent = 0); 591 // See concerns in `PDFPageGraphicsItem` for why this feels fragile. 592 enum { Type = UserType + 2 }; 593 int type() const; 594 void retranslateUi(); 595 596 protected: 597 void hoverEnterEvent(QGraphicsSceneHoverEvent *event); 598 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); 599 600 void mousePressEvent(QGraphicsSceneMouseEvent *event); 601 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); 602 603 private: 604 // Parent class has no copy constructor. 605 Q_DISABLE_COPY(PDFLinkGraphicsItem) 606 }; 607 608 609 // TODO: Should be turned into a QGraphicsPolygonItem 610 class PDFMarkupAnnotationGraphicsItem : public QGraphicsRectItem { 611 typedef QGraphicsRectItem Super; 612 613 QSharedPointer<Annotation::Markup> _annot; 614 bool _activated; 615 QWidget * _popup; 616 617 public: 618 PDFMarkupAnnotationGraphicsItem(QSharedPointer<Annotation::Markup> annot, QGraphicsItem *parent = 0); 619 // See concerns in `PDFPageGraphicsItem` for why this feels fragile. 620 enum { Type = UserType + 3 }; 621 int type() const; 622 623 protected: 624 void hoverEnterEvent(QGraphicsSceneHoverEvent *event); 625 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); 626 627 void mousePressEvent(QGraphicsSceneMouseEvent *event); 628 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); 629 630 private: 631 // Parent class has no copy constructor. 632 Q_DISABLE_COPY(PDFMarkupAnnotationGraphicsItem) 633 }; 634 635 class PDFActionEvent : public QEvent { 636 typedef QEvent Super; 637 638 public: 639 PDFActionEvent(const PDFAction * action); 640 static QEvent::Type ActionEvent; 641 const PDFAction * action; 642 }; 643 644 } // namespace QtPDF 645 646 // Note: Q_DECLARE_METATYPE must be specified _outside_ any namespace 647 // declaration (according to Qt docs) 648 649 // We need to declare a QList<PDFLinkGraphicsItem *> meta-type so we can 650 // pass it through inter-thread (i.e., queued) connections 651 Q_DECLARE_METATYPE(QList<QtPDF::PDFLinkGraphicsItem *>) 652 // We need to declare a QList<PDFMarkupAnnotationGraphicsItem *> meta-type so we can 653 // pass it through inter-thread (i.e., queued) connections 654 Q_DECLARE_METATYPE(QList<QtPDF::PDFMarkupAnnotationGraphicsItem *>) 655 656 657 #endif // End header include guard 658 659 // vim: set sw=2 ts=2 et 660