2
* * Copyright (C) 2006-2011 Anders Brander <anders@brander.dk>,
3
* * Anders Kvist <akv@lnxbx.dk> and Klaus Post <klauspost@gmail.com>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
* http://www.sqlite.org/capi3ref.html
49
#include "rawstudio.h"
50
#include "rs-metadata.h"
51
#include "rs-library.h"
52
#include "application.h"
55
#include "rs-library.h"
56
#include "conf_interface.h"
59
#include <libxml/encoding.h>
60
#include <libxml/xmlwriter.h>
63
#define LIBRARY_VERSION 2
64
#define TAGS_XML_FILE "tags.xml"
65
#define MAX_SEARCH_RESULTS 1000
70
gboolean dispose_has_run;
75
/* This mutex must be used when inserting data in a table with an
76
autocrementing column - which is ALWAYS for sqlite */
80
G_DEFINE_TYPE(RSLibrary, rs_library, G_TYPE_OBJECT)
82
static gint library_execute_sql(sqlite3 *db, const gchar *sql);
83
static void library_sqlite_error(sqlite3 *db, const gint result);
84
static gint library_create_tables(sqlite3 *db);
85
static gint library_find_tag_id(RSLibrary *library, const gchar *tagname);
86
static gint library_find_photo_id(RSLibrary *library, const gchar *photo);
87
static void library_photo_add_tag(RSLibrary *library, const gint photo_id, const gint tag_id, const gboolean autotag);
88
static gboolean library_is_photo_tagged(RSLibrary *library, const gint photo_id, const gint tag_id);
89
static gint library_add_photo(RSLibrary *library, const gchar *filename);
90
static gint library_add_tag(RSLibrary *library, const gchar *tagname);
91
static void library_delete_photo(RSLibrary *library, const gint photo_id);
92
static void library_delete_tag(RSLibrary *library, const gint tag_id);
93
static void library_photo_delete_tags(RSLibrary *library, const gint photo_id);
94
static void library_tag_delete_photos(RSLibrary *library, const gint tag_id);
95
static gboolean library_tag_is_used(RSLibrary *library, const gint tag_id);
96
static void library_photo_default_tags(RSLibrary *library, const gint photo_id, RSMetadata *metadata);
98
static GtkWidget *tag_search_entry = NULL;
101
rs_library_dispose(GObject *object)
103
RSLibrary *library = RS_LIBRARY(object);
105
if (!library->dispose_has_run)
107
library->dispose_has_run = TRUE;
109
sqlite3_close(library->db);
111
g_mutex_free(library->id_lock);
114
G_OBJECT_CLASS(rs_library_parent_class)->dispose (object);
118
rs_library_finalize(GObject *object)
120
G_OBJECT_CLASS(rs_library_parent_class)->finalize (object);
124
rs_library_class_init(RSLibraryClass *klass)
126
GObjectClass *object_class = G_OBJECT_CLASS(klass);
128
sqlite3_config(SQLITE_CONFIG_SERIALIZED);
129
object_class->dispose = rs_library_dispose;
130
object_class->finalize = rs_library_finalize;
134
rs_library_has_database_connection(RSLibrary *library)
136
if (library_execute_sql(library->db, "PRAGMA user_version;") == 0)
143
rs_library_get_init_error_msg(RSLibrary *library)
145
return g_strdup(library->error_init);
149
library_set_version(sqlite3 *db, gint version)
154
rc = sqlite3_prepare_v2(db, "update version set version = ?1;", -1, &stmt, NULL);
155
rc = sqlite3_bind_int(stmt, 1, version);
156
rc = sqlite3_step(stmt);
157
library_sqlite_error(db, rc);
158
sqlite3_finalize(stmt);
164
library_check_version(sqlite3 *db)
166
sqlite3_stmt *stmt, *stmt_update;
167
gint rc, version = 0, id;
170
rc = sqlite3_prepare_v2(db, "SELECT version FROM version", -1, &stmt, NULL);
171
rc = sqlite3_step(stmt);
172
if (rc == SQLITE_ROW)
173
version = sqlite3_column_int(stmt, 0);
174
rc = sqlite3_finalize(stmt);
176
while (version < LIBRARY_VERSION)
181
/* Alter table library - add identifier column */
182
sqlite3_prepare_v2(db, "alter table library add column identifier varchar(32)", -1, &stmt, NULL);
183
rc = sqlite3_step(stmt);
184
library_sqlite_error(db, rc);
185
sqlite3_finalize(stmt);
187
/* Run through all photos in library and insert unique identifier in library */
189
sqlite3_prepare_v2(db, "select filename from library", -1, &stmt, NULL);
190
while (sqlite3_step(stmt) == SQLITE_ROW)
192
filename = (gchar *) sqlite3_column_text(stmt, 0);
193
if (g_file_test(filename, G_FILE_TEST_EXISTS))
195
identifier = rs_file_checksum(filename);
196
rc = sqlite3_prepare_v2(db, "update library set identifier = ?1 WHERE filename = ?2;", -1, &stmt_update, NULL);
197
rc = sqlite3_bind_text(stmt_update, 1, identifier, -1, SQLITE_TRANSIENT);
198
rc = sqlite3_bind_text(stmt_update, 2, filename, -1, SQLITE_TRANSIENT);
199
rc = sqlite3_step(stmt_update);
200
library_sqlite_error(db, rc);
201
sqlite3_finalize(stmt_update);
205
sqlite3_finalize(stmt);
207
library_set_version(db, version+1);
211
library_execute_sql(db, "BEGIN TRANSACTION;");
212
sqlite3_prepare_v2(db, "select id,filename from library", -1, &stmt, NULL);
213
while (sqlite3_step(stmt) == SQLITE_ROW)
215
id = (gint) sqlite3_column_int(stmt, 0);
216
filename = rs_normalize_path((gchar *) sqlite3_column_text(stmt, 1));
217
if (filename) /* FIXME: This will only work for paths that exists */
219
rc = sqlite3_prepare_v2(db, "update library set filename = ?1 WHERE id = ?2;", -1, &stmt_update, NULL);
220
rc = sqlite3_bind_text(stmt_update, 1, filename, -1, SQLITE_TRANSIENT);
221
rc = sqlite3_bind_int(stmt_update, 2, id);
222
rc = sqlite3_step(stmt_update);
223
library_sqlite_error(db, rc);
224
sqlite3_finalize(stmt_update);
228
sqlite3_finalize(stmt);
229
library_set_version(db, version+1);
230
library_execute_sql(db, "COMMIT;");
234
/* We should never hit this */
235
g_debug("Some error occured in library_check_version() - please notify developers");
240
g_debug("Updated library database to version %d", version);
245
rs_library_init(RSLibrary *library)
249
gchar *database = g_strdup_printf("%s/.rawstudio/library.db", g_get_home_dir());
251
/* If unable to create database we exit */
252
if(sqlite3_open(database, &(library->db)))
254
gchar *msg = g_strdup_printf(_("Could not open database %s"), database);
255
g_debug("sqlite3 debug: %s\n", msg);
256
if (library->error_init)
257
g_free(library->error_init);
258
library->error_init = g_strdup(msg);
259
sqlite3_close(library->db);
263
if (rs_library_has_database_connection(library))
265
/* This is not FULL synchronous mode as default, since all data is re-creatable by local xml files.
266
From the sqlite3 manual:
267
With synchronous OFF (0), SQLite continues without syncing as soon as it has handed data off to
268
the operating system. If the application running SQLite crashes, the data will be safe, but the
269
database might become corrupted if the operating system crashes or the computer loses power before
270
that data has been written to the disk surface. On the other hand,
271
some operations are as much as 50 or more times faster with synchronous OFF. " */
272
library_execute_sql(library->db, "PRAGMA synchronous = OFF;");
274
/* Move our journal to memory, we're not doing banking for the Mafia */
275
library_execute_sql(library->db, "PRAGMA journal_mode = memory;");
277
/* Place temp tables in memory */
278
library_execute_sql(library->db, "PRAGMA temp_store = memory;");
280
rc = library_create_tables(library->db);
281
library_sqlite_error(library->db, rc);
283
library_check_version(library->db);
285
library->id_lock = g_mutex_new();
290
rs_library_get_singleton(void)
292
static GStaticMutex singleton_lock = G_STATIC_MUTEX_INIT;
293
static RSLibrary *singleton = NULL;
295
g_static_mutex_lock(&singleton_lock);
297
singleton = g_object_new(RS_TYPE_LIBRARY, NULL);
298
g_static_mutex_unlock(&singleton_lock);
304
library_execute_sql(sqlite3 *db, const gchar *sql)
306
sqlite3_stmt *statement;
308
if(SQLITE_OK != sqlite3_prepare(db, sql, -1, &statement, 0))
309
return sqlite3_errcode(db);
311
while (SQLITE_ROW == sqlite3_step(statement));
313
return sqlite3_finalize(statement);
317
library_sqlite_error(sqlite3 *db, gint result)
319
if (result != SQLITE_OK && result != SQLITE_DONE)
321
g_warning("sqlite3 warning: %s\n", sqlite3_errmsg(db));
326
library_create_tables(sqlite3 *db)
331
/* Create table (library) to hold all known photos */
332
sqlite3_prepare_v2(db, "create table library (id integer primary key, filename varchar(1024), identifier varchar(32))", -1, &stmt, NULL);
333
rc = sqlite3_step(stmt);
334
sqlite3_finalize(stmt);
336
/* Create table (tags) with all known tags */
337
sqlite3_prepare_v2(db, "create table tags (id integer primary key, tagname varchar(128))", -1, &stmt, NULL);
338
rc = sqlite3_step(stmt);
339
sqlite3_finalize(stmt);
341
/* Create table (phototags) to bind tags and photos together */
342
sqlite3_prepare_v2(db, "create table phototags (photo integer, tag integer, autotag integer)", -1, &stmt, NULL);
343
rc = sqlite3_step(stmt);
344
sqlite3_finalize(stmt);
346
/* Create table (version) to help keeping track of database version */
347
sqlite3_prepare_v2(db, "create table version (version integer)", -1, &stmt, NULL);
348
rc = sqlite3_step(stmt);
349
sqlite3_finalize(stmt);
351
rc = sqlite3_prepare_v2(db, "select * from version", -1, &stmt, NULL);
352
rc = sqlite3_step(stmt);
353
sqlite3_finalize(stmt);
354
if (rc != SQLITE_ROW)
356
/* Set current version */
357
rc = sqlite3_prepare_v2(db, "insert into version (version) values (?1);", -1, &stmt, NULL);
358
rc = sqlite3_bind_int(stmt, 1, LIBRARY_VERSION);
359
rc = sqlite3_step(stmt);
360
sqlite3_finalize(stmt);
362
rc = sqlite3_prepare_v2(db, "select identifier from library", -1, &stmt, NULL);
363
rc = sqlite3_step(stmt);
364
sqlite3_finalize(stmt);
366
/* Check if library.identifier exists */
367
if (rc == SQLITE_MISUSE)
369
library_set_version(db, 0);
377
library_find_tag_id(RSLibrary *library, const gchar *tagname)
379
sqlite3 *db = library->db;
381
gint rc, tag_id = -1;
383
rc = sqlite3_prepare_v2(db, "SELECT id FROM tags WHERE tagname = ?1;", -1, &stmt, NULL);
384
rc = sqlite3_bind_text(stmt, 1, tagname, -1, SQLITE_TRANSIENT);
385
rc = sqlite3_step(stmt);
386
if (rc == SQLITE_ROW)
387
tag_id = sqlite3_column_int(stmt, 0);
388
rc = sqlite3_finalize(stmt);
393
library_find_photo_id(RSLibrary *library, const gchar *photo)
395
sqlite3 *db = library->db;
397
gint rc, photo_id = -1;
399
rc = sqlite3_prepare_v2(db, "SELECT id FROM library WHERE filename = ?1;", -1, &stmt, NULL);
400
rc = sqlite3_bind_text(stmt, 1, photo, -1, SQLITE_TRANSIENT);
401
library_sqlite_error(db, rc);
402
rc = sqlite3_step(stmt);
403
if (rc == SQLITE_ROW)
404
photo_id = sqlite3_column_int(stmt, 0);
405
rc = sqlite3_finalize(stmt);
410
library_photo_add_tag(RSLibrary *library, const gint photo_id, const gint tag_id, const gboolean autotag)
412
sqlite3 *db = library->db;
416
gint autotag_tag = 0;
420
g_mutex_lock(library->id_lock);
421
rc = sqlite3_prepare_v2(db, "INSERT INTO phototags (photo, tag, autotag) VALUES (?1, ?2, ?3);", -1, &stmt, NULL);
422
rc = sqlite3_bind_int (stmt, 1, photo_id);
423
rc = sqlite3_bind_int (stmt, 2, tag_id);
424
rc = sqlite3_bind_int (stmt, 3, autotag_tag);
425
rc = sqlite3_step(stmt);
426
g_mutex_unlock(library->id_lock);
427
if (rc != SQLITE_DONE)
428
library_sqlite_error(db, rc);
429
sqlite3_finalize(stmt);
433
library_is_photo_tagged(RSLibrary *library, gint photo_id, gint tag_id)
435
sqlite3 *db = library->db;
439
rc = sqlite3_prepare_v2(db, "SELECT * FROM phototags WHERE photo = ?1 AND tag = ?2;", -1, &stmt, NULL);
440
rc = sqlite3_bind_int (stmt, 1, photo_id);
441
rc = sqlite3_bind_int (stmt, 2, tag_id);
442
rc = sqlite3_step(stmt);
443
sqlite3_finalize(stmt);
445
if (rc == SQLITE_ROW)
452
got_checksum(const gchar *checksum, gpointer user_data)
454
RSLibrary *library = rs_library_get_singleton();
455
sqlite3 *db = library->db;
458
sqlite3_prepare_v2(db, "UPDATE LIBRARY SET identifier=?1 WHERE id=?2;", -1, &stmt, NULL);
459
sqlite3_bind_text(stmt, 1, checksum, -1, SQLITE_TRANSIENT);
460
sqlite3_bind_int(stmt, 2, GPOINTER_TO_INT(user_data));
462
sqlite3_finalize(stmt);
466
library_add_photo(RSLibrary *library, const gchar *filename)
469
sqlite3 *db = library->db;
473
g_mutex_lock(library->id_lock);
474
sqlite3_prepare_v2(db, "INSERT INTO library (filename) VALUES (?1);", -1, &stmt, NULL);
475
rc = sqlite3_bind_text(stmt, 1, filename, -1, SQLITE_TRANSIENT);
476
rc = sqlite3_step(stmt);
477
id = sqlite3_last_insert_rowid(db);
478
g_mutex_unlock(library->id_lock);
479
if (rc != SQLITE_DONE)
480
library_sqlite_error(db, rc);
481
sqlite3_finalize(stmt);
483
rs_io_idle_read_checksum(filename, -1, got_checksum, GINT_TO_POINTER(id));
489
library_add_tag(RSLibrary *library, const gchar *tagname)
492
sqlite3 *db = library->db;
496
g_mutex_lock(library->id_lock);
497
sqlite3_prepare_v2(db, "INSERT INTO tags (tagname) VALUES (?1);", -1, &stmt, NULL);
498
rc = sqlite3_bind_text(stmt, 1, tagname, -1, SQLITE_TRANSIENT);
499
rc = sqlite3_step(stmt);
500
id = sqlite3_last_insert_rowid(db);
501
g_mutex_unlock(library->id_lock);
502
if (rc != SQLITE_DONE)
503
library_sqlite_error(db, rc);
504
sqlite3_finalize(stmt);
510
library_delete_photo(RSLibrary *library, gint photo_id)
512
sqlite3 *db = library->db;
516
rc = sqlite3_prepare_v2(db, "DELETE FROM library WHERE id = ?1;", -1, &stmt, NULL);
517
rc = sqlite3_bind_int(stmt, 1, photo_id);
518
library_sqlite_error(db, rc);
519
rc = sqlite3_step(stmt);
520
if (rc != SQLITE_DONE)
521
library_sqlite_error(db, rc);
522
rc = sqlite3_finalize(stmt);
526
library_delete_tag(RSLibrary *library, gint tag_id)
528
sqlite3 *db = library->db;
532
rc = sqlite3_prepare_v2(db, "DELETE FROM library WHERE filename = ?1;", -1, &stmt, NULL);
533
rc = sqlite3_bind_int(stmt, 1, tag_id);
534
library_sqlite_error(db, rc);
535
rc = sqlite3_step(stmt);
536
if (rc != SQLITE_DONE)
537
library_sqlite_error(db, rc);
538
rc = sqlite3_finalize(stmt);
542
library_photo_delete_tags(RSLibrary *library, gint photo_id)
544
sqlite3 *db = library->db;
548
rc = sqlite3_prepare_v2(db, "DELETE FROM phototags WHERE photo = ?1;", -1, &stmt, NULL);
549
rc = sqlite3_bind_int(stmt, 1, photo_id);
550
library_sqlite_error(db, rc);
551
rc = sqlite3_step(stmt);
552
if (rc != SQLITE_DONE)
553
library_sqlite_error(db, rc);
554
rc = sqlite3_finalize(stmt);
558
library_tag_delete_photos(RSLibrary *library, gint tag_id)
560
sqlite3 *db = library->db;
564
rc = sqlite3_prepare_v2(db, "DELETE FROM phototags WHERE tag = ?1;", -1, &stmt, NULL);
565
rc = sqlite3_bind_int(stmt, 1, tag_id);
566
library_sqlite_error(db, rc);
567
rc = sqlite3_step(stmt);
568
if (rc != SQLITE_DONE)
569
library_sqlite_error(db, rc);
570
rc = sqlite3_finalize(stmt);
574
library_tag_is_used(RSLibrary *library, gint tag_id)
576
sqlite3 *db = library->db;
580
rc = sqlite3_prepare_v2(db, "SELECT * FROM phototags WHERE tag = ?1;", -1, &stmt, NULL);
581
rc = sqlite3_bind_int (stmt, 1, tag_id);
582
rc = sqlite3_step(stmt);
583
sqlite3_finalize(stmt);
585
if (rc == SQLITE_ROW)
592
rs_library_add_photo(RSLibrary *library, const gchar *filename)
596
g_assert(RS_IS_LIBRARY(library));
597
if (!rs_library_has_database_connection(library)) return 0; /* FIXME */
599
photo_id = library_find_photo_id(library, filename);
602
g_debug("Adding photo to library: %s",filename);
603
photo_id = library_add_photo(library, filename);
610
rs_library_add_tag(RSLibrary *library, const gchar *tagname)
614
g_assert(RS_IS_LIBRARY(library));
615
if (!rs_library_has_database_connection(library)) return 0; /* FIXME */
617
tag_id = library_find_tag_id(library, tagname);
620
g_debug("Adding tag to tags: %s",tagname);
621
tag_id = library_add_tag(library, tagname);
628
rs_library_photo_add_tag(RSLibrary *library, const gchar *filename, gint tag_id, const gboolean autotag)
630
g_assert(RS_IS_LIBRARY(library));
631
if (!rs_library_has_database_connection(library)) return;
637
g_warning("Tag not known...");
641
photo_id = library_find_photo_id(library, filename);
644
g_warning("Photo not known...");
648
if (!library_is_photo_tagged(library, photo_id, tag_id))
649
library_photo_add_tag(library, photo_id, tag_id, autotag);
655
rs_library_delete_photo(RSLibrary *library, const gchar *photo)
657
g_assert(RS_IS_LIBRARY(library));
658
if (!rs_library_has_database_connection(library)) return;
662
photo_id = library_find_photo_id(library, photo);
665
g_warning("Photo not known...");
669
library_photo_delete_tags(library, photo_id);
670
library_delete_photo(library, photo_id);
671
rs_library_backup_tags(library, photo);
675
rs_library_delete_tag(RSLibrary *library, const gchar *tag, const gboolean force)
677
g_assert(RS_IS_LIBRARY(library));
678
if (!rs_library_has_database_connection(library)) return FALSE;
682
tag_id = library_find_tag_id(library, tag);
685
g_warning("Tag not known...");
689
if (library_tag_is_used(library, tag_id))
692
library_tag_delete_photos(library, tag_id);
693
library_delete_tag(library, tag_id);
697
g_warning("Tag is in use...");
701
library_delete_tag(library, tag_id);
706
rs_library_search(RSLibrary *library, GList *tags)
708
g_assert(RS_IS_LIBRARY(library));
709
if (!rs_library_has_database_connection(library)) return NULL;
713
sqlite3 *db = library->db;
715
gint n, num_tags = g_list_length(tags);
716
GList *photos = NULL;
717
GTimer *gt = g_timer_new();
720
sqlite3_prepare_v2(db, "create temp table filter (photo integer)", -1, &stmt, NULL);
721
rc = sqlite3_step(stmt);
722
sqlite3_finalize(stmt);
723
library_sqlite_error(db, rc);
725
for (n = 0; n < num_tags; n++)
727
tag = (gchar *) g_list_nth_data(tags, n);
729
g_mutex_lock(library->id_lock);
730
sqlite3_prepare_v2(db, "insert into filter select phototags.photo from phototags, tags where phototags.tag = tags.id and lower(tags.tagname) = lower(?1) ;", -1, &stmt, NULL);
731
rc = sqlite3_bind_text(stmt, 1, tag, -1, SQLITE_TRANSIENT);
732
rc = sqlite3_step(stmt);
733
sqlite3_finalize(stmt);
734
g_mutex_unlock(library->id_lock);
737
sqlite3_prepare_v2(db, "create temp table result (photo integer, count integer)", -1, &stmt, NULL);
738
rc = sqlite3_step(stmt);
739
sqlite3_finalize(stmt);
740
library_sqlite_error(db, rc);
742
g_mutex_lock(library->id_lock);
743
sqlite3_prepare_v2(db, "insert into result select photo, count(photo) from filter group by photo;", -1, &stmt, NULL);
744
rc = sqlite3_step(stmt);
745
sqlite3_finalize(stmt);
746
g_mutex_unlock(library->id_lock);
747
library_sqlite_error(db, rc);
749
sqlite3_prepare_v2(db, "select library.filename from library,result where library.id = result.photo and result.count = ?1 order by library.filename;", -1, &stmt, NULL);
750
rc = sqlite3_bind_int(stmt, 1, num_tags);
753
while (sqlite3_step(stmt) == SQLITE_ROW && count < MAX_SEARCH_RESULTS)
755
filename = g_strdup((gchar *) sqlite3_column_text(stmt, 0));
756
if (g_file_test(filename, G_FILE_TEST_EXISTS))
758
photos = g_list_append(photos, filename);
762
sqlite3_finalize(stmt);
763
library_sqlite_error(db, rc);
766
sqlite3_prepare_v2(db, "delete from filter;", -1, &stmt, NULL);
767
rc = sqlite3_step(stmt);
768
sqlite3_finalize(stmt);
769
library_sqlite_error(db, rc);
772
sqlite3_prepare_v2(db, "delete from result;", -1, &stmt, NULL);
773
rc = sqlite3_step(stmt);
774
sqlite3_finalize(stmt);
775
library_sqlite_error(db, rc);
777
g_debug("Search in library took %.03f seconds", g_timer_elapsed(gt, NULL));
784
library_photo_default_tags(RSLibrary *library, const gint photo_id, RSMetadata *metadata)
786
g_assert(RS_IS_LIBRARY(library));
790
if (metadata->make_ascii)
792
GList *temp = rs_split_string(metadata->make_ascii, " ");
793
tags = g_list_concat(tags, temp);
795
if (metadata->model_ascii)
797
GList *temp = rs_split_string(metadata->model_ascii, " ");
798
tags = g_list_concat(tags, temp);
800
if (metadata->lens_min_focal != -1 && metadata->lens_max_focal != -1)
803
if (metadata->lens_min_focal == metadata->lens_max_focal)
804
lens = g_strdup_printf("%dmm",(gint) metadata->lens_min_focal);
806
lens = g_strdup_printf("%d-%dmm",(gint) metadata->lens_min_focal, (gint) metadata->lens_max_focal);
807
tags = g_list_append(tags, g_strdup(lens));
810
if (metadata->focallength > 0)
813
if (metadata->focallength < 50)
814
text = g_strdup(_("wideangle"));
816
text = g_strdup(_("telephoto"));
817
tags = g_list_append(tags, g_strdup(text));
820
if (metadata->timestamp != -1)
824
GDate *date = g_date_new();
825
g_date_set_time_t(date, metadata->timestamp);
826
year = g_strdup_printf("%d", g_date_get_year(date));
827
gint m = g_date_get_month(date);
832
month = g_strdup(_("January")); /* FIXME: There may be a better way to do this */
835
month = g_strdup(_("February"));
838
month = g_strdup(_("March"));
841
month = g_strdup(_("April"));
844
month = g_strdup(_("May"));
847
month = g_strdup(_("June"));
850
month = g_strdup(_("July"));
853
month = g_strdup(_("August"));
856
month = g_strdup(_("September"));
859
month = g_strdup(_("October"));
862
month = g_strdup(_("November"));
865
month = g_strdup(_("December"));
869
tags = g_list_append(tags, g_strdup(year));
870
tags = g_list_append(tags, g_strdup(month));
878
library_execute_sql(library->db, "BEGIN TRANSACTION;");
879
gint *used_tags = g_malloc(g_list_length(tags) * sizeof(gint));
880
for(i = 0; i < g_list_length(tags); i++)
882
gchar *tag = (gchar *) g_list_nth_data(tags, i);
883
gint tag_id = rs_library_add_tag(library, tag);
885
/* Check if tag has already been added */
886
gboolean used = FALSE;
887
for (j = 0; j < i; j++)
888
if (tag_id == used_tags[j])
892
library_photo_add_tag(library, photo_id, tag_id, TRUE);
893
used_tags[i] = tag_id;
897
library_execute_sql(library->db, "COMMIT;");
902
rs_library_photo_tags(RSLibrary *library, const gchar *photo, const gboolean autotag)
904
g_assert(RS_IS_LIBRARY(library));
905
if (!rs_library_has_database_connection(library)) return NULL;
909
sqlite3 *db = library->db;
914
sqlite3_prepare_v2(db, "select tags.tagname from library,phototags,tags WHERE library.id=phototags.photo and phototags.tag=tags.id and library.filename = ?1;", -1, &stmt, NULL);
915
rc = sqlite3_bind_text(stmt, 1, photo, -1, NULL);
919
sqlite3_prepare_v2(db, "select tags.tagname from library,phototags,tags WHERE library.id=phototags.photo and phototags.tag=tags.id and library.filename = ?1 and phototags.autotag = 0;", -1, &stmt, NULL);
920
rc = sqlite3_bind_text(stmt, 1, photo, -1, NULL);
922
while (sqlite3_step(stmt) == SQLITE_ROW)
923
tags = g_list_append(tags, g_strdup((gchar *) sqlite3_column_text(stmt, 0)));
924
sqlite3_finalize(stmt);
925
library_sqlite_error(db, rc);
931
rs_library_find_tag(RSLibrary *library, const gchar *tag)
933
g_assert(RS_IS_LIBRARY(library));
934
if (!rs_library_has_database_connection(library)) return NULL;
938
sqlite3 *db = library->db;
941
rc = sqlite3_prepare_v2(db, "select tags.tagname from tags WHERE tags.tagname like ?1 order by tags.tagname;", -1, &stmt, NULL);
942
gchar *like = g_strdup_printf("%%%s%%", tag);
943
rc = sqlite3_bind_text(stmt, 1, like, -1, NULL);
944
library_sqlite_error(db, rc);
946
while (sqlite3_step(stmt) == SQLITE_ROW)
947
tags = g_list_append(tags, g_strdup((gchar *) sqlite3_column_text(stmt, 0)));
948
sqlite3_finalize(stmt);
949
library_sqlite_error(db, rc);
958
rs_library_set_tag_search(gchar *str)
962
gtk_entry_set_text(GTK_ENTRY(tag_search_entry), str);
967
rs_library_add_photo_with_metadata(RSLibrary *library, const gchar *photo, RSMetadata *metadata)
969
if (!rs_library_has_database_connection(library)) return;
971
/* Bail out if we already know the photo */
972
if (library_find_photo_id(library, photo) > -1)
975
gint photo_id = library_add_photo(library, photo);
976
library_photo_default_tags(library, photo_id, metadata);
979
static GStaticMutex backup_lock = G_STATIC_MUTEX_INIT;
982
rs_library_backup_tags(RSLibrary *library, const gchar *photo_filename)
984
if (!rs_library_has_database_connection(library)) return;
986
sqlite3 *db = library->db;
989
gchar *filename = NULL, *checksum, *tag, *t_filename;
991
gchar *directory = g_path_get_dirname(photo_filename);
992
gchar *dotdir = rs_dotdir_get(photo_filename);
994
g_static_mutex_lock (&backup_lock);
998
GString *gs = g_string_new(dotdir);
999
g_string_append(gs, G_DIR_SEPARATOR_S);
1000
g_string_append(gs, TAGS_XML_FILE);
1001
gchar *xmlfile = gs->str;
1002
g_string_free(gs, FALSE);
1004
xmlTextWriterPtr writer;
1006
writer = xmlNewTextWriterFilename(xmlfile, 0);
1012
g_static_mutex_unlock (&backup_lock);
1016
xmlTextWriterSetIndent(writer, 1);
1017
xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
1018
xmlTextWriterStartElement(writer, BAD_CAST "rawstudio-tags");
1019
xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "version", "%d", LIBRARY_VERSION);
1021
const gchar *temp = g_strdup_printf("%s/%%", directory);
1022
rc = sqlite3_prepare_v2(db, "select library.filename,library.identifier,tags.tagname,phototags.autotag from library,phototags,tags where library.filename like ?1 and phototags.photo = library.id and tags.id = phototags.tag order by library.filename;", -1, &stmt, NULL);
1023
rc = sqlite3_bind_text(stmt, 1, temp, -1, SQLITE_TRANSIENT);
1024
library_sqlite_error(db, rc);
1025
while (sqlite3_step(stmt) == SQLITE_ROW)
1027
t_filename = g_path_get_basename((gchar *) sqlite3_column_text(stmt, 0));
1028
if (g_strcmp0(t_filename, filename) != 0 || filename == NULL)
1030
if (filename != NULL)
1031
xmlTextWriterEndElement(writer);
1032
filename = t_filename;
1033
xmlTextWriterStartElement(writer, BAD_CAST "file");
1034
xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "name", "%s", filename);
1035
checksum = (gchar *) sqlite3_column_text(stmt, 1);
1036
xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "checksum", "%s", checksum);
1039
tag = (gchar *) sqlite3_column_text(stmt, 2);
1040
autotag = (gint) sqlite3_column_int(stmt, 3);
1041
xmlTextWriterStartElement(writer, BAD_CAST "tag");
1042
xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "name", "%s", tag);
1043
xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "auto", "%d", autotag);
1044
xmlTextWriterEndElement(writer);
1046
xmlTextWriterEndElement(writer);
1048
rc = sqlite3_finalize(stmt);
1050
xmlTextWriterEndDocument(writer);
1051
xmlFreeTextWriter(writer);
1055
g_static_mutex_unlock (&backup_lock);
1060
rs_library_restore_tags(const gchar *directory)
1062
RSLibrary *library = rs_library_get_singleton();
1064
if (!rs_library_has_database_connection(library)) return;
1066
gchar *dotdir = rs_dotdir_get(directory);
1070
GString *gs = g_string_new(dotdir);
1071
g_string_append(gs, G_DIR_SEPARATOR_S);
1072
g_string_append(gs, TAGS_XML_FILE);
1073
gchar *xmlfile = gs->str;
1074
g_string_free(gs, FALSE);
1076
if (!g_file_test(xmlfile, G_FILE_TEST_EXISTS))
1084
xmlNodePtr cur, cur2;
1088
gchar *filename, *identifier, *tagname;
1089
gint autotag, photoid, tagid;
1091
doc = xmlParseFile(xmlfile);
1095
cur = xmlDocGetRootElement(doc);
1097
if ((!xmlStrcmp(cur->name, BAD_CAST "rawstudio-tags")))
1099
val = xmlGetProp(cur, BAD_CAST "version");
1101
version = atoi((gchar *) val);
1102
if (version > LIBRARY_VERSION)
1112
cur = cur->xmlChildrenNode;
1115
if ((!xmlStrcmp(cur->name, BAD_CAST "file")))
1117
val = xmlGetProp(cur, BAD_CAST "name");
1118
filename = g_build_filename(directory, val, NULL);
1121
photoid = library_find_photo_id(library, filename);
1122
if ( photoid == -1 && g_file_test(filename, G_FILE_TEST_EXISTS))
1124
photoid = rs_library_add_photo(library, filename);
1126
val = xmlGetProp(cur, BAD_CAST "checksum");
1127
identifier = (gchar *) val;
1129
cur2 = cur->xmlChildrenNode;
1132
if ((!xmlStrcmp(cur2->name, BAD_CAST "tag")))
1134
val = xmlGetProp(cur2, BAD_CAST "name");
1135
tagname =(gchar*) val;
1136
tagid = library_find_tag_id(library, tagname);
1138
tagid = rs_library_add_tag(library, tagname);
1140
val = xmlGetProp(cur2, BAD_CAST "auto");
1141
autotag = atoi((gchar *) val);
1144
library_photo_add_tag(library, photoid, tagid, (autotag == 1));
1150
xmlFree(identifier);