cpw.darkrain42.xmpp.disco: af47c59c: Make the prpl be in charge of creating t...

paul at darkrain42.org paul at darkrain42.org
Sat Apr 25 16:17:23 EDT 2009


-----------------------------------------------------------------
Revision: af47c59c074fa17389abea8161fb8ce796606352
Ancestor: 1c315a1e91b34066238c7eb29c908517401b542b
Author: paul at darkrain42.org
Date: 2009-03-31T05:18:09
Branch: im.pidgin.cpw.darkrain42.xmpp.disco
URL: http://d.pidgin.im/viewmtn/revision/info/af47c59c074fa17389abea8161fb8ce796606352

Modified files:
        libpurple/disco.c libpurple/disco.h
        libpurple/protocols/jabber/disco.c
        libpurple/protocols/jabber/disco.h libpurple/prpl.h
        pidgin/gtkdisco.c

ChangeLog: 

Make the prpl be in charge of creating the PurpleDiscoList; UI data is
allocated via ops->create.

When the prpl sets protocol data, it also passed in a close_cb which is called
when destroying the struct to clean up the protocol data.

This still works, but I've introduced some bugs with cancelling the disco or
closing the GtkDisco dialog

-------------- next part --------------
============================================================
--- libpurple/disco.c	0438d84c60892a12efbce72df0fd51f6eb662927
+++ libpurple/disco.c	8fff4e6d842ff8171e546994f36466a67bc7d2f5
@@ -43,7 +43,8 @@ struct _PurpleDiscoList {
 	gboolean in_progress;
 
 	gpointer ui_data; /**< UI private data. */
-	gpointer proto_data; /** Prpl private data. */
+	gpointer proto_data; /**< Prpl private data. */
+	PurpleDiscoCloseCallback close_cb; /**< Callback to free the prpl data */
 	guint ref; /**< The reference count. */
 };
 
@@ -62,7 +63,7 @@ static PurpleDiscoUiOps *ops = NULL;
 
 static PurpleDiscoUiOps *ops = NULL;
 
-PurpleDiscoList *purple_disco_list_new(PurpleAccount *account, void *ui_data)
+PurpleDiscoList *purple_disco_list_new(PurpleAccount *account)
 {
 	PurpleDiscoList *list;
 
@@ -71,7 +72,6 @@ PurpleDiscoList *purple_disco_list_new(P
 	list = g_new0(PurpleDiscoList, 1);
 	list->account = account;
 	list->ref = 1;
-	list->ui_data = ui_data;
 
 	if (ops && ops->create)
 		ops->create(list);
@@ -105,6 +105,9 @@ static void purple_disco_list_destroy(Pu
 	if (ops && ops->destroy)
 		ops->destroy(list);
 
+	if (list->close_cb)
+		list->close_cb(list);
+
 	for (l = list->services; l; l = l->next) {
 		PurpleDiscoService *s = l->data;
 		purple_disco_list_service_destroy(list, s);
@@ -156,25 +159,21 @@ PurpleDiscoService *purple_disco_list_se
 	return s;
 }
 
-void purple_disco_get_list(PurpleDiscoList *list)
+PurpleDiscoList *purple_disco_get_list(PurpleConnection *pc)
 {
-	PurpleConnection *pc = NULL;
 	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	g_return_if_fail(list != NULL);
+	g_return_val_if_fail(pc != NULL, NULL);
 
-	pc = purple_account_get_connection(list->account);
-
-	g_return_if_fail(pc != NULL);
-
 	prpl = purple_connection_get_prpl(pc);
-
 	if (prpl != NULL)
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, disco_get_list))
-		prpl_info->disco_get_list(pc, list);
+		return prpl_info->disco_get_list(pc);
+
+	return NULL;
 }
 
 void purple_disco_cancel_get_list(PurpleDiscoList *list)
@@ -305,11 +304,13 @@ void purple_disco_list_set_protocol_data
 }
 
 void purple_disco_list_set_protocol_data(PurpleDiscoList *list,
-                                         gpointer proto_data)
+                                         gpointer proto_data,
+                                         PurpleDiscoCloseCallback cb)
 {
 	g_return_if_fail(list != NULL);
 
 	list->proto_data = proto_data;
+	list->close_cb   = cb;
 }
 
 gpointer purple_disco_list_get_protocol_data(PurpleDiscoList *list)
============================================================
--- libpurple/disco.h	8c37b7006bd5085f8f3d7e591f1c4a33910a5db6
+++ libpurple/disco.h	37ee5f1beb915973c11c9fd7798ea4b563035bec
@@ -35,6 +35,11 @@ typedef struct _PurpleDiscoUiOps PurpleD
 #include "account.h"
 
 /**
+ *
+ */
+typedef void  (*PurpleDiscoCloseCallback) (PurpleDiscoList *list);
+
+/**
  * The categories of services.
  */
 typedef enum
@@ -104,7 +109,7 @@ extern "C" {
  * @param account The account that's listing rooms.
  * @return The new service discovery list handle.
  */
-PurpleDiscoList *purple_disco_list_new(PurpleAccount *account, void *ui_data);
+PurpleDiscoList *purple_disco_list_new(PurpleAccount *account);
 
 /**
  * Increases the reference count on the service discovery list.
@@ -127,7 +132,7 @@ void purple_disco_list_unref(PurpleDisco
  * Instructs the prpl to start fetching the list.
  *
  */
-void purple_disco_get_list(PurpleDiscoList *list);
+PurpleDiscoList *purple_disco_get_list(PurpleConnection *gc);
 
 /**
  * Tells the prpl to stop fetching the list.
@@ -280,13 +285,17 @@ gboolean purple_disco_list_get_in_progre
  *
  * This should only be called from the associated prpl.
  *
- * @param list The disco list.
- * @param data The protocol data.
+ * @param list     The disco list.
+ * @param data     The protocol data.
+ * @param close_cb The function to be called when destroying the disco list to
+ *                 free the protocol data. May be NULL if the data does not need
+ *                 to be freed.
  *
  * @see purple_disco_list_get_protocol_data()
  * @since TODO
  */
-void purple_disco_list_set_protocol_data(PurpleDiscoList *list, gpointer data);
+void purple_disco_list_set_protocol_data(PurpleDiscoList *list, gpointer data,
+                                         PurpleDiscoCloseCallback cb);
 
 /**
  * Returns the disco list's protocol-specific data.
============================================================
--- libpurple/protocols/jabber/disco.c	cf738a22ab3bd9babf008f4b5fbcd243be054b58
+++ libpurple/protocols/jabber/disco.c	772ccf2e46237a1f7bf2c4eaf8567946f69acb60
@@ -48,6 +48,8 @@ struct jabber_disco_list_data {
 }
 
 struct jabber_disco_list_data {
+	JabberStream *js;
+	PurpleDiscoList *list;
 	char *server;
 	int fetch_count;
 };
@@ -408,7 +410,7 @@ struct _disco_data {
 }
 
 struct _disco_data {
-	PurpleDiscoList *list;
+	struct jabber_disco_list_data *list_data;
 	PurpleDiscoService *parent;
 	char *node;
 };
@@ -578,12 +580,19 @@ jabber_disco_list_data_destroy(struct ja
 static void
 jabber_disco_list_data_destroy(struct jabber_disco_list_data *data)
 {
-	g_return_if_fail(data != NULL);
-
 	g_free(data->server);
 	g_free(data);
 }
 
+static void
+disco_proto_data_destroy_cb(PurpleDiscoList *list)
+{
+	struct jabber_disco_list_data *data;
+	
+	data = purple_disco_list_get_protocol_data(list);
+	jabber_disco_list_data_destroy(data);
+}
+
 static PurpleDiscoServiceCategory
 jabber_disco_category_from_string(const gchar *str)
 {
@@ -632,7 +641,7 @@ jabber_disco_service_items_cb(JabberStre
 {
 	struct _disco_data *disco_data = data;
 	struct jabber_disco_list_data *list_data;
-	PurpleDiscoList *list = disco_data->list;
+	PurpleDiscoList *list;	
 	PurpleDiscoService *parent = disco_data->parent;
 	const char *parent_node = disco_data->node;
 	xmlnode *query = xmlnode_get_child(packet, "query");
@@ -641,16 +650,14 @@ jabber_disco_service_items_cb(JabberStre
 	xmlnode *child;
 	gboolean has_items = FALSE;
 
-	list_data = purple_disco_list_get_protocol_data(list);
+	list_data = disco_data->list_data;
+	list = list_data->list;
+
 	--list_data->fetch_count;
 
 	if (!from || !result || !query || strcmp(result, "result") != 0) {
-		if (list_data->fetch_count == 0) {
-			jabber_disco_list_data_destroy(list_data);
-			purple_disco_list_set_protocol_data(list, NULL);
-
+		if (list_data->fetch_count == 0)
 			purple_disco_list_set_in_progress(list, FALSE);
-		}
 
 		purple_disco_list_unref(list);
 		return;
@@ -685,7 +692,7 @@ jabber_disco_service_items_cb(JabberStre
 		}
 
 		disco_data = g_new0(struct _disco_data, 1);
-		disco_data->list = list;
+		disco_data->list_data = list_data;
 		disco_data->parent = parent;
 		disco_data->node = full_node;
 
@@ -701,12 +708,8 @@ jabber_disco_service_items_cb(JabberStre
 		jabber_iq_send(iq);
 	}
 
-	if (list_data->fetch_count == 0) {
-		jabber_disco_list_data_destroy(list_data);
-		purple_disco_list_set_protocol_data(list, NULL);
-
+	if (list_data->fetch_count == 0)
 		purple_disco_list_set_in_progress(list, FALSE);
-	}
 
 	purple_disco_list_unref(list);
 
@@ -719,7 +722,7 @@ jabber_disco_service_info_cb(JabberStrea
 {
 	struct _disco_data *disco_data = data;
 	struct jabber_disco_list_data *list_data;
-	PurpleDiscoList *list = disco_data->list;
+	PurpleDiscoList *list;
 	PurpleDiscoService *parent = disco_data->parent;
 	char *node = g_strdup(disco_data->node);
 	xmlnode *query, *ident, *child;
@@ -732,21 +735,19 @@ jabber_disco_service_info_cb(JabberStrea
 	PurpleDiscoServiceType type;
 	PurpleDiscoServiceFlags flags = PURPLE_DISCO_ADD;
 
+	list_data = disco_data->list_data;
+	list = list_data->list;
+
 	g_free(disco_data->node);
 	g_free(disco_data);
 
-	list_data = purple_disco_list_get_protocol_data(list);
 	--list_data->fetch_count;
 
 	if (!from || !result || strcmp(result, "result") != 0
 			|| (!(query = xmlnode_get_child(packet, "query")))
 			|| (!(ident = xmlnode_get_child(query, "identity")))) {
-		if (list_data->fetch_count == 0) {
-			jabber_disco_list_data_destroy(list_data);
-			purple_disco_list_set_protocol_data(list, NULL);
-
+		if (list_data->fetch_count == 0)
 			purple_disco_list_set_in_progress(list, FALSE);
-		}
 
 		purple_disco_list_unref(list);
 		return;
@@ -802,7 +803,7 @@ jabber_disco_service_info_cb(JabberStrea
 		++list_data->fetch_count;
 		purple_disco_list_ref(list);
 		disco_data = g_new0(struct _disco_data, 1);
-		disco_data->list = list;
+		disco_data->list_data = list_data;
 		disco_data->parent = s;
 
 		xmlnode_set_attrib(iq->node, "to", from);
@@ -812,12 +813,8 @@ jabber_disco_service_info_cb(JabberStrea
 		jabber_iq_send(iq);
 	}
 
-	if (list_data->fetch_count == 0) {
-		jabber_disco_list_data_destroy(list_data);
-		purple_disco_list_set_protocol_data(list, NULL);
-
+	if (list_data->fetch_count == 0)
 		purple_disco_list_set_in_progress(list, FALSE);
-	}
 
 	purple_disco_list_unref(list);
 
@@ -828,7 +825,6 @@ jabber_disco_server_items_cb(JabberStrea
 static void
 jabber_disco_server_items_cb(JabberStream *js, xmlnode *packet, gpointer data)
 {
-	PurpleDiscoList *list = data;
 	struct jabber_disco_list_data *list_data;
 	xmlnode *query, *child;
 	const char *from = xmlnode_get_attrib(packet, "from");
@@ -841,8 +837,16 @@ jabber_disco_server_items_cb(JabberStrea
 	if (strcmp(type, "result"))
 		return;
 
-	list_data = purple_disco_list_get_protocol_data(list);
+	list_data = data;
+	--list_data->fetch_count;
 
+	if (list_data->list == NULL) {
+		if (list_data->fetch_count == 0)
+			jabber_disco_list_data_destroy(list_data);
+
+		return;
+	}
+
 	query = xmlnode_get_child(packet, "query");
 
 	for(child = xmlnode_get_child(query, "item"); child;
@@ -851,15 +855,15 @@ jabber_disco_server_items_cb(JabberStrea
 		const char *jid;
 		struct _disco_data *disco_data;
 
-		if(!(jid = xmlnode_get_attrib(child, "jid")) || !purple_disco_list_get_protocol_data(list))
+		if(!(jid = xmlnode_get_attrib(child, "jid")))
 			continue;
 
 		disco_data = g_new0(struct _disco_data, 1);
-		disco_data->list = list;
+		disco_data->list_data = list_data;
 
 		has_items = TRUE;
 		++list_data->fetch_count;
-		purple_disco_list_ref(list);
+		purple_disco_list_ref(list_data->list);
 		iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info");
 		xmlnode_set_attrib(iq->node, "to", jid);
 		jabber_iq_set_callback(iq, jabber_disco_service_info_cb, disco_data);
@@ -868,89 +872,120 @@ jabber_disco_server_items_cb(JabberStrea
 	}
 
 	if (!has_items)
-		purple_disco_list_set_in_progress(list, FALSE);
+		purple_disco_list_set_in_progress(list_data->list, FALSE);
 
-	purple_disco_list_unref(list);
+	purple_disco_list_unref(list_data->list);
 }
 
 static void
 jabber_disco_server_info_cb(JabberStream *js, const char *who, JabberCapabilities caps, gpointer data)
 {
-	PurpleDiscoList *list = data;
-	JabberIq *iq;
+	struct jabber_disco_list_data *list_data;
 
+	list_data = data;
+	--list_data->fetch_count;
+
+	if (!list_data->list) {
+		purple_disco_list_unref(list_data->list);
+
+		if (list_data->fetch_count == 0)
+			jabber_disco_list_data_destroy(list_data);
+
+		return;
+	}
+
 	if (caps & JABBER_CAP_ITEMS) {
-		iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items");
+		JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items");
 		xmlnode_set_attrib(iq->node, "to", who);
-		jabber_iq_set_callback(iq, jabber_disco_server_items_cb, list);
-	
-		if (purple_disco_list_get_protocol_data(list))
-			jabber_iq_send(iq);
-		else
-			purple_disco_list_unref(list);
-	
+		jabber_iq_set_callback(iq, jabber_disco_server_items_cb, list_data);
+
+		++list_data->fetch_count;
+		purple_disco_list_ref(list_data->list);
+
+		jabber_iq_send(iq);
 	} else {
 		purple_notify_error(NULL, _("Error"), _("Server doesn't support service discovery"), NULL); 
-		purple_disco_list_set_in_progress(list, FALSE);
-		purple_disco_list_unref(list);
+		purple_disco_list_set_in_progress(list_data->list, FALSE);
 	}
+
+	purple_disco_list_unref(list_data->list);
 }
 
-static void
-jabber_disco_server_cb(PurpleDiscoList *list, PurpleRequestFields *fields)
+static void discolist_cancel_cb(struct jabber_disco_list_data *list_data, const char *server)
 {
-	PurpleAccount *account;
-	PurpleConnection *gc;
+	purple_disco_list_set_in_progress(list_data->list, FALSE);
+	purple_disco_list_unref(list_data->list);
+}
+
+static void discolist_ok_cb(struct jabber_disco_list_data *list_data, const char *server)
+{
 	JabberStream *js;
-	const char *server_name;
 
-	server_name = purple_request_fields_get_string(fields, "server");
+	js = list_data->js;
 
-	account = purple_disco_list_get_account(list);
-	gc = purple_account_get_connection(account);
-	if (!gc)
+	if (!server || !*server) {
+		purple_notify_error(js->gc, _("Invalid Server"), _("Invalid Server"), NULL);
+
+		purple_disco_list_set_in_progress(list_data->list, FALSE);
+		purple_disco_list_unref(list_data->list);
 		return;
-	js = purple_connection_get_protocol_data(gc);
+	}
 
-	purple_disco_list_set_in_progress(list, TRUE);
-	purple_debug_misc("jabber", "Service discovery for %s\n", server_name);
+	list_data->server = g_strdup(server);
 	if (js->last_disco_server)
 		g_free(js->last_disco_server);
-	js->last_disco_server = g_strdup(server_name);
+	js->last_disco_server = g_strdup(server);
 
-	jabber_disco_info_do(js, server_name, jabber_disco_server_info_cb, list);
+	purple_disco_list_set_in_progress(list_data->list, TRUE);
+
+	++list_data->fetch_count;
+	jabber_disco_info_do(js, list_data->server, jabber_disco_server_info_cb, list_data);
 }
 
-void
-jabber_disco_get_list(PurpleConnection *gc, PurpleDiscoList *list)
+PurpleDiscoList *
+jabber_disco_get_list(PurpleConnection *gc)
 {
 	PurpleAccount *account;
+	PurpleDiscoList *list;
 	JabberStream *js;
 	struct jabber_disco_list_data *disco_list_data;
 
 	account = purple_connection_get_account(gc);
 	js = purple_connection_get_protocol_data(gc);
 
+	/* We start with a ref */
+	list = purple_disco_list_new(account);
+
 	disco_list_data = g_new0(struct jabber_disco_list_data, 1);
-	purple_disco_list_set_protocol_data(list, disco_list_data);
+	disco_list_data->list = list;
+	disco_list_data->js = js;
+	purple_disco_list_set_protocol_data(list, disco_list_data, disco_proto_data_destroy_cb);
 
-	purple_disco_list_ref(list);
-
 	purple_request_input(gc, _("Server name request"), _("Enter an XMPP Server"),
 			_("Select an XMPP server to query"),
 			js->last_disco_server ? js->last_disco_server : js->user->domain,
 			FALSE, FALSE, NULL,
-			_("Find Services"), PURPLE_CALLBACK(jabber_disco_server_cb),
-			_("Cancel"), PURPLE_CALLBACK(jabber_disco_cancel),
+			_("Find Services"), PURPLE_CALLBACK(discolist_ok_cb),
+			_("Cancel"), PURPLE_CALLBACK(discolist_cancel_cb),
 			account, NULL, NULL, disco_list_data);
 
+	return list;
 }
 
 void
 jabber_disco_cancel(PurpleDiscoList *list)
 {
-	jabber_disco_list_data_destroy(purple_disco_list_get_protocol_data(list));
-	purple_disco_list_set_protocol_data(list, NULL);
+	struct jabber_disco_list_data *list_data = purple_disco_list_get_protocol_data(list);
+	purple_disco_list_set_protocol_data(list, NULL, NULL);
+
+	if (list_data->fetch_count == 0) {
+		/* Nothing outstanding, just free it now... */
+		jabber_disco_list_data_destroy(list_data);
+	} else {
+		/* We'll free it when the count is 0 */
+		list_data->list = NULL;
+	}
+
 	purple_disco_list_set_in_progress(list, FALSE);	
 }
 
============================================================
--- libpurple/protocols/jabber/disco.h	76dee344d30fd2e3a7129f5069a0df093966a37f
+++ libpurple/protocols/jabber/disco.h	06d3b22de8e170e8598344b7bd49e46988bec16c
@@ -35,7 +35,7 @@ void jabber_disco_info_do(JabberStream *
 void jabber_disco_info_do(JabberStream *js, const char *who,
 		JabberDiscoInfoCallback *callback, gpointer data);
 
-void jabber_disco_get_list(PurpleConnection *gc, PurpleDiscoList* list);
+PurpleDiscoList *jabber_disco_get_list(PurpleConnection *gc);
 void jabber_disco_cancel(PurpleDiscoList *list);
 
 int jabber_disco_service_register(PurpleConnection *gc, PurpleDiscoService *service);
============================================================
--- libpurple/prpl.h	cbeda6b021177c9548bc766128c665f5648aeabf
+++ libpurple/prpl.h	601a3e7cd72dddd998a7f2b9dc54f9ce91e1381c
@@ -464,7 +464,7 @@ struct _PurplePluginProtocolInfo
 	/**
 	 * Service discovery prpl callbacks
 	 */
-	void (*disco_get_list)(PurpleConnection *gc, PurpleDiscoList *list);
+	PurpleDiscoList *(*disco_get_list)(PurpleConnection *gc);
 
 	/**
 	 * Cancel fetching service list
============================================================
--- pidgin/gtkdisco.c	8cbbb19f3b9dfdc4481ac3517fd31e97944d889e
+++ pidgin/gtkdisco.c	ced88e22d73955d1cd3fb731ddaea284990a9384
@@ -38,9 +38,6 @@ typedef struct _PidginDiscoDialog {
 	
 	GtkWidget *sw;
 	GtkWidget *progress;
-	GtkTreeStore *model;
-	GtkWidget *tree;
-	GHashTable *cats; /** Meow. */
 
 	GtkWidget *stop_button;
 	GtkWidget *list_button;
@@ -52,6 +49,13 @@ typedef struct _PidginDiscoDialog {
 	PurpleDiscoList *discolist;
 } PidginDiscoDialog;
 
+typedef struct _PidginDiscoList {
+	PidginDiscoDialog *dialog;
+	GtkTreeStore *model;
+	GtkWidget *tree;
+	GHashTable *cats; /** Meow. */
+} PidginDiscoList;
+
 struct _menu_cb_info {
 	PurpleDiscoList *list;
 	PurpleDiscoService *service;
@@ -65,6 +69,8 @@ enum {
 	NUM_OF_COLUMNS
 };
 
+static void pidgin_disco_create_tree(PidginDiscoList *pdl);
+
 static void dialog_select_account_cb(GObject *w, PurpleAccount *account,
 				     PidginDiscoDialog *dialog)
 {
@@ -86,17 +92,31 @@ static void list_button_cb(GtkButton *bu
 static void list_button_cb(GtkButton *button, PidginDiscoDialog *dialog)
 {
 	PurpleConnection *gc;
+	PidginDiscoList *pdl;
 
 	gc = purple_account_get_connection(dialog->account);
 	if (!gc)
 		return;
 
-	if (dialog->discolist != NULL)
+	if (dialog->discolist != NULL) {
+		pdl = purple_disco_list_get_ui_data(dialog->discolist);
+		gtk_widget_destroy(pdl->tree);
 		purple_disco_list_unref(dialog->discolist);
-	
-	dialog->discolist = purple_disco_list_new(dialog->account, (void*) dialog);
+	}
 
-	purple_disco_get_list(dialog->discolist);
+	dialog->discolist = purple_disco_get_list(gc);
+	if (!dialog->discolist)
+		return;
+	/* We keep a copy... */
+	purple_disco_list_ref(dialog->discolist);
+
+	pdl = purple_disco_list_get_ui_data(dialog->discolist);
+	pdl->dialog = dialog;
+
+	pidgin_disco_create_tree(pdl);
+
+	if (dialog->account_widget)
+		gtk_widget_set_sensitive(dialog->account_widget, FALSE);
 }
 
 static void add_room_to_blist_cb(GtkButton *button, PidginDiscoDialog *dialog)
@@ -117,17 +137,18 @@ static void
 }
 
 static void
-selection_changed_cb(GtkTreeSelection *selection, PidginDiscoDialog *dialog) 
+selection_changed_cb(GtkTreeSelection *selection, PidginDiscoList *pdl)
 {
 	PurpleDiscoService *service;
 	PurpleDiscoServiceFlags flags;
 	GtkTreeIter iter;
 	GValue val;
 	static struct _menu_cb_info *info;
+	PidginDiscoDialog *dialog = pdl->dialog;
 
 	if (gtk_tree_selection_get_selected(selection, NULL, &iter)) {
 		val.g_type = 0;
-		gtk_tree_model_get_value(GTK_TREE_MODEL(dialog-> model), &iter, SERVICE_COLUMN, &val);
+		gtk_tree_model_get_value(GTK_TREE_MODEL(pdl->model), &iter, SERVICE_COLUMN, &val);
 		service = g_value_get_pointer(&val);
 		if (!service) {
 			gtk_widget_set_sensitive(dialog->add_button, FALSE);
@@ -157,8 +178,16 @@ delete_win_cb(GtkWidget *w, GdkEventAny 
 {
 	PidginDiscoDialog *dialog = d;
 
-	if (dialog->discolist)
+	if (dialog->discolist && purple_disco_list_get_in_progress(dialog->discolist))
+		purple_disco_cancel_get_list(dialog->discolist);
+
+	if (dialog->discolist) {
+		PidginDiscoList *pdl = purple_disco_list_get_ui_data(dialog->discolist);
+
+		if (pdl)
+			pdl->dialog = NULL;
 		purple_disco_list_unref(dialog->discolist);
+	}
 
 	g_free(dialog);
 
@@ -212,30 +241,30 @@ pidgin_disco_is_showable()
 	return FALSE;
 }
 
-static void pidgin_disco_create_tree(PidginDiscoDialog *dialog)
+static void pidgin_disco_create_tree(PidginDiscoList *pdl)
 {
 	GtkCellRenderer *text_renderer, *pixbuf_renderer;
 	GtkTreeViewColumn *column;
 	GtkTreeSelection *selection;
 
-	dialog->model = gtk_tree_store_new(NUM_OF_COLUMNS,
+	pdl->model = gtk_tree_store_new(NUM_OF_COLUMNS,
 			GDK_TYPE_PIXBUF,	/* PIXBUF_COLUMN */
 			G_TYPE_STRING,		/* NAME_COLUMN */
 			G_TYPE_STRING,		/* DESCRIPTION_COLUMN */
 			G_TYPE_POINTER		/* SERVICE_COLUMN */
 	);
 
-	dialog->tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
-	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(dialog->tree), TRUE);
+	pdl->tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pdl->model));
+	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(pdl->tree), TRUE);
 
-	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->tree));
+	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pdl->tree));
 	g_signal_connect(G_OBJECT(selection), "changed",
-					 G_CALLBACK(selection_changed_cb), dialog);
+					 G_CALLBACK(selection_changed_cb), pdl);
 
-	g_object_unref(dialog->model);
+	g_object_unref(pdl->model);
 
-	gtk_container_add(GTK_CONTAINER(dialog->sw), dialog->tree);
-	gtk_widget_show(dialog->tree);
+	gtk_container_add(GTK_CONTAINER(pdl->dialog->sw), pdl->tree);
+	gtk_widget_show(pdl->tree);
 
 	text_renderer = gtk_cell_renderer_text_new();
 	pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
@@ -256,7 +285,7 @@ static void pidgin_disco_create_tree(Pid
 	gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE);
 	gtk_tree_view_column_set_sort_column_id(GTK_TREE_VIEW_COLUMN(column), NAME_COLUMN);
 	gtk_tree_view_column_set_reorderable(GTK_TREE_VIEW_COLUMN(column), TRUE);
-	gtk_tree_view_append_column(GTK_TREE_VIEW(dialog->tree), column);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(pdl->tree), column);
 
 	column = gtk_tree_view_column_new_with_attributes(_("Description"), text_renderer,
 				"text", DESCRIPTION_COLUMN, NULL);
@@ -265,7 +294,7 @@ static void pidgin_disco_create_tree(Pid
 	gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE);
 	gtk_tree_view_column_set_sort_column_id(GTK_TREE_VIEW_COLUMN(column), DESCRIPTION_COLUMN);
 	gtk_tree_view_column_set_reorderable(GTK_TREE_VIEW_COLUMN(column), TRUE);
-	gtk_tree_view_append_column(GTK_TREE_VIEW(dialog->tree), column);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(pdl->tree), column);
 }
 
 static PidginDiscoDialog*
@@ -351,8 +380,6 @@ pidgin_disco_dialog_new_with_account(Pur
 	dialog->close_button = pidgin_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_CLOSE,
 					 G_CALLBACK(close_button_cb), dialog);
 
-	pidgin_disco_create_tree(dialog);
-
 	/* show the dialog window and return the dialog */
 	gtk_widget_show(dialog->window);
 
@@ -379,35 +406,42 @@ pidgin_disco_create(PurpleDiscoList *lis
 static void
 pidgin_disco_create(PurpleDiscoList *list)
 {
-	PidginDiscoDialog *dialog;
+	PidginDiscoList *pdl = g_new0(PidginDiscoList, 1);
 
-	dialog = purple_disco_list_get_ui_data(list);
+	purple_disco_list_set_ui_data(list, pdl);
 
-	dialog->cats = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)gtk_tree_row_reference_free);
+	pdl->cats = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)gtk_tree_row_reference_free);
 }
 
 
 static void
 pidgin_disco_destroy(PurpleDiscoList *list)
 {
-	PidginDiscoDialog *dialog;
-	
-	dialog = purple_disco_list_get_ui_data(list);
+	PidginDiscoList *pdl;
 
-	g_hash_table_destroy(dialog->cats);
+	pdl = purple_disco_list_get_ui_data(list);
+
+	g_hash_table_destroy(pdl->cats);
+	g_free(pdl);
+
+	purple_disco_list_set_ui_data(list, NULL);
 }
 
 static void pidgin_disco_in_progress(PurpleDiscoList *list, gboolean in_progress)
 {
+	PidginDiscoList *pdl;
 	PidginDiscoDialog *dialog;
 	
-	dialog = purple_disco_list_get_ui_data(list);
+	pdl = purple_disco_list_get_ui_data(list);
+	if (!pdl)
+		return;
 
+	dialog = pdl->dialog;
 	if (!dialog)
 		return;
 
 	if (in_progress) {
-		gtk_tree_store_clear(dialog->model);
+		gtk_tree_store_clear(pdl->model);
 		if (dialog->account_widget)
 			gtk_widget_set_sensitive(dialog->account_widget, FALSE);
 		gtk_widget_set_sensitive(dialog->stop_button, TRUE);
@@ -423,6 +457,7 @@ static void pidgin_disco_add_service(Pur
 
 static void pidgin_disco_add_service(PurpleDiscoList *list, PurpleDiscoService *service, PurpleDiscoService *parent)
 {
+	PidginDiscoList *pdl;
 	PidginDiscoDialog *dialog;
 	PurpleDiscoServiceCategory category;
 	PurpleDiscoServiceType type;
@@ -432,22 +467,23 @@ static void pidgin_disco_add_service(Pur
 	char *filename = NULL;
 	GdkPixbuf *pixbuf = NULL;
 
-	dialog = purple_disco_list_get_ui_data(list);
+	pdl = purple_disco_list_get_ui_data(list);
+	dialog = pdl->dialog;
 
 	purple_debug_info("disco", "Add_service \"%s\"\n", purple_disco_service_get_name(service));
 
 	gtk_progress_bar_pulse(GTK_PROGRESS_BAR(dialog->progress));
 
 	if (parent) {
-		rr = g_hash_table_lookup(dialog->cats, parent);
+		rr = g_hash_table_lookup(pdl->cats, parent);
 		path = gtk_tree_row_reference_get_path(rr);
 		if (path) {
-			gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &parent_iter, path);
+			gtk_tree_model_get_iter(GTK_TREE_MODEL(pdl->model), &parent_iter, path);
 			gtk_tree_path_free(path);
 		}
 	}
 
-	gtk_tree_store_append(dialog->model, &iter, (parent ? &parent_iter : NULL));
+	gtk_tree_store_append(pdl->model, &iter, (parent ? &parent_iter : NULL));
 
 	category = purple_disco_service_get_category(service);
 	type = purple_disco_service_get_type(service);
@@ -480,17 +516,17 @@ static void pidgin_disco_add_service(Pur
 		g_free(filename);
 	}
 
-	gtk_tree_store_set(dialog->model, &iter,
+	gtk_tree_store_set(pdl->model, &iter,
 			PIXBUF_COLUMN, pixbuf,
 			NAME_COLUMN, purple_disco_service_get_name(service),
 			DESCRIPTION_COLUMN, purple_disco_service_get_description(service),
 			SERVICE_COLUMN, service,
 			-1);
 
-	path = gtk_tree_model_get_path(GTK_TREE_MODEL(dialog->model), &iter);
+	path = gtk_tree_model_get_path(GTK_TREE_MODEL(pdl->model), &iter);
 
-	rr = gtk_tree_row_reference_new(GTK_TREE_MODEL(dialog->model), path);
-	g_hash_table_insert(dialog->cats, service, rr);
+	rr = gtk_tree_row_reference_new(GTK_TREE_MODEL(pdl->model), path);
+	g_hash_table_insert(pdl->cats, service, rr);
 
 	gtk_tree_path_free(path);
 


More information about the Commits mailing list