[evolution/gnome-2-28] Bug 599882 - Crash in em_folder_tree_select_prev_path() when wrapping to bottom
- From: Matthew Barnes <mbarnes src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [evolution/gnome-2-28] Bug 599882 - Crash in em_folder_tree_select_prev_path() when wrapping to bottom
- Date: Wed, 28 Oct 2009 19:40:46 +0000 (UTC)
commit 91e0696b738ecc991f8b6c33442040de4fec1873
Author: Matthew Barnes <mbarnes redhat com>
Date: Wed Oct 28 15:28:58 2009 -0400
Bug 599882 - Crash in em_folder_tree_select_prev_path() when wrapping to bottom
Also fixes a whole bunch of memory leaks caused by unfreed strings and
unfreed GtkTreePaths.
mail/em-folder-tree.c | 131 ++++++++++++++++++++++++++++++------------------
1 files changed, 82 insertions(+), 49 deletions(-)
---
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index b13a47a..3c56967 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -2421,31 +2421,55 @@ em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders)
return;
}
-static GtkTreeIter
-get_last_child (GtkTreeModel *model, GtkTreeIter *iter)
-{
- GtkTreeIter *child = g_new0 (GtkTreeIter, 1);
- gboolean has_child = gtk_tree_model_iter_has_child (model, iter);
-
- if (gtk_tree_model_iter_next (model, iter)) {
- return get_last_child (model, iter);
- } else if (has_child) {
- /* Pick the last one */
- gint nchildren = gtk_tree_model_iter_n_children (model, iter);
- gtk_tree_model_iter_nth_child ( model, child, iter, nchildren-1);
- return get_last_child (model, child);
+static gboolean
+folder_tree_descend (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreeIter *root)
+{
+ GtkTreeIter parent;
+ gint n_children;
+
+ /* Finds the rightmost descendant of the given root. */
+
+ if (root == NULL) {
+ n_children = gtk_tree_model_iter_n_children (model, NULL);
+
+ /* This will invalidate the iterator and return FALSE. */
+ if (n_children == 0)
+ return gtk_tree_model_get_iter_first (model, iter);
+
+ gtk_tree_model_iter_nth_child (
+ model, &parent, NULL, n_children - 1);
+ } else
+ parent = *root;
+
+ n_children = gtk_tree_model_iter_n_children (model, &parent);
+
+ while (n_children > 0) {
+ GtkTreeIter child;
+
+ gtk_tree_model_iter_nth_child (
+ model, &child, &parent, n_children - 1);
+
+ parent = child;
+
+ n_children = gtk_tree_model_iter_n_children (model, &parent);
}
- return *iter;
+ *iter = parent;
+
+ return TRUE;
}
void
-em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders)
+em_folder_tree_select_prev_path (EMFolderTree *folder_tree,
+ gboolean skip_read_folders)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
- GtkTreeIter iter, child;
- GtkTreePath *path = NULL, *current_path = NULL;
+ GtkTreePath *path = NULL;
+ GtkTreePath *sentinel;
+ GtkTreeIter iter;
guint unread = 0;
struct _EMFolderTreePrivate *priv = emft->priv;
@@ -2453,51 +2477,60 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders)
selection = gtk_tree_view_get_selection(emft->priv->treeview);
- if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ /* Nothing selected means nothing to do. */
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+
+ /* This prevents us from looping over the model indefinitely,
+ * looking for unread messages when there are none. */
+ sentinel = gtk_tree_model_get_path (model, &iter);
+
+ do {
+ GtkTreeIter descendant;
+
+ if (path != NULL)
+ gtk_tree_path_free (path);
- current_path = gtk_tree_model_get_path (model, &iter);
- do {
path = gtk_tree_model_get_path (model, &iter);
- if (!gtk_tree_path_prev (path)) {
+
+ if (gtk_tree_path_prev (path)) {
+ gtk_tree_model_get_iter (model, &iter, path);
+ folder_tree_descend (model, &descendant, &iter);
+
+ gtk_tree_path_free (path);
+ path = gtk_tree_model_get_path (model, &descendant);
+
+ } else if (gtk_tree_path_get_depth (path) > 1) {
gtk_tree_path_up (path);
- if (!gtk_tree_path_compare (gtk_tree_path_new_first (), path))
- {
- gtk_tree_model_get_iter_first (model, &iter);
- iter = get_last_child (model,&iter);
- path = gtk_tree_model_get_path (model, &iter);
- }
} else {
- gtk_tree_model_get_iter (model, &iter, path);
- if (gtk_tree_model_iter_has_child (model, &iter)) {
- gint nchildren = gtk_tree_model_iter_n_children (model, &iter);
- gtk_tree_model_iter_nth_child ( model, &child, &iter, nchildren-1);
- path = gtk_tree_model_get_path (model, &child);
- }
- }
+ folder_tree_descend (model, &descendant, NULL);
- /* TODO : Flags here for better options */
- gtk_tree_model_get_iter_from_string (model, &iter, gtk_tree_path_to_string (path) );
+ gtk_tree_path_free (path);
+ path = gtk_tree_model_get_path (model, &descendant);
+ }
+ gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter, COL_UINT_UNREAD, &unread, -1);
- } while (skip_read_folders && unread <=0 && gtk_tree_path_compare (current_path, path));
- }
+ } while (skip_read_folders && unread <= 0 &&
+ gtk_tree_path_compare (path, sentinel) != 0);
- if (path) {
- if (!gtk_tree_view_row_expanded (priv->treeview, path)) {
- gtk_tree_view_expand_to_path (priv->treeview, path);
- }
+ if (!gtk_tree_view_row_expanded (tree_view, path))
+ gtk_tree_view_expand_to_path (tree_view, path);
- gtk_tree_selection_select_path(selection, path);
+ gtk_tree_selection_select_path (selection, path);
- if (!priv->cursor_set) {
- gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE);
- priv->cursor_set = TRUE;
- }
- gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.5f, 0.0f);
+ if (!priv->cursor_set) {
+ gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE);
+ priv->cursor_set = TRUE;
}
- return;
+
+ gtk_tree_view_scroll_to_cell (
+ tree_view, path, NULL, TRUE, 0.5f, 0.0f);
+
+ gtk_tree_path_free (sentinel);
+ gtk_tree_path_free (path);
}
gchar *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]