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

0001 /*
0002  *  SPDX-License-Identifier: GPL-3.0-or-later
0003  */
0004 
0005 #include "KisResourceQueryMapper.h"
0006 
0007 #include "kis_assert.h"
0008 #include <QString>
0009 #include <QVariant>
0010 #include <QImage>
0011 #include <QByteArray>
0012 #include <QBuffer>
0013 #include <QDebug>
0014 #include <QSqlError>
0015 
0016 #include "KisResourceModel.h"
0017 #include "KisResourceLocator.h"
0018 #include "KisResourceModelProvider.h"
0019 #include "KisTag.h"
0020 
0021 
0022 
0023 QImage KisResourceQueryMapper::getThumbnailFromQuery(const QSqlQuery &query, bool useResourcePrefix)
0024 {
0025     QString storageLocation = query.value("location").toString();
0026     QString resourceType = query.value("resource_type").toString();
0027     QString filename = query.value(useResourcePrefix ? "resource_filename" : "filename").toString();
0028 
0029     QImage img = KisResourceLocator::instance()->thumbnailCached(storageLocation, resourceType, filename);
0030     if (!img.isNull()) {
0031         return img;
0032     } else {
0033         const int resourceId = query.value(useResourcePrefix ? "resource_id" : "id").toInt();
0034         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(resourceId >= 0, img);
0035 
0036         bool result = false;
0037         QSqlQuery thumbQuery;
0038         result = thumbQuery.prepare("SELECT thumbnail FROM resources WHERE resources.id = :resource_id");
0039         if (!result) {
0040             qWarning() << "Failed to prepare query for thumbnail of" << resourceId << thumbQuery.lastError();
0041             return img;
0042         }
0043 
0044         thumbQuery.bindValue(":resource_id", resourceId);
0045 
0046         result = thumbQuery.exec();
0047 
0048         if (!result) {
0049             qWarning() << "Failed to execute query for thumbnail of" << resourceId << thumbQuery.lastError();
0050             return img;
0051         }
0052 
0053         if (!thumbQuery.next()) {
0054             qWarning() << "Failed to find thumbnail of" << resourceId;
0055             return img;
0056         }
0057 
0058         QByteArray ba = thumbQuery.value("thumbnail").toByteArray();
0059         QBuffer buf(&ba);
0060         buf.open(QBuffer::ReadOnly);
0061         img.load(&buf, "PNG");
0062         KisResourceLocator::instance()->cacheThumbnail(storageLocation, resourceType, filename, img);
0063         return img;
0064     }
0065 }
0066 
0067 QVariant KisResourceQueryMapper::variantFromResourceQuery(const QSqlQuery &query, int column, int role, bool useResourcePrefix)
0068 {
0069     const QString resourceType = query.value("resource_type").toString();
0070 
0071     switch(role) {
0072     case Qt::DisplayRole:
0073     {
0074         switch(column) {
0075         case KisAbstractResourceModel::Id:
0076             return query.value(useResourcePrefix ? "resource_id" : "id");
0077         case KisAbstractResourceModel::StorageId:
0078             return query.value("storage_id");
0079         case KisAbstractResourceModel::Name:
0080             return query.value(useResourcePrefix ? "resource_name" : "name");
0081         case KisAbstractResourceModel::Filename:
0082             return query.value(useResourcePrefix ? "resource_filename" : "filename");
0083         case KisAbstractResourceModel::Tooltip:
0084             return query.value(useResourcePrefix ? "resource_tooltip" : "tooltip");
0085         case KisAbstractResourceModel::Thumbnail:
0086         {
0087             return QVariant::fromValue<QImage>(getThumbnailFromQuery(query, useResourcePrefix));
0088         }
0089         case KisAbstractResourceModel::Status:
0090             return query.value(useResourcePrefix ? "resource_status" : "status");
0091         case KisAbstractResourceModel::Location:
0092             return query.value("location");
0093         case KisAbstractResourceModel::ResourceType:
0094             return query.value("resource_type");
0095         case KisAbstractResourceModel::Dirty:
0096         {
0097             QString storageLocation = query.value("location").toString();
0098             QString filename = query.value(useResourcePrefix ? "resource_filename" : "filename").toString();
0099 
0100             // An uncached resource has not been loaded, so it cannot be dirty
0101             if (!KisResourceLocator::instance()->resourceCached(storageLocation, resourceType, filename)) {
0102                 return false;
0103             }
0104             else {
0105                 // Now we have to check the resource, but that's cheap since it's been loaded in any case
0106                 KoResourceSP resource = KisResourceLocator::instance()->resourceForId(query.value(useResourcePrefix ? "resource_id" : "id").toInt());
0107                 return resource->isDirty();
0108             }
0109         }
0110         case KisAbstractResourceModel::ResourceActive:
0111             return query.value("resource_active");
0112         case KisAbstractResourceModel::StorageActive:
0113             return query.value(useResourcePrefix ? "resource_storage_active" : "storage_active");
0114         default:
0115             ;
0116         };
0117         Q_FALLTHROUGH();
0118     }
0119     case Qt::DecorationRole:
0120     {
0121         if (column == KisAbstractResourceModel::Thumbnail) {
0122             return QVariant::fromValue<QImage>(getThumbnailFromQuery(query, useResourcePrefix));
0123         }
0124         return QVariant();
0125     }
0126     case Qt::StatusTipRole:
0127         return QVariant();
0128     case Qt::ToolTipRole:
0129         Q_FALLTHROUGH();
0130     case Qt::WhatsThisRole:
0131         return query.value("tooltip");
0132     case Qt::UserRole + KisAbstractResourceModel::Id:
0133         return query.value(useResourcePrefix ? "resource_id" : "id");
0134     case Qt::UserRole + KisAbstractResourceModel::StorageId:
0135         return query.value("storage_id");
0136     case Qt::UserRole + KisAbstractResourceModel::Name:
0137         return query.value(useResourcePrefix ? "resource_name" : "name");
0138     case Qt::UserRole + KisAbstractResourceModel::Filename:
0139         return query.value(useResourcePrefix ? "resource_filename" : "filename");
0140     case Qt::UserRole + KisAbstractResourceModel::Tooltip:
0141         return query.value(useResourcePrefix ? "resource_tooltip" : "tooltip");
0142     case Qt::UserRole + KisAbstractResourceModel::MD5:
0143         return query.value(useResourcePrefix ? "resource_md5sum" : "md5sum");
0144     case Qt::UserRole + KisAbstractResourceModel::Thumbnail:
0145     {
0146         return QVariant::fromValue<QImage>(getThumbnailFromQuery(query, useResourcePrefix));
0147     }
0148     case Qt::UserRole + KisAbstractResourceModel::Status:
0149         return query.value(useResourcePrefix ? "resource_status" : "status");
0150     case Qt::UserRole + KisAbstractResourceModel::Location:
0151         return query.value("location");
0152     case Qt::UserRole + KisAbstractResourceModel::ResourceType:
0153         return query.value("resource_type");
0154     case Qt::UserRole + KisAbstractResourceModel::Tags:
0155     {
0156         KisAllResourcesModel *resourceModel = KisResourceModelProvider::resourceModel(resourceType);
0157         QStringList tagNames;
0158         Q_FOREACH(const KisTagSP tag, resourceModel->tagsForResource(query.value(useResourcePrefix ? "resource_id" : "id").toInt())) {
0159             tagNames << tag->name();
0160         }
0161         return tagNames;
0162     }
0163     case Qt::UserRole + KisAbstractResourceModel::Dirty:
0164     {
0165         QString storageLocation = query.value("location").toString();
0166         QString filename = query.value(useResourcePrefix ? "resource_filename" : "filename").toString();
0167 
0168         // An uncached resource has not been loaded, so it cannot be dirty
0169         if (!KisResourceLocator::instance()->resourceCached(storageLocation, resourceType, filename)) {
0170             return false;
0171         }
0172         else {
0173             // Now we have to check the resource, but that's cheap since it's been loaded in any case
0174             KoResourceSP resource = KisResourceLocator::instance()->resourceForId(query.value(useResourcePrefix ? "resource_id" : "id").toInt());
0175             return resource->isDirty();
0176         }
0177     }
0178     case Qt::UserRole + KisAbstractResourceModel::MetaData:
0179     {
0180         QMap<QString, QVariant> r = KisResourceLocator::instance()->metaDataForResource(query.value(useResourcePrefix ? "resource_id" : "id").toInt());
0181         return r;
0182     }
0183     case Qt::UserRole + KisAbstractResourceModel::ResourceActive:
0184     {
0185         return query.value("resource_active");
0186     }
0187     case Qt::UserRole + KisAbstractResourceModel::StorageActive:
0188     {
0189         return query.value(useResourcePrefix ? "resource_storage_active" : "storage_active");
0190     }
0191     default:
0192         ;
0193     }
0194 
0195     return QVariant();
0196 }
0197