summaryrefslogtreecommitdiff
path: root/browse_model.c
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2009-12-23 17:10:39 +0100
committerJon Bergli Heier <snakebite@jvnv.net>2009-12-23 17:10:39 +0100
commit1f0ef0bc2e7d0b99feb05e57f1c15a5a739c48fa (patch)
treed9000823af75d35d8c0b7a18d51b250c4c674b28 /browse_model.c
parenta539fdf38688cbed984d9db1f08deaaf34eaf9e0 (diff)
Reworked the main window.
Images are now placed in their own icon view. Folders are selected in the above tree view, while the icon view displays thumbnails of the images in the selected folder. The thumbnails are cached using the thumbnail specification (~/.thumbnails/).
Diffstat (limited to 'browse_model.c')
-rw-r--r--browse_model.c443
1 files changed, 443 insertions, 0 deletions
diff --git a/browse_model.c b/browse_model.c
new file mode 100644
index 0000000..72aac8a
--- /dev/null
+++ b/browse_model.c
@@ -0,0 +1,443 @@
+#include "browse_model.h"
+
+static void browse_model_init(BrowseModel *browse_model);
+static void browse_model_class_init(BrowseModelClass *klass);
+static void browse_model_tree_model_init(GtkTreeModelIface *iface);
+static void browse_model_finalize(GObject *object);
+static GtkTreeModelFlags browse_model_get_flags(GtkTreeModel *tree_model);
+static gint browse_model_get_n_columns(GtkTreeModel *tree_model);
+static GType browse_model_get_column_type(GtkTreeModel *tree_model, gint index);
+static gboolean browse_model_get_iter(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path);
+static GtkTreePath *browse_model_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter);
+static void browse_model_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value);
+static gboolean browse_model_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter);
+static gboolean browse_model_iter_children(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent);
+static gboolean browse_model_iter_has_child(GtkTreeModel *tree_model, GtkTreeIter *iter);
+static gint browse_model_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter);
+static gboolean browse_model_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n);
+static gboolean browse_model_iter_parent(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child);
+
+static GObjectClass *parent_class = NULL;
+
+GType browse_model_get_type() {
+ static GType browse_model_type = 0;
+ if(browse_model_type == 0) {
+ static const GTypeInfo browse_model_info = {
+ sizeof(BrowseModelClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) browse_model_class_init,
+ NULL,
+ NULL,
+ sizeof(BrowseModel),
+ 0,
+ (GInstanceInitFunc) browse_model_init
+ };
+ static const GInterfaceInfo tree_model_info = {
+ (GInterfaceInitFunc) browse_model_tree_model_init,
+ NULL,
+ NULL
+ };
+ browse_model_type = g_type_register_static(G_TYPE_OBJECT, "BrowseModel", &browse_model_info, (GTypeFlags)0);
+ g_type_add_interface_static(browse_model_type, GTK_TYPE_TREE_MODEL, &tree_model_info);
+ }
+ return browse_model_type;
+}
+
+static void browse_model_class_init(BrowseModelClass *klass) {
+ GObjectClass *object_class;
+
+ parent_class = (GObjectClass*)g_type_class_peek_parent(klass);
+ object_class = (GObjectClass*)klass;
+
+ object_class->finalize = browse_model_finalize;
+}
+
+static void browse_model_tree_model_init(GtkTreeModelIface *iface) {
+ iface->get_flags = browse_model_get_flags;
+ iface->get_n_columns = browse_model_get_n_columns;
+ iface->get_column_type = browse_model_get_column_type;
+ iface->get_iter = browse_model_get_iter;
+ iface->get_path = browse_model_get_path;
+ iface->get_value = browse_model_get_value;
+ iface->iter_next = browse_model_iter_next;
+ iface->iter_children = browse_model_iter_children;
+ iface->iter_has_child = browse_model_iter_has_child;
+ iface->iter_n_children = browse_model_iter_n_children;
+ iface->iter_nth_child = browse_model_iter_nth_child;
+ iface->iter_parent = browse_model_iter_parent;
+}
+
+static void browse_model_init(BrowseModel *browse_model) {
+ BrowseModelRecord temp;
+ GArray *array;
+ browse_model->n_columns = BROWSE_MODEL_N_COLUMNS;
+
+ browse_model->column_types[0] = G_TYPE_STRING;
+
+ g_assert(BROWSE_MODEL_N_COLUMNS == 1);
+
+ browse_model->num_rows = 0;
+ browse_model->rows = g_array_new(TRUE, FALSE, sizeof(BrowseModelRecord));
+ browse_model->stamp = g_random_int();
+
+ if(db_get_top_level_directories(&array)) {
+ for(int i = 0; i < array->len; i++) {
+ struct directory_t *dir;
+
+ dir = &g_array_index(array, struct directory_t, i);
+
+ temp.dir.name = g_strdup(dir->name);
+ temp.dir.dirid = dir->dirid;
+ temp.parent = NULL;
+ temp.children = NULL;
+ temp.pos = i;
+
+ g_free(dir->name);
+
+ g_array_append_val(browse_model->rows, temp);
+ browse_model->num_rows++;
+ }
+ g_array_free(array, TRUE);
+ }
+}
+
+static void finalize_recursive(BrowseModelRecord *record) {
+ if(!record->children)
+ return;
+
+ for(int i = 0; i < record->children->len; i++) {
+ BrowseModelRecord *temp;
+ temp = &g_array_index(record->children, BrowseModelRecord, i);
+ g_free(temp->dir.name);
+ }
+}
+
+static void browse_model_finalize(GObject *object) {
+ BrowseModel *browse_model;
+
+ g_assert(MODEL_IS_BROWSE(object));
+
+ browse_model = BROWSE_MODEL(object);
+
+ for(int i = 0; i < browse_model->rows->len; i++) {
+ BrowseModelRecord *temp;
+ temp = &g_array_index(browse_model->rows, BrowseModelRecord, i);
+ g_free(temp->dir.name);
+ finalize_recursive(temp);
+ }
+
+ g_array_free(browse_model->rows, TRUE);
+}
+
+static GtkTreeModelFlags browse_model_get_flags(GtkTreeModel *tree_model) {
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), (GtkTreeModelFlags)0);
+
+ return GTK_TREE_MODEL_ITERS_PERSIST;
+}
+
+static gint browse_model_get_n_columns(GtkTreeModel *tree_model) {
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), 0);
+
+ return BROWSE_MODEL(tree_model)->n_columns;
+}
+
+static GType browse_model_get_column_type(GtkTreeModel *tree_model, gint index) {
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), G_TYPE_INVALID);
+ g_return_val_if_fail(index < BROWSE_MODEL(tree_model)->n_columns && index >= 0, G_TYPE_INVALID);
+
+ return BROWSE_MODEL(tree_model)->column_types[index];
+}
+
+inline static void fill_dir(BrowseModelRecord *record) {
+ GArray *array;
+
+ record->children = g_array_new(FALSE, FALSE, sizeof(BrowseModelRecord));
+ if(db_get_directories(record->dir.dirid, &array)) {
+ for(int i = 0; i < array->len; i++) {
+ BrowseModelRecord temp;
+ struct directory_t *dir;
+
+ dir = &g_array_index(array, struct directory_t, i);
+ temp.dir.name = g_strdup(dir->name);
+ temp.dir.dirid = dir->dirid;
+ temp.parent = record;
+ temp.children = NULL;
+ temp.pos = i;
+
+ g_array_append_val(record->children, temp);
+
+ g_free(dir->name);
+ }
+ g_array_free(array, TRUE);
+ }
+}
+
+#define BROWSE_MODEL_ENSURE_CHILDREN(obj) if(!(obj)->children) fill_dir((obj))
+
+inline static BrowseModelRecord *browse_model_get_record_recursive(BrowseModel *browse_model, gint *indices, gint depth) {
+ BrowseModelRecord *temp;
+ if(depth == 1) {
+ return &g_array_index(browse_model->rows, BrowseModelRecord, indices[depth-1]);
+ } else {
+ temp = browse_model_get_record_recursive(browse_model, indices, depth-1);
+ BROWSE_MODEL_ENSURE_CHILDREN(temp);
+ return &g_array_index(temp->children, BrowseModelRecord, indices[depth-1]);
+ }
+}
+
+static gboolean browse_model_get_iter(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path) {
+ BrowseModel *browse_model;
+ BrowseModelRecord *record;
+ gint *indices, n, depth;
+
+ g_assert(MODEL_IS_BROWSE(tree_model));
+ g_assert(path != NULL);
+
+ browse_model = BROWSE_MODEL(tree_model);
+
+ indices = gtk_tree_path_get_indices(path);
+ depth = gtk_tree_path_get_depth(path);
+
+ n = indices[depth-1];
+ //if(n >= browse_model->num_rows || n < 0)
+ // return FALSE;
+
+ //record = &g_array_index(browse_model->rows, BrowseModelRecord, n);
+ record = browse_model_get_record_recursive(browse_model, indices, depth);
+
+ g_assert(record != NULL);
+ g_assert(record->pos == n);
+
+ iter->stamp = browse_model->stamp;
+ iter->user_data = record;
+ iter->user_data2 = NULL;
+ iter->user_data3 = NULL;
+
+ return TRUE;
+}
+
+static GtkTreePath *browse_model_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter) {
+ GtkTreePath *path;
+ BrowseModelRecord *record;
+ BrowseModel *browse_model;
+
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), NULL);
+ g_return_val_if_fail(iter != NULL, NULL);
+ g_return_val_if_fail(iter->user_data != NULL, NULL);
+
+ browse_model = BROWSE_MODEL(tree_model);
+
+ record = (BrowseModelRecord*)iter->user_data;
+
+ path = gtk_tree_path_new();
+ gtk_tree_path_append_index(path, record->pos);
+
+ return path;
+}
+
+static void browse_model_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value) {
+ BrowseModelRecord *record;
+ BrowseModel *browse_model;
+
+ g_return_if_fail(MODEL_IS_BROWSE(tree_model));
+ g_return_if_fail(iter != NULL);
+ g_return_if_fail(column < BROWSE_MODEL(tree_model)->n_columns);
+
+ g_value_init(value, BROWSE_MODEL(tree_model)->column_types[column]);
+
+ browse_model = BROWSE_MODEL(tree_model);
+
+ record = (BrowseModelRecord*)iter->user_data;
+
+ g_return_if_fail(record != NULL);
+
+ //if(record->pos >= browse_model->num_rows)
+ // g_return_if_reached();
+
+ switch(column) {
+ case BROWSE_MODEL_COL_NAME:
+ g_value_set_string_take_ownership(value, (record->parent == NULL ? g_strdup(record->dir.name) : g_path_get_basename(record->dir.name)));
+ break;
+ }
+}
+
+static gboolean browse_model_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter) {
+ BrowseModelRecord *record, *nextrecord;
+ BrowseModel *browse_model;
+ GArray *array;
+
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), FALSE);
+
+ if(iter == NULL || iter->user_data == NULL)
+ return FALSE;
+
+ browse_model = BROWSE_MODEL(tree_model);
+
+ record = (BrowseModelRecord*)iter->user_data;
+
+ BROWSE_MODEL_ENSURE_CHILDREN(record);
+
+ array = (record->parent ? record->parent->children : browse_model->rows);
+
+ if((record->pos + 1) >= array->len)
+ return FALSE;
+
+ nextrecord = &g_array_index(array, BrowseModelRecord, record->pos + 1);
+
+ g_assert(nextrecord != NULL);
+ g_assert(nextrecord->pos == (record->pos + 1));
+
+ iter->stamp = browse_model->stamp;
+ iter->user_data = nextrecord;
+
+ return TRUE;
+}
+
+static gboolean browse_model_iter_children(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) {
+ BrowseModel *browse_model;
+ BrowseModelRecord *parent_record;
+
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), FALSE);
+
+ browse_model = BROWSE_MODEL(tree_model);
+
+ if(!parent) {
+ if(browse_model->num_rows == 0)
+ return FALSE;
+ iter->stamp = browse_model->stamp;
+ iter->user_data = &g_array_index(browse_model->rows, BrowseModelRecord, 0);
+ return TRUE;
+ }
+
+ //g_return_val_if_fail(parent == NULL || parent->user_data != NULL, FALSE);
+
+ parent_record = (BrowseModelRecord*)parent->user_data;
+
+ BROWSE_MODEL_ENSURE_CHILDREN(parent_record);
+
+ if(parent_record->children->len == 0)
+ return FALSE;
+
+ iter->stamp = browse_model->stamp;
+ iter->user_data = &g_array_index(parent_record->children, BrowseModelRecord, 0);
+
+ return TRUE;
+}
+
+static gboolean browse_model_iter_has_child(GtkTreeModel *tree_model, GtkTreeIter *iter) {
+ BrowseModelRecord *record;
+
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), FALSE);
+
+ record = (BrowseModelRecord*)iter->user_data;
+ BROWSE_MODEL_ENSURE_CHILDREN(record);
+
+ return (record->parent == NULL && BROWSE_MODEL(tree_model)->num_rows == 0 ? FALSE : (record->children->len > 0 ? TRUE : FALSE));
+}
+
+static gint browse_model_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter) {
+ BrowseModel *browse_model;
+ BrowseModelRecord *record;
+ GArray *array;
+ int n;
+
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), -1);
+ g_return_val_if_fail(iter == NULL || iter->user_data != NULL, 0);
+
+ browse_model = BROWSE_MODEL(tree_model);
+
+ if(!iter) {
+ return browse_model->num_rows;
+ }
+
+ record = (BrowseModelRecord*)iter->user_data;
+
+ //array = NULL;
+ //g_return_val_if_fail(db_get_wallpapers(record->dir.dirid, &array), -1);
+ //for(n = 0; (&g_array_index(array, struct wallpaper_t, n))->filepath; n++);
+
+ BROWSE_MODEL_ENSURE_CHILDREN(record);
+
+ return record->children->len;
+
+ return n;
+}
+
+static gboolean browse_model_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n) {
+ BrowseModelRecord *record, *parent_record;
+ BrowseModel *browse_model;
+
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), FALSE);
+
+ browse_model = BROWSE_MODEL(tree_model);
+
+ if(!parent) {
+ if(n >= browse_model->num_rows)
+ return FALSE;
+ record = &g_array_index(browse_model->rows, BrowseModelRecord, n);
+
+ iter->stamp = browse_model->stamp;
+ iter->user_data = record;
+
+ return TRUE;
+ }
+
+ //if(n >= browse_model->num_rows)
+ // return FALSE;
+
+ parent_record = parent->user_data;
+
+ BROWSE_MODEL_ENSURE_CHILDREN(parent_record);
+
+ if(n >= parent_record->children->len)
+ return FALSE;
+
+ record = &g_array_index(parent_record->children, BrowseModelRecord, n);
+
+ g_assert(record != NULL);
+ g_assert(record->pos == n);
+
+ iter->stamp = browse_model->stamp;
+ iter->user_data = record;
+
+ return TRUE;
+}
+
+static gboolean browse_model_iter_parent(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child) {
+ BrowseModelRecord *record, *childrecord;
+ BrowseModel *browse_model;
+
+ g_return_val_if_fail(MODEL_IS_BROWSE(tree_model), FALSE);
+
+ browse_model = BROWSE_MODEL(tree_model);
+
+ childrecord = (BrowseModelRecord*)child->user_data;
+
+ iter->stamp = browse_model->stamp;
+ iter->user_data = childrecord->parent;
+
+ return TRUE;
+}
+
+BrowseModel *browse_model_new() {
+ BrowseModel *new_browse_model;
+
+ new_browse_model = (BrowseModel*)g_object_new(MODEL_TYPE_BROWSE, NULL);
+
+ g_assert(new_browse_model != NULL);
+
+ return new_browse_model;
+}
+
+void browse_model_get_dir_record(GtkTreeModel *tree_model, GtkTreeIter *iter, struct directory_t **dir) {
+ BrowseModel *browse_model;
+ BrowseModelRecord *record;
+
+ g_assert(MODEL_IS_BROWSE(tree_model));
+ g_assert(iter != NULL);
+
+ browse_model = BROWSE_MODEL(tree_model);
+ record = (BrowseModelRecord*)iter->user_data;
+ *dir = &record->dir;
+}