aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy/empathy-chatroom-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy/empathy-chatroom-manager.c')
-rw-r--r--libempathy/empathy-chatroom-manager.c87
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);
}