summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--db.c52
-rw-r--r--db.h6
-rw-r--r--window_tag.c69
-rw-r--r--window_tag.h1
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*);