1 /* 2 SPDX-FileCopyrightText: 2017 Tobias Deiminger <haxtibal@t-online.de> 3 SPDX-FileCopyrightText: 2004-2005 Enrico Ros <eros.kde@email.it> 4 SPDX-FileCopyrightText: 2004-2006 Albert Astals Cid <aacid@kde.org> 5 6 Work sponsored by the LiMux project of the city of Munich: 7 SPDX-FileCopyrightText: 2017 Klarälvdalens Datakonsult AB a KDAB Group company <info@kdab.com> 8 9 With portions of code from kpdf/kpdf_pagewidget.cc by: 10 SPDX-FileCopyrightText: 2002 Wilco Greven <greven@kde.org> 11 SPDX-FileCopyrightText: 2003 Christophe Devriese <Christophe.Devriese@student.kuleuven.ac.be> 12 SPDX-FileCopyrightText: 2003 Laurent Montel <montel@kde.org> 13 SPDX-FileCopyrightText: 2003 Dirk Mueller <mueller@kde.org> 14 SPDX-FileCopyrightText: 2004 James Ots <kde@jamesots.com> 15 SPDX-FileCopyrightText: 2011 Jiri Baum - NICTA <jiri@baum.com.au> 16 17 SPDX-License-Identifier: GPL-2.0-or-later 18 */ 19 20 #ifndef _OKULAR_PAGEVIEWMOUSEANNOTATION_H_ 21 #define _OKULAR_PAGEVIEWMOUSEANNOTATION_H_ 22 23 #include <QObject> 24 25 #include "core/annotations.h" 26 #include "pageviewutils.h" 27 28 class QHelpEvent; 29 class QPainter; 30 class QPoint; 31 class PageView; 32 class PageViewItem; 33 class AnnotationDescription; 34 35 namespace Okular 36 { 37 class Document; 38 } 39 40 /* This class shall help to keep data for one annotation consistent. */ 41 class AnnotationDescription 42 { 43 public: AnnotationDescription()44 AnnotationDescription() 45 : annotation(nullptr) 46 , pageViewItem(nullptr) 47 , pageNumber(-1) 48 { 49 } 50 AnnotationDescription(PageViewItem *newPageViewItem, const QPoint eventPos); 51 bool isValid() const; 52 bool isContainedInPage(const Okular::Document *document, int pageNumber) const; 53 void invalidate(); 54 bool operator==(const AnnotationDescription &rhs) const 55 { 56 return (annotation == rhs.annotation); 57 } 58 Okular::Annotation *annotation; 59 PageViewItem *pageViewItem; 60 int pageNumber; 61 }; 62 63 /** 64 * @short Handle UI for annotation interactions, like moving, resizing and triggering actions. 65 * 66 * An object of this class tracks which annotation is currently under the mouse cursor. 67 * Some annotation types can be focused in order to move or resize them. 68 * State is determined from mouse and keyboard events, which are forwarded from the parent PageView object. 69 * Move and resize actions are dispatched to the Document object. 70 */ 71 class MouseAnnotation : public QObject 72 { 73 Q_OBJECT 74 75 public: 76 MouseAnnotation(PageView *parent, Okular::Document *document); 77 ~MouseAnnotation() override; 78 79 /* Process a mouse press event. eventPos: Mouse position in content area coordinates. */ 80 void routeMousePressEvent(PageViewItem *pageViewItem, const QPoint eventPos); 81 82 /* Process a mouse release event. */ 83 void routeMouseReleaseEvent(); 84 85 /* Process a mouse move event. eventPos: Mouse position in content area coordinates. */ 86 void routeMouseMoveEvent(PageViewItem *pageViewItem, const QPoint eventPos, bool leftButtonPressed); 87 88 /* Process a key event. */ 89 void routeKeyPressEvent(const QKeyEvent *e); 90 91 /* Process a tooltip event. eventPos: Mouse position in content area coordinates. */ 92 void routeTooltipEvent(const QHelpEvent *helpEvent); 93 94 /* Process a paint event. */ 95 void routePaint(QPainter *painter, const QRect paintRect); 96 97 /* Cancel the current selection or action, if any. */ 98 void cancel(); 99 100 /* Reset to initial state. Cancel current action and relinquish references to PageViewItem widgets. */ 101 void reset(); 102 103 Okular::Annotation *annotation() const; 104 105 /* Return true, if MouseAnnotation demands control for a mouse click on the current cursor position. */ 106 bool isMouseOver() const; 107 108 bool isActive() const; 109 110 bool isFocused() const; 111 112 bool isMoved() const; 113 114 bool isResized() const; 115 116 bool isModified() const; 117 118 Qt::CursorShape cursor() const; 119 120 /* Forward DocumentObserver::notifyPageChanged to this method. */ 121 void notifyAnnotationChanged(int pageNumber); 122 123 /* Forward DocumentObserver::notifySetup to this method. */ 124 void updateAnnotationPointers(); 125 126 enum MouseAnnotationState { StateInactive, StateFocused, StateMoving, StateResizing }; 127 128 enum ResizeHandleFlag { 129 RH_None = 0, 130 RH_Top = 1, 131 RH_Right = 2, 132 RH_Bottom = 4, 133 RH_Left = 8, 134 RH_TopLeft = RH_Top | RH_Left, 135 RH_BottomLeft = RH_Bottom | RH_Left, 136 RH_TopRight = RH_Top | RH_Right, 137 RH_BottomRight = RH_Bottom | RH_Right, 138 RH_Content = 16, 139 RH_AllHandles = RH_Top | RH_Right | RH_Bottom | RH_Left 140 }; 141 Q_DECLARE_FLAGS(ResizeHandle, ResizeHandleFlag) 142 143 private: 144 void setState(MouseAnnotationState state, const AnnotationDescription &ad); 145 QRect getFullBoundingRect(const AnnotationDescription &ad) const; 146 void performCommand(const QPoint newPos); 147 void finishCommand(); 148 void updateViewport(const AnnotationDescription &ad) const; 149 ResizeHandle getHandleAt(const QPoint eventPos, const AnnotationDescription &ad) const; 150 QRect getHandleRect(ResizeHandle handle, const AnnotationDescription &ad) const; 151 static void handleToAdjust(const QPointF dIn, QPointF &dOut1, QPointF &dOut2, MouseAnnotation::ResizeHandle handle, Okular::Rotation rotation); 152 static QPointF rotateInRect(const QPointF rotated, Okular::Rotation rotation); 153 static ResizeHandle rotateHandle(ResizeHandle handle, Okular::Rotation rotation); 154 void processAction(const AnnotationDescription &ad); 155 156 /* We often have to delegate to the document model and our parent widget. */ 157 Okular::Document *m_document; 158 PageView *m_pageView; 159 160 /* Remember which annotation is currently focused/modified. */ 161 MouseAnnotationState m_state; 162 MouseAnnotation::ResizeHandle m_handle; 163 AnnotationDescription m_focusedAnnotation; 164 165 /* Mouse tracking, always kept up to date with the latest mouse position and annotation under mouse cursor. */ 166 AnnotationDescription m_mouseOverAnnotation; 167 QPoint m_mousePosition; // in page view item coordinates 168 169 QList<ResizeHandle> m_resizeHandleList; 170 }; 171 172 #endif 173