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