Merged default branch soc.2013.gobjectification

Wed, 30 Oct 2013 02:58:57 +0530

author
Ankit Vani <a@nevitus.org>
date
Wed, 30 Oct 2013 02:58:57 +0530
branch
soc.2013.gobjectification
changeset 35050
9182e2960023
parent 35049
ba239f756f56 (current diff)
parent 34502
433382371e89 (diff)
child 35051
74d393e8fac7
child 36940
865a746c9a6f

Merged default branch

libpurple/Makefile.am file | annotate | diff | comparison | revisions
libpurple/request.h file | annotate | diff | comparison | revisions
pidgin/gtkmain.c file | annotate | diff | comparison | revisions
pidgin/gtkrequest.c file | annotate | diff | comparison | revisions
--- a/libpurple/Makefile.am	Mon Oct 28 20:58:24 2013 +0530
+++ b/libpurple/Makefile.am	Wed Oct 30 02:58:57 2013 +0530
@@ -102,6 +102,7 @@
 	prpl.c \
 	purple-socket.c \
 	request.c \
+	request-datasheet.c \
 	roomlist.c \
 	savedstatuses.c \
 	server.c \
@@ -174,6 +175,7 @@
 	prpl.h \
 	purple-socket.h \
 	request.h \
+	request-datasheet.h \
 	roomlist.h \
 	savedstatuses.h \
 	server.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/request-datasheet.c	Wed Oct 30 02:58:57 2013 +0530
@@ -0,0 +1,344 @@
+/**
+ * @file request-datasheet.c Request Datasheet API
+ * @ingroup core
+ */
+
+/* purple
+ *
+ * Purple 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 "request-datasheet.h"
+
+#include "debug.h"
+#include "signals.h"
+
+struct _PurpleRequestDatasheet
+{
+	guint col_count;
+	GArray *col_types;
+	GArray *col_titles;
+
+	GList *record_list;
+	GHashTable *record_li_by_key;
+};
+
+struct _PurpleRequestDatasheetRecord
+{
+	PurpleRequestDatasheet *sheet;
+	gpointer key;
+	gchar **data; /* at this point, there is only string data possible */
+};
+
+static void
+purple_request_datasheet_record_free(PurpleRequestDatasheetRecord *rec);
+
+/***** Datasheet API **********************************************************/
+
+PurpleRequestDatasheet *
+purple_request_datasheet_new(void)
+{
+	PurpleRequestDatasheet *sheet;
+
+	sheet = g_new0(PurpleRequestDatasheet, 1);
+
+	sheet->col_types = g_array_new(FALSE, FALSE,
+		sizeof(PurpleRequestDatasheetColumnType));
+	sheet->col_titles = g_array_new(FALSE, FALSE, sizeof(gchar *));
+	/* XXX: use g_array_set_clear_func when we depend on Glib 2.32 */
+
+	sheet->record_li_by_key = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+	purple_signal_register(sheet, "record-changed",
+		purple_marshal_VOID__POINTER_POINTER, NULL, 2,
+		purple_value_new(PURPLE_TYPE_BOXED,
+			"PurpleRequestDatasheet *"),
+		purple_value_new(PURPLE_TYPE_POINTER)); /* NULL for all */
+
+	purple_signal_register(sheet, "destroy",
+		purple_marshal_VOID__POINTER, NULL, 1,
+		purple_value_new(PURPLE_TYPE_BOXED,
+			"PurpleRequestDatasheet *"));
+
+	return sheet;
+}
+
+void
+purple_request_datasheet_free(PurpleRequestDatasheet *sheet)
+{
+	guint i;
+
+	g_return_if_fail(sheet != NULL);
+
+	purple_signal_emit(sheet, "destroy", sheet);
+	purple_signals_unregister_by_instance(sheet);
+
+	for (i = 0; i < sheet->col_titles->len; i++)
+		g_free(g_array_index(sheet->col_titles, gchar *, i));
+
+	g_array_free(sheet->col_titles, TRUE);
+	g_array_free(sheet->col_types, TRUE);
+
+	g_hash_table_destroy(sheet->record_li_by_key);
+	g_list_free_full(sheet->record_list,
+		(GDestroyNotify)purple_request_datasheet_record_free);
+
+	g_free(sheet);
+}
+
+void
+purple_request_datasheet_add_column(PurpleRequestDatasheet *sheet,
+	PurpleRequestDatasheetColumnType type, const gchar *title)
+{
+	gchar *title_clone;
+
+	g_return_if_fail(sheet != NULL);
+
+	if (sheet->record_list != NULL) {
+		purple_debug_error("request-datasheet", "Cannot modify model "
+			"when there is already some data");
+		return;
+	}
+
+	title_clone = g_strdup(title);
+	sheet->col_count++;
+	g_array_append_val(sheet->col_types, type);
+	g_array_append_val(sheet->col_titles, title_clone);
+}
+
+guint
+purple_request_datasheet_get_column_count(PurpleRequestDatasheet *sheet)
+{
+	g_return_val_if_fail(sheet != NULL, 0);
+
+	return sheet->col_count;
+	/*return sheet->col_types->len;*/
+}
+
+PurpleRequestDatasheetColumnType
+purple_request_datasheet_get_column_type(PurpleRequestDatasheet *sheet,
+	guint col_no)
+{
+	g_return_val_if_fail(sheet != NULL, 0);
+
+	return g_array_index(sheet->col_types,
+		PurpleRequestDatasheetColumnType, col_no);
+}
+
+const gchar *
+purple_request_datasheet_get_column_title(PurpleRequestDatasheet *sheet,
+	guint col_no)
+{
+	g_return_val_if_fail(sheet != NULL, 0);
+
+	return g_array_index(sheet->col_titles, gchar *, col_no);
+}
+
+const GList *
+purple_request_datasheet_get_records(PurpleRequestDatasheet *sheet)
+{
+	g_return_val_if_fail(sheet != NULL, NULL);
+
+	return sheet->record_list;
+}
+
+/***** Datasheet record API ***************************************************/
+
+static PurpleRequestDatasheetRecord *
+purple_request_datasheet_record_new(void)
+{
+	return g_new0(PurpleRequestDatasheetRecord, 1);
+}
+
+static void
+purple_request_datasheet_record_free(PurpleRequestDatasheetRecord *rec)
+{
+	g_strfreev(rec->data);
+	g_free(rec);
+}
+
+gpointer
+purple_request_datasheet_record_get_key(const PurpleRequestDatasheetRecord *rec)
+{
+	g_return_val_if_fail(rec != NULL, NULL);
+
+	return rec->key;
+}
+
+PurpleRequestDatasheet *
+purple_request_datasheet_record_get_datasheet(
+	PurpleRequestDatasheetRecord *rec)
+{
+	g_return_val_if_fail(rec != NULL, NULL);
+
+	return rec->sheet;
+}
+
+PurpleRequestDatasheetRecord *
+purple_request_datasheet_record_find(PurpleRequestDatasheet *sheet,
+	gpointer key)
+{
+	GList *it;
+
+	g_return_val_if_fail(sheet != NULL, NULL);
+
+	it = g_hash_table_lookup(sheet->record_li_by_key, key);
+	if (!it)
+		return NULL;
+
+	return it->data;
+}
+
+PurpleRequestDatasheetRecord *
+purple_request_datasheet_record_add(PurpleRequestDatasheet *sheet,
+	gpointer key)
+{
+	PurpleRequestDatasheetRecord *rec;
+
+	g_return_val_if_fail(sheet != NULL, NULL);
+
+	rec = purple_request_datasheet_record_find(sheet, key);
+	if (rec != NULL)
+		return rec;
+
+	rec = purple_request_datasheet_record_new();
+	rec->sheet = sheet;
+	rec->key = key;
+
+	/* we don't allow modifying collumn count when datasheet contains
+	 * any records */
+	rec->data = g_new0(gchar*,
+		purple_request_datasheet_get_column_count(sheet) + 1);
+
+	sheet->record_list = g_list_append(sheet->record_list, rec);
+	g_hash_table_insert(sheet->record_li_by_key, key,
+		g_list_find(sheet->record_list, rec));
+
+	purple_signal_emit(sheet, "record-changed", sheet, key);
+
+	return rec;
+}
+
+void
+purple_request_datasheet_record_remove(PurpleRequestDatasheet *sheet,
+	gpointer key)
+{
+	GList *it;
+
+	g_return_if_fail(sheet != NULL);
+
+	it = g_hash_table_lookup(sheet->record_li_by_key, key);
+	if (it == NULL)
+		return;
+
+	purple_request_datasheet_record_free(it->data);
+	sheet->record_list = g_list_delete_link(sheet->record_list, it);
+	g_hash_table_remove(sheet->record_li_by_key, key);
+
+	purple_signal_emit(sheet, "record-changed", sheet, key);
+}
+
+void
+purple_request_datasheet_record_remove_all(PurpleRequestDatasheet *sheet)
+{
+	g_return_if_fail(sheet != NULL);
+
+	g_list_free_full(sheet->record_list,
+		(GDestroyNotify)purple_request_datasheet_record_free);
+	sheet->record_list = NULL;
+	g_hash_table_remove_all(sheet->record_li_by_key);
+
+	purple_signal_emit(sheet, "record-changed", sheet, NULL);
+}
+
+static void
+purple_request_datasheet_record_set_common_data(
+	PurpleRequestDatasheetRecord *rec, guint col_no, const gchar *data)
+{
+	g_return_if_fail(rec != NULL);
+	g_return_if_fail(
+		purple_request_datasheet_get_column_count(rec->sheet) > col_no);
+
+	if (g_strcmp0(rec->data[col_no], data) == 0)
+		return;
+
+	/* we assume, model hasn't changed */
+	g_free(rec->data[col_no]);
+	rec->data[col_no] = g_strdup(data);
+
+	purple_signal_emit(rec->sheet, "record-changed", rec->sheet, rec->key);
+}
+
+void
+purple_request_datasheet_record_set_string_data(
+	PurpleRequestDatasheetRecord *rec, guint col_no, const gchar *data)
+{
+	g_return_if_fail(rec != NULL);
+	g_return_if_fail(purple_request_datasheet_get_column_type(rec->sheet,
+		col_no) == PURPLE_REQUEST_DATASHEET_COLUMN_STRING);
+
+	purple_request_datasheet_record_set_common_data(rec, col_no, data);
+}
+
+void
+purple_request_datasheet_record_set_image_data(
+	PurpleRequestDatasheetRecord *rec, guint col_no, const gchar *stock_id)
+{
+	g_return_if_fail(rec != NULL);
+	g_return_if_fail(purple_request_datasheet_get_column_type(rec->sheet,
+		col_no) == PURPLE_REQUEST_DATASHEET_COLUMN_IMAGE);
+
+	purple_request_datasheet_record_set_common_data(rec, col_no, stock_id);
+}
+
+const gchar *
+purple_request_datasheet_record_get_common_data(
+	const PurpleRequestDatasheetRecord *rec, guint col_no)
+{
+	g_return_val_if_fail(rec != NULL, NULL);
+	g_return_val_if_fail(
+		purple_request_datasheet_get_column_count(rec->sheet) > col_no,
+		NULL);
+
+	return rec->data[col_no];
+}
+
+const gchar *
+purple_request_datasheet_record_get_string_data(
+	const PurpleRequestDatasheetRecord *rec, guint col_no)
+{
+	g_return_val_if_fail(rec != NULL, NULL);
+	g_return_val_if_fail(purple_request_datasheet_get_column_type(
+		rec->sheet, col_no) == PURPLE_REQUEST_DATASHEET_COLUMN_STRING,
+		NULL);
+
+	return purple_request_datasheet_record_get_common_data(rec, col_no);
+}
+
+const gchar *
+purple_request_datasheet_record_get_image_data(
+	const PurpleRequestDatasheetRecord *rec, guint col_no)
+{
+	g_return_val_if_fail(rec != NULL, NULL);
+	g_return_val_if_fail(purple_request_datasheet_get_column_type(
+		rec->sheet, col_no) == PURPLE_REQUEST_DATASHEET_COLUMN_IMAGE,
+		NULL);
+
+	return purple_request_datasheet_record_get_common_data(rec, col_no);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/request-datasheet.h	Wed Oct 30 02:58:57 2013 +0530
@@ -0,0 +1,246 @@
+/**
+ * @file request-datasheet.h Request Datasheet API
+ * @ingroup core
+ */
+
+/* purple
+ *
+ * Purple 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 _PURPLE_REQUEST_DATA_H_
+#define _PURPLE_REQUEST_DATA_H_
+
+typedef struct _PurpleRequestDatasheet PurpleRequestDatasheet;
+typedef struct _PurpleRequestDatasheetRecord PurpleRequestDatasheetRecord;
+
+typedef enum
+{
+	PURPLE_REQUEST_DATASHEET_COLUMN_STRING,
+	PURPLE_REQUEST_DATASHEET_COLUMN_IMAGE
+} PurpleRequestDatasheetColumnType;
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**************************************************************************/
+/** @name Datasheet API                                                   */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Creates new Datasheet.
+ *
+ * @return The new datasheet.
+ */
+PurpleRequestDatasheet *
+purple_request_datasheet_new(void);
+
+/**
+ * Destroys datasheet with all its contents.
+ *
+ * @param sheet The datasheet.
+ */
+void
+purple_request_datasheet_free(PurpleRequestDatasheet *sheet);
+
+/**
+ * Adds a column to the datasheet.
+ *
+ * You cannot add a column if datasheet contains any data.
+ *
+ * @param sheet The datasheet.
+ * @param type  The column type.
+ * @param title The column title (may be @c NULL).
+ */
+void
+purple_request_datasheet_add_column(PurpleRequestDatasheet *sheet,
+	PurpleRequestDatasheetColumnType type, const gchar *title);
+
+/**
+ * Returns the column count of datasheet.
+ *
+ * @param sheet The datasheet.
+ *
+ * @return The column count.
+ */
+guint
+purple_request_datasheet_get_column_count(PurpleRequestDatasheet *sheet);
+
+/**
+ * Returns the column type for a datasheet.
+ *
+ * @param sheet  The datasheet.
+ * @param col_no The column number (0 is the first one).
+ *
+ * @return The column type.
+ */
+PurpleRequestDatasheetColumnType
+purple_request_datasheet_get_column_type(PurpleRequestDatasheet *sheet,
+	guint col_no);
+
+/**
+ * Returns the column title for a datasheet.
+ *
+ * @param sheet  The datasheet.
+ * @param col_no The column number (0 is the first one).
+ *
+ * @return The column title.
+ */
+const gchar *
+purple_request_datasheet_get_column_title(PurpleRequestDatasheet *sheet,
+	guint col_no);
+
+/**
+ * Returns the list of records in a datasheet.
+ *
+ * You shouldn't modify datasheet's data while iterating through it.
+ *
+ * @param sheet The datasheet.
+ *
+ * @constreturn The list of records.
+ */
+const GList *
+purple_request_datasheet_get_records(PurpleRequestDatasheet *sheet);
+
+/*@}*/
+
+
+/**************************************************************************/
+/** @name Datasheet record API                                            */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the key of a record.
+ *
+ * @param rec The record.
+ *
+ * @return The key.
+ */
+gpointer
+purple_request_datasheet_record_get_key(
+	const PurpleRequestDatasheetRecord *rec);
+
+/**
+ * Returns the datasheet of a record.
+ *
+ * @param rec The record.
+ *
+ * @return The datasheet.
+ */
+PurpleRequestDatasheet *
+purple_request_datasheet_record_get_datasheet(
+	PurpleRequestDatasheetRecord *rec);
+
+/**
+ * Looks up for a record in datasheet.
+ *
+ * @param sheet The datasheet.
+ * @param key   The key.
+ *
+ * @return The record if found, @c NULL otherwise.
+ */
+PurpleRequestDatasheetRecord *
+purple_request_datasheet_record_find(PurpleRequestDatasheet *sheet,
+	gpointer key);
+
+/**
+ * Adds a record to the datasheet.
+ *
+ * If the specified key already exists in datasheet, old record is returned.
+ *
+ * @param sheet The datasheet.
+ * @param key   The key.
+ *
+ * @return The record.
+ */
+PurpleRequestDatasheetRecord *
+purple_request_datasheet_record_add(PurpleRequestDatasheet *sheet,
+	gpointer key);
+
+/**
+ * Removes a record from a datasheet.
+ *
+ * @param sheet The datasheet.
+ * @param key   The key.
+ */
+void
+purple_request_datasheet_record_remove(PurpleRequestDatasheet *sheet,
+	gpointer key);
+
+/**
+ * Removes all records from a datasheet.
+ *
+ * @param sheet The datasheet.
+ */
+void
+purple_request_datasheet_record_remove_all(PurpleRequestDatasheet *sheet);
+
+/**
+ * Sets data for a string column of specified record.
+ *
+ * @param rec    The record.
+ * @param col_no The column.
+ * @param data   The data.
+ */
+void
+purple_request_datasheet_record_set_string_data(
+	PurpleRequestDatasheetRecord *rec, guint col_no, const gchar *data);
+
+/**
+ * Sets data for a image column of specified record.
+ *
+ * @param rec    The record.
+ * @param col_no The column.
+ * @param data   The stock identifier of a image.
+ */
+void
+purple_request_datasheet_record_set_image_data(
+	PurpleRequestDatasheetRecord *rec, guint col_no, const gchar *stock_id);
+
+/**
+ * Returns data for a string column of specified record.
+ *
+ * @param rec    The record.
+ * @param col_no The column.
+ *
+ * @return The data.
+ */
+const gchar *
+purple_request_datasheet_record_get_string_data(
+	const PurpleRequestDatasheetRecord *rec, guint col_no);
+
+/**
+ * Returns data for an image column of specified record.
+ *
+ * @param rec    The record.
+ * @param col_no The column.
+ *
+ * @return The stock id of an image.
+ */
+const gchar *
+purple_request_datasheet_record_get_image_data(
+	const PurpleRequestDatasheetRecord *rec, guint col_no);
+
+/*@}*/
+
+G_END_DECLS
+
+#endif /* _PURPLE_REQUEST_DATA_H_ */
--- a/libpurple/request.c	Mon Oct 28 20:58:24 2013 +0530
+++ b/libpurple/request.c	Wed Oct 30 02:58:57 2013 +0530
@@ -132,6 +132,10 @@
 			PurpleCertificate *cert;
 		} certificate;
 
+		struct
+		{
+			PurpleRequestDatasheet *sheet;
+		} datasheet;
 	} u;
 
 	void *ui_data;
@@ -985,6 +989,10 @@
 		g_hash_table_destroy(field->u.list.item_data);
 		g_hash_table_destroy(field->u.list.selected_table);
 	}
+	else if (field->type == PURPLE_REQUEST_FIELD_DATASHEET)
+	{
+		purple_request_datasheet_free(field->u.datasheet.sheet);
+	}
 
 	g_free(field);
 }
@@ -1972,6 +1980,31 @@
 	return field->u.certificate.cert;
 }
 
+PurpleRequestField *
+purple_request_field_datasheet_new(const char *id,
+	const gchar *text, PurpleRequestDatasheet *sheet)
+{
+	PurpleRequestField *field;
+
+	g_return_val_if_fail(id != NULL, NULL);
+	g_return_val_if_fail(sheet != NULL, NULL);
+
+	field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_DATASHEET);
+
+	field->u.datasheet.sheet = sheet;
+
+	return field;
+}
+
+PurpleRequestDatasheet *
+purple_request_field_datasheet_get_sheet(PurpleRequestField *field)
+{
+	g_return_val_if_fail(field != NULL, NULL);
+	g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_DATASHEET, NULL);
+
+	return field->u.datasheet.sheet;
+}
+
 /* -- */
 
 gboolean
--- a/libpurple/request.h	Mon Oct 28 20:58:24 2013 +0530
+++ b/libpurple/request.h	Wed Oct 30 02:58:57 2013 +0530
@@ -31,6 +31,7 @@
 #include <glib.h>
 
 #include "certificate.h"
+#include "request-datasheet.h"
 
 /**
  * A request field.
@@ -85,7 +86,8 @@
 	PURPLE_REQUEST_FIELD_LABEL,
 	PURPLE_REQUEST_FIELD_IMAGE,
 	PURPLE_REQUEST_FIELD_ACCOUNT,
-	PURPLE_REQUEST_FIELD_CERTIFICATE
+	PURPLE_REQUEST_FIELD_CERTIFICATE,
+	PURPLE_REQUEST_FIELD_DATASHEET
 
 } PurpleRequestFieldType;
 
@@ -1670,6 +1672,35 @@
 /*@}*/
 
 /**************************************************************************/
+/** @name Datasheet Field API                                             */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Creates a datasheet item field.
+ *
+ * @param id    The field ID.
+ * @param text  The label of the field, may be @c NULL.
+ * @param sheet The datasheet.
+ *
+ * @return The new field.
+ */
+PurpleRequestField *purple_request_field_datasheet_new(const char *id,
+	const gchar *text, PurpleRequestDatasheet *sheet);
+
+/**
+ * Returns a datasheet for a field.
+ *
+ * @param field The field.
+ *
+ * @constreturn The datasheet object.
+ */
+PurpleRequestDatasheet *purple_request_field_datasheet_get_sheet(
+	PurpleRequestField *field);
+
+/*@}*/
+
+/**************************************************************************/
 /** @name Validators for request fields.                                  */
 /**************************************************************************/
 /*@{*/
--- a/pidgin/gtkmain.c	Mon Oct 28 20:58:24 2013 +0530
+++ b/pidgin/gtkmain.c	Wed Oct 30 02:58:57 2013 +0530
@@ -275,6 +275,7 @@
 
 	pidgin_accounts_init();
 	pidgin_connection_init();
+	pidgin_request_init();
 	pidgin_blist_init();
 	pidgin_status_init();
 	pidgin_conversations_init();
@@ -308,6 +309,7 @@
 	pidgin_status_uninit();
 	pidgin_docklet_uninit();
 	pidgin_blist_uninit();
+	pidgin_request_uninit();
 	pidgin_connection_uninit();
 	pidgin_accounts_uninit();
 	pidgin_xfers_uninit();
--- a/pidgin/gtkrequest.c	Mon Oct 28 20:58:24 2013 +0530
+++ b/pidgin/gtkrequest.c	Wed Oct 30 02:58:57 2013 +0530
@@ -35,6 +35,7 @@
 #include "gtkutils.h"
 #include "pidginstock.h"
 #include "gtkblist.h"
+#include "gtkinternal.h"
 
 #include <gdk/gdkkeysyms.h>
 
@@ -48,8 +49,6 @@
 
 #include "gtk3compat.h"
 
-static GtkWidget * create_account_field(PurpleRequestField *field);
-
 typedef struct
 {
 	PurpleRequestType type;
@@ -95,6 +94,10 @@
 
 } PidginRequestData;
 
+static GHashTable *datasheet_stock = NULL;
+
+static GtkWidget * create_account_field(PurpleRequestField *field);
+
 static void
 pidgin_widget_decorate_account(GtkWidget *cont, PurpleAccount *account)
 {
@@ -1569,6 +1572,266 @@
 #endif
 }
 
+static GdkPixbuf*
+_pidgin_datasheet_stock_icon_get(const gchar *stock_name)
+{
+	GdkPixbuf *image = NULL;
+	gchar *domain, *id;
+
+	if (stock_name == NULL)
+		return NULL;
+
+	/* core is quitting */
+	if (datasheet_stock == NULL)
+		return NULL;
+
+	if (g_hash_table_lookup_extended(datasheet_stock, stock_name,
+		NULL, (gpointer*)&image))
+	{
+		return image;
+	}
+
+	domain = g_strdup(stock_name);
+	id = strchr(domain, '/');
+	if (!id) {
+		g_free(domain);
+		return NULL;
+	}
+	id[0] = '\0';
+	id++;
+
+	if (g_strcmp0(domain, "prpl") == 0) {
+		PurpleAccount *account;
+		gchar *prpl, *accountname;
+
+		prpl = id;
+		accountname = strchr(id, ':');
+
+		if (!accountname) {
+			g_free(domain);
+			return NULL;
+		}
+
+		accountname[0] = '\0';
+		accountname++;
+
+		account = purple_accounts_find(accountname, prpl);
+		if (account) {
+			image = pidgin_create_prpl_icon(account,
+				PIDGIN_PRPL_ICON_SMALL);
+		}
+	} else if (g_strcmp0(domain, "e2ee") == 0) {
+		image = pidgin_pixbuf_from_imgstore(
+			_pidgin_e2ee_stock_icon_get(id));
+	} else {
+		purple_debug_error("gtkrequest", "Unknown domain: %s", domain);
+		g_free(domain);
+		return NULL;
+	}
+
+	g_hash_table_insert(datasheet_stock, g_strdup(stock_name), image);
+	return image;
+}
+
+static void
+datasheet_update_rec(PurpleRequestDatasheetRecord *rec, GtkListStore *model,
+	GtkTreeIter *iter)
+{
+	guint i, col_count;
+	PurpleRequestDatasheet *sheet;
+
+	g_return_if_fail(rec != NULL);
+	g_return_if_fail(model != NULL);
+	g_return_if_fail(iter != NULL);
+
+	sheet = purple_request_datasheet_record_get_datasheet(rec);
+
+	g_return_if_fail(sheet != NULL);
+
+	col_count = purple_request_datasheet_get_column_count(sheet);
+
+	for (i = 0; i < col_count; i++) {
+		PurpleRequestDatasheetColumnType type;
+
+		type = purple_request_datasheet_get_column_type(
+			sheet, i);
+		if (type == PURPLE_REQUEST_DATASHEET_COLUMN_STRING) {
+			GValue val;
+
+			val.g_type = 0;
+			g_value_init(&val, G_TYPE_STRING);
+			g_value_set_string(&val,
+				purple_request_datasheet_record_get_string_data(
+					rec, i));
+			gtk_list_store_set_value(model, iter,
+				i + 1, &val);
+		} else if (type ==
+			PURPLE_REQUEST_DATASHEET_COLUMN_IMAGE)
+		{
+			GdkPixbuf *pixbuf;
+
+			pixbuf = _pidgin_datasheet_stock_icon_get(
+				purple_request_datasheet_record_get_image_data(
+					rec, i));
+			gtk_list_store_set(model, iter, i + 1,
+				pixbuf, -1);
+		} else
+			g_warn_if_reached();
+	}
+}
+
+static void
+datasheet_fill(PurpleRequestDatasheet *sheet, GtkListStore *model)
+{
+	const GList *it;
+
+	gtk_list_store_clear(model);
+
+	it = purple_request_datasheet_get_records(sheet);
+	for (; it != NULL; it = g_list_next(it)) {
+		PurpleRequestDatasheetRecord *rec = it->data;
+		GtkTreeIter iter;
+
+		gtk_list_store_append(model, &iter);
+		gtk_list_store_set(model, &iter, 0,
+			purple_request_datasheet_record_get_key(rec), -1);
+
+		datasheet_update_rec(rec, model, &iter);
+	}
+}
+
+static void
+datasheet_update(PurpleRequestDatasheet *sheet, gpointer key,
+	GtkListStore *model)
+{
+	PurpleRequestDatasheetRecord *rec;
+	GtkTreeIter iter;
+	GtkTreeModel *tmodel = GTK_TREE_MODEL(model);
+	gboolean found = FALSE;
+
+	g_return_if_fail(tmodel != NULL);
+
+	if (key == NULL) {
+		datasheet_fill(sheet, model);
+		return;
+	}
+
+	rec = purple_request_datasheet_record_find(sheet, key);
+
+	if (gtk_tree_model_get_iter_first(tmodel, &iter)) {
+		do {
+			gpointer ikey;
+
+			gtk_tree_model_get(tmodel, &iter, 0, &ikey, -1);
+
+			if (key == ikey) {
+				found = TRUE;
+				break;
+			}
+		} while (gtk_tree_model_iter_next(tmodel, &iter));
+	}
+
+	if (rec == NULL && !found) {
+		return;
+	}
+
+	if (rec == NULL) {
+		gtk_list_store_remove(model, &iter);
+		return;
+	}
+
+	if (!found) {
+		gtk_list_store_append(model, &iter);
+		gtk_list_store_set(model, &iter, 0, key, -1);
+	}
+
+	datasheet_update_rec(rec, model, &iter);
+}
+
+static GtkWidget *
+create_datasheet_field(PurpleRequestField *field)
+{
+	PurpleRequestDatasheet *sheet;
+	guint i, col_count;
+	GType *col_types;
+	GtkListStore *model;
+	GtkTreeView *view;
+	GtkWidget *scrollable;
+	GtkCellRenderer *renderer_image = NULL, *renderer_text = NULL;
+	GtkTreeViewColumn *id_column;
+
+	sheet = purple_request_field_datasheet_get_sheet(field);
+
+	col_count = purple_request_datasheet_get_column_count(sheet);
+
+	col_types = g_new0(GType, col_count + 1);
+	col_types[0] = G_TYPE_POINTER;
+	for (i = 0; i < col_count; i++) {
+		PurpleRequestDatasheetColumnType type;
+		type = purple_request_datasheet_get_column_type(sheet, i);
+		if (type == PURPLE_REQUEST_DATASHEET_COLUMN_STRING)
+			col_types[i + 1] = G_TYPE_STRING;
+		else if (type == PURPLE_REQUEST_DATASHEET_COLUMN_IMAGE)
+			col_types[i + 1] = GDK_TYPE_PIXBUF;
+		else
+			g_warn_if_reached();
+	}
+	model = gtk_list_store_newv(col_count + 1, col_types);
+	g_free(col_types);
+
+	view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(
+		GTK_TREE_MODEL(model)));
+	g_object_unref(G_OBJECT(model));
+
+	id_column = gtk_tree_view_column_new();
+	gtk_tree_view_column_set_visible(id_column, FALSE);
+	gtk_tree_view_append_column(view, id_column);
+
+	for (i = 0; i < col_count; i++) {
+		PurpleRequestDatasheetColumnType type;
+		const gchar *title;
+		GtkCellRenderer *renderer;
+		const gchar *type_str = "";
+
+		type = purple_request_datasheet_get_column_type(sheet, i);
+		title = purple_request_datasheet_get_column_title(sheet, i);
+
+		if (type == PURPLE_REQUEST_DATASHEET_COLUMN_STRING) {
+			type_str = "text";
+			if (!renderer_text)
+				renderer_text = gtk_cell_renderer_text_new();
+			renderer = renderer_text;
+		}
+		else if (type == PURPLE_REQUEST_DATASHEET_COLUMN_IMAGE) {
+			type_str = "pixbuf";
+			if (!renderer_image)
+				renderer_image = gtk_cell_renderer_pixbuf_new();
+			renderer = renderer_image;
+		} else
+			g_warn_if_reached();
+
+		if (title == NULL)
+			title = "";
+		gtk_tree_view_insert_column_with_attributes(
+			view, -1, title, renderer, type_str,
+			i + 1, NULL);
+	}
+
+	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
+
+	datasheet_fill(sheet, model);
+	purple_signal_connect(sheet, "record-changed",
+		pidgin_request_get_handle(),
+		PURPLE_CALLBACK(datasheet_update), model);
+
+	gtk_widget_set_size_request(GTK_WIDGET(view), 400, 250);
+
+	scrollable = pidgin_make_scrollable(GTK_WIDGET(view),
+		GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1);
+	gtk_widget_show(GTK_WIDGET(view));
+	return scrollable;
+}
+
 static void *
 pidgin_request_fields(const char *title, const char *primary,
 	const char *secondary, PurpleRequestFields *fields, const char *ok_text,
@@ -1779,6 +2042,7 @@
 		size_t col_num;
 		size_t row_num = 0;
 		guint tab_no;
+		gboolean contains_resizable = FALSE, frame_fill;
 
 		group      = gl->data;
 		field_list = purple_request_field_group_get_fields(group);
@@ -1818,6 +2082,9 @@
 
 			type = purple_request_field_get_type(field);
 
+			if (type == PURPLE_REQUEST_FIELD_DATASHEET)
+				contains_resizable = TRUE;
+
 			if (type == PURPLE_REQUEST_FIELD_LABEL)
 			{
 				if (col_num > 0)
@@ -1849,8 +2116,8 @@
 		gtk_table_set_row_spacings(GTK_TABLE(table), PIDGIN_HIG_BOX_SPACE);
 		gtk_table_set_col_spacings(GTK_TABLE(table), PIDGIN_HIG_BOX_SPACE);
 
-		gtk_box_pack_start(GTK_BOX(frame), table,
-			(notebook == NULL), (notebook == NULL), 0);
+		frame_fill = (notebook == NULL || contains_resizable);
+		gtk_box_pack_start(GTK_BOX(frame), table, frame_fill, frame_fill, 0);
 		gtk_widget_show(table);
 
 		for (row_num = 0, fl = field_list;
@@ -1942,6 +2209,8 @@
 						widget = create_account_field(field);
 					else if (type == PURPLE_REQUEST_FIELD_CERTIFICATE)
 						widget = create_certificate_field(field);
+					else if (type == PURPLE_REQUEST_FIELD_DATASHEET)
+						widget = create_datasheet_field(field);
 					else
 						continue;
 				}
@@ -2274,3 +2543,26 @@
 {
 	return &ops;
 }
+
+void *
+pidgin_request_get_handle(void)
+{
+	static int handle;
+
+	return &handle;
+}
+
+void
+pidgin_request_init(void)
+{
+	datasheet_stock = g_hash_table_new_full(g_str_hash, g_str_equal,
+		g_free, g_object_unref);
+}
+
+void
+pidgin_request_uninit(void)
+{
+	purple_signals_disconnect_by_handle(pidgin_request_get_handle());
+	g_hash_table_destroy(datasheet_stock);
+	datasheet_stock = NULL;
+}
--- a/pidgin/gtkrequest.h	Mon Oct 28 20:58:24 2013 +0530
+++ b/pidgin/gtkrequest.h	Wed Oct 30 02:58:57 2013 +0530
@@ -47,6 +47,30 @@
 GtkWindow *
 pidgin_request_get_dialog_window(void *ui_handle);
 
+/**************************************************************************/
+/** @name GTK+ Requests Subsystem                                         */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the gtk requests subsystem handle.
+ *
+ * @return The requests subsystem handle.
+ */
+void *pidgin_request_get_handle(void);
+
+/**
+ * Initializes the GTK+ requests subsystem.
+ */
+void pidgin_request_init(void);
+
+/**
+ * Uninitializes the GTK+ requests subsystem.
+ */
+void pidgin_request_uninit(void);
+
+/*@}*/
+
 G_END_DECLS
 
 #endif /* _PIDGINREQUEST_H_ */

mercurial