diff --git a/libs/resources/CMakeLists.txt b/libs/resources/CMakeLists.txt index 3e27bea816..9135401526 100644 --- a/libs/resources/CMakeLists.txt +++ b/libs/resources/CMakeLists.txt @@ -1,46 +1,47 @@ add_subdirectory(tests) set(kritaresources_LIB_SRCS KisResourceCacheDb.cpp KisResourceLoader.cpp KisResourceLoaderRegistry.cpp KisResourceLocator.cpp KisResourceStorage.cpp KisStoragePlugin.cpp KisAbrStorage.cpp KisAslStorage.cpp KisBundleStorage.cpp KisFolderStorage.cpp KoResource.cpp KoMD5Generator.cpp KoHashGeneratorProvider.cpp KoResourcePaths.cpp ) qt5_add_resources(kritaresources_LIB_SRCS sql.qrc) add_library(kritaresources SHARED ${kritaresources_LIB_SRCS}) generate_export_header(kritaresources BASE_NAME kritaresources) target_link_libraries(kritaresources PUBLIC Qt5::Core Qt5::Widgets PRIVATE Qt5::Sql kritaversion kritaglobal + kritaplugin KF5::ConfigCore KF5::CoreAddons KF5::I18n KF5::Archive ) set_target_properties(kritaresources PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaresources ${INSTALL_TARGETS_DEFAULT_ARGS} ) diff --git a/libs/resources/KisAbrStorage.cpp b/libs/resources/KisAbrStorage.cpp index 95a3d1be35..078347fd6d 100644 --- a/libs/resources/KisAbrStorage.cpp +++ b/libs/resources/KisAbrStorage.cpp @@ -1,51 +1,47 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisAbrStorage.h" KisAbrStorage::KisAbrStorage(const QString &location) : KisStoragePlugin(location) { } KisAbrStorage::~KisAbrStorage() { } KisResourceStorage::ResourceItem KisAbrStorage::resourceItem(const QString &url) { return KisResourceStorage::ResourceItem(); } -KisResourceStorage::ResourceItemIterator KisAbrStorage::resourceItems(const QString &resourceType) -{ - return KisResourceStorage::ResourceItemIterator(); -} KoResourceSP KisAbrStorage::resource(const QString &url) { return 0; } KisResourceStorage::ResourceIterator KisAbrStorage::resources(const QString &resourceType) { return KisResourceStorage::ResourceIterator(); } diff --git a/libs/resources/KisAbrStorage.h b/libs/resources/KisAbrStorage.h index f6a7d9ad61..6804d1fc2b 100644 --- a/libs/resources/KisAbrStorage.h +++ b/libs/resources/KisAbrStorage.h @@ -1,39 +1,38 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISABRSTORAGE_H #define KISABRSTORAGE_H #include class KisAbrStorage : public KisStoragePlugin { public: KisAbrStorage(const QString &location); virtual ~KisAbrStorage(); KisResourceStorage::ResourceItem resourceItem(const QString &url) override; - KisResourceStorage::ResourceItemIterator resourceItems(const QString &resourceType) override; KoResourceSP resource(const QString &url) override; KisResourceStorage::ResourceIterator resources(const QString &resourceType) override; }; #endif // KISABRSTORAGE_H diff --git a/libs/resources/KisAslStorage.cpp b/libs/resources/KisAslStorage.cpp index 2968be9460..3a7b3d4218 100644 --- a/libs/resources/KisAslStorage.cpp +++ b/libs/resources/KisAslStorage.cpp @@ -1,51 +1,46 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisAslStorage.h" KisAslStorage::KisAslStorage(const QString &location) : KisStoragePlugin(location) { } KisAslStorage::~KisAslStorage() { } KisResourceStorage::ResourceItem KisAslStorage::resourceItem(const QString &url) { return KisResourceStorage::ResourceItem(); } -KisResourceStorage::ResourceItemIterator KisAslStorage::resourceItems(const QString &resourceType) -{ - return KisResourceStorage::ResourceItemIterator(); -} - KoResourceSP KisAslStorage::resource(const QString &url) { return 0; } KisResourceStorage::ResourceIterator KisAslStorage::resources(const QString &resourceType) { return KisResourceStorage::ResourceIterator(); } diff --git a/libs/resources/KisAslStorage.h b/libs/resources/KisAslStorage.h index 8e2a7afde1..ac8517c9a5 100644 --- a/libs/resources/KisAslStorage.h +++ b/libs/resources/KisAslStorage.h @@ -1,39 +1,37 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISASLSTORAGE_H #define KISASLSTORAGE_H #include class KisAslStorage : public KisStoragePlugin { public: KisAslStorage(const QString &location); virtual ~KisAslStorage(); KisResourceStorage::ResourceItem resourceItem(const QString &url) override; - KisResourceStorage::ResourceItemIterator resourceItems(const QString &resourceType) override; - - KoResourceSP resource(const QString &url) override; + KoResourceSP resource(const QString &url) override; KisResourceStorage::ResourceIterator resources(const QString &resourceType) override; }; #endif // KISASLSTORAGE_H diff --git a/libs/resources/KisBundleStorage.cpp b/libs/resources/KisBundleStorage.cpp index 9453c12ca9..e3c78afbb8 100644 --- a/libs/resources/KisBundleStorage.cpp +++ b/libs/resources/KisBundleStorage.cpp @@ -1,49 +1,44 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisBundleStorage.h" KisBundleStorage::KisBundleStorage(const QString &location) : KisStoragePlugin(location) { } KisBundleStorage::~KisBundleStorage() { } KisResourceStorage::ResourceItem KisBundleStorage::resourceItem(const QString &url) { return KisResourceStorage::ResourceItem(); } -KisResourceStorage::ResourceItemIterator KisBundleStorage::resourceItems(const QString &resourceType) -{ - return KisResourceStorage::ResourceItemIterator(); -} - KoResourceSP KisBundleStorage::resource(const QString &url) { return 0; } KisResourceStorage::ResourceIterator KisBundleStorage::resources(const QString &resourceType) { return KisResourceStorage::ResourceIterator(); } diff --git a/libs/resources/KisBundleStorage.h b/libs/resources/KisBundleStorage.h index 6689d706b4..342ec07847 100644 --- a/libs/resources/KisBundleStorage.h +++ b/libs/resources/KisBundleStorage.h @@ -1,38 +1,36 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISBUNDLESTORAGE_H #define KISBUNDLESTORAGE_H #include class KisBundleStorage : public KisStoragePlugin { public: KisBundleStorage(const QString &location); virtual ~KisBundleStorage(); KisResourceStorage::ResourceItem resourceItem(const QString &url) override; - KisResourceStorage::ResourceItemIterator resourceItems(const QString &resourceType) override; - KoResourceSP resource(const QString &url) override; KisResourceStorage::ResourceIterator resources(const QString &resourceType) override; }; #endif // KISBUNDLESTORAGE_H diff --git a/libs/resources/KisFolderStorage.cpp b/libs/resources/KisFolderStorage.cpp index 6c6c749dbf..8c18b34ec8 100644 --- a/libs/resources/KisFolderStorage.cpp +++ b/libs/resources/KisFolderStorage.cpp @@ -1,50 +1,164 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisFolderStorage.h" +#include + +#include + +#include + +class FolderItem : public KisResourceStorage::ResourceItem +{ +public: + ~FolderItem() override {} + + QByteArray md5sum() const override + { + KisResourceLoaderBase *loader = KisResourceLoaderRegistry::instance()->get(resourceType); + if (loader) { + QFile f(url); + f.open(QFile::ReadOnly); + KoResourceSP res = loader->load(url, f); + f.close(); + if (res) { + return res->md5(); + } + } + return QByteArray(); + } +}; + +class FolderIterator : public KisResourceStorage::ResourceIterator +{ +public: + FolderIterator(const QString &location, const QString &resourceType) + : m_location(location) + , m_resourceType(resourceType) + { + m_loader = KisResourceLoaderRegistry::instance()->get(resourceType); + KIS_ASSERT(m_loader); + m_dirIterator.reset(new QDirIterator(location + '/' + resourceType, + m_loader->filters(), + QDir::Files | QDir::Readable, + QDirIterator::Subdirectories)); + } + + ~FolderIterator() override {} + + bool hasNext() const override + { + return m_dirIterator->hasNext(); + } + + void next() const override + { + m_dirIterator->next(); + } + + QString url() const override + { + return m_dirIterator->filePath(); + } + + QString type() const override + { + return m_resourceType; + } + + QDateTime lastModified() const override + { + return m_dirIterator->fileInfo().lastModified(); + } + + QByteArray md5sum() const override + { + if (!loadResourceInternal()) { + qWarning() << "Could not load resource" << m_dirIterator->filePath(); + return QByteArray(); + } + return m_resource->md5(); + + } + + KoResourceSP resource() const override + { + if (!loadResourceInternal()) { + qWarning() << "Could not load resource" << m_dirIterator->filePath(); + } + return m_resource; + } + +protected: + + bool loadResourceInternal() const { + if (!m_resource && m_resource->filename() != m_dirIterator->filePath()) { + QFile f(m_dirIterator->filePath()); + f.open(QFile::ReadOnly); + const_cast(this)->m_resource = m_loader->load(m_dirIterator->filePath(), f); + f.close(); + } + return !m_resource.isNull(); + } + + KoResourceSP m_resource; + KisResourceLoaderBase *m_loader {0}; + QScopedPointer m_dirIterator; + const QString m_location; + const QString m_resourceType; +}; + + KisFolderStorage::KisFolderStorage(const QString &location) : KisStoragePlugin(location) { - } KisFolderStorage::~KisFolderStorage() { } KisResourceStorage::ResourceItem KisFolderStorage::resourceItem(const QString &url) { - return KisResourceStorage::ResourceItem(); -} + QFileInfo fi(url); + FolderItem item; + item.url = url; + item.resourceType = fi.path().split("/").last(); + item.lastModified = fi.lastModified(); -KisResourceStorage::ResourceItemIterator KisFolderStorage::resourceItems(const QString &resourceType) -{ - return KisResourceStorage::ResourceItemIterator(); + return item; } KoResourceSP KisFolderStorage::resource(const QString &url) { - return 0; + QFileInfo fi(url); + const QString resourceType = fi.path().split("/").last(); + KisResourceLoaderBase *loader = KisResourceLoaderRegistry::instance()->get(resourceType); + QFile f(url); + f.open(QFile::ReadOnly); + KoResourceSP res = loader->load(url, f); + f.close(); + return res; } KisResourceStorage::ResourceIterator KisFolderStorage::resources(const QString &resourceType) { - return KisResourceStorage::ResourceIterator(); + return FolderIterator(location(), resourceType); } diff --git a/libs/resources/KisFolderStorage.h b/libs/resources/KisFolderStorage.h index fe173b56a6..0fe201ecde 100644 --- a/libs/resources/KisFolderStorage.h +++ b/libs/resources/KisFolderStorage.h @@ -1,39 +1,37 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISFOLDERSTORAGE_H #define KISFOLDERSTORAGE_H #include class KisFolderStorage : public KisStoragePlugin { public: KisFolderStorage(const QString &location); virtual ~KisFolderStorage(); KisResourceStorage::ResourceItem resourceItem(const QString &url) override; - KisResourceStorage::ResourceItemIterator resourceItems(const QString &resourceType) override; - KoResourceSP resource(const QString &url) override; KisResourceStorage::ResourceIterator resources(const QString &resourceType) override; }; #endif // KISFOLDERSTORAGE_H diff --git a/libs/resources/KisResourceCacheDb.cpp b/libs/resources/KisResourceCacheDb.cpp index a970e9837c..88de15ba30 100644 --- a/libs/resources/KisResourceCacheDb.cpp +++ b/libs/resources/KisResourceCacheDb.cpp @@ -1,331 +1,347 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisResourceCacheDb.h" #include #include #include #include #include #include #include "KisResourceLocator.h" const QString dbDriver = "QSQLITE"; const QStringList KisResourceCacheDb::resourceTypes = QStringList() << "BRUSH_TIP" << "GRADIENT" << "PAINTOP_PRESET" << "COLORSET" << "PATTERN" << "SYMBOL_LIBRARY" << "TEMPLATE" << "WORKSPACE" << "SESSION" << "UNKNOWN"; const QStringList KisResourceCacheDb::storageTypes = QStringList() << "UNKNOWN" << "FOLDER" << "BUNDLE" << "ADOBE_BRUSH_LIBRARY" << "ADOBE_STYLE_LIBRARY"; // Installed or created by the user const QString KisResourceCacheDb::dbLocationKey {"ResourceCacheDbDirectory"}; const QString KisResourceCacheDb::resourceCacheDbFilename {"resourcecache.sqlite"}; const QString KisResourceCacheDb::databaseVersion {"0.0.1"}; bool KisResourceCacheDb::s_valid {false}; bool KisResourceCacheDb::isValid() { return s_valid; } QSqlError initDb(const QString &location) { if (!QSqlDatabase::connectionNames().isEmpty()) { infoResources << "Already connected to resource cache database"; return QSqlError(); } QDir dbLocation(location); if (!dbLocation.exists()) { dbLocation.mkpath(dbLocation.path()); } QSqlDatabase db = QSqlDatabase::addDatabase(dbDriver); db.setDatabaseName(location + "/" + KisResourceCacheDb::resourceCacheDbFilename); if (!db.open()) { infoResources << "Could not connect to resource cache database"; return db.lastError(); } QStringList tables = QStringList() << "version_information" << "origin_types" << "resource_types" << "storages" << "tags" << "resources" << "translations" << "versioned_resources" << "resource_tags"; QStringList dbTables; // Verify whether we should recreate the database { bool allTablesPresent = true; dbTables = db.tables(); Q_FOREACH(const QString &table, tables) { if (!dbTables.contains(table)) { allTablesPresent = false; } } bool schemaIsOutDated = false; if (dbTables.contains("version_information")) { // Verify the version number QFile f(":/get_version_information.sql"); if (f.open(QFile::ReadOnly)) { QSqlQuery query(f.readAll()); if (query.size() > 0) { query.first(); QString schemaVersion = query.value(0).toString(); QString kritaVersion = query.value(1).toString(); QString creationDate = query.value(2).toString(); infoResources << "Database version" << schemaVersion << "Krita version that created the database" << kritaVersion << "At" << creationDate; if (schemaVersion != KisResourceCacheDb::databaseVersion) { // XXX: Implement migration warnResources << "Database schema is outdated, migration is needed"; schemaIsOutDated = true; } } } else { return QSqlError("Error executing SQL", "Could not open get_version_information.sql", QSqlError::StatementError); } } if (allTablesPresent && !schemaIsOutDated) { infoResources << "All tables are present and up to date"; return QSqlError(); } } // Create tables Q_FOREACH(const QString &table, tables) { QFile f(":/create_" + table + ".sql"); if (f.open(QFile::ReadOnly)) { QSqlQuery query; if (!query.exec(f.readAll())) { qWarning() << "Could not create table" << table; return db.lastError(); } infoResources << "Created table" << table; } else { return QSqlError("Error executing SQL", QString("Could not find SQL file %1").arg(table), QSqlError::StatementError); } } // Create indexes QStringList indexes = QStringList() << "storages"; Q_FOREACH(const QString &index, indexes) { QFile f(":/create_index_" + index + ".sql"); if (f.open(QFile::ReadOnly)) { QSqlQuery query; if (!query.exec(f.readAll())) { qWarning() << "Could not create index" << index; return db.lastError(); } infoResources << "Created table" << index; } else { return QSqlError("Error executing SQL", QString("Could not find SQL file %1").arg(index), QSqlError::StatementError); } } // Fill lookup tables { if (dbTables.contains("origin_types")) { QSqlQuery query; if (!query.exec("DELETE * FROM origin_types;")) { qWarning() << "Could not clear table origin_types" << db.lastError(); } } QFile f(":/fill_origin_types.sql"); if (f.open(QFile::ReadOnly)) { QString sql = f.readAll(); Q_FOREACH(const QString &originType, KisResourceCacheDb::storageTypes) { QSqlQuery query(sql); query.addBindValue(originType); if (!query.exec()) { qWarning() << "Could not insert" << originType << db.lastError() << query.executedQuery(); return db.lastError(); } } infoResources << "Filled lookup table origin_types"; } else { return QSqlError("Error executing SQL", QString("Could not find SQL fill_origin_types.sql."), QSqlError::StatementError); } } { if (dbTables.contains("resource_types")) { QSqlQuery query; if (!query.exec("DELETE * FROM resource_types;")) { qWarning() << "Could not cleare table resource_types" << db.lastError(); } } QFile f(":/fill_resource_types.sql"); if (f.open(QFile::ReadOnly)) { QString sql = f.readAll(); Q_FOREACH(const QString &resourceType, KisResourceCacheDb::resourceTypes) { QSqlQuery query(sql); query.addBindValue(resourceType); if (!query.exec()) { qWarning() << "Could not insert" << resourceType << db.lastError() << query.executedQuery(); return db.lastError(); } } infoResources << "Filled lookup table resource_types"; } else { return QSqlError("Error executing SQL", QString("Could not find SQL fill_resource_types.sql."), QSqlError::StatementError); } } { QFile f(":/fill_version_information.sql"); if (f.open(QFile::ReadOnly)) { QString sql = f.readAll(); QSqlQuery query; query.prepare(sql); query.addBindValue(KisResourceCacheDb::databaseVersion); query.addBindValue(KritaVersionWrapper::versionString()); query.addBindValue(QDateTime::currentDateTimeUtc().toString()); if (!query.exec()) { qWarning() << "Could not insert the current version" << db.lastError() << query.executedQuery() << query.boundValues(); return db.lastError(); } infoResources << "Filled version table"; } else { return QSqlError("Error executing SQL", QString("Could not find SQL fill_version_information.sql."), QSqlError::StatementError); } } return QSqlError(); } bool KisResourceCacheDb::initialize(const QString &location) { QSqlError err = initDb(location); if (err.isValid()) { qWarning() << "Could not initialize the database:" << err; } s_valid = !err.isValid(); return s_valid; } bool KisResourceCacheDb::addResource(KoResourceSP resource) { - // XXX - return false; + bool r = true; + + if (!s_valid) { + qWarning() << "KisResourceCacheDb::addResource: The database is not valid"; + return false; + } + + if (!resource || !resource->valid()) { + qWarning() << "KisResourceCacheDb::addResource: The resource is not valid"; + return false; + } + + + + return r; } bool KisResourceCacheDb::addResources(KisResourceStorageSP storage, QString folder) { KisResourceStorage::ResourceIterator iter = storage->resources(folder); while(iter.hasNext()) { iter.next(); KoResourceSP res = iter.resource(); if (!addResource(res)) { qWarning() << "Could not add resource" << res->filename() << "to the database"; } } return true; } bool KisResourceCacheDb::addStorage(KisResourceStorageSP storage, bool preinstalled) { bool r = true; - if (!s_valid) return false; + if (!s_valid) { + qWarning() << "The database is not valid"; + return false; + } { QSqlQuery q; r = q.prepare("SELECT * FROM storages WHERE location = :location"); q.bindValue(":location", storage->location()); r = q.exec(); if (!r) { qWarning() << "Could not select from storages"; return r; } if (q.first()) { //qDebug() << "This storage already exists"; return true; } } { QSqlQuery q; r = q.prepare("INSERT INTO storages " "(origin_type_id, location, datestamp, pre_installed, active)" "VALUES" "(:origin_type_id, :location, :datestamp, :pre_installed, :active);"); if (!r) { qWarning() << "Could not prepare query" << q.lastError(); return r; } q.bindValue(":origin_type_id", static_cast(storage->type())); q.bindValue(":location", storage->location()); q.bindValue(":datestamp", storage->timestamp().toMSecsSinceEpoch()); q.bindValue(":pre_installed", preinstalled); q.bindValue(":active", preinstalled ? 1 : 0); r = q.exec(); if (!r) qWarning() << "Could not execute query" << q.lastError(); } return r; } bool KisResourceCacheDb::synchronize(KisResourceStorageSP storage) { // Find the storage in the database qDebug() << storage->location() << storage->timestamp(); return true; } diff --git a/libs/resources/KisResourceLoader.cpp b/libs/resources/KisResourceLoader.cpp index 21600e2784..fcdfdfb194 100644 --- a/libs/resources/KisResourceLoader.cpp +++ b/libs/resources/KisResourceLoader.cpp @@ -1,21 +1,40 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ +#include + +#include + +/** + * @return a set of filters ("*.bla,*.foo") that is suitable for filtering + * the contents of a directory. + */ +QStringList KisResourceLoaderBase::filters() const +{ + QStringList filters; + Q_FOREACH(const QString &mimeType, mimetypes()) { + QStringList suffixes = KisMimeDatabase::suffixesForMimeType(mimeType); + Q_FOREACH(const QString &suffix, suffixes) { + filters << "*." + suffix; + } + } + return filters; +} #include "KisResourceLoader.h" diff --git a/libs/resources/KisResourceLoader.h b/libs/resources/KisResourceLoader.h index bd54b99580..38b6edc8f8 100644 --- a/libs/resources/KisResourceLoader.h +++ b/libs/resources/KisResourceLoader.h @@ -1,115 +1,121 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISRESOURCELOADER_H #define KISRESOURCELOADER_H #include #include #include #include #include #include #include /** * @brief The KisResourceLoader class is an abstract interface * class that must be implemented by actual resource classes and * registered with the KisResourceLoaderRegistry. */ class KRITARESOURCES_EXPORT KisResourceLoaderBase { public: KisResourceLoaderBase(const QString &id, const QString &folder, const QStringList &mimetypes) { m_id = id; m_folder = folder; m_mimetypes = mimetypes; } virtual ~KisResourceLoaderBase() { } + /** + * @return a set of filters ("*.bla,*.foo") that is suitable for filtering + * the contents of a directory. + */ + QStringList filters() const; + /** * @return the mimetypes this resource can load */ QStringList mimetypes() const { return m_mimetypes; } /** * @return the folder in the resource storage where resources * of this type are located */ QString folder() const { return m_folder; } QString resourceType() const { return id(); } /// For registration in KisResourceLoaderRegistry QString id() const { return m_id; } /** * Load this resource. * @return true if loading the resource succeeded. */ virtual KoResourceSP load(const QString &name, QIODevice &dev) { Q_UNUSED(name); Q_UNUSED(dev); return 0; }; private: QString m_id; QString m_folder; QStringList m_mimetypes; }; template class KRITARESOURCES_EXPORT KisResourceLoader : public KisResourceLoaderBase { public: KisResourceLoader(const QString &id, const QString &folder, const QStringList &mimetypes) : KisResourceLoaderBase(id, folder, mimetypes) { } KoResourceSP load(const QString &name, QIODevice &dev) override { QSharedPointer resource = QSharedPointer::create(name); if (resource->loadFromDevice(&dev)) { return resource; } return 0; } }; #endif // KISRESOURCELOADER_H diff --git a/libs/resources/KisResourceLocator.cpp b/libs/resources/KisResourceLocator.cpp index d6c7481945..3c39fe34b7 100644 --- a/libs/resources/KisResourceLocator.cpp +++ b/libs/resources/KisResourceLocator.cpp @@ -1,223 +1,224 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisResourceLocator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoResourcePaths.h" #include "KisResourceStorage.h" #include "KisResourceCacheDb.h" #include "KisResourceLoaderRegistry.h" const QString KisResourceLocator::resourceLocationKey {"ResourceDirectory"}; class KisResourceLocator::Private { public: QString resourceLocation; QList storages; QStringList errorMessages; }; KisResourceLocator::KisResourceLocator(QObject *parent) : QObject(parent) , d(new Private()) { } KisResourceLocator *KisResourceLocator::instance() { KisResourceLocator *locator = qApp->findChild(QString()); if (!locator) { locator = new KisResourceLocator(qApp); } return locator; } KisResourceLocator::~KisResourceLocator() { } KisResourceLocator::LocatorError KisResourceLocator::initialize(const QString &installationResourcesLocation) { InitalizationStatus initalizationStatus = InitalizationStatus::Unknown; KConfigGroup cfg(KSharedConfig::openConfig(), ""); d->resourceLocation = cfg.readEntry(resourceLocationKey, QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); QFileInfo fi(d->resourceLocation); if (!fi.exists()) { if (!QDir().mkpath(d->resourceLocation)) { d->errorMessages << i18n("1. Could not create the resource location at %1.", d->resourceLocation); return LocatorError::CannotCreateLocation; } initalizationStatus = InitalizationStatus::FirstRun; } if (!fi.isWritable()) { d->errorMessages << i18n("2. The resource location at %1 is not writable.", d->resourceLocation); return LocatorError::LocationReadOnly; } // Check whether we're updating from an older version if (initalizationStatus != InitalizationStatus::FirstRun) { QFile fi(d->resourceLocation + '/' + "KRITA_RESOURCE_VERSION"); if (!fi.exists()) { initalizationStatus = InitalizationStatus::FirstUpdate; } else { fi.open(QFile::ReadOnly); QVersionNumber resource_version = QVersionNumber::fromString(QString::fromUtf8(fi.readAll())); QVersionNumber krita_version = QVersionNumber::fromString(KritaVersionWrapper::versionString()); if (krita_version > resource_version) { initalizationStatus = InitalizationStatus::Updating; } else { initalizationStatus = InitalizationStatus::Initialized; } } } if (initalizationStatus != InitalizationStatus::Initialized) { KisResourceLocator::LocatorError res = firstTimeInstallation(initalizationStatus, installationResourcesLocation); if (res != LocatorError::Ok) { return res; } initalizationStatus = InitalizationStatus::Initialized; } findStorages(); return LocatorError::Ok; } QStringList KisResourceLocator::errorMessages() const { return d->errorMessages; } KisResourceLocator::LocatorError KisResourceLocator::firstTimeInstallation(InitalizationStatus initalizationStatus, const QString &installationResourcesLocation) { Q_UNUSED(initalizationStatus); Q_FOREACH(const QString &folder, KisResourceLoaderRegistry::instance()->resourceFolders()) { QDir dir(d->resourceLocation + '/' + folder + '/'); if (!dir.exists()) { if (!QDir().mkpath(d->resourceLocation + '/' + folder + '/')) { d->errorMessages << i18n("3. Could not create the resource location at %1.", dir.path()); return LocatorError::CannotCreateLocation; } } } Q_FOREACH(const QString &folder, KisResourceLoaderRegistry::instance()->resourceFolders()) { QDir dir(installationResourcesLocation + '/' + folder + '/'); if (dir.exists()) { Q_FOREACH(const QString &entry, dir.entryList(QDir::Files | QDir::Readable)) { QFile f(dir.canonicalPath() + '/'+ entry); if (!QFileInfo(d->resourceLocation + '/' + folder + '/' + entry).exists()) { if (!f.copy(d->resourceLocation + '/' + folder + '/' + entry)) { d->errorMessages << i18n("Could not copy resource %1 to %2").arg(f.fileName()).arg(d->resourceLocation + '/' + folder + '/' + entry); } } } } } QFile f(d->resourceLocation + '/' + "KRITA_RESOURCE_VERSION"); f.open(QFile::WriteOnly); f.write(KritaVersionWrapper::versionString().toUtf8()); f.close(); if (!initializeDb()) { return LocatorError::CannotInitializeDb; } return LocatorError::Ok; } bool KisResourceLocator::initializeDb() { QStringList filters = QStringList() << "*.bundle" << "*.abr" << "*.asl"; QDirIterator iter(d->resourceLocation, filters, QDir::Files, QDirIterator::Subdirectories); while (iter.hasNext()) { iter.next(); + qDebug() << "Considering storage" << iter.filePath(); KisResourceStorageSP storage = QSharedPointer::create(iter.filePath()); if (!KisResourceCacheDb::addStorage(storage, true)) { d->errorMessages.append(i18n("Could not add storage %1 to the cache database").arg(iter.filePath())); return false; } Q_FOREACH(const QString &folder, KisResourceLoaderRegistry::instance()->resourceFolders()) { if (!KisResourceCacheDb::addResources(storage, folder)) { d->errorMessages.append(i18n("Could not add resource type %1 to the cache database").arg(folder)); return false; } } } KisResourceCacheDb::addStorage(QSharedPointer::create(d->resourceLocation), false); return true; } void KisResourceLocator::findStorages() { d->storages.clear(); // Add the folder d->storages.append(QSharedPointer::create(d->resourceLocation)); // And add bundles and adobe libraries QStringList filters = QStringList() << "*.bundle" << "*.abr" << "*.asl"; QDirIterator iter(d->resourceLocation, filters, QDir::Files, QDirIterator::Subdirectories); while (iter.hasNext()) { iter.next(); d->storages.append(QSharedPointer::create(iter.filePath())); } } QList KisResourceLocator::storages() const { return d->storages; } bool KisResourceLocator::synchronizeDb() { d->errorMessages.clear(); Q_FOREACH(const KisResourceStorageSP storage, d->storages) { if (!KisResourceCacheDb::synchronize(storage)) { d->errorMessages.append(i18n("Could not synchronize %1 with the database").arg(storage->location())); } } return d->errorMessages.isEmpty(); } diff --git a/libs/resources/KisResourceStorage.cpp b/libs/resources/KisResourceStorage.cpp index 697fafed3a..27e8b435b8 100644 --- a/libs/resources/KisResourceStorage.cpp +++ b/libs/resources/KisResourceStorage.cpp @@ -1,121 +1,116 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisResourceStorage.h" #include #include #include "KisStoragePlugin.h" #include "KisFolderStorage.h" #include "KisBundleStorage.h" #include "KisAbrStorage.h" #include "KisAslStorage.h" class KisResourceStorage::Private { public: QString name; QString location; bool valid {false}; KisResourceStorage::StorageType storageType {KisResourceStorage::StorageType::Unknown}; QScopedPointer storagePlugin; }; KisResourceStorage::KisResourceStorage(const QString &location) : d(new Private()) { d->location = location; QFileInfo fi(d->location); if (fi.isDir()) { d->storagePlugin.reset(new KisFolderStorage(location)); d->name = location; d->storageType = StorageType::Folder; d->valid = fi.isWritable(); } else { if (d->location.endsWith(".bundle")) { d->storagePlugin.reset(new KisBundleStorage(location)); d->storageType = StorageType::Bundle; // XXX: should we also check whether there's a valid metadata entry? Or is this enough? d->valid = (fi.isReadable() && KZip(d->location).open(QIODevice::ReadOnly)); } else if (d->location.endsWith(".abr")) { d->storagePlugin.reset(new KisAbrStorage(location)); d->storageType = StorageType::AdobeBrushLibrary; d->valid = fi.isReadable(); } else if (d->location.endsWith(".asl")) { d->storagePlugin.reset(new KisAslStorage(location)); d->storageType = StorageType::AdobeStyleLibrary; d->valid = fi.isReadable(); } } } KisResourceStorage::~KisResourceStorage() { } QString KisResourceStorage::name() const { return d->name; } QString KisResourceStorage::location() const { return d->location; } KisResourceStorage::StorageType KisResourceStorage::type() const { return d->storageType; } QDateTime KisResourceStorage::timestamp() const { return QFileInfo(d->location).lastModified(); } KisResourceStorage::ResourceItem KisResourceStorage::resourceItem(const QString &url) { return d->storagePlugin->resourceItem(url); } -KisResourceStorage::ResourceItemIterator KisResourceStorage::resourceItems(const QString &resourceType) -{ - return d->storagePlugin->resourceItems(resourceType); -} - KoResourceSP KisResourceStorage::resource(const QString &url) { return d->storagePlugin->resource(url); } KisResourceStorage::ResourceIterator KisResourceStorage::resources(const QString &resourceType) { return d->storagePlugin->resources(resourceType); } bool KisResourceStorage::valid() const { return d->valid; } diff --git a/libs/resources/KisResourceStorage.h b/libs/resources/KisResourceStorage.h index 55f363394a..515b8c7bac 100644 --- a/libs/resources/KisResourceStorage.h +++ b/libs/resources/KisResourceStorage.h @@ -1,114 +1,104 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISRESOURCESTORAGE_H #define KISRESOURCESTORAGE_H #include #include #include #include #include #include /** * The KisResourceStorage class is the base class for * places where resources can be stored. Examples are * folders, bundles or Adobe resource libraries like * ABR files. */ class KRITARESOURCES_EXPORT KisResourceStorage { public: /// XXX: replace the default implementations with = 0 when all iterators have been implemented /// A resource item is simply an entry in the storage, struct ResourceItem { virtual ~ResourceItem() {} - QString url; - QString type; + QString resourceType; QDateTime lastModified; virtual QByteArray md5sum() const {return QByteArray();} }; - class ResourceItemIterator + class ResourceIterator { public: - virtual ~ResourceItemIterator() {} + virtual ~ResourceIterator() {} virtual bool hasNext() const {return false;}; virtual void next() const{}; - virtual QString url() const {return QString();} virtual QString type() const {return QString();} virtual QDateTime lastModified() const {return QDateTime();} + /// This only loads the resource when called virtual QByteArray md5sum() const {return QByteArray();} - }; - - class ResourceIterator : public ResourceItemIterator - { - public: - virtual ~ResourceIterator() {} - + /// This only loads the resource when called virtual KoResourceSP resource() const {return 0;} }; enum class StorageType : int { Unknown = 0, Folder = 1, Bundle = 2, AdobeBrushLibrary = 3, AdobeStyleLibrary = 4 }; KisResourceStorage(const QString &location); ~KisResourceStorage(); QString name() const; QString location() const; bool valid() const; StorageType type() const; QDateTime timestamp() const; - ResourceItem resourceItem(const QString &url); - ResourceItemIterator resourceItems(const QString &resourceType); - KoResourceSP resource(const QString &url); ResourceIterator resources(const QString &resourceType); private: class Private; QScopedPointer d; }; typedef QSharedPointer KisResourceStorageSP; #endif // KISRESOURCESTORAGE_H diff --git a/libs/resources/KisStoragePlugin.h b/libs/resources/KisStoragePlugin.h index ab1de98671..cfad7bae9d 100644 --- a/libs/resources/KisStoragePlugin.h +++ b/libs/resources/KisStoragePlugin.h @@ -1,54 +1,52 @@ /* * Copyright (C) 2018 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISSTORAGEPLUGIN_H #define KISSTORAGEPLUGIN_H #include #include #include /** * The KisResourceStoragePlugin class is the base class * for storage plugins. A storage plugin is used by * KisResourceStorage to locate resources and tags in * a kind of storage, like a folder, a bundle or an adobe * resource library. */ class KisStoragePlugin { public: KisStoragePlugin(const QString &location); virtual ~KisStoragePlugin(); virtual KisResourceStorage::ResourceItem resourceItem(const QString &url) = 0; - virtual KisResourceStorage::ResourceItemIterator resourceItems(const QString &resourceType) = 0; - virtual KoResourceSP resource(const QString &url) = 0; virtual KisResourceStorage::ResourceIterator resources(const QString &resourceType) = 0; protected: QString location() const; private: class Private; QScopedPointer d; }; #endif // KISSTORAGEPLUGIN_H