1 /*
2     SPDX-FileCopyrightText: 2004 Enrico Ros <eros.kde@email.it>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #ifndef _OKULAR_PRESENTATIONWIDGET_H_
8 #define _OKULAR_PRESENTATIONWIDGET_H_
9 
10 #include "core/area.h"
11 #include "core/observer.h"
12 #include "core/pagetransition.h"
13 #include <QDomElement>
14 #include <QList>
15 #include <QPixmap>
16 #include <QStringList>
17 #include <qwidget.h>
18 
19 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) // TODO Qt6: These are needed for oldQt_screenOf().
20 #include <QApplication>
21 #include <QScreen>
22 #include <QWindow>
23 #endif
24 
25 class QLineEdit;
26 class QToolBar;
27 class QTimer;
28 class QGestureEvent;
29 class KActionCollection;
30 class KSelectAction;
31 class SmoothPathEngine;
32 struct PresentationFrame;
33 class PresentationSearchBar;
34 class DrawingToolActions;
35 
36 namespace Okular
37 {
38 class Action;
39 class Annotation;
40 class Document;
41 class MovieAction;
42 class Page;
43 class RenditionAction;
44 }
45 
46 /**
47  * @short A widget that shows pages as fullscreen slides (with transitions fx).
48  *
49  * This is a fullscreen widget that displays
50  */
51 class PresentationWidget : public QWidget, public Okular::DocumentObserver
52 {
53     Q_OBJECT
54 public:
55     PresentationWidget(QWidget *parent, Okular::Document *doc, DrawingToolActions *drawingToolActions, KActionCollection *collection);
56     ~PresentationWidget() override;
57 
58     // inherited from DocumentObserver
59     void notifySetup(const QVector<Okular::Page *> &pages, int setupFlags) override;
60     void notifyViewportChanged(bool smoothMove) override;
61     void notifyPageChanged(int pageNumber, int changedFlags) override;
62     bool canUnloadPixmap(int pageNumber) const override;
63     void notifyCurrentPageChanged(int previous, int current) override;
64 
65 public Q_SLOTS:
66     void slotFind();
67 
68 protected:
69     // widget events
70     bool event(QEvent *e) override;
71     void keyPressEvent(QKeyEvent *e) override;
72     void wheelEvent(QWheelEvent *e) override;
73     void mousePressEvent(QMouseEvent *e) override;
74     void mouseReleaseEvent(QMouseEvent *e) override;
75     void mouseMoveEvent(QMouseEvent *e) override;
76     void paintEvent(QPaintEvent *e) override;
77     void resizeEvent(QResizeEvent *e) override;
78     void enterEvent(QEvent *e) override;
79     void leaveEvent(QEvent *e) override;
80     bool gestureEvent(QGestureEvent *e);
81 
82     // Catch TabletEnterProximity and TabletLeaveProximity events from the QApplication
83     bool eventFilter(QObject *o, QEvent *ev) override;
84 
85 private:
86     const void *getObjectRect(Okular::ObjectRect::ObjectType type, int x, int y, QRect *geometry = nullptr) const;
87     const Okular::Action *getLink(int x, int y, QRect *geometry = nullptr) const;
88     const Okular::Annotation *getAnnotation(int x, int y, QRect *geometry = nullptr) const;
89     void testCursorOnLink(int x, int y);
90     void overlayClick(const QPoint position);
91     void changePage(int newPage);
92     void generatePage(bool disableTransition = false);
93     void generateIntroPage(QPainter &p);
94     void generateContentsPage(int page, QPainter &p);
95     void generateOverlay();
96     void initTransition(const Okular::PageTransition *transition);
97     const Okular::PageTransition defaultTransition() const;
98     const Okular::PageTransition defaultTransition(int) const;
99     QRect routeMouseDrawingEvent(QMouseEvent *);
100     void startAutoChangeTimer();
101     /** @returns Configure -> Presentation -> Preferred screen */
102     QScreen *defaultScreen() const;
103     void requestPixmaps();
104     /** @param newScreen must be valid. */
105     void setScreen(const QScreen *newScreen);
106     void inhibitPowerManagement();
107     void allowPowerManagement();
108     void showTopBar(bool);
109     // create actions that interact with this widget
110     void setupActions();
111     void setPlayPauseIcon();
112 
113     // cache stuff
114     int m_width;
115     int m_height;
116     QPixmap m_lastRenderedPixmap;
117     QPixmap m_lastRenderedOverlay;
118     QRect m_overlayGeometry;
119     const Okular::Action *m_pressedLink;
120     bool m_handCursor;
121     SmoothPathEngine *m_drawingEngine;
122     QRect m_drawingRect;
123     uint m_screenInhibitCookie;
124     int m_sleepInhibitFd;
125 
126     // transition related
127     QTimer *m_transitionTimer;
128     QTimer *m_overlayHideTimer;
129     QTimer *m_nextPageTimer;
130     int m_transitionDelay;
131     int m_transitionMul;
132     int m_transitionSteps;
133     QList<QRect> m_transitionRects;
134     Okular::PageTransition m_currentTransition;
135     QPixmap m_currentPagePixmap;
136     QPixmap m_previousPagePixmap;
137     double m_currentPixmapOpacity;
138 
139     // misc stuff
140     QWidget *m_parentWidget;
141     Okular::Document *m_document;
142     QVector<PresentationFrame *> m_frames;
143     int m_frameIndex;
144     QStringList m_metaStrings;
145     QToolBar *m_topBar;
146     QLineEdit *m_pagesEdit;
147     PresentationSearchBar *m_searchBar;
148     KActionCollection *m_ac;
149     KSelectAction *m_screenSelect;
150     QDomElement m_currentDrawingToolElement;
151     bool m_isSetup;
152     bool m_blockNotifications;
153     bool m_inBlackScreenMode;
154     bool m_showSummaryView;
155     bool m_advanceSlides;
156     bool m_goToPreviousPageOnRelease;
157     bool m_goToNextPageOnRelease;
158 
159     /** TODO Qt6: Just use QWidget::screen() instead of this. */
oldQt_screenOf(const QWidget * widget)160     static inline QScreen *oldQt_screenOf(const QWidget *widget)
161     {
162 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
163         return widget->screen();
164 #else
165         if (widget->window() && widget->window()->windowHandle() && widget->window()->windowHandle()->screen()) {
166             return widget->window()->windowHandle()->screen();
167         } else {
168             return QApplication::primaryScreen();
169         }
170 #endif
171     }
172 
173 private Q_SLOTS:
174     void slotNextPage();
175     void slotPrevPage();
176     void slotFirstPage();
177     void slotLastPage();
178     void slotHideOverlay();
179     void slotTransitionStep();
180     void slotDelayedEvents();
181     void slotPageChanged();
182     void clearDrawings();
183     void chooseScreen(QAction *);
184     void toggleBlackScreenMode(bool);
185     void slotProcessMovieAction(const Okular::MovieAction *action);
186     void slotProcessRenditionAction(const Okular::RenditionAction *action);
187     void slotTogglePlayPause();
188     void slotChangeDrawingToolEngine(const QDomElement &element);
189     void slotAddDrawingToolActions();
190 };
191 
192 #endif
193