1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2003-2007 Imendio AB
4 * Copyright (C) 2007-2008 Collabora Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
21 * Authors: Xavier Claessens <xclaesse@gmail.com>
29 #include <glib/gstdio.h>
31 #include <telepathy-glib/util.h>
33 #include "empathy-log-manager.h"
34 #include "empathy-log-store-empathy.h"
35 #include "empathy-log-store.h"
36 #include "empathy-tp-chat.h"
37 #include "empathy-utils.h"
39 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
40 #include "empathy-debug.h"
42 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyLogManager)
46 } EmpathyLogManagerPriv;
48 G_DEFINE_TYPE (EmpathyLogManager, empathy_log_manager, G_TYPE_OBJECT);
50 static EmpathyLogManager * manager_singleton = NULL;
53 log_manager_finalize (GObject *object)
55 EmpathyLogManagerPriv *priv;
58 priv = GET_PRIV (object);
60 for (l = priv->stores; l; l = l->next)
62 EmpathyLogStore *store = (EmpathyLogStore *) l->data;
63 g_object_unref (store);
66 g_list_free (priv->stores);
70 log_manager_constructor (GType type,
72 GObjectConstructParam *props)
76 if (manager_singleton)
78 retval = g_object_ref (manager_singleton);
82 retval = G_OBJECT_CLASS (empathy_log_manager_parent_class)->constructor
83 (type, n_props, props);
85 manager_singleton = EMPATHY_LOG_MANAGER (retval);
86 g_object_add_weak_pointer (retval, (gpointer *) &manager_singleton);
88 priv = GET_PRIV (manager_singleton);
90 priv->sources = g_list_append (priv->sources,
91 empathy_log_source_empathy_get_source ());
98 empathy_log_manager_class_init (EmpathyLogManagerClass *klass)
100 GObjectClass *object_class = G_OBJECT_CLASS (klass);
102 object_class->constructor = log_manager_constructor;
103 object_class->finalize = log_manager_finalize;
105 g_type_class_add_private (object_class, sizeof (EmpathyLogManagerPriv));
109 empathy_log_manager_init (EmpathyLogManager *manager)
111 EmpathyLogManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
112 EMPATHY_TYPE_LOG_MANAGER, EmpathyLogManagerPriv);
114 priv->stores = g_list_append (priv->stores,
115 g_object_new (EMPATHY_TYPE_LOG_STORE_EMPATHY, NULL));
117 manager->priv = priv;
121 empathy_log_manager_dup_singleton (void)
123 return g_object_new (EMPATHY_TYPE_LOG_MANAGER, NULL);
127 empathy_log_manager_add_message (EmpathyLogManager *manager,
128 const gchar *chat_id,
130 EmpathyMessage *message,
133 EmpathyLogManagerPriv *priv;
135 gboolean out = FALSE;
136 gboolean found = FALSE;
138 /* TODO: When multiple log stores appear with add_message implementations
139 * make this customisable. */
140 const gchar *add_store = "Empathy";
142 g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), FALSE);
143 g_return_val_if_fail (chat_id != NULL, FALSE);
144 g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
146 priv = GET_PRIV (manager);
148 for (l = priv->stores; l; l = l->next)
150 if (!tp_strdiff (empathy_log_store_get_name (
151 EMPATHY_LOG_STORE (l->data)), add_store))
153 out = empathy_log_store_add_message (EMPATHY_LOG_STORE (l->data),
154 chat_id, chatroom, message, error);
161 DEBUG ("Failed to find chosen log store to write to.");
167 empathy_log_manager_exists (EmpathyLogManager *manager,
169 const gchar *chat_id,
173 EmpathyLogManagerPriv *priv;
175 g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), FALSE);
176 g_return_val_if_fail (MC_IS_ACCOUNT (account), FALSE);
177 g_return_val_if_fail (chat_id != NULL, FALSE);
179 priv = GET_PRIV (manager);
181 for (l = priv->stores; l; l = l->next)
183 if (empathy_log_store_exists (EMPATHY_LOG_STORE (l->data),
184 account, chat_id, chatroom))
192 log_manager_get_dates_foreach (gpointer data,
195 /* g_list_first is needed in case an older date was last inserted */
196 GList *orig = g_list_first (user_data);
198 if (g_list_find_custom (orig, data, (GCompareFunc) strcmp))
199 orig = g_list_insert_sorted (orig, g_strdup (data), (GCompareFunc) strcmp);
203 empathy_log_manager_get_dates (EmpathyLogManager *manager,
205 const gchar *chat_id,
208 GList *l, *out = NULL;
209 EmpathyLogManagerPriv *priv;
211 g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
212 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
213 g_return_val_if_fail (chat_id != NULL, NULL);
215 priv = GET_PRIV (manager);
217 for (l = priv->stores; l; l = l->next)
219 EmpathyLogStore *store = EMPATHY_LOG_STORE (l->data);
222 out = empathy_log_store_get_dates (store, account, chat_id, chatroom);
225 GList *new = empathy_log_store_get_dates (store, account, chat_id,
227 g_list_foreach (new, log_manager_get_dates_foreach, out);
229 g_list_foreach (new, (GFunc) g_free, NULL);
232 /* Similar reason for using g_list_first here as before */
233 out = g_list_first (out);
241 empathy_log_manager_get_messages_for_date (EmpathyLogManager *manager,
243 const gchar *chat_id,
247 GList *l, *out = NULL;
248 EmpathyLogManagerPriv *priv;
250 g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
251 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
252 g_return_val_if_fail (chat_id != NULL, NULL);
254 priv = GET_PRIV (manager);
256 for (l = priv->stores; l; l = l->next)
258 EmpathyLogStore *store = EMPATHY_LOG_STORE (l->data);
260 out = g_list_concat (out, empathy_log_store_get_messages_for_date (
261 store, account, chat_id, chatroom, date));
268 empathy_log_manager_get_last_messages (EmpathyLogManager *manager,
270 const gchar *chat_id,
273 GList *messages = NULL;
277 g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
278 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
279 g_return_val_if_fail (chat_id != NULL, NULL);
281 dates = empathy_log_manager_get_dates (manager, account, chat_id, chatroom);
283 l = g_list_last (dates);
285 messages = empathy_log_manager_get_messages_for_date (manager, account,
286 chat_id, chatroom, l->data);
288 g_list_foreach (dates, (GFunc) g_free, NULL);
295 empathy_log_manager_get_chats (EmpathyLogManager *manager,
298 GList *l, *out = NULL;
299 EmpathyLogManagerPriv *priv;
301 g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
302 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
304 priv = GET_PRIV (manager);
306 for (l = priv->stores; l; l = l->next)
308 EmpathyLogStore *store = EMPATHY_LOG_STORE (l->data);
310 out = g_list_concat (out,
311 empathy_log_store_get_chats (store, account));
318 empathy_log_manager_search_new (EmpathyLogManager *manager,
321 GList *l, *out = NULL;
322 EmpathyLogManagerPriv *priv;
324 g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
325 g_return_val_if_fail (!EMP_STR_EMPTY (text), NULL);
327 priv = GET_PRIV (manager);
329 for (l = priv->stores; l; l = l->next)
331 EmpathyLogStore *store = EMPATHY_LOG_STORE (l->data);
333 out = g_list_concat (out,
334 empathy_log_store_search_new (store, text));
341 empathy_log_manager_search_hit_free (EmpathyLogSearchHit *hit)
344 g_object_unref (hit->account);
347 g_free (hit->filename);
348 g_free (hit->chat_id);
350 g_slice_free (EmpathyLogSearchHit, hit);
354 empathy_log_manager_search_free (GList *hits)
358 for (l = hits; l; l = l->next)
360 empathy_log_manager_search_hit_free (l->data);
366 /* Format is just date, 20061201. */
368 empathy_log_manager_get_date_readable (const gchar *date)
372 t = empathy_time_parse (date);
374 return empathy_time_to_string_local (t, "%a %d %b %Y");
379 EmpathyLogManager *log_manager;
381 } MessageObserveData;
384 message_observe_data_free (MessageObserveData *data)
386 g_slice_free (MessageObserveData, data);
390 log_manager_chat_received_message_cb (EmpathyTpChat *tp_chat,
391 EmpathyMessage *message,
392 MessageObserveData *data)
394 GError *error = NULL;
395 TpHandleType handle_type;
397 tp_channel_get_handle (data->channel, &handle_type);
399 if (!empathy_log_manager_add_message (data->log_manager,
400 tp_channel_get_identifier (data->channel),
401 handle_type == TP_HANDLE_TYPE_ROOM,
404 DEBUG ("Failed to write message: %s",
405 error ? error->message : "No error message");
408 g_error_free (error);
413 log_manager_dispatcher_observe_cb (EmpathyDispatcher *dispatcher,
414 EmpathyDispatchOperation *operation,
415 EmpathyLogManager *log_manager)
419 channel_type = empathy_dispatch_operation_get_channel_type_id (operation);
421 if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
423 EmpathyTpChat *tp_chat;
425 MessageObserveData *data;
427 tp_chat = EMPATHY_TP_CHAT (
428 empathy_dispatch_operation_get_channel_wrapper (operation));
430 channel = empathy_dispatch_operation_get_channel (operation);
432 data = g_slice_new0 (MessageObserveData);
433 data->log_manager = log_manager;
434 data->channel = channel;
436 g_signal_connect_data (tp_chat, "message-received",
437 G_CALLBACK (log_manager_chat_received_message_cb), data,
438 (GClosureNotify) message_observe_data_free, 0);
444 empathy_log_manager_observe (EmpathyLogManager *log_manager,
445 EmpathyDispatcher *dispatcher)
447 g_signal_connect (dispatcher, "observe",
448 G_CALLBACK (log_manager_dispatcher_observe_cb), log_manager);