//------------------------------------------------------------------------------
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;
}
//------------------------------------------------------------------------------
Index::Index(GtkTreeIter* it, const bec::NodeId& node)
      : _raw_data((char *)it)
      , _ext(0)
{
  //memset(_raw_data, 0xff, sizeof(*it));
  //*_raw_data = 0;
  reset_iter(it);

  const int depth = node.depth();

  const Mode m = (depth < MaxDepth) ? (depth == 1 ? ListNode : Internal) : External;
  mode(m);

  if (m == External)
  {
    const std::string nrepr = node.toString();
    std::pair<ExternalMap::iterator, bool> res = _ext_map.insert(nrepr);
    _ext = const_cast<std::string*>(&(*(res.first)));
    it->user_data = (void*)_ext;
  }
  else if (m == Internal)
  {
    for (int i = 0; i < depth; ++i)
      word(i, node[i]);
  }
  else if (m == ListNode)
  {
    it->user_data = (void*)(intptr_t)(node[0]);
  }
}
//------------------------------------------------------------------------------
bool ListModelWrapper::get_iter_vfunc(const Path& path, iterator& iter) const {
  bool ret = false;
  GtkTreeIter* it = iter.gobj();

  // Invalidate iter_next
  reset_iter(iter);

  if (*_tm) {
    bec::NodeId node(path.to_string());

    if (node.is_valid() && node.back() < (*_tm)->count())
      ret = init_gtktreeiter(it, 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;
}