diff options
author | Shaun McCance <Shaun McCance> | 2009-09-18 05:17:49 +0800 |
---|---|---|
committer | Shaun McCance <shaunm@gnome.org> | 2009-11-25 04:43:07 +0800 |
commit | 3cbb3a10e138e1f777427311bf33f30cb6d4839e (patch) | |
tree | 5caf382ba69bb4b4c2b24efe4c7133dab0e4c382 /libempathy-gtk | |
parent | d068663d7d73c7dc54b560b3ed9846c218dd8f35 (diff) | |
download | gsoc2013-empathy-3cbb3a10e138e1f777427311bf33f30cb6d4839e.tar gsoc2013-empathy-3cbb3a10e138e1f777427311bf33f30cb6d4839e.tar.gz gsoc2013-empathy-3cbb3a10e138e1f777427311bf33f30cb6d4839e.tar.bz2 gsoc2013-empathy-3cbb3a10e138e1f777427311bf33f30cb6d4839e.tar.lz gsoc2013-empathy-3cbb3a10e138e1f777427311bf33f30cb6d4839e.tar.xz gsoc2013-empathy-3cbb3a10e138e1f777427311bf33f30cb6d4839e.tar.zst gsoc2013-empathy-3cbb3a10e138e1f777427311bf33f30cb6d4839e.zip |
Implemented file drags to contact list, along with row highlights
Diffstat (limited to 'libempathy-gtk')
-rw-r--r-- | libempathy-gtk/empathy-contact-list-view.c | 252 |
1 files changed, 173 insertions, 79 deletions
diff --git a/libempathy-gtk/empathy-contact-list-view.c b/libempathy-gtk/empathy-contact-list-view.c index c19ad32df..04a448817 100644 --- a/libempathy-gtk/empathy-contact-list-view.c +++ b/libempathy-gtk/empathy-contact-list-view.c @@ -88,17 +88,21 @@ enum { enum DndDragType { DND_DRAG_TYPE_CONTACT_ID, - DND_DRAG_TYPE_URL, + DND_DRAG_TYPE_URI_LIST, DND_DRAG_TYPE_STRING, }; static const GtkTargetEntry drag_types_dest[] = { + { "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST }, { "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID }, - { "text/uri-list", 0, DND_DRAG_TYPE_URL }, { "text/plain", 0, DND_DRAG_TYPE_STRING }, { "STRING", 0, DND_DRAG_TYPE_STRING }, }; +static const GtkTargetEntry drag_types_dest_file[] = { + { "text/uri-list", 0, DND_DRAG_TYPE_URI_LIST }, +}; + static const GtkTargetEntry drag_types_source[] = { { "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID }, }; @@ -244,102 +248,143 @@ contact_list_view_drag_data_received (GtkWidget *view, guint time_) { EmpathyContactListViewPriv *priv; - TpAccountManager *account_manager; - EmpathyTpContactFactory *factory = NULL; - TpAccount *account = NULL; GtkTreeModel *model; - GtkTreeViewDropPosition position; - GtkTreePath *path; - const gchar *id; + gboolean success = TRUE; + const gchar *sel_data; gchar **strv = NULL; - const gchar *account_id = NULL; - const gchar *contact_id = NULL; - gchar *new_group = NULL; - gchar *old_group = NULL; - DndGetContactData *data; gboolean is_row; - gboolean success = TRUE; + GtkTreeViewDropPosition position; + GtkTreePath *path; priv = GET_PRIV (view); model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); + sel_data = (const gchar*) gtk_selection_data_get_data (selection); + DEBUG ("Received %s%s drag & drop contact from roster with id:'%s'", + context->action == GDK_ACTION_MOVE ? "move" : "", + context->action == GDK_ACTION_COPY ? "copy" : "", + sel_data); + /* Get destination group information. */ is_row = gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (view), x, y, &path, &position); + if (!is_row) { + success = FALSE; + goto OUT; + } - if (is_row) { + if (info == DND_DRAG_TYPE_CONTACT_ID || info == DND_DRAG_TYPE_STRING) { + TpAccountManager *account_manager; + EmpathyTpContactFactory *factory = NULL; + TpAccount *account = NULL; + const gchar *account_id = NULL; + const gchar *contact_id = NULL; + gchar *new_group = NULL; + gchar *old_group = NULL; + DndGetContactData *data; new_group = empathy_contact_list_store_get_parent_group (model, - path, NULL); + path, NULL); gtk_tree_path_free (path); - } + path = NULL; + + /* Get source group information. */ + if (priv->drag_row) { + path = gtk_tree_row_reference_get_path (priv->drag_row); + if (path) { + old_group = empathy_contact_list_store_get_parent_group ( + model, path, NULL); + gtk_tree_path_free (path); + path = NULL; + } + } - /* Get source group information. */ - if (priv->drag_row) { - path = gtk_tree_row_reference_get_path (priv->drag_row); - if (path) { - old_group = empathy_contact_list_store_get_parent_group ( - model, path, NULL); - gtk_tree_path_free (path); + if (!tp_strdiff (old_group, new_group)) { + g_free (new_group); + g_free (old_group); + goto OUT; } - } - if (!tp_strdiff (old_group, new_group)) { - g_free (new_group); - g_free (old_group); - goto OUT; - } + /* FIXME: should probably make sure the account manager is prepared + * before calling _ensure_account on it. See bug 600115. */ + account_manager = tp_account_manager_dup (); + strv = g_strsplit (sel_data, ":", 2); + if (g_strv_length (strv) == 2) { + account_id = strv[0]; + contact_id = strv[1]; + account = tp_account_manager_ensure_account (account_manager, account_id); + } + if (account) { + TpConnection *connection; + + connection = tp_account_get_connection (account); + if (connection) { + factory = empathy_tp_contact_factory_dup_singleton (connection); + } + g_object_unref (account_manager); + + if (!factory) { + DEBUG ("Failed to get factory for account '%s'", account_id); + success = FALSE; + g_free (new_group); + g_free (old_group); + goto OUT; + } + } - id = (const gchar*) gtk_selection_data_get_data (selection); - DEBUG ("Received %s%s drag & drop contact from roster with id:'%s'", - context->action == GDK_ACTION_MOVE ? "move" : "", - context->action == GDK_ACTION_COPY ? "copy" : "", - id); - - /* FIXME: should probably make sure the account manager is prepared - * before calling _ensure_account on it. See bug 600115. */ - account_manager = tp_account_manager_dup (); - strv = g_strsplit (id, ":", 2); - if (g_strv_length (strv) == 2) { - account_id = strv[0]; - contact_id = strv[1]; - account = tp_account_manager_ensure_account (account_manager, account_id); - } - if (account) { - TpConnection *connection; + data = g_slice_new0 (DndGetContactData); + data->new_group = new_group; + data->old_group = old_group; + data->action = context->action; - connection = tp_account_get_connection (account); - if (connection) { - factory = empathy_tp_contact_factory_dup_singleton (connection); - } - } - g_object_unref (account_manager); + /* FIXME: We should probably wait for the cb before calling + * gtk_drag_finish */ + empathy_tp_contact_factory_get_from_id (factory, contact_id, + contact_list_view_drag_got_contact, + data, (GDestroyNotify) contact_list_view_dnd_get_contact_free, + G_OBJECT (view)); - if (!factory) { - DEBUG ("Failed to get factory for account '%s'", account_id); - success = FALSE; - g_free (new_group); - g_free (old_group); - goto OUT; + g_object_unref (factory); } + else if (info == DND_DRAG_TYPE_URI_LIST) { + GtkTreeIter iter; + const gchar *nl; + gchar *uri; + GFile *file; + EmpathyContact *contact; + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact, + -1); + if (!contact) { + success = FALSE; + goto OUT; + } - data = g_slice_new0 (DndGetContactData); - data->new_group = new_group; - data->old_group = old_group; - data->action = context->action; + nl = strstr (sel_data, "\r\n"); + if (!nl) { + nl = strchr (sel_data, '\n'); + } + if (nl) { + uri = g_strndup (sel_data, nl - sel_data); + file = g_file_new_for_uri (uri); + g_free (uri); + } + else { + file = g_file_new_for_uri (sel_data); + } - /* FIXME: We should probably wait for the cb before calling - * gtk_drag_finish */ - empathy_tp_contact_factory_get_from_id (factory, contact_id, - contact_list_view_drag_got_contact, - data, (GDestroyNotify) contact_list_view_dnd_get_contact_free, - G_OBJECT (view)); + empathy_send_file (contact, file); - g_object_unref (factory); + g_object_unref (file); + gtk_drag_finish (context, TRUE, FALSE, time_); + } OUT: + gtk_tree_path_free (path); g_strfreev (strv); gtk_drag_finish (context, success, FALSE, GDK_CURRENT_TIME); } @@ -363,12 +408,25 @@ contact_list_view_drag_motion (GtkWidget *widget, gint y, guint time_) { + EmpathyContactListViewPriv *priv; + GtkTreeModel *model; + static GtkTargetList *file_targets = NULL; + GdkAtom target; + GtkTreeIter iter; static DragMotionData *dm = NULL; GtkTreePath *path; gboolean is_row; gboolean is_different = FALSE; gboolean cleanup = TRUE; - int action = 0; + gboolean retval = TRUE; + + priv = GET_PRIV (EMPATHY_CONTACT_LIST_VIEW (widget)); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + if (file_targets == NULL) { + file_targets = gtk_target_list_new (drag_types_dest_file, + G_N_ELEMENTS (drag_types_dest_file)); + } is_row = gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, @@ -387,15 +445,51 @@ contact_list_view_drag_motion (GtkWidget *widget, cleanup &= FALSE; } - if (context->actions == GDK_ACTION_COPY) { - action = context->suggested_action; - } else if (context->actions & GDK_ACTION_MOVE) { - action = GDK_ACTION_MOVE; + if (path == NULL) { + gdk_drag_status (context, 0, time_); + gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, 0); + return FALSE; + } + target = gtk_drag_dest_find_target (widget, context, file_targets); + gtk_tree_model_get_iter (model, &iter, path); + + if (target == GDK_NONE) { + gboolean is_group; + gtk_tree_model_get (model, &iter, + EMPATHY_CONTACT_LIST_STORE_COL_IS_GROUP, &is_group, + -1); + if (is_group) { + gdk_drag_status (context, GDK_ACTION_MOVE, time_); + gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), + path, + GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); + } + else { + gdk_drag_status (context, 0, time_); + gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, 0); + retval = FALSE; + } + } + else { + EmpathyContact *contact; + gtk_tree_model_get (model, &iter, + EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact, + -1); + if (contact) { + gdk_drag_status (context, GDK_ACTION_COPY, time_); + gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), + path, + GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); + } + else { + gdk_drag_status (context, 0, time_); + gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget), NULL, 0); + retval = FALSE; + } } - gdk_drag_status (context, action, time_); if (!is_different && !cleanup) { - return TRUE; + return retval; } if (dm) { @@ -420,7 +514,7 @@ contact_list_view_drag_motion (GtkWidget *widget, dm); } - return TRUE; + return retval; } static void @@ -973,7 +1067,7 @@ contact_list_view_setup (EmpathyContactListView *view) /* Setup view */ g_object_set (view, "headers-visible", FALSE, - "reorderable", TRUE, + "reorderable", FALSE, "show-expanders", FALSE, NULL); |