Commit fec64199 authored by Boudewijn Rempt's avatar Boudewijn Rempt

Perform the initial tagging of resources

parent a4481f98
......@@ -3,3 +3,4 @@ Type=Tag
Name=Digital
Comment=Brush presets with a digital look and feel.
URL=Digital
Default Resources=a)_Eraser_Circle.kpp,b)_Basic-5_Size_default.kpp
......@@ -3,3 +3,4 @@ Type=Tag
Name=Erasers
Comment=Eraser Brush Presets
URL=Erasers
Default Resources=a)_Eraser_Circle.kpp
......@@ -244,18 +244,17 @@ bool KisResourceCacheDb::initialize(const QString &location)
return s_valid;
}
int KisResourceCacheDb::resourceIdForResource(KoResourceSP resource, const QString &resourceType)
int KisResourceCacheDb::resourceIdForResource(const QString &resourceFileName, const QString &resourceType)
{
QFile f(":/select_resource_id.sql");
f.open(QFile::ReadOnly);
QSqlQuery q;
if (!q.prepare(f.readAll())) {
qWarning() << "Could not read and prepare resourceIdForResource" << q.lastError();
return false;
return -1;
}
q.bindValue(":name", resource->name());
q.bindValue(":filename", resource->filename());
q.bindValue(":filename", resourceFileName);
q.bindValue(":resource_type", resourceType);
if (!q.exec()) {
......@@ -263,7 +262,6 @@ int KisResourceCacheDb::resourceIdForResource(KoResourceSP resource, const QStri
return -1;
}
if (!q.first()) {
qWarning() << "Could not find this reosurce" << resource->filename() << q.boundValues() << q.lastError();
return -1;
}
return q.value(0).toInt();
......@@ -274,10 +272,10 @@ bool KisResourceCacheDb::resourceNeedsUpdating(int resourceId, QDateTime timesta
{
QSqlQuery q;
if (!q.prepare("SELECT timestamp\n"
"FROM versioned_resources\n"
"WHERE resourceId = :resource_id\n"
"AND version = (SELECT MAX(version)\n"
" FROM versioned_resources\n"
"FROM versioned_resources\n"
"WHERE resourceId = :resource_id\n"
"AND version = (SELECT MAX(version)\n"
" FROM versioned_resources\n"
" WHERE resource_id = :resource_id);")) {
qWarning() << "Could not prepare resourceNeedsUpdating statement";
return false;
......@@ -375,27 +373,6 @@ bool KisResourceCacheDb::addResourceVersion(int resourceId, QDateTime timestamp,
return r;
}
bool KisResourceCacheDb::hasResource(KisResourceStorageSP storage, KoResourceSP resource, const QString &resourceType)
{
QFile f(":/select_resource.sql");
if (f.open(QFile::ReadOnly)) {
QSqlQuery q;
if (!q.prepare(f.readAll())) {
qWarning() << "Could not read and prepare select_resource.sql" << q.lastError();
return false;
}
q.bindValue(":storage", storage->location());
q.bindValue(":location", resource->filename());
q.bindValue(":resource_type", resourceType);
if (!q.exec()) {
qWarning() << "Could not query resources" << q.boundValues() << q.lastError();
}
return q.first();
}
qWarning() << "Could not open select_resource.sql";
return false;
}
bool KisResourceCacheDb::addResource(KisResourceStorageSP storage, QDateTime timestamp, KoResourceSP resource, const QString &resourceType)
{
bool r = false;
......@@ -411,8 +388,8 @@ bool KisResourceCacheDb::addResource(KisResourceStorageSP storage, QDateTime tim
}
// Check whether it already exists
if (hasResource(storage, resource, resourceType)) {
int resourceId = resourceIdForResource(resource, resourceType);
int resourceId = resourceIdForResource(resource->filename(), resourceType);
if (resourceId > -1) {
if (resourceNeedsUpdating(resourceId, timestamp)) {
r = addResourceVersion(resourceId, timestamp, storage, resource);
}
......@@ -450,7 +427,6 @@ bool KisResourceCacheDb::addResource(KisResourceStorageSP storage, QDateTime tim
}
}
// Then add a new version
int resourceId = resourceIdForResource(resource, resourceType);
QSqlQuery q;
r = q.prepare("INSERT INTO versioned_resources "
"(resource_id, storage_id, version, location, datestamp, deleted, checksum)"
......@@ -500,6 +476,60 @@ bool KisResourceCacheDb::addResources(KisResourceStorageSP storage, QString reso
return true;
}
bool KisResourceCacheDb::tagResource(KisResourceStorageSP storage, const QString resourceName, KisTagSP tag, const QString &resourceType)
{
// Get resource id
int resourceId = resourceIdForResource(storage->location() + "/" + resourceType + "/" + resourceName, resourceType);
if (resourceId < 0) {
qWarning() << "Could not find resource to tag" << storage->location() + "/" + resourceName << resourceType;
return false;
}
// Get tag id
int tagId {-1};
{
QFile f(":/select_tag.sql");
if (f.open(QFile::ReadOnly)) {
QSqlQuery q;
if (!q.prepare(f.readAll())) {
qWarning() << "Could not read and prepare select_tag.sql" << q.lastError();
return false;
}
q.bindValue(":url", tag->url());
q.bindValue(":resource_type", resourceType);
if (!q.exec()) {
qWarning() << "Could not query tags" << q.boundValues() << q.lastError();
return false;
}
if (!q.first()) {
qWarning() << "Could not find tag" << q.boundValues() << q.lastError();
return false;
}
tagId = q.value(0).toInt();
}
}
QSqlQuery q;
if (!q.prepare("INSERT INTO resource_tags\n"
"(resource_id, tag_id)\n"
"VALUES\n"
"(:resource_id, :tag_id);")) {
qWarning() << "Could not prepare tagResource statement" << q.lastError();
return false;
}
q.bindValue(":resource_id", resourceId);
q.bindValue(":tag_id", tagId);
if (!q.exec()) {
qWarning() << "Could not execute tagResource stagement" << q.boundValues() << q.lastError();
return false;
}
return true;
}
bool KisResourceCacheDb::hasTag(const QString &url, const QString &resourceType)
{
QFile f(":/select_tag.sql");
......@@ -562,8 +592,13 @@ bool KisResourceCacheDb::addTags(KisResourceStorageSP storage, QString resourceT
if (!addTag(resourceType, iter->url(), iter->name(), iter->comment())) {
qWarning() << "Could not add tag" << iter->url() << "to the database";
}
else {
qDebug() << "Added tag" << iter->url();
qDebug() << iter->tag()->defaultResources();
if (!iter->tag()->defaultResources().isEmpty()) {
Q_FOREACH(const QString &resourceName, iter->tag()->defaultResources()) {
if (!tagResource(storage, resourceName, iter->tag(), resourceType)) {
qWarning() << "Could not tag resource" << resourceName << "with tag" << iter->url();
}
}
}
}
return true;
......
......@@ -65,13 +65,13 @@ private:
~KisResourceCacheDb();
KisResourceCacheDb operator=(const KisResourceCacheDb&);
static int resourceIdForResource(KoResourceSP resource, const QString &resourceType);
static int resourceIdForResource(const QString &filename, const QString &resourceType);
static bool resourceNeedsUpdating(int resourceId, QDateTime timestamp);
static bool addResourceVersion(int resourceId, QDateTime timestamp, KisResourceStorageSP storage, KoResourceSP resource);
static bool hasResource(KisResourceStorageSP storage, KoResourceSP resource, const QString &resourceType);
static bool addResource(KisResourceStorageSP storage, QDateTime timestamp, KoResourceSP resource, const QString &resourceType);
static bool addResources(KisResourceStorageSP storage, QString resourceType);
static bool tagResource(KisResourceStorageSP storage, const QString resourceName, KisTagSP tag, const QString &resourceType);
static bool hasTag(const QString &url, const QString &resourceType);
static bool addTag(const QString &resourceType, const QString url, const QString name, const QString comment);
static bool addTags(KisResourceStorageSP storage, QString resourceType);
......
......@@ -38,12 +38,15 @@ const QByteArray KisTag::s_tag {"Tag"};
const QByteArray KisTag::s_name {"Name"};
const QByteArray KisTag::s_url {"URL"};
const QByteArray KisTag::s_comment {"Comment"};
const QByteArray KisTag::s_defaultResources {"Default Resources"};
class KisTag::Private {
public:
bool valid {false};
QString url;
QString name;
QString comment;
QStringList defaultResources;
KEntryMap map;
};
......@@ -54,7 +57,11 @@ KisTag::KisTag()
KisTag::~KisTag()
{
}
bool KisTag::valid() const
{
return d->valid;
}
QString KisTag::name() const
......@@ -62,7 +69,7 @@ QString KisTag::name() const
return d->name;
}
void KisTag::setName(const QString &name) const
void KisTag::setName(const QString &name)
{
d->map.setEntry(s_group, s_name, name, KEntryMap::EntryDirty);
d->name = name;
......@@ -73,7 +80,7 @@ QString KisTag::url() const
return d->url;
}
void KisTag::setUrl(const QString &url) const
void KisTag::setUrl(const QString &url)
{
d->map.setEntry(s_group, s_url, url, KEntryMap::EntryDirty);
d->url = url;
......@@ -84,12 +91,22 @@ QString KisTag::comment() const
return d->comment;
}
void KisTag::setComment(const QString &comment) const
void KisTag::setComment(const QString &comment)
{
d->map.setEntry(s_group, s_comment, comment, KEntryMap::EntryDirty);
d->comment = comment;
}
QStringList KisTag::defaultResources() const
{
return d->defaultResources;
}
void KisTag::setDefaultResources(const QStringList &defaultResources)
{
d->defaultResources = defaultResources;
}
bool KisTag::load(QIODevice &io)
{
if (!io.isOpen()) {
......@@ -113,6 +130,8 @@ bool KisTag::load(QIODevice &io)
d->url = d->map.getEntry(s_group, s_url);
d->name = d->map.getEntry(s_group, s_name, QString(), KEntryMap::SearchLocalized);
d->comment = d->map.getEntry(s_group, s_comment, QString(), KEntryMap::SearchLocalized);
d->defaultResources = d->map.getEntry(s_group, s_defaultResources, QString()).split(',', QString::SkipEmptyParts);
d->valid = true;
return true;
}
......@@ -120,6 +139,12 @@ bool KisTag::load(QIODevice &io)
bool KisTag::save(QIODevice &io)
{
KConfigIniBackend ini;
d->map.setEntry(s_group, s_url, d->url, KEntryMap::EntryDirty);
d->map.setEntry(s_group, s_name, d->name, KEntryMap::EntryDirty);
d->map.setEntry(s_group, s_comment, d->comment, KEntryMap::EntryDirty);
d->map.setEntry(s_group, s_defaultResources, d->defaultResources.join(','), KEntryMap::EntryDirty);
ini.writeEntries(QLocale().name().toUtf8(), io, d->map);
return true;
}
......
......@@ -44,14 +44,19 @@ public:
KisTag();
virtual ~KisTag();
bool valid() const;
QString name() const;
void setName(const QString &name) const;
void setName(const QString &name);
QString url() const;
void setUrl(const QString &url) const;
void setUrl(const QString &url);
QString comment() const;
void setComment(const QString &comment) const;
void setComment(const QString &comment);
QStringList defaultResources() const;
void setDefaultResources(const QStringList &defaultResources);
bool load(QIODevice &io);
bool save(QIODevice &io);
......@@ -64,6 +69,7 @@ private:
static const QByteArray s_name;
static const QByteArray s_url;
static const QByteArray s_comment;
static const QByteArray s_defaultResources;
class Private;
QScopedPointer<Private> d;
};
......
......@@ -14,7 +14,6 @@
<file alias="create_resource_tags.sql">sql/create_resource_tags.sql</file>
<file alias="get_version_information.sql">sql/get_version_information.sql</file>
<file alias="create_index_storages.sql">sql/create_index_storages.sql</file>
<file alias="select_resource.sql">sql/select_resource.sql</file>
<file alias="select_resource_id.sql">sql/select_resource_id.sql</file>
<file alias="select_tag.sql">sql/select_tag.sql</file>
</qresource>
......
......@@ -7,5 +7,6 @@ CREATE TABLE IF NOT EXISTS resources (
, thumbnail BLOB
, status INTEGER
, FOREIGN KEY(resource_type_id) REFERENCES resource_types(id)
, UNIQUE(resource_type_id, name, filename)
, UNIQUE(resource_type_id, name)
, UNIQUE(filename)
);
SELECT resources.id
FROM resources JOIN versioned_resources
WHERE resources.id = versioned_resources.resource_id
AND versioned_resources.version =
(SELECT MAX(version) FROM versioned_resources
WHERE versioned_resources.resource_id = resources.id)
AND versioned_resources.storage_id =
(SELECT storage_id FROM storages
WHERE location = :storage)
AND resources.resource_type_id =
(SELECT resource_type_id FROM resource_types
WHERE name = :resource_type)
AND versioned_resources.location = :location;
SELECT id
FROM resources
WHERE resource_type_id = (SELECT resource_type_id
FROM resource_types
WHERE name = :resource_type)
AND name = :name
FROM resource_types
WHERE name = :resource_type)
AND filename = :filename;
......@@ -66,7 +66,7 @@ void TestTagLoader ::testLoadTag()
void TestTagLoader::testSaveTag()
{
KisTag tagLoader;
KisTag tag1;
QFile f(QString(FILES_DATA_DIR) + "paintoppresets/test.desktop");
QVERIFY(f.exists());
......@@ -74,20 +74,25 @@ void TestTagLoader::testSaveTag()
f.open(QFile::ReadOnly);
QVERIFY(f.isOpen());
bool r = tagLoader.load(f);
bool r = tag1.load(f);
QVERIFY(r);
tagLoader.setName(QString("Test"));
tag1.setName(QString("Test"));
QByteArray ba;
QBuffer buf(&ba);
buf.open(QBuffer::WriteOnly);
tagLoader.save(buf);
tag1.save(buf);
buf.close();
QVERIFY(ba == QByteArray("[Desktop Entry]\nComment[nl_NL]=Jouw favoriete penseel presets\nComment=Your favorite brush presets\nName=Test\nType=Tag\nURL=* Favorites\n"));
buf.open(QBuffer::ReadOnly);
KisTag tag2;
tag2.load(buf);
QVERIFY(tag2.url() == tag1.url());
QVERIFY(tag2.name() == tag1.name());
QVERIFY(tag2.comment() == tag1.comment());
QVERIFY(tag2.defaultResources() == tag1.defaultResources());
}
......
......@@ -5,3 +5,4 @@ Name[nl]=* Favorieten
Comment=Your favorite brush presets
Comment[nl]=Jouw favoriete penseel presets
URL=* Favorites
Default Resources=test.kpp
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