1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2006-2007 Imendio AB
4 * Copyright (C) 2007-2008 Collabora Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 * Authors: Martyn Russell <martyn@imendio.com>
22 * Xavier Claessens <xclaesse@gmail.com>
30 #include <glib/gi18n-lib.h>
33 #include <telepathy-glib/account-manager.h>
34 #include <telepathy-logger/log-manager.h>
36 #include <libempathy/empathy-chatroom-manager.h>
37 #include <libempathy/empathy-chatroom.h>
38 #include <libempathy/empathy-message.h>
39 #include <libempathy/empathy-utils.h>
40 #include <libempathy/empathy-time.h>
42 #include "empathy-log-window.h"
43 #include "empathy-account-chooser.h"
44 #include "empathy-chat-view.h"
45 #include "empathy-theme-manager.h"
46 #include "empathy-ui-utils.h"
48 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
49 #include <libempathy/empathy-debug.h>
56 GtkWidget *entry_find;
57 GtkWidget *button_find;
58 GtkWidget *treeview_find;
59 GtkWidget *scrolledwindow_find;
60 EmpathyChatView *chatview_find;
61 GtkWidget *button_previous;
62 GtkWidget *button_next;
64 GtkWidget *vbox_chats;
65 GtkWidget *account_chooser_chats;
66 GtkWidget *entry_chats;
67 GtkWidget *calendar_chats;
68 GtkWidget *treeview_chats;
69 GtkWidget *scrolledwindow_chats;
70 EmpathyChatView *chatview_chats;
74 TplLogManager *log_manager;
76 /* Those are only used while waiting for the account chooser to be ready */
77 TpAccount *selected_account;
78 gchar *selected_chat_id;
79 gboolean selected_is_chatroom;
82 static void log_window_destroy_cb (GtkWidget *widget,
83 EmpathyLogWindow *window);
84 static void log_window_entry_find_changed_cb (GtkWidget *entry,
85 EmpathyLogWindow *window);
86 static void log_window_find_changed_cb (GtkTreeSelection *selection,
87 EmpathyLogWindow *window);
88 static void log_window_find_populate (EmpathyLogWindow *window,
89 const gchar *search_criteria);
90 static void log_window_find_setup (EmpathyLogWindow *window);
91 static void log_window_button_find_clicked_cb (GtkWidget *widget,
92 EmpathyLogWindow *window);
93 static void log_window_entry_find_activate_cb (GtkWidget *widget,
94 EmpathyLogWindow *window);
95 static void log_window_button_next_clicked_cb (GtkWidget *widget,
96 EmpathyLogWindow *window);
97 static void log_window_button_previous_clicked_cb (GtkWidget *widget,
98 EmpathyLogWindow *window);
99 static void log_window_button_close_clicked_cb (GtkWidget *widget,
100 EmpathyLogWindow *window);
101 static void log_window_chats_changed_cb (GtkTreeSelection *selection,
102 EmpathyLogWindow *window);
103 static void log_window_chats_populate (EmpathyLogWindow *window);
104 static void log_window_chats_setup (EmpathyLogWindow *window);
105 static void log_window_chats_accounts_changed_cb (GtkWidget *combobox,
106 EmpathyLogWindow *window);
107 static void log_window_chats_set_selected (EmpathyLogWindow *window);
108 static gboolean log_window_chats_get_selected (EmpathyLogWindow *window,
111 gboolean *is_chatroom);
112 static void log_window_chats_get_messages (EmpathyLogWindow *window,
113 GDate *date_to_show);
114 static void log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
115 EmpathyLogWindow *window);
116 static void log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
117 EmpathyLogWindow *window);
118 static void log_window_entry_chats_changed_cb (GtkWidget *entry,
119 EmpathyLogWindow *window);
120 static void log_window_entry_chats_activate_cb (GtkWidget *entry,
121 EmpathyLogWindow *window);
124 COL_FIND_ACCOUNT_ICON,
125 COL_FIND_ACCOUNT_NAME,
129 COL_FIND_IS_CHATROOM,
131 COL_FIND_DATE_READABLE,
140 COL_CHAT_IS_CHATROOM,
144 static EmpathyLogWindow *log_window = NULL;
147 account_manager_prepared_cb (GObject *source_object,
148 GAsyncResult *result,
151 TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
152 EmpathyLogWindow *window = user_data;
155 GError *error = NULL;
157 if (log_window == NULL)
160 if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
161 DEBUG ("Failed to prepare account manager: %s", error->message);
162 g_error_free (error);
166 accounts = tp_account_manager_get_valid_accounts (account_manager);
167 account_num = g_list_length (accounts);
168 g_list_free (accounts);
170 if (account_num > 1) {
171 gtk_widget_show (window->vbox_chats);
172 gtk_widget_show (window->account_chooser_chats);
174 gtk_widget_hide (window->vbox_chats);
175 gtk_widget_hide (window->account_chooser_chats);
180 account_chooser_ready_cb (EmpathyAccountChooser *chooser,
181 EmpathyLogWindow *window)
183 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
185 /* We'll display the account once the model has been populate with the chats
186 * of this account. */
187 empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (
188 window->account_chooser_chats), window->selected_account);
192 select_account_once_ready (EmpathyLogWindow *self,
194 const gchar *chat_id,
195 gboolean is_chatroom)
197 EmpathyAccountChooser *account_chooser = EMPATHY_ACCOUNT_CHOOSER (self->account_chooser_chats);
199 tp_clear_object (&self->selected_account);
200 self->selected_account = g_object_ref (account);
202 g_free (self->selected_chat_id);
203 self->selected_chat_id = g_strdup (chat_id);
205 self->selected_is_chatroom = is_chatroom;
207 if (empathy_account_chooser_is_ready (account_chooser))
208 account_chooser_ready_cb (account_chooser, self);
210 /* Chat will be selected once the account chooser is ready */
211 g_signal_connect (account_chooser, "ready",
212 G_CALLBACK (account_chooser_ready_cb), self);
216 empathy_log_window_show (TpAccount *account,
217 const gchar *chat_id,
218 gboolean is_chatroom,
221 EmpathyAccountChooser *account_chooser;
222 TpAccountManager *account_manager;
225 EmpathyLogWindow *window;
227 if (log_window != NULL) {
228 gtk_window_present (GTK_WINDOW (log_window->window));
230 if (account != NULL && chat_id != NULL) {
231 gtk_notebook_set_current_page (GTK_NOTEBOOK (log_window->notebook), 1);
232 select_account_once_ready (log_window, account, chat_id, is_chatroom);
235 return log_window->window;
238 log_window = g_new0 (EmpathyLogWindow, 1);
239 log_window->log_manager = tpl_log_manager_dup_singleton ();
243 filename = empathy_file_lookup ("empathy-log-window.ui",
245 gui = empathy_builder_get_file (filename,
246 "log_window", &window->window,
247 "notebook", &window->notebook,
248 "entry_find", &window->entry_find,
249 "button_find", &window->button_find,
250 "treeview_find", &window->treeview_find,
251 "scrolledwindow_find", &window->scrolledwindow_find,
252 "button_previous", &window->button_previous,
253 "button_next", &window->button_next,
254 "entry_chats", &window->entry_chats,
255 "calendar_chats", &window->calendar_chats,
256 "vbox_chats", &window->vbox_chats,
257 "treeview_chats", &window->treeview_chats,
258 "scrolledwindow_chats", &window->scrolledwindow_chats,
262 empathy_builder_connect (gui, window,
263 "log_window", "destroy", log_window_destroy_cb,
264 "entry_find", "changed", log_window_entry_find_changed_cb,
265 "entry_find", "activate", log_window_entry_find_activate_cb,
266 "button_previous", "clicked", log_window_button_previous_clicked_cb,
267 "button_next", "clicked", log_window_button_next_clicked_cb,
268 "button_close", "clicked", log_window_button_close_clicked_cb,
269 "button_close2", "clicked", log_window_button_close_clicked_cb,
270 "button_find", "clicked", log_window_button_find_clicked_cb,
271 "entry_chats", "changed", log_window_entry_chats_changed_cb,
272 "entry_chats", "activate", log_window_entry_chats_activate_cb,
275 g_object_unref (gui);
277 g_object_add_weak_pointer (G_OBJECT (window->window),
278 (gpointer) &log_window);
280 /* We set this up here so we can block it when needed. */
281 g_signal_connect (window->calendar_chats, "day-selected",
282 G_CALLBACK (log_window_calendar_chats_day_selected_cb),
284 g_signal_connect (window->calendar_chats, "month-changed",
285 G_CALLBACK (log_window_calendar_chats_month_changed_cb),
288 /* Configure Search EmpathyChatView */
289 window->chatview_find = empathy_theme_manager_create_view (empathy_theme_manager_get ());
290 gtk_container_add (GTK_CONTAINER (window->scrolledwindow_find),
291 GTK_WIDGET (window->chatview_find));
292 gtk_widget_show (GTK_WIDGET (window->chatview_find));
294 /* Configure Contacts EmpathyChatView */
295 window->chatview_chats = empathy_theme_manager_create_view (empathy_theme_manager_get ());
296 gtk_container_add (GTK_CONTAINER (window->scrolledwindow_chats),
297 GTK_WIDGET (window->chatview_chats));
298 gtk_widget_show (GTK_WIDGET (window->chatview_chats));
300 /* Account chooser for chats */
301 window->account_chooser_chats = empathy_account_chooser_new ();
302 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
304 gtk_box_pack_start (GTK_BOX (window->vbox_chats),
305 window->account_chooser_chats,
308 g_signal_connect (window->account_chooser_chats, "changed",
309 G_CALLBACK (log_window_chats_accounts_changed_cb),
313 account_manager = tp_account_manager_dup ();
314 tp_account_manager_prepare_async (account_manager, NULL,
315 account_manager_prepared_cb, window);
316 g_object_unref (account_manager);
319 log_window_find_setup (window);
322 log_window_chats_setup (window);
323 log_window_chats_populate (window);
325 if (account != NULL && chat_id != NULL)
326 select_account_once_ready (window, account, chat_id, is_chatroom);
328 if (parent != NULL) {
329 gtk_window_set_transient_for (GTK_WINDOW (window->window),
330 GTK_WINDOW (parent));
333 gtk_widget_show (window->window);
335 return window->window;
339 log_window_destroy_cb (GtkWidget *widget,
340 EmpathyLogWindow *window)
342 g_free (window->last_find);
343 g_object_unref (window->log_manager);
344 tp_clear_object (&window->selected_account);
345 g_free (window->selected_chat_id);
354 log_window_entry_find_changed_cb (GtkWidget *entry,
355 EmpathyLogWindow *window)
358 gboolean is_sensitive = TRUE;
360 str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
362 is_sensitive &= !EMP_STR_EMPTY (str);
364 !window->last_find ||
365 (window->last_find && tp_strdiff (window->last_find, str));
367 gtk_widget_set_sensitive (window->button_find, is_sensitive);
371 got_messages_for_date_cb (GObject *manager,
372 GAsyncResult *result,
375 EmpathyLogWindow *window = user_data;
378 gboolean can_do_previous;
379 gboolean can_do_next;
380 GError *error = NULL;
382 if (log_window == NULL)
385 if (!tpl_log_manager_get_messages_for_date_finish (TPL_LOG_MANAGER (manager),
386 result, &messages, &error)) {
387 DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
389 empathy_chat_view_append_event (window->chatview_find,
390 "Unable to retrieve messages for the selected date");
391 g_error_free (error);
395 for (l = messages; l; l = l->next) {
396 EmpathyMessage *message;
398 g_assert (TPL_IS_ENTRY (l->data));
400 message = empathy_message_from_tpl_log_entry (l->data);
401 g_object_unref (l->data);
402 empathy_chat_view_append_message (window->chatview_find, message);
403 g_object_unref (message);
405 g_list_free (messages);
407 /* Scroll to the most recent messages */
408 empathy_chat_view_scroll (window->chatview_find, TRUE);
410 /* Highlight and find messages */
411 empathy_chat_view_highlight (window->chatview_find,
414 empathy_chat_view_find_next (window->chatview_find,
418 empathy_chat_view_find_abilities (window->chatview_find,
423 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
424 gtk_widget_set_sensitive (window->button_next, can_do_next);
425 gtk_widget_set_sensitive (window->button_find, FALSE);
429 gdate_from_str (const gchar *str)
432 guint day, month, year;
434 if (sscanf (str, "%u", &u) != 1)
438 month = ((u / 100) % 100);
441 if (!g_date_valid_dmy (day, month, year))
444 return g_date_new_dmy (day, month, year);
448 log_window_find_changed_cb (GtkTreeSelection *selection,
449 EmpathyLogWindow *window)
456 gboolean is_chatroom;
460 /* Get selected information */
461 view = GTK_TREE_VIEW (window->treeview_find);
462 model = gtk_tree_view_get_model (view);
464 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
465 gtk_widget_set_sensitive (window->button_previous, FALSE);
466 gtk_widget_set_sensitive (window->button_next, FALSE);
468 empathy_chat_view_clear (window->chatview_find);
473 gtk_widget_set_sensitive (window->button_previous, TRUE);
474 gtk_widget_set_sensitive (window->button_next, TRUE);
476 gtk_tree_model_get (model, &iter,
477 COL_FIND_ACCOUNT, &account,
478 COL_FIND_CHAT_ID, &chat_id,
479 COL_FIND_IS_CHATROOM, &is_chatroom,
480 COL_FIND_DATE, &date,
483 /* Clear all current messages shown in the textview */
484 empathy_chat_view_clear (window->chatview_find);
486 /* Turn off scrolling temporarily */
487 empathy_chat_view_scroll (window->chatview_find, FALSE);
490 gdate = gdate_from_str (date);
493 tpl_log_manager_get_messages_for_date_async (window->log_manager,
498 got_messages_for_date_cb,
504 g_object_unref (account);
511 log_manager_searched_new_cb (GObject *manager,
512 GAsyncResult *result,
518 GtkListStore *store = user_data;
519 GError *error = NULL;
521 if (log_window == NULL)
524 if (!tpl_log_manager_search_finish (TPL_LOG_MANAGER (manager), result,
526 DEBUG ("%s. Aborting", error->message);
527 g_error_free (error);
531 for (l = hits; l; l = l->next) {
532 TplLogSearchHit *hit;
533 const gchar *account_name;
534 const gchar *account_icon;
535 gchar date_readable[255];
540 /* Protect against invalid data (corrupt or old log files. */
541 if (hit->account == NULL || hit->chat_id == NULL) {
545 g_date_strftime (date_readable, sizeof (date_readable),
546 EMPATHY_DATE_FORMAT_DISPLAY_SHORT, hit->date);
548 g_date_strftime (tmp, sizeof (tmp),
549 "%Y%m%d", hit->date);
551 account_name = tp_account_get_display_name (hit->account);
552 account_icon = tp_account_get_icon_name (hit->account);
554 gtk_list_store_append (store, &iter);
555 gtk_list_store_set (store, &iter,
556 COL_FIND_ACCOUNT_ICON, account_icon,
557 COL_FIND_ACCOUNT_NAME, account_name,
558 COL_FIND_ACCOUNT, hit->account,
559 COL_FIND_CHAT_NAME, hit->chat_id, /* FIXME */
560 COL_FIND_CHAT_ID, hit->chat_id,
561 COL_FIND_IS_CHATROOM, hit->is_chatroom,
563 COL_FIND_DATE_READABLE, date_readable,
566 /* FIXME: Update COL_FIND_CHAT_NAME */
567 if (hit->is_chatroom) {
573 tpl_log_manager_search_free (hits);
578 log_window_find_populate (EmpathyLogWindow *window,
579 const gchar *search_criteria)
583 GtkTreeSelection *selection;
586 view = GTK_TREE_VIEW (window->treeview_find);
587 model = gtk_tree_view_get_model (view);
588 selection = gtk_tree_view_get_selection (view);
589 store = GTK_LIST_STORE (model);
591 empathy_chat_view_clear (window->chatview_find);
593 gtk_list_store_clear (store);
595 if (EMP_STR_EMPTY (search_criteria)) {
596 /* Just clear the search. */
600 tpl_log_manager_search_async (window->log_manager, search_criteria,
601 log_manager_searched_new_cb, (gpointer) store);
605 log_window_find_setup (EmpathyLogWindow *window)
609 GtkTreeSelection *selection;
610 GtkTreeSortable *sortable;
611 GtkTreeViewColumn *column;
613 GtkCellRenderer *cell;
616 view = GTK_TREE_VIEW (window->treeview_find);
617 selection = gtk_tree_view_get_selection (view);
620 store = gtk_list_store_new (COL_FIND_COUNT,
621 G_TYPE_STRING, /* account icon name */
622 G_TYPE_STRING, /* account name */
623 TP_TYPE_ACCOUNT, /* account */
624 G_TYPE_STRING, /* chat name */
625 G_TYPE_STRING, /* chat id */
626 G_TYPE_BOOLEAN, /* is chatroom */
627 G_TYPE_STRING, /* date */
628 G_TYPE_STRING); /* date_readable */
630 model = GTK_TREE_MODEL (store);
631 sortable = GTK_TREE_SORTABLE (store);
633 gtk_tree_view_set_model (view, model);
636 column = gtk_tree_view_column_new ();
638 cell = gtk_cell_renderer_pixbuf_new ();
639 gtk_tree_view_column_pack_start (column, cell, FALSE);
640 gtk_tree_view_column_add_attribute (column, cell,
642 COL_FIND_ACCOUNT_ICON);
644 cell = gtk_cell_renderer_text_new ();
645 gtk_tree_view_column_pack_start (column, cell, TRUE);
646 gtk_tree_view_column_add_attribute (column, cell,
648 COL_FIND_ACCOUNT_NAME);
650 gtk_tree_view_column_set_title (column, _("Account"));
651 gtk_tree_view_append_column (view, column);
653 gtk_tree_view_column_set_resizable (column, TRUE);
654 gtk_tree_view_column_set_clickable (column, TRUE);
656 cell = gtk_cell_renderer_text_new ();
657 offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Conversation"),
658 cell, "text", COL_FIND_CHAT_NAME,
661 column = gtk_tree_view_get_column (view, offset - 1);
662 gtk_tree_view_column_set_sort_column_id (column, COL_FIND_CHAT_NAME);
663 gtk_tree_view_column_set_resizable (column, TRUE);
664 gtk_tree_view_column_set_clickable (column, TRUE);
666 cell = gtk_cell_renderer_text_new ();
667 offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Date"),
668 cell, "text", COL_FIND_DATE_READABLE,
671 column = gtk_tree_view_get_column (view, offset - 1);
672 gtk_tree_view_column_set_sort_column_id (column, COL_FIND_DATE);
673 gtk_tree_view_column_set_resizable (column, TRUE);
674 gtk_tree_view_column_set_clickable (column, TRUE);
676 /* Set up treeview properties */
677 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
678 gtk_tree_sortable_set_sort_column_id (sortable,
683 g_signal_connect (selection, "changed",
684 G_CALLBACK (log_window_find_changed_cb),
687 g_object_unref (store);
691 start_find_search (EmpathyLogWindow *window)
695 str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
697 /* Don't find the same crap again */
698 if (window->last_find && !tp_strdiff (window->last_find, str)) {
702 g_free (window->last_find);
703 window->last_find = g_strdup (str);
705 log_window_find_populate (window, str);
709 log_window_button_find_clicked_cb (GtkWidget *widget,
710 EmpathyLogWindow *window)
712 start_find_search (window);
716 log_window_entry_find_activate_cb (GtkWidget *entry,
717 EmpathyLogWindow *self)
719 start_find_search (self);
723 log_window_button_next_clicked_cb (GtkWidget *widget,
724 EmpathyLogWindow *window)
726 if (window->last_find) {
727 gboolean can_do_previous;
728 gboolean can_do_next;
730 empathy_chat_view_find_next (window->chatview_find,
734 empathy_chat_view_find_abilities (window->chatview_find,
739 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
740 gtk_widget_set_sensitive (window->button_next, can_do_next);
745 log_window_button_previous_clicked_cb (GtkWidget *widget,
746 EmpathyLogWindow *window)
748 if (window->last_find) {
749 gboolean can_do_previous;
750 gboolean can_do_next;
752 empathy_chat_view_find_previous (window->chatview_find,
756 empathy_chat_view_find_abilities (window->chatview_find,
761 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
762 gtk_widget_set_sensitive (window->button_next, can_do_next);
767 log_window_button_close_clicked_cb (GtkWidget *widget,
768 EmpathyLogWindow *window)
770 gtk_widget_destroy (window->window);
778 log_window_chats_changed_cb (GtkTreeSelection *selection,
779 EmpathyLogWindow *window)
781 /* Use last date by default */
782 gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
784 log_window_chats_get_messages (window, NULL);
788 log_manager_got_chats_cb (GObject *manager,
789 GAsyncResult *result,
792 EmpathyLogWindow *window = user_data;
797 GtkTreeSelection *selection;
800 GError *error = NULL;
801 gboolean select_account = FALSE;
803 if (log_window == NULL)
806 if (!tpl_log_manager_get_chats_finish (TPL_LOG_MANAGER (manager),
807 result, &chats, &error)) {
808 DEBUG ("%s. Aborting", error->message);
809 g_error_free (error);
813 view = GTK_TREE_VIEW (window->treeview_chats);
814 model = gtk_tree_view_get_model (view);
815 selection = gtk_tree_view_get_selection (view);
816 store = GTK_LIST_STORE (model);
818 for (l = chats; l; l = l->next) {
819 TplLogSearchHit *hit;
823 if (hit->account == NULL)
826 gtk_list_store_append (store, &iter);
827 gtk_list_store_set (store, &iter,
828 COL_CHAT_ICON, "empathy-available", /* FIXME */
829 COL_CHAT_NAME, hit->chat_id,
830 COL_CHAT_ACCOUNT, hit->account,
831 COL_CHAT_ID, hit->chat_id,
832 COL_CHAT_IS_CHATROOM, hit->is_chatroom,
835 if (window->selected_account != NULL &&
836 !tp_strdiff (tp_proxy_get_object_path (hit->account),
837 tp_proxy_get_object_path (window->selected_account)))
838 select_account = TRUE;
840 /* FIXME: Update COL_CHAT_ICON/NAME */
841 if (hit->is_chatroom) {
845 tpl_log_manager_search_free (chats);
847 /* Unblock signals */
848 g_signal_handlers_unblock_by_func (selection,
849 log_window_chats_changed_cb,
852 /* We display the selected account if we populate the model with chats from
855 log_window_chats_set_selected (window);
859 log_window_chats_populate (EmpathyLogWindow *window)
861 EmpathyAccountChooser *account_chooser;
866 GtkTreeSelection *selection;
869 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
870 account = empathy_account_chooser_dup_account (account_chooser);
872 view = GTK_TREE_VIEW (window->treeview_chats);
873 model = gtk_tree_view_get_model (view);
874 selection = gtk_tree_view_get_selection (view);
875 store = GTK_LIST_STORE (model);
877 if (account == NULL) {
878 gtk_list_store_clear (store);
882 /* Block signals to stop the logs being retrieved prematurely */
883 g_signal_handlers_block_by_func (selection,
884 log_window_chats_changed_cb,
887 gtk_list_store_clear (store);
889 tpl_log_manager_get_chats_async (window->log_manager, account,
890 log_manager_got_chats_cb, (gpointer) window);
894 log_window_chats_setup (EmpathyLogWindow *window)
898 GtkTreeSelection *selection;
899 GtkTreeSortable *sortable;
900 GtkTreeViewColumn *column;
902 GtkCellRenderer *cell;
904 view = GTK_TREE_VIEW (window->treeview_chats);
905 selection = gtk_tree_view_get_selection (view);
908 store = gtk_list_store_new (COL_CHAT_COUNT,
909 G_TYPE_STRING, /* icon */
910 G_TYPE_STRING, /* name */
911 TP_TYPE_ACCOUNT, /* account */
912 G_TYPE_STRING, /* id */
913 G_TYPE_BOOLEAN); /* is chatroom */
915 model = GTK_TREE_MODEL (store);
916 sortable = GTK_TREE_SORTABLE (store);
918 gtk_tree_view_set_model (view, model);
921 column = gtk_tree_view_column_new ();
923 cell = gtk_cell_renderer_pixbuf_new ();
924 gtk_tree_view_column_pack_start (column, cell, FALSE);
925 gtk_tree_view_column_add_attribute (column, cell,
929 cell = gtk_cell_renderer_text_new ();
930 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
931 gtk_tree_view_column_pack_start (column, cell, TRUE);
932 gtk_tree_view_column_add_attribute (column, cell,
936 gtk_tree_view_append_column (view, column);
938 /* set up treeview properties */
939 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
940 gtk_tree_sortable_set_sort_column_id (sortable,
945 g_signal_connect (selection, "changed",
946 G_CALLBACK (log_window_chats_changed_cb),
949 g_object_unref (store);
953 log_window_chats_accounts_changed_cb (GtkWidget *combobox,
954 EmpathyLogWindow *window)
956 /* Clear all current messages shown in the textview */
957 empathy_chat_view_clear (window->chatview_chats);
959 log_window_chats_populate (window);
963 log_window_chats_set_selected (EmpathyLogWindow *window)
967 GtkTreeSelection *selection;
972 view = GTK_TREE_VIEW (window->treeview_chats);
973 model = gtk_tree_view_get_model (view);
974 selection = gtk_tree_view_get_selection (view);
976 if (!gtk_tree_model_get_iter_first (model, &iter)) {
980 for (ok = TRUE; ok; ok = gtk_tree_model_iter_next (model, &iter)) {
981 TpAccount *this_account;
983 gboolean this_is_chatroom;
985 gtk_tree_model_get (model, &iter,
986 COL_CHAT_ACCOUNT, &this_account,
987 COL_CHAT_ID, &this_chat_id,
988 COL_CHAT_IS_CHATROOM, &this_is_chatroom,
991 if (this_account == window->selected_account &&
992 !tp_strdiff (this_chat_id, window->selected_chat_id) &&
993 this_is_chatroom == window->selected_is_chatroom) {
994 gtk_tree_selection_select_iter (selection, &iter);
995 path = gtk_tree_model_get_path (model, &iter);
996 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
997 gtk_tree_path_free (path);
998 g_object_unref (this_account);
999 g_free (this_chat_id);
1003 g_object_unref (this_account);
1004 g_free (this_chat_id);
1007 tp_clear_object (&window->selected_account);
1008 tp_clear_pointer (&window->selected_chat_id, g_free);
1012 log_window_chats_get_selected (EmpathyLogWindow *window,
1013 TpAccount **account,
1015 gboolean *is_chatroom)
1018 GtkTreeModel *model;
1019 GtkTreeSelection *selection;
1022 TpAccount *acc = NULL;
1023 gboolean room = FALSE;
1025 view = GTK_TREE_VIEW (window->treeview_chats);
1026 model = gtk_tree_view_get_model (view);
1027 selection = gtk_tree_view_get_selection (view);
1029 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
1033 gtk_tree_model_get (model, &iter,
1034 COL_CHAT_ACCOUNT, &acc,
1036 COL_CHAT_IS_CHATROOM, &room,
1039 if (chat_id != NULL) {
1044 if (account != NULL) {
1047 g_object_unref (acc);
1050 *is_chatroom = room;
1057 log_window_got_messages_for_date_cb (GObject *manager,
1058 GAsyncResult *result,
1061 EmpathyLogWindow *window = user_data;
1064 GError *error = NULL;
1066 if (log_window == NULL)
1069 if (!tpl_log_manager_get_messages_for_date_finish (TPL_LOG_MANAGER (manager),
1070 result, &messages, &error)) {
1071 DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
1073 empathy_chat_view_append_event (window->chatview_find,
1074 "Unable to retrieve messages for the selected date");
1075 g_error_free (error);
1079 for (l = messages; l; l = l->next) {
1080 EmpathyMessage *message = empathy_message_from_tpl_log_entry (l->data);
1081 g_object_unref (l->data);
1082 empathy_chat_view_append_message (window->chatview_chats,
1084 g_object_unref (message);
1086 g_list_free (messages);
1088 /* Turn back on scrolling */
1089 empathy_chat_view_scroll (window->chatview_find, TRUE);
1091 /* Give the search entry main focus */
1092 gtk_widget_grab_focus (window->entry_chats);
1097 log_window_get_messages_for_date (EmpathyLogWindow *window,
1102 gboolean is_chatroom;
1104 if (!log_window_chats_get_selected (window, &account,
1105 &chat_id, &is_chatroom)) {
1109 /* Clear all current messages shown in the textview */
1110 empathy_chat_view_clear (window->chatview_chats);
1112 /* Turn off scrolling temporarily */
1113 empathy_chat_view_scroll (window->chatview_find, FALSE);
1116 tpl_log_manager_get_messages_for_date_async (window->log_manager,
1120 log_window_got_messages_for_date_cb,
1124 g_object_unref (account);
1128 log_manager_got_dates_cb (GObject *manager,
1129 GAsyncResult *result,
1132 EmpathyLogWindow *window = user_data;
1135 guint year_selected;
1136 guint month_selected;
1137 gboolean day_selected = FALSE;
1139 GError *error = NULL;
1141 if (log_window == NULL)
1144 if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
1145 result, &dates, &error)) {
1146 DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
1148 empathy_chat_view_append_event (window->chatview_find,
1149 "Unable to retrieve messages' dates");
1153 for (l = dates; l; l = l->next) {
1156 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1167 if (g_date_get_year (d) != year_selected ||
1168 g_date_get_month (d) != month_selected) {
1172 DEBUG ("Marking date: %04u-%02u-%02u", g_date_get_year (d),
1173 g_date_get_month (d), g_date_get_day (d));
1175 gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats),
1176 g_date_get_day (d));
1182 day_selected = TRUE;
1184 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats),
1185 g_date_get_day (d));
1188 if (!day_selected) {
1189 /* Unselect the day in the calendar */
1190 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), 0);
1193 g_signal_handlers_unblock_by_func (window->calendar_chats,
1194 log_window_calendar_chats_day_selected_cb,
1198 /* Show messages of the most recent date */
1199 log_window_get_messages_for_date (window, date);
1202 g_list_foreach (dates, (GFunc) g_free, NULL);
1203 g_list_free (dates);
1208 log_window_chats_get_messages (EmpathyLogWindow *window,
1213 gboolean is_chatroom;
1214 guint year_selected;
1215 guint month_selected;
1219 if (!log_window_chats_get_selected (window, &account,
1220 &chat_id, &is_chatroom)) {
1224 g_signal_handlers_block_by_func (window->calendar_chats,
1225 log_window_calendar_chats_day_selected_cb,
1228 /* Either use the supplied date or get the last */
1230 /* Get a list of dates and show them on the calendar */
1231 tpl_log_manager_get_dates_async (window->log_manager,
1234 log_manager_got_dates_cb, (gpointer) window);
1235 /* signal unblocked at the end of the CB flow */
1237 day = g_date_get_day (date);
1238 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1245 if (g_date_get_year (date) != year_selected &&
1246 g_date_get_month (date) != month_selected) {
1250 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
1252 g_signal_handlers_unblock_by_func (window->calendar_chats,
1253 log_window_calendar_chats_day_selected_cb,
1258 /* Show messages of the selected date */
1259 log_window_get_messages_for_date (window, date);
1262 g_object_unref (account);
1267 log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
1268 EmpathyLogWindow *window)
1275 gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
1277 /* No date selected */
1280 /* We need this hear because it appears that the months start from 0 */
1283 date = g_date_new_dmy (day, month, year);
1285 DEBUG ("Currently selected date is: %04u-%02u-%02u", year, month, day);
1287 log_window_chats_get_messages (window, date);
1293 log_window_updating_calendar_month_cb (GObject *manager,
1294 GAsyncResult *result, gpointer user_data)
1296 EmpathyLogWindow *window = user_data;
1299 guint year_selected;
1300 guint month_selected;
1301 GError *error = NULL;
1303 if (log_window == NULL)
1306 if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
1307 result, &dates, &error)) {
1308 DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
1310 empathy_chat_view_append_event (window->chatview_find,
1311 "Unable to retrieve messages' dates");
1312 g_error_free (error);
1316 gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
1317 g_object_get (window->calendar_chats,
1318 "month", &month_selected,
1319 "year", &year_selected,
1322 /* We need this here because it appears that the months start from 0 */
1325 for (l = dates; l; l = l->next) {
1326 GDate *date = l->data;
1328 if (g_date_get_year (date) == year_selected &&
1329 g_date_get_month (date) == month_selected) {
1330 DEBUG ("Marking date: %04u-%02u-%02u", g_date_get_year (date),
1331 g_date_get_month (date), g_date_get_day (date));
1332 gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), g_date_get_day (date));
1336 g_list_foreach (dates, (GFunc) g_free, NULL);
1337 g_list_free (dates);
1339 DEBUG ("Currently showing month %d and year %d", month_selected,
1344 log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
1345 EmpathyLogWindow *window)
1349 gboolean is_chatroom;
1351 gtk_calendar_clear_marks (GTK_CALENDAR (calendar));
1353 if (!log_window_chats_get_selected (window, &account,
1354 &chat_id, &is_chatroom)) {
1355 DEBUG ("No chat selected to get dates for...");
1359 /* Get the log object for this contact */
1360 tpl_log_manager_get_dates_async (window->log_manager, account,
1361 chat_id, is_chatroom,
1362 log_window_updating_calendar_month_cb,
1365 g_object_unref (account);
1370 log_window_entry_chats_changed_cb (GtkWidget *entry,
1371 EmpathyLogWindow *window)
1375 str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1376 empathy_chat_view_highlight (window->chatview_chats, str, FALSE);
1379 empathy_chat_view_find_next (window->chatview_chats,
1387 log_window_entry_chats_activate_cb (GtkWidget *entry,
1388 EmpathyLogWindow *window)
1392 str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1395 empathy_chat_view_find_next (window->chatview_chats,