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;
75 GtkWidget *treeview_who;
76 GtkWidget *treeview_what;
77 GtkWidget *treeview_when;
78 GtkWidget *treeview_events;
80 GtkTreeStore *store_events;
82 GtkWidget *account_chooser;
86 TplActionChain *chain;
87 TplLogManager *log_manager;
89 /* Used to cancel logger calls when no longer needed */
92 /* List of owned TplLogSearchHits, free with tpl_log_search_hit_free */
96 /* Only used while waiting for the account chooser to be ready */
97 TpAccount *selected_account;
98 gchar *selected_chat_id;
99 gboolean selected_is_chatroom;
102 static void log_window_destroy_cb (GtkWidget *widget,
103 EmpathyLogWindow *window);
104 static void log_window_search_entry_changed_cb (GtkWidget *entry,
105 EmpathyLogWindow *window);
106 static void log_window_search_entry_activate_cb (GtkWidget *widget,
107 EmpathyLogWindow *window);
108 static void log_window_search_entry_icon_pressed_cb (GtkEntry *entry,
109 GtkEntryIconPosition icon_pos,
112 static void log_window_who_populate (EmpathyLogWindow *window);
113 static void log_window_who_setup (EmpathyLogWindow *window);
114 static void log_window_when_setup (EmpathyLogWindow *window);
115 static void log_window_what_setup (EmpathyLogWindow *window);
116 static void log_window_events_setup (EmpathyLogWindow *window);
117 static void log_window_chats_accounts_changed_cb (GtkWidget *combobox,
118 EmpathyLogWindow *window);
119 static void log_window_chats_set_selected (EmpathyLogWindow *window);
120 static void log_window_chats_get_messages (EmpathyLogWindow *window,
121 gboolean force_get_dates);
122 static void log_window_when_changed_cb (GtkTreeSelection *selection,
123 EmpathyLogWindow *window);
124 static void log_window_delete_menu_clicked_cb (GtkMenuItem *menuitem,
125 EmpathyLogWindow *window);
128 empathy_account_chooser_filter_has_logs (TpAccount *account,
129 EmpathyAccountChooserFilterResultCallback callback,
130 gpointer callback_data,
178 COL_EVENTS_PRETTY_DATE,
187 #define CALENDAR_ICON "stock_calendar"
189 /* Seconds between two messages to be considered one conversation */
190 #define MAX_GAP 30*60
192 #define WHAT_TYPE_SEPARATOR -1
196 EVENT_CALL_INCOMING = 1 << 0,
197 EVENT_CALL_OUTGOING = 1 << 1,
198 EVENT_CALL_MISSED = 1 << 2,
199 EVENT_CALL_ALL = 1 << 3,
202 static EmpathyLogWindow *log_window = NULL;
204 static gboolean has_element;
207 #define _date_copy(d) g_date_new_julian (g_date_get_julian (d))
212 EmpathyLogWindow *window;
216 TplEventTypeMask event_mask;
217 EventSubtype subtype;
222 ctx_new (EmpathyLogWindow *window,
226 TplEventTypeMask event_mask,
227 EventSubtype subtype,
230 Ctx *ctx = g_slice_new0 (Ctx);
232 ctx->window = window;
234 ctx->account = g_object_ref (account);
236 ctx->entity = g_object_ref (entity);
238 ctx->date = _date_copy (date);
239 ctx->event_mask = event_mask;
240 ctx->subtype = subtype;
249 tp_clear_object (&ctx->account);
250 tp_clear_object (&ctx->entity);
251 tp_clear_pointer (&ctx->date, g_date_free);
253 g_slice_free (Ctx, ctx);
257 account_chooser_ready_cb (EmpathyAccountChooser *chooser,
258 EmpathyLogWindow *window)
260 /* We'll display the account once the model has been populate with the chats
261 * of this account. */
262 empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (
263 window->account_chooser), window->selected_account);
267 select_account_once_ready (EmpathyLogWindow *self,
269 const gchar *chat_id,
270 gboolean is_chatroom)
272 EmpathyAccountChooser *account_chooser;
274 account_chooser = EMPATHY_ACCOUNT_CHOOSER (self->account_chooser);
276 tp_clear_object (&self->selected_account);
277 self->selected_account = g_object_ref (account);
279 g_free (self->selected_chat_id);
280 self->selected_chat_id = g_strdup (chat_id);
282 self->selected_is_chatroom = is_chatroom;
284 if (empathy_account_chooser_is_ready (account_chooser))
285 account_chooser_ready_cb (account_chooser, self);
287 /* Chat will be selected once the account chooser is ready */
288 g_signal_connect (account_chooser, "ready",
289 G_CALLBACK (account_chooser_ready_cb), self);
293 toolbutton_profile_clicked (GtkToolButton *toolbutton,
294 EmpathyLogWindow *window)
297 GtkTreeSelection *selection;
304 EmpathyContact *contact;
307 g_return_if_fail (window != NULL);
309 view = GTK_TREE_VIEW (log_window->treeview_who);
310 selection = gtk_tree_view_get_selection (view);
312 paths = gtk_tree_selection_get_selected_rows (selection, &model);
313 g_return_if_fail (paths != NULL);
316 gtk_tree_model_get_iter (model, &iter, path);
317 gtk_tree_model_get (model, &iter,
318 COL_WHO_ACCOUNT, &account,
319 COL_WHO_TARGET, &target,
323 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
325 g_return_if_fail (type == COL_TYPE_NORMAL);
327 contact = empathy_contact_from_tpl_contact (account, target);
328 empathy_contact_information_dialog_show (contact,
329 GTK_WINDOW (window->window));
330 g_object_unref (contact);
332 g_object_unref (account);
333 g_object_unref (target);
337 toolbutton_chat_clicked (GtkToolButton *toolbutton,
338 EmpathyLogWindow *window)
341 GtkTreeSelection *selection;
348 EmpathyContact *contact;
351 g_return_if_fail (window != NULL);
353 view = GTK_TREE_VIEW (log_window->treeview_who);
354 selection = gtk_tree_view_get_selection (view);
356 paths = gtk_tree_selection_get_selected_rows (selection, &model);
357 g_return_if_fail (paths != NULL);
360 gtk_tree_model_get_iter (model, &iter, path);
361 gtk_tree_model_get (model, &iter,
362 COL_WHO_ACCOUNT, &account,
363 COL_WHO_TARGET, &target,
367 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
369 g_return_if_fail (type == COL_TYPE_NORMAL);
371 contact = empathy_contact_from_tpl_contact (account, target);
372 empathy_chat_with_contact (contact,
373 gtk_get_current_event_time ());
375 g_object_unref (contact);
376 g_object_unref (account);
377 g_object_unref (target);
381 toolbutton_av_clicked (GtkToolButton *toolbutton,
382 EmpathyLogWindow *window)
385 GtkTreeSelection *selection;
395 g_return_if_fail (window != NULL);
397 view = GTK_TREE_VIEW (log_window->treeview_who);
398 selection = gtk_tree_view_get_selection (view);
400 paths = gtk_tree_selection_get_selected_rows (selection, &model);
401 g_return_if_fail (paths != NULL);
404 gtk_tree_model_get_iter (model, &iter, path);
405 gtk_tree_model_get (model, &iter,
406 COL_WHO_ACCOUNT, &account,
407 COL_WHO_NAME, &contact,
411 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
413 g_return_if_fail (type == COL_TYPE_NORMAL);
415 video = (GTK_WIDGET (toolbutton) == window->button_video);
417 empathy_call_new_with_streams (contact, account,
418 TRUE, video, gtk_get_current_event_time ());
421 g_object_unref (account);
425 empathy_log_window_show (TpAccount *account,
426 const gchar *chat_id,
427 gboolean is_chatroom,
430 EmpathyAccountChooser *account_chooser;
433 EmpathyLogWindow *window;
434 GtkWidget *vbox, *accounts, *search, *label, *quit;
436 if (log_window != NULL)
438 gtk_window_present (GTK_WINDOW (log_window->window));
440 if (account != NULL && chat_id != NULL)
441 select_account_once_ready (log_window, account, chat_id, is_chatroom);
443 return log_window->window;
446 log_window = g_new0 (EmpathyLogWindow, 1);
447 log_window->chain = _tpl_action_chain_new_async (NULL, NULL, NULL);
449 log_window->log_manager = tpl_log_manager_dup_singleton ();
453 filename = empathy_file_lookup ("empathy-log-window.ui", "libempathy-gtk");
454 gui = empathy_builder_get_file (filename,
455 "log_window", &window->window,
456 "toolbutton_profile", &window->button_profile,
457 "toolbutton_chat", &window->button_chat,
458 "toolbutton_call", &window->button_call,
459 "toolbutton_video", &window->button_video,
460 "toolbutton_accounts", &accounts,
461 "toolbutton_search", &search,
462 "imagemenuitem_quit", &quit,
463 "treeview_who", &window->treeview_who,
464 "treeview_what", &window->treeview_what,
465 "treeview_when", &window->treeview_when,
466 "treeview_events", &window->treeview_events,
467 "notebook", &window->notebook,
468 "spinner", &window->spinner,
472 empathy_builder_connect (gui, window,
473 "log_window", "destroy", log_window_destroy_cb,
474 "toolbutton_profile", "clicked", toolbutton_profile_clicked,
475 "toolbutton_chat", "clicked", toolbutton_chat_clicked,
476 "toolbutton_call", "clicked", toolbutton_av_clicked,
477 "toolbutton_video", "clicked", toolbutton_av_clicked,
478 "imagemenuitem_delete", "activate", log_window_delete_menu_clicked_cb,
481 g_object_unref (gui);
483 g_object_add_weak_pointer (G_OBJECT (window->window),
484 (gpointer) &log_window);
486 g_signal_connect_swapped (quit, "activate",
487 G_CALLBACK (gtk_widget_destroy), window->window);
489 /* Account chooser for chats */
490 vbox = gtk_vbox_new (FALSE, 3);
492 window->account_chooser = empathy_account_chooser_new ();
493 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
494 empathy_account_chooser_set_has_all_option (account_chooser, TRUE);
495 empathy_account_chooser_set_filter (account_chooser,
496 empathy_account_chooser_filter_has_logs, NULL);
497 empathy_account_chooser_set_all (account_chooser);
499 g_signal_connect (window->account_chooser, "changed",
500 G_CALLBACK (log_window_chats_accounts_changed_cb),
503 label = gtk_label_new (_("Show"));
505 gtk_box_pack_start (GTK_BOX (vbox),
506 window->account_chooser,
509 gtk_box_pack_start (GTK_BOX (vbox),
513 gtk_widget_show_all (vbox);
514 gtk_container_add (GTK_CONTAINER (accounts), vbox);
517 vbox = gtk_vbox_new (FALSE, 3);
519 window->search_entry = gtk_entry_new ();
520 gtk_entry_set_icon_from_stock (GTK_ENTRY (window->search_entry),
521 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND);
522 gtk_entry_set_icon_from_stock (GTK_ENTRY (window->search_entry),
523 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
525 label = gtk_label_new (_("Search"));
527 gtk_box_pack_start (GTK_BOX (vbox),
528 window->search_entry,
531 gtk_box_pack_start (GTK_BOX (vbox),
535 gtk_widget_show_all (vbox);
536 gtk_container_add (GTK_CONTAINER (search), vbox);
538 g_signal_connect (window->search_entry, "changed",
539 G_CALLBACK (log_window_search_entry_changed_cb),
542 g_signal_connect (window->search_entry, "activate",
543 G_CALLBACK (log_window_search_entry_activate_cb),
546 g_signal_connect (window->search_entry, "icon-press",
547 G_CALLBACK (log_window_search_entry_icon_pressed_cb),
551 log_window_events_setup (window);
552 log_window_who_setup (window);
553 log_window_what_setup (window);
554 log_window_when_setup (window);
556 log_window_who_populate (window);
558 if (account != NULL && chat_id != NULL)
559 select_account_once_ready (window, account, chat_id, is_chatroom);
562 gtk_window_set_transient_for (GTK_WINDOW (window->window),
563 GTK_WINDOW (parent));
565 gtk_widget_show (window->window);
567 return window->window;
571 log_window_destroy_cb (GtkWidget *widget,
572 EmpathyLogWindow *window)
574 if (window->source != 0)
575 g_source_remove (window->source);
577 g_free (window->last_find);
578 _tpl_action_chain_free (window->chain);
579 g_object_unref (window->log_manager);
580 tp_clear_object (&window->selected_account);
581 g_free (window->selected_chat_id);
587 account_equal (TpAccount *a,
590 return g_str_equal (tp_proxy_get_object_path (a),
591 tp_proxy_get_object_path (b));
595 entity_equal (TplEntity *a,
598 return g_str_equal (tpl_entity_get_identifier (a),
599 tpl_entity_get_identifier (b));
603 is_same_confroom (TplEvent *e1,
606 TplEntity *sender1 = tpl_event_get_sender (e1);
607 TplEntity *receiver1 = tpl_event_get_receiver (e1);
608 TplEntity *sender2 = tpl_event_get_sender (e2);
609 TplEntity *receiver2 = tpl_event_get_receiver (e2);
610 TplEntity *room1, *room2;
612 if (tpl_entity_get_entity_type (sender1) == TPL_ENTITY_ROOM)
614 else if (tpl_entity_get_entity_type (receiver1) == TPL_ENTITY_ROOM)
619 if (tpl_entity_get_entity_type (sender2) == TPL_ENTITY_ROOM)
621 else if (tpl_entity_get_entity_type (receiver2) == TPL_ENTITY_ROOM)
626 return g_str_equal (tpl_entity_get_identifier (room1),
627 tpl_entity_get_identifier (room1));
631 event_get_target (TplEvent *event)
633 TplEntity *sender = tpl_event_get_sender (event);
634 TplEntity *receiver = tpl_event_get_receiver (event);
636 if (tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
643 model_is_parent (GtkTreeModel *model,
647 TplEvent *stored_event;
650 gboolean found = FALSE;
653 if (gtk_tree_model_iter_parent (model, &parent, iter))
656 gtk_tree_model_get (model, iter,
657 COL_EVENTS_ACCOUNT, &account,
658 COL_EVENTS_TARGET, &target,
659 COL_EVENTS_EVENT, &stored_event,
662 if (G_OBJECT_TYPE (event) == G_OBJECT_TYPE (stored_event) &&
663 account_equal (account, tpl_event_get_account (event)) &&
664 (entity_equal (target, event_get_target (event)) ||
665 is_same_confroom (event, stored_event)))
670 gtk_tree_model_iter_nth_child (model, &child, iter,
671 gtk_tree_model_iter_n_children (model, iter) - 1);
673 gtk_tree_model_get (model, &child,
674 COL_EVENTS_TS, ×tamp,
677 if (ABS (tpl_event_get_timestamp (event) - timestamp) < MAX_GAP)
679 /* The gap is smaller than 30 min */
684 g_object_unref (stored_event);
685 g_object_unref (account);
686 g_object_unref (target);
692 get_contact_alias_for_message (EmpathyMessage *message)
694 EmpathyContact *sender, *receiver;
696 sender = empathy_message_get_sender (message);
697 receiver = empathy_message_get_receiver (message);
699 if (empathy_contact_is_user (sender))
700 return empathy_contact_get_alias (receiver);
702 return empathy_contact_get_alias (sender);
706 get_parent_iter_for_message (TplEvent *event,
707 EmpathyMessage *message,
713 gboolean parent_found = FALSE;
716 store = log_window->store_events;
717 model = GTK_TREE_MODEL (store);
719 for (next = gtk_tree_model_get_iter_first (model, &iter);
721 next = gtk_tree_model_iter_next (model, &iter))
723 if ((parent_found = model_is_parent (model, &iter, event)))
734 gchar *body, *pretty_date;
736 date = g_date_time_new_from_unix_utc (
737 tpl_event_get_timestamp (event));
739 pretty_date = g_date_time_format (date,
740 C_("A date with the time", "%A, %e %B %Y %X"));
742 body = g_markup_printf_escaped (_("Chat with %s"),
743 get_contact_alias_for_message (message));
745 gtk_tree_store_append (store, &iter, NULL);
746 gtk_tree_store_set (store, &iter,
747 COL_EVENTS_TS, tpl_event_get_timestamp (event),
748 COL_EVENTS_PRETTY_DATE, pretty_date,
749 COL_EVENTS_TEXT, body,
750 COL_EVENTS_ICON, "stock_text_justify",
751 COL_EVENTS_ACCOUNT, tpl_event_get_account (event),
752 COL_EVENTS_TARGET, event_get_target (event),
753 COL_EVENTS_EVENT, event,
759 g_free (pretty_date);
760 g_date_time_unref (date);
765 get_icon_for_event (TplEvent *event)
767 const gchar *icon = NULL;
769 if (TPL_IS_CALL_EVENT (event))
771 TplCallEvent *call = TPL_CALL_EVENT (event);
772 TplCallEndReason reason = tpl_call_event_get_end_reason (call);
773 TplEntity *sender = tpl_event_get_sender (event);
774 TplEntity *receiver = tpl_event_get_receiver (event);
776 if (reason == TPL_CALL_END_REASON_NO_ANSWER)
777 icon = EMPATHY_IMAGE_CALL_MISSED;
778 else if (tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
779 icon = EMPATHY_IMAGE_CALL_OUTGOING;
780 else if (tpl_entity_get_entity_type (receiver) == TPL_ENTITY_SELF)
781 icon = EMPATHY_IMAGE_CALL_INCOMING;
788 log_window_append_chat_message (TplEvent *event,
789 EmpathyMessage *message)
791 GtkTreeStore *store = log_window->store_events;
792 GtkTreeIter iter, parent;
793 gchar *pretty_date, *body;
796 date = g_date_time_new_from_unix_utc (
797 tpl_event_get_timestamp (event));
799 pretty_date = g_date_time_format (date, "%X");
801 get_parent_iter_for_message (event, message, &parent);
803 if (tpl_text_event_get_message_type (TPL_TEXT_EVENT (event))
804 == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION)
806 /* Translators: this is an emote: '* Danielle waves' */
807 body = g_markup_printf_escaped (_("<i>* %s %s</i>"),
808 tpl_entity_get_alias (tpl_event_get_sender (event)),
809 empathy_message_get_body (message));
813 /* Translators: this is a message: 'Danielle: hello'
814 * The string in bold is the sender's name */
815 body = g_markup_printf_escaped (_("<b>%s:</b> %s"),
816 tpl_entity_get_alias (tpl_event_get_sender (event)),
817 empathy_message_get_body (message));
820 gtk_tree_store_append (store, &iter, &parent);
821 gtk_tree_store_set (store, &iter,
822 COL_EVENTS_TS, tpl_event_get_timestamp (event),
823 COL_EVENTS_PRETTY_DATE, pretty_date,
824 COL_EVENTS_TEXT, body,
825 COL_EVENTS_ICON, get_icon_for_event (event),
826 COL_EVENTS_ACCOUNT, tpl_event_get_account (event),
827 COL_EVENTS_TARGET, event_get_target (event),
828 COL_EVENTS_EVENT, event,
832 g_free (pretty_date);
833 g_date_time_unref (date);
837 log_window_append_call (TplEvent *event,
838 EmpathyMessage *message)
840 TplCallEvent *call = TPL_CALL_EVENT (event);
841 GtkTreeStore *store = log_window->store_events;
842 GtkTreeIter iter, child;
843 gchar *pretty_date, *duration, *finished;
844 GDateTime *started_date, *finished_date;
847 started_date = g_date_time_new_from_unix_utc (
848 tpl_event_get_timestamp (event));
850 pretty_date = g_date_time_format (started_date,
851 C_("A date with the time", "%A, %e %B %Y %X"));
853 gtk_tree_store_append (store, &iter, NULL);
854 gtk_tree_store_set (store, &iter,
855 COL_EVENTS_TS, tpl_event_get_timestamp (event),
856 COL_EVENTS_PRETTY_DATE, pretty_date,
857 COL_EVENTS_TEXT, empathy_message_get_body (message),
858 COL_EVENTS_ICON, get_icon_for_event (event),
859 COL_EVENTS_ACCOUNT, tpl_event_get_account (event),
860 COL_EVENTS_TARGET, event_get_target (event),
861 COL_EVENTS_EVENT, event,
864 if (tpl_call_event_get_end_reason (call) != TPL_CALL_END_REASON_NO_ANSWER)
868 span = tpl_call_event_get_duration (TPL_CALL_EVENT (event));
870 duration = g_strdup_printf (_("%" G_GINT64_FORMAT " seconds"), span);
872 duration = g_strdup_printf (_("%" G_GINT64_FORMAT " minutes"),
875 finished_date = g_date_time_add (started_date, -span);
876 finished = g_date_time_format (finished_date, "%X");
877 g_date_time_unref (finished_date);
879 body = g_strdup_printf (_("Call took %s, ended at %s"),
885 gtk_tree_store_append (store, &child, &iter);
886 gtk_tree_store_set (store, &child,
887 COL_EVENTS_TS, tpl_event_get_timestamp (event),
888 COL_EVENTS_TEXT, body,
889 COL_EVENTS_ACCOUNT, tpl_event_get_account (event),
890 COL_EVENTS_TARGET, event_get_target (event),
891 COL_EVENTS_EVENT, event,
897 g_free (pretty_date);
898 g_date_time_unref (started_date);
902 log_window_append_message (TplEvent *event,
903 EmpathyMessage *message)
905 if (TPL_IS_TEXT_EVENT (event))
906 log_window_append_chat_message (event, message);
907 else if (TPL_IS_CALL_EVENT (event))
908 log_window_append_call (event, message);
910 DEBUG ("Message type not handled");
914 add_all_accounts_and_entities (GList **accounts,
921 view = GTK_TREE_VIEW (log_window->treeview_who);
922 model = gtk_tree_view_get_model (view);
924 if (!gtk_tree_model_get_iter_first (model, &iter))
933 gtk_tree_model_get (model, &iter,
934 COL_WHO_ACCOUNT, &account,
935 COL_WHO_TARGET, &entity,
939 if (type != COL_TYPE_NORMAL)
942 if (accounts != NULL)
943 *accounts = g_list_append (*accounts, account);
945 if (entities != NULL)
946 *entities = g_list_append (*entities, entity);
948 while (gtk_tree_model_iter_next (model, &iter));
952 log_window_get_selected (EmpathyLogWindow *window,
956 TplEventTypeMask *event_mask,
957 EventSubtype *subtype)
961 GtkTreeSelection *selection;
963 TplEventTypeMask ev = 0;
968 view = GTK_TREE_VIEW (window->treeview_who);
969 model = gtk_tree_view_get_model (view);
970 selection = gtk_tree_view_get_selection (view);
972 paths = gtk_tree_selection_get_selected_rows (selection, NULL);
976 if (accounts != NULL)
978 if (entities != NULL)
981 for (l = paths; l != NULL; l = l->next)
983 GtkTreePath *path = l->data;
987 gtk_tree_model_get_iter (model, &iter, path);
988 gtk_tree_model_get (model, &iter,
989 COL_WHO_ACCOUNT, &account,
990 COL_WHO_TARGET, &entity,
994 if (type == COL_TYPE_ANY)
996 if (accounts != NULL || entities != NULL)
997 add_all_accounts_and_entities (accounts, entities);
1001 if (accounts != NULL)
1002 *accounts = g_list_append (*accounts, g_object_ref (account));
1004 if (entities != NULL)
1005 *entities = g_list_append (*entities, g_object_ref (entity));
1007 g_object_unref (account);
1008 g_object_unref (entity);
1010 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
1012 view = GTK_TREE_VIEW (window->treeview_what);
1013 model = gtk_tree_view_get_model (view);
1014 selection = gtk_tree_view_get_selection (view);
1016 paths = gtk_tree_selection_get_selected_rows (selection, NULL);
1017 for (l = paths; l != NULL; l = l->next)
1019 GtkTreePath *path = l->data;
1020 TplEventTypeMask mask;
1021 EventSubtype submask;
1023 gtk_tree_model_get_iter (model, &iter, path);
1024 gtk_tree_model_get (model, &iter,
1025 COL_WHAT_TYPE, &mask,
1026 COL_WHAT_SUBTYPE, &submask,
1032 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
1034 view = GTK_TREE_VIEW (window->treeview_when);
1035 model = gtk_tree_view_get_model (view);
1036 selection = gtk_tree_view_get_selection (view);
1042 paths = gtk_tree_selection_get_selected_rows (selection, NULL);
1043 for (l = paths; l != NULL; l = l->next)
1045 GtkTreePath *path = l->data;
1048 gtk_tree_model_get_iter (model, &iter, path);
1049 gtk_tree_model_get (model, &iter,
1050 COL_WHEN_DATE, &date,
1053 *dates = g_list_append (*dates, date);
1055 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
1058 if (event_mask != NULL)
1061 if (subtype != NULL)
1068 model_has_entity (GtkTreeModel *model,
1073 TplLogSearchHit *hit = data;
1076 gboolean ret = FALSE;
1078 gtk_tree_model_get (model, iter,
1080 COL_WHO_ACCOUNT, &a,
1083 if (e != NULL && entity_equal (hit->target, e) &&
1084 a != NULL && account_equal (hit->account, a))
1086 ret = has_element = TRUE;
1089 tp_clear_object (&e);
1090 tp_clear_object (&a);
1096 model_has_date (GtkTreeModel *model,
1104 gtk_tree_model_get (model, iter,
1108 if (!g_date_compare (date, d))
1118 get_events_for_date (TplActionChain *chain, gpointer user_data);
1121 populate_events_from_search_hits (GList *accounts,
1125 TplEventTypeMask event_mask;
1126 EventSubtype subtype;
1129 gboolean is_anytime = FALSE;
1131 if (!log_window_get_selected (log_window,
1132 NULL, NULL, NULL, &event_mask, &subtype))
1135 anytime = g_date_new_dmy (2, 1, -1);
1136 if (g_list_find_custom (dates, anytime, (GCompareFunc) g_date_compare))
1139 for (l = log_window->hits; l != NULL; l = l->next)
1141 TplLogSearchHit *hit = l->data;
1143 gboolean found = FALSE;
1145 /* Protect against invalid data (corrupt or old log files). */
1146 if (hit->account == NULL || hit->target == NULL)
1149 for (acc = accounts, targ = targets;
1150 acc != NULL && targ != NULL && !found;
1151 acc = acc->next, targ = targ->next)
1153 TpAccount *account = acc->data;
1154 TplEntity *target = targ->data;
1156 if (account_equal (hit->account, account) &&
1157 entity_equal (hit->target, target))
1165 g_list_find_custom (dates, hit->date, (GCompareFunc) g_date_compare)
1170 ctx = ctx_new (log_window, hit->account, hit->target, hit->date,
1171 event_mask, subtype, log_window->count);
1172 _tpl_action_chain_append (log_window->chain,
1173 get_events_for_date, ctx);
1177 _tpl_action_chain_start (log_window->chain);
1179 g_date_free (anytime);
1183 format_date_for_display (GDate *date)
1189 /* g_date_strftime sucks */
1191 now = g_date_new ();
1192 g_date_set_time_t (now, time (NULL));
1194 days_elapsed = g_date_days_between (date, now);
1196 if (days_elapsed < 0)
1200 else if (days_elapsed == 0)
1202 text = g_strdup (_("Today"));
1204 else if (days_elapsed == 1)
1206 text = g_strdup (_("Yesterday"));
1212 dt = g_date_time_new_utc (g_date_get_year (date),
1213 g_date_get_month (date), g_date_get_day (date),
1216 if (days_elapsed <= 7)
1217 text = g_date_time_format (dt, "%A");
1219 text = g_date_time_format (dt,
1220 C_("A date such as '23 May 2010', "
1221 "%e is the day, %B the month and %Y the year",
1224 g_date_time_unref (dt);
1233 populate_dates_from_search_hits (GList *accounts,
1238 GtkTreeModel *model;
1239 GtkListStore *store;
1240 GtkTreeSelection *selection;
1243 if (log_window == NULL)
1246 view = GTK_TREE_VIEW (log_window->treeview_when);
1247 model = gtk_tree_view_get_model (view);
1248 store = GTK_LIST_STORE (model);
1249 selection = gtk_tree_view_get_selection (view);
1251 for (l = log_window->hits; l != NULL; l = l->next)
1253 TplLogSearchHit *hit = l->data;
1255 gboolean found = FALSE;
1257 /* Protect against invalid data (corrupt or old log files). */
1258 if (hit->account == NULL || hit->target == NULL)
1261 for (acc = accounts, targ = targets;
1262 acc != NULL && targ != NULL && !found;
1263 acc = acc->next, targ = targ->next)
1265 TpAccount *account = acc->data;
1266 TplEntity *target = targ->data;
1268 if (account_equal (hit->account, account) &&
1269 entity_equal (hit->target, target))
1276 /* Add the date if it's not already there */
1277 has_element = FALSE;
1278 gtk_tree_model_foreach (model, model_has_date, hit->date);
1281 gchar *text = format_date_for_display (hit->date);
1283 gtk_list_store_append (store, &iter);
1284 gtk_list_store_set (store, &iter,
1285 COL_WHEN_DATE, hit->date,
1286 COL_WHEN_TEXT, text,
1287 COL_WHEN_ICON, CALENDAR_ICON,
1292 if (gtk_tree_model_get_iter_first (model, &iter))
1294 gtk_list_store_prepend (store, &iter);
1295 gtk_list_store_set (store, &iter,
1296 COL_WHEN_DATE, g_date_new_dmy (1, 1, -1),
1297 COL_WHEN_TEXT, "separator",
1300 gtk_list_store_prepend (store, &iter);
1301 gtk_list_store_set (store, &iter,
1302 COL_WHEN_DATE, g_date_new_dmy (2, 1, -1),
1303 COL_WHEN_TEXT, _("Anytime"),
1306 if (gtk_tree_model_iter_nth_child (model, &iter, NULL, 2))
1307 gtk_tree_selection_select_iter (selection, &iter);
1312 populate_entities_from_search_hits (void)
1314 EmpathyAccountChooser *account_chooser;
1317 GtkTreeModel *model;
1319 GtkListStore *store;
1322 view = GTK_TREE_VIEW (log_window->treeview_who);
1323 model = gtk_tree_view_get_model (view);
1324 store = GTK_LIST_STORE (model);
1326 gtk_list_store_clear (store);
1328 account_chooser = EMPATHY_ACCOUNT_CHOOSER (log_window->account_chooser);
1329 account = empathy_account_chooser_get_account (account_chooser);
1331 for (l = log_window->hits; l; l = l->next)
1333 TplLogSearchHit *hit = l->data;
1335 /* Protect against invalid data (corrupt or old log files). */
1336 if (hit->account == NULL || hit->target == NULL)
1339 /* Filter based on the selected account */
1340 if (account != NULL && !account_equal (account, hit->account))
1343 /* Add the entity if it's not already there */
1344 has_element = FALSE;
1345 gtk_tree_model_foreach (model, model_has_entity, hit);
1348 TplEntityType type = tpl_entity_get_entity_type (hit->target);
1349 gboolean room = type == TPL_ENTITY_ROOM;
1351 gtk_list_store_append (store, &iter);
1352 gtk_list_store_set (store, &iter,
1353 COL_WHO_TYPE, COL_TYPE_NORMAL,
1354 COL_WHO_ICON, room ? EMPATHY_IMAGE_GROUP_MESSAGE
1355 : EMPATHY_IMAGE_AVATAR_DEFAULT,
1356 COL_WHO_NAME, tpl_entity_get_alias (hit->target),
1357 COL_WHO_ACCOUNT, hit->account,
1358 COL_WHO_TARGET, hit->target,
1363 if (gtk_tree_model_get_iter_first (model, &iter))
1365 gtk_list_store_prepend (store, &iter);
1366 gtk_list_store_set (store, &iter,
1367 COL_WHO_TYPE, COL_TYPE_SEPARATOR,
1368 COL_WHO_NAME, "separator",
1371 gtk_list_store_prepend (store, &iter);
1372 gtk_list_store_set (store, &iter,
1373 COL_WHO_TYPE, COL_TYPE_ANY,
1374 COL_WHO_NAME, _("Anyone"),
1378 /* FIXME: select old entity if still available */
1382 log_manager_searched_new_cb (GObject *manager,
1383 GAsyncResult *result,
1388 GtkTreeSelection *selection;
1389 GError *error = NULL;
1391 if (log_window == NULL)
1394 if (!tpl_log_manager_search_finish (TPL_LOG_MANAGER (manager),
1395 result, &hits, &error))
1397 DEBUG ("%s. Aborting", error->message);
1398 g_error_free (error);
1402 tp_clear_pointer (&log_window->hits, tpl_log_manager_search_free);
1403 log_window->hits = hits;
1405 populate_entities_from_search_hits ();
1407 view = GTK_TREE_VIEW (log_window->treeview_when);
1408 selection = gtk_tree_view_get_selection (view);
1410 g_signal_handlers_unblock_by_func (selection,
1411 log_window_when_changed_cb,
1416 log_window_find_populate (EmpathyLogWindow *window,
1417 const gchar *search_criteria)
1420 GtkTreeModel *model;
1421 GtkTreeSelection *selection;
1422 GtkListStore *store;
1424 gtk_tree_store_clear (window->store_events);
1426 view = GTK_TREE_VIEW (window->treeview_who);
1427 model = gtk_tree_view_get_model (view);
1428 store = GTK_LIST_STORE (model);
1430 gtk_list_store_clear (store);
1432 view = GTK_TREE_VIEW (window->treeview_when);
1433 model = gtk_tree_view_get_model (view);
1434 store = GTK_LIST_STORE (model);
1435 selection = gtk_tree_view_get_selection (view);
1437 gtk_list_store_clear (store);
1439 if (EMP_STR_EMPTY (search_criteria))
1441 tp_clear_pointer (&window->hits, tpl_log_manager_search_free);
1442 log_window_who_populate (window);
1446 g_signal_handlers_block_by_func (selection,
1447 log_window_when_changed_cb,
1450 tpl_log_manager_search_async (window->log_manager,
1451 search_criteria, TPL_EVENT_MASK_ANY,
1452 log_manager_searched_new_cb, NULL);
1456 start_find_search (EmpathyLogWindow *window)
1460 str = gtk_entry_get_text (GTK_ENTRY (window->search_entry));
1462 /* Don't find the same crap again */
1463 if (window->last_find && !tp_strdiff (window->last_find, str))
1466 g_free (window->last_find);
1467 window->last_find = g_strdup (str);
1469 log_window_find_populate (window, str);
1475 log_window_search_entry_changed_cb (GtkWidget *entry,
1476 EmpathyLogWindow *window)
1478 if (window->source != 0)
1479 g_source_remove (window->source);
1480 window->source = g_timeout_add (500, (GSourceFunc) start_find_search,
1485 log_window_search_entry_activate_cb (GtkWidget *entry,
1486 EmpathyLogWindow *self)
1488 start_find_search (self);
1492 log_window_search_entry_icon_pressed_cb (GtkEntry *entry,
1493 GtkEntryIconPosition icon_pos,
1497 if (icon_pos != GTK_ENTRY_ICON_SECONDARY)
1500 gtk_entry_buffer_set_text (gtk_entry_get_buffer (entry),
1505 log_window_update_buttons_sensitivity (EmpathyLogWindow *window,
1506 GtkTreeModel *model,
1507 GtkTreeSelection *selection)
1509 EmpathyContact *contact;
1510 EmpathyCapabilities capabilities;
1516 gboolean profile, chat, call, video;
1518 profile = chat = call = video = FALSE;
1520 if (!gtk_tree_model_get_iter_first (model, &iter))
1523 if (gtk_tree_selection_count_selected_rows (selection) != 1)
1526 if (gtk_tree_selection_iter_is_selected (selection, &iter))
1529 paths = gtk_tree_selection_get_selected_rows (selection, &model);
1530 g_return_if_fail (paths != NULL);
1533 gtk_tree_model_get_iter (model, &iter, path);
1534 gtk_tree_model_get (model, &iter,
1535 COL_WHO_ACCOUNT, &account,
1536 COL_WHO_TARGET, &target,
1539 g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
1541 contact = empathy_contact_from_tpl_contact (account, target);
1543 g_object_unref (account);
1544 g_object_unref (target);
1546 capabilities = empathy_contact_get_capabilities (contact);
1548 profile = chat = TRUE;
1549 call = capabilities & EMPATHY_CAPABILITIES_AUDIO;
1550 video = capabilities & EMPATHY_CAPABILITIES_VIDEO;
1553 gtk_widget_set_sensitive (window->button_profile, profile);
1554 gtk_widget_set_sensitive (window->button_chat, chat);
1555 gtk_widget_set_sensitive (window->button_call, call);
1556 gtk_widget_set_sensitive (window->button_video, video);
1560 log_window_who_changed_cb (GtkTreeSelection *selection,
1561 EmpathyLogWindow *window)
1564 GtkTreeModel *model;
1567 DEBUG ("log_window_who_changed_cb");
1569 view = gtk_tree_selection_get_tree_view (selection);
1570 model = gtk_tree_view_get_model (view);
1572 if (gtk_tree_model_get_iter_first (model, &iter))
1574 /* If 'Anyone' is selected, everything else should be deselected */
1575 if (gtk_tree_selection_iter_is_selected (selection, &iter))
1577 g_signal_handlers_block_by_func (selection,
1578 log_window_who_changed_cb,
1581 gtk_tree_selection_unselect_all (selection);
1582 gtk_tree_selection_select_iter (selection, &iter);
1584 g_signal_handlers_unblock_by_func (selection,
1585 log_window_who_changed_cb,
1590 log_window_update_buttons_sensitivity (window, model, selection);
1592 /* The contact changed, so the dates need to be updated */
1593 log_window_chats_get_messages (window, TRUE);
1597 log_manager_got_entities_cb (GObject *manager,
1598 GAsyncResult *result,
1601 Ctx *ctx = user_data;
1605 GtkTreeModel *model;
1606 GtkTreeSelection *selection;
1607 GtkListStore *store;
1609 GError *error = NULL;
1610 gboolean select_account = FALSE;
1612 if (log_window == NULL)
1615 if (log_window->count != ctx->count)
1618 if (!tpl_log_manager_get_entities_finish (TPL_LOG_MANAGER (manager),
1619 result, &entities, &error))
1621 DEBUG ("%s. Aborting", error->message);
1622 g_error_free (error);
1626 view = GTK_TREE_VIEW (ctx->window->treeview_who);
1627 model = gtk_tree_view_get_model (view);
1628 selection = gtk_tree_view_get_selection (view);
1629 store = GTK_LIST_STORE (model);
1631 /* Block signals to stop the logs being retrieved prematurely */
1632 g_signal_handlers_block_by_func (selection,
1633 log_window_who_changed_cb, ctx->window);
1635 for (l = entities; l; l = l->next)
1637 TplEntity *entity = TPL_ENTITY (l->data);
1638 TplEntityType type = tpl_entity_get_entity_type (entity);
1639 gboolean room = type == TPL_ENTITY_ROOM;
1641 gtk_list_store_append (store, &iter);
1642 gtk_list_store_set (store, &iter,
1643 COL_WHO_TYPE, COL_TYPE_NORMAL,
1644 COL_WHO_ICON, room ? EMPATHY_IMAGE_GROUP_MESSAGE
1645 : EMPATHY_IMAGE_AVATAR_DEFAULT,
1646 COL_WHO_NAME, tpl_entity_get_alias (entity),
1647 COL_WHO_ACCOUNT, ctx->account,
1648 COL_WHO_TARGET, entity,
1651 if (ctx->window->selected_account != NULL &&
1652 !tp_strdiff (tp_proxy_get_object_path (ctx->account),
1653 tp_proxy_get_object_path (ctx->window->selected_account)))
1654 select_account = TRUE;
1656 g_list_free_full (entities, g_object_unref);
1658 if (gtk_tree_model_get_iter_first (model, &iter))
1662 gtk_tree_model_get (model, &iter,
1663 COL_WHO_TYPE, &type,
1666 if (type != COL_TYPE_ANY)
1668 gtk_list_store_prepend (store, &iter);
1669 gtk_list_store_set (store, &iter,
1670 COL_WHO_TYPE, COL_TYPE_SEPARATOR,
1671 COL_WHO_NAME, "separator",
1674 gtk_list_store_prepend (store, &iter);
1675 gtk_list_store_set (store, &iter,
1676 COL_WHO_TYPE, COL_TYPE_ANY,
1677 COL_WHO_NAME, _("Anyone"),
1682 /* Unblock signals */
1683 g_signal_handlers_unblock_by_func (selection,
1684 log_window_who_changed_cb,
1687 /* We display the selected account if we populate the model with chats from
1690 log_window_chats_set_selected (ctx->window);
1693 _tpl_action_chain_continue (log_window->chain);
1698 get_entities_for_account (TplActionChain *chain, gpointer user_data)
1700 Ctx *ctx = user_data;
1702 tpl_log_manager_get_entities_async (ctx->window->log_manager, ctx->account,
1703 log_manager_got_entities_cb, ctx);
1707 select_first_entity (TplActionChain *chain, gpointer user_data)
1710 GtkTreeModel *model;
1711 GtkTreeSelection *selection;
1714 view = GTK_TREE_VIEW (log_window->treeview_who);
1715 model = gtk_tree_view_get_model (view);
1716 selection = gtk_tree_view_get_selection (view);
1718 if (gtk_tree_model_get_iter_first (model, &iter))
1719 gtk_tree_selection_select_iter (selection, &iter);
1721 _tpl_action_chain_continue (log_window->chain);
1725 log_window_who_populate (EmpathyLogWindow *window)
1727 EmpathyAccountChooser *account_chooser;
1729 gboolean all_accounts;
1731 GtkTreeModel *model;
1732 GtkTreeSelection *selection;
1733 GtkListStore *store;
1736 if (window->hits != NULL)
1738 populate_entities_from_search_hits ();
1742 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
1743 account = empathy_account_chooser_dup_account (account_chooser);
1744 all_accounts = empathy_account_chooser_has_all_selected (account_chooser);
1746 view = GTK_TREE_VIEW (window->treeview_who);
1747 model = gtk_tree_view_get_model (view);
1748 selection = gtk_tree_view_get_selection (view);
1749 store = GTK_LIST_STORE (model);
1751 /* Block signals to stop the logs being retrieved prematurely */
1752 g_signal_handlers_block_by_func (selection,
1753 log_window_who_changed_cb,
1756 gtk_list_store_clear (store);
1758 /* Unblock signals */
1759 g_signal_handlers_unblock_by_func (selection,
1760 log_window_who_changed_cb,
1763 _tpl_action_chain_clear (window->chain);
1766 if (!all_accounts && account == NULL)
1770 else if (!all_accounts)
1772 ctx = ctx_new (window, account, NULL, NULL, 0, 0, window->count);
1773 _tpl_action_chain_append (window->chain, get_entities_for_account, ctx);
1777 TpAccountManager *manager;
1778 GList *accounts, *l;
1780 manager = empathy_account_chooser_get_account_manager (account_chooser);
1781 accounts = tp_account_manager_get_valid_accounts (manager);
1783 for (l = accounts; l != NULL; l = l->next)
1787 ctx = ctx_new (window, account, NULL, NULL, 0, 0, window->count);
1788 _tpl_action_chain_append (window->chain,
1789 get_entities_for_account, ctx);
1792 g_list_free (accounts);
1794 _tpl_action_chain_append (window->chain, select_first_entity, NULL);
1795 _tpl_action_chain_start (window->chain);
1799 sort_by_name (GtkTreeModel *model,
1804 gchar *name1, *name2;
1808 gtk_tree_model_get (model, a,
1809 COL_WHO_TYPE, &type1,
1810 COL_WHO_NAME, &name1,
1813 gtk_tree_model_get (model, b,
1814 COL_WHO_TYPE, &type2,
1815 COL_WHO_NAME, &name2,
1818 if (type1 == COL_TYPE_ANY)
1820 else if (type2 == COL_TYPE_ANY)
1822 else if (type1 == COL_TYPE_SEPARATOR)
1824 else if (type2 == COL_TYPE_SEPARATOR)
1827 ret = g_strcmp0 (name1, name2);
1836 who_row_is_separator (GtkTreeModel *model,
1842 gtk_tree_model_get (model, iter,
1843 COL_WHO_TYPE, &type,
1846 return (type == COL_TYPE_SEPARATOR);
1850 log_window_events_setup (EmpathyLogWindow *window)
1853 GtkTreeModel *model;
1854 GtkTreeSelection *selection;
1855 GtkTreeSortable *sortable;
1856 GtkTreeViewColumn *column;
1857 GtkTreeStore *store;
1858 GtkCellRenderer *cell;
1860 view = GTK_TREE_VIEW (window->treeview_events);
1861 selection = gtk_tree_view_get_selection (view);
1864 window->store_events = store = gtk_tree_store_new (COL_EVENTS_COUNT,
1865 G_TYPE_INT, /* type */
1866 G_TYPE_INT64, /* timestamp */
1867 G_TYPE_STRING, /* stringified date */
1868 G_TYPE_STRING, /* icon */
1869 G_TYPE_STRING, /* name */
1870 TP_TYPE_ACCOUNT, /* account */
1871 TPL_TYPE_ENTITY, /* target */
1872 TPL_TYPE_EVENT); /* event */
1874 model = GTK_TREE_MODEL (store);
1875 sortable = GTK_TREE_SORTABLE (store);
1877 gtk_tree_view_set_model (view, model);
1880 column = gtk_tree_view_column_new ();
1882 cell = gtk_cell_renderer_pixbuf_new ();
1883 gtk_tree_view_column_pack_start (column, cell, FALSE);
1884 gtk_tree_view_column_add_attribute (column, cell,
1885 "icon-name", COL_EVENTS_ICON);
1887 cell = gtk_cell_renderer_text_new ();
1888 gtk_tree_view_column_pack_start (column, cell, TRUE);
1889 gtk_tree_view_column_add_attribute (column, cell,
1890 "markup", COL_EVENTS_TEXT);
1892 cell = gtk_cell_renderer_text_new ();
1893 g_object_set (cell, "xalign", 1.0, NULL);
1894 gtk_tree_view_column_pack_end (column, cell, FALSE);
1895 gtk_tree_view_column_add_attribute (column, cell,
1896 "text", COL_EVENTS_PRETTY_DATE);
1898 gtk_tree_view_append_column (view, column);
1900 /* set up treeview properties */
1901 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
1902 gtk_tree_view_set_headers_visible (view, FALSE);
1904 gtk_tree_sortable_set_sort_column_id (sortable,
1906 GTK_SORT_ASCENDING);
1908 gtk_tree_view_set_enable_search (view, FALSE);
1910 g_object_unref (store);
1914 log_window_who_setup (EmpathyLogWindow *window)
1917 GtkTreeModel *model;
1918 GtkTreeSelection *selection;
1919 GtkTreeSortable *sortable;
1920 GtkTreeViewColumn *column;
1921 GtkListStore *store;
1922 GtkCellRenderer *cell;
1924 view = GTK_TREE_VIEW (window->treeview_who);
1925 selection = gtk_tree_view_get_selection (view);
1928 store = gtk_list_store_new (COL_WHO_COUNT,
1929 G_TYPE_INT, /* type */
1930 G_TYPE_STRING, /* icon */
1931 G_TYPE_STRING, /* name */
1932 TP_TYPE_ACCOUNT, /* account */
1933 TPL_TYPE_ENTITY); /* target */
1935 model = GTK_TREE_MODEL (store);
1936 sortable = GTK_TREE_SORTABLE (store);
1938 gtk_tree_view_set_model (view, model);
1941 column = gtk_tree_view_column_new ();
1942 gtk_tree_view_column_set_title (column, _("Who"));
1944 cell = gtk_cell_renderer_pixbuf_new ();
1945 gtk_tree_view_column_pack_start (column, cell, FALSE);
1946 gtk_tree_view_column_add_attribute (column, cell,
1950 cell = gtk_cell_renderer_text_new ();
1951 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
1952 gtk_tree_view_column_pack_start (column, cell, TRUE);
1953 gtk_tree_view_column_add_attribute (column, cell,
1957 gtk_tree_view_append_column (view, column);
1959 /* set up treeview properties */
1960 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
1961 gtk_tree_view_set_row_separator_func (view, who_row_is_separator,
1964 gtk_tree_sortable_set_sort_column_id (sortable,
1966 GTK_SORT_ASCENDING);
1967 gtk_tree_sortable_set_sort_func (sortable,
1968 COL_WHO_NAME, sort_by_name,
1971 gtk_tree_view_set_search_column (view, COL_WHO_NAME);
1973 /* set up signals */
1974 g_signal_connect (selection, "changed",
1975 G_CALLBACK (log_window_who_changed_cb), window);
1977 g_object_unref (store);
1981 log_window_chats_accounts_changed_cb (GtkWidget *combobox,
1982 EmpathyLogWindow *window)
1984 /* Clear all current messages shown in the textview */
1985 gtk_tree_store_clear (window->store_events);
1987 log_window_who_populate (window);
1991 log_window_chats_set_selected (EmpathyLogWindow *window)
1994 GtkTreeModel *model;
1995 GtkTreeSelection *selection;
2000 view = GTK_TREE_VIEW (window->treeview_who);
2001 model = gtk_tree_view_get_model (view);
2002 selection = gtk_tree_view_get_selection (view);
2004 for (next = gtk_tree_model_get_iter_first (model, &iter);
2006 next = gtk_tree_model_iter_next (model, &iter))
2008 TpAccount *this_account;
2009 TplEntity *this_target;
2010 const gchar *this_chat_id;
2011 gboolean this_is_chatroom;
2014 gtk_tree_model_get (model, &iter,
2015 COL_WHO_TYPE, &this_type,
2016 COL_WHO_ACCOUNT, &this_account,
2017 COL_WHO_TARGET, &this_target,
2020 if (this_type != COL_TYPE_NORMAL)
2023 this_chat_id = tpl_entity_get_identifier (this_target);
2024 this_is_chatroom = tpl_entity_get_entity_type (this_target)
2027 if (this_account == window->selected_account &&
2028 !tp_strdiff (this_chat_id, window->selected_chat_id) &&
2029 this_is_chatroom == window->selected_is_chatroom)
2031 gtk_tree_selection_select_iter (selection, &iter);
2032 path = gtk_tree_model_get_path (model, &iter);
2033 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
2034 gtk_tree_path_free (path);
2035 g_object_unref (this_account);
2036 g_object_unref (this_target);
2040 g_object_unref (this_account);
2041 g_object_unref (this_target);
2044 tp_clear_object (&window->selected_account);
2045 tp_clear_pointer (&window->selected_chat_id, g_free);
2049 sort_by_date (GtkTreeModel *model,
2054 GDate *date1, *date2;
2056 gtk_tree_model_get (model, a,
2057 COL_WHEN_DATE, &date1,
2060 gtk_tree_model_get (model, b,
2061 COL_WHEN_DATE, &date2,
2064 return g_date_compare (date1, date2);
2068 when_row_is_separator (GtkTreeModel *model,
2075 gtk_tree_model_get (model, iter,
2076 COL_WHEN_TEXT, &when,
2079 ret = g_str_equal (when, "separator");
2085 log_window_when_changed_cb (GtkTreeSelection *selection,
2086 EmpathyLogWindow *window)
2089 GtkTreeModel *model;
2092 DEBUG ("log_window_when_changed_cb");
2094 view = gtk_tree_selection_get_tree_view (selection);
2095 model = gtk_tree_view_get_model (view);
2097 /* If 'Anytime' is selected, everything else should be deselected */
2098 if (gtk_tree_model_get_iter_first (model, &iter))
2100 if (gtk_tree_selection_iter_is_selected (selection, &iter))
2102 g_signal_handlers_block_by_func (selection,
2103 log_window_when_changed_cb,
2106 gtk_tree_selection_unselect_all (selection);
2107 gtk_tree_selection_select_iter (selection, &iter);
2109 g_signal_handlers_unblock_by_func (selection,
2110 log_window_when_changed_cb,
2115 log_window_chats_get_messages (window, FALSE);
2119 log_window_when_setup (EmpathyLogWindow *window)
2122 GtkTreeModel *model;
2123 GtkTreeSelection *selection;
2124 GtkTreeSortable *sortable;
2125 GtkTreeViewColumn *column;
2126 GtkListStore *store;
2127 GtkCellRenderer *cell;
2129 view = GTK_TREE_VIEW (window->treeview_when);
2130 selection = gtk_tree_view_get_selection (view);
2133 store = gtk_list_store_new (COL_WHEN_COUNT,
2134 G_TYPE_DATE, /* date */
2135 G_TYPE_STRING, /* stringified date */
2136 G_TYPE_STRING); /* icon */
2138 model = GTK_TREE_MODEL (store);
2139 sortable = GTK_TREE_SORTABLE (store);
2141 gtk_tree_view_set_model (view, model);
2144 column = gtk_tree_view_column_new ();
2145 gtk_tree_view_column_set_title (column, _("When"));
2147 cell = gtk_cell_renderer_pixbuf_new ();
2148 gtk_tree_view_column_pack_start (column, cell, FALSE);
2149 gtk_tree_view_column_add_attribute (column, cell,
2150 "icon-name", COL_WHEN_ICON);
2152 cell = gtk_cell_renderer_text_new ();
2153 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
2154 gtk_tree_view_column_pack_start (column, cell, TRUE);
2155 gtk_tree_view_column_add_attribute (column, cell,
2159 gtk_tree_view_append_column (view, column);
2161 /* set up treeview properties */
2162 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
2163 gtk_tree_view_set_row_separator_func (view, when_row_is_separator,
2165 gtk_tree_sortable_set_sort_column_id (sortable,
2167 GTK_SORT_DESCENDING);
2168 gtk_tree_sortable_set_sort_func (sortable,
2169 COL_WHEN_DATE, sort_by_date,
2172 gtk_tree_view_set_search_column (view, COL_WHEN_TEXT);
2174 /* set up signals */
2175 g_signal_connect (selection, "changed",
2176 G_CALLBACK (log_window_when_changed_cb),
2179 g_object_unref (store);
2183 what_row_is_separator (GtkTreeModel *model,
2189 gtk_tree_model_get (model, iter,
2190 COL_WHAT_TYPE, &type,
2193 return (type == WHAT_TYPE_SEPARATOR);
2197 log_window_what_changed_cb (GtkTreeSelection *selection,
2198 EmpathyLogWindow *window)
2201 GtkTreeModel *model;
2204 DEBUG ("log_window_what_changed_cb");
2206 view = gtk_tree_selection_get_tree_view (selection);
2207 model = gtk_tree_view_get_model (view);
2209 /* If 'Anything' is selected, everything else should be deselected */
2210 if (gtk_tree_model_get_iter_first (model, &iter))
2212 if (gtk_tree_selection_iter_is_selected (selection, &iter))
2214 g_signal_handlers_block_by_func (selection,
2215 log_window_what_changed_cb,
2218 gtk_tree_selection_unselect_all (selection);
2219 gtk_tree_selection_select_iter (selection, &iter);
2221 g_signal_handlers_unblock_by_func (selection,
2222 log_window_what_changed_cb,
2227 /* The dates need to be updated if we're not searching */
2228 log_window_chats_get_messages (window, window->hits == NULL);
2232 log_window_what_collapse_row_cb (GtkTreeView *tree_view,
2237 /* Reject collapsing */
2244 EventSubtype subtype;
2250 log_window_what_setup (EmpathyLogWindow *window)
2253 GtkTreeModel *model;
2254 GtkTreeSelection *selection;
2255 GtkTreeSortable *sortable;
2256 GtkTreeViewColumn *column;
2257 GtkTreeIter iter, parent;
2258 GtkTreeStore *store;
2259 GtkCellRenderer *cell;
2261 struct event events [] = {
2262 { TPL_EVENT_MASK_ANY, 0, NULL, _("Anything") },
2263 { WHAT_TYPE_SEPARATOR, 0, NULL, "separator" },
2264 { TPL_EVENT_MASK_TEXT, 0, "stock_text_justify", _("Text chats") },
2265 { TPL_EVENT_MASK_CALL, EVENT_CALL_ALL, "call-start", _("Calls") }
2267 struct event call_events [] = {
2268 { TPL_EVENT_MASK_CALL, EVENT_CALL_INCOMING, "call-start", _("Incoming calls") },
2269 { TPL_EVENT_MASK_CALL, EVENT_CALL_OUTGOING, "call-start", _("Outgoing calls") },
2270 { TPL_EVENT_MASK_CALL, EVENT_CALL_MISSED, "call-stop", _("Missed calls") }
2273 view = GTK_TREE_VIEW (window->treeview_what);
2274 selection = gtk_tree_view_get_selection (view);
2277 store = gtk_tree_store_new (COL_WHAT_COUNT,
2278 G_TYPE_INT, /* history type */
2279 G_TYPE_INT, /* history subtype */
2280 G_TYPE_STRING, /* stringified history type */
2281 G_TYPE_STRING); /* icon */
2283 model = GTK_TREE_MODEL (store);
2284 sortable = GTK_TREE_SORTABLE (store);
2286 gtk_tree_view_set_model (view, model);
2289 column = gtk_tree_view_column_new ();
2290 gtk_tree_view_column_set_title (column, _("What"));
2292 cell = gtk_cell_renderer_pixbuf_new ();
2293 gtk_tree_view_column_pack_start (column, cell, FALSE);
2294 gtk_tree_view_column_add_attribute (column, cell,
2295 "icon-name", COL_WHAT_ICON);
2297 cell = gtk_cell_renderer_text_new ();
2298 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
2299 gtk_tree_view_column_pack_start (column, cell, TRUE);
2300 gtk_tree_view_column_add_attribute (column, cell,
2301 "text", COL_WHAT_TEXT);
2303 gtk_tree_view_append_column (view, column);
2304 gtk_tree_view_set_search_column (view, COL_WHAT_TEXT);
2306 /* set up treeview properties */
2307 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
2308 gtk_tree_view_set_show_expanders (view, FALSE);
2309 gtk_tree_view_set_level_indentation (view, 12);
2310 gtk_tree_view_expand_all (view);
2311 gtk_tree_view_set_row_separator_func (view, what_row_is_separator,
2315 for (i = 0; i < G_N_ELEMENTS (events); i++)
2317 gtk_tree_store_append (store, &iter, NULL);
2318 gtk_tree_store_set (store, &iter,
2319 COL_WHAT_TYPE, events[i].type,
2320 COL_WHAT_SUBTYPE, events[i].subtype,
2321 COL_WHAT_TEXT, events[i].text,
2322 COL_WHAT_ICON, events[i].icon,
2326 gtk_tree_model_iter_nth_child (model, &parent, NULL, 3);
2327 for (i = 0; i < G_N_ELEMENTS (call_events); i++)
2329 gtk_tree_store_append (store, &iter, &parent);
2330 gtk_tree_store_set (store, &iter,
2331 COL_WHAT_TYPE, call_events[i].type,
2332 COL_WHAT_SUBTYPE, call_events[i].subtype,
2333 COL_WHAT_TEXT, call_events[i].text,
2334 COL_WHAT_ICON, call_events[i].icon,
2338 gtk_tree_view_expand_all (view);
2340 /* select 'Anything' */
2341 if (gtk_tree_model_get_iter_first (model, &iter))
2342 gtk_tree_selection_select_iter (selection, &iter);
2344 /* set up signals */
2345 g_signal_connect (view, "test-collapse-row",
2346 G_CALLBACK (log_window_what_collapse_row_cb),
2348 g_signal_connect (selection, "changed",
2349 G_CALLBACK (log_window_what_changed_cb),
2352 g_object_unref (store);
2356 start_spinner (void)
2358 gtk_spinner_start (GTK_SPINNER (log_window->spinner));
2359 gtk_notebook_set_current_page (GTK_NOTEBOOK (log_window->notebook),
2364 show_spinner (gpointer data)
2368 if (log_window == NULL)
2371 g_object_get (log_window->spinner, "active", &active, NULL);
2374 gtk_notebook_set_current_page (GTK_NOTEBOOK (log_window->notebook),
2381 show_events (TplActionChain *chain,
2384 gtk_spinner_stop (GTK_SPINNER (log_window->spinner));
2385 gtk_notebook_set_current_page (GTK_NOTEBOOK (log_window->notebook),
2388 _tpl_action_chain_continue (chain);
2392 log_window_got_messages_for_date_cb (GObject *manager,
2393 GAsyncResult *result,
2396 Ctx *ctx = user_data;
2398 GtkTreeModel *model;
2402 GError *error = NULL;
2405 if (log_window == NULL)
2411 if (log_window->count != ctx->count)
2414 if (!tpl_log_manager_get_events_for_date_finish (TPL_LOG_MANAGER (manager),
2415 result, &events, &error))
2417 DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
2419 g_error_free (error);
2423 for (l = events; l; l = l->next)
2425 TplEvent *event = l->data;
2426 gboolean append = TRUE;
2428 if (TPL_IS_CALL_EVENT (l->data)
2429 && ctx->event_mask & TPL_EVENT_MASK_CALL
2430 && ctx->event_mask != TPL_EVENT_MASK_ANY)
2432 TplCallEvent *call = l->data;
2436 if (ctx->subtype & EVENT_CALL_ALL)
2442 TplCallEndReason reason = tpl_call_event_get_end_reason (call);
2443 TplEntity *sender = tpl_event_get_sender (event);
2444 TplEntity *receiver = tpl_event_get_receiver (event);
2446 if (reason == TPL_CALL_END_REASON_NO_ANSWER)
2448 if (ctx->subtype & EVENT_CALL_MISSED)
2451 else if (ctx->subtype & EVENT_CALL_OUTGOING
2452 && tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
2456 else if (ctx->subtype & EVENT_CALL_INCOMING
2457 && tpl_entity_get_entity_type (receiver) == TPL_ENTITY_SELF)
2466 EmpathyMessage *msg = empathy_message_from_tpl_log_event (event);
2467 log_window_append_message (event, msg);
2468 g_object_unref (msg);
2471 g_object_unref (event);
2473 g_list_free (events);
2475 view = GTK_TREE_VIEW (log_window->treeview_events);
2476 model = gtk_tree_view_get_model (view);
2477 n = gtk_tree_model_iter_n_children (model, NULL) - 1;
2479 if (n >= 0 && gtk_tree_model_iter_nth_child (model, &iter, NULL, n))
2483 path = gtk_tree_model_get_path (model, &iter);
2484 gtk_tree_view_scroll_to_cell (view, path, NULL, FALSE, 0, 0);
2485 gtk_tree_path_free (path);
2491 _tpl_action_chain_continue (log_window->chain);
2495 get_events_for_date (TplActionChain *chain, gpointer user_data)
2497 Ctx *ctx = user_data;
2499 tpl_log_manager_get_events_for_date_async (ctx->window->log_manager,
2500 ctx->account, ctx->entity, ctx->event_mask,
2502 log_window_got_messages_for_date_cb,
2507 log_window_get_messages_for_dates (EmpathyLogWindow *window,
2510 GList *accounts, *targets, *acc, *targ, *l;
2511 TplEventTypeMask event_mask;
2512 EventSubtype subtype;
2513 GDate *date, *anytime, *separator;
2515 if (!log_window_get_selected (window,
2516 &accounts, &targets, NULL, &event_mask, &subtype))
2519 anytime = g_date_new_dmy (2, 1, -1);
2520 separator = g_date_new_dmy (1, 1, -1);
2522 _tpl_action_chain_clear (window->chain);
2525 for (acc = accounts, targ = targets;
2526 acc != NULL && targ != NULL;
2527 acc = acc->next, targ = targ->next)
2529 TpAccount *account = acc->data;
2530 TplEntity *target = targ->data;
2532 for (l = dates; l != NULL; l = l->next)
2537 if (g_date_compare (date, anytime) != 0)
2541 ctx = ctx_new (window, account, target, date, event_mask, subtype,
2543 _tpl_action_chain_append (window->chain, get_events_for_date, ctx);
2547 GtkTreeView *view = GTK_TREE_VIEW (window->treeview_when);
2548 GtkTreeModel *model = gtk_tree_view_get_model (view);
2553 for (next = gtk_tree_model_get_iter_first (model, &iter);
2555 next = gtk_tree_model_iter_next (model, &iter))
2559 gtk_tree_model_get (model, &iter,
2563 if (g_date_compare (d, anytime) != 0 &&
2564 g_date_compare (d, separator) != 0)
2566 ctx = ctx_new (window, account, target, d,
2567 event_mask, subtype, window->count);
2568 _tpl_action_chain_append (window->chain, get_events_for_date, ctx);
2576 g_timeout_add (1000, show_spinner, NULL);
2577 _tpl_action_chain_append (window->chain, show_events, NULL);
2578 _tpl_action_chain_start (window->chain);
2580 g_list_free_full (accounts, g_object_unref);
2581 g_list_free_full (targets, g_object_unref);
2582 g_date_free (separator);
2583 g_date_free (anytime);
2587 log_manager_got_dates_cb (GObject *manager,
2588 GAsyncResult *result,
2591 Ctx *ctx = user_data;
2593 GtkTreeModel *model;
2594 GtkTreeSelection *selection;
2595 GtkListStore *store;
2599 GError *error = NULL;
2601 if (log_window == NULL)
2604 if (log_window->count != ctx->count)
2607 if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
2608 result, &dates, &error))
2610 DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
2615 view = GTK_TREE_VIEW (log_window->treeview_when);
2616 model = gtk_tree_view_get_model (view);
2617 store = GTK_LIST_STORE (model);
2618 selection = gtk_tree_view_get_selection (view);
2620 for (l = dates; l != NULL; l = l->next)
2622 GDate *date = l->data;
2624 /* Add the date if it's not already there */
2625 has_element = FALSE;
2626 gtk_tree_model_foreach (model, model_has_date, date);
2629 gchar *text = format_date_for_display (date);
2631 gtk_list_store_append (store, &iter);
2632 gtk_list_store_set (store, &iter,
2633 COL_WHEN_DATE, date,
2634 COL_WHEN_TEXT, text,
2635 COL_WHEN_ICON, CALENDAR_ICON,
2642 if (gtk_tree_model_get_iter_first (model, &iter))
2644 gchar *separator = NULL;
2646 if (gtk_tree_model_iter_next (model, &iter))
2648 gtk_tree_model_get (model, &iter,
2649 COL_WHEN_TEXT, &separator,
2653 if (g_strcmp0 (separator, "separator") != 0)
2655 gtk_list_store_prepend (store, &iter);
2656 gtk_list_store_set (store, &iter,
2657 COL_WHEN_DATE, g_date_new_dmy (1, 1, -1),
2658 COL_WHEN_TEXT, "separator",
2661 gtk_list_store_prepend (store, &iter);
2662 gtk_list_store_set (store, &iter,
2663 COL_WHEN_DATE, g_date_new_dmy (2, 1, -1),
2664 COL_WHEN_TEXT, _("Anytime"),
2669 g_list_free_full (dates, g_free);
2672 _tpl_action_chain_continue (log_window->chain);
2676 select_first_date (TplActionChain *chain, gpointer user_data)
2679 GtkTreeModel *model;
2680 GtkTreeSelection *selection;
2683 view = GTK_TREE_VIEW (log_window->treeview_when);
2684 model = gtk_tree_view_get_model (view);
2685 selection = gtk_tree_view_get_selection (view);
2687 /* Show messages of the most recent date */
2688 if (gtk_tree_model_iter_nth_child (model, &iter, NULL, 2))
2689 gtk_tree_selection_select_iter (selection, &iter);
2691 _tpl_action_chain_continue (log_window->chain);
2695 get_dates_for_entity (TplActionChain *chain, gpointer user_data)
2697 Ctx *ctx = user_data;
2699 tpl_log_manager_get_dates_async (ctx->window->log_manager,
2700 ctx->account, ctx->entity, ctx->event_mask,
2701 log_manager_got_dates_cb, ctx);
2705 log_window_chats_get_messages (EmpathyLogWindow *window,
2706 gboolean force_get_dates)
2708 GList *accounts, *targets, *dates;
2709 TplEventTypeMask event_mask;
2711 GtkTreeModel *model;
2712 GtkListStore *store;
2713 GtkTreeSelection *selection;
2715 if (!log_window_get_selected (window, &accounts, &targets,
2716 &dates, &event_mask, NULL))
2719 view = GTK_TREE_VIEW (window->treeview_when);
2720 selection = gtk_tree_view_get_selection (view);
2721 model = gtk_tree_view_get_model (view);
2722 store = GTK_LIST_STORE (model);
2724 /* Clear all current messages shown in the textview */
2725 gtk_tree_store_clear (window->store_events);
2727 _tpl_action_chain_clear (window->chain);
2730 /* If there's a search use the returned hits */
2731 if (window->hits != NULL)
2733 if (force_get_dates)
2735 g_signal_handlers_block_by_func (selection,
2736 log_window_when_changed_cb,
2739 gtk_list_store_clear (store);
2741 g_signal_handlers_unblock_by_func (selection,
2742 log_window_when_changed_cb,
2745 populate_dates_from_search_hits (accounts, targets);
2749 populate_events_from_search_hits (accounts, targets, dates);
2752 /* Either use the supplied date or get the last */
2753 else if (force_get_dates || dates == NULL)
2757 g_signal_handlers_block_by_func (selection,
2758 log_window_when_changed_cb,
2761 gtk_list_store_clear (store);
2763 g_signal_handlers_unblock_by_func (selection,
2764 log_window_when_changed_cb,
2767 /* Get a list of dates and show them on the treeview */
2768 for (targ = targets, acc = accounts;
2769 targ != NULL && acc != NULL;
2770 targ = targ->next, acc = acc->next)
2772 TpAccount *account = acc->data;
2773 TplEntity *target = targ->data;
2774 Ctx *ctx = ctx_new (window, account, target, NULL, event_mask, 0,
2777 _tpl_action_chain_append (window->chain, get_dates_for_entity, ctx);
2779 _tpl_action_chain_append (window->chain, select_first_date, NULL);
2780 _tpl_action_chain_start (window->chain);
2784 /* Show messages of the selected date */
2785 log_window_get_messages_for_dates (window, dates);
2788 g_list_free_full (accounts, g_object_unref);
2789 g_list_free_full (targets, g_object_unref);
2790 g_list_free_full (dates, (GFreeFunc) g_date_free);
2794 EmpathyAccountChooserFilterResultCallback callback;
2796 } FilterCallbackData;
2799 got_entities (GObject *manager,
2800 GAsyncResult *result,
2803 FilterCallbackData *data = user_data;
2805 GError *error = NULL;
2807 if (!tpl_log_manager_get_entities_finish (TPL_LOG_MANAGER (manager),
2808 result, &entities, &error))
2810 DEBUG ("Could not get entities: %s", error->message);
2811 g_error_free (error);
2812 data->callback (FALSE, data->user_data);
2816 data->callback (entities != NULL, data->user_data);
2818 g_list_free_full (entities, g_object_unref);
2821 g_slice_free (FilterCallbackData, data);
2825 empathy_account_chooser_filter_has_logs (TpAccount *account,
2826 EmpathyAccountChooserFilterResultCallback callback,
2827 gpointer callback_data,
2830 TplLogManager *manager = tpl_log_manager_dup_singleton ();
2831 FilterCallbackData *cb_data = g_slice_new0 (FilterCallbackData);
2833 cb_data->callback = callback;
2834 cb_data->user_data = callback_data;
2836 tpl_log_manager_get_entities_async (manager, account, got_entities, cb_data);
2838 g_object_unref (manager);
2842 log_window_logger_clear_account_cb (TpProxy *proxy,
2843 const GError *error,
2845 GObject *weak_object)
2847 EmpathyLogWindow *window = user_data;
2850 g_warning ("Error when clearing logs: %s", error->message);
2852 /* Refresh the log viewer so the logs are cleared if the account
2853 * has been deleted */
2854 gtk_tree_store_clear (window->store_events);
2855 log_window_who_populate (window);
2857 /* Re-filter the account chooser so the accounts without logs get greyed out */
2858 empathy_account_chooser_set_filter (
2859 EMPATHY_ACCOUNT_CHOOSER (window->account_chooser),
2860 empathy_account_chooser_filter_has_logs, NULL);
2864 log_window_clear_logs_chooser_select_account (EmpathyAccountChooser *chooser,
2865 EmpathyLogWindow *window)
2867 EmpathyAccountChooser *account_chooser;
2869 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
2871 empathy_account_chooser_set_account (chooser,
2872 empathy_account_chooser_get_account (account_chooser));
2876 log_window_delete_menu_clicked_cb (GtkMenuItem *menuitem,
2877 EmpathyLogWindow *window)
2879 GtkWidget *dialog, *content_area, *hbox, *label;
2880 EmpathyAccountChooser *account_chooser;
2884 GError *error = NULL;
2886 account_chooser = (EmpathyAccountChooser *) empathy_account_chooser_new ();
2887 empathy_account_chooser_set_has_all_option (account_chooser, TRUE);
2888 empathy_account_chooser_set_filter (account_chooser,
2889 empathy_account_chooser_filter_has_logs, NULL);
2891 /* Select the same account as in the history window */
2892 if (empathy_account_chooser_is_ready (account_chooser))
2893 log_window_clear_logs_chooser_select_account (account_chooser, window);
2895 g_signal_connect (account_chooser, "ready",
2896 G_CALLBACK (log_window_clear_logs_chooser_select_account), window);
2898 dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (window->window),
2899 GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
2901 _("Are you sure you want to delete all logs of previous conversations?"));
2903 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
2904 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2905 _("Clear All"), GTK_RESPONSE_APPLY,
2908 content_area = gtk_message_dialog_get_message_area (
2909 GTK_MESSAGE_DIALOG (dialog));
2911 hbox = gtk_hbox_new (FALSE, 6);
2912 label = gtk_label_new (_("Delete from:"));
2913 gtk_box_pack_start (GTK_BOX (hbox), label,
2915 gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (account_chooser),
2917 gtk_box_pack_start (GTK_BOX (content_area), hbox,
2920 gtk_widget_show_all (hbox);
2922 response_id = gtk_dialog_run (GTK_DIALOG (dialog));
2924 if (response_id != GTK_RESPONSE_APPLY)
2927 bus = tp_dbus_daemon_dup (&error);
2930 g_warning ("Could not delete logs: %s", error->message);
2931 g_error_free (error);
2935 logger = g_object_new (TP_TYPE_PROXY,
2936 "bus-name", "org.freedesktop.Telepathy.Logger",
2937 "object-path", "/org/freedesktop/Telepathy/Logger",
2940 g_object_unref (bus);
2942 tp_proxy_add_interface_by_id (logger, EMP_IFACE_QUARK_LOGGER);
2944 if (empathy_account_chooser_has_all_selected (account_chooser))
2946 DEBUG ("Deleting logs for all the accounts");
2948 emp_cli_logger_call_clear (logger, -1,
2949 log_window_logger_clear_account_cb,
2950 window, NULL, G_OBJECT (window->window));
2956 account = empathy_account_chooser_get_account (account_chooser);
2958 DEBUG ("Deleting logs for %s", tp_proxy_get_object_path (account));
2960 emp_cli_logger_call_clear_account (logger, -1,
2961 tp_proxy_get_object_path (account),
2962 log_window_logger_clear_account_cb,
2963 window, NULL, G_OBJECT (window->window));
2966 g_object_unref (logger);
2968 gtk_widget_destroy (dialog);