Commit 8425aa1f authored by Jesse van den Kieboom's avatar Jesse van den Kieboom

Moved handling drag and drop of the view from GeditWindow into GeditView.

	* gedit-utils.h:
	* gedit-utils.c:
	* gedit-window.c:
	* gedit-view.c:
	* gedit-view.h:
	
	Moved handling drag and drop of the view from GeditWindow into 
	GeditView. Added a signal 'drop-uris' to GeditView which is emitted
	when uris have been dropped on the view. All the dnd for the view is
	now handled in the default signal handlers for drag_motion, drag_drop
	and drag_data_received. This way, the default behaviour of gedit
	loading uris dropped on the view can be changed by connecting to
	the drag_drop and drag_data_received signals from for example a 
	plugin. This wasn't possible before because the window connected
	signals to the view which made it impossible to intervene the signal
	handling.

svn path=/trunk/; revision=5742
parent f2b74309
2007-07-25 Jesse van den Kieboom <jesse@icecrew.nl>
* gedit-utils.h:
* gedit-utils.c:
* gedit-window.c:
* gedit-view.c:
* gedit-view.h:
Moved handling drag and drop of the view from GeditWindow into
GeditView. Added a signal 'drop-uris' to GeditView which is emitted
when uris have been dropped on the view. All the dnd for the view is
now handled in the default signal handlers for drag_motion, drag_drop
and drag_data_received. This way, the default behaviour of gedit
loading uris dropped on the view can be changed by connecting to
the drag_drop and drag_data_received signals from for example a
plugin. This wasn't possible before because the window connected
signals to the view which made it impossible to intervene the signal
handling.
2007-07-23 Paolo Borelli <pborelli@katamail.com>
* bindings/python/gedit.defs:
......
......@@ -1139,3 +1139,45 @@ gedit_utils_format_uri_for_display (const gchar *uri)
return uri_for_display;
}
}
/**
* gedit_utils_drop_get_uris:
* @selection_data: the #GtkSelectionData from drag_data_received
* @info: the info from drag_data_received
*
* Create a list of valid uri's from a uri-list drop.
*
* Return value: a string array which will hold the uris or NULL if there
* were no valid uris. g_strfreev should be used when the
* string array is no longer used
*/
gchar **
gedit_utils_drop_get_uris (GtkSelectionData *selection_data)
{
gchar **uris;
gint i;
gint p = 0;
gchar **uri_list;
uris = g_uri_list_extract_uris ((gchar *) selection_data->data);
uri_list = g_new0(gchar *, g_strv_length (uris) + 1);
for (i = 0; uris[i] != NULL; i++)
{
gchar *uri;
uri = gedit_utils_make_canonical_uri_from_shell_arg (uris[i]);
/* Silently ignore malformed URI/filename */
if (uri != NULL)
uri_list[p++] = uri;
}
if (*uri_list == NULL)
{
g_free(uri_list);
return NULL;
}
return uri_list;
}
......@@ -146,6 +146,9 @@ gchar *gedit_utils_make_canonical_uri_from_shell_arg
* resulting string */
gchar *gedit_utils_format_uri_for_display (const gchar *uri);
/* Turns data from a drop into a list of well formatted uris */
gchar **gedit_utils_drop_get_uris (GtkSelectionData *selection_data);
G_END_DECLS
#endif /* __GEDIT_UTILS_H__ */
......
......@@ -61,6 +61,11 @@ typedef enum
SEARCH
} SearchMode;
enum
{
TARGET_URI_LIST = 100
};
struct _GeditViewPrivate
{
GtkTooltips *tooltips;
......@@ -97,25 +102,42 @@ struct _GeditViewPrivate
/* The search entry completion is shared among all the views */
GtkListStore *search_completion_model = NULL;
static void gedit_view_destroy (GtkObject *object);
static void gedit_view_finalize (GObject *object);
static gint gedit_view_focus_out (GtkWidget *widget,
GdkEventFocus *event);
static gboolean start_interactive_search (GeditView *view);
static gboolean start_interactive_goto_line (GeditView *view);
static gboolean reset_searched_text (GeditView *view);
static void hide_search_window (GeditView *view,
gboolean cancel);
static gint gedit_view_expose (GtkWidget *widget,
GdkEventExpose *event);
static void search_highlight_updated_cb (GeditDocument *doc,
GtkTextIter *start,
GtkTextIter *end,
GeditView *view);
static void gedit_view_destroy (GtkObject *object);
static void gedit_view_finalize (GObject *object);
static gint gedit_view_focus_out (GtkWidget *widget,
GdkEventFocus *event);
static gboolean gedit_view_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static void gedit_view_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time);
static gboolean gedit_view_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static gboolean start_interactive_search (GeditView *view);
static gboolean start_interactive_goto_line (GeditView *view);
static gboolean reset_searched_text (GeditView *view);
static void hide_search_window (GeditView *view,
gboolean cancel);
static gint gedit_view_expose (GtkWidget *widget,
GdkEventExpose *event);
static void search_highlight_updated_cb (GeditDocument *doc,
GtkTextIter *start,
GtkTextIter *end,
GeditView *view);
G_DEFINE_TYPE(GeditView, gedit_view, GTK_TYPE_SOURCE_VIEW)
......@@ -125,6 +147,7 @@ enum
START_INTERACTIVE_SEARCH,
START_INTERACTIVE_GOTO_LINE,
RESET_SEARCHED_TEXT,
DROP_URIS,
LAST_SIGNAL
};
......@@ -160,6 +183,24 @@ gedit_view_class_init (GeditViewClass *klass)
widget_class->focus_out_event = gedit_view_focus_out;
widget_class->expose_event = gedit_view_expose;
/*
* Override the gtk_text_view_drag_motion and drag_drop
* functions to get URIs
*
* If the mime type is text/uri-list, then we will accept
* the potential drop, or request the data (depending on the
* function).
*
* If the drag context has any other mime type, then pass the
* information onto the GtkTextView's standard handlers.
* (widget_class->function_name).
*
* See bug #89881 for details
*/
widget_class->drag_motion = gedit_view_drag_motion;
widget_class->drag_data_received = gedit_view_drag_data_received;
widget_class->drag_drop = gedit_view_drag_drop;
klass->start_interactive_search = start_interactive_search;
klass->start_interactive_goto_line = start_interactive_goto_line;
......@@ -192,6 +233,24 @@ gedit_view_class_init (GeditViewClass *klass)
gedit_marshal_BOOLEAN__NONE,
G_TYPE_BOOLEAN, 0);
/* A new signal DROP_URIS has been added to allow plugins to intercept
* the default dnd behaviour of 'text/uri-list'. GeditView now handles
* dnd in the default handlers of drag_drop, drag_motion and
* drag_data_received. The view emits drop_uris from drag_data_received
* if valid uris have been dropped. Plugins should connect to
* drag_motion, drag_drop and drag_data_received to change this
* default behaviour. They should _NOT_ use this signal because this
* will not prevent gedit from loading the uri
*/
view_signals[DROP_URIS] =
g_signal_new ("drop_uris",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GeditViewClass, drop_uris),
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1, G_TYPE_STRV);
g_type_class_add_private (klass, sizeof (GeditViewPrivate));
binding_set = gtk_binding_set_by_class (klass);
......@@ -218,7 +277,9 @@ scroll_to_cursor_on_init (GeditView *view)
static void
gedit_view_init (GeditView *view)
{
{
GtkTargetList *tl;
gedit_debug (DEBUG_VIEW);
view->priv = GEDIT_VIEW_GET_PRIVATE (view);
......@@ -265,7 +326,13 @@ gedit_view_init (GeditView *view)
view->priv->scroll_idle = g_idle_add ((GSourceFunc) scroll_to_cursor_on_init, view);
view->priv->typeselect_flush_timeout = 0;
view->priv->wrap_around = TRUE;
view->priv->wrap_around = TRUE;
/* Drag and drop support */
tl = gtk_drag_dest_get_target_list (GTK_WIDGET (view));
if (tl != NULL)
gtk_target_list_add_uri_targets (tl, TARGET_URI_LIST);
}
static void
......@@ -1637,6 +1704,101 @@ gedit_view_expose (GtkWidget *widget,
return (* GTK_WIDGET_CLASS (gedit_view_parent_class)->expose_event)(widget, event);
}
static GdkAtom
drag_get_uri_target (GtkWidget *widget,
GdkDragContext *context)
{
GdkAtom target;
GtkTargetList *tl;
tl = gtk_target_list_new (NULL, 0);
gtk_target_list_add_uri_targets (tl, 0);
target = gtk_drag_dest_find_target (widget, context, tl);
gtk_target_list_unref (tl);
return target;
}
static gboolean
gedit_view_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
gboolean result;
/* If this is a URL, deal with it here, or pass to the text view */
if (drag_get_uri_target (widget, context) != GDK_NONE)
{
gdk_drag_status (context, context->suggested_action, time);
result = TRUE;
}
else
{
/* Chain up */
result = GTK_WIDGET_CLASS (gedit_view_parent_class)->drag_motion (widget, context, x, y, time);
}
return result;
}
static void
gedit_view_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time)
{
gchar **uri_list;
/* If this is an URL emit DROP_URIS, otherwise chain up the signal */
if (info == TARGET_URI_LIST)
{
uri_list = gedit_utils_drop_get_uris (selection_data);
if (uri_list != NULL)
{
g_signal_emit (widget, view_signals[DROP_URIS], 0, uri_list);
g_strfreev (uri_list);
}
}
else
{
GTK_WIDGET_CLASS (gedit_view_parent_class)->drag_data_received (widget, context, x, y, selection_data, info, time);
}
}
static gboolean
gedit_view_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
gboolean result;
GdkAtom target;
/* If this is a URL, just get the drag data */
target = drag_get_uri_target (widget, context);
if (target != GDK_NONE)
{
gtk_drag_get_data (widget, context, target, time);
result = TRUE;
}
else
{
/* Chain up */
result = GTK_WIDGET_CLASS (gedit_view_parent_class)->drag_drop (widget, context, x, y, time);
}
return result;
}
static void
search_highlight_updated_cb (GeditDocument *doc,
GtkTextIter *start,
......
......@@ -79,6 +79,8 @@ struct _GeditViewClass
gboolean (* start_interactive_search) (GeditView *view);
gboolean (* start_interactive_goto_line)(GeditView *view);
gboolean (* reset_searched_text) (GeditView *view);
void (* drop_uris) (GeditView *view,
gchar **uri_list);
};
/*
......
......@@ -83,11 +83,6 @@ enum
TARGET_URI_LIST = 100
};
static const GtkTargetEntry drag_types[] =
{
{ "text/uri-list", 0, TARGET_URI_LIST },
};
G_DEFINE_TYPE(GeditWindow, gedit_window, GTK_TYPE_WINDOW)
static void recent_manager_changed (GtkRecentManager *manager,
......@@ -2279,138 +2274,84 @@ sync_name (GeditTab *tab,
gedit_plugins_engine_update_plugins_ui (window, FALSE);
}
static void
drag_data_received_cb (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
static GeditWindow *
get_drop_window (GtkWidget *widget)
{
GtkWidget *target_window;
gchar **uris;
GSList *uri_list = NULL;
gint i;
if (info != TARGET_URI_LIST)
return;
target_window = gtk_widget_get_toplevel (widget);
g_return_val_if_fail (GEDIT_IS_WINDOW (target_window), NULL);
g_return_if_fail (widget != NULL);
if ((GEDIT_WINDOW(target_window)->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION) != 0)
return NULL;
return GEDIT_WINDOW (target_window);
}
target_window = gtk_widget_get_toplevel (widget);
g_return_if_fail (GEDIT_IS_WINDOW (target_window));
static void
load_uris_from_drop (GeditWindow *window,
gchar **uri_list)
{
GSList *uris = NULL;
gint i;
if ((GEDIT_WINDOW(target_window)->priv->state & GEDIT_WINDOW_STATE_SAVING_SESSION) != 0)
if (uri_list == NULL)
return;
uris = g_uri_list_extract_uris ((gchar *) selection_data->data);
for (i = 0; uris[i] != NULL; i++)
for (i = 0; uri_list[i] != NULL; ++i)
{
gchar *uri;
uri = gedit_utils_make_canonical_uri_from_shell_arg (uris[i]);
/* Silently ignore malformed URI/filename */
if (uri != NULL)
uri_list = g_slist_prepend (uri_list, uri);
uris = g_slist_prepend (uris, uri_list[i]);
}
g_strfreev (uris);
if (uri_list == NULL)
return;
uri_list = g_slist_reverse (uri_list);
gedit_commands_load_uris (GEDIT_WINDOW (target_window),
uri_list,
uris = g_slist_reverse (uris);
gedit_commands_load_uris (window,
uris,
NULL,
0);
g_slist_foreach (uri_list, (GFunc) g_free, NULL);
g_slist_free (uri_list);
g_slist_free (uris);
}
/*
* Override the gtk_text_view_drag_motion and drag_drop
* functions to get URIs
*
* If the mime type is text/uri-list, then we will accept
* the potential drop, or request the data (depending on the
* function).
*
* If the drag context has any other mime type, then pass the
* information onto the GtkTextView's standard handlers.
* (widget_class->function_name).
*
* See bug #89881 for details
*/
static gboolean
drag_motion_cb (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
/* Handle drops on the GeditWindow */
static void
drag_data_received_cb (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
GtkTargetList *tl;
GtkWidgetClass *widget_class;
gboolean result;
GeditWindow *window;
gchar **uri_list;
tl = gtk_target_list_new (drag_types,
G_N_ELEMENTS (drag_types));
window = get_drop_window (widget);
if (window == NULL)
return;
/* If this is a URL, deal with it here, or pass to the text view */
if (gtk_drag_dest_find_target (widget, context, tl) != GDK_NONE)
{
gdk_drag_status (context, context->suggested_action, time);
result = TRUE;
}
else
if (info == TARGET_URI_LIST)
{
widget_class = GTK_WIDGET_GET_CLASS (widget);
result = (*widget_class->drag_motion) (widget, context, x, y, time);
uri_list = gedit_utils_drop_get_uris(selection_data);
load_uris_from_drop (window, uri_list);
g_strfreev (uri_list);
}
gtk_target_list_unref (tl);
return result;
}
static gboolean
drag_drop_cb (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
/* Handle drops on the GeditView */
static void
drop_uris_cb (GtkWidget *widget,
gchar **uri_list)
{
GtkTargetList *tl;
GtkWidgetClass *widget_class;
gboolean result;
GdkAtom target;
tl = gtk_target_list_new (drag_types,
G_N_ELEMENTS (drag_types));
/* If this is a URL, just get the drag data */
target = gtk_drag_dest_find_target (widget, context, tl);
if (target != GDK_NONE)
{
gtk_drag_get_data (widget, context, target, time);
result = TRUE;
}
else
{
widget_class = GTK_WIDGET_GET_CLASS (widget);
result = (*widget_class->drag_drop) (widget, context, x, y, time);
}
GeditWindow *window;
gtk_target_list_unref (tl);
window = get_drop_window (widget);
if (window == NULL)
return;
return result;
load_uris_from_drop (window, uri_list);
}
static void
......@@ -2536,7 +2477,6 @@ notebook_tab_added (GeditNotebook *notebook,
{
GeditView *view;
GeditDocument *doc;
GtkTargetList *tl;
GtkAction *action;
gedit_debug (DEBUG_WINDOW);
......@@ -2605,29 +2545,9 @@ notebook_tab_added (GeditNotebook *notebook,
update_documents_list_menu (window);
/* CHECK: it seems to me this does not work when tab are moved between
windows */
/* Drag and drop support */
tl = gtk_drag_dest_get_target_list (GTK_WIDGET (view));
g_return_if_fail (tl != NULL);
gtk_target_list_add_table (tl, drag_types, G_N_ELEMENTS (drag_types));
g_signal_connect (view,
"drag_data_received",
G_CALLBACK (drag_data_received_cb),
NULL);
/* Get signals before the standard text view functions to deal
* with uris for text files.
*/
g_signal_connect (view,
"drag_motion",
G_CALLBACK (drag_motion_cb),
NULL);
g_signal_connect (view,
"drag_drop",
G_CALLBACK (drag_drop_cb),
"drop_uris",
G_CALLBACK (drop_uris_cb),
NULL);
update_window_state (window);
......@@ -2684,13 +2604,7 @@ notebook_tab_removed (GeditNotebook *notebook,
G_CALLBACK (editable_changed),
window);
g_signal_handlers_disconnect_by_func (view,
G_CALLBACK (drag_data_received_cb),
NULL);
g_signal_handlers_disconnect_by_func (view,
G_CALLBACK (drag_motion_cb),
NULL);
g_signal_handlers_disconnect_by_func (view,
G_CALLBACK (drag_drop_cb),
G_CALLBACK (drop_uris_cb),
NULL);
g_return_if_fail (window->priv->num_tabs >= 0);
......@@ -3147,6 +3061,7 @@ gedit_window_init (GeditWindow *window)
{
static gboolean is_first = TRUE;
GtkWidget *main_box;
GtkTargetList *tl;
gedit_debug (DEBUG_WINDOW);
......@@ -3219,15 +3134,28 @@ gedit_window_init (GeditWindow *window)
gtk_widget_show (window->priv->hpaned);
gtk_widget_show (window->priv->vpaned);
/* Drag and drop support */
/* Drag and drop support, set targets to NULL because we add the
default uri_targets below */
gtk_drag_dest_set (GTK_WIDGET (window),
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_DROP,
drag_types,
G_N_ELEMENTS (drag_types),
NULL,
0,
GDK_ACTION_COPY);
/* Add uri targets */
tl = gtk_drag_dest_get_target_list (GTK_WIDGET (window));
if (tl == NULL)
{
tl = gtk_target_list_new (NULL, 0);
gtk_drag_dest_set_target_list (GTK_WIDGET (window), tl);
gtk_target_list_unref (tl);
}
gtk_target_list_add_uri_targets (tl, TARGET_URI_LIST);
/* Connect signals */
g_signal_connect (window->priv->notebook,
"switch_page",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment