diff options
Diffstat (limited to 'libempathy/empathy-chatroom-manager.c')
-rw-r--r-- | libempathy/empathy-chatroom-manager.c | 87 |
1 files changed, 74 insertions, 13 deletions
diff --git a/libempathy/empathy-chatroom-manager.c b/libempathy/empathy-chatroom-manager.c index edf6d6ced..a4b95aadf 100644 --- a/libempathy/empathy-chatroom-manager.c +++ b/libempathy/empathy-chatroom-manager.c @@ -67,6 +67,8 @@ typedef struct /* source id of the autosave timer */ gint save_timer_id; gboolean ready; + GFileMonitor *monitor; + gboolean writing; TpBaseClient *observer; } EmpathyChatroomManagerPriv; @@ -103,6 +105,8 @@ chatroom_manager_file_save (EmpathyChatroomManager *manager) priv = GET_PRIV (manager); + priv->writing = TRUE; + doc = xmlNewDoc ((const xmlChar *) "1.0"); root = xmlNewNode (NULL, (const xmlChar *) "chatrooms"); xmlDocSetRootElement (doc, root); @@ -145,6 +149,7 @@ chatroom_manager_file_save (EmpathyChatroomManager *manager) xmlMemoryDump (); + priv->writing = FALSE; return TRUE; } @@ -338,8 +343,11 @@ chatroom_manager_get_all (EmpathyChatroomManager *manager) !chatroom_manager_file_parse (manager, priv->file)) return FALSE; - priv->ready = TRUE; - g_object_notify (G_OBJECT (manager), "ready"); + if (!priv->ready) + { + priv->ready = TRUE; + g_object_notify (G_OBJECT (manager), "ready"); + } return TRUE; } @@ -396,16 +404,37 @@ chatroom_manager_dispose (GObject *object) priv = GET_PRIV (object); tp_clear_object (&priv->observer); + tp_clear_object (&priv->monitor); (G_OBJECT_CLASS (empathy_chatroom_manager_parent_class)->dispose) (object); } static void +clear_chatrooms (EmpathyChatroomManager *self) +{ + EmpathyChatroomManagerPriv *priv = GET_PRIV (self); + GList *l; + + for (l = priv->chatrooms; l != NULL; l = g_list_next (l)) + { + EmpathyChatroom *chatroom = l->data; + + g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb, + self); + g_signal_emit (self, signals[CHATROOM_REMOVED], 0, chatroom); + + g_object_unref (chatroom); + } + + g_list_free (priv->chatrooms); + priv->chatrooms = NULL; +} + +static void chatroom_manager_finalize (GObject *object) { EmpathyChatroomManager *self = EMPATHY_CHATROOM_MANAGER (object); EmpathyChatroomManagerPriv *priv; - GList *l; priv = GET_PRIV (object); @@ -419,30 +448,45 @@ chatroom_manager_finalize (GObject *object) chatroom_manager_file_save (self); } - for (l = priv->chatrooms; l != NULL; l = g_list_next (l)) - { - EmpathyChatroom *chatroom = l->data; + clear_chatrooms (self); - g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb, - self); - - g_object_unref (chatroom); - } - - g_list_free (priv->chatrooms); g_free (priv->file); (G_OBJECT_CLASS (empathy_chatroom_manager_parent_class)->finalize) (object); } static void +file_changed_cb (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + EmpathyChatroomManager *self = user_data; + EmpathyChatroomManagerPriv *priv = GET_PRIV (self); + + if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) + return; + + if (priv->writing) + return; + + DEBUG ("chatrooms file changed; reloading list"); + + clear_chatrooms (self); + chatroom_manager_get_all (self); +} + +static void account_manager_ready_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { EmpathyChatroomManager *self = EMPATHY_CHATROOM_MANAGER (user_data); + EmpathyChatroomManagerPriv *priv = GET_PRIV (self); TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object); GError *error = NULL; + GFile *file; if (!tp_account_manager_prepare_finish (manager, result, &error)) { @@ -453,7 +497,24 @@ account_manager_ready_cb (GObject *source_object, chatroom_manager_get_all (self); + /* Set up file monitor */ + file = g_file_new_for_path (priv->file); + + priv->monitor = g_file_monitor (file, 0, NULL, &error); + if (priv->monitor == NULL) + { + DEBUG ("Failed to create file monitor on %s: %s", priv->file, + error->message); + + g_error_free (error); + goto out; + } + + g_signal_connect (priv->monitor, "changed", G_CALLBACK (file_changed_cb), + self); + out: + tp_clear_object (&file); g_object_unref (self); } |