This source file includes following definitions.
- AddSingleNodeToTreeStore
- RecursiveResolve
- OnFolderNameEdited
- MakeFolderTreeStore
- AddToTreeStore
- MakeTreeViewForStore
- GetCellRendererText
- AddToTreeStoreAt
- CommitTreeStoreDifferencesBetween
- GetIdFromTreeIter
- GetTitleFromTreeIter
#include "chrome/browser/ui/gtk/bookmarks/bookmark_tree_model.h"
#include <gtk/gtk.h>
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "ui/gfx/image/image.h"
namespace {
const char* kCellRendererTextKey = "__CELL_RENDERER_TEXT__";
void AddSingleNodeToTreeStore(GtkTreeStore* store, const BookmarkNode* node,
GtkTreeIter *iter, GtkTreeIter* parent) {
gtk_tree_store_append(store, iter, parent);
gtk_tree_store_set(store,
iter,
FOLDER_ICON,
GtkThemeService::GetFolderIcon(true).ToGdkPixbuf(),
FOLDER_NAME,
base::UTF16ToUTF8(node->GetTitle()).c_str(),
ITEM_ID,
node->id(),
IS_EDITABLE,
node->type() == BookmarkNode::FOLDER,
-1);
}
void RecursiveResolve(BookmarkModel* bb_model,
const BookmarkNode* bb_node,
GtkTreeStore* tree_store,
GtkTreeIter* parent_iter,
GtkTreePath* selected_path,
const BookmarkNode** selected_node) {
GtkTreePath* current_path =
gtk_tree_model_get_path(GTK_TREE_MODEL(tree_store), 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(GTK_TREE_MODEL(tree_store), &child_iter,
parent_iter)) {
do {
int64 id = GetIdFromTreeIter(GTK_TREE_MODEL(tree_store), &child_iter);
base::string16 title =
GetTitleFromTreeIter(GTK_TREE_MODEL(tree_store), &child_iter);
const BookmarkNode* child_bb_node = NULL;
if (id == 0) {
child_bb_node = bb_model->AddFolder(
bb_node, bb_node->child_count(), title);
GValue value = { 0 };
g_value_init(&value, G_TYPE_INT64);
g_value_set_int64(&value, child_bb_node->id());
gtk_tree_store_set_value(tree_store, &child_iter, ITEM_ID, &value);
} else {
for (int j = 0; j < bb_node->child_count(); ++j) {
const 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_store, &child_iter,
selected_path, selected_node);
} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(tree_store), &child_iter));
}
}
void OnFolderNameEdited(GtkCellRendererText* render,
gchar* path, gchar* new_folder_name, GtkTreeStore* tree_store) {
GtkTreeIter folder_iter;
GtkTreePath* tree_path = gtk_tree_path_new_from_string(path);
gboolean rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store),
&folder_iter, tree_path);
DCHECK(rv);
gtk_tree_store_set(
tree_store, &folder_iter, FOLDER_NAME, new_folder_name, -1);
gtk_tree_path_free(tree_path);
}
}
GtkTreeStore* MakeFolderTreeStore() {
return gtk_tree_store_new(FOLDER_STORE_NUM_COLUMNS, GDK_TYPE_PIXBUF,
G_TYPE_STRING, G_TYPE_INT64, G_TYPE_BOOLEAN);
}
void AddToTreeStore(BookmarkModel* model, int64 selected_id,
GtkTreeStore* store, GtkTreeIter* selected_iter) {
const BookmarkNode* root_node = model->root_node();
for (int i = 0; i < root_node->child_count(); ++i) {
const BookmarkNode* child = root_node->GetChild(i);
if (child->IsVisible())
AddToTreeStoreAt(child, selected_id, store, selected_iter, NULL);
}
}
GtkWidget* MakeTreeViewForStore(GtkTreeStore* store) {
GtkTreeViewColumn* column = gtk_tree_view_column_new();
GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(column, image_renderer, FALSE);
gtk_tree_view_column_add_attribute(column, image_renderer,
"pixbuf", FOLDER_ICON);
GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new();
g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
g_signal_connect(text_renderer, "edited", G_CALLBACK(OnFolderNameEdited),
store);
gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
gtk_tree_view_column_set_attributes(column, text_renderer,
"text", FOLDER_NAME,
"editable", IS_EDITABLE,
NULL);
GtkWidget* tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
g_object_unref(store);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
g_object_set_data(G_OBJECT(tree_view), kCellRendererTextKey, text_renderer);
return tree_view;
}
GtkCellRenderer* GetCellRendererText(GtkTreeView* tree_view) {
return static_cast<GtkCellRenderer*>(
g_object_get_data(G_OBJECT(tree_view), kCellRendererTextKey));
}
void AddToTreeStoreAt(const BookmarkNode* node, int64 selected_id,
GtkTreeStore* store, GtkTreeIter* selected_iter,
GtkTreeIter* parent) {
if (!node->is_folder())
return;
GtkTreeIter iter;
AddSingleNodeToTreeStore(store, node, &iter, parent);
if (selected_iter && node->id() == selected_id) {
*selected_iter = iter;
}
for (int i = 0; i < node->child_count(); ++i) {
AddToTreeStoreAt(node->GetChild(i), selected_id, store, selected_iter,
&iter);
}
}
const BookmarkNode* CommitTreeStoreDifferencesBetween(
BookmarkModel* bb_model, GtkTreeStore* tree_store, GtkTreeIter* selected) {
const 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";
const BookmarkNode* root_node = bb_model->root_node();
do {
DCHECK(GetIdFromTreeIter(tree_model, &tree_root) != 0)
<< "It should be impossible to add another toplevel node";
int64 id = GetIdFromTreeIter(tree_model, &tree_root);
const BookmarkNode* child_node = NULL;
for (int j = 0; j < root_node->child_count(); ++j) {
const 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_store, &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;
}
int64 GetIdFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) {
GValue value = { 0, };
int64 ret_val = -1;
gtk_tree_model_get_value(model, iter, ITEM_ID, &value);
if (G_VALUE_HOLDS_INT64(&value))
ret_val = g_value_get_int64(&value);
else
NOTREACHED() << "Impossible type mismatch";
return ret_val;
}
base::string16 GetTitleFromTreeIter(GtkTreeModel* model, GtkTreeIter* iter) {
GValue value = { 0, };
base::string16 ret_val;
gtk_tree_model_get_value(model, iter, FOLDER_NAME, &value);
if (G_VALUE_HOLDS_STRING(&value)) {
const gchar* utf8str = g_value_get_string(&value);
ret_val = base::UTF8ToUTF16(utf8str);
g_value_unset(&value);
} else {
NOTREACHED() << "Impossible type mismatch";
}
return ret_val;
}