diff options
29 files changed, 2443 insertions, 178 deletions
@@ -1,3 +1,50 @@ +2007-05-31 Xavier Claessens <xclaesse@gmail.com> + + * libempathy-gtk/gossip-account-chooser.c: Fix warning when selecting + all accounts. + + * src/empathy-accounts-main.c: + * libempathy-gtk/empathy-status-icon.c: + * libempathy-gtk/gossip-accounts-dialog.h: + * libempathy-gtk/gossip-accounts-dialog.c: + * libempathy-gtk/gossip-preferences.h: + * libempathy-gtk/gossip-preferences.c: Set parent window. + + * libempathy-gtk/empathy-main-window.c: Implement favorite chatroom + menu and fix a leak. + + * libempathy-gtk/Makefile.am: + * libempathy/Makefile.am: + * libempathy/gossip-chatroom.c: + * libempathy/gossip-chatroom.h: + * libempathy/gossip-chatroom-manager.c: + * libempathy/gossip-chatroom-manager.h: + * libempathy/gossip-chatroom-manager.dtd: + * libempathy-gtk/gossip-chatrooms-window.glade: + * libempathy-gtk/gossip-chatrooms-window.c: + * libempathy-gtk/gossip-chatrooms-window.h: New files to implement + favorite chatrooms and a window to show them. + + + * libempathy-gtk/gossip-chat.c: Fix tooltip leaked. + + * libempathy-gtk/gossip-chat-window.h: + * libempathy-gtk/gossip-chat-window.c: Do not use deprecated + gtk_object_sink(). Implement favorite chatroom features. Find a chat + by comparing the account AND the chat ID. + + * src/empathy-chat-main.c: + * libempathy/empathy-tp-chat.h: + * libempathy/empathy-tp-chat.c: + * libempathy/gossip-utils.h: + * libempathy/gossip-utils.c: empathy_tp_chat_get_id() returns the Text + channel's name. The chat ID is unique only for a specified account. + + * libempathy/empathy-tp-contact-list.c: Fix some leaks and add a FIXME + comment for a leak not yet fixed. + + * TODO: Would be cool to have a glade catalog for libempathy-gtk. + 2007-05-26 Xavier Claessens <xclaesse@gmail.com> * libempathy-gtk/gossip-contact-list-store.c: Do not highlight contacts @@ -3,7 +3,7 @@ Things you can do if you want to help: - Rename all files and functions name to use the empathy namespace. - Porting gossip-account-widget-*.{c,h} from gossip project (Guillaume is already working on IRC widget). - Porting various UI widgets from gossip to libempathy-gtk for contact info, adding contact, personal info, etc. - - GtkWidget-ify gossip widgets imported in libempathy-gtk. Actually most window/dialog do not inherit from GtkWindow/GtkDialog... + - GtkWidget-ify gossip widgets imported in libempathy-gtk. Actually most window/dialog do not inherit from GtkWindow/GtkDialog. Need to create a glade catalog. - Fix setting subscription for contacts in EmpathyTpContactList. - Filter channels before dispatching them. For example we need a GtkStatusIcon that blink when an event arrives (text/voip/ft channel) and tells the MC to dispatch the channel only when the user clicked the icon. Like in gossip. For that we need a filter DBus API in MC, not yet written. - Make use of NetworkManager to set the presence diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am index f28e7411c..183f7d8e2 100644 --- a/libempathy-gtk/Makefile.am +++ b/libempathy-gtk/Makefile.am @@ -34,6 +34,7 @@ libempathy_gtk_la_SOURCES = \ 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-chatrooms-window.c gossip-chatrooms-window.h \ gossip-ui-utils.c gossip-ui-utils.h libempathy_gtk_la_LIBADD = \ @@ -52,6 +53,7 @@ glade_DATA = \ gossip-account-widget-jabber.glade \ gossip-new-chatroom-dialog.glade \ gossip-group-chat.glade \ + gossip-chatrooms-window.glade \ gossip-chat.glade dtddir = $(datadir)/empathy diff --git a/libempathy-gtk/empathy-main-window.c b/libempathy-gtk/empathy-main-window.c index b10f6c8d6..befe2f531 100644 --- a/libempathy-gtk/empathy-main-window.c +++ b/libempathy-gtk/empathy-main-window.c @@ -31,6 +31,8 @@ #include <libempathy/gossip-contact.h> #include <libempathy/gossip-debug.h> #include <libempathy/gossip-utils.h> +#include <libempathy/gossip-chatroom-manager.h> +#include <libempathy/gossip-chatroom.h> #include <libempathy/empathy-contact-list.h> #include <libempathy/empathy-contact-manager.h> @@ -46,6 +48,7 @@ #include "gossip-accounts-dialog.h" #include "gossip-about-dialog.h" #include "gossip-new-chatroom-dialog.h" +#include "gossip-chatrooms-window.h" #define DEBUG_DOMAIN "MainWindow" @@ -62,6 +65,7 @@ typedef struct { GossipContactListView *list_view; GossipContactListStore *list_store; MissionControl *mc; + GossipChatroomManager *chatroom_manager; /* Main widgets */ GtkWidget *window; @@ -93,68 +97,79 @@ typedef struct { guint size_timeout_id; } EmpathyMainWindow; -static void main_window_destroy_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_favorite_chatroom_menu_setup (void); -static void main_window_chat_quit_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_chat_new_message_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_chat_history_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_room_join_new_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_room_join_favorites_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_room_manage_favorites_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_chat_add_contact_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_chat_show_offline_cb (GtkCheckMenuItem *item, - EmpathyMainWindow *window); -static gboolean main_window_edit_button_press_event_cb (GtkWidget *widget, - GdkEventButton *event, - EmpathyMainWindow *window); -static void main_window_edit_accounts_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_edit_personal_information_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_edit_preferences_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_help_about_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static void main_window_help_contents_cb (GtkWidget *widget, - EmpathyMainWindow *window); -static gboolean main_window_throbber_button_press_event_cb (GtkWidget *throbber_ebox, - GdkEventButton *event, - gpointer user_data); -static void main_window_status_changed_cb (MissionControl *mc, - TelepathyConnectionStatus status, - McPresence presence, - TelepathyConnectionStatusReason reason, - const gchar *unique_name, - EmpathyMainWindow *window); -static void main_window_update_status (EmpathyMainWindow *window); -static void main_window_accels_load (void); -static void main_window_accels_save (void); -static void main_window_connection_items_setup (EmpathyMainWindow *window, - GladeXML *glade); -static gboolean main_window_configure_event_timeout_cb (EmpathyMainWindow *window); -static gboolean main_window_configure_event_cb (GtkWidget *widget, - GdkEventConfigure *event, - EmpathyMainWindow *window); -static void main_window_notify_show_offline_cb (GossipConf *conf, - const gchar *key, - gpointer check_menu_item); -static void main_window_notify_show_avatars_cb (GossipConf *conf, - const gchar *key, - EmpathyMainWindow *window); -static void main_window_notify_compact_contact_list_cb (GossipConf *conf, - const gchar *key, - EmpathyMainWindow *window); -static void main_window_notify_sort_criterium_cb (GossipConf *conf, - const gchar *key, - EmpathyMainWindow *window); +static void main_window_destroy_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_favorite_chatroom_menu_setup (EmpathyMainWindow *window); +static void main_window_favorite_chatroom_menu_added_cb (GossipChatroomManager *manager, + GossipChatroom *chatroom, + EmpathyMainWindow *window); +static void main_window_favorite_chatroom_menu_removed_cb (GossipChatroomManager *manager, + GossipChatroom *chatroom, + EmpathyMainWindow *window); +static void main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem *menu_item, + GossipChatroom *chatroom); +static void main_window_favorite_chatroom_menu_update (EmpathyMainWindow *window); +static void main_window_favorite_chatroom_menu_add (EmpathyMainWindow *window, + GossipChatroom *chatroom); +static void main_window_chat_quit_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_chat_new_message_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_chat_history_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_room_join_new_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_room_join_favorites_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_room_manage_favorites_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_chat_add_contact_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_chat_show_offline_cb (GtkCheckMenuItem *item, + EmpathyMainWindow *window); +static gboolean main_window_edit_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + EmpathyMainWindow *window); +static void main_window_edit_accounts_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_edit_personal_information_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_edit_preferences_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_help_about_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static void main_window_help_contents_cb (GtkWidget *widget, + EmpathyMainWindow *window); +static gboolean main_window_throbber_button_press_event_cb (GtkWidget *throbber_ebox, + GdkEventButton *event, + EmpathyMainWindow *window); +static void main_window_status_changed_cb (MissionControl *mc, + TelepathyConnectionStatus status, + McPresence presence, + TelepathyConnectionStatusReason reason, + const gchar *unique_name, + EmpathyMainWindow *window); +static void main_window_update_status (EmpathyMainWindow *window); +static void main_window_accels_load (void); +static void main_window_accels_save (void); +static void main_window_connection_items_setup (EmpathyMainWindow *window, + GladeXML *glade); +static gboolean main_window_configure_event_timeout_cb (EmpathyMainWindow *window); +static gboolean main_window_configure_event_cb (GtkWidget *widget, + GdkEventConfigure *event, + EmpathyMainWindow *window); +static void main_window_notify_show_offline_cb (GossipConf *conf, + const gchar *key, + gpointer check_menu_item); +static void main_window_notify_show_avatars_cb (GossipConf *conf, + const gchar *key, + EmpathyMainWindow *window); +static void main_window_notify_compact_contact_list_cb (GossipConf *conf, + const gchar *key, + EmpathyMainWindow *window); +static void main_window_notify_sort_criterium_cb (GossipConf *conf, + const gchar *key, + EmpathyMainWindow *window); GtkWidget * empathy_main_window_show (void) @@ -227,7 +242,7 @@ empathy_main_window_show (void) window, NULL); /* Set up menu */ - main_window_favorite_chatroom_menu_setup (); + main_window_favorite_chatroom_menu_setup (window); gtk_widget_hide (window->edit_context); gtk_widget_hide (window->edit_context_separator); @@ -263,7 +278,7 @@ empathy_main_window_show (void) g_signal_connect (ebox, "button-press-event", G_CALLBACK (main_window_throbber_button_press_event_cb), - NULL); + window); /* Set up contact list. */ gossip_status_presets_get_all (); @@ -374,8 +389,116 @@ main_window_destroy_cb (GtkWidget *widget, } static void -main_window_favorite_chatroom_menu_setup (void) +main_window_favorite_chatroom_menu_setup (EmpathyMainWindow *window) { + GList *chatrooms, *l; + + window->chatroom_manager = gossip_chatroom_manager_new (); + chatrooms = gossip_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL); + window->room_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (window->room)); + + for (l = chatrooms; l; l = l->next) { + main_window_favorite_chatroom_menu_add (window, l->data); + } + + if (!chatrooms) { + gtk_widget_hide (window->room_sep); + } + + gtk_widget_set_sensitive (window->room_join_favorites, chatrooms != NULL); + + g_signal_connect (window->chatroom_manager, "chatroom-added", + G_CALLBACK (main_window_favorite_chatroom_menu_added_cb), + window); + g_signal_connect (window->chatroom_manager, "chatroom-removed", + G_CALLBACK (main_window_favorite_chatroom_menu_removed_cb), + window); + + g_list_free (chatrooms); +} + +static void +main_window_favorite_chatroom_menu_added_cb (GossipChatroomManager *manager, + GossipChatroom *chatroom, + EmpathyMainWindow *window) +{ + main_window_favorite_chatroom_menu_add (window, chatroom); + gtk_widget_show (window->room_sep); + gtk_widget_set_sensitive (window->room_join_favorites, TRUE); +} + +static void +main_window_favorite_chatroom_menu_removed_cb (GossipChatroomManager *manager, + GossipChatroom *chatroom, + EmpathyMainWindow *window) +{ + GtkWidget *menu_item; + + menu_item = g_object_get_data (G_OBJECT (chatroom), "menu_item"); + + g_object_set_data (G_OBJECT (chatroom), "menu_item", NULL); + gtk_widget_destroy (menu_item); + + main_window_favorite_chatroom_menu_update (window); +} + +static void +main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem *menu_item, + GossipChatroom *chatroom) +{ +/*FIXME: + GossipSession *session; + GossipAccount *account; + GossipChatroomProvider *provider; + + session = gossip_app_get_session (); + account = gossip_chatroom_get_account (chatroom); + provider = gossip_session_get_chatroom_provider (session, account); + + gossip_group_chat_new (provider, chatroom); +*/ +} + +static void +main_window_favorite_chatroom_menu_update (EmpathyMainWindow *window) +{ + GList *chatrooms; + + chatrooms = gossip_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL); + + if (chatrooms) { + gtk_widget_show (window->room_sep); + } else { + gtk_widget_hide (window->room_sep); + } + + gtk_widget_set_sensitive (window->room_join_favorites, chatrooms != NULL); + g_list_free (chatrooms); +} + +static void +main_window_favorite_chatroom_menu_add (EmpathyMainWindow *window, + GossipChatroom *chatroom) +{ + GtkWidget *menu_item; + const gchar *name; + + if (g_object_get_data (G_OBJECT (chatroom), "menu_item")) { + return; + } + + name = gossip_chatroom_get_name (chatroom); + menu_item = gtk_menu_item_new_with_label (name); + + g_object_set_data (G_OBJECT (chatroom), "menu_item", menu_item); + g_signal_connect (menu_item, "activate", + G_CALLBACK (main_window_favorite_chatroom_menu_activate_cb), + chatroom); + + gtk_menu_shell_insert (GTK_MENU_SHELL (window->room_menu), + menu_item, 3); + + gtk_widget_show (menu_item); } static void @@ -417,7 +540,7 @@ static void main_window_room_manage_favorites_cb (GtkWidget *widget, EmpathyMainWindow *window) { - //gossip_chatrooms_window_show (NULL, FALSE); + gossip_chatrooms_window_show (GTK_WINDOW (window->window)); } static void @@ -510,7 +633,7 @@ static void main_window_edit_accounts_cb (GtkWidget *widget, EmpathyMainWindow *window) { - gossip_accounts_dialog_show (); + gossip_accounts_dialog_show (GTK_WINDOW (window->window)); } static void @@ -524,7 +647,7 @@ static void main_window_edit_preferences_cb (GtkWidget *widget, EmpathyMainWindow *window) { - gossip_preferences_show (); + gossip_preferences_show (GTK_WINDOW (window->window)); } static void @@ -542,16 +665,16 @@ main_window_help_contents_cb (GtkWidget *widget, } static gboolean -main_window_throbber_button_press_event_cb (GtkWidget *throbber_ebox, - GdkEventButton *event, - gpointer user_data) +main_window_throbber_button_press_event_cb (GtkWidget *throbber_ebox, + GdkEventButton *event, + EmpathyMainWindow *window) { if (event->type != GDK_BUTTON_PRESS || event->button != 1) { return FALSE; } - gossip_accounts_dialog_show (); + gossip_accounts_dialog_show (GTK_WINDOW (window->window)); return FALSE; } @@ -614,8 +737,6 @@ main_window_update_status (EmpathyMainWindow *window) for (l = window->widgets_disconnected; l; l = l->next) { gtk_widget_set_sensitive (l->data, (disconnected > 0)); } - - //app_favorite_chatroom_menu_update (); } /* @@ -768,6 +889,7 @@ main_window_notify_sort_criterium_cb (GossipConf *conf, type = gossip_contact_list_store_sort_get_type (); enum_class = G_ENUM_CLASS (g_type_class_peek (type)); enum_value = g_enum_get_value_by_nick (enum_class, str); + g_free (str); if (enum_value) { gossip_contact_list_store_set_sort_criterium (window->list_store, diff --git a/libempathy-gtk/empathy-status-icon.c b/libempathy-gtk/empathy-status-icon.c index 21082276a..01a542493 100644 --- a/libempathy-gtk/empathy-status-icon.c +++ b/libempathy-gtk/empathy-status-icon.c @@ -231,7 +231,7 @@ status_icon_toggle_visibility (EmpathyStatusIcon *icon) } else { gossip_debug (DEBUG_DOMAIN, "No enabled account, Showing account dialog"); - gossip_accounts_dialog_show (); + gossip_accounts_dialog_show (GTK_WINDOW (priv->window)); } } } diff --git a/libempathy-gtk/gossip-account-chooser.c b/libempathy-gtk/gossip-account-chooser.c index 9cb8e5d41..dfed1bb54 100644 --- a/libempathy-gtk/gossip-account-chooser.c +++ b/libempathy-gtk/gossip-account-chooser.c @@ -593,6 +593,9 @@ account_chooser_set_account_foreach (GtkTreeModel *model, /* Special case so we can make it possible to select the All option */ if (!data->account && !account) { equal = TRUE; + } + else if ((data->account && !account) || (!data->account && account)) { + equal = FALSE; } else { equal = gossip_account_equal (data->account, account); g_object_unref (account); diff --git a/libempathy-gtk/gossip-accounts-dialog.c b/libempathy-gtk/gossip-accounts-dialog.c index 6d7934544..2a3a92764 100644 --- a/libempathy-gtk/gossip-accounts-dialog.c +++ b/libempathy-gtk/gossip-accounts-dialog.c @@ -944,7 +944,7 @@ accounts_dialog_destroy_cb (GtkWidget *widget, } GtkWidget * -gossip_accounts_dialog_show (void) +gossip_accounts_dialog_show (GtkWindow *parent) { static GossipAccountsDialog *dialog = NULL; GladeXML *glade; @@ -1026,6 +1026,11 @@ gossip_accounts_dialog_show (void) accounts_dialog_setup (dialog); accounts_dialog_model_select_first (dialog); + if (parent) { + gtk_window_set_transient_for (GTK_WINDOW (dialog->window), + GTK_WINDOW (parent)); + } + gtk_widget_show (dialog->window); return dialog->window; diff --git a/libempathy-gtk/gossip-accounts-dialog.h b/libempathy-gtk/gossip-accounts-dialog.h index e78b33506..5b058e6a4 100644 --- a/libempathy-gtk/gossip-accounts-dialog.h +++ b/libempathy-gtk/gossip-accounts-dialog.h @@ -28,7 +28,7 @@ G_BEGIN_DECLS -GtkWidget *gossip_accounts_dialog_show (void); +GtkWidget *gossip_accounts_dialog_show (GtkWindow *parent); G_END_DECLS diff --git a/libempathy-gtk/gossip-chat-window.c b/libempathy-gtk/gossip-chat-window.c index 35f3f9ae7..6979e450e 100644 --- a/libempathy-gtk/gossip-chat-window.c +++ b/libempathy-gtk/gossip-chat-window.c @@ -36,10 +36,12 @@ #include <libempathy/empathy-contact-manager.h> #include <libempathy/empathy-contact-list.h> +#include <libempathy/gossip-chatroom-manager.h> #include <libempathy/gossip-contact.h> #include <libempathy/gossip-debug.h> #include <libempathy/gossip-message.h> #include <libempathy/gossip-conf.h> +#include <libempathy/gossip-utils.h> #include "gossip-chat-window.h" #include "empathy-images.h" @@ -274,8 +276,7 @@ gossip_chat_window_init (GossipChatWindow *window) priv = GET_PRIV (window); - priv->tooltips = g_object_ref (gtk_tooltips_new ()); - gtk_object_sink (GTK_OBJECT (priv->tooltips)); + priv->tooltips = g_object_ref_sink (gtk_tooltips_new ()); glade = gossip_glade_get_file ("gossip-chat.glade", "chat_window", @@ -762,9 +763,10 @@ chat_window_update_menu (GossipChatWindow *window) is_connected = gossip_chat_is_connected (priv->current_chat); if (gossip_chat_is_group_chat (priv->current_chat)) { - GossipGroupChat *group_chat; - gboolean saved = TRUE; - gboolean show_contacts; + GossipGroupChat *group_chat; + GossipChatroom *chatroom; + GossipChatroomManager *manager; + gboolean show_contacts; group_chat = GOSSIP_GROUP_CHAT (priv->current_chat); @@ -778,13 +780,13 @@ chat_window_update_menu (GossipChatWindow *window) /* Can we add this room to our favourites and are we * connected to the room? */ - /* FIXME: - manager = gossip_app_get_chatroom_manager (); - id = gossip_chatroom_get_id (chatroom); - saved = gossip_chatroom_manager_find (manager, id) != NULL; - */ + manager = gossip_chatroom_manager_new (); + chatroom = gossip_chatroom_manager_find (manager, + priv->current_chat->account, + gossip_chat_get_id (priv->current_chat)); + g_object_unref (manager); - gtk_widget_set_sensitive (priv->menu_room_add, !saved); + gtk_widget_set_sensitive (priv->menu_room_add, chatroom == NULL); gtk_widget_set_sensitive (priv->menu_conv_insert_smiley, is_connected); gtk_widget_set_sensitive (priv->menu_room_join_new, is_connected); gtk_widget_set_sensitive (priv->menu_room_invite, is_connected); @@ -1079,9 +1081,7 @@ static void chat_window_room_add_activate_cb (GtkWidget *menuitem, GossipChatWindow *window) { -/* FIXME: GossipChatWindowPriv *priv; - GossipGroupChat *group_chat; GossipChatroomManager *manager; GossipChatroom *chatroom; @@ -1093,16 +1093,17 @@ chat_window_room_add_activate_cb (GtkWidget *menuitem, return; } - group_chat = GOSSIP_GROUP_CHAT (priv->current_chat); - chatroom = gossip_group_chat_get_chatroom (group_chat); - gossip_chatroom_set_favourite (chatroom, TRUE); + chatroom = gossip_chatroom_new_full (priv->current_chat->account, + gossip_chat_get_id (priv->current_chat), + gossip_chat_get_name (priv->current_chat), + FALSE); - manager = gossip_app_get_chatroom_manager (); + manager = gossip_chatroom_manager_new (); gossip_chatroom_manager_add (manager, chatroom); - gossip_chatroom_manager_store (manager); - chat_window_update_menu (window); -*/ + + g_object_unref (chatroom); + g_object_unref (manager); } static void @@ -1597,7 +1598,6 @@ chat_window_drag_data_received (GtkWidget *widget, GossipChatWindow *old_window; McAccount *account; const gchar *id = NULL; - gchar *chat_id; if (selection) { id = (const gchar*) selection->data; @@ -1615,10 +1615,8 @@ chat_window_drag_data_received (GtkWidget *widget, } account = gossip_contact_get_account (contact); - chat_id = empathy_tp_chat_build_id (account, id); - chat = gossip_chat_window_find_chat_by_id (chat_id); + chat = gossip_chat_window_find_chat (account, id); old_window = gossip_chat_get_window (chat); - g_free (chat_id); if (old_window) { if (old_window == window) { @@ -1882,7 +1880,8 @@ gossip_chat_window_has_focus (GossipChatWindow *window) } GossipChat * -gossip_chat_window_find_chat_by_id (const gchar *id) +gossip_chat_window_find_chat (McAccount *account, + const gchar *id) { GList *l; @@ -1899,7 +1898,8 @@ gossip_chat_window_find_chat_by_id (const gchar *id) chat = ll->data; - if (strcmp (id, gossip_chat_get_id (chat)) == 0) { + if (gossip_account_equal (account, chat->account) && + strcmp (id, gossip_chat_get_id (chat)) == 0) { return chat; } } diff --git a/libempathy-gtk/gossip-chat-window.h b/libempathy-gtk/gossip-chat-window.h index 18b06ad90..b58e5dac3 100644 --- a/libempathy-gtk/gossip-chat-window.h +++ b/libempathy-gtk/gossip-chat-window.h @@ -30,6 +30,8 @@ #include <glib-object.h> +#include <libmissioncontrol/mc-account.h> + G_BEGIN_DECLS #define GOSSIP_TYPE_CHAT_WINDOW (gossip_chat_window_get_type ()) @@ -70,7 +72,8 @@ void gossip_chat_window_move_chat (GossipChatWindow *old_wind void gossip_chat_window_switch_to_chat (GossipChatWindow *window, GossipChat *chat); gboolean gossip_chat_window_has_focus (GossipChatWindow *window); -GossipChat * gossip_chat_window_find_chat_by_id (const gchar *id); +GossipChat * gossip_chat_window_find_chat (McAccount *account, + const gchar *id); G_END_DECLS diff --git a/libempathy-gtk/gossip-chat.c b/libempathy-gtk/gossip-chat.c index 4072b6eae..a29c31818 100644 --- a/libempathy-gtk/gossip-chat.c +++ b/libempathy-gtk/gossip-chat.c @@ -228,7 +228,7 @@ gossip_chat_init (GossipChat *chat) priv = GET_PRIV (chat); priv->manager = empathy_contact_manager_new (); - priv->tooltips = gtk_tooltips_new (); + priv->tooltips = g_object_ref_sink (gtk_tooltips_new ()); priv->default_window_height = -1; priv->vscroll_visible = FALSE; priv->sensitive = TRUE; @@ -337,6 +337,7 @@ chat_finalize (GObject *object) chat_composing_remove_timeout (chat); g_object_unref (chat->account); g_object_unref (priv->manager); + g_object_unref (priv->tooltips); if (priv->tp_chat) { g_object_unref (priv->tp_chat); diff --git a/libempathy-gtk/gossip-chatrooms-window.c b/libempathy-gtk/gossip-chatrooms-window.c new file mode 100644 index 000000000..5ff5d8812 --- /dev/null +++ b/libempathy-gtk/gossip-chatrooms-window.c @@ -0,0 +1,530 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2004-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: Xavier Claessens <xclaesse@gmail.com> + * Martyn Russell <martyn@imendio.com> + * Mikael Hallendal <micke@imendio.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 <libempathy/gossip-chatroom-manager.h> +#include <libempathy/gossip-utils.h> + +#include "gossip-account-chooser.h" +#include "gossip-chatrooms-window.h" +//#include "gossip-edit-chatroom-dialog.h" +#include "gossip-new-chatroom-dialog.h" +#include "gossip-ui-utils.h" + +typedef struct { + GossipChatroomManager *manager; + + GtkWidget *window; + GtkWidget *hbox_account; + GtkWidget *label_account; + GtkWidget *account_chooser; + GtkWidget *treeview; + GtkWidget *button_remove; + GtkWidget *button_edit; + GtkWidget *button_close; + + gint room_column; +} GossipChatroomsWindow; + +static void chatrooms_window_destroy_cb (GtkWidget *widget, + GossipChatroomsWindow *window); +static void chatrooms_window_model_setup (GossipChatroomsWindow *window); +static void chatrooms_window_model_add_columns (GossipChatroomsWindow *window); +static void chatrooms_window_model_refresh_data (GossipChatroomsWindow *window, + gboolean first_time); +static void chatrooms_window_model_add (GossipChatroomsWindow *window, + GossipChatroom *chatroom, + gboolean set_active); +static void chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle *cell, + gchar *path_string, + GossipChatroomsWindow *window); +static GossipChatroom * chatrooms_window_model_get_selected (GossipChatroomsWindow *window); +static void chatrooms_window_model_action_selected (GossipChatroomsWindow *window); +static void chatrooms_window_row_activated_cb (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + GossipChatroomsWindow *window); +static void chatrooms_window_button_remove_clicked_cb (GtkWidget *widget, + GossipChatroomsWindow *window); +static void chatrooms_window_button_edit_clicked_cb (GtkWidget *widget, + GossipChatroomsWindow *window); +static void chatrooms_window_button_close_clicked_cb (GtkWidget *widget, + GossipChatroomsWindow *window); +static void chatrooms_window_chatroom_added_cb (GossipChatroomManager *manager, + GossipChatroom *chatroom, + GossipChatroomsWindow *window); +static void chatrooms_window_account_changed_cb (GtkWidget *combo_box, + GossipChatroomsWindow *window); + +enum { + COL_IMAGE, + COL_NAME, + COL_ROOM, + COL_AUTO_CONNECT, + COL_POINTER, + COL_COUNT +}; + +void +gossip_chatrooms_window_show (GtkWindow *parent) +{ + static GossipChatroomsWindow *window = NULL; + GladeXML *glade; + + if (window) { + gtk_window_present (GTK_WINDOW (window->window)); + return; + } + + window = g_new0 (GossipChatroomsWindow, 1); + + glade = gossip_glade_get_file ("gossip-chatrooms-window.glade", + "chatrooms_window", + NULL, + "chatrooms_window", &window->window, + "hbox_account", &window->hbox_account, + "label_account", &window->label_account, + "treeview", &window->treeview, + "button_edit", &window->button_edit, + "button_remove", &window->button_remove, + "button_close", &window->button_close, + NULL); + + gossip_glade_connect (glade, + window, + "chatrooms_window", "destroy", chatrooms_window_destroy_cb, + "button_remove", "clicked", chatrooms_window_button_remove_clicked_cb, + "button_edit", "clicked", chatrooms_window_button_edit_clicked_cb, + "button_close", "clicked", chatrooms_window_button_close_clicked_cb, + NULL); + + g_object_unref (glade); + + g_object_add_weak_pointer (G_OBJECT (window->window), (gpointer) &window); + + /* Get the session and chat room manager */ + window->manager = gossip_chatroom_manager_new (); + + g_signal_connect (window->manager, "chatroom-added", + G_CALLBACK (chatrooms_window_chatroom_added_cb), + window); + + /* Account chooser for chat rooms */ + window->account_chooser = gossip_account_chooser_new (); + gossip_account_chooser_set_account (GOSSIP_ACCOUNT_CHOOSER (window->account_chooser), NULL); + g_object_set (window->account_chooser, + "can-select-all", TRUE, + "has-all-option", TRUE, + NULL); + + gtk_box_pack_start (GTK_BOX (window->hbox_account), + window->account_chooser, + TRUE, TRUE, 0); + + g_signal_connect (window->account_chooser, "changed", + G_CALLBACK (chatrooms_window_account_changed_cb), + window); + + gtk_widget_show (window->account_chooser); + + /* Set up chatrooms */ + chatrooms_window_model_setup (window); + + /* Set focus */ + gtk_widget_grab_focus (window->treeview); + + /* Last touches */ + if (parent) { + gtk_window_set_transient_for (GTK_WINDOW (window->window), + GTK_WINDOW (parent)); + } + + gtk_widget_show (window->window); +} + +static void +chatrooms_window_destroy_cb (GtkWidget *widget, + GossipChatroomsWindow *window) +{ + g_object_unref (window->manager); + g_free (window); +} + +static void +chatrooms_window_model_setup (GossipChatroomsWindow *window) +{ + GtkTreeView *view; + GtkListStore *store; + GtkTreeSelection *selection; + + /* View */ + view = GTK_TREE_VIEW (window->treeview); + + g_signal_connect (view, "row-activated", + G_CALLBACK (chatrooms_window_row_activated_cb), + window); + + /* Store */ + store = gtk_list_store_new (COL_COUNT, + G_TYPE_STRING, /* Image */ + G_TYPE_STRING, /* Name */ + G_TYPE_STRING, /* Room */ + G_TYPE_BOOLEAN, /* Auto start */ + GOSSIP_TYPE_CHATROOM); /* Chatroom */ + + gtk_tree_view_set_model (view, GTK_TREE_MODEL (store)); + + /* Selection */ + selection = gtk_tree_view_get_selection (view); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + /* Columns */ + chatrooms_window_model_add_columns (window); + + /* Add data */ + chatrooms_window_model_refresh_data (window, TRUE); + + /* Clean up */ + g_object_unref (store); +} + +static void +chatrooms_window_model_add_columns (GossipChatroomsWindow *window) +{ + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + gint count; + + view = GTK_TREE_VIEW (window->treeview); + model = gtk_tree_view_get_model (view); + + gtk_tree_view_set_headers_visible (view, TRUE); + gtk_tree_view_set_headers_clickable (view, TRUE); + + /* Name & Status */ + column = gtk_tree_view_column_new (); + count = gtk_tree_view_append_column (view, column); + + gtk_tree_view_column_set_title (column, _("Name")); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_column_set_sort_column_id (column, count - 1); + + cell = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, cell, FALSE); + gtk_tree_view_column_add_attribute (column, cell, "icon-name", COL_IMAGE); + + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, + "xpad", 4, + "ypad", 1, + NULL); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME); + + /* Room */ + cell = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (_("Room"), cell, + "text", COL_ROOM, + NULL); + count = gtk_tree_view_append_column (view, column); + gtk_tree_view_column_set_sort_column_id (column, count - 1); + window->room_column = count - 1; + + /* Chatroom auto connect */ + cell = gtk_cell_renderer_toggle_new (); + column = gtk_tree_view_column_new_with_attributes (_("Auto Connect"), cell, + "active", COL_AUTO_CONNECT, + NULL); + count = gtk_tree_view_append_column (view, column); + gtk_tree_view_column_set_sort_column_id (column, count - 1); + + g_signal_connect (cell, "toggled", + G_CALLBACK (chatrooms_window_model_cell_auto_connect_toggled), + window); + + /* Sort model */ + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), 0, + GTK_SORT_ASCENDING); +} + +static void +chatrooms_window_model_refresh_data (GossipChatroomsWindow *window, + gboolean first_time) +{ + GtkTreeView *view; + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkListStore *store; + GtkTreeIter iter; + GtkTreeViewColumn *column; + GossipAccountChooser *account_chooser; + McAccount *account; + GList *chatrooms, *l; + + view = GTK_TREE_VIEW (window->treeview); + selection = gtk_tree_view_get_selection (view); + model = gtk_tree_view_get_model (view); + store = GTK_LIST_STORE (model); + + /* Look up chatrooms */ + account_chooser = GOSSIP_ACCOUNT_CHOOSER (window->account_chooser); + account = gossip_account_chooser_get_account (account_chooser); + + chatrooms = gossip_chatroom_manager_get_chatrooms (window->manager, account); + + /* Sort out columns, we only show the server column for + * selected protocol types, such as Jabber. + */ + if (account) { + column = gtk_tree_view_get_column (view, window->room_column); + gtk_tree_view_column_set_visible (column, TRUE); + } else { + column = gtk_tree_view_get_column (view, window->room_column); + gtk_tree_view_column_set_visible (column, FALSE); + } + + /* Clean out the store */ + gtk_list_store_clear (store); + + /* Populate with chatroom list. */ + for (l = chatrooms; l; l = l->next) { + chatrooms_window_model_add (window, l->data, FALSE); + } + + if (gtk_tree_model_get_iter_first (model, &iter)) { + gtk_tree_selection_select_iter (selection, &iter); + } + + if (account) { + g_object_unref (account); + } + + g_list_free (chatrooms); +} + +static void +chatrooms_window_model_add (GossipChatroomsWindow *window, + GossipChatroom *chatroom, + gboolean set_active) +{ + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkListStore *store; + GtkTreeIter iter; + + view = GTK_TREE_VIEW (window->treeview); + selection = gtk_tree_view_get_selection (view); + model = gtk_tree_view_get_model (view); + store = GTK_LIST_STORE (model); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COL_NAME, gossip_chatroom_get_name (chatroom), + COL_ROOM, gossip_chatroom_get_room (chatroom), + COL_AUTO_CONNECT, gossip_chatroom_get_auto_connect (chatroom), + COL_POINTER, chatroom, + -1); + + if (set_active) { + gtk_tree_selection_select_iter (selection, &iter); + } +} + +static void +chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle *cell, + gchar *path_string, + GossipChatroomsWindow *window) +{ + GossipChatroom *chatroom; + gboolean enabled; + GtkTreeView *view; + GtkTreeModel *model; + GtkListStore *store; + GtkTreePath *path; + GtkTreeIter iter; + + view = GTK_TREE_VIEW (window->treeview); + model = gtk_tree_view_get_model (view); + store = GTK_LIST_STORE (model); + + path = gtk_tree_path_new_from_string (path_string); + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + COL_AUTO_CONNECT, &enabled, + COL_POINTER, &chatroom, + -1); + + enabled = !enabled; + + gossip_chatroom_set_auto_connect (chatroom, enabled); + gossip_chatroom_manager_store (window->manager); + + gtk_list_store_set (store, &iter, COL_AUTO_CONNECT, enabled, -1); + gtk_tree_path_free (path); + g_object_unref (chatroom); +} + +static GossipChatroom * +chatrooms_window_model_get_selected (GossipChatroomsWindow *window) +{ + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + GossipChatroom *chatroom = NULL; + + view = GTK_TREE_VIEW (window->treeview); + selection = gtk_tree_view_get_selection (view); + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1); + } + + return chatroom; +} + +static void +chatrooms_window_model_action_selected (GossipChatroomsWindow *window) +{ + GossipChatroom *chatroom; + GtkTreeView *view; + GtkTreeModel *model; + + view = GTK_TREE_VIEW (window->treeview); + model = gtk_tree_view_get_model (view); + + chatroom = chatrooms_window_model_get_selected (window); + if (!chatroom) { + return; + } + + //gossip_edit_chatroom_dialog_show (GTK_WINDOW (window->window), chatroom); + + g_object_unref (chatroom); +} + +static void +chatrooms_window_row_activated_cb (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + GossipChatroomsWindow *window) +{ + if (GTK_WIDGET_IS_SENSITIVE (window->button_edit)) { + chatrooms_window_model_action_selected (window); + } +} + +static void +chatrooms_window_button_remove_clicked_cb (GtkWidget *widget, + GossipChatroomsWindow *window) +{ + GossipChatroom *chatroom; + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + + /* Remove from treeview */ + view = GTK_TREE_VIEW (window->treeview); + selection = gtk_tree_view_get_selection (view); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) { + return; + } + + gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1); + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + + /* Remove from config */ + gossip_chatroom_manager_remove (window->manager, chatroom); + + g_object_unref (chatroom); +} + +static void +chatrooms_window_button_edit_clicked_cb (GtkWidget *widget, + GossipChatroomsWindow *window) +{ + GossipChatroom *chatroom; + + chatroom = chatrooms_window_model_get_selected (window); + if (!chatroom) { + return; + } + + //gossip_edit_chatroom_dialog_show (GTK_WINDOW (window->window), chatroom); + + g_object_unref (chatroom); +} + +static void +chatrooms_window_button_close_clicked_cb (GtkWidget *widget, + GossipChatroomsWindow *window) +{ + gtk_widget_destroy (window->window); +} + +static void +chatrooms_window_chatroom_added_cb (GossipChatroomManager *manager, + GossipChatroom *chatroom, + GossipChatroomsWindow *window) +{ + GossipAccountChooser *account_chooser; + McAccount *account; + + account_chooser = GOSSIP_ACCOUNT_CHOOSER (window->account_chooser); + account = gossip_account_chooser_get_account (account_chooser); + + if (!account) { + chatrooms_window_model_add (window, chatroom, FALSE); + } else { + if (gossip_account_equal (account, gossip_chatroom_get_account (chatroom))) { + chatrooms_window_model_add (window, chatroom, FALSE); + } + + g_object_unref (account); + } +} + +static void +chatrooms_window_account_changed_cb (GtkWidget *combo_box, + GossipChatroomsWindow *window) +{ + chatrooms_window_model_refresh_data (window, FALSE); +} + diff --git a/libempathy-gtk/gossip-chatrooms-window.glade b/libempathy-gtk/gossip-chatrooms-window.glade new file mode 100644 index 000000000..ad2971e00 --- /dev/null +++ b/libempathy-gtk/gossip-chatrooms-window.glade @@ -0,0 +1,477 @@ +<?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="edit_chatroom_dialog"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Edit Favorite Room</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">False</property> + <property name="destroy_with_parent">False</property> + <property name="icon_name">gtk-edit</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-vbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area3"> + <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-cancel</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">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button_save"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-save</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">-5</property> + </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="GtkTable" id="table4"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="n_rows">5</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + + <child> + <widget class="GtkEntry" id="entry_room"> + <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="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="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> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entry_nickname"> + <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="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_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="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_server"> + <property name="visible">True</property> + <property name="label" translatable="yes">S_erver:</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="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_nickname"> + <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_nickname</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="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_name"> + <property name="visible">True</property> + <property name="label" translatable="yes">N_ame:</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_name</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="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entry_name"> + <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="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="checkbutton_auto_connect"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Join this chat room when Gossip starts and you are connected</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Join room on start_up</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> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="chatrooms_window"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Manage Favorite Rooms</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</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_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + + <child> + <widget class="GtkVBox" id="vbox12"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkVBox" id="vbox18"> + <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">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow1"> + <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="can_focus">True</property> + <property name="has_focus">True</property> + <property name="headers_visible">True</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> + + <child> + <widget class="GtkHButtonBox" id="hbuttonbox3"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkButton" id="button_close"> + <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> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button_remove"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-remove</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button_edit"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-edit</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </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-chatrooms-window.h b/libempathy-gtk/gossip-chatrooms-window.h new file mode 100644 index 000000000..d1314ec29 --- /dev/null +++ b/libempathy-gtk/gossip-chatrooms-window.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2004-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: Xavier Claessens <xclaesse@gmail.com> + * Martyn Russell <martyn@imendio.com> + * Mikael Hallendal <micke@imendio.com> + */ + +#ifndef __GOSSIP_CHATROOMS_WINDOW_H__ +#define __GOSSIP_CHATROOMS_WINDOW_H__ + +G_BEGIN_DECLS + +void gossip_chatrooms_window_show (GtkWindow *parent); + +G_END_DECLS + +#endif /* __GOSSIP_CHATROOMS_WINDOW_H__ */ diff --git a/libempathy-gtk/gossip-preferences.c b/libempathy-gtk/gossip-preferences.c index 52c4a804c..fd93353df 100644 --- a/libempathy-gtk/gossip-preferences.c +++ b/libempathy-gtk/gossip-preferences.c @@ -914,7 +914,7 @@ preferences_destroy_cb (GtkWidget *widget, } GtkWidget * -gossip_preferences_show (void) +gossip_preferences_show (GtkWindow *parent) { static GossipPreferences *preferences; GladeXML *glade; @@ -973,6 +973,11 @@ gossip_preferences_show (void) gtk_widget_show (page); } + if (parent) { + gtk_window_set_transient_for (GTK_WINDOW (preferences->dialog), + GTK_WINDOW (parent)); + } + gtk_widget_show (preferences->dialog); return preferences->dialog; diff --git a/libempathy-gtk/gossip-preferences.h b/libempathy-gtk/gossip-preferences.h index 74ecc9041..35b26621f 100644 --- a/libempathy-gtk/gossip-preferences.h +++ b/libempathy-gtk/gossip-preferences.h @@ -25,7 +25,7 @@ #ifndef __GOSSIP_PREFERENCES_H__ #define __GOSSIP_PREFERENCES_H__ -#include <gtk/gtkwidget.h> +#include <gtk/gtkwindow.h> G_BEGIN_DECLS @@ -49,7 +49,7 @@ G_BEGIN_DECLS #define GOSSIP_PREFS_CONTACTS_SORT_CRITERIUM GOSSIP_PREFS_PATH "/contacts/sort_criterium" #define GOSSIP_PREFS_HINTS_CLOSE_MAIN_WINDOW GOSSIP_PREFS_PATH "/hints/close_main_window" -GtkWidget * gossip_preferences_show (void); +GtkWidget * gossip_preferences_show (GtkWindow *parent); G_END_DECLS diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am index 684d4e64b..2b1d75ecf 100644 --- a/libempathy/Makefile.am +++ b/libempathy/Makefile.am @@ -24,6 +24,8 @@ libempathy_la_SOURCES = \ gossip-debug.c gossip-debug.h \ gossip-utils.c gossip-utils.h \ gossip-message.c gossip-message.h \ + gossip-chatroom-manager.c gossip-chatroom-manager.h \ + gossip-chatroom.c gossip-chatroom.h \ empathy-contact-list.c empathy-contact-list.h \ empathy-contact-manager.c empathy-contact-manager.h \ empathy-tp-contact-list.c empathy-tp-contact-list.h \ @@ -49,8 +51,13 @@ libempathy_includedir = $(includedir)/empathy/ empathy-chandler-glue.h: empathy-chandler.xml $(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) --prefix=empathy_chandler --mode=glib-server --output=$@ $< +dtddir = $(datadir)/empathy +dtd_DATA = \ + gossip-chatroom-manager.dtd + EXTRA_DIST = \ empathy-marshal.list \ - empathy-chandler.xml + empathy-chandler.xml \ + $(dtd_DATA) CLEANFILES = $(BUILT_SOURCES) diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index 3c4f55423..ed6a49323 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -488,65 +488,11 @@ empathy_tp_chat_get_id (EmpathyTpChat *chat) return priv->id; } - priv->id = empathy_tp_chat_build_id_for_chan (priv->account, priv->tp_chan); + priv->id = gossip_get_channel_id (priv->account, priv->tp_chan); return priv->id; } -gchar * -empathy_tp_chat_build_id (McAccount *account, - const gchar *contact_id) -{ - /* A handle name is unique only for a specific account */ - return g_strdup_printf ("%s/%s", - mc_account_get_unique_name (account), - contact_id); -} - -gchar * -empathy_tp_chat_build_id_for_chan (McAccount *account, - TpChan *tp_chan) -{ - MissionControl *mc; - TpConn *tp_conn; - GArray *handles; - gchar **names; - gchar *id; - GError *error = NULL; - - g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); - g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL); - - mc = gossip_mission_control_new (); - tp_conn = mission_control_get_connection (mc, account, NULL); - g_object_unref (mc); - - /* Get the handle's name */ - handles = g_array_new (FALSE, FALSE, sizeof (guint)); - g_array_append_val (handles, tp_chan->handle); - if (!tp_conn_inspect_handles (DBUS_G_PROXY (tp_conn), - tp_chan->handle_type, - handles, - &names, - &error)) { - gossip_debug (DEBUG_DOMAIN, - "Couldn't get id: %s", - error ? error->message : "No error given"); - g_clear_error (&error); - g_array_free (handles, TRUE); - g_object_unref (tp_conn); - - return NULL; - } - - id = empathy_tp_chat_build_id (account, *names); - - g_strfreev (names); - g_object_unref (tp_conn); - - return id; -} - static void tp_chat_destroy_cb (TpChan *text_chan, EmpathyTpChat *chat) diff --git a/libempathy/empathy-tp-chat.h b/libempathy/empathy-tp-chat.h index a9278c3f1..55bbfcd3d 100644 --- a/libempathy/empathy-tp-chat.h +++ b/libempathy/empathy-tp-chat.h @@ -65,10 +65,6 @@ void empathy_tp_chat_send (EmpathyTpChat * void empathy_tp_chat_set_state (EmpathyTpChat *chat, TelepathyChannelChatState state); const gchar * empathy_tp_chat_get_id (EmpathyTpChat *chat); -gchar * empathy_tp_chat_build_id (McAccount *account, - const gchar *contact_id); -gchar * empathy_tp_chat_build_id_for_chan (McAccount *account, - TpChan *tp_chan); G_END_DECLS diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c index 64bec75ff..6af5ed064 100644 --- a/libempathy/empathy-tp-contact-list.c +++ b/libempathy/empathy-tp-contact-list.c @@ -641,6 +641,7 @@ empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list, } if (new_handles->len == 0) { + g_array_free (new_handles, TRUE); return contacts; } @@ -1448,6 +1449,7 @@ tp_contact_list_group_members_added_cb (GossipTelepathyGroup *group, contact = GOSSIP_CONTACT (l->data); contact_groups = gossip_contact_get_groups (contact); + /* FIXME: this leaks */ if (!g_list_find_custom (contact_groups, group_name, (GCompareFunc) strcmp)) { @@ -1663,6 +1665,7 @@ tp_contact_list_request_avatar_cb (DBusGProxy *proxy, n_avatar_requests--; tp_contact_list_start_avatar_requests (data->list); + g_object_unref (contact); g_slice_free (TpContactListAvatarRequestData, data); } @@ -1699,6 +1702,7 @@ tp_contact_list_aliases_update_cb (DBusGProxy *proxy, tp_contact_list_block_contact (list, contact); gossip_contact_set_name (contact, alias); tp_contact_list_unblock_contact (list, contact); + g_object_unref (contact); gossip_debug (DEBUG_DOMAIN, "contact %d renamed to %s (update cb)", handle, alias); @@ -1727,6 +1731,7 @@ tp_contact_list_request_aliases_cb (DBusGProxy *proxy, tp_contact_list_block_contact (data->list, contact); gossip_contact_set_name (contact, *name); tp_contact_list_unblock_contact (data->list, contact); + g_object_unref (contact); gossip_debug (DEBUG_DOMAIN, "contact %d renamed to %s (request cb)", data->handles[i], *name); @@ -1781,6 +1786,8 @@ tp_contact_list_parse_presence_foreach (guint handle, tp_contact_list_block_contact (list, contact); gossip_contact_set_presence (contact, presence); tp_contact_list_unblock_contact (list, contact); + + g_object_unref (contact); } static void diff --git a/libempathy/gossip-chatroom-manager.c b/libempathy/gossip-chatroom-manager.c new file mode 100644 index 000000000..ade0b0ba0 --- /dev/null +++ b/libempathy/gossip-chatroom-manager.c @@ -0,0 +1,500 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2004-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: Xavier Claessens <xclaesse@gmail.com> + * Martyn Russell <martyn@imendio.com> + */ + +#include "config.h" + +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <libxml/parser.h> +#include <libxml/tree.h> + +#include "gossip-debug.h" +#include "gossip-chatroom-manager.h" +#include "gossip-utils.h" + +#define DEBUG_DOMAIN "ChatroomManager" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CHATROOM_MANAGER, GossipChatroomManagerPriv)) + +#define CHATROOMS_XML_FILENAME "chatrooms.xml" +#define CHATROOMS_DTD_FILENAME "gossip-chatroom-manager.dtd" + +struct _GossipChatroomManagerPriv { + GList *chatrooms; +}; + +static void gossip_chatroom_manager_class_init (GossipChatroomManagerClass *klass); +static void gossip_chatroom_manager_init (GossipChatroomManager *manager); +static void chatroom_manager_finalize (GObject *object); +static gboolean chatroom_manager_get_all (GossipChatroomManager *manager); +static gboolean chatroom_manager_file_parse (GossipChatroomManager *manager, + const gchar *filename); +static void chatroom_manager_parse_chatroom (GossipChatroomManager *manager, + xmlNodePtr node); +static gboolean chatroom_manager_file_save (GossipChatroomManager *manager); + +enum { + CHATROOM_ADDED, + CHATROOM_REMOVED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE (GossipChatroomManager, gossip_chatroom_manager, G_TYPE_OBJECT); + +static void +gossip_chatroom_manager_class_init (GossipChatroomManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = chatroom_manager_finalize; + + signals[CHATROOM_ADDED] = + g_signal_new ("chatroom-added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, GOSSIP_TYPE_CHATROOM); + signals[CHATROOM_REMOVED] = + g_signal_new ("chatroom-removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, GOSSIP_TYPE_CHATROOM); + + g_type_class_add_private (object_class, + sizeof (GossipChatroomManagerPriv)); +} + +static void +gossip_chatroom_manager_init (GossipChatroomManager *manager) +{ +} + +static void +chatroom_manager_finalize (GObject *object) +{ + GossipChatroomManagerPriv *priv; + + priv = GET_PRIV (object); + + g_list_foreach (priv->chatrooms, (GFunc) g_object_unref, NULL); + g_list_free (priv->chatrooms); + + (G_OBJECT_CLASS (gossip_chatroom_manager_parent_class)->finalize) (object); +} + +GossipChatroomManager * +gossip_chatroom_manager_new (void) +{ + static GossipChatroomManager *manager = NULL; + + if (!manager) { + GossipChatroomManagerPriv *priv; + + manager = g_object_new (GOSSIP_TYPE_CHATROOM_MANAGER, NULL); + priv = GET_PRIV (manager); + chatroom_manager_get_all (manager); + + g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager); + } else { + g_object_ref (manager); + } + + return manager; +} + +gboolean +gossip_chatroom_manager_add (GossipChatroomManager *manager, + GossipChatroom *chatroom) +{ + GossipChatroomManagerPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager), FALSE); + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), FALSE); + + priv = GET_PRIV (manager); + + /* don't add more than once */ + if (!gossip_chatroom_manager_find (manager, + gossip_chatroom_get_account (chatroom), + gossip_chatroom_get_room (chatroom))) { + priv->chatrooms = g_list_append (priv->chatrooms, g_object_ref (chatroom)); + chatroom_manager_file_save (manager); + + g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom); + + return TRUE; + } + + return FALSE; +} + +void +gossip_chatroom_manager_remove (GossipChatroomManager *manager, + GossipChatroom *chatroom) +{ + GossipChatroomManagerPriv *priv; + GList *l; + + g_return_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager)); + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + + priv = GET_PRIV (manager); + + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *this_chatroom; + + this_chatroom = l->data; + + if (gossip_chatroom_equal (chatroom, this_chatroom)) { + priv->chatrooms = g_list_delete_link (priv->chatrooms, l); + + chatroom_manager_file_save (manager); + + g_signal_emit (manager, signals[CHATROOM_REMOVED], 0, this_chatroom); + g_object_unref (this_chatroom); + break; + } + } +} + +GossipChatroom * +gossip_chatroom_manager_find (GossipChatroomManager *manager, + McAccount *account, + const gchar *room) +{ + GossipChatroomManagerPriv *priv; + GList *l; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager), NULL); + g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (room != NULL, NULL); + + priv = GET_PRIV (manager); + + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *chatroom; + McAccount *this_account; + const gchar *this_room; + + chatroom = l->data; + this_account = gossip_chatroom_get_account (chatroom); + this_room = gossip_chatroom_get_room (chatroom); + + if (gossip_account_equal (account, this_account) && + strcmp (this_room, room) == 0) { + return chatroom; + } + } + + return NULL; +} + +GList * +gossip_chatroom_manager_get_chatrooms (GossipChatroomManager *manager, + McAccount *account) +{ + GossipChatroomManagerPriv *priv; + GList *chatrooms, *l; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager), NULL); + + priv = GET_PRIV (manager); + + if (!account) { + return g_list_copy (priv->chatrooms); + } + + chatrooms = NULL; + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *chatroom; + + chatroom = l->data; + + if (gossip_account_equal (account, + gossip_chatroom_get_account (chatroom))) { + chatrooms = g_list_append (chatrooms, chatroom); + } + } + + return chatrooms; +} + +guint +gossip_chatroom_manager_get_count (GossipChatroomManager *manager, + McAccount *account) +{ + GossipChatroomManagerPriv *priv; + GList *l; + guint count = 0; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager), 0); + + priv = GET_PRIV (manager); + + if (!account) { + return g_list_length (priv->chatrooms); + } + + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *chatroom; + + chatroom = l->data; + + if (gossip_account_equal (account, + gossip_chatroom_get_account (chatroom))) { + count++; + } + } + + return count; +} + +void +gossip_chatroom_manager_store (GossipChatroomManager *manager) +{ + g_return_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager)); + + chatroom_manager_file_save (manager); +} + +/* + * API to save/load and parse the chatrooms file. + */ + +static gboolean +chatroom_manager_get_all (GossipChatroomManager *manager) +{ + GossipChatroomManagerPriv *priv; + gchar *dir; + gchar *file_with_path = NULL; + + priv = GET_PRIV (manager); + + dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL); + if (!g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR); + } + + file_with_path = g_build_filename (dir, CHATROOMS_XML_FILENAME, NULL); + g_free (dir); + + /* read file in */ + if (g_file_test (file_with_path, G_FILE_TEST_EXISTS) && + !chatroom_manager_file_parse (manager, file_with_path)) { + g_free (file_with_path); + return FALSE; + } + + g_free (file_with_path); + + return TRUE; +} + +static gboolean +chatroom_manager_file_parse (GossipChatroomManager *manager, + const gchar *filename) +{ + GossipChatroomManagerPriv *priv; + xmlParserCtxtPtr ctxt; + xmlDocPtr doc; + xmlNodePtr chatrooms; + xmlNodePtr node; + + priv = GET_PRIV (manager); + + gossip_debug (DEBUG_DOMAIN, "Attempting to parse file:'%s'...", filename); + + ctxt = xmlNewParserCtxt (); + + /* Parse and validate the file. */ + doc = xmlCtxtReadFile (ctxt, filename, NULL, 0); + if (!doc) { + g_warning ("Failed to parse file:'%s'", filename); + xmlFreeParserCtxt (ctxt); + return FALSE; + } + + if (!gossip_xml_validate (doc, CHATROOMS_DTD_FILENAME)) { + g_warning ("Failed to validate file:'%s'", filename); + xmlFreeDoc(doc); + xmlFreeParserCtxt (ctxt); + return FALSE; + } + + /* The root node, chatrooms. */ + chatrooms = xmlDocGetRootElement (doc); + + for (node = chatrooms->children; node; node = node->next) { + if (strcmp ((gchar *) node->name, "chatroom") == 0) { + chatroom_manager_parse_chatroom (manager, node); + } + } + + gossip_debug (DEBUG_DOMAIN, + "Parsed %d chatrooms", + g_list_length (priv->chatrooms)); + + xmlFreeDoc(doc); + xmlFreeParserCtxt (ctxt); + + return TRUE; +} + +static void +chatroom_manager_parse_chatroom (GossipChatroomManager *manager, + xmlNodePtr node) +{ + GossipChatroomManagerPriv *priv; + GossipChatroom *chatroom; + McAccount *account; + xmlNodePtr child; + gchar *str; + gchar *name; + gchar *room; + gchar *account_id; + gboolean auto_connect; + + priv = GET_PRIV (manager); + + /* default values. */ + name = NULL; + room = NULL; + auto_connect = TRUE; + account_id = NULL; + + for (child = node->children; child; child = child->next) { + gchar *tag; + + if (xmlNodeIsText (child)) { + continue; + } + + tag = (gchar *) child->name; + str = (gchar *) xmlNodeGetContent (child); + + if (strcmp (tag, "name") == 0) { + name = g_strdup (str); + } + else if (strcmp (tag, "room") == 0) { + room = g_strdup (str); + } + else if (strcmp (tag, "auto_connect") == 0) { + if (strcmp (str, "yes") == 0) { + auto_connect = TRUE; + } else { + auto_connect = FALSE; + } + } + else if (strcmp (tag, "account") == 0) { + account_id = g_strdup (str); + } + + xmlFree (str); + } + + account = mc_account_lookup (account_id); + if (!account) { + g_free (name); + g_free (room); + g_free (account_id); + return; + } + + chatroom = gossip_chatroom_new_full (account, + room, + name, + auto_connect); + + priv->chatrooms = g_list_prepend (priv->chatrooms, chatroom); + + g_object_unref (account); + g_free (name); + g_free (room); + g_free (account_id); +} + +static gboolean +chatroom_manager_file_save (GossipChatroomManager *manager) +{ + GossipChatroomManagerPriv *priv; + xmlDocPtr doc; + xmlNodePtr root; + GList *l; + gchar *dir; + gchar *file; + + priv = GET_PRIV (manager); + + dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL); + if (!g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR); + } + + file = g_build_filename (dir, CHATROOMS_XML_FILENAME, NULL); + g_free (dir); + + doc = xmlNewDoc ("1.0"); + root = xmlNewNode (NULL, "chatrooms"); + xmlDocSetRootElement (doc, root); + + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *chatroom; + xmlNodePtr node; + const gchar *account_id; + + chatroom = l->data; + account_id = mc_account_get_unique_name (gossip_chatroom_get_account (chatroom)); + + node = xmlNewChild (root, NULL, "chatroom", NULL); + xmlNewTextChild (node, NULL, "name", gossip_chatroom_get_name (chatroom)); + xmlNewTextChild (node, NULL, "room", gossip_chatroom_get_room (chatroom)); + xmlNewTextChild (node, NULL, "account", account_id); + xmlNewTextChild (node, NULL, "auto_connect", gossip_chatroom_get_auto_connect (chatroom) ? "yes" : "no"); + } + + /* Make sure the XML is indented properly */ + xmlIndentTreeOutput = 1; + + gossip_debug (DEBUG_DOMAIN, "Saving file:'%s'", file); + xmlSaveFormatFileEnc (file, doc, "utf-8", 1); + xmlFreeDoc (doc); + + xmlCleanupParser (); + xmlMemoryDump (); + + g_free (file); + + return TRUE; +} diff --git a/libempathy/gossip-chatroom-manager.dtd b/libempathy/gossip-chatroom-manager.dtd new file mode 100644 index 000000000..5d94a57c2 --- /dev/null +++ b/libempathy/gossip-chatroom-manager.dtd @@ -0,0 +1,17 @@ +<!-- + DTD for Gossips Chat Rooms. + by Martyn Russell <martyn@imendio.com> + v0.2 +--> + +<!-- Root element. --> +<!ELEMENT chatrooms (chatroom*)> + +<!ELEMENT chatroom + (name,room,account,(auto_connect?))> + +<!ELEMENT name (#PCDATA)> +<!ELEMENT room (#PCDATA)> +<!ELEMENT auto_connect (#PCDATA)> +<!ELEMENT account (#PCDATA)> + diff --git a/libempathy/gossip-chatroom-manager.h b/libempathy/gossip-chatroom-manager.h new file mode 100644 index 000000000..7d10a0fc1 --- /dev/null +++ b/libempathy/gossip-chatroom-manager.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2004-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: Xavier Claessens <xclaesse@gmail.com> + * Martyn Russell <martyn@imendio.com> + */ + +#ifndef __GOSSIP_CHATROOM_MANAGER_H__ +#define __GOSSIP_CHATROOM_MANAGER_H__ + +#include <glib-object.h> + +#include <libmissioncontrol/mc-account.h> + +#include "gossip-chatroom.h" + +G_BEGIN_DECLS + +#define GOSSIP_TYPE_CHATROOM_MANAGER (gossip_chatroom_manager_get_type ()) +#define GOSSIP_CHATROOM_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_CHATROOM_MANAGER, GossipChatroomManager)) +#define GOSSIP_CHATROOM_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GOSSIP_TYPE_CHATROOM_MANAGER, GossipChatroomManagerClass)) +#define GOSSIP_IS_CHATROOM_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_CHATROOM_MANAGER)) +#define GOSSIP_IS_CHATROOM_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_CHATROOM_MANAGER)) +#define GOSSIP_CHATROOM_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_CHATROOM_MANAGER, GossipChatroomManagerClass)) + +typedef struct _GossipChatroomManager GossipChatroomManager; +typedef struct _GossipChatroomManagerClass GossipChatroomManagerClass; +typedef struct _GossipChatroomManagerPriv GossipChatroomManagerPriv; + +struct _GossipChatroomManager { + GObject parent; +}; + +struct _GossipChatroomManagerClass { + GObjectClass parent_class; +}; + +GType gossip_chatroom_manager_get_type (void) G_GNUC_CONST; +GossipChatroomManager *gossip_chatroom_manager_new (void); +gboolean gossip_chatroom_manager_add (GossipChatroomManager *manager, + GossipChatroom *chatroom); +void gossip_chatroom_manager_remove (GossipChatroomManager *manager, + GossipChatroom *chatroom); +GossipChatroom * gossip_chatroom_manager_find (GossipChatroomManager *manager, + McAccount *account, + const gchar *room); +GList * gossip_chatroom_manager_get_chatrooms (GossipChatroomManager *manager, + McAccount *account); +guint gossip_chatroom_manager_get_count (GossipChatroomManager *manager, + McAccount *account); +void gossip_chatroom_manager_store (GossipChatroomManager *manager); + +G_END_DECLS + +#endif /* __GOSSIP_CHATROOM_MANAGER_H__ */ diff --git a/libempathy/gossip-chatroom.c b/libempathy/gossip-chatroom.c new file mode 100644 index 000000000..eccd2824c --- /dev/null +++ b/libempathy/gossip-chatroom.c @@ -0,0 +1,360 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * 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: Xavier Claessens <xclaesse@gmail.com> + */ + +#include "config.h" + +#include <string.h> + +#include <glib.h> + +#include "gossip-chatroom.h" +#include "gossip-utils.h" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CHATROOM, GossipChatroomPriv)) + +struct _GossipChatroomPriv { + McAccount *account; + gchar *room; + gchar *name; + gboolean auto_connect; +}; + +static void gossip_chatroom_class_init (GossipChatroomClass *klass); +static void gossip_chatroom_init (GossipChatroom *chatroom); +static void chatroom_finalize (GObject *object); +static void chatroom_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void chatroom_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +enum { + PROP_0, + PROP_ACCOUNT, + PROP_ROOM, + PROP_NAME, + PROP_AUTO_CONNECT, +}; + +G_DEFINE_TYPE (GossipChatroom, gossip_chatroom, G_TYPE_OBJECT); + +static void +gossip_chatroom_class_init (GossipChatroomClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = chatroom_finalize; + object_class->get_property = chatroom_get_property; + object_class->set_property = chatroom_set_property; + + g_object_class_install_property (object_class, + PROP_ACCOUNT, + g_param_spec_object ("account", + "Chatroom Account", + "The account associated with an chatroom", + MC_TYPE_ACCOUNT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_ROOM, + g_param_spec_string ("room", + "Chatroom Room", + "Chatroom represented as 'room@server'", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_NAME, + g_param_spec_string ("name", + "Chatroom Name", + "Chatroom name", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_AUTO_CONNECT, + g_param_spec_boolean ("auto_connect", + "Chatroom Auto Connect", + "Connect on startup", + FALSE, + G_PARAM_READWRITE)); + + + g_type_class_add_private (object_class, sizeof (GossipChatroomPriv)); +} + +static void +gossip_chatroom_init (GossipChatroom *chatroom) +{ +} + +static void +chatroom_finalize (GObject *object) +{ + GossipChatroomPriv *priv; + + priv = GET_PRIV (object); + + g_object_unref (priv->account); + g_free (priv->room); + g_free (priv->name); + + (G_OBJECT_CLASS (gossip_chatroom_parent_class)->finalize) (object); +} + +static void +chatroom_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + GossipChatroomPriv *priv; + + priv = GET_PRIV (object); + + switch (param_id) { + case PROP_ACCOUNT: + g_value_set_object (value, priv->account); + break; + case PROP_ROOM: + g_value_set_string (value, priv->room); + break; + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + case PROP_AUTO_CONNECT: + g_value_set_boolean (value, priv->auto_connect); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +static void +chatroom_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + GossipChatroomPriv *priv; + + priv = GET_PRIV (object); + + switch (param_id) { + case PROP_ACCOUNT: + gossip_chatroom_set_account (GOSSIP_CHATROOM (object), + g_value_get_object (value)); + break; + case PROP_ROOM: + gossip_chatroom_set_room (GOSSIP_CHATROOM (object), + g_value_get_string (value)); + break; + case PROP_NAME: + gossip_chatroom_set_name (GOSSIP_CHATROOM (object), + g_value_get_string (value)); + break; + case PROP_AUTO_CONNECT: + gossip_chatroom_set_auto_connect (GOSSIP_CHATROOM (object), + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +GossipChatroom * +gossip_chatroom_new (McAccount *account, + const gchar *room) +{ + g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (room != NULL, NULL); + + return g_object_new (GOSSIP_TYPE_CHATROOM, + "account", account, + "room", room, + NULL); +} + +GossipChatroom * +gossip_chatroom_new_full (McAccount *account, + const gchar *room, + const gchar *name, + gboolean auto_connect) +{ + g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (room != NULL, NULL); + + return g_object_new (GOSSIP_TYPE_CHATROOM, + "account", account, + "room", room, + "name", name, + "auto_connect", auto_connect, + NULL); +} + +McAccount * +gossip_chatroom_get_account (GossipChatroom *chatroom) +{ + GossipChatroomPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), NULL); + + priv = GET_PRIV (chatroom); + return priv->account; +} + +void +gossip_chatroom_set_account (GossipChatroom *chatroom, + McAccount *account) +{ + GossipChatroomPriv *priv; + + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + g_return_if_fail (MC_IS_ACCOUNT (account)); + + priv = GET_PRIV (chatroom); + + if (account == priv->account) { + return; + } + if (priv->account) { + g_object_unref (priv->account); + } + priv->account = g_object_ref (account); + + g_object_notify (G_OBJECT (chatroom), "account"); +} + +const gchar * +gossip_chatroom_get_room (GossipChatroom *chatroom) +{ + GossipChatroomPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), NULL); + + priv = GET_PRIV (chatroom); + return priv->room; +} + +void +gossip_chatroom_set_room (GossipChatroom *chatroom, + const gchar *room) +{ + GossipChatroomPriv *priv; + + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + g_return_if_fail (room != NULL); + + priv = GET_PRIV (chatroom); + + g_free (priv->room); + priv->room = g_strdup (room); + + g_object_notify (G_OBJECT (chatroom), "room"); +} + +const gchar * +gossip_chatroom_get_name (GossipChatroom *chatroom) +{ + GossipChatroomPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), NULL); + + priv = GET_PRIV (chatroom); + + if (G_STR_EMPTY (priv->name)) { + return priv->room; + } + + return priv->name; +} + +void +gossip_chatroom_set_name (GossipChatroom *chatroom, + const gchar *name) +{ + GossipChatroomPriv *priv; + + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + g_return_if_fail (name != NULL); + + priv = GET_PRIV (chatroom); + + g_free (priv->name); + priv->name = g_strdup (name); + + g_object_notify (G_OBJECT (chatroom), "name"); +} + +gboolean +gossip_chatroom_get_auto_connect (GossipChatroom *chatroom) +{ + GossipChatroomPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), FALSE); + + priv = GET_PRIV (chatroom); + return priv->auto_connect; +} + +void +gossip_chatroom_set_auto_connect (GossipChatroom *chatroom, + gboolean auto_connect) +{ + GossipChatroomPriv *priv; + + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + + priv = GET_PRIV (chatroom); + + priv->auto_connect = auto_connect; + + g_object_notify (G_OBJECT (chatroom), "auto-connect"); +} + +gboolean +gossip_chatroom_equal (gconstpointer v1, + gconstpointer v2) +{ + McAccount *account_a; + McAccount *account_b; + const gchar *room_a; + const gchar *room_b; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (v1), FALSE); + g_return_val_if_fail (GOSSIP_IS_CHATROOM (v2), FALSE); + + account_a = gossip_chatroom_get_account (GOSSIP_CHATROOM (v1)); + account_b = gossip_chatroom_get_account (GOSSIP_CHATROOM (v2)); + + room_a = gossip_chatroom_get_room (GOSSIP_CHATROOM (v1)); + room_b = gossip_chatroom_get_room (GOSSIP_CHATROOM (v2)); + + return gossip_account_equal (account_a, account_b) && g_str_equal (room_a, room_b); +} + + diff --git a/libempathy/gossip-chatroom.h b/libempathy/gossip-chatroom.h new file mode 100644 index 000000000..70614a368 --- /dev/null +++ b/libempathy/gossip-chatroom.h @@ -0,0 +1,78 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * 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: Xavier Claessens <xclaesse@gmail.com> + */ + +#ifndef __GOSSIP_CHATROOM_H__ +#define __GOSSIP_CHATROOM_H__ + +#include <glib-object.h> + +#include <libmissioncontrol/mc-account.h> + +G_BEGIN_DECLS + +#define GOSSIP_TYPE_CHATROOM (gossip_chatroom_get_type ()) +#define GOSSIP_CHATROOM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_CHATROOM, GossipChatroom)) +#define GOSSIP_CHATROOM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GOSSIP_TYPE_CHATROOM, GossipChatroomClass)) +#define GOSSIP_IS_CHATROOM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_CHATROOM)) +#define GOSSIP_IS_CHATROOM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_CHATROOM)) +#define GOSSIP_CHATROOM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_CHATROOM, GossipChatroomClass)) + +#define GOSSIP_TYPE_CHATROOM_INVITE (gossip_chatroom_invite_get_gtype ()) + +typedef struct _GossipChatroom GossipChatroom; +typedef struct _GossipChatroomClass GossipChatroomClass; +typedef struct _GossipChatroomPriv GossipChatroomPriv; + +struct _GossipChatroom { + GObject parent; +}; + +struct _GossipChatroomClass { + GObjectClass parent_class; +}; + +GType gossip_chatroom_get_type (void) G_GNUC_CONST; +GossipChatroom *gossip_chatroom_new (McAccount *account, + const gchar *room); +GossipChatroom *gossip_chatroom_new_full (McAccount *account, + const gchar *room, + const gchar *name, + gboolean auto_connect); +McAccount * gossip_chatroom_get_account (GossipChatroom *chatroom); +void gossip_chatroom_set_account (GossipChatroom *chatroom, + McAccount *account); +const gchar * gossip_chatroom_get_room (GossipChatroom *chatroom); +void gossip_chatroom_set_room (GossipChatroom *chatroom, + const gchar *room); +const gchar * gossip_chatroom_get_name (GossipChatroom *chatroom); +void gossip_chatroom_set_name (GossipChatroom *chatroom, + const gchar *name); +gboolean gossip_chatroom_get_auto_connect (GossipChatroom *chatroom); +void gossip_chatroom_set_auto_connect (GossipChatroom *chatroom, + gboolean auto_connect); +gboolean gossip_chatroom_equal (gconstpointer v1, + gconstpointer v2); + + +G_BEGIN_DECLS + +#endif /* __GOSSIP_CHATROOM_H__ */ diff --git a/libempathy/gossip-utils.c b/libempathy/gossip-utils.c index 6ab70ce4a..579981616 100644 --- a/libempathy/gossip-utils.c +++ b/libempathy/gossip-utils.c @@ -33,7 +33,6 @@ #include <glib/gi18n.h> #include <libxml/uri.h> -#include <libmissioncontrol/mc-account.h> #include <libtelepathy/tp-helpers.h> #include "gossip-debug.h" @@ -447,3 +446,51 @@ gossip_mission_control_new (void) return mc; } +gchar * +gossip_get_channel_id (McAccount *account, + TpChan *tp_chan) +{ + MissionControl *mc; + TpConn *tp_conn; + GArray *handles; + gchar **names; + gchar *name; + GError *error; + + g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL); + + mc = gossip_mission_control_new (); + tp_conn = mission_control_get_connection (mc, account, NULL); + g_object_unref (mc); + + if (!tp_conn) { + return NULL; + } + + /* Get the handle's name */ + handles = g_array_new (FALSE, FALSE, sizeof (guint)); + g_array_append_val (handles, tp_chan->handle); + if (!tp_conn_inspect_handles (DBUS_G_PROXY (tp_conn), + tp_chan->handle_type, + handles, + &names, + &error)) { + gossip_debug (DEBUG_DOMAIN, + "Couldn't get id: %s", + error ? error->message : "No error given"); + + g_clear_error (&error); + g_array_free (handles, TRUE); + g_object_unref (tp_conn); + + return NULL; + } + + name = *names; + g_free (names); + g_object_unref (tp_conn); + + return name; +} + diff --git a/libempathy/gossip-utils.h b/libempathy/gossip-utils.h index 052dfb781..638c114bd 100644 --- a/libempathy/gossip-utils.h +++ b/libempathy/gossip-utils.h @@ -32,6 +32,9 @@ #include <libxml/parser.h> #include <libxml/tree.h> +#include <libtelepathy/tp-chan.h> + +#include <libmissioncontrol/mc-account.h> #include <libmissioncontrol/mission-control.h> #include "gossip-contact.h" @@ -85,10 +88,12 @@ GValue * gossip_string_to_g_value (const gchar *str, gboolean gossip_g_value_equal (const GValue *value1, const GValue *value2); -guint gossip_account_hash (gconstpointer key); -gboolean gossip_account_equal (gconstpointer a, - gconstpointer b); -MissionControl *gossip_mission_control_new (void); +guint gossip_account_hash (gconstpointer key); +gboolean gossip_account_equal (gconstpointer a, + gconstpointer b); +MissionControl *gossip_mission_control_new (void); +gchar * gossip_get_channel_id (McAccount *account, + TpChan *tp_chan); G_END_DECLS diff --git a/src/empathy-accounts-main.c b/src/empathy-accounts-main.c index 954b3cea7..1f53e131e 100644 --- a/src/empathy-accounts-main.c +++ b/src/empathy-accounts-main.c @@ -44,7 +44,7 @@ main (int argc, char *argv[]) gtk_init (&argc, &argv); - dialog = gossip_accounts_dialog_show (); + dialog = gossip_accounts_dialog_show (NULL); g_signal_connect (dialog, "destroy", G_CALLBACK (destroy_cb), diff --git a/src/empathy-chat-main.c b/src/empathy-chat-main.c index 86b4608bd..fb0964934 100644 --- a/src/empathy-chat-main.c +++ b/src/empathy-chat-main.c @@ -113,8 +113,8 @@ new_channel_cb (EmpathyChandler *chandler, mc = gossip_mission_control_new (); account = mission_control_get_account_for_connection (mc, tp_conn, NULL); - id = empathy_tp_chat_build_id_for_chan (account, tp_chan); - chat = gossip_chat_window_find_chat_by_id (id); + id = gossip_get_channel_id (account, tp_chan); + chat = gossip_chat_window_find_chat (account, id); g_free (id); g_object_unref (mc); @@ -185,7 +185,7 @@ main (int argc, char *argv[]) debug_mode = TRUE; } - exit_timeout_start (); + //sexit_timeout_start (); chandler = empathy_chandler_new (BUS_NAME, OBJECT_PATH); g_signal_connect (chandler, "new-channel", |