File indexing completed on 2024-05-12 15:59:51
0001 /* 0002 * SPDX-FileCopyrightText: 2018 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef KISRESOURCEMODEL_H 0008 #define KISRESOURCEMODEL_H 0009 0010 #include <QAbstractTableModel> 0011 #include <QSortFilterProxyModel> 0012 0013 #include <kritaresources_export.h> 0014 0015 #include <KoResource.h> 0016 #include <KisTag.h> 0017 0018 0019 /** 0020 * KisAbstractResourceModel defines the interface for accessing resources 0021 * that is used in KisResourceModel and the various filter/proxy models 0022 */ 0023 class KRITARESOURCES_EXPORT KisAbstractResourceModel { 0024 0025 public: 0026 0027 /** 0028 * @brief The Columns enum indexes the columns in the model. To get 0029 * the thumbnail for a particular resource, create the index with 0030 * QModelIndex(row, Thumbnail). 0031 */ 0032 enum Columns { 0033 Id = 0, 0034 StorageId, 0035 Name, 0036 Filename, 0037 Tooltip, 0038 Thumbnail, 0039 Status, 0040 Location, 0041 ResourceType, 0042 Tags, 0043 MD5, 0044 /// A larger thumbnail for displaying in a tooltip. 200x200 or so. 0045 LargeThumbnail, 0046 /// A dirty resource is one that has been modified locally but not saved 0047 Dirty, 0048 /// MetaData is a map of key, value pairs that is associated with this resource 0049 MetaData, 0050 /// Whether the current resource is active 0051 ResourceActive, 0052 /// Whether the current resource's storage is active 0053 StorageActive, 0054 }; 0055 0056 virtual ~KisAbstractResourceModel(){} 0057 0058 /** 0059 * @brief resourceForIndex returns a properly versioned and id'ed resource object 0060 */ 0061 virtual KoResourceSP resourceForIndex(QModelIndex index = QModelIndex()) const = 0; 0062 0063 /** 0064 * @brief indexFromResource 0065 * @param resource 0066 * @return 0067 */ 0068 virtual QModelIndex indexForResource(KoResourceSP resource) const = 0; 0069 0070 /** 0071 * @brief indexFromResource 0072 * @param resourceId resource id for which we want to get an index 0073 * @return 0074 */ 0075 virtual QModelIndex indexForResourceId(int resourceId) const = 0; 0076 0077 /** 0078 * @brief setResourceActive changes 'active' state of the resource 0079 * @param index the index of the resource 0080 * @param value new 'active' state of the resource 0081 * @return true if the new state has been assigned successfully 0082 */ 0083 virtual bool setResourceActive(const QModelIndex &index, bool value) = 0; 0084 0085 /** 0086 * A convenience function to put a resource into inactive state 0087 */ 0088 inline bool setResourceInactive(const QModelIndex &index) { 0089 return setResourceActive(index, false); 0090 } 0091 0092 /** 0093 * @brief importResourceFile 0094 * @param filename 0095 * @return 0096 */ 0097 virtual KoResourceSP importResourceFile(const QString &filename, const bool allowOverwrite, const QString &storageId = QString("")) = 0; 0098 0099 /** 0100 * @brief importResource imports a resource from a QIODevice 0101 * 0102 * Importing a resource from a binary blob is the only way to guarantee that its 0103 * MD5 checksum is kept persistent. The underlying storage will just copy bytes 0104 * into its location. 0105 * 0106 * @param filename file name of the resource if preset. File name may be used 0107 * for addressing the resource, so it is usually preferred to 0108 * preserve it. 0109 * 0110 * @param device device where the resource should be read from 0111 * 0112 * @return the loaded resource object 0113 */ 0114 virtual KoResourceSP importResource(const QString &filename, QIODevice *device, const bool allowOverwrite, const QString &storageId = QString("")) = 0; 0115 0116 /** 0117 * @brief importWillOverwriteResource checks is importing a resource with this filename will overwrite anything 0118 * 0119 * If this funciton returns true, then importResource() is guaranteed to 0120 * fail with 'allowOverwrite' set to false. 0121 * 0122 * @param filename file name of the resource if preset. File name may be used 0123 * for addressing the resource, so it is usually preferred to 0124 * preserve it. 0125 * 0126 * @return true if the some existing will be overwritten while importing 0127 */ 0128 virtual bool importWillOverwriteResource(const QString &fileName, const QString &storageLocation = QString()) const = 0; 0129 0130 /** 0131 * @brief exportResource exports a resource into a QIODevice 0132 * 0133 * Exporting a resource as a binary blob is the only way to guarantee that its 0134 * MD5 checksum is kept persistent. The underlying storage will just copy bytes 0135 * into the device without doing any conversions 0136 * 0137 * @param resource the resource to be exported 0138 * 0139 * @param device device where the resource should be written to 0140 * 0141 * @return true if export operation has been successful 0142 */ 0143 virtual bool exportResource(KoResourceSP resource, QIODevice *device) = 0; 0144 0145 /** 0146 * @brief addResource adds the given resource to the database and storage. If the resource 0147 * already exists in the given storage with md5, filename or name, the existing resource 0148 * will be updated instead. If the existing resource was inactive, it will be actived 0149 * (undeleted). 0150 * 0151 * @param resource the resource itself 0152 * @param storageId the id of the storage (could be "memory" for temporary 0153 * resources, the document's storage id for document storages or empty to save 0154 * to the default resources folder 0155 * @return true if adding the resource succeeded. 0156 */ 0157 virtual bool addResource(KoResourceSP resource, const QString &storageId = QString("")) = 0; 0158 0159 /** 0160 * @brief updateResource creates a new version ofthe resource in the storage and 0161 * in the database. This will also set the resource to active if it was inactive. 0162 * 0163 * Note: if the storage does not support versioning, updating the resource will fail. 0164 * 0165 * @param resource 0166 * @return true if the resource was succesfull updated, 0167 */ 0168 virtual bool updateResource(KoResourceSP resource) = 0; 0169 0170 /** 0171 * @brief reloadResource 0172 * @param resource 0173 * @return 0174 */ 0175 virtual bool reloadResource(KoResourceSP resource) = 0; 0176 0177 /** 0178 * @brief renameResource name the given resource. The resource will have its 0179 * name field reset, will be saved to the storage and there will be a new 0180 * version created in the database. 0181 * @param resource The resource to rename 0182 * @param name The new name 0183 * @return true if the operation succeeded. 0184 */ 0185 virtual bool renameResource(KoResourceSP resource, const QString &name) = 0; 0186 0187 /** 0188 * @brief setResourceMetaData 0189 * @param metadata 0190 * @return 0191 */ 0192 virtual bool setResourceMetaData(KoResourceSP resource, QMap<QString, QVariant> metadata) = 0; 0193 }; 0194 0195 class KRITARESOURCES_EXPORT KisAbstractResourceFilterInterface 0196 { 0197 public: 0198 virtual ~KisAbstractResourceFilterInterface() {} 0199 0200 enum ResourceFilter { 0201 ShowInactiveResources = 0, 0202 ShowActiveResources, 0203 ShowAllResources 0204 }; 0205 0206 enum StorageFilter { 0207 ShowInactiveStorages = 0, 0208 ShowActiveStorages, 0209 ShowAllStorages 0210 }; 0211 public: 0212 0213 /** 0214 * Select status of the resources that should be shown 0215 */ 0216 virtual void setResourceFilter(ResourceFilter filter) = 0; 0217 0218 /** 0219 * Select status of the storages that should be shown 0220 */ 0221 virtual void setStorageFilter(StorageFilter filter) = 0; 0222 }; 0223 0224 /** 0225 * @brief The KisAllresourcesModel class provides access to the cache database 0226 * for a particular resource type. Instances should be retrieved using 0227 * KisResourceModelProvider. All resources are part of this model, active and 0228 * inactive, from all storages, active and inactive. 0229 */ 0230 class KRITARESOURCES_EXPORT KisAllResourcesModel : public QAbstractTableModel, public KisAbstractResourceModel 0231 { 0232 Q_OBJECT 0233 0234 private: 0235 friend class KisResourceModelProvider; 0236 friend class KisResourceModel; 0237 friend class KisResourceQueryMapper; 0238 KisAllResourcesModel(const QString &resourceType, QObject *parent = 0); 0239 0240 public: 0241 0242 ~KisAllResourcesModel() override; 0243 0244 // QAbstractItemModel API 0245 0246 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 0247 int columnCount(const QModelIndex &parent = QModelIndex()) const override; 0248 QVariant data(const QModelIndex &index, int role) const override; 0249 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 0250 bool setData(const QModelIndex &index, const QVariant &value, int role) override; 0251 Qt::ItemFlags flags(const QModelIndex &index) const override; 0252 0253 // Resources API 0254 0255 KoResourceSP resourceForIndex(QModelIndex index = QModelIndex()) const override; 0256 QModelIndex indexForResource(KoResourceSP resource) const override; 0257 QModelIndex indexForResourceId(int resourceId) const override; 0258 bool setResourceActive(const QModelIndex &index, bool value) override; 0259 KoResourceSP importResourceFile(const QString &filename, const bool allowOverwrite, const QString &storageId = QString("")) override; 0260 KoResourceSP importResource(const QString &filename, QIODevice *device, const bool allowOverwrite, const QString &storageId = QString("")) override; 0261 bool importWillOverwriteResource(const QString &fileName, const QString &storageLocation = QString()) const override; 0262 bool exportResource(KoResourceSP resource, QIODevice *device) override; 0263 bool addResource(KoResourceSP resource, const QString &storageId = QString("")) override; 0264 bool updateResource(KoResourceSP resource) override; 0265 bool reloadResource(KoResourceSP resource) override; 0266 bool renameResource(KoResourceSP resource, const QString &name) override; 0267 bool setResourceMetaData(KoResourceSP resource, QMap<QString, QVariant> metadata) override; 0268 0269 private Q_SLOTS: 0270 0271 void storageActiveStateChanged(const QString &location); 0272 0273 /** 0274 * A special connection for KisResourceLocator, which can import 0275 * a resource on its own (all other places are supposed to do that 0276 * via KisResourceModel). This call is needed to make sure the 0277 * internal query in the model is reset. 0278 * 0279 * WARNING: the resource is expected to be added to the **end** 0280 * of the model, that is, its resourceId is expected to be greater 0281 * than any existing resource. 0282 */ 0283 void beginExternalResourceImport(const QString &resourceType, int numResources); 0284 0285 /** 0286 * \see beginExternalResourceImport 0287 */ 0288 void endExternalResourceImport(const QString &resourceType); 0289 0290 /** 0291 * A special connection for KisResourceLocator, which can remove the resource 0292 * while importing something with overwrite. In such a case the locator will 0293 * emit both, remove and insert signals for both the resources. 0294 */ 0295 void beginExternalResourceRemove(const QString &resourceType, const QVector<int> &resourceId); 0296 0297 /** 0298 * \see beginExternalResourceRemove 0299 */ 0300 void endExternalResourceRemove(const QString &resourceType); 0301 0302 /** 0303 * A special connection for KisResourceLocator, which is triggered when the 0304 * resource changes its 'active' state 0305 */ 0306 void slotResourceActiveStateChanged(const QString &resourceType, int resourceId); 0307 0308 public: 0309 0310 KoResourceSP resourceForId(int id) const; 0311 0312 /** 0313 * @brief resourceExists checks whether there is a resource with, in order, 0314 * the given md5, the filename or the resource name. 0315 */ 0316 bool resourceExists(const QString &md5, const QString &filename, const QString &name); 0317 0318 /** 0319 * resourceForFilename returns the first resource with the given filename that 0320 * is active and is in an active store. Note that the filename does not include 0321 * a path to the storage, and if there are resources with the same filename 0322 * in several active storages, only one resource is returned. 0323 * 0324 * @param filename the filename we're looking for 0325 * @param checkDependentResources: check whether we should try to find a resource embedded 0326 * in a resource that's not been loaded yet in the metadata table. 0327 * @return a resource if one is found, or 0 if none are found 0328 */ 0329 QVector<KoResourceSP> resourcesForFilename(QString filename) const; 0330 0331 /** 0332 * resourceForName returns the first resource with the given name that 0333 * is active and is in an active store. Note that if there are resources 0334 * with the same name in several active storages, only one resource 0335 * is returned. 0336 * 0337 * @return a resource if one is found, or 0 if none are found 0338 */ 0339 QVector<KoResourceSP> resourcesForName(const QString &name) const; 0340 QVector<KoResourceSP> resourcesForMD5(const QString &md5sum) const; 0341 QVector<KisTagSP> tagsForResource(int resourceId) const; 0342 0343 private: 0344 0345 bool resetQuery(); 0346 0347 struct Private; 0348 Private *const d; 0349 0350 }; 0351 0352 /** 0353 * @brief The KisResourceModel class provides the main access to resources. It is possible 0354 * to filter the resources returned by the active status flag of the resources and the 0355 * storages 0356 */ 0357 class KRITARESOURCES_EXPORT KisResourceModel : public QSortFilterProxyModel, public KisAbstractResourceModel, public KisAbstractResourceFilterInterface 0358 { 0359 Q_OBJECT 0360 0361 public: 0362 0363 KisResourceModel(const QString &type, QObject *parent = 0); 0364 ~KisResourceModel() override; 0365 0366 0367 void setResourceFilter(ResourceFilter filter) override; 0368 void setStorageFilter(StorageFilter filter) override; 0369 0370 void showOnlyUntaggedResources(bool showOnlyUntagged); 0371 0372 public: 0373 0374 KoResourceSP resourceForIndex(QModelIndex index = QModelIndex()) const override; 0375 QModelIndex indexForResource(KoResourceSP resource) const override; 0376 QModelIndex indexForResourceId(int resourceId) const override; 0377 bool setResourceActive(const QModelIndex &index, bool value) override; 0378 KoResourceSP importResourceFile(const QString &filename, const bool allowOverwrite, const QString &storageId = QString("")) override; 0379 KoResourceSP importResource(const QString &filename, QIODevice *device, const bool allowOverwrite, const QString &storageId = QString("")) override; 0380 bool importWillOverwriteResource(const QString &fileName, const QString &storageLocation = QString()) const override; 0381 bool exportResource(KoResourceSP resource, QIODevice *device) override; 0382 bool addResource(KoResourceSP resource, const QString &storageId = QString("")) override; 0383 bool updateResource(KoResourceSP resource) override; 0384 bool reloadResource(KoResourceSP resource) override; 0385 bool renameResource(KoResourceSP resource, const QString &name) override; 0386 bool setResourceMetaData(KoResourceSP resource, QMap<QString, QVariant> metadata) override; 0387 0388 public: 0389 0390 KoResourceSP resourceForId(int id) const; 0391 0392 /** 0393 * resourceForFilename returns the resources with the given filename that 0394 * fit the current filters. Note that the filename does not include 0395 * a path to the storage. 0396 * 0397 * @return a resource if one is found, or 0 if none are found 0398 */ 0399 QVector<KoResourceSP> resourcesForFilename(QString fileName) const; 0400 0401 /** 0402 * resourceForName returns the resources with the given name that 0403 * fit the current filters. 0404 * 0405 * @return a resource if one is found, or 0 if none are found 0406 */ 0407 QVector<KoResourceSP> resourcesForName(QString name) const; 0408 QVector<KoResourceSP> resourcesForMD5(const QString md5sum) const; 0409 QVector<KisTagSP> tagsForResource(int resourceId) const; 0410 0411 protected: 0412 0413 bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override; 0414 bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; 0415 bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; 0416 0417 private: 0418 QVector<KoResourceSP> filterByColumn(const QString filter, KisAllResourcesModel::Columns column) const; 0419 bool filterResource(const QModelIndex &idx) const; 0420 0421 struct Private; 0422 Private *const d; 0423 0424 Q_DISABLE_COPY(KisResourceModel) 0425 0426 }; 0427 0428 0429 0430 #endif // KISRESOURCEMODEL_H