Finish up the invite dialog with contact completion and documentation for all.

Mon, 29 Apr 2019 15:15:24 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Mon, 29 Apr 2019 15:15:24 -0500
changeset 39579
34e0b0e7df81
parent 39578
03e375280534
child 39580
716c307bb9e3

Finish up the invite dialog with contact completion and documentation for all.

ChangeLog.API file | annotate | diff | comparison | revisions
pidgin/gtkconv.c file | annotate | diff | comparison | revisions
pidgin/meson.build file | annotate | diff | comparison | revisions
pidgin/pidgincontactcompletion.c file | annotate | diff | comparison | revisions
pidgin/pidgincontactcompletion.h file | annotate | diff | comparison | revisions
pidgin/pidgininvitedialog.c file | annotate | diff | comparison | revisions
pidgin/pidgininvitedialog.h file | annotate | diff | comparison | revisions
--- a/ChangeLog.API	Mon Apr 29 15:15:03 2019 -0500
+++ b/ChangeLog.API	Mon Apr 29 15:15:24 2019 -0500
@@ -21,6 +21,8 @@
 		* purple_account_privacy_get_permitted
 		* PurpleAccountPresence and PurpleBuddyPresence inherit PurplePresence
 		* purple_account_presence_new
+		* purple_blist_walk
+		* PurpleBlistWalkFunc
 		* purple_buddy_presence_new
 		* purple_account_register_completed
 		* purple_blist_node_is_transient
@@ -556,9 +558,20 @@
 
 	Pidgin:
 		Added:
+		* PidginContactCompletion
+		* pidgin_contact_completion_new
+		* pidgin_contact_completion_get_account
+		* pidgin_contact_completion_set_account
 		* pidgin_create_webview
 		* PidginDockletFlag
 		* pidgin_gdk_pixbuf_new_from_image
+		* PidginInviteDialog
+		* pidgin_invite_dialog_new
+		* pidgin_invite_dialog_set_contact
+		* pidgin_invite_dialog_get_contact
+		* pidgin_invite_dialog_set_message
+		* pidgin_invite_dialog_get_message
+		* pidgin_invite_dialog_get_conversation
 		* PidginPluginInfo, inherits PurplePluginInfo
 		* Various WebKit-related functions in gtkwebview.h
 
--- a/pidgin/gtkconv.c	Mon Apr 29 15:15:03 2019 -0500
+++ b/pidgin/gtkconv.c	Mon Apr 29 15:15:24 2019 -0500
@@ -776,36 +776,19 @@
 	gtk_widget_grab_focus(PIDGIN_CONVERSATION(conv)->entry);
 }
 
-static gboolean
-chat_invite_filter(const PidginBuddyCompletionEntry *entry, gpointer data)
-{
-	PurpleAccount *filter_account = data;
-	PurpleAccount *account = NULL;
-
-	if (entry->is_buddy) {
-		if (PURPLE_BUDDY_IS_ONLINE(entry->entry.buddy))
-			account = purple_buddy_get_account(entry->entry.buddy);
-		else
-			return FALSE;
-	} else {
-		account = entry->entry.logged_buddy->account;
-	}
-	if (account == filter_account)
-		return TRUE;
-	return FALSE;
-}
-
-static void
-do_invite(GtkWidget *w, int resp, PurpleChatConversation *chat)
-{
+static void
+do_invite(GtkWidget *w, int resp, gpointer data)
+{
+	PidginInviteDialog *dialog = PIDGIN_INVITE_DIALOG(w);
+	PurpleChatConversation *chat = pidgin_invite_dialog_get_conversation(dialog);
 	const gchar *contact, *message;
 
 	if (resp == GTK_RESPONSE_ACCEPT) {
-		contact = pidgin_invite_dialog_get_contact(PIDGIN_INVITE_DIALOG(w));
+		contact = pidgin_invite_dialog_get_contact(dialog);
 		if (!g_ascii_strcasecmp(contact, ""))
 			return;
 
-		message = pidgin_invite_dialog_get_message(PIDGIN_INVITE_DIALOG(w));
+		message = pidgin_invite_dialog_get_message(dialog);
 
 		purple_serv_chat_invite(purple_conversation_get_connection(PURPLE_CONVERSATION(chat)),
 						 purple_chat_conversation_get_id(chat),
@@ -821,16 +804,11 @@
 	PurpleChatConversation *chat = PURPLE_CHAT_CONVERSATION(gtkconv->active_conv);
 
 	if (invite_dialog == NULL) {
-		invite_dialog = pidgin_invite_dialog_new();
-
-		/*
-		pidgin_setup_screenname_autocomplete(info->entry, NULL, chat_invite_filter,
-				purple_conversation_get_account(PURPLE_CONVERSATION(chat)));
-		*/
+		invite_dialog = pidgin_invite_dialog_new(chat);
 
 		/* Connect the signals. */
 		g_signal_connect(G_OBJECT(invite_dialog), "response",
-						 G_CALLBACK(do_invite), chat);
+						 G_CALLBACK(do_invite), NULL);
 	}
 
 	gtk_widget_show_all(invite_dialog);
--- a/pidgin/meson.build	Mon Apr 29 15:15:03 2019 -0500
+++ b/pidgin/meson.build	Mon Apr 29 15:15:24 2019 -0500
@@ -42,6 +42,7 @@
 	'libpidgin.c',
 	'minidialog.c',
 	'pidginabout.c',
+	'pidgincontactcompletion.c',
 	'pidgindebug.c',
 	'pidgindebugplugininfo.c',
 	'pidgingdkpixbuf.c',
@@ -95,6 +96,7 @@
 	'gtkxfer.h',
 	'minidialog.h',
 	'pidginabout.h',
+	'pidgincontactcompletion.h',
 	'pidgindebug.h',
 	'pidgindebugplugininfo.h',
 	'pidgingdkpixbuf.h',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidgincontactcompletion.c	Mon Apr 29 15:15:24 2019 -0500
@@ -0,0 +1,294 @@
+/* pidgin
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "pidgincontactcompletion.h"
+
+#include <purple.h>
+
+struct _PidginContactCompletion {
+	GtkEntryCompletion parent;
+	PurpleAccount *account;
+};
+
+enum {
+	PIDGIN_CONTACT_COMPLETION_COLUMN_CONTACT,
+	PIDGIN_CONTACT_COMPLETION_COLUMN_ACCOUNT,
+	PIDGIN_CONTACT_COMPLETION_N_COLMUNS,
+};
+
+enum {
+	PROP_0,
+	PROP_ACCOUNT,
+	N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = {0, };
+
+G_DEFINE_TYPE(PidginContactCompletion, pidgin_contact_completion, GTK_TYPE_ENTRY_COMPLETION);
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+pidgin_contact_completion_walk_contact_func(PurpleBlistNode *node, gpointer data) {
+	PurpleBuddy *buddy = PURPLE_BUDDY(node);
+	PurpleAccount *account = purple_buddy_get_account(buddy);
+	GtkListStore *store = GTK_LIST_STORE(data);
+	GtkTreeIter iter;
+	const gchar *name;
+
+	name = purple_buddy_get_name(buddy);
+	if(name == NULL) {
+		name = "";
+	}
+
+	gtk_list_store_append(store, &iter);
+	gtk_list_store_set(
+		store,
+		&iter,
+		PIDGIN_CONTACT_COMPLETION_COLUMN_CONTACT, name,
+		PIDGIN_CONTACT_COMPLETION_COLUMN_ACCOUNT, account,
+		-1
+	);
+}
+
+static GtkTreeModel *
+pidgin_contact_completion_create_model(void) {
+	GtkListStore *store = NULL;
+
+	store = gtk_list_store_new(
+		PIDGIN_CONTACT_COMPLETION_N_COLMUNS,
+		G_TYPE_STRING,
+		PURPLE_TYPE_ACCOUNT
+	);
+
+	purple_blist_walk(NULL,
+	                  NULL,
+	                  NULL,
+	                  pidgin_contact_completion_walk_contact_func,
+	                  store
+	);
+
+	return GTK_TREE_MODEL(store);
+}
+
+static gboolean
+pidgin_contact_completion_match_func(GtkEntryCompletion *completion,
+                                     const gchar *key,
+                                     GtkTreeIter *iter,
+                                     gpointer data)
+{
+	GtkTreeModel *model = NULL;
+	PidginContactCompletion *comp = PIDGIN_CONTACT_COMPLETION(completion);
+	gchar *name = NULL;
+
+	model = gtk_entry_completion_get_model(completion);
+
+	gtk_tree_model_get(
+		model,
+		iter,
+		PIDGIN_CONTACT_COMPLETION_COLUMN_CONTACT, &name,
+		-1
+	);
+
+	if(name == NULL) {
+		return FALSE;
+	}
+
+	if(!purple_str_has_prefix(name, key)) {
+		g_free(name);
+		return FALSE;
+	}
+
+	if(PURPLE_IS_ACCOUNT(comp->account)) {
+		PurpleAccount *account = NULL;
+
+		gtk_tree_model_get(
+			model,
+			iter,
+			PIDGIN_CONTACT_COMPLETION_COLUMN_ACCOUNT, &account,
+			-1
+		);
+
+		if(account != comp->account) {
+			g_object_unref(account);
+			return FALSE;
+		}
+
+		g_object_unref(account);
+	}
+
+	return TRUE;
+}
+
+/******************************************************************************
+ * GObject Implemention
+ *****************************************************************************/
+static void
+pidgin_contact_completion_init(PidginContactCompletion *comp) {
+}
+
+static void
+pidgin_contact_completion_constructed(GObject *obj) {
+	GtkTreeModel *model = NULL;
+
+	G_OBJECT_CLASS(pidgin_contact_completion_parent_class)->constructed(obj);
+
+	model = pidgin_contact_completion_create_model();
+
+	gtk_entry_completion_set_model(
+		GTK_ENTRY_COMPLETION(obj),
+		model
+	);
+
+	gtk_entry_completion_set_match_func(
+		GTK_ENTRY_COMPLETION(obj),
+		pidgin_contact_completion_match_func,
+		NULL,
+		NULL
+	);
+
+	gtk_entry_completion_set_text_column(
+		GTK_ENTRY_COMPLETION(obj),
+		PIDGIN_CONTACT_COMPLETION_COLUMN_CONTACT
+	);
+}
+
+static void
+pidgin_contact_completion_get_property(GObject *obj,
+                                       guint param_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+	PidginContactCompletion *comp = PIDGIN_CONTACT_COMPLETION(obj);
+
+	switch(param_id) {
+		case PROP_ACCOUNT:
+			g_value_set_object(value, pidgin_contact_completion_get_account(comp));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+pidgin_contact_completion_set_property(GObject *obj,
+                                       guint param_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+	PidginContactCompletion *comp = PIDGIN_CONTACT_COMPLETION(obj);
+
+	switch(param_id) {
+		case PROP_ACCOUNT:
+			pidgin_contact_completion_set_account(comp,
+			                                      g_value_get_object(value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+pidgin_contact_completion_finalize(GObject *obj) {
+	PidginContactCompletion *comp = PIDGIN_CONTACT_COMPLETION(obj);
+
+	g_object_unref(comp->account);
+
+	G_OBJECT_CLASS(pidgin_contact_completion_parent_class)->finalize(obj);
+}
+
+static void
+pidgin_contact_completion_class_init(PidginContactCompletionClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	/* The only solution I could find to make this work was to implement the
+	 * constructed handler and chain up to the parent.  If you find another,
+	 * better way, please implement it :)
+	 */
+	obj_class->constructed = pidgin_contact_completion_constructed;
+
+	obj_class->get_property = pidgin_contact_completion_get_property;
+	obj_class->set_property = pidgin_contact_completion_set_property;
+	obj_class->finalize = pidgin_contact_completion_finalize;
+
+	properties[PROP_ACCOUNT] = g_param_spec_object(
+		"account",
+		"account",
+		"The account to filter by or NULL for no filtering",
+		PURPLE_TYPE_ACCOUNT,
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT
+	);
+
+	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+GtkEntryCompletion *
+pidgin_contact_completion_new(void) {
+	return GTK_ENTRY_COMPLETION(g_object_new(PIDGIN_TYPE_CONTACT_COMPLETION, NULL));
+}
+
+/**
+ * pidgin_contact_completion_get_account:
+ * @completion: The #PidginContactCompletion instance.
+ *
+ * Gets the #PurpleAccount who's contacts we're filtering for, or %NULL if
+ * there is no filtering.
+ *
+ * Returns: (transfer full): The #PurpleAccount.
+ */
+PurpleAccount *
+pidgin_contact_completion_get_account(PidginContactCompletion *completion) {
+	g_return_val_if_fail(PIDGIN_IS_CONTACT_COMPLETION(completion), NULL);
+
+	return g_object_ref(completion->account);
+}
+
+/**
+ * pidgin_contact_completion_set_account:
+ * @completion: The #PidginContactCompletion instance.
+ * @account: The #PurpleAccount to filter for.
+ *
+ * Sets the #PurpleAccount who's contacts should be shown or %NULL
+ * to show contacts from all accounts.
+ */
+void
+pidgin_contact_completion_set_account(PidginContactCompletion *completion,
+                                      PurpleAccount *account)
+{
+	g_return_if_fail(PIDGIN_IS_CONTACT_COMPLETION(completion));
+
+	if(completion->account != NULL) {
+		g_clear_pointer(&completion->account, g_object_unref);
+	}
+
+	if(PURPLE_IS_ACCOUNT(account)) {
+		completion->account = g_object_ref(account);
+	}
+
+	g_object_notify_by_pspec(G_OBJECT(completion),
+	                         properties[PROP_ACCOUNT]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidgincontactcompletion.h	Mon Apr 29 15:15:24 2019 -0500
@@ -0,0 +1,89 @@
+/* pidgin
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef PIDGIN_CONTACT_COMPLETION_H
+#define PIDGIN_CONTACT_COMPLETION_H
+
+/**
+ * SECTION:pidgincontactcompletion
+ * @section_id: pidgin-contact-completion
+ * @short_description: A GtkEntryCompletion for contacts
+ * @title: Contact Name Completion
+ *
+ * #PidginContactCompletion should be treated like a normal
+ * #GtkEntryCompletion, except it already does all of the setup for the
+ * completion.  You can also filter by a #PurpleAccount to limit what's shown.
+ *
+ * |[<!-- language="C" -->
+ * GtkWidget *entry = gtk_entry_new();
+ * GtkEntryCompletion *completion = pidgin_contact_completion_new();
+ *
+ * gtk_entry_set_completion(GTK_ENTRY(entry), completion);
+ * pidgin_contact_completion_set_account(PIDGIN_CONTACT_COMPLETION(completion), account);
+ * g_object_unref(completion);
+ * ]|
+ */
+
+#include <gtk/gtk.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+#define PIDGIN_TYPE_CONTACT_COMPLETION  pidgin_contact_completion_get_type()
+
+G_DECLARE_FINAL_TYPE(PidginContactCompletion, pidgin_contact_completion, PIDGIN,
+		CONTACT_COMPLETION, GtkEntryCompletion)
+
+/**
+ * pidgin_contact_completion_new:
+ *
+ * Creates a new #GtkEntryCompletion for looking up contacts.
+ *
+ * Returns: (transfer full): The new #GtkEntryCompletion instance.
+ */
+GtkEntryCompletion *pidgin_contact_completion_new(void);
+
+/**
+ * pidgin_contact_completion_get_account:
+ * @completion: The #PidginContactCompletion instance.
+ *
+ * Gets the account that @completion is filtering for.  If no filtering is set
+ * %NULL will be returned.
+ *
+ * Returns: (transfer full) (nullable): The #PurpleAccount that's being
+ *          filtered for.
+ */
+PurpleAccount *pidgin_contact_completion_get_account(PidginContactCompletion *completion);
+
+/**
+ * pidgin_contact_completion_set_account:
+ * @completion: The #PidginContactCompletion instance.
+ * @account: (nullable): The #PurpleAccount to filter for or %NULL.
+ *
+ * Set the #PurpleAccount that @completion should filter for.  If @account is
+ * %NULL, all filtering will be disabled.
+ */
+void pidgin_contact_completion_set_account(PidginContactCompletion *completion, PurpleAccount *account);
+
+G_END_DECLS
+
+#endif /* PIDGIN_CONTACT_COMPLETION_H */
--- a/pidgin/pidgininvitedialog.c	Mon Apr 29 15:15:03 2019 -0500
+++ b/pidgin/pidgininvitedialog.c	Mon Apr 29 15:15:24 2019 -0500
@@ -18,6 +18,7 @@
  */
 
 #include "pidgininvitedialog.h"
+#include "pidgincontactcompletion.h"
 
 struct _PidginInviteDialog {
 	GtkDialog parent;
@@ -26,12 +27,15 @@
 typedef struct {
 	GtkWidget *contact;
 	GtkWidget *message;
+
+	PurpleChatConversation *conversation;
 } PidginInviteDialogPrivate;
 
 enum {
 	PROP_ZERO,
 	PROP_CONTACT,
 	PROP_MESSAGE,
+	PROP_CONVERSATION,
 	N_PROPERTIES,
 };
 
@@ -40,6 +44,24 @@
 G_DEFINE_TYPE_WITH_PRIVATE(PidginInviteDialog, pidgin_invite_dialog, GTK_TYPE_DIALOG);
 
 /******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+pidgin_invite_dialog_set_conversation(PidginInviteDialog *dialog,
+                                      PurpleChatConversation *conversation)
+{
+	PidginInviteDialogPrivate *priv = NULL;
+
+	g_return_if_fail(PIDGIN_IS_INVITE_DIALOG(dialog));
+
+	priv = pidgin_invite_dialog_get_instance_private(dialog);
+
+	priv->conversation = g_object_ref(conversation);
+
+	g_object_notify_by_pspec(G_OBJECT(dialog), properties[PROP_CONVERSATION]);
+}
+
+/******************************************************************************
  * GObject Stuff
  *****************************************************************************/
 static void
@@ -59,6 +81,10 @@
 			g_value_set_string(value,
 			                   pidgin_invite_dialog_get_message(dialog));
 			break;
+		case PROP_CONVERSATION:
+			g_value_set_object(value,
+			                   pidgin_invite_dialog_get_conversation(dialog));
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
 			break;
@@ -82,6 +108,10 @@
 			pidgin_invite_dialog_set_message(dialog,
 			                                 g_value_get_string(value));
 			break;
+		case PROP_CONVERSATION:
+			pidgin_invite_dialog_set_conversation(dialog,
+			                                      g_value_get_object(value));
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
 			break;
@@ -106,6 +136,34 @@
 }
 
 static void
+pidgin_invite_dialog_constructed(GObject *obj) {
+	PidginInviteDialog *dialog = PIDGIN_INVITE_DIALOG(obj);
+	PidginInviteDialogPrivate *priv = NULL;
+	GtkEntryCompletion *completion = NULL;
+
+	priv = pidgin_invite_dialog_get_instance_private(dialog);
+
+	completion = pidgin_contact_completion_new();
+
+	/* constructed is called after all properties are set, so we set the
+	 * account for the completion from the conversation we were created with.
+	 */
+	if(priv->conversation) {
+		PurpleAccount *account = purple_conversation_get_account(PURPLE_CONVERSATION(priv->conversation));
+
+		if(account != NULL) {
+			pidgin_contact_completion_set_account(
+				PIDGIN_CONTACT_COMPLETION(completion),
+				account
+			);
+		}
+	}
+
+	gtk_entry_set_completion(GTK_ENTRY(priv->contact), completion);
+	g_object_unref(completion);
+}
+
+static void
 pidgin_invite_dialog_class_init(PidginInviteDialogClass *klass) {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
@@ -113,6 +171,7 @@
 	obj_class->get_property = pidgin_invite_dialog_get_property;
 	obj_class->set_property = pidgin_invite_dialog_set_property;
 	obj_class->finalize = pidgin_invite_dialog_finalize;
+	obj_class->constructed = pidgin_invite_dialog_constructed;
 
 	gtk_widget_class_set_template_from_resource(
 		widget_class,
@@ -144,6 +203,13 @@
 		NULL,
 		G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
 
+	properties[PROP_CONVERSATION] = g_param_spec_object(
+		"conversation",
+		"conversation",
+		"The conversation that someone is being invited to",
+		PURPLE_TYPE_CHAT_CONVERSATION,
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
 	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
 }
 
@@ -151,8 +217,11 @@
  * Public API
  *****************************************************************************/
 GtkWidget *
-pidgin_invite_dialog_new(void) {
-	return GTK_WIDGET(g_object_new(PIDGIN_TYPE_INVITE_DIALOG, NULL));
+pidgin_invite_dialog_new(PurpleChatConversation *conversation) {
+	return GTK_WIDGET(g_object_new(
+		PIDGIN_TYPE_INVITE_DIALOG,
+		"conversation", conversation,
+		NULL));
 }
 
 const gchar *
@@ -211,3 +280,13 @@
 	}
 }
 
+PurpleChatConversation *
+pidgin_invite_dialog_get_conversation(PidginInviteDialog *dialog) {
+	PidginInviteDialogPrivate *priv = NULL;
+
+	g_return_val_if_fail(PIDGIN_IS_INVITE_DIALOG(dialog), NULL);
+
+	priv = pidgin_invite_dialog_get_instance_private(dialog);
+
+	return priv->conversation;
+}
--- a/pidgin/pidgininvitedialog.h	Mon Apr 29 15:15:03 2019 -0500
+++ b/pidgin/pidgininvitedialog.h	Mon Apr 29 15:15:24 2019 -0500
@@ -1,15 +1,65 @@
+/* pidgin
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
 #ifndef PIDGIN_INVITE_DIALOG_H
 #define PIDGIN_INVITE_DIALOG_H
 
 /**
  * SECTION:pidgininvitedialog
  * @section_id: pidgin-invite-dialog
- * @short_description: <filename>pidgininvitedialog.h</filename>
+ * @short_description: A dialog widget to invite others to chat
  * @title: Invite Dialog
+ *
+ * #PidginInviteDialog is a simple #GtkDialog that presents the user with an
+ * interface to invite another user to a conversation.  Name completion is
+ * automatically setup as well.
+ *
+ * |[<!-- language="C" -->
+ * static void
+ * do_invite(GtkWidget *widget, int resp, gpointer data) {
+ *     PidginInviteDialog *dialog = PIDGIN_INVITE_DIALOG(widget);
+ *
+ *     if(resp == GTK_RESPONSE_ACCEPT) {
+ *         g_message(
+ *             "user wants to invite %s with message %s",
+ *             pidgin_invite_dialog_get_contact(dialog),
+ *             pidgin_invite_dialog_get_message(dialog)
+ *         );
+ *     }
+ * }
+ *
+ * static void
+ * do_invite(PurpleChatConversation *conv) {
+ *     GtkWidget *dialog = pidgin_invite_dialog_new(conv);
+ *     g_signal_connect(G_OBJECT(dialog), "response",
+ *                      G_CALLBACK(do_invite), NULL);
+ *
+ * }
+ * ]|
  */
 
 #include <gtk/gtk.h>
 
+#include <purple.h>
+
 G_BEGIN_DECLS
 
 #define PIDGIN_TYPE_INVITE_DIALOG  pidgin_invite_dialog_get_type()
@@ -17,14 +67,70 @@
 G_DECLARE_FINAL_TYPE(PidginInviteDialog, pidgin_invite_dialog, PIDGIN,
 		INVITE_DIALOG, GtkDialog)
 
-GtkWidget *pidgin_invite_dialog_new(void);
+/**
+ * pidgin_invite_dialog_new:
+ * @conversation: The #PurpleChatConversation instance.
+ *
+ * Creates a new #PidginInviteDialog to invite someone to @conversation.
+ *
+ * Returns: (transfer full): The new #PidginInviteDialog instance.
+ */
+GtkWidget *pidgin_invite_dialog_new(PurpleChatConversation *conversation);
 
+/**
+ * pidgin_invite_dialog_set_contact:
+ * @dialog: The #PidginInviteDialog instance.
+ * @contact: The contact to invite.
+ *
+ * Sets the contact that should be invited.  This function is intended to be
+ * used to prepopulate the dialog in cases where you just need to prompt the
+ * user for an invite message.
+ */
 void pidgin_invite_dialog_set_contact(PidginInviteDialog *dialog, const gchar *contact);
+
+/**
+ * pidgin_invite_dialog_get_contact:
+ * @dialog: #PidginInviteDialog instance.
+ *
+ * Gets the contact that was entered in @dialog.  This string is only valid as
+ * long as @dialog exists.
+ *
+ * Returns: (transfer none): The contact that was entered.
+ */
 const gchar *pidgin_invite_dialog_get_contact(PidginInviteDialog *dialog);
 
+/**
+ * pidgin_invite_dialog_set_message:
+ * @dialog: The #PidginInviteDialog instance.
+ * @message: The message that should be displayed.
+ *
+ * Sets the message to be displayed in @dialog.  The main use case is to
+ * prepopulate the message.
+ */
 void pidgin_invite_dialog_set_message(PidginInviteDialog *dialog, const gchar *message);
+
+/**
+ * pidgin_invite_dialog_get_message:
+ * @dialog: The #PidginInviteDialog instance.
+ *
+ * Gets the message that was entered in @dialog.  The returned value is only
+ * valid as long as @dialog exists.
+ *
+ * Returns: (transfer none): The message that was entered in @dialog.
+ */
 const gchar *pidgin_invite_dialog_get_message(PidginInviteDialog *dialog);
 
+/**
+ * pidgin_invite_dialog_get_conversation:
+ * @dialog: The #PidginInviteDialog instance.
+ *
+ * Gets the #PurpleChatConversation that @dialog was created for.
+ *
+ * Returns: (transfer none): The #PurpleChatConversation that @dialog was
+ *          created with.
+ */
+PurpleChatConversation *pidgin_invite_dialog_get_conversation(PidginInviteDialog *dialog);
+
 G_END_DECLS
 
 #endif /* PIDGIN_INVITE_DIALOG_H */

mercurial