File indexing completed on 2024-04-28 04:32:41

0001 /*
0002     SPDX-FileCopyrightText: 2004-2005 Enrico Ros <eros.kde@email.it>
0003     SPDX-FileCopyrightText: 2004-2007 Albert Astals Cid <aacid@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef _OKULAR_DOCUMENT_P_H_
0009 #define _OKULAR_DOCUMENT_P_H_
0010 
0011 #include "document.h"
0012 #include "script/event_p.h"
0013 
0014 #include "synctex/synctex_parser.h"
0015 #include <memory>
0016 
0017 // qt/kde/system includes
0018 #include <KConfigDialog>
0019 #include <KPluginMetaData>
0020 #include <QHash>
0021 #include <QMap>
0022 #include <QMutex>
0023 #include <QPointer>
0024 #include <QUrl>
0025 
0026 // local includes
0027 #include "fontinfo.h"
0028 #include "generator.h"
0029 
0030 class QUndoStack;
0031 class QEventLoop;
0032 class QFile;
0033 class QTimer;
0034 class QTemporaryFile;
0035 class KPluginMetaData;
0036 
0037 struct AllocatedPixmap;
0038 struct ArchiveData;
0039 struct RunningSearch;
0040 
0041 namespace Okular
0042 {
0043 class ScriptAction;
0044 class ConfigInterface;
0045 class PageController;
0046 class SaveInterface;
0047 class Scripter;
0048 class View;
0049 }
0050 
0051 struct GeneratorInfo {
0052     explicit GeneratorInfo(Okular::Generator *g, const KPluginMetaData &data)
0053         : generator(g)
0054         , metadata(data)
0055         , config(nullptr)
0056         , save(nullptr)
0057         , configChecked(false)
0058         , saveChecked(false)
0059     {
0060     }
0061 
0062     Okular::Generator *generator;
0063     KPluginMetaData metadata;
0064     Okular::ConfigInterface *config;
0065     Okular::SaveInterface *save;
0066     bool configChecked : 1;
0067     bool saveChecked : 1;
0068 };
0069 
0070 namespace Okular
0071 {
0072 class OKULARCORE_EXPORT BackendConfigDialog : public KConfigDialog
0073 {
0074     Q_OBJECT
0075 public:
0076     BackendConfigDialog(QWidget *parent, const QString &name, KCoreConfigSkeleton *config)
0077         : KConfigDialog(parent, name, config)
0078     {
0079     }
0080 
0081     KPageWidget *thePageWidget()
0082     {
0083         return pageWidget();
0084     }
0085 };
0086 
0087 class FontExtractionThread;
0088 
0089 struct DoContinueDirectionMatchSearchStruct {
0090     QSet<int> *pagesToNotify;
0091     RegularAreaRect *match;
0092     int currentPage;
0093     int searchID;
0094 };
0095 
0096 enum LoadDocumentInfoFlag {
0097     LoadNone = 0,
0098     LoadPageInfo = 1,    // Load annotations and forms
0099     LoadGeneralInfo = 2, // History, rotation, ...
0100     LoadAllInfo = 0xff
0101 };
0102 Q_DECLARE_FLAGS(LoadDocumentInfoFlags, LoadDocumentInfoFlag)
0103 
0104 class DocumentPrivate
0105 {
0106 public:
0107     explicit DocumentPrivate(Document *parent)
0108         : m_parent(parent)
0109         , m_tempFile(nullptr)
0110         , m_docSize(-1)
0111         , m_allocatedPixmapsTotalMemory(0)
0112         , m_maxAllocatedTextPages(0)
0113         , m_warnedOutOfMemory(false)
0114         , m_rotation(Rotation0)
0115         , m_exportCached(false)
0116         , m_bookmarkManager(nullptr)
0117         , m_memCheckTimer(nullptr)
0118         , m_saveBookmarksTimer(nullptr)
0119         , m_generator(nullptr)
0120         , m_walletGenerator(nullptr)
0121         , m_generatorsLoaded(false)
0122         , m_pageController(nullptr)
0123         , m_closingLoop(nullptr)
0124         , m_scripter(nullptr)
0125         , m_archiveData(nullptr)
0126         , m_fontsCached(false)
0127         , m_annotationEditingEnabled(true)
0128         , m_annotationBeingModified(false)
0129         , m_undoStack(nullptr)
0130         , m_docdataMigrationNeeded(false)
0131         , m_synctex_scanner(nullptr)
0132     {
0133         calculateMaxTextPages();
0134     }
0135 
0136     // private methods
0137     bool updateMetadataXmlNameAndDocSize();
0138     QString pagesSizeString() const;
0139     QString namePaperSize(double inchesWidth, double inchesHeight) const;
0140     QString localizedSize(const QSizeF size) const;
0141     qulonglong calculateMemoryToFree();
0142     void cleanupPixmapMemory();
0143     void cleanupPixmapMemory(qulonglong memoryToFree);
0144     AllocatedPixmap *searchLowestPriorityPixmap(bool unloadableOnly = false, bool thenRemoveIt = false, DocumentObserver *observer = nullptr /* any */);
0145     void calculateMaxTextPages();
0146     qulonglong getTotalMemory();
0147     qulonglong getFreeMemory(qulonglong *freeSwap = nullptr);
0148     bool loadDocumentInfo(LoadDocumentInfoFlags loadWhat);
0149     bool loadDocumentInfo(QFile &infoFile, LoadDocumentInfoFlags loadWhat);
0150     void loadViewsInfo(View *view, const QDomElement &e);
0151     void saveViewsInfo(View *view, QDomElement &e) const;
0152     QUrl giveAbsoluteUrl(const QString &fileName) const;
0153     bool openRelativeFile(const QString &fileName);
0154     Generator *loadGeneratorLibrary(const KPluginMetaData &service);
0155     void loadAllGeneratorLibraries();
0156     void loadServiceList(const QVector<KPluginMetaData> &offers);
0157     void unloadGenerator(const GeneratorInfo &info);
0158     void cacheExportFormats();
0159     void setRotationInternal(int r, bool notify);
0160     ConfigInterface *generatorConfig(GeneratorInfo &info);
0161     SaveInterface *generatorSave(GeneratorInfo &info);
0162     Document::OpenResult openDocumentInternal(const KPluginMetaData &offer, bool isstdin, const QString &docFile, const QByteArray &filedata, const QString &password);
0163     static ArchiveData *unpackDocumentArchive(const QString &archivePath);
0164     bool savePageDocumentInfo(QTemporaryFile *infoFile, int what) const;
0165     DocumentViewport nextDocumentViewport() const;
0166     void notifyAnnotationChanges(int page);
0167     void notifyFormChanges(int page);
0168     bool canAddAnnotationsNatively() const;
0169     bool canModifyExternalAnnotations() const;
0170     bool canRemoveExternalAnnotations() const;
0171     OKULARCORE_EXPORT static QString docDataFileName(const QUrl &url, qint64 document_size);
0172     bool cancelRenderingBecauseOf(PixmapRequest *executingRequest, PixmapRequest *newRequest);
0173 
0174     // Methods that implement functionality needed by undo commands
0175     void performAddPageAnnotation(int page, Annotation *annotation);
0176     void performRemovePageAnnotation(int page, Annotation *annotation);
0177     void performModifyPageAnnotation(int page, Annotation *annotation, bool appearanceChanged);
0178     void performSetAnnotationContents(const QString &newContents, Annotation *annot, int pageNumber);
0179 
0180     void recalculateForms();
0181 
0182     // private slots
0183     void saveDocumentInfo() const;
0184     void slotTimedMemoryCheck();
0185     void sendGeneratorPixmapRequest();
0186     void rotationFinished(int page, Okular::Page *okularPage);
0187     void slotFontReadingProgress(int page);
0188     void fontReadingGotFont(const Okular::FontInfo &font);
0189     void slotGeneratorConfigChanged();
0190     void refreshPixmaps(int);
0191     void _o_configChanged();
0192     void doContinueDirectionMatchSearch(void *doContinueDirectionMatchSearchStruct);
0193     void doContinueAllDocumentSearch(void *pagesToNotifySet, void *pageMatchesMap, int currentPage, int searchID);
0194     void doContinueGooglesDocumentSearch(void *pagesToNotifySet, void *pageMatchesMap, int currentPage, int searchID, const QStringList &words);
0195 
0196     void doProcessSearchMatch(RegularAreaRect *match, RunningSearch *search, QSet<int> *pagesToNotify, int currentPage, int searchID, bool moveViewport, const QColor &color);
0197 
0198     /**
0199      * Executes a JavaScript script from the setInterval function.
0200      *
0201      * @since 1.9
0202      */
0203     void executeScript(const QString &function);
0204 
0205     // generators stuff
0206     /**
0207      * This method is used by the generators to signal the finish of
0208      * the pixmap generation @p request.
0209      */
0210     void requestDone(PixmapRequest *request);
0211     void textGenerationDone(Page *page);
0212     /**
0213      * Sets the bounding box of the given @p page (in terms of upright orientation, i.e., Rotation0).
0214      */
0215     void setPageBoundingBox(int page, const NormalizedRect &boundingBox);
0216 
0217     /**
0218      * Request a particular metadata of the Document itself (ie, not something
0219      * depending on the document type/backend).
0220      */
0221     QVariant documentMetaData(const Generator::DocumentMetaDataKey key, const QVariant &option) const;
0222 
0223     /**
0224      * Return whether the normalized rectangle @p rectOfInterest on page number @p rectPage
0225      * is fully visible.
0226      */
0227     bool isNormalizedRectangleFullyVisible(const Okular::NormalizedRect &rectOfInterest, int rectPage);
0228 
0229     // For sync files
0230     void loadSyncFile(const QString &filePath);
0231 
0232     void clearAndWaitForRequests();
0233 
0234     OKULARCORE_EXPORT static QString diff(const QString &oldVal, const QString &newVal);
0235 
0236     /*
0237      * Executes a ScriptAction with the event passed as parameter.
0238      */
0239     void executeScriptEvent(const std::shared_ptr<Event> &event, const Okular::ScriptAction *linkscript);
0240 
0241     /*
0242      * Find the corresponding page number for the form field passed as parameter.
0243      */
0244     int findFieldPageNumber(Okular::FormField *field);
0245 
0246     // member variables
0247     Document *m_parent;
0248     QPointer<QWidget> m_widget;
0249 
0250     // find descriptors, mapped by ID (we handle multiple searches)
0251     QMap<int, RunningSearch *> m_searches;
0252     bool m_searchCancelled;
0253 
0254     // needed because for remote documents docFileName is a local file and
0255     // we want the remote url when the document refers to relativeNames
0256     QUrl m_url;
0257 
0258     // cached stuff
0259     QString m_docFileName;
0260     QString m_xmlFileName;
0261     QTemporaryFile *m_tempFile;
0262     qint64 m_docSize;
0263 
0264     // viewport stuff
0265     std::list<DocumentViewport> m_viewportHistory;
0266     std::list<DocumentViewport>::iterator m_viewportIterator;
0267     DocumentViewport m_nextDocumentViewport; // see Link::Goto for an explanation
0268     QString m_nextDocumentDestination;
0269 
0270     // observers / requests / allocator stuff
0271     QSet<DocumentObserver *> m_observers;
0272     std::list<PixmapRequest *> m_pixmapRequestsStack;
0273     std::list<PixmapRequest *> m_executingPixmapRequests;
0274     QMutex m_pixmapRequestsMutex;
0275     std::list<AllocatedPixmap *> m_allocatedPixmaps;
0276     qulonglong m_allocatedPixmapsTotalMemory;
0277     QList<int> m_allocatedTextPagesFifo;
0278     int m_maxAllocatedTextPages;
0279     bool m_warnedOutOfMemory;
0280 
0281     // the rotation applied to the document
0282     Rotation m_rotation;
0283 
0284     // the current size of the pages (if available), and the cache of the
0285     // available page sizes
0286     PageSize m_pageSize;
0287     PageSize::List m_pageSizes;
0288 
0289     // cache of the export formats
0290     bool m_exportCached;
0291     ExportFormat::List m_exportFormats;
0292     ExportFormat m_exportToText;
0293 
0294     // our bookmark manager
0295     BookmarkManager *m_bookmarkManager;
0296 
0297     // timers (memory checking / info saver)
0298     QTimer *m_memCheckTimer;
0299     QTimer *m_saveBookmarksTimer;
0300 
0301     QHash<QString, GeneratorInfo> m_loadedGenerators;
0302     Generator *m_generator;
0303     QString m_generatorName;
0304     Generator *m_walletGenerator;
0305     bool m_generatorsLoaded;
0306     QVector<Page *> m_pagesVector;
0307     QVector<VisiblePageRect *> m_pageRects;
0308 
0309     // cache of the mimetype we support
0310     QStringList m_supportedMimeTypes;
0311 
0312     PageController *m_pageController;
0313     QEventLoop *m_closingLoop;
0314 
0315     Scripter *m_scripter;
0316 
0317     ArchiveData *m_archiveData;
0318     QString m_archivedFileName;
0319 
0320     QPointer<FontExtractionThread> m_fontThread;
0321     bool m_fontsCached;
0322     QSet<DocumentInfo::Key> m_documentInfoAskedKeys;
0323     DocumentInfo m_documentInfo;
0324     FontInfo::List m_fontsCache;
0325 
0326     QSet<View *> m_views;
0327 
0328     bool m_annotationEditingEnabled;
0329     bool m_annotationBeingModified; // is an annotation currently being moved or resized?
0330     bool m_metadataLoadingCompleted;
0331 
0332     QUndoStack *m_undoStack;
0333     QDomNode m_prevPropsOfAnnotBeingModified;
0334 
0335     // Since 0.21, we no longer support saving annotations and form data in
0336     // the docdata/ directory and we ask the user to migrate them to an
0337     // external file as soon as possible, otherwise the document will be
0338     // shown in read-only mode. This flag is set if the docdata/ XML file
0339     // for the current document contains any annotation or form.
0340     bool m_docdataMigrationNeeded;
0341 
0342     synctex_scanner_p m_synctex_scanner;
0343 
0344     QString m_openError;
0345 
0346     // generator selection
0347     static QVector<KPluginMetaData> availableGenerators();
0348     static QVector<KPluginMetaData> configurableGenerators();
0349     static KPluginMetaData generatorForMimeType(const QMimeType &type, QWidget *widget, const QVector<KPluginMetaData> &triedOffers = QVector<KPluginMetaData>());
0350 
0351     // overrides the editor command (for example with a command from the command line)
0352     QString editorCommandOverride;
0353 };
0354 
0355 class DocumentInfoPrivate
0356 {
0357 public:
0358     QMap<QString, QString> values; // key -> value
0359     QMap<QString, QString> titles; // key -> title For the custom keys
0360 };
0361 
0362 }
0363 
0364 #endif
0365 
0366 /* kate: replace-tabs on; indent-width 4; */