diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-05 00:35:09 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-05 00:35:09 +0000 |
commit | 140aea057fa118579380f685f362f2533862b03f (patch) | |
tree | 627c15d8adda34f2c602589e0bac815bbdc7d4d9 /chrome/browser/gtk/bookmark_tree_model.cc | |
parent | 57e3074163dc21bc3bc8cd37dc05f191532d836a (diff) | |
download | chromium_src-140aea057fa118579380f685f362f2533862b03f.zip chromium_src-140aea057fa118579380f685f362f2533862b03f.tar.gz chromium_src-140aea057fa118579380f685f362f2533862b03f.tar.bz2 |
Port the folder selector portion of the BookmarkEditor to GTK.
Mirrors the BookmarkEditorView method, where the contents of BookmarkModel
are copied to a temporary model so changes can be discarded if the user hits
Cancel. In the GTK version, we copy not into another BookmarkModel, but into
a GtkTreeStore, which serves as a model to the GtkTreeView on screen.
Also ports the unit tests.
http://crbug.com/11250
Review URL: http://codereview.chromium.org/99361
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15257 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk/bookmark_tree_model.cc')
-rw-r--r-- | chrome/browser/gtk/bookmark_tree_model.cc | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/chrome/browser/gtk/bookmark_tree_model.cc b/chrome/browser/gtk/bookmark_tree_model.cc new file mode 100644 index 0000000..309a9a1 --- /dev/null +++ b/chrome/browser/gtk/bookmark_tree_model.cc @@ -0,0 +1,161 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/gtk/bookmark_tree_model.h" + +#include <gtk/gtk.h> + +#include "base/string_util.h" +#include "chrome/browser/bookmarks/bookmark_model.h" + +namespace { + +// Helper function for BuildTreeStoreFrom() which recursively inserts data from +// a BookmarkNode tree into a GtkTreeStore. +void RecursiveInsert(BookmarkNode* node, int selected_id, + GtkTreeStore* store, GtkTreeIter* selected_iter, + GtkTreeIter* parent) { + GtkTreeIter iter; + + for (int i = 0; i < node->GetChildCount(); ++i) { + BookmarkNode* child = node->GetChild(i); + if (child->is_folder()) { + gtk_tree_store_append(store, &iter, parent); + gtk_tree_store_set(store, &iter, + 0, WideToUTF8(child->GetTitle()).c_str(), + 1, child->id(), + -1); + if (selected_id && child->id() == selected_id) { + // Save the iterator. Since we're using a GtkTreeStore, we're + // guaranteed that the iterator will remain valid as long as the above + // appended item exists. + *selected_iter = iter; + } + + RecursiveInsert(child, selected_id, store, selected_iter, &iter); + } + } +} + +// Helper function for CommitTreeStoreDifferencesBetween() which recursively +// merges changes back from a GtkTreeStore into a tree of BookmarkNodes. This +// function only works on non-root nodes; our caller handles that special case. +void RecursiveResolve(BookmarkModel* bb_model, BookmarkNode* bb_node, + GtkTreeModel* tree_model, GtkTreeIter* parent_iter, + GtkTreePath* selected_path, + BookmarkNode** selected_node) { + GtkTreePath* current_path = gtk_tree_model_get_path(tree_model, parent_iter); + if (gtk_tree_path_compare(current_path, selected_path) == 0) + *selected_node = bb_node; + gtk_tree_path_free(current_path); + + GtkTreeIter child_iter; + if (gtk_tree_model_iter_children(tree_model, &child_iter, parent_iter)) { + do { + int id = bookmark_utils::GetIdFromTreeIter(tree_model, &child_iter); + std::wstring title = + bookmark_utils::GetTitleFromTreeIter(tree_model, &child_iter); + BookmarkNode* child_bb_node = NULL; + if (id == 0) { + child_bb_node = bb_model->AddGroup(bb_node, bb_node->GetChildCount(), + title); + } else { + // Existing node, reset the title (BBModel ignores changes if the title + // is the same). + for (int j = 0; j < bb_node->GetChildCount(); ++j) { + BookmarkNode* node = bb_node->GetChild(j); + if (node->is_folder() && node->id() == id) { + child_bb_node = node; + break; + } + } + DCHECK(child_bb_node); + bb_model->SetTitle(child_bb_node, title); + } + RecursiveResolve(bb_model, child_bb_node, + tree_model, &child_iter, + selected_path, selected_node); + } while (gtk_tree_model_iter_next(tree_model, &child_iter)); + } +} + +} // namespace + +namespace bookmark_utils { + +void BuildTreeStoreFrom(BookmarkModel* model, int selected_id, + GtkTreeStore** store, GtkTreeIter* selected_iter) { + *store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT); + RecursiveInsert(model->root_node(), selected_id, *store, selected_iter, NULL); +} + +BookmarkNode* CommitTreeStoreDifferencesBetween( + BookmarkModel* bb_model, GtkTreeStore* tree_store, GtkTreeIter* selected) { + BookmarkNode* node_to_return = NULL; + GtkTreeModel* tree_model = GTK_TREE_MODEL(tree_store); + + GtkTreePath* selected_path = gtk_tree_model_get_path(tree_model, selected); + + GtkTreeIter tree_root; + if (!gtk_tree_model_get_iter_first(tree_model, &tree_root)) + NOTREACHED() << "Impossible missing bookmarks case"; + + // The top level of this tree is weird and needs to be special cased. The + // BookmarksNode tree is rooted on a root node while the GtkTreeStore has a + // set of top level nodes that are the root BookmarksNode's children. These + // items in the top level are not editable and therefore don't need the extra + // complexity of trying to modify their title. + BookmarkNode* root_node = bb_model->root_node(); + do { + DCHECK(GetIdFromTreeIter(tree_model, &tree_root) != 0) + << "It should be impossible to add another toplevel node"; + + int id = GetIdFromTreeIter(tree_model, &tree_root); + BookmarkNode* child_node = NULL; + for (int j = 0; j < root_node->GetChildCount(); ++j) { + BookmarkNode* node = root_node->GetChild(j); + if (node->is_folder() && node->id() == id) { + child_node = node; + break; + } + } + DCHECK(child_node); + + GtkTreeIter child_iter = tree_root; + RecursiveResolve(bb_model, child_node, tree_model, &child_iter, + selected_path, &node_to_return); + } while (gtk_tree_model_iter_next(tree_model, &tree_root)); + + gtk_tree_path_free(selected_path); + return node_to_return; +} + +int GetIdFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) { + GValue value = { 0, }; + int ret_val = -1; + gtk_tree_model_get_value(model, iter, 1, &value); + if (G_VALUE_HOLDS_INT(&value)) + ret_val = g_value_get_int(&value); + else + NOTREACHED() << "Impossible type mismatch"; + + return ret_val; +} + +std::wstring GetTitleFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) { + GValue value = { 0, }; + std::wstring ret_val; + gtk_tree_model_get_value(model, iter, 0, &value); + if (G_VALUE_HOLDS_STRING(&value)) { + const gchar* utf8str = g_value_get_string(&value); + ret_val = UTF8ToWide(utf8str); + g_value_unset(&value); + } else { + NOTREACHED() << "Impossible type mismatch"; + } + + return ret_val; +} + +} // namespace bookmark_utils |