From fafec940b379879cf31479616338c041ece668a9 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Tue, 29 Jan 2013 01:14:10 -0600 Subject: Redo the logic for computing drop positions Instead of having an accept_uri_drops flag, we'll always advertise as accepting URI drops. However, we'll see if the caller actually handles the drag-action-requested signal. If it does, we'll indeed allow performing file operations when URIs are dropped. Otherwise, we'll only allow creating bookmarks from dragged URIs. Dragging URIs directly into a places item will cause the sidebar to check if the caller allows file operations. Dragging URIs between places items will cause the sidebar to create bookmarks for those URIs instead. Signed-off-by: Federico Mena Quintero --- gtk/gtkplacessidebar.c | 155 +++++++++++++++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 57 deletions(-) diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c index 0eef2f5d47..511060771e 100644 --- a/gtk/gtkplacessidebar.c +++ b/gtk/gtkplacessidebar.c @@ -1225,6 +1225,12 @@ clicked_eject_button (GtkPlacesSidebar *sidebar, return FALSE; } +static gboolean +pos_is_into_or_before (GtkTreeViewDropPosition pos) +{ + return (pos == GTK_TREE_VIEW_DROP_BEFORE || pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); +} + /* Computes the appropriate row and position for dropping */ static gboolean compute_drop_position (GtkTreeView *tree_view, @@ -1238,6 +1244,7 @@ compute_drop_position (GtkTreeView *tree_view, GtkTreeIter iter; PlaceType place_type; SectionType section_type; + gboolean drop_possible; if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, @@ -1253,41 +1260,62 @@ compute_drop_position (GtkTreeView *tree_view, PLACES_SIDEBAR_COLUMN_SECTION_TYPE, §ion_type, -1); + drop_possible = TRUE; + /* Never drop on headings, but special case the bookmarks heading, * so we can drop bookmarks in between it and the first bookmark. */ if (place_type == PLACES_HEADING - && section_type != SECTION_BOOKMARKS) { - gtk_tree_path_free (*path); - *path = NULL; - - return FALSE; - } + && section_type != SECTION_BOOKMARKS) + drop_possible = FALSE; /* Dragging a bookmark? */ if (sidebar->drag_data_received && sidebar->drag_data_info == GTK_TREE_MODEL_ROW) { /* Don't allow reordering bookmarks into non-bookmark areas */ - if (section_type != SECTION_BOOKMARKS) { - gtk_tree_path_free (*path); - *path = NULL; + if (section_type != SECTION_BOOKMARKS) + drop_possible = FALSE; - return FALSE; + /* Bookmarks can only be reordered. Disallow dropping directly into them; only allow dropping between them. */ + if (place_type == PLACES_HEADING) { + if (pos_is_into_or_before (*pos)) + drop_possible = FALSE; + else + *pos = GTK_TREE_VIEW_DROP_AFTER; + } else { + if (pos_is_into_or_before (*pos)) + *pos = GTK_TREE_VIEW_DROP_BEFORE; + else + *pos = GTK_TREE_VIEW_DROP_AFTER; } - - printf ("dragging a bookmark, pos = %d\n", *pos); } else { - printf ("dragging a file, pos = %d\n", *pos); + /* Dragging a file */ + + /* Outside the bookmarks section, URIs can only be dropped + * directly into places items. Inside the bookmarks section, + * they can be dropped between items (to create new bookmarks) + * or in items themselves (to request a move/copy file + * operation). + */ + if (section_type != SECTION_BOOKMARKS) + *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE; + else { + if (place_type == PLACES_HEADING) { + if (pos_is_into_or_before (*pos)) + drop_possible = FALSE; + else + *pos = GTK_TREE_VIEW_DROP_AFTER; + } + } } -#if 0 - if (sidebar->drag_data_received && - sidebar->drag_data_info == GTK_TREE_MODEL_ROW) { - /* bookmark rows can only be reordered */ - *pos = GTK_TREE_VIEW_DROP_AFTER; - } else { - *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE; + + if (!drop_possible) { + gtk_tree_path_free (*path); + *path = NULL; + + return FALSE; } -#endif + return TRUE; } @@ -1323,6 +1351,18 @@ free_drag_data (GtkPlacesSidebar *sidebar) } } +static const char * +pos_to_string (GtkTreeViewDropPosition pos) +{ + switch (pos) { + case GTK_TREE_VIEW_DROP_BEFORE: return "BEFORE"; + case GTK_TREE_VIEW_DROP_AFTER: return "AFTER"; + case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: return "INTO_OR_BEFORE"; + case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: return "INTO_OR_AFTER"; + default: return "INVALID"; + } +} + static gboolean drag_motion_callback (GtkTreeView *tree_view, GdkDragContext *context, @@ -1349,35 +1389,39 @@ drag_motion_callback (GtkTreeView *tree_view, path = NULL; res = compute_drop_position (tree_view, x, y, &path, &pos, sidebar); - printf ("compute_drop_position(): pos %d, result %d\n", pos, res); - if (!res) { goto out; } - if (pos == GTK_TREE_VIEW_DROP_AFTER) { - if (sidebar->drag_data_received && - sidebar->drag_data_info == GTK_TREE_MODEL_ROW) { - action = GDK_ACTION_MOVE; - } + printf ("compute_drop_position(): path %d, pos %s\n", gtk_tree_path_get_indices (path)[0], pos_to_string (pos)); + + if (sidebar->drag_data_received && + sidebar->drag_data_info == GTK_TREE_MODEL_ROW) { + /* Dragging bookmarks always moves them to another position in the bookmarks list */ + action = GDK_ACTION_MOVE; } else { - if (sidebar->accept_uri_drops) { - if (sidebar->drag_list != NULL) { - GFile *dest_file; - - gtk_tree_model_get_iter (GTK_TREE_MODEL (sidebar->store), - &iter, path); - gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), - &iter, - PLACES_SIDEBAR_COLUMN_URI, &uri, - -1); - - dest_file = g_file_new_for_uri (uri); - g_free (uri); + /* URIs are being dragged. See if the caller wants to handle a + * file move/copy operation itself, or if we should only try to + * create bookmarks out of the dragged URIs. + */ + if (sidebar->drag_list != NULL) { + GFile *dest_file; - emit_drag_action_requested (sidebar, context, dest_file, sidebar->drag_list, &action); - g_object_unref (dest_file); - } + gtk_tree_model_get_iter (GTK_TREE_MODEL (sidebar->store), + &iter, path); + gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), + &iter, + PLACES_SIDEBAR_COLUMN_URI, &uri, + -1); + + dest_file = g_file_new_for_uri (uri); + + emit_drag_action_requested (sidebar, context, dest_file, sidebar->drag_list, &action); + + printf ("dragging URIs, dest_file = %s, action_requested = %d\n", uri, action); + + g_object_unref (dest_file); + g_free (uri); } } @@ -1503,7 +1547,9 @@ drag_data_received_callback (GtkWidget *widget, success = FALSE; - if (tree_pos == GTK_TREE_VIEW_DROP_AFTER) { + if (sidebar->drag_data_info == GTK_TREE_MODEL_ROW) { + /* A bookmark got reordered */ + model = gtk_tree_view_get_model (tree_view); if (!gtk_tree_model_get_iter (model, &iter, tree_path)) { @@ -1520,21 +1566,16 @@ drag_data_received_callback (GtkWidget *widget, goto out; } - if (tree_pos == GTK_TREE_VIEW_DROP_AFTER && place_type != PLACES_HEADING) { - /* heading already has position 0 */ + if (place_type == PLACES_HEADING) + position = 0; + else if (tree_pos == GTK_TREE_VIEW_DROP_AFTER) position++; - } - switch (info) { - case GTK_TREE_MODEL_ROW: - reorder_bookmarks (sidebar, position); - success = TRUE; - break; - default: - g_assert_not_reached (); - break; - } + reorder_bookmarks (sidebar, position); + success = TRUE; } else { + /* Dropping URIs! */ + GdkDragAction real_action; char **uris; GList *source_file_list; -- cgit v1.2.1