2 * Copyright (C) 2006-2007 Imendio AB
3 * Copyright (C) 2007-2011 Collabora Ltd.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301 USA
20 * Authors: Martyn Russell <martyn@imendio.com>
21 * Xavier Claessens <xclaesse@gmail.com>
22 * Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
30 #include <glib/gi18n-lib.h>
33 #include <telepathy-glib/telepathy-glib.h>
34 #include <telepathy-glib/proxy-subclass.h>
36 #include <telepathy-logger/telepathy-logger.h>
37 #include <telepathy-logger/call-event.h>
39 #include <extensions/extensions.h>
41 #include <libempathy/action-chain-internal.h>
42 #include <libempathy/empathy-chatroom-manager.h>
43 #include <libempathy/empathy-chatroom.h>
44 #include <libempathy/empathy-message.h>
45 #include <libempathy/empathy-request-util.h>
46 #include <libempathy/empathy-utils.h>
47 #include <libempathy/empathy-time.h>
49 #include "empathy-log-window.h"
50 #include "empathy-account-chooser.h"
51 #include "empathy-call-utils.h"
52 #include "empathy-chat-view.h"
53 #include "empathy-contact-dialogs.h"
54 #include "empathy-images.h"
55 #include "empathy-theme-manager.h"
56 #include "empathy-ui-utils.h"
58 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
59 #include <libempathy/empathy-debug.h>
65 GtkWidget *button_profile;
66 GtkWidget *button_chat;
67 GtkWidget *button_call;
68 GtkWidget *button_video;
70 GtkWidget *search_entry;
72 GtkWidget *treeview_who;
73 GtkWidget *treeview_what;
74 GtkWidget *treeview_when;
75 GtkWidget *treeview_events;
77 GtkTreeStore *store_events;
79 GtkWidget *account_chooser;
83 TplActionChain *chain;
84 TplLogManager *log_manager;
86 /* Used to cancel logger calls when no longer needed */
89 /* List of owned TplLogSearchHits, free with tpl_log_search_hit_free */
93 /* Only used while waiting for the account chooser to be ready */
94 TpAccount *selected_account;
95 gchar *selected_chat_id;
96 gboolean selected_is_chatroom;
99 static void log_window_destroy_cb (GtkWidget *widget,
100 EmpathyLogWindow *window);
101 static void log_window_search_entry_changed_cb (GtkWidget *entry,
102 EmpathyLogWindow *window);
103 static void log_window_search_entry_activate_cb (GtkWidget *widget,
104 EmpathyLogWindow *window);
105 static void log_window_who_populate (EmpathyLogWindow *window);
106 static void log_window_who_setup (EmpathyLogWindow *window);
107 static void log_window_when_setup (EmpathyLogWindow *window);
108 static void log_window_what_setup (EmpathyLogWindow *window);
109 static void log_window_events_setup (EmpathyLogWindow *window);
110 static void log_window_chats_accounts_changed_cb (GtkWidget *combobox,
111 EmpathyLogWindow *window);
112 static void log_window_chats_set_selected (EmpathyLogWindow *window);
113 static void log_window_chats_get_messages (EmpathyLogWindow *window,
114 gboolean force_get_dates);
115 static void log_window_when_changed_cb (GtkTreeSelection *selection,
116 EmpathyLogWindow *window);
117 static void log_window_delete_menu_clicked_cb (GtkMenuItem *menuitem,
118 EmpathyLogWindow *window);
121 empathy_account_chooser_filter_has_logs (TpAccount *account,
122 EmpathyAccountChooserFilterResultCallback callback,
123 gpointer callback_data,
165 COL_EVENTS_PRETTY_DATE,
174 #define CALENDAR_ICON "stock_calendar"
176 /* Seconds between two messages to be considered one conversation */
177 #define MAX_GAP 30*60
179 #define WHAT_TYPE_SEPARATOR -1
183 EVENT_CALL_INCOMING = 1 << 0,
184 EVENT_CALL_OUTGOING = 1 << 1,
185 EVENT_CALL_MISSED = 1 << 2,
186 EVENT_CALL_ALL = 1 << 3,
189 static EmpathyLogWindow *log_window = NULL;
191 static gboolean has_element;
194 #define _date_copy(d) g_date_new_julian (g_date_get_julian (d))
199 EmpathyLogWindow *window;
203 TplEventTypeMask event_mask;
204 EventSubtype subtype;
209 ctx_new (EmpathyLogWindow *window,
213 TplEventTypeMask event_mask,
214 EventSubtype subtype,
217 Ctx *ctx = g_slice_new0 (Ctx);
219 ctx->window = window;
221 ctx->account = g_object_ref (account);
223 ctx->entity = g_object_ref (entity);
225 ctx->date = _date_copy (date);
226 ctx->event_mask = event_mask;
227 ctx->subtype = subtype;
236 tp_clear_object (&ctx->account);
237 tp_clear_object (&ctx->entity);
238 tp_clear_pointer (&ctx->date, g_date_free);
240 g_slice_free (Ctx, ctx);
244 account_chooser_ready_cb (EmpathyAccountChooser *chooser,
245 EmpathyLogWindow *window)
247 /* We'll display the account once the model has been populate with the chats
248 * of this account. */
249 empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (
250 window->account_chooser), window->selected_account);
254 select_account_once_ready (EmpathyLogWindow *self,
256 const gchar *chat_id,
257 gboolean is_chatroom)
259 EmpathyAccountChooser *account_chooser;
261 account_chooser = EMPATHY_ACCOUNT_CHOOSER (self->account_chooser);
263 tp_clear_object (&self->selected_account);
264 self->selected_account = g_object_ref (account);
266 g_free (self->selected_chat_id);
267 self->selected_chat_id = g_strdup (chat_id);
269 self->selected_is_chatroom = is_chatroom;
271 if (empathy_account_chooser_is_ready (account_chooser))
272 account_chooser_ready_cb (account_chooser, self);
274 /* Chat will be selected once the account chooser is ready */
275 g_signal_connect (account_chooser, "ready",
276 G_CALLBACK (account_chooser_ready_cb), self);
280 toolbutton_profile_clicked (GtkToolButton *toolbutton,
281 EmpathyLogWindow *window)
284 GtkTreeSelection *selection;
289 EmpathyContact *contact;
292 g_return_if_fail (window != NULL);
294 view = GTK_TREE_VIEW (log_window->treeview_who);
295 selection = gtk_tree_view_get_selection (view);
297 if (gtk_tree_selection_get_selected (selection, &model, &iter))
299 gtk_tree_model_get (model, &iter,
300 COL_WHO_ACCOUNT, &account,
301 COL_WHO_TARGET, &target,
306 if (type == COL_TYPE_NORMAL)
308 contact = empathy_contact_from_tpl_contact (account, target);
309 empathy_contact_information_dialog_show (contact,
310 GTK_WINDOW (window->window));
311 g_object_unref (contact);
315 g_warn_if_reached ();
318 g_object_unref (account);
319 g_object_unref (target);
323 toolbutton_chat_clicked (GtkToolButton *toolbutton,
324 EmpathyLogWindow *window)
327 GtkTreeSelection *selection;
332 EmpathyContact *contact;
335 g_return_if_fail (window != NULL);
337 view = GTK_TREE_VIEW (log_window->treeview_who);
338 selection = gtk_tree_view_get_selection (view);
340 if (gtk_tree_selection_get_selected (selection, &model, &iter))
342 gtk_tree_model_get (model, &iter,
343 COL_WHO_ACCOUNT, &account,
344 COL_WHO_TARGET, &target,
349 g_return_if_fail (type == COL_TYPE_NORMAL);
351 contact = empathy_contact_from_tpl_contact (account, target);
352 empathy_chat_with_contact (contact,
353 gtk_get_current_event_time ());
355 g_object_unref (contact);
356 g_object_unref (account);
357 g_object_unref (target);
361 toolbutton_av_clicked (GtkToolButton *toolbutton,
362 EmpathyLogWindow *window)
365 GtkTreeSelection *selection;
373 g_return_if_fail (window != NULL);
375 view = GTK_TREE_VIEW (log_window->treeview_who);
376 selection = gtk_tree_view_get_selection (view);
378 if (gtk_tree_selection_get_selected (selection, &model, &iter))
380 gtk_tree_model_get (model, &iter,
381 COL_WHO_ACCOUNT, &account,
382 COL_WHO_NAME, &contact,
387 g_return_if_fail (type == COL_TYPE_NORMAL);
389 video = (GTK_WIDGET (toolbutton) == window->button_video);
391 empathy_call_new_with_streams (contact, account,
392 TRUE, video, gtk_get_current_event_time ());
395 g_object_unref (account);
399 empathy_log_window_show (TpAccount *account,
400 const gchar *chat_id,
401 gboolean is_chatroom,
404 EmpathyAccountChooser *account_chooser;
407 EmpathyLogWindow *window;
408 GtkWidget *vbox, *accounts, *search, *label, *quit;
410 if (log_window != NULL)
412 gtk_window_present (GTK_WINDOW (log_window->window));
414 if (account != NULL && chat_id != NULL)
415 select_account_once_ready (log_window, account, chat_id, is_chatroom);
417 return log_window->window;
420 log_window = g_new0 (EmpathyLogWindow, 1);
421 log_window->chain = _tpl_action_chain_new_async (NULL, NULL, NULL);
423 log_window->log_manager = tpl_log_manager_dup_singleton ();
427 filename = empathy_file_lookup ("empathy-log-window.ui", "libempathy-gtk");
428 gui = empathy_builder_get_file (filename,
429 "log_window", &window->window,
430 "toolbutton_profile", &window->button_profile,
431 "toolbutton_chat", &window->button_chat,
432 "toolbutton_call", &window->button_call,
433 "toolbutton_video", &window->button_video,
434 "toolbutton_accounts", &accounts,
435 "toolbutton_search", &search,
436 "imagemenuitem_quit", &quit,
437 "treeview_who", &window->treeview_who,
438 "treeview_what", &window->treeview_what,
439 "treeview_when", &window->treeview_when,
440 "treeview_events", &window->treeview_events,
444 empathy_builder_connect (gui, window,
445 "log_window", "destroy", log_window_destroy_cb,
446 "toolbutton_profile", "clicked", toolbutton_profile_clicked,
447 "toolbutton_chat", "clicked", toolbutton_chat_clicked,
448 "toolbutton_call", "clicked", toolbutton_av_clicked,
449 "toolbutton_video", "clicked", toolbutton_av_clicked,
450 "imagemenuitem_delete", "activate", log_window_delete_menu_clicked_cb,
453 g_object_unref (gui);
455 g_object_add_weak_pointer (G_OBJECT (window->window),
456 (gpointer) &log_window);
458 g_signal_connect_swapped (quit, "activate",
459 G_CALLBACK (gtk_widget_destroy), window->window);
461 /* Account chooser for chats */
462 vbox = gtk_vbox_new (FALSE, 3);
464 window->account_chooser = empathy_account_chooser_new ();
465 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
466 empathy_account_chooser_set_has_all_option (account_chooser, TRUE);
467 empathy_account_chooser_set_filter (account_chooser,
468 empathy_account_chooser_filter_has_logs, NULL);
470 g_signal_connect (window->account_chooser, "changed",
471 G_CALLBACK (log_window_chats_accounts_changed_cb),
474 label = gtk_label_new (_("Show"));
476 gtk_box_pack_start (GTK_BOX (vbox),
477 window->account_chooser,
480 gtk_box_pack_start (GTK_BOX (vbox),
484 gtk_widget_show_all (vbox);
485 gtk_container_add (GTK_CONTAINER (accounts), vbox);
488 vbox = gtk_vbox_new (FALSE, 3);
490 window->search_entry = gtk_entry_new ();
491 gtk_entry_set_icon_from_stock (GTK_ENTRY (window->search_entry),
492 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND);
494 label = gtk_label_new (_("Search"));
496 gtk_box_pack_start (GTK_BOX (vbox),
497 window->search_entry,
500 gtk_box_pack_start (GTK_BOX (vbox),
504 gtk_widget_show_all (vbox);
505 gtk_container_add (GTK_CONTAINER (search), vbox);
507 g_signal_connect (window->search_entry, "changed",
508 G_CALLBACK (log_window_search_entry_changed_cb),
511 g_signal_connect (window->search_entry, "activate",
512 G_CALLBACK (log_window_search_entry_activate_cb),
516 log_window_events_setup (window);
517 log_window_who_setup (window);
518 log_window_what_setup (window);
519 log_window_when_setup (window);
521 log_window_who_populate (window);
523 if (account != NULL && chat_id != NULL)
524 select_account_once_ready (window, account, chat_id, is_chatroom);
527 gtk_window_set_transient_for (GTK_WINDOW (window->window),
528 GTK_WINDOW (parent));
530 gtk_widget_show (window->window);
532 return window->window;
536 log_window_destroy_cb (GtkWidget *widget,
537 EmpathyLogWindow *window)
539 if (window->source != 0)
540 g_source_remove (window->source);
542 g_free (window->last_find);
543 _tpl_action_chain_free (window->chain);
544 g_object_unref (window->log_manager);
545 tp_clear_object (&window->selected_account);
546 g_free (window->selected_chat_id);
552 account_equal (TpAccount *a,
555 return g_str_equal (tp_proxy_get_object_path (a),
556 tp_proxy_get_object_path (b));
560 entity_equal (TplEntity *a,
563 return g_str_equal (tpl_entity_get_identifier (a),
564 tpl_entity_get_identifier (b));
568 is_same_confroom (TplEvent *e1,
571 TplEntity *sender1 = tpl_event_get_sender (e1);
572 TplEntity *receiver1 = tpl_event_get_receiver (e1);
573 TplEntity *sender2 = tpl_event_get_sender (e2);
574 TplEntity *receiver2 = tpl_event_get_receiver (e2);
575 TplEntity *room1, *room2;
577 if (tpl_entity_get_entity_type (sender1) == TPL_ENTITY_ROOM)
579 else if (tpl_entity_get_entity_type (receiver1) == TPL_ENTITY_ROOM)
584 if (tpl_entity_get_entity_type (sender2) == TPL_ENTITY_ROOM)
586 else if (tpl_entity_get_entity_type (receiver2) == TPL_ENTITY_ROOM)
591 return g_str_equal (tpl_entity_get_identifier (room1),
592 tpl_entity_get_identifier (room1));
596 event_get_target (TplEvent *event)
598 TplEntity *sender = tpl_event_get_sender (event);
599 TplEntity *receiver = tpl_event_get_receiver (event);
601 if (tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
607 static gboolean parent_found;
608 static GtkTreeIter model_parent;
611 model_is_parent (GtkTreeModel *model,
616 TplEvent *event = data;
617 TplEvent *stored_event;
620 gboolean found = FALSE;
623 if (gtk_tree_model_iter_parent (model, &parent, iter))
626 gtk_tree_model_get (model, iter,
627 COL_EVENTS_ACCOUNT, &account,
628 COL_EVENTS_TARGET, &target,
629 COL_EVENTS_EVENT, &stored_event,
632 if (G_OBJECT_TYPE (event) == G_OBJECT_TYPE (stored_event) &&
633 account_equal (account, tpl_event_get_account (event)) &&
634 (entity_equal (target, event_get_target (event)) ||
635 is_same_confroom (event, stored_event)))
640 gtk_tree_model_iter_nth_child (model, &child, iter,
641 gtk_tree_model_iter_n_children (model, iter) - 1);
643 gtk_tree_model_get (model, &child,
644 COL_EVENTS_TS, ×tamp,
647 if (ABS (tpl_event_get_timestamp (event) - timestamp) < MAX_GAP)
649 /* The gap is smaller than 30 min */
650 model_parent = *iter;
651 parent_found = found = TRUE;
655 g_object_unref (stored_event);
656 g_object_unref (account);
657 g_object_unref (target);
663 get_contact_alias_for_message (EmpathyMessage *message)
665 EmpathyContact *sender, *receiver;
667 sender = empathy_message_get_sender (message);
668 receiver = empathy_message_get_receiver (message);
670 if (empathy_contact_is_user (sender))
671 return empathy_contact_get_alias (receiver);
673 return empathy_contact_get_alias (sender);
677 get_parent_iter_for_message (TplEvent *event,
678 EmpathyMessage *message,
684 store = log_window->store_events;
685 model = GTK_TREE_MODEL (store);
687 parent_found = FALSE;
688 gtk_tree_model_foreach (model, model_is_parent, event);
692 *parent = model_parent;
698 gchar *body, *pretty_date;
700 date = g_date_time_new_from_unix_utc (
701 tpl_event_get_timestamp (event));
703 pretty_date = g_date_time_format (date, "%x");
705 body = g_strdup_printf (_("Chat with %s"),
706 get_contact_alias_for_message (message));
708 gtk_tree_store_append (store, &iter, NULL);
709 gtk_tree_store_set (store, &iter,
710 COL_EVENTS_TS, tpl_event_get_timestamp (event),
711 COL_EVENTS_PRETTY_DATE, pretty_date,
712 COL_EVENTS_TEXT, body,
713 COL_EVENTS_ICON, "stock_text_justify",
714 COL_EVENTS_ACCOUNT, tpl_event_get_account (event),
715 COL_EVENTS_TARGET, event_get_target (event),
716 COL_EVENTS_EVENT, event,
722 g_free (pretty_date);
723 g_date_time_unref (date);
728 get_icon_for_event (TplEvent *event)
730 const gchar *icon = NULL;
732 if (TPL_IS_CALL_EVENT (event))
734 TplCallEvent *call = TPL_CALL_EVENT (event);
735 TplCallEndReason reason = tpl_call_event_get_end_reason (call);
736 TplEntity *sender = tpl_event_get_sender (event);
737 TplEntity *receiver = tpl_event_get_receiver (event);
739 if (reason == TPL_CALL_END_REASON_NO_ANSWER)
740 icon = EMPATHY_IMAGE_CALL_MISSED;
741 else if (tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
742 icon = EMPATHY_IMAGE_CALL_OUTGOING;
743 else if (tpl_entity_get_entity_type (receiver) == TPL_ENTITY_SELF)
744 icon = EMPATHY_IMAGE_CALL_INCOMING;
751 log_window_append_chat_message (TplEvent *event,
752 EmpathyMessage *message)
754 GtkTreeStore *store = log_window->store_events;
755 GtkTreeIter iter, parent;
756 gchar *pretty_date, *body;
759 date = g_date_time_new_from_unix_utc (
760 tpl_event_get_timestamp (event));
762 pretty_date = g_date_time_format (date, "%x");
764 get_parent_iter_for_message (event, message, &parent);
766 if (tpl_text_event_get_message_type (TPL_TEXT_EVENT (event))
767 == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION)
769 body = g_strdup_printf ("* %s %s",
770 tpl_entity_get_alias (tpl_event_get_sender (event)),
771 empathy_message_get_body (message));
775 body = g_strdup_printf (
776 C_("First is a contact, second is what was said", "%s: %s"),
777 tpl_entity_get_alias (tpl_event_get_sender (event)),
778 empathy_message_get_body (message));
781 gtk_tree_store_append (store, &iter, &parent);
782 gtk_tree_store_set (store, &iter,
783 COL_EVENTS_TS, tpl_event_get_timestamp (event),
784 COL_EVENTS_PRETTY_DATE, pretty_date,
785 COL_EVENTS_TEXT, body,
786 COL_EVENTS_ICON, get_icon_for_event (event),
787 COL_EVENTS_ACCOUNT, tpl_event_get_account (event),
788 COL_EVENTS_TARGET, event_get_target (event),
789 COL_EVENTS_EVENT, event,
793 g_free (pretty_date);
794 g_date_time_unref (date);
798 log_window_append_call (TplEvent *event,
799 EmpathyMessage *message)
801 TplCallEvent *call = TPL_CALL_EVENT (event);
802 GtkTreeStore *store = log_window->store_events;
803 GtkTreeIter iter, child;
804 gchar *pretty_date, *duration, *finished;
805 GDateTime *started_date, *finished_date;
808 started_date = g_date_time_new_from_unix_utc (
809 tpl_event_get_timestamp (event));
811 pretty_date = g_date_time_format (started_date, "%x");
813 gtk_tree_store_append (store, &iter, NULL);
814 gtk_tree_store_set (store, &iter,
815 COL_EVENTS_TS, tpl_event_get_timestamp (event),
816 COL_EVENTS_PRETTY_DATE, pretty_date,
817 COL_EVENTS_TEXT, empathy_message_get_body (message),
818 COL_EVENTS_ICON, get_icon_for_event (event),
819 COL_EVENTS_ACCOUNT, tpl_event_get_account (event),
820 COL_EVENTS_TARGET, event_get_target (event),
821 COL_EVENTS_EVENT, event,
824 if (tpl_call_event_get_end_reason (call) != TPL_CALL_END_REASON_NO_ANSWER)
828 span = tpl_call_event_get_duration (TPL_CALL_EVENT (event));
830 duration = g_strdup_printf (_("%" G_GINT64_FORMAT " seconds"), span);
832 duration = g_strdup_printf (_("%" G_GINT64_FORMAT " minutes"),
835 finished_date = g_date_time_add (started_date, -span);
836 finished = g_date_time_format (finished_date, "%X");
837 g_date_time_unref (finished_date);
839 body = g_strdup_printf (_("Call took %s, ended at %s"),
845 gtk_tree_store_append (store, &child, &iter);
846 gtk_tree_store_set (store, &child,
847 COL_EVENTS_TS, tpl_event_get_timestamp (event),
848 COL_EVENTS_TEXT, body,
849 COL_EVENTS_ACCOUNT, tpl_event_get_account (event),
850 COL_EVENTS_TARGET, event_get_target (event),
851 COL_EVENTS_EVENT, event,
857 g_free (pretty_date);
858 g_date_time_unref (started_date);
862 log_window_append_message (TplEvent *event,
863 EmpathyMessage *message)
865 if (TPL_IS_TEXT_EVENT (event))
866 log_window_append_chat_message (event, message);
867 else if (TPL_IS_CALL_EVENT (event))
868 log_window_append_call (event, message);
870 DEBUG ("Message type not handled");
874 add_all_accounts_and_entities (GList **accounts,
881 view = GTK_TREE_VIEW (log_window->treeview_who);
882 model = gtk_tree_view_get_model (view);
884 if (!gtk_tree_model_get_iter_first (model, &iter))
893 gtk_tree_model_get (model, &iter,
894 COL_WHO_ACCOUNT, &account,
895 COL_WHO_TARGET, &entity,
899 if (type != COL_TYPE_NORMAL)
902 if (accounts != NULL)
903 *accounts = g_list_append (*accounts, account);
905 if (entities != NULL)
906 *entities = g_list_append (*entities, entity);
908 while (gtk_tree_model_iter_next (model, &iter));
912 log_window_get_selected (EmpathyLogWindow *window,
916 TplEventTypeMask *event_mask,
917 EventSubtype *subtype)
921 GtkTreeSelection *selection;
923 TplEventTypeMask ev = 0;
928 view = GTK_TREE_VIEW (window->treeview_who);
929 model = gtk_tree_view_get_model (view);
930 selection = gtk_tree_view_get_selection (view);
932 paths = gtk_tree_selection_get_selected_rows (selection, NULL);
936 if (accounts != NULL)
938 if (entities != NULL)
941 for (l = paths; l != NULL; l = l->next)
943 GtkTreePath *path = l->data;
947 gtk_tree_model_get_iter (model, &iter, path);
948 gtk_tree_model_get (model, &iter,
949 COL_WHO_ACCOUNT, &account,
950 COL_WHO_TARGET, &entity,
954 if (type == COL_TYPE_ANY)
956 if (accounts != NULL || entities != NULL)
957 add_all_accounts_and_entities (accounts, entities);
961 if (accounts != NULL)
962 *accounts = g_list_append (*accounts, g_object_ref (account));
964 if (entities != NULL)
965 *entities = g_list_append (*entities, g_object_ref (entity));
967 g_object_unref (account);
968 g_object_unref (entity);
970 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
972 view = GTK_TREE_VIEW (window->treeview_what);
973 model = gtk_tree_view_get_model (view);
974 selection = gtk_tree_view_get_selection (view);
976 paths = gtk_tree_selection_get_selected_rows (selection, NULL);
977 for (l = paths; l != NULL; l = l->next)
979 GtkTreePath *path = l->data;
980 TplEventTypeMask mask;
981 EventSubtype submask;
983 gtk_tree_model_get_iter (model, &iter, path);
984 gtk_tree_model_get (model, &iter,
985 COL_WHAT_TYPE, &mask,
986 COL_WHAT_SUBTYPE, &submask,
992 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
994 view = GTK_TREE_VIEW (window->treeview_when);
995 model = gtk_tree_view_get_model (view);
996 selection = gtk_tree_view_get_selection (view);
1002 paths = gtk_tree_selection_get_selected_rows (selection, NULL);
1003 for (l = paths; l != NULL; l = l->next)
1005 GtkTreePath *path = l->data;
1008 gtk_tree_model_get_iter (model, &iter, path);
1009 gtk_tree_model_get (model, &iter,
1010 COL_WHEN_DATE, &date,
1013 *dates = g_list_append (*dates, date);
1015 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
1018 if (event_mask != NULL)
1021 if (subtype != NULL)
1028 model_has_entity (GtkTreeModel *model,
1033 TplLogSearchHit *hit = data;
1036 gboolean ret = FALSE;
1038 gtk_tree_model_get (model, iter,
1040 COL_WHO_ACCOUNT, &a,
1043 if (e != NULL && entity_equal (hit->target, e) &&
1044 a != NULL && account_equal (hit->account, a))
1046 ret = has_element = TRUE;
1049 tp_clear_object (&e);
1050 tp_clear_object (&a);
1056 model_has_date (GtkTreeModel *model,
1064 gtk_tree_model_get (model, iter,
1068 if (!g_date_compare (date, d))
1078 get_events_for_date (TplActionChain *chain, gpointer user_data);
1081 populate_events_from_search_hits (GList *accounts,
1085 TplEventTypeMask event_mask;
1086 EventSubtype subtype;
1089 gboolean is_anytime = FALSE;
1091 if (!log_window_get_selected (log_window,
1092 NULL, NULL, NULL, &event_mask, &subtype))
1095 anytime = g_date_new_dmy (2, 1, -1);
1096 if (g_list_find_custom (dates, anytime, (GCompareFunc) g_date_compare))
1099 for (l = log_window->hits; l != NULL; l = l->next)
1101 TplLogSearchHit *hit = l->data;
1103 gboolean found = FALSE;
1105 /* Protect against invalid data (corrupt or old log files). */
1106 if (hit->account == NULL || hit->target == NULL)
1109 for (acc = accounts, targ = targets;
1110 acc != NULL && targ != NULL && !found;
1111 acc = acc->next, targ = targ->next)
1113 TpAccount *account = acc->data;
1114 TplEntity *target = targ->data;
1116 if (account_equal (hit->account, account) &&
1117 entity_equal (hit->target, target))
1125 g_list_find_custom (dates, hit->date, (GCompareFunc) g_date_compare)
1130 ctx = ctx_new (log_window, hit->account, hit->target, hit->date,
1131 event_mask, subtype, log_window->count);
1132 _tpl_action_chain_append (log_window->chain,
1133 get_events_for_date, ctx);
1137 _tpl_action_chain_start (log_window->chain);
1139 g_date_free (anytime);
1143 format_date_for_display (GDate *date)
1149 /* g_date_strftime sucks */
1151 now = g_date_new ();
1152 g_date_set_time_t (now, time (NULL));
1154 days_elapsed = g_date_days_between (date, now);
1156 if (days_elapsed < 0)
1160 else if (days_elapsed == 0)
1162 text = g_strdup (_("Today"));
1164 else if (days_elapsed == 1)
1166 text = g_strdup (_("Yesterday"));
1172 dt = g_date_time_new_utc (g_date_get_year (date),
1173 g_date_get_month (date), g_date_get_day (date),
1176 if (days_elapsed <= 7)
1177 text = g_date_time_format (dt, "%A");
1179 text = g_date_time_format (dt,
1180 C_("A date such as '23 May 2010', "
1181 "%e is the day, %B the month and %Y the year",
1184 g_date_time_unref (dt);
1193 populate_dates_from_search_hits (GList *accounts,
1198 GtkTreeModel *model;
1199 GtkListStore *store;
1200 GtkTreeSelection *selection;
1203 if (log_window == NULL)
1206 view = GTK_TREE_VIEW (log_window->treeview_when);
1207 model = gtk_tree_view_get_model (view);
1208 store = GTK_LIST_STORE (model);
1209 selection = gtk_tree_view_get_selection (view);
1211 for (l = log_window->hits; l != NULL; l = l->next)
1213 TplLogSearchHit *hit = l->data;
1215 gboolean found = FALSE;
1217 /* Protect against invalid data (corrupt or old log files). */
1218 if (hit->account == NULL || hit->target == NULL)
1221 for (acc = accounts, targ = targets;
1222 acc != NULL && targ != NULL && !found;
1223 acc = acc->next, targ = targ->next)
1225 TpAccount *account = acc->data;
1226 TplEntity *target = targ->data;
1228 if (account_equal (hit->account, account) &&
1229 entity_equal (hit->target, target))
1236 /* Add the date if it's not already there */
1237 has_element = FALSE;
1238 gtk_tree_model_foreach (model, model_has_date, hit->date);
1241 gchar *text = format_date_for_display (hit->date);
1243 gtk_list_store_append (store, &iter);
1244 gtk_list_store_set (store, &iter,
1245 COL_WHEN_DATE, hit->date,
1246 COL_WHEN_TEXT, text,
1247 COL_WHEN_ICON, CALENDAR_ICON,
1252 if (gtk_tree_model_get_iter_first (model, &iter))
1254 gtk_list_store_prepend (store, &iter);
1255 gtk_list_store_set (store, &iter,
1256 COL_WHEN_DATE, g_date_new_dmy (1, 1, -1),
1257 COL_WHEN_TEXT, "separator",
1260 gtk_list_store_prepend (store, &iter);
1261 gtk_list_store_set (store, &iter,
1262 COL_WHEN_DATE, g_date_new_dmy (2, 1, -1),
1263 COL_WHEN_TEXT, _("Anytime"),
1266 gtk_tree_selection_select_iter (selection, &iter);
1271 populate_entities_from_search_hits (void)
1273 EmpathyAccountChooser *account_chooser;
1276 GtkTreeModel *model;
1278 GtkListStore *store;
1281 view = GTK_TREE_VIEW (log_window->treeview_who);
1282 model = gtk_tree_view_get_model (view);
1283 store = GTK_LIST_STORE (model);
1285 gtk_list_store_clear (store);
1287 account_chooser = EMPATHY_ACCOUNT_CHOOSER (log_window->account_chooser);
1288 account = empathy_account_chooser_get_account (account_chooser);
1290 for (l = log_window->hits; l; l = l->next)
1292 TplLogSearchHit *hit = l->data;
1294 /* Protect against invalid data (corrupt or old log files). */
1295 if (hit->account == NULL || hit->target == NULL)
1298 /* Filter based on the selected account */
1299 if (account != NULL && !account_equal (account, hit->account))
1302 /* Add the entity if it's not already there */
1303 has_element = FALSE;
1304 gtk_tree_model_foreach (model, model_has_entity, hit);
1307 TplEntityType type = tpl_entity_get_entity_type (hit->target);
1308 gboolean room = type == TPL_ENTITY_ROOM;
1310 gtk_list_store_append (store, &iter);
1311 gtk_list_store_set (store, &iter,
1312 COL_WHO_TYPE, COL_TYPE_NORMAL,
1313 COL_WHO_ICON, room ? EMPATHY_IMAGE_GROUP_MESSAGE
1314 : EMPATHY_IMAGE_AVATAR_DEFAULT,
1315 COL_WHO_NAME, tpl_entity_get_alias (hit->target),
1316 COL_WHO_ACCOUNT, hit->account,
1317 COL_WHO_TARGET, hit->target,
1322 if (gtk_tree_model_get_iter_first (model, &iter))
1324 gtk_list_store_prepend (store, &iter);
1325 gtk_list_store_set (store, &iter,
1326 COL_WHO_TYPE, COL_TYPE_SEPARATOR,
1327 COL_WHO_NAME, "separator",
1330 gtk_list_store_prepend (store, &iter);
1331 gtk_list_store_set (store, &iter,
1332 COL_WHO_TYPE, COL_TYPE_ANY,
1333 COL_WHO_NAME, _("Anyone"),
1337 /* FIXME: select old entity if still available */
1341 log_manager_searched_new_cb (GObject *manager,
1342 GAsyncResult *result,
1347 GtkTreeSelection *selection;
1348 GError *error = NULL;
1350 if (log_window == NULL)
1353 if (!tpl_log_manager_search_finish (TPL_LOG_MANAGER (manager),
1354 result, &hits, &error))
1356 DEBUG ("%s. Aborting", error->message);
1357 g_error_free (error);
1361 tp_clear_pointer (&log_window->hits, tpl_log_manager_search_free);
1362 log_window->hits = hits;
1364 populate_entities_from_search_hits ();
1366 view = GTK_TREE_VIEW (log_window->treeview_when);
1367 selection = gtk_tree_view_get_selection (view);
1369 g_signal_handlers_unblock_by_func (selection,
1370 log_window_when_changed_cb,
1375 log_window_find_populate (EmpathyLogWindow *window,
1376 const gchar *search_criteria)
1379 GtkTreeModel *model;
1380 GtkTreeSelection *selection;
1381 GtkListStore *store;
1383 gtk_tree_store_clear (window->store_events);
1385 view = GTK_TREE_VIEW (window->treeview_who);
1386 model = gtk_tree_view_get_model (view);
1387 store = GTK_LIST_STORE (model);
1389 gtk_list_store_clear (store);
1391 view = GTK_TREE_VIEW (window->treeview_when);
1392 model = gtk_tree_view_get_model (view);
1393 store = GTK_LIST_STORE (model);
1394 selection = gtk_tree_view_get_selection (view);
1396 gtk_list_store_clear (store);
1398 if (EMP_STR_EMPTY (search_criteria))
1400 tp_clear_pointer (&window->hits, tpl_log_manager_search_free);
1401 log_window_who_populate (window);
1405 g_signal_handlers_block_by_func (selection,
1406 log_window_when_changed_cb,
1409 tpl_log_manager_search_async (window->log_manager,
1410 search_criteria, TPL_EVENT_MASK_ANY,
1411 log_manager_searched_new_cb, NULL);
1415 start_find_search (EmpathyLogWindow *window)
1419 str = gtk_entry_get_text (GTK_ENTRY (window->search_entry));
1421 /* Don't find the same crap again */
1422 if (window->last_find && !tp_strdiff (window->last_find, str))
1425 g_free (window->last_find);
1426 window->last_find = g_strdup (str);
1428 log_window_find_populate (window, str);
1434 log_window_search_entry_changed_cb (GtkWidget *entry,
1435 EmpathyLogWindow *window)
1437 if (window->source != 0)
1438 g_source_remove (window->source);
1439 window->source = g_timeout_add (500, (GSourceFunc) start_find_search,
1444 log_window_search_entry_activate_cb (GtkWidget *entry,
1445 EmpathyLogWindow *self)
1447 start_find_search (self);
1455 log_window_who_changed_cb (GtkTreeSelection *selection,
1456 EmpathyLogWindow *window)
1459 GtkTreeModel *model;
1461 gboolean someone = FALSE;
1463 DEBUG ("log_window_who_changed_cb");
1465 view = gtk_tree_selection_get_tree_view (selection);
1466 model = gtk_tree_view_get_model (view);
1468 if (gtk_tree_model_get_iter_first (model, &iter))
1470 /* If 'Anyone' is selected, everything else should be deselected */
1471 if (gtk_tree_selection_iter_is_selected (selection, &iter))
1473 g_signal_handlers_block_by_func (selection,
1474 log_window_who_changed_cb,
1477 gtk_tree_selection_unselect_all (selection);
1478 gtk_tree_selection_select_iter (selection, &iter);
1480 g_signal_handlers_unblock_by_func (selection,
1481 log_window_who_changed_cb,
1484 else if (gtk_tree_selection_count_selected_rows (selection) == 1)
1490 gtk_widget_set_sensitive (window->button_profile, someone);
1491 gtk_widget_set_sensitive (window->button_chat, someone);
1492 gtk_widget_set_sensitive (window->button_call, someone);
1493 gtk_widget_set_sensitive (window->button_video, someone);
1495 /* The contact changed, so the dates need to be updated */
1496 log_window_chats_get_messages (window, TRUE);
1500 log_manager_got_entities_cb (GObject *manager,
1501 GAsyncResult *result,
1504 Ctx *ctx = user_data;
1508 GtkTreeModel *model;
1509 GtkTreeSelection *selection;
1510 GtkListStore *store;
1512 GError *error = NULL;
1513 gboolean select_account = FALSE;
1515 if (log_window == NULL)
1518 if (log_window->count != ctx->count)
1521 if (!tpl_log_manager_get_entities_finish (TPL_LOG_MANAGER (manager),
1522 result, &entities, &error))
1524 DEBUG ("%s. Aborting", error->message);
1525 g_error_free (error);
1529 view = GTK_TREE_VIEW (ctx->window->treeview_who);
1530 model = gtk_tree_view_get_model (view);
1531 selection = gtk_tree_view_get_selection (view);
1532 store = GTK_LIST_STORE (model);
1534 /* Block signals to stop the logs being retrieved prematurely */
1535 g_signal_handlers_block_by_func (selection,
1536 log_window_who_changed_cb, ctx->window);
1538 for (l = entities; l; l = l->next)
1540 TplEntity *entity = TPL_ENTITY (l->data);
1541 TplEntityType type = tpl_entity_get_entity_type (entity);
1542 gboolean room = type == TPL_ENTITY_ROOM;
1544 gtk_list_store_append (store, &iter);
1545 gtk_list_store_set (store, &iter,
1546 COL_WHO_TYPE, COL_TYPE_NORMAL,
1547 COL_WHO_ICON, room ? EMPATHY_IMAGE_GROUP_MESSAGE
1548 : EMPATHY_IMAGE_AVATAR_DEFAULT,
1549 COL_WHO_NAME, tpl_entity_get_alias (entity),
1550 COL_WHO_ACCOUNT, ctx->account,
1551 COL_WHO_TARGET, entity,
1554 if (ctx->window->selected_account != NULL &&
1555 !tp_strdiff (tp_proxy_get_object_path (ctx->account),
1556 tp_proxy_get_object_path (ctx->window->selected_account)))
1557 select_account = TRUE;
1559 g_list_free_full (entities, g_object_unref);
1561 if (gtk_tree_model_get_iter_first (model, &iter))
1565 gtk_tree_model_get (model, &iter,
1566 COL_WHO_TYPE, &type,
1569 if (type != COL_TYPE_ANY)
1571 gtk_list_store_prepend (store, &iter);
1572 gtk_list_store_set (store, &iter,
1573 COL_WHO_TYPE, COL_TYPE_SEPARATOR,
1574 COL_WHO_NAME, "separator",
1577 gtk_list_store_prepend (store, &iter);
1578 gtk_list_store_set (store, &iter,
1579 COL_WHO_TYPE, COL_TYPE_ANY,
1580 COL_WHO_NAME, _("Anyone"),
1585 /* Unblock signals */
1586 g_signal_handlers_unblock_by_func (selection,
1587 log_window_who_changed_cb,
1590 /* We display the selected account if we populate the model with chats from
1593 log_window_chats_set_selected (ctx->window);
1596 _tpl_action_chain_continue (log_window->chain);
1601 get_entities_for_account (TplActionChain *chain, gpointer user_data)
1603 Ctx *ctx = user_data;
1605 tpl_log_manager_get_entities_async (ctx->window->log_manager, ctx->account,
1606 log_manager_got_entities_cb, ctx);
1610 select_first_entity (TplActionChain *chain, gpointer user_data)
1613 GtkTreeModel *model;
1614 GtkTreeSelection *selection;
1617 view = GTK_TREE_VIEW (log_window->treeview_who);
1618 model = gtk_tree_view_get_model (view);
1619 selection = gtk_tree_view_get_selection (view);
1621 if (gtk_tree_model_get_iter_first (model, &iter))
1622 gtk_tree_selection_select_iter (selection, &iter);
1624 _tpl_action_chain_continue (log_window->chain);
1628 log_window_who_populate (EmpathyLogWindow *window)
1630 EmpathyAccountChooser *account_chooser;
1632 gboolean all_accounts;
1634 GtkTreeModel *model;
1635 GtkTreeSelection *selection;
1636 GtkListStore *store;
1639 if (window->hits != NULL)
1641 populate_entities_from_search_hits ();
1645 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
1646 account = empathy_account_chooser_dup_account (account_chooser);
1647 all_accounts = empathy_account_chooser_has_all_selected (account_chooser);
1649 view = GTK_TREE_VIEW (window->treeview_who);
1650 model = gtk_tree_view_get_model (view);
1651 selection = gtk_tree_view_get_selection (view);
1652 store = GTK_LIST_STORE (model);
1654 /* Block signals to stop the logs being retrieved prematurely */
1655 g_signal_handlers_block_by_func (selection,
1656 log_window_who_changed_cb,
1659 gtk_list_store_clear (store);
1661 /* Unblock signals */
1662 g_signal_handlers_unblock_by_func (selection,
1663 log_window_who_changed_cb,
1666 _tpl_action_chain_clear (window->chain);
1669 if (!all_accounts && account == NULL)
1673 else if (!all_accounts)
1675 ctx = ctx_new (window, account, NULL, NULL, 0, 0, window->count);
1676 _tpl_action_chain_append (window->chain, get_entities_for_account, ctx);
1680 TpAccountManager *manager;
1681 GList *accounts, *l;
1683 manager = empathy_account_chooser_get_account_manager (account_chooser);
1684 accounts = tp_account_manager_get_valid_accounts (manager);
1686 for (l = accounts; l != NULL; l = l->next)
1690 ctx = ctx_new (window, account, NULL, NULL, 0, 0, window->count);
1691 _tpl_action_chain_append (window->chain,
1692 get_entities_for_account, ctx);
1695 g_list_free (accounts);
1697 _tpl_action_chain_append (window->chain, select_first_entity, NULL);
1698 _tpl_action_chain_start (window->chain);
1702 sort_by_name (GtkTreeModel *model,
1707 gchar *name1, *name2;
1711 gtk_tree_model_get (model, a,
1712 COL_WHO_TYPE, &type1,
1713 COL_WHO_NAME, &name1,
1716 gtk_tree_model_get (model, b,
1717 COL_WHO_TYPE, &type2,
1718 COL_WHO_NAME, &name2,
1721 if (type1 == COL_TYPE_ANY)
1723 else if (type2 == COL_TYPE_ANY)
1725 else if (type1 == COL_TYPE_SEPARATOR)
1727 else if (type2 == COL_TYPE_SEPARATOR)
1730 ret = g_strcmp0 (name1, name2);
1739 who_row_is_separator (GtkTreeModel *model,
1745 gtk_tree_model_get (model, iter,
1746 COL_WHO_TYPE, &type,
1749 return (type == COL_TYPE_SEPARATOR);
1753 log_window_events_setup (EmpathyLogWindow *window)
1756 GtkTreeModel *model;
1757 GtkTreeSelection *selection;
1758 GtkTreeSortable *sortable;
1759 GtkTreeViewColumn *column;
1760 GtkTreeStore *store;
1761 GtkCellRenderer *cell;
1763 view = GTK_TREE_VIEW (window->treeview_events);
1764 selection = gtk_tree_view_get_selection (view);
1767 window->store_events = store = gtk_tree_store_new (COL_EVENTS_COUNT,
1768 G_TYPE_INT, /* type */
1769 G_TYPE_INT64, /* timestamp */
1770 G_TYPE_STRING, /* stringified date */
1771 G_TYPE_STRING, /* icon */
1772 G_TYPE_STRING, /* name */
1773 TP_TYPE_ACCOUNT, /* account */
1774 TPL_TYPE_ENTITY, /* target */
1775 TPL_TYPE_EVENT); /* event */
1777 model = GTK_TREE_MODEL (store);
1778 sortable = GTK_TREE_SORTABLE (store);
1780 gtk_tree_view_set_model (view, model);
1783 column = gtk_tree_view_column_new ();
1785 cell = gtk_cell_renderer_pixbuf_new ();
1786 gtk_tree_view_column_pack_start (column, cell, FALSE);
1787 gtk_tree_view_column_add_attribute (column, cell,
1788 "icon-name", COL_EVENTS_ICON);
1790 cell = gtk_cell_renderer_text_new ();
1791 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
1792 gtk_tree_view_column_pack_start (column, cell, TRUE);
1793 gtk_tree_view_column_add_attribute (column, cell,
1794 "text", COL_EVENTS_TEXT);
1796 cell = gtk_cell_renderer_text_new ();
1797 gtk_tree_view_column_pack_end (column, cell, FALSE);
1798 gtk_tree_view_column_add_attribute (column, cell,
1799 "text", COL_EVENTS_PRETTY_DATE);
1801 gtk_tree_view_append_column (view, column);
1803 /* set up treeview properties */
1804 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
1805 gtk_tree_view_set_headers_visible (view, FALSE);
1807 gtk_tree_sortable_set_sort_column_id (sortable,
1809 GTK_SORT_ASCENDING);
1811 g_object_unref (store);
1815 log_window_who_setup (EmpathyLogWindow *window)
1818 GtkTreeModel *model;
1819 GtkTreeSelection *selection;
1820 GtkTreeSortable *sortable;
1821 GtkTreeViewColumn *column;
1822 GtkListStore *store;
1823 GtkCellRenderer *cell;
1825 view = GTK_TREE_VIEW (window->treeview_who);
1826 selection = gtk_tree_view_get_selection (view);
1829 store = gtk_list_store_new (COL_WHO_COUNT,
1830 G_TYPE_INT, /* type */
1831 G_TYPE_STRING, /* icon */
1832 G_TYPE_STRING, /* name */
1833 TP_TYPE_ACCOUNT, /* account */
1834 TPL_TYPE_ENTITY); /* target */
1836 model = GTK_TREE_MODEL (store);
1837 sortable = GTK_TREE_SORTABLE (store);
1839 gtk_tree_view_set_model (view, model);
1842 column = gtk_tree_view_column_new ();
1843 gtk_tree_view_column_set_title (column, _("Who"));
1845 cell = gtk_cell_renderer_pixbuf_new ();
1846 gtk_tree_view_column_pack_start (column, cell, FALSE);
1847 gtk_tree_view_column_add_attribute (column, cell,
1851 cell = gtk_cell_renderer_text_new ();
1852 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
1853 gtk_tree_view_column_pack_start (column, cell, TRUE);
1854 gtk_tree_view_column_add_attribute (column, cell,
1858 gtk_tree_view_append_column (view, column);
1860 /* set up treeview properties */
1861 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
1862 gtk_tree_view_set_row_separator_func (view, who_row_is_separator,
1865 gtk_tree_sortable_set_sort_column_id (sortable,
1867 GTK_SORT_ASCENDING);
1868 gtk_tree_sortable_set_sort_func (sortable,
1869 COL_WHO_NAME, sort_by_name,
1872 /* set up signals */
1873 g_signal_connect (selection, "changed",
1874 G_CALLBACK (log_window_who_changed_cb), window);
1876 g_object_unref (store);
1880 log_window_chats_accounts_changed_cb (GtkWidget *combobox,
1881 EmpathyLogWindow *window)
1883 /* Clear all current messages shown in the textview */
1884 gtk_tree_store_clear (window->store_events);
1886 log_window_who_populate (window);
1890 log_window_chats_set_selected (EmpathyLogWindow *window)
1893 GtkTreeModel *model;
1894 GtkTreeSelection *selection;
1899 view = GTK_TREE_VIEW (window->treeview_who);
1900 model = gtk_tree_view_get_model (view);
1901 selection = gtk_tree_view_get_selection (view);
1903 for (next = gtk_tree_model_get_iter_first (model, &iter);
1905 next = gtk_tree_model_iter_next (model, &iter))
1907 TpAccount *this_account;
1908 TplEntity *this_target;
1909 const gchar *this_chat_id;
1910 gboolean this_is_chatroom;
1912 gtk_tree_model_get (model, &iter,
1913 COL_WHO_ACCOUNT, &this_account,
1914 COL_WHO_TARGET, &this_target,
1917 this_chat_id = tpl_entity_get_identifier (this_target);
1918 this_is_chatroom = tpl_entity_get_entity_type (this_target)
1921 if (this_account == window->selected_account &&
1922 !tp_strdiff (this_chat_id, window->selected_chat_id) &&
1923 this_is_chatroom == window->selected_is_chatroom)
1925 gtk_tree_selection_select_iter (selection, &iter);
1926 path = gtk_tree_model_get_path (model, &iter);
1927 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
1928 gtk_tree_path_free (path);
1929 g_object_unref (this_account);
1930 g_object_unref (this_target);
1934 g_object_unref (this_account);
1935 g_object_unref (this_target);
1938 tp_clear_object (&window->selected_account);
1939 tp_clear_pointer (&window->selected_chat_id, g_free);
1943 sort_by_date (GtkTreeModel *model,
1948 GDate *date1, *date2;
1950 gtk_tree_model_get (model, a,
1951 COL_WHEN_DATE, &date1,
1954 gtk_tree_model_get (model, b,
1955 COL_WHEN_DATE, &date2,
1958 return g_date_compare (date1, date2);
1962 when_row_is_separator (GtkTreeModel *model,
1969 gtk_tree_model_get (model, iter,
1970 COL_WHEN_TEXT, &when,
1973 ret = g_str_equal (when, "separator");
1979 log_window_when_changed_cb (GtkTreeSelection *selection,
1980 EmpathyLogWindow *window)
1983 GtkTreeModel *model;
1986 DEBUG ("log_window_when_changed_cb");
1988 view = gtk_tree_selection_get_tree_view (selection);
1989 model = gtk_tree_view_get_model (view);
1991 /* If 'Anytime' is selected, everything else should be deselected */
1992 if (gtk_tree_model_get_iter_first (model, &iter))
1994 if (gtk_tree_selection_iter_is_selected (selection, &iter))
1996 g_signal_handlers_block_by_func (selection,
1997 log_window_when_changed_cb,
2000 gtk_tree_selection_unselect_all (selection);
2001 gtk_tree_selection_select_iter (selection, &iter);
2003 g_signal_handlers_unblock_by_func (selection,
2004 log_window_when_changed_cb,
2009 log_window_chats_get_messages (window, FALSE);
2013 log_window_when_setup (EmpathyLogWindow *window)
2016 GtkTreeModel *model;
2017 GtkTreeSelection *selection;
2018 GtkTreeSortable *sortable;
2019 GtkTreeViewColumn *column;
2020 GtkListStore *store;
2021 GtkCellRenderer *cell;
2023 view = GTK_TREE_VIEW (window->treeview_when);
2024 selection = gtk_tree_view_get_selection (view);
2027 store = gtk_list_store_new (COL_WHEN_COUNT,
2028 G_TYPE_DATE, /* date */
2029 G_TYPE_STRING, /* stringified date */
2030 G_TYPE_STRING); /* icon */
2032 model = GTK_TREE_MODEL (store);
2033 sortable = GTK_TREE_SORTABLE (store);
2035 gtk_tree_view_set_model (view, model);
2038 column = gtk_tree_view_column_new ();
2039 gtk_tree_view_column_set_title (column, _("When"));
2041 cell = gtk_cell_renderer_pixbuf_new ();
2042 gtk_tree_view_column_pack_start (column, cell, FALSE);
2043 gtk_tree_view_column_add_attribute (column, cell,
2044 "icon-name", COL_WHEN_ICON);
2046 cell = gtk_cell_renderer_text_new ();
2047 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
2048 gtk_tree_view_column_pack_start (column, cell, TRUE);
2049 gtk_tree_view_column_add_attribute (column, cell,
2053 gtk_tree_view_append_column (view, column);
2055 /* set up treeview properties */
2056 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
2057 gtk_tree_view_set_row_separator_func (view, when_row_is_separator,
2059 gtk_tree_sortable_set_sort_column_id (sortable,
2061 GTK_SORT_DESCENDING);
2062 gtk_tree_sortable_set_sort_func (sortable,
2063 COL_WHEN_DATE, sort_by_date,
2066 /* set up signals */
2067 g_signal_connect (selection, "changed",
2068 G_CALLBACK (log_window_when_changed_cb),
2071 g_object_unref (store);
2075 what_row_is_separator (GtkTreeModel *model,
2081 gtk_tree_model_get (model, iter,
2082 COL_WHAT_TYPE, &type,
2085 return (type == WHAT_TYPE_SEPARATOR);
2089 log_window_what_changed_cb (GtkTreeSelection *selection,
2090 EmpathyLogWindow *window)
2093 GtkTreeModel *model;
2096 DEBUG ("log_window_what_changed_cb");
2098 view = gtk_tree_selection_get_tree_view (selection);
2099 model = gtk_tree_view_get_model (view);
2101 /* If 'Anything' is selected, everything else should be deselected */
2102 if (gtk_tree_model_get_iter_first (model, &iter))
2104 if (gtk_tree_selection_iter_is_selected (selection, &iter))
2106 g_signal_handlers_block_by_func (selection,
2107 log_window_what_changed_cb,
2110 gtk_tree_selection_unselect_all (selection);
2111 gtk_tree_selection_select_iter (selection, &iter);
2113 g_signal_handlers_unblock_by_func (selection,
2114 log_window_what_changed_cb,
2119 /* The dates need to be updated if we're not searching */
2120 log_window_chats_get_messages (window, window->hits == NULL);
2124 log_window_what_collapse_row_cb (GtkTreeView *tree_view,
2129 /* Reject collapsing */
2136 EventSubtype subtype;
2142 log_window_what_setup (EmpathyLogWindow *window)
2145 GtkTreeModel *model;
2146 GtkTreeSelection *selection;
2147 GtkTreeSortable *sortable;
2148 GtkTreeViewColumn *column;
2149 GtkTreeIter iter, parent;
2150 GtkTreeStore *store;
2151 GtkCellRenderer *cell;
2153 struct event events [] = {
2154 { TPL_EVENT_MASK_ANY, 0, NULL, _("Anything") },
2155 { WHAT_TYPE_SEPARATOR, 0, NULL, "separator" },
2156 { TPL_EVENT_MASK_TEXT, 0, "stock_text_justify", _("Text chats") },
2157 { TPL_EVENT_MASK_CALL, EVENT_CALL_ALL, "call-start", _("Calls") }
2159 struct event call_events [] = {
2160 { TPL_EVENT_MASK_CALL, EVENT_CALL_INCOMING, "call-start", _("Incoming calls") },
2161 { TPL_EVENT_MASK_CALL, EVENT_CALL_OUTGOING, "call-start", _("Outgoing calls") },
2162 { TPL_EVENT_MASK_CALL, EVENT_CALL_MISSED, "call-stop", _("Missed calls") }
2165 view = GTK_TREE_VIEW (window->treeview_what);
2166 selection = gtk_tree_view_get_selection (view);
2169 store = gtk_tree_store_new (COL_WHAT_COUNT,
2170 G_TYPE_INT, /* history type */
2171 G_TYPE_INT, /* history subtype */
2172 G_TYPE_STRING, /* stringified history type */
2173 G_TYPE_STRING, /* icon */
2174 G_TYPE_BOOLEAN); /* expander (hidden) */
2176 model = GTK_TREE_MODEL (store);
2177 sortable = GTK_TREE_SORTABLE (store);
2179 gtk_tree_view_set_model (view, model);
2182 column = gtk_tree_view_column_new ();
2183 gtk_tree_view_column_set_title (column, _("What"));
2185 cell = gtk_cell_renderer_pixbuf_new ();
2186 gtk_tree_view_column_pack_start (column, cell, FALSE);
2187 gtk_tree_view_column_add_attribute (column, cell,
2188 "icon-name", COL_WHAT_ICON);
2190 cell = gtk_cell_renderer_text_new ();
2191 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
2192 gtk_tree_view_column_pack_start (column, cell, TRUE);
2193 gtk_tree_view_column_add_attribute (column, cell,
2194 "text", COL_WHAT_TEXT);
2196 gtk_tree_view_append_column (view, column);
2198 /* set up treeview properties */
2199 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
2200 gtk_tree_view_set_show_expanders (view, FALSE);
2201 gtk_tree_view_set_level_indentation (view, 12);
2202 gtk_tree_view_expand_all (view);
2203 gtk_tree_view_set_row_separator_func (view, what_row_is_separator,
2207 for (i = 0; i < G_N_ELEMENTS (events); i++)
2209 gtk_tree_store_append (store, &iter, NULL);
2210 gtk_tree_store_set (store, &iter,
2211 COL_WHAT_TYPE, events[i].type,
2212 COL_WHAT_SUBTYPE, events[i].subtype,
2213 COL_WHAT_TEXT, events[i].text,
2214 COL_WHAT_ICON, events[i].icon,
2218 gtk_tree_model_iter_nth_child (model, &parent, NULL, 3);
2219 for (i = 0; i < G_N_ELEMENTS (call_events); i++)
2221 gtk_tree_store_append (store, &iter, &parent);
2222 gtk_tree_store_set (store, &iter,
2223 COL_WHAT_TYPE, call_events[i].type,
2224 COL_WHAT_SUBTYPE, call_events[i].subtype,
2225 COL_WHAT_TEXT, call_events[i].text,
2226 COL_WHAT_ICON, call_events[i].icon,
2230 gtk_tree_view_expand_all (view);
2232 /* select 'Anything' */
2233 if (gtk_tree_model_get_iter_first (model, &iter))
2234 gtk_tree_selection_select_iter (selection, &iter);
2236 /* set up signals */
2237 g_signal_connect (view, "test-collapse-row",
2238 G_CALLBACK (log_window_what_collapse_row_cb),
2240 g_signal_connect (selection, "changed",
2241 G_CALLBACK (log_window_what_changed_cb),
2244 g_object_unref (store);
2248 log_window_got_messages_for_date_cb (GObject *manager,
2249 GAsyncResult *result,
2252 Ctx *ctx = user_data;
2255 GError *error = NULL;
2257 if (log_window == NULL)
2260 if (log_window->count != ctx->count)
2263 if (!tpl_log_manager_get_events_for_date_finish (TPL_LOG_MANAGER (manager),
2264 result, &events, &error))
2266 DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
2268 g_error_free (error);
2272 for (l = events; l; l = l->next)
2274 TplEvent *event = l->data;
2275 gboolean append = TRUE;
2277 if (TPL_IS_CALL_EVENT (l->data)
2278 && ctx->event_mask & TPL_EVENT_MASK_CALL
2279 && ctx->event_mask != TPL_EVENT_MASK_ANY)
2281 TplCallEvent *call = l->data;
2285 if (ctx->subtype & EVENT_CALL_ALL)
2291 TplCallEndReason reason = tpl_call_event_get_end_reason (call);
2292 TplEntity *sender = tpl_event_get_sender (event);
2293 TplEntity *receiver = tpl_event_get_receiver (event);
2295 if (reason == TPL_CALL_END_REASON_NO_ANSWER)
2297 if (ctx->subtype & EVENT_CALL_MISSED)
2300 else if (ctx->subtype & EVENT_CALL_OUTGOING
2301 && tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
2305 else if (ctx->subtype & EVENT_CALL_INCOMING
2306 && tpl_entity_get_entity_type (receiver) == TPL_ENTITY_SELF)
2315 EmpathyMessage *msg = empathy_message_from_tpl_log_event (event);
2316 log_window_append_message (event, msg);
2317 g_object_unref (msg);
2320 g_object_unref (event);
2322 g_list_free (events);
2327 _tpl_action_chain_continue (log_window->chain);
2331 get_events_for_date (TplActionChain *chain, gpointer user_data)
2333 Ctx *ctx = user_data;
2335 tpl_log_manager_get_events_for_date_async (ctx->window->log_manager,
2336 ctx->account, ctx->entity, ctx->event_mask,
2338 log_window_got_messages_for_date_cb,
2343 log_window_get_messages_for_dates (EmpathyLogWindow *window,
2346 GList *accounts, *targets, *acc, *targ, *l;
2347 TplEventTypeMask event_mask;
2348 EventSubtype subtype;
2349 GDate *date, *anytime, *separator;
2351 if (!log_window_get_selected (window,
2352 &accounts, &targets, NULL, &event_mask, &subtype))
2355 anytime = g_date_new_dmy (2, 1, -1);
2356 separator = g_date_new_dmy (1, 1, -1);
2358 _tpl_action_chain_clear (window->chain);
2361 for (acc = accounts, targ = targets;
2362 acc != NULL && targ != NULL;
2363 acc = acc->next, targ = targ->next)
2365 TpAccount *account = acc->data;
2366 TplEntity *target = targ->data;
2368 for (l = dates; l != NULL; l = l->next)
2373 if (g_date_compare (date, anytime) != 0)
2377 ctx = ctx_new (window, account, target, date, event_mask, subtype,
2379 _tpl_action_chain_append (window->chain, get_events_for_date, ctx);
2383 GtkTreeView *view = GTK_TREE_VIEW (window->treeview_when);
2384 GtkTreeModel *model = gtk_tree_view_get_model (view);
2389 for (next = gtk_tree_model_get_iter_first (model, &iter);
2391 next = gtk_tree_model_iter_next (model, &iter))
2395 gtk_tree_model_get (model, &iter,
2399 if (g_date_compare (d, anytime) != 0 &&
2400 g_date_compare (d, separator) != 0)
2402 ctx = ctx_new (window, account, target, d,
2403 event_mask, subtype, window->count);
2404 _tpl_action_chain_append (window->chain, get_events_for_date, ctx);
2411 _tpl_action_chain_start (window->chain);
2413 g_list_free_full (accounts, g_object_unref);
2414 g_list_free_full (targets, g_object_unref);
2415 g_date_free (separator);
2416 g_date_free (anytime);
2420 log_manager_got_dates_cb (GObject *manager,
2421 GAsyncResult *result,
2424 Ctx *ctx = user_data;
2426 GtkTreeModel *model;
2427 GtkTreeSelection *selection;
2428 GtkListStore *store;
2432 GError *error = NULL;
2434 if (log_window == NULL)
2437 if (log_window->count != ctx->count)
2440 if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
2441 result, &dates, &error))
2443 DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
2448 view = GTK_TREE_VIEW (log_window->treeview_when);
2449 model = gtk_tree_view_get_model (view);
2450 store = GTK_LIST_STORE (model);
2451 selection = gtk_tree_view_get_selection (view);
2453 for (l = dates; l != NULL; l = l->next)
2455 GDate *date = l->data;
2457 /* Add the date if it's not already there */
2458 has_element = FALSE;
2459 gtk_tree_model_foreach (model, model_has_date, date);
2462 gchar *text = format_date_for_display (date);
2464 gtk_list_store_append (store, &iter);
2465 gtk_list_store_set (store, &iter,
2466 COL_WHEN_DATE, date,
2467 COL_WHEN_TEXT, text,
2468 COL_WHEN_ICON, CALENDAR_ICON,
2475 if (gtk_tree_model_get_iter_first (model, &iter))
2477 gchar *separator = NULL;
2479 if (gtk_tree_model_iter_next (model, &iter))
2481 gtk_tree_model_get (model, &iter,
2482 COL_WHEN_TEXT, &separator,
2486 if (g_strcmp0 (separator, "separator") != 0)
2488 gtk_list_store_prepend (store, &iter);
2489 gtk_list_store_set (store, &iter,
2490 COL_WHEN_DATE, g_date_new_dmy (1, 1, -1),
2491 COL_WHEN_TEXT, "separator",
2494 gtk_list_store_prepend (store, &iter);
2495 gtk_list_store_set (store, &iter,
2496 COL_WHEN_DATE, g_date_new_dmy (2, 1, -1),
2497 COL_WHEN_TEXT, _("Anytime"),
2502 g_list_free_full (dates, g_free);
2505 _tpl_action_chain_continue (log_window->chain);
2509 select_first_date (TplActionChain *chain, gpointer user_data)
2512 GtkTreeModel *model;
2513 GtkTreeSelection *selection;
2516 view = GTK_TREE_VIEW (log_window->treeview_when);
2517 model = gtk_tree_view_get_model (view);
2518 selection = gtk_tree_view_get_selection (view);
2520 /* Show messages of the most recent date */
2521 if (gtk_tree_model_get_iter_first (model, &iter))
2522 gtk_tree_selection_select_iter (selection, &iter);
2524 _tpl_action_chain_continue (log_window->chain);
2528 get_dates_for_entity (TplActionChain *chain, gpointer user_data)
2530 Ctx *ctx = user_data;
2532 tpl_log_manager_get_dates_async (ctx->window->log_manager,
2533 ctx->account, ctx->entity, ctx->event_mask,
2534 log_manager_got_dates_cb, ctx);
2538 log_window_chats_get_messages (EmpathyLogWindow *window,
2539 gboolean force_get_dates)
2541 GList *accounts, *targets, *dates;
2542 TplEventTypeMask event_mask;
2544 GtkTreeModel *model;
2545 GtkListStore *store;
2546 GtkTreeSelection *selection;
2548 if (!log_window_get_selected (window, &accounts, &targets,
2549 &dates, &event_mask, NULL))
2552 view = GTK_TREE_VIEW (window->treeview_when);
2553 selection = gtk_tree_view_get_selection (view);
2554 model = gtk_tree_view_get_model (view);
2555 store = GTK_LIST_STORE (model);
2557 /* Clear all current messages shown in the textview */
2558 gtk_tree_store_clear (window->store_events);
2560 _tpl_action_chain_clear (window->chain);
2563 /* If there's a search use the returned hits */
2564 if (window->hits != NULL)
2566 if (force_get_dates)
2568 g_signal_handlers_block_by_func (selection,
2569 log_window_when_changed_cb,
2572 gtk_list_store_clear (store);
2574 g_signal_handlers_unblock_by_func (selection,
2575 log_window_when_changed_cb,
2578 populate_dates_from_search_hits (accounts, targets);
2582 populate_events_from_search_hits (accounts, targets, dates);
2585 /* Either use the supplied date or get the last */
2586 else if (force_get_dates || dates == NULL)
2590 g_signal_handlers_block_by_func (selection,
2591 log_window_when_changed_cb,
2594 gtk_list_store_clear (store);
2596 g_signal_handlers_unblock_by_func (selection,
2597 log_window_when_changed_cb,
2600 /* Get a list of dates and show them on the treeview */
2601 for (targ = targets, acc = accounts;
2602 targ != NULL && acc != NULL;
2603 targ = targ->next, acc = acc->next)
2605 TpAccount *account = acc->data;
2606 TplEntity *target = targ->data;
2607 Ctx *ctx = ctx_new (window, account, target, NULL, event_mask, 0,
2610 _tpl_action_chain_append (window->chain, get_dates_for_entity, ctx);
2612 _tpl_action_chain_append (window->chain, select_first_date, NULL);
2613 _tpl_action_chain_start (window->chain);
2617 /* Show messages of the selected date */
2618 log_window_get_messages_for_dates (window, dates);
2621 g_list_free_full (accounts, g_object_unref);
2622 g_list_free_full (targets, g_object_unref);
2623 g_list_free_full (dates, (GFreeFunc) g_date_free);
2627 EmpathyAccountChooserFilterResultCallback callback;
2629 } FilterCallbackData;
2632 got_entities (GObject *manager,
2633 GAsyncResult *result,
2636 FilterCallbackData *data = user_data;
2638 GError *error = NULL;
2640 if (!tpl_log_manager_get_entities_finish (TPL_LOG_MANAGER (manager),
2641 result, &entities, &error))
2643 DEBUG ("Could not get entities: %s", error->message);
2644 g_error_free (error);
2645 data->callback (FALSE, data->user_data);
2649 data->callback (entities != NULL, data->user_data);
2651 g_list_free_full (entities, g_object_unref);
2654 g_slice_free (FilterCallbackData, data);
2658 empathy_account_chooser_filter_has_logs (TpAccount *account,
2659 EmpathyAccountChooserFilterResultCallback callback,
2660 gpointer callback_data,
2663 TplLogManager *manager = tpl_log_manager_dup_singleton ();
2664 FilterCallbackData *cb_data = g_slice_new0 (FilterCallbackData);
2666 cb_data->callback = callback;
2667 cb_data->user_data = callback_data;
2669 tpl_log_manager_get_entities_async (manager, account, got_entities, cb_data);
2671 g_object_unref (manager);
2675 log_window_logger_clear_account_cb (TpProxy *proxy,
2676 const GError *error,
2678 GObject *weak_object)
2680 EmpathyLogWindow *window = user_data;
2683 g_warning ("Error when clearing logs: %s", error->message);
2685 /* Refresh the log viewer so the logs are cleared if the account
2686 * has been deleted */
2687 gtk_tree_store_clear (window->store_events);
2688 log_window_who_populate (window);
2690 /* Re-filter the account chooser so the accounts without logs get greyed out */
2691 empathy_account_chooser_set_filter (
2692 EMPATHY_ACCOUNT_CHOOSER (window->account_chooser),
2693 empathy_account_chooser_filter_has_logs, NULL);
2697 log_window_clear_logs_chooser_select_account (EmpathyAccountChooser *chooser,
2698 EmpathyLogWindow *window)
2700 EmpathyAccountChooser *account_chooser;
2702 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
2704 empathy_account_chooser_set_account (chooser,
2705 empathy_account_chooser_get_account (account_chooser));
2709 log_window_delete_menu_clicked_cb (GtkMenuItem *menuitem,
2710 EmpathyLogWindow *window)
2712 GtkWidget *dialog, *content_area, *hbox, *label;
2713 EmpathyAccountChooser *account_chooser;
2717 GError *error = NULL;
2719 account_chooser = (EmpathyAccountChooser *) empathy_account_chooser_new ();
2720 empathy_account_chooser_set_has_all_option (account_chooser, TRUE);
2721 empathy_account_chooser_set_filter (account_chooser,
2722 empathy_account_chooser_filter_has_logs, NULL);
2724 /* Select the same account as in the history window */
2725 if (empathy_account_chooser_is_ready (account_chooser))
2726 log_window_clear_logs_chooser_select_account (account_chooser, window);
2728 g_signal_connect (account_chooser, "ready",
2729 G_CALLBACK (log_window_clear_logs_chooser_select_account), window);
2731 dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (window->window),
2732 GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
2734 _("Are you sure you want to delete all logs of previous conversations?"));
2736 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
2737 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2738 _("Clear All"), GTK_RESPONSE_APPLY,
2741 content_area = gtk_message_dialog_get_message_area (
2742 GTK_MESSAGE_DIALOG (dialog));
2744 hbox = gtk_hbox_new (FALSE, 6);
2745 label = gtk_label_new (_("Delete from:"));
2746 gtk_box_pack_start (GTK_BOX (hbox), label,
2748 gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (account_chooser),
2750 gtk_box_pack_start (GTK_BOX (content_area), hbox,
2753 gtk_widget_show_all (hbox);
2755 response_id = gtk_dialog_run (GTK_DIALOG (dialog));
2757 if (response_id != GTK_RESPONSE_APPLY)
2760 bus = tp_dbus_daemon_dup (&error);
2763 g_warning ("Could not delete logs: %s", error->message);
2764 g_error_free (error);
2768 logger = g_object_new (TP_TYPE_PROXY,
2769 "bus-name", "org.freedesktop.Telepathy.Logger",
2770 "object-path", "/org/freedesktop/Telepathy/Logger",
2773 g_object_unref (bus);
2775 tp_proxy_add_interface_by_id (logger, EMP_IFACE_QUARK_LOGGER);
2777 if (empathy_account_chooser_has_all_selected (account_chooser))
2779 DEBUG ("Deleting logs for all the accounts");
2781 emp_cli_logger_call_clear (logger, -1,
2782 log_window_logger_clear_account_cb,
2783 window, NULL, G_OBJECT (window->window));
2789 account = empathy_account_chooser_get_account (account_chooser);
2791 DEBUG ("Deleting logs for %s", tp_proxy_get_object_path (account));
2793 emp_cli_logger_call_clear_account (logger, -1,
2794 tp_proxy_get_object_path (account),
2795 log_window_logger_clear_account_cb,
2796 window, NULL, G_OBJECT (window->window));
2799 g_object_unref (logger);
2801 gtk_widget_destroy (dialog);