From 9120a30db940b4e2a4f08ff6436161810b4f8302 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Mon, 4 Jan 2010 02:18:51 +0100 Subject: Implemented tag searching. --- db.c | 77 +++++++++++++++++++++++++++++++ db.h | 1 + thumbnails.c | 2 +- walls.ui | 20 ++++++++ window_main.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 239 insertions(+), 5 deletions(-) diff --git a/db.c b/db.c index d47793a..0688d75 100644 --- a/db.c +++ b/db.c @@ -402,6 +402,83 @@ int db_get_wallpapers(sqlite_uint64 dirid, GArray **array) { return 1; } +static gchar *gen_joinstring(int c) { + char **split, *join; + + split = g_malloc(sizeof(gchar*) * (c+1)); + split[c] = NULL; + + for(int i = 0; i < c; i++) { + split[i] = "?"; + } + + join = g_strjoinv(", ", split); + + g_free(split); + + return join; +} + +/* + * tags = uint64 + * walls = struct tag_t * + */ +int db_get_walls_by_tags(GArray *tags, GArray **array) { + sqlite3_stmt *stmt; + int rc; + char *join, *query; + struct wallpaper_t temp, *temp2; + + join = gen_joinstring(tags->len); + query = g_strdup_printf("SELECT w.id, w.filepath, w.size, w.width, w.height " + "FROM wallpaper w JOIN walltags t ON (t.wallid = w.id) WHERE t.tagid IN (%s)", + join); + g_free(join); + + rc = sqlite3_prepare_v2(db, query, -1, &stmt, NULL); + + g_free(query); + + if(rc != SQLITE_OK) { + return 0; + } + + for(int i = 0; i < tags->len; i++) { + sqlite_uint64 id; + + id = g_array_index(tags, sqlite_uint64, i); + rc = sqlite3_bind_int64(stmt, i + 1, id); + + if(rc != SQLITE_OK) { + sqlite3_finalize(stmt); + return 0; + } + } + + *array = g_array_new(FALSE, FALSE, sizeof(struct wallpaper_t)); + while((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + temp.filepath = g_strdup(sqlite3_column_text(stmt, 1)); + temp.id = sqlite3_column_int64(stmt, 0); + temp.size = sqlite3_column_int(stmt, 2); + temp.width = sqlite3_column_int(stmt, 3); + temp.height = sqlite3_column_int(stmt, 4); + g_array_append_val(*array, temp); + } + + sqlite3_finalize(stmt); + + if(rc != SQLITE_DONE) { + for(int i = 0; i < (*array)->len; i++) { + temp2 = &g_array_index(*array, struct wallpaper_t, i); + g_free(temp2->filepath); + } + g_array_free(*array, TRUE); + return 0; + } + + return 1; +} + sqlite_uint64 db_add_tag(const char *name) { sqlite3_stmt *stmt; int rc; diff --git a/db.h b/db.h index 9cc1aec..0819c69 100644 --- a/db.h +++ b/db.h @@ -33,6 +33,7 @@ sqlite_uint64 db_get_wallpaper(const char*); int db_get_wallpaper_data(sqlite_uint64, struct wallpaper_t*); int db_get_wall_tags(sqlite_uint64, GArray**); int db_get_wallpapers(sqlite_uint64, GArray**); +int db_get_walls_by_tags(GArray*, GArray**); sqlite_uint64 db_add_tag(const char*); int db_get_tags_all(GArray**); int db_add_wall_tag(sqlite_uint64, sqlite_uint64); diff --git a/thumbnails.c b/thumbnails.c index 003120e..0bffcf5 100644 --- a/thumbnails.c +++ b/thumbnails.c @@ -73,7 +73,7 @@ GdkPixbuf *get_thumbnail(const gchar *filepath) { if(!pb) { g_warning("%s", error->message); - g_free(error); + g_error_free(error); g_free(thumbname); return NULL; } diff --git a/walls.ui b/walls.ui index 242a5b1..7bff6c6 100644 --- a/walls.ui +++ b/walls.ui @@ -95,6 +95,7 @@ True True + True @@ -118,6 +119,25 @@ False + + + True + True + + + 1 + + + + + True + Tags + + + 1 + False + + False diff --git a/window_main.c b/window_main.c index a78a6fa..5183c57 100644 --- a/window_main.c +++ b/window_main.c @@ -7,7 +7,6 @@ #include "walls_ui.h" #include "db.h" #include "browse_model.h" -#include "walls_model.h" #include "wallpapers.h" #include "thumbnails.h" #include "walls_conf.h" @@ -25,7 +24,7 @@ GtkImage *image = NULL; GtkWidget *layout = NULL; GtkStatusbar *statusbar; GtkIconView *thumbview; -GtkWidget *window_hpane, *window_vpane; +GtkWidget *window_hpane, *window_vpane, *foldtree, *tagview; GThread *add_thread = NULL, *thumb_thread = NULL; @@ -35,6 +34,7 @@ gchar *cur_wall_msg = NULL; guint image_context; void on_foldtree_selection_changed(GtkTreeSelection *treeselection, gpointer user_data); +void on_main_tagview_cell_toggled(GtkCellRendererToggle *cell_renderer, gchar *path_string, gpointer user_data); inline static void foldtree_create_model(GtkTreeView *foldtree) { GtkTreeModel *tree_model; @@ -62,6 +62,52 @@ inline static void foldtree_init(GtkTreeView *foldtree) { g_signal_connect(selection, "changed", G_CALLBACK(on_foldtree_selection_changed), foldtree); } +inline static void tagview_create_model(GtkTreeView *tagview) { + GtkListStore *model; + GArray *array; + struct tag_t *tag; + GtkTreeIter iter; + + model = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_UINT64); + + if(db_get_tags_all(&array)) { + for(int i = 0; i < array->len; i++) { + tag = &g_array_index(array, struct tag_t, i); + gtk_list_store_append(model, &iter); + gtk_list_store_set(model, &iter, 0, FALSE, 1, g_strdup(tag->name), 2, tag->id, -1); + g_free(tag->name); + } + g_array_free(array, TRUE); + } + + gtk_tree_view_set_model(tagview, GTK_TREE_MODEL(model)); +} + +inline static void tagview_init(GtkTreeView *tagview) { + GtkTreeViewColumn *col1, *col2; + GtkCellRenderer *renderer; + GtkTreeSelection *selection; + + col1 = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(col1, "Show"); + gtk_tree_view_append_column(tagview, col1); + + col2 = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(col2, "Name"); + gtk_tree_view_append_column(tagview, col2); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(col1, renderer, FALSE); + gtk_tree_view_column_add_attribute(col1, renderer, "active", 0); + g_signal_connect(renderer, "toggled", G_CALLBACK(on_main_tagview_cell_toggled), tagview); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_end(col2, renderer, TRUE); + gtk_tree_view_column_add_attribute(col2, renderer, "text", 1); + + tagview_create_model(tagview); +} + static void set_resize_msg(gdouble scale) { gchar *msg; @@ -223,7 +269,7 @@ static void fill_wall_list(GtkListStore *liststore, GArray *array) { g_array_free(array, TRUE); } -void on_foldtree_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) { +static void display_from_foldtree(GtkTreeSelection *treeselection) { GtkTreeModel *model; GtkTreeIter iter; struct directory_t *dir; @@ -231,6 +277,9 @@ void on_foldtree_selection_changed(GtkTreeSelection *treeselection, gpointer use GtkListStore *liststore; GError *error = NULL; + if(treeselection == NULL) + treeselection = gtk_tree_view_get_selection(GTK_TREE_VIEW(foldtree)); + if(gtk_tree_selection_get_selected(treeselection, &model, &iter)) { browse_model_get_dir_record(model, &iter, &dir); @@ -250,6 +299,11 @@ void on_foldtree_selection_changed(GtkTreeSelection *treeselection, gpointer use } } + +void on_foldtree_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) { + display_from_foldtree(treeselection); +} + void on_thumbview_selection_changed(GtkIconView *iconview, gpointer user_data) { GList *list; GValue value; @@ -276,6 +330,75 @@ void on_thumbview_selection_changed(GtkIconView *iconview, gpointer user_data) { } } + +void display_from_tagview() { + GtkTreeIter iter; + GtkTreeModel *model; + GtkListStore *liststore; + GValue value = {0}; + gboolean active; + GArray *tagarray, *wallarray; + guint64 id; + GError *error = NULL; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(tagview)); + + if(!gtk_tree_model_get_iter_first(model, &iter)) + return; + + tagarray = g_array_new(FALSE, FALSE, sizeof(guint64)); + + do { + gtk_tree_model_get_value(model, &iter, 0, &value); + active = g_value_get_boolean(&value); + g_value_unset(&value); + + if(!active) + continue; + + gtk_tree_model_get_value(model, &iter, 2, &value); + id = g_value_get_uint64(&value); + g_value_unset(&value); + + g_array_append_val(tagarray, id); + } while(gtk_tree_model_iter_next(model, &iter)); + + if(!db_get_walls_by_tags(tagarray, &wallarray)) { + g_array_free(tagarray, TRUE); + g_warning("Could not fetch walls by tags\n"); + return; + } + + liststore = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT64); + fill_wall_list(liststore, wallarray); + gtk_icon_view_set_model(thumbview, GTK_TREE_MODEL(liststore)); + + thumb_thread = g_thread_create(add_thumbs_thread, liststore, FALSE, &error); + + if(!thumb_thread) { + g_warning("%s\n", error->message); + g_error_free(error); + } +} + +void on_main_tagview_cell_toggled(GtkCellRendererToggle *cell_renderer, gchar *path_string, gpointer user_data) { + GtkTreeIter iter; + GtkTreeModel *model; + GValue value = {0}; + gboolean active; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(tagview)); + + gtk_tree_model_get_iter_from_string(model, &iter, path_string); + gtk_tree_model_get_value(model, &iter, 0, &value); + active = g_value_get_boolean(&value); + g_value_unset(&value); + + gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, !active, -1); + + display_from_tagview(); +} + gpointer add_dir_thread(gpointer data) { gchar *directory; @@ -433,6 +556,17 @@ gboolean on_thumbview_button_press_event(GtkWidget *widget, GdkEventButton *even return FALSE; } +gboolean on_left_pages_switch_page(GtkNotebook *notebook, GtkNotebookTab page, guint page_num, gpointer user_data) { + switch(page_num) { + case 0: + display_from_foldtree(NULL); + break; + case 1: + display_from_tagview(); + break; + } +} + static void save_window() { gint width, height; @@ -464,7 +598,6 @@ static void set_sizes() { } int gui_main(int argc, char **argv) { - GtkWidget *foldtree; GtkBuilder *builder ; GError *error = NULL; GdkColor color; @@ -492,6 +625,9 @@ int gui_main(int argc, char **argv) { foldtree = GTK_WIDGET(gtk_builder_get_object(builder, "foldtree")); foldtree_init(GTK_TREE_VIEW(foldtree)); + tagview = GTK_WIDGET(gtk_builder_get_object(builder, "tagview")); + tagview_init(GTK_TREE_VIEW(tagview)); + thumbview = GTK_ICON_VIEW(gtk_builder_get_object(builder, "thumbview")); gtk_icon_view_set_pixbuf_column(thumbview, 0); -- cgit v1.2.3