30 #include "gnc-tree-model-selection.h"
34 static void gnc_tree_model_selection_finalize (GObject *
object);
36 static void gnc_tree_model_selection_tree_model_init (GtkTreeModelIface *iface);
37 static GtkTreeModelFlags gnc_tree_model_selection_get_flags (GtkTreeModel *tree_model);
38 static int gnc_tree_model_selection_get_n_columns (GtkTreeModel *tree_model);
39 static GType gnc_tree_model_selection_get_column_type (GtkTreeModel *tree_model,
41 static gboolean gnc_tree_model_selection_get_iter (GtkTreeModel *tree_model,
44 static GtkTreePath *gnc_tree_model_selection_get_path (GtkTreeModel *tree_model,
46 static void gnc_tree_model_selection_get_value (GtkTreeModel *tree_model,
50 static gboolean gnc_tree_model_selection_iter_next (GtkTreeModel *tree_model,
52 static gboolean gnc_tree_model_selection_iter_children (GtkTreeModel *tree_model,
55 static gboolean gnc_tree_model_selection_iter_has_child (GtkTreeModel *tree_model,
57 static int gnc_tree_model_selection_iter_n_children (GtkTreeModel *tree_model,
59 static gboolean gnc_tree_model_selection_iter_nth_child (GtkTreeModel *tree_model,
63 static gboolean gnc_tree_model_selection_iter_parent (GtkTreeModel *tree_model,
67 static void gnc_tree_model_selection_row_changed (GtkTreeModel *tree_model,
71 static void gnc_tree_model_selection_row_inserted (GtkTreeModel *tree_model,
75 static void gnc_tree_model_selection_row_has_child_toggled (GtkTreeModel *tree_model,
79 static void gnc_tree_model_selection_row_deleted (GtkTreeModel *tree_model,
82 static void gnc_tree_model_selection_rows_reordered (GtkTreeModel *tree_model,
88 static void gnc_tree_model_selection_toggled (GtkCellRendererToggle *toggle,
94 GtkTreeModel *child_model;
96 GHashTable *selections;
99 #define GNC_TREE_MODEL_SELECTION_GET_PRIVATE(o) \
100 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_MODEL_SELECTION, GncTreeModelSelectionPrivate))
102 static GObjectClass *parent_class = NULL;
105 gnc_tree_model_selection_get_type (
void)
107 static GType gnc_tree_model_selection_type = 0;
109 if (gnc_tree_model_selection_type == 0)
111 static const GTypeInfo our_info =
116 (GClassInitFunc) gnc_tree_model_selection_class_init,
121 (GInstanceInitFunc) gnc_tree_model_selection_init
124 static const GInterfaceInfo tree_model_info =
126 (GInterfaceInitFunc) gnc_tree_model_selection_tree_model_init,
131 gnc_tree_model_selection_type = g_type_register_static (G_TYPE_OBJECT,
132 "GncTreeModelSelection",
135 g_type_add_interface_static (gnc_tree_model_selection_type,
140 return gnc_tree_model_selection_type;
146 GObjectClass *object_class = G_OBJECT_CLASS (klass);
148 parent_class = g_type_class_peek_parent (klass);
150 object_class->finalize = gnc_tree_model_selection_finalize;
160 while (model->stamp == 0)
162 model->stamp = g_random_int ();
165 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
166 priv->selections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
170 gnc_tree_model_selection_finalize (GObject *
object)
175 g_return_if_fail (
object != NULL);
176 g_return_if_fail (GNC_IS_TREE_MODEL_SELECTION (
object));
178 model = GNC_TREE_MODEL_SELECTION (
object);
179 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
181 g_object_unref (priv->child_model);
182 g_hash_table_destroy (priv->selections);
184 G_OBJECT_CLASS (parent_class)->finalize (
object);
188 gnc_tree_model_selection_new (GtkTreeModel *child_model)
193 model = g_object_new (GNC_TYPE_TREE_MODEL_SELECTION, NULL);
194 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
196 priv->child_model = child_model;
197 g_object_ref (child_model);
198 g_signal_connect (G_OBJECT (child_model),
"row_changed",
199 G_CALLBACK (gnc_tree_model_selection_row_changed), model);
200 g_signal_connect (G_OBJECT (child_model),
"row_inserted",
201 G_CALLBACK (gnc_tree_model_selection_row_inserted), model);
202 g_signal_connect (G_OBJECT (child_model),
"row_has_child_toggled",
203 G_CALLBACK (gnc_tree_model_selection_row_has_child_toggled), model);
204 g_signal_connect (G_OBJECT (child_model),
"row_deleted",
205 G_CALLBACK (gnc_tree_model_selection_row_deleted), model);
206 g_signal_connect (G_OBJECT (child_model),
"rows_reordered",
207 G_CALLBACK (gnc_tree_model_selection_rows_reordered), model);
209 return GTK_TREE_MODEL (model);
214 GtkTreeIter *selection_iter,
215 GtkTreeIter *child_iter)
217 g_return_if_fail (GNC_IS_TREE_MODEL_SELECTION (model));
218 g_return_if_fail (child_iter != NULL);
219 g_return_if_fail (selection_iter != NULL);
221 selection_iter->stamp = model->stamp;
223 selection_iter->user_data = gtk_tree_iter_copy (child_iter);
228 GtkTreeIter *child_iter,
229 GtkTreeIter *selection_iter)
231 g_return_if_fail (GNC_IS_TREE_MODEL_SELECTION (model));
232 g_return_if_fail (selection_iter != NULL);
233 g_return_if_fail (GNC_TREE_MODEL_SELECTION (model)->stamp == selection_iter->stamp);
234 g_return_if_fail (selection_iter->user_data != NULL);
235 g_return_if_fail (child_iter != NULL);
237 child_iter->stamp = ((GtkTreeIter *) selection_iter->user_data)->stamp;
238 child_iter->user_data = ((GtkTreeIter *) selection_iter->user_data)->user_data;
239 child_iter->user_data2 = ((GtkTreeIter *) selection_iter->user_data)->user_data2;
240 child_iter->user_data3 = ((GtkTreeIter *) selection_iter->user_data)->user_data3;
253 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
254 path_string = gtk_tree_model_get_string_from_iter (GTK_TREE_MODEL (model), iter);
256 if (selected == (g_hash_table_lookup (priv->selections, path_string) != NULL))
258 g_free (path_string);
264 g_hash_table_insert (priv->selections, g_strdup (path_string), GINT_TO_POINTER (1));
268 g_hash_table_remove (priv->selections, path_string);
271 path = gtk_tree_path_new_from_string (path_string);
272 gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, iter);
273 gtk_tree_path_free (path);
275 g_free (path_string);
279 gnc_tree_model_selection_tree_model_init (GtkTreeModelIface *iface)
281 iface->get_flags = gnc_tree_model_selection_get_flags;
282 iface->get_n_columns = gnc_tree_model_selection_get_n_columns;
283 iface->get_column_type = gnc_tree_model_selection_get_column_type;
284 iface->get_iter = gnc_tree_model_selection_get_iter;
285 iface->get_path = gnc_tree_model_selection_get_path;
286 iface->get_value = gnc_tree_model_selection_get_value;
287 iface->iter_next = gnc_tree_model_selection_iter_next;
288 iface->iter_children = gnc_tree_model_selection_iter_children;
289 iface->iter_has_child = gnc_tree_model_selection_iter_has_child;
290 iface->iter_n_children = gnc_tree_model_selection_iter_n_children;
291 iface->iter_nth_child = gnc_tree_model_selection_iter_nth_child;
292 iface->iter_parent = gnc_tree_model_selection_iter_parent;
295 static GtkTreeModelFlags
296 gnc_tree_model_selection_get_flags (GtkTreeModel *tree_model)
301 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), 0);
303 model = GNC_TREE_MODEL_SELECTION (tree_model);
304 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
306 return gtk_tree_model_get_flags (priv->child_model);
310 gnc_tree_model_selection_get_n_columns (GtkTreeModel *tree_model)
315 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), 0);
317 model = GNC_TREE_MODEL_SELECTION (tree_model);
318 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
320 return gtk_tree_model_get_n_columns (priv->child_model) + 1;
324 gnc_tree_model_selection_get_column_type (GtkTreeModel *tree_model,
329 gint columns = gnc_tree_model_selection_get_n_columns (tree_model);
331 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), G_TYPE_INVALID);
332 g_return_val_if_fail ((index >= 0) && (index < columns), G_TYPE_INVALID);
334 model = GNC_TREE_MODEL_SELECTION (tree_model);
335 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
337 if (index < columns - 1)
339 return gtk_tree_model_get_column_type (priv->child_model, index);
343 return G_TYPE_BOOLEAN;
348 gnc_tree_model_selection_get_iter (GtkTreeModel *tree_model,
354 GtkTreeIter child_iter;
356 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), FALSE);
358 model = GNC_TREE_MODEL_SELECTION (tree_model);
359 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
361 if (!gtk_tree_model_get_iter (priv->child_model, &child_iter, path))
366 gnc_tree_model_selection_convert_child_iter_to_iter (model, iter, &child_iter);
372 gnc_tree_model_selection_get_path (GtkTreeModel *tree_model,
377 GtkTreeIter child_iter;
379 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), NULL);
380 g_return_val_if_fail (iter != NULL, NULL);
381 g_return_val_if_fail (iter->stamp == GNC_TREE_MODEL_SELECTION (tree_model)->stamp, NULL);
383 model = GNC_TREE_MODEL_SELECTION (tree_model);
384 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
386 gnc_tree_model_selection_convert_iter_to_child_iter (model, &child_iter, iter);
388 return gtk_tree_model_get_path (priv->child_model, &child_iter);
392 gnc_tree_model_selection_get_value (GtkTreeModel *tree_model,
397 gint columns = gnc_tree_model_selection_get_n_columns (tree_model);
400 GtkTreeIter child_iter;
403 g_return_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model));
404 g_return_if_fail ((column >= 0) && (column < columns));
405 g_return_if_fail (iter != NULL);
406 g_return_if_fail (iter->stamp == GNC_TREE_MODEL_SELECTION (tree_model)->stamp);
408 model = GNC_TREE_MODEL_SELECTION (tree_model);
409 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
411 gnc_tree_model_selection_convert_iter_to_child_iter (model, &child_iter, iter);
413 if (column < columns - 1)
415 gtk_tree_model_get_value (priv->child_model, &child_iter, column, value);
419 g_value_init (value, G_TYPE_BOOLEAN);
421 path = gtk_tree_model_get_string_from_iter (priv->child_model, &child_iter);
422 g_value_set_boolean (value, g_hash_table_lookup (priv->selections, path) != NULL);
428 gnc_tree_model_selection_iter_next (GtkTreeModel *tree_model,
433 GtkTreeIter child_iter;
435 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), FALSE);
436 g_return_val_if_fail (iter != NULL, FALSE);
437 g_return_val_if_fail (iter->stamp == GNC_TREE_MODEL_SELECTION (tree_model)->stamp, FALSE);
439 model = GNC_TREE_MODEL_SELECTION (tree_model);
440 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
442 gnc_tree_model_selection_convert_iter_to_child_iter (model, &child_iter, iter);
444 if (!gtk_tree_model_iter_next (priv->child_model, &child_iter))
450 gnc_tree_model_selection_convert_child_iter_to_iter (model, iter, &child_iter);
457 gnc_tree_model_selection_iter_children (GtkTreeModel *tree_model,
463 GtkTreeIter child_iter;
464 GtkTreeIter child_parent;
466 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), FALSE);
468 model = GNC_TREE_MODEL_SELECTION (tree_model);
469 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
473 if (!gtk_tree_model_iter_children (priv->child_model, &child_iter, NULL))
478 g_return_val_if_fail (parent != NULL, FALSE);
479 g_return_val_if_fail (parent->stamp == model->stamp, FALSE);
481 gnc_tree_model_selection_convert_iter_to_child_iter (model, &child_parent, parent);
483 if (!gtk_tree_model_iter_children (priv->child_model, &child_iter, &child_parent))
487 gnc_tree_model_selection_convert_child_iter_to_iter (model, iter, &child_iter);
493 gnc_tree_model_selection_iter_has_child (GtkTreeModel *tree_model,
498 GtkTreeIter child_iter;
500 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), FALSE);
501 g_return_val_if_fail (iter != NULL, FALSE);
502 g_return_val_if_fail (iter->stamp == GNC_TREE_MODEL_SELECTION (tree_model)->stamp, FALSE);
504 model = GNC_TREE_MODEL_SELECTION (tree_model);
505 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
507 gnc_tree_model_selection_convert_iter_to_child_iter (model, &child_iter, iter);
509 return gtk_tree_model_iter_has_child (priv->child_model, &child_iter);
513 gnc_tree_model_selection_iter_n_children (GtkTreeModel *tree_model,
518 GtkTreeIter child_iter;
520 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), 0);
522 model = GNC_TREE_MODEL_SELECTION (tree_model);
523 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
527 return gtk_tree_model_iter_n_children (priv->child_model, NULL);
531 g_return_val_if_fail (iter != NULL, 0);
532 g_return_val_if_fail (iter->stamp == model->stamp, 0);
534 gnc_tree_model_selection_convert_iter_to_child_iter (model, &child_iter, iter);
536 return gtk_tree_model_iter_n_children (priv->child_model, &child_iter);
541 gnc_tree_model_selection_iter_nth_child (GtkTreeModel *tree_model,
548 GtkTreeIter child_iter;
549 GtkTreeIter child_parent;
551 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), FALSE);
553 model = GNC_TREE_MODEL_SELECTION (tree_model);
554 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
558 if (!gtk_tree_model_iter_nth_child (priv->child_model, &child_iter, NULL, n))
563 g_return_val_if_fail (iter != NULL, FALSE);
564 g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
566 gnc_tree_model_selection_convert_iter_to_child_iter (model, &child_parent, parent);
568 if (!gtk_tree_model_iter_nth_child (priv->child_model, &child_iter, &child_parent, n))
572 gnc_tree_model_selection_convert_child_iter_to_iter (model, iter, &child_iter);
578 gnc_tree_model_selection_iter_parent (GtkTreeModel *tree_model,
584 GtkTreeIter child_child;
585 GtkTreeIter child_iter;
587 g_return_val_if_fail (GNC_IS_TREE_MODEL_SELECTION (tree_model), FALSE);
588 g_return_val_if_fail (child != NULL, FALSE);
589 g_return_val_if_fail (child->stamp == GNC_TREE_MODEL_SELECTION (tree_model)->stamp, FALSE);
591 model = GNC_TREE_MODEL_SELECTION (tree_model);
592 priv = GNC_TREE_MODEL_SELECTION_GET_PRIVATE(model);
594 gnc_tree_model_selection_convert_iter_to_child_iter (model, &child_child, child);
596 if (!gtk_tree_model_iter_parent (priv->child_model, &child_iter, &child_child))
602 gnc_tree_model_selection_convert_child_iter_to_iter (model, iter, &child_iter);
609 gnc_tree_model_selection_row_changed (GtkTreeModel *tree_model,
614 GtkTreeIter selection_iter;
616 gnc_tree_model_selection_convert_child_iter_to_iter (selection_model, &selection_iter, iter);
618 gtk_tree_model_row_changed (GTK_TREE_MODEL (selection_model), path, &selection_iter);
622 gnc_tree_model_selection_row_inserted (GtkTreeModel *tree_model,
627 GtkTreeIter selection_iter;
629 gnc_tree_model_selection_convert_child_iter_to_iter (selection_model, &selection_iter, iter);
631 gtk_tree_model_row_inserted (GTK_TREE_MODEL (selection_model), path, &selection_iter);
635 gnc_tree_model_selection_row_has_child_toggled (GtkTreeModel *tree_model,
640 GtkTreeIter selection_iter;
642 gnc_tree_model_selection_convert_child_iter_to_iter (selection_model, &selection_iter, iter);
644 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (selection_model), path, &selection_iter);
648 gnc_tree_model_selection_row_deleted (GtkTreeModel *tree_model,
652 gtk_tree_model_row_deleted (GTK_TREE_MODEL (selection_model), path);
656 gnc_tree_model_selection_rows_reordered (GtkTreeModel *tree_model,
662 GtkTreeIter selection_iter;
664 gnc_tree_model_selection_convert_child_iter_to_iter (selection_model, &selection_iter, iter);
666 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (selection_model), path, &selection_iter, new_order);
670 gnc_tree_model_selection_toggled (GtkCellRendererToggle *toggle,
676 if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), &iter, path))
678 gnc_tree_model_selection_set_selected (model, &iter, !gtk_cell_renderer_toggle_get_active (toggle));