Commit 663255d0 authored by Boudewijn Rempt's avatar Boudewijn Rempt

Implement the initial creation of the database

Note: not all create table statements are finished yet.
parent 68b57f8b
......@@ -14,6 +14,7 @@ target_link_libraries(kritaresources
PUBLIC
Qt5::Core
PRIVATE
kritaversion
Qt5::Sql
KF5::ConfigCore
KF5::CoreAddons
......
......@@ -23,8 +23,30 @@
#include <QDir>
#include <QDirIterator>
#include <KritaVersionWrapper.h>
const QString dbDriver = "QSQLITE";
const QString dbLocationKey = "cachedblocation";
const QStringList KisResourceCacheDb::resourceTypes = QStringList() << "BRUSH_TIP"
<< "GRADIENT"
<< "PAINTOP_PRESET"
<< "COLORSET"
<< "PATTERN"
<< "SYMBOL_LIBRARY"
<< "TEMPLATE"
<< "WORKSPACE"
<< "SESSION";
const QStringList KisResourceCacheDb::originTypes = QStringList() << "INSTALLATION" // Installed by Krita
<< "BUNDLE" // Bundle installed by the user
<< "ADOBE_LIBRARY" // ABR or ASL or similar Adobe resource library
<< "USER"; // Installed or created by the user
const QString KisResourceCacheDb::dbLocationKey {"ResourceCacheDbDirectory"};
const QString KisResourceCacheDb::ResourceCacheDbFilename {"resourcecache.sqlite"};
const QString KisResourceCacheDb::databaseVersion {"0.0.1"};
class KisResourceCacheDb::Private
{
......@@ -35,14 +57,9 @@ public:
QSqlError initDb(const QString &location);
};
KisResourceCacheDb::KisResourceCacheDb(const QString &location)
KisResourceCacheDb::KisResourceCacheDb()
: d(new Private())
{
QSqlError err = d->initDb(location);
if (err.isValid()) {
qWarning() << "Could not initialize the database:" << err;
}
d->valid = !err.isValid();
}
KisResourceCacheDb::~KisResourceCacheDb()
......@@ -54,6 +71,17 @@ bool KisResourceCacheDb::isValid() const
return d->valid;
}
bool KisResourceCacheDb::initialize(const QString &location) const
{
QSqlError err = d->initDb(location);
if (err.isValid()) {
qWarning() << "Could not initialize the database:" << err;
}
d->valid = !err.isValid();
return d->valid;
}
QSqlError KisResourceCacheDb::Private::initDb(const QString &location)
{
QSqlDatabase db = QSqlDatabase::addDatabase(dbDriver);
......@@ -69,7 +97,8 @@ QSqlError KisResourceCacheDb::Private::initDb(const QString &location)
return db.lastError();
}
QStringList tables = QStringList() << "origin_types"
QStringList tables = QStringList() << "version_information"
<< "origin_types"
<< "resource_types"
<< "stores"
<< "tags"
......@@ -78,13 +107,44 @@ QSqlError KisResourceCacheDb::Private::initDb(const QString &location)
<< "versioned_resources"
<< "resource_tags";
QSqlQuery query;
// Verify whether we should recreate the database
{
bool allTablesPresent = true;
QStringList dbTables = db.tables();
Q_FOREACH(const QString &table, tables) {
if (!dbTables.contains(table)) {
allTablesPresent = false;
}
}
if (allTablesPresent) {
// Verify the version number
return QSqlError();
}
else {
// Clear the look-up tables
if (dbTables.contains("origin_types")) {
QSqlQuery query;
if (!query.exec("DELETE * FROM origin_types;")) {
qWarning() << "Could not clear table origin_types" << db.lastError();
}
}
if (dbTables.contains("resource_types")) {
QSqlQuery query;
if (!query.exec("DELETE * FROM resource_types;")) {
qWarning() << "Could not cleare table resource_types" << db.lastError();
}
}
}
}
Q_FOREACH(const QString &table, tables) {
QFile f(":/create_" + table + ".sql");
if (f.open(QFile::ReadOnly)) {
QString sql(f.readAll());
QSqlQuery query;
if (!query.exec(sql)) {
qWarning() << "Could not create table" << table;
return db.lastError();
}
}
......@@ -94,46 +154,61 @@ QSqlError KisResourceCacheDb::Private::initDb(const QString &location)
}
{
QStringList originTypes = QStringList() << "INSTALLATION" // Installed by Krita
<< "BUNDLE" // Bundle installed by the user
<< "ADOBE_LIBRARY" // ABR or ASL or similar Adobe resource library
<< "USER"; // Installed or created by the user
QFile f(":/fill_origin_types.sql");
f.open(QFile::ReadOnly);
QString sql = f.readAll();
Q_FOREACH(const QString &originType, originTypes) {
query.addBindValue(originTypes.indexOf(originType));
query.addBindValue(originType);
if (!query.exec(sql)) {
qDebug() << "Could not insert" << originType;
return db.lastError();
if (f.open(QFile::ReadOnly)) {
QString sql = f.readAll();
Q_FOREACH(const QString &originType, originTypes) {
QSqlQuery query;
query.prepare(sql);
query.addBindValue(originType);
if (!query.exec()) {
qWarning() << "Could not insert" << originType << db.lastError() << query.executedQuery();
return db.lastError();
}
}
}
else {
return QSqlError("Error executing SQL", QString("Could not find SQL fill_origin_types.sql."), QSqlError::StatementError);
}
}
{
QStringList resourceTypes = QStringList() << "BRUSH_TIP"
<< "GRADIENT"
<< "PAINTOP_PRESET"
<< "COLORSET"
<< "PATTERN"
<< "SYMBOL_LIBRARY"
<< "TEMPLATE"
<< "WORKSPACE"
<< "SESSION";
QFile f(":/fill_resource_types.sql");
f.open(QFile::ReadOnly);
QString sql = f.readAll();
if (f.open(QFile::ReadOnly)) {
QString sql = f.readAll();
Q_FOREACH(const QString &resourceType, resourceTypes) {
QSqlQuery query;
query.prepare(sql);
query.addBindValue(resourceType);
if (!query.exec()) {
qWarning() << "Could not insert" << resourceType << db.lastError() << query.executedQuery();
return db.lastError();
}
}
}
else {
return QSqlError("Error executing SQL", QString("Could not find SQL fill_resource_types.sql."), QSqlError::StatementError);
}
}
Q_FOREACH(const QString &resourceType, resourceTypes) {
query.addBindValue(resourceTypes.indexOf(resourceType));
query.addBindValue(resourceType);
if (!query.exec(sql)) {
qDebug() << "Could not insert" << resourceType;
{
QFile f(":/fill_version_information.sql");
if (f.open(QFile::ReadOnly)) {
QString sql = f.readAll();
QSqlQuery query;
query.prepare(sql);
query.addBindValue(databaseVersion);
query.addBindValue(KritaVersionWrapper::versionString());
query.addBindValue(QDateTime::currentDateTimeUtc().toString());
if (!query.exec()) {
qWarning() << "Could not insert the current version" << db.lastError() << query.executedQuery();
return db.lastError();
}
}
else {
return QSqlError("Error executing SQL", QString("Could not find SQL fill_version_information.sql."), QSqlError::StatementError);
}
}
return QSqlError();
}
......@@ -25,21 +25,26 @@
#include <kritaresources_export.h>
const QString ResourceCacheDbFilename = "resourcecache.sqlite";
/**
* @brief The KisResourceCacheDb class encapsulates the database that
* caches information about the resources available to the user.
*
* KisApplication creates and initializes the database. All other methods
* are static and can be used from anywhere.
*/
class KRITARESOURCES_EXPORT KisResourceCacheDb
{
public:
static const QString dbLocationKey;
static const QString ResourceCacheDbFilename;
static const QString databaseVersion;
/**
* @brief KisResourceCacheDb create a resource cache database.
* @param location the location of the database
*/
explicit KisResourceCacheDb(const QString &location);
explicit KisResourceCacheDb();
~KisResourceCacheDb();
/**
......@@ -48,8 +53,19 @@ public:
*/
bool isValid() const;
/**
* @brief initialize
* @param location the location of the database
* @return true if the database has been initialized correctly
*/
bool initialize(const QString &location) const;
private:
friend class TestResourceCacheDb;
static const QStringList resourceTypes;
static const QStringList originTypes;
class Private;
QScopedPointer<Private> d;
......
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource>
<file alias="create_version_information.sql">sql/create_version_information.sql</file>
<file alias="fill_version_information.sql">sql/fill_version_information.sql</file>
<file alias="create_origin_types.sql">sql/create_origin_types.sql</file>
<file alias="fill_origin_types.sql">sql/create_origin_types.sql</file>
<file alias="fill_origin_types.sql">sql/fill_origin_types.sql</file>
<file alias="create_stores.sql">sql/create_stores.sql</file>
<file alias="create_tags.sql">sql/create_tags.sql</file>
<file alias="create_resource_types.sql">sql/create_resource_types.sql</file>
<file alias="fill_resource_types.sql">sql/create_resource_types.sql</file>
<file alias="fill_resource_types.sql">sql/fill_resource_types.sql</file>
<file alias="create_resources.sql">sql/create_resources.sql</file>
<file alias="create_translations.sql">sql/create_translations.sql</file>
<file alias="create_versioned_resources.sql">sql/create_versioned_resources.sql</file>
......
CREATE TABLE IF NOT EXISTS version_information (
id INTEGER PRIMARY KEY
, database_version TEXT
, krita_version TEXT
, creation_date TEXT
)
INSERT into origin_types (id, name) VALUES(?,?);
INSERT into origin_types (name) VALUES (?);
INSERT into resource_types (id, name) VALUES(?,?);
INSERT INTO resource_types (name) VALUES (?);
INSERT INTO version_information (
database_version
, krita_version
, creation_date
)
VALUES (
?
,?
,?
);
......@@ -29,21 +29,22 @@ void TestResourceCacheDb::initTestCase()
{
QDir dbLocation(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
if (dbLocation.exists()) {
QFile(dbLocation.path() + "/" + ResourceCacheDbFilename).remove();
QFile(dbLocation.path() + "/" + KisResourceCacheDb::ResourceCacheDbFilename).remove();
dbLocation.rmpath(dbLocation.path());
}
}
void TestResourceCacheDb::testCreateDatabase()
{
KisResourceCacheDb cacheDb(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
Q_UNUSED(cacheDb);
KisResourceCacheDb cacheDb;
bool res = cacheDb.initialize(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
QVERIFY(res);
QVERIFY(cacheDb.isValid());
QSqlDatabase sqlDb = QSqlDatabase::database();
QStringList tables = QStringList() << "origin_types"
QStringList tables = QStringList() << "version_information"
<< "origin_types"
<< "resource_types"
<< "stores"
<< "tags"
......@@ -56,22 +57,31 @@ void TestResourceCacheDb::testCreateDatabase()
Q_FOREACH(const QString &table, tables) {
QVERIFY2(dbTables.contains(table), table.toLatin1());
}
}
void TestResourceCacheDb::testLookupTables()
{
QSqlQuery query;
bool r = query.exec("SELECT COUNT(*) FROM origin_types");
QVERIFY(r);
QVERIFY(query.lastError() == QSqlError());
query.first();
QVERIFY(query.value(0).toInt() == KisResourceCacheDb::originTypes.count());
r = query.exec("SELECT COUNT(*) FROM resource_types");
QVERIFY(r);
QVERIFY(query.lastError() == QSqlError());
query.first();
QVERIFY(query.value(0).toInt() == KisResourceCacheDb::resourceTypes.count());
}
void TestResourceCacheDb::cleanupTestCase()
{
QDir dbLocation(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
bool res = QFile(dbLocation.path() + "/" + ResourceCacheDbFilename).remove();
bool res = QFile(dbLocation.path() + "/" + KisResourceCacheDb::ResourceCacheDbFilename).remove();
Q_ASSERT(res);
res = dbLocation.rmpath(dbLocation.path());
Q_ASSERT(res);
}
QTEST_MAIN(TestResourceCacheDb)
......
......@@ -536,7 +536,7 @@ add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} )
generate_export_header(kritaui BASE_NAME kritaui)
target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network
kritaimpex kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES}
kritaimpex kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils kritaresources ${PNG_LIBRARIES} ${EXIV2_LIBRARIES}
)
if (HAVE_QT_MULTIMEDIA)
......
......@@ -93,7 +93,7 @@
#include "KisViewManager.h"
#include "kis_workspace_resource.h"
#include <KisAutoSaveRecoveryDialog.h>
#include <KisResourceCacheDb.h>
#include <KritaVersionWrapper.h>
#include <dialogs/KisSessionManagerDialog.h>
......@@ -105,6 +105,7 @@ class KisApplication::Private
{
public:
Private() {}
KisResourceCacheDb resourceDatabase;
QPointer<KisSplashScreen> splashScreen;
KisAutoSaveRecoveryDialog *autosaveDialog {0};
QPointer<KisMainWindow> mainWindow; // The first mainwindow we create on startup
......
......@@ -57,6 +57,8 @@
#include <KoVBox.h>
#include <KoResourcePaths.h>
#include <KisResourceCacheDb.h>
#include "KisProofingConfiguration.h"
#include "KoColorConversionTransformation.h"
#include "KoColorSpace.h"
......@@ -212,7 +214,7 @@ GeneralTab::GeneralTab(QWidget *_parent, const char *_name)
//
m_urlCacheDbLocation->setMode(KoFileDialog::OpenDirectory);
m_urlCacheDbLocation->setConfigurationName("cachedb_location");
m_urlCacheDbLocation->setFileName(cfg.readEntry<QString>("ResourceCacheDbDirectory", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)));
m_urlCacheDbLocation->setFileName(cfg.readEntry<QString>(KisResourceCacheDb::dbLocationKey, QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)));
m_urlResourceFolder->setMode(KoFileDialog::OpenDirectory);
m_urlResourceFolder->setConfigurationName("resource_directory");
......@@ -263,7 +265,7 @@ void GeneralTab::setDefault()
cursorColor.fromQColor(cfg.getCursorMainColor(true));
cursorColorBtutton->setColor(cursorColor);
m_urlCacheDbLocation->setFileName(cfg.readEntry<QString>("ResourceCacheDbDirectory", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)));
m_urlCacheDbLocation->setFileName(cfg.readEntry<QString>(KisResourceCacheDb::dbLocationKey, QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)));
m_urlResourceFolder->setFileName(cfg.readEntry<QString>("ResourceDirectory", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)));
}
......@@ -1299,7 +1301,7 @@ bool KisDlgPreferences::editPreferences()
cfg.setUndoStackLimit(dialog->m_general->undoStackSize());
cfg.setFavoritePresets(dialog->m_general->favoritePresets());
cfg.writeEntry("ResourceCacheDbDirectory", dialog->m_general->m_urlCacheDbLocation->fileName());
cfg.writeEntry(KisResourceCacheDb::dbLocationKey, dialog->m_general->m_urlCacheDbLocation->fileName());
cfg.writeEntry("ResourceDirectory", dialog->m_general->m_urlResourceFolder->fileName());
// Color settings
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment