summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk/gtk_tree.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/gtk/gtk_tree.cc')
-rw-r--r--chrome/browser/gtk/gtk_tree.cc213
1 files changed, 196 insertions, 17 deletions
diff --git a/chrome/browser/gtk/gtk_tree.cc b/chrome/browser/gtk/gtk_tree.cc
index 5594c58..744a4a6 100644
--- a/chrome/browser/gtk/gtk_tree.cc
+++ b/chrome/browser/gtk/gtk_tree.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -92,17 +92,107 @@ void TableAdapter::SetModel(TableModel* 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;
- if (row == 0) {
+ 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,
- row - 1);
+ 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);
}
@@ -110,21 +200,69 @@ 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,
+ WideToUTF8(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, start);
+ 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);
}
@@ -140,20 +278,66 @@ void TableAdapter::OnItemsAdded(int start, int length) {
}
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, start);
+ 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) {
- if (!rv) {
- NOTREACHED();
- return;
+ while (IsGroupRow(&iter)) {
+ rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
+ if (!rv) {
+ NOTREACHED();
+ return;
+ }
}
- rv = gtk_list_store_remove(list_store_, &iter);
+ 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
@@ -202,7 +386,7 @@ void TreeAdapter::FillRow(GtkTreeIter* iter, TreeModelNode* node) {
pixbuf = GtkThemeProvider::GetFolderIcon(true);
gtk_tree_store_set(tree_store_, iter,
COL_ICON, pixbuf,
- COL_TITLE, WideToUTF8(node->GetTitle()).c_str(),
+ COL_TITLE, UTF16ToUTF8(node->GetTitle()).c_str(),
COL_NODE_PTR, node,
-1);
}
@@ -278,11 +462,6 @@ void TreeAdapter::TreeNodesRemoved(TreeModel* model,
delegate_->OnAnyModelUpdate();
}
-void TreeAdapter::TreeNodeChildrenReordered(TreeModel* model,
- TreeModelNode* parent) {
- NOTIMPLEMENTED();
-}
-
void TreeAdapter::TreeNodeChanged(TreeModel* model, TreeModelNode* node) {
delegate_->OnAnyModelUpdateStart();
GtkTreeIter iter;