aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-10-29 03:28:58 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-10-29 03:32:41 +0800
commit5a7992dca23eabdad214ae8f80f6050024d912d9 (patch)
tree65bfe816023967274ef43f4c049c8eb636c58322
parent38caddc649d0ffbc9721d61a706324626fadd6a8 (diff)
downloadgsoc2013-evolution-5a7992dca23eabdad214ae8f80f6050024d912d9.tar
gsoc2013-evolution-5a7992dca23eabdad214ae8f80f6050024d912d9.tar.gz
gsoc2013-evolution-5a7992dca23eabdad214ae8f80f6050024d912d9.tar.bz2
gsoc2013-evolution-5a7992dca23eabdad214ae8f80f6050024d912d9.tar.lz
gsoc2013-evolution-5a7992dca23eabdad214ae8f80f6050024d912d9.tar.xz
gsoc2013-evolution-5a7992dca23eabdad214ae8f80f6050024d912d9.tar.zst
gsoc2013-evolution-5a7992dca23eabdad214ae8f80f6050024d912d9.zip
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.
-rw-r--r--mail/em-folder-tree.c131
1 files changed, 82 insertions, 49 deletions
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index a4f91409d9..f1274f7c50 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -2287,32 +2287,56 @@ em_folder_tree_select_next_path (EMFolderTree *folder_tree, gboolean skip_read_f
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 *folder_tree, gboolean skip_read_folders)
+em_folder_tree_select_prev_path (EMFolderTree *folder_tree,
+ gboolean skip_read_folders)
{
GtkTreeView *tree_view;
GtkTreeSelection *selection;
GtkTreeModel *model;
- GtkTreeIter iter, child;
- GtkTreePath *path = NULL, *current_path = NULL;
+ GtkTreePath *path = NULL;
+ GtkTreePath *sentinel;
+ GtkTreeIter iter;
guint unread = 0;
EMFolderTreePrivate *priv = folder_tree->priv;
@@ -2321,51 +2345,60 @@ em_folder_tree_select_prev_path (EMFolderTree *folder_tree, gboolean skip_read_f
tree_view = GTK_TREE_VIEW (folder_tree);
selection = gtk_tree_view_get_selection (tree_view);
- 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 (tree_view, path)) {
- gtk_tree_view_expand_to_path (tree_view, 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 (tree_view, path, NULL, FALSE);
- priv->cursor_set = TRUE;
- }
- gtk_tree_view_scroll_to_cell (tree_view, 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);
}
void