[brasero/gnome-2-30] Fix multi DND in GtkFileChooser It had stopped working due to recent changes in above widget. It als



commit de2da5710d290f0edd244cb77db85f0f7cedb3e0
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date:   Mon May 24 17:52:44 2010 +0200

    Fix multi DND in GtkFileChooser
    It had stopped working due to recent changes in above widget.
    It also fix a warning that appears in valgrind as an invalid read so it could be a candidate to fix #612834

 src/brasero-file-chooser.c |   37 +++++++++++++++++++++++++++++++++++--
 src/brasero-multi-dnd.c    |   26 +++++++++++---------------
 src/brasero-multi-dnd.h    |    3 +++
 src/eggtreemultidnd.c      |   35 +++++++++++++++++++++++++++++++----
 4 files changed, 80 insertions(+), 21 deletions(-)
---
diff --git a/src/brasero-file-chooser.c b/src/brasero-file-chooser.c
index 1a1b68f..5caf48e 100644
--- a/src/brasero-file-chooser.c
+++ b/src/brasero-file-chooser.c
@@ -37,6 +37,7 @@
 #include <gtk/gtk.h>
 
 #include "eggtreemultidnd.h"
+#include "brasero-multi-dnd.h"
 
 #include "brasero-setting.h"
 #include "brasero-file-chooser.h"
@@ -210,10 +211,25 @@ brasero_file_chooser_allocation_changed (GtkWidget *widget,
 	brasero_file_chooser_position_percent (G_OBJECT (widget), width, position);
 }
 
+static void
+brasero_file_chooser_notify_model (GtkTreeView *treeview,
+                                   GParamSpec *pspec,
+                                   gpointer NULL_data)
+{
+	GtkTreeModel *model;
+
+	model = gtk_tree_view_get_model (treeview);
+	if (model && !EGG_IS_TREE_MULTI_DRAG_SOURCE (model)) {
+		GType type;
+
+		type = G_OBJECT_TYPE (model);
+		brasero_enable_multi_DND_for_model_type (type);
+	}
+}
+
 void
 brasero_file_chooser_customize (GtkWidget *widget, gpointer null_data)
 {
-
 	/* we explore everything until we reach a treeview (there are two) */
 	if (GTK_IS_TREE_VIEW (widget)) {
 		GtkTargetList *list;
@@ -228,8 +244,25 @@ brasero_file_chooser_customize (GtkWidget *widget, gpointer null_data)
 		 * the warning messages we get if we do */
 
 		if (found
-		&&  gtk_tree_selection_get_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget))) == GTK_SELECTION_MULTIPLE)
+		&&  gtk_tree_selection_get_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget))) == GTK_SELECTION_MULTIPLE) {
+			GtkTreeModel *model;
+
+			/* This is done because GtkFileChooser does not use a
+			 * GtkListStore or GtkTreeStore any more. */
 			egg_tree_multi_drag_add_drag_support (GTK_TREE_VIEW (widget));
+			model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+			if (model) {
+				GType type;
+
+				type = G_OBJECT_TYPE (model);
+				brasero_enable_multi_DND_for_model_type (type);
+			}
+			else
+				g_signal_connect (widget,
+				                  "notify::model",
+				                  G_CALLBACK (brasero_file_chooser_notify_model),
+				                  NULL);
+		}
 	}
 	else if (GTK_IS_BUTTON (widget)) {
 		GtkWidget *image;
diff --git a/src/brasero-multi-dnd.c b/src/brasero-multi-dnd.c
index f6a69e2..bf7b6a2 100644
--- a/src/brasero-multi-dnd.c
+++ b/src/brasero-multi-dnd.c
@@ -200,31 +200,27 @@ static const GInterfaceInfo brasero_data_track_cfg_multi_DND_drag_source_info =
 	NULL
 };
 
-void
-brasero_enable_multi_DND (void)
+gboolean
+brasero_enable_multi_DND_for_model_type (GType type)
 {
-	GType object_type;
-
-	object_type = gtk_tree_model_filter_get_type ();
-	g_type_add_interface_static (object_type,
+	g_type_add_interface_static (type,
 				     EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
 				     &multi_DND_drag_source_info);
+	return TRUE;
+}
 
-	object_type = gtk_tree_model_sort_get_type ();
-	g_type_add_interface_static (object_type,
+void
+brasero_enable_multi_DND (void)
+{
+	g_type_add_interface_static (GTK_TYPE_TREE_MODEL_SORT,
 				     EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
 				     &multi_DND_drag_source_info);
-
-	object_type = gtk_tree_store_get_type ();
-	g_type_add_interface_static (object_type,
+	g_type_add_interface_static (GTK_TYPE_TREE_STORE,
 				     EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
 				     &multi_DND_drag_source_info);
-
-	object_type = gtk_list_store_get_type ();
-	g_type_add_interface_static (object_type,
+	g_type_add_interface_static (GTK_TYPE_LIST_STORE,
 				     EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
 				     &multi_DND_drag_source_info);
-
 	g_type_add_interface_static (BRASERO_TYPE_TRACK_DATA_CFG,
 				     EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
 				     &brasero_data_track_cfg_multi_DND_drag_source_info);
diff --git a/src/brasero-multi-dnd.h b/src/brasero-multi-dnd.h
index 507d93e..8a37637 100644
--- a/src/brasero-multi-dnd.h
+++ b/src/brasero-multi-dnd.h
@@ -33,6 +33,9 @@ G_BEGIN_DECLS
 void
 brasero_enable_multi_DND (void);
 
+gboolean
+brasero_enable_multi_DND_for_model_type (GType type);
+
 G_END_DECLS
 
 #endif /* _MULTI_DND_H */
diff --git a/src/eggtreemultidnd.c b/src/eggtreemultidnd.c
index 35a085f..970affc 100644
--- a/src/eggtreemultidnd.c
+++ b/src/eggtreemultidnd.c
@@ -349,6 +349,15 @@ egg_tree_multi_drag_motion_event (GtkWidget      *widget,
   return TRUE;
 }
 
+static void
+_treeview_destroyed (GtkWidget *widget,
+                     gpointer user_data)
+{
+	gboolean *called = user_data;
+	*called = TRUE;
+	g_object_ref (widget);
+}
+
 static gboolean
 egg_tree_multi_drag_button_press_event (GtkWidget      *widget,
 					GdkEventButton *event,
@@ -395,7 +404,9 @@ egg_tree_multi_drag_button_press_event (GtkWidget      *widget,
   if (path && gtk_tree_selection_path_is_selected (selection, path))
     {
       GList *iter;
+      gulong sig_id;
       GList *selected;
+      gboolean called = FALSE;
       GtkWidgetClass *widget_klass;
 
       /* The call to ::button_press_event will unselect all selected rows so
@@ -403,14 +414,30 @@ egg_tree_multi_drag_button_press_event (GtkWidget      *widget,
        * again. */
       selected = gtk_tree_selection_get_selected_rows (selection, NULL);
 
+      /* In some rare cases (like for a GtkFileChooserDialog when the user
+       * double-clicks a row) "destroy" is called during ::button_press_event
+       * calls which makes widget and selection invalid afterwards.
+       * Note: it seems that a call to "destroy" makes all signals invalid as
+       * well so do not disconnect */
+      sig_id = g_signal_connect (widget,
+                                 "destroy",
+                                 G_CALLBACK (_treeview_destroyed),
+                                 &called);
+
       widget_klass = GTK_WIDGET_GET_CLASS (tree_view);
       widget_klass->button_press_event (widget, event);
 
-      for (iter = selected; iter; iter = iter->next) {
-        gtk_tree_selection_select_path (selection, iter->data);
-	gtk_tree_path_free (iter->data);
+      if (!called)
+	g_signal_handler_disconnect (widget, sig_id);
+
+      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+      if (selection) {
+	      for (iter = selected; iter; iter = iter->next) {
+		gtk_tree_selection_select_path (selection, iter->data);
+		gtk_tree_path_free (iter->data);
+	      }
+	      g_list_free (selected);
       }
-      g_list_free (selected);
 
       priv_data->pressed_button = event->button;
       priv_data->x = event->x;



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