Krita Source Code Documentation
Loading...
Searching...
No Matches
KisResourceQueryMapper.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2020 Boudewijn Rempt <boud@valdyas.org>
3 * SPDX-FileCopyrightText: 2021 Agata Cacko <cacko.azh@gmail.com>
4 * SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com>
5 * SPDX-FileCopyrightText: 2023 L. E. Segovia <amy@amyspark.me>
6 *
7 * SPDX-License-Identifier: GPL-3.0-or-later
8 */
9
11
12#include <QBuffer>
13#include <QByteArray>
14#include <QDebug>
15#include <QFont>
16#include <QImage>
17#include <QSqlError>
18#include <QString>
19#include <QVariant>
20
21#include "KisResourceLocator.h"
23#include "KisResourceModel.h"
26#include "KisTag.h"
27#include "kis_assert.h"
28
29
30QImage KisResourceQueryMapper::getThumbnailFromQuery(const QSqlQuery &query, bool useResourcePrefix)
31{
32 const QString storageLocation =
33 KisResourceLocator::instance()->makeStorageLocationAbsolute(query.value("location").toString());
34 const QString resourceType = query.value("resource_type").toString();
35 const QString filename = query.value(useResourcePrefix ? "resource_filename" : "filename").toString();
36
37 // NOTE: Only use the private methods of KisResourceThumbnailCache here to prevent any chances of
38 // recursion.
39 QImage img =
40 KisResourceThumbnailCache::instance()->originalImage(storageLocation, resourceType, filename);
41 if (!img.isNull()) {
42 return img;
43 } else {
44 const int resourceId = query.value(useResourcePrefix ? "resource_id" : "id").toInt();
45 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(resourceId >= 0, img);
46
47 bool result = false;
48 QSqlQuery thumbQuery;
49 result = thumbQuery.prepare("SELECT thumbnail FROM resources WHERE resources.id = :resource_id");
50 if (!result) {
51 qWarning() << "Failed to prepare query for thumbnail of" << resourceId << thumbQuery.lastError();
52 return img;
53 }
54
55 thumbQuery.bindValue(":resource_id", resourceId);
56
57 result = thumbQuery.exec();
58
59 if (!result) {
60 qWarning() << "Failed to execute query for thumbnail of" << resourceId << thumbQuery.lastError();
61 return img;
62 }
63
64 if (!thumbQuery.next()) {
65 qWarning() << "Failed to find thumbnail of" << resourceId;
66 return img;
67 }
68
69 QByteArray ba = thumbQuery.value("thumbnail").toByteArray();
70 QBuffer buf(&ba);
71 buf.open(QBuffer::ReadOnly);
72 img.load(&buf, "PNG");
73
74 KisResourceThumbnailCache::instance()->insert(storageLocation, resourceType, filename, img);
75 return img;
76 }
77}
78
79QVariant KisResourceQueryMapper::variantFromResourceQuery(const QSqlQuery &query, int column, int role, bool useResourcePrefix)
80{
81 const QString resourceType = query.value("resource_type").toString();
82
83 switch(role) {
84 case Qt::FontRole:
85 return QFont();
86 case Qt::DisplayRole:
87 {
88 switch(column) {
90 return query.value(useResourcePrefix ? "resource_id" : "id");
92 return query.value("storage_id");
94 return query.value(useResourcePrefix ? "resource_name" : "name");
96 return query.value(useResourcePrefix ? "resource_filename" : "filename");
98 return query.value(useResourcePrefix ? "resource_tooltip" : "tooltip");
100 {
101 return QVariant::fromValue<QImage>(getThumbnailFromQuery(query, useResourcePrefix));
102 }
104 return query.value(useResourcePrefix ? "resource_active" : "status");
106 return query.value("location");
108 return query.value("resource_type");
110 {
111 QString storageLocation = query.value("location").toString();
112 QString filename = query.value(useResourcePrefix ? "resource_filename" : "filename").toString();
113
114 // An uncached resource has not been loaded, so it cannot be dirty
115 if (!KisResourceLocator::instance()->resourceCached(storageLocation, resourceType, filename)) {
116 return false;
117 }
118 else {
119 // Now we have to check the resource, but that's cheap since it's been loaded in any case
120 KoResourceSP resource = KisResourceLocator::instance()->resourceForId(query.value(useResourcePrefix ? "resource_id" : "id").toInt());
121 return resource->isDirty();
122 }
123 }
125 return query.value("resource_active");
127 return query.value(useResourcePrefix ? "resource_storage_active" : "storage_active");
128 default:
129 ;
130 };
131 Q_FALLTHROUGH();
132 }
133 case Qt::DecorationRole:
134 {
136 return QVariant::fromValue<QImage>(getThumbnailFromQuery(query, useResourcePrefix));
137 }
138 return QVariant();
139 }
140 case Qt::CheckStateRole: {
141 switch (column) {
143 if (query.value(useResourcePrefix ? "resource_active" : "status").toInt() == 0) {
144 return Qt::Unchecked;
145 } else {
146 return Qt::Checked;
147 }
149 const QString storageLocation = query.value("location").toString();
150 const QString filename = query.value(useResourcePrefix ? "resource_filename" : "filename").toString();
151
152 // An uncached resource has not been loaded, so it cannot be dirty
153 if (!KisResourceLocator::instance()->resourceCached(storageLocation, resourceType, filename)) {
154 return Qt::Unchecked;
155 } else {
156 // Now we have to check the resource, but that's cheap since it's been loaded in any case
158 query.value(useResourcePrefix ? "resource_id" : "id").toInt());
159 return resource->isDirty() ? Qt::Checked : Qt::Unchecked;
160 }
161 }
163 if (query.value("resource_active").toInt() == 0) {
164 return Qt::Unchecked;
165 } else {
166 return Qt::Checked;
167 }
169 if (query.value(useResourcePrefix ? "resource_storage_active" : "storage_active").toInt() == 0) {
170 return Qt::Unchecked;
171 } else {
172 return Qt::Checked;
173 }
174 default:
175 return {};
176 };
177 }
178 case Qt::StatusTipRole:
179 return QVariant();
180 case Qt::ToolTipRole:
181 Q_FALLTHROUGH();
182 case Qt::WhatsThisRole:
183 return query.value(useResourcePrefix ? "resource_tooltip" : "tooltip");
184 case Qt::UserRole + KisAbstractResourceModel::Id:
185 return query.value(useResourcePrefix ? "resource_id" : "id");
186 case Qt::UserRole + KisAbstractResourceModel::StorageId:
187 return query.value("storage_id");
188 case Qt::UserRole + KisAbstractResourceModel::Name:
189 return query.value(useResourcePrefix ? "resource_name" : "name");
190 case Qt::UserRole + KisAbstractResourceModel::Filename:
191 return query.value(useResourcePrefix ? "resource_filename" : "filename");
192 case Qt::UserRole + KisAbstractResourceModel::Tooltip:
193 return query.value(useResourcePrefix ? "resource_tooltip" : "tooltip");
194 case Qt::UserRole + KisAbstractResourceModel::MD5:
195 return query.value(useResourcePrefix ? "resource_md5sum" : "md5sum");
196 case Qt::UserRole + KisAbstractResourceModel::Thumbnail:
197 {
198 return QVariant::fromValue<QImage>(getThumbnailFromQuery(query, useResourcePrefix));
199 }
200 case Qt::UserRole + KisAbstractResourceModel::Status:
201 return query.value(useResourcePrefix ? "resource_active" : "status");
202 case Qt::UserRole + KisAbstractResourceModel::Location:
203 return query.value("location");
204 case Qt::UserRole + KisAbstractResourceModel::ResourceType:
205 return query.value("resource_type");
206 case Qt::UserRole + KisAbstractResourceModel::Tags:
207 {
209 QStringList tagNames;
210 Q_FOREACH(const KisTagSP tag, resourceModel->tagsForResource(query.value(useResourcePrefix ? "resource_id" : "id").toInt())) {
211 tagNames << tag->name();
212 }
213 return tagNames;
214 }
215 case Qt::UserRole + KisAbstractResourceModel::Dirty:
216 {
217 QString storageLocation = query.value("location").toString();
218 QString filename = query.value(useResourcePrefix ? "resource_filename" : "filename").toString();
219
220 // An uncached resource has not been loaded, so it cannot be dirty
221 if (!KisResourceLocator::instance()->resourceCached(storageLocation, resourceType, filename)) {
222 return false;
223 }
224 else {
225 // Now we have to check the resource, but that's cheap since it's been loaded in any case
226 KoResourceSP resource = KisResourceLocator::instance()->resourceForId(query.value(useResourcePrefix ? "resource_id" : "id").toInt());
227 return resource->isDirty();
228 }
229 }
230 case Qt::UserRole + KisAbstractResourceModel::MetaData:
231 {
232 QMap<QString, QVariant> r = KisResourceLocator::instance()->metaDataForResource(query.value(useResourcePrefix ? "resource_id" : "id").toInt());
233 return r;
234 }
236 {
237 return query.value("resource_active");
238 }
239 case Qt::UserRole + KisAbstractResourceModel::StorageActive:
240 {
241 return query.value(useResourcePrefix ? "resource_storage_active" : "storage_active");
242 }
243 case Qt::UserRole + KisAbstractResourceModel::BrokenStatus:
244 {
245 if (resourceType == ResourceType::PaintOpPresets) {
247 const int id = query.value(useResourcePrefix ? "resource_id" : "id").toInt();
248 const QStringList requiredBrushes =
249 metaDataModel->metaDataValue(id, "dependent_resources_filenames").toStringList();
250 if (!requiredBrushes.isEmpty()) {
252 Q_FOREACH (const QString brushFile, requiredBrushes) {
253 if (!model->resourceExists("", brushFile, "")) {
254 qWarning() << "dependent resource" << brushFile << "misses.";
255 return true;
256 }
257 }
258 }
259 }
260
261 return false;
262 }
264 {
265 if (resourceType == ResourceType::PaintOpPresets) {
267 const int id = query.value(useResourcePrefix ? "resource_id" : "id").toInt();
268 const QStringList requiredBrushes =
269 metaDataModel->metaDataValue(id, "dependent_resources_filenames").toStringList();
270 QStringList missingResources;
271 if (!requiredBrushes.isEmpty()) {
273 Q_FOREACH (const QString brushFile, requiredBrushes) {
274 if (!model->resourceExists("", brushFile, "")) {
275 missingResources << brushFile;
276 break;
277 }
278 }
279 if (!missingResources.isEmpty()) {
280 QString resourcesList;
281 Q_FOREACH (const QString &resource, missingResources) {
282 resourcesList += "<li>" + resource + "</li>";
283 }
284
285 return QString(
286 "%1</br>"
287 "<ul style=\"list-style-type: disc; margin: 0px;\">%2</ul>")
288 .arg(i18n("Some resources are missing:"), resourcesList);
289 }
290 }
291 }
292 return QVariant();
293 }
294 default:
295 ;
296 }
297
298 return QVariant();
299}
300
@ Status
Whether the resource is active. Duplicate of ResourceActive.
@ ResourceActive
Whether the current resource is active.
@ Dirty
A dirty resource is one that has been modified locally but not saved.
@ MetaData
MetaData is a map of key, value pairs that is associated with this resource.
@ BrokenStatus
Whether the resource is broken (bool)
@ StorageActive
Whether the current resource's storage is active.
The KisAllresourcesModel class provides access to the cache database for a particular resource type....
bool resourceExists(const QString &md5, const QString &filename, const QString &name)
resourceExists checks whether there is a resource with, in order, the given md5, the filename or the ...
QVector< KisTagSP > tagsForResource(int resourceId) const
bool resourceCached(QString storageLocation, const QString &resourceType, const QString &filename) const
QString makeStorageLocationAbsolute(QString storageLocation) const
QMap< QString, QVariant > metaDataForResource(int id) const
metaDataForResource
KoResourceSP resourceForId(int resourceId)
resourceForId returns the resource with the given id, or 0 if no such resource exists....
static KisResourceLocator * instance()
QVariant metaDataValue(int resourceId, const QString &key)
static KisAllResourcesModel * resourceModel(const QString &resourceType)
static KisResourceMetaDataModel * resourceMetadataModel()
static QImage getThumbnailFromQuery(const QSqlQuery &query, bool useResourcePrefix)
static QVariant variantFromResourceQuery(const QSqlQuery &query, int column, int role, bool useResourcePrefix)
variantFromResourceQuery returns a QVariant for the given column and or role
void insert(const QString &storageLocation, const QString &resourceType, const QString &filename, const QImage &image)
static KisResourceThumbnailCache * instance()
QImage originalImage(const QString &storageLocation, const QString &resourceType, const QString &filename) const
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
const QString Brushes
const QString PaintOpPresets