172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/bookmarks/bookmark_tree_model.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gtk/gtk.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_model.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kCellRendererTextKey = "__CELL_RENDERER_TEXT__";
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddSingleNodeToTreeStore(GtkTreeStore* store, const BookmarkNode* node,
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              GtkTreeIter *iter, GtkTreeIter* parent) {
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_store_append(store, iter, parent);
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It would be easy to show a different icon when the folder is open (as they
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // do on Windows, for example), using pixbuf-expander-closed and
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pixbuf-expander-open. Unfortunately there is no GTK_STOCK_OPEN_DIRECTORY
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (and indeed, Nautilus does not render an expanded directory any
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // differently).
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_store_set(store, iter,
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bookmark_utils::FOLDER_ICON, GtkThemeService::GetFolderIcon(true),
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      bookmark_utils::FOLDER_NAME,
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      UTF16ToUTF8(node->GetTitle()).c_str(),
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bookmark_utils::ITEM_ID, node->id(),
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We don't want to use node->is_folder() because that would let the
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // user edit "Bookmarks Bar" and "Other Bookmarks".
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bookmark_utils::IS_EDITABLE, node->type() == BookmarkNode::FOLDER,
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      -1);
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Helper function for CommitTreeStoreDifferencesBetween() which recursively
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// merges changes back from a GtkTreeStore into a tree of BookmarkNodes. This
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// function only works on non-root nodes; our caller handles that special case.
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RecursiveResolve(BookmarkModel* bb_model, const BookmarkNode* bb_node,
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      GtkTreeModel* tree_model, GtkTreeIter* parent_iter,
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      GtkTreePath* selected_path,
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      const BookmarkNode** selected_node) {
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreePath* current_path = gtk_tree_model_get_path(tree_model, parent_iter);
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (gtk_tree_path_compare(current_path, selected_path) == 0)
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *selected_node = bb_node;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_path_free(current_path);
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter child_iter;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (gtk_tree_model_iter_children(tree_model, &child_iter, parent_iter)) {
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    do {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int64 id = bookmark_utils::GetIdFromTreeIter(tree_model, &child_iter);
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      string16 title =
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          bookmark_utils::GetTitleFromTreeIter(tree_model, &child_iter);
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const BookmarkNode* child_bb_node = NULL;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (id == 0) {
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        child_bb_node = bb_model->AddFolder(
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            bb_node, bb_node->child_count(), title);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // Existing node, reset the title (BookmarkModel ignores changes if the
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // title is the same).
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        for (int j = 0; j < bb_node->child_count(); ++j) {
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          const BookmarkNode* node = bb_node->GetChild(j);
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (node->is_folder() && node->id() == id) {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            child_bb_node = node;
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            break;
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK(child_bb_node);
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bb_model->SetTitle(child_bb_node, title);
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      RecursiveResolve(bb_model, child_bb_node,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       tree_model, &child_iter,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       selected_path, selected_node);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } while (gtk_tree_model_iter_next(tree_model, &child_iter));
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Update the folder name in the GtkTreeStore.
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OnFolderNameEdited(GtkCellRendererText* render,
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gchar* path, gchar* new_folder_name, GtkTreeStore* tree_store) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter folder_iter;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreePath* tree_path = gtk_tree_path_new_from_string(path);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gboolean rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store),
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        &folder_iter, tree_path);
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(rv);
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_store_set(tree_store, &folder_iter,
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     bookmark_utils::FOLDER_NAME, new_folder_name,
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     -1);
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_path_free(tree_path);
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace bookmark_utils {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkTreeStore* MakeFolderTreeStore() {
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gtk_tree_store_new(FOLDER_STORE_NUM_COLUMNS, GDK_TYPE_PIXBUF,
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            G_TYPE_STRING, G_TYPE_INT64, G_TYPE_BOOLEAN);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddToTreeStore(BookmarkModel* model, int64 selected_id,
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    GtkTreeStore* store, GtkTreeIter* selected_iter) {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* root_node = model->root_node();
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (int i = 0; i < root_node->child_count(); ++i) {
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddToTreeStoreAt(root_node->GetChild(i), selected_id, store, selected_iter,
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     NULL);
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* MakeTreeViewForStore(GtkTreeStore* store) {
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeViewColumn* column = gtk_tree_view_column_new();
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new();
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_pack_start(column, image_renderer, FALSE);
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_add_attribute(column, image_renderer,
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     "pixbuf", FOLDER_ICON);
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new();
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_renderer, "edited", G_CALLBACK(OnFolderNameEdited),
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   store);
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_attributes(column, text_renderer,
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      "text", FOLDER_NAME,
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      "editable", IS_EDITABLE,
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      NULL);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Let |tree_view| own the store.
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(store);
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_set_data(G_OBJECT(tree_view), kCellRendererTextKey, text_renderer);
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return tree_view;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkCellRenderer* GetCellRendererText(GtkTreeView* tree_view) {
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return static_cast<GtkCellRenderer*>(
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      g_object_get_data(G_OBJECT(tree_view), kCellRendererTextKey));
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddToTreeStoreAt(const BookmarkNode* node, int64 selected_id,
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      GtkTreeStore* store, GtkTreeIter* selected_iter,
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      GtkTreeIter* parent) {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!node->is_folder())
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter iter;
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddSingleNodeToTreeStore(store, node, &iter, parent);
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (selected_iter && node->id() == selected_id) {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     // Save the iterator. Since we're using a GtkTreeStore, we're
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     // guaranteed that the iterator will remain valid as long as the above
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     // appended item exists.
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     *selected_iter = iter;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (int i = 0; i < node->child_count(); ++i) {
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddToTreeStoreAt(node->GetChild(i), selected_id, store, selected_iter,
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     &iter);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* CommitTreeStoreDifferencesBetween(
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BookmarkModel* bb_model, GtkTreeStore* tree_store, GtkTreeIter* selected) {
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node_to_return = NULL;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeModel* tree_model = GTK_TREE_MODEL(tree_store);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreePath* selected_path = gtk_tree_model_get_path(tree_model, selected);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter tree_root;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!gtk_tree_model_get_iter_first(tree_model, &tree_root))
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Impossible missing bookmarks case";
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The top level of this tree is weird and needs to be special cased. The
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // BookmarksNode tree is rooted on a root node while the GtkTreeStore has a
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // set of top level nodes that are the root BookmarksNode's children. These
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // items in the top level are not editable and therefore don't need the extra
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // complexity of trying to modify their title.
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* root_node = bb_model->root_node();
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(GetIdFromTreeIter(tree_model, &tree_root) != 0)
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << "It should be impossible to add another toplevel node";
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int64 id = GetIdFromTreeIter(tree_model, &tree_root);
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* child_node = NULL;
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (int j = 0; j < root_node->child_count(); ++j) {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const BookmarkNode* node = root_node->GetChild(j);
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (node->is_folder() && node->id() == id) {
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        child_node = node;
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(child_node);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkTreeIter child_iter = tree_root;
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    RecursiveResolve(bb_model, child_node, tree_model, &child_iter,
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     selected_path, &node_to_return);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (gtk_tree_model_iter_next(tree_model, &tree_root));
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_path_free(selected_path);
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node_to_return;
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 GetIdFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) {
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GValue value = { 0, };
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 ret_val = -1;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_model_get_value(model, iter, ITEM_ID, &value);
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (G_VALUE_HOLDS_INT64(&value))
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ret_val = g_value_get_int64(&value);
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Impossible type mismatch";
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ret_val;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstring16 GetTitleFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) {
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GValue value = { 0, };
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  string16 ret_val;
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_model_get_value(model, iter, FOLDER_NAME, &value);
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (G_VALUE_HOLDS_STRING(&value)) {
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gchar* utf8str = g_value_get_string(&value);
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret_val = UTF8ToUTF16(utf8str);
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_value_unset(&value);
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Impossible type mismatch";
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ret_val;
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace bookmark_utils
232