2 /* $Id: treemodel.ccg,v 1.13 2006/05/11 11:40:24 murrayc Exp $ */
4 /* Copyright 1998-2002 The gtkmm Development Team
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <gtkmm/treeiter.h>
22 #include <gtkmm/treepath.h>
23 #include <gtk/gtktreestore.h>
24 #include <gtk/gtktreemodel.h>
29 static gboolean proxy_foreach_iter_callback(GtkTreeModel* model, GtkTreePath*, GtkTreeIter* iter, void* data)
31 typedef Gtk::TreeModel::SlotForeachIter SlotType;
32 SlotType& slot = *static_cast<SlotType*>(data);
34 #ifdef GLIBMM_EXCEPTIONS_ENABLED
37 #endif //GLIBMM_EXCEPTIONS_ENABLED
38 return slot(Gtk::TreeModel::iterator(model, iter));
39 #ifdef GLIBMM_EXCEPTIONS_ENABLED
43 Glib::exception_handlers_invoke();
45 #endif //GLIBMM_EXCEPTIONS_ENABLED
50 static gboolean proxy_foreach_path_callback(GtkTreeModel*, GtkTreePath* path, GtkTreeIter*, void* data)
52 typedef Gtk::TreeModel::SlotForeachPath SlotType;
53 SlotType& slot = *static_cast<SlotType*>(data);
55 #ifdef GLIBMM_EXCEPTIONS_ENABLED
58 #endif //GLIBMM_EXCEPTIONS_ENABLED
59 return slot(Gtk::TreeModel::Path(path, true));
60 #ifdef GLIBMM_EXCEPTIONS_ENABLED
64 Glib::exception_handlers_invoke();
66 #endif //GLIBMM_EXCEPTIONS_ENABLED
71 static gboolean proxy_foreach_path_and_iter_callback(GtkTreeModel* model, GtkTreePath* path,
72 GtkTreeIter* iter, void* data)
74 typedef Gtk::TreeModel::SlotForeachPathAndIter SlotType;
75 SlotType& slot = *static_cast<SlotType*>(data);
77 #ifdef GLIBMM_EXCEPTIONS_ENABLED
80 #endif //GLIBMM_EXCEPTIONS_ENABLED
81 return slot(Gtk::TreeModel::Path(path, true), Gtk::TreeModel::iterator(model, iter));
82 #ifdef GLIBMM_EXCEPTIONS_ENABLED
86 Glib::exception_handlers_invoke();
88 #endif //GLIBMM_EXCEPTIONS_ENABLED
93 } //anonymous namespace
96 //Help the code generator, so that it doesn't have to fully qualify this type:
97 typedef Gtk::TreeModel::iterator iterator;
102 TreeModel::iterator TreeModel::get_iter(const Path& path)
104 Gtk::TreeModel::iterator iter(this);
105 gtk_tree_model_get_iter(gobj(), iter.gobj(), const_cast<GtkTreePath*>(path.gobj()));
109 TreeModel::iterator TreeModel::get_iter(const Glib::ustring& path_string)
111 Gtk::TreeModel::iterator iter (this);
112 gtk_tree_model_get_iter_from_string(gobj(), iter.gobj(), path_string.c_str());
116 TreeModel::Children TreeModel::children()
118 return TreeNodeChildren(this);
121 TreeModel::Children TreeModel::children() const
123 //TODO: Remove the const when we have a real const TreeNodeChildren, when we have a real const_iterator.
124 return TreeNodeChildren(const_cast<TreeModel*>(this));
127 void TreeModel::set_value_impl(const iterator&, int, const Glib::ValueBase&)
129 g_assert_not_reached();
132 void TreeModel::get_value_impl(const iterator& row, int column, Glib::ValueBase& value) const
134 gtk_tree_model_get_value(
135 const_cast<GtkTreeModel*>(gobj()),
136 const_cast<GtkTreeIter*>(row.gobj()),
137 column, value.gobj());
140 void TreeModel::foreach_iter(const SlotForeachIter& slot)
142 SlotForeachIter slot_copy (slot);
143 gtk_tree_model_foreach(gobj(), &proxy_foreach_iter_callback, &slot_copy);
146 void TreeModel::foreach_path(const SlotForeachPath& slot)
148 SlotForeachPath slot_copy (slot);
149 gtk_tree_model_foreach(gobj(), &proxy_foreach_path_callback, &slot_copy);
152 void TreeModel::foreach(const SlotForeachPathAndIter& slot)
154 SlotForeachPathAndIter slot_copy (slot);
155 gtk_tree_model_foreach(gobj(), &proxy_foreach_path_and_iter_callback, &slot_copy);
158 bool TreeModel::iter_is_valid(const iterator& iter) const
160 //This method is overriden in TreeStore and ListStore.
161 //This implementation will only be used as a default for custom derived TreeModels,
162 //and when we wrap a C GtkTreeModel with a Gtk::TreeModel instance, without knowing what derived C type it is.
164 // This check is almost the same as the private VALID_ITER() macro in gtkliststore.c and
166 return (!iter.is_end_ && iter.gobj()->stamp != 0);
169 #ifdef GLIBMM_VFUNCS_ENABLED
171 // Custom vfunc callbacks, because the C++ vfuncs have different parameters and return types
172 // that can not be generated automatically:
173 gboolean TreeModel_Class::iter_next_vfunc_callback(GtkTreeModel* self, GtkTreeIter* iter)
175 CppObjectType *const obj = dynamic_cast<CppObjectType*>(
176 Glib::ObjectBase::_get_current_wrapper((GObject*)self));
178 // Non-gtkmmproc-generated custom classes implicitly call the default
179 // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
180 // generated classes can use this optimisation, which avoids the unnecessary
181 // parameter conversions if there is no possibility of the virtual function
183 if(obj && obj->is_derived_())
185 #ifdef GLIBMM_EXCEPTIONS_ENABLED
186 try // Trap C++ exceptions which would normally be lost because this is a C callback.
188 #endif //GLIBMM_EXCEPTIONS_ENABLED
189 // Call the virtual member method, which derived classes might override.
190 TreeModel::iterator iter_input = TreeModel::iterator(self, iter);
191 TreeModel::iterator iter_next( self, iter ); //Copies iter by value.
192 gboolean test = obj->iter_next_vfunc(iter_input, iter_next);
194 //Copy the new iter value to the C output parameter:
196 *iter = *(iter_next.gobj());
199 #ifdef GLIBMM_EXCEPTIONS_ENABLED
203 Glib::exception_handlers_invoke();
205 #endif //GLIBMM_EXCEPTIONS_ENABLED
209 BaseClassType *const base = static_cast<BaseClassType*>(
210 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
211 g_type_interface_peek(G_OBJECT_GET_CLASS(self), CppObjectType::get_type()) // Get the interface.
215 // Call the original underlying C function:
216 if(base && base->iter_next)
217 return (*base->iter_next)(self, iter);
220 typedef gboolean RType;
225 bool TreeModel::iter_next_vfunc(const iterator& iter, iterator& iter_next) const
227 //Call the default C implementation:
229 BaseClassType *const base = static_cast<BaseClassType*>(
230 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
231 g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface.
235 if(base && base->iter_next)
237 TreeModel::iterator iter_copy = iter;
238 gboolean test = (*base->iter_next)(const_cast<GtkTreeModel*>(gobj()), iter_copy.gobj());
240 iter_next = iter_copy;
248 gboolean TreeModel_Class::get_iter_vfunc_callback(GtkTreeModel* self, GtkTreeIter* iter, GtkTreePath* path)
250 CppObjectType *const obj = dynamic_cast<CppObjectType*>(
251 Glib::ObjectBase::_get_current_wrapper((GObject*)self));
253 // Non-gtkmmproc-generated custom classes implicitly call the default
254 // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
255 // generated classes can use this optimisation, which avoids the unnecessary
256 // parameter conversions if there is no possibility of the virtual function
258 if(obj && obj->is_derived_())
260 #ifdef GLIBMM_EXCEPTIONS_ENABLED
261 try // Trap C++ exceptions which would normally be lost because this is a C callback.
263 #endif //GLIBMM_EXCEPTIONS_ENABLED
264 // Call the virtual member method, which derived classes might override.
265 Gtk::TreeModel::iterator iter_out(self, iter); //copies the iter by value.
266 gboolean test = obj->get_iter_vfunc(Gtk::TreePath(path, true), iter_out);
268 //Copy the new iter value to the C output parameter:
270 *iter = *(iter_out.gobj());
273 #ifdef GLIBMM_EXCEPTIONS_ENABLED
277 Glib::exception_handlers_invoke();
279 #endif //GLIBMM_EXCEPTIONS_ENABLED
283 BaseClassType *const base = static_cast<BaseClassType*>(
284 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
285 g_type_interface_peek(G_OBJECT_GET_CLASS(self), CppObjectType::get_type()) // Get the interface.
288 // Call the original underlying C function:
289 if(base && base->get_iter)
290 return (*base->get_iter)(self, iter, const_cast<GtkTreePath*>(path));
293 typedef gboolean RType;
297 bool TreeModel::get_iter_vfunc(const Path& path, iterator& iter) const
299 //Call the default C implementation:
301 BaseClassType *const base = static_cast<BaseClassType*>(
302 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
303 g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface.
307 if(base && base->get_iter)
309 return (*base->get_iter)( const_cast<GtkTreeModel*>(gobj()), iter.gobj(), const_cast<GtkTreePath*>(path.gobj()) );
315 gboolean TreeModel_Class::iter_children_vfunc_callback(GtkTreeModel* self, GtkTreeIter* iter, GtkTreeIter* parent)
317 CppObjectType *const obj = dynamic_cast<CppObjectType*>(
318 Glib::ObjectBase::_get_current_wrapper((GObject*)self));
320 // Non-gtkmmproc-generated custom classes implicitly call the default
321 // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
322 // generated classes can use this optimisation, which avoids the unnecessary
323 // parameter conversions if there is no possibility of the virtual function
325 if(obj && obj->is_derived_())
327 #ifdef GLIBMM_EXCEPTIONS_ENABLED
328 try // Trap C++ exceptions which would normally be lost because this is a C callback.
330 #endif //GLIBMM_EXCEPTIONS_ENABLED
331 // Call the virtual member method, which derived classes might override.
332 Gtk::TreeModel::iterator iter_out(self, iter); //copies the iter by value.
334 gboolean test = false;
337 //Deal with this case, which is documented in the C docs as:
338 //" If @parent is %NULL returns the first node, equivalent to
339 // <literal>gtk_tree_model_get_iter_first (tree_model, iter);</literal> "
340 test = obj->iter_nth_root_child_vfunc(0, iter_out);
345 Gtk::TreeModel::iterator parent_cpp(self, parent);
346 test = obj->iter_children_vfunc(parent_cpp, iter_out);
349 //Copy the new iter value to the C output parameter:
351 *iter = *(iter_out.gobj());
354 #ifdef GLIBMM_EXCEPTIONS_ENABLED
358 Glib::exception_handlers_invoke();
360 #endif //GLIBMM_EXCEPTIONS_ENABLED
364 BaseClassType *const base = static_cast<BaseClassType*>(
365 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
366 g_type_interface_peek(G_OBJECT_GET_CLASS(self), CppObjectType::get_type()) // Get the interface.
369 // Call the original underlying C function:
370 if(base && base->iter_children)
371 return (*base->iter_children)(self, iter, parent);
374 typedef gboolean RType;
378 bool TreeModel::iter_children_vfunc(const iterator& parent, iterator& iter) const
380 //Call the default C implementation:
382 BaseClassType *const base = static_cast<BaseClassType*>(
383 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
384 g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface.
388 if(base && base->iter_children)
390 return (*base->iter_children)( const_cast<GtkTreeModel*>(gobj()), iter.gobj(), const_cast<GtkTreeIter*>(parent.gobj()) );
396 gboolean TreeModel_Class::iter_parent_vfunc_callback(GtkTreeModel* self, GtkTreeIter* iter, GtkTreeIter* child)
398 CppObjectType *const obj = dynamic_cast<CppObjectType*>(
399 Glib::ObjectBase::_get_current_wrapper((GObject*)self));
401 // Non-gtkmmproc-generated custom classes implicitly call the default
402 // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
403 // generated classes can use this optimisation, which avoids the unnecessary
404 // parameter conversions if there is no possibility of the virtual function
406 if(obj && obj->is_derived_())
408 #ifdef GLIBMM_EXCEPTIONS_ENABLED
409 try // Trap C++ exceptions which would normally be lost because this is a C callback.
411 #endif //GLIBMM_EXCEPTIONS_ENABLED
412 // Call the virtual member method, which derived classes might override.
413 Gtk::TreeModel::iterator iter_out(self, iter);
414 Gtk::TreeModel::iterator child_cpp(self, child);
415 gboolean test = obj->iter_parent_vfunc(child_cpp, iter_out);
417 //Copy the new iter value to the C output parameter:
419 *iter = *(iter_out.gobj());
422 #ifdef GLIBMM_EXCEPTIONS_ENABLED
426 Glib::exception_handlers_invoke();
428 #endif //GLIBMM_EXCEPTIONS_ENABLED
432 BaseClassType *const base = static_cast<BaseClassType*>(
433 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
434 g_type_interface_peek(G_OBJECT_GET_CLASS(self), CppObjectType::get_type()) // Get the interface.
437 // Call the original underlying C function:
438 if(base && base->iter_parent)
439 return (*base->iter_parent)(self, iter, child);
442 typedef gboolean RType;
446 bool TreeModel::iter_parent_vfunc(const iterator& child, iterator& iter) const
448 //Call the default C implementation:
450 BaseClassType *const base = static_cast<BaseClassType*>(
451 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
452 g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface.
456 if(base && base->iter_parent)
458 return (*base->iter_parent)( const_cast<GtkTreeModel*>(gobj()), iter.gobj(), const_cast<GtkTreeIter*>(child.gobj()) );
464 gboolean TreeModel_Class::iter_nth_child_vfunc_callback(GtkTreeModel* self, GtkTreeIter* iter, GtkTreeIter* parent, int n)
466 CppObjectType *const obj = dynamic_cast<CppObjectType*>(
467 Glib::ObjectBase::_get_current_wrapper((GObject*)self));
469 // Non-gtkmmproc-generated custom classes implicitly call the default
470 // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
471 // generated classes can use this optimisation, which avoids the unnecessary
472 // parameter conversions if there is no possibility of the virtual function
474 if(obj && obj->is_derived_())
476 #ifdef GLIBMM_EXCEPTIONS_ENABLED
477 try // Trap C++ exceptions which would normally be lost because this is a C callback.
479 #endif //GLIBMM_EXCEPTIONS_ENABLED
480 // Call the virtual member method, which derived classes might override.
481 Gtk::TreeModel::iterator iter_out(self, iter);
483 gboolean test = false;
486 // Deal with this special case, docuemnted in the C docs as:
487 // "As a special case, if @parent is %NULL, then the nth root node is set.":
488 test = obj->iter_nth_root_child_vfunc(n, iter_out);
493 Gtk::TreeModel::iterator parent_cpp(self, parent);
494 test = obj->iter_nth_child_vfunc(parent_cpp, n, iter_out);
497 //Copy the new iter value to the C output parameter:
499 *iter = *(iter_out.gobj());
502 #ifdef GLIBMM_EXCEPTIONS_ENABLED
506 Glib::exception_handlers_invoke();
508 #endif //GLIBMM_EXCEPTIONS_ENABLED
512 BaseClassType *const base = static_cast<BaseClassType*>(
513 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
514 g_type_interface_peek(G_OBJECT_GET_CLASS(self), CppObjectType::get_type()) // Get the interface.
517 // Call the original underlying C function:
518 if(base && base->iter_nth_child)
519 return (*base->iter_nth_child)(self, iter, parent, n);
522 typedef gboolean RType;
526 bool TreeModel::iter_nth_child_vfunc(const iterator& parent, int n, iterator& iter) const
528 //Call the default C implementation:
530 BaseClassType *const base = static_cast<BaseClassType*>(
531 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
532 g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface.
536 if(base && base->iter_nth_child)
538 return (*base->iter_nth_child)( const_cast<GtkTreeModel*>(gobj()), iter.gobj(), const_cast<GtkTreeIter*>(parent.gobj()), n );
544 //See the implementation of iter_children_vfunc_callback() and iter_nth_child_vfunc_callback()
545 //to find out why this virtual function exists:
546 bool TreeModel::iter_nth_root_child_vfunc(int n, iterator& iter) const
548 //Call the default C implementation:
550 BaseClassType *const base = static_cast<BaseClassType*>(
551 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
552 g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface.
556 if(base && base->iter_nth_child)
558 //This means that iter_nth_child(0) might be called by iter_children_vfunc_callback(),
559 //but hopefully that's exactly the same thing. TODO: Ask why both vfuncs exist. murrayc.
560 return (*base->iter_nth_child)( const_cast<GtkTreeModel*>(gobj()), iter.gobj(), 0 /* the null parent */, n );
566 gboolean TreeModel_Class::iter_n_children_vfunc_callback(GtkTreeModel* self, GtkTreeIter* iter)
568 CppObjectType *const obj = dynamic_cast<CppObjectType*>(
569 Glib::ObjectBase::_get_current_wrapper((GObject*)self));
571 // Non-gtkmmproc-generated custom classes implicitly call the default
572 // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
573 // generated classes can use this optimisation, which avoids the unnecessary
574 // parameter conversions if there is no possibility of the virtual function
576 if(obj && obj->is_derived_())
578 #ifdef GLIBMM_EXCEPTIONS_ENABLED
579 try // Trap C++ exceptions which would normally be lost because this is a C callback.
581 #endif //GLIBMM_EXCEPTIONS_ENABLED
582 // Call the virtual member method, which derived classes might override.
584 //Deal with the case that iter is null, as described in the C docs:
586 return obj->iter_n_children_vfunc( Gtk::TreeModel::iterator(self, iter) );
588 return obj->iter_n_root_children_vfunc();
589 #ifdef GLIBMM_EXCEPTIONS_ENABLED
593 Glib::exception_handlers_invoke();
595 #endif //GLIBMM_EXCEPTIONS_ENABLED
599 BaseClassType *const base = static_cast<BaseClassType*>(
600 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
601 g_type_interface_peek(G_OBJECT_GET_CLASS(self), CppObjectType::get_type()) // Get the interface.
604 // Call the original underlying C function:
605 if(base && base->iter_n_children)
606 return (*base->iter_n_children)(self, iter);
609 typedef gboolean RType;
613 int TreeModel::iter_n_children_vfunc(const iterator& iter) const
615 BaseClassType *const base = static_cast<BaseClassType*>(
616 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
617 g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface.
620 if(base && base->iter_n_children)
621 return (*base->iter_n_children)(const_cast<GtkTreeModel*>(gobj()), const_cast<GtkTreeIter*>((iter).gobj()));
627 int TreeModel::iter_n_root_children_vfunc() const
629 BaseClassType *const base = static_cast<BaseClassType*>(
630 g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface).
631 g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface.
634 if(base && base->iter_n_children)
635 return (*base->iter_n_children)(const_cast<GtkTreeModel*>(gobj()), 0 /* null iter to mean root node, as described in C docs */);
641 #endif //GLIBMM_VFUNCS_ENABLED
644 void TreeModel::rows_reordered(const Path& path, const iterator& iter, const Glib::ArrayHandle<int>& new_order)
646 //The size of the array seems to be based on the known number of children. murrayc.
647 gtk_tree_model_rows_reordered(gobj(), const_cast<GtkTreePath*>((path).gobj()), const_cast<GtkTreeIter*>((iter).gobj()), const_cast<int*>(new_order.data()));
650 void TreeModel::rows_reordered(const Path& path, const Glib::ArrayHandle<int>& new_order)
652 //The size of the array seems to be based on the known number of children. murrayc.
653 gtk_tree_model_rows_reordered(gobj(), const_cast<GtkTreePath*>((path).gobj()), 0, const_cast<int*>(new_order.data()));