/* * Copyright (C) 2007-2008 Guillaume Desmottes * Copyright (C) 2010 Collabora Ltd. * * 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 */ #include "config.h" #include "tpaw-irc-network-chooser.h" #include "tpaw-irc-network-chooser-dialog.h" #include "tpaw-irc-network-manager.h" #include "tpaw-utils.h" #define DEBUG_FLAG TPAW_DEBUG_ACCOUNT | TPAW_DEBUG_IRC #include "tpaw-debug.h" #define DEFAULT_IRC_NETWORK "irc.gimp.org" #define DEFAULT_IRC_PORT 6667 #define DEFAULT_IRC_SSL FALSE enum { PROP_SETTINGS = 1 }; enum { SIG_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; struct _TpawIrcNetworkChooserPriv { TpawAccountSettings *settings; TpawIrcNetworkManager *network_manager; GtkWidget *dialog; /* Displayed network */ TpawIrcNetwork *network; }; G_DEFINE_TYPE (TpawIrcNetworkChooser, tpaw_irc_network_chooser, GTK_TYPE_BUTTON); static void tpaw_irc_network_chooser_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { TpawIrcNetworkChooser *self = TPAW_IRC_NETWORK_CHOOSER (object); switch (prop_id) { case PROP_SETTINGS: self->priv->settings = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void tpaw_irc_network_chooser_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { TpawIrcNetworkChooser *self = TPAW_IRC_NETWORK_CHOOSER (object); switch (prop_id) { case PROP_SETTINGS: g_value_set_object (value, self->priv->settings); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void unset_server_params (TpawIrcNetworkChooser *self) { DEBUG ("Unset server, port and use-ssl"); tpaw_account_settings_unset (self->priv->settings, "server"); tpaw_account_settings_unset (self->priv->settings, "port"); tpaw_account_settings_unset (self->priv->settings, "use-ssl"); } static gchar * dup_network_service (TpawIrcNetwork *network) { /* Account.Service has to be a lower case alphanumeric string which may * also contain '-' but not start with it. */ #define VALID G_CSET_a_2_z G_CSET_DIGITS "-" gchar *service, *tmp; service = g_strdup (tpaw_irc_network_get_name (network)); service = g_strstrip (service); if (tp_str_empty (service)) { g_free (service); return NULL; } tmp = service; service = g_ascii_strdown (service, -1); g_free (tmp); service = g_strcanon (service, VALID, '-'); if (service[0] == '-') { tmp = service; service = g_strdup (service + 1); g_free (tmp); } return service; } static void update_server_params (TpawIrcNetworkChooser *self) { GSList *servers; const gchar *charset; g_assert (self->priv->network != NULL); charset = tpaw_irc_network_get_charset (self->priv->network); DEBUG ("Setting charset to %s", charset); tpaw_account_settings_set (self->priv->settings, "charset", g_variant_new_string (charset)); servers = tpaw_irc_network_get_servers (self->priv->network); if (g_slist_length (servers) > 0) { /* set the first server as CM server */ TpawIrcServer *server = servers->data; gchar *address; guint port; gboolean ssl; gchar *service; g_object_get (server, "address", &address, "port", &port, "ssl", &ssl, NULL); DEBUG ("Setting server to %s", address); tpaw_account_settings_set (self->priv->settings, "server", g_variant_new_string (address)); DEBUG ("Setting port to %u", port); tpaw_account_settings_set (self->priv->settings, "port", g_variant_new_uint32 (port)); DEBUG ("Setting use-ssl to %s", ssl ? "TRUE": "FALSE" ); tpaw_account_settings_set (self->priv->settings, "use-ssl", g_variant_new_boolean (ssl)); /* Set Account.Service */ service = dup_network_service (self->priv->network); DEBUG ("Setting Service to %s", service); tpaw_account_settings_set_service (self->priv->settings, service); g_free (address); g_free (service); } else { /* No server. Unset values */ unset_server_params (self); } g_slist_foreach (servers, (GFunc) g_object_unref, NULL); g_slist_free (servers); } static void set_label (TpawIrcNetworkChooser *self) { g_assert (self->priv->network != NULL); gtk_button_set_label (GTK_BUTTON (self), tpaw_irc_network_get_name (self->priv->network)); } static void set_label_from_settings (TpawIrcNetworkChooser *self) { gchar *server; tp_clear_object (&self->priv->network); server = tpaw_account_settings_dup_string (self->priv->settings, "server"); if (server != NULL) { TpawIrcServer *srv; gint port; gboolean ssl; self->priv->network = tpaw_irc_network_manager_find_network_by_address ( self->priv->network_manager, server); if (self->priv->network != NULL) { /* The network is known */ g_object_ref (self->priv->network); set_label (self); return; } /* We don't have this network. Let's create it */ port = tpaw_account_settings_get_uint32 (self->priv->settings, "port"); ssl = tpaw_account_settings_get_boolean (self->priv->settings, "use-ssl"); DEBUG ("Create a network %s", server); self->priv->network = tpaw_irc_network_new (server); srv = tpaw_irc_server_new (server, port, ssl); tpaw_irc_network_append_server (self->priv->network, srv); tpaw_irc_network_manager_add (self->priv->network_manager, self->priv->network); set_label (self); g_object_unref (srv); g_free (server); return; } /* Set default network */ self->priv->network = tpaw_irc_network_manager_find_network_by_address ( self->priv->network_manager, DEFAULT_IRC_NETWORK); if (self->priv->network == NULL) { /* Default network is not known, recreate it */ TpawIrcServer *srv; self->priv->network = tpaw_irc_network_new (DEFAULT_IRC_NETWORK); srv = tpaw_irc_server_new (DEFAULT_IRC_NETWORK, DEFAULT_IRC_PORT, DEFAULT_IRC_SSL); tpaw_irc_network_append_server (self->priv->network, srv); tpaw_irc_network_manager_add (self->priv->network_manager, self->priv->network); g_object_unref (srv); } set_label (self); update_server_params (self); g_object_ref (self->priv->network); } static void dialog_response_cb (GtkDialog *dialog, gint response, TpawIrcNetworkChooser *self) { TpawIrcNetworkChooserDialog *chooser = TPAW_IRC_NETWORK_CHOOSER_DIALOG (self->priv->dialog); if (response != GTK_RESPONSE_CLOSE && response != GTK_RESPONSE_DELETE_EVENT) return; if (tpaw_irc_network_chooser_dialog_get_changed (chooser)) { tp_clear_object (&self->priv->network); self->priv->network = g_object_ref ( tpaw_irc_network_chooser_dialog_get_network (chooser)); update_server_params (self); set_label (self); g_signal_emit (self, signals[SIG_CHANGED], 0); } gtk_widget_destroy (self->priv->dialog); self->priv->dialog = NULL; } static void clicked_cb (GtkButton *button, gpointer user_data) { TpawIrcNetworkChooser *self = TPAW_IRC_NETWORK_CHOOSER (button); GtkWindow *window; if (self->priv->dialog != NULL) goto out; window = tpaw_get_toplevel_window (GTK_WIDGET (button)); self->priv->dialog = tpaw_irc_network_chooser_dialog_new ( self->priv->settings, self->priv->network, window); gtk_widget_show_all (self->priv->dialog); tp_g_signal_connect_object (self->priv->dialog, "response", G_CALLBACK (dialog_response_cb), button, 0); out: tpaw_window_present (GTK_WINDOW (self->priv->dialog)); } static void tpaw_irc_network_chooser_constructed (GObject *object) { TpawIrcNetworkChooser *self = (TpawIrcNetworkChooser *) object; G_OBJECT_CLASS (tpaw_irc_network_chooser_parent_class)->constructed (object); g_assert (self->priv->settings != NULL); set_label_from_settings (self); g_signal_connect (self, "clicked", G_CALLBACK (clicked_cb), self); } static void tpaw_irc_network_chooser_dispose (GObject *object) { TpawIrcNetworkChooser *self = (TpawIrcNetworkChooser *) object; tp_clear_object (&self->priv->settings); tp_clear_object (&self->priv->network_manager); tp_clear_object (&self->priv->network); if (G_OBJECT_CLASS (tpaw_irc_network_chooser_parent_class)->dispose) G_OBJECT_CLASS (tpaw_irc_network_chooser_parent_class)->dispose (object); } static void tpaw_irc_network_chooser_class_init (TpawIrcNetworkChooserClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->get_property = tpaw_irc_network_chooser_get_property; object_class->set_property = tpaw_irc_network_chooser_set_property; object_class->constructed = tpaw_irc_network_chooser_constructed; object_class->dispose = tpaw_irc_network_chooser_dispose; g_object_class_install_property (object_class, PROP_SETTINGS, g_param_spec_object ("settings", "Settings", "The TpawAccountSettings to show and edit", TPAW_TYPE_ACCOUNT_SETTINGS, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); signals[SIG_CHANGED] = g_signal_new ("changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0); g_type_class_add_private (object_class, sizeof (TpawIrcNetworkChooserPriv)); } static void tpaw_irc_network_chooser_init (TpawIrcNetworkChooser *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TPAW_TYPE_IRC_NETWORK_CHOOSER, TpawIrcNetworkChooserPriv); self->priv->network_manager = tpaw_irc_network_manager_dup_default (); } GtkWidget * tpaw_irc_network_chooser_new (TpawAccountSettings *settings) { return g_object_new (TPAW_TYPE_IRC_NETWORK_CHOOSER, "settings", settings, NULL); } TpawIrcNetwork * tpaw_irc_network_chooser_get_network (TpawIrcNetworkChooser *self) { return self->priv->network; }