Krita Source Code Documentation
Loading...
Searching...
No Matches
KisResourceLocator Class Reference

#include <KisResourceLocator.h>

+ Inheritance diagram for KisResourceLocator:

Classes

class  Private
 
struct  ResourceStorage
 

Public Types

enum class  LocatorError {
  Ok , LocationReadOnly , CannotCreateLocation , CannotInitializeDb ,
  CannotSynchronizeDb
}
 

Signals

void beginExternalResourceImport (const QString &resourceType, int numResources)
 Emitted when the locator needs to add an embedded resource.
 
void beginExternalResourceRemove (const QString &resourceType, const QVector< int > resourceIds)
 Emitted when the locator needs to add an embedded resource.
 
void endExternalResourceImport (const QString &resourceType)
 Emitted when the locator finished importing the embedded resource.
 
void endExternalResourceRemove (const QString &resourceType)
 Emitted when the locator finished importing the embedded resource.
 
void progressMessage (const QString &)
 
void resourceActiveStateChanged (const QString &resourceType, int resourceId)
 Emitted when a resource changes its active state.
 
void storageAdded (const QString &location)
 Emitted whenever a storage is added.
 
void storageRemoved (const QString &location)
 Emitted whenever a storage is removed.
 
void storageResynchronized (const QString &storage, bool isBulkResynchronization)
 
void storagesBulkSynchronizationFinished ()
 

Public Member Functions

bool addStorage (const QString &storageLocation, KisResourceStorageSP storage)
 addStorage Adds a new resource storage to the database. The storage is will be marked as not pre-installed. If there is already a storage with the given location, it will first be removed.
 
QStringList errorMessages () const
 errorMessages
 
QString filePathForResource (KoResourceSP resource)
 
bool hasStorage (const QString &storageLocation)
 hasStorage can be used to check whether the given storage already exists
 
LocatorError initialize (const QString &installationResourcesLocation)
 initialize Setup the resource locator for use.
 
void purge (const QString &storageLocation)
 purge purges the local resource cache
 
void purgeTag (const QString tagUrl, const QString resourceType)
 
bool removeStorage (const QString &storageLocation)
 removeStorage removes the temporary storage from the database
 
QString resourceLocationBase () const
 resourceLocationBase is the place where all resource storages (folder, bundles etc. are located. This is a writable place.
 
void updateFontStorage ()
 This updates the "fontregistry" storage. Called when the font directories change;.
 
 ~KisResourceLocator ()
 

Static Public Member Functions

static KisResourceLocatorinstance ()
 
static void saveTags ()
 saveTags saves all tags to .tag files in the resource folder
 

Static Public Attributes

static const QString resourceLocationKey {"ResourceDirectory"}
 

Private Types

enum class  InitializationStatus {
  Unknown , Initialized , FirstRun , FirstUpdate ,
  Updating
}
 

Private Member Functions

bool addResource (const QString &resourceType, const KoResourceSP resource, const QString &storageLocation=QString())
 addResource adds the given resource to the database and potentially a storage
 
bool exportResource (KoResourceSP resource, QIODevice *device)
 exportResource
 
void findStorages ()
 
LocatorError firstTimeInstallation (InitializationStatus initializationStatus, const QString &installationResourcesLocation)
 
KisResourceStorageSP folderStorage () const
 
KisResourceStorageSP fontStorage () const
 
ResourceStorage getResourceStorage (int resourceId) const
 
KoResourceSP importResource (const QString &resourceType, const QString &fileName, QIODevice *device, const bool allowOverwrite, const QString &storageLocation=QString())
 importResource
 
KoResourceSP importResourceFromFile (const QString &resourceType, const QString &fileName, const bool allowOverwrite, const QString &storageLocation=QString())
 importResourceFromFile
 
bool importWillOverwriteResource (const QString &resourceType, const QString &fileName, const QString &storageLocation=QString()) const
 return whether importing will overwrite some existing resource
 
 KisResourceLocator (const KisResourceLocator &)
 
 KisResourceLocator (QObject *parent)
 
void loadRequiredResources (KoResourceSP resource)
 
QString makeStorageLocationAbsolute (QString storageLocation) const
 
QString makeStorageLocationRelative (QString location) const
 
KisResourceStorageSP memoryStorage () const
 
QMap< QString, QVariant > metaDataForResource (int id) const
 metaDataForResource
 
QMap< QString, QVariant > metaDataForStorage (const QString &storageLocation) const
 metaDataForStorage
 
KisResourceLocator operator= (const KisResourceLocator &)
 
bool reloadResource (const QString &resourceType, const KoResourceSP resource)
 Reloads the resource from its persistent storage.
 
KoResourceSP resource (QString storageLocation, const QString &resourceType, const QString &filename)
 resource finds a physical resource in one of the storages
 
bool resourceCached (QString storageLocation, const QString &resourceType, const QString &filename) const
 
KoResourceSP resourceForId (int resourceId)
 resourceForId returns the resource with the given id, or 0 if no such resource exists. The resource object will have its id set but not its version.
 
bool setMetaDataForResource (int id, QMap< QString, QVariant > map) const
 setMetaDataForResource
 
void setMetaDataForStorage (const QString &storageLocation, QMap< QString, QVariant > map) const
 setMetaDataForStorage
 
bool setResourceActive (int resourceId, bool active)
 setResourceActive
 
KisResourceStorageSP storageByLocation (const QString &location) const
 
QList< KisResourceStorageSPstorages () const
 
bool synchronizeDb ()
 
KisTagSP tagForUrl (const QString &tagUrl, const QString resourceType)
 tagForUrl create a tag from the database
 
bool updateResource (const QString &resourceType, const KoResourceSP resource)
 updateResource
 

Static Private Member Functions

static KisTagSP tagForUrlNoCache (const QString &tagUrl, const QString resourceType)
 tagForUrlNoCache create a tag from the database, don't use cache
 

Private Attributes

QScopedPointer< Privated
 

Friends

class KisAllResourcesModel
 
class KisAllTagResourceModel
 
class KisAllTagsModel
 
class KisBrushTypeMetaDataFixup
 
class KisMyPaintPaintOpPreset
 
class KisResourceCacheDb
 
class KisResourceQueryMapper
 
class KisResourceThumbnailCache
 
class KisResourceUserOperations
 
class KisStorageFilterProxyModel
 
class KisStorageModel
 
class KisTagResourceModel
 
class Resource
 
class TestResourceLocator
 
class TestResourceModel
 

Detailed Description

The KisResourceLocator class locates all resource storages (folders, bundles, various adobe resource libraries) in the resource location.

The resource location is always a writable folder.

There is one resource locator which is owned by the QApplication object.

The resource location is configurable, but there is only one location where Krita will look for resources.

Definition at line 32 of file KisResourceLocator.h.

Member Enumeration Documentation

◆ InitializationStatus

enum class KisResourceLocator::InitializationStatus
strongprivate
Enumerator
Unknown 
Initialized 
FirstRun 
FirstUpdate 
Updating 

Definition at line 329 of file KisResourceLocator.h.

329 {
330 Unknown, // We don't know whether Krita has run on this system for this resource location yet
331 Initialized, // Everything is ready to start synchronizing the database
332 FirstRun, // Krita hasn't run for this resource location yet
333 FirstUpdate, // Krita was installed, but it's a version from before the resource locator existed, only user-defined resources are present
334 Updating // Krita is updating from an older version with resource locator
335 };

◆ LocatorError

Enumerator
Ok 
LocationReadOnly 
CannotCreateLocation 
CannotInitializeDb 
CannotSynchronizeDb 

Definition at line 47 of file KisResourceLocator.h.

Constructor & Destructor Documentation

◆ ~KisResourceLocator()

KisResourceLocator::~KisResourceLocator ( )

Definition at line 74 of file KisResourceLocator.cpp.

75{
76}

◆ KisResourceLocator() [1/2]

KisResourceLocator::KisResourceLocator ( QObject * parent)
private

Definition at line 57 of file KisResourceLocator.cpp.

58 : QObject(parent)
59 , d(new Private())
60{
61}
QScopedPointer< Private > d

◆ KisResourceLocator() [2/2]

KisResourceLocator::KisResourceLocator ( const KisResourceLocator & )
private

Member Function Documentation

◆ addResource()

bool KisResourceLocator::addResource ( const QString & resourceType,
const KoResourceSP resource,
const QString & storageLocation = QString() )
private

addResource adds the given resource to the database and potentially a storage

Parameters
resourceTypethe type of the resource
resourcethe actual resource object
storageLocationthe storage where the resource will be saved. By default this is the default folder storage.
Returns
true if successful

And to the database.

The metadata will be set by KisResourceCacheDb, which is not very consistent with KisResourceLocator::updateResource(), but works :)

Definition at line 622 of file KisResourceLocator.cpp.

623{
624 if (!resource || !resource->valid()) return false;
625
626 KisResourceStorageSP storage = d->storages[makeStorageLocationAbsolute(storageLocation)];
627 Q_ASSERT(storage);
628
629 //If we have gotten this far and the resource still doesn't have a filename to save to, we should generate one.
630 if (resource->filename().isEmpty()) {
631 resource->setFilename(resource->name().split(" ").join("_") + resource->defaultFileExtension());
632 }
633
634 if (resource->version() != 0) { // Can happen with cloned resources
635 resource->setVersion(0);
636 }
637
638 // Save the resource to the storage storage
639 if (!storage->addResource(resource)) {
640 qWarning() << "Could not add resource" << resource->filename() << "to the storage" << storageLocation;
641 return false;
642 }
643
644 resource->setStorageLocation(storageLocation);
645 resource->setMD5Sum(storage->resourceMd5(resourceType + "/" + resource->filename()));
646 resource->setDirty(false);
648
649 d->resourceCache[QPair<QString, QString>(storageLocation, resourceType + "/" + resource->filename())] = resource;
650
656 const bool result = KisResourceCacheDb::addResource(storage,
657 storage->timeStampForResource(resourceType, resource->filename()),
658 resource,
659 resourceType);
660 return result;
661}
static bool addResource(KisResourceStorageSP storage, QDateTime timestamp, KoResourceSP resource, const QString &resourceType)
KoResourceSP resource(QString storageLocation, const QString &resourceType, const QString &filename)
resource finds a physical resource in one of the storages
void loadRequiredResources(KoResourceSP resource)
QString makeStorageLocationAbsolute(QString storageLocation) const

References KisResourceCacheDb::addResource(), d, loadRequiredResources(), makeStorageLocationAbsolute(), and resource().

◆ addStorage()

bool KisResourceLocator::addStorage ( const QString & storageLocation,
KisResourceStorageSP storage )

addStorage Adds a new resource storage to the database. The storage is will be marked as not pre-installed. If there is already a storage with the given location, it will first be removed.

Parameters
storageLocationa unique name for the given storage
storagea storage object
Returns
true if the storage has been added successfully

Definition at line 786 of file KisResourceLocator.cpp.

787{
788 if (d->storages.contains(storageLocation)) {
789 if (!removeStorage(storageLocation)) {
790 qWarning() << "could not remove" << storageLocation;
791 return false;
792 }
793 }
794
795 QVector<std::pair<QString, int>> addedResources;
796 Q_FOREACH(const QString &type, KisResourceLoaderRegistry::instance()->resourceTypes()) {
797 int numAddedResources = 0;
798
799 QSharedPointer<KisResourceStorage::ResourceIterator> it = storage->resources(type);
800 while (it->hasNext()) {
801 it->next();
802 numAddedResources++;
803 }
804
805 if (numAddedResources > 0) {
806 addedResources << std::make_pair(type, numAddedResources);
807 }
808 }
809
810 Q_FOREACH (const auto &typedResources, addedResources) {
811 Q_EMIT beginExternalResourceImport(typedResources.first, typedResources.second);
812 }
813
814 d->storages[storageLocation] = storage;
815 if (!KisResourceCacheDb::addStorage(storage, false)) {
816 d->errorMessages.append(i18n("Could not add %1 to the database", storage->location()));
817 qWarning() << d->errorMessages;
818 return false;
819 }
820
822 d->errorMessages.append(QString("Could not add tags for storage %1 to the cache database").arg(storage->location()));
823 qWarning() << d->errorMessages;
824 return false;
825 }
826
827 Q_FOREACH (const auto &typedResources, addedResources) {
828 Q_EMIT endExternalResourceImport(typedResources.first);
829 }
830
831 Q_EMIT storageAdded(makeStorageLocationRelative(storage->location()));
832 return true;
833}
static bool addStorage(KisResourceStorageSP storage, bool preinstalled)
static bool addStorageTags(KisResourceStorageSP storage)
static KisResourceLoaderRegistry * instance()
void storageAdded(const QString &location)
Emitted whenever a storage is added.
bool removeStorage(const QString &storageLocation)
removeStorage removes the temporary storage from the database
void beginExternalResourceImport(const QString &resourceType, int numResources)
Emitted when the locator needs to add an embedded resource.
QString makeStorageLocationRelative(QString location) const
void endExternalResourceImport(const QString &resourceType)
Emitted when the locator finished importing the embedded resource.

References KisResourceCacheDb::addStorage(), KisResourceCacheDb::addStorageTags(), beginExternalResourceImport(), d, endExternalResourceImport(), KisResourceLoaderRegistry::instance(), makeStorageLocationRelative(), removeStorage(), and storageAdded().

◆ beginExternalResourceImport

void KisResourceLocator::beginExternalResourceImport ( const QString & resourceType,
int numResources )
signal

Emitted when the locator needs to add an embedded resource.

◆ beginExternalResourceRemove

void KisResourceLocator::beginExternalResourceRemove ( const QString & resourceType,
const QVector< int > resourceIds )
signal

Emitted when the locator needs to add an embedded resource.

◆ endExternalResourceImport

void KisResourceLocator::endExternalResourceImport ( const QString & resourceType)
signal

Emitted when the locator finished importing the embedded resource.

◆ endExternalResourceRemove

void KisResourceLocator::endExternalResourceRemove ( const QString & resourceType)
signal

Emitted when the locator finished importing the embedded resource.

◆ errorMessages()

QStringList KisResourceLocator::errorMessages ( ) const

errorMessages

Returns

Definition at line 135 of file KisResourceLocator.cpp.

136{
137 return d->errorMessages;
138}

References d.

◆ exportResource()

bool KisResourceLocator::exportResource ( KoResourceSP resource,
QIODevice * device )
private

exportResource

Parameters
resourceresource to be exported
deviceQIODevice where the resource should be loaded to
Returns
true if the resource has been exported successfully

Definition at line 613 of file KisResourceLocator.cpp.

614{
615 if (!resource || !resource->valid() || resource->resourceId() < 0) return false;
616
617 const QString resourceUrl = resource->resourceType().first + "/" + resource->filename();
618 KisResourceStorageSP storage = d->storages[makeStorageLocationAbsolute(resource->storageLocation())];
619 return storage->exportResource(resourceUrl, device);
620}

References d, makeStorageLocationAbsolute(), and resource().

◆ filePathForResource()

QString KisResourceLocator::filePathForResource ( KoResourceSP resource)

Returns the full file path of the resource if it has any separate physical representation on the disk

Definition at line 956 of file KisResourceLocator.cpp.

957{
958 const QString storageLocation = makeStorageLocationAbsolute(resource->storageLocation());
959 KisResourceStorageSP storage = d->storages[storageLocation];
960 if (!storage) {
961 qWarning() << "Could not find storage" << storageLocation;
962 return QString();
963 }
964
965 const QString resourceUrl = resource->resourceType().first + "/" + resource->filename();
966
967 return storage->resourceFilePath(resourceUrl);
968}

References d, makeStorageLocationAbsolute(), and resource().

◆ findStorages()

void KisResourceLocator::findStorages ( )
private

Definition at line 1029 of file KisResourceLocator.cpp.

1030{
1031 d->storages.clear();
1032 d->resourceCache.clear();
1033
1034 // Add the folder
1036 Q_ASSERT(storage->location() == d->resourceLocation);
1037 d->storages[d->resourceLocation] = storage;
1038
1039 // Add the memory storage
1040 d->storages["memory"] = QSharedPointer<KisResourceStorage>::create("memory");
1041 d->storages["memory"]->setMetaData(KisResourceStorage::s_meta_name, i18n("Temporary Resources"));
1042
1043 // Add font storage
1045 if (fontStorage && fontStorage->valid()) {
1046 d->storages["fontregistry"] = fontStorage;
1047 d->storages["fontregistry"]->setMetaData(KisResourceStorage::s_meta_name, i18n("Font Storage"));
1048 }
1049
1050 // And add bundles and adobe libraries
1051 QStringList filters = QStringList() << "*.bundle" << "*.abr" << "*.asl";
1052 QDirIterator iter(d->resourceLocation, filters, QDir::Files, QDirIterator::Subdirectories);
1053 while (iter.hasNext()) {
1054 iter.next();
1056 if (!storage->valid()) {
1057 // we still add the storage to the list and try to read whatever possible
1058 qWarning() << "KisResourceLocator::findStorages: the storage is invalid" << storage->location();
1059 }
1060 d->storages[storage->location()] = storage;
1061 }
1062
1063 // Add any missing storage types to the resource cache database.
1064 Q_FOREACH(const KisResourceStorage::StorageType &type, KisStoragePluginRegistry::instance()->storageTypes()) {
1066 }
1067}
QList< QString > QStringList
static bool registerStorageType(const KisResourceStorage::StorageType storageType)
registerStorageType registers this storage type in the database
KisResourceStorageSP fontStorage() const
static const QString s_meta_name
static KisStoragePluginRegistry * instance()

References d, fontStorage(), KisStoragePluginRegistry::instance(), KisResourceCacheDb::registerStorageType(), and KisResourceStorage::s_meta_name.

◆ firstTimeInstallation()

KisResourceLocator::LocatorError KisResourceLocator::firstTimeInstallation ( InitializationStatus initializationStatus,
const QString & installationResourcesLocation )
private

Definition at line 979 of file KisResourceLocator.cpp.

980{
981 Q_EMIT progressMessage(i18n("Krita is running for the first time. Initialization will take some time."));
982 Q_UNUSED(initializationStatus);
983
984 Q_FOREACH(const QString &folder, KisResourceLoaderRegistry::instance()->resourceTypes()) {
985 QDir dir(d->resourceLocation + '/' + folder + '/');
986 if (!dir.exists()) {
987 if (!QDir().mkpath(d->resourceLocation + '/' + folder + '/')) {
988 d->errorMessages << i18n("3. Could not create the resource location at %1.", dir.path());
990 }
991 }
992 }
993
994 Q_FOREACH(const QString &folder, KisResourceLoaderRegistry::instance()->resourceTypes()) {
995 QDir dir(installationResourcesLocation + '/' + folder + '/');
996 if (dir.exists()) {
997 Q_FOREACH(const QString &entry, dir.entryList(QDir::Files | QDir::Readable)) {
998 QFile f(dir.canonicalPath() + '/'+ entry);
999 if (!QFileInfo(d->resourceLocation + '/' + folder + '/' + entry).exists()) {
1000 if (!f.copy(d->resourceLocation + '/' + folder + '/' + entry)) {
1001 d->errorMessages << i18n("Could not copy resource %1 to %2", f.fileName(), d->resourceLocation + '/' + folder + '/' + entry);
1002 }
1003 }
1004 }
1005 }
1006 }
1007
1008 // And add bundles and adobe libraries
1009 QStringList filters = QStringList() << "*.bundle" << "*.abr" << "*.asl";
1010 QDirIterator iter(installationResourcesLocation, filters, QDir::Files, QDirIterator::Subdirectories);
1011 while (iter.hasNext()) {
1012 iter.next();
1013 Q_EMIT progressMessage(i18n("Installing the resources from bundle %1.", iter.filePath()));
1014 QFile f(iter.filePath());
1015 Q_ASSERT(f.exists());
1016 if (!f.copy(d->resourceLocation + '/' + iter.fileName())) {
1017 d->errorMessages << i18n("Could not copy resource %1 to %2", f.fileName(), d->resourceLocation);
1018 }
1019 }
1020
1021 QFile f(d->resourceLocation + '/' + "KRITA_RESOURCE_VERSION");
1022 f.open(QFile::WriteOnly);
1023 f.write(KritaVersionWrapper::versionString().toUtf8());
1024 f.close();
1025
1026 return LocatorError::Ok;
1027}
void progressMessage(const QString &)
KRITAVERSION_EXPORT QString versionString(bool checkGit=false)

References CannotCreateLocation, d, KisResourceLoaderRegistry::instance(), Ok, progressMessage(), and KritaVersionWrapper::versionString().

◆ folderStorage()

KisResourceStorageSP KisResourceLocator::folderStorage ( ) const
private

Definition at line 1089 of file KisResourceLocator.cpp.

1090{
1091 return storageByLocation(d->resourceLocation);
1092}
KisResourceStorageSP storageByLocation(const QString &location) const

References d, and storageByLocation().

◆ fontStorage()

KisResourceStorageSP KisResourceLocator::fontStorage ( ) const
private

Definition at line 1099 of file KisResourceLocator.cpp.

1100{
1101 return storageByLocation("fontregistry");
1102}

References storageByLocation().

◆ getResourceStorage()

KisResourceLocator::ResourceStorage KisResourceLocator::getResourceStorage ( int resourceId) const
private

Definition at line 1104 of file KisResourceLocator.cpp.

1105{
1106 ResourceStorage rs;
1107
1108 QSqlQuery q;
1109 bool r = q.prepare("SELECT storages.location\n"
1110 ", resource_types.name as resource_type\n"
1111 ", resources.filename\n"
1112 "FROM resources\n"
1113 ", storages\n"
1114 ", resource_types\n"
1115 "WHERE resources.id = :resource_id\n"
1116 "AND resources.storage_id = storages.id\n"
1117 "AND resource_types.id = resources.resource_type_id");
1118 if (!r) {
1119 qWarning() << "KisResourceLocator::removeResource: could not prepare query." << q.lastError();
1120 return rs;
1121 }
1122
1123
1124 q.bindValue(":resource_id", resourceId);
1125
1126 r = q.exec();
1127 if (!r) {
1128 qWarning() << "KisResourceLocator::removeResource: could not execute query." << q.lastError();
1129 return rs;
1130 }
1131
1132 q.first();
1133
1134 QString storageLocation = q.value("location").toString();
1135 QString resourceType= q.value("resource_type").toString();
1136 QString resourceFilename = q.value("filename").toString();
1137
1138 rs.storageLocation = makeStorageLocationAbsolute(storageLocation);
1139 rs.resourceType = resourceType;
1140 rs.resourceFileName = resourceFilename;
1141
1142 return rs;
1143}

References makeStorageLocationAbsolute(), KisResourceLocator::ResourceStorage::resourceFileName, KisResourceLocator::ResourceStorage::resourceType, and KisResourceLocator::ResourceStorage::storageLocation.

◆ hasStorage()

bool KisResourceLocator::hasStorage ( const QString & storageLocation)

hasStorage can be used to check whether the given storage already exists

Parameters
storageLocationthe name of the storage
Returns
true if the storage is known

Definition at line 874 of file KisResourceLocator.cpp.

875{
876 return d->storages.contains(document);
877}

References d.

◆ importResource()

KoResourceSP KisResourceLocator::importResource ( const QString & resourceType,
const QString & fileName,
QIODevice * device,
const bool allowOverwrite,
const QString & storageLocation = QString() )
private

importResource

Parameters
resourceType
fileNamefilename that should be assigned to the resource
deviceQIODevice where the resource should be loaded from
storageLocationoptional, the storage where the resource will be stored. Empty means in the default Folder storage.
Returns
the imported resource, which has been added to the database and the cache

Make sure that this resource is the latest version of the resource. Also, we cannot just return existingResource, because it has uninitialized fields. It should go through the initialization by the locator's caching system.

Definition at line 444 of file KisResourceLocator.cpp.

445{
446 KisResourceStorageSP storage = d->storages[makeStorageLocationAbsolute(storageLocation)];
447
448 QByteArray resourceData = device->readAll();
450
451 {
452 QBuffer buf(&resourceData);
453 buf.open(QBuffer::ReadOnly);
454
456
457 if (!loader) {
458 qWarning() << "Could not import" << fileName << ": resource doesn't load.";
459 return nullptr;
460 }
461
462 resource = loader->load(QFileInfo(fileName).fileName(), buf, KisGlobalResourcesInterface::instance());
463 }
464
465 if (!resource || !resource->valid()) {
466 qWarning() << "Could not import" << fileName << ": resource doesn't load.";
467 return nullptr;
468 }
469
470 const QString md5 = KoMD5Generator::generateHash(resourceData);
471 const QString resourceUrl = resourceType + "/" + resource->filename();
472
473 const KoResourceSP existingResource = storage->resource(resourceUrl);
474
475 if (existingResource) {
476 const QString existingResourceMd5Sum = storage->resourceMd5(resourceUrl);
477
478 if (!allowOverwrite) {
479 return nullptr;
480 }
481
482 if (existingResourceMd5Sum == md5 &&
483 existingResource->filename() == resource->filename()) {
484
492 int existingResourceId = -1;
493 bool r = KisResourceCacheDb::getResourceIdFromFilename(existingResource->filename(), resourceType, storageLocation, existingResourceId);
494
495 if (r && existingResourceId > 0) {
496 return resourceForId(existingResourceId);
497 }
498 }
499
500 qWarning() << "A resource with the same filename but a different MD5 already exists in the storage" << resourceType << fileName << storageLocation;
501 if (storageLocation == "") {
502 qWarning() << "Proceeding with overwriting the existing resource...";
503 // remove all versions of the resource from the resource folder
504 QStringList versionsLocations;
505
506 // this resource has id -1, we need correct id
507 int existingResourceId = -1;
508 bool r = KisResourceCacheDb::getResourceIdFromVersionedFilename(existingResource->filename(), resourceType, storageLocation, existingResourceId);
509
510 if (r && existingResourceId >= 0) {
511 if (KisResourceCacheDb::getAllVersionsLocations(existingResourceId, versionsLocations)) {
512
513 for (int i = 0; i < versionsLocations.size(); i++) {
514 QFileInfo fi(this->resourceLocationBase() + "/" + resourceType + "/" + versionsLocations[i]);
515 if (fi.exists()) {
516 r = QFile::remove(fi.filePath());
517 if (!r) {
518 qWarning() << "KisResourceLocator::importResourceFromFile: Removal of " << fi.filePath()
519 << "was requested, but it wasn't possible, something went wrong.";
520 }
521 } else {
522 qWarning() << "KisResourceLocator::importResourceFromFile: Removal of " << fi.filePath()
523 << "was requested, but it doesn't exist.";
524 }
525 }
526 } else {
527 qWarning() << "KisResourceLocator::importResourceFromFile: Finding all locations for " << existingResourceId << "was requested, but it failed.";
528 return nullptr;
529 }
530 } else {
531 qWarning() << "KisResourceLocator::importResourceFromFile: there is no resource file found in the location of " << storageLocation << resource->filename() << resourceType;
532 return nullptr;
533 }
534
535 Q_EMIT beginExternalResourceRemove(resourceType, {existingResourceId});
536
537 // remove everything related to this resource from the database (remember about tags and versions!!!)
539
540 {
541 const QString absoluteStorageLocation = makeStorageLocationAbsolute(resource->storageLocation());
542 KisResourceThumbnailCache::instance()->remove(absoluteStorageLocation, resourceType, existingResource->filename());
543 }
544
545 Q_EMIT endExternalResourceRemove(resourceType);
546
547 if (!r) {
548 qWarning() << "KisResourceLocator::importResourceFromFile: Removing resource with id " << existingResourceId << "completely from the database failed.";
549 return nullptr;
550 }
551
552 } else {
553 qWarning() << "KisResourceLocator::importResourceFromFile: Overwriting of the resource was denied, aborting import.";
554 return nullptr;
555 }
556 }
557
558 QBuffer buf(&resourceData);
559 buf.open(QBuffer::ReadOnly);
560
561 if (storage->importResource(resourceUrl, &buf)) {
562 resource = storage->resource(resourceUrl);
563
564 if (!resource) {
565 qWarning() << "Could not retrieve imported resource from the storage" << resourceType << fileName << storageLocation;
566 return nullptr;
567 }
568
569 resource->setStorageLocation(storageLocation);
570 resource->setMD5Sum(storage->resourceMd5(resourceUrl));
571 resource->setVersion(0);
572 resource->setDirty(false);
574
575 Q_EMIT beginExternalResourceImport(resourceType, 1);
576
577 // Insert into the database
578 const bool result = KisResourceCacheDb::addResource(storage,
579 storage->timeStampForResource(resourceType, resource->filename()),
580 resource,
581 resourceType);
582
583 Q_EMIT endExternalResourceImport(resourceType);
584
585 if (!result) {
586 return nullptr;
587 }
588
589 // resourceCaches use absolute locations
590 const QString absoluteStorageLocation = makeStorageLocationAbsolute(resource->storageLocation());
591 const QPair<QString, QString> key = {absoluteStorageLocation, resourceType + "/" + resource->filename()};
592 // Add to the cache
593 d->resourceCache[key] = resource;
595
596 return resource;
597 }
598
599 return nullptr;
600}
static KisResourcesInterfaceSP instance()
static QString mimeTypeForFile(const QString &file, bool checkExistingFiles=true)
Find the mimetype for the given filename. The filename must include a suffix.
static bool getAllVersionsLocations(int resourceId, QStringList &outVersionsLocationsList)
static bool getResourceIdFromFilename(QString filename, QString resourceType, QString storageLocation, int &outResourceId)
The function will find the resource only if it is the latest version.
static bool removeResourceCompletely(int resourceId)
static bool getResourceIdFromVersionedFilename(QString filename, QString resourceType, QString storageLocation, int &outResourceId)
Note that here you can put even the original filename - any filename from the versioned_resources - a...
The KisResourceLoader class is an abstract interface class that must be implemented by actual resourc...
bool load(KoResourceSP resource, QIODevice &dev, KisResourcesInterfaceSP resourcesInterface)
KisResourceLoaderBase * loader(const QString &resourceType, const QString &mimetype) const
void endExternalResourceRemove(const QString &resourceType)
Emitted when the locator finished importing the embedded resource.
QString resourceLocationBase() const
resourceLocationBase is the place where all resource storages (folder, bundles etc....
void beginExternalResourceRemove(const QString &resourceType, const QVector< int > resourceIds)
Emitted when the locator needs to add an embedded resource.
KoResourceSP resourceForId(int resourceId)
resourceForId returns the resource with the given id, or 0 if no such resource exists....
void insert(const QString &storageLocation, const QString &resourceType, const QString &filename, const QImage &image)
static KisResourceThumbnailCache * instance()
void remove(const QString &storageLocation, const QString &resourceType, const QString &filename)
static QString generateHash(const QString &filename)
generateHash reads the given file and generates a hex-encoded md5sum for the file.

References KisResourceCacheDb::addResource(), beginExternalResourceImport(), beginExternalResourceRemove(), d, endExternalResourceImport(), endExternalResourceRemove(), KoMD5Generator::generateHash(), KisResourceCacheDb::getAllVersionsLocations(), KisResourceCacheDb::getResourceIdFromFilename(), KisResourceCacheDb::getResourceIdFromVersionedFilename(), KisResourceThumbnailCache::insert(), KisGlobalResourcesInterface::instance(), KisResourceLoaderRegistry::instance(), KisResourceThumbnailCache::instance(), KisResourceLoaderBase::load(), KisResourceLoaderRegistry::loader(), loadRequiredResources(), makeStorageLocationAbsolute(), KisMimeDatabase::mimeTypeForFile(), KisResourceThumbnailCache::remove(), KisResourceCacheDb::removeResourceCompletely(), resource(), resourceForId(), and resourceLocationBase().

◆ importResourceFromFile()

KoResourceSP KisResourceLocator::importResourceFromFile ( const QString & resourceType,
const QString & fileName,
const bool allowOverwrite,
const QString & storageLocation = QString() )
private

importResourceFromFile

Parameters
resourceType
fileName
storageLocationoptional, the storage where the resource will be stored. Empty means in the default Folder storage.
Returns
the imported resource, which has been added to the database and the cache

Definition at line 433 of file KisResourceLocator.cpp.

434{
435 QFile f(fileName);
436 if (!f.open(QFile::ReadOnly)) {
437 qWarning() << "Could not open" << fileName << "for loading";
438 return nullptr;
439 }
440
441 return importResource(resourceType, fileName, &f, allowOverwrite, storageLocation);
442}
KoResourceSP importResource(const QString &resourceType, const QString &fileName, QIODevice *device, const bool allowOverwrite, const QString &storageLocation=QString())
importResource

References importResource().

◆ importWillOverwriteResource()

bool KisResourceLocator::importWillOverwriteResource ( const QString & resourceType,
const QString & fileName,
const QString & storageLocation = QString() ) const
private

return whether importing will overwrite some existing resource

Parameters
resourceType
fileNamefilename that should be assigned to the resource
storageLocationoptional, the storage where the resource will be stored. Empty means in the default Folder storage.

Definition at line 602 of file KisResourceLocator.cpp.

603{
604 KisResourceStorageSP storage = d->storages[makeStorageLocationAbsolute(storageLocation)];
605
606 const QString resourceUrl = resourceType + "/" + QFileInfo(fileName).fileName();
607
608 const KoResourceSP existingResource = storage->resource(resourceUrl);
609
610 return !existingResource.isNull();
611}

References d, and makeStorageLocationAbsolute().

◆ initialize()

KisResourceLocator::LocatorError KisResourceLocator::initialize ( const QString & installationResourcesLocation)

initialize Setup the resource locator for use.

Parameters
installationResourcesLocationthe place where the resources that come packaged with Krita reside.

Definition at line 78 of file KisResourceLocator.cpp.

79{
81
82 d->resourceLocation = KoResourcePaths::getAppDataLocation();
83
84 if (!d->resourceLocation.endsWith('/')) d->resourceLocation += '/';
85
86 QFileInfo fi(d->resourceLocation);
87
88 if (!fi.exists()) {
89 if (!QDir().mkpath(d->resourceLocation)) {
90 d->errorMessages << i18n("1. Could not create the resource location at %1.", d->resourceLocation);
92 }
93 initializationStatus = InitializationStatus::FirstRun;
94 }
95
96 if (!fi.isWritable()) {
97 d->errorMessages << i18n("2. The resource location at %1 is not writable.", d->resourceLocation);
99 }
100
101 // Check whether we're updating from an older version
102 if (initializationStatus != InitializationStatus::FirstRun) {
103 QFile fi(d->resourceLocation + '/' + "KRITA_RESOURCE_VERSION");
104 if (!fi.exists()) {
105 initializationStatus = InitializationStatus::FirstUpdate;
106 }
107 else {
108 fi.open(QFile::ReadOnly);
109 QVersionNumber resource_version = QVersionNumber::fromString(QString::fromUtf8(fi.readAll()));
110 QVersionNumber krita_version = QVersionNumber::fromString(KritaVersionWrapper::versionString());
111 if (krita_version > resource_version) {
112 initializationStatus = InitializationStatus::Updating;
113 }
114 else {
115 initializationStatus = InitializationStatus::Initialized;
116 }
117 }
118 }
119
120 if (initializationStatus != InitializationStatus::Initialized) {
121 KisResourceLocator::LocatorError res = firstTimeInstallation(initializationStatus, installationResourcesLocation);
122 if (res != LocatorError::Ok) {
123 return res;
124 }
125 initializationStatus = InitializationStatus::Initialized;
126 }
127
128 if (!synchronizeDb()) {
130 }
131
132 return LocatorError::Ok;
133}
LocatorError firstTimeInstallation(InitializationStatus initializationStatus, const QString &installationResourcesLocation)
static QString getAppDataLocation()

References CannotCreateLocation, CannotSynchronizeDb, d, FirstRun, firstTimeInstallation(), FirstUpdate, KoResourcePaths::getAppDataLocation(), Initialized, LocationReadOnly, Ok, synchronizeDb(), Unknown, Updating, and KritaVersionWrapper::versionString().

◆ instance()

KisResourceLocator * KisResourceLocator::instance ( )
static

Definition at line 63 of file KisResourceLocator.cpp.

64{
65 // Not a regular Q_GLOBAL_STATIC, because we want this deleted as
66 // part of the app destructor.
67 KisResourceLocator *locator = qApp->findChild<KisResourceLocator *>(QString());
68 if (!locator) {
69 locator = new KisResourceLocator(qApp);
70 }
71 return locator;
72}
KisResourceLocator(QObject *parent)

References KisResourceLocator().

◆ loadRequiredResources()

void KisResourceLocator::loadRequiredResources ( KoResourceSP resource)
private

Loads all the resources required by resource into the cache

loadRequiredResources() also loads embedded resources and adds them into the database.

First load the side-loaded resources, since they may be linked by the linked resources.

Now load the linked resources

Definition at line 153 of file KisResourceLocator.cpp.

154{
155 auto loadResourcesGroup =
156 [this] (QList<KoResourceLoadResult> resources,
157 const QString &resourceGroup) {
158
159 Q_FOREACH (KoResourceLoadResult res, resources) {
160 switch (res.type())
161 {
163 KIS_SAFE_ASSERT_RECOVER_NOOP(res.resource()->resourceId() >= 0);
164 break;
167 QByteArray data = res.embeddedResource().data();
168 QBuffer buffer(&data);
169 buffer.open(QBuffer::ReadOnly);
170
171 importResource(sig.type, sig.filename, &buffer, false, "memory");
172 break;
173 }
175 qWarning() << "Failed to load" << resourceGroup << "resource:" << res.signature();
176 break;
177 }
178 }
179 };
180
185 loadResourcesGroup(resource->takeSideLoadedResources(KisGlobalResourcesInterface::instance()), "side-loaded");
186
190 loadResourcesGroup(resource->requiredResources(KisGlobalResourcesInterface::instance()), "linked");
191}
const KoResourceSignature & signature() const
QByteArray data() const
KoResourceSP resource() const noexcept
KoEmbeddedResource embeddedResource() const noexcept
KoResourceSignature signature() const
A simple wrapper object for the main information about the resource.
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KoEmbeddedResource::data(), KoResourceLoadResult::EmbeddedResource, KoResourceLoadResult::embeddedResource(), KoResourceLoadResult::ExistingResource, KoResourceLoadResult::FailedLink, KoResourceSignature::filename, importResource(), KisGlobalResourcesInterface::instance(), KIS_SAFE_ASSERT_RECOVER_NOOP, KoResourceLoadResult::resource(), resource(), KoEmbeddedResource::signature(), KoResourceLoadResult::signature(), KoResourceLoadResult::type(), and KoResourceSignature::type.

◆ makeStorageLocationAbsolute()

QString KisResourceLocator::makeStorageLocationAbsolute ( QString storageLocation) const
private

Definition at line 1145 of file KisResourceLocator.cpp.

1146{
1147// debugResource << "makeStorageLocationAbsolute" << storageLocation;
1148
1149 if (storageLocation.isEmpty()) {
1150 return resourceLocationBase();
1151 }
1152
1153 if (QFileInfo(storageLocation).isRelative() && (storageLocation.endsWith(".bundle", Qt::CaseInsensitive)
1154 || storageLocation.endsWith(".asl", Qt::CaseInsensitive)
1155 || storageLocation.endsWith(".abr", Qt::CaseInsensitive))) {
1156 if (resourceLocationBase().endsWith('/') || resourceLocationBase().endsWith("\\")) {
1157 storageLocation = resourceLocationBase() + storageLocation;
1158 }
1159 else {
1160 storageLocation = resourceLocationBase() + '/' + storageLocation;
1161 }
1162 }
1163
1164// debugResource << "\t" << storageLocation;
1165 return storageLocation;
1166}

References resourceLocationBase().

◆ makeStorageLocationRelative()

QString KisResourceLocator::makeStorageLocationRelative ( QString location) const
private

Definition at line 1238 of file KisResourceLocator.cpp.

1239{
1240// debugResource << "makeStorageLocationRelative" << location << "locationbase" << resourceLocationBase();
1241 return location.remove(resourceLocationBase());
1242}

References resourceLocationBase().

◆ memoryStorage()

KisResourceStorageSP KisResourceLocator::memoryStorage ( ) const
private

Definition at line 1094 of file KisResourceLocator.cpp.

1095{
1096 return storageByLocation("memory");
1097}

References storageByLocation().

◆ metaDataForResource()

QMap< QString, QVariant > KisResourceLocator::metaDataForResource ( int id) const
private

metaDataForResource

Parameters
id
Returns

Definition at line 738 of file KisResourceLocator.cpp.

739{
740 return KisResourceCacheDb::metaDataForId(id, "resources");
741}
static QMap< QString, QVariant > metaDataForId(int id, const QString &tableName)
metaDataForId

References KisResourceCacheDb::metaDataForId().

◆ metaDataForStorage()

QMap< QString, QVariant > KisResourceLocator::metaDataForStorage ( const QString & storageLocation) const
private

metaDataForStorage

Parameters
storage
Returns

Definition at line 748 of file KisResourceLocator.cpp.

749{
750 QMap<QString, QVariant> metadata;
751 if (!d->storages.contains(makeStorageLocationAbsolute(storageLocation))) {
752 qWarning() << storageLocation << "not in" << d->storages.keys();
753 return metadata;
754 }
755
756 KisResourceStorageSP st = d->storages[makeStorageLocationAbsolute(storageLocation)];
757
758 if (d->storages[makeStorageLocationAbsolute(storageLocation)].isNull()) {
759 return metadata;
760 }
761
762 Q_FOREACH(const QString key, st->metaDataKeys()) {
763 metadata[key] = st->metaData(key);
764 }
765 return metadata;
766}

References d, and makeStorageLocationAbsolute().

◆ operator=()

KisResourceLocator KisResourceLocator::operator= ( const KisResourceLocator & )
private

◆ progressMessage

void KisResourceLocator::progressMessage ( const QString & )
signal

◆ purge()

void KisResourceLocator::purge ( const QString & storageLocation)

purge purges the local resource cache

Definition at line 776 of file KisResourceLocator.cpp.

777{
778 Q_FOREACH(const auto key, d->resourceCache.keys()) {
779 if (key.first == storageLocation) {
780 d->resourceCache.remove(key);
782 }
783 }
784}

References d, KisResourceThumbnailCache::instance(), and KisResourceThumbnailCache::remove().

◆ purgeTag()

void KisResourceLocator::purgeTag ( const QString tagUrl,
const QString resourceType )

Remove the given tag from the cache

Definition at line 951 of file KisResourceLocator.cpp.

952{
953 d->tagCache.remove(QPair<QString, QString>(resourceType, tagUrl));
954}

References d.

◆ reloadResource()

bool KisResourceLocator::reloadResource ( const QString & resourceType,
const KoResourceSP resource )
private

Reloads the resource from its persistent storage.

Parameters
resourceTypethe type of the resource
resourcethe actual resource object
Returns
true if reloading was successful. When returned false, resource is kept unchanged

Definition at line 712 of file KisResourceLocator.cpp.

713{
714 // This resource isn't in the database yet, so we cannot reload it
715 if (resource->resourceId() < 0) return false;
716
717 QString storageLocation = makeStorageLocationAbsolute(resource->storageLocation());
718 Q_ASSERT(d->storages.contains(storageLocation));
719
720 KisResourceStorageSP storage = d->storages[storageLocation];
721
722 if (!storage->loadVersionedResource(resource)) {
723 qWarning() << "Failed to reload the resource" << resource->name() << "from storage" << storageLocation;
724 return false;
725 }
726
727 resource->setMD5Sum(storage->resourceMd5(resourceType + "/" + resource->filename()));
728 resource->setDirty(false);
730
731 // We haven't changed the version of the resource, so the cache must be still valid
732 QPair<QString, QString> key = QPair<QString, QString> (storageLocation, resourceType + "/" + resource->filename());
733 Q_ASSERT(d->resourceCache[key] == resource);
734
735 return true;
736}

References d, loadRequiredResources(), makeStorageLocationAbsolute(), and resource().

◆ removeStorage()

bool KisResourceLocator::removeStorage ( const QString & storageLocation)

removeStorage removes the temporary storage from the database

Parameters
storageLocationthe unique name of the storage
Returns
true is successful.

Definition at line 835 of file KisResourceLocator.cpp.

836{
837 // Cloned documents have a document storage, but that isn't in the locator.
838 if (!d->storages.contains(storageLocation)) {
839 return true;
840 }
841
843
844 Q_FOREACH(const QString &type, KisResourceLoaderRegistry::instance()->resourceTypes()) {
845 const QVector<int> resources = KisResourceCacheDb::resourcesForStorage(type, storageLocation);
846 if (!resources.isEmpty()) {
847 removedResources << std::make_pair(type, resources);
848 }
849 }
850
851 Q_FOREACH (const auto &typedResources, removedResources) {
852 Q_EMIT beginExternalResourceRemove(typedResources.first, typedResources.second);
853 }
854
855 purge(storageLocation);
856
857 KisResourceStorageSP storage = d->storages.take(storageLocation);
858
859 if (!KisResourceCacheDb::deleteStorage(storage)) {
860 d->errorMessages.append(i18n("Could not remove storage %1 from the database", storage->location()));
861 qWarning() << d->errorMessages;
862 return false;
863 }
864
865 Q_FOREACH (const auto &typedResources, removedResources) {
866 Q_EMIT endExternalResourceRemove(typedResources.first);
867 }
868
869 Q_EMIT storageRemoved(makeStorageLocationRelative(storage->location()));
870
871 return true;
872}
static QVector< int > resourcesForStorage(const QString &resourceType, const QString &storageLocation)
static bool deleteStorage(KisResourceStorageSP storage)
Actually delete the storage and all its resources from the database (i.e., nothing is set to inactive...
void storageRemoved(const QString &location)
Emitted whenever a storage is removed.
void purge(const QString &storageLocation)
purge purges the local resource cache

References beginExternalResourceRemove(), d, KisResourceCacheDb::deleteStorage(), endExternalResourceRemove(), KisResourceLoaderRegistry::instance(), makeStorageLocationRelative(), purge(), KisResourceCacheDb::resourcesForStorage(), and storageRemoved().

◆ resource()

KoResourceSP KisResourceLocator::resource ( QString storageLocation,
const QString & resourceType,
const QString & filename )
private

resource finds a physical resource in one of the storages

Parameters
storageLocationthe storage containing the resource. If empty, this is the folder storage.

Note that the resource does not have the version or id field set, so this cannot be used directly, but only through KisResourceModel.

Parameters
resourceTypethe type of the resource
filenamethe filename of the resource including extension, but without any paths
Returns
A resource if found, or 0

Definition at line 317 of file KisResourceLocator.cpp.

318{
319 storageLocation = makeStorageLocationAbsolute(storageLocation);
320
321 QPair<QString, QString> key = QPair<QString, QString> (storageLocation, resourceType + "/" + filename);
322
324 if (d->resourceCache.contains(key)) {
325 resource = d->resourceCache[key];
326 }
327 else {
328 KisResourceStorageSP storage = d->storages[storageLocation];
329 if (!storage) {
330 qWarning() << "Could not find storage" << storageLocation;
331 return 0;
332 }
333
334 resource = storage->resource(resourceType + "/" + filename);
335
336 if (resource) {
337 d->resourceCache[key] = resource;
338 // load all the embedded resources into temporary "memory" storage
340 }
341 }
342
343 if (!resource) {
344 qWarning() << "KoResourceSP KisResourceLocator::resource" << storageLocation << resourceType << filename << "was not found";
345 return 0;
346 }
347
348 resource->setStorageLocation(storageLocation);
349 Q_ASSERT(!resource->storageLocation().isEmpty());
350
351 if (resource->resourceId() < 0 || resource->version() < 0) {
352 QSqlQuery q;
353 if (!q.prepare("SELECT resources.id\n"
354 ", versioned_resources.version as version\n"
355 ", versioned_resources.md5sum as md5sum\n"
356 ", resources.name\n"
357 ", resources.status\n"
358 "FROM resources\n"
359 ", storages\n"
360 ", resource_types\n"
361 ", versioned_resources\n"
362 "WHERE storages.id = resources.storage_id\n"
363 "AND storages.location = :storage_location\n"
364 "AND resource_types.id = resources.resource_type_id\n"
365 "AND resource_types.name = :resource_type\n"
366 "AND resources.filename = :filename\n"
367 "AND versioned_resources.resource_id = resources.id\n"
368 "AND versioned_resources.version = (SELECT MAX(version) FROM versioned_resources WHERE versioned_resources.resource_id = resources.id)")) {
369 qWarning() << "Could not prepare id/version query" << q.lastError();
370
371 }
372
373 q.bindValue(":storage_location", makeStorageLocationRelative(storageLocation));
374 q.bindValue(":resource_type", resourceType);
375 q.bindValue(":filename", filename);
376
377 if (!q.exec()) {
378 qWarning() << "Could not execute id/version query" << q.lastError() << q.boundValues();
379 }
380
381 if (!q.first()) {
382 qWarning() << "Could not find the resource in the database" << storageLocation << resourceType << filename;
383 }
384
385 resource->setResourceId(q.value(0).toInt());
386 Q_ASSERT(resource->resourceId() >= 0);
387
388 resource->setVersion(q.value(1).toInt());
389 Q_ASSERT(resource->version() >= 0);
390
391 resource->setMD5Sum(q.value(2).toString());
392 Q_ASSERT(!resource->md5Sum().isEmpty());
393
394 resource->setActive(q.value(4).toBool());
395
396 // To override resources that use the filename for the name, which is versioned, and we don't want the version number in the name
397 resource->setName(q.value(3).toString());;
398 }
399
400 if (!resource) {
401 qWarning() << "Could not find resource" << resourceType + "/" + filename;
402 return 0;
403 }
404
405 return resource;
406}

References d, loadRequiredResources(), makeStorageLocationAbsolute(), makeStorageLocationRelative(), and resource().

◆ resourceActiveStateChanged

void KisResourceLocator::resourceActiveStateChanged ( const QString & resourceType,
int resourceId )
signal

Emitted when a resource changes its active state.

◆ resourceCached()

bool KisResourceLocator::resourceCached ( QString storageLocation,
const QString & resourceType,
const QString & filename ) const
private
Returns
true if the resource is present in the cache, false if it hasn't been loaded

Definition at line 145 of file KisResourceLocator.cpp.

146{
147 storageLocation = makeStorageLocationAbsolute(storageLocation);
148 QPair<QString, QString> key = QPair<QString, QString> (storageLocation, resourceType + "/" + filename);
149
150 return d->resourceCache.contains(key);
151}

References d, and makeStorageLocationAbsolute().

◆ resourceForId()

KoResourceSP KisResourceLocator::resourceForId ( int resourceId)
private

resourceForId returns the resource with the given id, or 0 if no such resource exists. The resource object will have its id set but not its version.

Parameters
resourceIdthe id

Definition at line 408 of file KisResourceLocator.cpp.

409{
410 ResourceStorage rs = getResourceStorage(resourceId);
411 KoResourceSP r = resource(rs.storageLocation, rs.resourceType, rs.resourceFileName);
412 return r;
413}
ResourceStorage getResourceStorage(int resourceId) const

References getResourceStorage(), resource(), KisResourceLocator::ResourceStorage::resourceFileName, KisResourceLocator::ResourceStorage::resourceType, and KisResourceLocator::ResourceStorage::storageLocation.

◆ resourceLocationBase()

QString KisResourceLocator::resourceLocationBase ( ) const

resourceLocationBase is the place where all resource storages (folder, bundles etc. are located. This is a writable place.

Returns
the base location for all storages.

Definition at line 140 of file KisResourceLocator.cpp.

141{
142 return d->resourceLocation;
143}

References d.

◆ saveTags()

void KisResourceLocator::saveTags ( )
static

saveTags saves all tags to .tag files in the resource folder

Definition at line 879 of file KisResourceLocator.cpp.

880{
881 QSqlQuery query;
882
883 if (!query.prepare("SELECT tags.url \n"
884 ", resource_types.name \n"
885 "FROM tags\n"
886 ", resource_types\n"
887 "WHERE tags.resource_type_id = resource_types.id\n"))
888 {
889 qWarning() << "Could not prepare save tags query" << query.lastError();
890 return;
891 }
892
893 if (!query.exec()) {
894 qWarning() << "Could not execute save tags query" << query.lastError();
895 return;
896 }
897
898 // this needs to use ResourcePaths because it is sometimes called during initialization
899 // (when the database versions don't match up and tags need to be saved)
900 QString resourceLocation = KoResourcePaths::getAppDataLocation() + "/";
901
902 while (query.next()) {
903 // Save tag...
904 KisTagSP tag = tagForUrlNoCache(query.value("tags.url").toString(),
905 query.value("resource_types.name").toString());
906
907 if (!tag || !tag->valid()) {
908 continue;
909 }
910
911
912 QString filename = tag->filename();
913 if (filename.isEmpty() || QFileInfo(filename).suffix().isEmpty()) {
914 filename = tag->url() + ".tag";
915 }
916
917
918 if (QFileInfo(filename).suffix() != "tag" && QFileInfo(filename).suffix() != "TAG") {
919 // it's either .abr file, or maybe a .bundle
920 // or something else, but not a tag file
921 dbgResources << "Skipping saving tag " << tag->name(false) << filename << tag->resourceType();
922 continue;
923 }
924
925 filename.remove(resourceLocation);
926
927 QFile f(resourceLocation + "/" + tag->resourceType() + '/' + filename);
928
929 if (!f.open(QFile::WriteOnly)) {
930 qWarning () << "Could not open tag file for writing" << f.fileName();
931 continue;
932 }
933
934 QBuffer buf;
935 buf.open(QIODevice::WriteOnly);;
936
937 if (!tag->save(buf)) {
938 qWarning() << "Could not save tag to" << f.fileName();
939 buf.close();
940 f.close();
941 continue;
942 }
943
944 f.write(buf.data());
945 f.flush();
946
947 f.close();
948 }
949}
static KisTagSP tagForUrlNoCache(const QString &tagUrl, const QString resourceType)
tagForUrlNoCache create a tag from the database, don't use cache
#define dbgResources
Definition kis_debug.h:43

References dbgResources, KoResourcePaths::getAppDataLocation(), and tagForUrlNoCache().

◆ setMetaDataForResource()

bool KisResourceLocator::setMetaDataForResource ( int id,
QMap< QString, QVariant > map ) const
private

setMetaDataForResource

Parameters
id
map
Returns

Definition at line 743 of file KisResourceLocator.cpp.

744{
745 return KisResourceCacheDb::updateMetaDataForId(map, id, "resources");
746}
static bool updateMetaDataForId(const QMap< QString, QVariant > map, int id, const QString &tableName)
setMetaDataForId removes all metadata for the given id and table name, and inserts the metadata in th...

References KisResourceCacheDb::updateMetaDataForId().

◆ setMetaDataForStorage()

void KisResourceLocator::setMetaDataForStorage ( const QString & storageLocation,
QMap< QString, QVariant > map ) const
private

setMetaDataForStorage

Parameters
storage
map

Definition at line 768 of file KisResourceLocator.cpp.

769{
770 Q_ASSERT(d->storages.contains(storageLocation));
771 Q_FOREACH(const QString &key, map.keys()) {
772 d->storages[storageLocation]->setMetaData(key, map[key]);
773 }
774}

References d.

◆ setResourceActive()

bool KisResourceLocator::setResourceActive ( int resourceId,
bool active )
private

setResourceActive

Parameters
resourceId
activeshows if the resource should be set as active or not
Returns

Definition at line 415 of file KisResourceLocator.cpp.

416{
417 // First remove the resource from the cache
418 ResourceStorage rs = getResourceStorage(resourceId);
419 QPair<QString, QString> key = QPair<QString, QString> (rs.storageLocation, rs.resourceType + "/" + rs.resourceFileName);
420
421 d->resourceCache.remove(key);
422 if (!active) {
424 }
425
426 bool result = KisResourceCacheDb::setResourceActive(resourceId, active);
427
428 Q_EMIT resourceActiveStateChanged(rs.resourceType, resourceId);
429
430 return result;
431}
static bool setResourceActive(int resourceId, bool active=false)
Make this resource active or inactive; this does not remove the resource from disk or from the databa...
void resourceActiveStateChanged(const QString &resourceType, int resourceId)
Emitted when a resource changes its active state.

References d, getResourceStorage(), KisResourceThumbnailCache::instance(), KisResourceThumbnailCache::remove(), resourceActiveStateChanged(), KisResourceLocator::ResourceStorage::resourceFileName, KisResourceLocator::ResourceStorage::resourceType, KisResourceCacheDb::setResourceActive(), and KisResourceLocator::ResourceStorage::storageLocation.

◆ storageAdded

void KisResourceLocator::storageAdded ( const QString & location)
signal

Emitted whenever a storage is added.

◆ storageByLocation()

KisResourceStorageSP KisResourceLocator::storageByLocation ( const QString & location) const
private

Definition at line 1074 of file KisResourceLocator.cpp.

1075{
1076 if (!d->storages.contains(location)) {
1077 qWarning() << "No" << location << "storage defined:" << d->storages.keys();
1078 return 0;
1079 }
1080 KisResourceStorageSP storage = d->storages[location];
1081 if (!storage || !storage->valid()) {
1082 qWarning() << "Could not retrieve the" << location << "storage object or the object is not valid";
1083 return 0;
1084 }
1085
1086 return storage;
1087}

References d.

◆ storageRemoved

void KisResourceLocator::storageRemoved ( const QString & location)
signal

Emitted whenever a storage is removed.

◆ storageResynchronized

void KisResourceLocator::storageResynchronized ( const QString & storage,
bool isBulkResynchronization )
signal

Emitted when a storage is resynchronized using KisresourceCacheDb::synchronizeStorage()

if isBulkResynchronization then this resynchronization happened as a part of bulk resynchronization at the start of Krita. At the end of this bulk action storagesBulkSynchronizationFinished() will be emitted as well.

◆ storages()

QList< KisResourceStorageSP > KisResourceLocator::storages ( ) const
private

Definition at line 1069 of file KisResourceLocator.cpp.

1070{
1071 return d->storages.values();
1072}

References d.

◆ storagesBulkSynchronizationFinished

void KisResourceLocator::storagesBulkSynchronizationFinished ( )
signal

Emitted when bulk-synchronization of all the storages has been finished

See also
storageResynchronized

◆ synchronizeDb()

bool KisResourceLocator::synchronizeDb ( )
private

In the current layout of the database we cannot set FOREIGN KEY for the metadata table (since it links to both, resources and storages), hence we should manually track the orphaned data.

Theoretically, these should be none, if our code is correct, but who knows anything about our code...

Definition at line 1168 of file KisResourceLocator.cpp.

1169{
1170 Q_EMIT progressMessage(i18n("Synchronizing the resources."));
1171
1172 d->errorMessages.clear();
1173
1174 // Add resource types that have been added since first-time installation.
1175 Q_FOREACH(auto loader, KisResourceLoaderRegistry::instance()->values()) {
1176 KisResourceCacheDb::registerResourceType(loader->resourceType());
1177 }
1178
1179
1180 findStorages();
1181 Q_FOREACH(const KisResourceStorageSP storage, d->storages) {
1183 d->errorMessages.append(i18n("Could not synchronize %1 with the database", storage->location()));
1184 } else {
1185 Q_EMIT storageResynchronized(storage->location(), true);
1186 }
1187 }
1188
1189 Q_FOREACH(const KisResourceStorageSP storage, d->storages) {
1190 if (!KisResourceCacheDb::addStorageTags(storage)) {
1191 d->errorMessages.append(i18n("Could not synchronize %1 with the database", storage->location()));
1192 }
1193 }
1194
1196
1206
1207 // now remove the storages that no longer exists
1208 KisStorageModel model;
1209
1210 QList<QString> storagesToRemove;
1211 for (int i = 0; i < model.rowCount(); i++) {
1212 QModelIndex idx = model.index(i, 0);
1213 QString location = model.data(idx, Qt::UserRole + KisStorageModel::Location).toString();
1214 storagesToRemove << location;
1215 }
1216
1217 for (int i = 0; i < storagesToRemove.size(); i++) {
1218 QString location = storagesToRemove[i];
1219 if (!d->storages.contains(this->makeStorageLocationAbsolute(location))) {
1220 if (!KisResourceCacheDb::deleteStorage(location)) {
1221 d->errorMessages.append(i18n("Could not remove storage %1 from the database", this->makeStorageLocationAbsolute(location)));
1222 qWarning() << d->errorMessages;
1223 return false;
1224 }
1225 Q_EMIT storageRemoved(this->makeStorageLocationAbsolute(location));
1226 }
1227 }
1228
1229
1230 d->errorMessages <<
1232
1233 d->resourceCache.clear();
1234 return d->errorMessages.isEmpty();
1235}
static bool removeOrphanedMetaData()
removeOrphanedMetaData Previous versions of Krita never removed metadata, so this function doublechec...
static bool registerResourceType(const QString &resourceType)
registerResourceType registers this resource type in the database
static bool synchronizeStorage(KisResourceStorageSP storage)
void storagesBulkSynchronizationFinished()
void storageResynchronized(const QString &storage, bool isBulkResynchronization)
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override

References KisResourceCacheDb::addStorageTags(), d, KisStorageModel::data(), KisResourceCacheDb::deleteStorage(), KisResourceLoaderRegistry::executeAllFixups(), findStorages(), KisResourceLoaderRegistry::instance(), KisStorageModel::Location, makeStorageLocationAbsolute(), progressMessage(), KisResourceCacheDb::registerResourceType(), KisResourceCacheDb::removeOrphanedMetaData(), KisStorageModel::rowCount(), storageRemoved(), storageResynchronized(), storagesBulkSynchronizationFinished(), and KisResourceCacheDb::synchronizeStorage().

◆ tagForUrl()

KisTagSP KisResourceLocator::tagForUrl ( const QString & tagUrl,
const QString resourceType )
private

tagForUrl create a tag from the database

Parameters
tagUrlthe url
Returns
a complete tag with all translated names and comments.

Definition at line 193 of file KisResourceLocator.cpp.

194{
195 if (d->tagCache.contains(QPair<QString, QString>(resourceType, tagUrl))) {
196 return d->tagCache[QPair<QString, QString>(resourceType, tagUrl)];
197 }
198
199 KisTagSP tag = tagForUrlNoCache(tagUrl, resourceType);
200
201 if (tag && tag->valid()) {
202 d->tagCache[QPair<QString, QString>(resourceType, tagUrl)] = tag;
203 }
204
205 return tag;
206}

References d, and tagForUrlNoCache().

◆ tagForUrlNoCache()

KisTagSP KisResourceLocator::tagForUrlNoCache ( const QString & tagUrl,
const QString resourceType )
staticprivate

tagForUrlNoCache create a tag from the database, don't use cache

Parameters
tagUrlurl of the tag
resourceTyperesource type of the tag
Returns

Definition at line 208 of file KisResourceLocator.cpp.

209{
210 QSqlQuery query;
211 bool r = query.prepare("SELECT tags.id\n"
212 ", tags.url\n"
213 ", tags.active\n"
214 ", tags.name\n"
215 ", tags.comment\n"
216 ", tags.filename\n"
217 ", resource_types.name as resource_type\n"
218 ", resource_types.id\n"
219 "FROM tags\n"
220 ", resource_types\n"
221 "WHERE tags.resource_type_id = resource_types.id\n"
222 "AND resource_types.name = :resource_type\n"
223 "AND tags.url = :tag_url\n");
224
225 if (!r) {
226 qWarning() << "Could not prepare KisResourceLocator::tagForUrl query" << query.lastError();
227 return KisTagSP();
228 }
229
230 query.bindValue(":resource_type", resourceType);
231 query.bindValue(":tag_url", tagUrl);
232
233 r = query.exec();
234 if (!r) {
235 qWarning() << "Could not execute KisResourceLocator::tagForUrl query" << query.lastError() << query.boundValues();
236 return KisTagSP();
237 }
238
239 r = query.first();
240 if (!r) {
241 return KisTagSP();
242 }
243
244 KisTagSP tag(new KisTag());
245
246 int tagId = query.value("tags.id").toInt();
247 int resourceTypeId = query.value("resource_types.id").toInt();
248
249 tag->setUrl(query.value("url").toString());
250 tag->setResourceType(resourceType);
251 tag->setId(query.value("id").toInt());
252 tag->setActive(query.value("active").toBool());
253 tag->setName(query.value("name").toString());
254 tag->setComment(query.value("comment").toString());
255 tag->setFilename(query.value("filename").toString());
256 tag->setValid(true);
257
258
259 QMap<QString, QString> names;
260 QMap<QString, QString> comments;
261
262 r = query.prepare("SELECT language\n"
263 ", name\n"
264 ", comment\n"
265 "FROM tag_translations\n"
266 "WHERE tag_id = :id");
267
268 if (!r) {
269 qWarning() << "Could not prepare KisResourceLocator::tagForUrl translation query" << query.lastError();
270 }
271
272 query.bindValue(":id", tag->id());
273
274 if (!query.exec()) {
275 qWarning() << "Could not execute KisResourceLocator::tagForUrl translation query" << query.lastError();
276 }
277
278 while (query.next()) {
279 names[query.value(0).toString()] = query.value(1).toString();
280 comments[query.value(0).toString()] = query.value(2).toString();
281 }
282
283 tag->setNames(names);
284 tag->setComments(comments);
285
286 QSqlQuery defaultResourcesQuery;
287
288 if (!defaultResourcesQuery.prepare("SELECT resources.filename\n"
289 "FROM resources\n"
290 ", resource_tags\n"
291 "WHERE resource_tags.tag_id = :tag_id\n"
292 "AND resources.resource_type_id = :type_id\n"
293 "AND resource_tags.resource_id = resources.id\n"
294 "AND resource_tags.active = 1\n")) {
295 qWarning() << "Could not prepare resource/tag query" << defaultResourcesQuery.lastError();
296 }
297
298 defaultResourcesQuery.bindValue(":tag_id", tagId);
299 defaultResourcesQuery.bindValue(":type_id", resourceTypeId);
300
301 if (!defaultResourcesQuery.exec()) {
302 qWarning() << "Could not execute resource/tag query" << defaultResourcesQuery.lastError();
303 }
304
305 QStringList resourceFileNames;
306
307 while (defaultResourcesQuery.next()) {
308 resourceFileNames << defaultResourcesQuery.value("resources.filename").toString();
309 }
310
311 tag->setDefaultResources(resourceFileNames);
312
313 return tag;
314}
QSharedPointer< KisTag > KisTagSP
Definition KisTag.h:20
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

◆ updateFontStorage()

void KisResourceLocator::updateFontStorage ( )

This updates the "fontregistry" storage. Called when the font directories change;.

Definition at line 970 of file KisResourceLocator.cpp.

971{
973 qWarning() << i18n("Could not synchronize updated font registry with the database");
974 } else {
975 Q_EMIT storageResynchronized(fontStorage()->location(), false);
976 }
977}

References fontStorage(), storageResynchronized(), and KisResourceCacheDb::synchronizeStorage().

◆ updateResource()

bool KisResourceLocator::updateResource ( const QString & resourceType,
const KoResourceSP resource )
private

updateResource

Parameters
resourceType
resource
Returns

Definition at line 663 of file KisResourceLocator.cpp.

664{
665 QString storageLocation = makeStorageLocationAbsolute(resource->storageLocation());
666
667 Q_ASSERT(d->storages.contains(storageLocation));
668
669 if (resource->resourceId() < 0) {
670 return addResource(resourceType, resource);
671 }
672
673 KisResourceStorageSP storage = d->storages[storageLocation];
674
675 if (!storage->supportsVersioning()) return false;
676
677 // remove older version
678 KisResourceThumbnailCache::instance()->remove(storageLocation, resourceType, resource->filename());
679
680 resource->updateThumbnail();
681 resource->setVersion(resource->version() + 1);
682 resource->setActive(true);
683
684 if (!storage->saveAsNewVersion(resource)) {
685 qWarning() << "Failed to save the new version of " << resource->name() << "to storage" << storageLocation;
686 return false;
687 }
688
689 resource->setMD5Sum(storage->resourceMd5(resourceType + "/" + resource->filename()));
690 resource->setDirty(false);
692
693 // The version needs already to have been incremented
694 if (!KisResourceCacheDb::addResourceVersion(resource->resourceId(), QDateTime::currentDateTime(), storage, resource)) {
695 qWarning() << "Failed to add a new version of the resource to the database" << resource->name();
696 return false;
697 }
698
699 if (!setMetaDataForResource(resource->resourceId(), resource->metadata())) {
700 qWarning() << "Failed to update resource metadata" << resource;
701 return false;
702 }
703
704 // Update the resource in the cache
705 QPair<QString, QString> key = QPair<QString, QString> (storageLocation, resourceType + "/" + resource->filename());
706 d->resourceCache[key] = resource;
708
709 return true;
710}
static bool addResourceVersion(int resourceId, QDateTime timestamp, KisResourceStorageSP storage, KoResourceSP resource)
addResourceVersion adds a new version of the resource to the database. The resource itself already sh...
bool addResource(const QString &resourceType, const KoResourceSP resource, const QString &storageLocation=QString())
addResource adds the given resource to the database and potentially a storage
bool setMetaDataForResource(int id, QMap< QString, QVariant > map) const
setMetaDataForResource

References addResource(), KisResourceCacheDb::addResourceVersion(), d, KisResourceThumbnailCache::insert(), KisResourceThumbnailCache::instance(), loadRequiredResources(), makeStorageLocationAbsolute(), KisResourceThumbnailCache::remove(), resource(), and setMetaDataForResource().

Friends And Related Symbol Documentation

◆ KisAllResourcesModel

friend class KisAllResourcesModel
friend

Definition at line 166 of file KisResourceLocator.h.

◆ KisAllTagResourceModel

friend class KisAllTagResourceModel
friend

Definition at line 167 of file KisResourceLocator.h.

◆ KisAllTagsModel

friend class KisAllTagsModel
friend

Definition at line 164 of file KisResourceLocator.h.

◆ KisBrushTypeMetaDataFixup

friend class KisBrushTypeMetaDataFixup
friend

Definition at line 176 of file KisResourceLocator.h.

◆ KisMyPaintPaintOpPreset

friend class KisMyPaintPaintOpPreset
friend

Definition at line 356 of file KisResourceLocator.h.

◆ KisResourceCacheDb

friend class KisResourceCacheDb
friend

Definition at line 172 of file KisResourceLocator.h.

◆ KisResourceQueryMapper

friend class KisResourceQueryMapper
friend

Definition at line 174 of file KisResourceLocator.h.

◆ KisResourceThumbnailCache

friend class KisResourceThumbnailCache
friend

Definition at line 177 of file KisResourceLocator.h.

◆ KisResourceUserOperations

friend class KisResourceUserOperations
friend

Definition at line 175 of file KisResourceLocator.h.

◆ KisStorageFilterProxyModel

friend class KisStorageFilterProxyModel
friend

Definition at line 173 of file KisResourceLocator.h.

◆ KisStorageModel

friend class KisStorageModel
friend

Definition at line 168 of file KisResourceLocator.h.

◆ KisTagResourceModel

friend class KisTagResourceModel
friend

Definition at line 165 of file KisResourceLocator.h.

◆ Resource

friend class Resource
friend

Definition at line 171 of file KisResourceLocator.h.

◆ TestResourceLocator

friend class TestResourceLocator
friend

Definition at line 169 of file KisResourceLocator.h.

◆ TestResourceModel

friend class TestResourceModel
friend

Definition at line 170 of file KisResourceLocator.h.

Member Data Documentation

◆ d

QScopedPointer<Private> KisResourceLocator::d
private

Definition at line 363 of file KisResourceLocator.h.

◆ resourceLocationKey

const QString KisResourceLocator::resourceLocationKey {"ResourceDirectory"}
static

Definition at line 46 of file KisResourceLocator.h.


The documentation for this class was generated from the following files: