Index: chrome/browser/gtk/gtk_tree.cc |
=================================================================== |
--- chrome/browser/gtk/gtk_tree.cc (revision 71352) |
+++ chrome/browser/gtk/gtk_tree.cc (working copy) |
@@ -1,473 +0,0 @@ |
-// Copyright (c) 2010 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/gtk_tree.h" |
- |
-#include "app/table_model.h" |
-#include "base/logging.h" |
-#include "base/utf_string_conversions.h" |
-#include "chrome/browser/gtk/gtk_theme_provider.h" |
-#include "gfx/gtk_util.h" |
-#include "third_party/skia/include/core/SkBitmap.h" |
- |
-namespace gtk_tree { |
- |
-gint GetRowNumForPath(GtkTreePath* path) { |
- gint* indices = gtk_tree_path_get_indices(path); |
- if (!indices) { |
- NOTREACHED(); |
- return -1; |
- } |
- return indices[0]; |
-} |
- |
-gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter) { |
- GtkTreePath* path = gtk_tree_model_get_path(model, iter); |
- int row = GetRowNumForPath(path); |
- gtk_tree_path_free(path); |
- return row; |
-} |
- |
-gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model, |
- GtkTreePath* sort_path) { |
- GtkTreePath *child_path = gtk_tree_model_sort_convert_path_to_child_path( |
- GTK_TREE_MODEL_SORT(sort_model), sort_path); |
- int row = GetRowNumForPath(child_path); |
- gtk_tree_path_free(child_path); |
- return row; |
-} |
- |
-void SelectAndFocusRowNum(int row, GtkTreeView* tree_view) { |
- GtkTreeModel* model = gtk_tree_view_get_model(tree_view); |
- if (!model) { |
- NOTREACHED(); |
- return; |
- } |
- GtkTreeIter iter; |
- if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) { |
- NOTREACHED(); |
- return; |
- } |
- GtkTreePath* path = gtk_tree_model_get_path(model, &iter); |
- gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE); |
- gtk_tree_path_free(path); |
-} |
- |
-bool RemoveRecursively(GtkTreeStore* tree_store, GtkTreeIter* iter) { |
- GtkTreeIter child; |
- if (gtk_tree_model_iter_children(GTK_TREE_MODEL(tree_store), &child, iter)) { |
- while (true) { |
- if (!RemoveRecursively(tree_store, &child)) |
- break; |
- } |
- } |
- return gtk_tree_store_remove(tree_store, iter); |
-} |
- |
-void GetSelectedIndices(GtkTreeSelection* selection, std::set<int>* out) { |
- GList* list = gtk_tree_selection_get_selected_rows( |
- selection, NULL); |
- GList* node; |
- for (node = list; node != NULL; node = node->next) { |
- out->insert( |
- gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(node->data))); |
- } |
- g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); |
- g_list_free(list); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// TableAdapter |
- |
-TableAdapter::TableAdapter(Delegate* delegate, GtkListStore* list_store, |
- TableModel* table_model) |
- : delegate_(delegate), list_store_(list_store), table_model_(table_model) { |
- if (table_model) |
- table_model->SetObserver(this); |
-} |
- |
-void TableAdapter::SetModel(TableModel* table_model) { |
- table_model_ = table_model; |
- table_model_->SetObserver(this); |
-} |
- |
-bool TableAdapter::IsGroupRow(GtkTreeIter* iter) const { |
- if (!table_model_->HasGroups()) |
- return false; |
- gboolean is_header = false; |
- gboolean is_separator = false; |
- gtk_tree_model_get(GTK_TREE_MODEL(list_store_), |
- iter, |
- COL_IS_HEADER, |
- &is_header, |
- COL_IS_SEPARATOR, |
- &is_separator, |
- -1); |
- return is_header || is_separator; |
-} |
- |
-static int OffsetForGroupIndex(size_t group_index) { |
- // Every group consists of a header and a separator row, and there is a blank |
- // row between groups. |
- return 3 * group_index + 2; |
-} |
- |
-void TableAdapter::MapListStoreIndicesToModelRows( |
- const std::set<int>& list_store_indices, |
- RemoveRowsTableModel::Rows* model_rows) { |
- if (!table_model_->HasGroups()) { |
- for (std::set<int>::const_iterator it = list_store_indices.begin(); |
- it != list_store_indices.end(); |
- ++it) { |
- model_rows->insert(*it); |
- } |
- return; |
- } |
- |
- const TableModel::Groups& groups = table_model_->GetGroups(); |
- TableModel::Groups::const_iterator group_it = groups.begin(); |
- for (std::set<int>::const_iterator list_store_it = list_store_indices.begin(); |
- list_store_it != list_store_indices.end(); |
- ++list_store_it) { |
- int list_store_index = *list_store_it; |
- GtkTreeIter iter; |
- bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), |
- &iter, |
- NULL, |
- list_store_index); |
- if (!rv) { |
- NOTREACHED(); |
- return; |
- } |
- int group = -1; |
- gtk_tree_model_get(GTK_TREE_MODEL(list_store_), |
- &iter, |
- COL_GROUP_ID, |
- &group, |
- -1); |
- while (group_it->id != group) { |
- ++group_it; |
- if (group_it == groups.end()) { |
- NOTREACHED(); |
- return; |
- } |
- } |
- int offset = OffsetForGroupIndex(group_it - groups.begin()); |
- model_rows->insert(list_store_index - offset); |
- } |
-} |
- |
-int TableAdapter::GetListStoreIndexForModelRow(int model_row) const { |
- if (!table_model_->HasGroups()) |
- return model_row; |
- int group = table_model_->GetGroupID(model_row); |
- const TableModel::Groups& groups = table_model_->GetGroups(); |
- for (TableModel::Groups::const_iterator it = groups.begin(); |
- it != groups.end(); ++it) { |
- if (it->id == group) { |
- return model_row + OffsetForGroupIndex(it - groups.begin()); |
- } |
- } |
- NOTREACHED(); |
- return -1; |
-} |
- |
-void TableAdapter::AddNodeToList(int row) { |
- GtkTreeIter iter; |
- int list_store_index = GetListStoreIndexForModelRow(row); |
- if (list_store_index == 0) { |
- gtk_list_store_prepend(list_store_, &iter); |
- } else { |
- GtkTreeIter sibling; |
- gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling, NULL, |
- list_store_index - 1); |
- gtk_list_store_insert_after(list_store_, &iter, &sibling); |
- } |
- |
- if (table_model_->HasGroups()) { |
- gtk_list_store_set(list_store_, |
- &iter, |
- COL_WEIGHT, PANGO_WEIGHT_NORMAL, |
- COL_WEIGHT_SET, TRUE, |
- COL_GROUP_ID, table_model_->GetGroupID(row), |
- -1); |
- } |
- delegate_->SetColumnValues(row, &iter); |
-} |
- |
-void TableAdapter::OnModelChanged() { |
- delegate_->OnAnyModelUpdateStart(); |
- gtk_list_store_clear(list_store_); |
- delegate_->OnModelChanged(); |
- |
- if (table_model_->HasGroups()) { |
- const TableModel::Groups& groups = table_model_->GetGroups(); |
- for (TableModel::Groups::const_iterator it = groups.begin(); |
- it != groups.end(); ++it) { |
- GtkTreeIter iter; |
- if (it != groups.begin()) { |
- // Blank row between groups. |
- gtk_list_store_append(list_store_, &iter); |
- gtk_list_store_set(list_store_, &iter, COL_IS_HEADER, TRUE, -1); |
- } |
- // Group title. |
- gtk_list_store_append(list_store_, &iter); |
- gtk_list_store_set(list_store_, |
- &iter, |
- COL_WEIGHT, |
- PANGO_WEIGHT_BOLD, |
- COL_WEIGHT_SET, |
- TRUE, |
- COL_TITLE, |
- UTF16ToUTF8(it->title).c_str(), |
- COL_IS_HEADER, |
- TRUE, |
- -1); |
- // Group separator. |
- gtk_list_store_append(list_store_, &iter); |
- gtk_list_store_set(list_store_, |
- &iter, |
- COL_IS_HEADER, |
- TRUE, |
- COL_IS_SEPARATOR, |
- TRUE, |
- -1); |
- } |
- } |
- |
- for (int i = 0; i < table_model_->RowCount(); ++i) |
- AddNodeToList(i); |
- delegate_->OnAnyModelUpdate(); |
-} |
- |
-void TableAdapter::OnItemsChanged(int start, int length) { |
- if (length == 0) |
- return; |
- delegate_->OnAnyModelUpdateStart(); |
- int list_store_index = GetListStoreIndexForModelRow(start); |
- GtkTreeIter iter; |
- bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), |
- &iter, |
- NULL, |
- list_store_index); |
- for (int i = 0; i < length; ++i) { |
- if (!rv) { |
- NOTREACHED(); |
- return; |
- } |
- while (IsGroupRow(&iter)) { |
- rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter); |
- if (!rv) { |
- NOTREACHED(); |
- return; |
- } |
- } |
- delegate_->SetColumnValues(start + i, &iter); |
- rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter); |
- } |
- delegate_->OnAnyModelUpdate(); |
-} |
- |
-void TableAdapter::OnItemsAdded(int start, int length) { |
- delegate_->OnAnyModelUpdateStart(); |
- for (int i = 0; i < length; ++i) { |
- AddNodeToList(start + i); |
- } |
- delegate_->OnAnyModelUpdate(); |
-} |
- |
-void TableAdapter::OnItemsRemoved(int start, int length) { |
- if (length == 0) |
- return; |
- delegate_->OnAnyModelUpdateStart(); |
- // When this method is called, the model has already removed the items, so |
- // accessing items in the model from |start| on may not be possible anymore. |
- // Therefore we use the item right before that, if it exists. |
- int list_store_index = 0; |
- if (start > 0) |
- list_store_index = GetListStoreIndexForModelRow(start - 1) + 1; |
- GtkTreeIter iter; |
- bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), |
- &iter, |
- NULL, |
- list_store_index); |
- if (!rv) { |
- NOTREACHED(); |
- return; |
- } |
- for (int i = 0; i < length; ++i) { |
- while (IsGroupRow(&iter)) { |
- rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter); |
- if (!rv) { |
- NOTREACHED(); |
- return; |
- } |
- } |
- gtk_list_store_remove(list_store_, &iter); |
- } |
- delegate_->OnAnyModelUpdate(); |
-} |
- |
-// static |
-gboolean TableAdapter::OnCheckRowIsSeparator(GtkTreeModel* model, |
- GtkTreeIter* iter, |
- gpointer user_data) { |
- gboolean is_separator; |
- gtk_tree_model_get(model, |
- iter, |
- COL_IS_SEPARATOR, |
- &is_separator, |
- -1); |
- return is_separator; |
-} |
- |
-// static |
-gboolean TableAdapter::OnSelectionFilter(GtkTreeSelection* selection, |
- GtkTreeModel* model, |
- GtkTreePath* path, |
- gboolean path_currently_selected, |
- gpointer user_data) { |
- GtkTreeIter iter; |
- if (!gtk_tree_model_get_iter(model, &iter, path)) { |
- NOTREACHED(); |
- return TRUE; |
- } |
- gboolean is_header; |
- gtk_tree_model_get(model, &iter, COL_IS_HEADER, &is_header, -1); |
- return !is_header; |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// TreeAdapter |
- |
-TreeAdapter::TreeAdapter(Delegate* delegate, TreeModel* tree_model) |
- : delegate_(delegate), |
- tree_model_(tree_model) { |
- tree_store_ = gtk_tree_store_new(COL_COUNT, |
- GDK_TYPE_PIXBUF, |
- G_TYPE_STRING, |
- G_TYPE_POINTER); |
- tree_model->AddObserver(this); |
- |
- std::vector<SkBitmap> icons; |
- tree_model->GetIcons(&icons); |
- for (size_t i = 0; i < icons.size(); ++i) { |
- pixbufs_.push_back(gfx::GdkPixbufFromSkBitmap(&icons[i])); |
- } |
-} |
- |
-TreeAdapter::~TreeAdapter() { |
- g_object_unref(tree_store_); |
- for (size_t i = 0; i < pixbufs_.size(); ++i) |
- g_object_unref(pixbufs_[i]); |
-} |
- |
-void TreeAdapter::Init() { |
- gtk_tree_store_clear(tree_store_); |
- Fill(NULL, tree_model_->GetRoot()); |
-} |
- |
- |
-TreeModelNode* TreeAdapter::GetNode(GtkTreeIter* iter) { |
- TreeModelNode* node; |
- gtk_tree_model_get(GTK_TREE_MODEL(tree_store_), iter, |
- COL_NODE_PTR, &node, |
- -1); |
- return node; |
-} |
- |
-void TreeAdapter::FillRow(GtkTreeIter* iter, TreeModelNode* node) { |
- GdkPixbuf* pixbuf = NULL; |
- int icon_index = tree_model_->GetIconIndex(node); |
- if (icon_index >= 0 && icon_index < static_cast<int>(pixbufs_.size())) |
- pixbuf = pixbufs_[icon_index]; |
- else |
- pixbuf = GtkThemeProvider::GetFolderIcon(true); |
- gtk_tree_store_set(tree_store_, iter, |
- COL_ICON, pixbuf, |
- COL_TITLE, UTF16ToUTF8(node->GetTitle()).c_str(), |
- COL_NODE_PTR, node, |
- -1); |
-} |
- |
-void TreeAdapter::Fill(GtkTreeIter* parent_iter, TreeModelNode* parent_node) { |
- if (parent_iter) |
- FillRow(parent_iter, parent_node); |
- GtkTreeIter iter; |
- int child_count = tree_model_->GetChildCount(parent_node); |
- for (int i = 0; i < child_count; ++i) { |
- TreeModelNode* node = tree_model_->GetChild(parent_node, i); |
- gtk_tree_store_append(tree_store_, &iter, parent_iter); |
- Fill(&iter, node); |
- } |
-} |
- |
-GtkTreePath* TreeAdapter::GetTreePath(TreeModelNode* node) { |
- GtkTreePath* path = gtk_tree_path_new(); |
- TreeModelNode* parent = node; |
- while (parent) { |
- parent = tree_model_->GetParent(parent); |
- if (parent) { |
- int idx = tree_model_->IndexOfChild(parent, node); |
- gtk_tree_path_prepend_index(path, idx); |
- node = parent; |
- } |
- } |
- return path; |
-} |
- |
-bool TreeAdapter::GetTreeIter(TreeModelNode* node, GtkTreeIter* iter) { |
- GtkTreePath* path = GetTreePath(node); |
- bool rv = false; |
- // Check the path ourselves since gtk_tree_model_get_iter prints a warning if |
- // given an empty path. The path will be empty when it points to the root |
- // node and we are using SetRootShown(false). |
- if (gtk_tree_path_get_depth(path) > 0) |
- rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), iter, path); |
- gtk_tree_path_free(path); |
- return rv; |
-} |
- |
-void TreeAdapter::TreeNodesAdded(TreeModel* model, |
- TreeModelNode* parent, |
- int start, |
- int count) { |
- delegate_->OnAnyModelUpdateStart(); |
- GtkTreeIter parent_iter; |
- GtkTreeIter* parent_iter_ptr = NULL; |
- GtkTreeIter iter; |
- if (GetTreeIter(parent, &parent_iter)) |
- parent_iter_ptr = &parent_iter; |
- for (int i = 0; i < count; ++i) { |
- gtk_tree_store_insert(tree_store_, &iter, parent_iter_ptr, start + i); |
- Fill(&iter, tree_model_->GetChild(parent, start + i)); |
- } |
- delegate_->OnAnyModelUpdate(); |
-} |
- |
-void TreeAdapter::TreeNodesRemoved(TreeModel* model, |
- TreeModelNode* parent, |
- int start, |
- int count) { |
- delegate_->OnAnyModelUpdateStart(); |
- GtkTreeIter iter; |
- GtkTreePath* path = GetTreePath(parent); |
- gtk_tree_path_append_index(path, start); |
- gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), &iter, path); |
- gtk_tree_path_free(path); |
- for (int i = 0; i < count; ++i) { |
- RemoveRecursively(tree_store_, &iter); |
- } |
- delegate_->OnAnyModelUpdate(); |
-} |
- |
-void TreeAdapter::TreeNodeChanged(TreeModel* model, TreeModelNode* node) { |
- delegate_->OnAnyModelUpdateStart(); |
- GtkTreeIter iter; |
- if (GetTreeIter(node, &iter)) |
- FillRow(&iter, node); |
- delegate_->OnAnyModelUpdate(); |
-} |
- |
-} // namespace gtk_tree |