File indexing completed on 2024-05-19 04:27:42

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