Install ardour as a binary, a script and a set of shared
[ardour.git] / libs / gtkmm2 / gtk / gtkmm / treeiter.cc
1 // Generated by gtkmmproc -- DO NOT MODIFY!
2
3 #include <gtkmm/treeiter.h>
4 #include <gtkmm/private/treeiter_p.h>
5
6 // -*- c++ -*-
7 /* $Id$ */
8
9 /* Copyright 1998-2002 The gtkmm Development Team
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the Free
23  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #include <gtkmm/treemodel.h>
27
28 namespace
29 {
30
31 // This is copied from Totem. In future there might be a version in GTK+ itself - see bug #
32 void gtkmm_gtk_tree_model_iter_previous(GtkTreeModel* tree_model, GtkTreeIter* iter)
33 {
34   GtkTreePath *const path = gtk_tree_model_get_path(tree_model, iter);
35
36   if(gtk_tree_path_prev(path))
37     gtk_tree_model_get_iter(tree_model, iter, path);
38   else
39     g_assert_not_reached();
40
41   gtk_tree_path_free(path);
42 }
43
44 } // anonymous namespace
45
46
47 namespace Gtk
48 {
49
50 /**** Gtk::TreeIter ********************************************************/
51
52 TreeIter::TreeIter()
53 :
54   TreeIterBase(),
55   model_      (0),
56   is_end_     (false)
57 {}
58
59 TreeIter::TreeIter(TreeModel* model)
60 :
61   TreeIterBase(),
62   model_      (model),
63   is_end_     (false)
64 {}
65
66 TreeIter::TreeIter(GtkTreeModel* model, const GtkTreeIter* iter)
67 :
68   TreeIterBase(iter),
69   model_      (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model))),
70   is_end_     (iter == 0)
71 {}
72
73 TreeIter& TreeIter::operator++()
74 {
75   g_assert(!is_end_);
76
77   GtkTreeIter previous = gobject_;
78
79   if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_))
80   {
81     is_end_ = true;
82     gtk_tree_model_iter_parent(model_->gobj(), &gobject_, &previous);
83   }
84
85   return *this;
86 }
87
88 const TreeIter TreeIter::operator++(int)
89 {
90   g_assert(!is_end_);
91
92   TreeIter previous (*this);
93
94   if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_))
95   {
96     is_end_ = true;
97     gtk_tree_model_iter_parent(model_->gobj(), &gobject_, &previous.gobject_);
98   }
99
100   return previous;
101 }
102
103 TreeIter& TreeIter::operator--()
104 {
105   if(!is_end_)
106   {
107     gtkmm_gtk_tree_model_iter_previous(model_->gobj(), &gobject_);
108   }
109   else // --end yields last
110   {
111     GtkTreeIter next = gobject_;
112     GtkTreeIter *const parent = (next.stamp != 0) ? &next : 0;
113
114     const int index = gtk_tree_model_iter_n_children(model_->gobj(), parent) - 1;
115     is_end_ = !gtk_tree_model_iter_nth_child(model_->gobj(), &gobject_, parent, index);
116
117     g_assert(!is_end_);
118   }
119
120   return *this;
121 }
122
123 const TreeIter TreeIter::operator--(int)
124 {
125   TreeIter next (*this);
126
127   if(!is_end_)
128   {
129     gtkmm_gtk_tree_model_iter_previous(model_->gobj(), &gobject_);
130   }
131   else // --end yields last
132   {
133     GtkTreeIter *const parent = (next.gobject_.stamp != 0) ? &next.gobject_ : 0;
134
135     const int index = gtk_tree_model_iter_n_children(model_->gobj(), parent) - 1;
136     is_end_ = !gtk_tree_model_iter_nth_child(model_->gobj(), &gobject_, parent, index);
137
138     g_assert(!is_end_);
139   }
140
141   return next;
142 }
143
144 /* There is no public gtk_tree_iter_equal(), so we must write our own.
145  */
146 bool TreeIter::equal(const TreeIter& other) const
147 {
148   g_assert(model_ == other.model_);
149
150   // A GtkTreeIter has the same stamp value as its model.
151   g_assert(gobject_.stamp == other.gobject_.stamp || is_end_ || other.is_end_);
152
153   //TODO: Allow custom treemodels to provide a different implementation.
154   
155   // If all user_data pointers are equal we can assume the iterators to be
156   // equal.  This should be safe since GtkTreeIter lacks destroy notification,
157   // thus there is no way to attach more data fields to the iterator.
158   return (is_end_ == other.is_end_) &&
159          (gobject_.user_data  == other.gobject_.user_data)  &&
160          (gobject_.user_data2 == other.gobject_.user_data2) &&
161          (gobject_.user_data3 == other.gobject_.user_data3);
162 }
163
164 TreeIter::operator bool() const
165 {
166   // Test whether the GtkTreeIter is valid and not an end iterator.  This check
167   // is almost the same as the private VALID_ITER() macro in gtkliststore.c and
168   // gtktreestore.c.
169   return (!is_end_ && gobject_.stamp != 0);
170 }
171
172 void TreeIter::setup_end_iterator(const TreeIter& last_valid)
173 {
174   g_assert(model_ == last_valid.model_);
175
176   if(last_valid.is_end_)
177     gobject_ = last_valid.gobject_;
178   else
179     gtk_tree_model_iter_parent(model_->gobj(), &gobject_, const_cast<GtkTreeIter*>(&last_valid.gobject_));
180
181   is_end_ = true;
182 }
183
184 void TreeIter::set_model_refptr(const Glib::RefPtr<TreeModel>& model)
185 {
186   model_ = model.operator->();
187 }
188
189 void TreeIter::set_model_gobject(GtkTreeModel* model)
190 {
191   model_ = dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model));
192 }
193
194 GtkTreeModel* TreeIter::get_model_gobject() const
195 {
196   return (model_) ? model_->gobj() : 0;
197 }
198
199
200 int TreeIter::get_stamp() const
201 {
202   return gobj()->stamp;
203 }
204
205 void TreeIter::set_stamp(int stamp)
206 {
207   gobj()->stamp = stamp;
208
209
210
211 /**** Gtk::TreeRow *********************************************************/
212
213 const TreeNodeChildren& TreeRow::children() const
214 {
215   g_assert(!is_end_);
216
217   return static_cast<const TreeNodeChildren&>(static_cast<const TreeIter&>(*this));
218 }
219
220 TreeIter TreeRow::parent() const
221 {
222   TreeIter iter (model_);
223
224   if(is_end_)
225     iter.gobject_ = gobject_;
226   else
227     gtk_tree_model_iter_parent(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_));
228
229   return iter;
230 }
231
232 void TreeRow::set_value_impl(int column, const Glib::ValueBase& value) const
233 {
234   model_->set_value_impl(*this, column, value);
235 }
236
237 void TreeRow::get_value_impl(int column, Glib::ValueBase& value) const
238 {
239   model_->get_value_impl(*this, column, value);
240 }
241
242 TreeRow::operator bool() const
243 {
244   return TreeIter::operator bool();
245 }
246
247
248 /**** Gtk::TreeNodeChildren ************************************************/
249
250 TreeNodeChildren::iterator TreeNodeChildren::begin()
251 {
252   iterator iter (model_);
253
254   // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
255   // node.  This behaviour is needed to implement Gtk::TreeModel::children().
256
257   if(gobject_.stamp != 0)
258   {
259     if(!gtk_tree_model_iter_children(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_)))
260     {
261       // Assign the already known parent, in order to create an end iterator.
262       iter.gobject_ = gobject_;
263       iter.is_end_ = true;
264     }
265   }
266   else
267   {
268     if(!gtk_tree_model_get_iter_first(model_->gobj(), iter.gobj()))
269     {
270       // No need to copy the GtkTreeIter, since iter.gobject_ is already empty.
271       iter.is_end_ = true;
272     }
273   }
274
275   return iter;
276 }
277
278 TreeNodeChildren::const_iterator TreeNodeChildren::begin() const
279 {
280   //TODO: Reduce the copy/paste from the non-const begin()?
281   
282   const_iterator iter (model_);
283
284   // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
285   // node.  This behaviour is needed to implement Gtk::TreeModel::children().
286
287   if(gobject_.stamp != 0)
288   {
289     if(!gtk_tree_model_iter_children(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_)))
290     {
291       // Assign the already known parent, in order to create an end iterator.
292       iter.gobject_ = gobject_;
293       iter.is_end_ = true;
294     }
295   }
296   else
297   {
298     if(!gtk_tree_model_get_iter_first(model_->gobj(), iter.gobj()))
299     {
300       // No need to copy the GtkTreeIter, since iter.gobject_ is already empty.
301       iter.is_end_ = true;
302     }
303   }
304
305   return iter;
306 }
307
308 TreeNodeChildren::iterator TreeNodeChildren::end()
309 {
310   // Just copy the parent, and turn it into an end iterator.
311   iterator iter (*this);
312   iter.is_end_ = true;
313   return iter;
314 }
315
316 TreeNodeChildren::const_iterator TreeNodeChildren::end() const
317 {
318   // Just copy the parent, and turn it into an end iterator.
319   const_iterator iter (*this);
320   iter.is_end_ = true;
321   return iter;
322 }
323
324 TreeNodeChildren::value_type TreeNodeChildren::operator[](TreeNodeChildren::size_type index) const
325 {
326   iterator iter (model_);
327
328   GtkTreeIter *const parent = const_cast<GtkTreeIter*>(get_parent_gobject());
329
330   if(!gtk_tree_model_iter_nth_child(model_->gobj(), iter.gobj(), parent, index))
331   {
332     // Assign the already known parent, in order to create an end iterator.
333     iter.gobject_ = gobject_;
334     iter.is_end_ = true;
335   }
336
337   return *iter;
338 }
339
340 TreeNodeChildren::size_type TreeNodeChildren::size() const
341 {
342   GtkTreeIter *const parent = const_cast<GtkTreeIter*>(get_parent_gobject());
343
344   return gtk_tree_model_iter_n_children(model_->gobj(), parent);
345 }
346
347 bool TreeNodeChildren::empty() const
348 {
349   // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
350   // node.  This behaviour is needed to implement Gtk::TreeModel::children().
351
352   if(gobject_.stamp == 0)
353   {
354     GtkTreeIter dummy;
355     return !gtk_tree_model_get_iter_first(model_->gobj(), &dummy);
356   }
357
358   return !gtk_tree_model_iter_has_child(model_->gobj(), const_cast<GtkTreeIter*>(&gobject_));
359 }
360
361 } // namespace Gtk
362
363
364 namespace
365 {
366 } // anonymous namespace
367
368
369 namespace Gtk
370 {
371
372
373 // static
374 GType TreeIterBase::get_type()
375 {
376   return gtk_tree_iter_get_type();
377 }
378
379 TreeIterBase::TreeIterBase()
380 {
381   GLIBMM_INITIALIZE_STRUCT(gobject_, GtkTreeIter);
382 }
383
384 TreeIterBase::TreeIterBase(const GtkTreeIter* gobject)
385 {
386   if(gobject)
387     gobject_ = *gobject;
388   else
389     GLIBMM_INITIALIZE_STRUCT(gobject_, GtkTreeIter);
390 }
391
392
393 } // namespace Gtk
394
395