[gitg] Implemented XDS DND protocol for direct save
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gitg] Implemented XDS DND protocol for direct save
- Date: Mon, 11 Jan 2010 21:35:05 +0000 (UTC)
commit 19c533f8736914a308397e21cc73063d909fb093
Author: Jesse van den Kieboom <jessevdk gnome org>
Date: Mon Jan 11 22:34:51 2010 +0100
Implemented XDS DND protocol for direct save
This allows you to for example drag a revision into nautilus generating
a format patch
gitg/gitg-dnd.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 163 insertions(+), 2 deletions(-)
---
diff --git a/gitg/gitg-dnd.c b/gitg/gitg-dnd.c
index 0613271..bbe8150 100644
--- a/gitg/gitg-dnd.c
+++ b/gitg/gitg-dnd.c
@@ -10,15 +10,22 @@ enum
DRAG_TARGET_TREEISH,
DRAG_TARGET_REVISION,
DRAG_TARGET_TEXT,
- DRAG_TARGET_URI
+ DRAG_TARGET_URI,
+ DRAG_TARGET_DIRECT_SAVE
};
+#define XDS_ATOM gdk_atom_intern ("XdndDirectSave0", FALSE)
+#define TEXT_ATOM gdk_atom_intern ("text/plain", FALSE)
+
+#define MAX_XDS_ATOM_VAL_LEN 4096
+
static GtkTargetEntry target_dest_entries[] = {
{"gitg-ref", GTK_TARGET_SAME_WIDGET, DRAG_TARGET_REF}
};
static GtkTargetEntry target_source_entries[] = {
- {"x-gitg/treeish-list", GTK_TARGET_OTHER_APP, DRAG_TARGET_TREEISH}
+ {"x-gitg/treeish-list", GTK_TARGET_OTHER_APP, DRAG_TARGET_TREEISH},
+ {"XdndDirectSave0", GTK_TARGET_OTHER_APP, DRAG_TARGET_DIRECT_SAVE}
};
typedef struct
@@ -41,6 +48,7 @@ typedef struct
GitgRevision *revision;
guint scroll_timeout;
+ gchar *xds_destination;
} GitgDndData;
#define GITG_DND_DATA_KEY "GitgDndDataKey"
@@ -322,6 +330,27 @@ create_revision_drag_icon (GtkTreeView *tree_view,
return ret;
}
+static gchar *
+generate_format_patch_filename (GitgRevision *revision)
+{
+ gchar *subject = g_strdup (gitg_revision_get_subject (revision));
+ gchar *ptr = subject;
+ gchar *filename;
+
+ do
+ {
+ if (g_utf8_get_char (ptr) == ' ')
+ {
+ *ptr = '-';
+ }
+ } while (*(ptr = g_utf8_next_char (ptr)));
+
+ filename = g_strdup_printf ("0001-%s.patch", subject);
+ g_free (subject);
+
+ return filename;
+}
+
static void
begin_drag (GtkWidget *widget,
GdkEvent *event,
@@ -394,6 +423,17 @@ begin_drag (GtkWidget *widget,
1,
event);
GdkPixbuf *icon;
+ gchar *filename;
+
+ filename = generate_format_patch_filename (revision);
+
+ gdk_property_change (context->source_window,
+ XDS_ATOM, TEXT_ATOM,
+ 8, GDK_PROP_MODE_REPLACE,
+ (guchar *) filename,
+ strlen (filename));
+
+ g_free (filename);
icon = create_revision_drag_icon (tree_view, revision);
@@ -749,6 +789,48 @@ revision_to_treeish (GitgRepository *repository,
return ret;
}
+static gchar *
+get_xds_filename (GdkDragContext *context)
+{
+ gchar *ret;
+
+ if (context == NULL || context->source_window == NULL)
+ {
+ return NULL;
+ }
+
+ guint len;
+
+ if (gdk_property_get (context->source_window,
+ XDS_ATOM, TEXT_ATOM,
+ 0, MAX_XDS_ATOM_VAL_LEN,
+ FALSE, NULL, NULL, &len,
+ (unsigned char **) &ret))
+ {
+ ret[len] = '\0';
+ return ret;
+ }
+
+ return NULL;
+}
+
+static gboolean
+has_direct_save (GdkDragContext *context)
+{
+ gboolean ret;
+
+ if (!g_list_find (context->targets, XDS_ATOM))
+ {
+ return FALSE;
+ }
+
+ gchar *filename = get_xds_filename (context);
+ ret = filename && *filename;
+ g_free (filename);
+
+ return ret;
+}
+
static void
gitg_drag_source_data_get_cb (GtkWidget *widget,
GdkDragContext *context,
@@ -764,6 +846,33 @@ gitg_drag_source_data_get_cb (GtkWidget *widget,
GitgRepository *repository = GITG_REPOSITORY (gtk_tree_view_get_model (GTK_TREE_VIEW (widget)));
+ if (has_direct_save (context))
+ {
+ gchar *destination = get_xds_filename (context);
+
+ if (destination && *destination)
+ {
+ data->xds_destination = g_strdup (destination);
+
+ gtk_selection_data_set (selection,
+ selection->target,
+ 8,
+ "S",
+ 1);
+ }
+ else
+ {
+ gtk_selection_data_set (selection,
+ selection->target,
+ 8,
+ "E",
+ 1);
+ }
+
+ g_free (destination);
+ return;
+ }
+
switch (info)
{
case DRAG_TARGET_TEXT:
@@ -792,6 +901,52 @@ gitg_drag_source_data_get_cb (GtkWidget *widget,
}
}
+static void
+format_patch (GtkTreeView *tree_view,
+ GitgDndData *data)
+{
+ GitgRepository *repository;
+
+ repository = GITG_REPOSITORY (gtk_tree_view_get_model (tree_view));
+ gchar *sha1 = gitg_revision_get_sha1 (data->revision);
+
+ /* FIXME: this is all sync and bad... */
+ gchar **ret = gitg_repository_command_with_outputv (repository, NULL,
+ "format-patch",
+ "-1",
+ "--stdout",
+ sha1,
+ NULL);
+
+ gchar *content = g_strjoinv ("\n", ret);
+ g_strfreev (ret);
+
+ g_file_set_contents (data->xds_destination, content, -1, NULL);
+
+ g_free (sha1);
+ g_free (content);
+}
+
+static void
+gitg_drag_source_end_cb (GtkTreeView *tree_view,
+ GdkDragContext *context,
+ GitgDndData *data)
+{
+ if (data->revision)
+ {
+ gdk_property_delete (context->source_window, XDS_ATOM);
+
+ if (data->xds_destination != NULL)
+ {
+ /* Do extract it there then */
+ format_patch (tree_view, data);
+
+ g_free (data->xds_destination);
+ data->xds_destination = NULL;
+ }
+ }
+}
+
void
gitg_dnd_enable (GtkTreeView *tree_view,
GitgDndCallback callback,
@@ -861,6 +1016,11 @@ gitg_dnd_enable (GtkTreeView *tree_view,
"drag-leave",
G_CALLBACK (gitg_drag_source_leave_cb),
data);
+
+ g_signal_connect (tree_view,
+ "drag-end",
+ G_CALLBACK (gitg_drag_source_end_cb),
+ data);
}
void
@@ -875,6 +1035,7 @@ gitg_dnd_disable (GtkTreeView *tree_view)
g_signal_handlers_disconnect_by_func (tree_view, gitg_drag_source_drop_cb, data);
g_signal_handlers_disconnect_by_func (tree_view, gitg_drag_source_leave_cb, data);
g_signal_handlers_disconnect_by_func (tree_view, gitg_drag_source_data_get_cb, data);
+ g_signal_handlers_disconnect_by_func (tree_view, gitg_drag_source_end_cb, data);
g_object_set_data (G_OBJECT (tree_view), GITG_DND_DATA_KEY, NULL);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]