From 6fe758a0d83f6872585a177a2e821d4105642308 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 31 May 2007 06:34:41 +0000 Subject: Fix warning when selecting all accounts. 2007-05-31 Xavier Claessens * 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 --- libempathy/Makefile.am | 9 +- libempathy/empathy-tp-chat.c | 56 +--- libempathy/empathy-tp-chat.h | 4 - libempathy/empathy-tp-contact-list.c | 7 + libempathy/gossip-chatroom-manager.c | 500 +++++++++++++++++++++++++++++++++ libempathy/gossip-chatroom-manager.dtd | 17 ++ libempathy/gossip-chatroom-manager.h | 72 +++++ libempathy/gossip-chatroom.c | 360 ++++++++++++++++++++++++ libempathy/gossip-chatroom.h | 78 +++++ libempathy/gossip-utils.c | 49 +++- libempathy/gossip-utils.h | 13 +- 11 files changed, 1100 insertions(+), 65 deletions(-) create mode 100644 libempathy/gossip-chatroom-manager.c create mode 100644 libempathy/gossip-chatroom-manager.dtd create mode 100644 libempathy/gossip-chatroom-manager.h create mode 100644 libempathy/gossip-chatroom.c create mode 100644 libempathy/gossip-chatroom.h (limited to 'libempathy') diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am index 684d4e64b..2b1d75ecf 100644 --- a/libempathy/Makefile.am +++ b/libempathy/Makefile.am @@ -24,6 +24,8 @@ libempathy_la_SOURCES = \ gossip-debug.c gossip-debug.h \ gossip-utils.c gossip-utils.h \ gossip-message.c gossip-message.h \ + gossip-chatroom-manager.c gossip-chatroom-manager.h \ + gossip-chatroom.c gossip-chatroom.h \ empathy-contact-list.c empathy-contact-list.h \ empathy-contact-manager.c empathy-contact-manager.h \ empathy-tp-contact-list.c empathy-tp-contact-list.h \ @@ -49,8 +51,13 @@ libempathy_includedir = $(includedir)/empathy/ empathy-chandler-glue.h: empathy-chandler.xml $(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) --prefix=empathy_chandler --mode=glib-server --output=$@ $< +dtddir = $(datadir)/empathy +dtd_DATA = \ + gossip-chatroom-manager.dtd + EXTRA_DIST = \ empathy-marshal.list \ - empathy-chandler.xml + empathy-chandler.xml \ + $(dtd_DATA) CLEANFILES = $(BUILT_SOURCES) diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index 3c4f55423..ed6a49323 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -488,65 +488,11 @@ empathy_tp_chat_get_id (EmpathyTpChat *chat) return priv->id; } - priv->id = empathy_tp_chat_build_id_for_chan (priv->account, priv->tp_chan); + priv->id = gossip_get_channel_id (priv->account, priv->tp_chan); return priv->id; } -gchar * -empathy_tp_chat_build_id (McAccount *account, - const gchar *contact_id) -{ - /* A handle name is unique only for a specific account */ - return g_strdup_printf ("%s/%s", - mc_account_get_unique_name (account), - contact_id); -} - -gchar * -empathy_tp_chat_build_id_for_chan (McAccount *account, - TpChan *tp_chan) -{ - MissionControl *mc; - TpConn *tp_conn; - GArray *handles; - gchar **names; - gchar *id; - GError *error = NULL; - - g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); - g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL); - - mc = gossip_mission_control_new (); - tp_conn = mission_control_get_connection (mc, account, NULL); - g_object_unref (mc); - - /* Get the handle's name */ - handles = g_array_new (FALSE, FALSE, sizeof (guint)); - g_array_append_val (handles, tp_chan->handle); - if (!tp_conn_inspect_handles (DBUS_G_PROXY (tp_conn), - tp_chan->handle_type, - handles, - &names, - &error)) { - gossip_debug (DEBUG_DOMAIN, - "Couldn't get id: %s", - error ? error->message : "No error given"); - g_clear_error (&error); - g_array_free (handles, TRUE); - g_object_unref (tp_conn); - - return NULL; - } - - id = empathy_tp_chat_build_id (account, *names); - - g_strfreev (names); - g_object_unref (tp_conn); - - return id; -} - static void tp_chat_destroy_cb (TpChan *text_chan, EmpathyTpChat *chat) diff --git a/libempathy/empathy-tp-chat.h b/libempathy/empathy-tp-chat.h index a9278c3f1..55bbfcd3d 100644 --- a/libempathy/empathy-tp-chat.h +++ b/libempathy/empathy-tp-chat.h @@ -65,10 +65,6 @@ void empathy_tp_chat_send (EmpathyTpChat * void empathy_tp_chat_set_state (EmpathyTpChat *chat, TelepathyChannelChatState state); const gchar * empathy_tp_chat_get_id (EmpathyTpChat *chat); -gchar * empathy_tp_chat_build_id (McAccount *account, - const gchar *contact_id); -gchar * empathy_tp_chat_build_id_for_chan (McAccount *account, - TpChan *tp_chan); G_END_DECLS diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c index 64bec75ff..6af5ed064 100644 --- a/libempathy/empathy-tp-contact-list.c +++ b/libempathy/empathy-tp-contact-list.c @@ -641,6 +641,7 @@ empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list, } if (new_handles->len == 0) { + g_array_free (new_handles, TRUE); return contacts; } @@ -1448,6 +1449,7 @@ tp_contact_list_group_members_added_cb (GossipTelepathyGroup *group, contact = GOSSIP_CONTACT (l->data); contact_groups = gossip_contact_get_groups (contact); + /* FIXME: this leaks */ if (!g_list_find_custom (contact_groups, group_name, (GCompareFunc) strcmp)) { @@ -1663,6 +1665,7 @@ tp_contact_list_request_avatar_cb (DBusGProxy *proxy, n_avatar_requests--; tp_contact_list_start_avatar_requests (data->list); + g_object_unref (contact); g_slice_free (TpContactListAvatarRequestData, data); } @@ -1699,6 +1702,7 @@ tp_contact_list_aliases_update_cb (DBusGProxy *proxy, tp_contact_list_block_contact (list, contact); gossip_contact_set_name (contact, alias); tp_contact_list_unblock_contact (list, contact); + g_object_unref (contact); gossip_debug (DEBUG_DOMAIN, "contact %d renamed to %s (update cb)", handle, alias); @@ -1727,6 +1731,7 @@ tp_contact_list_request_aliases_cb (DBusGProxy *proxy, tp_contact_list_block_contact (data->list, contact); gossip_contact_set_name (contact, *name); tp_contact_list_unblock_contact (data->list, contact); + g_object_unref (contact); gossip_debug (DEBUG_DOMAIN, "contact %d renamed to %s (request cb)", data->handles[i], *name); @@ -1781,6 +1786,8 @@ tp_contact_list_parse_presence_foreach (guint handle, tp_contact_list_block_contact (list, contact); gossip_contact_set_presence (contact, presence); tp_contact_list_unblock_contact (list, contact); + + g_object_unref (contact); } static void diff --git a/libempathy/gossip-chatroom-manager.c b/libempathy/gossip-chatroom-manager.c new file mode 100644 index 000000000..ade0b0ba0 --- /dev/null +++ b/libempathy/gossip-chatroom-manager.c @@ -0,0 +1,500 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2004-2007 Imendio AB + * Copyright (C) 2007 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Xavier Claessens + * Martyn Russell + */ + +#include "config.h" + +#include +#include +#include + +#include +#include + +#include "gossip-debug.h" +#include "gossip-chatroom-manager.h" +#include "gossip-utils.h" + +#define DEBUG_DOMAIN "ChatroomManager" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CHATROOM_MANAGER, GossipChatroomManagerPriv)) + +#define CHATROOMS_XML_FILENAME "chatrooms.xml" +#define CHATROOMS_DTD_FILENAME "gossip-chatroom-manager.dtd" + +struct _GossipChatroomManagerPriv { + GList *chatrooms; +}; + +static void gossip_chatroom_manager_class_init (GossipChatroomManagerClass *klass); +static void gossip_chatroom_manager_init (GossipChatroomManager *manager); +static void chatroom_manager_finalize (GObject *object); +static gboolean chatroom_manager_get_all (GossipChatroomManager *manager); +static gboolean chatroom_manager_file_parse (GossipChatroomManager *manager, + const gchar *filename); +static void chatroom_manager_parse_chatroom (GossipChatroomManager *manager, + xmlNodePtr node); +static gboolean chatroom_manager_file_save (GossipChatroomManager *manager); + +enum { + CHATROOM_ADDED, + CHATROOM_REMOVED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE (GossipChatroomManager, gossip_chatroom_manager, G_TYPE_OBJECT); + +static void +gossip_chatroom_manager_class_init (GossipChatroomManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = chatroom_manager_finalize; + + signals[CHATROOM_ADDED] = + g_signal_new ("chatroom-added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, GOSSIP_TYPE_CHATROOM); + signals[CHATROOM_REMOVED] = + g_signal_new ("chatroom-removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, GOSSIP_TYPE_CHATROOM); + + g_type_class_add_private (object_class, + sizeof (GossipChatroomManagerPriv)); +} + +static void +gossip_chatroom_manager_init (GossipChatroomManager *manager) +{ +} + +static void +chatroom_manager_finalize (GObject *object) +{ + GossipChatroomManagerPriv *priv; + + priv = GET_PRIV (object); + + g_list_foreach (priv->chatrooms, (GFunc) g_object_unref, NULL); + g_list_free (priv->chatrooms); + + (G_OBJECT_CLASS (gossip_chatroom_manager_parent_class)->finalize) (object); +} + +GossipChatroomManager * +gossip_chatroom_manager_new (void) +{ + static GossipChatroomManager *manager = NULL; + + if (!manager) { + GossipChatroomManagerPriv *priv; + + manager = g_object_new (GOSSIP_TYPE_CHATROOM_MANAGER, NULL); + priv = GET_PRIV (manager); + chatroom_manager_get_all (manager); + + g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager); + } else { + g_object_ref (manager); + } + + return manager; +} + +gboolean +gossip_chatroom_manager_add (GossipChatroomManager *manager, + GossipChatroom *chatroom) +{ + GossipChatroomManagerPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager), FALSE); + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), FALSE); + + priv = GET_PRIV (manager); + + /* don't add more than once */ + if (!gossip_chatroom_manager_find (manager, + gossip_chatroom_get_account (chatroom), + gossip_chatroom_get_room (chatroom))) { + priv->chatrooms = g_list_append (priv->chatrooms, g_object_ref (chatroom)); + chatroom_manager_file_save (manager); + + g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom); + + return TRUE; + } + + return FALSE; +} + +void +gossip_chatroom_manager_remove (GossipChatroomManager *manager, + GossipChatroom *chatroom) +{ + GossipChatroomManagerPriv *priv; + GList *l; + + g_return_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager)); + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + + priv = GET_PRIV (manager); + + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *this_chatroom; + + this_chatroom = l->data; + + if (gossip_chatroom_equal (chatroom, this_chatroom)) { + priv->chatrooms = g_list_delete_link (priv->chatrooms, l); + + chatroom_manager_file_save (manager); + + g_signal_emit (manager, signals[CHATROOM_REMOVED], 0, this_chatroom); + g_object_unref (this_chatroom); + break; + } + } +} + +GossipChatroom * +gossip_chatroom_manager_find (GossipChatroomManager *manager, + McAccount *account, + const gchar *room) +{ + GossipChatroomManagerPriv *priv; + GList *l; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager), NULL); + g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (room != NULL, NULL); + + priv = GET_PRIV (manager); + + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *chatroom; + McAccount *this_account; + const gchar *this_room; + + chatroom = l->data; + this_account = gossip_chatroom_get_account (chatroom); + this_room = gossip_chatroom_get_room (chatroom); + + if (gossip_account_equal (account, this_account) && + strcmp (this_room, room) == 0) { + return chatroom; + } + } + + return NULL; +} + +GList * +gossip_chatroom_manager_get_chatrooms (GossipChatroomManager *manager, + McAccount *account) +{ + GossipChatroomManagerPriv *priv; + GList *chatrooms, *l; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager), NULL); + + priv = GET_PRIV (manager); + + if (!account) { + return g_list_copy (priv->chatrooms); + } + + chatrooms = NULL; + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *chatroom; + + chatroom = l->data; + + if (gossip_account_equal (account, + gossip_chatroom_get_account (chatroom))) { + chatrooms = g_list_append (chatrooms, chatroom); + } + } + + return chatrooms; +} + +guint +gossip_chatroom_manager_get_count (GossipChatroomManager *manager, + McAccount *account) +{ + GossipChatroomManagerPriv *priv; + GList *l; + guint count = 0; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager), 0); + + priv = GET_PRIV (manager); + + if (!account) { + return g_list_length (priv->chatrooms); + } + + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *chatroom; + + chatroom = l->data; + + if (gossip_account_equal (account, + gossip_chatroom_get_account (chatroom))) { + count++; + } + } + + return count; +} + +void +gossip_chatroom_manager_store (GossipChatroomManager *manager) +{ + g_return_if_fail (GOSSIP_IS_CHATROOM_MANAGER (manager)); + + chatroom_manager_file_save (manager); +} + +/* + * API to save/load and parse the chatrooms file. + */ + +static gboolean +chatroom_manager_get_all (GossipChatroomManager *manager) +{ + GossipChatroomManagerPriv *priv; + gchar *dir; + gchar *file_with_path = NULL; + + priv = GET_PRIV (manager); + + dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL); + if (!g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR); + } + + file_with_path = g_build_filename (dir, CHATROOMS_XML_FILENAME, NULL); + g_free (dir); + + /* read file in */ + if (g_file_test (file_with_path, G_FILE_TEST_EXISTS) && + !chatroom_manager_file_parse (manager, file_with_path)) { + g_free (file_with_path); + return FALSE; + } + + g_free (file_with_path); + + return TRUE; +} + +static gboolean +chatroom_manager_file_parse (GossipChatroomManager *manager, + const gchar *filename) +{ + GossipChatroomManagerPriv *priv; + xmlParserCtxtPtr ctxt; + xmlDocPtr doc; + xmlNodePtr chatrooms; + xmlNodePtr node; + + priv = GET_PRIV (manager); + + gossip_debug (DEBUG_DOMAIN, "Attempting to parse file:'%s'...", filename); + + ctxt = xmlNewParserCtxt (); + + /* Parse and validate the file. */ + doc = xmlCtxtReadFile (ctxt, filename, NULL, 0); + if (!doc) { + g_warning ("Failed to parse file:'%s'", filename); + xmlFreeParserCtxt (ctxt); + return FALSE; + } + + if (!gossip_xml_validate (doc, CHATROOMS_DTD_FILENAME)) { + g_warning ("Failed to validate file:'%s'", filename); + xmlFreeDoc(doc); + xmlFreeParserCtxt (ctxt); + return FALSE; + } + + /* The root node, chatrooms. */ + chatrooms = xmlDocGetRootElement (doc); + + for (node = chatrooms->children; node; node = node->next) { + if (strcmp ((gchar *) node->name, "chatroom") == 0) { + chatroom_manager_parse_chatroom (manager, node); + } + } + + gossip_debug (DEBUG_DOMAIN, + "Parsed %d chatrooms", + g_list_length (priv->chatrooms)); + + xmlFreeDoc(doc); + xmlFreeParserCtxt (ctxt); + + return TRUE; +} + +static void +chatroom_manager_parse_chatroom (GossipChatroomManager *manager, + xmlNodePtr node) +{ + GossipChatroomManagerPriv *priv; + GossipChatroom *chatroom; + McAccount *account; + xmlNodePtr child; + gchar *str; + gchar *name; + gchar *room; + gchar *account_id; + gboolean auto_connect; + + priv = GET_PRIV (manager); + + /* default values. */ + name = NULL; + room = NULL; + auto_connect = TRUE; + account_id = NULL; + + for (child = node->children; child; child = child->next) { + gchar *tag; + + if (xmlNodeIsText (child)) { + continue; + } + + tag = (gchar *) child->name; + str = (gchar *) xmlNodeGetContent (child); + + if (strcmp (tag, "name") == 0) { + name = g_strdup (str); + } + else if (strcmp (tag, "room") == 0) { + room = g_strdup (str); + } + else if (strcmp (tag, "auto_connect") == 0) { + if (strcmp (str, "yes") == 0) { + auto_connect = TRUE; + } else { + auto_connect = FALSE; + } + } + else if (strcmp (tag, "account") == 0) { + account_id = g_strdup (str); + } + + xmlFree (str); + } + + account = mc_account_lookup (account_id); + if (!account) { + g_free (name); + g_free (room); + g_free (account_id); + return; + } + + chatroom = gossip_chatroom_new_full (account, + room, + name, + auto_connect); + + priv->chatrooms = g_list_prepend (priv->chatrooms, chatroom); + + g_object_unref (account); + g_free (name); + g_free (room); + g_free (account_id); +} + +static gboolean +chatroom_manager_file_save (GossipChatroomManager *manager) +{ + GossipChatroomManagerPriv *priv; + xmlDocPtr doc; + xmlNodePtr root; + GList *l; + gchar *dir; + gchar *file; + + priv = GET_PRIV (manager); + + dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL); + if (!g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR); + } + + file = g_build_filename (dir, CHATROOMS_XML_FILENAME, NULL); + g_free (dir); + + doc = xmlNewDoc ("1.0"); + root = xmlNewNode (NULL, "chatrooms"); + xmlDocSetRootElement (doc, root); + + for (l = priv->chatrooms; l; l = l->next) { + GossipChatroom *chatroom; + xmlNodePtr node; + const gchar *account_id; + + chatroom = l->data; + account_id = mc_account_get_unique_name (gossip_chatroom_get_account (chatroom)); + + node = xmlNewChild (root, NULL, "chatroom", NULL); + xmlNewTextChild (node, NULL, "name", gossip_chatroom_get_name (chatroom)); + xmlNewTextChild (node, NULL, "room", gossip_chatroom_get_room (chatroom)); + xmlNewTextChild (node, NULL, "account", account_id); + xmlNewTextChild (node, NULL, "auto_connect", gossip_chatroom_get_auto_connect (chatroom) ? "yes" : "no"); + } + + /* Make sure the XML is indented properly */ + xmlIndentTreeOutput = 1; + + gossip_debug (DEBUG_DOMAIN, "Saving file:'%s'", file); + xmlSaveFormatFileEnc (file, doc, "utf-8", 1); + xmlFreeDoc (doc); + + xmlCleanupParser (); + xmlMemoryDump (); + + g_free (file); + + return TRUE; +} diff --git a/libempathy/gossip-chatroom-manager.dtd b/libempathy/gossip-chatroom-manager.dtd new file mode 100644 index 000000000..5d94a57c2 --- /dev/null +++ b/libempathy/gossip-chatroom-manager.dtd @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/libempathy/gossip-chatroom-manager.h b/libempathy/gossip-chatroom-manager.h new file mode 100644 index 000000000..7d10a0fc1 --- /dev/null +++ b/libempathy/gossip-chatroom-manager.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2004-2007 Imendio AB + * Copyright (C) 2007 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Xavier Claessens + * Martyn Russell + */ + +#ifndef __GOSSIP_CHATROOM_MANAGER_H__ +#define __GOSSIP_CHATROOM_MANAGER_H__ + +#include + +#include + +#include "gossip-chatroom.h" + +G_BEGIN_DECLS + +#define GOSSIP_TYPE_CHATROOM_MANAGER (gossip_chatroom_manager_get_type ()) +#define GOSSIP_CHATROOM_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_CHATROOM_MANAGER, GossipChatroomManager)) +#define GOSSIP_CHATROOM_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GOSSIP_TYPE_CHATROOM_MANAGER, GossipChatroomManagerClass)) +#define GOSSIP_IS_CHATROOM_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_CHATROOM_MANAGER)) +#define GOSSIP_IS_CHATROOM_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_CHATROOM_MANAGER)) +#define GOSSIP_CHATROOM_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_CHATROOM_MANAGER, GossipChatroomManagerClass)) + +typedef struct _GossipChatroomManager GossipChatroomManager; +typedef struct _GossipChatroomManagerClass GossipChatroomManagerClass; +typedef struct _GossipChatroomManagerPriv GossipChatroomManagerPriv; + +struct _GossipChatroomManager { + GObject parent; +}; + +struct _GossipChatroomManagerClass { + GObjectClass parent_class; +}; + +GType gossip_chatroom_manager_get_type (void) G_GNUC_CONST; +GossipChatroomManager *gossip_chatroom_manager_new (void); +gboolean gossip_chatroom_manager_add (GossipChatroomManager *manager, + GossipChatroom *chatroom); +void gossip_chatroom_manager_remove (GossipChatroomManager *manager, + GossipChatroom *chatroom); +GossipChatroom * gossip_chatroom_manager_find (GossipChatroomManager *manager, + McAccount *account, + const gchar *room); +GList * gossip_chatroom_manager_get_chatrooms (GossipChatroomManager *manager, + McAccount *account); +guint gossip_chatroom_manager_get_count (GossipChatroomManager *manager, + McAccount *account); +void gossip_chatroom_manager_store (GossipChatroomManager *manager); + +G_END_DECLS + +#endif /* __GOSSIP_CHATROOM_MANAGER_H__ */ diff --git a/libempathy/gossip-chatroom.c b/libempathy/gossip-chatroom.c new file mode 100644 index 000000000..eccd2824c --- /dev/null +++ b/libempathy/gossip-chatroom.c @@ -0,0 +1,360 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Xavier Claessens + */ + +#include "config.h" + +#include + +#include + +#include "gossip-chatroom.h" +#include "gossip-utils.h" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CHATROOM, GossipChatroomPriv)) + +struct _GossipChatroomPriv { + McAccount *account; + gchar *room; + gchar *name; + gboolean auto_connect; +}; + +static void gossip_chatroom_class_init (GossipChatroomClass *klass); +static void gossip_chatroom_init (GossipChatroom *chatroom); +static void chatroom_finalize (GObject *object); +static void chatroom_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void chatroom_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +enum { + PROP_0, + PROP_ACCOUNT, + PROP_ROOM, + PROP_NAME, + PROP_AUTO_CONNECT, +}; + +G_DEFINE_TYPE (GossipChatroom, gossip_chatroom, G_TYPE_OBJECT); + +static void +gossip_chatroom_class_init (GossipChatroomClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = chatroom_finalize; + object_class->get_property = chatroom_get_property; + object_class->set_property = chatroom_set_property; + + g_object_class_install_property (object_class, + PROP_ACCOUNT, + g_param_spec_object ("account", + "Chatroom Account", + "The account associated with an chatroom", + MC_TYPE_ACCOUNT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_ROOM, + g_param_spec_string ("room", + "Chatroom Room", + "Chatroom represented as 'room@server'", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_NAME, + g_param_spec_string ("name", + "Chatroom Name", + "Chatroom name", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_AUTO_CONNECT, + g_param_spec_boolean ("auto_connect", + "Chatroom Auto Connect", + "Connect on startup", + FALSE, + G_PARAM_READWRITE)); + + + g_type_class_add_private (object_class, sizeof (GossipChatroomPriv)); +} + +static void +gossip_chatroom_init (GossipChatroom *chatroom) +{ +} + +static void +chatroom_finalize (GObject *object) +{ + GossipChatroomPriv *priv; + + priv = GET_PRIV (object); + + g_object_unref (priv->account); + g_free (priv->room); + g_free (priv->name); + + (G_OBJECT_CLASS (gossip_chatroom_parent_class)->finalize) (object); +} + +static void +chatroom_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + GossipChatroomPriv *priv; + + priv = GET_PRIV (object); + + switch (param_id) { + case PROP_ACCOUNT: + g_value_set_object (value, priv->account); + break; + case PROP_ROOM: + g_value_set_string (value, priv->room); + break; + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + case PROP_AUTO_CONNECT: + g_value_set_boolean (value, priv->auto_connect); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +static void +chatroom_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + GossipChatroomPriv *priv; + + priv = GET_PRIV (object); + + switch (param_id) { + case PROP_ACCOUNT: + gossip_chatroom_set_account (GOSSIP_CHATROOM (object), + g_value_get_object (value)); + break; + case PROP_ROOM: + gossip_chatroom_set_room (GOSSIP_CHATROOM (object), + g_value_get_string (value)); + break; + case PROP_NAME: + gossip_chatroom_set_name (GOSSIP_CHATROOM (object), + g_value_get_string (value)); + break; + case PROP_AUTO_CONNECT: + gossip_chatroom_set_auto_connect (GOSSIP_CHATROOM (object), + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +GossipChatroom * +gossip_chatroom_new (McAccount *account, + const gchar *room) +{ + g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (room != NULL, NULL); + + return g_object_new (GOSSIP_TYPE_CHATROOM, + "account", account, + "room", room, + NULL); +} + +GossipChatroom * +gossip_chatroom_new_full (McAccount *account, + const gchar *room, + const gchar *name, + gboolean auto_connect) +{ + g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (room != NULL, NULL); + + return g_object_new (GOSSIP_TYPE_CHATROOM, + "account", account, + "room", room, + "name", name, + "auto_connect", auto_connect, + NULL); +} + +McAccount * +gossip_chatroom_get_account (GossipChatroom *chatroom) +{ + GossipChatroomPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), NULL); + + priv = GET_PRIV (chatroom); + return priv->account; +} + +void +gossip_chatroom_set_account (GossipChatroom *chatroom, + McAccount *account) +{ + GossipChatroomPriv *priv; + + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + g_return_if_fail (MC_IS_ACCOUNT (account)); + + priv = GET_PRIV (chatroom); + + if (account == priv->account) { + return; + } + if (priv->account) { + g_object_unref (priv->account); + } + priv->account = g_object_ref (account); + + g_object_notify (G_OBJECT (chatroom), "account"); +} + +const gchar * +gossip_chatroom_get_room (GossipChatroom *chatroom) +{ + GossipChatroomPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), NULL); + + priv = GET_PRIV (chatroom); + return priv->room; +} + +void +gossip_chatroom_set_room (GossipChatroom *chatroom, + const gchar *room) +{ + GossipChatroomPriv *priv; + + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + g_return_if_fail (room != NULL); + + priv = GET_PRIV (chatroom); + + g_free (priv->room); + priv->room = g_strdup (room); + + g_object_notify (G_OBJECT (chatroom), "room"); +} + +const gchar * +gossip_chatroom_get_name (GossipChatroom *chatroom) +{ + GossipChatroomPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), NULL); + + priv = GET_PRIV (chatroom); + + if (G_STR_EMPTY (priv->name)) { + return priv->room; + } + + return priv->name; +} + +void +gossip_chatroom_set_name (GossipChatroom *chatroom, + const gchar *name) +{ + GossipChatroomPriv *priv; + + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + g_return_if_fail (name != NULL); + + priv = GET_PRIV (chatroom); + + g_free (priv->name); + priv->name = g_strdup (name); + + g_object_notify (G_OBJECT (chatroom), "name"); +} + +gboolean +gossip_chatroom_get_auto_connect (GossipChatroom *chatroom) +{ + GossipChatroomPriv *priv; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (chatroom), FALSE); + + priv = GET_PRIV (chatroom); + return priv->auto_connect; +} + +void +gossip_chatroom_set_auto_connect (GossipChatroom *chatroom, + gboolean auto_connect) +{ + GossipChatroomPriv *priv; + + g_return_if_fail (GOSSIP_IS_CHATROOM (chatroom)); + + priv = GET_PRIV (chatroom); + + priv->auto_connect = auto_connect; + + g_object_notify (G_OBJECT (chatroom), "auto-connect"); +} + +gboolean +gossip_chatroom_equal (gconstpointer v1, + gconstpointer v2) +{ + McAccount *account_a; + McAccount *account_b; + const gchar *room_a; + const gchar *room_b; + + g_return_val_if_fail (GOSSIP_IS_CHATROOM (v1), FALSE); + g_return_val_if_fail (GOSSIP_IS_CHATROOM (v2), FALSE); + + account_a = gossip_chatroom_get_account (GOSSIP_CHATROOM (v1)); + account_b = gossip_chatroom_get_account (GOSSIP_CHATROOM (v2)); + + room_a = gossip_chatroom_get_room (GOSSIP_CHATROOM (v1)); + room_b = gossip_chatroom_get_room (GOSSIP_CHATROOM (v2)); + + return gossip_account_equal (account_a, account_b) && g_str_equal (room_a, room_b); +} + + diff --git a/libempathy/gossip-chatroom.h b/libempathy/gossip-chatroom.h new file mode 100644 index 000000000..70614a368 --- /dev/null +++ b/libempathy/gossip-chatroom.h @@ -0,0 +1,78 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Xavier Claessens + */ + +#ifndef __GOSSIP_CHATROOM_H__ +#define __GOSSIP_CHATROOM_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define GOSSIP_TYPE_CHATROOM (gossip_chatroom_get_type ()) +#define GOSSIP_CHATROOM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_CHATROOM, GossipChatroom)) +#define GOSSIP_CHATROOM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GOSSIP_TYPE_CHATROOM, GossipChatroomClass)) +#define GOSSIP_IS_CHATROOM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_CHATROOM)) +#define GOSSIP_IS_CHATROOM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_CHATROOM)) +#define GOSSIP_CHATROOM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_CHATROOM, GossipChatroomClass)) + +#define GOSSIP_TYPE_CHATROOM_INVITE (gossip_chatroom_invite_get_gtype ()) + +typedef struct _GossipChatroom GossipChatroom; +typedef struct _GossipChatroomClass GossipChatroomClass; +typedef struct _GossipChatroomPriv GossipChatroomPriv; + +struct _GossipChatroom { + GObject parent; +}; + +struct _GossipChatroomClass { + GObjectClass parent_class; +}; + +GType gossip_chatroom_get_type (void) G_GNUC_CONST; +GossipChatroom *gossip_chatroom_new (McAccount *account, + const gchar *room); +GossipChatroom *gossip_chatroom_new_full (McAccount *account, + const gchar *room, + const gchar *name, + gboolean auto_connect); +McAccount * gossip_chatroom_get_account (GossipChatroom *chatroom); +void gossip_chatroom_set_account (GossipChatroom *chatroom, + McAccount *account); +const gchar * gossip_chatroom_get_room (GossipChatroom *chatroom); +void gossip_chatroom_set_room (GossipChatroom *chatroom, + const gchar *room); +const gchar * gossip_chatroom_get_name (GossipChatroom *chatroom); +void gossip_chatroom_set_name (GossipChatroom *chatroom, + const gchar *name); +gboolean gossip_chatroom_get_auto_connect (GossipChatroom *chatroom); +void gossip_chatroom_set_auto_connect (GossipChatroom *chatroom, + gboolean auto_connect); +gboolean gossip_chatroom_equal (gconstpointer v1, + gconstpointer v2); + + +G_BEGIN_DECLS + +#endif /* __GOSSIP_CHATROOM_H__ */ diff --git a/libempathy/gossip-utils.c b/libempathy/gossip-utils.c index 6ab70ce4a..579981616 100644 --- a/libempathy/gossip-utils.c +++ b/libempathy/gossip-utils.c @@ -33,7 +33,6 @@ #include #include -#include #include #include "gossip-debug.h" @@ -447,3 +446,51 @@ gossip_mission_control_new (void) return mc; } +gchar * +gossip_get_channel_id (McAccount *account, + TpChan *tp_chan) +{ + MissionControl *mc; + TpConn *tp_conn; + GArray *handles; + gchar **names; + gchar *name; + GError *error; + + g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL); + + mc = gossip_mission_control_new (); + tp_conn = mission_control_get_connection (mc, account, NULL); + g_object_unref (mc); + + if (!tp_conn) { + return NULL; + } + + /* Get the handle's name */ + handles = g_array_new (FALSE, FALSE, sizeof (guint)); + g_array_append_val (handles, tp_chan->handle); + if (!tp_conn_inspect_handles (DBUS_G_PROXY (tp_conn), + tp_chan->handle_type, + handles, + &names, + &error)) { + gossip_debug (DEBUG_DOMAIN, + "Couldn't get id: %s", + error ? error->message : "No error given"); + + g_clear_error (&error); + g_array_free (handles, TRUE); + g_object_unref (tp_conn); + + return NULL; + } + + name = *names; + g_free (names); + g_object_unref (tp_conn); + + return name; +} + diff --git a/libempathy/gossip-utils.h b/libempathy/gossip-utils.h index 052dfb781..638c114bd 100644 --- a/libempathy/gossip-utils.h +++ b/libempathy/gossip-utils.h @@ -32,6 +32,9 @@ #include #include +#include + +#include #include #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 -- cgit v1.2.3