Krita Source Code Documentation
Loading...
Searching...
No Matches
KisFolderStorage.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2018 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#include "KisFolderStorage.h"
8
9#include <QDirIterator>
10#include <KisMimeDatabase.h>
11#include <kis_debug.h>
12#include <KisTag.h>
15#include <kis_pointer_utils.h>
16#include <KoMD5Generator.h>
17
18
20{
21public:
22
23 FolderTagIterator(const QString &location, const QString &resourceType)
24 : m_location(location)
25 , m_resourceType(resourceType)
26 {
27 m_dirIterator.reset(new QDirIterator(location + '/' + resourceType,
28 QStringList() << "*.tag",
29 QDir::Files | QDir::Readable,
30 QDirIterator::Subdirectories));
31 }
32
33 bool hasNext() const override
34 {
35 return m_dirIterator->hasNext();
36 }
37
38 void next() override
39 {
40 m_dirIterator->next();
41 const_cast<FolderTagIterator*>(this)->m_tag.reset(new KisTag);
42 if (!load(m_tag)) {
43 qWarning() << "Could not load tag" << m_dirIterator->filePath();
44 }
45 }
46
47 KisTagSP tag() const override
48 {
49 return m_tag;
50 }
51
52private:
53
54 bool load(KisTagSP tag) const
55 {
56 QFile f(m_dirIterator->filePath());
57 tag->setFilename(m_dirIterator->fileName());
58 if (f.exists()) {
59 f.open(QFile::ReadOnly);
60 if (!tag->load(f)) {
61 qWarning() << m_dirIterator->filePath() << "is not a valid tag desktop file";
62 return false;
63 }
64
65 }
66 return true;
67 }
68
69 QScopedPointer<QDirIterator> m_dirIterator;
70 QString m_location;
73};
74
75
77{
78public:
79 ~FolderItem() override {}
80};
81
82
83KisFolderStorage::KisFolderStorage(const QString &location)
84 : KisStoragePlugin(location)
85{
86}
87
91
92bool KisFolderStorage::saveAsNewVersion(const QString &resourceType, KoResourceSP _resource)
93{
94 return KisStorageVersioningHelper::addVersionedResource(location() + "/" + resourceType, _resource, 0);
95}
96
98{
99 QFileInfo fi(url);
100 FolderItem item;
101 item.url = url;
102 item.folder = fi.path().split("/").last();
103 item.lastModified = fi.lastModified();
104 return item;
105}
106
108{
109 QFileInfo fi(location() + '/' + resource->resourceType().first + '/' + resource->filename());
110
111 QFile f(fi.absoluteFilePath());
112 if (!f.open(QFile::ReadOnly)) {
113 qWarning() << "Could not open" << fi.absoluteFilePath() << "for reading";
114 return false;
115 }
116
117 bool r = resource->loadFromDevice(&f, KisGlobalResourcesInterface::instance());
118
119 // Check for the thumbnail
120 if (r) {
122
123 if ((resource->image().isNull() || resource->thumbnail().isNull()) && !resource->thumbnailPath().isNull()) {
124 QImage img(location() + '/' + resource->resourceType().first + '/' + resource->thumbnailPath());
125 resource->setImage(img);
126 resource->updateThumbnail();
127 }
128 }
129
130 return r;
131}
132
133QString KisFolderStorage::resourceMd5(const QString &url)
134{
135 QString result;
136
137 QFile file(location() + "/" + url);
138 if (file.exists() && file.open(QIODevice::ReadOnly)) {
139 result = KoMD5Generator::generateHash(file.readAll());
140 }
141
142 return result;
143}
144
145QString KisFolderStorage::resourceFilePath(const QString &url)
146{
147 QFileInfo file(location() + "/" + url);
148 return file.exists() ? file.absoluteFilePath() : QString();
149}
150
152{
154
155 const QString resourcesSaveLocation = location() + "/" + resourceType;
156
157 QDirIterator it(resourcesSaveLocation,
158 KisResourceLoaderRegistry::instance()->filters(resourceType),
159 QDir::Files | QDir::Readable,
160 QDirIterator::Subdirectories);;
161
162 while (it.hasNext()) {
163 it.next();
164 QFileInfo info(it.fileInfo());
165
167 entry.filename = it.filePath().mid(resourcesSaveLocation.size() + 1);
168
169 // Don't load 4.x backup resources
170 if (entry.filename.contains("backup")) {
171 continue;
172 }
173
174 entry.lastModified = info.lastModified();
175 entry.tagList = {}; // TODO
176 entry.resourceType = resourceType;
177 entries.append(entry);
178 }
179
181
182 return toQShared(new KisVersionedStorageIterator(entries, this));
183}
184
189
190bool KisFolderStorage::importResource(const QString &url, QIODevice *device)
191{
192 bool result = false;
193
194 const QString resourcesLocation = location() + "/" + url;
195
196 QFile f(resourcesLocation);
197
198 if (f.exists()) return result;
199
200 if (f.open(QFile::WriteOnly)) {
201 qint64 writtenBytes = f.write(device->readAll());
202 f.close();
203 result = (writtenBytes == device->size());
204 } else {
205 qWarning() << "Cannot open" << resourcesLocation << "for writing";
206 }
207
208 KoResourceSP resourceAfterLoading = resource(url);
209
210 if (resourceAfterLoading.isNull()) {
211 f.remove();
212 return false;
213 }
214
215 return result;
216}
217
218bool KisFolderStorage::exportResource(const QString &url, QIODevice *device)
219{
220 bool result = false;
221
222 const QString resourcesLocation = location() + "/" + url;
223
224 QFile f(resourcesLocation);
225
226 if (!f.exists()) return result;
227
228 if (f.open(QFile::ReadOnly)) {
229 device->write(f.readAll());
230 f.close();
231 result = true;
232 } else {
233 qWarning() << "Cannot open" << resourcesLocation << "for reading";
234 }
235
236 return result;
237}
238
239bool KisFolderStorage::addResource(const QString &resourceType, KoResourceSP resource)
240{
241 if (!resource || !resource->valid()) return false;
242
243 const QString resourcesSaveLocation = location() + "/" + resourceType;
244
245 QFileInfo fi(resourcesSaveLocation + "/" + resource->filename());
246 if (fi.exists()) {
247 qWarning() << "Resource" << resourceType << resource->filename() << "already exists in" << resourcesSaveLocation;
248 return false;
249 }
250
251 QFile resourceFile(fi.absoluteFilePath());
252 if (!resourceFile.open(QFile::WriteOnly)) {
253 qWarning() << "Could not open" << fi.absoluteFilePath() << "for writing.";
254 return false;
255 }
256
257 if (!resource->saveToDevice(&resourceFile)) {
258 qWarning() << "Could not save resource to" << fi.absoluteFilePath();
259 resourceFile.close();
260 return false;
261 }
262 resourceFile.close();
263
264
265
266
267 return true;
268}
269
274
275QVariant KisFolderStorage::metaData(const QString &key) const
276{
278 return i18n("Local Resources");
279 }
280 return QVariant();
281
282}
QList< QString > QStringList
~FolderItem() override
bool hasNext() const override
KisTagSP tag() const override
A tag object on which we can set properties and which we can save.
void next() override
The iterator is only valid if next() has been called at least once.
bool load(KisTagSP tag) const
QScopedPointer< QDirIterator > m_dirIterator
FolderTagIterator(const QString &location, const QString &resourceType)
KisFolderStorage(const QString &location)
bool loadVersionedResource(KoResourceSP resource) override
QString resourceMd5(const QString &url) override
QVariant metaData(const QString &key) const override
bool addResource(const QString &resourceType, KoResourceSP resource) override
QStringList metaDataKeys() const override
QString resourceFilePath(const QString &url) override
KisResourceStorage::ResourceItem resourceItem(const QString &url) override
bool importResource(const QString &url, QIODevice *device) override
bool exportResource(const QString &url, QIODevice *device) override
QSharedPointer< KisResourceStorage::ResourceIterator > resources(const QString &resourceType) override
bool saveAsNewVersion(const QString &resourceType, KoResourceSP resource) override
Adds or updates this resource to the storage.
QSharedPointer< KisResourceStorage::TagIterator > tags(const QString &resourceType) override
static KisResourcesInterfaceSP instance()
static KisResourceLoaderRegistry * instance()
static const QString s_meta_name
QString location() const
virtual KoResourceSP resource(const QString &url)
void sanitizeResourceFileNameCase(KoResourceSP resource, const QDir &parentDir)
static void detectFileVersions(QVector< VersionedResourceEntry > &allFiles)
static bool addVersionedResource(const QString &saveLocation, KoResourceSP resource, int minVersion)
The KisTag loads a tag from a .tag file. A .tag file is a .desktop file. The following fields are imp...
Definition KisTag.h:34
static QString generateHash(const QString &filename)
generateHash reads the given file and generates a hex-encoded md5sum for the file.
QSharedPointer< T > toQShared(T *ptr)
A resource item is simply an entry in the storage,.