1/* 2 * Copyright 1998-2002 The gtkmm Development Team 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19#include <gtk/gtk.h> 20 21 22static gboolean SignalProxy_Visible_gtk_callback(GtkTreeModel* model, GtkTreeIter* iter, gpointer data) 23{ 24 auto the_slot = static_cast<Gtk::TreeModelFilter::SlotVisible*>(data); 25 26 try 27 { 28 return (*the_slot)( Gtk::TreeModel::const_iterator(model, iter) ); 29 } 30 catch(...) 31 { 32 Glib::exception_handlers_invoke(); 33 } 34 35 return FALSE; //An arbitary default, just to avoid the compiler warning. 36} 37 38static void SignalProxy_Visible_gtk_callback_destroy(void* data) 39{ 40 delete static_cast<Gtk::TreeModelFilter::SlotVisible*>(data); 41} 42 43 44static void SignalProxy_Modify_gtk_callback(GtkTreeModel* model, GtkTreeIter* iter, GValue* value, gint column, gpointer data) 45{ 46 auto the_slot = static_cast<Gtk::TreeModelFilter::SlotModify*>(data); 47 48 try 49 { 50 //Initialize the input parameter with the appropriate type for this column. 51 //Then the C++ handler can just use operator==() without calling init on the value output arg: 52 Glib::ValueBase cppValue; 53 auto column_type = gtk_tree_model_get_column_type(model, column); 54 cppValue.init(column_type); 55 56 (*the_slot)( Gtk::TreeModel::const_iterator(model, iter), cppValue, column ); 57 58 //GTK+ has already done this for us: g_value_init(value, column_type); 59 60 //If the C++ handler has inited value with an inappropriate GType, then this will fail, 61 //but they should not do that because it makes no sense. 62 g_value_copy(cppValue.gobj() /* source */, value /* destination */); 63 } 64 catch(...) 65 { 66 Glib::exception_handlers_invoke(); 67 } 68} 69 70static void SignalProxy_Modify_gtk_callback_destroy(void* data) 71{ 72 delete static_cast<Gtk::TreeModelFilter::SlotModify*>(data); 73} 74 75 76typedef Gtk::TreeModel::Path Path; //So that the generated method implemenations can use this a return type. 77 78namespace Gtk 79{ 80 81TreeModelFilter::TreeModelFilter(const Glib::RefPtr<TreeModel>& child_model) 82: 83 _CONSTRUCT("child_model", child_model->gobj()) 84{ 85} 86 87TreeModelFilter::TreeModelFilter(const Glib::RefPtr<TreeModel>& child_model, const TreeModel::Path& virtual_root) 88: 89 _CONSTRUCT("child_model", child_model->gobj(), "virtual_root", (virtual_root.empty() ? nullptr : const_cast<GtkTreePath*>((virtual_root).gobj())) ) 90{ 91} 92 93void TreeModelFilter::set_visible_func(const SlotVisible& slot) 94{ 95 // Create a copy of the slot. A pointer to this will be passed 96 // through the callback's data parameter. It will be deleted 97 // when SignalProxy_Visible_gtk_callback_destroy() is called. 98 auto slot_copy = new SlotVisible(slot); 99 100 gtk_tree_model_filter_set_visible_func(gobj(), 101 &SignalProxy_Visible_gtk_callback, slot_copy, 102 &SignalProxy_Visible_gtk_callback_destroy); 103} 104 105 106TreeModel::iterator TreeModelFilter::convert_child_iter_to_iter(const iterator& child_iter) const 107{ 108 TreeIter filter_iter (const_cast<TreeModelFilter*>(this)); 109 110 gtk_tree_model_filter_convert_child_iter_to_iter( 111 const_cast<GtkTreeModelFilter*>(gobj()), filter_iter.gobj(), 112 const_cast<GtkTreeIter*>(child_iter.gobj())); 113 114 return filter_iter; 115} 116 117TreeModel::iterator TreeModelFilter::convert_iter_to_child_iter(const iterator& filter_iter) const 118{ 119 const auto child_model = gtk_tree_model_filter_get_model(const_cast<GtkTreeModelFilter*>(gobj())); 120 121 TreeIter child_iter (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) child_model, false))); 122 123 gtk_tree_model_filter_convert_iter_to_child_iter( 124 const_cast<GtkTreeModelFilter*>(gobj()), child_iter.gobj(), 125 const_cast<GtkTreeIter*>(filter_iter.gobj())); 126 127 return child_iter; 128} 129 130void TreeModelFilter::set_modify_func(const TreeModelColumnRecord& columns, const SlotModify& slot) 131{ 132 // Create a copy of the slot. A pointer to this will be passed 133 // through the callback's data parameter. It will be deleted 134 // when SignalProxy_Modify_gtk_callback_destroy() is called. 135 auto slot_copy = new SlotModify(slot); 136 137 gtk_tree_model_filter_set_modify_func(gobj(), 138 columns.size(), const_cast<GType*>(columns.types()), 139 &SignalProxy_Modify_gtk_callback, slot_copy, 140 &SignalProxy_Modify_gtk_callback_destroy); 141} 142 143void TreeModelFilter::set_value_impl(const iterator& row, int column, const Glib::ValueBase& value) 144{ 145 // Avoid two extra ref/unref cycles -- we don't store the child 146 // model pointer anywhere, so it's OK to do this _internally_. 147 148 const auto child_model = dynamic_cast<TreeModel*>( 149 Glib::wrap_auto((GObject*) gtk_tree_model_filter_get_model(gobj()), false)); 150 151 TreeIter child_iter (child_model); 152 153 gtk_tree_model_filter_convert_iter_to_child_iter( 154 gobj(), child_iter.gobj(), const_cast<GtkTreeIter*>(row.gobj())); 155 156 child_model->set_value_impl(child_iter, column, value); 157} 158 159 160} // namespace Gtk 161