aboutsummaryrefslogtreecommitdiffstats
path: root/tp-account-widgets
diff options
context:
space:
mode:
authorEmanuele Aina <emanuele.aina@collabora.com>2013-03-27 00:39:28 +0800
committerMarco Barisione <marco.barisione@collabora.co.uk>2013-08-20 18:03:04 +0800
commite2c9efce03711a62db2eadc118fd2266da325d73 (patch)
treed16ad4f66d5cea66bfc735e2249f1d57490950fb /tp-account-widgets
parent5cbc27ef0f4373175af5725d1a0b78d464bb23b3 (diff)
downloadgsoc2013-empathy-e2c9efce03711a62db2eadc118fd2266da325d73.tar
gsoc2013-empathy-e2c9efce03711a62db2eadc118fd2266da325d73.tar.gz
gsoc2013-empathy-e2c9efce03711a62db2eadc118fd2266da325d73.tar.bz2
gsoc2013-empathy-e2c9efce03711a62db2eadc118fd2266da325d73.tar.lz
gsoc2013-empathy-e2c9efce03711a62db2eadc118fd2266da325d73.tar.xz
gsoc2013-empathy-e2c9efce03711a62db2eadc118fd2266da325d73.tar.zst
gsoc2013-empathy-e2c9efce03711a62db2eadc118fd2266da325d73.zip
tp-account-widgets: Move the IRC support sources with the account widget
To handle different networks and servers the IRC account widget uses many helper object and functions. Move them close to the IRC account widget sources. https://bugzilla.gnome.org/show_bug.cgi?id=699492
Diffstat (limited to 'tp-account-widgets')
-rw-r--r--tp-account-widgets/Makefile.am9
-rw-r--r--tp-account-widgets/empathy-irc-network-manager.c852
-rw-r--r--tp-account-widgets/empathy-irc-network-manager.h85
-rw-r--r--tp-account-widgets/empathy-irc-network.c389
-rw-r--r--tp-account-widgets/empathy-irc-network.h86
-rw-r--r--tp-account-widgets/empathy-irc-server.c222
-rw-r--r--tp-account-widgets/empathy-irc-server.h64
7 files changed, 1705 insertions, 2 deletions
diff --git a/tp-account-widgets/Makefile.am b/tp-account-widgets/Makefile.am
index c3a23a009..38a482e1b 100644
--- a/tp-account-widgets/Makefile.am
+++ b/tp-account-widgets/Makefile.am
@@ -1,5 +1,3 @@
-include $(top_srcdir)/tools/flymake.mk
-
AM_CPPFLAGS = \
$(ERROR_CFLAGS) \
-I$(top_srcdir)/libempathy \
@@ -25,6 +23,9 @@ libtp_account_widgets_sources = \
empathy-irc-network-chooser.c \
empathy-irc-network-chooser-dialog.c \
empathy-irc-network-dialog.c \
+ empathy-irc-network-manager.c \
+ empathy-irc-network.c \
+ empathy-irc-server.c \
totem-subtitle-encoding.c \
$(NULL)
@@ -35,6 +36,10 @@ libtp_account_widgets_headers = \
empathy-irc-network-chooser-dialog.h \
empathy-irc-network-chooser.h \
empathy-irc-network-dialog.h \
+ empathy-irc-network-manager.h \
+ empathy-irc-network.h \
+ empathy-irc-server.h \
+ empathy-utils.h \
totem-subtitle-encoding.h \
$(NULL)
diff --git a/tp-account-widgets/empathy-irc-network-manager.c b/tp-account-widgets/empathy-irc-network-manager.c
new file mode 100644
index 000000000..3f53a49ad
--- /dev/null
+++ b/tp-account-widgets/empathy-irc-network-manager.c
@@ -0,0 +1,852 @@
+/*
+ * Copyright (C) 2007-2008 Guillaume Desmottes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#include "config.h"
+#include "empathy-irc-network-manager.h"
+
+#include <sys/stat.h>
+
+#include "empathy-utils.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_IRC
+#include "empathy-debug.h"
+
+#define IRC_NETWORKS_DTD_RESOURCENAME "/org/gnome/Empathy/empathy-irc-networks.dtd"
+#define IRC_NETWORKS_FILENAME "irc-networks.xml"
+#define SAVE_TIMER 4
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcNetworkManager)
+typedef struct {
+ GHashTable *networks;
+
+ gchar *global_file;
+ gchar *user_file;
+ guint last_id;
+
+ /* Do we have to save modifications to the user file ? */
+ gboolean have_to_save;
+ /* Are we loading networks from XML files ? */
+ gboolean loading;
+ /* source id of the autosave timer */
+ gint save_timer_id;
+} EmpathyIrcNetworkManagerPriv;
+
+/* properties */
+enum
+{
+ PROP_GLOBAL_FILE = 1,
+ PROP_USER_FILE,
+ LAST_PROPERTY
+};
+
+G_DEFINE_TYPE (EmpathyIrcNetworkManager, empathy_irc_network_manager,
+ G_TYPE_OBJECT);
+
+static void irc_network_manager_load_servers (
+ EmpathyIrcNetworkManager *manager);
+static gboolean irc_network_manager_file_parse (
+ EmpathyIrcNetworkManager *manager, const gchar *filename,
+ gboolean user_defined);
+static gboolean irc_network_manager_file_save (
+ EmpathyIrcNetworkManager *manager);
+
+static void
+empathy_irc_network_manager_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIrcNetworkManager *self = EMPATHY_IRC_NETWORK_MANAGER (object);
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ switch (property_id)
+ {
+ case PROP_GLOBAL_FILE:
+ g_value_set_string (value, priv->global_file);
+ break;
+ case PROP_USER_FILE:
+ g_value_set_string (value, priv->user_file);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+empathy_irc_network_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIrcNetworkManager *self = EMPATHY_IRC_NETWORK_MANAGER (object);
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ switch (property_id)
+ {
+ case PROP_GLOBAL_FILE:
+ g_free (priv->global_file);
+ priv->global_file = g_value_dup_string (value);
+ break;
+ case PROP_USER_FILE:
+ g_free (priv->user_file);
+ priv->user_file = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+empathy_irc_network_manager_constructor (GType type,
+ guint n_props,
+ GObjectConstructParam *props)
+{
+ GObject *obj;
+ EmpathyIrcNetworkManager *self;
+
+ /* Parent constructor chain */
+ obj = G_OBJECT_CLASS (empathy_irc_network_manager_parent_class)->
+ constructor (type, n_props, props);
+
+ self = EMPATHY_IRC_NETWORK_MANAGER (obj);
+ irc_network_manager_load_servers (self);
+
+ return obj;
+}
+
+static void
+empathy_irc_network_manager_finalize (GObject *object)
+{
+ EmpathyIrcNetworkManager *self = EMPATHY_IRC_NETWORK_MANAGER (object);
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ if (priv->save_timer_id > 0)
+ {
+ g_source_remove (priv->save_timer_id);
+ }
+
+ if (priv->have_to_save)
+ {
+ irc_network_manager_file_save (self);
+ }
+
+ g_free (priv->global_file);
+ g_free (priv->user_file);
+
+ g_hash_table_unref (priv->networks);
+
+ G_OBJECT_CLASS (empathy_irc_network_manager_parent_class)->finalize (object);
+}
+
+static void
+empathy_irc_network_manager_init (EmpathyIrcNetworkManager *self)
+{
+ EmpathyIrcNetworkManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EMPATHY_TYPE_IRC_NETWORK_MANAGER, EmpathyIrcNetworkManagerPriv);
+
+ self->priv = priv;
+
+ priv->networks = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, (GDestroyNotify) g_object_unref);
+
+ priv->last_id = 0;
+
+ priv->have_to_save = FALSE;
+ priv->loading = FALSE;
+ priv->save_timer_id = 0;
+}
+
+static void
+empathy_irc_network_manager_class_init (EmpathyIrcNetworkManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *param_spec;
+
+ object_class->constructor = empathy_irc_network_manager_constructor;
+ object_class->get_property = empathy_irc_network_manager_get_property;
+ object_class->set_property = empathy_irc_network_manager_set_property;
+
+ g_type_class_add_private (object_class, sizeof (EmpathyIrcNetworkManagerPriv));
+
+ object_class->finalize = empathy_irc_network_manager_finalize;
+
+ param_spec = g_param_spec_string (
+ "global-file",
+ "path of the global networks file",
+ "The path of the system-wide filename from which we have to load"
+ " the networks list",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_GLOBAL_FILE, param_spec);
+
+ param_spec = g_param_spec_string (
+ "user-file",
+ "path of the user networks file",
+ "The path of user's filename from which we have to load"
+ " the networks list and to which we'll save his modifications",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_USER_FILE, param_spec);
+}
+
+/**
+ * empathy_irc_network_manager_new:
+ * @global_file: the path of the global networks file, or %NULL
+ * @user_file: the path of the user networks file, or %NULL
+ *
+ * Creates a new #EmpathyIrcNetworkManager
+ *
+ * Returns: a new #EmpathyIrcNetworkManager
+ */
+EmpathyIrcNetworkManager *
+empathy_irc_network_manager_new (const gchar *global_file,
+ const gchar *user_file)
+{
+ EmpathyIrcNetworkManager *manager;
+
+ manager = g_object_new (EMPATHY_TYPE_IRC_NETWORK_MANAGER,
+ "global-file", global_file,
+ "user-file", user_file,
+ NULL);
+
+ return manager;
+}
+
+static gboolean
+save_timeout (EmpathyIrcNetworkManager *self)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ priv->save_timer_id = 0;
+ irc_network_manager_file_save (self);
+
+ return FALSE;
+}
+
+static void
+reset_save_timeout (EmpathyIrcNetworkManager *self)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ if (priv->save_timer_id > 0)
+ {
+ g_source_remove (priv->save_timer_id);
+ }
+
+ priv->save_timer_id = g_timeout_add_seconds (SAVE_TIMER,
+ (GSourceFunc) save_timeout, self);
+}
+
+static void
+network_modified (EmpathyIrcNetwork *network,
+ EmpathyIrcNetworkManager *self)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ network->user_defined = TRUE;
+
+ if (!priv->loading)
+ {
+ priv->have_to_save = TRUE;
+ reset_save_timeout (self);
+ }
+}
+
+static void
+add_network (EmpathyIrcNetworkManager *self,
+ EmpathyIrcNetwork *network,
+ const gchar *id)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ g_hash_table_insert (priv->networks, g_strdup (id), g_object_ref (network));
+
+ g_signal_connect (network, "modified", G_CALLBACK (network_modified), self);
+}
+
+/**
+ * empathy_irc_network_manager_add:
+ * @manager: an #EmpathyIrcNetworkManager
+ * @network: the #EmpathyIrcNetwork to add
+ *
+ * Add an #EmpathyIrcNetwork to the given #EmpathyIrcNetworkManager.
+ *
+ */
+void
+empathy_irc_network_manager_add (EmpathyIrcNetworkManager *self,
+ EmpathyIrcNetwork *network)
+{
+ EmpathyIrcNetworkManagerPriv *priv;
+ gchar *id = NULL;
+
+ g_return_if_fail (EMPATHY_IS_IRC_NETWORK_MANAGER (self));
+ g_return_if_fail (EMPATHY_IS_IRC_NETWORK (network));
+
+ priv = GET_PRIV (self);
+
+ /* generate an id for this network */
+ do
+ {
+ g_free (id);
+ id = g_strdup_printf ("id%u", ++priv->last_id);
+ } while (g_hash_table_lookup (priv->networks, id) != NULL &&
+ priv->last_id < G_MAXUINT);
+
+ if (priv->last_id == G_MAXUINT)
+ {
+ DEBUG ("Can't add network: too many networks using a similar ID");
+ return;
+ }
+
+ DEBUG ("add server with \"%s\" as ID", id);
+
+ network->user_defined = TRUE;
+ add_network (self, network, id);
+
+ priv->have_to_save = TRUE;
+ reset_save_timeout (self);
+
+ g_free (id);
+}
+
+/**
+ * empathy_irc_network_manager_remove:
+ * @manager: an #EmpathyIrcNetworkManager
+ * @network: the #EmpathyIrcNetwork to remove
+ *
+ * Remove an #EmpathyIrcNetwork from the given #EmpathyIrcNetworkManager.
+ *
+ */
+void
+empathy_irc_network_manager_remove (EmpathyIrcNetworkManager *self,
+ EmpathyIrcNetwork *network)
+{
+ EmpathyIrcNetworkManagerPriv *priv;
+
+ g_return_if_fail (EMPATHY_IS_IRC_NETWORK_MANAGER (self));
+ g_return_if_fail (EMPATHY_IS_IRC_NETWORK (network));
+
+ priv = GET_PRIV (self);
+
+ network->user_defined = TRUE;
+ network->dropped = TRUE;
+
+ priv->have_to_save = TRUE;
+ reset_save_timeout (self);
+}
+
+static void
+append_active_networks_to_list (const gchar *id,
+ EmpathyIrcNetwork *network,
+ GSList **list)
+{
+ if (network->dropped)
+ return;
+
+ *list = g_slist_prepend (*list, g_object_ref (network));
+}
+
+static void
+append_dropped_networks_to_list (const gchar *id,
+ EmpathyIrcNetwork *network,
+ GSList **list)
+{
+ if (!network->dropped)
+ return;
+
+ *list = g_slist_prepend (*list, g_object_ref (network));
+}
+
+static GSList *
+get_network_list (EmpathyIrcNetworkManager *self,
+ gboolean get_active)
+{
+ EmpathyIrcNetworkManagerPriv *priv;
+ GSList *irc_networks = NULL;
+
+ g_return_val_if_fail (EMPATHY_IS_IRC_NETWORK_MANAGER (self), NULL);
+
+ priv = GET_PRIV (self);
+
+ if (get_active)
+ {
+ g_hash_table_foreach (priv->networks,
+ (GHFunc) append_active_networks_to_list, &irc_networks);
+ }
+ else
+ {
+ g_hash_table_foreach (priv->networks,
+ (GHFunc) append_dropped_networks_to_list, &irc_networks);
+ }
+
+ return irc_networks;
+}
+
+/**
+ * empathy_irc_network_manager_get_networks:
+ * @manager: an #EmpathyIrcNetworkManager
+ *
+ * Get the list of #EmpathyIrcNetwork associated with the given
+ * manager.
+ *
+ * Returns: a new #GSList of refed #EmpathyIrcNetwork
+ */
+GSList *
+empathy_irc_network_manager_get_networks (EmpathyIrcNetworkManager *self)
+{
+ return get_network_list (self, TRUE);
+}
+
+/**
+ * empathy_irc_network_manager_get_dropped_networks:
+ * @manager: an #EmpathyIrcNetworkManager
+ *
+ * Get the list of dropped #EmpathyIrcNetworks associated with the given
+ * manager.
+ *
+ * Returns: a new #GSList of refed dropped #EmpathyIrcNetworks
+ */
+GSList *
+empathy_irc_network_manager_get_dropped_networks (EmpathyIrcNetworkManager *self)
+{
+ return get_network_list (self, FALSE);
+}
+
+/*
+ * API to save/load and parse the irc_networks file.
+ */
+
+static void
+load_global_file (EmpathyIrcNetworkManager *self)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ if (priv->global_file == NULL)
+ return;
+
+ if (!g_file_test (priv->global_file, G_FILE_TEST_EXISTS))
+ {
+ DEBUG ("Global networks file %s doesn't exist", priv->global_file);
+ return;
+ }
+
+ irc_network_manager_file_parse (self, priv->global_file, FALSE);
+}
+
+static void
+load_user_file (EmpathyIrcNetworkManager *self)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ if (priv->user_file == NULL)
+ return;
+
+ if (!g_file_test (priv->user_file, G_FILE_TEST_EXISTS))
+ {
+ DEBUG ("User networks file %s doesn't exist", priv->global_file);
+ return;
+ }
+
+ irc_network_manager_file_parse (self, priv->user_file, TRUE);
+}
+
+static void
+irc_network_manager_load_servers (EmpathyIrcNetworkManager *self)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+
+ priv->loading = TRUE;
+
+ load_global_file (self);
+ load_user_file (self);
+
+ priv->loading = FALSE;
+ priv->have_to_save = FALSE;
+}
+
+static void
+irc_network_manager_parse_irc_server (EmpathyIrcNetwork *network,
+ xmlNodePtr node)
+{
+ xmlNodePtr server_node;
+
+ for (server_node = node->children; server_node;
+ server_node = server_node->next)
+ {
+ gchar *address = NULL, *port = NULL, *ssl = NULL;
+
+ if (strcmp ((const gchar *) server_node->name, "server") != 0)
+ continue;
+
+ address = (gchar *) xmlGetProp (server_node, (const xmlChar *) "address");
+ port = (gchar *) xmlGetProp (server_node, (const xmlChar *) "port");
+ ssl = (gchar *) xmlGetProp (server_node, (const xmlChar *) "ssl");
+
+ if (address != NULL)
+ {
+ gint port_nb = 0;
+ gboolean have_ssl = FALSE;
+ EmpathyIrcServer *server;
+
+ if (port != NULL)
+ port_nb = strtol (port, NULL, 10);
+
+ if (port_nb <= 0 || port_nb > G_MAXUINT16)
+ port_nb = 6667;
+
+ if (ssl == NULL || strcmp (ssl, "TRUE") == 0)
+ have_ssl = TRUE;
+
+ DEBUG ("parsed server %s port %d ssl %d", address, port_nb, have_ssl);
+
+ server = empathy_irc_server_new (address, port_nb, have_ssl);
+ empathy_irc_network_append_server (network, server);
+ }
+
+ if (address)
+ xmlFree (address);
+ if (port)
+ xmlFree (port);
+ if (ssl)
+ xmlFree (ssl);
+ }
+}
+
+static void
+irc_network_manager_parse_irc_network (EmpathyIrcNetworkManager *self,
+ xmlNodePtr node,
+ gboolean user_defined)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+ EmpathyIrcNetwork *network;
+ xmlNodePtr child;
+ gchar *str;
+ gchar *id, *name;
+
+ id = (gchar *) xmlGetProp (node, (const xmlChar *) "id");
+ if (xmlHasProp (node, (const xmlChar *) "dropped"))
+ {
+ if (!user_defined)
+ {
+ DEBUG ("the 'dropped' attribute shouldn't be used in the global file");
+ }
+
+ network = g_hash_table_lookup (priv->networks, id);
+ if (network != NULL)
+ {
+ network->dropped = TRUE;
+ network->user_defined = TRUE;
+ }
+ xmlFree (id);
+ return;
+ }
+
+ if (!xmlHasProp (node, (const xmlChar *) "name"))
+ return;
+
+ name = (gchar *) xmlGetProp (node, (const xmlChar *) "name");
+ network = empathy_irc_network_new (name);
+
+ if (xmlHasProp (node, (const xmlChar *) "network_charset"))
+ {
+ gchar *charset;
+ charset = (gchar *) xmlGetProp (node, (const xmlChar *) "network_charset");
+ g_object_set (network, "charset", charset, NULL);
+ xmlFree (charset);
+ }
+
+ add_network (self, network, id);
+ DEBUG ("add network %s (id %s)", name, id);
+
+ for (child = node->children; child; child = child->next)
+ {
+ gchar *tag;
+
+ tag = (gchar *) child->name;
+ str = (gchar *) xmlNodeGetContent (child);
+
+ if (!str)
+ continue;
+
+ if (strcmp (tag, "servers") == 0)
+ {
+ irc_network_manager_parse_irc_server (network, child);
+ }
+
+ xmlFree (str);
+ }
+
+ network->user_defined = user_defined;
+ g_object_unref (network);
+ xmlFree (name);
+ xmlFree (id);
+}
+
+static gboolean
+irc_network_manager_file_parse (EmpathyIrcNetworkManager *self,
+ const gchar *filename,
+ gboolean user_defined)
+{
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr doc;
+ xmlNodePtr networks;
+ xmlNodePtr node;
+
+ DEBUG ("Attempting to parse file:'%s'...", filename);
+
+ ctxt = xmlNewParserCtxt ();
+
+ /* Parse and validate the file. */
+ doc = xmlCtxtReadFile (ctxt, filename, NULL, 0);
+ if (!doc)
+ {
+ g_warning ("Failed to parse file:'%s'", filename);
+ xmlFreeParserCtxt (ctxt);
+ return FALSE;
+ }
+
+ if (!empathy_xml_validate_from_resource (doc, IRC_NETWORKS_DTD_RESOURCENAME)) {
+ g_warning ("Failed to validate file:'%s'", filename);
+ xmlFreeDoc (doc);
+ xmlFreeParserCtxt (ctxt);
+ return FALSE;
+ }
+
+ /* The root node, networks. */
+ networks = xmlDocGetRootElement (doc);
+
+ for (node = networks->children; node; node = node->next)
+ {
+ irc_network_manager_parse_irc_network (self, node, user_defined);
+ }
+
+ xmlFreeDoc (doc);
+ xmlFreeParserCtxt (ctxt);
+
+ return TRUE;
+}
+
+static void
+write_network_to_xml (const gchar *id,
+ EmpathyIrcNetwork *network,
+ xmlNodePtr root)
+{
+ xmlNodePtr network_node, servers_node;
+ GSList *servers, *l;
+ gchar *name, *charset;
+
+ if (!network->user_defined)
+ /* no need to write this network to the XML */
+ return;
+
+ network_node = xmlNewChild (root, NULL, (const xmlChar *) "network", NULL);
+ xmlNewProp (network_node, (const xmlChar *) "id", (const xmlChar *) id);
+
+ if (network->dropped)
+ {
+ xmlNewProp (network_node, (const xmlChar *) "dropped",
+ (const xmlChar *) "1");
+ return;
+ }
+
+ g_object_get (network,
+ "name", &name,
+ "charset", &charset,
+ NULL);
+ xmlNewProp (network_node, (const xmlChar *) "name", (const xmlChar *) name);
+ xmlNewProp (network_node, (const xmlChar *) "network_charset",
+ (const xmlChar *) charset);
+ g_free (name);
+ g_free (charset);
+
+ servers = empathy_irc_network_get_servers (network);
+
+ servers_node = xmlNewChild (network_node, NULL, (const xmlChar *) "servers",
+ NULL);
+ for (l = servers; l != NULL; l = g_slist_next (l))
+ {
+ EmpathyIrcServer *server;
+ xmlNodePtr server_node;
+ gchar *address, *tmp;
+ guint port;
+ gboolean ssl;
+
+ server = l->data;
+
+ server_node = xmlNewChild (servers_node, NULL, (const xmlChar *) "server",
+ NULL);
+
+ g_object_get (server,
+ "address", &address,
+ "port", &port,
+ "ssl", &ssl,
+ NULL);
+
+ xmlNewProp (server_node, (const xmlChar *) "address",
+ (const xmlChar *) address);
+
+ tmp = g_strdup_printf ("%u", port);
+ xmlNewProp (server_node, (const xmlChar *) "port",
+ (const xmlChar *) tmp);
+ g_free (tmp);
+
+ xmlNewProp (server_node, (const xmlChar *) "ssl",
+ ssl ? (const xmlChar *) "TRUE": (const xmlChar *) "FALSE");
+
+ g_free (address);
+ }
+
+ /* free the list */
+ g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+ g_slist_free (servers);
+}
+
+static gboolean
+irc_network_manager_file_save (EmpathyIrcNetworkManager *self)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+ xmlDocPtr doc;
+ xmlNodePtr root;
+
+ if (priv->user_file == NULL)
+ {
+ DEBUG ("can't save: no user file defined");
+ return FALSE;
+ }
+
+ DEBUG ("Saving IRC networks");
+
+ doc = xmlNewDoc ((const xmlChar *) "1.0");
+ root = xmlNewNode (NULL, (const xmlChar *) "networks");
+ xmlDocSetRootElement (doc, root);
+
+ g_hash_table_foreach (priv->networks, (GHFunc) write_network_to_xml, root);
+
+ /* Make sure the XML is indented properly */
+ xmlIndentTreeOutput = 1;
+
+ xmlSaveFormatFileEnc (priv->user_file, doc, "utf-8", 1);
+ xmlFreeDoc (doc);
+
+ xmlMemoryDump ();
+
+ priv->have_to_save = FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+find_network_by_address (const gchar *id,
+ EmpathyIrcNetwork *network,
+ const gchar *address)
+{
+ GSList *servers, *l;
+ gboolean found = FALSE;
+
+ if (network->dropped)
+ return FALSE;
+
+ servers = empathy_irc_network_get_servers (network);
+
+ for (l = servers; l != NULL && !found; l = g_slist_next (l))
+ {
+ EmpathyIrcServer *server = l->data;
+ gchar *_address;
+
+ g_object_get (server, "address", &_address, NULL);
+ found = (_address != NULL && strcmp (address, _address) == 0);
+
+ g_free (_address);
+ }
+
+ g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+ g_slist_free (servers);
+
+ return found;
+}
+
+/**
+ * empathy_irc_network_manager_find_network_by_address:
+ * @manager: an #EmpathyIrcNetworkManager
+ * @address: the server address to look for
+ *
+ * Find the #EmpathyIrcNetwork which owns an #EmpathyIrcServer
+ * that has the given address.
+ *
+ * Returns: the found #EmpathyIrcNetwork, or %NULL if not found.
+ */
+EmpathyIrcNetwork *
+empathy_irc_network_manager_find_network_by_address (
+ EmpathyIrcNetworkManager *self,
+ const gchar *address)
+{
+ EmpathyIrcNetworkManagerPriv *priv = GET_PRIV (self);
+ EmpathyIrcNetwork *network;
+
+ g_return_val_if_fail (address != NULL, NULL);
+
+ network = g_hash_table_find (priv->networks,
+ (GHRFunc) find_network_by_address, (gchar *) address);
+
+ return network;
+}
+
+EmpathyIrcNetworkManager *
+empathy_irc_network_manager_dup_default (void)
+{
+ static EmpathyIrcNetworkManager *default_mgr = NULL;
+ gchar *dir, *user_file_with_path, *global_file_with_path;
+
+ if (default_mgr != NULL)
+ return g_object_ref (default_mgr);
+
+ dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL);
+ g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
+ user_file_with_path = g_build_filename (dir, IRC_NETWORKS_FILENAME, NULL);
+ g_free (dir);
+
+ global_file_with_path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"),
+ "libempathy", IRC_NETWORKS_FILENAME, NULL);
+ if (!g_file_test (global_file_with_path, G_FILE_TEST_EXISTS))
+ {
+ g_free (global_file_with_path);
+ global_file_with_path = g_build_filename (DATADIR, "empathy",
+ IRC_NETWORKS_FILENAME, NULL);
+ }
+
+ default_mgr = empathy_irc_network_manager_new (
+ global_file_with_path, user_file_with_path);
+
+ g_object_add_weak_pointer (G_OBJECT (default_mgr), (gpointer *) &default_mgr);
+
+ g_free (global_file_with_path);
+ g_free (user_file_with_path);
+ return default_mgr;
+}
diff --git a/tp-account-widgets/empathy-irc-network-manager.h b/tp-account-widgets/empathy-irc-network-manager.h
new file mode 100644
index 000000000..19df2f7e1
--- /dev/null
+++ b/tp-account-widgets/empathy-irc-network-manager.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007-2008 Guillaume Desmottes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#ifndef __EMPATHY_IRC_NETWORK_MANAGER_H__
+#define __EMPATHY_IRC_NETWORK_MANAGER_H__
+
+#include <glib-object.h>
+
+#include "empathy-irc-network.h"
+
+G_BEGIN_DECLS
+
+typedef struct _EmpathyIrcNetworkManager EmpathyIrcNetworkManager;
+typedef struct _EmpathyIrcNetworkManagerClass EmpathyIrcNetworkManagerClass;
+
+struct _EmpathyIrcNetworkManager
+{
+ GObject parent;
+ gpointer priv;
+};
+
+struct _EmpathyIrcNetworkManagerClass
+{
+ GObjectClass parent_class;
+};
+
+GType empathy_irc_network_manager_get_type (void);
+
+/* TYPE MACROS */
+#define EMPATHY_TYPE_IRC_NETWORK_MANAGER \
+ (empathy_irc_network_manager_get_type ())
+#define EMPATHY_IRC_NETWORK_MANAGER(o) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_IRC_NETWORK_MANAGER, \
+ EmpathyIrcNetworkManager))
+#define EMPATHY_IRC_NETWORK_MANAGER_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_IRC_NETWORK_MANAGER, \
+ EmpathyIrcNetworkManagerClass))
+#define EMPATHY_IS_IRC_NETWORK_MANAGER(o) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_IRC_NETWORK_MANAGER))
+#define EMPATHY_IS_IRC_NETWORK_MANAGER_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_IRC_NETWORK_MANAGER))
+#define EMPATHY_IRC_NETWORK_MANAGER_GET_CLASS(o) \
+ (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_IRC_NETWORK_MANAGER, \
+ EmpathyIrcNetworkManagerClass))
+
+EmpathyIrcNetworkManager * empathy_irc_network_manager_new (
+ const gchar *global_file, const gchar *user_file);
+
+EmpathyIrcNetworkManager * empathy_irc_network_manager_dup_default (void);
+
+void empathy_irc_network_manager_add (EmpathyIrcNetworkManager *manager,
+ EmpathyIrcNetwork *network);
+
+void empathy_irc_network_manager_remove (EmpathyIrcNetworkManager *manager,
+ EmpathyIrcNetwork *network);
+
+GSList * empathy_irc_network_manager_get_networks (
+ EmpathyIrcNetworkManager *manager);
+
+GSList * empathy_irc_network_manager_get_dropped_networks (
+ EmpathyIrcNetworkManager *manager);
+
+EmpathyIrcNetwork * empathy_irc_network_manager_find_network_by_address (
+ EmpathyIrcNetworkManager *manager, const gchar *address);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_IRC_NETWORK_MANAGER_H__ */
diff --git a/tp-account-widgets/empathy-irc-network.c b/tp-account-widgets/empathy-irc-network.c
new file mode 100644
index 000000000..e01116e96
--- /dev/null
+++ b/tp-account-widgets/empathy-irc-network.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2007 Guillaume Desmottes
+ *
+ * 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 St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#include "config.h"
+#include "empathy-irc-network.h"
+
+#include "empathy-utils.h"
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcNetwork)
+typedef struct
+{
+ gchar *name;
+ gchar *charset;
+ GSList *servers;
+} EmpathyIrcNetworkPriv;
+
+/* properties */
+enum
+{
+ PROP_NAME = 1,
+ PROP_CHARSET,
+ LAST_PROPERTY
+};
+
+/* signals */
+enum
+{
+ MODIFIED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+G_DEFINE_TYPE (EmpathyIrcNetwork, empathy_irc_network, G_TYPE_OBJECT);
+
+static void
+server_modified_cb (EmpathyIrcServer *server,
+ EmpathyIrcNetwork *self)
+{
+ g_signal_emit (self, signals[MODIFIED], 0);
+}
+
+static void
+empathy_irc_network_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIrcNetwork *self = EMPATHY_IRC_NETWORK (object);
+ EmpathyIrcNetworkPriv *priv = GET_PRIV (self);
+
+ switch (property_id)
+ {
+ case PROP_NAME:
+ g_value_set_string (value, priv->name);
+ break;
+ case PROP_CHARSET:
+ g_value_set_string (value, priv->charset);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+empathy_irc_network_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIrcNetwork *self = EMPATHY_IRC_NETWORK (object);
+ EmpathyIrcNetworkPriv *priv = GET_PRIV (self);
+
+ switch (property_id)
+ {
+ case PROP_NAME:
+ if (tp_strdiff (priv->name, g_value_get_string (value)))
+ {
+ g_free (priv->name);
+ priv->name = g_value_dup_string (value);
+ g_signal_emit (object, signals[MODIFIED], 0);
+ }
+ break;
+ case PROP_CHARSET:
+ if (tp_strdiff (priv->charset, g_value_get_string (value)))
+ {
+ g_free (priv->charset);
+ priv->charset = g_value_dup_string (value);
+ g_signal_emit (object, signals[MODIFIED], 0);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+empathy_irc_network_dispose (GObject *object)
+{
+ EmpathyIrcNetwork *self = EMPATHY_IRC_NETWORK (object);
+ EmpathyIrcNetworkPriv *priv = GET_PRIV (self);
+ GSList *l;
+
+ for (l = priv->servers; l != NULL; l = g_slist_next (l))
+ {
+ g_signal_handlers_disconnect_by_func (l->data,
+ G_CALLBACK (server_modified_cb), self);
+ g_object_unref (l->data);
+ }
+
+ G_OBJECT_CLASS (empathy_irc_network_parent_class)->dispose (object);
+}
+
+static void
+empathy_irc_network_finalize (GObject *object)
+{
+ EmpathyIrcNetwork *self = EMPATHY_IRC_NETWORK (object);
+ EmpathyIrcNetworkPriv *priv = GET_PRIV (self);
+
+ g_slist_free (priv->servers);
+ g_free (priv->name);
+ g_free (priv->charset);
+
+ G_OBJECT_CLASS (empathy_irc_network_parent_class)->finalize (object);
+}
+
+static void
+empathy_irc_network_init (EmpathyIrcNetwork *self)
+{
+ EmpathyIrcNetworkPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EMPATHY_TYPE_IRC_NETWORK, EmpathyIrcNetworkPriv);
+
+ self->priv = priv;
+
+ priv->servers = NULL;
+
+ self->user_defined = TRUE;
+ self->dropped = FALSE;
+}
+
+static void
+empathy_irc_network_class_init (EmpathyIrcNetworkClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *param_spec;
+
+ object_class->get_property = empathy_irc_network_get_property;
+ object_class->set_property = empathy_irc_network_set_property;
+
+ g_type_class_add_private (object_class, sizeof (EmpathyIrcNetworkPriv));
+
+ object_class->dispose = empathy_irc_network_dispose;
+ object_class->finalize = empathy_irc_network_finalize;
+
+ param_spec = g_param_spec_string (
+ "name",
+ "Network name",
+ "The displayed name of this network",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_NAME, param_spec);
+
+ param_spec = g_param_spec_string (
+ "charset",
+ "Charset",
+ "The charset to use on this network",
+ "UTF-8",
+ G_PARAM_CONSTRUCT |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_CHARSET, param_spec);
+
+ /**
+ * EmpathyIrcNetwork::modified:
+ * @network: the object that received the signal
+ *
+ * Emitted when either a property or a server of the network is modified or
+ * when a network is activated.
+ *
+ */
+ signals[MODIFIED] = g_signal_new (
+ "modified",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE, 0);
+}
+
+/**
+ * empathy_irc_network_activate:
+ * @self: the name of the network
+ *
+ * Activates a #EmpathyIrcNetwork.
+ *
+ */
+void
+empathy_irc_network_activate (EmpathyIrcNetwork *self)
+{
+ g_return_if_fail (EMPATHY_IS_IRC_NETWORK (self));
+ g_return_if_fail (self->dropped);
+
+ self->dropped = FALSE;
+
+ g_signal_emit (self, signals[MODIFIED], 0);
+}
+
+/**
+ * empathy_irc_network_new:
+ * @name: the name of the network
+ *
+ * Creates a new #EmpathyIrcNetwork.
+ *
+ * Returns: a new #EmpathyIrcNetwork
+ */
+EmpathyIrcNetwork *
+empathy_irc_network_new (const gchar *name)
+{
+ return g_object_new (EMPATHY_TYPE_IRC_NETWORK,
+ "name", name,
+ NULL);
+}
+
+/**
+ * empathy_irc_network_get_servers:
+ * @network: an #EmpathyIrcNetwork
+ *
+ * Get the list of #EmpathyIrcServer that belongs to this network.
+ * These servers are sorted according their priority.
+ * So the first one will be the first used when trying to connect to
+ * the network.
+ *
+ * Returns: a new #GSList of refed #EmpathyIrcServer.
+ */
+GSList *
+empathy_irc_network_get_servers (EmpathyIrcNetwork *self)
+{
+ EmpathyIrcNetworkPriv *priv;
+ GSList *servers = NULL, *l;
+
+ g_return_val_if_fail (EMPATHY_IS_IRC_NETWORK (self), NULL);
+ priv = GET_PRIV (self);
+
+ for (l = priv->servers; l != NULL; l = g_slist_next (l))
+ {
+ servers = g_slist_prepend (servers, g_object_ref (l->data));
+ }
+
+ return g_slist_reverse (servers);
+}
+
+/**
+ * empathy_irc_network_append_server:
+ * @network: an #EmpathyIrcNetwork
+ * @server: the #EmpathyIrcServer to add
+ *
+ * Add an #EmpathyIrcServer to the given #EmpathyIrcNetwork. The server
+ * is added at the last position in network's servers list.
+ *
+ */
+void
+empathy_irc_network_append_server (EmpathyIrcNetwork *self,
+ EmpathyIrcServer *server)
+{
+ EmpathyIrcNetworkPriv *priv;
+
+ g_return_if_fail (EMPATHY_IS_IRC_NETWORK (self));
+ g_return_if_fail (server != NULL && EMPATHY_IS_IRC_SERVER (server));
+
+ priv = GET_PRIV (self);
+
+ g_return_if_fail (g_slist_find (priv->servers, server) == NULL);
+
+ priv->servers = g_slist_append (priv->servers, g_object_ref (server));
+
+ g_signal_connect (server, "modified", G_CALLBACK (server_modified_cb), self);
+
+ g_signal_emit (self, signals[MODIFIED], 0);
+}
+
+/**
+ * empathy_irc_network_remove_server:
+ * @network: an #EmpathyIrcNetwork
+ * @server: the #EmpathyIrcServer to remove
+ *
+ * Remove an #EmpathyIrcServer from the servers list of the
+ * given #EmpathyIrcNetwork.
+ *
+ */
+void
+empathy_irc_network_remove_server (EmpathyIrcNetwork *self,
+ EmpathyIrcServer *server)
+{
+ EmpathyIrcNetworkPriv *priv;
+ GSList *l;
+
+ g_return_if_fail (EMPATHY_IS_IRC_NETWORK (self));
+ g_return_if_fail (server != NULL && EMPATHY_IS_IRC_SERVER (server));
+
+ priv = GET_PRIV (self);
+
+ l = g_slist_find (priv->servers, server);
+ if (l == NULL)
+ return;
+
+ g_object_unref (l->data);
+ priv->servers = g_slist_delete_link (priv->servers, l);
+ g_signal_handlers_disconnect_by_func (server, G_CALLBACK (server_modified_cb),
+ self);
+
+ g_signal_emit (self, signals[MODIFIED], 0);
+}
+
+/**
+ * empathy_irc_network_set_server_position:
+ * @network: an #EmpathyIrcNetwork
+ * @server: the #EmpathyIrcServer to move
+ * @pos: the position to move the server. If this is negative, or is larger than
+ * the number of servers in the list, the server is moved to the end of the
+ * list.
+ *
+ * Move an #EmpathyIrcServer in the servers list of the given
+ * #EmpathyIrcNetwork.
+ *
+ */
+void
+empathy_irc_network_set_server_position (EmpathyIrcNetwork *self,
+ EmpathyIrcServer *server,
+ gint pos)
+{
+ EmpathyIrcNetworkPriv *priv;
+ GSList *l;
+
+ g_return_if_fail (EMPATHY_IS_IRC_NETWORK (self));
+ g_return_if_fail (server != NULL && EMPATHY_IS_IRC_SERVER (server));
+
+ priv = GET_PRIV (self);
+
+ l = g_slist_find (priv->servers, server);
+ if (l == NULL)
+ return;
+
+ priv->servers = g_slist_delete_link (priv->servers, l);
+ priv->servers = g_slist_insert (priv->servers, server, pos);
+
+ g_signal_emit (self, signals[MODIFIED], 0);
+}
+
+const gchar *
+empathy_irc_network_get_name (EmpathyIrcNetwork *self)
+{
+ EmpathyIrcNetworkPriv *priv = GET_PRIV (self);
+
+ return priv->name;
+}
+
+const gchar *
+empathy_irc_network_get_charset (EmpathyIrcNetwork *self)
+{
+ EmpathyIrcNetworkPriv *priv = GET_PRIV (self);
+
+ return priv->charset;
+}
diff --git a/tp-account-widgets/empathy-irc-network.h b/tp-account-widgets/empathy-irc-network.h
new file mode 100644
index 000000000..a298ced9a
--- /dev/null
+++ b/tp-account-widgets/empathy-irc-network.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2007-2008 Guillaume Desmottes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#ifndef __EMPATHY_IRC_NETWORK_H__
+#define __EMPATHY_IRC_NETWORK_H__
+
+#include <glib-object.h>
+
+#include "empathy-irc-server.h"
+
+G_BEGIN_DECLS
+
+typedef struct _EmpathyIrcNetwork EmpathyIrcNetwork;
+typedef struct _EmpathyIrcNetworkClass EmpathyIrcNetworkClass;
+
+struct _EmpathyIrcNetwork
+{
+ GObject parent;
+ gpointer priv;
+
+ gboolean user_defined;
+ gboolean dropped;
+};
+
+struct _EmpathyIrcNetworkClass
+{
+ GObjectClass parent_class;
+};
+
+GType empathy_irc_network_get_type (void);
+
+/* TYPE MACROS */
+#define EMPATHY_TYPE_IRC_NETWORK (empathy_irc_network_get_type ())
+#define EMPATHY_IRC_NETWORK(o) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_IRC_NETWORK, \
+ EmpathyIrcNetwork))
+#define EMPATHY_IRC_NETWORK_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_IRC_NETWORK,\
+ EmpathyIrcNetworkClass))
+#define EMPATHY_IS_IRC_NETWORK(o) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_IRC_NETWORK))
+#define EMPATHY_IS_IRC_NETWORK_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_IRC_NETWORK))
+#define EMPATHY_IRC_NETWORK_GET_CLASS(o) \
+ (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_IRC_NETWORK, \
+ EmpathyIrcNetworkClass))
+
+void empathy_irc_network_activate (EmpathyIrcNetwork *self);
+
+EmpathyIrcNetwork * empathy_irc_network_new (const gchar *name);
+
+GSList * empathy_irc_network_get_servers (EmpathyIrcNetwork *network);
+
+void empathy_irc_network_append_server (EmpathyIrcNetwork *network,
+ EmpathyIrcServer *server);
+
+void empathy_irc_network_remove_server (EmpathyIrcNetwork *network,
+ EmpathyIrcServer *server);
+
+void empathy_irc_network_set_server_position (EmpathyIrcNetwork *network,
+ EmpathyIrcServer *server, gint pos);
+
+const gchar * empathy_irc_network_get_name (EmpathyIrcNetwork *network);
+
+const gchar * empathy_irc_network_get_charset (EmpathyIrcNetwork *network);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_IRC_NETWORK_H__ */
diff --git a/tp-account-widgets/empathy-irc-server.c b/tp-account-widgets/empathy-irc-server.c
new file mode 100644
index 000000000..75eb016dd
--- /dev/null
+++ b/tp-account-widgets/empathy-irc-server.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2007-2008 Guillaume Desmottes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#include "config.h"
+#include "empathy-irc-server.h"
+
+#include "empathy-utils.h"
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcServer)
+typedef struct
+{
+ gchar *address;
+ guint port;
+ gboolean ssl;
+} EmpathyIrcServerPriv;
+
+/* properties */
+enum
+{
+ PROP_ADDRESS = 1,
+ PROP_PORT,
+ PROP_SSL,
+ LAST_PROPERTY
+};
+
+/* signals */
+enum
+{
+ MODIFIED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+G_DEFINE_TYPE (EmpathyIrcServer, empathy_irc_server, G_TYPE_OBJECT);
+
+static void
+empathy_irc_server_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIrcServer *self = EMPATHY_IRC_SERVER (object);
+ EmpathyIrcServerPriv *priv = GET_PRIV (self);
+
+ switch (property_id)
+ {
+ case PROP_ADDRESS:
+ g_value_set_string (value, priv->address);
+ break;
+ case PROP_PORT:
+ g_value_set_uint (value, priv->port);
+ break;
+ case PROP_SSL:
+ g_value_set_boolean (value, priv->ssl);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+empathy_irc_server_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIrcServer *self = EMPATHY_IRC_SERVER (object);
+ EmpathyIrcServerPriv *priv = GET_PRIV (self);
+
+ switch (property_id)
+ {
+ case PROP_ADDRESS:
+ if (tp_strdiff (priv->address, g_value_get_string (value)))
+ {
+ g_free (priv->address);
+ priv->address = g_value_dup_string (value);
+ g_signal_emit (object, signals[MODIFIED], 0);
+ }
+ break;
+ case PROP_PORT:
+ if (priv->port != g_value_get_uint (value))
+ {
+ priv->port = g_value_get_uint (value);
+ g_signal_emit (object, signals[MODIFIED], 0);
+ }
+ break;
+ case PROP_SSL:
+ if (priv->ssl != g_value_get_boolean (value))
+ {
+ priv->ssl = g_value_get_boolean (value);
+ g_signal_emit (object, signals[MODIFIED], 0);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+empathy_irc_server_finalize (GObject *object)
+{
+ EmpathyIrcServer *self = EMPATHY_IRC_SERVER (object);
+ EmpathyIrcServerPriv *priv = GET_PRIV (self);
+
+ g_free (priv->address);
+
+ G_OBJECT_CLASS (empathy_irc_server_parent_class)->finalize (object);
+}
+
+static void
+empathy_irc_server_init (EmpathyIrcServer *self)
+{
+ EmpathyIrcServerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EMPATHY_TYPE_IRC_SERVER, EmpathyIrcServerPriv);
+
+ self->priv = priv;
+}
+
+static void
+empathy_irc_server_class_init (EmpathyIrcServerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *param_spec;
+
+ object_class->get_property = empathy_irc_server_get_property;
+ object_class->set_property = empathy_irc_server_set_property;
+
+ g_type_class_add_private (object_class, sizeof (EmpathyIrcServerPriv));
+
+ object_class->finalize = empathy_irc_server_finalize;
+
+ param_spec = g_param_spec_string (
+ "address",
+ "Server address",
+ "The address of this server",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_ADDRESS, param_spec);
+
+ param_spec = g_param_spec_uint (
+ "port",
+ "Server port",
+ "The port to use to connect on this server",
+ 1, G_MAXUINT16, 6667,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_PORT, param_spec);
+
+ param_spec = g_param_spec_boolean (
+ "ssl",
+ "SSL",
+ "If this server needs SSL connection",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_SSL, param_spec);
+
+ /**
+ * EmpathyIrcServer::modified:
+ * @server: the object that received the signal
+ *
+ * Emitted when a property of the server is modified.
+ *
+ */
+ signals[MODIFIED] = g_signal_new (
+ "modified",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE, 0);
+}
+
+/**
+ * empathy_irc_server_new:
+ * @address: the address
+ * @port: the port
+ * @ssl: %TRUE if the server needs a SSL connection
+ *
+ * Creates a new #EmpathyIrcServer
+ *
+ * Returns: a new #EmpathyIrcServer
+ */
+EmpathyIrcServer *
+empathy_irc_server_new (const gchar *address,
+ guint port,
+ gboolean ssl)
+{
+ return g_object_new (EMPATHY_TYPE_IRC_SERVER,
+ "address", address,
+ "port", port,
+ "ssl", ssl,
+ NULL);
+}
diff --git a/tp-account-widgets/empathy-irc-server.h b/tp-account-widgets/empathy-irc-server.h
new file mode 100644
index 000000000..d72af64ac
--- /dev/null
+++ b/tp-account-widgets/empathy-irc-server.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007-2008 Guillaume Desmottes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#ifndef __EMPATHY_IRC_SERVER_H__
+#define __EMPATHY_IRC_SERVER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _EmpathyIrcServer EmpathyIrcServer;
+typedef struct _EmpathyIrcServerClass EmpathyIrcServerClass;
+
+struct _EmpathyIrcServer
+{
+ GObject parent;
+ gpointer priv;
+};
+
+struct _EmpathyIrcServerClass
+{
+ GObjectClass parent_class;
+};
+
+GType empathy_irc_server_get_type (void);
+
+/* TYPE MACROS */
+#define EMPATHY_TYPE_IRC_SERVER (empathy_irc_server_get_type ())
+#define EMPATHY_IRC_SERVER(o) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_IRC_SERVER, EmpathyIrcServer))
+#define EMPATHY_IRC_SERVER_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_IRC_SERVER, \
+ EmpathyIrcServerClass))
+#define EMPATHY_IS_IRC_SERVER(o) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_IRC_SERVER))
+#define EMPATHY_IS_IRC_SERVER_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_IRC_SERVER))
+#define EMPATHY_IRC_SERVER_GET_CLASS(o) \
+ (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_IRC_SERVER,\
+ EmpathyIrcServerClass))
+
+EmpathyIrcServer * empathy_irc_server_new (const gchar *address, guint port,
+ gboolean ssl);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_IRC_SERVER_H__ */