Fix warning when selecting all accounts.
authorXavier Claessens <xclaesse@gmail.com>
Thu, 31 May 2007 06:34:41 +0000 (06:34 +0000)
committerXavier Claessens <xclaesse@src.gnome.org>
Thu, 31 May 2007 06:34:41 +0000 (06:34 +0000)
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.

svn path=/trunk/; revision=100

29 files changed:
ChangeLog
TODO
libempathy-gtk/Makefile.am
libempathy-gtk/empathy-main-window.c
libempathy-gtk/empathy-status-icon.c
libempathy-gtk/gossip-account-chooser.c
libempathy-gtk/gossip-accounts-dialog.c
libempathy-gtk/gossip-accounts-dialog.h
libempathy-gtk/gossip-chat-window.c
libempathy-gtk/gossip-chat-window.h
libempathy-gtk/gossip-chat.c
libempathy-gtk/gossip-chatrooms-window.c [new file with mode: 0644]
libempathy-gtk/gossip-chatrooms-window.glade [new file with mode: 0644]
libempathy-gtk/gossip-chatrooms-window.h [new file with mode: 0644]
libempathy-gtk/gossip-preferences.c
libempathy-gtk/gossip-preferences.h
libempathy/Makefile.am
libempathy/empathy-tp-chat.c
libempathy/empathy-tp-chat.h
libempathy/empathy-tp-contact-list.c
libempathy/gossip-chatroom-manager.c [new file with mode: 0644]
libempathy/gossip-chatroom-manager.dtd [new file with mode: 0644]
libempathy/gossip-chatroom-manager.h [new file with mode: 0644]
libempathy/gossip-chatroom.c [new file with mode: 0644]
libempathy/gossip-chatroom.h [new file with mode: 0644]
libempathy/gossip-utils.c
libempathy/gossip-utils.h
src/empathy-accounts-main.c
src/empathy-chat-main.c

index 5683628..ff1c7e1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/TODO b/TODO
index da967a3..8367547 100644 (file)
--- a/TODO
+++ b/TODO
@@ -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
index f28e741..183f7d8 100644 (file)
@@ -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
index b10f6c8..befe2f5 100644 (file)
@@ -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, 
index 2108227..01a5424 100644 (file)
@@ -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));
                }
        }
 }
index 9cb8e5d..dfed1bb 100644 (file)
@@ -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);
index 6d79345..2a3a927 100644 (file)
@@ -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;
index e78b335..5b058e6 100644 (file)
@@ -28,7 +28,7 @@
 
 G_BEGIN_DECLS
 
-GtkWidget *gossip_accounts_dialog_show (void);
+GtkWidget *gossip_accounts_dialog_show (GtkWindow *parent);
 
 G_END_DECLS
 
index 35f3f9a..6979e45 100644 (file)
 
 #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;
                        }
                }
index 18b06ad..b58e5da 100644 (file)
@@ -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
 
index 4072b6e..a29c318 100644 (file)
@@ -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 (file)
index 0000000..5ff5d88
--- /dev/null
@@ -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 (file)
index 0000000..ad2971e
--- /dev/null
@@ -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 (file)
index 0000000..d1314ec
--- /dev/null
@@ -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__ */
index 52c4a80..fd93353 100644 (file)
@@ -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;
index 74ecc90..35b2662 100644 (file)
@@ -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
 
index 684d4e6..2b1d75e 100644 (file)
@@ -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)
index 3c4f554..ed6a493 100644 (file)
@@ -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)
index a9278c3..55bbfcd 100644 (file)
@@ -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
 
index 64bec75..6af5ed0 100644 (file)
@@ -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 (file)
index 0000000..ade0b0b
--- /dev/null
@@ -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 (file)
index 0000000..5d94a57
--- /dev/null
@@ -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 (file)
index 0000000..7d10a0f
--- /dev/null
@@ -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 (file)
index 0000000..eccd282
--- /dev/null
@@ -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 (file)
index 0000000..70614a3
--- /dev/null
@@ -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__ */
index 6ab70ce..5799816 100644 (file)
@@ -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;
+}
+
index 052dfb7..638c114 100644 (file)
@@ -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
 
index 954b3ce..1f53e13 100644 (file)
@@ -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),
index 86b4608..fb09649 100644 (file)
@@ -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",