/* $Id$ */ /*- * Copyright (c) 2006 Benedikt Meurer . * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include typedef struct _ThunarTreeModelItem ThunarTreeModelItem; static void thunar_tree_model_class_init (ThunarTreeModelClass *klass); static void thunar_tree_model_tree_model_init (GtkTreeModelIface *iface); static void thunar_tree_model_init (ThunarTreeModel *model); static void thunar_tree_model_finalize (GObject *object); static GtkTreeModelFlags thunar_tree_model_get_flags (GtkTreeModel *tree_model); static gint thunar_tree_model_get_n_columns (GtkTreeModel *tree_model); static GType thunar_tree_model_get_column_type (GtkTreeModel *tree_model, gint column); static gboolean thunar_tree_model_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path); static GtkTreePath *thunar_tree_model_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter); static void thunar_tree_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value); static gboolean thunar_tree_model_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter); static gboolean thunar_tree_model_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent); static gboolean thunar_tree_model_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter); static gint thunar_tree_model_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter); static gboolean thunar_tree_model_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n); static gboolean thunar_tree_model_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child); static void thunar_tree_model_ref_node (GtkTreeModel *tree_model, GtkTreeIter *iter); static void thunar_tree_model_unref_node (GtkTreeModel *tree_model, GtkTreeIter *iter); struct _ThunarTreeModelClass { GObjectClass __parent__; }; struct _ThunarTreeModel { GObject __parent__; GNode *root; guint stamp; }; struct _ThunarTreeModelItem { gint ref_count; ThunarFile *file; ThunarFolder *folder; }; static GObjectClass *thunar_tree_model_parent_class; GType thunar_tree_model_get_type (void) { static GType type = G_TYPE_INVALID; if (G_UNLIKELY (type == G_TYPE_INVALID)) { static const GTypeInfo info = { sizeof (ThunarTreeModelClass), NULL, NULL, (GClassInitFunc) thunar_tree_model_class_init, NULL, NULL, sizeof (ThunarTreeModel), 0, (GInstanceInitFunc) thunar_tree_model_init, NULL, }; static const GInterfaceInfo tree_model_info = { (GInterfaceInitFunc) thunar_tree_model_tree_model_init, NULL, NULL, }; type = g_type_register_static (G_TYPE_OBJECT, I_("ThunarTreeModel"), &info, 0); g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL, &tree_model_info); } return type; } static void thunar_tree_model_class_init (ThunarTreeModelClass *klass) { GObjectClass *gobject_class; /* determine the parent type class */ thunar_tree_model_parent_class = g_type_class_peek_parent (klass); gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = thunar_tree_model_finalize; } static void thunar_tree_model_tree_model_init (GtkTreeModelIface *iface) { iface->get_flags = thunar_tree_model_get_flags; iface->get_n_columns = thunar_tree_model_get_n_columns; iface->get_column_type = thunar_tree_model_get_column_type; iface->get_iter = thunar_tree_model_get_iter; iface->get_path = thunar_tree_model_get_path; iface->get_value = thunar_tree_model_get_value; iface->iter_next = thunar_tree_model_iter_next; iface->iter_children = thunar_tree_model_iter_children; iface->iter_has_child = thunar_tree_model_iter_has_child; iface->iter_n_children = thunar_tree_model_iter_n_children; iface->iter_nth_child = thunar_tree_model_iter_nth_child; iface->iter_parent = thunar_tree_model_iter_parent; } static void thunar_tree_model_init (ThunarTreeModel *model) { model->stamp = g_random_int (); } static void thunar_tree_model_finalize (GObject *object) { (*G_OBJECT_CLASS (thunar_tree_model_parent_class)->finalize) (object); } static GtkTreeModelFlags thunar_tree_model_get_flags (GtkTreeModel *tree_model) { return GTK_TREE_MODEL_ITERS_PERSIST; } static gint thunar_tree_model_get_n_columns (GtkTreeModel *tree_model) { return THUNAR_TREE_MODEL_N_COLUMNS; } static GType thunar_tree_model_get_column_type (GtkTreeModel *tree_model, gint column) { switch (column) { case THUNAR_SHORTCUTS_MODEL_COLUMN_FILE: return THUNAR_TYPE_FILE; case THUNAR_SHORTCUTS_MODEL_COLUMN_NAME: return G_TYPE_STRING; } g_assert_not_reached (); return G_TYPE_INVALID; } static gboolean thunar_tree_model_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path) { ThunarTreeModel *model = THUNAR_TREE_MODEL (tree_model); GtkTreeIter parent; const gint *indices; gint depth; gint n; g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); /* determine the path depth */ depth = gtk_tree_path_get_depth (path); /* determine the path indices */ indices = gtk_tree_path_get_indices (path); /* initialize the parent iterator with the root element */ parent.stamp = model->stamp; parent.user_data = model->root; if (gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[0])) return FALSE; for (n = 1; n < depth; ++n) { parent = *iter; if (!gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[n])) return FALSE; } return TRUE; } static GtkTreePath *thunar_tree_model_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter); static void thunar_tree_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value); static gboolean thunar_tree_model_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter) { ThunarTreeModel *model = THUNAR_TREE_MODEL (tree_model); g_return_val_if_fail (THUNAR_IS_TREE_MODEL (model), FALSE); g_return_val_if_fail (iter->stamp == model->stamp, FALSE); g_return_val_if_fail (iter->user_data != NULL, FALSE); iter->user_data = G_NODE (iter->user_data)->next; return (iter->user_data != NULL); } static gboolean thunar_tree_model_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) { ThunarTreeModel *model = THUNAR_TREE_MODEL (tree_model); GNode *children; g_return_val_if_fail (THUNAR_IS_TREE_MODEL (model), FALSE); g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE); g_return_val_if_fail (parent == NULL || parent->stamp == model->stamp, FALSE); if (G_LIKELY (parent != NULL)) children = g_node_first_child (parent->user_data); else children = g_node_first_child (model->root); if (G_LIKELY (children != NULL)) { iter->stamp = model->stamp; iter->user_data = children; return TRUE; } return FALSE; } static gboolean thunar_tree_model_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter) { ThunarTreeModel *model = THUNAR_TREE_MODEL (tree_model); g_return_val_if_fail (THUNAR_IS_TREE_MODEL (model), FALSE); g_return_val_if_fail (iter->stamp == model->stamp, FALSE); g_return_val_if_fail (iter->user_data != NULL, FALSE); return (g_node_first_child (iter->user_data) != NULL); } static gint thunar_tree_model_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter); static gboolean thunar_tree_model_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n) { ThunarTreeModel *model = THUNAR_TREE_MODEL (tree_model); GNode *child; g_return_val_if_fail (THUNAR_IS_TREE_MODEL (model), FALSE); g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE); g_return_val_if_fail (parent == NULL || parent->stamp == model->stamp, FALSE); child = g_node_nth_child ((parent != NULL) ? parent->user_data : model->root, n); if (G_LIKELY (child != NULL)) { iter->stamp = model->stamp; iter->user_data = child; return TRUE; } return FALSE; } static gboolean thunar_tree_model_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child);