10#include <QApplication>
15#include <QRegularExpression>
19#include <boost/optional.hpp>
92 d->name = QFileInfo(
d->location).fileName();
94 QFileInfo fi(
d->location);
98 d->valid = fi.isWritable();
100 else if (
d->name.endsWith(
".bundle", Qt::CaseInsensitive)) {
104 d->valid = (fi.isReadable() && QuaZip(
d->location).open(QuaZip::mdUnzip));
106 else if (
d->name.endsWith(
".abr", Qt::CaseInsensitive)) {
109 d->valid = fi.isReadable();
111 else if (
d->name.endsWith(
".asl", Qt::CaseInsensitive)) {
114 d->valid =
d->storagePlugin->isValid();
116 else if (
d->location ==
"fontregistry") {
119 auto storage = factory->create(
location);
120 d->storagePlugin.reset(storage);
130 else if (
d->location ==
"memory" || !QUuid::fromString(
d->location).isNull() || (!
d->location.isEmpty() && !fi.exists())) {
156 d->location = rhs.
d->location;
157 d->storageType = rhs.
d->storageType;
164 d->storagePlugin = rhs.
d->storagePlugin;
188 return d->storageType;
193 return d->storagePlugin->thumbnail();
198 return d->storagePlugin->timestamp();
203 QFileInfo li(
d->location);
204 if (li.suffix().toLower() ==
"bundle") {
205 QFileInfo bf(
d->location +
"_modified/" + resourceType +
"/" + filename);
207 return bf.lastModified();
209 }
else if (QFileInfo(
d->location +
"/" + resourceType +
"/" + filename).exists()) {
210 return QFileInfo(
d->location +
"/" + resourceType +
"/" + filename).lastModified();
217 return d->storagePlugin->resourceItem(url);
222 return d->storagePlugin->resource(url);
227 return d->storagePlugin->resourceMd5(url);
232 return d->storagePlugin->resourceFilePath(url);
237 return d->storagePlugin->resources(resourceType);
242 return d->storagePlugin->tags(resourceType);
249 return d->storagePlugin->saveAsNewVersion(
resource->resourceType().first,
resource);
261 return d->storagePlugin->importResource(url, device);
266 return d->storagePlugin->exportResource(url, device);
271 return d->storagePlugin->supportsVersioning();
276 return d->storagePlugin->loadVersionedResource(
resource);
281 d->storagePlugin->setMetaData(key,
value);
291 return d->storagePlugin->metaDataKeys();
296 return d->storagePlugin->metaData(key);
311 return d->storagePlugin.data();
323 QRegularExpression exp(
"^(.*)\\.(\\d\\d*)\\.(.+)$");
325 QRegularExpressionMatch res = exp.match(filename);
327 if (res.hasMatch()) {
328 return VersionedFileParts({res.captured(1), res.captured(2).toInt(), res.captured(3)});
338 guess->version = qMax(guess->version, minVersion);
340 QFileInfo info(filename);
342 guess->basename = info.baseName();
343 guess->version = minVersion;
344 guess->suffix = info.completeSuffix();
352 std::function<
bool(QString)> checkExists)
354 int version = qMax(resource->version(), minVersion);
362 int numPlaceholders = 4;
364 if (version > 9999) {
365 numPlaceholders = qFloor(std::log10(version)) + 1;
368 QString versionString = QString(
"%1").arg(version, numPlaceholders, 10, QChar(
'0'));
371 if (versionString ==
"0000" && qApp->applicationName() ==
"krita") {
372 newFilename = resource->filename();
381 if (checkExists(newFilename)) {
383 if (version == std::numeric_limits<int>::max()) {
397 for (
auto it = allFiles.begin(); it != allFiles.end(); ++it) {
400 it->guessedVersion = parts.
version;
405 boost::optional<QString> lastResourceKey;
406 int availableVersion = 0;
407 for (
auto it = allFiles.begin(); it != allFiles.end(); ++it) {
408 if (!lastResourceKey || *lastResourceKey != it->guessedKey) {
409 availableVersion = 0;
410 lastResourceKey = it->guessedKey;
413 if (it->guessedVersion < availableVersion) {
414 it->guessedVersion = availableVersion;
417 availableVersion = it->guessedVersion + 1;
425 int version = qMax(resource->version(), minVersion);
430 QString newFilename =
432 [saveLocation] (
const QString &filename) {
433 return QFileInfo(saveLocation +
"/" + filename).exists();
436 if (newFilename.isEmpty())
return false;
438 QFile file(saveLocation +
"/" + newFilename);
441 if (!file.open(QFile::WriteOnly)) {
442 qWarning() <<
"Could not open resource file for writing" << newFilename;
446 if (!resource->saveToDevice(&file)) {
447 qWarning() <<
"Could not save resource file" << newFilename;
451 resource->setFilename(newFilename);
454 if (!resource->thumbnailPath().isEmpty()) {
457 if (!QFileInfo(saveLocation +
"/" + resource->thumbnailPath()).exists()) {
458 QImage thumbnail = resource->thumbnail();
459 thumbnail.save(saveLocation +
"/" + resource->thumbnailPath());
477 bool hasNext()
const override {
481 void next()
override {
485 QString url()
const override
487 return m_parent->url();
490 QString type()
const override
492 return m_parent->type();
495 QDateTime lastModified()
const override
497 return m_parent->lastModified();
500 int guessedVersion()
const override
502 return m_parent->guessedVersion();
507 return toQShared(
new DumbIterator(m_parent));
513 return m_parent->resource();
517 bool m_isStarted =
false;
526 if (m_cachedResource && m_cachedResourceUrl == url()) {
527 return m_cachedResource;
530 m_cachedResource = resourceImpl();
531 m_cachedResourceUrl = url();
533 return m_cachedResource;
539 , m_begin(m_entries.constBegin())
540 , m_end(m_entries.constEnd())
584 m_it = std::prev(nextChunk);
589 return m_it->resourceType +
"/" +
m_it->filename;
594 return m_it->resourceType;
599 return m_it->lastModified;
609 return m_it->guessedVersion;
624 void next()
override {
634 return toQShared(
new VersionsIterator(m_entries, m_it, std::next(m_it), q));
float value(const T *src, size_t ch)
VersionedFileParts guessFileNamePartsLazy(const QString &filename, int minVersion)
boost::optional< VersionedFileParts > guessFilenameParts(const QString &filename)
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
QSharedPointer< KisResourceStorage > KisResourceStorageSP
The KisMemoryStorage class stores the temporary resources that are not saved to disk or bundle....
QSharedPointer< KisStoragePlugin > storagePlugin
KisResourceStorage::StorageType storageType
virtual QSharedPointer< KisResourceStorage::ResourceIterator > versions() const
KoResourceSP resource() const
KoResourceSP resource(const QString &url)
The loaded resource for an entry in the storage.
QDateTime timestamp() const
KisResourceStorageSP clone() const
KisResourceStorage & operator=(const KisResourceStorage &rhs)
QVariant metaData(const QString &key) const
static const QString s_meta_author
static const QString s_meta_title
QSharedPointer< ResourceIterator > resources(const QString &resourceType) const
An iterator over all the resources in the storage.
static const QString s_meta_user_defined
static const QString s_meta_creation_date
static const QString s_meta_value
static const QString s_meta_email
bool valid() const
true if the storage exists and can be used
bool exportResource(const QString &url, QIODevice *device)
static const QString s_meta_license
static const QString s_xmlns_meta
bool addResource(KoResourceSP resource)
void setMetaData(const QString &key, const QVariant &value)
bool loadVersionedResource(KoResourceSP resource)
Reloads the given resource from the persistent storage.
QString location() const
The absolute location of the storage.
static const QString s_meta_description
QSharedPointer< TagIterator > tags(const QString &resourceType) const
An iterator over all the tags in the resource.
KisStoragePlugin * testingGetStoragePlugin()
static const QString s_meta_dc_date
bool supportsVersioning() const
QStringList metaDataKeys() const
ResourceItem resourceItem(const QString &url)
And entry in the storage; this is not the loaded resource.
void setStorageId(int storageId)
bool saveAsNewVersion(KoResourceSP resource)
Creates a new version of the given resource.
static const QString s_meta_website
static const QString s_meta_generator
StorageType type() const
The type of the storage.
static const QString s_meta_version
static const QString s_meta_name
QString resourceMd5(const QString &url)
The MD5 checksum of the resource in the storage.
QScopedPointer< Private > d
QDateTime timeStampForResource(const QString &resourceType, const QString &filename) const
static const QString s_xmlns_dc
static const QString s_meta_initial_creator
static const QString s_meta_creator
bool importResource(const QString &url, QIODevice *device)
QImage thumbnail() const
The icond for the storage.
KisResourceStorage(const QString &location)
QString resourceFilePath(const QString &url)
void addStoragePluginFactory(KisResourceStorage::StorageType storageType, KisStoragePluginFactoryBase *factory)
KisStoragePluginRegistry()
QList< KisResourceStorage::StorageType > storageTypes() const
virtual ~KisStoragePluginRegistry()
static KisStoragePluginRegistry * instance()
QMap< KisResourceStorage::StorageType, KisStoragePluginFactoryBase * > m_storageFactoryMap
virtual KoResourceSP resource(const QString &url)
static void detectFileVersions(QVector< VersionedResourceEntry > &allFiles)
static QString chooseUniqueName(KoResourceSP resource, int minVersion, std::function< bool(QString)> checkExists)
static bool addVersionedResource(const QString &saveLocation, KoResourceSP resource, int minVersion)
int guessedVersion() const override
const QVector< VersionedResourceEntry > m_entries
QString url() const override
QVector< VersionedResourceEntry >::const_iterator m_it
QDateTime lastModified() const override
KisVersionedStorageIterator(const QVector< VersionedResourceEntry > &entries, KisStoragePlugin *_q)
bool hasNext() const override
QVector< VersionedResourceEntry >::const_iterator m_begin
void next() override
The iterator is only valid if next() has been called at least once.
QVector< VersionedResourceEntry >::const_iterator m_chunkStart
QVector< VersionedResourceEntry >::const_iterator m_end
QString type() const override
QSharedPointer< KisResourceStorage::ResourceIterator > versions() const override
KoResourceSP resourceImpl() const override
This only loads the resource when called.
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
QSharedPointer< T > toQShared(T *ptr)
A resource item is simply an entry in the storage,.