2
/* $Id: treeiter.ccg,v 1.10 2006/04/12 08:23:29 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 Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 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
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser 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/treemodel.h>
28
/**** Gtk::TreeIter ********************************************************/
37
TreeIter::TreeIter(TreeModel* model)
44
TreeIter::TreeIter(GtkTreeModel* model, const GtkTreeIter* iter)
47
model_ (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model))),
51
TreeIter& TreeIter::operator++()
55
GtkTreeIter previous = gobject_;
57
if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_))
60
gtk_tree_model_iter_parent(Glib::unwrap(model_), &gobject_, &previous);
66
const TreeIter TreeIter::operator++(int)
70
TreeIter previous (*this);
72
if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_))
75
gtk_tree_model_iter_parent(Glib::unwrap(model_), &gobject_, &previous.gobject_);
81
TreeIter& TreeIter::operator--()
85
gtk_tree_model_iter_previous(Glib::unwrap(model_), &gobject_);
87
else // --end yields last
89
GtkTreeIter next = gobject_;
90
GtkTreeIter *const parent = (next.stamp != 0) ? &next : 0;
92
const int index = gtk_tree_model_iter_n_children(Glib::unwrap(model_), parent) - 1;
93
is_end_ = !gtk_tree_model_iter_nth_child(Glib::unwrap(model_), &gobject_, parent, index);
101
const TreeIter TreeIter::operator--(int)
103
TreeIter next (*this);
107
gtk_tree_model_iter_previous(Glib::unwrap(model_), &gobject_);
109
else // --end yields last
111
GtkTreeIter *const parent = (next.gobject_.stamp != 0) ? &next.gobject_ : 0;
113
const int index = gtk_tree_model_iter_n_children(model_->gobj(), parent) - 1;
114
is_end_ = !gtk_tree_model_iter_nth_child(model_->gobj(), &gobject_, parent, index);
122
/* There is no public gtk_tree_iter_equal(), so we must write our own.
124
bool TreeIter::equal(const TreeIter& other) const
126
g_assert(model_ == other.model_);
128
// A GtkTreeIter has the same stamp value as its model.
129
g_assert(gobject_.stamp == other.gobject_.stamp || is_end_ || other.is_end_);
131
// If all user_data pointers are equal we can assume the iterators to be
132
// equal. This should be safe since GtkTreeIter lacks destroy notification,
133
// thus there is no way to attach more data fields to the iterator.
134
return (is_end_ == other.is_end_) &&
135
(gobject_.user_data == other.gobject_.user_data) &&
136
(gobject_.user_data2 == other.gobject_.user_data2) &&
137
(gobject_.user_data3 == other.gobject_.user_data3);
140
TreeIter::operator const void*() const
142
// Test whether the GtkTreeIter is valid and not an end iterator. This check
143
// is almost the same as the private VALID_ITER() macro in gtkliststore.c and
145
return (!is_end_ && gobject_.stamp) ? GINT_TO_POINTER(1) : 0;
148
void TreeIter::setup_end_iterator(const TreeIter& last_valid)
150
g_assert(model_ == last_valid.model_);
152
if(last_valid.is_end_)
153
gobject_ = last_valid.gobject_;
155
gtk_tree_model_iter_parent(model_->gobj(), &gobject_, const_cast<GtkTreeIter*>(&last_valid.gobject_));
160
void TreeIter::set_model_refptr(const Glib::RefPtr<TreeModel>& model)
162
model_ = model.operator->();
165
void TreeIter::set_model_gobject(GtkTreeModel* model)
167
model_ = dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model));
170
GtkTreeModel* TreeIter::get_model_gobject() const
172
return (model_) ? model_->gobj() : 0;
176
int TreeIter::get_stamp() const
178
return gobj()->stamp;
181
void TreeIter::set_stamp(int stamp)
183
gobj()->stamp = stamp;
187
/**** Gtk::TreeRow *********************************************************/
189
const TreeNodeChildren& TreeRow::children() const
193
return static_cast<const TreeNodeChildren&>(static_cast<const TreeIter&>(*this));
196
TreeIter TreeRow::parent() const
198
TreeIter iter (model_);
201
iter.gobject_ = gobject_;
203
gtk_tree_model_iter_parent(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_));
208
void TreeRow::set_value_impl(int column, const Glib::ValueBase& value) const
210
model_->set_value_impl(*this, column, value);
213
void TreeRow::get_value_impl(int column, Glib::ValueBase& value) const
215
model_->get_value_impl(*this, column, value);
218
TreeRow::operator const void*() const
220
return TreeIter::operator const void*();
224
/**** Gtk::TreeNodeChildren ************************************************/
226
TreeNodeChildren::iterator TreeNodeChildren::begin()
228
iterator iter (model_);
230
// If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
231
// node. This behaviour is needed to implement Gtk::TreeModel::children().
233
if(gobject_.stamp != 0)
235
if(!gtk_tree_model_iter_children(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_)))
237
// Assign the already known parent, in order to create an end iterator.
238
iter.gobject_ = gobject_;
244
if(!gtk_tree_model_get_iter_first(model_->gobj(), iter.gobj()))
246
// No need to copy the GtkTreeIter, since iter.gobject_ is already empty.
254
TreeNodeChildren::const_iterator TreeNodeChildren::begin() const
256
//TODO: Reduce the copy/paste from the non-const begin()?
258
const_iterator iter (model_);
260
// If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
261
// node. This behaviour is needed to implement Gtk::TreeModel::children().
263
if(gobject_.stamp != 0)
265
if(!gtk_tree_model_iter_children(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_)))
267
// Assign the already known parent, in order to create an end iterator.
268
iter.gobject_ = gobject_;
274
if(!gtk_tree_model_get_iter_first(model_->gobj(), iter.gobj()))
276
// No need to copy the GtkTreeIter, since iter.gobject_ is already empty.
284
TreeNodeChildren::iterator TreeNodeChildren::end()
286
// Just copy the parent, and turn it into an end iterator.
287
iterator iter (*this);
292
TreeNodeChildren::const_iterator TreeNodeChildren::end() const
294
// Just copy the parent, and turn it into an end iterator.
295
const_iterator iter (*this);
300
TreeNodeChildren::value_type TreeNodeChildren::operator[](TreeNodeChildren::size_type index) const
302
iterator iter (model_);
304
GtkTreeIter *const parent = const_cast<GtkTreeIter*>(get_parent_gobject());
306
if(!gtk_tree_model_iter_nth_child(model_->gobj(), iter.gobj(), parent, index))
308
// Assign the already known parent, in order to create an end iterator.
309
iter.gobject_ = gobject_;
316
TreeNodeChildren::size_type TreeNodeChildren::size() const
318
GtkTreeIter *const parent = const_cast<GtkTreeIter*>(get_parent_gobject());
320
return gtk_tree_model_iter_n_children(model_->gobj(), parent);
323
bool TreeNodeChildren::empty() const
325
// If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
326
// node. This behaviour is needed to implement Gtk::TreeModel::children().
328
if(gobject_.stamp == 0)
331
return !gtk_tree_model_get_iter_first(model_->gobj(), &dummy);
334
return !gtk_tree_model_iter_has_child(model_->gobj(), const_cast<GtkTreeIter*>(&gobject_));