[gtkmm] Gtk::TreeIter: Make a real const_iterator



commit 5e420c96f1ce3517295eb15e5425c918174c6730
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Thu Jan 5 12:50:41 2017 +0100

    Gtk::TreeIter: Make a real const_iterator
    
    Rewrite the whole TreeIter class hierarchy, including TreeRow and
    TreeNodeChildren. TreeRow and TreeNodeChildren (a TreeRow container) are no
    longer subclasses of TreeIter. TreeIter is a template class, instantiated as
    TreeIter<TreeRow> and TreeIter<const TreeRow> to get TreeNodeChildren::iterator
    and TreeNodeChildren::const_iterator, a.k.a. TreeModel::iterator and
    TreeModel::const_iterator. Bug #134520

 demos/gtk-demo/demowindow.cc             |    2 +-
 demos/gtk-demo/demowindow.h              |    2 +-
 demos/gtk-demo/example_change_display.cc |    9 +-
 demos/gtk-demo/example_iconview.cc       |    8 +-
 gtk/gtkmm/listviewtext.cc                |   14 +-
 gtk/gtkmm/treeview_private.cc            |    6 +-
 gtk/src/combobox.ccg                     |    2 +-
 gtk/src/comboboxtext.ccg                 |    7 +-
 gtk/src/entrycompletion.ccg              |    2 +-
 gtk/src/iconview.ccg                     |    2 +-
 gtk/src/iconview.hg                      |    2 +-
 gtk/src/liststore.hg                     |    2 +-
 gtk/src/treeiter.ccg                     |  172 ++++++-----
 gtk/src/treeiter.hg                      |  478 ++++++++++++++++++++----------
 gtk/src/treemodel.ccg                    |    4 +-
 gtk/src/treemodel.hg                     |    5 +-
 gtk/src/treemodelfilter.ccg              |    8 +-
 gtk/src/treemodelsort.ccg                |    6 +-
 gtk/src/treemodelsort.hg                 |    2 +-
 gtk/src/treepath.ccg                     |    4 +-
 gtk/src/treesortable.ccg                 |    2 +-
 gtk/src/treesortable.hg                  |    4 +-
 gtk/src/treestore.hg                     |    2 +-
 gtk/src/treeview.ccg                     |    4 +-
 gtk/src/treeview.hg                      |    8 +-
 tools/m4/convert_gtk.m4                  |    2 +-
 26 files changed, 480 insertions(+), 279 deletions(-)
---
diff --git a/demos/gtk-demo/demowindow.cc b/demos/gtk-demo/demowindow.cc
index 26e7e23..dbca1fa 100644
--- a/demos/gtk-demo/demowindow.cc
+++ b/demos/gtk-demo/demowindow.cc
@@ -185,7 +185,7 @@ void DemoWindow::on_treeview_row_activated(const Gtk::TreeModel::Path& path, Gtk
   }
 }
 
-void DemoWindow::run_example(const Gtk::TreeModel::Row& row)
+void DemoWindow::run_example(Gtk::TreeModel::Row& row)
 {
   const DemoColumns& columns = demo_columns();
 
diff --git a/demos/gtk-demo/demowindow.h b/demos/gtk-demo/demowindow.h
index 739ea8d..2cd53bd 100644
--- a/demos/gtk-demo/demowindow.h
+++ b/demos/gtk-demo/demowindow.h
@@ -37,7 +37,7 @@ public:
   ~DemoWindow() override;
 
 protected:
-  void run_example(const Gtk::TreeModel::Row& row);
+  void run_example(Gtk::TreeModel::Row& row);
   void configure_header_bar();
 
   void fill_tree();
diff --git a/demos/gtk-demo/example_change_display.cc b/demos/gtk-demo/example_change_display.cc
index be39f09..43ac50d 100644
--- a/demos/gtk-demo/example_change_display.cc
+++ b/demos/gtk-demo/example_change_display.cc
@@ -194,12 +194,13 @@ void Example_ChangeDisplay::initialize_displays()
 
 void Example_ChangeDisplay::on_display_closed(bool /* is_error */, Glib::RefPtr<Gdk::Display> display)
 {
-  for(auto row : m_refListStore_Display->children())
+  auto children = m_refListStore_Display->children();
+  for (auto iter = children.begin(); iter != children.end(); ++iter)
   {
-    Glib::RefPtr<Gdk::Display> refDisplay = row[m_columns_display.m_display];
-    if(refDisplay == display)
+    Glib::RefPtr<Gdk::Display> refDisplay = (*iter)[m_columns_display.m_display];
+    if (refDisplay == display)
     {
-      m_refListStore_Display->erase(row);
+      m_refListStore_Display->erase(iter);
     }
   }
 }
diff --git a/demos/gtk-demo/example_iconview.cc b/demos/gtk-demo/example_iconview.cc
index 3023377..4a9b009 100644
--- a/demos/gtk-demo/example_iconview.cc
+++ b/demos/gtk-demo/example_iconview.cc
@@ -24,7 +24,7 @@ protected:
   virtual void on_button_home();
   virtual void on_iconview_item_activated(const Gtk::TreeModel::Path& path);
 
-  virtual int on_model_sort(const Gtk::TreeModel::iterator& a, const Gtk::TreeModel::iterator& b);
+  virtual int on_model_sort(const Gtk::TreeModel::const_iterator& a, const Gtk::TreeModel::const_iterator& 
b);
 
   class ModelColumns : public Gtk::TreeModelColumnRecord
   {
@@ -128,14 +128,14 @@ Example_IconView::Example_IconView()
   show_all();
 }
 
-int Example_IconView::on_model_sort(const Gtk::TreeModel::iterator& a, const Gtk::TreeModel::iterator& b)
+int Example_IconView::on_model_sort(const Gtk::TreeModel::const_iterator& a, const 
Gtk::TreeModel::const_iterator& b)
 {
   /* We need this function because we want to sort
    * folders before files.
    */
 
-  Gtk::TreeModel::Row row_a = *a;
-  Gtk::TreeModel::Row row_b = *b;
+  const Gtk::TreeModel::Row row_a = *a;
+  const Gtk::TreeModel::Row row_b = *b;
 
   const bool a_is_dir = row_a[m_columns.is_directory];
   const bool b_is_dir = row_b[m_columns.is_directory];
diff --git a/gtk/gtkmm/listviewtext.cc b/gtk/gtkmm/listviewtext.cc
index 9cd44b6..d8d2844 100644
--- a/gtk/gtkmm/listviewtext.cc
+++ b/gtk/gtkmm/listviewtext.cc
@@ -108,7 +108,7 @@ void ListViewText::insert(guint row, const Glib::ustring& column_one_value)
 {
   g_return_if_fail( row < size() );
 
-  Gtk::ListStore::const_iterator iter = m_model->children()[row];
+  Gtk::ListStore::iterator iter = m_model->children()[row].get_iter();
   Gtk::TreeModel::Row newRow = *(m_model->insert(iter));
 
   if(!column_one_value.empty())
@@ -128,8 +128,8 @@ Glib::ustring ListViewText::get_text(guint row, guint column) const
 
   g_return_val_if_fail( row < size(), result );
 
-  Gtk::TreeModel::iterator iter = m_model->children()[row];
-  iter->get_value(column, result);
+  const Gtk::TreeModel::Row childrow = m_model->children()[row];
+  childrow.get_value(column, result);
 
   return result;
 }
@@ -138,16 +138,16 @@ void ListViewText::set_text(guint row, guint column, const Glib::ustring& value)
 {
   g_return_if_fail( row < size() );
 
-  Gtk::TreeModel::iterator iter = m_model->children()[row];
-  (*iter)->set_value(column, value);
+  Gtk::TreeModel::Row childrow = m_model->children()[row];
+  childrow.set_value(column, value);
 }
 
 void ListViewText::set_text(guint row, const Glib::ustring& value)
 {
   g_return_if_fail( row < size() );
 
-  Gtk::TreeModel::iterator iter = m_model->children()[ row ];
-  (*iter)->set_value(0, value);
+  Gtk::TreeModel::Row childrow = m_model->children()[row];
+  childrow.set_value(0, value);
 }
 
 guint ListViewText::size() const
diff --git a/gtk/gtkmm/treeview_private.cc b/gtk/gtkmm/treeview_private.cc
index 2840a3d..04d73e0 100644
--- a/gtk/gtkmm/treeview_private.cc
+++ b/gtk/gtkmm/treeview_private.cc
@@ -36,8 +36,8 @@ void SignalProxy_CellData_gtk_callback(GtkTreeViewColumn*, GtkCellRenderer* cell
   try
   {
     // use Slot::operator()
-    Gtk::TreeModel::iterator cppiter = TreeIter(model, iter);
-    if(!cppiter->get_model_gobject())
+    Gtk::TreeModel::iterator cppiter = Gtk::TreeModel::iterator(model, iter);
+    if(!cppiter.get_model_gobject())
     {
       g_warning("SignalProxy_CellData_gtk_callback() The cppiter has no model\n");
       return;
@@ -63,7 +63,7 @@ gboolean SignalProxy_RowSeparator_gtk_callback(GtkTreeModel* model, GtkTreeIter*
 
   try
   {
-    return (*the_slot)(Glib::wrap(model, true), Gtk::TreeIter(model, iter));
+    return (*the_slot)(Glib::wrap(model, true), Gtk::TreeModel::iterator(model, iter));
   }
   catch(...)
   {
diff --git a/gtk/src/combobox.ccg b/gtk/src/combobox.ccg
index e8f296b..30ba714 100644
--- a/gtk/src/combobox.ccg
+++ b/gtk/src/combobox.ccg
@@ -62,7 +62,7 @@ TreeModel::iterator ComboBox::get_active()
 
 TreeModel::const_iterator ComboBox::get_active() const
 {
-  Gtk::TreeModel::iterator iter;
+  Gtk::TreeModel::const_iterator iter;
 
   const auto model = get_model();
   if(model)
diff --git a/gtk/src/comboboxtext.ccg b/gtk/src/comboboxtext.ccg
index 3e6bead..b4bb86a 100644
--- a/gtk/src/comboboxtext.ccg
+++ b/gtk/src/comboboxtext.ccg
@@ -33,14 +33,15 @@ void ComboBoxText::set_active_text(const Glib::ustring& text)
   auto model = get_model();
   if(model)
   {
-    for(const auto& row : model->children())
+    auto enditer = model->children().end();
+    for(auto iter = model->children().begin(); iter != enditer; ++iter)
     {
       Glib::ustring this_text;
-      row.get_value(0, this_text);
+      iter->get_value(0, this_text);
 
       if(this_text == text)
       {
-        set_active(row);
+        set_active(iter);
         return; //success
       }
     }
diff --git a/gtk/src/entrycompletion.ccg b/gtk/src/entrycompletion.ccg
index 7c7260e..21f5b43 100644
--- a/gtk/src/entrycompletion.ccg
+++ b/gtk/src/entrycompletion.ccg
@@ -240,7 +240,7 @@ bool Gtk::EntryCompletion::on_match_selected(const TreeModel::iterator& iter)
   );
 
   if(base && base->match_selected)
-    return (*base->match_selected)(gobj(), iter.get_model_gobject(), const_cast<GtkTreeIter*>(iter.gobj()));
+    return (*base->match_selected)(gobj(), const_cast<GtkTreeModel*>(iter.get_model_gobject()), 
const_cast<GtkTreeIter*>(iter.gobj()));
   else
   {
     typedef bool RType;
diff --git a/gtk/src/iconview.ccg b/gtk/src/iconview.ccg
index 8566a0c..9f33975 100644
--- a/gtk/src/iconview.ccg
+++ b/gtk/src/iconview.ccg
@@ -222,7 +222,7 @@ IconView::get_tooltip_context_iter(int& x, int& y,
                                       nullptr,
                                       &src_iter);
 
-  iter = TreeIter(gtk_icon_view_get_model(this->gobj()), &src_iter);
+  iter = Gtk::TreeModel::iterator(gtk_icon_view_get_model(this->gobj()), &src_iter);
 
   return result;
 }
diff --git a/gtk/src/iconview.hg b/gtk/src/iconview.hg
index 15fa51d..3274d6a 100644
--- a/gtk/src/iconview.hg
+++ b/gtk/src/iconview.hg
@@ -380,7 +380,7 @@ public:
    * @param x: the x coordinate (relative to widget coordinates)
    * @param y: the y coordinate (relative to widget coordinates)
    * @param keyboard_tip: whether this is a keyboard tooltip or not
-   * @param iter: a pointer to receive a Gtk::TreeIter
+   * @param iter: a pointer to receive a Gtk::TreeModel::iterator
    *
    * This function is supposed to be used in a Gtk::Widget::query-tooltip
    * signal handler for Gtk::IconView. The x, y and keyboard_tip values
diff --git a/gtk/src/liststore.hg b/gtk/src/liststore.hg
index 3790fef..51929bf 100644
--- a/gtk/src/liststore.hg
+++ b/gtk/src/liststore.hg
@@ -143,7 +143,7 @@ public:
 
   _WRAP_METHOD(void clear(), gtk_list_store_clear)
 
-  _WRAP_METHOD(bool iter_is_valid(const iterator& iter) const, gtk_list_store_iter_is_valid)
+  _WRAP_METHOD(bool iter_is_valid(const const_iterator& iter) const, gtk_list_store_iter_is_valid)
 
 protected:
   void set_value_impl(const iterator& row, int column, const Glib::ValueBase& value) override;
diff --git a/gtk/src/treeiter.ccg b/gtk/src/treeiter.ccg
index d7d7e6a..db3dac4 100644
--- a/gtk/src/treeiter.ccg
+++ b/gtk/src/treeiter.ccg
@@ -22,60 +22,60 @@
 namespace Gtk
 {
 
-/**** Gtk::TreeIter ********************************************************/
+/**** Gtk::TreeIterBase2 ***************************************************/
 
-TreeIter::TreeIter()
+TreeIterBase2::TreeIterBase2()
 :
   TreeIterBase(),
   model_      (nullptr),
   is_end_     (false)
 {}
 
-TreeIter::TreeIter(TreeModel* model)
+TreeIterBase2::TreeIterBase2(TreeModel* model)
 :
   TreeIterBase(),
   model_      (model),
   is_end_     (false)
 {}
 
-TreeIter::TreeIter(GtkTreeModel* model, const GtkTreeIter* iter)
+TreeIterBase2::TreeIterBase2(GtkTreeModel* model, const GtkTreeIter* iter)
 :
   TreeIterBase(iter),
-  model_      (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model))),
+  model_      (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*)model))),
   is_end_     (iter == nullptr)
 {}
 
-TreeIter& TreeIter::operator++()
-{
-  g_assert(!is_end_);
+/**** Gtk::TreeIterBase3 ***************************************************/
 
-  auto previous = gobject_;
+TreeIterBase3::TreeIterBase3()
+:
+  TreeIterBase2()
+{}
 
-  if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_))
-  {
-    is_end_ = true;
-    gtk_tree_model_iter_parent(Glib::unwrap(model_), &gobject_, &previous);
-  }
+TreeIterBase3::TreeIterBase3(TreeModel* model)
+:
+  TreeIterBase2(model)
+{}
 
-  return *this;
-}
+TreeIterBase3::TreeIterBase3(GtkTreeModel* model, const GtkTreeIter* iter)
+:
+  TreeIterBase2(model, iter)
+{}
 
-const TreeIter TreeIter::operator++(int)
+void TreeIterBase3::plus_plus()
 {
   g_assert(!is_end_);
 
-  TreeIter previous (*this);
+  auto previous = gobject_;
 
   if(!gtk_tree_model_iter_next(model_->gobj(), &gobject_))
   {
     is_end_ = true;
-    gtk_tree_model_iter_parent(Glib::unwrap(model_), &gobject_, &previous.gobject_);
+    gtk_tree_model_iter_parent(Glib::unwrap(model_), &gobject_, &previous);
   }
-
-  return previous;
 }
 
-TreeIter& TreeIter::operator--()
+void TreeIterBase3::minus_minus()
 {
   if(!is_end_)
   {
@@ -91,34 +91,11 @@ TreeIter& TreeIter::operator--()
 
     g_assert(!is_end_);
   }
-
-  return *this;
-}
-
-const TreeIter TreeIter::operator--(int)
-{
-  TreeIter next (*this);
-
-  if(!is_end_)
-  {
-    gtk_tree_model_iter_previous(Glib::unwrap(model_), &gobject_);
-  }
-  else // --end yields last
-  {
-    const auto parent = (next.gobject_.stamp != 0) ? &next.gobject_ : nullptr;
-
-    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
+bool TreeIterBase3::equal(const TreeIterBase3& other) const
 {
   g_assert(model_ == other.model_);
 
@@ -134,15 +111,7 @@ bool TreeIter::equal(const TreeIter& other) const
          (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;
-}
-
-void TreeIter::setup_end_iterator(const TreeIter& last_valid)
+void TreeIterBase3::setup_end_iterator(const TreeIterBase3& last_valid)
 {
   g_assert(model_ == last_valid.model_);
 
@@ -154,28 +123,32 @@ void TreeIter::setup_end_iterator(const TreeIter& last_valid)
   is_end_ = true;
 }
 
-void TreeIter::set_model_refptr(const Glib::RefPtr<TreeModel>& model)
+void TreeIterBase3::set_model_refptr(const Glib::RefPtr<TreeModel>& model)
 {
   model_ = model.operator->();
 }
 
-void TreeIter::set_model_gobject(GtkTreeModel* model)
+void TreeIterBase3::set_model_gobject(GtkTreeModel* model)
 {
   model_ = dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) model));
 }
 
-GtkTreeModel* TreeIter::get_model_gobject() const
+GtkTreeModel* TreeIterBase3::get_model_gobject()
 {
   return (model_) ? model_->gobj() : nullptr;
 }
 
+const GtkTreeModel* TreeIterBase3::get_model_gobject() const
+{
+  return (model_) ? model_->gobj() : nullptr;
+}
 
-int TreeIter::get_stamp() const
+int TreeIterBase3::get_stamp() const
 {
   return gobj()->stamp;
 }
 
-void TreeIter::set_stamp(int stamp)
+void TreeIterBase3::set_stamp(int stamp)
 {
   gobj()->stamp = stamp;
 }
@@ -183,16 +156,33 @@ void TreeIter::set_stamp(int stamp)
 
 /**** Gtk::TreeRow *********************************************************/
 
-const TreeNodeChildren& TreeRow::children() const
+TreeNodeChildren& TreeRow::children()
 {
   g_assert(!is_end_);
 
-  return static_cast<const TreeNodeChildren&>(static_cast<const TreeIter&>(*this));
+  return static_cast<TreeNodeChildren&>(static_cast<TreeIterBase2&>(*this));
 }
 
-TreeIter TreeRow::parent() const
+const TreeNodeChildren& TreeRow::children() const
 {
-  TreeIter iter (model_);
+  return const_cast<TreeRow*>(this)->children();
+}
+
+TreeIter<TreeRow> TreeRow::parent()
+{
+  TreeIter<TreeRow> iter(model_);
+
+  if(is_end_)
+    iter.gobject_ = gobject_;
+  else
+    gtk_tree_model_iter_parent(model_->gobj(), iter.gobj(), &gobject_);
+
+  return iter;
+}
+
+TreeIter<const TreeRow> TreeRow::parent() const
+{
+  TreeIter<const TreeRow> iter(model_);
 
   if(is_end_)
     iter.gobject_ = gobject_;
@@ -202,26 +192,39 @@ TreeIter TreeRow::parent() const
   return iter;
 }
 
-void TreeRow::set_value_impl(int column, const Glib::ValueBase& value) const
+TreeIter<TreeRow> TreeRow::get_iter()
 {
-  model_->set_value_impl(*this, column, value);
+  return static_cast<TreeIter<TreeRow>&>(static_cast<TreeIterBase2&>(*this));
+}
+
+TreeIter<const TreeRow> TreeRow::get_iter() const
+{
+  return static_cast<const TreeIter<const TreeRow>&>(static_cast<const TreeIterBase2&>(*this));
+}
+
+void TreeRow::set_value_impl(int column, const Glib::ValueBase& value)
+{
+  model_->set_value_impl(static_cast<TreeIter<TreeRow>&>(static_cast<TreeIterBase2&>(*this)), column, value);
 }
 
 void TreeRow::get_value_impl(int column, Glib::ValueBase& value) const
 {
-  model_->get_value_impl(*this, column, value);
+  model_->get_value_impl(static_cast<const TreeIter<const TreeRow>&>(static_cast<const 
TreeIterBase2&>(*this)), column, value);
 }
 
 TreeRow::operator bool() const
 {
-  return TreeIter::operator bool();
-
+  // 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;
 }
+
 /**** Gtk::TreeNodeChildren ************************************************/
 
 TreeNodeChildren::iterator TreeNodeChildren::begin()
 {
-  iterator iter (model_);
+  iterator iter(model_);
 
   // If the iterator is invalid (stamp == 0), assume a 'virtual' toplevel
   // node.  This behaviour is needed to implement Gtk::TreeModel::children().
@@ -251,7 +254,7 @@ TreeNodeChildren::const_iterator TreeNodeChildren::begin() const
 {
   //TODO: Reduce the copy/paste from the non-const begin()?
 
-  const_iterator iter (model_);
+  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().
@@ -280,7 +283,8 @@ TreeNodeChildren::const_iterator TreeNodeChildren::begin() const
 TreeNodeChildren::iterator TreeNodeChildren::end()
 {
   // Just copy the parent, and turn it into an end iterator.
-  iterator iter (*this);
+  iterator iter(model_);
+  iter.gobject_ = gobject_;
   iter.is_end_ = true;
   return iter;
 }
@@ -288,14 +292,31 @@ TreeNodeChildren::iterator TreeNodeChildren::end()
 TreeNodeChildren::const_iterator TreeNodeChildren::end() const
 {
   // Just copy the parent, and turn it into an end iterator.
-  const_iterator iter (*this);
+  const_iterator iter(model_);
+  iter.gobject_ = gobject_;
   iter.is_end_ = true;
   return iter;
 }
 
-TreeNodeChildren::value_type TreeNodeChildren::operator[](TreeNodeChildren::size_type index) const
+TreeNodeChildren::value_type TreeNodeChildren::operator[](TreeNodeChildren::size_type index)
+{
+  iterator iter(model_);
+
+  const auto 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;
+}
+
+const TreeNodeChildren::value_type TreeNodeChildren::operator[](TreeNodeChildren::size_type index) const
 {
-  iterator iter (model_);
+  const_iterator iter(model_);
 
   const auto parent = const_cast<GtkTreeIter*>(get_parent_gobject());
 
@@ -331,4 +352,3 @@ bool TreeNodeChildren::empty() const
 }
 
 } // namespace Gtk
-
diff --git a/gtk/src/treeiter.hg b/gtk/src/treeiter.hg
index bb0c002..71065b2 100644
--- a/gtk/src/treeiter.hg
+++ b/gtk/src/treeiter.hg
@@ -1,17 +1,17 @@
 /* Copyright(C) 1998-2002 The gtkmm Development Team
  *
- * This library is free software, ) you can redistribute it and/or
+ * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, ) either
- * version 2.1 of the License, or(at your option) any later version.
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library, ) if not, write to the Free Software
+ * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
@@ -20,6 +20,7 @@ _DEFS(gtkmm,gtk)
 
 #include <gtkmm/treemodelcolumn.h>
 #include <iterator>
+#include <type_traits>
 #include <gtk/gtk.h> /* for GtkTreeIter */
 #ifdef GLIBMM_HAVE_SUN_REVERSE_ITERATOR
 #include <cstddef> /* for std::ptrdiff_t */
@@ -29,39 +30,140 @@ namespace Gtk
 {
 
 class TreeModel;
+template <typename T>
+class TreeIter;
 class TreeRow;
 class TreeNodeChildren;
 
-/**
+// Why all the base classes?
+//
+// TreeIterBase2 contains data members that can't be declared in TreeIterBase,
+// because a _CLASS_BOXEDTYPE_STATIC can't contain data members other than
+// the gmmproc-generated GtkTreeIter gobject_.
+//
+// TreeIterBase3 contains those parts of TreeIter<> that does not have to be in
+// the template class.
+
+/** Base of TreeIter, TreeRow and TreeNodeChildren.
+ *
  * @ingroup TreeView
  */
 class TreeIterBase
 {
   _CLASS_BOXEDTYPE_STATIC(TreeIterBase, GtkTreeIter)
   _IGNORE(gtk_tree_iter_copy, gtk_tree_iter_free)
- _NO_WRAP_FUNCTION() //A wrap() for TreeIterBase* wouldn't be very helpful.
+  _NO_WRAP_FUNCTION() // A wrap() for TreeIterBase* wouldn't be very helpful.
 };
 
+/** Base of TreeIter, TreeRow and TreeNodeChildren.
+ *
+ * @ingroup TreeView
+ */
+class TreeIterBase2 : public TreeIterBase
+{
+protected:
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  TreeIterBase2();
+  explicit TreeIterBase2(TreeModel* model); // used in TreeModel methods
+  TreeIterBase2(GtkTreeModel* model, const GtkTreeIter* iter); // used by signal proxies
+
+  // Yes, using a simple TreeModel* rather than Glib::RefPtr<TreeModel>
+  // violates the general policy. But Gtk::TreeIter should have a trivial
+  // copy constructor and assignment operator, i.e. it must contain only
+  // POD (plain old data).
+  //
+  // Gtk::TreeIter is copied a lot, particularly often as return value from
+  // methods. Postfix ++ must return by value, and STL algorithms usually
+  // pass iterators by value, too. With a RefPtr<> as member data, copying
+  // would no longer be trivial, and even cause frequent calls to reference()
+  // and unreference(). That usually doesn't matter much for GUI stuff, but
+  // Gtk::TreeModel is used as a generic container. Imagine a for-loop that
+  // checks whether iter != children.end() on each iteration.
+
+  TreeModel* model_;
+  bool       is_end_;
+
+  // For the conversion and assignment from iterator to const_iterator
+  friend class Gtk::TreeIter<const Gtk::TreeRow>;
+  friend class Gtk::TreeRow;
+  friend class Gtk::TreeNodeChildren;
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+}; // class TreeIterBase2
+
+/** Base of TreeIter.
+ *
+ * Contains the common parts of TreeIter<TreeRow> and TreeIter<const&nbsp;TreeRow>.
+ *
+ * @ingroup TreeView
+ */
+class TreeIterBase3 : public TreeIterBase2
+{
+public:
+
+  bool equal(const TreeIterBase3& other) const;
+
+  /** This is only useful when implementing a custom Gtk::TreeModel class.
+   * Compare the iterator's stamp with your model's stamp to discover whether it is valid.
+   * @see set_stamp().
+   * @result The iterator's stamp.
+   */
+  int get_stamp() const;
+
+  /** This is only useful when implementing a custom Gtk::TreeModel class.
+   * Set the stamp to be equal to your model's stamp, to mark the iterator as valid.
+   * When your model's structure changes, you should increment your model's stamp
+   * to mark all older iterators as invalid. They will be recognised as invalid because
+   * they will then have an incorrect stamp.
+   */
+  void set_stamp(int stamp);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+  void set_model_refptr(const Glib::RefPtr<TreeModel>& model);
+  void set_model_gobject(GtkTreeModel* model);
+  GtkTreeModel* get_model_gobject();
+  const GtkTreeModel* get_model_gobject() const;
+
+  void setup_end_iterator(const TreeIterBase3& last_valid);
+
+  const GtkTreeIter* get_gobject_if_not_end() const
+  { return (!is_end_) ? &gobject_ : nullptr; }
+
+  const GtkTreeIter* get_parent_gobject_if_end() const
+  { return (is_end_ && gobject_.stamp) ? &gobject_ : nullptr; }
+
+protected:
+  TreeIterBase3();
+  explicit TreeIterBase3(TreeModel* model); // used in TreeModel methods
+  TreeIterBase3(GtkTreeModel* model, const GtkTreeIter* iter); // used by signal proxies
+
+  // Common part of operator++() and operator++(int).
+  void plus_plus();
+  // Common part of operator--() and operator--(int).
+  void minus_minus();
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+}; // class TreeIterBase3
 
 // In order to offer STL-like iterator functionality, we cannot wrap
-// GtkTreeIter directly.  Most GTK+ functions that operate on GtkTreeIter
-// are virtual functions in GtkTreeModel.  Therefore, the C++ TreeIter
+// GtkTreeIter directly. Most GTK+ functions that operate on GtkTreeIter
+// are virtual functions in GtkTreeModel. Therefore, the C++ TreeIter
 // must store a pointer to the Gtk::TreeModel to which it belongs.
 //
 // Another problem, which is much worse, is that the GTK+ tree iterator
-// doesn't support the STL-style half-open interval [begin,end).  Instead,
+// doesn't support the STL-style half-open interval [begin,end). Instead,
 // it uses a [first,last] interval, and functions return FALSE to indicate
-// the end was reached.  Also, some functions accept a NULL GtkTreeIter*,
+// the end was reached. Also, some functions accept a NULL GtkTreeIter*,
 // which will be interpreted as the end() iterator.
 //
 // Most of the immense complexity in the Gtk::TreeIter implementation is
-// needed for proper emulation of [begin,end) intervals.  Unfortunately,
+// needed for proper emulation of [begin,end) intervals. Unfortunately,
 // it's not even possible to encapsulate everything in the TreeIter
-// class.  Almost all wrapper methods dealing with GtkTreeIter must be
-// carefully implemented by hand.  TODO: document implementation details
-
-//TODO: Implement a const_iterator too:
-//danielk says that this ConstTreeIter class should return a ConstTreeRow, which would not allow operator=.
+// class. Almost all wrapper methods dealing with GtkTreeIter must be
+// carefully implemented by hand.
+//TODO: document implementation details.
 
 /** A Gtk::TreeModel::iterator is a reference to a specific node on a specific
  * model.
@@ -88,113 +190,78 @@ class TreeIterBase
  * the Gtk::TREE_MODEL_ITERS_PERSIST flag was added to indicate this behaviour -
  * see Gtk::TreeModel::get_flags().
  *
- * Typedefed as Gtk::TreeModel::iterator.
- * The Gtk::TreeModel iterator.
+ * Typedefed as Gtk::TreeModel::iterator and Gtk::TreeModel::const_iterator.
+ *
+ * @tparam T <TreeRow> for an iterator, or <const&nbsp;TreeRow> for a const_iterator.
+ *
  * @ingroup TreeView
  */
-class TreeIter : public TreeIterBase
+template <typename T>
+class TreeIter : public TreeIterBase3
 {
+  static_assert(std::is_same<T, TreeRow>::value || std::is_same<T, const TreeRow>::value,
+                "TreeIter can only iterate over TreeRow or const TreeRow");
+
 public:
-  typedef std::bidirectional_iterator_tag iterator_category;
-  typedef Gtk::TreeRow              value_type;
-  typedef int                       difference_type;
-  typedef const Gtk::TreeRow&       reference;
-  typedef const Gtk::TreeRow*       pointer;
+  using iterator_category = std::bidirectional_iterator_tag;
+  using value_type        = TreeRow;
+  using difference_type   = int;
+  using reference         = T&;
+  using pointer           = T*;
 
   TreeIter();
 
-  TreeIter&      operator++();
-  const TreeIter operator++(int);
+  /// iterator to const_iterator conversion.
+  template <typename T2, typename = typename std::enable_if<!std::is_same<T, T2>::value &&
+    std::is_same<T, const T2>::value, T2>::type>
+  TreeIter(const TreeIter<T2>& src);
+
+  /// iterator to const_iterator assignment.
+  template <typename T2, typename = typename std::enable_if<!std::is_same<T, T2>::value &&
+    std::is_same<T, const T2>::value, T2>::type>
+  TreeIter& operator=(const TreeIter<T2>& src);
 
-  /** Please note that this is very slow compared to operator++().
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  explicit TreeIter(TreeModel* model); // used in TreeModel methods
+  TreeIter(GtkTreeModel* model, const GtkTreeIter* iter); // used by signal proxies
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+  TreeIter& operator++();
+  TreeIter  operator++(int);
+
+  /** Note that this is very slow compared to operator++().
    */
-  TreeIter&      operator--();
+  TreeIter& operator--();
 
-  /** Please note that this is very slow compared to operator++().
+  /** Note that this is very slow compared to operator++(int).
    */
-  const TreeIter operator--(int);
+  TreeIter operator--(int);
 
   inline reference operator*()  const;
   inline pointer   operator->() const;
 
-  bool equal(const TreeIter& other) const;
-
   /** Discover whether the iterator is valid, and not equal to end().
    * For instance,
    * @code
-   * if(treeiter)
-   *   do_something()
+   * if (treeiter)
+   *   do_something();
    * @endcode
    *
    * @newin{3,22}
    */
-  explicit operator bool() const;
-
-  /** This is only useful when implementing a custom Gtk::TreeModel class.
-   * Compare the iterator's stamp with your model's stamp to discover whether it is valid.
-   * @see set_stamp().
-   * @result The iterator's stamp.
-   */
-  int get_stamp() const;
-
-  /** This is only useful when implementing a custom Gtk::TreeModel class.
-   * Set the stamp to be equal to your model's stamp, to mark the iterator as valid.
-   * When your model's structure changes, you should increment your model's stamp
-   * to mark all older iterators as invalid. They will be recognised as invalid because
-   * they will then have an incorrect stamp.
-   */
-  void set_stamp(int stamp);
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-  explicit TreeIter(TreeModel* model); // used in TreeModel methods
-  TreeIter(GtkTreeModel* model, const GtkTreeIter* iter); // used by signal proxies
-
-  void set_model_refptr(const Glib::RefPtr<TreeModel>& model);
-  void set_model_gobject(GtkTreeModel* model);
-  GtkTreeModel* get_model_gobject() const;
-
-  void setup_end_iterator(const TreeIter& last_valid);
-
-  const GtkTreeIter* get_gobject_if_not_end() const
-    { return (!is_end_) ? &gobject_ : nullptr; }
-
-  const GtkTreeIter* get_parent_gobject_if_end() const
-    { return (is_end_ && gobject_.stamp) ? &gobject_ : nullptr; }
-
-protected:
-
-  // Yes, using a simple TreeModel* rather than Glib::RefPtr<TreeModel>
-  // violates the general policy.  But Gtk::TreeIter should have a trivial
-  // copy constructor and assignment operator, i.e. it must contain only
-  // POD (plain old data).
-  //
-  // Gtk::TreeIter is copied a lot, particularly often as return value from
-  // methods.  Postfix ++ must return by value, and STL algorithms usually
-  // pass iterators by value, too.  With a RefPtr<> as member data, copying
-  // would no longer be trivial, and even cause frequent calls to reference()
-  // and unreference().  That usually doesn't matter much for GUI stuff, but
-  // Gtk::TreeModel is used as a generic container.  Imagine a for-loop that
-  // checks whether iter != children.end() on each iteration.
-
-  TreeModel* model_;
-  bool       is_end_;
-
-  friend class Gtk::TreeRow;
-  friend class Gtk::TreeNodeChildren;
-  friend class Gtk::TreeModel;
+  inline explicit operator bool() const;
 
-#endif // DOXYGEN_SHOULD_SKIP_THIS
-};
+}; // class TreeIter<>
 
 /** @relates Gtk::TreeIter */
-inline bool operator==(const TreeIter& lhs, const TreeIter& rhs)
-  { return lhs.equal(rhs); }
+template <typename T>
+inline bool operator==(const TreeIter<T>& lhs, const TreeIter<T>& rhs)
+{ return lhs.equal(rhs); }
 
 /** @relates Gtk::TreeIter */
-inline bool operator!=(const TreeIter& lhs, const TreeIter& rhs)
-  { return !lhs.equal(rhs); }
-
+template <typename T>
+inline bool operator!=(const TreeIter<T>& lhs, const TreeIter<T>& rhs)
+{ return !lhs.equal(rhs); }
 
 template <class ColumnType>
 class TreeValueProxy
@@ -208,26 +275,29 @@ public:
   inline operator ColumnType() const;
 
 private:
-  const TreeRow&                      row_;
-  const TreeModelColumn<ColumnType>&  column_;
+  TreeRow& row_;
+  const TreeModelColumn<ColumnType>& column_;
 
   // no copy assignment
-  TreeValueProxy<ColumnType>& operator=(const TreeValueProxy<ColumnType>&);
+  TreeValueProxy<ColumnType>& operator=(const TreeValueProxy<ColumnType>&) = delete;
 };
 
 
 /** Typedefed as TreeModel::Row.
  *
- * Dereference a TreeModel::iterator to get the Row. Use operator[] or set_value() and get_value() to access 
the
- * values in the columns of this row.
+ * Dereference a TreeModel::iterator to get the Row. Use operator[] or set_value()
+ * and get_value() to access the values in the columns of this row.
+ *
+ * If the model contains a hierarchy of rows (such as Gtk::TreeStore), then you
+ * can access the child rows with children().
  *
- * If the model contains a hierarchy of rows (such as Gtk::TreeStore), then you can access the child rows 
with
- * children().
+ * You can use get_iter() to get an iterator that points to the Row, e.g. for use
+ * in a parameter that takes a const&nbsp;TreeModel::iterator& or a
+ * const&nbsp;TreeModel::const_iterator&.
  *
- * You can use a const TreeModel::Row& for any parameter that takes a const TreeModel::iterator&.
  * @ingroup TreeView
  */
-class TreeRow : public TreeIter //We use public inheritance so that we can cast from a TreeRow to a TreeIter.
+class TreeRow : public TreeIterBase2
 {
 public:
 
@@ -237,10 +307,13 @@ public:
    *
    * This is just a more convenient syntax that does the same thing as set_value() and get_value().
    *
-   * @param column The model column..
+   * @param column The model column.
    */
   template <class ColumnType> inline
-  TreeValueProxy<ColumnType> operator[](const TreeModelColumn<ColumnType>& column) const;
+  TreeValueProxy<ColumnType> operator[](const TreeModelColumn<ColumnType>& column);
+
+  template <class ColumnType> inline
+  const TreeValueProxy<ColumnType> operator[](const TreeModelColumn<ColumnType>& column) const;
 
   /** Sets the value of this @a column of this row.
    * This is a templated method, so the compiler will not allow you to provide an inappropriate type
@@ -252,7 +325,7 @@ public:
    * @param data The new value to use for this column of this row.
    */
   template <class ColumnType>
-  void set_value(const TreeModelColumn<ColumnType>& column, const ColumnType& data) const;
+  void set_value(const TreeModelColumn<ColumnType>& column, const ColumnType& data);
 
   /** Use set_value(const TreeModelColumn<>& column, const ColumnType& data) unless
    * you do not know the column type at compile-time.
@@ -261,7 +334,7 @@ public:
    * @param data The new value to use for this column of this row.
    */
   template <class ColumnType>
-  void set_value(int column, const ColumnType& data) const;
+  void set_value(int column, const ColumnType& data);
 
   /** Gets the value of this @a column of this row.
    * This is a templated method, so the compiler will not allow you to provide an inappropriate type
@@ -287,18 +360,38 @@ public:
   /** This returns an STL-like container API, for iterating over the rows.
    * See also Gtk::TreeModel::children() for the top-level children.
    */
+  TreeNodeChildren& children();
+
+  /** This returns an STL-like container API, for iterating over the rows.
+   * See also Gtk::TreeModel::children() for the top-level children.
+   */
   const TreeNodeChildren& children() const;
 
   /** Gets an iterator to the parent row of this row.
    * @result An iterator to the parent row.
    */
-  TreeIter parent() const;
+  TreeIter<TreeRow> parent();
+
+  /** Gets a const_iterator to the parent row of this row.
+   * @result A const_iterator to the parent row.
+   */
+  TreeIter<const TreeRow> parent() const;
+
+  /** Gets an iterator to this row.
+   * @result An iterator to this row.
+   */
+  TreeIter<TreeRow> get_iter();
+
+  /** Gets a const_iterator to this row.
+   * @result A const_iterator to this row.
+   */
+  TreeIter<const TreeRow> get_iter() const;
 
   /** Discover whether this is a valid row.
    * For instance,
    * @code
-   * if(treerow)
-   *   do_something()
+   * if (treerow)
+   *   do_something();
    * @endcode
    *
    * @newin{3,22}
@@ -306,39 +399,43 @@ public:
   explicit operator bool() const;
 
   /// Provides access to the underlying C GObject.
-  GtkTreeIter*       gobj()       { return TreeIter::gobj(); }
+  GtkTreeIter*       gobj()       { return TreeIterBase::gobj(); }
 
   /// Provides access to the underlying C GObject.
-  const GtkTreeIter* gobj() const { return TreeIter::gobj(); }
+  const GtkTreeIter* gobj() const { return TreeIterBase::gobj(); }
 
 private:
   // Forwarders to Gtk::TreeModel virtual methods.
-  void set_value_impl(int column, const Glib::ValueBase& value) const;
+  void set_value_impl(int column, const Glib::ValueBase& value);
   void get_value_impl(int column, Glib::ValueBase& value) const;
-};
+
+}; // class TreeRow
 
 
 //TODO: Document begin(), end(), size(), etc, in an STL-style way. murrayc.
 
-/** typedefed as TreeModel::Children.
- * Virtual container of TreeModel::Row items.
+/** Virtual container of TreeModel::Row items.
+ *
+ * typedefed as TreeModel::Children.
+ *
  * @ingroup TreeView
  */
-class TreeNodeChildren : public TreeIter
+class TreeNodeChildren : public TreeIterBase2
 {
 public:
-  typedef Gtk::TreeRow  value_type;
-  typedef unsigned int  size_type;
-  typedef int           difference_type;
-  typedef Gtk::TreeIter iterator;
-  typedef Gtk::TreeIter const_iterator; //TODO: Make it a real const_iterator.
+  using value_type      = Gtk::TreeRow;
+  using size_type       = unsigned int;
+  using difference_type = int;
+  using iterator        = Gtk::TreeIter<Gtk::TreeRow>;
+  using const_iterator  = Gtk::TreeIter<const Gtk::TreeRow>;
 
   iterator begin();
   const_iterator begin() const;
   iterator end();
   const_iterator end()   const;
 
-  value_type operator[](size_type index) const;
+  value_type operator[](size_type index);
+  const value_type operator[](size_type index) const;
 
   size_type size() const;
   bool empty() const;
@@ -346,8 +443,8 @@ public:
   /** Discover whether this is a valid TreeNodeChildren.
    * For instance,
    * @code
-   * if(children)
-   *   do_something()
+   * if (children)
+   *   do_something();
    * @endcode
    *
    * @newin{3,22}
@@ -360,38 +457,115 @@ public:
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
   explicit TreeNodeChildren(TreeModel* model)
-    : TreeIter(model) {}
+    : TreeIterBase2(model) {}
 
   const GtkTreeIter* get_parent_gobject() const
     { return (gobject_.stamp != 0) ? &gobject_ : nullptr; }
 
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
-};
+
+}; // class TreeNodeChildren
 
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
 /**** Gtk::TreeIter ********************************************************/
 
-inline
-TreeIter::reference TreeIter::operator*() const
+template <typename T>
+TreeIter<T>::TreeIter()
+:
+  TreeIterBase3()
+{}
+
+template <typename T>
+template <typename T2, typename>
+TreeIter<T>::TreeIter(const TreeIter<T2>& src)
+:
+  TreeIterBase3()
 {
-  return static_cast<const TreeRow&>(*this);
+  gobject_ = src.gobject_;
+  model_   = src.model_;
+  is_end_  = src.is_end_;
 }
 
-inline
-TreeIter::pointer TreeIter::operator->() const
+template <typename T>
+template <typename T2, typename>
+TreeIter<T>& TreeIter<T>::operator=(const TreeIter<T2>& src)
 {
-  return static_cast<const TreeRow*>(this);
+  gobject_ = src.gobject_;
+  model_   = src.model_;
+  is_end_  = src.is_end_;
 }
 
+template <typename T>
+TreeIter<T>::TreeIter(TreeModel* model)
+:
+  TreeIterBase3(model)
+{}
+
+template <typename T>
+TreeIter<T>::TreeIter(GtkTreeModel* model, const GtkTreeIter* iter)
+:
+  TreeIterBase3(model, iter)
+{}
+
+template <typename T> inline
+TreeIter<T>& TreeIter<T>::operator++()
+{
+  plus_plus();
+  return *this;
+}
+
+template <typename T> inline
+TreeIter<T> TreeIter<T>::operator++(int)
+{
+  TreeIter previous(*this);
+  plus_plus();
+  return previous;
+}
+
+template <typename T> inline
+TreeIter<T>& TreeIter<T>::operator--()
+{
+  minus_minus();
+  return *this;
+}
+
+template <typename T> inline
+TreeIter<T> TreeIter<T>::operator--(int)
+{
+  TreeIter next(*this);
+  minus_minus();
+  return next;
+}
+
+template <typename T> inline
+typename TreeIter<T>::reference TreeIter<T>::operator*() const
+{
+  return static_cast<reference>(static_cast<TreeIterBase2&>(const_cast<TreeIter&>(*this)));
+}
+
+template <typename T> inline
+typename TreeIter<T>::pointer TreeIter<T>::operator->() const
+{
+  return static_cast<pointer>(static_cast<TreeIterBase2*>(const_cast<TreeIter*>(this)));
+}
+
+template <typename T> inline
+TreeIter<T>::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;
+}
 
 /**** Gtk::TreeValueProxy<> ************************************************/
 
 template <class ColumnType> inline
 TreeValueProxy<ColumnType>::TreeValueProxy(const TreeRow& row, const TreeModelColumn<ColumnType>& column)
 :
-  row_    (row),
+  row_    (const_cast<TreeRow&>(row)),
   column_ (column)
 {}
 
@@ -412,15 +586,21 @@ TreeValueProxy<ColumnType>::operator ColumnType() const
 /**** Gtk::TreeRow *********************************************************/
 
 template <class ColumnType> inline
-TreeValueProxy<ColumnType> TreeRow::operator[](const TreeModelColumn<ColumnType>& column) const
+const TreeValueProxy<ColumnType> TreeRow::operator[](const TreeModelColumn<ColumnType>& column) const
+{
+  return TreeValueProxy<ColumnType>(*this, column);
+}
+
+template <class ColumnType> inline
+TreeValueProxy<ColumnType> TreeRow::operator[](const TreeModelColumn<ColumnType>& column)
 {
   return TreeValueProxy<ColumnType>(*this, column);
 }
 
 template <class ColumnType>
-void TreeRow::set_value(const TreeModelColumn<ColumnType>& column, const ColumnType& data) const
+void TreeRow::set_value(const TreeModelColumn<ColumnType>& column, const ColumnType& data)
 {
-  typedef typename Gtk::TreeModelColumn<ColumnType>::ValueType ValueType;
+  using ValueType = typename Gtk::TreeModelColumn<ColumnType>::ValueType;
 
   ValueType value;
   value.init(column.type());
@@ -430,13 +610,12 @@ void TreeRow::set_value(const TreeModelColumn<ColumnType>& column, const ColumnT
 }
 
 template <class ColumnType>
-void TreeRow::set_value(int column, const ColumnType& data) const
+void TreeRow::set_value(int column, const ColumnType& data)
 {
-  //This could fail at run-time, because the wrong ColumnType might be used.
-  //It's only for dynamically generated model columns.
+  // This could fail at run-time, because the wrong ColumnType might be used.
+  // It's only for dynamically generated model columns.
 
-  typedef typename Gtk::TreeModelColumn<ColumnType> type_cppcolumn;
-  typedef typename type_cppcolumn::ValueType ValueType;
+  using ValueType = typename Gtk::TreeModelColumn<ColumnType>::ValueType;
 
   ValueType value;
   value.init(ValueType::value_type());
@@ -448,7 +627,7 @@ void TreeRow::set_value(int column, const ColumnType& data) const
 template <class ColumnType>
 ColumnType TreeRow::get_value(const TreeModelColumn<ColumnType>& column) const
 {
-  typedef typename Gtk::TreeModelColumn<ColumnType>::ValueType ValueType;
+  using ValueType = typename Gtk::TreeModelColumn<ColumnType>::ValueType;
 
   ValueType value;
   this->get_value_impl(column.index(), value);
@@ -459,10 +638,10 @@ ColumnType TreeRow::get_value(const TreeModelColumn<ColumnType>& column) const
 template <class ColumnType>
 void TreeRow::get_value(int column, ColumnType& data) const
 {
-  //This could fail at run-time, because the wrong ColumnType might be used.
-  //It's only for dynamically generated model columns.
+  // This could fail at run-time, because the wrong ColumnType might be used.
+  // It's only for dynamically generated model columns.
 
-  typedef typename Gtk::TreeModelColumn<ColumnType>::ValueType ValueType;
+  using ValueType = typename Gtk::TreeModelColumn<ColumnType>::ValueType;
 
   ValueType value;
   this->get_value_impl(column, value);
@@ -473,4 +652,3 @@ void TreeRow::get_value(int column, ColumnType& data) const
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
 } // namespace Gtk
-
diff --git a/gtk/src/treemodel.ccg b/gtk/src/treemodel.ccg
index e52ebc5..5766464 100644
--- a/gtk/src/treemodel.ccg
+++ b/gtk/src/treemodel.ccg
@@ -116,11 +116,11 @@ void TreeModel::set_value_impl(const iterator&, int, const Glib::ValueBase&)
   g_assert_not_reached();
 }
 
-void TreeModel::get_value_impl(const iterator& row, int column, Glib::ValueBase& value) const
+void TreeModel::get_value_impl(const const_iterator& iter, int column, Glib::ValueBase& value) const
 {
   gtk_tree_model_get_value(
       const_cast<GtkTreeModel*>(gobj()),
-      const_cast<GtkTreeIter*>(row.gobj()),
+      const_cast<GtkTreeIter*>(iter.gobj()),
       column, value.gobj());
 }
 
diff --git a/gtk/src/treemodel.hg b/gtk/src/treemodel.hg
index 28684f7..f63b849 100644
--- a/gtk/src/treemodel.hg
+++ b/gtk/src/treemodel.hg
@@ -396,15 +396,14 @@ dnl
    * Row::set_value() work.
    * Your implementation of set_value_impl() should call row_changed() after changing the value.
    */
-  virtual void set_value_impl(const iterator& row, int column, const Glib::ValueBase& value);
+  virtual void set_value_impl(const iterator& iter, int column, const Glib::ValueBase& value);
 
   //This might not need to be virtual, but it's not a big deal. murrayc.
-  virtual void get_value_impl(const iterator& row, int column, Glib::ValueBase& value) const;
+  virtual void get_value_impl(const const_iterator& iter, int column, Glib::ValueBase& value) const;
 
   friend class Gtk::TreeModelFilter;
   friend class Gtk::TreeModelSort;
   friend class Gtk::TreeRow;
-  friend class Gtk::TreeIter;
 };
 
 } // namespace Gtk
diff --git a/gtk/src/treemodelfilter.ccg b/gtk/src/treemodelfilter.ccg
index a229d7f..3c7a073 100644
--- a/gtk/src/treemodelfilter.ccg
+++ b/gtk/src/treemodelfilter.ccg
@@ -53,7 +53,7 @@ static void SignalProxy_Modify_gtk_callback(GtkTreeModel* model, GtkTreeIter* it
     auto column_type = gtk_tree_model_get_column_type(model, column);
     cppValue.init(column_type);
 
-    (*the_slot)( Gtk::TreeModel::const_iterator(model, iter), cppValue, column );
+    (*the_slot)( Gtk::TreeModel::iterator(model, iter), cppValue, column );
 
     //GTK+ has already done this for us: g_value_init(value, column_type);
 
@@ -105,7 +105,7 @@ void TreeModelFilter::set_visible_func(const SlotVisible& slot)
 
 TreeModel::iterator TreeModelFilter::convert_child_iter_to_iter(const iterator& child_iter) const
 {
-  TreeIter filter_iter (const_cast<TreeModelFilter*>(this));
+  iterator filter_iter(const_cast<TreeModelFilter*>(this));
 
   gtk_tree_model_filter_convert_child_iter_to_iter(
       const_cast<GtkTreeModelFilter*>(gobj()), filter_iter.gobj(),
@@ -118,7 +118,7 @@ TreeModel::iterator TreeModelFilter::convert_iter_to_child_iter(const iterator&
 {
   const auto child_model = gtk_tree_model_filter_get_model(const_cast<GtkTreeModelFilter*>(gobj()));
 
-  TreeIter child_iter (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) child_model, false)));
+  iterator child_iter(dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*)child_model, false)));
 
   gtk_tree_model_filter_convert_iter_to_child_iter(
       const_cast<GtkTreeModelFilter*>(gobj()), child_iter.gobj(),
@@ -148,7 +148,7 @@ void TreeModelFilter::set_value_impl(const iterator& row, int column, const Glib
   const auto child_model = dynamic_cast<TreeModel*>(
       Glib::wrap_auto((GObject*) gtk_tree_model_filter_get_model(gobj()), false));
 
-  TreeIter child_iter (child_model);
+  iterator child_iter(child_model);
 
   gtk_tree_model_filter_convert_iter_to_child_iter(
       gobj(), child_iter.gobj(), const_cast<GtkTreeIter*>(row.gobj()));
diff --git a/gtk/src/treemodelsort.ccg b/gtk/src/treemodelsort.ccg
index 4e508c5..e892c7c 100644
--- a/gtk/src/treemodelsort.ccg
+++ b/gtk/src/treemodelsort.ccg
@@ -25,7 +25,7 @@ namespace Gtk
 
 TreeModel::iterator TreeModelSort::convert_child_iter_to_iter(const iterator& child_iter) const
 {
-  TreeIter sorted_iter (const_cast<TreeModelSort*>(this));
+  iterator sorted_iter(const_cast<TreeModelSort*>(this));
 
   gtk_tree_model_sort_convert_child_iter_to_iter(
       const_cast<GtkTreeModelSort*>(gobj()), sorted_iter.gobj(),
@@ -38,7 +38,7 @@ TreeModel::iterator TreeModelSort::convert_iter_to_child_iter(const iterator& so
 {
   const auto child_model = gtk_tree_model_sort_get_model(const_cast<GtkTreeModelSort*>(gobj()));
 
-  TreeIter child_iter (dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) child_model, false)));
+  iterator child_iter(dynamic_cast<TreeModel*>(Glib::wrap_auto((GObject*) child_model, false)));
 
   gtk_tree_model_sort_convert_iter_to_child_iter(
       const_cast<GtkTreeModelSort*>(gobj()), child_iter.gobj(),
@@ -55,7 +55,7 @@ void TreeModelSort::set_value_impl(const iterator& row, int column, const Glib::
   const auto child_model = dynamic_cast<TreeModel*>(
       Glib::wrap_auto((GObject*) gtk_tree_model_sort_get_model(gobj()), false));
 
-  TreeIter child_iter (child_model);
+  iterator child_iter(child_model);
 
   gtk_tree_model_sort_convert_iter_to_child_iter(
       gobj(), child_iter.gobj(), const_cast<GtkTreeIter*>(row.gobj()));
diff --git a/gtk/src/treemodelsort.hg b/gtk/src/treemodelsort.hg
index 4eb9ec5..87042d5 100644
--- a/gtk/src/treemodelsort.hg
+++ b/gtk/src/treemodelsort.hg
@@ -86,7 +86,7 @@ public:
   _WRAP_METHOD(void reset_default_sort_func(), gtk_tree_model_sort_reset_default_sort_func)
   _WRAP_METHOD(void clear_cache(), gtk_tree_model_sort_clear_cache)
 
-  _WRAP_METHOD(bool iter_is_valid(const iterator& iter) const, gtk_tree_model_sort_iter_is_valid)
+  _WRAP_METHOD(bool iter_is_valid(const const_iterator& iter) const, gtk_tree_model_sort_iter_is_valid)
 
   _WRAP_PROPERTY("model", Glib::RefPtr<TreeModel>)
 
diff --git a/gtk/src/treepath.ccg b/gtk/src/treepath.ccg
index 57b7c25..4951df3 100644
--- a/gtk/src/treepath.ccg
+++ b/gtk/src/treepath.ccg
@@ -51,7 +51,9 @@ TreePath::TreePath(const Glib::ustring& path)
 TreePath::TreePath(const TreeModel::iterator& iter)
 :
   // The GtkTreePath* is always newly created.
-  gobject_ (gtk_tree_model_get_path(iter.get_model_gobject(), const_cast<GtkTreeIter*>(iter.gobj())))
+  gobject_(gtk_tree_model_get_path(
+    const_cast<GtkTreeModel*>(iter.get_model_gobject()),
+    const_cast<GtkTreeIter*>(iter.gobj())))
 {
   if (!gobject_)
     gobject_ = gtk_tree_path_new();
diff --git a/gtk/src/treesortable.ccg b/gtk/src/treesortable.ccg
index 31645aa..077f360 100644
--- a/gtk/src/treesortable.ccg
+++ b/gtk/src/treesortable.ccg
@@ -22,7 +22,7 @@ static int SignalProxy_Compare_gtk_callback(GtkTreeModel* model, GtkTreeIter* lh
   try
   {
     // use Slot::operator()
-    return (*the_slot)(Gtk::TreeIter(model, lhs), Gtk::TreeIter(model, rhs));
+    return (*the_slot)(Gtk::TreeModel::const_iterator(model, lhs), Gtk::TreeModel::const_iterator(model, 
rhs));
   }
   catch(...)
   {
diff --git a/gtk/src/treesortable.hg b/gtk/src/treesortable.hg
index 0d21fa8..b8a478c 100644
--- a/gtk/src/treesortable.hg
+++ b/gtk/src/treesortable.hg
@@ -66,9 +66,9 @@ public:
                gtk_tree_sortable_set_sort_column_id)
 
   /** This callback should return -1 if a compares before b, 0 if they compare equal, 1 if a compares after 
b.
-   * For instance, int on_sort_compare(const Gtk::TreeModel::iterator& a, const Gtk::TreeModel::iterator& b);
+   * For instance, int on_sort_compare(const Gtk::TreeModel::const_iterator& a, const 
Gtk::TreeModel::const_iterator& b);
    */
-  typedef sigc::slot<int(const Gtk::TreeModel::iterator&, const Gtk::TreeModel::iterator&)> SlotCompare;
+  typedef sigc::slot<int(const Gtk::TreeModel::const_iterator&, const Gtk::TreeModel::const_iterator&)> 
SlotCompare;
 
   _IGNORE(gtk_tree_sortable_set_sort_func, gtk_tree_sortable_set_default_sort_func)
 
diff --git a/gtk/src/treestore.hg b/gtk/src/treestore.hg
index 1e2adba..303de87 100644
--- a/gtk/src/treestore.hg
+++ b/gtk/src/treestore.hg
@@ -158,7 +158,7 @@ public:
   _WRAP_METHOD(bool is_ancestor(const iterator& iter, const iterator& descendant) const, 
gtk_tree_store_is_ancestor)
   _WRAP_METHOD(int iter_depth(const iterator& iter) const, gtk_tree_store_iter_depth)
 
-  _WRAP_METHOD(bool iter_is_valid(const iterator& iter) const, gtk_tree_store_iter_is_valid)
+  _WRAP_METHOD(bool iter_is_valid(const const_iterator& iter) const, gtk_tree_store_iter_is_valid)
 
 protected:
   void set_value_impl(const iterator& row, int column, const Glib::ValueBase& value) override;
diff --git a/gtk/src/treeview.ccg b/gtk/src/treeview.ccg
index d31eed8..d270f79 100644
--- a/gtk/src/treeview.ccg
+++ b/gtk/src/treeview.ccg
@@ -55,7 +55,7 @@ static gboolean SignalProxy_SearchEqual_gtk_callback(GtkTreeModel* model, int co
 
   try
   {
-    return (*the_slot)(Glib::wrap(model, true), column, key, Gtk::TreeIter(model, iter));
+    return (*the_slot)(Glib::wrap(model, true), column, key, Gtk::TreeModel::const_iterator(model, iter));
   }
   catch(...)
   {
@@ -438,7 +438,7 @@ TreeView::get_tooltip_context_iter(int& x, int& y,
                                       nullptr,
                                       &src_iter);
 
-  iter = TreeIter(gtk_tree_view_get_model(this->gobj()), &src_iter);
+  iter = TreeModel::iterator(gtk_tree_view_get_model(this->gobj()), &src_iter);
 
   return result;
 }
diff --git a/gtk/src/treeview.hg b/gtk/src/treeview.hg
index bbd0d47..d6c23d0 100644
--- a/gtk/src/treeview.hg
+++ b/gtk/src/treeview.hg
@@ -647,8 +647,8 @@ public:
   _WRAP_METHOD(void set_search_column(const TreeModelColumnBase& column), gtk_tree_view_set_search_column)
   _WRAP_METHOD(void set_search_column(int column), gtk_tree_view_set_search_column)
 
-  ///void on_search_equal(const Glib::RefPtr<TreeModel>& model, int column, const Glib::ustring& key, const 
TreeModel::iterator& iter)
-  typedef sigc::slot<bool(const Glib::RefPtr<TreeModel>&, int, const Glib::ustring&, const 
TreeModel::iterator&)> SlotSearchEqual;
+  /// void on_search_equal(const Glib::RefPtr<TreeModel>& model, int column, const Glib::ustring& key, const 
TreeModel::const_iterator& iter)
+  typedef sigc::slot<bool(const Glib::RefPtr<TreeModel>&, int, const Glib::ustring&, const 
TreeModel::const_iterator&)> SlotSearchEqual;
   //SlotSearchEqual get_search_equal_func();
   _IGNORE(gtk_tree_view_get_search_equal_func)
 
@@ -758,7 +758,7 @@ public:
    * @param x: the x coordinate (relative to widget coordinates)
    * @param y: the y coordinate (relative to widget coordinates)
    * @param keyboard_tip: whether this is a keyboard tooltip or not
-   * @param iter: a pointer to receive a Gtk::TreeIter
+   * @param iter: a pointer to receive a Gtk::TreeModel::iterator
    *
    * This function is supposed to be used in a Gtk::Widget::query-tooltip
    * signal handler for Gtk::TreeView. The x, y and keyboard_tip values
@@ -770,7 +770,7 @@ public:
    * tooltips the row returned will be the cursor item. When true, then the
    * iter which has been provided will be set to point to
    * that row and the corresponding model. x and y will always be converted
-   * to be relative to Gtk::TreeView's bin_window if keyboard_tooltip is false.
+   * to be relative to Gtk::TreeView's bin_window if keyboard_tip is false.
    *
    * Return value: whether or not the given tooltip context points to a row.
    *
diff --git a/tools/m4/convert_gtk.m4 b/tools/m4/convert_gtk.m4
index 40e2a39..88b110b 100644
--- a/tools/m4/convert_gtk.m4
+++ b/tools/m4/convert_gtk.m4
@@ -436,10 +436,10 @@ _CONVERSION(`const Glib::RefPtr<EntryBuffer>&',`GtkEntryBuffer*',__CONVERT_REFPT
 _CONVERSION(`const iterator&',`const GtkTreeIter*',__FR2P)
 #_CONVERSION(`const TreeIter&',`GtkTreeIter*',__FCR2P)
 _CONVERSION(`const iterator&',`GtkTreeIter*',__FCR2P)
+_CONVERSION(`const const_iterator&',`GtkTreeIter*',__FCR2P)
 _CONVERSION(`const TreeModel::Row&',`GtkTreeIter*',__FCR2P)
 _CONVERSION(`iterator&',`GtkTreeIter*',__FR2P)
 _CONVERSION(`const TreeModel::iterator&',`GtkTreeIter*',__FCR2P)
-_CONVERSION(`const iterator&',`GtkTreeIter*',__FCR2P)
 _CONVERSION(`TreeViewColumn&',`GtkTreeViewColumn*',__FR2P)
 _CONVERSION(`GtkTreeViewColumn*',`TreeViewColumn*',`Glib::wrap($3)')
 _CONVERSION(`GtkTreeViewColumn*',`const TreeViewColumn*',`Glib::wrap($3)')


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]