[gnome-documents/wip/ui-changes: 16/25] views: add support for text/uri-list DnD source



commit e8615546c503db75b3e147c4799bf943e7f90210
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Thu Mar 1 17:24:43 2012 -0500

    views: add support for text/uri-list DnD source
    
    Support being a text/uri-list DnD source. This means we're now able to
    drag items outside of the views to applications who understand the
    protocol.

 src/lib/gd-main-icon-view.c    |   42 +++++++++++++++++++++++
 src/lib/gd-main-list-view.c    |   43 +++++++++++++++++++++++
 src/lib/gd-main-view-generic.c |   73 ++++++++++++++++++++++++++++++++++++++++
 src/lib/gd-main-view-generic.h |    6 +++
 src/lib/gd-main-view.c         |    6 ++--
 5 files changed, 167 insertions(+), 3 deletions(-)
---
diff --git a/src/lib/gd-main-icon-view.c b/src/lib/gd-main-icon-view.c
index b796280..a7f98f2 100644
--- a/src/lib/gd-main-icon-view.c
+++ b/src/lib/gd-main-icon-view.c
@@ -51,11 +51,47 @@ on_icon_selection_changed (GtkIconView *iv,
   g_signal_emit_by_name (self, "view-selection-changed");
 }
 
+static GtkTreePath*
+get_source_row (GdkDragContext *context)
+{
+  GtkTreeRowReference *ref;
+
+  ref = g_object_get_data (G_OBJECT (context), "gtk-icon-view-source-row");
+
+  if (ref)
+    return gtk_tree_row_reference_get_path (ref);
+  else
+    return NULL;
+}
+
+static void
+gd_main_icon_view_drag_data_get (GtkWidget *widget,
+                                 GdkDragContext *drag_context,
+                                 GtkSelectionData *data,
+                                 guint info,
+                                 guint time)
+{
+  GdMainIconView *self = GD_MAIN_ICON_VIEW (widget);
+  GtkTreeModel *model = gtk_icon_view_get_model (GTK_ICON_VIEW (self));
+
+  if (info != 0)
+    return;
+
+  _gd_main_view_generic_dnd_common (model, self->priv->selection_mode,
+                                    get_source_row (drag_context), data);
+
+  GTK_WIDGET_CLASS (gd_main_icon_view_parent_class)->drag_data_get (widget, drag_context,
+                                                                    data, info, time);
+}
+
 static void
 gd_main_icon_view_constructed (GObject *obj)
 {
   GdMainIconView *self = GD_MAIN_ICON_VIEW (obj);
   GtkCellRenderer *cell;
+  const GtkTargetEntry targets[] = {
+    { "text/uri-list", GTK_TARGET_OTHER_APP, 0 }
+  };
 
   G_OBJECT_CLASS (gd_main_icon_view_parent_class)->constructed (obj);
 
@@ -95,6 +131,11 @@ gd_main_icon_view_constructed (GObject *obj)
                                  "text", GD_MAIN_COLUMN_TITLE);
   gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
                                  "line-two", GD_MAIN_COLUMN_AUTHOR);
+
+  gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (self),
+                                          GDK_BUTTON1_MASK,
+                                          targets, 1,
+                                          GDK_ACTION_COPY);
 }
 
 static void
@@ -104,6 +145,7 @@ gd_main_icon_view_class_init (GdMainIconViewClass *klass)
   GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
 
   oclass->constructed = gd_main_icon_view_constructed;
+  wclass->drag_data_get = gd_main_icon_view_drag_data_get;
 
   gtk_widget_class_install_style_property (wclass,
                                            g_param_spec_int ("check-icon-size",
diff --git a/src/lib/gd-main-list-view.c b/src/lib/gd-main-list-view.c
index 34dabf3..7b9fd51 100644
--- a/src/lib/gd-main-list-view.c
+++ b/src/lib/gd-main-list-view.c
@@ -38,12 +38,48 @@ G_DEFINE_TYPE_WITH_CODE (GdMainListView, gd_main_list_view, GTK_TYPE_TREE_VIEW,
                          G_IMPLEMENT_INTERFACE (GD_TYPE_MAIN_VIEW_GENERIC,
                                                 gd_main_view_generic_iface_init))
 
+static GtkTreePath*
+get_source_row (GdkDragContext *context)
+{
+  GtkTreeRowReference *ref =
+    g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
+
+  if (ref)
+    return gtk_tree_row_reference_get_path (ref);
+  else
+    return NULL;
+}
+
+static void
+gd_main_list_view_drag_data_get (GtkWidget *widget,
+                                 GdkDragContext *drag_context,
+                                 GtkSelectionData *data,
+                                 guint info,
+                                 guint time)
+{
+  GdMainListView *self = GD_MAIN_LIST_VIEW (widget);
+  GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (self));
+
+  if (info != 0)
+    return;
+
+  _gd_main_view_generic_dnd_common (model,
+                                    self->priv->selection_mode,
+                                    get_source_row (drag_context), data);
+
+  GTK_WIDGET_CLASS (gd_main_list_view_parent_class)->drag_data_get (widget, drag_context,
+                                                                    data, info, time);
+}
+
 static void
 gd_main_list_view_constructed (GObject *obj)
 {
   GdMainListView *self = GD_MAIN_LIST_VIEW (obj);
   GtkCellRenderer *cell;
   GtkTreeSelection *selection;
+  const GtkTargetEntry targets[] = {
+    { "text/uri-list", GTK_TARGET_OTHER_APP, 0 }
+  };
 
   G_OBJECT_CLASS (gd_main_list_view_parent_class)->constructed (obj);
 
@@ -91,14 +127,21 @@ gd_main_list_view_constructed (GObject *obj)
                                       "text", GD_MAIN_COLUMN_TITLE);
   gtk_tree_view_column_add_attribute (self->priv->tree_col, cell,
                                       "line-two", GD_MAIN_COLUMN_AUTHOR);
+
+  gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (self),
+                                          GDK_BUTTON1_MASK,
+                                          targets, 1,
+                                          GDK_ACTION_COPY);
 }
 
 static void
 gd_main_list_view_class_init (GdMainListViewClass *klass)
 {
   GObjectClass *oclass = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
 
   oclass->constructed = gd_main_list_view_constructed;
+  wclass->drag_data_get = gd_main_list_view_drag_data_get;
 
   g_type_class_add_private (klass, sizeof (GdMainListViewPrivate));
 }
diff --git a/src/lib/gd-main-view-generic.c b/src/lib/gd-main-view-generic.c
index f3d1600..9b69391 100644
--- a/src/lib/gd-main-view-generic.c
+++ b/src/lib/gd-main-view-generic.c
@@ -19,6 +19,7 @@
  *
  */
 
+#include "gd-main-view.h"
 #include "gd-main-view-generic.h"
 
 enum {
@@ -93,3 +94,75 @@ gd_main_view_generic_scroll_to_path (GdMainViewGeneric *self,
 
   (* iface->scroll_to_path) (self, path);
 }
+
+static gboolean
+build_selection_uris_foreach (GtkTreeModel *model,
+                              GtkTreePath *path,
+                              GtkTreeIter *iter,
+                              gpointer user_data)
+{
+  GPtrArray *ptr_array = user_data;
+  gchar *uri;
+  gboolean is_selected;
+
+  gtk_tree_model_get (model, iter,
+                      GD_MAIN_COLUMN_URI, &uri,
+                      GD_MAIN_COLUMN_SELECTED, &is_selected,
+                      -1);
+
+  if (is_selected)
+    g_ptr_array_add (ptr_array, uri);
+  else
+    g_free (uri);
+
+  return FALSE;
+}
+
+static gchar **
+model_get_selection_uris (GtkTreeModel *model)
+{
+  GPtrArray *ptr_array = g_ptr_array_new ();
+
+  gtk_tree_model_foreach (model,
+                          build_selection_uris_foreach,
+                          ptr_array);
+  
+  g_ptr_array_add (ptr_array, NULL);
+  return (gchar **) g_ptr_array_free (ptr_array, FALSE);
+}
+
+void
+_gd_main_view_generic_dnd_common (GtkTreeModel *model,
+                                  gboolean selection_mode,
+                                  GtkTreePath *path,
+                                  GtkSelectionData *data)
+{
+  gchar **uris;
+
+  if (selection_mode)
+    {
+      uris = model_get_selection_uris (model);
+    }
+  else
+    {
+      GtkTreeIter iter;
+      gboolean res;
+      gchar *uri = NULL;
+
+      if (path != NULL)
+        {
+          res = gtk_tree_model_get_iter (model, &iter, path);
+          if (res)
+            gtk_tree_model_get (model, &iter,
+                                GD_MAIN_COLUMN_URI, &uri,
+                                -1);
+        }
+
+      uris = g_new0 (gchar *, 2);
+      uris[0] = uri;
+      uris[1] = NULL;
+    }
+
+  gtk_selection_data_set_uris (data, uris);
+  g_strfreev (uris);
+}
diff --git a/src/lib/gd-main-view-generic.h b/src/lib/gd-main-view-generic.h
index f99a950..b59b547 100644
--- a/src/lib/gd-main-view-generic.h
+++ b/src/lib/gd-main-view-generic.h
@@ -86,6 +86,12 @@ GtkTreePath * gd_main_view_generic_get_path_at_pos (GdMainViewGeneric *self,
                                                     gint x,
                                                     gint y);
 
+/* private */
+void _gd_main_view_generic_dnd_common (GtkTreeModel *model,
+                                       gboolean selection_mode,
+                                       GtkTreePath *path,
+                                       GtkSelectionData *data);
+
 G_END_DECLS
 
 #endif /* __GD_MAIN_VIEW_GENERIC_H__ */
diff --git a/src/lib/gd-main-view.c b/src/lib/gd-main-view.c
index 1ebd72b..2990e84 100644
--- a/src/lib/gd-main-view.c
+++ b/src/lib/gd-main-view.c
@@ -242,7 +242,7 @@ on_button_release_selection_mode (GdMainView *self,
 
   g_signal_emit_by_name (generic, "view-selection-changed");
 
-  return TRUE;
+  return FALSE;
 }
 
 static gboolean
@@ -266,7 +266,7 @@ on_button_release_view_mode (GdMainView *self,
   g_signal_emit (self, signals[ITEM_ACTIVATED], 0, id, path);
   g_free (id);
 
-  return TRUE;
+  return FALSE;
 }
 
 static gboolean
@@ -358,7 +358,7 @@ on_button_press_event (GtkWidget *view,
   /* TODO: eat button press events for now; in the future we might want
    * to add support for DnD.
    */
-  return TRUE;
+  return FALSE;
 }
 
 static void



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