]> git.0d.be Git - empathy.git/commitdiff
Merge commit 'cassidy/irc'
authorXavier Claessens <xclaesse@src.gnome.org>
Sun, 17 Feb 2008 23:38:19 +0000 (23:38 +0000)
committerXavier Claessens <xclaesse@src.gnome.org>
Sun, 17 Feb 2008 23:38:19 +0000 (23:38 +0000)
svn path=/trunk/; revision=649

36 files changed:
TODO
configure.ac
docs/libempathy-gtk/libempathy-gtk-docs.sgml
docs/libempathy/libempathy-docs.sgml
docs/libempathy/libempathy.types
libempathy-gtk/Makefile.am
libempathy-gtk/empathy-account-widget-irc.c [new file with mode: 0644]
libempathy-gtk/empathy-account-widget-irc.glade [new file with mode: 0644]
libempathy-gtk/empathy-account-widget-irc.h [new file with mode: 0644]
libempathy-gtk/empathy-accounts-dialog.c
libempathy-gtk/empathy-irc-network-dialog.c [new file with mode: 0644]
libempathy-gtk/empathy-irc-network-dialog.h [new file with mode: 0644]
libempathy-gtk/totem-subtitle-encoding.c [new file with mode: 0644]
libempathy-gtk/totem-subtitle-encoding.h [new file with mode: 0644]
libempathy/Makefile.am
libempathy/empathy-irc-network-manager.c [new file with mode: 0644]
libempathy/empathy-irc-network-manager.h [new file with mode: 0644]
libempathy/empathy-irc-network.c [new file with mode: 0644]
libempathy/empathy-irc-network.h [new file with mode: 0644]
libempathy/empathy-irc-networks.dtd [new file with mode: 0644]
libempathy/empathy-irc-server.c [new file with mode: 0644]
libempathy/empathy-irc-server.h [new file with mode: 0644]
libempathy/irc-networks.xml [new file with mode: 0644]
m4/Makefile.am [new file with mode: 0644]
po/POTFILES.in
tests/Makefile.am
tests/check-empathy-irc-network-manager.c [new file with mode: 0644]
tests/check-empathy-irc-network.c [new file with mode: 0644]
tests/check-empathy-irc-server.c [new file with mode: 0644]
tests/check-irc-helper.c [new file with mode: 0644]
tests/check-irc-helper.h [new file with mode: 0644]
tests/check-libempathy.h
tests/check-main.c
tests/xml/.gitignore [new file with mode: 0644]
tests/xml/default-irc-networks-sample.xml [new file with mode: 0644]
tests/xml/user-irc-networks-sample.xml [new file with mode: 0644]

diff --git a/TODO b/TODO
index 187f6191ed36d286a8952c12a575f6a6380ad436..ebeb081a6698eee24e6282d5fbf0fdcbf4a52e05 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,7 +1,5 @@
 Things you can do if you want to help:
 
 Things you can do if you want to help:
 
- - Specialised UI for configuring IRC accounts. (Guillaume is already working
-   on IRC widget).
  - UI for inviting a contact in a chatroom.
  - UI for accept/refuse invitation to join a chatroom and VoIP calls.
  - UI to send a message directly to a contact.
  - UI for inviting a contact in a chatroom.
  - UI for accept/refuse invitation to join a chatroom and VoIP calls.
  - UI to send a message directly to a contact.
@@ -25,7 +23,7 @@ Things you can do if you want to help:
  - See with Gnome Online Desktop project how to implement meta-contacts and
    merge information from multiple contacts.
  - Testing and Bugfixing.
  - See with Gnome Online Desktop project how to implement meta-contacts and
    merge information from multiple contacts.
  - Testing and Bugfixing.
+
 If you want to contribute you can ask for information at
  - #telepathy on freenode
  - Telepathy's mailing list: telepathy@lists.freedesktop.org
 If you want to contribute you can ask for information at
  - #telepathy on freenode
  - Telepathy's mailing list: telepathy@lists.freedesktop.org
index 2c0f90e1a1e3a6950af0675616bfff60841222e6..ac012243a068a5d5918dde7000ea4c4afcdf4527 100644 (file)
@@ -291,6 +291,7 @@ AM_CONDITIONAL(HAVE_VOIP, test "x$enable_voip" = "xyes")
 # -----------------------------------------------------------
 AC_DEFINE_UNQUOTED([UNINSTALLED_GLADE_DIR], ["`pwd`/libempathy-gtk"], [path to glade files])
 AC_DEFINE_UNQUOTED([UNINSTALLED_DTD_DIR], ["`pwd`/libempathy"], [path to dtd files])
 # -----------------------------------------------------------
 AC_DEFINE_UNQUOTED([UNINSTALLED_GLADE_DIR], ["`pwd`/libempathy-gtk"], [path to glade files])
 AC_DEFINE_UNQUOTED([UNINSTALLED_DTD_DIR], ["`pwd`/libempathy"], [path to dtd files])
+AC_DEFINE_UNQUOTED([UNINSTALLED_IRC_DIR], ["`pwd`/libempathy"], [path to IRC network file])
 
 # -----------------------------------------------------------
 
 
 # -----------------------------------------------------------
 
index e2f09b5ca92ddfc7946e1c59e38bf7ebc4f02ed1..ac591a78a3dbbbba491c171cb8cbff9e00631727 100644 (file)
@@ -52,6 +52,8 @@
     <xi:include href="xml/empathy-status-icon.xml"/>
     <xi:include href="xml/empathy-theme-manager.xml"/>
     <xi:include href="xml/empathy-ui-utils.xml"/>
     <xi:include href="xml/empathy-status-icon.xml"/>
     <xi:include href="xml/empathy-theme-manager.xml"/>
     <xi:include href="xml/empathy-ui-utils.xml"/>
+    <xi:include href="xml/empathy-account-widget-irc.xml"/>
+    <xi:include href="xml/empathy-irc-network-dialog.xml"/>
     </chapter>
   </part>
 
     </chapter>
   </part>
 
index dbc8cb573c2be85d09c4504693fcf8aed13f4fbd..2b71a7da152401dd000168a0919e652061ce4bb3 100644 (file)
@@ -39,6 +39,9 @@
       <xi:include href="xml/empathy-tp-contact-list.xml"/>
       <xi:include href="xml/empathy-tp-group.xml"/>
       <xi:include href="xml/empathy-tp-roomlist.xml"/>
       <xi:include href="xml/empathy-tp-contact-list.xml"/>
       <xi:include href="xml/empathy-tp-group.xml"/>
       <xi:include href="xml/empathy-tp-roomlist.xml"/>
+      <xi:include href="xml/empathy-irc-server.xml"/>
+      <xi:include href="xml/empathy-irc-network.xml"/>
+      <xi:include href="xml/empathy-irc-network-manager.xml"/>
       <xi:include href="xml/empathy-utils.xml"/>
     </chapter>
   </part>
       <xi:include href="xml/empathy-utils.xml"/>
     </chapter>
   </part>
index 657fa00675c596108fac78112d2741b948585bfe..fed32f1e1a7b64766c97d1b1ba4f3ea8aca6791e 100644 (file)
@@ -15,4 +15,6 @@ empathy_tp_contact_factory_get_type
 empathy_tp_contact_list_get_type
 empathy_tp_group_get_type
 empathy_tp_roomlist_get_type
 empathy_tp_contact_list_get_type
 empathy_tp_group_get_type
 empathy_tp_roomlist_get_type
-
+empathy_irc_server_get_type
+empathy_irc_network_get_type
+empathy_irc_network_manager_get_type
index 24c933714e125439c24543378d9b906fd8617934..f5321517059f61674ad48929e5cdbfad33a07575 100644 (file)
@@ -23,6 +23,7 @@ libempathy_gtk_la_SOURCES =                   \
        empathy-contact-dialogs.c               \
        empathy-accounts-dialog.c               \
        empathy-account-widget.c                \
        empathy-contact-dialogs.c               \
        empathy-accounts-dialog.c               \
        empathy-account-widget.c                \
+       empathy-account-widget-irc.c            \
        empathy-profile-chooser.c               \
        empathy-cell-renderer-expander.c        \
        empathy-cell-renderer-text.c            \
        empathy-profile-chooser.c               \
        empathy-cell-renderer-expander.c        \
        empathy-cell-renderer-text.c            \
@@ -53,7 +54,9 @@ libempathy_gtk_la_SOURCES =                   \
        empathy-avatar-chooser.c                \
        empathy-avatar-image.c                  \
        empathy-ui-utils.c                      \
        empathy-avatar-chooser.c                \
        empathy-avatar-image.c                  \
        empathy-ui-utils.c                      \
-       empathy-new-message-dialog.c
+       empathy-new-message-dialog.c            \
+       empathy-irc-network-dialog.c            \
+       totem-subtitle-encoding.c  totem-subtitle-encoding.h
 
 # do not distribute generated files
 nodist_libempathy_gtk_la_SOURCES =\
 
 # do not distribute generated files
 nodist_libempathy_gtk_la_SOURCES =\
@@ -76,6 +79,7 @@ libempathy_gtk_headers =                      \
        empathy-contact-dialogs.h               \
        empathy-accounts-dialog.h               \
        empathy-account-widget.h                \
        empathy-contact-dialogs.h               \
        empathy-accounts-dialog.h               \
        empathy-account-widget.h                \
+       empathy-account-widget-irc.h            \
        empathy-profile-chooser.h               \
        empathy-cell-renderer-expander.h        \
        empathy-cell-renderer-text.h            \
        empathy-profile-chooser.h               \
        empathy-cell-renderer-expander.h        \
        empathy-cell-renderer-text.h            \
@@ -106,7 +110,8 @@ libempathy_gtk_headers =                    \
        empathy-avatar-chooser.h                \
        empathy-avatar-image.h                  \
        empathy-ui-utils.h                      \
        empathy-avatar-chooser.h                \
        empathy-avatar-image.h                  \
        empathy-ui-utils.h                      \
-       empathy-new-message-dialog.h
+       empathy-new-message-dialog.h            \
+       empathy-irc-network-dialog.h
 
 libempathy_gtk_includedir = $(includedir)/libempathy-gtk/
 libempathy_gtk_include_HEADERS =               \
 
 libempathy_gtk_includedir = $(includedir)/libempathy-gtk/
 libempathy_gtk_include_HEADERS =               \
@@ -125,6 +130,7 @@ glade_DATA =                                        \
        empathy-account-widget-jabber.glade     \
        empathy-account-widget-msn.glade        \
        empathy-account-widget-salut.glade      \
        empathy-account-widget-jabber.glade     \
        empathy-account-widget-msn.glade        \
        empathy-account-widget-salut.glade      \
+       empathy-account-widget-irc.glade        \
        empathy-new-chatroom-dialog.glade       \
        empathy-group-chat.glade                \
        empathy-chatrooms-window.glade          \
        empathy-new-chatroom-dialog.glade       \
        empathy-group-chat.glade                \
        empathy-chatrooms-window.glade          \
diff --git a/libempathy-gtk/empathy-account-widget-irc.c b/libempathy-gtk/empathy-account-widget-irc.c
new file mode 100644 (file)
index 0000000..35fa769
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+#include <libmissioncontrol/mc-account.h>
+#include <libmissioncontrol/mc-protocol.h>
+
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-debug.h>
+#include <libempathy/empathy-irc-network-manager.h>
+
+#include "empathy-irc-network-dialog.h"
+#include "empathy-account-widget.h"
+#include "empathy-account-widget-irc.h"
+#include "empathy-ui-utils.h"
+
+#define DEBUG_DOMAIN "AccountWidgetIRC"
+
+#define IRC_NETWORKS_FILENAME "irc-networks.xml"
+
+typedef struct {
+  McAccount *account;
+  EmpathyIrcNetworkManager *network_manager;
+
+  GtkWidget *vbox_settings;
+
+  GtkWidget *combobox_network;
+  GtkWidget *button_add_network;
+  GtkWidget *button_network;
+  GtkWidget *button_remove;
+} EmpathyAccountWidgetIrc;
+
+enum {
+  COL_NETWORK_OBJ,
+  COL_NETWORK_NAME,
+};
+
+static void
+account_widget_irc_destroy_cb (GtkWidget *widget,
+                               EmpathyAccountWidgetIrc *settings)
+{
+  g_object_unref (settings->network_manager);
+  g_object_unref (settings->account);
+  g_slice_free (EmpathyAccountWidgetIrc, settings);
+}
+
+static void
+unset_server_params (EmpathyAccountWidgetIrc *settings)
+{
+  empathy_debug (DEBUG_DOMAIN, "Unset server, port and use-ssl");
+  mc_account_unset_param (settings->account, "server");
+  mc_account_unset_param (settings->account, "port");
+  mc_account_unset_param (settings->account, "use-ssl");
+}
+
+static void
+update_server_params (EmpathyAccountWidgetIrc *settings)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  EmpathyIrcNetwork *network;
+  GSList *servers;
+  gchar *charset;
+
+  if (!gtk_combo_box_get_active_iter (
+        GTK_COMBO_BOX (settings->combobox_network), &iter))
+    {
+      unset_server_params (settings);
+      return;
+    }
+
+  model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
+  gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
+
+  g_assert (network != NULL);
+
+  g_object_get (network, "charset", &charset, NULL);
+  empathy_debug (DEBUG_DOMAIN, "Setting charset to %s", charset);
+  mc_account_set_param_string (settings->account, "charset", charset);
+  g_free (charset);
+
+  servers = empathy_irc_network_get_servers (network);
+  if (g_slist_length (servers) > 0)
+    {
+      /* set the first server as CM server */
+      EmpathyIrcServer *server = servers->data;
+      gchar *address;
+      guint port;
+      gboolean ssl;
+
+      g_object_get (server,
+          "address", &address,
+          "port", &port,
+          "ssl", &ssl,
+          NULL);
+
+      empathy_debug (DEBUG_DOMAIN, "Setting server to %s", address);
+      mc_account_set_param_string (settings->account, "server", address);
+      empathy_debug (DEBUG_DOMAIN, "Setting port to %u", port);
+      mc_account_set_param_int (settings->account, "port", port);
+      empathy_debug (DEBUG_DOMAIN, "Setting use-ssl to %s",
+          ssl ? "TRUE": "FALSE" );
+      mc_account_set_param_boolean (settings->account, "use-ssl", ssl);
+
+      g_free (address);
+    }
+  else
+    {
+      /* No server. Unset values */
+      unset_server_params (settings);
+    }
+
+  g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+  g_slist_free (servers);
+  g_object_unref (network);
+}
+
+static void
+irc_network_dialog_destroy_cb (GtkWidget *widget,
+                               EmpathyAccountWidgetIrc *settings)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  EmpathyIrcNetwork *network;
+  gchar *name;
+
+  /* name could be changed */
+  gtk_combo_box_get_active_iter (GTK_COMBO_BOX (settings->combobox_network),
+      &iter);
+  model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
+  gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
+
+  g_object_get (network, "name", &name, NULL);
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+      COL_NETWORK_NAME, name, -1);
+
+  update_server_params (settings);
+
+  g_object_unref (network);
+  g_free (name);
+}
+
+static void
+display_irc_network_dialog (EmpathyAccountWidgetIrc *settings,
+                            EmpathyIrcNetwork *network)
+{
+  GtkWindow *window;
+  GtkWidget *dialog;
+
+  window = empathy_get_toplevel_window (settings->vbox_settings);
+  dialog = empathy_irc_network_dialog_show (network, GTK_WIDGET (window));
+  g_signal_connect (dialog, "destroy",
+      G_CALLBACK (irc_network_dialog_destroy_cb), settings);
+}
+
+static void
+account_widget_irc_button_edit_network_clicked_cb (
+    GtkWidget *button,
+    EmpathyAccountWidgetIrc *settings)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  EmpathyIrcNetwork *network;
+
+  gtk_combo_box_get_active_iter (GTK_COMBO_BOX (settings->combobox_network),
+      &iter);
+  model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
+  gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
+
+  g_assert (network != NULL);
+
+  display_irc_network_dialog (settings, network);
+
+  g_object_unref (network);
+}
+
+static void
+account_widget_irc_button_remove_clicked_cb (GtkWidget *button,
+                                             EmpathyAccountWidgetIrc *settings)
+{
+  EmpathyIrcNetwork *network;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  gchar *name;
+
+  gtk_combo_box_get_active_iter (GTK_COMBO_BOX (settings->combobox_network),
+      &iter);
+  model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
+  gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
+
+  g_assert (network != NULL);
+
+  g_object_get (network, "name", &name, NULL);
+  empathy_debug (DEBUG_DOMAIN, "Remove network %s", name);
+
+  gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+  empathy_irc_network_manager_remove (settings->network_manager, network);
+
+  /* Select the first network */
+  if (gtk_tree_model_get_iter_first (model, &iter))
+    {
+      gtk_combo_box_set_active_iter (
+          GTK_COMBO_BOX (settings->combobox_network), &iter);
+    }
+
+  g_free (name);
+  g_object_unref (network);
+}
+
+static void
+account_widget_irc_button_add_network_clicked_cb (GtkWidget *button,
+                                                  EmpathyAccountWidgetIrc *settings)
+{
+  EmpathyIrcNetwork *network;
+  GtkTreeModel *model;
+  GtkListStore *store;
+  gchar *name;
+  GtkTreeIter iter;
+
+  network = empathy_irc_network_new (_("New Network"));
+  empathy_irc_network_manager_add (settings->network_manager, network);
+
+  model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
+  store = GTK_LIST_STORE (model);
+
+  g_object_get (network, "name", &name, NULL);
+
+  gtk_list_store_insert_with_values (store, &iter, -1,
+      COL_NETWORK_OBJ, network,
+      COL_NETWORK_NAME, name,
+      -1);
+
+  gtk_combo_box_set_active_iter (GTK_COMBO_BOX (settings->combobox_network),
+      &iter);
+
+  display_irc_network_dialog (settings, network);
+
+  g_free (name);
+  g_object_unref (network);
+}
+
+static void
+account_widget_irc_combobox_network_changed_cb (GtkWidget *combobox,
+                                                EmpathyAccountWidgetIrc *settings)
+{
+  update_server_params (settings);
+}
+
+static void
+fill_networks_model (EmpathyAccountWidgetIrc *settings,
+                     EmpathyIrcNetwork *network_to_select)
+{
+  GSList *networks, *l;
+  GtkTreeModel *model;
+  GtkListStore *store;
+
+  networks = empathy_irc_network_manager_get_networks (
+      settings->network_manager);
+
+  model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
+  store = GTK_LIST_STORE (model);
+
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      gchar *name;
+      EmpathyIrcNetwork *network = l->data;
+      GtkTreeIter iter;
+
+      g_object_get (network, "name", &name, NULL);
+
+      gtk_list_store_insert_with_values (store, &iter, -1,
+          COL_NETWORK_OBJ, network,
+          COL_NETWORK_NAME, name,
+          -1);
+
+       if (network == network_to_select)
+         {
+           gtk_combo_box_set_active_iter (
+               GTK_COMBO_BOX (settings->combobox_network), &iter);
+         }
+
+      g_free (name);
+      g_object_unref (network);
+    }
+
+  if (network_to_select == NULL)
+    {
+      /* Select the first network */
+      GtkTreeIter iter;
+
+      if (gtk_tree_model_get_iter_first (model, &iter))
+        {
+          gtk_combo_box_set_active_iter (
+              GTK_COMBO_BOX (settings->combobox_network), &iter);
+
+          update_server_params (settings);
+        }
+    }
+
+  g_slist_free (networks);
+}
+
+static void
+account_widget_irc_setup (EmpathyAccountWidgetIrc *settings)
+{
+  gchar *nick = NULL;
+  gchar *fullname = NULL;
+  gchar *server = NULL;
+  gint port = 6667;
+  gchar *charset;
+  gboolean ssl = FALSE;
+  EmpathyIrcNetwork *network = NULL;
+
+  mc_account_get_param_string (settings->account, "account", &nick);
+  mc_account_get_param_string (settings->account, "fullname", &fullname);
+  mc_account_get_param_string (settings->account, "server", &server);
+  mc_account_get_param_string (settings->account, "charset", &charset);
+  mc_account_get_param_int (settings->account, "port", &port);
+  mc_account_get_param_boolean (settings->account, "use-ssl", &ssl);
+
+  if (!nick)
+    {
+      nick = g_strdup (g_get_user_name ());
+      mc_account_set_param_string (settings->account, "account", nick);
+    }
+
+  if (!fullname)
+    {
+      fullname = g_strdup (g_get_real_name ());
+      if (!fullname)
+        {
+          fullname = g_strdup (nick);
+        }
+      mc_account_set_param_string (settings->account, "fullname", fullname);
+    }
+
+  if (server != NULL)
+    {
+      GtkListStore *store;
+
+      network = empathy_irc_network_manager_find_network_by_address (
+          settings->network_manager, server);
+
+
+      store = GTK_LIST_STORE (gtk_combo_box_get_model (
+            GTK_COMBO_BOX (settings->combobox_network)));
+
+      if (network != NULL)
+        {
+          gchar *name;
+
+          g_object_set (network, "charset", charset, NULL);
+
+          g_object_get (network, "name", &name, NULL);
+          empathy_debug (DEBUG_DOMAIN, "Account use network %s", name);
+
+          g_free (name);
+        }
+      else
+        {
+          /* We don't have this network. Let's create it */
+          EmpathyIrcServer *srv;
+          GtkTreeIter iter;
+
+          empathy_debug (DEBUG_DOMAIN, "Create a network %s", server);
+          network = empathy_irc_network_new (server);
+          srv = empathy_irc_server_new (server, port, ssl);
+
+          empathy_irc_network_append_server (network, srv);
+          empathy_irc_network_manager_add (settings->network_manager, network);
+
+          gtk_list_store_insert_with_values (store, &iter, -1,
+              COL_NETWORK_OBJ, network,
+              COL_NETWORK_NAME, server,
+              -1);
+
+          gtk_combo_box_set_active_iter (
+              GTK_COMBO_BOX (settings->combobox_network), &iter);
+
+          g_object_unref (srv);
+          g_object_unref (network);
+        }
+    }
+
+
+  fill_networks_model (settings, network);
+
+  g_free (nick);
+  g_free (fullname);
+  g_free (server);
+  g_free (charset);
+}
+
+/**
+ * empathy_account_widget_irc_new:
+ * @account: the #McAccount to configure
+ *
+ * Creates a new IRC account widget to configure a given #McAccount
+ *
+ * Returns: The toplevel container of the configuration widget
+ */
+GtkWidget *
+empathy_account_widget_irc_new (McAccount *account)
+{
+  EmpathyAccountWidgetIrc *settings;
+  gchar *dir, *user_file_with_path, *global_file_with_path;
+  GladeXML *glade;
+  GtkListStore *store;
+  GtkCellRenderer *renderer;
+
+  settings = g_slice_new0 (EmpathyAccountWidgetIrc);
+  settings->account = g_object_ref (account);
+
+  dir = g_build_filename (g_get_home_dir (), ".gnome2", 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 (UNINSTALLED_IRC_DIR,
+      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);
+    }
+
+  settings->network_manager = empathy_irc_network_manager_new (
+      global_file_with_path,
+      user_file_with_path);
+
+  g_free (global_file_with_path);
+  g_free (user_file_with_path);
+
+  glade = empathy_glade_get_file ("empathy-account-widget-irc.glade",
+      "vbox_irc_settings",
+      NULL,
+      "vbox_irc_settings", &settings->vbox_settings,
+      "combobox_network", &settings->combobox_network,
+      "button_network", &settings->button_network,
+      "button_add_network", &settings->button_add_network,
+      "button_remove", &settings->button_remove,
+      NULL);
+
+  /* Fill the networks combobox */
+  store = gtk_list_store_new (2, G_TYPE_OBJECT, G_TYPE_STRING);
+
+  gtk_cell_layout_clear (GTK_CELL_LAYOUT (settings->combobox_network)); 
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (settings->combobox_network),
+      renderer, TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (settings->combobox_network),
+      renderer,
+      "text", COL_NETWORK_NAME,
+      NULL);
+
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+      COL_NETWORK_NAME,
+      GTK_SORT_ASCENDING);
+
+  gtk_combo_box_set_model (GTK_COMBO_BOX (settings->combobox_network),
+      GTK_TREE_MODEL (store));
+  g_object_unref (store);
+
+  account_widget_irc_setup (settings);
+
+  empathy_account_widget_handle_params (account, glade,
+      "entry_nick", "account",
+      "entry_fullname", "fullname",
+      "entry_password", "password",
+      "entry_quit_message", "quit-message",
+      NULL);
+
+  empathy_glade_connect (glade, settings,
+      "vbox_irc_settings", "destroy", account_widget_irc_destroy_cb,
+      "button_network", "clicked", account_widget_irc_button_edit_network_clicked_cb,
+      "button_add_network", "clicked", account_widget_irc_button_add_network_clicked_cb,
+      "button_remove", "clicked", account_widget_irc_button_remove_clicked_cb,
+      "combobox_network", "changed", account_widget_irc_combobox_network_changed_cb,
+      NULL);
+
+  g_object_unref (glade);
+
+  return settings->vbox_settings;
+}
diff --git a/libempathy-gtk/empathy-account-widget-irc.glade b/libempathy-gtk/empathy-account-widget-irc.glade
new file mode 100644 (file)
index 0000000..14c757c
--- /dev/null
@@ -0,0 +1,451 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.0 on Sun Feb 17 01:08:25 2008 -->
+<glade-interface>
+  <widget class="GtkWindow" id="account_irc_settings">
+    <property name="title" translatable="yes">irc account settings</property>
+    <property name="resizable">False</property>
+    <child>
+      <widget class="GtkTable" id="vbox_irc_settings">
+        <property name="visible">True</property>
+        <property name="n_rows">5</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">12</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <widget class="GtkLabel" id="label_network">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Network:</property>
+            <property name="use_underline">True</property>
+          </widget>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHBox" id="hbox174">
+            <property name="visible">True</property>
+            <property name="spacing">2</property>
+            <child>
+              <widget class="GtkComboBox" id="combobox_network">
+                <property name="visible">True</property>
+                <property name="items" translatable="yes"></property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button_add_network">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="tooltip" translatable="yes">Create a new IRC network</property>
+                <property name="response_id">0</property>
+                <child>
+                  <widget class="GtkImage" id="image2">
+                    <property name="visible">True</property>
+                    <property name="stock">gtk-add</property>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button_network">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="tooltip" translatable="yes">Edit the selected IRC network</property>
+                <property name="response_id">0</property>
+                <child>
+                  <widget class="GtkImage" id="image834">
+                    <property name="visible">True</property>
+                    <property name="stock">gtk-edit</property>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button_remove">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="tooltip" translatable="yes">Remove the selected IRC network</property>
+                <property name="response_id">0</property>
+                <child>
+                  <widget class="GtkImage" id="image835">
+                    <property name="visible">True</property>
+                    <property name="stock">gtk-remove</property>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="label_nick">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Nickname:</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">entry_nick</property>
+          </widget>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkEntry" id="entry_nick">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="invisible_char">*</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="label_fullname">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Real name:</property>
+          </widget>
+          <packing>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="label_password">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Password:</property>
+          </widget>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkEntry" id="entry_password">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="visibility">False</property>
+            <property name="invisible_char">*</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkEntry" id="entry_fullname">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="label_quit_message">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Quit message:</property>
+          </widget>
+          <packing>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkEntry" id="entry_quit_message">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkDialog" id="irc_network_dialog">
+    <property name="visible">True</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Network</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="icon_name">gtk-edit</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="skip_pager_hint">True</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox10">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkFrame" id="frame14">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">GTK_SHADOW_NONE</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment28">
+                <property name="visible">True</property>
+                <property name="top_padding">6</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkTable" id="table14">
+                    <property name="visible">True</property>
+                    <property name="n_rows">2</property>
+                    <property name="n_columns">2</property>
+                    <property name="column_spacing">12</property>
+                    <property name="row_spacing">6</property>
+                    <child>
+                      <widget class="GtkComboBox" id="combobox_charset">
+                        <property name="visible">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options">GTK_FILL</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkEntry" id="entry_network">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label_charset">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Charset:</property>
+                      </widget>
+                      <packing>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label_network">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Network:</property>
+                      </widget>
+                      <packing>
+                        <property name="x_options">GTK_FILL</property>
+                        <property name="y_options"></property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label_network">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;b&gt;Network&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkFrame" id="frame15">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">GTK_SHADOW_NONE</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment29">
+                <property name="visible">True</property>
+                <property name="top_padding">6</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkTable" id="table15">
+                    <property name="visible">True</property>
+                    <property name="n_rows">1</property>
+                    <property name="n_columns">2</property>
+                    <property name="column_spacing">6</property>
+                    <property name="row_spacing">6</property>
+                    <child>
+                      <widget class="GtkVButtonBox" id="vbuttonbox1">
+                        <property name="visible">True</property>
+                        <property name="spacing">6</property>
+                        <property name="layout_style">GTK_BUTTONBOX_START</property>
+                        <child>
+                          <widget class="GtkButton" id="button_add">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="can_default">True</property>
+                            <property name="label">gtk-add</property>
+                            <property name="use_stock">True</property>
+                            <property name="response_id">0</property>
+                          </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkButton" id="button_remove">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="can_default">True</property>
+                            <property name="label">gtk-remove</property>
+                            <property name="use_stock">True</property>
+                            <property name="response_id">0</property>
+                          </widget>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkButton" id="button_up">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="can_default">True</property>
+                            <property name="label">gtk-go-up</property>
+                            <property name="use_stock">True</property>
+                            <property name="response_id">0</property>
+                          </widget>
+                          <packing>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkButton" id="button_down">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="can_default">True</property>
+                            <property name="label">gtk-go-down</property>
+                            <property name="use_stock">True</property>
+                            <property name="response_id">0</property>
+                          </widget>
+                          <packing>
+                            <property name="position">3</property>
+                          </packing>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="x_options">GTK_FILL</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkScrolledWindow" id="scrolledwindow19">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+                        <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                        <property name="shadow_type">GTK_SHADOW_IN</property>
+                        <child>
+                          <widget class="GtkTreeView" id="treeview_servers">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="enable_search">False</property>
+                          </widget>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="y_options">GTK_FILL</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label_servers">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;b&gt;Servers&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area10">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button_close">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-close</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-7</property>
+              </widget>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/libempathy-gtk/empathy-account-widget-irc.h b/libempathy-gtk/empathy-account-widget-irc.h
new file mode 100644 (file)
index 0000000..6ead048
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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_ACCOUNT_WIDGET_IRC_H__
+#define __EMPATHY_ACCOUNT_WIDGET_IRC_H__
+
+#include <gtk/gtkwidget.h>
+#include <libmissioncontrol/mc-account.h>
+
+G_BEGIN_DECLS
+
+GtkWidget * empathy_account_widget_irc_new (McAccount *account);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_ACCOUNT_WIDGET_IRC_H__ */
index 93b7b005b5d560b2f37da91cb4b92a8535af1138..832063371eb9572aaf7285461c9535b9594ec350 100644 (file)
@@ -46,6 +46,7 @@
 #include "empathy-accounts-dialog.h"
 #include "empathy-profile-chooser.h"
 #include "empathy-account-widget.h"
 #include "empathy-accounts-dialog.h"
 #include "empathy-profile-chooser.h"
 #include "empathy-account-widget.h"
+#include "empathy-account-widget-irc.h"
 
 #define DEBUG_DOMAIN "AccountDialog"
 
 
 #define DEBUG_DOMAIN "AccountDialog"
 
@@ -269,6 +270,10 @@ accounts_dialog_update_account (EmpathyAccountsDialog *dialog,
                        dialog->settings_widget =
                                empathy_account_widget_salut_new (account);
                }
                        dialog->settings_widget =
                                empathy_account_widget_salut_new (account);
                }
+               else if (!tp_strdiff (config_ui, "irc")) {
+                       dialog->settings_widget =
+                               empathy_account_widget_irc_new (account);
+               }
                else {
                        dialog->settings_widget = 
                                empathy_account_widget_generic_new (account);
                else {
                        dialog->settings_widget = 
                                empathy_account_widget_generic_new (account);
diff --git a/libempathy-gtk/empathy-irc-network-dialog.c b/libempathy-gtk/empathy-irc-network-dialog.c
new file mode 100644 (file)
index 0000000..9a42c64
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+#include <libmissioncontrol/mc-account.h>
+#include <libmissioncontrol/mc-protocol.h>
+
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-debug.h>
+
+#include <libempathy/empathy-irc-network-manager.h>
+#include "empathy-ui-utils.h"
+#include "totem-subtitle-encoding.h"
+
+#include "empathy-irc-network-dialog.h"
+
+#define DEBUG_DOMAIN "AccountWidgetIRC"
+
+typedef struct {
+  EmpathyIrcNetwork *network;
+
+  GtkWidget *dialog;
+  GtkWidget *button_close;
+
+  GtkWidget *entry_network;
+  GtkWidget *combobox_charset;
+
+  GtkWidget *treeview_servers;
+  GtkWidget *button_add;
+  GtkWidget *button_remove;
+  GtkWidget *button_up;
+  GtkWidget *button_down;
+} EmpathyIrcNetworkDialog;
+
+static void
+irc_network_dialog_destroy_cb (GtkWidget *widget,
+                               EmpathyIrcNetworkDialog *dialog)
+{
+  g_object_unref (dialog->network);
+
+  g_slice_free (EmpathyIrcNetworkDialog, dialog);
+}
+
+static void
+irc_network_dialog_close_clicked_cb (GtkWidget *widget,
+                                     EmpathyIrcNetworkDialog *dialog)
+{
+  gtk_widget_destroy (dialog->dialog);
+}
+
+enum {
+  COL_SRV_OBJ,
+  COL_ADR,
+  COL_PORT,
+  COL_SSL
+};
+
+static void
+add_server_to_store (GtkListStore *store,
+                     EmpathyIrcServer *server,
+                     GtkTreeIter *iter)
+{
+  gchar *address;
+  guint port;
+  gboolean ssl;
+
+  g_object_get (server,
+      "address", &address,
+      "port", &port,
+      "ssl", &ssl,
+      NULL);
+
+  gtk_list_store_insert_with_values (store, iter, -1,
+      COL_SRV_OBJ, server,
+      COL_ADR, address,
+      COL_PORT, port,
+      COL_SSL, ssl,
+      -1);
+
+  g_free (address);
+}
+
+static void
+irc_network_dialog_setup (EmpathyIrcNetworkDialog *dialog)
+{
+  gchar *name, *charset;
+  GSList *servers, *l;
+  GtkListStore *store;
+
+  g_object_get (dialog->network,
+      "name", &name,
+      "charset", &charset,
+      NULL);
+  gtk_entry_set_text (GTK_ENTRY (dialog->entry_network), name);
+
+  store = GTK_LIST_STORE (gtk_tree_view_get_model (
+        GTK_TREE_VIEW (dialog->treeview_servers)));
+
+  servers = empathy_irc_network_get_servers (dialog->network);
+  for (l = servers; l != NULL; l = g_slist_next (l))
+    {
+      EmpathyIrcServer *server = l->data;
+      GtkTreeIter iter;
+
+      add_server_to_store (store, server, &iter);
+    }
+
+  totem_subtitle_encoding_set (GTK_COMBO_BOX (dialog->combobox_charset),
+      charset);
+
+  g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+  g_slist_free (servers);
+  g_free (name);
+  g_free (charset);
+}
+
+static void
+irc_network_dialog_address_edited_cb (GtkCellRendererText *renderer,
+                                      gchar *path,
+                                      gchar *new_text,
+                                      EmpathyIrcNetworkDialog *dialog)
+{
+  EmpathyIrcServer *server;
+  GtkTreeModel *model;
+  GtkTreePath  *treepath;
+  GtkTreeIter iter;
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers));
+  treepath = gtk_tree_path_new_from_string (path);
+  gtk_tree_model_get_iter (model, &iter, treepath);
+  gtk_tree_model_get (model, &iter,
+      COL_SRV_OBJ, &server,
+      -1);
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+      COL_ADR, new_text,
+      -1);
+
+  g_object_set (server, "address", new_text, NULL);
+
+  gtk_tree_path_free (treepath);
+  g_object_unref (server);
+}
+
+static void
+irc_network_dialog_port_edited_cb (GtkCellRendererText *renderer,
+                                   gchar *path,
+                                   gchar *new_text,
+                                   EmpathyIrcNetworkDialog *dialog)
+{
+  EmpathyIrcServer *server;
+  GtkTreeModel *model;
+  GtkTreePath  *treepath;
+  GtkTreeIter iter;
+  guint port;
+
+  port = strtoul (new_text, NULL, 10);
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers));
+  treepath = gtk_tree_path_new_from_string (path);
+  gtk_tree_model_get_iter (model, &iter, treepath);
+  gtk_tree_model_get (model, &iter,
+      COL_SRV_OBJ, &server,
+      -1);
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+      COL_PORT, port,
+      -1);
+
+  g_object_set (server, "port", port, NULL);
+
+  gtk_tree_path_free (treepath);
+  g_object_unref (server);
+}
+
+static void
+irc_network_dialog_ssl_toggled_cb (GtkCellRendererText *renderer,
+                                   gchar *path,
+                                   EmpathyIrcNetworkDialog *dialog)
+{
+  EmpathyIrcServer *server;
+  GtkTreeModel *model;
+  GtkTreePath  *treepath;
+  GtkTreeIter iter;
+  gboolean ssl;
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers));
+  treepath = gtk_tree_path_new_from_string (path);
+  gtk_tree_model_get_iter (model, &iter, treepath);
+  gtk_tree_model_get (model, &iter,
+      COL_SRV_OBJ, &server,
+      COL_SSL, &ssl,
+      -1);
+  ssl = !ssl;
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+      COL_SSL, ssl,
+      -1);
+
+  g_object_set (server, "ssl", ssl, NULL);
+
+  gtk_tree_path_free (treepath);
+  g_object_unref (server);
+}
+
+static gboolean
+irc_network_dialog_network_focus_cb (GtkWidget *widget,
+                                     GdkEventFocus *event,
+                                     EmpathyIrcNetworkDialog *dialog)
+{
+  const gchar *str;
+
+  str = gtk_entry_get_text (GTK_ENTRY (widget));
+
+  g_object_set (dialog->network, "name", str, NULL);
+
+  return FALSE;
+}
+
+static void
+irc_network_dialog_network_update_buttons (EmpathyIrcNetworkDialog *dialog)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreePath *path;
+  GtkTreeIter iter;
+  gboolean can_remove = FALSE, can_move_up = FALSE, can_move_down = FALSE;
+  int selected;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (
+        dialog->treeview_servers));
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
+  {
+    path = gtk_tree_model_get_path (model, &iter);
+
+    selected = gtk_tree_path_get_indices (path)[0];
+
+    can_remove = TRUE;
+    can_move_up = selected > 0;
+    can_move_down = 
+      selected < gtk_tree_model_iter_n_children (model, NULL) - 1;
+
+    gtk_tree_path_free (path);
+  }
+
+  gtk_widget_set_sensitive (dialog->button_remove, can_remove);
+  gtk_widget_set_sensitive (dialog->button_up, can_move_up);
+  gtk_widget_set_sensitive (dialog->button_down, can_move_down);
+}
+
+static void
+irc_network_dialog_button_add_clicked_cb (GtkWidget *widget,
+                                          EmpathyIrcNetworkDialog *dialog)
+{
+  EmpathyIrcServer *server;
+  GtkListStore *store;
+  GtkTreeIter iter;
+  GtkTreePath *path;
+  GtkTreeViewColumn *column;
+
+  store = GTK_LIST_STORE (gtk_tree_view_get_model (
+        GTK_TREE_VIEW (dialog->treeview_servers)));
+
+  server = empathy_irc_server_new (_("new server"), 6667, FALSE);
+  empathy_irc_network_append_server (dialog->network, server);
+  add_server_to_store (store, server, &iter);
+
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+  column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers),
+      0);
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->treeview_servers), path,
+      column, TRUE);
+
+  irc_network_dialog_network_update_buttons (dialog);
+
+  gtk_tree_path_free (path);
+  g_object_unref (server);
+}
+
+static void
+irc_network_dialog_button_remove_clicked_cb (GtkWidget *widget,
+                                             EmpathyIrcNetworkDialog *dialog)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  EmpathyIrcServer *server;
+
+  selection = gtk_tree_view_get_selection (
+      GTK_TREE_VIEW (dialog->treeview_servers));
+
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    return;
+
+  gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1);
+
+  gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+  empathy_irc_network_remove_server (dialog->network, server);
+
+  irc_network_dialog_network_update_buttons (dialog);
+
+  g_object_unref (server);
+}
+
+static void
+irc_network_dialog_button_up_clicked_cb (GtkWidget *widget,
+                                         EmpathyIrcNetworkDialog *dialog)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreeIter iter, iter_prev;
+  GtkTreePath *path;
+  gint *pos;
+  EmpathyIrcServer *server;
+
+  selection = gtk_tree_view_get_selection (
+      GTK_TREE_VIEW (dialog->treeview_servers));
+
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    return;
+
+  path = gtk_tree_model_get_path (model, &iter);
+
+  if (!gtk_tree_path_prev (path))
+  {
+    gtk_tree_path_free (path);
+    return;
+  }
+
+  gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1);
+
+  gtk_tree_model_get_iter (model, &iter_prev, path);
+  gtk_list_store_swap (GTK_LIST_STORE (model), &iter_prev, &iter);
+
+  pos = gtk_tree_path_get_indices (path);
+  empathy_irc_network_set_server_position (dialog->network, server, *pos);
+
+  irc_network_dialog_network_update_buttons (dialog);
+
+  g_object_unref (server);
+  gtk_tree_path_free (path);
+}
+
+static void
+irc_network_dialog_button_down_clicked_cb (GtkWidget *widget,
+                                           EmpathyIrcNetworkDialog *dialog)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreeIter iter, iter_prev;
+  GtkTreePath *path;
+  EmpathyIrcServer *server;
+  gint *pos;
+
+  selection = gtk_tree_view_get_selection (
+      GTK_TREE_VIEW (dialog->treeview_servers));
+
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    return;
+
+  path = gtk_tree_model_get_path (model, &iter);
+
+  gtk_tree_path_next (path);
+  if (!gtk_tree_model_get_iter (model, &iter_prev, path))
+    {
+      gtk_tree_path_free (path);
+      return;
+    }
+
+  gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1);
+
+  gtk_list_store_swap (GTK_LIST_STORE (model), &iter_prev, &iter);
+
+  pos = gtk_tree_path_get_indices (path);
+  empathy_irc_network_set_server_position (dialog->network, server, *pos);
+
+  irc_network_dialog_network_update_buttons (dialog);
+
+  gtk_tree_path_free (path);
+}
+
+static void
+irc_network_dialog_selection_changed_cb (GtkTreeSelection  *treeselection,
+                                         EmpathyIrcNetworkDialog *dialog)
+{
+  irc_network_dialog_network_update_buttons (dialog);
+}
+
+static void
+irc_network_dialog_combobox_charset_changed_cb (GtkWidget *combobox,
+                                                EmpathyIrcNetworkDialog *dialog)
+{
+  const gchar *charset;
+
+  charset = totem_subtitle_encoding_get_selected (GTK_COMBO_BOX (combobox));
+  g_object_set (dialog->network, "charset", charset, NULL);
+}
+
+static void
+change_network (EmpathyIrcNetworkDialog *dialog,
+                EmpathyIrcNetwork *network)
+{
+  GtkListStore *store;
+
+  if (dialog->network == network)
+    /* No need to change */
+    return;
+
+  if (dialog->network != NULL)
+    {
+      g_object_unref (dialog->network);
+    }
+
+  dialog->network = network;
+  g_object_ref (network);
+
+  store = GTK_LIST_STORE (gtk_tree_view_get_model (
+        GTK_TREE_VIEW (dialog->treeview_servers)));
+  gtk_list_store_clear (store);
+
+  irc_network_dialog_setup (dialog);
+}
+
+/**
+ * empathy_irc_network_dialog_show:
+ * @network: the #EmpathyIrcNetwork to configure
+ * @parent: the parent of this dialog
+ *
+ * Display a dialog to configure a given #EmpathyIrcNetwork.
+ * This function is a singleton so if a configuration dialog already
+ * exists we use this one to edit the network.
+ *
+ * Returns: The displayed #GtkDialog
+ */
+GtkWidget *
+empathy_irc_network_dialog_show (EmpathyIrcNetwork *network,
+                                 GtkWidget *parent)
+{
+  static EmpathyIrcNetworkDialog *dialog = NULL;
+  GladeXML *glade;
+  GtkListStore *store;
+  GtkCellRenderer *renderer;
+  GtkAdjustment *adjustment;
+  GtkTreeSelection *selection;
+  GtkTreeViewColumn *column;
+
+  g_return_val_if_fail (network != NULL, NULL);
+
+  if (dialog != NULL)
+    {
+      change_network (dialog, network);
+      gtk_window_present (GTK_WINDOW (dialog->dialog));
+
+      return dialog->dialog;
+    }
+
+  dialog = g_slice_new0 (EmpathyIrcNetworkDialog);
+
+  dialog->network = network;
+  g_object_ref (dialog->network);
+
+  glade = empathy_glade_get_file ("empathy-account-widget-irc.glade",
+      "irc_network_dialog",
+      NULL,
+      "irc_network_dialog", &dialog->dialog,
+      "button_close", &dialog->button_close,
+      "entry_network", &dialog->entry_network,
+      "combobox_charset", &dialog->combobox_charset,
+      "treeview_servers", &dialog->treeview_servers,
+      "button_add", &dialog->button_add,
+      "button_remove", &dialog->button_remove,
+      "button_up", &dialog->button_up,
+      "button_down", &dialog->button_down,
+      NULL);
+
+  store = gtk_list_store_new (4, G_TYPE_OBJECT, G_TYPE_STRING,
+      G_TYPE_UINT, G_TYPE_BOOLEAN);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview_servers),
+      GTK_TREE_MODEL (store));
+  g_object_unref (store);
+
+  /* address */
+  renderer = gtk_cell_renderer_text_new ();
+  g_object_set (renderer, "editable", TRUE, NULL);
+  g_signal_connect (renderer, "edited",
+      G_CALLBACK (irc_network_dialog_address_edited_cb), dialog);
+  gtk_tree_view_insert_column_with_attributes (
+      GTK_TREE_VIEW (dialog->treeview_servers),
+      -1, _("Server"), renderer, "text", COL_ADR,
+      NULL);
+
+  /* port */
+  adjustment = (GtkAdjustment *) gtk_adjustment_new (6667, 1, G_MAXUINT16,
+      1, 10, 0);
+  renderer = gtk_cell_renderer_spin_new ();
+  g_object_set (renderer,
+      "editable", TRUE, 
+      "adjustment", adjustment,
+      NULL);
+  g_signal_connect (renderer, "edited",
+      G_CALLBACK (irc_network_dialog_port_edited_cb), dialog);
+  gtk_tree_view_insert_column_with_attributes (
+      GTK_TREE_VIEW (dialog->treeview_servers),
+      -1, _("Port"), renderer, "text", COL_PORT,
+      NULL);
+  column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers),
+      1);
+  gtk_tree_view_column_set_expand (column, TRUE);
+
+  /* SSL */
+  renderer = gtk_cell_renderer_toggle_new ();
+  g_object_set (renderer, "activatable", TRUE, NULL);
+  g_signal_connect (renderer, "toggled",
+      G_CALLBACK (irc_network_dialog_ssl_toggled_cb), dialog);
+  gtk_tree_view_insert_column_with_attributes (
+      GTK_TREE_VIEW (dialog->treeview_servers),
+      -1, _("SSL"), renderer, "active", COL_SSL,
+      NULL);
+
+  selection = gtk_tree_view_get_selection (
+      GTK_TREE_VIEW (dialog->treeview_servers));
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+  /* charset */
+  totem_subtitle_encoding_init (GTK_COMBO_BOX (dialog->combobox_charset));
+
+  irc_network_dialog_setup (dialog);
+
+  empathy_glade_connect (glade, dialog,
+      "irc_network_dialog", "destroy", irc_network_dialog_destroy_cb,
+      "button_close", "clicked", irc_network_dialog_close_clicked_cb,
+      "entry_network", "focus-out-event", irc_network_dialog_network_focus_cb,
+      "button_add", "clicked", irc_network_dialog_button_add_clicked_cb,
+      "button_remove", "clicked", irc_network_dialog_button_remove_clicked_cb,
+      "button_up", "clicked", irc_network_dialog_button_up_clicked_cb,
+      "button_down", "clicked", irc_network_dialog_button_down_clicked_cb,
+      "combobox_charset", "changed", irc_network_dialog_combobox_charset_changed_cb,
+      NULL);
+
+  g_object_unref (glade);
+
+  g_object_add_weak_pointer (G_OBJECT (dialog->dialog),
+      (gpointer) &dialog);
+
+  g_signal_connect (selection, "changed",
+      G_CALLBACK (irc_network_dialog_selection_changed_cb),
+      dialog);
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog),
+      GTK_WINDOW (parent));
+  gtk_window_set_modal (GTK_WINDOW (dialog->dialog), TRUE);
+
+  irc_network_dialog_network_update_buttons (dialog);
+
+  return dialog->dialog;
+}
diff --git a/libempathy-gtk/empathy-irc-network-dialog.h b/libempathy-gtk/empathy-irc-network-dialog.h
new file mode 100644 (file)
index 0000000..9858496
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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_DIALOG_H__
+#define __EMPATHY_IRC_NETWORK_DIALOG_H__
+
+#include <gtk/gtkwidget.h>
+
+#include <libempathy/empathy-irc-network.h>
+
+G_BEGIN_DECLS
+
+GtkWidget * empathy_irc_network_dialog_show (EmpathyIrcNetwork *network,
+    GtkWidget *parent);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_IRC_NETWORK_DIALOG_H__ */
diff --git a/libempathy-gtk/totem-subtitle-encoding.c b/libempathy-gtk/totem-subtitle-encoding.c
new file mode 100644 (file)
index 0000000..e0eef08
--- /dev/null
@@ -0,0 +1,585 @@
+/* 
+ * Copyright (C) 2001-2006 Bastien Nocera <hadess@hadess.net>
+ *
+ * encoding list copied from gnome-terminal/encoding.c
+ *
+ * This program 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 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Totem project hereby grant permission for non-gpl compatible GStreamer
+ * plugins to be used and distributed together with GStreamer and Totem. This
+ * permission are above and beyond the permissions granted by the GPL license
+ * Totem is covered by.
+ *
+ * Monday 7th February 2005: Christian Schaller: Add exception clause.
+ * See license_change file for details.
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n.h>
+#include "totem-subtitle-encoding.h"
+#include <string.h>
+
+typedef enum
+{
+  SUBTITLE_ENCODING_CURRENT_LOCALE,
+
+  SUBTITLE_ENCODING_ISO_8859_6,
+  SUBTITLE_ENCODING_IBM_864,
+  SUBTITLE_ENCODING_MAC_ARABIC,
+  SUBTITLE_ENCODING_WINDOWS_1256,
+
+  SUBTITLE_ENCODING_ARMSCII_8,
+
+  SUBTITLE_ENCODING_ISO_8859_4,
+  SUBTITLE_ENCODING_ISO_8859_13,
+  SUBTITLE_ENCODING_WINDOWS_1257,
+
+  SUBTITLE_ENCODING_ISO_8859_14,
+
+  SUBTITLE_ENCODING_ISO_8859_2,
+  SUBTITLE_ENCODING_IBM_852,
+  SUBTITLE_ENCODING_MAC_CE,
+  SUBTITLE_ENCODING_WINDOWS_1250,
+
+  SUBTITLE_ENCODING_GB18030,
+  SUBTITLE_ENCODING_GB2312,
+  SUBTITLE_ENCODING_GBK,
+  SUBTITLE_ENCODING_HZ,
+
+  SUBTITLE_ENCODING_BIG5,
+  SUBTITLE_ENCODING_BIG5_HKSCS,
+  SUBTITLE_ENCODING_EUC_TW,
+
+  SUBTITLE_ENCODING_MAC_CROATIAN,
+
+  SUBTITLE_ENCODING_ISO_8859_5,
+  SUBTITLE_ENCODING_IBM_855,
+  SUBTITLE_ENCODING_ISO_IR_111,
+  SUBTITLE_ENCODING_KOI8_R,
+  SUBTITLE_ENCODING_MAC_CYRILLIC,
+  SUBTITLE_ENCODING_WINDOWS_1251,
+
+  SUBTITLE_ENCODING_CP_866,
+
+  SUBTITLE_ENCODING_MAC_UKRAINIAN,
+  SUBTITLE_ENCODING_KOI8_U,
+
+  SUBTITLE_ENCODING_GEOSTD8,
+
+  SUBTITLE_ENCODING_ISO_8859_7,
+  SUBTITLE_ENCODING_MAC_GREEK,
+  SUBTITLE_ENCODING_WINDOWS_1253,
+
+  SUBTITLE_ENCODING_MAC_GUJARATI,
+
+  SUBTITLE_ENCODING_MAC_GURMUKHI,
+
+  SUBTITLE_ENCODING_ISO_8859_8_I,
+  SUBTITLE_ENCODING_IBM_862,
+  SUBTITLE_ENCODING_MAC_HEBREW,
+  SUBTITLE_ENCODING_WINDOWS_1255,
+
+  SUBTITLE_ENCODING_ISO_8859_8,
+
+  SUBTITLE_ENCODING_MAC_DEVANAGARI,
+
+  SUBTITLE_ENCODING_MAC_ICELANDIC,
+
+  SUBTITLE_ENCODING_EUC_JP,
+  SUBTITLE_ENCODING_ISO_2022_JP,
+  SUBTITLE_ENCODING_SHIFT_JIS,
+
+  SUBTITLE_ENCODING_EUC_KR,
+  SUBTITLE_ENCODING_ISO_2022_KR,
+  SUBTITLE_ENCODING_JOHAB,
+  SUBTITLE_ENCODING_UHC,
+
+  SUBTITLE_ENCODING_ISO_8859_10,
+
+  SUBTITLE_ENCODING_MAC_FARSI,
+
+  SUBTITLE_ENCODING_ISO_8859_16,
+  SUBTITLE_ENCODING_MAC_ROMANIAN,
+
+  SUBTITLE_ENCODING_ISO_8859_3,
+
+  SUBTITLE_ENCODING_TIS_620,
+
+  SUBTITLE_ENCODING_ISO_8859_9,
+  SUBTITLE_ENCODING_IBM_857,
+  SUBTITLE_ENCODING_MAC_TURKISH,
+  SUBTITLE_ENCODING_WINDOWS_1254,
+
+  SUBTITLE_ENCODING_UTF_7,
+  SUBTITLE_ENCODING_UTF_8,
+  SUBTITLE_ENCODING_UTF_16,
+  SUBTITLE_ENCODING_UCS_2,
+  SUBTITLE_ENCODING_UCS_4,
+
+  SUBTITLE_ENCODING_ISO_8859_1,
+  SUBTITLE_ENCODING_ISO_8859_15,
+  SUBTITLE_ENCODING_IBM_850,
+  SUBTITLE_ENCODING_MAC_ROMAN,
+  SUBTITLE_ENCODING_WINDOWS_1252,
+
+  SUBTITLE_ENCODING_TCVN,
+  SUBTITLE_ENCODING_VISCII,
+  SUBTITLE_ENCODING_WINDOWS_1258,
+
+  SUBTITLE_ENCODING_LAST
+} SubtitleEncodingIndex;
+
+
+typedef struct
+{
+  int index;
+  gboolean valid;
+  char *charset;
+  char *name;
+} SubtitleEncoding;
+
+
+static SubtitleEncoding encodings[] = {
+
+  {SUBTITLE_ENCODING_CURRENT_LOCALE, TRUE,
+      NULL, N_("Current Locale")},
+
+  {SUBTITLE_ENCODING_ISO_8859_6, FALSE,
+      "ISO-8859-6", N_("Arabic")},
+  {SUBTITLE_ENCODING_IBM_864, FALSE,
+      "IBM864", N_("Arabic")},
+  {SUBTITLE_ENCODING_MAC_ARABIC, FALSE,
+      "MAC_ARABIC", N_("Arabic")},
+  {SUBTITLE_ENCODING_WINDOWS_1256, FALSE,
+      "WINDOWS-1256", N_("Arabic")},
+
+  {SUBTITLE_ENCODING_ARMSCII_8, FALSE,
+      "ARMSCII-8", N_("Armenian")},
+
+  {SUBTITLE_ENCODING_ISO_8859_4, FALSE,
+      "ISO-8859-4", N_("Baltic")},
+  {SUBTITLE_ENCODING_ISO_8859_13, FALSE,
+      "ISO-8859-13", N_("Baltic")},
+  {SUBTITLE_ENCODING_WINDOWS_1257, FALSE,
+      "WINDOWS-1257", N_("Baltic")},
+
+  {SUBTITLE_ENCODING_ISO_8859_14, FALSE,
+      "ISO-8859-14", N_("Celtic")},
+
+  {SUBTITLE_ENCODING_ISO_8859_2, FALSE,
+      "ISO-8859-2", N_("Central European")},
+  {SUBTITLE_ENCODING_IBM_852, FALSE,
+      "IBM852", N_("Central European")},
+  {SUBTITLE_ENCODING_MAC_CE, FALSE,
+      "MAC_CE", N_("Central European")},
+  {SUBTITLE_ENCODING_WINDOWS_1250, FALSE,
+      "WINDOWS-1250", N_("Central European")},
+
+  {SUBTITLE_ENCODING_GB18030, FALSE,
+      "GB18030", N_("Chinese Simplified")},
+  {SUBTITLE_ENCODING_GB2312, FALSE,
+      "GB2312", N_("Chinese Simplified")},
+  {SUBTITLE_ENCODING_GBK, FALSE,
+      "GBK", N_("Chinese Simplified")},
+  {SUBTITLE_ENCODING_HZ, FALSE,
+      "HZ", N_("Chinese Simplified")},
+
+  {SUBTITLE_ENCODING_BIG5, FALSE,
+      "BIG5", N_("Chinese Traditional")},
+  {SUBTITLE_ENCODING_BIG5_HKSCS, FALSE,
+      "BIG5-HKSCS", N_("Chinese Traditional")},
+  {SUBTITLE_ENCODING_EUC_TW, FALSE,
+      "EUC-TW", N_("Chinese Traditional")},
+
+  {SUBTITLE_ENCODING_MAC_CROATIAN, FALSE,
+      "MAC_CROATIAN", N_("Croatian")},
+
+  {SUBTITLE_ENCODING_ISO_8859_5, FALSE,
+      "ISO-8859-5", N_("Cyrillic")},
+  {SUBTITLE_ENCODING_IBM_855, FALSE,
+      "IBM855", N_("Cyrillic")},
+  {SUBTITLE_ENCODING_ISO_IR_111, FALSE,
+      "ISO-IR-111", N_("Cyrillic")},
+  {SUBTITLE_ENCODING_KOI8_R, FALSE,
+      "KOI8-R", N_("Cyrillic")},
+  {SUBTITLE_ENCODING_MAC_CYRILLIC, FALSE,
+      "MAC-CYRILLIC", N_("Cyrillic")},
+  {SUBTITLE_ENCODING_WINDOWS_1251, FALSE,
+      "WINDOWS-1251", N_("Cyrillic")},
+
+  {SUBTITLE_ENCODING_CP_866, FALSE,
+      "CP866", N_("Cyrillic/Russian")},
+
+  {SUBTITLE_ENCODING_MAC_UKRAINIAN, FALSE,
+      "MAC_UKRAINIAN", N_("Cyrillic/Ukrainian")},
+  {SUBTITLE_ENCODING_KOI8_U, FALSE,
+      "KOI8-U", N_("Cyrillic/Ukrainian")},
+
+  {SUBTITLE_ENCODING_GEOSTD8, FALSE,
+      "GEORGIAN-PS", N_("Georgian")},
+
+  {SUBTITLE_ENCODING_ISO_8859_7, FALSE,
+      "ISO-8859-7", N_("Greek")},
+  {SUBTITLE_ENCODING_MAC_GREEK, FALSE,
+      "MAC_GREEK", N_("Greek")},
+  {SUBTITLE_ENCODING_WINDOWS_1253, FALSE,
+      "WINDOWS-1253", N_("Greek")},
+
+  {SUBTITLE_ENCODING_MAC_GUJARATI, FALSE,
+      "MAC_GUJARATI", N_("Gujarati")},
+
+  {SUBTITLE_ENCODING_MAC_GURMUKHI, FALSE,
+      "MAC_GURMUKHI", N_("Gurmukhi")},
+
+  {SUBTITLE_ENCODING_ISO_8859_8_I, FALSE,
+      "ISO-8859-8-I", N_("Hebrew")},
+  {SUBTITLE_ENCODING_IBM_862, FALSE,
+      "IBM862", N_("Hebrew")},
+  {SUBTITLE_ENCODING_MAC_HEBREW, FALSE,
+      "MAC_HEBREW", N_("Hebrew")},
+  {SUBTITLE_ENCODING_WINDOWS_1255, FALSE,
+      "WINDOWS-1255", N_("Hebrew")},
+
+  {SUBTITLE_ENCODING_ISO_8859_8, FALSE,
+      "ISO-8859-8", N_("Hebrew Visual")},
+
+  {SUBTITLE_ENCODING_MAC_DEVANAGARI, FALSE,
+      "MAC_DEVANAGARI", N_("Hindi")},
+
+  {SUBTITLE_ENCODING_MAC_ICELANDIC, FALSE,
+      "MAC_ICELANDIC", N_("Icelandic")},
+
+  {SUBTITLE_ENCODING_EUC_JP, FALSE,
+      "EUC-JP", N_("Japanese")},
+  {SUBTITLE_ENCODING_ISO_2022_JP, FALSE,
+      "ISO2022JP", N_("Japanese")},
+  {SUBTITLE_ENCODING_SHIFT_JIS, FALSE,
+      "SHIFT-JIS", N_("Japanese")},
+
+  {SUBTITLE_ENCODING_EUC_KR, FALSE,
+      "EUC-KR", N_("Korean")},
+  {SUBTITLE_ENCODING_ISO_2022_KR, FALSE,
+      "ISO2022KR", N_("Korean")},
+  {SUBTITLE_ENCODING_JOHAB, FALSE,
+      "JOHAB", N_("Korean")},
+  {SUBTITLE_ENCODING_UHC, FALSE,
+      "UHC", N_("Korean")},
+
+  {SUBTITLE_ENCODING_ISO_8859_10, FALSE,
+      "ISO-8859-10", N_("Nordic")},
+
+  {SUBTITLE_ENCODING_MAC_FARSI, FALSE,
+      "MAC_FARSI", N_("Persian")},
+
+  {SUBTITLE_ENCODING_ISO_8859_16, FALSE,
+      "ISO-8859-16", N_("Romanian")},
+  {SUBTITLE_ENCODING_MAC_ROMANIAN, FALSE,
+      "MAC_ROMANIAN", N_("Romanian")},
+
+  {SUBTITLE_ENCODING_ISO_8859_3, FALSE,
+      "ISO-8859-3", N_("South European")},
+
+  {SUBTITLE_ENCODING_TIS_620, FALSE,
+      "TIS-620", N_("Thai")},
+
+  {SUBTITLE_ENCODING_ISO_8859_9, FALSE,
+      "ISO-8859-9", N_("Turkish")},
+  {SUBTITLE_ENCODING_IBM_857, FALSE,
+      "IBM857", N_("Turkish")},
+  {SUBTITLE_ENCODING_MAC_TURKISH, FALSE,
+      "MAC_TURKISH", N_("Turkish")},
+  {SUBTITLE_ENCODING_WINDOWS_1254, FALSE,
+      "WINDOWS-1254", N_("Turkish")},
+
+  {SUBTITLE_ENCODING_UTF_7, FALSE,
+      "UTF-7", N_("Unicode")},
+  {SUBTITLE_ENCODING_UTF_8, FALSE,
+      "UTF-8", N_("Unicode")},
+  {SUBTITLE_ENCODING_UTF_16, FALSE,
+      "UTF-16", N_("Unicode")},
+  {SUBTITLE_ENCODING_UCS_2, FALSE,
+      "UCS-2", N_("Unicode")},
+  {SUBTITLE_ENCODING_UCS_4, FALSE,
+      "UCS-4", N_("Unicode")},
+
+  {SUBTITLE_ENCODING_ISO_8859_1, FALSE,
+      "ISO-8859-1", N_("Western")},
+  {SUBTITLE_ENCODING_ISO_8859_15, FALSE,
+      "ISO-8859-15", N_("Western")},
+  {SUBTITLE_ENCODING_IBM_850, FALSE,
+      "IBM850", N_("Western")},
+  {SUBTITLE_ENCODING_MAC_ROMAN, FALSE,
+      "MAC_ROMAN", N_("Western")},
+  {SUBTITLE_ENCODING_WINDOWS_1252, FALSE,
+      "WINDOWS-1252", N_("Western")},
+
+  {SUBTITLE_ENCODING_TCVN, FALSE,
+      "TCVN", N_("Vietnamese")},
+  {SUBTITLE_ENCODING_VISCII, FALSE,
+      "VISCII", N_("Vietnamese")},
+  {SUBTITLE_ENCODING_WINDOWS_1258, FALSE,
+      "WINDOWS-1258", N_("Vietnamese")}
+};
+
+static const SubtitleEncoding *
+find_encoding_by_charset (const char *charset)
+{
+  int i;
+
+  i = 1;                        /* skip current locale */
+  while (i < SUBTITLE_ENCODING_LAST) {
+    if (strcasecmp (charset, encodings[i].charset) == 0)
+      return &encodings[i];
+
+    ++i;
+  }
+
+  if (strcasecmp (charset,
+          encodings[SUBTITLE_ENCODING_CURRENT_LOCALE].charset) == 0)
+    return &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE];
+
+  return NULL;
+}
+
+static void
+subtitle_encoding_init (void)
+{
+  int i;
+  gsize bytes_read, bytes_written;
+  gchar *converted;
+  gchar ascii_sample[96];
+
+  g_get_charset ((const char **)
+      &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE].charset);
+
+  g_assert (G_N_ELEMENTS (encodings) == SUBTITLE_ENCODING_LAST);
+
+  /* Initialize the sample text with all of the printing ASCII characters
+   * from space (32) to the tilde (126), 95 in all. */
+  for (i = 0; i < (int) sizeof (ascii_sample); i++)
+    ascii_sample[i] = i + 32;
+
+  ascii_sample[sizeof (ascii_sample) - 1] = '\0';
+
+  i = 0;
+  while (i < SUBTITLE_ENCODING_LAST) {
+    bytes_read = 0;
+    bytes_written = 0;
+
+    g_assert (encodings[i].index == i);
+
+    /* Translate the names */
+    encodings[i].name = _(encodings[i].name);
+
+    /* Test that the encoding is a proper superset of ASCII (which naive
+     * apps are going to use anyway) by attempting to validate the text
+     * using the current encoding.  This also flushes out any encodings
+     * which the underlying GIConv implementation can't support.
+     */
+    converted = g_convert (ascii_sample, sizeof (ascii_sample) - 1,
+        encodings[i].charset, encodings[i].charset,
+        &bytes_read, &bytes_written, NULL);
+
+    /* The encoding is only valid if ASCII passes through cleanly. */
+    if (i == SUBTITLE_ENCODING_CURRENT_LOCALE)
+      encodings[i].valid = TRUE;
+    else
+      encodings[i].valid =
+          (bytes_read == (sizeof (ascii_sample) - 1)) &&
+          (converted != NULL) && (strcmp (converted, ascii_sample) == 0);
+
+#ifdef DEBUG_ENCODINGS
+    if (!encodings[i].valid) {
+      g_print ("Rejecting encoding %s as invalid:\n", encodings[i].charset);
+      g_print (" input  \"%s\"\n", ascii_sample);
+      g_print (" output \"%s\"\n\n", converted ? converted : "(null)");
+    }
+#endif
+
+    /* Discard the converted string. */
+    g_free (converted);
+
+    ++i;
+  }
+}
+
+static int
+subtitle_encoding_get_index (const char *charset)
+{
+  const SubtitleEncoding *e;
+
+  e = find_encoding_by_charset (charset);
+  if (e != NULL)
+    return e->index;
+  else
+    return SUBTITLE_ENCODING_CURRENT_LOCALE;
+}
+
+static const char *
+subtitle_encoding_get_charset (int index)
+{
+  const SubtitleEncoding *e;
+
+  if (index >= SUBTITLE_ENCODING_LAST)
+    e = &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE];
+  else if (index < SUBTITLE_ENCODING_CURRENT_LOCALE)
+    e = &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE];
+  else if (!encodings[index].valid)
+    e = &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE];
+  else
+    e = &encodings[index];
+  return e->charset;
+}
+
+enum
+{
+  INDEX_COL,
+  NAME_COL
+};
+
+static gint
+compare (GtkTreeModel * model, GtkTreeIter * a, GtkTreeIter * b, gpointer data)
+{
+  gchar *str_a, *str_b;
+  gint result;
+
+  gtk_tree_model_get (model, a, NAME_COL, &str_a, -1);
+  gtk_tree_model_get (model, b, NAME_COL, &str_b, -1);
+
+  result = strcmp (str_a, str_b);
+
+  g_free (str_a);
+  g_free (str_b);
+
+  return result;
+}
+
+static void
+is_encoding_sensitive (GtkCellLayout * cell_layout,
+    GtkCellRenderer * cell,
+    GtkTreeModel * tree_model, GtkTreeIter * iter, gpointer data)
+{
+
+  gboolean sensitive;
+
+  sensitive = !gtk_tree_model_iter_has_child (tree_model, iter);
+  g_object_set (cell, "sensitive", sensitive, NULL);
+}
+
+static GtkTreeModel *
+subtitle_encoding_create_store (void)
+{
+  gchar *label;
+  gchar *lastlang = "";
+  GtkTreeIter iter, iter2;
+  GtkTreeStore *store;
+  int i;
+
+  store = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_STRING);
+
+  for (i = 0; i < SUBTITLE_ENCODING_LAST; i++) {
+    if (encodings[i].valid) {
+      if (strcmp (lastlang, encodings[i].name)) {
+        lastlang = encodings[i].name;
+        gtk_tree_store_append (store, &iter, NULL);
+        gtk_tree_store_set (store, &iter, INDEX_COL,
+            -1, NAME_COL, lastlang, -1);
+      }
+      label = g_strdup_printf("%s (%s)", lastlang, encodings[i].charset);
+      gtk_tree_store_append (store, &iter2, &iter);
+      gtk_tree_store_set (store, &iter2, INDEX_COL,
+          encodings[i].index, NAME_COL, label, -1);
+      g_free(label);
+    }
+  }
+  gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store),
+      compare, NULL, NULL);
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+      NAME_COL, GTK_SORT_ASCENDING);
+  return GTK_TREE_MODEL (store);
+}
+
+static void
+subtitle_encoding_combo_render (GtkComboBox * combo)
+{
+  GtkCellRenderer *renderer;
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+      "text", NAME_COL, NULL);
+  gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
+      renderer, is_encoding_sensitive, NULL, NULL);
+}
+
+const char *
+totem_subtitle_encoding_get_selected (GtkComboBox * combo)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  gint index = -1;
+
+  model = gtk_combo_box_get_model (combo);
+  if (gtk_combo_box_get_active_iter (combo, &iter)) {
+    gtk_tree_model_get (model, &iter, INDEX_COL, &index, -1);
+  }
+  if (index == -1)
+    return NULL;
+  return subtitle_encoding_get_charset (index);
+}
+
+void
+totem_subtitle_encoding_set (GtkComboBox * combo, const char *encoding)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter, iter2;
+  gint index, i;
+
+  g_return_if_fail (encoding != NULL);
+
+  model = gtk_combo_box_get_model (combo);
+  index = subtitle_encoding_get_index (encoding);
+  gtk_tree_model_get_iter_first (model, &iter);
+  do {
+    if (!gtk_tree_model_iter_has_child (model, &iter))
+      continue;
+    if (!gtk_tree_model_iter_children (model, &iter2, &iter))
+      continue;
+    do {
+      gtk_tree_model_get (model, &iter2, INDEX_COL, &i, -1);
+      if (i == index)
+        break;
+    } while (gtk_tree_model_iter_next (model, &iter2));
+    if (i == index)
+      break;
+  } while (gtk_tree_model_iter_next (model, &iter));
+  gtk_combo_box_set_active_iter (combo, &iter2);
+}
+
+void
+totem_subtitle_encoding_init (GtkComboBox *combo)
+{
+  GtkTreeModel *model;
+  subtitle_encoding_init ();
+  model = subtitle_encoding_create_store ();
+  gtk_combo_box_set_model (combo, model);
+  g_object_unref (model);
+  subtitle_encoding_combo_render (combo);
+}
+
+/*
+ * vim: sw=2 ts=8 cindent noai bs=2
+ */
diff --git a/libempathy-gtk/totem-subtitle-encoding.h b/libempathy-gtk/totem-subtitle-encoding.h
new file mode 100644 (file)
index 0000000..7283f00
--- /dev/null
@@ -0,0 +1,12 @@
+/* Encoding stuff */
+
+#ifndef TOTEM_SUBTITLE_ENCODING_H
+#define TOTEM_SUBTITLE_ENCODING_H
+
+#include <gtk/gtk.h>
+
+void totem_subtitle_encoding_init (GtkComboBox *combo);
+void totem_subtitle_encoding_set (GtkComboBox *combo, const char *encoding);
+const char * totem_subtitle_encoding_get_selected (GtkComboBox *combo);
+
+#endif /* SUBTITLE_ENCODING_H */
index 5d0c021b26cd53cc8f073fc395f6f5e259f37fd1..b952be270ee0137a816ff633de18407326909e23 100644 (file)
@@ -41,7 +41,10 @@ libempathy_la_SOURCES =                                      \
        empathy-chandler.c                              \
        empathy-filter.c                                \
        empathy-idle.c                                  \
        empathy-chandler.c                              \
        empathy-filter.c                                \
        empathy-idle.c                                  \
-       empathy-log-manager.c
+       empathy-log-manager.c                           \
+       empathy-irc-network-manager.c                   \
+       empathy-irc-network.c                           \
+       empathy-irc-server.c
 
 # do not distribute generated files
 nodist_libempathy_la_SOURCES =\
 
 # do not distribute generated files
 nodist_libempathy_la_SOURCES =\
@@ -78,7 +81,10 @@ libempathy_headers =                         \
        empathy-chandler.h                      \
        empathy-filter.h                        \
        empathy-idle.h                          \
        empathy-chandler.h                      \
        empathy-filter.h                        \
        empathy-idle.h                          \
-       empathy-log-manager.h
+       empathy-log-manager.h                   \
+       empathy-irc-network-manager.h           \
+       empathy-irc-network.h                   \
+       empathy-irc-server.h
 
 libempathy_includedir = $(includedir)/libempathy/
 libempathy_include_HEADERS =                   \
 
 libempathy_includedir = $(includedir)/libempathy/
 libempathy_include_HEADERS =                   \
@@ -154,12 +160,17 @@ dtddir = $(datadir)/empathy
 dtd_DATA =                                     \
        empathy-status-presets.dtd              \
        empathy-contact-groups.dtd              \
 dtd_DATA =                                     \
        empathy-status-presets.dtd              \
        empathy-contact-groups.dtd              \
-       empathy-chatroom-manager.dtd
+       empathy-chatroom-manager.dtd            \
+       empathy-irc-networks.dtd
 
 stylesheetdir = $(datadir)/empathy
 stylesheet_DATA =              \
        empathy-log-manager.xsl
 
 
 stylesheetdir = $(datadir)/empathy
 stylesheet_DATA =              \
        empathy-log-manager.xsl
 
+ircnetworksdir = $(datadir)/empathy
+ircnetworks_DATA =             \
+       irc-networks.xml
+
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libempathy.pc
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libempathy.pc
 
@@ -169,7 +180,8 @@ EXTRA_DIST =                        \
        empathy-filter.xml      \
        tp-stream-engine.xml    \
        $(stylesheet_DATA)      \
        empathy-filter.xml      \
        tp-stream-engine.xml    \
        $(stylesheet_DATA)      \
-       $(dtd_DATA)
+       $(dtd_DATA)             \
+       $(ircnetworks_DATA)
 
 CLEANFILES =                           \
        $(BUILT_SOURCES)                \
 
 CLEANFILES =                           \
        $(BUILT_SOURCES)                \
diff --git a/libempathy/empathy-irc-network-manager.c b/libempathy/empathy-irc-network-manager.c
new file mode 100644 (file)
index 0000000..f88b93b
--- /dev/null
@@ -0,0 +1,801 @@
+/*
+ * 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 <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <libempathy/empathy-debug.h>
+
+#include "empathy-utils.h"
+#include "empathy-irc-network-manager.h"
+
+#define DEBUG_DOMAIN "IrcNetworkManager"
+#define IRC_NETWORKS_DTD_FILENAME "empathy-irc-networks.dtd"
+#define SAVE_TIMER 4
+
+G_DEFINE_TYPE (EmpathyIrcNetworkManager, empathy_irc_network_manager,
+    G_TYPE_OBJECT);
+
+/* properties */
+enum
+{
+  PROP_GLOBAL_FILE = 1,
+  PROP_USER_FILE,
+  LAST_PROPERTY
+};
+
+typedef struct _EmpathyIrcNetworkManagerPrivate
+    EmpathyIrcNetworkManagerPrivate;
+
+struct _EmpathyIrcNetworkManagerPrivate {
+  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;
+};
+
+#define EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE(obj)\
+    ((EmpathyIrcNetworkManagerPrivate *) obj->priv)
+
+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);
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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);
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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);
+  EmpathyIrcNetworkManagerPrivate *priv = 
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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_destroy (priv->networks);
+
+  G_OBJECT_CLASS (empathy_irc_network_manager_parent_class)->finalize (object);
+}
+
+static void
+empathy_irc_network_manager_init (EmpathyIrcNetworkManager *self)
+{
+  EmpathyIrcNetworkManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+      EMPATHY_TYPE_IRC_NETWORK_MANAGER, EmpathyIrcNetworkManagerPrivate);
+
+  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 (EmpathyIrcNetworkManagerPrivate));
+
+  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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (self);
+
+  priv->save_timer_id = 0;
+  irc_network_manager_file_save (self);
+
+  return FALSE;
+}
+
+static void
+reset_save_timeout (EmpathyIrcNetworkManager *self)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv;
+  gchar *id = NULL;
+
+  g_return_if_fail (EMPATHY_IS_IRC_NETWORK_MANAGER (self));
+  g_return_if_fail (EMPATHY_IS_IRC_NETWORK (network));
+
+  priv = EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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)
+    {
+      empathy_debug (DEBUG_DOMAIN,
+          "Can't add network: too many networks using a similiar ID");
+      return;
+    }
+
+  empathy_debug (DEBUG_DOMAIN, "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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv;
+
+  g_return_if_fail (EMPATHY_IS_IRC_NETWORK_MANAGER (self));
+  g_return_if_fail (EMPATHY_IS_IRC_NETWORK (network));
+
+  priv = EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (self);
+
+  network->user_defined = TRUE;
+  network->dropped = TRUE;
+
+  priv->have_to_save = TRUE;
+  reset_save_timeout (self);
+}
+
+static void
+append_network_to_list (const gchar *id,
+                        EmpathyIrcNetwork *network,
+                        GSList **list)
+{
+  if (network->dropped)
+    return;
+
+  *list = g_slist_prepend (*list, g_object_ref (network));
+}
+
+/**
+ * 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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv;
+  GSList *irc_networks = NULL;
+
+  g_return_val_if_fail (EMPATHY_IS_IRC_NETWORK_MANAGER (self), NULL);
+
+  priv = EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (self);
+
+  g_hash_table_foreach (priv->networks, (GHFunc) append_network_to_list,
+      &irc_networks);
+
+  return irc_networks;
+}
+
+/*
+ * API to save/load and parse the irc_networks file.
+ */
+
+static void
+load_global_file (EmpathyIrcNetworkManager *self)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (self);
+
+  if (priv->global_file == NULL)
+    return;
+
+  if (!g_file_test (priv->global_file, G_FILE_TEST_EXISTS))
+    {
+      empathy_debug (DEBUG_DOMAIN, "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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (self);
+
+  if (priv->user_file == NULL)
+    return;
+
+  if (!g_file_test (priv->user_file, G_FILE_TEST_EXISTS))
+    {
+      empathy_debug (DEBUG_DOMAIN, "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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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 (server_node->name, "server") != 0)
+        continue;
+
+      address = xmlGetProp (server_node, "address");
+      port = xmlGetProp (server_node, "port");
+      ssl = xmlGetProp (server_node, "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;
+
+          empathy_debug (DEBUG_DOMAIN, "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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (self);
+  EmpathyIrcNetwork  *network;
+  xmlNodePtr child;
+  gchar *str;
+  gchar *id, *name;
+
+  id = xmlGetProp (node, "id");
+  if (xmlHasProp (node, "dropped"))
+    {
+      if (!user_defined)
+        {
+          empathy_debug (DEBUG_DOMAIN, "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, "name"))
+    return;
+
+  name = xmlGetProp (node, "name");
+  network = empathy_irc_network_new (name);
+
+  if (xmlHasProp (node, "network_charset"))
+    {
+      gchar *charset;
+      charset = xmlGetProp (node, "network_charset");
+      g_object_set (network, "charset", charset, NULL);
+      xmlFree (charset);
+    }
+
+  add_network (self, network, id);
+  empathy_debug (DEBUG_DOMAIN, "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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv;
+  xmlParserCtxtPtr ctxt;
+  xmlDocPtr doc;
+  xmlNodePtr networks;
+  xmlNodePtr node;
+
+  priv = EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (self);
+
+  empathy_debug (DEBUG_DOMAIN, "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 (doc, IRC_NETWORKS_DTD_FILENAME)) {
+    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, "network", NULL);
+  xmlNewProp (network_node, "id", id);
+
+  if (network->dropped)
+    {
+      xmlNewProp (network_node, "dropped", "1");
+      return;
+    }
+
+  g_object_get (network,
+      "name", &name,
+      "charset", &charset,
+      NULL);
+  xmlNewProp (network_node, "name", name);
+  xmlNewProp (network_node, "network_charset", charset);
+  g_free (name);
+  g_free (charset);
+
+  servers = empathy_irc_network_get_servers (network);
+
+  servers_node = xmlNewChild (network_node, NULL, "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, "server", NULL);
+
+      g_object_get (server,
+          "address", &address,
+          "port", &port,
+          "ssl", &ssl,
+          NULL);
+
+      xmlNewProp (server_node, "address", address);
+
+      tmp = g_strdup_printf ("%u", port);
+      xmlNewProp (server_node, "port", tmp);
+      g_free (tmp);
+
+      xmlNewProp (server_node, "ssl", ssl ? "TRUE": "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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (self);
+  xmlDocPtr doc;
+  xmlNodePtr root;
+
+  if (priv->user_file == NULL)
+    {
+      empathy_debug (DEBUG_DOMAIN, "can't save: no user file defined");
+      return FALSE;
+    }
+
+  empathy_debug (DEBUG_DOMAIN, "Saving IRC networks");
+
+  doc = xmlNewDoc ("1.0");
+  root = xmlNewNode (NULL, "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);
+
+  xmlCleanupParser ();
+  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)
+{
+  EmpathyIrcNetworkManagerPrivate *priv =
+    EMPATHY_IRC_NETWORK_MANAGER_GET_PRIVATE (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;
+}
diff --git a/libempathy/empathy-irc-network-manager.h b/libempathy/empathy-irc-network-manager.h
new file mode 100644 (file)
index 0000000..a853a07
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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);
+
+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);
+
+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/libempathy/empathy-irc-network.c b/libempathy/empathy-irc-network.c
new file mode 100644 (file)
index 0000000..f754ade
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <telepathy-glib/util.h>
+
+#include "empathy-marshal.h"
+#include "empathy-irc-network.h"
+
+G_DEFINE_TYPE (EmpathyIrcNetwork, empathy_irc_network, G_TYPE_OBJECT);
+
+/* properties */
+enum
+{
+  PROP_NAME = 1,
+  PROP_CHARSET,
+  LAST_PROPERTY
+};
+
+/* signals */
+enum
+{
+  MODIFIED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+typedef struct _EmpathyIrcNetworkPrivate EmpathyIrcNetworkPrivate;
+
+struct _EmpathyIrcNetworkPrivate
+{
+  gchar *name;
+  gchar *charset;
+  GSList *servers;
+};
+
+#define EMPATHY_IRC_NETWORK_GET_PRIVATE(obj)\
+    ((EmpathyIrcNetworkPrivate *) obj->priv)
+
+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);
+  EmpathyIrcNetworkPrivate *priv = EMPATHY_IRC_NETWORK_GET_PRIVATE (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);
+  EmpathyIrcNetworkPrivate *priv = EMPATHY_IRC_NETWORK_GET_PRIVATE (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);
+  EmpathyIrcNetworkPrivate *priv = EMPATHY_IRC_NETWORK_GET_PRIVATE (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);
+  EmpathyIrcNetworkPrivate *priv = EMPATHY_IRC_NETWORK_GET_PRIVATE (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)
+{
+  EmpathyIrcNetworkPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+      EMPATHY_TYPE_IRC_NETWORK, EmpathyIrcNetworkPrivate);
+
+  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 (EmpathyIrcNetworkPrivate));
+
+  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.
+   *
+   */
+  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_VOID__VOID,
+      G_TYPE_NONE, 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)
+{
+  EmpathyIrcNetworkPrivate *priv;
+  GSList *servers = NULL, *l;
+
+  g_return_val_if_fail (EMPATHY_IS_IRC_NETWORK (self), NULL);
+  priv = EMPATHY_IRC_NETWORK_GET_PRIVATE (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)
+{
+  EmpathyIrcNetworkPrivate *priv;
+
+  g_return_if_fail (EMPATHY_IS_IRC_NETWORK (self));
+  g_return_if_fail (server != NULL && EMPATHY_IS_IRC_SERVER (server));
+
+  priv = EMPATHY_IRC_NETWORK_GET_PRIVATE (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)
+{
+  EmpathyIrcNetworkPrivate *priv;
+  GSList *l;
+
+  g_return_if_fail (EMPATHY_IS_IRC_NETWORK (self));
+  g_return_if_fail (server != NULL && EMPATHY_IS_IRC_SERVER (server));
+
+  priv = EMPATHY_IRC_NETWORK_GET_PRIVATE (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)
+{
+  EmpathyIrcNetworkPrivate *priv;
+  GSList *l;
+
+  g_return_if_fail (EMPATHY_IS_IRC_NETWORK (self));
+  g_return_if_fail (server != NULL && EMPATHY_IS_IRC_SERVER (server));
+
+  priv = EMPATHY_IRC_NETWORK_GET_PRIVATE (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);
+}
diff --git a/libempathy/empathy-irc-network.h b/libempathy/empathy-irc-network.h
new file mode 100644 (file)
index 0000000..ac146a1
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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))
+
+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);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_IRC_NETWORK_H__ */
diff --git a/libempathy/empathy-irc-networks.dtd b/libempathy/empathy-irc-networks.dtd
new file mode 100644 (file)
index 0000000..692e613
--- /dev/null
@@ -0,0 +1,18 @@
+<!--
+  DTD for Empathys irc networks.
+  by Xavier Claessens <xclaesse@gmail.com>
+-->
+
+
+<!ELEMENT networks (network*)>
+<!ELEMENT network (servers*)>
+<!ATTLIST network id ID #REQUIRED>
+<!ATTLIST network name CDATA #IMPLIED>
+<!ATTLIST network network_charset CDATA #IMPLIED>
+<!ATTLIST network dropped CDATA #IMPLIED>
+
+<!ELEMENT servers (server*)>
+<!ELEMENT server EMPTY>
+<!ATTLIST server address CDATA #REQUIRED>
+<!ATTLIST server port CDATA #REQUIRED>
+<!ATTLIST server ssl CDATA #REQUIRED>
diff --git a/libempathy/empathy-irc-server.c b/libempathy/empathy-irc-server.c
new file mode 100644 (file)
index 0000000..510acc7
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <telepathy-glib/util.h>
+
+#include "empathy-marshal.h"
+#include "empathy-irc-server.h"
+
+G_DEFINE_TYPE (EmpathyIrcServer, empathy_irc_server, G_TYPE_OBJECT);
+
+/* properties */
+enum
+{
+  PROP_ADDRESS = 1,
+  PROP_PORT,
+  PROP_SSL,
+  LAST_PROPERTY
+};
+
+/* signals */
+enum
+{
+  MODIFIED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+typedef struct _EmpathyIrcServerPrivate EmpathyIrcServerPrivate;
+
+struct _EmpathyIrcServerPrivate
+{
+  gchar *address;
+  gint port;
+  gboolean ssl;
+};
+
+#define EMPATHY_IRC_SERVER_GET_PRIVATE(obj)\
+    ((EmpathyIrcServerPrivate *) obj->priv)
+
+static void
+empathy_irc_server_get_property (GObject *object,
+                                 guint property_id,
+                                 GValue *value,
+                                 GParamSpec *pspec)
+{
+  EmpathyIrcServer *self = EMPATHY_IRC_SERVER (object);
+  EmpathyIrcServerPrivate *priv = EMPATHY_IRC_SERVER_GET_PRIVATE (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);
+  EmpathyIrcServerPrivate *priv = EMPATHY_IRC_SERVER_GET_PRIVATE (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);
+  EmpathyIrcServerPrivate *priv = EMPATHY_IRC_SERVER_GET_PRIVATE (self);
+
+  g_free (priv->address);
+
+  G_OBJECT_CLASS (empathy_irc_server_parent_class)->finalize (object);
+}
+
+static void
+empathy_irc_server_init (EmpathyIrcServer *self)
+{
+  EmpathyIrcServerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+      EMPATHY_TYPE_IRC_SERVER, EmpathyIrcServerPrivate);
+
+  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 (EmpathyIrcServerPrivate));
+
+  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_VOID__VOID,
+      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/libempathy/empathy-irc-server.h b/libempathy/empathy-irc-server.h
new file mode 100644 (file)
index 0000000..09f8c1e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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__ */
diff --git a/libempathy/irc-networks.xml b/libempathy/irc-networks.xml
new file mode 100644 (file)
index 0000000..383ba25
--- /dev/null
@@ -0,0 +1,543 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<networks>
+  <network name="Debian Servers" id="debian_servers">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.debian.org"/>
+      <server ssl="FALSE" port="6667" address="irc.oftc.net"/>
+    </servers>
+  </network>
+  <network name="Ubuntu Servers" id="ubuntu_servers">
+    <servers>
+      <server ssl="FALSE" port="8001" address="irc.ubuntu.com"/>
+    </servers>
+  </network>
+  <network name="2600net" id="a2600net">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.2600.net"/>
+    </servers>
+  </network>
+  <network name="AccessIRC" id="accessirc">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.accessirc.net"/>
+      <server ssl="FALSE" port="6667" address="eu.accessirc.net"/>
+    </servers>
+  </network>
+  <network name="AfterNET" id="afternet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.afternet.org"/>
+      <server ssl="FALSE" port="6667" address="us.afternet.org"/>
+      <server ssl="FALSE" port="6667" address="eu.afternet.org"/>
+    </servers>
+  </network>
+  <network name="Aitvaras" id="aitvaras">
+    <servers>
+      <server ssl="TRUE" port="6668" address="irc.data.lt"/>
+      <server ssl="TRUE" port="6668" address="irc-ssl.omnitel.net"/>
+      <server ssl="TRUE" port="9999" address="irc-ssl.le.lt"/>
+      <server ssl="FALSE" port="6667" address="irc.data.lt"/>
+      <server ssl="FALSE" port="6667" address="irc.omnitel.net"/>
+      <server ssl="FALSE" port="6667" address="irc.ktu.lt"/>
+      <server ssl="FALSE" port="6667" address="irc.le.lt"/>
+      <server ssl="FALSE" port="6667" address="irc.takas.lt"/>
+      <server ssl="FALSE" port="6667" address="irc.5ci.net"/>
+      <server ssl="FALSE" port="6667" address="irc.kis.lt"/>
+    </servers>
+  </network>
+  <network name="AmigaNet" id="amiganet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.amiganet.org"/>
+      <server ssl="FALSE" port="6667" address="us.amiganet.org"/>
+      <server ssl="FALSE" port="6667" address="uk.amiganet.org"/>
+    </servers>
+  </network>
+  <network name="ARCNet" id="arcnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="se1.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="us1.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="us2.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="us3.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="ca1.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="de1.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="de3.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="ch1.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="be1.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="nl3.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="uk1.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="uk2.arcnet.vapor.com"/>
+      <server ssl="FALSE" port="6667" address="fr1.arcnet.vapor.com"/>
+    </servers>
+  </network>
+  <network name="AstroLink" id="astrolink">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.astrolink.org"/>
+    </servers>
+  </network>
+  <network name="AustNet" id="austnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="au.austnet.org"/>
+      <server ssl="FALSE" port="6667" address="us.austnet.org"/>
+      <server ssl="FALSE" port="6667" address="ca.austnet.org"/>
+    </servers>
+  </network>
+  <network name="AzzurraNet" id="azzurranet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.azzurra.org"/>
+      <server ssl="FALSE" port="6667" address="crypto.azzurra.org"/>
+    </servers>
+  </network>
+  <network name="Beirut" id="beirut">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.beirut.com"/>
+    </servers>
+  </network>
+  <network name="ChatJunkies" id="chatjunkies">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.chatjunkies.org"/>
+      <server ssl="FALSE" port="6667" address="nl.chatjunkies.org"/>
+    </servers>
+  </network>
+  <network name="ChatNet" id="chatnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="US.ChatNet.Org"/>
+      <server ssl="FALSE" port="6667" address="EU.ChatNet.Org"/>
+    </servers>
+  </network>
+  <network name="ChatSociety" id="chatsociety">
+    <servers>
+      <server ssl="FALSE" port="6667" address="us.chatsociety.net"/>
+      <server ssl="FALSE" port="6667" address="eu.chatsociety.net"/>
+    </servers>
+  </network>
+  <network name="ChatSpike" id="chatspike">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.chatspike.net"/>
+    </servers>
+  </network>
+  <network name="ChillFactory" id="chillfactory">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.chillfactory.net"/>
+    </servers>
+  </network>
+  <network name="CoolChat" id="coolchat">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.coolchat.net"/>
+    </servers>
+  </network>
+  <network name="Criten" id="criten">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.criten.net"/>
+      <server ssl="FALSE" port="6667" address="irc.eu.criten.net"/>
+    </servers>
+  </network>
+  <network name="DALnet" id="dalnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.dal.net"/>
+      <server ssl="FALSE" port="6667" address="irc.eu.dal.net"/>
+    </servers>
+  </network>
+  <network name="Dark-Tou-Net" id="dark-tou-net">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.d-t-net.de"/>
+      <server ssl="FALSE" port="6667" address="bw.d-t-net.de"/>
+      <server ssl="FALSE" port="6667" address="nc.d-t-net.de"/>
+      <server ssl="FALSE" port="6667" address="wakka.d-t-net.de"/>
+    </servers>
+  </network>
+  <network name="DarkMyst" id="darkmyst">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.darkmyst.org"/>
+    </servers>
+  </network>
+  <network name="DeepIRC" id="deepirc">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.deepirc.net"/>
+    </servers>
+  </network>
+  <network name="DeltaAnime" id="deltaanime">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.deltaanime.net"/>
+    </servers>
+  </network>
+  <network name="EFnet" id="efnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.blackened.com"/>
+      <server ssl="FALSE" port="6667" address="irc.Prison.NET"/>
+      <server ssl="FALSE" port="6667" address="irc.Qeast.net"/>
+      <server ssl="FALSE" port="6667" address="irc.efnet.pl"/>
+      <server ssl="FALSE" port="6667" address="efnet.demon.co.uk"/>
+      <server ssl="FALSE" port="6667" address="irc.lightning.net"/>
+      <server ssl="FALSE" port="6667" address="irc.mindspring.com"/>
+      <server ssl="FALSE" port="6667" address="irc.easynews.com"/>
+      <server ssl="FALSE" port="6667" address="irc.servercentral.net"/>
+    </servers>
+  </network>
+  <network name="EnterTheGame" id="enterthegame">
+    <servers>
+      <server ssl="FALSE" port="6667" address="IRC.EnterTheGame.Com"/>
+    </servers>
+  </network>
+  <network name="EUIrc" id="euirc">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.euirc.net"/>
+      <server ssl="FALSE" port="6667" address="irc.ham.de.euirc.net"/>
+      <server ssl="FALSE" port="6667" address="irc.ber.de.euirc.net"/>
+      <server ssl="FALSE" port="6667" address="irc.ffm.de.euirc.net"/>
+      <server ssl="FALSE" port="6667" address="irc.bre.de.euirc.net"/>
+      <server ssl="FALSE" port="6667" address="irc.hes.de.euirc.net"/>
+      <server ssl="FALSE" port="6667" address="irc.vie.at.euirc.net"/>
+      <server ssl="FALSE" port="6667" address="irc.inn.at.euirc.net"/>
+      <server ssl="FALSE" port="6667" address="irc.bas.ch.euirc.net"/>
+    </servers>
+  </network>
+  <network name="EuropNet" id="europnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.europnet.org"/>
+    </servers>
+  </network>
+  <network name="EU-IRC" id="eu-irc">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.eu-irc.net"/>
+    </servers>
+  </network>
+  <network name="FDFNet" id="fdfnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.fdfnet.net"/>
+      <server ssl="FALSE" port="6667" address="irc.eu.fdfnet.net"/>
+    </servers>
+  </network>
+  <network name="FEFNet" id="fefnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.fef.net"/>
+      <server ssl="FALSE" port="6667" address="irc.ggn.net"/>
+      <server ssl="FALSE" port="6667" address="irc.vendetta.com"/>
+    </servers>
+  </network>
+  <network name="FreeNode" id="freenode">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.freenode.net"/>
+    </servers>
+  </network>
+  <network name="GalaxyNet" id="galaxynet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.galaxynet.org"/>
+    </servers>
+  </network>
+  <network name="GamesNET" id="gamesnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.gamesnet.net"/>
+      <server ssl="FALSE" port="6667" address="irc.ca.gamesnet.net"/>
+      <server ssl="FALSE" port="6667" address="irc.eu.gamesnet.net"/>
+    </servers>
+  </network>
+  <network name="German-Elite" id="german-elite">
+    <servers>
+      <server ssl="FALSE" port="6667" address="dominion.german-elite.net"/>
+      <server ssl="FALSE" port="6667" address="komatu.german-elite.net"/>
+    </servers>
+  </network>
+  <network name="GimpNet" id="gimpnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.gimp.org"/>
+      <server ssl="FALSE" port="6667" address="irc.us.gimp.org"/>
+    </servers>
+  </network>
+  <network name="HabberNet" id="habbernet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.habber.net"/>
+    </servers>
+  </network>
+  <network name="Hashmark" id="hashmark">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.hashmark.net"/>
+    </servers>
+  </network>
+  <network name="IdleMonkeys" id="idlemonkeys">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.idlemonkeys.net"/>
+    </servers>
+  </network>
+  <network name="insiderZ.DE" id="insiderz.de">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.insiderz.de"/>
+      <server ssl="FALSE" port="6666" address="irc.insiderz.de"/>
+    </servers>
+  </network>
+  <network name="IrcLink" id="irclink">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.irclink.net"/>
+      <server ssl="FALSE" port="6667" address="Alesund.no.eu.irclink.net"/>
+      <server ssl="FALSE" port="6667" address="Oslo.no.eu.irclink.net"/>
+      <server ssl="FALSE" port="6667" address="frogn.no.eu.irclink.net"/>
+      <server ssl="FALSE" port="6667" address="tonsberg.no.eu.irclink.net"/>
+    </servers>
+  </network>
+  <network name="IRCNet" id="ircnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.ircnet.com"/>
+      <server ssl="FALSE" port="6668" address="irc.stealth.net"/>
+      <server ssl="FALSE" port="6667" address="ircnet.demon.co.uk"/>
+      <server ssl="FALSE" port="6667" address="irc.datacomm.ch"/>
+      <server ssl="FALSE" port="6667" address="random.ircd.de"/>
+      <server ssl="FALSE" port="6667" address="ircnet.netvision.net.il"/>
+      <server ssl="FALSE" port="6667" address="irc.cs.hut.fi"/>
+    </servers>
+  </network>
+  <network name="Irctoo.net" id="irctoo.net">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.irctoo.net"/>
+    </servers>
+  </network>
+  <network name="Krstarica" id="krstarica">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.krstarica.com"/>
+    </servers>
+  </network>
+  <network name="Librenet" id="librenet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.librenet.net"/>
+      <server ssl="FALSE" port="6667" address="ielf.fr.librenet.net"/>
+    </servers>
+  </network>
+  <network name="LinkNet" id="linknet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.link-net.org"/>
+      <server ssl="FALSE" port="6667" address="irc.no.link-net.org"/>
+      <server ssl="FALSE" port="6667" address="irc.bahnhof.se"/>
+    </servers>
+  </network>
+  <network name="MagicStar" id="magicstar">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.magicstar.net"/>
+    </servers>
+  </network>
+  <network name="Majistic" id="majistic">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.majistic.net"/>
+    </servers>
+  </network>
+  <network name="MindForge" id="mindforge">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.mindforge.org"/>
+    </servers>
+  </network>
+  <network name="MIXXnet" id="mixxnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.mixxnet.net"/>
+    </servers>
+  </network>
+  <network name="NeverNET" id="nevernet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.nevernet.net"/>
+      <server ssl="FALSE" port="6667" address="imagine.nevernet.net"/>
+      <server ssl="FALSE" port="6667" address="dimension.nevernet.net"/>
+      <server ssl="FALSE" port="6667" address="universe.nevernet.net"/>
+      <server ssl="FALSE" port="6667" address="wayland.nevernet.net"/>
+      <server ssl="FALSE" port="6667" address="forte.nevernet.net"/>
+    </servers>
+  </network>
+  <network name="NixHelpNet" id="nixhelpnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="us.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="uk.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="uk2.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="uk3.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="nl.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="ca.ld.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="us.co.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="us.ca.nixhelp.org"/>
+      <server ssl="FALSE" port="6667" address="us.pa.nixhelp.org"/>
+    </servers>
+  </network>
+  <network name="NullusNet" id="nullusnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.nullus.net"/>
+    </servers>
+  </network>
+  <network name="Oceanius" id="oceanius">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.oceanius.com"/>
+    </servers>
+  </network>
+  <network name="OFTC" id="oftc">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.oftc.net"/>
+    </servers>
+  </network>
+  <network name="OtherNet" id="othernet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.othernet.org"/>
+    </servers>
+  </network>
+  <network name="Oz.org" id="oz.org">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.oz.org"/>
+      <server ssl="FALSE" port="6667" address="germany.oz.org"/>
+      <server ssl="FALSE" port="6667" address="sandiego.oz.org"/>
+      <server ssl="FALSE" port="6667" address="us.oz.org"/>
+      <server ssl="FALSE" port="6667" address="au.oz.org"/>
+      <server ssl="FALSE" port="6667" address="rockhampton.oz.org"/>
+      <server ssl="FALSE" port="6667" address="wollongong.oz.org"/>
+      <server ssl="FALSE" port="6667" address="waix.oz.org"/>
+    </servers>
+  </network>
+  <network name="PTlink" id="ptlink">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.PTlink.net"/>
+      <server ssl="FALSE" port="6667" address="aaia.PTlink.net"/>
+    </servers>
+  </network>
+  <network name="PTNe" id="ptne">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.PTNet.org"/>
+      <server ssl="FALSE" port="6667" address="rccn.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="uevora.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="umoderna.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="ist.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="aaum.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="uc.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="ualg.ptnet.org"/>
+      <server ssl="FALSE" port="6667" address="madinfo.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="ua.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="ipg.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="isec.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="utad.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="iscte.PTnet.org"/>
+      <server ssl="FALSE" port="6667" address="ubi.PTnet.org"/>
+    </servers>
+  </network>
+  <network name="QuakeNet" id="quakenet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.quakenet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.se.quakenet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.dk.quakenet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.no.quakenet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.fi.quakenet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.be.quakenet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.uk.quakenet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.de.quakenet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.it.quakenet.org"/>
+    </servers>
+  </network>
+  <network name="RebelChat" id="rebelchat">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.rebelchat.org"/>
+    </servers>
+  </network>
+  <network name="RizeNET" id="rizenet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.rizenet.org"/>
+      <server ssl="FALSE" port="6667" address="omega.rizenet.org"/>
+      <server ssl="FALSE" port="6667" address="evelance.rizenet.org"/>
+      <server ssl="FALSE" port="6667" address="lisa.rizenet.org"/>
+      <server ssl="FALSE" port="6667" address="scott.rizenet.org"/>
+    </servers>
+  </network>
+  <network name="RusNet" id="rusnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.tomsk.net"/>
+      <server ssl="FALSE" port="6667" address="irc.rinet.ru"/>
+      <server ssl="FALSE" port="6667" address="irc.run.net"/>
+      <server ssl="FALSE" port="6667" address="irc.ru"/>
+      <server ssl="FALSE" port="6667" address="irc.lucky.net"/>
+    </servers>
+  </network>
+  <network name="SceneNet" id="scenenet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.scene.org"/>
+      <server ssl="FALSE" port="6667" address="irc.eu.scene.org"/>
+      <server ssl="FALSE" port="6667" address="irc.us.scene.org"/>
+    </servers>
+  </network>
+  <network name="SlashNET" id="slashnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.slashnet.org"/>
+      <server ssl="FALSE" port="6667" address="area51.slashnet.org"/>
+      <server ssl="FALSE" port="6667" address="moo.slashnet.org"/>
+      <server ssl="FALSE" port="6667" address="radon.slashnet.org"/>
+    </servers>
+  </network>
+  <network name="Sohbet.Net" id="sohbet.net">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.sohbet.net"/>
+    </servers>
+  </network>
+  <network name="SolidIRC" id="solidirc">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.solidirc.com"/>
+    </servers>
+  </network>
+  <network name="SorceryNet" id="sorcerynet">
+    <servers>
+      <server ssl="FALSE" port="9000" address="irc.sorcery.net"/>
+      <server ssl="FALSE" port="9000" address="irc.us.sorcery.net"/>
+      <server ssl="FALSE" port="9000" address="irc.eu.sorcery.net"/>
+    </servers>
+  </network>
+  <network name="Spidernet" id="spidernet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="us.spidernet.org"/>
+      <server ssl="FALSE" port="6667" address="eu.spidernet.org"/>
+      <server ssl="FALSE" port="6667" address="irc.spidernet.org"/>
+    </servers>
+  </network>
+  <network name="StarChat" id="starchat">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.starchat.net"/>
+      <server ssl="FALSE" port="6667" address="gainesville.starchat.net"/>
+      <server ssl="FALSE" port="6667" address="freebsd.starchat.net"/>
+      <server ssl="FALSE" port="6667" address="sunset.starchat.net"/>
+      <server ssl="FALSE" port="6667" address="revenge.starchat.net"/>
+      <server ssl="FALSE" port="6667" address="tahoma.starchat.net"/>
+      <server ssl="FALSE" port="6667" address="neo.starchat.net"/>
+    </servers>
+  </network>
+  <network name="TNI3" id="tni3">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.tni3.com"/>
+    </servers>
+  </network>
+  <network name="UnderNet" id="undernet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="us.undernet.org"/>
+      <server ssl="FALSE" port="6667" address="eu.undernet.org"/>
+    </servers>
+  </network>
+  <network name="UniBG" id="unibg">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.lirex.com"/>
+      <server ssl="FALSE" port="6667" address="irc.naturella.com"/>
+      <server ssl="FALSE" port="6667" address="irc.spnet.net"/>
+      <server ssl="FALSE" port="6667" address="irc.techno-link.com"/>
+      <server ssl="FALSE" port="6667" address="irc.telecoms.bg"/>
+      <server ssl="FALSE" port="6667" address="irc.tu-varna.edu"/>
+    </servers>
+  </network>
+  <network name="Whiffle" id="whiffle">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.whiffle.org"/>
+    </servers>
+  </network>
+  <network name="Worldnet" id="worldnet">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.worldnet.net"/>
+      <server ssl="FALSE" port="6667" address="irc.fr.worldnet.net"/>
+    </servers>
+  </network>
+  <network name="Xentonix.net" id="xentonix.net">
+    <servers>
+      <server ssl="FALSE" port="6667" address="irc.ffm.de.eu.xentonix.net"/>
+      <server ssl="FALSE" port="6667" address="irc.kar.de.eu.xentonix.net"/>
+      <server ssl="FALSE" port="6667" address="irc.vie.at.eu.xentonix.net"/>
+    </servers>
+  </network>
+  <network name="XWorld" id="xworld">
+    <servers>
+      <server ssl="FALSE" port="6667" address="Buffalo.NY.US.XWorld.org"/>
+      <server ssl="FALSE" port="6667" address="Minneapolis.MN.US.Xworld.Org"/>
+      <server ssl="FALSE" port="6667" address="Rochester.NY.US.XWorld.org"/>
+      <server ssl="FALSE" port="6667" address="Bayern.DE.EU.XWorld.Org"/>
+      <server ssl="FALSE" port="6667" address="Chicago.IL.US.XWorld.Org"/>
+    </servers>
+  </network>
+</networks>
diff --git a/m4/Makefile.am b/m4/Makefile.am
new file mode 100644 (file)
index 0000000..e69de29
index bc36d382745294661c1013303a95b7ffeeb5c4d7..6efa6b064673744039b69f90ca2b8b31e70b08c3 100644 (file)
@@ -53,6 +53,10 @@ libempathy-gtk/empathy-status-icon.glade
 libempathy-gtk/empathy-theme-boxes.c
 libempathy-gtk/empathy-theme-irc.c
 libempathy-gtk/empathy-theme-manager.c
 libempathy-gtk/empathy-theme-boxes.c
 libempathy-gtk/empathy-theme-irc.c
 libempathy-gtk/empathy-theme-manager.c
+libempathy-gtk/empathy-account-widget-irc.c
+libempathy-gtk/empathy-account-widget-irc.glade
+libempathy-gtk/empathy-irc-network-dialog.c
+libempathy-gtk/totem-subtitle-encoding.c
 
 megaphone/data/GNOME_Megaphone_Applet.schemas.in
 megaphone/data/GNOME_Megaphone_Applet.server.in.in
 
 megaphone/data/GNOME_Megaphone_Applet.schemas.in
 megaphone/data/GNOME_Megaphone_Applet.server.in.in
index c72173818fb59c50dd5f1d15b8125d38232c4e8b..9eb54132f72dd798fc49c31f1438c95ee4a86946 100644 (file)
@@ -26,7 +26,12 @@ check_main_SOURCES =                             \
     check-helpers.c                              \
     check-helpers.h                              \
     check-libempathy.h                           \
     check-helpers.c                              \
     check-helpers.h                              \
     check-libempathy.h                           \
-    check-empathy-utils.c
+    check-empathy-utils.c                        \
+    check-irc-helper.h                           \
+    check-irc-helper.c                           \
+    check-empathy-irc-server.c                   \
+    check-empathy-irc-network.c                  \
+    check-empathy-irc-network-manager.c
 
 check_main_LDADD = \
     @CHECK_LIBS@ \
 
 check_main_LDADD = \
     @CHECK_LIBS@ \
diff --git a/tests/check-empathy-irc-network-manager.c b/tests/check-empathy-irc-network-manager.c
new file mode 100644 (file)
index 0000000..c3e8531
--- /dev/null
@@ -0,0 +1,824 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <glib/gstdio.h>
+
+#include <check.h>
+#include "check-helpers.h"
+#include "check-libempathy.h"
+#include "check-irc-helper.h"
+
+#include <libempathy/empathy-irc-network-manager.h>
+
+#define GLOBAL_SAMPLE "xml/default-irc-networks-sample.xml"
+#define USER_SAMPLE "xml/user-irc-networks-sample.xml"
+#define USER_FILE "xml/user-irc-networks.xml"
+
+START_TEST (test_empathy_irc_network_manager_add)
+{
+  EmpathyIrcNetworkManager *mgr;
+  EmpathyIrcNetwork *network;
+  GSList *networks;
+  gchar *name;
+
+  mgr = empathy_irc_network_manager_new (NULL, NULL);
+  fail_if (mgr == NULL);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (networks != NULL);
+
+  /* add a network */
+  network = empathy_irc_network_new ("My Network");
+  fail_if (network == NULL);
+  empathy_irc_network_manager_add (mgr, network);
+  g_object_unref (network);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 1);
+  g_object_get (networks->data, "name", &name, NULL);
+  fail_if (name == NULL || strcmp (name, "My Network") != 0);
+  g_free (name);
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+
+  /* add another network having the same name */
+  network = empathy_irc_network_new ("My Network");
+  fail_if (network == NULL);
+  empathy_irc_network_manager_add (mgr, network);
+  g_object_unref (network);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 2);
+  g_object_get (networks->data, "name", &name, NULL);
+  fail_if (name == NULL || strcmp (name, "My Network") != 0);
+  g_free (name);
+  g_object_get (g_slist_next(networks)->data, "name", &name, NULL);
+  fail_if (name == NULL || strcmp (name, "My Network") != 0);
+  g_free (name);
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+
+  g_object_unref (mgr);
+}
+END_TEST
+
+START_TEST (test_load_global_file)
+{
+  EmpathyIrcNetworkManager *mgr;
+  gchar *global_file, *user_file;
+  GSList *networks, *l;
+  struct server_t freenode_servers[] = {
+    { "irc.freenode.net", 6667, FALSE },
+    { "irc.eu.freenode.net", 6667, FALSE }};
+  struct server_t gimpnet_servers[] = {
+    { "irc.gimp.org", 6667, FALSE },
+    { "irc.us.gimp.org", 6667, FALSE }};
+  struct server_t test_servers[] = {
+    { "irc.test.org", 6669, TRUE }};
+  struct server_t undernet_servers[] = {
+    { "eu.undernet.org", 6667, FALSE }};
+  gboolean network_checked[4];
+
+  mgr = empathy_irc_network_manager_new (GLOBAL_SAMPLE, NULL);
+
+  g_object_get (mgr,
+      "global-file", &global_file,
+      "user-file", &user_file,
+      NULL);
+  fail_if (global_file == NULL || strcmp (global_file, GLOBAL_SAMPLE) != 0);
+  fail_if (user_file != NULL);
+  g_free (global_file);
+  g_free (user_file);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 4);
+
+  network_checked[0] = network_checked[1] = network_checked[2] =
+    network_checked[3] = FALSE;
+  /* check networks and servers */
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      gchar *name;
+
+      g_object_get (l->data, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, "Freenode") == 0)
+        {
+          check_network (l->data, "Freenode", "UTF-8", freenode_servers, 2);
+          network_checked[0] = TRUE;
+        }
+      else if (strcmp (name, "GIMPNet") == 0)
+        {
+          check_network (l->data, "GIMPNet", "UTF-8", gimpnet_servers, 2);
+          network_checked[1] = TRUE;
+        }
+      else if (strcmp (name, "Test Server") == 0)
+        {
+          check_network (l->data, "Test Server", "ISO-8859-1", test_servers, 1);
+          network_checked[2] = TRUE;
+        }
+      else if (strcmp (name, "Undernet") == 0)
+        {
+          check_network (l->data, "Undernet", "UTF-8", undernet_servers, 1);
+          network_checked[3] = TRUE;
+        }
+      else
+        {
+          fail_if (TRUE);
+        }
+
+      g_free (name);
+    }
+  fail_if (!network_checked[0] || !network_checked[1] || !network_checked[2] ||
+      !network_checked[3]);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+}
+END_TEST
+
+static gboolean
+remove_network_named (EmpathyIrcNetworkManager *mgr,
+                      const gchar *network_name)
+{
+  GSList *networks, *l;
+  gboolean removed = FALSE;
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+
+  /* check networks and servers */
+  for (l = networks; l != NULL && !removed; l = g_slist_next (l))
+    {
+      EmpathyIrcNetwork *network = l->data;
+      gchar *name;
+
+      g_object_get (network, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, network_name) == 0)
+        {
+          empathy_irc_network_manager_remove (mgr, network);
+          removed = TRUE;
+        }
+
+      g_free (name);
+    }
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+
+  return removed;
+}
+
+START_TEST (test_empathy_irc_network_manager_remove)
+{
+  EmpathyIrcNetworkManager *mgr;
+  GSList *networks, *l;
+  struct server_t freenode_servers[] = {
+    { "irc.freenode.net", 6667, FALSE },
+    { "irc.eu.freenode.net", 6667, FALSE }};
+  struct server_t test_servers[] = {
+    { "irc.test.org", 6669, TRUE }};
+  struct server_t undernet_servers[] = {
+    { "eu.undernet.org", 6667, FALSE }};
+  gboolean network_checked[3];
+  gboolean result;
+
+  mgr = empathy_irc_network_manager_new (GLOBAL_SAMPLE, NULL);
+
+  result = remove_network_named (mgr, "GIMPNet");
+  fail_if (!result);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 3);
+
+  network_checked[0] = network_checked[1] = network_checked[2] = FALSE;
+  /* check networks and servers */
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      gchar *name;
+
+      g_object_get (l->data, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, "Freenode") == 0)
+        {
+          check_network (l->data, "Freenode", "UTF-8", freenode_servers, 2);
+          network_checked[0] = TRUE;
+        }
+      else if (strcmp (name, "Test Server") == 0)
+        {
+          check_network (l->data, "Test Server", "ISO-8859-1", test_servers, 1);
+          network_checked[1] = TRUE;
+        }
+      else if (strcmp (name, "Undernet") == 0)
+        {
+          check_network (l->data, "Undernet", "UTF-8", undernet_servers, 1);
+          network_checked[2] = TRUE;
+        }
+      else
+        {
+          fail_if (TRUE);
+        }
+
+      g_free (name);
+    }
+  fail_if (!network_checked[0] || !network_checked[1] || !network_checked[2]);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+}
+END_TEST
+
+static void
+copy_user_file (void)
+{
+  gboolean result;
+  gchar *buffer;
+  gsize length;
+
+  result = g_file_get_contents (USER_SAMPLE, &buffer, &length, NULL);
+  fail_if (!result);
+
+  result = g_file_set_contents (USER_FILE, buffer, length, NULL);
+  fail_if (!result);
+
+  g_free (buffer);
+}
+
+START_TEST (test_load_user_file)
+{
+  EmpathyIrcNetworkManager *mgr;
+  gchar *global_file, *user_file;
+  GSList *networks, *l;
+  struct server_t gimpnet_servers[] = {
+    { "irc.gimp.org", 6667, FALSE },
+    { "irc.us.gimp.org", 6667, FALSE },
+    { "irc.au.gimp.org", 6667, FALSE }};
+  struct server_t my_server[] = {
+    { "irc.mysrv.net", 7495, TRUE }};
+  struct server_t another_server[] = {
+    { "irc.anothersrv.be", 6660, FALSE }};
+  gboolean network_checked[3];
+
+  copy_user_file ();
+  mgr = empathy_irc_network_manager_new (NULL, USER_FILE);
+
+  g_object_get (mgr,
+      "global-file", &global_file,
+      "user-file", &user_file,
+      NULL);
+  fail_if (global_file != NULL);
+  fail_if (user_file == NULL || strcmp (user_file, USER_FILE) != 0);
+  g_free (global_file);
+  g_free (user_file);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 3);
+
+  network_checked[0] = network_checked[1] = network_checked[2] = FALSE;
+  /* check networks and servers */
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      gchar *name;
+
+      g_object_get (l->data, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, "GIMPNet") == 0)
+        {
+          check_network (l->data, "GIMPNet", "UTF-8", gimpnet_servers, 3);
+          network_checked[0] = TRUE;
+        }
+      else if (strcmp (name, "My Server") == 0)
+        {
+          check_network (l->data, "My Server", "UTF-8", my_server, 1);
+          network_checked[1] = TRUE;
+        }
+      else if (strcmp (name, "Another Server") == 0)
+        {
+          check_network (l->data, "Another Server", "UTF-8", another_server, 1);
+          network_checked[2] = TRUE;
+        }
+      else
+        {
+          fail_if (TRUE);
+        }
+
+      g_free (name);
+    }
+  fail_if (!network_checked[0] || !network_checked[1] || !network_checked[2]);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+}
+END_TEST
+
+START_TEST (test_load_both_files)
+{
+  EmpathyIrcNetworkManager *mgr;
+  gchar *global_file, *user_file;
+  GSList *networks, *l;
+  struct server_t freenode_servers[] = {
+    { "irc.freenode.net", 6667, FALSE },
+    { "irc.eu.freenode.net", 6667, FALSE }};
+  struct server_t gimpnet_servers[] = {
+    { "irc.gimp.org", 6667, FALSE },
+    { "irc.us.gimp.org", 6667, FALSE },
+    { "irc.au.gimp.org", 6667, FALSE }};
+  struct server_t my_server[] = {
+    { "irc.mysrv.net", 7495, TRUE }};
+  struct server_t another_server[] = {
+    { "irc.anothersrv.be", 6660, FALSE }};
+  struct server_t undernet_servers[] = {
+    { "eu.undernet.org", 6667, FALSE }};
+  gboolean network_checked[5];
+
+  mgr = empathy_irc_network_manager_new (GLOBAL_SAMPLE, USER_FILE);
+
+  g_object_get (mgr,
+      "global-file", &global_file,
+      "user-file", &user_file,
+      NULL);
+  fail_if (global_file == NULL || strcmp (global_file, GLOBAL_SAMPLE) != 0);
+  fail_if (user_file == NULL || strcmp (user_file, USER_FILE) != 0);
+  g_free (global_file);
+  g_free (user_file);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 5);
+
+  network_checked[0] = network_checked[1] = network_checked[2] =
+    network_checked[3] = network_checked[4] = FALSE;
+  /* check networks and servers */
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      gchar *name;
+
+      g_object_get (l->data, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, "Freenode") == 0)
+        {
+          check_network (l->data, "Freenode", "UTF-8", freenode_servers, 2);
+          network_checked[0] = TRUE;
+        }
+      else if (strcmp (name, "GIMPNet") == 0)
+        {
+          check_network (l->data, "GIMPNet", "UTF-8", gimpnet_servers, 3);
+          network_checked[1] = TRUE;
+        }
+      else if (strcmp (name, "My Server") == 0)
+        {
+          check_network (l->data, "My Server", "UTF-8", my_server, 1);
+          network_checked[2] = TRUE;
+        }
+      else if (strcmp (name, "Another Server") == 0)
+        {
+          check_network (l->data, "Another Server", "UTF-8", another_server, 1);
+          network_checked[3] = TRUE;
+        }
+      else if (strcmp (name, "Undernet") == 0)
+        {
+          check_network (l->data, "Undernet", "UTF-8", undernet_servers, 1);
+          network_checked[4] = TRUE;
+        }
+      else
+        {
+          fail_if (TRUE);
+        }
+
+      g_free (name);
+    }
+  fail_if (!network_checked[0] || !network_checked[1] || !network_checked[2] ||
+      !network_checked[3] || !network_checked[4]);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+}
+END_TEST
+
+START_TEST (test_modify_user_file)
+{
+  EmpathyIrcNetworkManager *mgr;
+  EmpathyIrcNetwork *network;
+  EmpathyIrcServer *server;
+  gchar *global_file, *user_file;
+  GSList *networks, *l;
+  struct server_t gimpnet_servers[] = {
+    { "irc.gimp.org", 6667, TRUE },
+    { "irc.us.gimp.org", 6668, FALSE }};
+  struct server_t great_server[] = {
+    { "irc.greatserver.com", 7873, TRUE }};
+  struct server_t another_server[] = {
+    { "irc.anothersrv.be", 6660, FALSE }};
+  gboolean network_modified[2];
+  gboolean network_checked[3];
+
+  copy_user_file ();
+  mgr = empathy_irc_network_manager_new (NULL, USER_FILE);
+
+  g_object_get (mgr,
+      "global-file", &global_file,
+      "user-file", &user_file,
+      NULL);
+  fail_if (global_file != NULL);
+  fail_if (user_file == NULL || strcmp (user_file, USER_FILE) != 0);
+  g_free (global_file);
+  g_free (user_file);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 3);
+
+  network_modified[0] = network_modified[1] = FALSE;
+  /* check networks and servers */
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      EmpathyIrcNetwork *network;
+      gchar *name;
+
+      network = l->data;
+      g_object_get (network, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, "GIMPNet") == 0)
+        {
+          GSList *servers, *ll;
+
+          /* change charset */
+          g_object_set (network, "charset", "ISO-8859-1", NULL);
+
+          servers = empathy_irc_network_get_servers (network);
+          for (ll = servers; ll != NULL; ll = g_slist_next (ll))
+            {
+              EmpathyIrcServer *server;
+              gchar *address;
+
+              server = ll->data;
+              g_object_get (server, "address", &address, NULL);
+              if (strcmp (address, "irc.gimp.org") == 0)
+                {
+                  /* change SSL */
+                  g_object_set (server, "ssl", TRUE, NULL);
+                }
+              else if (strcmp (address, "irc.us.gimp.org") == 0)
+                {
+                  /* change port */
+                  g_object_set (server, "port", 6668, NULL);
+                }
+              else if (strcmp (address, "irc.au.gimp.org") == 0)
+                {
+                  /* remove this server */
+                  empathy_irc_network_remove_server (network, server);
+                }
+              else
+                {
+                  fail_if (TRUE);
+                }
+
+              g_free (address);
+            }
+
+          network_modified[0] = TRUE;
+
+          g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+          g_slist_free (servers);
+        }
+      else if (strcmp (name, "My Server") == 0)
+        {
+          /* remove this network */
+          empathy_irc_network_manager_remove (mgr, network);
+          network_modified[1] = TRUE;
+        }
+      else if (strcmp (name, "Another Server") == 0)
+        {
+          /* Don't change this one */
+        }
+      else
+        {
+          fail_if (TRUE);
+        }
+
+      g_free (name);
+    }
+  fail_if (!network_modified[0] || !network_modified[1]);
+
+  /* Add a new network */
+  network = empathy_irc_network_new ("Great Server");
+  server = empathy_irc_server_new ("irc.greatserver.com", 7873, TRUE);
+  empathy_irc_network_append_server (network, server);
+  empathy_irc_network_manager_add (mgr, network);
+  g_object_unref (server);
+  g_object_unref (network);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+
+
+  /* Now let's reload the file and check its contain */
+  mgr = empathy_irc_network_manager_new (NULL, USER_FILE);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 3);
+
+  network_checked[0] = network_checked[1] = network_checked[2] = FALSE;
+  /* check networks and servers */
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      gchar *name;
+
+      g_object_get (l->data, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, "GIMPNet") == 0)
+        {
+          check_network (l->data, "GIMPNet", "ISO-8859-1", gimpnet_servers, 2);
+          network_checked[0] = TRUE;
+        }
+      else if (strcmp (name, "Great Server") == 0)
+        {
+          check_network (l->data, "Great Server", "UTF-8", great_server, 1);
+          network_checked[1] = TRUE;
+        }
+      else if (strcmp (name, "Another Server") == 0)
+        {
+          check_network (l->data, "Another Server", "UTF-8", another_server, 1);
+          network_checked[2] = TRUE;
+        }
+      else
+        {
+          fail_if (TRUE);
+        }
+
+      g_free (name);
+    }
+  fail_if (!network_checked[0] || !network_checked[1] || !network_checked[2]);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+}
+END_TEST
+
+START_TEST (test_modify_both_files)
+{
+  EmpathyIrcNetworkManager *mgr;
+  EmpathyIrcNetwork *network;
+  EmpathyIrcServer *server;
+  gchar *global_file, *user_file;
+  GSList *networks, *l;
+  struct server_t gimpnet_servers[] = {
+    { "irc.gimp.org", 6667, TRUE },
+    { "irc.us.gimp.org", 6668, FALSE }};
+  struct server_t great_server[] = {
+    { "irc.greatserver.com", 7873, TRUE }};
+  struct server_t another_server[] = {
+    { "irc.anothersrv.be", 6660, FALSE }};
+  struct server_t undernet_servers[] = {
+    { "eu.undernet.org", 6667, FALSE },
+    { "us.undernet.org", 6667, FALSE }};
+  gboolean network_modified[4];
+  gboolean network_checked[4];
+
+  copy_user_file ();
+  mgr = empathy_irc_network_manager_new (GLOBAL_SAMPLE, USER_FILE);
+
+  g_object_get (mgr,
+      "global-file", &global_file,
+      "user-file", &user_file,
+      NULL);
+  fail_if (global_file == NULL || strcmp (global_file, GLOBAL_SAMPLE) != 0);
+  fail_if (user_file == NULL || strcmp (user_file, USER_FILE) != 0);
+  g_free (global_file);
+  g_free (user_file);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 5);
+
+  network_modified[0] = network_modified[1] = network_modified[2] =
+    network_modified[3] = FALSE;
+  /* check networks and servers */
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      EmpathyIrcNetwork *network;
+      gchar *name;
+
+      network = l->data;
+      g_object_get (network, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, "GIMPNet") == 0)
+        {
+          /* Modify user network */
+          GSList *servers, *ll;
+
+          servers = empathy_irc_network_get_servers (network);
+          for (ll = servers; ll != NULL; ll = g_slist_next (ll))
+            {
+              EmpathyIrcServer *server;
+              gchar *address;
+
+              server = ll->data;
+              g_object_get (server, "address", &address, NULL);
+              if (strcmp (address, "irc.gimp.org") == 0)
+                {
+                  /* change SSL */
+                  g_object_set (server, "ssl", TRUE, NULL);
+                }
+              else if (strcmp (address, "irc.us.gimp.org") == 0)
+                {
+                  /* change port */
+                  g_object_set (server, "port", 6668, NULL);
+                }
+              else if (strcmp (address, "irc.au.gimp.org") == 0)
+                {
+                  /* remove this server */
+                  empathy_irc_network_remove_server (network, server);
+                }
+              else
+                {
+                  fail_if (TRUE);
+                }
+
+              g_free (address);
+            }
+
+          network_modified[0] = TRUE;
+
+          g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+          g_slist_free (servers);
+        }
+      else if (strcmp (name, "My Server") == 0)
+        {
+          /* remove user network */
+          empathy_irc_network_manager_remove (mgr, network);
+          network_modified[1] = TRUE;
+        }
+      else if (strcmp (name, "Freenode") == 0)
+        {
+          /* remove global network */
+          empathy_irc_network_manager_remove (mgr, network);
+          network_modified[2] = TRUE;
+        }
+      else if (strcmp (name, "Undernet") == 0)
+        {
+          /* modify global network */
+          EmpathyIrcServer *server;
+
+          server = empathy_irc_server_new ("us.undernet.org", 6667, FALSE);
+          empathy_irc_network_append_server (network, server);
+          g_object_unref (server);
+
+          network_modified[3] = TRUE;
+        }
+      else if (strcmp (name, "Another Server") == 0)
+        {
+          /* Don't change this one */
+        }
+      else
+        {
+          fail_if (TRUE);
+        }
+
+      g_free (name);
+    }
+  fail_if (!network_modified[0] || !network_modified[1] || !network_modified[2]
+      || !network_modified[3]);
+
+  /* Add a new network */
+  network = empathy_irc_network_new ("Great Server");
+  server = empathy_irc_server_new ("irc.greatserver.com", 7873, TRUE);
+  empathy_irc_network_append_server (network, server);
+  empathy_irc_network_manager_add (mgr, network);
+  g_object_unref (server);
+  g_object_unref (network);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+
+
+  /* Now let's reload the file and check its contain */
+  mgr = empathy_irc_network_manager_new (GLOBAL_SAMPLE, USER_FILE);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 4);
+
+  network_checked[0] = network_checked[1] = network_checked[2] =
+    network_checked[3] = FALSE;
+  /* check networks and servers */
+  for (l = networks; l != NULL; l = g_slist_next (l))
+    {
+      gchar *name;
+
+      g_object_get (l->data, "name", &name, NULL);
+      fail_if (name == NULL);
+
+      if (strcmp (name, "GIMPNet") == 0)
+        {
+          check_network (l->data, "GIMPNet", "UTF-8", gimpnet_servers, 2);
+          network_checked[0] = TRUE;
+        }
+      else if (strcmp (name, "Great Server") == 0)
+        {
+          check_network (l->data, "Great Server", "UTF-8", great_server, 1);
+          network_checked[1] = TRUE;
+        }
+      else if (strcmp (name, "Another Server") == 0)
+        {
+          check_network (l->data, "Another Server", "UTF-8", another_server, 1);
+          network_checked[2] = TRUE;
+        }
+      else if (strcmp (name, "Undernet") == 0)
+        {
+          check_network (l->data, "Undernet", "UTF-8", undernet_servers, 2);
+          network_checked[3] = TRUE;
+        }
+      else
+        {
+          fail_if (TRUE);
+        }
+
+      g_free (name);
+    }
+  fail_if (!network_checked[0] || !network_checked[1] || !network_checked[2] ||
+      !network_checked[3]);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+}
+END_TEST
+
+START_TEST (test_empathy_irc_network_manager_find_network_by_address)
+{
+  EmpathyIrcNetworkManager *mgr;
+  EmpathyIrcNetwork *network;
+  struct server_t freenode_servers[] = {
+    { "irc.freenode.net", 6667, FALSE },
+    { "irc.eu.freenode.net", 6667, FALSE }};
+
+  mgr = empathy_irc_network_manager_new (GLOBAL_SAMPLE, NULL);
+
+  network = empathy_irc_network_manager_find_network_by_address (mgr,
+      "irc.freenode.net");
+  fail_if (network == NULL);
+  check_network (network, "Freenode", "UTF-8", freenode_servers, 2);
+
+  network = empathy_irc_network_manager_find_network_by_address (mgr,
+      "irc.eu.freenode.net");
+  fail_if (network == NULL);
+  check_network (network, "Freenode", "UTF-8", freenode_servers, 2);
+
+  network = empathy_irc_network_manager_find_network_by_address (mgr,
+      "unknown");
+  fail_if (network != NULL);
+
+  g_object_unref (mgr);
+}
+END_TEST
+
+START_TEST (test_no_modify_with_empty_user_file)
+{
+  EmpathyIrcNetworkManager *mgr;
+  GSList *networks;
+
+  /* user don't have a networks file yet */
+  g_unlink (USER_FILE);
+
+  mgr = empathy_irc_network_manager_new (GLOBAL_SAMPLE, USER_FILE);
+  g_object_unref (mgr);
+
+  /* We didn't modify anything so USER_FILE should be empty */
+  mgr = empathy_irc_network_manager_new (NULL, USER_FILE);
+
+  networks = empathy_irc_network_manager_get_networks (mgr);
+  fail_if (g_slist_length (networks) != 0);
+
+  g_slist_foreach (networks, (GFunc) g_object_unref, NULL);
+  g_slist_free (networks);
+  g_object_unref (mgr);
+}
+END_TEST
+
+TCase *
+make_empathy_irc_network_manager_tcase (void)
+{
+    TCase *tc = tcase_create ("empathy-irc-network-manager");
+    tcase_add_test (tc, test_empathy_irc_network_manager_add);
+    tcase_add_test (tc, test_load_global_file);
+    tcase_add_test (tc, test_empathy_irc_network_manager_remove);
+    tcase_add_test (tc, test_load_user_file);
+    tcase_add_test (tc, test_load_both_files);
+    tcase_add_test (tc, test_modify_user_file);
+    tcase_add_test (tc, test_modify_both_files);
+    tcase_add_test (tc, test_empathy_irc_network_manager_find_network_by_address);
+    tcase_add_test (tc, test_no_modify_with_empty_user_file);
+    return tc;
+}
diff --git a/tests/check-empathy-irc-network.c b/tests/check-empathy-irc-network.c
new file mode 100644 (file)
index 0000000..b8124a3
--- /dev/null
@@ -0,0 +1,240 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <check.h>
+#include "check-helpers.h"
+#include "check-libempathy.h"
+#include "check-irc-helper.h"
+
+#include <libempathy/empathy-irc-network.h>
+
+START_TEST (test_empathy_irc_network_new)
+{
+  EmpathyIrcNetwork *network;
+
+  network = empathy_irc_network_new ("Network1");
+  check_network (network, "Network1", "UTF-8", NULL, 0);
+
+  g_object_unref (network);
+}
+END_TEST
+
+START_TEST (test_property_change)
+{
+  EmpathyIrcNetwork *network;
+
+  network = empathy_irc_network_new ("Network1");
+  check_network (network, "Network1", "UTF-8", NULL, 0);
+
+  g_object_set (network,
+      "name", "Network2",
+      "charset", "ISO-8859-1",
+      NULL);
+
+  check_network (network, "Network2", "ISO-8859-1", NULL, 0);
+
+  g_object_unref (network);
+
+}
+END_TEST
+
+static gboolean modified;
+
+static void
+modified_cb (EmpathyIrcNetwork *network,
+             gpointer unused)
+{
+  modified = TRUE;
+}
+
+START_TEST (test_modified_signal)
+{
+  EmpathyIrcNetwork *network;
+
+  network = empathy_irc_network_new ("Network1");
+  check_network (network, "Network1", "UTF-8", NULL, 0);
+
+  modified = FALSE;
+  g_signal_connect (network, "modified", G_CALLBACK (modified_cb), NULL);
+
+  g_object_set (network, "name", "Network2", NULL);
+  fail_if (!modified);
+  modified = FALSE;
+  g_object_set (network, "name", "Network2", NULL);
+  fail_if (modified);
+
+  g_object_unref (network);
+}
+END_TEST
+
+static void
+add_servers (EmpathyIrcNetwork *network,
+             struct server_t *servers,
+             guint nb_servers)
+{
+  guint i;
+
+  for (i = 0; i < nb_servers; i ++)
+    {
+      EmpathyIrcServer *server;
+
+      server = empathy_irc_server_new (servers[i].address,
+          servers[i].port, servers[i].ssl);
+      modified = FALSE;
+      empathy_irc_network_append_server (network, server);
+      fail_if (!modified);
+      g_object_unref (server);
+    }
+}
+
+START_TEST (test_add_server)
+{
+  EmpathyIrcNetwork *network;
+  EmpathyIrcServer *server;
+  GSList *servers, *l;
+  struct server_t test_servers[] = {
+    { "server1", 6667, FALSE },
+    { "server2", 6668, TRUE },
+    { "server3", 6667, FALSE },
+    { "server4", 6669, TRUE }};
+  struct server_t servers_without_3[] = {
+    { "server1", 6667, FALSE },
+    { "server2", 6668, TRUE },
+    { "server4", 6669, TRUE }};
+
+  network = empathy_irc_network_new ("Network1");
+  check_network (network, "Network1", "UTF-8", NULL, 0);
+
+  modified = FALSE;
+  g_signal_connect (network, "modified", G_CALLBACK (modified_cb), NULL);
+
+  check_network (network, "Network1", "UTF-8", NULL, 0);
+
+  /* add the servers */
+  add_servers (network, test_servers, 4);
+
+  check_network (network, "Network1", "UTF-8", test_servers, 4);
+
+  /* Now let's remove the 3rd server */
+  servers = empathy_irc_network_get_servers (network);
+  l = g_slist_nth (servers, 2);
+  fail_if (l == NULL);
+  server = l->data;
+  modified = FALSE;
+  empathy_irc_network_remove_server (network, server);
+  fail_if (!modified);
+
+  /* free the list */
+  g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+  g_slist_free (servers);
+
+  /* The 3rd server should have disappear */
+  check_network (network, "Network1", "UTF-8", servers_without_3, 3);
+
+  g_object_unref (network);
+}
+END_TEST
+
+START_TEST (test_modified_signal_because_of_server)
+{
+  EmpathyIrcNetwork *network;
+  EmpathyIrcServer *server;
+
+  network = empathy_irc_network_new ("Network1");
+  check_network (network, "Network1", "UTF-8", NULL, 0);
+
+  g_signal_connect (network, "modified", G_CALLBACK (modified_cb), NULL);
+
+  server = empathy_irc_server_new ("server1", 6667, FALSE);
+  empathy_irc_network_append_server (network, server);
+
+  /* Change server properties */
+  modified = FALSE;
+  g_object_set (server, "address", "server2", NULL);
+  fail_if (!modified);
+  modified = FALSE;
+  g_object_set (server, "port", 6668, NULL);
+  fail_if (!modified);
+  modified = FALSE;
+  g_object_set (server, "ssl", TRUE, NULL);
+  fail_if (!modified);
+
+  empathy_irc_network_remove_server (network, server);
+  modified = FALSE;
+  g_object_set (server, "address", "server3", NULL);
+  /* We removed the server so the network is not modified anymore */
+  fail_if (modified);
+
+  g_object_unref (network);
+}
+END_TEST
+
+START_TEST (test_empathy_irc_network_set_server_position)
+{
+  EmpathyIrcNetwork *network;
+  GSList *servers, *l;
+  struct server_t test_servers[] = {
+    { "server1", 6667, FALSE },
+    { "server2", 6668, TRUE },
+    { "server3", 6667, FALSE },
+    { "server4", 6669, TRUE }};
+  struct server_t test_servers_sorted[] = {
+    { "server2", 6668, TRUE },
+    { "server4", 6669, TRUE },
+    { "server3", 6667, FALSE },
+    { "server1", 6667, FALSE }};
+
+  network = empathy_irc_network_new ("Network1");
+  check_network (network, "Network1", "UTF-8", NULL, 0);
+
+  modified = FALSE;
+  g_signal_connect (network, "modified", G_CALLBACK (modified_cb), NULL);
+
+  /* add the servers */
+  add_servers (network, test_servers, 4);
+  check_network (network, "Network1", "UTF-8", test_servers, 4);
+
+  /* get servers list */
+  servers = empathy_irc_network_get_servers (network);
+  fail_if (g_slist_length (servers) != 4);
+  modified = FALSE;
+
+  /* server1 go to the last position */
+  empathy_irc_network_set_server_position (network, servers->data, -1);
+
+  /* server2 go to the first position */
+  l = servers->next;
+  empathy_irc_network_set_server_position (network, l->data, 0);
+
+  /* server3 go to the third position */
+  l = l->next;
+  empathy_irc_network_set_server_position (network, l->data, 2);
+
+  /* server4 go to the second position*/
+  l = l->next;
+  empathy_irc_network_set_server_position (network, l->data, 1);
+
+  fail_if (!modified);
+
+  /* free the list */
+  g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+  g_slist_free (servers);
+
+  /* Check if servers are sorted */
+  check_network (network, "Network1", "UTF-8", test_servers_sorted, 4);
+}
+END_TEST
+
+TCase *
+make_empathy_irc_network_tcase (void)
+{
+    TCase *tc = tcase_create ("empathy-irc-network");
+    tcase_add_test (tc, test_empathy_irc_network_new);
+    tcase_add_test (tc, test_property_change);
+    tcase_add_test (tc, test_modified_signal);
+    tcase_add_test (tc, test_add_server);
+    tcase_add_test (tc, test_modified_signal_because_of_server);
+    tcase_add_test (tc, test_empathy_irc_network_set_server_position);
+    return tc;
+}
diff --git a/tests/check-empathy-irc-server.c b/tests/check-empathy-irc-server.c
new file mode 100644 (file)
index 0000000..52607f2
--- /dev/null
@@ -0,0 +1,93 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <check.h>
+#include "check-helpers.h"
+#include "check-libempathy.h"
+#include "check-irc-helper.h"
+
+#include <libempathy/empathy-irc-server.h>
+
+START_TEST (test_empathy_irc_server_new)
+{
+  EmpathyIrcServer *server;
+
+  server = empathy_irc_server_new ("test.localhost", 6667, TRUE);
+  check_server (server, "test.localhost", 6667, TRUE);
+
+  g_object_unref (server);
+}
+END_TEST
+
+START_TEST (test_property_change)
+{
+  EmpathyIrcServer *server;
+
+  server = empathy_irc_server_new ("test.localhost", 6667, TRUE);
+  fail_if (server == NULL);
+
+  g_object_set (server,
+      "address", "test2.localhost",
+      "port", 6668,
+      "ssl", FALSE,
+      NULL);
+
+  check_server (server, "test2.localhost", 6668, FALSE);
+
+  g_object_unref (server);
+}
+END_TEST
+
+static gboolean modified = FALSE;
+
+static void
+modified_cb (EmpathyIrcServer *server,
+             gpointer unused)
+{
+  modified = TRUE;
+}
+
+START_TEST (test_modified_signal)
+{
+  EmpathyIrcServer *server;
+
+  server = empathy_irc_server_new ("test.localhost", 6667, TRUE);
+  fail_if (server == NULL);
+
+  g_signal_connect (server, "modified", G_CALLBACK (modified_cb), NULL);
+
+  /* address */
+  g_object_set (server, "address", "test2.localhost", NULL);
+  fail_if (!modified);
+  modified = FALSE;
+  g_object_set (server, "address", "test2.localhost", NULL);
+  fail_if (modified);
+
+  /* port */
+  g_object_set (server, "port", 6668, NULL);
+  fail_if (!modified);
+  modified = FALSE;
+  g_object_set (server, "port", 6668, NULL);
+  fail_if (modified);
+
+  /* ssl */
+  g_object_set (server, "ssl", FALSE, NULL);
+  fail_if (!modified);
+  modified = FALSE;
+  g_object_set (server, "ssl", FALSE, NULL);
+  fail_if (modified);
+
+  g_object_unref (server);
+}
+END_TEST
+
+TCase *
+make_empathy_irc_server_tcase (void)
+{
+    TCase *tc = tcase_create ("empathy-irc-server");
+    tcase_add_test (tc, test_empathy_irc_server_new);
+    tcase_add_test (tc, test_property_change);
+    tcase_add_test (tc, test_modified_signal);
+    return tc;
+}
diff --git a/tests/check-irc-helper.c b/tests/check-irc-helper.c
new file mode 100644 (file)
index 0000000..477b134
--- /dev/null
@@ -0,0 +1,80 @@
+#include "check-irc-helper.h"
+
+void
+check_server (EmpathyIrcServer *server,
+              const gchar *_address,
+              guint _port,
+              gboolean _ssl)
+{
+  gchar *address;
+  guint port;
+  gboolean ssl;
+
+  fail_if (server == NULL);
+
+  g_object_get (server,
+      "address", &address,
+      "port", &port,
+      "ssl", &ssl,
+      NULL);
+
+  fail_if (address == NULL || strcmp (address, _address) != 0);
+  fail_if (port != _port);
+  fail_if (ssl != _ssl);
+
+  g_free (address);
+}
+
+void
+check_network (EmpathyIrcNetwork *network,
+              const gchar *_name,
+              const gchar *_charset,
+              struct server_t *_servers,
+              guint nb_servers)
+{
+  gchar  *name, *charset;
+  GSList *servers, *l;
+  guint i;
+
+  fail_if (network == NULL);
+
+  g_object_get (network,
+      "name", &name,
+      "charset", &charset,
+      NULL);
+
+  fail_if (name == NULL || strcmp (name, _name) != 0);
+  fail_if (charset == NULL || strcmp (charset, _charset) != 0);
+
+  servers = empathy_irc_network_get_servers (network);
+  fail_if (g_slist_length (servers) != nb_servers);
+
+  /* Is that the right servers ? */
+  for (l = servers, i = 0; l != NULL; l = g_slist_next (l), i++)
+    {
+      EmpathyIrcServer *server;
+      gchar *address;
+      guint port;
+      gboolean ssl;
+
+      server = l->data;
+
+      g_object_get (server,
+          "address", &address,
+          "port", &port,
+          "ssl", &ssl,
+          NULL);
+
+      fail_if (address == NULL || strcmp (address, _servers[i].address)
+          != 0);
+      fail_if (port != _servers[i].port);
+      fail_if (ssl != _servers[i].ssl);
+
+      g_free (address);
+    }
+
+  g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
+  g_slist_free (servers);
+  g_free (name);
+  g_free (charset);
+}
diff --git a/tests/check-irc-helper.h b/tests/check-irc-helper.h
new file mode 100644 (file)
index 0000000..32a34b6
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <check.h>
+#include "check-helpers.h"
+
+#include <libempathy/empathy-irc-server.h>
+#include <libempathy/empathy-irc-network.h>
+#include <libempathy/empathy-irc-network-manager.h>
+
+#ifndef __CHECK_IRC_HELPER_H__
+#define __CHECK_IRC_HELPER_H__
+
+struct server_t
+{
+  gchar *address;
+  guint port;
+  gboolean ssl;
+};
+
+void check_server (EmpathyIrcServer *server, const gchar *_address,
+    guint _port, gboolean _ssl);
+
+void check_network (EmpathyIrcNetwork *network, const gchar *_name,
+    const gchar *_charset, struct server_t *_servers, guint nb_servers);
+
+#endif /* __CHECK_IRC_HELPER_H__ */
index 1f330258397b71216412ec97800a2796f2e249fd..0f9388dcff4e2b261768ebf4bbd67abde7beb1ca 100644 (file)
@@ -2,5 +2,8 @@
 #define __CHECK_LIBEMPATHY__
 
 TCase * make_empathy_utils_tcase (void);
 #define __CHECK_LIBEMPATHY__
 
 TCase * make_empathy_utils_tcase (void);
+TCase * make_empathy_irc_server_tcase (void);
+TCase * make_empathy_irc_network_tcase (void);
+TCase * make_empathy_irc_network_manager_tcase (void);
 
 #endif /* #ifndef __CHECK_LIBEMPATHY__ */
 
 #endif /* #ifndef __CHECK_LIBEMPATHY__ */
index 6dcfe3237ef1be4d785b6d88f0afebd87b9b3199..f0e366d0394abc5399c72b90c0981e2bcdfeb306 100644 (file)
@@ -16,6 +16,9 @@ make_libempathy_suite (void)
     Suite *s = suite_create ("libempathy");
 
     suite_add_tcase (s, make_empathy_utils_tcase ());
     Suite *s = suite_create ("libempathy");
 
     suite_add_tcase (s, make_empathy_utils_tcase ());
+    suite_add_tcase (s, make_empathy_irc_server_tcase ());
+    suite_add_tcase (s, make_empathy_irc_network_tcase ());
+    suite_add_tcase (s, make_empathy_irc_network_manager_tcase ());
 
     return s;
 }
 
     return s;
 }
diff --git a/tests/xml/.gitignore b/tests/xml/.gitignore
new file mode 100644 (file)
index 0000000..01af91d
--- /dev/null
@@ -0,0 +1 @@
+user-irc-networks.xml
diff --git a/tests/xml/default-irc-networks-sample.xml b/tests/xml/default-irc-networks-sample.xml
new file mode 100644 (file)
index 0000000..257919c
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<networks>
+  <network id="freenode" name="Freenode">
+    <servers>
+      <server address="irc.freenode.net" port="6667" ssl="FALSE" />
+      <server address="irc.eu.freenode.net" port="6667" ssl="FALSE" />
+    </servers>
+  </network>
+
+  <network id="gimpnet" name="GIMPNet">
+    <servers>
+      <server address="irc.gimp.org" port="6667" ssl="FALSE" />
+      <server address="irc.us.gimp.org" port="6667" ssl="FALSE" />
+    </servers>
+  </network>
+
+  <network id="testsrv" name="Test Server" network_charset="ISO-8859-1">
+    <servers>
+      <server address="irc.test.org" port="6669" ssl="TRUE" />
+    </servers>
+  </network>
+
+  <network id="undernet" name="Undernet">
+    <servers>
+      <server address="eu.undernet.org" port="6667" ssl="FALSE" />
+    </servers>
+  </network>
+
+</networks>
diff --git a/tests/xml/user-irc-networks-sample.xml b/tests/xml/user-irc-networks-sample.xml
new file mode 100644 (file)
index 0000000..9e4f086
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<networks>
+  <network id="gimpnet" name="GIMPNet">
+    <servers>
+      <server address="irc.gimp.org" port="6667" ssl="FALSE" />
+      <server address="irc.us.gimp.org" port="6667" ssl="FALSE" />
+      <server address="irc.au.gimp.org" port="6667" ssl="FALSE" />
+    </servers>
+  </network>
+
+  <network id="testsrv" name="Test Server" dropped="1"/>
+
+  <network id="mysrv" name="My Server">
+    <servers>
+      <server address="irc.mysrv.net" port="7495" ssl="TRUE" />
+    </servers>
+  </network>
+
+  <network id="anothersrv" name="Another Server">
+    <servers>
+      <server address="irc.anothersrv.be" port="6660" ssl="FALSE" />
+    </servers>
+  </network>
+
+</networks>