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     SPDX-FileCopyrightText: 2007 Jan Hambrecht <jaham@gmx.net>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-or-later
0007  */
0008 #include <KoResource.h>
0009 
0010 #include <QDomElement>
0011 #include <QFileInfo>
0012 #include <QDebug>
0013 #include <QImage>
0014 #include <QBuffer>
0015 
0016 #include <kis_debug.h>
0017 #include "KoMD5Generator.h"
0018 #include "kis_assert.h"
0019 
0020 #include "KoResourceLoadResult.h"
0021 
0022 
0023 struct KoResourceSPStaticRegistrar {
0024     KoResourceSPStaticRegistrar() {
0025         qRegisterMetaType<KoResourceSP>("KoResourceSP");
0026     }
0027 };
0028 static KoResourceSPStaticRegistrar __registrar1;
0029 
0030 
0031 struct Q_DECL_HIDDEN KoResource::Private {
0032     int version {-1};
0033     int resourceId {-1};
0034     bool valid {false};
0035     bool active {true};
0036     bool permanent {false};
0037     bool dirty {false};
0038     QString name;
0039     QString filename;
0040     QString storageLocation;
0041     QString md5sum;
0042     QImage image;
0043     QMap<QString, QVariant> metadata;
0044 };
0045 
0046 KoResource::KoResource()
0047     : d(new Private)
0048 {
0049 }
0050 
0051 KoResource::KoResource(const QString& filename)
0052     : d(new Private)
0053 {
0054     d->filename = filename;
0055     d->name = QFileInfo(filename).fileName();
0056 }
0057 
0058 KoResource::~KoResource()
0059 {
0060     delete d;
0061 }
0062 
0063 KoResource::KoResource(const KoResource &rhs)
0064     : d(new Private(*rhs.d))
0065 {
0066 }
0067 
0068 bool KoResource::load(KisResourcesInterfaceSP resourcesInterface)
0069 {
0070     QFile file(filename());
0071 
0072     if (!file.exists()) {
0073         qWarning() << "Resource file doesn't exist: " << filename();
0074         return false;
0075     }
0076 
0077     if (file.size() == 0) {
0078         qWarning() << "Resource file is empty: " << filename();
0079         return false;
0080     }
0081 
0082     if (!file.open(QIODevice::ReadOnly)) {
0083         qWarning() << "Cannot open resource file for reading" << filename();
0084         return false;
0085     }
0086 
0087     const bool res = loadFromDevice(&file, resourcesInterface);
0088 
0089     if (!res) {
0090         qWarning() << "Could not load resource file" << filename();
0091     }
0092 
0093     file.close();
0094 
0095     return res;
0096 }
0097 
0098 bool KoResource::save()
0099 {
0100     if (filename().isEmpty()) return false;
0101 
0102     QFile file(filename());
0103 
0104     if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
0105         warnKrita << "Can't open file for writing" << filename();
0106         return false;
0107     }
0108 
0109     saveToDevice(&file);
0110 
0111     file.close();
0112     return true;
0113 }
0114 
0115 bool KoResource::saveToDevice(QIODevice *dev) const
0116 {
0117     Q_UNUSED(dev);
0118     return true;
0119 }
0120 
0121 QImage KoResource::image() const
0122 {
0123     return d->image;
0124 }
0125 
0126 void KoResource::updateThumbnail()
0127 {
0128 }
0129 
0130 void KoResource::updateLinkedResourcesMetaData(KisResourcesInterfaceSP /*resourcesInterface*/)
0131 {
0132 }
0133 
0134 QImage KoResource::thumbnail() const
0135 {
0136     return image();
0137 }
0138 
0139 QString KoResource::thumbnailPath() const
0140 {
0141     return QString();
0142 }
0143 
0144 void KoResource::setImage(const QImage &image)
0145 {
0146     d->image = image;
0147 }
0148 
0149 QString KoResource::md5Sum(bool generateIfEmpty) const
0150 {
0151     // [this assert is disputable] ephemeral resources have no md5
0152     KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!isEphemeral(), QString());
0153 
0154     if (d->md5sum.isEmpty() && generateIfEmpty) {
0155         // non-serializable resources should always have an externally generated md5
0156         KIS_SAFE_ASSERT_RECOVER_NOOP(isSerializable());
0157         dbgResources << "No MD5 for" << this << this->name();
0158         QBuffer buf;
0159         buf.open(QFile::WriteOnly);
0160         saveToDevice(&buf);
0161         buf.close();
0162         const_cast<KoResource*>(this)->setMD5Sum(KoMD5Generator::generateHash(buf.data()));
0163     }
0164     return d->md5sum;
0165 }
0166 
0167 void KoResource::setMD5Sum(const QString &md5sum)
0168 {
0169     /// ephemeral resources have no md5, trying to assign
0170     /// them one is considered an error
0171     KIS_SAFE_ASSERT_RECOVER_RETURN(!isEphemeral());
0172 
0173     if (valid()) {
0174         Q_ASSERT(!md5sum.isEmpty());
0175     }
0176     d->md5sum = md5sum;
0177 }
0178 
0179 QString KoResource::filename() const
0180 {
0181     return d->filename;
0182 }
0183 
0184 void KoResource::setFilename(const QString& filename)
0185 {
0186     d->filename = QFileInfo(filename).fileName();
0187 }
0188 
0189 QString KoResource::name() const
0190 {
0191     return d->name;
0192 }
0193 
0194 void KoResource::setName(const QString& name)
0195 {
0196     d->name = name;
0197 }
0198 
0199 bool KoResource::valid() const
0200 {
0201     return d->valid;
0202 }
0203 
0204 void KoResource::setValid(bool valid)
0205 {
0206     d->valid = valid;
0207 }
0208 
0209 bool KoResource::active() const
0210 {
0211     return d->active;
0212 }
0213 
0214 void KoResource::setActive(bool active)
0215 {
0216     d->active = active;
0217 }
0218 
0219 
0220 QString KoResource::defaultFileExtension() const
0221 {
0222     return QString();
0223 }
0224 
0225 bool KoResource::permanent() const
0226 {
0227     return d->permanent;
0228 }
0229 
0230 void KoResource::setPermanent(bool permanent)
0231 {
0232     d->permanent = permanent;
0233 }
0234 
0235 int KoResource::resourceId() const
0236 {
0237     return d->resourceId;
0238 }
0239 
0240 QList<KoResourceLoadResult> KoResource::requiredResources(KisResourcesInterfaceSP globalResourcesInterface) const
0241 {
0242     return linkedResources(globalResourcesInterface) + embeddedResources(globalResourcesInterface);
0243 }
0244 
0245 QList<KoResourceLoadResult> KoResource::linkedResources(KisResourcesInterfaceSP globalResourcesInterface) const
0246 {
0247     QList<KoResourceLoadResult> list;
0248     Q_UNUSED(list);
0249 
0250     Q_UNUSED(globalResourcesInterface);
0251     return {};
0252 }
0253 
0254 QList<KoResourceLoadResult> KoResource::embeddedResources(KisResourcesInterfaceSP globalResourcesInterface) const
0255 {
0256     Q_UNUSED(globalResourcesInterface);
0257     return {};
0258 }
0259 
0260 QList<int> KoResource::requiredCanvasResources() const
0261 {
0262     return {};
0263 }
0264 
0265 QString KoResource::storageLocation() const
0266 {
0267     return d->storageLocation;
0268 }
0269 
0270 void KoResource::setDirty(bool value)
0271 {
0272     d->dirty = value;
0273 }
0274 
0275 bool KoResource::isDirty() const
0276 {
0277     return d->dirty;
0278 }
0279 
0280 void KoResource::addMetaData(QString key, QVariant value)
0281 {
0282     d->metadata.insert(key, value);
0283 }
0284 
0285 QMap<QString, QVariant> KoResource::metadata() const
0286 {
0287     return d->metadata;
0288 }
0289 
0290 int KoResource::version() const
0291 {
0292     return d->version;
0293 }
0294 
0295 void KoResource::setVersion(int version)
0296 {
0297     d->version = version;
0298 }
0299 
0300 void KoResource::setResourceId(int id)
0301 {
0302     d->resourceId = id;
0303 }
0304 
0305 KoResourceSignature KoResource::signature() const
0306 {
0307     return KoResourceSignature(resourceType().first, md5Sum(false), filename(), name());
0308 }
0309 
0310 bool KoResource::isEphemeral() const
0311 {
0312     return false;
0313 }
0314 
0315 bool KoResource::isSerializable() const
0316 {
0317     return !isEphemeral();
0318 }
0319 
0320 void KoResource::setStorageLocation(const QString &location)
0321 {
0322     d->storageLocation = location;
0323 }