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 static void log_window_chats_get_messages (EmpathyLogWindow *window,
112 GDate *date_to_show);
113 static void log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
114 EmpathyLogWindow *window);
115 static void log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
116 EmpathyLogWindow *window);
117 static void log_window_entry_chats_changed_cb (GtkWidget *entry,
118 EmpathyLogWindow *window);
119 static void log_window_entry_chats_activate_cb (GtkWidget *entry,
120 EmpathyLogWindow *window);
123 COL_FIND_ACCOUNT_ICON,
124 COL_FIND_ACCOUNT_NAME,
129 COL_FIND_DATE_READABLE,
141 static EmpathyLogWindow *log_window = NULL;
144 account_manager_prepared_cb (GObject *source_object,
145 GAsyncResult *result,
148 TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
149 EmpathyLogWindow *window = user_data;
152 GError *error = NULL;
154 if (log_window == NULL)
157 if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
158 DEBUG ("Failed to prepare account manager: %s", error->message);
159 g_error_free (error);
163 accounts = tp_account_manager_get_valid_accounts (account_manager);
164 account_num = g_list_length (accounts);
165 g_list_free (accounts);
167 if (account_num > 1) {
168 gtk_widget_show (window->vbox_chats);
169 gtk_widget_show (window->account_chooser_chats);
171 gtk_widget_hide (window->vbox_chats);
172 gtk_widget_hide (window->account_chooser_chats);
177 account_chooser_ready_cb (EmpathyAccountChooser *chooser,
178 EmpathyLogWindow *window)
180 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
182 /* We'll display the account once the model has been populate with the chats
183 * of this account. */
184 empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (
185 window->account_chooser_chats), window->selected_account);
189 select_account_once_ready (EmpathyLogWindow *self,
191 const gchar *chat_id,
192 gboolean is_chatroom)
194 EmpathyAccountChooser *account_chooser = EMPATHY_ACCOUNT_CHOOSER (self->account_chooser_chats);
196 tp_clear_object (&self->selected_account);
197 self->selected_account = g_object_ref (account);
199 g_free (self->selected_chat_id);
200 self->selected_chat_id = g_strdup (chat_id);
202 self->selected_is_chatroom = is_chatroom;
204 if (empathy_account_chooser_is_ready (account_chooser))
205 account_chooser_ready_cb (account_chooser, self);
207 /* Chat will be selected once the account chooser is ready */
208 g_signal_connect (account_chooser, "ready",
209 G_CALLBACK (account_chooser_ready_cb), self);
213 empathy_log_window_show (TpAccount *account,
214 const gchar *chat_id,
215 gboolean is_chatroom,
218 TpAccountManager *account_manager;
221 EmpathyLogWindow *window;
222 EmpathyThemeManager *theme_mgr;
224 if (log_window != NULL) {
225 gtk_window_present (GTK_WINDOW (log_window->window));
227 if (account != NULL && chat_id != NULL) {
228 gtk_notebook_set_current_page (GTK_NOTEBOOK (log_window->notebook), 1);
229 select_account_once_ready (log_window, account, chat_id, is_chatroom);
232 return log_window->window;
235 log_window = g_new0 (EmpathyLogWindow, 1);
236 log_window->log_manager = tpl_log_manager_dup_singleton ();
240 filename = empathy_file_lookup ("empathy-log-window.ui",
242 gui = empathy_builder_get_file (filename,
243 "log_window", &window->window,
244 "notebook", &window->notebook,
245 "entry_find", &window->entry_find,
246 "button_find", &window->button_find,
247 "treeview_find", &window->treeview_find,
248 "scrolledwindow_find", &window->scrolledwindow_find,
249 "button_previous", &window->button_previous,
250 "button_next", &window->button_next,
251 "entry_chats", &window->entry_chats,
252 "calendar_chats", &window->calendar_chats,
253 "vbox_chats", &window->vbox_chats,
254 "treeview_chats", &window->treeview_chats,
255 "scrolledwindow_chats", &window->scrolledwindow_chats,
259 empathy_builder_connect (gui, window,
260 "log_window", "destroy", log_window_destroy_cb,
261 "entry_find", "changed", log_window_entry_find_changed_cb,
262 "entry_find", "activate", log_window_entry_find_activate_cb,
263 "button_previous", "clicked", log_window_button_previous_clicked_cb,
264 "button_next", "clicked", log_window_button_next_clicked_cb,
265 "button_close", "clicked", log_window_button_close_clicked_cb,
266 "button_close2", "clicked", log_window_button_close_clicked_cb,
267 "button_find", "clicked", log_window_button_find_clicked_cb,
268 "entry_chats", "changed", log_window_entry_chats_changed_cb,
269 "entry_chats", "activate", log_window_entry_chats_activate_cb,
272 g_object_unref (gui);
274 g_object_add_weak_pointer (G_OBJECT (window->window),
275 (gpointer) &log_window);
277 /* We set this up here so we can block it when needed. */
278 g_signal_connect (window->calendar_chats, "day-selected",
279 G_CALLBACK (log_window_calendar_chats_day_selected_cb),
281 g_signal_connect (window->calendar_chats, "month-changed",
282 G_CALLBACK (log_window_calendar_chats_month_changed_cb),
285 /* Configure Search EmpathyChatView */
286 theme_mgr = empathy_theme_manager_dup_singleton ();
287 window->chatview_find = empathy_theme_manager_create_view (theme_mgr);
288 gtk_container_add (GTK_CONTAINER (window->scrolledwindow_find),
289 GTK_WIDGET (window->chatview_find));
290 gtk_widget_show (GTK_WIDGET (window->chatview_find));
292 /* Configure Contacts EmpathyChatView */
293 window->chatview_chats = empathy_theme_manager_create_view (theme_mgr);
294 gtk_container_add (GTK_CONTAINER (window->scrolledwindow_chats),
295 GTK_WIDGET (window->chatview_chats));
296 gtk_widget_show (GTK_WIDGET (window->chatview_chats));
297 g_object_unref (theme_mgr);
299 /* Account chooser for chats */
300 window->account_chooser_chats = empathy_account_chooser_new ();
302 gtk_box_pack_start (GTK_BOX (window->vbox_chats),
303 window->account_chooser_chats,
306 g_signal_connect (window->account_chooser_chats, "changed",
307 G_CALLBACK (log_window_chats_accounts_changed_cb),
311 account_manager = tp_account_manager_dup ();
312 tp_account_manager_prepare_async (account_manager, NULL,
313 account_manager_prepared_cb, window);
314 g_object_unref (account_manager);
317 log_window_find_setup (window);
320 log_window_chats_setup (window);
321 log_window_chats_populate (window);
323 if (account != NULL && chat_id != NULL)
324 select_account_once_ready (window, account, chat_id, is_chatroom);
326 if (parent != NULL) {
327 gtk_window_set_transient_for (GTK_WINDOW (window->window),
328 GTK_WINDOW (parent));
331 gtk_widget_show (window->window);
333 return window->window;
337 log_window_destroy_cb (GtkWidget *widget,
338 EmpathyLogWindow *window)
340 g_free (window->last_find);
341 g_object_unref (window->log_manager);
342 tp_clear_object (&window->selected_account);
343 g_free (window->selected_chat_id);
352 log_window_entry_find_changed_cb (GtkWidget *entry,
353 EmpathyLogWindow *window)
356 gboolean is_sensitive = TRUE;
358 str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
360 is_sensitive &= !EMP_STR_EMPTY (str);
362 !window->last_find ||
363 (window->last_find && tp_strdiff (window->last_find, str));
365 gtk_widget_set_sensitive (window->button_find, is_sensitive);
369 got_events_for_date_cb (GObject *manager,
370 GAsyncResult *result,
373 EmpathyLogWindow *window = user_data;
376 gboolean can_do_previous;
377 gboolean can_do_next;
378 GError *error = NULL;
380 if (log_window == NULL)
383 if (!tpl_log_manager_get_events_for_date_finish (TPL_LOG_MANAGER (manager),
384 result, &messages, &error)) {
385 DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
387 empathy_chat_view_append_event (window->chatview_find,
388 "Unable to retrieve messages for the selected date");
389 g_error_free (error);
393 for (l = messages; l; l = l->next) {
394 EmpathyMessage *message;
396 g_assert (TPL_IS_EVENT (l->data));
398 message = empathy_message_from_tpl_log_event (l->data);
399 g_object_unref (l->data);
400 empathy_chat_view_append_message (window->chatview_find, message);
401 g_object_unref (message);
403 g_list_free (messages);
405 /* Scroll to the most recent messages */
406 empathy_chat_view_scroll (window->chatview_find, TRUE);
408 /* Highlight and find messages */
409 empathy_chat_view_highlight (window->chatview_find,
412 empathy_chat_view_find_next (window->chatview_find,
416 empathy_chat_view_find_abilities (window->chatview_find,
421 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
422 gtk_widget_set_sensitive (window->button_next, can_do_next);
423 gtk_widget_set_sensitive (window->button_find, FALSE);
427 gdate_from_str (const gchar *str)
430 guint day, month, year;
432 if (sscanf (str, "%u", &u) != 1)
436 month = ((u / 100) % 100);
439 if (!g_date_valid_dmy (day, month, year))
442 return g_date_new_dmy (day, month, year);
446 log_window_find_changed_cb (GtkTreeSelection *selection,
447 EmpathyLogWindow *window)
457 /* Get selected information */
458 view = GTK_TREE_VIEW (window->treeview_find);
459 model = gtk_tree_view_get_model (view);
461 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
462 gtk_widget_set_sensitive (window->button_previous, FALSE);
463 gtk_widget_set_sensitive (window->button_next, FALSE);
465 empathy_chat_view_clear (window->chatview_find);
470 gtk_widget_set_sensitive (window->button_previous, TRUE);
471 gtk_widget_set_sensitive (window->button_next, TRUE);
473 gtk_tree_model_get (model, &iter,
474 COL_FIND_ACCOUNT, &account,
475 COL_FIND_TARGET, &target,
476 COL_FIND_DATE, &date,
479 /* Clear all current messages shown in the textview */
480 empathy_chat_view_clear (window->chatview_find);
482 /* Turn off scrolling temporarily */
483 empathy_chat_view_scroll (window->chatview_find, FALSE);
486 gdate = gdate_from_str (date);
489 tpl_log_manager_get_events_for_date_async (window->log_manager,
494 got_events_for_date_cb,
500 g_object_unref (account);
501 g_object_unref (target);
507 log_manager_searched_new_cb (GObject *manager,
508 GAsyncResult *result,
514 GtkListStore *store = user_data;
515 GError *error = NULL;
517 if (log_window == NULL)
520 if (!tpl_log_manager_search_finish (TPL_LOG_MANAGER (manager), result,
522 DEBUG ("%s. Aborting", error->message);
523 g_error_free (error);
527 for (l = hits; l; l = l->next) {
528 TplLogSearchHit *hit;
529 const gchar *account_name;
530 const gchar *account_icon;
531 gchar date_readable[255];
536 /* Protect against invalid data (corrupt or old log files. */
537 if (hit->account == NULL || hit->target == NULL) {
541 g_date_strftime (date_readable, sizeof (date_readable),
542 EMPATHY_DATE_FORMAT_DISPLAY_SHORT, hit->date);
544 g_date_strftime (tmp, sizeof (tmp),
545 "%Y%m%d", hit->date);
547 account_name = tp_account_get_display_name (hit->account);
548 account_icon = tp_account_get_icon_name (hit->account);
550 gtk_list_store_append (store, &iter);
551 gtk_list_store_set (store, &iter,
552 COL_FIND_ACCOUNT_ICON, account_icon,
553 COL_FIND_ACCOUNT_NAME, account_name,
554 COL_FIND_ACCOUNT, hit->account,
555 COL_FIND_CHAT_NAME, tpl_entity_get_alias (hit->target),
556 COL_FIND_TARGET, hit->target,
558 COL_FIND_DATE_READABLE, date_readable,
561 /* FIXME: Update COL_FIND_CHAT_NAME */
562 if (tpl_entity_get_entity_type (hit->target) == TPL_ENTITY_ROOM) {
568 tpl_log_manager_search_free (hits);
573 log_window_find_populate (EmpathyLogWindow *window,
574 const gchar *search_criteria)
580 view = GTK_TREE_VIEW (window->treeview_find);
581 model = gtk_tree_view_get_model (view);
582 store = GTK_LIST_STORE (model);
584 empathy_chat_view_clear (window->chatview_find);
586 gtk_list_store_clear (store);
588 if (EMP_STR_EMPTY (search_criteria)) {
589 /* Just clear the search. */
593 tpl_log_manager_search_async (window->log_manager,
594 search_criteria, TPL_EVENT_MASK_TEXT,
595 log_manager_searched_new_cb, (gpointer) store);
599 log_window_find_setup (EmpathyLogWindow *window)
603 GtkTreeSelection *selection;
604 GtkTreeSortable *sortable;
605 GtkTreeViewColumn *column;
607 GtkCellRenderer *cell;
610 view = GTK_TREE_VIEW (window->treeview_find);
611 selection = gtk_tree_view_get_selection (view);
614 store = gtk_list_store_new (COL_FIND_COUNT,
615 G_TYPE_STRING, /* account icon name */
616 G_TYPE_STRING, /* account name */
617 TP_TYPE_ACCOUNT, /* account */
618 G_TYPE_STRING, /* chat name */
619 TPL_TYPE_ENTITY, /* target */
620 G_TYPE_STRING, /* date */
621 G_TYPE_STRING); /* date_readable */
623 model = GTK_TREE_MODEL (store);
624 sortable = GTK_TREE_SORTABLE (store);
626 gtk_tree_view_set_model (view, model);
629 column = gtk_tree_view_column_new ();
631 cell = gtk_cell_renderer_pixbuf_new ();
632 gtk_tree_view_column_pack_start (column, cell, FALSE);
633 gtk_tree_view_column_add_attribute (column, cell,
635 COL_FIND_ACCOUNT_ICON);
637 cell = gtk_cell_renderer_text_new ();
638 gtk_tree_view_column_pack_start (column, cell, TRUE);
639 gtk_tree_view_column_add_attribute (column, cell,
641 COL_FIND_ACCOUNT_NAME);
643 gtk_tree_view_column_set_title (column, _("Account"));
644 gtk_tree_view_append_column (view, column);
646 gtk_tree_view_column_set_resizable (column, TRUE);
647 gtk_tree_view_column_set_clickable (column, TRUE);
649 cell = gtk_cell_renderer_text_new ();
650 offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Conversation"),
651 cell, "text", COL_FIND_CHAT_NAME,
654 column = gtk_tree_view_get_column (view, offset - 1);
655 gtk_tree_view_column_set_sort_column_id (column, COL_FIND_CHAT_NAME);
656 gtk_tree_view_column_set_resizable (column, TRUE);
657 gtk_tree_view_column_set_clickable (column, TRUE);
659 cell = gtk_cell_renderer_text_new ();
660 offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Date"),
661 cell, "text", COL_FIND_DATE_READABLE,
664 column = gtk_tree_view_get_column (view, offset - 1);
665 gtk_tree_view_column_set_sort_column_id (column, COL_FIND_DATE);
666 gtk_tree_view_column_set_resizable (column, TRUE);
667 gtk_tree_view_column_set_clickable (column, TRUE);
669 /* Set up treeview properties */
670 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
671 gtk_tree_sortable_set_sort_column_id (sortable,
676 g_signal_connect (selection, "changed",
677 G_CALLBACK (log_window_find_changed_cb),
680 g_object_unref (store);
684 start_find_search (EmpathyLogWindow *window)
688 str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
690 /* Don't find the same crap again */
691 if (window->last_find && !tp_strdiff (window->last_find, str)) {
695 g_free (window->last_find);
696 window->last_find = g_strdup (str);
698 log_window_find_populate (window, str);
702 log_window_button_find_clicked_cb (GtkWidget *widget,
703 EmpathyLogWindow *window)
705 start_find_search (window);
709 log_window_entry_find_activate_cb (GtkWidget *entry,
710 EmpathyLogWindow *self)
712 start_find_search (self);
716 log_window_button_next_clicked_cb (GtkWidget *widget,
717 EmpathyLogWindow *window)
719 if (window->last_find) {
720 gboolean can_do_previous;
721 gboolean can_do_next;
723 empathy_chat_view_find_next (window->chatview_find,
727 empathy_chat_view_find_abilities (window->chatview_find,
732 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
733 gtk_widget_set_sensitive (window->button_next, can_do_next);
738 log_window_button_previous_clicked_cb (GtkWidget *widget,
739 EmpathyLogWindow *window)
741 if (window->last_find) {
742 gboolean can_do_previous;
743 gboolean can_do_next;
745 empathy_chat_view_find_previous (window->chatview_find,
749 empathy_chat_view_find_abilities (window->chatview_find,
754 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
755 gtk_widget_set_sensitive (window->button_next, can_do_next);
760 log_window_button_close_clicked_cb (GtkWidget *widget,
761 EmpathyLogWindow *window)
763 gtk_widget_destroy (window->window);
771 log_window_chats_changed_cb (GtkTreeSelection *selection,
772 EmpathyLogWindow *window)
774 /* Use last date by default */
775 gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
777 log_window_chats_get_messages (window, NULL);
781 log_manager_got_entities_cb (GObject *manager,
782 GAsyncResult *result,
785 EmpathyLogWindow *window = user_data;
786 EmpathyAccountChooser *account_chooser;
792 GtkTreeSelection *selection;
795 GError *error = NULL;
796 gboolean select_account = FALSE;
798 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
799 account = empathy_account_chooser_get_account (account_chooser);
801 view = GTK_TREE_VIEW (window->treeview_chats);
803 if (log_window == NULL)
806 if (!tpl_log_manager_get_entities_finish (TPL_LOG_MANAGER (manager),
807 result, &entities, &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 = entities; l; l = l->next) {
821 entity = TPL_ENTITY (l->data);
823 gtk_list_store_append (store, &iter);
824 gtk_list_store_set (store, &iter,
825 COL_CHAT_ICON, "empathy-available", /* FIXME */
826 COL_CHAT_NAME, tpl_entity_get_alias (entity),
827 COL_CHAT_ACCOUNT, account,
828 COL_CHAT_TARGET, entity,
831 if (window->selected_account != NULL &&
832 !tp_strdiff (tp_proxy_get_object_path (account),
833 tp_proxy_get_object_path (window->selected_account)))
834 select_account = TRUE;
836 /* FIXME: Update COL_CHAT_ICON/NAME */
837 if (tpl_entity_get_entity_type (entity) == TPL_ENTITY_ROOM) {
841 g_list_free_full (entities, g_object_unref);
843 /* Unblock signals */
844 g_signal_handlers_unblock_by_func (selection,
845 log_window_chats_changed_cb,
848 /* We display the selected account if we populate the model with chats from
851 log_window_chats_set_selected (window);
855 log_window_chats_populate (EmpathyLogWindow *window)
857 EmpathyAccountChooser *account_chooser;
862 GtkTreeSelection *selection;
865 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
866 account = empathy_account_chooser_dup_account (account_chooser);
868 view = GTK_TREE_VIEW (window->treeview_chats);
869 model = gtk_tree_view_get_model (view);
870 selection = gtk_tree_view_get_selection (view);
871 store = GTK_LIST_STORE (model);
873 if (account == NULL) {
874 gtk_list_store_clear (store);
878 /* Block signals to stop the logs being retrieved prematurely */
879 g_signal_handlers_block_by_func (selection,
880 log_window_chats_changed_cb,
883 gtk_list_store_clear (store);
885 tpl_log_manager_get_entities_async (window->log_manager, account,
886 log_manager_got_entities_cb, (gpointer) window);
890 log_window_chats_setup (EmpathyLogWindow *window)
894 GtkTreeSelection *selection;
895 GtkTreeSortable *sortable;
896 GtkTreeViewColumn *column;
898 GtkCellRenderer *cell;
900 view = GTK_TREE_VIEW (window->treeview_chats);
901 selection = gtk_tree_view_get_selection (view);
904 store = gtk_list_store_new (COL_CHAT_COUNT,
905 G_TYPE_STRING, /* icon */
906 G_TYPE_STRING, /* name */
907 TP_TYPE_ACCOUNT, /* account */
908 TPL_TYPE_ENTITY); /* target */
910 model = GTK_TREE_MODEL (store);
911 sortable = GTK_TREE_SORTABLE (store);
913 gtk_tree_view_set_model (view, model);
916 column = gtk_tree_view_column_new ();
918 cell = gtk_cell_renderer_pixbuf_new ();
919 gtk_tree_view_column_pack_start (column, cell, FALSE);
920 gtk_tree_view_column_add_attribute (column, cell,
924 cell = gtk_cell_renderer_text_new ();
925 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
926 gtk_tree_view_column_pack_start (column, cell, TRUE);
927 gtk_tree_view_column_add_attribute (column, cell,
931 gtk_tree_view_append_column (view, column);
933 /* set up treeview properties */
934 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
935 gtk_tree_sortable_set_sort_column_id (sortable,
940 g_signal_connect (selection, "changed",
941 G_CALLBACK (log_window_chats_changed_cb),
944 g_object_unref (store);
948 log_window_chats_accounts_changed_cb (GtkWidget *combobox,
949 EmpathyLogWindow *window)
951 /* Clear all current messages shown in the textview */
952 empathy_chat_view_clear (window->chatview_chats);
954 log_window_chats_populate (window);
958 log_window_chats_set_selected (EmpathyLogWindow *window)
962 GtkTreeSelection *selection;
967 view = GTK_TREE_VIEW (window->treeview_chats);
968 model = gtk_tree_view_get_model (view);
969 selection = gtk_tree_view_get_selection (view);
971 if (!gtk_tree_model_get_iter_first (model, &iter)) {
975 for (ok = TRUE; ok; ok = gtk_tree_model_iter_next (model, &iter)) {
976 TpAccount *this_account;
977 TplEntity *this_target;
978 const gchar *this_chat_id;
979 gboolean this_is_chatroom;
981 gtk_tree_model_get (model, &iter,
982 COL_CHAT_ACCOUNT, &this_account,
983 COL_CHAT_TARGET, &this_target,
986 this_chat_id = tpl_entity_get_identifier (this_target);
987 this_is_chatroom = tpl_entity_get_entity_type (this_target) == TPL_ENTITY_ROOM;
989 if (this_account == window->selected_account &&
990 !tp_strdiff (this_chat_id, window->selected_chat_id) &&
991 this_is_chatroom == window->selected_is_chatroom) {
992 gtk_tree_selection_select_iter (selection, &iter);
993 path = gtk_tree_model_get_path (model, &iter);
994 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
995 gtk_tree_path_free (path);
996 g_object_unref (this_account);
997 g_object_unref (this_target);
1001 g_object_unref (this_account);
1002 g_object_unref (this_target);
1005 tp_clear_object (&window->selected_account);
1006 tp_clear_pointer (&window->selected_chat_id, g_free);
1010 log_window_chats_get_selected (EmpathyLogWindow *window,
1011 TpAccount **account,
1015 GtkTreeModel *model;
1016 GtkTreeSelection *selection;
1019 TpAccount *acc = NULL;
1021 view = GTK_TREE_VIEW (window->treeview_chats);
1022 model = gtk_tree_view_get_model (view);
1023 selection = gtk_tree_view_get_selection (view);
1025 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
1029 gtk_tree_model_get (model, &iter,
1030 COL_CHAT_ACCOUNT, &acc,
1031 COL_CHAT_TARGET, &targ,
1034 if (account != NULL) {
1035 *account = g_object_ref (acc);
1038 if (target != NULL) {
1039 *target = g_object_ref (targ);
1042 g_object_unref (acc);
1043 g_object_unref (targ);
1049 log_window_got_messages_for_date_cb (GObject *manager,
1050 GAsyncResult *result,
1053 EmpathyLogWindow *window = user_data;
1056 GError *error = NULL;
1058 if (log_window == NULL)
1061 if (!tpl_log_manager_get_events_for_date_finish (TPL_LOG_MANAGER (manager),
1062 result, &events, &error)) {
1063 DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
1065 empathy_chat_view_append_event (window->chatview_find,
1066 "Unable to retrieve messages for the selected date");
1067 g_error_free (error);
1071 for (l = events; l; l = l->next) {
1072 EmpathyMessage *message = empathy_message_from_tpl_log_event (l->data);
1073 g_object_unref (l->data);
1074 empathy_chat_view_append_message (window->chatview_chats,
1076 g_object_unref (message);
1078 g_list_free (events);
1080 /* Turn back on scrolling */
1081 empathy_chat_view_scroll (window->chatview_find, TRUE);
1083 /* Give the search entry main focus */
1084 gtk_widget_grab_focus (window->entry_chats);
1089 log_window_get_messages_for_date (EmpathyLogWindow *window,
1095 if (!log_window_chats_get_selected (window, &account, &target)) {
1099 /* Clear all current messages shown in the textview */
1100 empathy_chat_view_clear (window->chatview_chats);
1102 /* Turn off scrolling temporarily */
1103 empathy_chat_view_scroll (window->chatview_find, FALSE);
1106 tpl_log_manager_get_events_for_date_async (window->log_manager,
1107 account, target, TPL_EVENT_MASK_TEXT,
1109 log_window_got_messages_for_date_cb,
1112 g_object_unref (account);
1113 g_object_unref (target);
1117 log_manager_got_dates_cb (GObject *manager,
1118 GAsyncResult *result,
1121 EmpathyLogWindow *window = user_data;
1124 guint year_selected;
1125 guint month_selected;
1126 gboolean day_selected = FALSE;
1128 GError *error = NULL;
1130 if (log_window == NULL)
1133 if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
1134 result, &dates, &error)) {
1135 DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
1137 empathy_chat_view_append_event (window->chatview_find,
1138 "Unable to retrieve messages' dates");
1142 for (l = dates; l; l = l->next) {
1145 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1156 if (g_date_get_year (d) != year_selected ||
1157 g_date_get_month (d) != month_selected) {
1161 DEBUG ("Marking date: %04u-%02u-%02u", g_date_get_year (d),
1162 g_date_get_month (d), g_date_get_day (d));
1164 gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats),
1165 g_date_get_day (d));
1171 day_selected = TRUE;
1173 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats),
1174 g_date_get_day (d));
1177 if (!day_selected) {
1178 /* Unselect the day in the calendar */
1179 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), 0);
1182 g_signal_handlers_unblock_by_func (window->calendar_chats,
1183 log_window_calendar_chats_day_selected_cb,
1187 /* Show messages of the most recent date */
1188 log_window_get_messages_for_date (window, date);
1191 g_list_foreach (dates, (GFunc) g_free, NULL);
1192 g_list_free (dates);
1197 log_window_chats_get_messages (EmpathyLogWindow *window,
1202 guint year_selected;
1203 guint month_selected;
1207 if (!log_window_chats_get_selected (window, &account, &target)) {
1211 g_signal_handlers_block_by_func (window->calendar_chats,
1212 log_window_calendar_chats_day_selected_cb,
1215 /* Either use the supplied date or get the last */
1217 /* Get a list of dates and show them on the calendar */
1218 tpl_log_manager_get_dates_async (window->log_manager,
1219 account, target, TPL_EVENT_MASK_TEXT,
1220 log_manager_got_dates_cb, (gpointer) window);
1221 /* signal unblocked at the end of the CB flow */
1223 day = g_date_get_day (date);
1224 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1231 if (g_date_get_year (date) != year_selected &&
1232 g_date_get_month (date) != month_selected) {
1236 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
1238 g_signal_handlers_unblock_by_func (window->calendar_chats,
1239 log_window_calendar_chats_day_selected_cb,
1244 /* Show messages of the selected date */
1245 log_window_get_messages_for_date (window, date);
1248 g_object_unref (account);
1249 g_object_unref (target);
1253 log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
1254 EmpathyLogWindow *window)
1261 gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
1263 /* No date selected */
1266 /* We need this hear because it appears that the months start from 0 */
1269 date = g_date_new_dmy (day, month, year);
1271 DEBUG ("Currently selected date is: %04u-%02u-%02u", year, month, day);
1273 log_window_chats_get_messages (window, date);
1279 log_window_updating_calendar_month_cb (GObject *manager,
1280 GAsyncResult *result, gpointer user_data)
1282 EmpathyLogWindow *window = user_data;
1285 guint year_selected;
1286 guint month_selected;
1287 GError *error = NULL;
1289 if (log_window == NULL)
1292 if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
1293 result, &dates, &error)) {
1294 DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
1296 empathy_chat_view_append_event (window->chatview_find,
1297 "Unable to retrieve messages' dates");
1298 g_error_free (error);
1302 gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
1303 g_object_get (window->calendar_chats,
1304 "month", &month_selected,
1305 "year", &year_selected,
1308 /* We need this here because it appears that the months start from 0 */
1311 for (l = dates; l; l = l->next) {
1312 GDate *date = l->data;
1314 if (g_date_get_year (date) == year_selected &&
1315 g_date_get_month (date) == month_selected) {
1316 DEBUG ("Marking date: %04u-%02u-%02u", g_date_get_year (date),
1317 g_date_get_month (date), g_date_get_day (date));
1318 gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), g_date_get_day (date));
1322 g_list_foreach (dates, (GFunc) g_free, NULL);
1323 g_list_free (dates);
1325 DEBUG ("Currently showing month %d and year %d", month_selected,
1330 log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
1331 EmpathyLogWindow *window)
1336 gtk_calendar_clear_marks (GTK_CALENDAR (calendar));
1338 if (!log_window_chats_get_selected (window, &account, &target)) {
1339 DEBUG ("No chat selected to get dates for...");
1343 /* Get the log object for this contact */
1344 tpl_log_manager_get_dates_async (window->log_manager, account, target,
1345 TPL_EVENT_MASK_TEXT,
1346 log_window_updating_calendar_month_cb,
1349 g_object_unref (account);
1350 g_object_unref (target);
1354 log_window_entry_chats_changed_cb (GtkWidget *entry,
1355 EmpathyLogWindow *window)
1359 str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1360 empathy_chat_view_highlight (window->chatview_chats, str, FALSE);
1363 empathy_chat_view_find_next (window->chatview_chats,
1371 log_window_entry_chats_activate_cb (GtkWidget *entry,
1372 EmpathyLogWindow *window)
1376 str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1379 empathy_chat_view_find_next (window->chatview_chats,