//------------------------------------------------------------------------------
bool TreeModelWrapper::iter_nth_child_vfunc(const iterator& parent, int n, iterator& iter) const {
  // dprint("%s\n", __FUNCTION__);
  // Sets @a iter to be the child of @a parent using the given index.  The first
  // index is 0.  If @a n is too big, or @a parent has no children, @a iter is set
  // to an invalid iterator and false is returned.
  // See also iter_nth_root_child_vfunc()
  bool ret = false;
  bec::NodeId parent_node(node_for_iter(parent));

  // Invalidate iter_next
  reset_iter(iter);
  if (tm()) {
    if (parent_node.is_valid()) {
      const int children_count = tm()->count_children(parent_node);

      if (n >= 0 && children_count > 0 && n < children_count) {
        bec::NodeId child(tm()->get_child(parent_node, n));
        if (child.is_valid()) {
          init_gtktreeiter(iter.gobj(), child);
          ret = true;
          // dprint("%s(parent->'%s', int n = %i, iter->'%s')\n", __FUNCTION__, parent_node.repr().c_str(), n,
          // child.repr().c_str());
        }
      }
    }
  }
  return ret;
}
//------------------------------------------------------------------------------
bool ListModelWrapper::iter_next_vfunc(const iterator& iter, iterator& iter_next) const
{
  bool ret = false;
  bec::NodeId current_node= node_for_iter(iter);

  //g_message("LMW::iter_next_vfunc: %s", _name.c_str());

  // Invalidate iter_next
  reset_iter(iter_next);

  if (*_tm)
  {
    if (current_node.is_valid() && (*_tm)->has_next(current_node))
    {
      try
      {
        // Obtain parent of the current node to get number of children of the parent node
        current_node = (*_tm)->get_next(current_node);
      }
      catch (...)
      {
        current_node= bec::NodeId();
      }
      // Check if the resulted nodeid is valid and setup iter_next with values pointing to the nodeid
      if ( current_node.is_valid() )
        ret = init_gtktreeiter(iter_next.gobj(), current_node);
    }
  }
  return ret;
}
//------------------------------------------------------------------------------
void ListModelWrapper::set_value_impl(const iterator& row, int column, const Glib::ValueBase& value)
{
  if (!*_tm)
    return;

  bec::NodeId node(node_for_iter(row));

  if ( node.is_valid() )
  {
    const GType type = *(_columns.types() + column);
    column = _columns.ui2bec(column);

    if ( column < 0 )
    {
      if ( !_fake_column_value_setter.empty() )
        _fake_column_value_setter(row, column, type, value);
    }
    else
    {
      switch ( type )
      {
      case G_TYPE_BOOLEAN:
        {
          Glib::Value<bool>   v;
          v.init(value.gobj());
          lmwdprint("LMW::set_value_impl:%s node %s, column %i, value %i\n", _name.c_str(), node.repr().c_str(), column, v.get());
          (*_tm)->set_field(node, column, (ssize_t)v.get());
          break;
        }
      case G_TYPE_INT:
      case G_TYPE_UINT:
        {
          Glib::Value<ssize_t>   v;
          v.init(value.gobj());
          lmwdprint("LMW::set_value_impl: node %s, column %i, value %i\n", node.repr().c_str(), column, v.get());
          (*_tm)->set_field(node, column, v.get());
          break;
        }
      case G_TYPE_FLOAT:
      case G_TYPE_DOUBLE:
        {
          Glib::Value<double>  v;
          v.init(value.gobj());
          (*_tm)->set_field(node, column, v.get());
          break;
        }
      case G_TYPE_STRING:
        {
          Glib::Value<std::string>   v;
          v.init(value.gobj());
          (*_tm)->set_field(node, column, v.get());
          lmwdprint("LMW::set_value: %s '%s'\n", _name.c_str(), v.get().c_str());
          break;
        }
      default:
        break;
      }
    }
  }
}
void TreeModelWrapper::tree_row_expanded(const iterator& iter, const Path& path) {
  if (tm()) {
    if (_expanded_rows)
      _expanded_rows->insert(path.to_string());

    tm()->expand_node(node_for_iter(iter));
  }
}
//------------------------------------------------------------------------------
Gtk::TreeModel::Path ListModelWrapper::get_path_vfunc(const iterator& iter) const {
  const bec::NodeId node = node_for_iter(iter);
  Gtk::TreeModel::Path path;

  if (node.is_valid()) {
    const int node_depth = node.depth();

    for (int i = 0; i < node_depth; i++)
      path.push_back(node[i]);
  }

  return path;
}
Gtk::TreeModel::Path TreeModelWrapper::get_path_vfunc(const iterator& iter) const {
  bec::NodeId node = node_for_iter(iter);
  Gtk::TreeModel::Path path;

  if (node.is_valid()) {
    const int node_depth = node.depth();

    // get path from an iterator. The iterator points to the node, so
    // we have to trim the root node prefix so we have a path to the tree
    for (int i = bec::NodeId(_root_node_path).depth(); i < node_depth; i++)
      path.push_back(node[i]);
  }
  return path;
}
//------------------------------------------------------------------------------
int TreeModelWrapper::iter_n_children_vfunc(const iterator& iter) const {
  if (!_children_count_enabled)
    return 1;

  int ret = 0;

  bec::NodeId node(node_for_iter(iter));

  if (tm() && node.is_valid()) {
    // can't expand here otherwise the live tree will pre-fetch everything when the tree is shown
    if (!_delay_expanding_nodes)
      // need to expand here because otherwise the backend won't know how many children the node has
      tm()->expand_node(node);

    ret = tm()->count_children(node);
  }

  return ret;
}
//------------------------------------------------------------------------------
bool TreeModelWrapper::iter_parent_vfunc(const iterator& child, iterator& iter) const {
  // dprint("%s\n", __FUNCTION__);
  bool ret = false;
  if (tm()) {
    bec::NodeId node(node_for_iter(child));

    if (node.is_valid()) {
      // Make iter (parent would be iterator) invalid from the start, just in case the code below
      // will fail
      reset_iter(iter);

      bec::NodeId would_be_parent(tm()->get_parent(node));
      if (would_be_parent.is_valid()) {
        init_gtktreeiter(iter.gobj(), would_be_parent);
        ret = true;
        // dprint("%s(child->'%s', parent->'%s')\n", __FUNCTION__, bec::NodeId(tm->nodeuid_to_path(uid)).repr().c_str(),
        // would_be_parent.repr().c_str());
      }
    }
  }
  return ret;
}
//------------------------------------------------------------------------------
bool ListModelWrapper::iter_is_valid(const iterator& iter) const {
  bec::NodeId node(node_for_iter(iter));

  return node.is_valid();
}
//------------------------------------------------------------------------------
void ListModelWrapper::get_value_vfunc(const iterator& iter, int column, Glib::ValueBase& value) const {
  if (!*_tm)
    return;

  bec::NodeId node = node_for_iter(iter);

  if (node.is_valid()) {
    const GType type = *(_columns.types() + column);

    column = _columns.ui2bec(column);

    if (column < 0) {
      if (!_fake_column_value_getter.empty())
        _fake_column_value_getter(iter, column, type, value);
    } else if (type == GDK_TYPE_PIXBUF) {
      get_icon_value(iter, column, node, value);
    } else {
      switch (type) {
        case G_TYPE_BOOLEAN: {
          bool bv = false;
          (*_tm)->get_field(node, column, bv);
          set_glib_bool(value, bv);
          lmwdprint("LMW::get_value_vfunc: %s: node %s, col %i: value: %i\n", _name.c_str(), node.repr().c_str(),
                    column, bv);
          break;
        }
        case G_TYPE_INT:
        case G_TYPE_UINT: {
          ssize_t iv = 0;
          (*_tm)->get_field(node, column, iv);
          set_glib_int(value, iv);
          lmwdprint("LMW::get_value_vfunc: %s: node %s, col %i: value: %i\n", _name.c_str(), node.repr().c_str(),
                    column, iv);
          break;
        }
        case G_TYPE_LONG:
        case G_TYPE_ULONG:
        case G_TYPE_INT64:
        case G_TYPE_UINT64: {
          throw std::logic_error("Imlement long ints in get_value_func");
          break;
        }
        case G_TYPE_FLOAT:
        case G_TYPE_DOUBLE: {
          double dv = 0.0;
          (*_tm)->get_field(node, column, dv);
          set_glib_double(value, dv);
          lmwdprint("LMW::get_value_vfunc: %s: node %s, col %i: value: %f\n", _name.c_str(), node.repr().c_str(),
                    column, dv);
          break;
        }
        case G_TYPE_STRING: {
          std::string sv;
          if (column < 0)
            sv = (*_tm)->get_field_description(node, -column);
          else
            (*_tm)->get_field_repr(node, column, sv);
          set_glib_string(value, sv, true);
          lmwdprint("LMW::get_value_vfunc: %s: node %s, col %i: value: '%s'\n", _name.c_str(), node.repr().c_str(),
                    column, sv.c_str());
          break;
        }
        default:
          set_glib_string(value, "<unkn>");
          break;
      }
    }
  }
}