/*
* 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-lib.h>
#include <gtk/gtk.h>
#include <libempathy/empathy-utils.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_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC
#include <libempathy/empathy-debug.h>
#define IRC_NETWORKS_FILENAME "irc-networks.xml"
typedef struct {
EmpathyAccountSettings *settings;
EmpathyIrcNetworkManager *network_manager;
GtkWidget *vbox_settings;
GtkWidget *combobox_network;
} 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->settings);
g_slice_free (EmpathyAccountWidgetIrc, settings);
}
static void
unset_server_params (EmpathyAccountWidgetIrc *settings)
{
DEBUG ("Unset server, port and use-ssl");
empathy_account_settings_unset (settings->settings, "server");
empathy_account_settings_unset (settings->settings, "port");
empathy_account_settings_unset (settings->settings, "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);
DEBUG ("Setting charset to %s", charset);
empathy_account_settings_set_string (settings->settings, "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);
DEBUG ("Setting server to %s", address);
empathy_account_settings_set_string (settings->settings,
"server", address);
DEBUG ("Setting port to %u", port);
empathy_account_settings_set_uint32 (settings->settings, "port", port);
DEBUG ("Setting use-ssl to %s", ssl ? "TRUE": "FALSE" );
empathy_account_settings_set_boolean (settings->settings,
"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);
DEBUG ("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)
{
const gchar *nick = NULL;
const gchar *fullname = NULL;
const gchar *server = NULL;
gint port = 6667;
const gchar *charset;
gboolean ssl = FALSE;
EmpathyIrcNetwork *network = NULL;
nick = empathy_account_settings_get_string (settings->settings, "account");
fullname = empathy_account_settings_get_string (settings->settings,
"fullname");
server = empathy_account_settings_get_string (settings->settings, "server");
charset = empathy_account_settings_get_string (settings->settings, "charset");
port = empathy_account_settings_get_uint32 (settings->settings, "port");
ssl = empathy_account_settings_get_boolean (settings->settings, "use-ssl");
if (!nick)
{
nick = g_strdup (g_get_user_name ());
empathy_account_settings_set_string (settings->settings,
"account", nick);
}
if (!fullname)
{
fullname = g_strdup (g_get_real_name ());
if (!fullname)
{
fullname = g_strdup (nick);
}
empathy_account_settings_set_string (settings->settings,
"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);
DEBUG ("Account use network %s", name);
g_free (name);
}
else
{
/* We don't have this network. Let's create it */
EmpathyIrcServer *srv;
GtkTreeIter iter;
DEBUG ("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);
}
/**
* empathy_account_widget_irc_new:
* @settings: the #EmpathyAccountSettings to configure
*
* Creates a new IRC account widget to configure a given #EmpathyAccount
*
* Returns: The toplevel container of the configuration widget
*/
GtkWidget *
empathy_account_widget_irc_new (EmpathyAccountSettings *account_settings)
{
EmpathyAccountWidgetIrc *settings;
gchar *dir, *user_file_with_path, *global_file_with_path;
GtkBuilder *gui;
GtkWidget *widget;
GtkListStore *store;
GtkCellRenderer *renderer;
gchar *filename;
settings = g_slice_new0 (EmpathyAccountWidgetIrc);
settings->settings = g_object_ref (account_settings);
dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL);
g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
user_file_with_path = g_build_filename (dir, IRC_NETWORKS_FILENAME, NULL);
g_free (dir);
global_file_with_path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"),
"libempathy-gtk", 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);
filename = empathy_file_lookup ("empathy-account-widget-irc.ui",
"libempathy-gtk");
gui = empathy_builder_get_file (filename,
"vbox_irc", &widget,
"table_irc_settings", &settings->vbox_settings,
"combobox_network", &settings->combobox_network,
NULL);
g_free (filename);
/* 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_settings, gui,
"entry_nick", "account",
"entry_fullname", "fullname",
"entry_password", "password",
"entry_quit_message", "quit-message",
NULL);
empathy_builder_connect (gui, settings,
"table_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_network", "clicked",
account_widget_irc_button_remove_clicked_cb,
"combobox_network", "changed",
account_widget_irc_combobox_network_changed_cb,
NULL);
empathy_account_widget_set_default_focus (gui, "entry_nick");
empathy_account_widget_add_apply_button (account_settings, widget);
return empathy_builder_unref_and_keep_widget (gui, widget);
}