Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: chrome/browser/gtk/gtk_tree.cc

Issue 6251001: Move chrome/browser/gtk/ to chrome/browser/ui/gtk/... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/gtk/gtk_tree.h ('k') | chrome/browser/gtk/gtk_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/gtk/gtk_tree.h"
6
7 #include "app/table_model.h"
8 #include "base/logging.h"
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/gtk/gtk_theme_provider.h"
11 #include "gfx/gtk_util.h"
12 #include "third_party/skia/include/core/SkBitmap.h"
13
14 namespace gtk_tree {
15
16 gint GetRowNumForPath(GtkTreePath* path) {
17 gint* indices = gtk_tree_path_get_indices(path);
18 if (!indices) {
19 NOTREACHED();
20 return -1;
21 }
22 return indices[0];
23 }
24
25 gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter) {
26 GtkTreePath* path = gtk_tree_model_get_path(model, iter);
27 int row = GetRowNumForPath(path);
28 gtk_tree_path_free(path);
29 return row;
30 }
31
32 gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model,
33 GtkTreePath* sort_path) {
34 GtkTreePath *child_path = gtk_tree_model_sort_convert_path_to_child_path(
35 GTK_TREE_MODEL_SORT(sort_model), sort_path);
36 int row = GetRowNumForPath(child_path);
37 gtk_tree_path_free(child_path);
38 return row;
39 }
40
41 void SelectAndFocusRowNum(int row, GtkTreeView* tree_view) {
42 GtkTreeModel* model = gtk_tree_view_get_model(tree_view);
43 if (!model) {
44 NOTREACHED();
45 return;
46 }
47 GtkTreeIter iter;
48 if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) {
49 NOTREACHED();
50 return;
51 }
52 GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
53 gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE);
54 gtk_tree_path_free(path);
55 }
56
57 bool RemoveRecursively(GtkTreeStore* tree_store, GtkTreeIter* iter) {
58 GtkTreeIter child;
59 if (gtk_tree_model_iter_children(GTK_TREE_MODEL(tree_store), &child, iter)) {
60 while (true) {
61 if (!RemoveRecursively(tree_store, &child))
62 break;
63 }
64 }
65 return gtk_tree_store_remove(tree_store, iter);
66 }
67
68 void GetSelectedIndices(GtkTreeSelection* selection, std::set<int>* out) {
69 GList* list = gtk_tree_selection_get_selected_rows(
70 selection, NULL);
71 GList* node;
72 for (node = list; node != NULL; node = node->next) {
73 out->insert(
74 gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(node->data)));
75 }
76 g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
77 g_list_free(list);
78 }
79
80 ////////////////////////////////////////////////////////////////////////////////
81 // TableAdapter
82
83 TableAdapter::TableAdapter(Delegate* delegate, GtkListStore* list_store,
84 TableModel* table_model)
85 : delegate_(delegate), list_store_(list_store), table_model_(table_model) {
86 if (table_model)
87 table_model->SetObserver(this);
88 }
89
90 void TableAdapter::SetModel(TableModel* table_model) {
91 table_model_ = table_model;
92 table_model_->SetObserver(this);
93 }
94
95 bool TableAdapter::IsGroupRow(GtkTreeIter* iter) const {
96 if (!table_model_->HasGroups())
97 return false;
98 gboolean is_header = false;
99 gboolean is_separator = false;
100 gtk_tree_model_get(GTK_TREE_MODEL(list_store_),
101 iter,
102 COL_IS_HEADER,
103 &is_header,
104 COL_IS_SEPARATOR,
105 &is_separator,
106 -1);
107 return is_header || is_separator;
108 }
109
110 static int OffsetForGroupIndex(size_t group_index) {
111 // Every group consists of a header and a separator row, and there is a blank
112 // row between groups.
113 return 3 * group_index + 2;
114 }
115
116 void TableAdapter::MapListStoreIndicesToModelRows(
117 const std::set<int>& list_store_indices,
118 RemoveRowsTableModel::Rows* model_rows) {
119 if (!table_model_->HasGroups()) {
120 for (std::set<int>::const_iterator it = list_store_indices.begin();
121 it != list_store_indices.end();
122 ++it) {
123 model_rows->insert(*it);
124 }
125 return;
126 }
127
128 const TableModel::Groups& groups = table_model_->GetGroups();
129 TableModel::Groups::const_iterator group_it = groups.begin();
130 for (std::set<int>::const_iterator list_store_it = list_store_indices.begin();
131 list_store_it != list_store_indices.end();
132 ++list_store_it) {
133 int list_store_index = *list_store_it;
134 GtkTreeIter iter;
135 bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
136 &iter,
137 NULL,
138 list_store_index);
139 if (!rv) {
140 NOTREACHED();
141 return;
142 }
143 int group = -1;
144 gtk_tree_model_get(GTK_TREE_MODEL(list_store_),
145 &iter,
146 COL_GROUP_ID,
147 &group,
148 -1);
149 while (group_it->id != group) {
150 ++group_it;
151 if (group_it == groups.end()) {
152 NOTREACHED();
153 return;
154 }
155 }
156 int offset = OffsetForGroupIndex(group_it - groups.begin());
157 model_rows->insert(list_store_index - offset);
158 }
159 }
160
161 int TableAdapter::GetListStoreIndexForModelRow(int model_row) const {
162 if (!table_model_->HasGroups())
163 return model_row;
164 int group = table_model_->GetGroupID(model_row);
165 const TableModel::Groups& groups = table_model_->GetGroups();
166 for (TableModel::Groups::const_iterator it = groups.begin();
167 it != groups.end(); ++it) {
168 if (it->id == group) {
169 return model_row + OffsetForGroupIndex(it - groups.begin());
170 }
171 }
172 NOTREACHED();
173 return -1;
174 }
175
176 void TableAdapter::AddNodeToList(int row) {
177 GtkTreeIter iter;
178 int list_store_index = GetListStoreIndexForModelRow(row);
179 if (list_store_index == 0) {
180 gtk_list_store_prepend(list_store_, &iter);
181 } else {
182 GtkTreeIter sibling;
183 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling, NULL,
184 list_store_index - 1);
185 gtk_list_store_insert_after(list_store_, &iter, &sibling);
186 }
187
188 if (table_model_->HasGroups()) {
189 gtk_list_store_set(list_store_,
190 &iter,
191 COL_WEIGHT, PANGO_WEIGHT_NORMAL,
192 COL_WEIGHT_SET, TRUE,
193 COL_GROUP_ID, table_model_->GetGroupID(row),
194 -1);
195 }
196 delegate_->SetColumnValues(row, &iter);
197 }
198
199 void TableAdapter::OnModelChanged() {
200 delegate_->OnAnyModelUpdateStart();
201 gtk_list_store_clear(list_store_);
202 delegate_->OnModelChanged();
203
204 if (table_model_->HasGroups()) {
205 const TableModel::Groups& groups = table_model_->GetGroups();
206 for (TableModel::Groups::const_iterator it = groups.begin();
207 it != groups.end(); ++it) {
208 GtkTreeIter iter;
209 if (it != groups.begin()) {
210 // Blank row between groups.
211 gtk_list_store_append(list_store_, &iter);
212 gtk_list_store_set(list_store_, &iter, COL_IS_HEADER, TRUE, -1);
213 }
214 // Group title.
215 gtk_list_store_append(list_store_, &iter);
216 gtk_list_store_set(list_store_,
217 &iter,
218 COL_WEIGHT,
219 PANGO_WEIGHT_BOLD,
220 COL_WEIGHT_SET,
221 TRUE,
222 COL_TITLE,
223 UTF16ToUTF8(it->title).c_str(),
224 COL_IS_HEADER,
225 TRUE,
226 -1);
227 // Group separator.
228 gtk_list_store_append(list_store_, &iter);
229 gtk_list_store_set(list_store_,
230 &iter,
231 COL_IS_HEADER,
232 TRUE,
233 COL_IS_SEPARATOR,
234 TRUE,
235 -1);
236 }
237 }
238
239 for (int i = 0; i < table_model_->RowCount(); ++i)
240 AddNodeToList(i);
241 delegate_->OnAnyModelUpdate();
242 }
243
244 void TableAdapter::OnItemsChanged(int start, int length) {
245 if (length == 0)
246 return;
247 delegate_->OnAnyModelUpdateStart();
248 int list_store_index = GetListStoreIndexForModelRow(start);
249 GtkTreeIter iter;
250 bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
251 &iter,
252 NULL,
253 list_store_index);
254 for (int i = 0; i < length; ++i) {
255 if (!rv) {
256 NOTREACHED();
257 return;
258 }
259 while (IsGroupRow(&iter)) {
260 rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
261 if (!rv) {
262 NOTREACHED();
263 return;
264 }
265 }
266 delegate_->SetColumnValues(start + i, &iter);
267 rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
268 }
269 delegate_->OnAnyModelUpdate();
270 }
271
272 void TableAdapter::OnItemsAdded(int start, int length) {
273 delegate_->OnAnyModelUpdateStart();
274 for (int i = 0; i < length; ++i) {
275 AddNodeToList(start + i);
276 }
277 delegate_->OnAnyModelUpdate();
278 }
279
280 void TableAdapter::OnItemsRemoved(int start, int length) {
281 if (length == 0)
282 return;
283 delegate_->OnAnyModelUpdateStart();
284 // When this method is called, the model has already removed the items, so
285 // accessing items in the model from |start| on may not be possible anymore.
286 // Therefore we use the item right before that, if it exists.
287 int list_store_index = 0;
288 if (start > 0)
289 list_store_index = GetListStoreIndexForModelRow(start - 1) + 1;
290 GtkTreeIter iter;
291 bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
292 &iter,
293 NULL,
294 list_store_index);
295 if (!rv) {
296 NOTREACHED();
297 return;
298 }
299 for (int i = 0; i < length; ++i) {
300 while (IsGroupRow(&iter)) {
301 rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
302 if (!rv) {
303 NOTREACHED();
304 return;
305 }
306 }
307 gtk_list_store_remove(list_store_, &iter);
308 }
309 delegate_->OnAnyModelUpdate();
310 }
311
312 // static
313 gboolean TableAdapter::OnCheckRowIsSeparator(GtkTreeModel* model,
314 GtkTreeIter* iter,
315 gpointer user_data) {
316 gboolean is_separator;
317 gtk_tree_model_get(model,
318 iter,
319 COL_IS_SEPARATOR,
320 &is_separator,
321 -1);
322 return is_separator;
323 }
324
325 // static
326 gboolean TableAdapter::OnSelectionFilter(GtkTreeSelection* selection,
327 GtkTreeModel* model,
328 GtkTreePath* path,
329 gboolean path_currently_selected,
330 gpointer user_data) {
331 GtkTreeIter iter;
332 if (!gtk_tree_model_get_iter(model, &iter, path)) {
333 NOTREACHED();
334 return TRUE;
335 }
336 gboolean is_header;
337 gtk_tree_model_get(model, &iter, COL_IS_HEADER, &is_header, -1);
338 return !is_header;
339 }
340
341 ////////////////////////////////////////////////////////////////////////////////
342 // TreeAdapter
343
344 TreeAdapter::TreeAdapter(Delegate* delegate, TreeModel* tree_model)
345 : delegate_(delegate),
346 tree_model_(tree_model) {
347 tree_store_ = gtk_tree_store_new(COL_COUNT,
348 GDK_TYPE_PIXBUF,
349 G_TYPE_STRING,
350 G_TYPE_POINTER);
351 tree_model->AddObserver(this);
352
353 std::vector<SkBitmap> icons;
354 tree_model->GetIcons(&icons);
355 for (size_t i = 0; i < icons.size(); ++i) {
356 pixbufs_.push_back(gfx::GdkPixbufFromSkBitmap(&icons[i]));
357 }
358 }
359
360 TreeAdapter::~TreeAdapter() {
361 g_object_unref(tree_store_);
362 for (size_t i = 0; i < pixbufs_.size(); ++i)
363 g_object_unref(pixbufs_[i]);
364 }
365
366 void TreeAdapter::Init() {
367 gtk_tree_store_clear(tree_store_);
368 Fill(NULL, tree_model_->GetRoot());
369 }
370
371
372 TreeModelNode* TreeAdapter::GetNode(GtkTreeIter* iter) {
373 TreeModelNode* node;
374 gtk_tree_model_get(GTK_TREE_MODEL(tree_store_), iter,
375 COL_NODE_PTR, &node,
376 -1);
377 return node;
378 }
379
380 void TreeAdapter::FillRow(GtkTreeIter* iter, TreeModelNode* node) {
381 GdkPixbuf* pixbuf = NULL;
382 int icon_index = tree_model_->GetIconIndex(node);
383 if (icon_index >= 0 && icon_index < static_cast<int>(pixbufs_.size()))
384 pixbuf = pixbufs_[icon_index];
385 else
386 pixbuf = GtkThemeProvider::GetFolderIcon(true);
387 gtk_tree_store_set(tree_store_, iter,
388 COL_ICON, pixbuf,
389 COL_TITLE, UTF16ToUTF8(node->GetTitle()).c_str(),
390 COL_NODE_PTR, node,
391 -1);
392 }
393
394 void TreeAdapter::Fill(GtkTreeIter* parent_iter, TreeModelNode* parent_node) {
395 if (parent_iter)
396 FillRow(parent_iter, parent_node);
397 GtkTreeIter iter;
398 int child_count = tree_model_->GetChildCount(parent_node);
399 for (int i = 0; i < child_count; ++i) {
400 TreeModelNode* node = tree_model_->GetChild(parent_node, i);
401 gtk_tree_store_append(tree_store_, &iter, parent_iter);
402 Fill(&iter, node);
403 }
404 }
405
406 GtkTreePath* TreeAdapter::GetTreePath(TreeModelNode* node) {
407 GtkTreePath* path = gtk_tree_path_new();
408 TreeModelNode* parent = node;
409 while (parent) {
410 parent = tree_model_->GetParent(parent);
411 if (parent) {
412 int idx = tree_model_->IndexOfChild(parent, node);
413 gtk_tree_path_prepend_index(path, idx);
414 node = parent;
415 }
416 }
417 return path;
418 }
419
420 bool TreeAdapter::GetTreeIter(TreeModelNode* node, GtkTreeIter* iter) {
421 GtkTreePath* path = GetTreePath(node);
422 bool rv = false;
423 // Check the path ourselves since gtk_tree_model_get_iter prints a warning if
424 // given an empty path. The path will be empty when it points to the root
425 // node and we are using SetRootShown(false).
426 if (gtk_tree_path_get_depth(path) > 0)
427 rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), iter, path);
428 gtk_tree_path_free(path);
429 return rv;
430 }
431
432 void TreeAdapter::TreeNodesAdded(TreeModel* model,
433 TreeModelNode* parent,
434 int start,
435 int count) {
436 delegate_->OnAnyModelUpdateStart();
437 GtkTreeIter parent_iter;
438 GtkTreeIter* parent_iter_ptr = NULL;
439 GtkTreeIter iter;
440 if (GetTreeIter(parent, &parent_iter))
441 parent_iter_ptr = &parent_iter;
442 for (int i = 0; i < count; ++i) {
443 gtk_tree_store_insert(tree_store_, &iter, parent_iter_ptr, start + i);
444 Fill(&iter, tree_model_->GetChild(parent, start + i));
445 }
446 delegate_->OnAnyModelUpdate();
447 }
448
449 void TreeAdapter::TreeNodesRemoved(TreeModel* model,
450 TreeModelNode* parent,
451 int start,
452 int count) {
453 delegate_->OnAnyModelUpdateStart();
454 GtkTreeIter iter;
455 GtkTreePath* path = GetTreePath(parent);
456 gtk_tree_path_append_index(path, start);
457 gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), &iter, path);
458 gtk_tree_path_free(path);
459 for (int i = 0; i < count; ++i) {
460 RemoveRecursively(tree_store_, &iter);
461 }
462 delegate_->OnAnyModelUpdate();
463 }
464
465 void TreeAdapter::TreeNodeChanged(TreeModel* model, TreeModelNode* node) {
466 delegate_->OnAnyModelUpdateStart();
467 GtkTreeIter iter;
468 if (GetTreeIter(node, &iter))
469 FillRow(&iter, node);
470 delegate_->OnAnyModelUpdate();
471 }
472
473 } // namespace gtk_tree
OLDNEW
« no previous file with comments | « chrome/browser/gtk/gtk_tree.h ('k') | chrome/browser/gtk/gtk_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698