File indexing completed on 2024-05-12 15:59:54

0001 /*  This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2003 Patrick Julien <freak@codepimps.org>
0003     SPDX-FileCopyrightText: 2005 Boudewijn Rempt <boud@valdyas.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006  */
0007 #ifndef KORESOURCE_H
0008 #define KORESOURCE_H
0009 
0010 #include <QImage>
0011 #include <QString>
0012 #include <QHash>
0013 #include <QSharedPointer>
0014 #include <QDebug>
0015 
0016 #include "KoResourceSignature.h"
0017 
0018 #include "KisResourceTypes.h"
0019 #include <boost/operators.hpp>
0020 
0021 #include <kritaresources_export.h>
0022 
0023 class QDomDocument;
0024 class QDomElement;
0025 
0026 class KoResource;
0027 typedef QSharedPointer<KoResource> KoResourceSP;
0028 
0029 class KisResourcesInterface;
0030 typedef QSharedPointer<KisResourcesInterface> KisResourcesInterfaceSP;
0031 
0032 class KoResourceLoadResult;
0033 
0034 namespace ResourceTestHelper {
0035 void overrideResourceVesion(KoResourceSP resource, int version);
0036 }
0037 
0038 /**
0039  * The KoResource class provides a representation of resources.  This
0040  * includes, but not limited to, brushes and patterns.
0041  *
0042  * A resource knows its filename, but not the location where it's stored.
0043  * A new version of a resource is stored with an updated filename, the old
0044  * version isn't renamed.
0045  *
0046  */
0047 class KRITARESOURCES_EXPORT KoResource : public boost::equality_comparable<KoResource>
0048 {
0049 public:
0050 
0051     /**
0052      * Creates a new KoResource object using @p filename.  No file is opened
0053      * in the constructor, you have to call load.
0054      *
0055      * @param filename the file name to save and load from.
0056      */
0057     KoResource();
0058     explicit KoResource(const QString &filename);
0059     virtual ~KoResource();
0060     KoResource(const KoResource &rhs);
0061     KoResource &operator=(const KoResource &rhs) = delete;
0062 
0063     virtual KoResourceSP clone() const = 0;
0064 
0065 
0066 
0067 public:
0068     /**
0069      * Load this resource.
0070      * @return true if loading the resource succeeded.
0071      */
0072     bool load(KisResourcesInterfaceSP resourcesInterface);
0073     virtual bool loadFromDevice(QIODevice *dev, KisResourcesInterfaceSP resourcesInterface) = 0;
0074 
0075     /**
0076      * Save this resource.
0077      *@return true if saving the resource succeeded.
0078      */
0079     bool save();
0080     virtual bool saveToDevice(QIODevice* dev) const;
0081 
0082     /**
0083      * @returns a QImage image representing this resource: in the case
0084      * of some resources, it is the actual resource.
0085      *
0086      * This image could be null. The image can be in any valid format.
0087      */
0088     QImage image() const;
0089     void setImage(const QImage &image);
0090 
0091     /**
0092      * @brief updateThumbnail updates the thumbnail for this resource.
0093      * Reimplement if your thumbnail is something else than the image
0094      * set with setImage.
0095      */
0096     virtual void updateThumbnail();
0097 
0098     /**
0099      * Requests the resource to update its linked-resources
0100      * metadata stored in metaData()["dependent_resources_filenames"].
0101      *
0102      * This request comes from KisResourceLocator every time a
0103      * new version of the resource is added to the database.
0104      */
0105     virtual void updateLinkedResourcesMetaData(KisResourcesInterfaceSP resourcesInterface);
0106 
0107     /**
0108      * @brief thumbnail the thumbnail image to use in resource selectors
0109      * @return a valid qimage. All thumbnails for a given resource have the
0110      * same size (which is not true for image(), but that size need not
0111      * be square. By default it's the same as image(), but that is not guaranteed.
0112      */
0113     virtual QImage thumbnail() const;
0114 
0115     /**
0116      * @brief thumbnailPath returns the path to a separate thumbnail image, outside
0117      *        the actual resource file itself. If the path is relative, it is supposed
0118      *        start in the same location as the resource itself. If it's absolute,
0119      *        that is, it starts with "/", it is from the root of the storage.
0120      * @return an empty string if the thumbnail is part of the resource
0121      */
0122     virtual QString thumbnailPath() const;
0123 
0124     /**
0125      * @param generateIfEmpty: if the resource does not have an md5sum set,
0126      * if this is true, the resource saves itself into a buffer and calculates
0127      * the md5sum over that. This may be different from the actual md5sum you
0128      * would get calculated over the actual resource file.
0129      * @return the md5sum calculated over the contents of the resource. This
0130      * is in hex-encoded string format.
0131      */
0132     QString md5Sum(bool generateIfEmpty = true) const;
0133 
0134     /// Set the md5sum of this resource. It must be in hex-encoded string format
0135     void setMD5Sum(const QString &md5sum);
0136 
0137     /// @return the filename of this resource within the container (folder, bundle, ...)
0138     QString filename() const;
0139     void setFilename(const QString& filename);
0140 
0141     /// @return the user-visible name of the resource
0142     virtual QString name() const;
0143     void setName(const QString& name);
0144 
0145     /// @return true if the resource is ready for use
0146     bool valid() const;
0147     void setValid(bool valid);
0148 
0149     /// @return true if the resource is marked as active in the database (inactive means "deleted")
0150     bool active() const;
0151     void setActive(bool active);
0152 
0153     /// @return the default file extension which should be used when saving the resource
0154     virtual QString defaultFileExtension() const;
0155 
0156     /// @return true if the resource is permanent and can't be removed by the user
0157     bool permanent() const;
0158     void setPermanent(bool permanent);
0159 
0160     /// @return the name of the storage location of the resource
0161     QString storageLocation() const;
0162     void setStorageLocation(const QString &location);
0163 
0164     /// Mark the preset as modified but not saved
0165     void setDirty(bool value);
0166 
0167     /// @return true if the preset has been modified, but not saved
0168     bool isDirty() const;
0169 
0170     /// store the given key, value pair in the resource
0171     void addMetaData(QString key, QVariant value);
0172 
0173     /// get a map with all the metadata
0174     QMap<QString, QVariant> metadata() const;
0175 
0176     /// Get the version of the resource
0177     int version() const;
0178     void setVersion(int version);
0179 
0180     /// @return the unique id of the resource in the resource database
0181     int resourceId() const;
0182     void setResourceId(int id);
0183 
0184     /// @return the resource type
0185     virtual QPair<QString, QString> resourceType() const = 0;
0186 
0187     /**
0188      * @return the signature of the resource which is enough for referencing
0189      * the resource in somewhat unique way
0190      */
0191     KoResourceSignature signature() const;
0192 
0193     /**
0194      * Ephemeral resource is a type of resource that has no physical
0195      * representation on disk. Therefore, its load()/save() calls do
0196      * nothing. Such resources will always have empty md5Sum() and,
0197      * therefore, will never be stored in the resources database.
0198      *
0199      * This type of resources is created directly by the corresponding
0200      * factory or other object (e.g. KisAutoBrushFactory).
0201      *
0202      * Ephemeral resource cannot be serializable.
0203      */
0204     virtual bool isEphemeral() const;
0205 
0206     /**
0207      * Serializable resource is the one which can be saved/loaded into a
0208      * specific storage via saveToDevice()/loadFromDevice() methods. Some
0209      * resources, like KisAbrBrush or KisPsdLayerStyle, are stored in
0210      * specific libraries in "batches". Such resources cannot be saved
0211      * individually. They are created by the corresponding factories.
0212      *
0213      * In contrast to ephemeral resource, non-serializable resource
0214      * will always have a correct md5Sum() and may be stored in the
0215      * resources database.
0216      */
0217     virtual bool isSerializable() const;
0218 
0219     /**
0220      * Loads all the required resources either from \p globalResourcesInterface or
0221      * from embedded data. The preset first tries to fetch the required resource
0222      * from the global source, and only if it fails, tries to load it from the
0223      * embedded data. One can check if the loaded resource is embedded by checking
0224      * its resourceId().
0225      *
0226      * The set of resources returned is basically: linkedResources() + embeddedResources()
0227      */
0228     QList<KoResourceLoadResult> requiredResources(KisResourcesInterfaceSP globalResourcesInterface) const;
0229 
0230     /**
0231      * @return all the resources that are needed but (*this) resource and
0232      * are not embedded into it. The resources are fetched from
0233      * \p globalResourcesInterface. If fetching of some resources is failed,
0234      * then (*this) resource is invalid.
0235      */
0236     virtual QList<KoResourceLoadResult> linkedResources(KisResourcesInterfaceSP globalResourcesInterface) const;
0237 
0238     /**
0239      * @return all the resources that were embedded into (*this) resource.
0240      * If the resources were already added to the global database, then they
0241      * are fetched from \p globalResourcesInterface to save time/memory.
0242      */
0243     virtual QList<KoResourceLoadResult> embeddedResources(KisResourcesInterfaceSP globalResourcesInterface) const;
0244 
0245     /**
0246      * A list of per-canvas active resources that are needed for this resource
0247      * to function properly. E.g. some gradients may require Fg/Bg colors and
0248      * some presets would like to know about the current gradient selection.
0249      *
0250      * @return a list of canvas resources needed for the current resource
0251      */
0252     virtual QList<int> requiredCanvasResources() const;
0253 
0254 private:
0255     struct Private;
0256     Private* const d;
0257 };
0258 
0259 static inline bool operator==(const KoResource &resource1, const KoResource &resource2)
0260 {
0261     return (resource1.md5Sum() == resource2.md5Sum());
0262 }
0263 
0264 static inline uint qHash(const KoResource &resource)
0265 {
0266     return qHash(resource.md5Sum());
0267 }
0268 
0269 Q_DECLARE_METATYPE(QSharedPointer<KoResource>)
0270 
0271 
0272 
0273 inline QDebug operator<<(QDebug dbg, const KoResourceSP res)
0274 {
0275     if (!res) {
0276         dbg.noquote() << "NULL Resource";
0277     }
0278     else {
0279         dbg.nospace() << "[RESOURCE] Name: " << res->name()
0280                       << " Version: " << res->version()
0281                       << " Filename: " << res->filename()
0282                       << " MD5: " << res->md5Sum(false)
0283                       << " Type: " << res->resourceType()
0284                       << " Valid: " << res->valid()
0285                       << " Storage: " << res->storageLocation();
0286     }
0287     return dbg.space();
0288 }
0289 
0290 #endif // KORESOURCE_H_
0291