[nautilus] Cache drag selections on drag begin
- From: William Jon McCann <mccann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus] Cache drag selections on drag begin
- Date: Tue, 22 Jan 2013 15:49:14 +0000 (UTC)
commit 1b4eec6e523543c413d7c0da95436f92358ba80a
Author: William Jon McCann <jmccann redhat com>
Date: Mon Jan 21 17:54:44 2013 -0500
Cache drag selections on drag begin
Since the contents of the view may change.
https://bugzilla.gnome.org/show_bug.cgi?id=692234
libnautilus-private/nautilus-canvas-dnd.c | 13 ++-
libnautilus-private/nautilus-dnd.c | 73 +++++++++++++++
libnautilus-private/nautilus-dnd.h | 10 ++
src/nautilus-list-model.c | 127 ++++----------------------
src/nautilus-list-model.h | 3 +
src/nautilus-list-view.c | 144 ++++++++++++++++-------------
src/nautilus-places-sidebar.c | 3 +-
7 files changed, 195 insertions(+), 178 deletions(-)
---
diff --git a/libnautilus-private/nautilus-canvas-dnd.c b/libnautilus-private/nautilus-canvas-dnd.c
index efa71d8..8e7501b 100644
--- a/libnautilus-private/nautilus-canvas-dnd.c
+++ b/libnautilus-private/nautilus-canvas-dnd.c
@@ -311,6 +311,8 @@ drag_data_get_callback (GtkWidget *widget,
guint32 time,
gpointer data)
{
+ NautilusDragInfo *drag_info;
+
g_assert (widget != NULL);
g_assert (NAUTILUS_IS_CANVAS_CONTAINER (widget));
g_return_if_fail (context != NULL);
@@ -319,8 +321,8 @@ drag_data_get_callback (GtkWidget *widget,
* the selection data in the right format. Pass it means to
* iterate all the selected icons.
*/
- nautilus_drag_drag_data_get (widget, context, selection_data,
- info, time, widget, each_icon_get_data_binder);
+ drag_info = &(NAUTILUS_CANVAS_CONTAINER (widget)->details->dnd_info->drag_info);
+ nautilus_drag_drag_data_get_from_cache (drag_info->selection_cache, context, selection_data, info, time);
}
@@ -1307,6 +1309,7 @@ drag_begin_callback (GtkWidget *widget,
gpointer data)
{
NautilusCanvasContainer *container;
+ NautilusDragInfo *drag_info;
cairo_surface_t *surface;
double x1, y1, x2, y2, winx, winy;
int x_offset, y_offset;
@@ -1333,6 +1336,12 @@ drag_begin_callback (GtkWidget *widget,
cairo_surface_set_device_offset (surface, -x_offset, -y_offset);
gtk_drag_set_icon_surface (context, surface);
cairo_surface_destroy (surface);
+
+ /* cache the data at the beginning since the view may change */
+ drag_info = &(container->details->dnd_info->drag_info);
+ drag_info->selection_cache = nautilus_drag_create_selection_cache (widget,
+ each_icon_get_data_binder);
+
}
void
diff --git a/libnautilus-private/nautilus-dnd.c b/libnautilus-private/nautilus-dnd.c
index afb3c54..cba7b05 100644
--- a/libnautilus-private/nautilus-dnd.c
+++ b/libnautilus-private/nautilus-dnd.c
@@ -81,6 +81,7 @@ nautilus_drag_finalize (NautilusDragInfo *drag_info)
{
gtk_target_list_unref (drag_info->target_list);
nautilus_drag_destroy_selection_list (drag_info->selection_list);
+ nautilus_drag_destroy_selection_list (drag_info->selection_cache);
g_free (drag_info);
}
@@ -585,9 +586,81 @@ add_one_uri (const char *uri, int x, int y, int w, int h, gpointer data)
g_string_append (result, "\r\n");
}
+static void
+cache_one_item (const char *uri,
+ int x, int y,
+ int w, int h,
+ gpointer data)
+{
+ GList **cache = data;
+ NautilusDragSelectionItem *item;
+
+ item = nautilus_drag_selection_item_new ();
+ item->uri = g_strdup (uri);
+ item->icon_x = x;
+ item->icon_y = y;
+ item->icon_width = w;
+ item->icon_height = h;
+ *cache = g_list_prepend (*cache, item);
+}
+
+GList *
+nautilus_drag_create_selection_cache (gpointer container_context,
+ NautilusDragEachSelectedItemIterator each_selected_item_iterator)
+{
+ GList *cache = NULL;
+
+ (* each_selected_item_iterator) (cache_one_item, container_context, &cache);
+ cache = g_list_reverse (cache);
+
+ return cache;
+}
+
/* Common function for drag_data_get_callback calls.
* Returns FALSE if it doesn't handle drag data */
gboolean
+nautilus_drag_drag_data_get_from_cache (GList *cache,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time)
+{
+ GList *l;
+ GString *result;
+ NautilusDragEachSelectedItemDataGet func;
+
+ if (cache == NULL) {
+ return FALSE;
+ }
+
+ switch (info) {
+ case NAUTILUS_ICON_DND_GNOME_ICON_LIST:
+ func = add_one_gnome_icon;
+ break;
+ case NAUTILUS_ICON_DND_URI_LIST:
+ case NAUTILUS_ICON_DND_TEXT:
+ func = add_one_uri;
+ break;
+ default:
+ return FALSE;
+ }
+
+ result = g_string_new (NULL);
+
+ for (l = cache; l != NULL; l = l->next) {
+ NautilusDragSelectionItem *item = l->data;
+ (*func) (item->uri, item->icon_x, item->icon_y, item->icon_width, item->icon_height, result);
+ }
+
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data),
+ 8, (guchar *) result->str, result->len);
+ g_string_free (result, TRUE);
+
+ return TRUE;
+}
+
+gboolean
nautilus_drag_drag_data_get (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
diff --git a/libnautilus-private/nautilus-dnd.h b/libnautilus-private/nautilus-dnd.h
index 0c45b88..6f42609 100644
--- a/libnautilus-private/nautilus-dnd.h
+++ b/libnautilus-private/nautilus-dnd.h
@@ -82,6 +82,9 @@ typedef struct {
*/
GList *selection_list;
+ /* cache of selected URIs, representing items being dragged */
+ GList *selection_cache;
+
/* has the drop occured ? */
gboolean drop_occured;
@@ -137,6 +140,13 @@ gboolean nautilus_drag_drag_data_get (GtkWidget *widget,
guint32 time,
gpointer container_context,
NautilusDragEachSelectedItemIterator each_selected_item_iterator);
+GList *nautilus_drag_create_selection_cache (gpointer container_context,
+ NautilusDragEachSelectedItemIterator each_selected_item_iterator);
+gboolean nautilus_drag_drag_data_get_from_cache (GList *cache,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time);
int nautilus_drag_modifier_based_action (int default_action,
int non_default_action);
diff --git a/src/nautilus-list-model.c b/src/nautilus-list-model.c
index fb87484..ba8cb59 100644
--- a/src/nautilus-list-model.c
+++ b/src/nautilus-list-model.c
@@ -33,7 +33,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-#include <libegg/eggtreemultidnd.h>
#include <eel/eel-graphic-effects.h>
#include <libnautilus-private/nautilus-dnd.h>
@@ -56,7 +55,6 @@ static int nautilus_list_model_file_entry_compare_func (gconstpointer a,
gpointer user_data);
static void nautilus_list_model_tree_model_init (GtkTreeModelIface *iface);
static void nautilus_list_model_sortable_init (GtkTreeSortableIface *iface);
-static void nautilus_list_model_multi_drag_source_init (EggTreeMultiDragSourceIface *iface);
struct NautilusListModelDetails {
GSequence *files;
@@ -101,17 +99,13 @@ G_DEFINE_TYPE_WITH_CODE (NautilusListModel, nautilus_list_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
nautilus_list_model_tree_model_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
- nautilus_list_model_sortable_init)
- G_IMPLEMENT_INTERFACE (EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
- nautilus_list_model_multi_drag_source_init));
+ nautilus_list_model_sortable_init));
static const GtkTargetEntry drag_types [] = {
{ NAUTILUS_ICON_DND_GNOME_ICON_LIST_TYPE, 0, NAUTILUS_ICON_DND_GNOME_ICON_LIST },
{ NAUTILUS_ICON_DND_URI_LIST_TYPE, 0, NAUTILUS_ICON_DND_URI_LIST },
};
-static GtkTargetList *drag_target_list = NULL;
-
static void
file_entry_free (FileEntry *file_entry)
{
@@ -765,101 +759,6 @@ nautilus_list_model_has_default_sort_func (GtkTreeSortable *sortable)
return FALSE;
}
-static gboolean
-nautilus_list_model_multi_row_draggable (EggTreeMultiDragSource *drag_source, GList *path_list)
-{
- return TRUE;
-}
-
-static void
-each_path_get_data_binder (NautilusDragEachSelectedItemDataGet data_get,
- gpointer context,
- gpointer data)
-{
- DragDataGetInfo *info;
- GList *l;
- NautilusFile *file;
- GtkTreeRowReference *row;
- GtkTreePath *path;
- char *uri;
- GdkRectangle cell_area;
- GtkTreeViewColumn *column;
-
- info = context;
-
- g_return_if_fail (info->model->details->drag_view);
-
- column = gtk_tree_view_get_column (info->model->details->drag_view, 0);
-
- for (l = info->path_list; l != NULL; l = l->next) {
- row = l->data;
-
- path = gtk_tree_row_reference_get_path (row);
- file = nautilus_list_model_file_for_path (info->model, path);
- if (file) {
- gtk_tree_view_get_cell_area
- (info->model->details->drag_view,
- path,
- column,
- &cell_area);
-
- uri = nautilus_file_get_uri (file);
-
- (*data_get) (uri,
- 0,
- cell_area.y - info->model->details->drag_begin_y,
- cell_area.width, cell_area.height,
- data);
-
- g_free (uri);
-
- nautilus_file_unref (file);
- }
-
- gtk_tree_path_free (path);
- }
-}
-
-static gboolean
-nautilus_list_model_multi_drag_data_get (EggTreeMultiDragSource *drag_source,
- GList *path_list,
- GtkSelectionData *selection_data)
-{
- NautilusListModel *model;
- DragDataGetInfo context;
- guint target_info;
-
- model = NAUTILUS_LIST_MODEL (drag_source);
-
- context.model = model;
- context.path_list = path_list;
-
- if (!drag_target_list) {
- drag_target_list = nautilus_list_model_get_drag_target_list ();
- }
-
- if (gtk_target_list_find (drag_target_list,
- gtk_selection_data_get_target (selection_data),
- &target_info)) {
- nautilus_drag_drag_data_get (NULL,
- NULL,
- selection_data,
- target_info,
- GDK_CURRENT_TIME,
- &context,
- each_path_get_data_binder);
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-static gboolean
-nautilus_list_model_multi_drag_data_delete (EggTreeMultiDragSource *drag_source, GList *path_list)
-{
- return TRUE;
-}
-
static void
add_dummy_row (NautilusListModel *model, FileEntry *parent_entry)
{
@@ -1392,6 +1291,22 @@ nautilus_list_model_set_drag_view (NautilusListModel *model,
model->details->drag_begin_y = drag_begin_y;
}
+GtkTreeView *
+nautilus_list_model_get_drag_view (NautilusListModel *model,
+ int *drag_begin_x,
+ int *drag_begin_y)
+{
+ if (drag_begin_x != NULL) {
+ *drag_begin_x = model->details->drag_begin_x;
+ }
+
+ if (drag_begin_y != NULL) {
+ *drag_begin_y = model->details->drag_begin_y;
+ }
+
+ return model->details->drag_view;
+}
+
GtkTargetList *
nautilus_list_model_get_drag_target_list ()
{
@@ -1548,14 +1463,6 @@ nautilus_list_model_sortable_init (GtkTreeSortableIface *iface)
iface->has_default_sort_func = nautilus_list_model_has_default_sort_func;
}
-static void
-nautilus_list_model_multi_drag_source_init (EggTreeMultiDragSourceIface *iface)
-{
- iface->row_draggable = nautilus_list_model_multi_row_draggable;
- iface->drag_data_get = nautilus_list_model_multi_drag_data_get;
- iface->drag_data_delete = nautilus_list_model_multi_drag_data_delete;
-}
-
void
nautilus_list_model_subdirectory_done_loading (NautilusListModel *model, NautilusDirectory *directory)
{
diff --git a/src/nautilus-list-model.h b/src/nautilus-list-model.h
index 0b07e8c..57ecd64 100644
--- a/src/nautilus-list-model.h
+++ b/src/nautilus-list-model.h
@@ -114,6 +114,9 @@ void nautilus_list_model_set_drag_view (NautilusListModel *model,
GtkTreeView *view,
int begin_x,
int begin_y);
+GtkTreeView * nautilus_list_model_get_drag_view (NautilusListModel *model,
+ int *drag_begin_x,
+ int *drag_begin_y);
GtkTargetList * nautilus_list_model_get_drag_target_list (void);
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index e7b7b5e..90f3c50 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -40,7 +40,6 @@
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
-#include <libegg/eggtreemultidnd.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include <libnautilus-extension/nautilus-column-provider.h>
@@ -354,7 +353,7 @@ drag_data_get_callback (GtkWidget *widget,
{
GtkTreeView *tree_view;
GtkTreeModel *model;
- GList *ref_list;
+ GList *selection_cache;
tree_view = GTK_TREE_VIEW (widget);
@@ -364,67 +363,12 @@ drag_data_get_callback (GtkWidget *widget,
return;
}
- ref_list = g_object_get_data (G_OBJECT (context), "drag-info");
-
- if (ref_list == NULL) {
+ selection_cache = g_object_get_data (G_OBJECT (context), "drag-info");
+ if (selection_cache == NULL) {
return;
}
- if (EGG_IS_TREE_MULTI_DRAG_SOURCE (model)) {
- egg_tree_multi_drag_source_drag_data_get (EGG_TREE_MULTI_DRAG_SOURCE (model),
- ref_list,
- selection_data);
- }
-}
-
-static void
-filtered_selection_foreach (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- struct SelectionForeachData *selection_data;
- GtkTreeIter parent;
- GtkTreeIter child;
-
- selection_data = data;
-
- /* If the parent folder is also selected, don't include this file in the
- * file operation, since that would copy it to the toplevel target instead
- * of keeping it as a child of the copied folder
- */
- child = *iter;
- while (gtk_tree_model_iter_parent (model, &parent, &child)) {
- if (gtk_tree_selection_iter_is_selected (selection_data->selection,
- &parent)) {
- return;
- }
- child = parent;
- }
-
- selection_data->list = g_list_prepend (selection_data->list,
- gtk_tree_row_reference_new (model, path));
-}
-
-static GList *
-get_filtered_selection_refs (GtkTreeView *tree_view)
-{
- struct SelectionForeachData selection_data;
-
- selection_data.list = NULL;
- selection_data.selection = gtk_tree_view_get_selection (tree_view);
-
- gtk_tree_selection_selected_foreach (selection_data.selection,
- filtered_selection_foreach,
- &selection_data);
- return g_list_reverse (selection_data.list);
-}
-
-static void
-ref_list_free (GList *ref_list)
-{
- g_list_foreach (ref_list, (GFunc) gtk_tree_row_reference_free, NULL);
- g_list_free (ref_list);
+ nautilus_drag_drag_data_get_from_cache (selection_cache, context, selection_data, info, time);
}
static void
@@ -466,12 +410,80 @@ get_drag_pixbuf (NautilusListView *view)
return ret;
}
+/* iteration glue struct */
+typedef struct {
+ NautilusListView *view;
+ NautilusDragEachSelectedItemDataGet iteratee;
+ gpointer iteratee_data;
+} ListGetDataBinderContext;
+
+static void
+item_get_data_binder (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ ListGetDataBinderContext *context = data;
+ NautilusFile *file;
+ GtkTreeView *treeview;
+ GtkTreeViewColumn *column;
+ GdkRectangle cell_area;
+ int drag_begin_y = 0;
+ char *uri;
+
+ treeview = nautilus_list_model_get_drag_view (context->view->details->model,
+ NULL,
+ &drag_begin_y);
+ column = gtk_tree_view_get_column (treeview, 0);
+
+ file = nautilus_list_model_file_for_path (NAUTILUS_LIST_MODEL (model), path);
+ if (file == NULL) {
+ return;
+ }
+
+ gtk_tree_view_get_cell_area (treeview,
+ path,
+ column,
+ &cell_area);
+
+ uri = nautilus_file_get_uri (file);
+ nautilus_file_unref (file);
+
+ /* pass the uri, mouse-relative x/y and icon width/height */
+ context->iteratee (uri,
+ 0,
+ cell_area.y - drag_begin_y,
+ cell_area.width,
+ cell_area.height,
+ context->iteratee_data);
+
+ g_free (uri);
+}
+
+static void
+each_item_get_data_binder (NautilusDragEachSelectedItemDataGet iteratee,
+ gpointer iterator_context,
+ gpointer data)
+{
+ NautilusListView *view = NAUTILUS_LIST_VIEW (iterator_context);
+ ListGetDataBinderContext context;
+ GtkTreeSelection *selection;
+
+ context.view = view;
+ context.iteratee = iteratee;
+ context.iteratee_data = data;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view->details->tree_view));
+ gtk_tree_selection_selected_foreach (selection, item_get_data_binder, &context);
+}
+
+
static void
drag_begin_callback (GtkWidget *widget,
GdkDragContext *context,
NautilusListView *view)
{
- GList *ref_list;
+ GList *selection_cache;
GdkPixbuf *pixbuf;
pixbuf = get_drag_pixbuf (view);
@@ -486,12 +498,14 @@ drag_begin_callback (GtkWidget *widget,
stop_drag_check (view);
view->details->drag_started = TRUE;
-
- ref_list = get_filtered_selection_refs (GTK_TREE_VIEW (widget));
+
+ selection_cache = nautilus_drag_create_selection_cache (view,
+ each_item_get_data_binder);
+
g_object_set_data_full (G_OBJECT (context),
"drag-info",
- ref_list,
- (GDestroyNotify)ref_list_free);
+ selection_cache,
+ (GDestroyNotify)nautilus_drag_destroy_selection_list);
}
static gboolean
diff --git a/src/nautilus-places-sidebar.c b/src/nautilus-places-sidebar.c
index afb7203..b337a1c 100644
--- a/src/nautilus-places-sidebar.c
+++ b/src/nautilus-places-sidebar.c
@@ -1309,7 +1309,6 @@ build_selection_list (const char *data)
int i;
uris = g_uri_list_extract_uris (data);
-
result = NULL;
for (i = 0; uris[i]; i++) {
uri = uris[i];
@@ -1467,7 +1466,9 @@ drag_data_received_callback (GtkWidget *widget,
switch (info) {
case TEXT_URI_LIST:
selection_list = build_selection_list ((const gchar *) gtk_selection_data_get_data (selection_data));
+ g_assert (selection_list);
uris = uri_list_from_selection (selection_list);
+ g_assert (uris);
nautilus_file_operations_copy_move (uris, NULL, drop_uri,
real_action, GTK_WIDGET (tree_view),
NULL, NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]