Re: [PATCH] - Add drag drop of bookmarks to places sidebar
- From: Jamie McCracken <jamiemcc blueyonder co uk>
- To: Jamie McCracken <jamiemcc blueyonder co uk>
- Cc: "nautilus-list gnome org" <nautilus-list gnome org>, Alexander Larsson <alexl redhat com>
- Subject: Re: [PATCH] - Add drag drop of bookmarks to places sidebar
- Date: Mon, 11 Jul 2005 02:01:31 +0100
Jamie McCracken wrote:
Attached is patch to allow drag drop of folder uris to blank rows in the
places sidebar.
Also added some ints to sidebar for later use.
Updated this to include :
- highlights row when dragging
- copies files when dropped onto exisitng place
- added volume/bookmark pointer to list store for forthcoming popup menu
--
Mr Jamie McCracken
http://www.advogato.org/person/jamiemcc/
Index: src/nautilus-places-sidebar.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-places-sidebar.c,v
retrieving revision 1.1
diff -u -r1.1 nautilus-places-sidebar.c
--- src/nautilus-places-sidebar.c 1 Jul 2005 14:13:49 -0000 1.1
+++ src/nautilus-places-sidebar.c 11 Jul 2005 00:55:24 -0000
@@ -28,12 +28,14 @@
#include <eel/eel-glib-extensions.h>
#include <eel/eel-preferences.h>
#include <eel/eel-string.h>
+#include <eel/eel-stock-dialogs.h>
#include <gtk/gtkalignment.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtkcellrendererpixbuf.h>
#include <gtk/gtkcellrenderertext.h>
#include <gtk/gtkliststore.h>
+#include <gtk/gtkmessagedialog.h>
#include <gtk/gtksizegroup.h>
#include <gtk/gtkstock.h>
#include <gtk/gtktreemodel.h>
@@ -45,6 +47,7 @@
#include <libnautilus-private/nautilus-sidebar-provider.h>
#include <libnautilus-private/nautilus-module.h>
#include <libnautilus-private/nautilus-file-utilities.h>
+#include <libnautilus-private/nautilus-file-operations.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libgnomevfs/gnome-vfs-volume-monitor.h>
@@ -81,7 +84,7 @@
PLACES_SIDEBAR_COLUMN_URI,
PLACES_SIDEBAR_COLUMN_NAME,
PLACES_SIDEBAR_COLUMN_ICON,
-
+ PLACES_SIDEBAR_COLUMN_USER_DATA,
PLACES_SIDEBAR_COLUMN_COUNT
};
@@ -92,6 +95,12 @@
PLACES_SEPARATOR
} PlaceType;
+static const GtkTargetEntry dest_targets[] = {
+ { "text/uri-list", 0, 0}
+};
+
+#define MAX_BOOKMARK_LENGTH 80
+
static void nautilus_places_sidebar_iface_init (NautilusSidebarIface *iface);
static void sidebar_provider_iface_init (NautilusSidebarProviderIface *iface);
static GType nautilus_places_sidebar_provider_get_type (void);
@@ -104,10 +113,9 @@
G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SIDEBAR_PROVIDER,
sidebar_provider_iface_init));
-
static GtkTreeIter
add_place (GtkListStore *store, PlaceType place_type,
- const char *name, const char *icon, const char *uri)
+ const char *name, const char *icon, const char *uri, gpointer user_data)
{
GdkPixbuf *pixbuf;
GtkTreeIter iter;
@@ -119,6 +127,7 @@
PLACES_SIDEBAR_COLUMN_NAME, name,
PLACES_SIDEBAR_COLUMN_URI, uri,
PLACES_SIDEBAR_COLUMN_ROW_TYPE, place_type,
+ PLACES_SIDEBAR_COLUMN_USER_DATA, user_data,
-1);
if (pixbuf != NULL) {
g_object_unref (pixbuf);
@@ -126,6 +135,35 @@
return iter;
}
+
+static void
+unref_volumes (NautilusPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ gboolean valid;
+ gpointer ptr;
+ GnomeVFSVolume *volume;
+ PlaceType place_type;
+
+ valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (sidebar->store), &iter);
+
+ while (valid) {
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
+ PLACES_SIDEBAR_COLUMN_USER_DATA, &ptr,
+ -1);
+ if (place_type == PLACES_MOUNTED_VOLUME) {
+ volume = GNOME_VFS_VOLUME (ptr);
+ if (volume) {
+ gnome_vfs_volume_unref (volume);
+ }
+ }
+ valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (sidebar->store), &iter);
+ }
+}
+
+
+
static void
update_places (NautilusPlacesSidebar *sidebar)
{
@@ -135,10 +173,14 @@
GnomeVFSVolumeMonitor *volume_monitor;
GList *volumes, *l;
GnomeVFSVolume *volume;
- int bookmark_count, index;
+ int index, bookmark_count;
char *location, *icon, *mount_uri, *name, *desktop_path;
selection = gtk_tree_view_get_selection (sidebar->tree_view);
+
+ /* unref existing volumes before clearing */
+ unref_volumes (sidebar);
+
gtk_list_store_clear (sidebar->store);
location = nautilus_window_info_get_current_location (sidebar->window);
@@ -149,7 +191,7 @@
if (strcmp (g_get_home_dir(), desktop_path) != 0) {
mount_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ());
last_iter = add_place (sidebar->store, PLACES_BUILT_IN,
- _("Home"), "gnome-fs-home", mount_uri);
+ _("Home"), "gnome-fs-home", mount_uri, NULL);
if (strcmp (location, mount_uri) == 0) {
gtk_tree_selection_select_iter (selection, &last_iter);
}
@@ -158,7 +200,7 @@
mount_uri = gnome_vfs_get_uri_from_local_path (desktop_path);
last_iter = add_place (sidebar->store, PLACES_BUILT_IN,
- _("Desktop"), "gnome-fs-desktop", mount_uri);
+ _("Desktop"), "gnome-fs-desktop", mount_uri, NULL);
if (strcmp (location, mount_uri) == 0) {
gtk_tree_selection_select_iter (selection, &last_iter);
}
@@ -167,7 +209,7 @@
mount_uri = "file:///"; // No need to strdup
last_iter = add_place (sidebar->store, PLACES_BUILT_IN,
- _("Filesystem"), "gnome-fs-blockdev", mount_uri);
+ _("Filesystem"), "gnome-fs-blockdev", mount_uri, NULL);
if (strcmp (location, mount_uri) == 0) {
gtk_tree_selection_select_iter (selection, &last_iter);
}
@@ -187,11 +229,10 @@
mount_uri = gnome_vfs_volume_get_activation_uri (volume);
name = gnome_vfs_volume_get_display_name (volume);
last_iter = add_place (sidebar->store, PLACES_MOUNTED_VOLUME,
- name, icon, mount_uri);
+ name, icon, mount_uri, volume);
if (strcmp (location, mount_uri) == 0) {
gtk_tree_selection_select_iter (selection, &last_iter);
}
- gnome_vfs_volume_unref (volume);
g_free (icon);
g_free (name);
g_free (mount_uri);
@@ -206,9 +247,8 @@
gtk_list_store_set (sidebar->store, &iter,
PLACES_SIDEBAR_COLUMN_ROW_TYPE, PLACES_SEPARATOR,
-1);
-
+
/* add bookmarks */
-
bookmark_count = nautilus_bookmark_list_length (sidebar->bookmarks);
for (index = 0; index < bookmark_count; ++index) {
bookmark = nautilus_bookmark_list_item_at (sidebar->bookmarks, index);
@@ -217,7 +257,7 @@
icon = nautilus_bookmark_get_icon (bookmark);
mount_uri = nautilus_bookmark_get_uri (bookmark);
last_iter = add_place (sidebar->store, PLACES_BOOKMARK,
- name, icon, mount_uri);
+ name, icon, mount_uri, bookmark);
if (strcmp (location, mount_uri) == 0) {
gtk_tree_selection_select_iter (selection, &last_iter);
}
@@ -225,9 +265,9 @@
g_free (icon);
g_free (mount_uri);
}
-
- g_free (location);
+ g_free (location);
+
}
static gboolean
@@ -361,6 +401,168 @@
}
+static gboolean
+is_uri_directory (const char *uri)
+{
+ gboolean result;
+ NautilusFile *file;
+
+ file = nautilus_file_get (uri);
+ if (!file) {
+ return FALSE;
+ }
+ result = nautilus_file_is_directory (file);
+ nautilus_file_unref (file);
+ return result;
+}
+
+static gboolean
+drag_motion_callback (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ guint32 time,
+ gpointer data)
+{
+ NautilusPlacesSidebar *sidebar;
+ GtkTreePath *path;
+ GtkTreeViewDropPosition pos;
+
+ sidebar = NAUTILUS_PLACES_SIDEBAR (data);
+
+ gtk_tree_view_get_dest_row_at_pos (sidebar->tree_view,
+ x, y, &path, &pos);
+
+ if (path) {
+ gtk_tree_view_set_drag_dest_row
+ (sidebar->tree_view,
+ path,
+ GTK_TREE_VIEW_DROP_INTO_OR_BEFORE);
+ gtk_tree_path_free (path);
+ } else {
+ gtk_tree_view_set_drag_dest_row (sidebar->tree_view,
+ NULL,
+ 0);
+ }
+ return TRUE;
+}
+
+static void
+drag_leave_callback (GtkWidget *widget,
+ GdkDragContext *context,
+ guint32 time,
+ gpointer data)
+{
+ NautilusPlacesSidebar *sidebar;
+
+ sidebar = NAUTILUS_PLACES_SIDEBAR (data);
+
+ gtk_tree_view_set_drag_dest_row (sidebar->tree_view,
+ NULL,
+ 0);
+}
+
+
+static void
+drag_data_received_callback (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time_,
+ gpointer user_data)
+{
+ NautilusPlacesSidebar *sidebar;
+ GtkListStore *store;
+ gboolean abort_drag_drop;
+ GtkTreePath *path;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GList *item_uris;
+ char *uri;
+
+ sidebar = NAUTILUS_PLACES_SIDEBAR (user_data);
+ store = GTK_LIST_STORE (gtk_tree_view_get_model (sidebar->tree_view));
+ model = gtk_tree_view_get_model (sidebar->tree_view);
+ abort_drag_drop = FALSE;
+ item_uris = NULL;
+
+ if (!gtk_tree_view_get_path_at_pos (sidebar->tree_view, x, y, &path, NULL, NULL, NULL)) {
+ /* add dragged folders to bookmarks */
+ gtk_tree_path_free (path);
+ if (selection_data->target == gdk_atom_intern ("text/uri-list", FALSE)) {
+
+ char **uris;
+ int i;
+
+ uris = g_uri_list_extract_uris (selection_data->data);
+ for (i = 0; uris[i]; i++) {
+ char *name;
+ NautilusBookmark *bookmark;
+
+ if (!is_uri_directory (uris[i])) {
+ abort_drag_drop = TRUE;
+ break;
+ }
+ name = nautilus_compute_title_for_uri (uris[i]);
+ name = eel_str_middle_truncate (name, MAX_BOOKMARK_LENGTH);
+ bookmark = nautilus_bookmark_new (uris[i], name);
+ g_free (name);
+ if (!nautilus_bookmark_list_contains (sidebar->bookmarks, bookmark)) {
+ nautilus_bookmark_list_append (sidebar->bookmarks, bookmark);
+ } else {
+ g_object_unref (bookmark);
+ }
+ }
+ g_strfreev (uris);
+ if (abort_drag_drop) {
+ eel_run_simple_dialog (
+ GTK_WIDGET (sidebar),
+ FALSE,
+ GTK_MESSAGE_ERROR,
+ _("Only folders can be set as bookmarks"),
+ _("You have attempted to add a non-folder as a bookmark"),
+ _("Bookmark Error"),
+ GTK_STOCK_OK, NULL);
+ }
+ }
+ return;
+ }
+
+ /* copy dragged files to dropped on uri */
+ if (!gtk_tree_model_get_iter (model, &iter, path)) {
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_model_get (model, &iter, PLACES_SIDEBAR_COLUMN_URI, &uri, -1);
+
+ if (uri != NULL) {
+ if (selection_data->target == gdk_atom_intern ("text/uri-list", FALSE)) {
+ char **uris;
+ int i;
+
+ uris = g_uri_list_extract_uris (selection_data->data);
+
+ for (i = 0; uris[i]; i++) {
+ item_uris = g_list_prepend (item_uris, g_strdup (uris[i]));
+ }
+ g_strfreev (uris);
+
+ item_uris = g_list_reverse (item_uris);
+
+ nautilus_file_operations_copy_move (item_uris, NULL, uri,
+ GDK_ACTION_COPY,
+ GTK_WIDGET (sidebar->tree_view),
+ NULL, NULL);
+ }
+ g_free (uri);
+ }
+
+ g_signal_stop_emission_by_name (widget, "drag-data-received");
+}
+
static void
nautilus_places_sidebar_init (NautilusPlacesSidebar *sidebar)
{
@@ -414,7 +616,8 @@
G_TYPE_INT,
G_TYPE_STRING,
G_TYPE_STRING,
- GDK_TYPE_PIXBUF
+ GDK_TYPE_PIXBUF,
+ G_TYPE_POINTER
);
gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (sidebar->store));
@@ -433,10 +636,28 @@
selection = gtk_tree_view_get_selection (tree_view);
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+ gtk_drag_dest_set (GTK_WIDGET (tree_view),
+ GTK_DEST_DEFAULT_ALL,
+ dest_targets,
+ 1,
+ GDK_ACTION_COPY);
+
g_signal_connect_object
(tree_view, "row_activated",
G_CALLBACK (row_activated_callback), sidebar, 0);
+ g_signal_connect_object (tree_view,
+ "drag_motion",
+ G_CALLBACK (drag_motion_callback),
+ sidebar, 0);
+ g_signal_connect_object (tree_view,
+ "drag_leave",
+ G_CALLBACK (drag_leave_callback),
+ sidebar, 0);
+
+ g_signal_connect (tree_view, "drag-data-received",
+ G_CALLBACK (drag_data_received_callback), sidebar);
+
eel_preferences_add_callback (NAUTILUS_PREFERENCES_CLICK_POLICY,
click_policy_changed_callback,
sidebar);
@@ -458,6 +679,8 @@
g_free (sidebar->uri);
sidebar->uri = NULL;
+ unref_volumes (sidebar);
+
if (sidebar->store != NULL) {
g_object_unref (sidebar->store);
sidebar->store = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]