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