summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2010-01-04 02:18:51 +0100
committerJon Bergli Heier <snakebite@jvnv.net>2010-01-04 02:18:51 +0100
commit9120a30db940b4e2a4f08ff6436161810b4f8302 (patch)
treecaff1f4bb039ad0c84972f28578263285117f3ab
parent2b6c3414c4785582a20023820507c9c89042b385 (diff)
Implemented tag searching.
-rw-r--r--db.c77
-rw-r--r--db.h1
-rw-r--r--thumbnails.c2
-rw-r--r--walls.ui20
-rw-r--r--window_main.c144
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 @@
<object class="GtkNotebook" id="left_pages">
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <signal name="switch_page" handler="on_left_pages_switch_page"/>
<child>
<object class="GtkScrolledWindow" id="filtree_scroller">
<property name="visible">True</property>
@@ -118,6 +119,25 @@
<property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <object class="GtkTreeView" id="tagview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Tags</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="resize">False</property>
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);