1 /*
2     SPDX-FileCopyrightText: 2004-2005 Enrico Ros <eros.kde@email.it>
3     SPDX-FileCopyrightText: 2004-2007 Albert Astals Cid <aacid@kde.org>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #ifndef _OKULAR_DOCUMENT_P_H_
9 #define _OKULAR_DOCUMENT_P_H_
10 
11 #include "document.h"
12 #include "script/event_p.h"
13 
14 #include "synctex/synctex_parser.h"
15 #include <memory>
16 
17 // qt/kde/system includes
18 #include <KConfigDialog>
19 #include <KPluginMetaData>
20 #include <QHash>
21 #include <QLinkedList>
22 #include <QMap>
23 #include <QMutex>
24 #include <QPointer>
25 #include <QUrl>
26 
27 // local includes
28 #include "fontinfo.h"
29 #include "generator.h"
30 
31 class QUndoStack;
32 class QEventLoop;
33 class QFile;
34 class QTimer;
35 class QTemporaryFile;
36 class KPluginMetaData;
37 
38 struct AllocatedPixmap;
39 struct ArchiveData;
40 struct RunningSearch;
41 
42 namespace Okular
43 {
44 class ScriptAction;
45 class ConfigInterface;
46 class PageController;
47 class SaveInterface;
48 class Scripter;
49 class View;
50 }
51 
52 struct GeneratorInfo {
GeneratorInfoGeneratorInfo53     explicit GeneratorInfo(Okular::Generator *g, const KPluginMetaData &data)
54         : generator(g)
55         , metadata(data)
56         , config(nullptr)
57         , save(nullptr)
58         , configChecked(false)
59         , saveChecked(false)
60     {
61     }
62 
63     Okular::Generator *generator;
64     KPluginMetaData metadata;
65     Okular::ConfigInterface *config;
66     Okular::SaveInterface *save;
67     bool configChecked : 1;
68     bool saveChecked : 1;
69 };
70 
71 namespace Okular
72 {
73 class OKULARCORE_EXPORT BackendConfigDialog : public KConfigDialog
74 {
75     Q_OBJECT
76 public:
BackendConfigDialog(QWidget * parent,const QString & name,KCoreConfigSkeleton * config)77     BackendConfigDialog(QWidget *parent, const QString &name, KCoreConfigSkeleton *config)
78         : KConfigDialog(parent, name, config)
79     {
80     }
81 
thePageWidget()82     KPageWidget *thePageWidget()
83     {
84         return pageWidget();
85     }
86 };
87 
88 class FontExtractionThread;
89 
90 struct DoContinueDirectionMatchSearchStruct {
91     QSet<int> *pagesToNotify;
92     RegularAreaRect *match;
93     int currentPage;
94     int searchID;
95 };
96 
97 enum LoadDocumentInfoFlag {
98     LoadNone = 0,
99     LoadPageInfo = 1,    // Load annotations and forms
100     LoadGeneralInfo = 2, // History, rotation, ...
101     LoadAllInfo = 0xff
102 };
Q_DECLARE_FLAGS(LoadDocumentInfoFlags,LoadDocumentInfoFlag)103 Q_DECLARE_FLAGS(LoadDocumentInfoFlags, LoadDocumentInfoFlag)
104 
105 class DocumentPrivate
106 {
107 public:
108     explicit DocumentPrivate(Document *parent)
109         : m_parent(parent)
110         , m_tempFile(nullptr)
111         , m_docSize(-1)
112         , m_allocatedPixmapsTotalMemory(0)
113         , m_maxAllocatedTextPages(0)
114         , m_warnedOutOfMemory(false)
115         , m_rotation(Rotation0)
116         , m_exportCached(false)
117         , m_bookmarkManager(nullptr)
118         , m_memCheckTimer(nullptr)
119         , m_saveBookmarksTimer(nullptr)
120         , m_generator(nullptr)
121         , m_walletGenerator(nullptr)
122         , m_generatorsLoaded(false)
123         , m_pageController(nullptr)
124         , m_closingLoop(nullptr)
125         , m_scripter(nullptr)
126         , m_archiveData(nullptr)
127         , m_fontsCached(false)
128         , m_annotationEditingEnabled(true)
129         , m_annotationBeingModified(false)
130         , m_docdataMigrationNeeded(false)
131         , m_synctex_scanner(nullptr)
132     {
133         calculateMaxTextPages();
134     }
135 
136     // private methods
137     bool updateMetadataXmlNameAndDocSize();
138     QString pagesSizeString() const;
139     QString namePaperSize(double inchesWidth, double inchesHeight) const;
140     QString localizedSize(const QSizeF size) const;
141     qulonglong calculateMemoryToFree();
142     void cleanupPixmapMemory();
143     void cleanupPixmapMemory(qulonglong memoryToFree);
144     AllocatedPixmap *searchLowestPriorityPixmap(bool unloadableOnly = false, bool thenRemoveIt = false, DocumentObserver *observer = nullptr /* any */);
145     void calculateMaxTextPages();
146     qulonglong getTotalMemory();
147     qulonglong getFreeMemory(qulonglong *freeSwap = nullptr);
148     bool loadDocumentInfo(LoadDocumentInfoFlags loadWhat);
149     bool loadDocumentInfo(QFile &infoFile, LoadDocumentInfoFlags loadWhat);
150     void loadViewsInfo(View *view, const QDomElement &e);
151     void saveViewsInfo(View *view, QDomElement &e) const;
152     QUrl giveAbsoluteUrl(const QString &fileName) const;
153     bool openRelativeFile(const QString &fileName);
154     Generator *loadGeneratorLibrary(const KPluginMetaData &service);
155     void loadAllGeneratorLibraries();
156     void loadServiceList(const QVector<KPluginMetaData> &offers);
157     void unloadGenerator(const GeneratorInfo &info);
158     void cacheExportFormats();
159     void setRotationInternal(int r, bool notify);
160     ConfigInterface *generatorConfig(GeneratorInfo &info);
161     SaveInterface *generatorSave(GeneratorInfo &info);
162     Document::OpenResult openDocumentInternal(const KPluginMetaData &offer, bool isstdin, const QString &docFile, const QByteArray &filedata, const QString &password);
163     static ArchiveData *unpackDocumentArchive(const QString &archivePath);
164     bool savePageDocumentInfo(QTemporaryFile *infoFile, int what) const;
165     DocumentViewport nextDocumentViewport() const;
166     void notifyAnnotationChanges(int page);
167     void notifyFormChanges(int page);
168     bool canAddAnnotationsNatively() const;
169     bool canModifyExternalAnnotations() const;
170     bool canRemoveExternalAnnotations() const;
171     OKULARCORE_EXPORT static QString docDataFileName(const QUrl &url, qint64 document_size);
172     bool cancelRenderingBecauseOf(PixmapRequest *executingRequest, PixmapRequest *newRequest);
173 
174     // Methods that implement functionality needed by undo commands
175     void performAddPageAnnotation(int page, Annotation *annotation);
176     void performRemovePageAnnotation(int page, Annotation *annotation);
177     void performModifyPageAnnotation(int page, Annotation *annotation, bool appearanceChanged);
178     void performSetAnnotationContents(const QString &newContents, Annotation *annot, int pageNumber);
179 
180     void recalculateForms();
181 
182     // private slots
183     void saveDocumentInfo() const;
184     void slotTimedMemoryCheck();
185     void sendGeneratorPixmapRequest();
186     void rotationFinished(int page, Okular::Page *okularPage);
187     void slotFontReadingProgress(int page);
188     void fontReadingGotFont(const Okular::FontInfo &font);
189     void slotGeneratorConfigChanged();
190     void refreshPixmaps(int);
191     void _o_configChanged();
192     void doContinueDirectionMatchSearch(void *doContinueDirectionMatchSearchStruct);
193     void doContinueAllDocumentSearch(void *pagesToNotifySet, void *pageMatchesMap, int currentPage, int searchID);
194     void doContinueGooglesDocumentSearch(void *pagesToNotifySet, void *pageMatchesMap, int currentPage, int searchID, const QStringList &words);
195 
196     void doProcessSearchMatch(RegularAreaRect *match, RunningSearch *search, QSet<int> *pagesToNotify, int currentPage, int searchID, bool moveViewport, const QColor &color);
197 
198     /**
199      * Executes a JavaScript script from the setInterval function.
200      *
201      * @since 1.9
202      */
203     void executeScript(const QString &function);
204 
205     // generators stuff
206     /**
207      * This method is used by the generators to signal the finish of
208      * the pixmap generation @p request.
209      */
210     void requestDone(PixmapRequest *request);
211     void textGenerationDone(Page *page);
212     /**
213      * Sets the bounding box of the given @p page (in terms of upright orientation, i.e., Rotation0).
214      */
215     void setPageBoundingBox(int page, const NormalizedRect &boundingBox);
216 
217     /**
218      * Request a particular metadata of the Document itself (ie, not something
219      * depending on the document type/backend).
220      */
221     QVariant documentMetaData(const Generator::DocumentMetaDataKey key, const QVariant &option) const;
222 
223     /**
224      * Return whether the normalized rectangle @p rectOfInterest on page number @p rectPage
225      * is fully visible.
226      */
227     bool isNormalizedRectangleFullyVisible(const Okular::NormalizedRect &rectOfInterest, int rectPage);
228 
229     // For sync files
230     void loadSyncFile(const QString &filePath);
231 
232     void clearAndWaitForRequests();
233 
234     /*
235      * Executes a ScriptAction with the event passed as parameter.
236      */
237     void executeScriptEvent(const std::shared_ptr<Event> &event, const Okular::ScriptAction *linkscript);
238 
239     /*
240      * Find the corresponding page number for the form field passed as parameter.
241      */
242     int findFieldPageNumber(Okular::FormField *field);
243 
244     // member variables
245     Document *m_parent;
246     QPointer<QWidget> m_widget;
247 
248     // find descriptors, mapped by ID (we handle multiple searches)
249     QMap<int, RunningSearch *> m_searches;
250     bool m_searchCancelled;
251 
252     // needed because for remote documents docFileName is a local file and
253     // we want the remote url when the document refers to relativeNames
254     QUrl m_url;
255 
256     // cached stuff
257     QString m_docFileName;
258     QString m_xmlFileName;
259     QTemporaryFile *m_tempFile;
260     qint64 m_docSize;
261 
262     // viewport stuff
263     QLinkedList<DocumentViewport> m_viewportHistory;
264     QLinkedList<DocumentViewport>::iterator m_viewportIterator;
265     DocumentViewport m_nextDocumentViewport; // see Link::Goto for an explanation
266     QString m_nextDocumentDestination;
267 
268     // observers / requests / allocator stuff
269     QSet<DocumentObserver *> m_observers;
270     QLinkedList<PixmapRequest *> m_pixmapRequestsStack;
271     QLinkedList<PixmapRequest *> m_executingPixmapRequests;
272     QMutex m_pixmapRequestsMutex;
273     QLinkedList<AllocatedPixmap *> m_allocatedPixmaps;
274     qulonglong m_allocatedPixmapsTotalMemory;
275     QList<int> m_allocatedTextPagesFifo;
276     int m_maxAllocatedTextPages;
277     bool m_warnedOutOfMemory;
278 
279     // the rotation applied to the document
280     Rotation m_rotation;
281 
282     // the current size of the pages (if available), and the cache of the
283     // available page sizes
284     PageSize m_pageSize;
285     PageSize::List m_pageSizes;
286 
287     // cache of the export formats
288     bool m_exportCached;
289     ExportFormat::List m_exportFormats;
290     ExportFormat m_exportToText;
291 
292     // our bookmark manager
293     BookmarkManager *m_bookmarkManager;
294 
295     // timers (memory checking / info saver)
296     QTimer *m_memCheckTimer;
297     QTimer *m_saveBookmarksTimer;
298 
299     QHash<QString, GeneratorInfo> m_loadedGenerators;
300     Generator *m_generator;
301     QString m_generatorName;
302     Generator *m_walletGenerator;
303     bool m_generatorsLoaded;
304     QVector<Page *> m_pagesVector;
305     QVector<VisiblePageRect *> m_pageRects;
306 
307     // cache of the mimetype we support
308     QStringList m_supportedMimeTypes;
309 
310     PageController *m_pageController;
311     QEventLoop *m_closingLoop;
312 
313     Scripter *m_scripter;
314 
315     ArchiveData *m_archiveData;
316     QString m_archivedFileName;
317 
318     QPointer<FontExtractionThread> m_fontThread;
319     bool m_fontsCached;
320     QSet<DocumentInfo::Key> m_documentInfoAskedKeys;
321     DocumentInfo m_documentInfo;
322     FontInfo::List m_fontsCache;
323 
324     QSet<View *> m_views;
325 
326     bool m_annotationEditingEnabled;
327     bool m_annotationBeingModified; // is an annotation currently being moved or resized?
328     bool m_metadataLoadingCompleted;
329 
330     QUndoStack *m_undoStack;
331     QDomNode m_prevPropsOfAnnotBeingModified;
332 
333     // Since 0.21, we no longer support saving annotations and form data in
334     // the docdata/ directory and we ask the user to migrate them to an
335     // external file as soon as possible, otherwise the document will be
336     // shown in read-only mode. This flag is set if the docdata/ XML file
337     // for the current document contains any annotation or form.
338     bool m_docdataMigrationNeeded;
339 
340     synctex_scanner_p m_synctex_scanner;
341 
342     QString m_openError;
343 
344     // generator selection
345     static QVector<KPluginMetaData> availableGenerators();
346     static QVector<KPluginMetaData> configurableGenerators();
347     static KPluginMetaData generatorForMimeType(const QMimeType &type, QWidget *widget, const QVector<KPluginMetaData> &triedOffers = QVector<KPluginMetaData>());
348 };
349 
350 class DocumentInfoPrivate
351 {
352 public:
353     QMap<QString, QString> values; // key -> value
354     QMap<QString, QString> titles; // key -> title For the custom keys
355 };
356 
357 }
358 
359 #endif
360 
361 /* kate: replace-tabs on; indent-width 4; */
362