diff options
author | Xavier Claessens <xclaesse@gmail.com> | 2007-05-24 07:01:46 +0800 |
---|---|---|
committer | Xavier Claessens <xclaesse@src.gnome.org> | 2007-05-24 07:01:46 +0800 |
commit | 726dec7bfdafeae5d1cbaf00149aa0659ce589a4 (patch) | |
tree | c69bb33a1a7c50dddc37cf1be09b26ba128bcf06 /libempathy-gtk | |
parent | a7b98a1b882d17da63c9165042282db78aff508b (diff) | |
download | gsoc2013-empathy-726dec7bfdafeae5d1cbaf00149aa0659ce589a4.tar gsoc2013-empathy-726dec7bfdafeae5d1cbaf00149aa0659ce589a4.tar.gz gsoc2013-empathy-726dec7bfdafeae5d1cbaf00149aa0659ce589a4.tar.bz2 gsoc2013-empathy-726dec7bfdafeae5d1cbaf00149aa0659ce589a4.tar.lz gsoc2013-empathy-726dec7bfdafeae5d1cbaf00149aa0659ce589a4.tar.xz gsoc2013-empathy-726dec7bfdafeae5d1cbaf00149aa0659ce589a4.tar.zst gsoc2013-empathy-726dec7bfdafeae5d1cbaf00149aa0659ce589a4.zip |
New objects: GossipAccountChooser and GossipNewChatroom, we can now join
2007-05-24 Xavier Claessens <xclaesse@gmail.com>
* libempathy-gtk/gossip-account-chooser.c:
* libempathy-gtk/gossip-new-chatroom-dialog.c:
* libempathy-gtk/gossip-account-widget-jabber.c:
* libempathy-gtk/gossip-account-chooser.h:
* libempathy-gtk/gossip-new-chatroom-dialog.h:
* libempathy-gtk/gossip-group-chat.c:
* libempathy-gtk/empathy-main-window.c:
* libempathy-gtk/gossip-new-chatroom-dialog.glade:
* libempathy-gtk/gossip-account-widget-jabber.glade:
* libempathy-gtk/Makefile.am:
* libempathy/empathy-tp-chatroom.c:
* data/gtalk.profile:
* data/jabber.profile:
* data/salut.profile:
* data/Makefile.am:
* data/empathy.desktop.in.in:
* data/msn.profile:
* data/irc.profile: New objects: GossipAccountChooser and
GossipNewChatroom, we can now join any chatroom. Adding IRC profile.
svn path=/trunk/; revision=89
Diffstat (limited to 'libempathy-gtk')
-rw-r--r-- | libempathy-gtk/Makefile.am | 3 | ||||
-rw-r--r-- | libempathy-gtk/empathy-main-window.c | 4 | ||||
-rw-r--r-- | libempathy-gtk/gossip-account-chooser.c | 633 | ||||
-rw-r--r-- | libempathy-gtk/gossip-account-chooser.h | 66 | ||||
-rw-r--r-- | libempathy-gtk/gossip-account-widget-jabber.c | 14 | ||||
-rw-r--r-- | libempathy-gtk/gossip-account-widget-jabber.glade | 59 | ||||
-rw-r--r-- | libempathy-gtk/gossip-group-chat.c | 1 | ||||
-rw-r--r-- | libempathy-gtk/gossip-new-chatroom-dialog.c | 770 | ||||
-rw-r--r-- | libempathy-gtk/gossip-new-chatroom-dialog.glade | 519 | ||||
-rw-r--r-- | libempathy-gtk/gossip-new-chatroom-dialog.h | 34 |
10 files changed, 2052 insertions, 51 deletions
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am index 7a5d1893a..f28e7411c 100644 --- a/libempathy-gtk/Makefile.am +++ b/libempathy-gtk/Makefile.am @@ -32,6 +32,8 @@ libempathy_gtk_la_SOURCES = \ gossip-status-presets.c gossip-status-presets.h \ gossip-presence-chooser.c gossip-presence-chooser.h \ gossip-about-dialog.c gossip-about-dialog.h \ + gossip-account-chooser.c gossip-account-chooser.h \ + gossip-new-chatroom-dialog.c gossip-new-chatroom-dialog.h \ gossip-ui-utils.c gossip-ui-utils.h libempathy_gtk_la_LIBADD = \ @@ -48,6 +50,7 @@ glade_DATA = \ gossip-presence-chooser.glade \ gossip-accounts-dialog.glade \ gossip-account-widget-jabber.glade \ + gossip-new-chatroom-dialog.glade \ gossip-group-chat.glade \ gossip-chat.glade diff --git a/libempathy-gtk/empathy-main-window.c b/libempathy-gtk/empathy-main-window.c index 9f2e9daf0..aa49cffe0 100644 --- a/libempathy-gtk/empathy-main-window.c +++ b/libempathy-gtk/empathy-main-window.c @@ -45,7 +45,7 @@ #include "gossip-preferences.h" #include "gossip-accounts-dialog.h" #include "gossip-about-dialog.h" - +#include "gossip-new-chatroom-dialog.h" #define DEBUG_DOMAIN "MainWindow" @@ -403,7 +403,7 @@ static void main_window_room_join_new_cb (GtkWidget *widget, EmpathyMainWindow *window) { - //gossip_new_chatroom_dialog_show (GTK_WINDOW (window->window)); + gossip_new_chatroom_dialog_show (GTK_WINDOW (window->window)); } static void diff --git a/libempathy-gtk/gossip-account-chooser.c b/libempathy-gtk/gossip-account-chooser.c new file mode 100644 index 000000000..8d3439f7e --- /dev/null +++ b/libempathy-gtk/gossip-account-chooser.c @@ -0,0 +1,633 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2005-2007 Imendio AB + * + * 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: Martyn Russell <martyn@imendio.com> + */ + +#include "config.h" + +#include <string.h> + +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <glade/glade.h> + +#include <libtelepathy/tp-conn.h> +#include <libmissioncontrol/mc-account-monitor.h> +#include <libmissioncontrol/mission-control.h> + +#include <libempathy/gossip-utils.h> + +#include "gossip-ui-utils.h" +#include "gossip-account-chooser.h" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_ACCOUNT_CHOOSER, GossipAccountChooserPriv)) + +typedef struct { + MissionControl *mc; + McAccountMonitor *monitor; + + gboolean set_active_item; + gboolean can_select_all; + gboolean has_all_option; +} GossipAccountChooserPriv; + +typedef struct { + GossipAccountChooser *chooser; + McAccount *account; + gboolean set; +} SetAccountData; + +enum { + COL_ACCOUNT_IMAGE, + COL_ACCOUNT_TEXT, + COL_ACCOUNT_ENABLED, /* Usually tied to connected state */ + COL_ACCOUNT_POINTER, + COL_ACCOUNT_COUNT +}; + +static void account_chooser_finalize (GObject *object); +static void account_chooser_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void account_chooser_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); +static void account_chooser_setup (GossipAccountChooser *chooser); +static void account_chooser_account_created_cb (McAccountMonitor *monitor, + const gchar *unique_name, + GossipAccountChooser *chooser); +static void account_chooser_account_add_foreach (McAccount *account, + GossipAccountChooser *chooser); +static void account_chooser_account_deleted_cb (McAccountMonitor *monitor, + const gchar *unique_name, + GossipAccountChooser *chooser); +static void account_chooser_account_remove_foreach (McAccount *account, + GossipAccountChooser *chooser); +static void account_chooser_update_iter (GossipAccountChooser *chooser, + GtkTreeIter *iter, + McAccount *account); +static void account_chooser_status_changed_cb (MissionControl *mc, + TelepathyConnectionStatus status, + McPresence presence, + TelepathyConnectionStatusReason reason, + const gchar *unique_name, + GossipAccountChooser *chooser); +static gboolean account_chooser_separator_func (GtkTreeModel *model, + GtkTreeIter *iter, + GossipAccountChooser *chooser); +static gboolean account_chooser_set_account_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + SetAccountData *data); +static gboolean account_chooser_set_enabled_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + GossipAccountChooser *chooser); + +enum { + PROP_0, + PROP_CAN_SELECT_ALL, + PROP_HAS_ALL_OPTION, +}; + +G_DEFINE_TYPE (GossipAccountChooser, gossip_account_chooser, GTK_TYPE_COMBO_BOX); + +static void +gossip_account_chooser_class_init (GossipAccountChooserClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = account_chooser_finalize; + object_class->get_property = account_chooser_get_property; + object_class->set_property = account_chooser_set_property; + + g_object_class_install_property (object_class, + PROP_CAN_SELECT_ALL, + g_param_spec_boolean ("can-select-all", + "Can Select All", + "Should the user be able to select offline accounts", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_HAS_ALL_OPTION, + g_param_spec_boolean ("has-all-option", + "Has All Option", + "Have a separate option in the list to mean ALL accounts", + FALSE, + G_PARAM_READWRITE)); + + g_type_class_add_private (object_class, sizeof (GossipAccountChooserPriv)); +} + +static void +gossip_account_chooser_init (GossipAccountChooser *chooser) +{ +} + +static void +account_chooser_finalize (GObject *object) +{ + GossipAccountChooser *chooser; + GossipAccountChooserPriv *priv; + + chooser = GOSSIP_ACCOUNT_CHOOSER (object); + priv = GET_PRIV (object); + + g_signal_handlers_disconnect_by_func (priv->monitor, + account_chooser_account_created_cb, + chooser); + g_signal_handlers_disconnect_by_func (priv->monitor, + account_chooser_account_deleted_cb, + chooser); + dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc), + "AccountStatusChanged", + G_CALLBACK (account_chooser_status_changed_cb), + chooser); + g_object_unref (priv->mc); + g_object_unref (priv->monitor); + + G_OBJECT_CLASS (gossip_account_chooser_parent_class)->finalize (object); +} + +static void +account_chooser_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + GossipAccountChooserPriv *priv; + + priv = GET_PRIV (object); + + switch (param_id) { + case PROP_CAN_SELECT_ALL: + g_value_set_boolean (value, priv->can_select_all); + break; + case PROP_HAS_ALL_OPTION: + g_value_set_boolean (value, priv->has_all_option); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +static void +account_chooser_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + GossipAccountChooserPriv *priv; + + priv = GET_PRIV (object); + + switch (param_id) { + case PROP_CAN_SELECT_ALL: + gossip_account_chooser_set_can_select_all (GOSSIP_ACCOUNT_CHOOSER (object), + g_value_get_boolean (value)); + break; + case PROP_HAS_ALL_OPTION: + gossip_account_chooser_set_has_all_option (GOSSIP_ACCOUNT_CHOOSER (object), + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +GtkWidget * +gossip_account_chooser_new (void) +{ + GossipAccountChooserPriv *priv; + McAccountMonitor *monitor; + GtkWidget *chooser; + + monitor = mc_account_monitor_new (); + chooser = g_object_new (GOSSIP_TYPE_ACCOUNT_CHOOSER, NULL); + + priv = GET_PRIV (chooser); + + priv->mc = gossip_mission_control_new (); + priv->monitor = mc_account_monitor_new (); + + g_signal_connect (priv->monitor, "account-created", + G_CALLBACK (account_chooser_account_created_cb), + chooser); + g_signal_connect (priv->monitor, "account-deleted", + G_CALLBACK (account_chooser_account_deleted_cb), + chooser); + dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged", + G_CALLBACK (account_chooser_status_changed_cb), + chooser, NULL); + + account_chooser_setup (GOSSIP_ACCOUNT_CHOOSER (chooser)); + + return chooser; +} + +McAccount * +gossip_account_chooser_get_account (GossipAccountChooser *chooser) +{ + GossipAccountChooserPriv *priv; + McAccount *account; + GtkTreeModel *model; + GtkTreeIter iter; + + g_return_val_if_fail (GOSSIP_IS_ACCOUNT_CHOOSER (chooser), NULL); + + priv = GET_PRIV (chooser); + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser)); + gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser), &iter); + + gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1); + + return account; +} + +gboolean +gossip_account_chooser_set_account (GossipAccountChooser *chooser, + McAccount *account) +{ + GtkComboBox *combobox; + GtkTreeModel *model; + GtkTreeIter iter; + SetAccountData data; + + g_return_val_if_fail (GOSSIP_IS_ACCOUNT_CHOOSER (chooser), FALSE); + + combobox = GTK_COMBO_BOX (chooser); + model = gtk_combo_box_get_model (combobox); + gtk_combo_box_get_active_iter (combobox, &iter); + + data.chooser = chooser; + data.account = account; + + gtk_tree_model_foreach (model, + (GtkTreeModelForeachFunc) account_chooser_set_account_foreach, + &data); + + return data.set; +} + +gboolean +gossip_account_chooser_get_can_select_all (GossipAccountChooser *chooser) +{ + GossipAccountChooserPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_ACCOUNT_CHOOSER (chooser), FALSE); + + priv = GET_PRIV (chooser); + + return priv->can_select_all; +} + +void +gossip_account_chooser_set_can_select_all (GossipAccountChooser *chooser, + gboolean can_select_all) +{ + GossipAccountChooserPriv *priv; + GtkComboBox *combobox; + GtkTreeModel *model; + + g_return_if_fail (GOSSIP_IS_ACCOUNT_CHOOSER (chooser)); + + priv = GET_PRIV (chooser); + + if (priv->can_select_all == can_select_all) { + return; + } + + combobox = GTK_COMBO_BOX (chooser); + model = gtk_combo_box_get_model (combobox); + + priv->can_select_all = can_select_all; + + gtk_tree_model_foreach (model, + (GtkTreeModelForeachFunc) account_chooser_set_enabled_foreach, + chooser); + + g_object_notify (G_OBJECT (chooser), "can-select-all"); +} + +gboolean +gossip_account_chooser_get_has_all_option (GossipAccountChooser *chooser) +{ + GossipAccountChooserPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_ACCOUNT_CHOOSER (chooser), FALSE); + + priv = GET_PRIV (chooser); + + return priv->has_all_option; +} + +void +gossip_account_chooser_set_has_all_option (GossipAccountChooser *chooser, + gboolean has_all_option) +{ + GossipAccountChooserPriv *priv; + GtkComboBox *combobox; + GtkListStore *store; + GtkTreeModel *model; + GtkTreeIter iter; + + g_return_if_fail (GOSSIP_IS_ACCOUNT_CHOOSER (chooser)); + + priv = GET_PRIV (chooser); + + if (priv->has_all_option == has_all_option) { + return; + } + + combobox = GTK_COMBO_BOX (chooser); + model = gtk_combo_box_get_model (combobox); + store = GTK_LIST_STORE (model); + + priv->has_all_option = has_all_option; + + /* + * The first 2 options are the ALL and separator + */ + + if (has_all_option) { + gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (chooser), + (GtkTreeViewRowSeparatorFunc) + account_chooser_separator_func, + chooser, + NULL); + + gtk_list_store_prepend (store, &iter); + gtk_list_store_set (store, &iter, + COL_ACCOUNT_TEXT, NULL, + COL_ACCOUNT_ENABLED, TRUE, + COL_ACCOUNT_POINTER, NULL, + -1); + + gtk_list_store_prepend (store, &iter); + gtk_list_store_set (store, &iter, + COL_ACCOUNT_TEXT, _("All"), + COL_ACCOUNT_ENABLED, TRUE, + COL_ACCOUNT_POINTER, NULL, + -1); + } else { + if (gtk_tree_model_get_iter_first (model, &iter)) { + if (gtk_list_store_remove (GTK_LIST_STORE (model), &iter)) { + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + } + } + + gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (chooser), + (GtkTreeViewRowSeparatorFunc) + NULL, + NULL, + NULL); + } + + g_object_notify (G_OBJECT (chooser), "has-all-option"); +} + +static void +account_chooser_setup (GossipAccountChooser *chooser) +{ + GossipAccountChooserPriv *priv; + GList *accounts; + GtkListStore *store; + GtkCellRenderer *renderer; + GtkComboBox *combobox; + + priv = GET_PRIV (chooser); + + /* Set up combo box with new store */ + combobox = GTK_COMBO_BOX (chooser); + + gtk_cell_layout_clear (GTK_CELL_LAYOUT (combobox)); + + store = gtk_list_store_new (COL_ACCOUNT_COUNT, + G_TYPE_STRING, + G_TYPE_STRING, /* Name */ + G_TYPE_BOOLEAN, /* Enabled */ + MC_TYPE_ACCOUNT); + + gtk_combo_box_set_model (combobox, GTK_TREE_MODEL (store)); + + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, + "icon-name", COL_ACCOUNT_IMAGE, + "sensitive", COL_ACCOUNT_ENABLED, + NULL); + g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, + "text", COL_ACCOUNT_TEXT, + "sensitive", COL_ACCOUNT_ENABLED, + NULL); + + /* Populate accounts */ + accounts = mc_accounts_list (); + g_list_foreach (accounts, + (GFunc) account_chooser_account_add_foreach, + chooser); + + mc_accounts_list_free (accounts); + g_object_unref (store); +} + +static void +account_chooser_account_created_cb (McAccountMonitor *monitor, + const gchar *unique_name, + GossipAccountChooser *chooser) +{ + McAccount *account; + + account = mc_account_lookup (unique_name); + account_chooser_account_add_foreach (account, chooser); + g_object_unref (account); +} + +static void +account_chooser_account_add_foreach (McAccount *account, + GossipAccountChooser *chooser) +{ + GossipAccountChooserPriv *priv; + GtkListStore *store; + GtkComboBox *combobox; + GtkTreeIter iter; + + priv = GET_PRIV (chooser); + + combobox = GTK_COMBO_BOX (chooser); + store = GTK_LIST_STORE (gtk_combo_box_get_model (combobox)); + + gtk_list_store_append (store, &iter); + account_chooser_update_iter (chooser, &iter, account); +} + +static void +account_chooser_account_deleted_cb (McAccountMonitor *monitor, + const gchar *unique_name, + GossipAccountChooser *chooser) +{ + McAccount *account; + + account = mc_account_lookup (unique_name); + account_chooser_account_remove_foreach (account, chooser); + g_object_unref (account); +} + +static void +account_chooser_account_remove_foreach (McAccount *account, + GossipAccountChooser *chooser) +{ + /* Fixme: TODO */ +} + +static void +account_chooser_update_iter (GossipAccountChooser *chooser, + GtkTreeIter *iter, + McAccount *account) +{ + GossipAccountChooserPriv *priv; + GtkListStore *store; + GtkComboBox *combobox; + TpConn *tp_conn; + const gchar *icon_name; + gboolean is_enabled; + + priv = GET_PRIV (chooser); + + combobox = GTK_COMBO_BOX (chooser); + store = GTK_LIST_STORE (gtk_combo_box_get_model (combobox)); + + icon_name = gossip_icon_name_from_account (account); + tp_conn = mission_control_get_connection (priv->mc, account, NULL); + is_enabled = (tp_conn != NULL || priv->can_select_all); + + if (tp_conn) { + g_object_unref (tp_conn); + } + + gtk_list_store_set (store, iter, + COL_ACCOUNT_IMAGE, icon_name, + COL_ACCOUNT_TEXT, mc_account_get_display_name (account), + COL_ACCOUNT_ENABLED, is_enabled, + COL_ACCOUNT_POINTER, account, + -1); + + /* set first connected account as active account */ + if (priv->set_active_item == FALSE && is_enabled) { + priv->set_active_item = TRUE; + gtk_combo_box_set_active_iter (combobox, iter); + } +} + +static void +account_chooser_status_changed_cb (MissionControl *mc, + TelepathyConnectionStatus status, + McPresence presence, + TelepathyConnectionStatusReason reason, + const gchar *unique_name, + GossipAccountChooser *chooser) +{ +} + +static gboolean +account_chooser_separator_func (GtkTreeModel *model, + GtkTreeIter *iter, + GossipAccountChooser *chooser) +{ + GossipAccountChooserPriv *priv; + gchar *text; + gboolean is_separator; + + priv = GET_PRIV (chooser); + + if (!priv->has_all_option) { + return FALSE; + } + + gtk_tree_model_get (model, iter, COL_ACCOUNT_TEXT, &text, -1); + is_separator = text == NULL; + g_free (text); + + return is_separator; +} + +static gboolean +account_chooser_set_account_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + SetAccountData *data) +{ + McAccount *account; + gboolean equal; + + gtk_tree_model_get (model, iter, COL_ACCOUNT_POINTER, &account, -1); + + /* Special case so we can make it possible to select the All option */ + if (!data->account && !account) { + equal = TRUE; + } else { + equal = gossip_account_equal (data->account, account); + g_object_unref (account); + } + + if (equal) { + GtkComboBox *combobox; + + combobox = GTK_COMBO_BOX (data->chooser); + gtk_combo_box_set_active_iter (combobox, iter); + + data->set = TRUE; + } + + return equal; +} + +static gboolean +account_chooser_set_enabled_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + GossipAccountChooser *chooser) +{ + GossipAccountChooserPriv *priv; + McAccount *account; + + priv = GET_PRIV (chooser); + + gtk_tree_model_get (model, iter, COL_ACCOUNT_POINTER, &account, -1); + if (!account) { + return FALSE; + } + + account_chooser_update_iter (chooser, iter, account); + g_object_unref (account); + + return FALSE; +} + diff --git a/libempathy-gtk/gossip-account-chooser.h b/libempathy-gtk/gossip-account-chooser.h new file mode 100644 index 000000000..b2d7c0cdd --- /dev/null +++ b/libempathy-gtk/gossip-account-chooser.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2005-2007 Imendio AB + * + * 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: Martyn Russell <martyn@imendio.com> + */ + +#ifndef __GOSSIP_ACCOUNT_CHOOSER_H__ +#define __GOSSIP_ACCOUNT_CHOOSER_H__ + +#include <gtk/gtkcombobox.h> + +#include <libmissioncontrol/mc-account.h> + +G_BEGIN_DECLS + +#define GOSSIP_TYPE_ACCOUNT_CHOOSER (gossip_account_chooser_get_type ()) +#define GOSSIP_ACCOUNT_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_ACCOUNT_CHOOSER, GossipAccountChooser)) +#define GOSSIP_ACCOUNT_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GOSSIP_TYPE_ACCOUNT_CHOOSER, GossipAccountChooserClass)) +#define GOSSIP_IS_ACCOUNT_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_ACCOUNT_CHOOSER)) +#define GOSSIP_IS_ACCOUNT_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_ACCOUNT_CHOOSER)) +#define GOSSIP_ACCOUNT_CHOOSER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_ACCOUNT_CHOOSER, GossipAccountChooserClass)) + +typedef struct _GossipAccountChooser GossipAccountChooser; +typedef struct _GossipAccountChooserClass GossipAccountChooserClass; + +struct _GossipAccountChooser { + GtkComboBox parent; +}; + +struct _GossipAccountChooserClass { + GtkComboBoxClass parent_class; +}; + +GType gossip_account_chooser_get_type (void) G_GNUC_CONST; +GtkWidget * gossip_account_chooser_new (void); +McAccount * gossip_account_chooser_get_account (GossipAccountChooser *chooser); +gboolean gossip_account_chooser_set_account (GossipAccountChooser *chooser, + McAccount *account); +gboolean gossip_account_chooser_get_can_select_all (GossipAccountChooser *chooser); + +void gossip_account_chooser_set_can_select_all (GossipAccountChooser *chooser, + gboolean can_select_all); +gboolean gossip_account_chooser_get_has_all_option (GossipAccountChooser *chooser); +void gossip_account_chooser_set_has_all_option (GossipAccountChooser *chooser, + gboolean has_all_option); + +G_END_DECLS + +#endif /* __GOSSIP_ACCOUNT_CHOOSER_H__ */ + diff --git a/libempathy-gtk/gossip-account-widget-jabber.c b/libempathy-gtk/gossip-account-widget-jabber.c index 8282777bd..e7334b4b5 100644 --- a/libempathy-gtk/gossip-account-widget-jabber.c +++ b/libempathy-gtk/gossip-account-widget-jabber.c @@ -30,6 +30,8 @@ #include <gtk/gtk.h> #include <glade/glade.h> +#include <libmissioncontrol/mc-profile.h> + #include <libempathy/gossip-utils.h> #include "gossip-account-widget-jabber.h" @@ -187,6 +189,18 @@ account_widget_jabber_setup (GossipAccountWidgetJabber *settings) mc_account_get_param_string (settings->account, "password", &password); mc_account_get_param_boolean (settings->account, "old-ssl", &old_ssl); + if (!id) { + McProfile *profile; + const gchar *server; + + profile = mc_account_get_profile (settings->account); + server = mc_profile_get_default_account_domain (profile); + if (server) { + id = g_strconcat ("user@", server, NULL); + } + g_object_unref (profile); + } + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (settings->checkbutton_ssl), old_ssl); gtk_entry_set_text (GTK_ENTRY (settings->entry_id), id ? id : ""); gtk_entry_set_text (GTK_ENTRY (settings->entry_password), password ? password : ""); diff --git a/libempathy-gtk/gossip-account-widget-jabber.glade b/libempathy-gtk/gossip-account-widget-jabber.glade index 19d13990a..12eec7576 100644 --- a/libempathy-gtk/gossip-account-widget-jabber.glade +++ b/libempathy-gtk/gossip-account-widget-jabber.glade @@ -309,62 +309,23 @@ </child> <child> - <widget class="GtkVBox" id="vbox1"> + <widget class="GtkEntry" id="entry_id"> <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkEntry" id="entry_id"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="label" translatable="yes"><small><b><span foreground="#555">Example: user@jabber.org</span></b></small></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> </widget> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> <property name="top_attach">0</property> <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> + <property name="y_options"></property> </packing> </child> </widget> diff --git a/libempathy-gtk/gossip-group-chat.c b/libempathy-gtk/gossip-group-chat.c index b955ee21e..6cf897d67 100644 --- a/libempathy-gtk/gossip-group-chat.c +++ b/libempathy-gtk/gossip-group-chat.c @@ -187,6 +187,7 @@ gossip_group_chat_new (McAccount *account, /* Create contact list */ priv->store = gossip_contact_list_store_new (EMPATHY_CONTACT_LIST (priv->tp_chat)); priv->view = gossip_contact_list_view_new (priv->store); + gossip_contact_list_store_set_show_offline (priv->store, TRUE); gtk_container_add (GTK_CONTAINER (priv->scrolled_window_contacts), GTK_WIDGET (priv->view)); gtk_widget_show (GTK_WIDGET (priv->view)); diff --git a/libempathy-gtk/gossip-new-chatroom-dialog.c b/libempathy-gtk/gossip-new-chatroom-dialog.c new file mode 100644 index 000000000..6c16ecb11 --- /dev/null +++ b/libempathy-gtk/gossip-new-chatroom-dialog.c @@ -0,0 +1,770 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006-2007 Imendio AB + * Copyright (C) 2007 Collabora Ltd. + * + * 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: Martyn Russell <martyn@imendio.com> + * Xavier Claessens <xclaesse@gmail.com> + */ + +#include "config.h" + +#include <string.h> +#include <stdio.h> + +#include <gtk/gtk.h> +#include <glade/glade.h> +#include <glib.h> +#include <glib/gi18n.h> + +#include <libmissioncontrol/mission-control.h> +#include <libmissioncontrol/mc-account.h> +#include <libmissioncontrol/mc-profile.h> + +#include <libempathy/gossip-utils.h> +#include <libempathy/gossip-debug.h> + +#include "gossip-new-chatroom-dialog.h" +#include "gossip-account-chooser.h" +//#include "gossip-chatrooms-window.h" +#include "gossip-ui-utils.h" +#include "ephy-spinner.h" + +#define DEBUG_DOMAIN "NewChatroomDialog" + +typedef struct { + GtkWidget *window; + + GtkWidget *vbox_widgets; + + GtkWidget *hbox_account; + GtkWidget *label_account; + GtkWidget *account_chooser; + + GtkWidget *hbox_server; + GtkWidget *label_server; + GtkWidget *entry_server; + GtkWidget *togglebutton_refresh; + + GtkWidget *hbox_room; + GtkWidget *label_room; + GtkWidget *entry_room; + + GtkWidget *hbox_nick; + GtkWidget *label_nick; + GtkWidget *entry_nick; + + GtkWidget *vbox_browse; + GtkWidget *image_status; + GtkWidget *label_status; + GtkWidget *hbox_status; + GtkWidget *throbber; + GtkWidget *treeview; + GtkTreeModel *model; + GtkTreeModel *filter; + + GtkWidget *button_join; + GtkWidget *button_close; +} GossipNewChatroomDialog; + +typedef struct { + guint handle; + gchar *channel_type; + gchar *name; + gchar *id; +} EmpathyRoomListItem; + +enum { + COL_IMAGE, + COL_NAME, + COL_POINTER, + COL_COUNT +}; + +static void +new_chatroom_dialog_response_cb (GtkWidget *widget, + gint response, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_destroy_cb (GtkWidget *widget, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_model_setup (GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_model_add_columns (GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_update_buttons (GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_update_widgets (GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_account_changed_cb (GtkComboBox *combobox, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_model_add (GossipNewChatroomDialog *dialog, + EmpathyRoomListItem *item); +static void +new_chatroom_dialog_model_clear (GossipNewChatroomDialog *dialog); +static GList * +new_chatroom_dialog_model_get_selected (GossipNewChatroomDialog *dialog); +static gboolean +new_chatroom_dialog_model_filter_func (GtkTreeModel *model, + GtkTreeIter *iter, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_model_row_activated_cb (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_model_row_inserted_cb (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_model_row_deleted_cb (GtkTreeModel *model, + GtkTreePath *path, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_model_selection_changed (GtkTreeSelection *selection, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_set_defaults (GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_join (GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_request_handles_cb (DBusGProxy *proxy, + GArray *handles, + GError *error, + McAccount *account); +static void +new_chatroom_dialog_entry_changed_cb (GtkWidget *entry, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_browse_start (GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_browse_stop (GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_entry_server_activate_cb (GtkWidget *widget, + GossipNewChatroomDialog *dialog); +static void +new_chatroom_dialog_togglebutton_refresh_toggled_cb (GtkWidget *widget, + GossipNewChatroomDialog *dialog); + +static GossipNewChatroomDialog *dialog_p = NULL; + +void +gossip_new_chatroom_dialog_show (GtkWindow *parent) +{ + GossipNewChatroomDialog *dialog; + GladeXML *glade; + GList *accounts; + gint account_num; + GtkSizeGroup *size_group; + + if (dialog_p) { + gtk_window_present (GTK_WINDOW (dialog_p->window)); + return; + } + + dialog_p = dialog = g_new0 (GossipNewChatroomDialog, 1); + + glade = gossip_glade_get_file ("gossip-new-chatroom-dialog.glade", + "new_chatroom_dialog", + NULL, + "new_chatroom_dialog", &dialog->window, + "hbox_account", &dialog->hbox_account, + "label_account", &dialog->label_account, + "vbox_widgets", &dialog->vbox_widgets, + "label_server", &dialog->label_server, + "label_room", &dialog->label_room, + "label_nick", &dialog->label_nick, + "hbox_server", &dialog->hbox_server, + "hbox_room", &dialog->hbox_room, + "hbox_nick", &dialog->hbox_nick, + "entry_server", &dialog->entry_server, + "entry_room", &dialog->entry_room, + "entry_nick", &dialog->entry_nick, + "togglebutton_refresh", &dialog->togglebutton_refresh, + "vbox_browse", &dialog->vbox_browse, + "image_status", &dialog->image_status, + "label_status", &dialog->label_status, + "hbox_status", &dialog->hbox_status, + "treeview", &dialog->treeview, + "button_join", &dialog->button_join, + NULL); + + gossip_glade_connect (glade, + dialog, + "new_chatroom_dialog", "response", new_chatroom_dialog_response_cb, + "new_chatroom_dialog", "destroy", new_chatroom_dialog_destroy_cb, + "entry_nick", "changed", new_chatroom_dialog_entry_changed_cb, + "entry_server", "changed", new_chatroom_dialog_entry_changed_cb, + "entry_server", "activate", new_chatroom_dialog_entry_server_activate_cb, + "entry_room", "changed", new_chatroom_dialog_entry_changed_cb, + "togglebutton_refresh", "toggled", new_chatroom_dialog_togglebutton_refresh_toggled_cb, + NULL); + + g_object_unref (glade); + + g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog_p); + + /* Label alignment */ + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + gtk_size_group_add_widget (size_group, dialog->label_account); + gtk_size_group_add_widget (size_group, dialog->label_server); + gtk_size_group_add_widget (size_group, dialog->label_room); + gtk_size_group_add_widget (size_group, dialog->label_nick); + + g_object_unref (size_group); + + /* Account chooser for custom */ + dialog->account_chooser = gossip_account_chooser_new (); + gtk_box_pack_start (GTK_BOX (dialog->hbox_account), + dialog->account_chooser, + TRUE, TRUE, 0); + gtk_widget_show (dialog->account_chooser); + + g_signal_connect (GTK_COMBO_BOX (dialog->account_chooser), "changed", + G_CALLBACK (new_chatroom_dialog_account_changed_cb), + dialog); + + /* Populate */ + accounts = mc_accounts_list (); + account_num = g_list_length (accounts); + + g_list_foreach (accounts, (GFunc) g_object_unref, NULL); + g_list_free (accounts); + + if (account_num > 1) { + gtk_widget_show (dialog->hbox_account); + } else { + /* Show no accounts combo box */ + gtk_widget_hide (dialog->hbox_account); + } + + /* Add throbber */ + dialog->throbber = ephy_spinner_new (); + ephy_spinner_set_size (EPHY_SPINNER (dialog->throbber), GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_widget_show (dialog->throbber); + + gtk_box_pack_start (GTK_BOX (dialog->hbox_status), dialog->throbber, + FALSE, FALSE, 0); + + /* Set up chatrooms treeview */ + new_chatroom_dialog_model_setup (dialog); + + /* Set things up according to the account type */ + new_chatroom_dialog_update_widgets (dialog); + + if (parent) { + gtk_window_set_transient_for (GTK_WINDOW (dialog->window), + GTK_WINDOW (parent)); + } + + gtk_widget_show (dialog->window); +} + +static void +new_chatroom_dialog_response_cb (GtkWidget *widget, + gint response, + GossipNewChatroomDialog *dialog) +{ + if (response == GTK_RESPONSE_OK) { + new_chatroom_dialog_join (dialog); + } + + gtk_widget_destroy (widget); +} + +static void +new_chatroom_dialog_destroy_cb (GtkWidget *widget, + GossipNewChatroomDialog *dialog) +{ + g_object_unref (dialog->model); + g_object_unref (dialog->filter); + + g_free (dialog); +} + +static void +new_chatroom_dialog_model_setup (GossipNewChatroomDialog *dialog) +{ + GtkTreeView *view; + GtkListStore *store; + GtkTreeSelection *selection; + + /* View */ + view = GTK_TREE_VIEW (dialog->treeview); + + g_signal_connect (view, "row-activated", + G_CALLBACK (new_chatroom_dialog_model_row_activated_cb), + dialog); + + /* Store/Model */ + store = gtk_list_store_new (COL_COUNT, + G_TYPE_STRING, /* Image */ + G_TYPE_STRING, /* Text */ + G_TYPE_POINTER); /* infos */ + + dialog->model = GTK_TREE_MODEL (store); + + /* Filter */ + dialog->filter = gtk_tree_model_filter_new (dialog->model, NULL); + + gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (dialog->filter), + (GtkTreeModelFilterVisibleFunc) + new_chatroom_dialog_model_filter_func, + dialog, + NULL); + + gtk_tree_view_set_model (view, dialog->filter); + + g_signal_connect (dialog->filter, "row-inserted", + G_CALLBACK (new_chatroom_dialog_model_row_inserted_cb), + dialog); + g_signal_connect (dialog->filter, "row-deleted", + G_CALLBACK (new_chatroom_dialog_model_row_deleted_cb), + dialog); + + /* Selection */ + selection = gtk_tree_view_get_selection (view); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), + COL_NAME, GTK_SORT_ASCENDING); + + g_signal_connect (selection, "changed", + G_CALLBACK (new_chatroom_dialog_model_selection_changed), dialog); + + /* Columns */ + new_chatroom_dialog_model_add_columns (dialog); +} + +static void +new_chatroom_dialog_model_add_columns (GossipNewChatroomDialog *dialog) +{ + GtkTreeView *view; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + + view = GTK_TREE_VIEW (dialog->treeview); + gtk_tree_view_set_headers_visible (view, FALSE); + + /* Chatroom pointer */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, _("Chat Rooms")); + + cell = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, cell, FALSE); + + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, + "xpad", (guint) 4, + "ypad", (guint) 1, + "ellipsize", PANGO_ELLIPSIZE_END, + NULL); + + gtk_tree_view_column_pack_start (column, cell, TRUE); + + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); +} + +static void +new_chatroom_dialog_update_buttons (GossipNewChatroomDialog *dialog) +{ + GtkButton *button; + GtkWidget *image; + GtkTreeView *view; + GtkTreeModel *model; + guint items; + const gchar *room; + + /* Sort out Join button. */ + button = GTK_BUTTON (dialog->button_join); + + image = gtk_button_get_image (button); + if (!image) { + image = gtk_image_new (); + gtk_button_set_image (button, image); + } + //gtk_button_set_use_stock (button, FALSE); + + room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room)); + + /* Collect necessary information first. */ + view = GTK_TREE_VIEW (dialog->treeview); + model = gtk_tree_view_get_model (view); + items = gtk_tree_model_iter_n_children (model, NULL); + + if (items < 1 && !G_STR_EMPTY (room)) { + gtk_button_set_label (button, _("Create")); + gtk_image_set_from_stock (GTK_IMAGE (image), + GTK_STOCK_NEW, + GTK_ICON_SIZE_BUTTON); + } else { + gtk_button_set_label (button, _("Join")); + gtk_image_set_from_stock (GTK_IMAGE (image), + GTK_STOCK_EXECUTE, + GTK_ICON_SIZE_BUTTON); + } + + gtk_widget_set_sensitive (dialog->button_join, !G_STR_EMPTY (room)); +} + +static void +new_chatroom_dialog_update_widgets (GossipNewChatroomDialog *dialog) +{ + GossipAccountChooser *account_chooser; + McAccount *account; + McProfile *profile; + const gchar *protocol; + + account_chooser = GOSSIP_ACCOUNT_CHOOSER (dialog->account_chooser); + account = gossip_account_chooser_get_account (account_chooser); + profile = mc_account_get_profile (account); + protocol = mc_profile_get_protocol_name (profile); + + /* hardcode here known protocols */ + if (strcmp (protocol, "jabber") == 0 || + strcmp (protocol, "salut") == 0) { + gtk_widget_show (dialog->hbox_server); + gtk_widget_show (dialog->hbox_nick); + gtk_widget_show (dialog->vbox_browse); + } + else if (strcmp (protocol, "irc") == 0) { + gtk_widget_hide (dialog->hbox_server); + gtk_widget_hide (dialog->hbox_nick); + gtk_widget_show (dialog->vbox_browse); + } else { + gtk_widget_hide (dialog->hbox_server); + gtk_widget_hide (dialog->hbox_nick); + gtk_widget_hide (dialog->vbox_browse); + } + + new_chatroom_dialog_set_defaults (dialog); + new_chatroom_dialog_update_buttons (dialog); + + /* Final set up of the dialog */ + gtk_widget_grab_focus (dialog->entry_room); + + g_object_unref (account); + g_object_unref (profile); +} + +static void +new_chatroom_dialog_account_changed_cb (GtkComboBox *combobox, + GossipNewChatroomDialog *dialog) +{ + new_chatroom_dialog_update_widgets (dialog); +} + +static void +new_chatroom_dialog_model_add (GossipNewChatroomDialog *dialog, + EmpathyRoomListItem *item) +{ + GtkTreeView *view; + GtkTreeSelection *selection; + GtkListStore *store; + GtkTreeIter iter; + + /* Add to model */ + view = GTK_TREE_VIEW (dialog->treeview); + selection = gtk_tree_view_get_selection (view); + store = GTK_LIST_STORE (dialog->model); + + gtk_list_store_append (store, &iter); + + gtk_list_store_set (store, &iter, + COL_NAME, item->name, + COL_POINTER, item, + -1); +} + +static void +new_chatroom_dialog_model_clear (GossipNewChatroomDialog *dialog) +{ + GtkListStore *store; + + store = GTK_LIST_STORE (dialog->model); + gtk_list_store_clear (store); +} + +static GList * +new_chatroom_dialog_model_get_selected (GossipNewChatroomDialog *dialog) +{ + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GList *rows, *l; + GList *chatrooms = NULL; + + view = GTK_TREE_VIEW (dialog->treeview); + selection = gtk_tree_view_get_selection (view); + model = gtk_tree_view_get_model (view); + + rows = gtk_tree_selection_get_selected_rows (selection, NULL); + for (l = rows; l; l = l->next) { + GtkTreeIter iter; + EmpathyRoomListItem *chatroom; + + if (!gtk_tree_model_get_iter (model, &iter, l->data)) { + continue; + } + + gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1); + chatrooms = g_list_append (chatrooms, chatroom); + } + + g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL); + g_list_free (rows); + + return chatrooms; +} + +static gboolean +new_chatroom_dialog_model_filter_func (GtkTreeModel *model, + GtkTreeIter *iter, + GossipNewChatroomDialog *dialog) +{ + EmpathyRoomListItem *chatroom; + const gchar *text; + gchar *room_nocase; + gchar *text_nocase; + gboolean found = FALSE; + + gtk_tree_model_get (model, iter, COL_POINTER, &chatroom, -1); + + if (!chatroom) { + return TRUE; + } + + text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room)); + + /* Casefold */ + room_nocase = g_utf8_casefold (chatroom->id, -1); + text_nocase = g_utf8_casefold (text, -1); + + /* Compare */ + if (g_utf8_strlen (text_nocase, -1) < 1 || + strstr (room_nocase, text_nocase)) { + found = TRUE; + } + + g_free (room_nocase); + g_free (text_nocase); + + return found; +} + +static void +new_chatroom_dialog_model_row_activated_cb (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + GossipNewChatroomDialog *dialog) +{ + gtk_widget_activate (dialog->button_join); +} + +static void +new_chatroom_dialog_model_row_inserted_cb (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + GossipNewChatroomDialog *dialog) +{ + new_chatroom_dialog_update_buttons (dialog); +} + +static void +new_chatroom_dialog_model_row_deleted_cb (GtkTreeModel *model, + GtkTreePath *path, + GossipNewChatroomDialog *dialog) +{ + new_chatroom_dialog_update_buttons (dialog); +} + +static void +new_chatroom_dialog_model_selection_changed (GtkTreeSelection *selection, + GossipNewChatroomDialog *dialog) +{ + new_chatroom_dialog_update_buttons (dialog); +} + +static void +new_chatroom_dialog_set_defaults (GossipNewChatroomDialog *dialog) +{ + McAccount *account; + McProfile *profile; + GossipAccountChooser *account_chooser; + const gchar *server; + + account_chooser = GOSSIP_ACCOUNT_CHOOSER (dialog->account_chooser); + account = gossip_account_chooser_get_account (account_chooser); + profile = mc_account_get_profile (account); + server = mc_profile_get_default_account_domain (profile); + + if (server) { + gchar *conference_server; + + conference_server = g_strconcat ("conference.", + server, NULL); + gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), + conference_server); + g_free (conference_server); + } + + g_object_unref (account); + g_object_unref (profile); +} + +static void +new_chatroom_dialog_join (GossipNewChatroomDialog *dialog) +{ + McAccount *account; + GossipAccountChooser *account_chooser; + MissionControl *mc; + TpConn *tp_conn; + GList *chatrooms, *l; + const gchar *room; + const gchar *server; + gchar *room_name = NULL; + const gchar *room_names[2] = {NULL, NULL}; + + chatrooms = new_chatroom_dialog_model_get_selected (dialog); + if (chatrooms) { + for (l = chatrooms; l; l = l->next) { + /* Join it */ + } + g_list_free (chatrooms); + return; + } + + room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room)); + server = gtk_entry_get_text (GTK_ENTRY (dialog->entry_server)); + account_chooser = GOSSIP_ACCOUNT_CHOOSER (dialog->account_chooser); + account = gossip_account_chooser_get_account (account_chooser); + mc = gossip_mission_control_new (); + tp_conn = mission_control_get_connection (mc, account, NULL); + + if (!tp_conn) { + g_object_unref (mc); + return; + } + + if (!G_STR_EMPTY (server)) { + room_name = g_strconcat (room, "@", server, NULL); + room_names[0] = room_name; + } else { + room_names[0] = room; + } + + gossip_debug (DEBUG_DOMAIN, "Requesting handle for room '%s'", + room_names[0]); + + /* Gives the ref of account/tp_conn to the callback */ + tp_conn_request_handles_async (DBUS_G_PROXY (tp_conn), + TP_HANDLE_TYPE_ROOM, + room_names, + (tp_conn_request_handles_reply) + new_chatroom_dialog_request_handles_cb, + account); + g_free (room_name); + g_object_unref (mc); +} + +static void +new_chatroom_dialog_request_handles_cb (DBusGProxy *proxy, + GArray *handles, + GError *error, + McAccount *account) +{ + MissionControl *mc; + guint handle; + + if (error) { + gossip_debug (DEBUG_DOMAIN, + "Error requesting room handle: %s", + error ? error->message : "No error given"); + goto OUT; + } + + mc = gossip_mission_control_new (); + handle = g_array_index (handles, guint, 0); + + gossip_debug (DEBUG_DOMAIN, "Got handle %d, requesting channel", handle); + mission_control_request_channel (mc, + account, + TP_IFACE_CHANNEL_TYPE_TEXT, + handle, + TP_HANDLE_TYPE_ROOM, + NULL, NULL); + g_object_unref (mc); + +OUT: + g_object_unref (account); + g_object_unref (proxy); +} + +static void +new_chatroom_dialog_entry_changed_cb (GtkWidget *entry, + GossipNewChatroomDialog *dialog) +{ + if (entry == dialog->entry_room) { + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (dialog->filter)); + } + + new_chatroom_dialog_update_buttons (dialog); +} + +static void +new_chatroom_dialog_browse_start (GossipNewChatroomDialog *dialog) +{ + if (0) { + new_chatroom_dialog_model_clear (dialog); + new_chatroom_dialog_model_add (dialog, NULL); + } +} + +static void +new_chatroom_dialog_browse_stop (GossipNewChatroomDialog *dialog) +{ +} + +static void +new_chatroom_dialog_entry_server_activate_cb (GtkWidget *widget, + GossipNewChatroomDialog *dialog) +{ + new_chatroom_dialog_togglebutton_refresh_toggled_cb (dialog->togglebutton_refresh, + dialog); +} + +static void +new_chatroom_dialog_togglebutton_refresh_toggled_cb (GtkWidget *widget, + GossipNewChatroomDialog *dialog) +{ + gboolean toggled; + + toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + + if (toggled) { + new_chatroom_dialog_browse_start (dialog); + } else { + new_chatroom_dialog_browse_stop (dialog); + } +} + diff --git a/libempathy-gtk/gossip-new-chatroom-dialog.glade b/libempathy-gtk/gossip-new-chatroom-dialog.glade new file mode 100644 index 000000000..49bdadb64 --- /dev/null +++ b/libempathy-gtk/gossip-new-chatroom-dialog.glade @@ -0,0 +1,519 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkDialog" id="new_chatroom_dialog"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Join New</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">350</property> + <property name="resizable">False</property> + <property name="destroy_with_parent">False</property> + <property name="icon_name">gtk-new</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">False</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area4"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="button_cancel"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-7</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button_join"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + + <child> + <widget class="GtkAlignment" id="alignment4"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <property name="top_padding">0</property> + <property name="bottom_padding">0</property> + <property name="left_padding">0</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkHBox" id="hbox29"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-execute</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label79"> + <property name="visible">True</property> + <property name="label" translatable="yes">Join</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox_widgets"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">18</property> + + <child> + <widget class="GtkHBox" id="hbox_account"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkLabel" id="label_account"> + <property name="visible">True</property> + <property name="label" translatable="yes">Account:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox_browse"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox_server"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkLabel" id="label_server"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Server:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">entry_server</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entry_server"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <property name="width_chars">25</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkToggleButton" id="togglebutton_refresh"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Re_fresh</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox_room"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkLabel" id="label_room"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Room:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">entry_room</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entry_room"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Enter the room name to join here or click on one or more rooms in the list.</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">True</property> + <property name="width_chars">32</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox_nick"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkLabel" id="label_nick"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Nickname:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">entry_nick</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entry_nick"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox_browse"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox_status"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox35"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">3</property> + + <child> + <widget class="GtkImage" id="image_status"> + <property name="visible">True</property> + <property name="icon_size">2</property> + <property name="icon_name">gtk-find</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_status"> + <property name="visible">True</property> + <property name="label" translatable="yes">Browse:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <property name="height_request">150</property> + <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> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="treeview"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">This list represents all chat rooms hosted on the server you have entered.</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/libempathy-gtk/gossip-new-chatroom-dialog.h b/libempathy-gtk/gossip-new-chatroom-dialog.h new file mode 100644 index 000000000..44b7ce67f --- /dev/null +++ b/libempathy-gtk/gossip-new-chatroom-dialog.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006-2007 Imendio AB + * Copyright (C) 2007 Collabora Ltd. + * + * 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: Martyn Russell <martyn@imendio.com> + * Xavier Claessens <xclaesse@gmail.com> + */ + +#ifndef __GOSSIP_NEW_CHATROOMS_WINDOW_H__ +#define __GOSSIP_NEW_CHATROOMS_WINDOW_H__ + +G_BEGIN_DECLS + +void gossip_new_chatroom_dialog_show (GtkWindow *parent); + +G_END_DECLS + +#endif /* __GOSSIP_NEW_CHATROOMS_WINDOW_H__ */ |