Clean up the drag and drop code and allow ripping off the Dive Profile

Linus had used some deprecated interfcase and didn't correctly untangle
the new window that he created (hiding it the window... very nifty).

I think I'm closer to the real solution with a data structure that keeps
track of the components of the new top level window that I need to be able
to untangle (and eventually, destroy) at the end.

The one error I also can't seem to get rid of is the
Clean up the drag and drop code and allow ripping of the Dive Profile

Gtk-CRITICAL **: IA__gtk_selection_data_set: assertion `length <= 0' failed

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2011-09-27 16:23:59 -07:00
parent 1d7f5a4de1
commit f4d50ffa3b

View file

@ -17,7 +17,7 @@
#include "libdivecomputer.h" #include "libdivecomputer.h"
GtkWidget *main_window, *divelist_window; GtkWidget *main_window;
GtkWidget *main_vbox; GtkWidget *main_vbox;
GtkWidget *error_info_bar; GtkWidget *error_info_bar;
GtkWidget *error_label; GtkWidget *error_label;
@ -460,34 +460,50 @@ static void switch_page(GtkNotebook *notebook, gint arg1, gpointer user_data)
repaint_dive(); repaint_dive();
} }
static const char notebook_group[] = "123"; static const char notebook_name[] = "123";
#define GRP_ID ((void *)notebook_group)
typedef struct {
char *name;
GtkWidget *widget;
GtkWidget *box;
gulong delete_handler;
gulong destroy_handler;
} notebook_data_t;
static notebook_data_t nbd[2]; /* we rip at most two notebook pages off */
static GtkNotebook *create_new_notebook_window(GtkNotebook *source, static GtkNotebook *create_new_notebook_window(GtkNotebook *source,
GtkWidget *page, GtkWidget *page,
gint x, gint y, gpointer data) gint x, gint y, gpointer data)
{ {
GtkWidget *win, *notebook, *vbox; GtkWidget *win, *notebook, *vbox;
notebook_data_t *nbdp;
/* We don't detatch twice */ /* pick the right notebook page data and return if both are detached */
if (divelist_window) if (nbd[0].widget == NULL)
nbdp = nbd;
else if (nbd[1].widget == NULL)
nbdp = nbd + 1;
else
return NULL; return NULL;
divelist_window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); nbdp->name = strdup(gtk_widget_get_name(page));
gtk_window_set_title(GTK_WINDOW(win), "Dive List"); nbdp->widget = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(win), nbdp->name);
gtk_window_move(GTK_WINDOW(win), x, y); gtk_window_move(GTK_WINDOW(win), x, y);
/* Destroying the dive list will kill the application */ /* Destroying the dive list will kill the application */
g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(on_delete), NULL); nbdp->delete_handler = g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(on_delete), NULL);
g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL); nbdp->destroy_handler = g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL);
vbox = gtk_vbox_new(FALSE, 0); nbdp->box = vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(win), vbox); gtk_container_add(GTK_CONTAINER(win), vbox);
notebook = gtk_notebook_new(); notebook = gtk_notebook_new();
gtk_notebook_set_group(GTK_NOTEBOOK(notebook), GRP_ID); gtk_widget_set_name(notebook, nbdp->name);
gtk_notebook_set_group_name(GTK_NOTEBOOK(notebook), notebook_name);
gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 6); gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 6);
gtk_widget_set_size_request(notebook, 350, 250); gtk_widget_set_size_request(notebook, 450, 350);
gtk_widget_show_all(win); gtk_widget_show_all(win);
return GTK_NOTEBOOK(notebook); return GTK_NOTEBOOK(notebook);
@ -499,8 +515,8 @@ static void drag_cb(GtkWidget *widget, GdkDragContext *context,
guint info, guint time, guint info, guint time,
gpointer user_data) gpointer user_data)
{ {
GtkWidget *source, *target; GtkWidget *source;
GtkWidget *tab; notebook_data_t *nbdp;
/* /*
* We don't actually really *use* this yet, but Dirk wants to * We don't actually really *use* this yet, but Dirk wants to
@ -508,23 +524,26 @@ static void drag_cb(GtkWidget *widget, GdkDragContext *context,
* this all to figure out which window we're talking about. * this all to figure out which window we're talking about.
*/ */
source = gtk_drag_get_source_widget(context); source = gtk_drag_get_source_widget(context);
target = (GtkWidget *) user_data; if (! strcmp(nbd[0].name,gtk_widget_get_name(source)))
tab = *(GtkWidget **)selection_data->data; nbdp = nbd;
else if (! strcmp(nbd[1].name,gtk_widget_get_name(source)))
nbdp = nbd + 1;
else
/* HU? */
return;
gtk_drag_finish(context, TRUE, TRUE, time); gtk_drag_finish(context, TRUE, TRUE, time);
/* /* we no longer need the widget - but getting rid of this is hard;
* Horrible, horrible hack. We hide the old divelist window, and * remove the signal handler, remove the notebook from the box
* set it to NULL. So if we drag the thing back out, we'll create * then destroy the widget (and clear out our data structure) */
* a new window. Ugh. g_signal_handler_disconnect(nbdp->widget,nbdp->delete_handler);
* g_signal_handler_disconnect(nbdp->widget,nbdp->destroy_handler);
* Actually destroying the divelist window triggers the whole gtk_container_remove(GTK_CONTAINER(nbdp->box), source);
* destroy callback, which we don't want. gtk_widget_destroy(nbdp->widget);
*/ nbdp->widget = NULL;
if (source != target) { free(nbdp->name);
gtk_widget_hide(divelist_window); nbdp->name = NULL;
divelist_window = NULL;
}
} }
void init_ui(int argc, char **argv) void init_ui(int argc, char **argv)
@ -579,21 +598,25 @@ void init_ui(int argc, char **argv)
/* Notebook for dive info vs profile vs .. */ /* Notebook for dive info vs profile vs .. */
notebook = gtk_notebook_new(); notebook = gtk_notebook_new();
gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 6); gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 6);
gtk_notebook_set_group(GTK_NOTEBOOK(notebook), GRP_ID); gtk_notebook_set_group_name(GTK_NOTEBOOK(notebook), notebook_name);
gtk_notebook_set_window_creation_hook(create_new_notebook_window, NULL, NULL); g_signal_connect(notebook, "create-window", G_CALLBACK(create_new_notebook_window), NULL);
gtk_drag_dest_set(notebook, GTK_DEST_DEFAULT_ALL, &notebook_target, 1, GDK_ACTION_MOVE); gtk_drag_dest_set(notebook, GTK_DEST_DEFAULT_ALL, &notebook_target, 1, GDK_ACTION_MOVE);
g_signal_connect(notebook, "drag-data-received", G_CALLBACK(drag_cb), notebook); g_signal_connect(notebook, "drag-data-received", G_CALLBACK(drag_cb), notebook);
g_signal_connect(notebook, "switch-page", G_CALLBACK(switch_page), NULL); g_signal_connect(notebook, "switch-page", G_CALLBACK(switch_page), NULL);
/* Create the actual divelist */ /* Create the actual divelist */
dive_list = dive_list_create(); dive_list = dive_list_create();
gtk_widget_set_name(dive_list, "Dive List");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dive_list, gtk_label_new("Dive List")); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dive_list, gtk_label_new("Dive List"));
gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(notebook), dive_list, 1); gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(notebook), dive_list, 1);
gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(notebook), dive_list, 1); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(notebook), dive_list, 1);
/* Frame for dive profile */ /* Frame for dive profile */
dive_profile = dive_profile_widget(); dive_profile = dive_profile_widget();
gtk_widget_set_name(dive_profile, "Dive Profile");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dive_profile, gtk_label_new("Dive Profile")); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dive_profile, gtk_label_new("Dive Profile"));
gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(notebook), dive_profile, 1);
gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(notebook), dive_profile, 1);
/* Frame for extended dive info */ /* Frame for extended dive info */
dive_info = extended_dive_info_widget(); dive_info = extended_dive_info_widget();