diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2010-08-26 20:03:11 +0800 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2010-08-26 20:03:11 +0800 |
commit | 2de3bc4c03f97f1ceea44f43a1b86dedcb7e6893 (patch) | |
tree | 1e10eda9d904d4d29664f79193b4b6f70823c5a8 | |
parent | f7a63b4c249208122cfa17f668a19d853d158dfa (diff) | |
parent | e62460125c8a90e0f77f18326d597868ca01a42c (diff) | |
download | gsoc2013-empathy-2de3bc4c03f97f1ceea44f43a1b86dedcb7e6893.tar gsoc2013-empathy-2de3bc4c03f97f1ceea44f43a1b86dedcb7e6893.tar.gz gsoc2013-empathy-2de3bc4c03f97f1ceea44f43a1b86dedcb7e6893.tar.bz2 gsoc2013-empathy-2de3bc4c03f97f1ceea44f43a1b86dedcb7e6893.tar.lz gsoc2013-empathy-2de3bc4c03f97f1ceea44f43a1b86dedcb7e6893.tar.xz gsoc2013-empathy-2de3bc4c03f97f1ceea44f43a1b86dedcb7e6893.tar.zst gsoc2013-empathy-2de3bc4c03f97f1ceea44f43a1b86dedcb7e6893.zip |
Merge branch 'irc-widget-588243'
-rw-r--r-- | libempathy-gtk/Makefile.am | 4 | ||||
-rw-r--r-- | libempathy-gtk/empathy-account-widget-irc.c | 403 | ||||
-rw-r--r-- | libempathy-gtk/empathy-account-widget-irc.ui | 78 | ||||
-rw-r--r-- | libempathy-gtk/empathy-irc-network-chooser-dialog.c | 629 | ||||
-rw-r--r-- | libempathy-gtk/empathy-irc-network-chooser-dialog.h | 71 | ||||
-rw-r--r-- | libempathy-gtk/empathy-irc-network-chooser.c | 360 | ||||
-rw-r--r-- | libempathy-gtk/empathy-irc-network-chooser.h | 61 | ||||
-rw-r--r-- | libempathy/empathy-irc-network-manager.c | 34 | ||||
-rw-r--r-- | libempathy/empathy-irc-network-manager.h | 2 | ||||
-rw-r--r-- | libempathy/empathy-irc-network.c | 16 | ||||
-rw-r--r-- | libempathy/empathy-irc-network.h | 4 |
11 files changed, 1204 insertions, 458 deletions
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am index de6cba2f1..d81b97253 100644 --- a/libempathy-gtk/Makefile.am +++ b/libempathy-gtk/Makefile.am @@ -63,6 +63,8 @@ libempathy_gtk_handwritten_source = \ empathy-individual-store.c \ empathy-individual-view.c \ empathy-individual-widget.c \ + empathy-irc-network-chooser.c \ + empathy-irc-network-chooser-dialog.c \ empathy-irc-network-dialog.c \ empathy-kludge-label.c \ empathy-log-window.c \ @@ -123,6 +125,8 @@ libempathy_gtk_headers = \ empathy-individual-store.h \ empathy-individual-view.h \ empathy-individual-widget.h \ + empathy-irc-network-chooser.h \ + empathy-irc-network-chooser-dialog.h \ empathy-irc-network-dialog.h \ empathy-kludge-label.h \ empathy-log-window.h \ diff --git a/libempathy-gtk/empathy-account-widget-irc.c b/libempathy-gtk/empathy-account-widget-irc.c index f98d54bbd..d60af5ea8 100644 --- a/libempathy-gtk/empathy-account-widget-irc.c +++ b/libempathy-gtk/empathy-account-widget-irc.c @@ -28,9 +28,9 @@ #include <gtk/gtk.h> #include <libempathy/empathy-utils.h> -#include <libempathy/empathy-irc-network-manager.h> #include "empathy-irc-network-dialog.h" +#include "empathy-irc-network-chooser.h" #include "empathy-account-widget.h" #include "empathy-account-widget-private.h" #include "empathy-account-widget-irc.h" @@ -39,304 +39,29 @@ #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC #include <libempathy/empathy-debug.h> -#define IRC_NETWORKS_FILENAME "irc-networks.xml" -#define DEFAULT_IRC_NETWORK "irc.gimp.org" - typedef struct { EmpathyAccountWidget *self; - EmpathyIrcNetworkManager *network_manager; GtkWidget *vbox_settings; - GtkWidget *combobox_network; + GtkWidget *network_chooser; } 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_slice_free (EmpathyAccountWidgetIrc, settings); } static void -unset_server_params (EmpathyAccountWidgetIrc *settings) -{ - EmpathyAccountSettings *ac_settings; - - g_object_get (settings->self, "settings", &ac_settings, NULL); - DEBUG ("Unset server, port and use-ssl"); - empathy_account_settings_unset (ac_settings, "server"); - empathy_account_settings_unset (ac_settings, "port"); - empathy_account_settings_unset (ac_settings, "use-ssl"); -} - -static void -update_server_params (EmpathyAccountWidgetIrc *settings) -{ - GtkTreeIter iter; - GtkTreeModel *model; - EmpathyIrcNetwork *network; - GSList *servers; - gchar *charset; - EmpathyAccountSettings *ac_settings; - - g_object_get (settings->self, "settings", &ac_settings, NULL); - - 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 (ac_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 (ac_settings, "server", address); - DEBUG ("Setting port to %u", port); - empathy_account_settings_set_uint32 (ac_settings, "port", port); - DEBUG ("Setting use-ssl to %s", ssl ? "TRUE": "FALSE" ); - empathy_account_settings_set_boolean (ac_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); - empathy_account_widget_changed (settings->self); - - 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); - empathy_account_widget_changed (settings->self); -} - -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; EmpathyAccountSettings *ac_settings; g_object_get (settings->self, "settings", &ac_settings, NULL); @@ -344,7 +69,6 @@ account_widget_irc_setup (EmpathyAccountWidgetIrc *settings) nick = empathy_account_settings_get_string (ac_settings, "account"); fullname = empathy_account_settings_get_string (ac_settings, "fullname"); - server = empathy_account_settings_get_string (ac_settings, "server"); charset = empathy_account_settings_get_string (ac_settings, "charset"); port = empathy_account_settings_get_uint32 (ac_settings, "port"); ssl = empathy_account_settings_get_boolean (ac_settings, "use-ssl"); @@ -366,63 +90,13 @@ account_widget_irc_setup (EmpathyAccountWidgetIrc *settings) empathy_account_settings_set_string (ac_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); - } - } - - if (network == NULL) - { - network = empathy_irc_network_manager_find_network_by_address ( - settings->network_manager, DEFAULT_IRC_NETWORK); - } - - fill_networks_model (settings, network); - update_server_params (settings); +static void +network_changed_cb (EmpathyIrcNetworkChooser *chooser, + EmpathyAccountWidgetIrc *settings) +{ + empathy_account_widget_changed (settings->self); } void @@ -431,60 +105,29 @@ empathy_account_widget_irc_build (EmpathyAccountWidget *self, GtkWidget **table_common_settings) { EmpathyAccountWidgetIrc *settings; - gchar *dir, *user_file_with_path, *global_file_with_path; - GtkListStore *store; - GtkCellRenderer *renderer; + EmpathyAccountSettings *ac_settings; settings = g_slice_new0 (EmpathyAccountWidgetIrc); settings->self = self; - dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); - g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR); - user_file_with_path = g_build_filename (dir, IRC_NETWORKS_FILENAME, NULL); - g_free (dir); - - global_file_with_path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), - "libempathy", IRC_NETWORKS_FILENAME, NULL); - if (!g_file_test (global_file_with_path, G_FILE_TEST_EXISTS)) - { - g_free (global_file_with_path); - global_file_with_path = g_build_filename (DATADIR, "empathy", - IRC_NETWORKS_FILENAME, NULL); - } - - 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); - self->ui_details->gui = empathy_builder_get_file (filename, "table_irc_settings", table_common_settings, "vbox_irc", &self->ui_details->widget, "table_irc_settings", &settings->vbox_settings, - "combobox_network", &settings->combobox_network, NULL); - /* Fill the networks combobox */ - store = gtk_list_store_new (2, G_TYPE_OBJECT, G_TYPE_STRING); + /* Add network chooser button */ + g_object_get (settings->self, "settings", &ac_settings, NULL); - 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); + settings->network_chooser = empathy_irc_network_chooser_new (ac_settings); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), - COL_NETWORK_NAME, - GTK_SORT_ASCENDING); + g_signal_connect (settings->network_chooser, "changed", + G_CALLBACK (network_changed_cb), settings); - gtk_combo_box_set_model (GTK_COMBO_BOX (settings->combobox_network), - GTK_TREE_MODEL (store)); - g_object_unref (store); + gtk_table_attach (GTK_TABLE (*table_common_settings), + settings->network_chooser, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); + + gtk_widget_show (settings->network_chooser); account_widget_irc_setup (settings); @@ -497,15 +140,9 @@ empathy_account_widget_irc_build (EmpathyAccountWidget *self, empathy_builder_connect (self->ui_details->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); self->ui_details->default_focus = g_strdup ("entry_nick"); + + g_object_unref (ac_settings); } diff --git a/libempathy-gtk/empathy-account-widget-irc.ui b/libempathy-gtk/empathy-account-widget-irc.ui index af733fb95..de0aa00cd 100644 --- a/libempathy-gtk/empathy-account-widget-irc.ui +++ b/libempathy-gtk/empathy-account-widget-irc.ui @@ -257,7 +257,6 @@ </object> <object class="GtkVBox" id="vbox_irc"> <property name="visible">True</property> - <property name="orientation">vertical</property> <child> <object class="GtkTable" id="table_irc_settings"> <property name="visible">True</property> @@ -373,80 +372,6 @@ </packing> </child> <child> - <object class="GtkHBox" id="hbox174"> - <property name="visible">True</property> - <property name="spacing">2</property> - <child> - <object class="GtkComboBox" id="combobox_network"> - <property name="visible">True</property> - </object> - <packing> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_add_network"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <child> - <object class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="stock">gtk-add</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_network"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <child> - <object class="GtkImage" id="image834"> - <property name="visible">True</property> - <property name="stock">gtk-edit</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_remove_network"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <child> - <object class="GtkImage" id="image835"> - <property name="visible">True</property> - <property name="stock">gtk-remove</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">3</property> - </packing> - </child> - </object> - <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> <object class="GtkLabel" id="label_network2"> <property name="visible">True</property> <property name="xalign">0</property> @@ -458,6 +383,9 @@ <property name="y_options"></property> </packing> </child> + <child> + <placeholder/> + </child> </object> <packing> <property name="position">0</property> diff --git a/libempathy-gtk/empathy-irc-network-chooser-dialog.c b/libempathy-gtk/empathy-irc-network-chooser-dialog.c new file mode 100644 index 000000000..c1335e539 --- /dev/null +++ b/libempathy-gtk/empathy-irc-network-chooser-dialog.c @@ -0,0 +1,629 @@ +/* + * 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 <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-ui-utils.h" +#include "empathy-live-search.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC +#include <libempathy/empathy-debug.h> + +#include "empathy-irc-network-chooser-dialog.h" + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcNetworkChooserDialog) + +enum { + PROP_SETTINGS = 1, + PROP_NETWORK +}; + +typedef struct { + EmpathyAccountSettings *settings; + EmpathyIrcNetwork *network; + + EmpathyIrcNetworkManager *network_manager; + gboolean changed; + + GtkWidget *treeview; + GtkListStore *store; + GtkTreeModelFilter *filter; + GtkWidget *search; + GtkWidget *select_button; + + gulong search_sig; +} EmpathyIrcNetworkChooserDialogPriv; + +enum { + COL_NETWORK_OBJ, + COL_NETWORK_NAME, +}; + +G_DEFINE_TYPE (EmpathyIrcNetworkChooserDialog, empathy_irc_network_chooser_dialog, + GTK_TYPE_DIALOG); + +static void +empathy_irc_network_chooser_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (object); + + switch (prop_id) + { + case PROP_SETTINGS: + priv->settings = g_value_dup_object (value); + break; + case PROP_NETWORK: + priv->network = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +empathy_irc_network_chooser_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (object); + + switch (prop_id) + { + case PROP_SETTINGS: + g_value_set_object (value, priv->settings); + break; + case PROP_NETWORK: + g_value_set_object (value, priv->network); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* The iter returned by *it is a priv->store iter (not a filter one) */ +static EmpathyIrcNetwork * +dup_selected_network (EmpathyIrcNetworkChooserDialog *self, + GtkTreeIter *it) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + EmpathyIrcNetwork *network; + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreeModel *model; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return NULL; + + gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1); + g_assert (network != NULL); + + if (it != NULL) + { + gtk_tree_model_filter_convert_iter_to_child_iter (priv->filter, it, + &iter); + } + + return network; +} + +static void +treeview_changed_cb (GtkTreeView *treeview, + EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + EmpathyIrcNetwork *network; + + network = dup_selected_network (self, NULL); + if (network == priv->network) + { + g_object_unref (network); + return; + } + + tp_clear_object (&priv->network); + /* Transfer the reference */ + priv->network = network; + + priv->changed = TRUE; +} + +/* Take a filter iterator as argument */ +static void +scroll_to_iter (EmpathyIrcNetworkChooserDialog *self, + GtkTreeIter *filter_iter) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + GtkTreePath *path; + + path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->filter), filter_iter); + + if (path != NULL) + { + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->treeview), + path, NULL, FALSE, 0, 0); + + gtk_tree_path_free (path); + } +} + +/* Take a filter iterator as argument */ +static void +select_iter (EmpathyIrcNetworkChooserDialog *self, + GtkTreeIter *filter_iter, + gboolean emulate_changed) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + GtkTreeSelection *selection; + GtkTreePath *path; + + /* Select the network */ + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (priv->treeview)); + + gtk_tree_selection_select_iter (selection, filter_iter); + + path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->filter), filter_iter); + if (path != NULL) + { + gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->treeview), path, + NULL, FALSE); + + gtk_tree_path_free (path); + } + + /* Scroll to the selected network */ + scroll_to_iter (self, filter_iter); + + if (emulate_changed) + { + /* gtk_tree_selection_select_iter doesn't fire the 'cursor-changed' signal + * so we call the callback manually. */ + treeview_changed_cb (GTK_TREE_VIEW (priv->treeview), self); + } +} + +static GtkTreeIter +iter_to_filter_iter (EmpathyIrcNetworkChooserDialog *self, + GtkTreeIter *iter) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + GtkTreeIter filter_iter; + + g_assert (gtk_tree_model_filter_convert_child_iter_to_iter (priv->filter, + &filter_iter, iter)); + + return filter_iter; +} + +static void +fill_store (EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + GSList *networks, *l; + + networks = empathy_irc_network_manager_get_networks ( + priv->network_manager); + + for (l = networks; l != NULL; l = g_slist_next (l)) + { + EmpathyIrcNetwork *network = l->data; + GtkTreeIter iter; + + gtk_list_store_insert_with_values (priv->store, &iter, -1, + COL_NETWORK_OBJ, network, + COL_NETWORK_NAME, empathy_irc_network_get_name (network), + -1); + + if (network == priv->network) + { + GtkTreeIter filter_iter = iter_to_filter_iter (self, &iter); + + select_iter (self, &filter_iter, FALSE); + } + + g_object_unref (network); + } + + g_slist_free (networks); +} + +static void +irc_network_dialog_destroy_cb (GtkWidget *widget, + EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + EmpathyIrcNetwork *network; + GtkTreeIter iter, filter_iter; + + priv->changed = TRUE; + + network = dup_selected_network (self, &iter); + if (network == NULL) + return; + + /* name could be changed */ + gtk_list_store_set (GTK_LIST_STORE (priv->store), &iter, + COL_NETWORK_NAME, empathy_irc_network_get_name (network), -1); + + filter_iter = iter_to_filter_iter (self, &iter); + scroll_to_iter (self, &filter_iter); + + gtk_widget_grab_focus (priv->treeview); + + g_object_unref (network); +} + +static void +display_irc_network_dialog (EmpathyIrcNetworkChooserDialog *self, + EmpathyIrcNetwork *network) +{ + GtkWidget *dialog; + + dialog = empathy_irc_network_dialog_show (network, NULL); + + g_signal_connect (dialog, "destroy", + G_CALLBACK (irc_network_dialog_destroy_cb), self); +} + +static void +edit_network (EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetwork *network; + + network = dup_selected_network (self, NULL); + if (network == NULL) + return; + + display_irc_network_dialog (self, network); + + g_object_unref (network); +} + +static void +add_network (EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + EmpathyIrcNetwork *network; + GtkTreeIter iter, filter_iter; + + gtk_widget_hide (priv->search); + + network = empathy_irc_network_new (_("New Network")); + empathy_irc_network_manager_add (priv->network_manager, network); + + gtk_list_store_insert_with_values (priv->store, &iter, -1, + COL_NETWORK_OBJ, network, + COL_NETWORK_NAME, empathy_irc_network_get_name (network), + -1); + + filter_iter = iter_to_filter_iter (self, &iter); + select_iter (self, &filter_iter, TRUE); + + display_irc_network_dialog (self, network); + + g_object_unref (network); +} + +static void +remove_network (EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + EmpathyIrcNetwork *network; + GtkTreeIter iter; + + network = dup_selected_network (self, &iter); + if (network == NULL) + return; + + /* Hide the search after picking the network to get the right one */ + gtk_widget_hide (priv->search); + + DEBUG ("Remove network %s", empathy_irc_network_get_name (network)); + + gtk_list_store_remove (priv->store, &iter); + empathy_irc_network_manager_remove (priv->network_manager, network); + + /* Select next network */ + if (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store), &iter)) + { + GtkTreeIter filter_iter = iter_to_filter_iter (self, &iter); + + select_iter (self, &filter_iter, TRUE); + } + + gtk_widget_grab_focus (priv->treeview); + + g_object_unref (network); +} + +static void +dialog_response_cb (GtkDialog *dialog, + gint response, + EmpathyIrcNetworkChooserDialog *self) +{ + if (response == GTK_RESPONSE_OK) + add_network (self); + else if (response == GTK_RESPONSE_APPLY) + edit_network (self); + else if (response == GTK_RESPONSE_REJECT) + remove_network (self); +} + +static gboolean +filter_visible_func (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (user_data); + EmpathyIrcNetwork *network; + gboolean visible; + + gtk_tree_model_get (model, iter, COL_NETWORK_OBJ, &network, -1); + + visible = empathy_live_search_match (EMPATHY_LIVE_SEARCH (priv->search), + empathy_irc_network_get_name (network)); + + g_object_unref (network); + return visible; +} + + +static void +search_text_notify_cb (EmpathyLiveSearch *search, + GParamSpec *pspec, + EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + GtkTreeIter filter_iter; + gboolean sensitive = FALSE; + + gtk_tree_model_filter_refilter (priv->filter); + + /* Is there at least one network in the view ? */ + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->filter), + &filter_iter)) + { + const gchar *text; + + text = empathy_live_search_get_text (EMPATHY_LIVE_SEARCH (priv->search)); + if (!EMP_STR_EMPTY (text)) + { + /* We are doing a search, select the first matching network */ + select_iter (self, &filter_iter, TRUE); + } + else + { + /* Search has been cancelled. Scroll to the selected network */ + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (priv->treeview)); + + if (gtk_tree_selection_get_selected (selection, NULL, &filter_iter)) + scroll_to_iter (self, &filter_iter); + } + + sensitive = TRUE; + } + + gtk_widget_set_sensitive (priv->select_button, sensitive); +} + +static void +dialog_destroy_cb (GtkWidget *widget, + EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + + g_signal_handler_disconnect (priv->search, priv->search_sig); +} + +static void +empathy_irc_network_chooser_dialog_constructed (GObject *object) +{ + EmpathyIrcNetworkChooserDialog *self = (EmpathyIrcNetworkChooserDialog *) object; + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + GtkDialog *dialog = GTK_DIALOG (self); + GtkCellRenderer *renderer; + GtkWidget *vbox; + GtkTreeViewColumn *column; + GtkWidget *scroll; + + g_assert (priv->settings != NULL); + + gtk_window_set_title (GTK_WINDOW (self), _("Choose an IRC network")); + + /* Create store and treeview */ + priv->store = gtk_list_store_new (2, G_TYPE_OBJECT, G_TYPE_STRING); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store), + COL_NETWORK_NAME, + GTK_SORT_ASCENDING); + + priv->treeview = gtk_tree_view_new (); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE); + gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->treeview), FALSE); + + column = gtk_tree_view_column_new (); + gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (column), + renderer, + "text", COL_NETWORK_NAME, + NULL); + + /* add the treeview in a GtkScrolledWindow */ + vbox = gtk_dialog_get_content_area (dialog); + + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + gtk_container_add (GTK_CONTAINER (scroll), priv->treeview); + gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 6); + + /* Live search */ + priv->search = empathy_live_search_new (priv->treeview); + + gtk_box_pack_start (GTK_BOX (vbox), priv->search, FALSE, TRUE, 0); + + priv->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new ( + GTK_TREE_MODEL (priv->store), NULL)); + gtk_tree_model_filter_set_visible_func (priv->filter, + filter_visible_func, self, NULL); + + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), + GTK_TREE_MODEL (priv->filter)); + + priv->search_sig = g_signal_connect (priv->search, "notify::text", + G_CALLBACK (search_text_notify_cb), self); + + /* Add buttons */ + gtk_dialog_add_buttons (dialog, + GTK_STOCK_ADD, GTK_RESPONSE_OK, + GTK_STOCK_EDIT, GTK_RESPONSE_APPLY, + GTK_STOCK_REMOVE, GTK_RESPONSE_REJECT, + NULL); + + priv->select_button = gtk_dialog_add_button (dialog, _("Select"), + GTK_RESPONSE_CLOSE); + + fill_store (self); + + g_signal_connect (priv->treeview, "cursor-changed", + G_CALLBACK (treeview_changed_cb), self); + + g_signal_connect (self, "response", + G_CALLBACK (dialog_response_cb), self); + g_signal_connect (self, "destroy", + G_CALLBACK (dialog_destroy_cb), self); + + /* Request a side ensuring to display at least some networks */ + gtk_widget_set_size_request (GTK_WIDGET (self), -1, 300); + + gtk_window_set_modal (GTK_WINDOW (self), TRUE); +} + +static void +empathy_irc_network_chooser_dialog_dispose (GObject *object) +{ + EmpathyIrcNetworkManager *self = (EmpathyIrcNetworkManager *) object; + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + + tp_clear_object (&priv->settings); + tp_clear_object (&priv->network); + tp_clear_object (&priv->network_manager); + tp_clear_object (&priv->store); + tp_clear_object (&priv->filter); + + if (G_OBJECT_CLASS (empathy_irc_network_chooser_dialog_parent_class)->dispose) + G_OBJECT_CLASS (empathy_irc_network_chooser_dialog_parent_class)->dispose (object); +} + +static void +empathy_irc_network_chooser_dialog_class_init (EmpathyIrcNetworkChooserDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = empathy_irc_network_chooser_dialog_get_property; + object_class->set_property = empathy_irc_network_chooser_dialog_set_property; + object_class->constructed = empathy_irc_network_chooser_dialog_constructed; + object_class->dispose = empathy_irc_network_chooser_dialog_dispose; + + g_object_class_install_property (object_class, PROP_SETTINGS, + g_param_spec_object ("settings", + "Settings", + "The EmpathyAccountSettings to show and edit", + EMPATHY_TYPE_ACCOUNT_SETTINGS, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_NETWORK, + g_param_spec_object ("network", + "Network", + "The EmpathyIrcNetwork selected in the treeview", + EMPATHY_TYPE_IRC_NETWORK, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, + sizeof (EmpathyIrcNetworkChooserDialogPriv)); +} + +static void +empathy_irc_network_chooser_dialog_init (EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, EmpathyIrcNetworkChooserDialogPriv); + self->priv = priv; + + priv->network_manager = empathy_irc_network_manager_dup_default (); +} + +GtkWidget * +empathy_irc_network_chooser_dialog_new (EmpathyAccountSettings *settings, + EmpathyIrcNetwork *network, + GtkWindow *parent) +{ + return g_object_new (EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, + "settings", settings, + "network", network, + "transient-for", parent, + NULL); +} + +EmpathyIrcNetwork * +empathy_irc_network_chooser_dialog_get_network ( + EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + + return priv->network; +} + +gboolean +empathy_irc_network_chooser_dialog_get_changed ( + EmpathyIrcNetworkChooserDialog *self) +{ + EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self); + + return priv->changed; +} diff --git a/libempathy-gtk/empathy-irc-network-chooser-dialog.h b/libempathy-gtk/empathy-irc-network-chooser-dialog.h new file mode 100644 index 000000000..0d4f24e7f --- /dev/null +++ b/libempathy-gtk/empathy-irc-network-chooser-dialog.h @@ -0,0 +1,71 @@ +/* + * 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 <gdesmott@gnome.org> + */ + +#ifndef __EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_H__ +#define __EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_H__ + +#include <gtk/gtk.h> + +#include <libempathy/empathy-account-settings.h> +#include <libempathy/empathy-irc-network.h> + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG (empathy_irc_network_chooser_dialog_get_type ()) +#define EMPATHY_IRC_NETWORK_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, EmpathyIrcNetworkChooserDialog)) +#define EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \ + EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, EmpathyIrcNetworkChooserDialogClass)) +#define EMPATHY_IS_IRC_NETWORK_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG)) +#define EMPATHY_IS_IRC_NETWORK_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \ + EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG)) +#define EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_GET_CLASS(o) ( \ + G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, \ + EmpathyIrcNetworkChooserDialogClass)) + +typedef struct { + GtkDialog parent; + + /*<private>*/ + gpointer priv; +} EmpathyIrcNetworkChooserDialog; + +typedef struct { + GtkDialogClass parent_class; +} EmpathyIrcNetworkChooserDialogClass; + +GType empathy_irc_network_chooser_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget * empathy_irc_network_chooser_dialog_new ( + EmpathyAccountSettings *settings, + EmpathyIrcNetwork *network, + GtkWindow *parent); + +EmpathyIrcNetwork * empathy_irc_network_chooser_dialog_get_network ( + EmpathyIrcNetworkChooserDialog *self); + +gboolean empathy_irc_network_chooser_dialog_get_changed ( + EmpathyIrcNetworkChooserDialog *self); + +G_END_DECLS + +#endif /* __EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_H__ */ diff --git a/libempathy-gtk/empathy-irc-network-chooser.c b/libempathy-gtk/empathy-irc-network-chooser.c new file mode 100644 index 000000000..55a90fd0c --- /dev/null +++ b/libempathy-gtk/empathy-irc-network-chooser.c @@ -0,0 +1,360 @@ +/* + * 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 <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-ui-utils.h" +#include "empathy-irc-network-chooser-dialog.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC +#include <libempathy/empathy-debug.h> + +#include "empathy-irc-network-chooser.h" + +#define DEFAULT_IRC_NETWORK "irc.gimp.org" + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcNetworkChooser) + +enum { + PROP_SETTINGS = 1 +}; + +enum { + SIG_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct { + EmpathyAccountSettings *settings; + + EmpathyIrcNetworkManager *network_manager; + GtkWidget *dialog; + /* Displayed network */ + EmpathyIrcNetwork *network; +} EmpathyIrcNetworkChooserPriv; + +G_DEFINE_TYPE (EmpathyIrcNetworkChooser, empathy_irc_network_chooser, + GTK_TYPE_BUTTON); + +static void +empathy_irc_network_chooser_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (object); + + switch (prop_id) + { + case PROP_SETTINGS: + priv->settings = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +empathy_irc_network_chooser_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (object); + + switch (prop_id) + { + case PROP_SETTINGS: + g_value_set_object (value, priv->settings); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +unset_server_params (EmpathyIrcNetworkChooser *self) +{ + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self); + + DEBUG ("Unset server, port and use-ssl"); + empathy_account_settings_unset (priv->settings, "server"); + empathy_account_settings_unset (priv->settings, "port"); + empathy_account_settings_unset (priv->settings, "use-ssl"); +} + +static void +update_server_params (EmpathyIrcNetworkChooser *self) +{ + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self); + GSList *servers; + const gchar *charset; + + g_assert (priv->network != NULL); + + charset = empathy_irc_network_get_charset (priv->network); + DEBUG ("Setting charset to %s", charset); + empathy_account_settings_set_string (priv->settings, "charset", charset); + + servers = empathy_irc_network_get_servers (priv->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 (priv->settings, "server", address); + DEBUG ("Setting port to %u", port); + empathy_account_settings_set_uint32 (priv->settings, "port", port); + DEBUG ("Setting use-ssl to %s", ssl ? "TRUE": "FALSE" ); + empathy_account_settings_set_boolean (priv->settings, "use-ssl", ssl); + + g_free (address); + } + 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 (EmpathyIrcNetworkChooser *self) +{ + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self); + + g_assert (priv->network != NULL); + + gtk_button_set_label (GTK_BUTTON (self), + empathy_irc_network_get_name (priv->network)); +} + +static void +set_label_from_settings (EmpathyIrcNetworkChooser *self) +{ + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self); + const gchar *server; + + tp_clear_object (&priv->network); + + server = empathy_account_settings_get_string (priv->settings, "server"); + + if (server != NULL) + { + EmpathyIrcServer *srv; + gint port; + gboolean ssl; + + priv->network = empathy_irc_network_manager_find_network_by_address ( + priv->network_manager, server); + + if (priv->network != NULL) + { + /* The network is known */ + g_object_ref (priv->network); + set_label (self); + return; + } + + /* We don't have this network. Let's create it */ + port = empathy_account_settings_get_uint32 (priv->settings, "port"); + ssl = empathy_account_settings_get_boolean (priv->settings, + "use-ssl"); + + DEBUG ("Create a network %s", server); + priv->network = empathy_irc_network_new (server); + srv = empathy_irc_server_new (server, port, ssl); + + empathy_irc_network_append_server (priv->network, srv); + empathy_irc_network_manager_add (priv->network_manager, priv->network); + + set_label (self); + + g_object_unref (srv); + return; + } + + /* Set default network */ + priv->network = empathy_irc_network_manager_find_network_by_address ( + priv->network_manager, DEFAULT_IRC_NETWORK); + g_assert (priv->network != NULL); + + set_label (self); + update_server_params (self); + g_object_ref (priv->network); +} + +static void +dialog_response_cb (GtkDialog *dialog, + gint response, + EmpathyIrcNetworkChooser *self) +{ + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self); + EmpathyIrcNetworkChooserDialog *chooser = + EMPATHY_IRC_NETWORK_CHOOSER_DIALOG (priv->dialog); + + if (response != GTK_RESPONSE_CLOSE && + response != GTK_RESPONSE_DELETE_EVENT) + return; + + if (empathy_irc_network_chooser_dialog_get_changed (chooser)) + { + tp_clear_object (&priv->network); + + priv->network = g_object_ref ( + empathy_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 (priv->dialog); + priv->dialog = NULL; +} + +static void +clicked_cb (GtkButton *button, + gpointer user_data) +{ + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (button); + GtkWindow *window; + + if (priv->dialog != NULL) + goto out; + + window = empathy_get_toplevel_window (GTK_WIDGET (button)); + + priv->dialog = empathy_irc_network_chooser_dialog_new (priv->settings, + priv->network, window); + gtk_widget_show_all (priv->dialog); + + tp_g_signal_connect_object (priv->dialog, "response", + G_CALLBACK (dialog_response_cb), button, 0); + +out: + empathy_window_present (GTK_WINDOW (priv->dialog)); +} + +static void +empathy_irc_network_chooser_constructed (GObject *object) +{ + EmpathyIrcNetworkChooser *self = (EmpathyIrcNetworkChooser *) object; + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self); + + g_assert (priv->settings != NULL); + + set_label_from_settings (self); + + g_signal_connect (self, "clicked", G_CALLBACK (clicked_cb), self); +} + +static void +empathy_irc_network_chooser_dispose (GObject *object) +{ + EmpathyIrcNetworkManager *self = (EmpathyIrcNetworkManager *) object; + EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self); + + tp_clear_object (&priv->settings); + tp_clear_object (&priv->network_manager); + tp_clear_object (&priv->network); + + if (G_OBJECT_CLASS (empathy_irc_network_chooser_parent_class)->dispose) + G_OBJECT_CLASS (empathy_irc_network_chooser_parent_class)->dispose (object); +} + +static void +empathy_irc_network_chooser_class_init (EmpathyIrcNetworkChooserClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = empathy_irc_network_chooser_get_property; + object_class->set_property = empathy_irc_network_chooser_set_property; + object_class->constructed = empathy_irc_network_chooser_constructed; + object_class->dispose = empathy_irc_network_chooser_dispose; + + g_object_class_install_property (object_class, PROP_SETTINGS, + g_param_spec_object ("settings", + "Settings", + "The EmpathyAccountSettings to show and edit", + EMPATHY_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_VOID__VOID, + G_TYPE_NONE, + 0); + + g_type_class_add_private (object_class, + sizeof (EmpathyIrcNetworkChooserPriv)); +} + +static void +empathy_irc_network_chooser_init (EmpathyIrcNetworkChooser *self) +{ + EmpathyIrcNetworkChooserPriv *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + EMPATHY_TYPE_IRC_NETWORK_CHOOSER, EmpathyIrcNetworkChooserPriv); + self->priv = priv; + + priv->network_manager = empathy_irc_network_manager_dup_default (); +} + +GtkWidget * +empathy_irc_network_chooser_new (EmpathyAccountSettings *settings) +{ + return g_object_new (EMPATHY_TYPE_IRC_NETWORK_CHOOSER, + "settings", settings, + NULL); +} diff --git a/libempathy-gtk/empathy-irc-network-chooser.h b/libempathy-gtk/empathy-irc-network-chooser.h new file mode 100644 index 000000000..442ac2d53 --- /dev/null +++ b/libempathy-gtk/empathy-irc-network-chooser.h @@ -0,0 +1,61 @@ +/* + * 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 <gdesmott@gnome.org> + */ + +#ifndef __EMPATHY_IRC_NETWORK_CHOOSER_H__ +#define __EMPATHY_IRC_NETWORK_CHOOSER_H__ + +#include <gtk/gtk.h> + +#include <libempathy/empathy-account-settings.h> + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_IRC_NETWORK_CHOOSER (empathy_irc_network_chooser_get_type ()) +#define EMPATHY_IRC_NETWORK_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + EMPATHY_TYPE_IRC_NETWORK_CHOOSER, EmpathyIrcNetworkChooser)) +#define EMPATHY_IRC_NETWORK_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \ + EMPATHY_TYPE_IRC_NETWORK_CHOOSER, EmpathyIrcNetworkChooserClass)) +#define EMPATHY_IS_IRC_NETWORK_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + EMPATHY_TYPE_IRC_NETWORK_CHOOSER)) +#define EMPATHY_IS_IRC_NETWORK_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \ + EMPATHY_TYPE_IRC_NETWORK_CHOOSER)) +#define EMPATHY_IRC_NETWORK_CHOOSER_GET_CLASS(o) ( \ + G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_IRC_NETWORK_CHOOSER, \ + EmpathyIrcNetworkChooserClass)) + +typedef struct { + GtkButton parent; + + /*<private>*/ + gpointer priv; +} EmpathyIrcNetworkChooser; + +typedef struct { + GtkButtonClass parent_class; +} EmpathyIrcNetworkChooserClass; + +GType empathy_irc_network_chooser_get_type (void) G_GNUC_CONST; + +GtkWidget * empathy_irc_network_chooser_new (EmpathyAccountSettings *settings); + +G_END_DECLS + +#endif /* __EMPATHY_IRC_NETWORK_CHOOSER_H__ */ diff --git a/libempathy/empathy-irc-network-manager.c b/libempathy/empathy-irc-network-manager.c index 97d19a0eb..5e0530938 100644 --- a/libempathy/empathy-irc-network-manager.c +++ b/libempathy/empathy-irc-network-manager.c @@ -32,6 +32,7 @@ #include "empathy-debug.h" #define IRC_NETWORKS_DTD_FILENAME "empathy-irc-networks.dtd" +#define IRC_NETWORKS_FILENAME "irc-networks.xml" #define SAVE_TIMER 4 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcNetworkManager) @@ -781,3 +782,36 @@ empathy_irc_network_manager_find_network_by_address ( return network; } + +EmpathyIrcNetworkManager * +empathy_irc_network_manager_dup_default (void) +{ + static EmpathyIrcNetworkManager *default_mgr = NULL; + gchar *dir, *user_file_with_path, *global_file_with_path; + + if (default_mgr != NULL) + return g_object_ref (default_mgr); + + dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); + g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR); + user_file_with_path = g_build_filename (dir, IRC_NETWORKS_FILENAME, NULL); + g_free (dir); + + global_file_with_path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), + "libempathy", IRC_NETWORKS_FILENAME, NULL); + if (!g_file_test (global_file_with_path, G_FILE_TEST_EXISTS)) + { + g_free (global_file_with_path); + global_file_with_path = g_build_filename (DATADIR, "empathy", + IRC_NETWORKS_FILENAME, NULL); + } + + default_mgr = empathy_irc_network_manager_new ( + global_file_with_path, user_file_with_path); + + g_object_add_weak_pointer (G_OBJECT (default_mgr), (gpointer *) &default_mgr); + + g_free (global_file_with_path); + g_free (user_file_with_path); + return default_mgr; +} diff --git a/libempathy/empathy-irc-network-manager.h b/libempathy/empathy-irc-network-manager.h index a050f4723..11c84836f 100644 --- a/libempathy/empathy-irc-network-manager.h +++ b/libempathy/empathy-irc-network-manager.h @@ -63,6 +63,8 @@ GType empathy_irc_network_manager_get_type (void); EmpathyIrcNetworkManager * empathy_irc_network_manager_new ( const gchar *global_file, const gchar *user_file); +EmpathyIrcNetworkManager * empathy_irc_network_manager_dup_default (void); + void empathy_irc_network_manager_add (EmpathyIrcNetworkManager *manager, EmpathyIrcNetwork *network); diff --git a/libempathy/empathy-irc-network.c b/libempathy/empathy-irc-network.c index 9b75f0e82..d5b0bdcb9 100644 --- a/libempathy/empathy-irc-network.c +++ b/libempathy/empathy-irc-network.c @@ -359,3 +359,19 @@ empathy_irc_network_set_server_position (EmpathyIrcNetwork *self, g_signal_emit (self, signals[MODIFIED], 0); } + +const gchar * +empathy_irc_network_get_name (EmpathyIrcNetwork *self) +{ + EmpathyIrcNetworkPriv *priv = GET_PRIV (self); + + return priv->name; +} + +const gchar * +empathy_irc_network_get_charset (EmpathyIrcNetwork *self) +{ + EmpathyIrcNetworkPriv *priv = GET_PRIV (self); + + return priv->charset; +} diff --git a/libempathy/empathy-irc-network.h b/libempathy/empathy-irc-network.h index b10b2769e..9d78f3c3f 100644 --- a/libempathy/empathy-irc-network.h +++ b/libempathy/empathy-irc-network.h @@ -75,6 +75,10 @@ void empathy_irc_network_remove_server (EmpathyIrcNetwork *network, void empathy_irc_network_set_server_position (EmpathyIrcNetwork *network, EmpathyIrcServer *server, gint pos); +const gchar * empathy_irc_network_get_name (EmpathyIrcNetwork *network); + +const gchar * empathy_irc_network_get_charset (EmpathyIrcNetwork *network); + G_END_DECLS #endif /* __EMPATHY_IRC_NETWORK_H__ */ |