File indexing completed on 2024-05-19 04:27:38

0001 /*
0002  * SPDX-FileCopyrightText: 2018 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #ifndef KISRESOURCELOCATOR_H
0008 #define KISRESOURCELOCATOR_H
0009 
0010 #include <QObject>
0011 #include <QScopedPointer>
0012 #include <QStringList>
0013 #include <QString>
0014 
0015 #include "kritaresources_export.h"
0016 
0017 #include <KisResourceStorage.h>
0018 
0019 
0020 /**
0021  * The KisResourceLocator class locates all resource storages (folders,
0022  * bundles, various adobe resource libraries) in the resource location.
0023  *
0024  * The resource location is always a writable folder.
0025  *
0026  * There is one resource locator which is owned by the QApplication
0027  * object.
0028  *
0029  * The resource location is configurable, but there is only one location
0030  * where Krita will look for resources.
0031  */
0032 class KRITARESOURCES_EXPORT KisResourceLocator : public QObject
0033 {
0034     Q_OBJECT
0035 public:
0036 
0037     // The configuration key that holds the resource location
0038     // for this installation of Krita. The location is
0039     // QStandardPaths::AppDataLocation by default, but that
0040     // can be changed.
0041     static const QString resourceLocationKey;
0042 
0043     static KisResourceLocator *instance();
0044 
0045     ~KisResourceLocator();
0046 
0047     enum class LocatorError {
0048         Ok,
0049         LocationReadOnly,
0050         CannotCreateLocation,
0051         CannotInitializeDb,
0052         CannotSynchronizeDb
0053     };
0054 
0055     /**
0056      * @brief initialize Setup the resource locator for use.
0057      *
0058      * @param installationResourcesLocation the place where the resources
0059      * that come packaged with Krita reside.
0060      */
0061     LocatorError initialize(const QString &installationResourcesLocation);
0062 
0063     /**
0064      * @brief errorMessages
0065      * @return
0066      */
0067     QStringList errorMessages() const;
0068 
0069     /**
0070      * @brief resourceLocationBase is the place where all resource storages (folder,
0071      * bundles etc. are located. This is a writable place.
0072      * @return the base location for all storages.
0073      */
0074     QString resourceLocationBase() const;
0075 
0076     /**
0077      * @brief purge purges the local resource cache
0078      */
0079     void purge(const QString &storageLocation);
0080 
0081     /**
0082      * @brief addStorage Adds a new resource storage to the database. The storage is
0083      * will be marked as not pre-installed. If there is already a storage with the
0084      * given location, it will first be removed.
0085      * @param storageLocation a unique name for the given storage
0086      * @param storage a storage object
0087      * @return true if the storage has been added successfully
0088      */
0089     bool addStorage(const QString &storageLocation, KisResourceStorageSP storage);
0090 
0091     /**
0092      * @brief removeStorage removes the temporary storage from the database
0093      * @param storageLocation the unique name of the storage
0094      * @return true is successful.
0095      */
0096     bool removeStorage(const QString &storageLocation);
0097 
0098     /**
0099      * @brief hasStorage can be used to check whether the given storage already exists
0100      * @param storageLocation the name of the storage
0101      * @return true if the storage is known
0102      */
0103     bool hasStorage(const QString &storageLocation);
0104 
0105 
0106     /**
0107      * @brief saveTags saves all tags to .tag files in the resource folder
0108      */
0109     static void saveTags();
0110 
0111     /**
0112      * Remove the given tag from the cache
0113      */
0114     void purgeTag(const QString tagUrl, const QString resourceType);
0115 
0116     /**
0117      * Returns the full file path of the resource if it has any
0118      * separate physical representation on the disk
0119      */
0120     QString filePathForResource(KoResourceSP resource);
0121 
0122 Q_SIGNALS:
0123 
0124     void progressMessage(const QString&);
0125 
0126     /// Emitted whenever a storage is added
0127     void storageAdded(const QString &location);
0128 
0129     /// Emitted whenever a storage is removed
0130     void storageRemoved(const QString &location);
0131 
0132     /// Emitted when the locator needs to add an embedded resource
0133     void beginExternalResourceImport(const QString &resourceType, int numResources);
0134 
0135     /// Emitted when the locator finished importing the embedded resource
0136     void endExternalResourceImport(const QString &resourceType);
0137 
0138     /// Emitted when the locator needs to add an embedded resource
0139     void beginExternalResourceRemove(const QString &resourceType, const QVector<int> resourceIds);
0140 
0141     /// Emitted when the locator finished importing the embedded resource
0142     void endExternalResourceRemove(const QString &resourceType);
0143 
0144     /// Emitted when a resource changes its active state
0145     void resourceActiveStateChanged(const QString &resourceType, int resourceId);
0146 
0147 private:
0148 
0149     friend class KisAllTagsModel;
0150     friend class KisTagResourceModel;
0151     friend class KisAllResourcesModel;
0152     friend class KisAllTagResourceModel;
0153     friend class KisStorageModel;
0154     friend class TestResourceLocator;
0155     friend class TestResourceModel;
0156     friend class Resource;
0157     friend class KisResourceCacheDb;
0158     friend class KisStorageFilterProxyModel;
0159     friend class KisResourceQueryMapper;
0160     friend class KisResourceUserOperations;
0161     friend class KisBrushTypeMetaDataFixup;
0162     friend class KisResourceThumbnailCache;
0163 
0164     /// @return true if the resource is present in the cache, false if it hasn't been loaded
0165     bool resourceCached(QString storageLocation, const QString &resourceType, const QString &filename) const;
0166 
0167     /**
0168      * @brief resource finds a physical resource in one of the storages
0169      * @param storageLocation the storage containing the resource. If empty,
0170      * this is the folder storage.
0171      *
0172      * Note that the resource does not have the version or id field set, so this cannot be used directly,
0173      * but only through KisResourceModel.
0174      *
0175      * @param resourceType the type of the resource
0176      * @param filename the filename of the resource including extension, but without
0177      * any paths
0178      * @return A resource if found, or 0
0179      */
0180     KoResourceSP resource(QString storageLocation, const QString &resourceType, const QString &filename);
0181 
0182     /**
0183      * @brief resourceForId returns the resource with the given id, or 0 if no such resource exists.
0184      * The resource object will have its id set but not its version.
0185      * @param resourceId the id
0186      */
0187     KoResourceSP resourceForId(int resourceId);
0188 
0189     /**
0190      * @brief setResourceActive
0191      * @param resourceId
0192      * @param active shows if the resource should be set as active or not
0193      * @return
0194      */
0195     bool setResourceActive(int resourceId, bool active);
0196 
0197     /**
0198      * @brief importResourceFromFile
0199      * @param resourceType
0200      * @param fileName
0201      * @param storageLocation: optional, the storage where the resource will be stored. Empty means in the default Folder storage.
0202      * @return the imported resource, which has been added to the database and the cache
0203      */
0204     KoResourceSP importResourceFromFile(const QString &resourceType, const QString &fileName, const bool allowOverwrite, const QString &storageLocation = QString());
0205 
0206     /**
0207      * @brief importResource
0208      * @param resourceType
0209      * @param fileName: filename that should be assigned to the resource
0210      * @param device: QIODevice where the resource should be loaded from
0211      * @param storageLocation: optional, the storage where the resource will be stored. Empty means in the default Folder storage.
0212      * @return the imported resource, which has been added to the database and the cache
0213      */
0214     KoResourceSP importResource(const QString &resourceType, const QString &fileName, QIODevice *device, const bool allowOverwrite, const QString &storageLocation = QString());
0215 
0216     /**
0217      * @brief return whether importing will overwrite some existing resource
0218      * @param resourceType
0219      * @param fileName: filename that should be assigned to the resource
0220      * @param storageLocation: optional, the storage where the resource will be stored. Empty means in the default Folder storage.
0221      */
0222     bool importWillOverwriteResource(const QString &resourceType, const QString &fileName, const QString &storageLocation = QString()) const;
0223 
0224     /**
0225      * @brief exportResource
0226      * @param resource resource to be exported
0227      * @param device: QIODevice where the resource should be loaded to
0228      * @return true if the resource has been exported successfully
0229      */
0230     bool exportResource(KoResourceSP resource, QIODevice *device);
0231 
0232     /**
0233      * @brief addResource adds the given resource to the database and potentially a storage
0234      * @param resourceType the type of the resource
0235      * @param resource the actual resource object
0236      * @param storageLocation the storage where the resource will be saved. By default this is the default folder storage.
0237      * @return true if successful
0238      */
0239     bool addResource(const QString &resourceType, const KoResourceSP resource, const QString &storageLocation = QString());
0240 
0241     /**
0242      * @brief updateResource
0243      * @param resourceType
0244      * @param resource
0245      * @return
0246      */
0247     bool updateResource(const QString &resourceType, const KoResourceSP resource);
0248 
0249     /**
0250      * @brief Reloads the resource from its persistent storage
0251      * @param resourceType the type of the resource
0252      * @param resource the actual resource object
0253      * @return true if reloading was successful. When returned false,
0254      *         \p resource is kept unchanged
0255      */
0256     bool reloadResource(const QString &resourceType, const KoResourceSP resource);
0257 
0258     /**
0259      * @brief metaDataForResource
0260      * @param id
0261      * @return
0262      */
0263     QMap<QString, QVariant> metaDataForResource(int id) const;
0264 
0265     /**
0266      * @brief setMetaDataForResource
0267      * @param id
0268      * @param map
0269      * @return
0270      */
0271     bool setMetaDataForResource(int id, QMap<QString, QVariant> map) const;
0272 
0273     /**
0274      * @brief metaDataForStorage
0275      * @param storage
0276      * @return
0277      */
0278     QMap<QString, QVariant> metaDataForStorage(const QString &storageLocation) const;
0279 
0280     /**
0281      * @brief setMetaDataForStorage
0282      * @param storage
0283      * @param map
0284      */
0285     void setMetaDataForStorage(const QString &storageLocation, QMap<QString, QVariant> map) const;
0286 
0287     /**
0288      * Loads all the resources required by \p resource into the cache
0289      *
0290      * loadRequiredResources() also loads embedded resources and adds them
0291      * into the database.
0292      */
0293     void loadRequiredResources(KoResourceSP resource);
0294 
0295     /**
0296      * @brief tagForUrl create a tag from the database
0297      * @param tagUrl the url
0298      * @return a complete tag with all translated names and comments.
0299      */
0300     KisTagSP tagForUrl(const QString &tagUrl, const QString resourceType);
0301 
0302     /**
0303      * @brief tagForUrlNoCache create a tag from the database, don't use cache
0304      * @param tagUrl url of the tag
0305      * @param resourceType resource type of the tag
0306      * @return
0307      */
0308     static KisTagSP tagForUrlNoCache(const QString &tagUrl, const QString resourceType);
0309 
0310     KisResourceLocator(QObject *parent);
0311     KisResourceLocator(const KisResourceLocator&);
0312     KisResourceLocator operator=(const KisResourceLocator&);
0313 
0314     enum class InitializationStatus {
0315         Unknown,      // We don't know whether Krita has run on this system for this resource location yet
0316         Initialized,  // Everything is ready to start synchronizing the database
0317         FirstRun,     // Krita hasn't run for this resource location yet
0318         FirstUpdate,  // Krita was installed, but it's a version from before the resource locator existed, only user-defined resources are present
0319         Updating      // Krita is updating from an older version with resource locator
0320     };
0321 
0322     LocatorError firstTimeInstallation(InitializationStatus initializationStatus, const QString &installationResourcesLocation);
0323 
0324     // First time installation
0325     bool initializeDb();
0326 
0327     // Synchronize on restarting Krita to see whether the user has added any storages or resources to the resources location
0328     bool synchronizeDb();
0329 
0330     void findStorages();
0331     QList<KisResourceStorageSP> storages() const;
0332 
0333     KisResourceStorageSP storageByLocation(const QString &location) const;
0334     KisResourceStorageSP folderStorage() const;
0335     KisResourceStorageSP memoryStorage() const;
0336 
0337     struct ResourceStorage {
0338         QString storageLocation;
0339         QString resourceType;
0340         QString resourceFileName;
0341      };
0342 
0343     friend class KisMyPaintPaintOpPreset;
0344 
0345     ResourceStorage getResourceStorage(int resourceId) const;
0346     QString makeStorageLocationAbsolute(QString storageLocation) const;
0347     QString makeStorageLocationRelative(QString location) const;
0348 
0349     class Private;
0350     QScopedPointer<Private> d;
0351 };
0352 
0353 #endif // KISRESOURCELOCATOR_H