diff options
Diffstat (limited to 'libs/gtkmm2/gtk/gtkmm/treeiter.cc')
-rw-r--r-- | libs/gtkmm2/gtk/gtkmm/treeiter.cc | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/libs/gtkmm2/gtk/gtkmm/treeiter.cc b/libs/gtkmm2/gtk/gtkmm/treeiter.cc new file mode 100644 index 0000000000..8c355c353d --- /dev/null +++ b/libs/gtkmm2/gtk/gtkmm/treeiter.cc @@ -0,0 +1,395 @@ +// Generated by gtkmmproc -- DO NOT MODIFY! + +#include <gtkmm/treeiter.h> +#include <gtkmm/private/treeiter_p.h> + +// -*- c++ -*- +/* $Id$ */ + +/* Copyright 1998-2002 The gtkmm Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <gtkmm/treemodel.h> + +namespace +{ + +// This is copied from Totem. In future there might be a version in GTK+ itself - see bug # +void gtkmm_gtk_tree_model_iter_previous(GtkTreeModel* tree_model, GtkTreeIter* iter) +{ + GtkTreePath *const path = gtk_tree_model_get_path(tree_model, iter); + + if(gtk_tree_path_prev(path)) + gtk_tree_model_get_iter(tree_model, iter, path); + else + g_assert_not_reached(); + + gtk_tree_path_free(path); +} + +} // anonymous namespace + + +namespace Gtk +{ + +/**** Gtk::TreeIter ********************************************************/ + +TreeIter::TreeIter() +: + TreeIterBase(), + model_ (0), + is_end_ (false) +{} + +TreeIter::TreeIter(TreeModel* model) +: + TreeIterBase(), + model_ (model), + is_end_ (false) +{} + +TreeIter::TreeIter(GtkTreeModel* model, const GtkTreeIter* iter) +: + TreeIterBase(iter), + model_ (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model))), + is_end_ (iter == 0) +{} + +TreeIter& TreeIter::operator++() +{ + g_assert(!is_end_); + + GtkTreeIter previous = gobject_; + + if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_)) + { + is_end_ = true; + gtk_tree_model_iter_parent(model_->gobj(), &gobject_, &previous); + } + + return *this; +} + +const TreeIter TreeIter::operator++(int) +{ + g_assert(!is_end_); + + TreeIter previous (*this); + + if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_)) + { + is_end_ = true; + gtk_tree_model_iter_parent(model_->gobj(), &gobject_, &previous.gobject_); + } + + return previous; +} + +TreeIter& TreeIter::operator--() +{ + if(!is_end_) + { + gtkmm_gtk_tree_model_iter_previous(model_->gobj(), &gobject_); + } + else // --end yields last + { + GtkTreeIter next = gobject_; + GtkTreeIter *const parent = (next.stamp != 0) ? &next : 0; + + const int index = gtk_tree_model_iter_n_children(model_->gobj(), parent) - 1; + is_end_ = !gtk_tree_model_iter_nth_child(model_->gobj(), &gobject_, parent, index); + + g_assert(!is_end_); + } + + return *this; +} + +const TreeIter TreeIter::operator--(int) +{ + TreeIter next (*this); + + if(!is_end_) + { + gtkmm_gtk_tree_model_iter_previous(model_->gobj(), &gobject_); + } + else // --end yields last + { + GtkTreeIter *const parent = (next.gobject_.stamp != 0) ? &next.gobject_ : 0; + + const int index = gtk_tree_model_iter_n_children(model_->gobj(), parent) - 1; + is_end_ = !gtk_tree_model_iter_nth_child(model_->gobj(), &gobject_, parent, index); + + g_assert(!is_end_); + } + + return next; +} + +/* There is no public gtk_tree_iter_equal(), so we must write our own. + */ +bool TreeIter::equal(const TreeIter& other) const +{ + g_assert(model_ == other.model_); + + // A GtkTreeIter has the same stamp value as its model. + g_assert(gobject_.stamp == other.gobject_.stamp || is_end_ || other.is_end_); + + //TODO: Allow custom treemodels to provide a different implementation. + + // If all user_data pointers are equal we can assume the iterators to be + // equal. This should be safe since GtkTreeIter lacks destroy notification, + // thus there is no way to attach more data fields to the iterator. + return (is_end_ == other.is_end_) && + (gobject_.user_data == other.gobject_.user_data) && + (gobject_.user_data2 == other.gobject_.user_data2) && + (gobject_.user_data3 == other.gobject_.user_data3); +} + +TreeIter::operator bool() const +{ + // Test whether the GtkTreeIter is valid and not an end iterator. This check + // is almost the same as the private VALID_ITER() macro in gtkliststore.c and + // gtktreestore.c. + return (!is_end_ && gobject_.stamp != 0); +} + +void TreeIter::setup_end_iterator(const TreeIter& last_valid) +{ + g_assert(model_ == last_valid.model_); + + if(last_valid.is_end_) + gobject_ = last_valid.gobject_; + else + gtk_tree_model_iter_parent(model_->gobj(), &gobject_, const_cast<GtkTreeIter*>(&last_valid.gobject_)); + + is_end_ = true; +} + +void TreeIter::set_model_refptr(const Glib::RefPtr<TreeModel>& model) +{ + model_ = model.operator->(); +} + +void TreeIter::set_model_gobject(GtkTreeModel* model) +{ + model_ = dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model)); +} + +GtkTreeModel* TreeIter::get_model_gobject() const +{ + return (model_) ? model_->gobj() : 0; +} + + +int TreeIter::get_stamp() const +{ + return gobj()->stamp; +} + +void TreeIter::set_stamp(int stamp) +{ + gobj()->stamp = stamp; +} + + +/**** Gtk::TreeRow *********************************************************/ + +const TreeNodeChildren& TreeRow::children() const +{ + g_assert(!is_end_); + + return static_cast<const TreeNodeChildren&>(static_cast<const TreeIter&>(*this)); +} + +TreeIter TreeRow::parent() const +{ + TreeIter iter (model_); + + if(is_end_) + iter.gobject_ = gobject_; + else + gtk_tree_model_iter_parent(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_)); + + return iter; +} + +void TreeRow::set_value_impl(int column, const Glib::ValueBase& value) const +{ + model_->set_value_impl(*this, column, value); +} + +void TreeRow::get_value_impl(int column, Glib::ValueBase& value) const +{ + model_->get_value_impl(*this, column, value); +} + +TreeRow::operator bool() const +{ + return TreeIter::operator bool(); +} + + +/**** Gtk::TreeNodeChildren ************************************************/ + +TreeNodeChildren::iterator TreeNodeChildren::begin() +{ + iterator iter (model_); + + // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel + // node. This behaviour is needed to implement Gtk::TreeModel::children(). + + if(gobject_.stamp != 0) + { + if(!gtk_tree_model_iter_children(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_))) + { + // Assign the already known parent, in order to create an end iterator. + iter.gobject_ = gobject_; + iter.is_end_ = true; + } + } + else + { + if(!gtk_tree_model_get_iter_first(model_->gobj(), iter.gobj())) + { + // No need to copy the GtkTreeIter, since iter.gobject_ is already empty. + iter.is_end_ = true; + } + } + + return iter; +} + +TreeNodeChildren::const_iterator TreeNodeChildren::begin() const +{ + //TODO: Reduce the copy/paste from the non-const begin()? + + const_iterator iter (model_); + + // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel + // node. This behaviour is needed to implement Gtk::TreeModel::children(). + + if(gobject_.stamp != 0) + { + if(!gtk_tree_model_iter_children(model_->gobj(), iter.gobj(), const_cast<GtkTreeIter*>(&gobject_))) + { + // Assign the already known parent, in order to create an end iterator. + iter.gobject_ = gobject_; + iter.is_end_ = true; + } + } + else + { + if(!gtk_tree_model_get_iter_first(model_->gobj(), iter.gobj())) + { + // No need to copy the GtkTreeIter, since iter.gobject_ is already empty. + iter.is_end_ = true; + } + } + + return iter; +} + +TreeNodeChildren::iterator TreeNodeChildren::end() +{ + // Just copy the parent, and turn it into an end iterator. + iterator iter (*this); + iter.is_end_ = true; + return iter; +} + +TreeNodeChildren::const_iterator TreeNodeChildren::end() const +{ + // Just copy the parent, and turn it into an end iterator. + const_iterator iter (*this); + iter.is_end_ = true; + return iter; +} + +TreeNodeChildren::value_type TreeNodeChildren::operator[](TreeNodeChildren::size_type index) const +{ + iterator iter (model_); + + GtkTreeIter *const parent = const_cast<GtkTreeIter*>(get_parent_gobject()); + + if(!gtk_tree_model_iter_nth_child(model_->gobj(), iter.gobj(), parent, index)) + { + // Assign the already known parent, in order to create an end iterator. + iter.gobject_ = gobject_; + iter.is_end_ = true; + } + + return *iter; +} + +TreeNodeChildren::size_type TreeNodeChildren::size() const +{ + GtkTreeIter *const parent = const_cast<GtkTreeIter*>(get_parent_gobject()); + + return gtk_tree_model_iter_n_children(model_->gobj(), parent); +} + +bool TreeNodeChildren::empty() const +{ + // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel + // node. This behaviour is needed to implement Gtk::TreeModel::children(). + + if(gobject_.stamp == 0) + { + GtkTreeIter dummy; + return !gtk_tree_model_get_iter_first(model_->gobj(), &dummy); + } + + return !gtk_tree_model_iter_has_child(model_->gobj(), const_cast<GtkTreeIter*>(&gobject_)); +} + +} // namespace Gtk + + +namespace +{ +} // anonymous namespace + + +namespace Gtk +{ + + +// static +GType TreeIterBase::get_type() +{ + return gtk_tree_iter_get_type(); +} + +TreeIterBase::TreeIterBase() +{ + GLIBMM_INITIALIZE_STRUCT(gobject_, GtkTreeIter); +} + +TreeIterBase::TreeIterBase(const GtkTreeIter* gobject) +{ + if(gobject) + gobject_ = *gobject; + else + GLIBMM_INITIALIZE_STRUCT(gobject_, GtkTreeIter); +} + + +} // namespace Gtk + + |