# HG changeset patch # User Sean Egan # Date 1047369473 0 # Node ID cb5b23dfd82ba6cf1f0c1193a50e7424fe81695f # Parent ac7ca2bd6d4f8a4b69b384a07f803959ddc6e3ce [gaim-migrate @ 5013] Started on buddy list drag-n-drop. This will be useful mostly for editing the buddy list but I decided to sleep before doing that. You can drag a buddy into a conversation window now, though. Which is cool. But, even that's not complete yet. I'll have fun tomorrow. committer: Tailor Script diff -r ac7ca2bd6d4f -r cb5b23dfd82b src/buddy.c --- a/src/buddy.c Tue Mar 11 03:59:42 2003 +0000 +++ b/src/buddy.c Tue Mar 11 07:57:53 2003 +0000 @@ -178,6 +178,7 @@ GtkTreeIter iter; GtkWidget *menu, *menuitem; GtkWidget *image; + GtkTreeSelection *sel; GList *list; struct prpl *prpl; @@ -232,7 +233,12 @@ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time); - return FALSE; +#if (1) /* This code only exists because GTK doesn't work. If we return FALSE here, as would be normal + * the event propoagates down and somehow gets interpreted as the start of a drag event. */ + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); + gtk_tree_selection_select_path(sel, path); + return TRUE; +#endif } static void gaim_gtk_blist_reordered_cb(GtkTreeModel *model, @@ -284,6 +290,43 @@ } } +static void gaim_gtk_blist_drag_data_get_cb (GtkWidget *widget, + GdkDragContext *dc, + GtkSelectionData *data, + guint info, + guint time, + gpointer *null) +{ + if (data->target == gdk_atom_intern("GAIM_BUDDY", FALSE)) { + GtkTreeRowReference *ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); + GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(ref); + GtkTreeIter iter; + GaimBlistNode *node = NULL; + GValue val = {0}; + gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, sourcerow); + gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); + node = g_value_get_pointer(&val); + if (GAIM_BLIST_NODE_IS_BUDDY(node)) + gtk_selection_data_set (data, + gdk_atom_intern ("GAIM_BUDDY", FALSE), + 8, /* bits */ + (void*)&node, + sizeof (node)); + } + +} + +static void gaim_gtk_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, + GtkSelectionData *sd, guint info, guint t) +{ + if (sd->target == gdk_atom_intern("GAIM_BUDDY", FALSE)) { + struct buddy *b = NULL; + GtkTreePath *path = NULL; + memcpy(&b, sd->data, sizeof(b)); + gtk_tree_view_get_dest_row_at_pos(widget, x, y, &path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); + } +} + /*************************************************** * Crap * ***************************************************/ @@ -553,6 +596,8 @@ node->ui_data = g_new0(struct gaim_gtk_blist_node, 1); } +enum {DRAG_BUDDY, DRAG_ROW}; + static void gaim_gtk_blist_show(struct gaim_buddy_list *list) { GtkItemFactory *ift; @@ -561,6 +606,8 @@ GtkWidget *sw; GtkWidget *button; GtkSizeGroup *sg; + GtkTargetEntry gte[] = {{"GAIM_BUDDY", GTK_TARGET_SAME_APP, DRAG_ROW}, + {"application/x-im-contact", 0, DRAG_BUDDY}}; if (gtkblist) { gtk_widget_show(gtkblist->window); @@ -600,10 +647,17 @@ gtkblist->treemodel = gtk_tree_store_new(BLIST_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); - /* This is broken because GTK is broken - g_signal_connect(G_OBJECT(gtkblist->treemodel), "row-reordered", gaim_gtk_blist_reordered_cb, NULL); */ - + gtkblist->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gtkblist->treemodel)); + + /* Set up dnd */ + gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(gtkblist->treeview), GDK_BUTTON1_MASK, gte, + 2, GDK_ACTION_COPY); + gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(gtkblist->treeview), gte, 2, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", gaim_gtk_blist_drag_data_rcv_cb, NULL); + g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-get", gaim_gtk_blist_drag_data_get_cb, NULL); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(gtkblist->treeview), FALSE); diff -r ac7ca2bd6d4f -r cb5b23dfd82b src/gtkconv.c --- a/src/gtkconv.c Tue Mar 11 03:59:42 2003 +0000 +++ b/src/gtkconv.c Tue Mar 11 07:57:53 2003 +0000 @@ -3198,10 +3198,16 @@ static void conv_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, - GtkSelectionData *sd, guint info, guint t, gpointer data) + GtkSelectionData *sd, guint info, guint t) { - do_error_dialog("MWAHAHAHA! I AM A TROLL! I AM GOING TO EAT YOU!", - NULL, GAIM_WARNING); + if (sd->target == gdk_atom_intern("GAIM_BUDDY", FALSE)) { + struct buddy *b = NULL; + memcpy(&b, sd->data, sizeof(b)); + gaim_conversation_new(GAIM_CONV_IM, b->account, b->name); + } + + /* do_error_dialog("MWAHAHAHA! I AM A TROLL! I AM GOING TO EAT YOU!", + NULL, GAIM_WARNING); */ } /************************************************************************** @@ -3335,8 +3341,9 @@ static const GtkTargetEntry te[] = { {"text/plain", 0, 0}, - {"text/uri-list", 1, 0}, - {"STRING", 2, 0} + {"text/uri-list", 0, 1}, + {"GAIM_BUDDY", 0, 2}, + {"STRING", 0, 3} }; static void @@ -3407,8 +3414,7 @@ GDK_ACTION_COPY); gtk_drag_dest_set(gtkconv->imhtml, GTK_DEST_DEFAULT_MOTION | - GTK_DEST_DEFAULT_HIGHLIGHT | - GTK_DEST_DEFAULT_DROP, + GTK_DEST_DEFAULT_DROP, te, sizeof(te) / sizeof(GtkTargetEntry), GDK_ACTION_DEFAULT | GDK_ACTION_COPY | GDK_ACTION_MOVE); gtk_drag_dest_set(gtkconv->entry, diff -r ac7ca2bd6d4f -r cb5b23dfd82b src/prefs.c --- a/src/prefs.c Tue Mar 11 03:59:42 2003 +0000 +++ b/src/prefs.c Tue Mar 11 07:57:53 2003 +0000 @@ -344,7 +344,7 @@ GtkTreeSelection *sel; GtkTreePath *path = NULL; GtkWidget *label; - GtkTargetEntry te[3] = {{"text/plain", 0, 0},{"text/uri-list", 1, 0},{"STRING", 2, 0}}; + GtkTargetEntry te[3] = {{"text/plain", 0, 0},{"text/uri-list", 0, 1},{"STRING", 0, 2}}; ret = gtk_vbox_new(FALSE, 18); gtk_container_set_border_width (GTK_CONTAINER (ret), 12);