From 7c099e76ae58a548f1f2123c40de1ef7597ad6a5 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Sat, 8 May 2010 21:14:34 +0200 Subject: Handle active and inconsistent tags in a more elegant way in the tag dialog. --- db.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ db.h | 6 ++++++ window_tag.c | 69 ++++++++++++++++-------------------------------------------- window_tag.h | 1 + 4 files changed, 77 insertions(+), 51 deletions(-) diff --git a/db.c b/db.c index 38a24e2..2e3c5bf 100644 --- a/db.c +++ b/db.c @@ -743,3 +743,55 @@ int db_remove_wall_tag(sqlite_uint64 wallid, sqlite_uint64 tagid) { return 0; } } + +int db_wall_tags_inconsistent(GArray *wallarray, GHashTable **inconsistent_table) { + sqlite3_stmt *stmt; + int rc; + gchar *join, *query; + + join = gen_joinstring(wallarray->len); + query = g_strdup_printf("SELECT t.id, COUNT(t.id) FROM tag t JOIN walltags wt ON (t.id = wt.tagid AND wt.wallid IN (%s)) GROUP BY t.id", join); + + rc = sqlite3_prepare_v2(db, query, -1, &stmt, NULL); + + g_free(query); + + if(rc != SQLITE_OK) { + return 0; + } + + for(int i = 0; i < wallarray->len; i++) { + sqlite3_uint64 wallid = g_array_index(wallarray, guint64, i); + + rc = sqlite3_bind_int64(stmt, i + 1, wallid); + if(rc != SQLITE_OK) { + sqlite3_finalize(stmt); + return 0; + } + } + + *inconsistent_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); + while((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + struct tag_inconsistent_data_t *data = g_malloc(sizeof(struct tag_inconsistent_data_t)); + int count; + sqlite3_uint64 tagid; + + tagid = sqlite3_column_int64(stmt, 0); + count = sqlite3_column_int(stmt, 1); + // set active if selected + data->active = count > 0; + // set inconsistent if not selected by none or all + data->inconsistent = !(count == 0 || count == wallarray->len); + + g_hash_table_insert(*inconsistent_table, (gpointer)tagid, data); + } + + sqlite3_finalize(stmt); + + if(rc != SQLITE_DONE) { + g_hash_table_destroy(*inconsistent_table); + return 0; + } + + return 1; +} diff --git a/db.h b/db.h index 969bace..97a830c 100644 --- a/db.h +++ b/db.h @@ -25,6 +25,11 @@ struct tag_t { sqlite_uint64 parent; }; +struct tag_inconsistent_data_t { + gboolean active; + gboolean inconsistent; +}; + int db_open(); void db_close(); sqlite_uint64 db_add_directory(const char*, sqlite_uint64); @@ -45,5 +50,6 @@ int db_get_tags(GArray**, sqlite_uint64); int db_add_wall_tag(sqlite_uint64, sqlite_uint64); void db_remove_tag(sqlite_uint64); int db_remove_wall_tag(sqlite_uint64, sqlite_uint64); +int db_wall_tags_inconsistent(GArray*, GHashTable**); #endif diff --git a/window_tag.c b/window_tag.c index 52db1ad..6a067dc 100644 --- a/window_tag.c +++ b/window_tag.c @@ -26,79 +26,40 @@ void on_tagview_cell_toggled(GtkCellRendererToggle *cell_renderer, gchar *path_s } } -/* TODO: Find a better way to do this. */ -inline static gboolean is_tag_inconsistent(struct tag_t *tag, GArray *walltags, gboolean *exists) { - gint n_y, n_n; - GArray *walltag_single; - gboolean found; - struct tag_t *wall_tag; - - n_y = n_n = 0; - - for(int i = 0; i < walltags->len; i++) { - walltag_single = g_array_index(walltags, GArray*, i); - found = FALSE; - for(int j = 0; j < walltag_single->len; j++) { - wall_tag = &g_array_index(walltag_single, struct tag_t, j); - if(wall_tag->id == tag->id) { - n_y++; - found = TRUE; - break; - } - } - if(!found) - n_n++; - } - if(n_y == 0) - *exists = FALSE; - else - *exists = TRUE; - return (n_n == 0 || n_y == 0 ? FALSE : TRUE); -} - /** * foreach-callback for setting checked and inconsistent in the tag model. */ static gboolean tagview_model_foreach(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) { struct tag_t *tag; - gboolean inconsistent, exists; + struct tagdialog_data_t *data; + struct tag_inconsistent_data_t *inconsistent_data; + + data = user_data; tag_model_get_tag_record(GTK_TREE_MODEL(model), iter, &tag); - inconsistent = is_tag_inconsistent(tag, (GArray*)user_data, &exists); - tag_model_set_checked(GTK_TREE_MODEL(model), iter, exists); - tag_model_set_inconsistent(GTK_TREE_MODEL(model), iter, inconsistent); + inconsistent_data = g_hash_table_lookup(data->inconsistent_table, tag->id); + if(inconsistent_data) { + tag_model_set_checked(GTK_TREE_MODEL(model), iter, inconsistent_data->active); + tag_model_set_inconsistent(GTK_TREE_MODEL(model), iter, inconsistent_data->inconsistent); + } return FALSE; } static void tagview_create_model(GtkTreeView *tagview, gpointer user_data) { GtkTreeModel *model; - GArray *walltags, *walltag_single, *wallarray; + GArray *wallarray; struct tagdialog_data_t *data; data = user_data; wallarray = data->wallarray; - walltags = g_array_new(FALSE, FALSE, sizeof(GArray*)); - for(int i = 0; i < wallarray->len; i++) { - if(db_get_wall_tags(g_array_index(wallarray, guint64, i), &walltag_single)) { - g_array_append_val(walltags, walltag_single); - } else { - g_error("db_get_wall_tags failed\n"); - return; - } - } + db_wall_tags_inconsistent(wallarray, &(data->inconsistent_table)); model = GTK_TREE_MODEL(tag_model_new()); gtk_tree_view_set_model(tagview, GTK_TREE_MODEL(model)); - gtk_tree_model_foreach(GTK_TREE_MODEL(model), tagview_model_foreach, walltags); - - for(int i = 0; i < walltags->len; i++) { - walltag_single = g_array_index(walltags, GArray*, i); - g_array_free(walltag_single, TRUE); - } - g_array_free(walltags, TRUE); + gtk_tree_model_foreach(GTK_TREE_MODEL(model), tagview_model_foreach, user_data); gtk_tree_view_expand_all(tagview); } @@ -228,6 +189,11 @@ void on_tags_selnonebtn_clicked(GtkButton *button, gpointer user_data) { } void on_tagsdialog_destroy(GtkObject *object, gpointer user_data) { + struct tagdialog_data_t *data; + + data = user_data; + + g_hash_table_destroy(data->inconsistent_table); g_free(user_data); } @@ -263,6 +229,7 @@ struct tagdialog_data_t *window_tagview_new(GtkWidget *parent, GArray* array) { data->dialog = GTK_WIDGET(dialog); data->tagview = GTK_WIDGET(tagview); data->wallarray = array; + data->inconsistent_table = NULL; tagview_init(tagview, data); diff --git a/window_tag.h b/window_tag.h index 96fceac..41e941f 100644 --- a/window_tag.h +++ b/window_tag.h @@ -8,6 +8,7 @@ struct tagdialog_data_t { GtkWidget *dialog; GtkWidget *tagview; GArray *wallarray; + GHashTable *inconsistent_table; }; struct tagdialog_data_t *window_tagview_new(GtkWidget*, GArray*); -- cgit v1.2.3