[totem/gnome-3-12] main: Fix potential data loss when removing multiple files



commit b469c525e1cf6fd1a34dce18503afed86e9fcf6b
Author: Bastien Nocera <hadess hadess net>
Date:   Thu May 15 19:28:35 2014 +0200

    main: Fix potential data loss when removing multiple files
    
    We were using a list of GtkTreePaths and deleting the items one-by-one
    when the user clicked the "Delete" button. But after the first deletion,
    the tree model would have changed, and instead of pointing to the 2nd
    item we wanted to delete, the GtkTreePath would have pointed to another
    item, usually not one that we wanted to delete.
    
    We now use GtkTreeRowReferences, which will always point to the same
    row, as long as it exists.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=729778

 src/totem-grilo.c |   21 +++++++++++++++++----
 1 files changed, 17 insertions(+), 4 deletions(-)
---
diff --git a/src/totem-grilo.c b/src/totem-grilo.c
index 88cac19..98730c4 100644
--- a/src/totem-grilo.c
+++ b/src/totem-grilo.c
@@ -2068,7 +2068,8 @@ static void
 delete_foreach (gpointer data,
                gpointer user_data)
 {
-       GtkTreePath *path = data;
+       GtkTreeRowReference *ref = data;
+       GtkTreePath *path;
        GtkTreeModel *view_model = user_data;
        GtkTreeIter iter;
        GrlSource *source;
@@ -2079,8 +2080,11 @@ delete_foreach (gpointer data,
        GtkTreeModel *model;
        GtkTreeIter real_model_iter;
 
-       if (!gtk_tree_model_get_iter (view_model, &iter, path))
+       path = gtk_tree_row_reference_get_path (ref);
+       if (!path || !gtk_tree_model_get_iter (view_model, &iter, path)) {
+               g_warning ("An item that was scheduled for removal isn't available any more");
                return;
+       }
 
        gtk_tree_model_get (view_model, &iter,
                            MODEL_RESULTS_CONTENT, &media,
@@ -2145,14 +2149,23 @@ delete_cb (TotemSelectionToolbar *bar,
           TotemGrilo            *self)
 {
        GtkTreeModel *model;
-       GList *list;
+       GList *list, *l;
 
        g_signal_handlers_block_by_func (self->priv->browser, "view-selection-changed", self);
 
        model = gd_main_view_get_model (GD_MAIN_VIEW (self->priv->browser));
        list = gd_main_view_get_selection (GD_MAIN_VIEW (self->priv->browser));
+
+       /* GList of GtkTreePaths to a GList of GtkTreeRowReferences */
+       for (l = list; l != NULL; l = l->next) {
+               GtkTreeRowReference *ref;
+
+               ref = gtk_tree_row_reference_new (model, l->data);
+               gtk_tree_path_free (l->data);
+               l->data = ref;
+       }
        g_list_foreach (list, delete_foreach, model);
-       g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+       g_list_free_full (list, (GDestroyNotify) gtk_tree_row_reference_free);
 
        g_signal_handlers_unblock_by_func (self->priv->browser, "view-selection-changed", self);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]