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_chats_changed_cb (GtkTreeSelection *selection,
100 EmpathyLogWindow *window);
101 static void log_window_chats_populate (EmpathyLogWindow *window);
102 static void log_window_chats_setup (EmpathyLogWindow *window);
103 static void log_window_chats_accounts_changed_cb (GtkWidget *combobox,
104 EmpathyLogWindow *window);
105 static void log_window_chats_set_selected (EmpathyLogWindow *window,
107 const gchar *chat_id,
108 gboolean is_chatroom);
109 static gboolean log_window_chats_get_selected (EmpathyLogWindow *window,
112 gboolean *is_chatroom);
113 static void log_window_chats_get_messages (EmpathyLogWindow *window,
114 GDate *date_to_show);
115 static void log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
116 EmpathyLogWindow *window);
117 static void log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
118 EmpathyLogWindow *window);
119 static void log_window_entry_chats_changed_cb (GtkWidget *entry,
120 EmpathyLogWindow *window);
121 static void log_window_entry_chats_activate_cb (GtkWidget *entry,
122 EmpathyLogWindow *window);
125 COL_FIND_ACCOUNT_ICON,
126 COL_FIND_ACCOUNT_NAME,
130 COL_FIND_IS_CHATROOM,
132 COL_FIND_DATE_READABLE,
141 COL_CHAT_IS_CHATROOM,
145 static EmpathyLogWindow *log_window = NULL;
148 account_manager_prepared_cb (GObject *source_object,
149 GAsyncResult *result,
152 TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
153 EmpathyLogWindow *window = user_data;
156 GError *error = NULL;
158 if (log_window == NULL)
161 if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
162 DEBUG ("Failed to prepare account manager: %s", error->message);
163 g_error_free (error);
167 accounts = tp_account_manager_get_valid_accounts (account_manager);
168 account_num = g_list_length (accounts);
169 g_list_free (accounts);
171 if (account_num > 1) {
172 gtk_widget_show (window->vbox_chats);
173 gtk_widget_show (window->account_chooser_chats);
175 gtk_widget_hide (window->vbox_chats);
176 gtk_widget_hide (window->account_chooser_chats);
181 account_chooser_ready_cb (EmpathyAccountChooser *chooser,
182 EmpathyLogWindow *window)
184 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
185 log_window_chats_set_selected (window, window->selected_account,
186 window->selected_chat_id, window->selected_is_chatroom);
190 empathy_log_window_show (TpAccount *account,
191 const gchar *chat_id,
192 gboolean is_chatroom,
195 EmpathyAccountChooser *account_chooser;
196 TpAccountManager *account_manager;
199 EmpathyLogWindow *window;
202 gtk_window_present (GTK_WINDOW (log_window->window));
204 if (account && chat_id) {
205 gtk_notebook_set_current_page (GTK_NOTEBOOK (log_window->notebook), 1);
206 log_window_chats_set_selected (log_window, account,
207 chat_id, is_chatroom);
210 return log_window->window;
213 log_window = g_new0 (EmpathyLogWindow, 1);
214 log_window->log_manager = tpl_log_manager_dup_singleton ();
218 filename = empathy_file_lookup ("empathy-log-window.ui",
220 gui = empathy_builder_get_file (filename,
221 "log_window", &window->window,
222 "notebook", &window->notebook,
223 "entry_find", &window->entry_find,
224 "button_find", &window->button_find,
225 "treeview_find", &window->treeview_find,
226 "scrolledwindow_find", &window->scrolledwindow_find,
227 "button_previous", &window->button_previous,
228 "button_next", &window->button_next,
229 "entry_chats", &window->entry_chats,
230 "calendar_chats", &window->calendar_chats,
231 "vbox_chats", &window->vbox_chats,
232 "treeview_chats", &window->treeview_chats,
233 "scrolledwindow_chats", &window->scrolledwindow_chats,
237 empathy_builder_connect (gui, window,
238 "log_window", "destroy", log_window_destroy_cb,
239 "entry_find", "changed", log_window_entry_find_changed_cb,
240 "entry_find", "activate", log_window_entry_find_activate_cb,
241 "button_previous", "clicked", log_window_button_previous_clicked_cb,
242 "button_next", "clicked", log_window_button_next_clicked_cb,
243 "button_find", "clicked", log_window_button_find_clicked_cb,
244 "entry_chats", "changed", log_window_entry_chats_changed_cb,
245 "entry_chats", "activate", log_window_entry_chats_activate_cb,
248 g_object_unref (gui);
250 g_object_add_weak_pointer (G_OBJECT (window->window),
251 (gpointer) &log_window);
253 /* We set this up here so we can block it when needed. */
254 g_signal_connect (window->calendar_chats, "day-selected",
255 G_CALLBACK (log_window_calendar_chats_day_selected_cb),
257 g_signal_connect (window->calendar_chats, "month-changed",
258 G_CALLBACK (log_window_calendar_chats_month_changed_cb),
261 /* Configure Search EmpathyChatView */
262 window->chatview_find = empathy_theme_manager_create_view (empathy_theme_manager_get ());
263 gtk_container_add (GTK_CONTAINER (window->scrolledwindow_find),
264 GTK_WIDGET (window->chatview_find));
265 gtk_widget_show (GTK_WIDGET (window->chatview_find));
267 /* Configure Contacts EmpathyChatView */
268 window->chatview_chats = empathy_theme_manager_create_view (empathy_theme_manager_get ());
269 gtk_container_add (GTK_CONTAINER (window->scrolledwindow_chats),
270 GTK_WIDGET (window->chatview_chats));
271 gtk_widget_show (GTK_WIDGET (window->chatview_chats));
273 /* Account chooser for chats */
274 window->account_chooser_chats = empathy_account_chooser_new ();
275 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
277 gtk_box_pack_start (GTK_BOX (window->vbox_chats),
278 window->account_chooser_chats,
281 g_signal_connect (window->account_chooser_chats, "changed",
282 G_CALLBACK (log_window_chats_accounts_changed_cb),
286 account_manager = tp_account_manager_dup ();
287 tp_account_manager_prepare_async (account_manager, NULL,
288 account_manager_prepared_cb, window);
289 g_object_unref (account_manager);
292 log_window_find_setup (window);
295 log_window_chats_setup (window);
296 log_window_chats_populate (window);
298 if (account && chat_id) {
299 window->selected_account = account;
300 window->selected_chat_id = g_strdup (chat_id);
301 window->selected_is_chatroom = is_chatroom;
303 if (empathy_account_chooser_is_ready (account_chooser))
304 account_chooser_ready_cb (account_chooser, window);
306 /* Chat will be selected once the account chooser is ready */
307 g_signal_connect (account_chooser, "ready",
308 G_CALLBACK (account_chooser_ready_cb), window);
312 gtk_window_set_transient_for (GTK_WINDOW (window->window),
313 GTK_WINDOW (parent));
316 gtk_widget_show (window->window);
318 return window->window;
322 log_window_destroy_cb (GtkWidget *widget,
323 EmpathyLogWindow *window)
325 g_free (window->last_find);
326 g_object_unref (window->log_manager);
327 g_free (window->selected_chat_id);
336 log_window_entry_find_changed_cb (GtkWidget *entry,
337 EmpathyLogWindow *window)
340 gboolean is_sensitive = TRUE;
342 str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
344 is_sensitive &= !EMP_STR_EMPTY (str);
346 !window->last_find ||
347 (window->last_find && strcmp (window->last_find, str) != 0);
349 gtk_widget_set_sensitive (window->button_find, is_sensitive);
353 got_messages_for_date_cb (GObject *manager,
354 GAsyncResult *result,
357 EmpathyLogWindow *window = user_data;
360 gboolean can_do_previous;
361 gboolean can_do_next;
362 GError *error = NULL;
364 if (log_window == NULL)
367 if (!tpl_log_manager_get_messages_for_date_finish (TPL_LOG_MANAGER (manager),
368 result, &messages, &error)) {
369 DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
371 empathy_chat_view_append_event (window->chatview_find,
372 "Unable to retrieve messages for the selected date");
373 g_error_free (error);
377 for (l = messages; l; l = l->next) {
378 EmpathyMessage *message;
380 g_assert (TPL_IS_ENTRY (l->data));
382 message = empathy_message_from_tpl_log_entry (l->data);
383 g_object_unref (l->data);
384 empathy_chat_view_append_message (window->chatview_find, message);
385 g_object_unref (message);
387 g_list_free (messages);
389 /* Scroll to the most recent messages */
390 empathy_chat_view_scroll (window->chatview_find, TRUE);
392 /* Highlight and find messages */
393 empathy_chat_view_highlight (window->chatview_find,
396 empathy_chat_view_find_next (window->chatview_find,
400 empathy_chat_view_find_abilities (window->chatview_find,
405 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
406 gtk_widget_set_sensitive (window->button_next, can_do_next);
407 gtk_widget_set_sensitive (window->button_find, FALSE);
411 gdate_from_str (const gchar *str)
414 guint day, month, year;
416 if (sscanf (str, "%u", &u) != 1)
420 month = ((u / 100) % 100);
423 if (!g_date_valid_dmy (day, month, year))
426 return g_date_new_dmy (day, month, year);
430 log_window_find_changed_cb (GtkTreeSelection *selection,
431 EmpathyLogWindow *window)
438 gboolean is_chatroom;
442 /* Get selected information */
443 view = GTK_TREE_VIEW (window->treeview_find);
444 model = gtk_tree_view_get_model (view);
446 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
447 gtk_widget_set_sensitive (window->button_previous, FALSE);
448 gtk_widget_set_sensitive (window->button_next, FALSE);
450 empathy_chat_view_clear (window->chatview_find);
455 gtk_widget_set_sensitive (window->button_previous, TRUE);
456 gtk_widget_set_sensitive (window->button_next, TRUE);
458 gtk_tree_model_get (model, &iter,
459 COL_FIND_ACCOUNT, &account,
460 COL_FIND_CHAT_ID, &chat_id,
461 COL_FIND_IS_CHATROOM, &is_chatroom,
462 COL_FIND_DATE, &date,
465 /* Clear all current messages shown in the textview */
466 empathy_chat_view_clear (window->chatview_find);
468 /* Turn off scrolling temporarily */
469 empathy_chat_view_scroll (window->chatview_find, FALSE);
472 gdate = gdate_from_str (date);
475 tpl_log_manager_get_messages_for_date_async (window->log_manager,
480 got_messages_for_date_cb,
486 g_object_unref (account);
493 log_manager_searched_new_cb (GObject *manager,
494 GAsyncResult *result,
500 GtkListStore *store = user_data;
501 GError *error = NULL;
503 if (log_window == NULL)
506 if (!tpl_log_manager_search_finish (TPL_LOG_MANAGER (manager), result,
508 DEBUG ("%s. Aborting", error->message);
509 g_error_free (error);
513 for (l = hits; l; l = l->next) {
514 TplLogSearchHit *hit;
515 const gchar *account_name;
516 const gchar *account_icon;
517 gchar date_readable[255];
522 /* Protect against invalid data (corrupt or old log files. */
523 if (!hit->account || !hit->chat_id) {
527 g_date_strftime (date_readable, sizeof (date_readable),
528 EMPATHY_TIME_FORMAT_DISPLAY_LONG, hit->date);
530 g_date_strftime (tmp, sizeof (tmp),
531 "%Y%m%d", hit->date);
533 account_name = tp_account_get_display_name (hit->account);
534 account_icon = tp_account_get_icon_name (hit->account);
536 gtk_list_store_append (store, &iter);
537 gtk_list_store_set (store, &iter,
538 COL_FIND_ACCOUNT_ICON, account_icon,
539 COL_FIND_ACCOUNT_NAME, account_name,
540 COL_FIND_ACCOUNT, hit->account,
541 COL_FIND_CHAT_NAME, hit->chat_id, /* FIXME */
542 COL_FIND_CHAT_ID, hit->chat_id,
543 COL_FIND_IS_CHATROOM, hit->is_chatroom,
545 COL_FIND_DATE_READABLE, date_readable,
548 /* FIXME: Update COL_FIND_CHAT_NAME */
549 if (hit->is_chatroom) {
555 tpl_log_manager_search_free (hits);
560 log_window_find_populate (EmpathyLogWindow *window,
561 const gchar *search_criteria)
565 GtkTreeSelection *selection;
568 view = GTK_TREE_VIEW (window->treeview_find);
569 model = gtk_tree_view_get_model (view);
570 selection = gtk_tree_view_get_selection (view);
571 store = GTK_LIST_STORE (model);
573 empathy_chat_view_clear (window->chatview_find);
575 gtk_list_store_clear (store);
577 if (EMP_STR_EMPTY (search_criteria)) {
578 /* Just clear the search. */
582 tpl_log_manager_search_async (window->log_manager, search_criteria,
583 log_manager_searched_new_cb, (gpointer) store);
587 log_window_find_setup (EmpathyLogWindow *window)
591 GtkTreeSelection *selection;
592 GtkTreeSortable *sortable;
593 GtkTreeViewColumn *column;
595 GtkCellRenderer *cell;
598 view = GTK_TREE_VIEW (window->treeview_find);
599 selection = gtk_tree_view_get_selection (view);
602 store = gtk_list_store_new (COL_FIND_COUNT,
603 G_TYPE_STRING, /* account icon name */
604 G_TYPE_STRING, /* account name */
605 TP_TYPE_ACCOUNT, /* account */
606 G_TYPE_STRING, /* chat name */
607 G_TYPE_STRING, /* chat id */
608 G_TYPE_BOOLEAN, /* is chatroom */
609 G_TYPE_STRING, /* date */
610 G_TYPE_STRING); /* date_readable */
612 model = GTK_TREE_MODEL (store);
613 sortable = GTK_TREE_SORTABLE (store);
615 gtk_tree_view_set_model (view, model);
618 column = gtk_tree_view_column_new ();
620 cell = gtk_cell_renderer_pixbuf_new ();
621 gtk_tree_view_column_pack_start (column, cell, FALSE);
622 gtk_tree_view_column_add_attribute (column, cell,
624 COL_FIND_ACCOUNT_ICON);
626 cell = gtk_cell_renderer_text_new ();
627 gtk_tree_view_column_pack_start (column, cell, TRUE);
628 gtk_tree_view_column_add_attribute (column, cell,
630 COL_FIND_ACCOUNT_NAME);
632 gtk_tree_view_column_set_title (column, _("Account"));
633 gtk_tree_view_append_column (view, column);
635 gtk_tree_view_column_set_resizable (column, TRUE);
636 gtk_tree_view_column_set_clickable (column, TRUE);
638 cell = gtk_cell_renderer_text_new ();
639 offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Conversation"),
640 cell, "text", COL_FIND_CHAT_NAME,
643 column = gtk_tree_view_get_column (view, offset - 1);
644 gtk_tree_view_column_set_sort_column_id (column, COL_FIND_CHAT_NAME);
645 gtk_tree_view_column_set_resizable (column, TRUE);
646 gtk_tree_view_column_set_clickable (column, TRUE);
648 cell = gtk_cell_renderer_text_new ();
649 offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Date"),
650 cell, "text", COL_FIND_DATE_READABLE,
653 column = gtk_tree_view_get_column (view, offset - 1);
654 gtk_tree_view_column_set_sort_column_id (column, COL_FIND_DATE);
655 gtk_tree_view_column_set_resizable (column, TRUE);
656 gtk_tree_view_column_set_clickable (column, TRUE);
658 /* Set up treeview properties */
659 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
660 gtk_tree_sortable_set_sort_column_id (sortable,
665 g_signal_connect (selection, "changed",
666 G_CALLBACK (log_window_find_changed_cb),
669 g_object_unref (store);
673 start_find_search (EmpathyLogWindow *window)
677 str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
679 /* Don't find the same crap again */
680 if (window->last_find && strcmp (window->last_find, str) == 0) {
684 g_free (window->last_find);
685 window->last_find = g_strdup (str);
687 log_window_find_populate (window, str);
691 log_window_button_find_clicked_cb (GtkWidget *widget,
692 EmpathyLogWindow *window)
694 start_find_search (window);
698 log_window_entry_find_activate_cb (GtkWidget *entry,
699 EmpathyLogWindow *self)
701 start_find_search (self);
705 log_window_button_next_clicked_cb (GtkWidget *widget,
706 EmpathyLogWindow *window)
708 if (window->last_find) {
709 gboolean can_do_previous;
710 gboolean can_do_next;
712 empathy_chat_view_find_next (window->chatview_find,
716 empathy_chat_view_find_abilities (window->chatview_find,
721 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
722 gtk_widget_set_sensitive (window->button_next, can_do_next);
727 log_window_button_previous_clicked_cb (GtkWidget *widget,
728 EmpathyLogWindow *window)
730 if (window->last_find) {
731 gboolean can_do_previous;
732 gboolean can_do_next;
734 empathy_chat_view_find_previous (window->chatview_find,
738 empathy_chat_view_find_abilities (window->chatview_find,
743 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
744 gtk_widget_set_sensitive (window->button_next, can_do_next);
753 log_window_chats_changed_cb (GtkTreeSelection *selection,
754 EmpathyLogWindow *window)
756 /* Use last date by default */
757 gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
759 log_window_chats_get_messages (window, NULL);
763 log_manager_got_chats_cb (GObject *manager,
764 GAsyncResult *result,
767 EmpathyLogWindow *window = user_data;
770 EmpathyAccountChooser *account_chooser;
774 GtkTreeSelection *selection;
777 GError *error = NULL;
779 if (log_window == NULL)
782 if (!tpl_log_manager_get_chats_finish (TPL_LOG_MANAGER (manager),
783 result, &chats, &error)) {
784 DEBUG ("%s. Aborting", error->message);
785 g_error_free (error);
789 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
790 account = empathy_account_chooser_dup_account (account_chooser);
792 view = GTK_TREE_VIEW (window->treeview_chats);
793 model = gtk_tree_view_get_model (view);
794 selection = gtk_tree_view_get_selection (view);
795 store = GTK_LIST_STORE (model);
797 for (l = chats; l; l = l->next) {
798 TplLogSearchHit *hit;
802 gtk_list_store_append (store, &iter);
803 gtk_list_store_set (store, &iter,
804 COL_CHAT_ICON, "empathy-available", /* FIXME */
805 COL_CHAT_NAME, hit->chat_id,
806 COL_CHAT_ACCOUNT, account,
807 COL_CHAT_ID, hit->chat_id,
808 COL_CHAT_IS_CHATROOM, hit->is_chatroom,
811 /* FIXME: Update COL_CHAT_ICON/NAME */
812 if (hit->is_chatroom) {
816 tpl_log_manager_search_free (chats);
818 /* Unblock signals */
819 g_signal_handlers_unblock_by_func (selection,
820 log_window_chats_changed_cb,
823 g_object_unref (account);
827 log_window_chats_populate (EmpathyLogWindow *window)
829 EmpathyAccountChooser *account_chooser;
834 GtkTreeSelection *selection;
837 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
838 account = empathy_account_chooser_dup_account (account_chooser);
840 view = GTK_TREE_VIEW (window->treeview_chats);
841 model = gtk_tree_view_get_model (view);
842 selection = gtk_tree_view_get_selection (view);
843 store = GTK_LIST_STORE (model);
845 if (account == NULL) {
846 gtk_list_store_clear (store);
850 /* Block signals to stop the logs being retrieved prematurely */
851 g_signal_handlers_block_by_func (selection,
852 log_window_chats_changed_cb,
855 gtk_list_store_clear (store);
857 tpl_log_manager_get_chats_async (window->log_manager, account,
858 log_manager_got_chats_cb, (gpointer) window);
862 log_window_chats_setup (EmpathyLogWindow *window)
866 GtkTreeSelection *selection;
867 GtkTreeSortable *sortable;
868 GtkTreeViewColumn *column;
870 GtkCellRenderer *cell;
872 view = GTK_TREE_VIEW (window->treeview_chats);
873 selection = gtk_tree_view_get_selection (view);
876 store = gtk_list_store_new (COL_CHAT_COUNT,
877 G_TYPE_STRING, /* icon */
878 G_TYPE_STRING, /* name */
879 TP_TYPE_ACCOUNT, /* account */
880 G_TYPE_STRING, /* id */
881 G_TYPE_BOOLEAN); /* is chatroom */
883 model = GTK_TREE_MODEL (store);
884 sortable = GTK_TREE_SORTABLE (store);
886 gtk_tree_view_set_model (view, model);
889 column = gtk_tree_view_column_new ();
891 cell = gtk_cell_renderer_pixbuf_new ();
892 gtk_tree_view_column_pack_start (column, cell, FALSE);
893 gtk_tree_view_column_add_attribute (column, cell,
897 cell = gtk_cell_renderer_text_new ();
898 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
899 gtk_tree_view_column_pack_start (column, cell, TRUE);
900 gtk_tree_view_column_add_attribute (column, cell,
904 gtk_tree_view_append_column (view, column);
906 /* set up treeview properties */
907 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
908 gtk_tree_sortable_set_sort_column_id (sortable,
913 g_signal_connect (selection, "changed",
914 G_CALLBACK (log_window_chats_changed_cb),
917 g_object_unref (store);
921 log_window_chats_accounts_changed_cb (GtkWidget *combobox,
922 EmpathyLogWindow *window)
924 /* Clear all current messages shown in the textview */
925 empathy_chat_view_clear (window->chatview_chats);
927 log_window_chats_populate (window);
931 log_window_chats_set_selected (EmpathyLogWindow *window,
933 const gchar *chat_id,
934 gboolean is_chatroom)
936 EmpathyAccountChooser *account_chooser;
939 GtkTreeSelection *selection;
944 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
945 empathy_account_chooser_set_account (account_chooser, account);
947 view = GTK_TREE_VIEW (window->treeview_chats);
948 model = gtk_tree_view_get_model (view);
949 selection = gtk_tree_view_get_selection (view);
951 if (!gtk_tree_model_get_iter_first (model, &iter)) {
955 for (ok = TRUE; ok; ok = gtk_tree_model_iter_next (model, &iter)) {
956 TpAccount *this_account;
958 gboolean this_is_chatroom;
960 gtk_tree_model_get (model, &iter,
961 COL_CHAT_ACCOUNT, &this_account,
962 COL_CHAT_ID, &this_chat_id,
963 COL_CHAT_IS_CHATROOM, &this_is_chatroom,
966 if (this_account == account &&
967 strcmp (this_chat_id, chat_id) == 0 &&
968 this_is_chatroom == is_chatroom) {
969 gtk_tree_selection_select_iter (selection, &iter);
970 path = gtk_tree_model_get_path (model, &iter);
971 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
972 gtk_tree_path_free (path);
973 g_object_unref (this_account);
974 g_free (this_chat_id);
978 g_object_unref (this_account);
979 g_free (this_chat_id);
984 log_window_chats_get_selected (EmpathyLogWindow *window,
987 gboolean *is_chatroom)
991 GtkTreeSelection *selection;
994 TpAccount *acc = NULL;
995 gboolean room = FALSE;
997 view = GTK_TREE_VIEW (window->treeview_chats);
998 model = gtk_tree_view_get_model (view);
999 selection = gtk_tree_view_get_selection (view);
1001 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
1005 gtk_tree_model_get (model, &iter,
1006 COL_CHAT_ACCOUNT, &acc,
1008 COL_CHAT_IS_CHATROOM, &room,
1019 g_object_unref (acc);
1022 *is_chatroom = room;
1029 log_window_got_messages_for_date_cb (GObject *manager,
1030 GAsyncResult *result,
1033 EmpathyLogWindow *window = user_data;
1036 GError *error = NULL;
1038 if (log_window == NULL)
1041 if (!tpl_log_manager_get_messages_for_date_finish (TPL_LOG_MANAGER (manager),
1042 result, &messages, &error)) {
1043 DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
1045 empathy_chat_view_append_event (window->chatview_find,
1046 "Unable to retrieve messages for the selected date");
1047 g_error_free (error);
1051 for (l = messages; l; l = l->next) {
1052 EmpathyMessage *message = empathy_message_from_tpl_log_entry (l->data);
1053 g_object_unref (l->data);
1054 empathy_chat_view_append_message (window->chatview_chats,
1056 g_object_unref (message);
1058 g_list_free (messages);
1060 /* Turn back on scrolling */
1061 empathy_chat_view_scroll (window->chatview_find, TRUE);
1063 /* Give the search entry main focus */
1064 gtk_widget_grab_focus (window->entry_chats);
1069 log_window_get_messages_for_date (EmpathyLogWindow *window,
1074 gboolean is_chatroom;
1076 if (!log_window_chats_get_selected (window, &account,
1077 &chat_id, &is_chatroom)) {
1081 /* Clear all current messages shown in the textview */
1082 empathy_chat_view_clear (window->chatview_chats);
1084 /* Turn off scrolling temporarily */
1085 empathy_chat_view_scroll (window->chatview_find, FALSE);
1088 tpl_log_manager_get_messages_for_date_async (window->log_manager,
1092 log_window_got_messages_for_date_cb,
1097 log_manager_got_dates_cb (GObject *manager,
1098 GAsyncResult *result,
1101 EmpathyLogWindow *window = user_data;
1104 guint year_selected;
1105 guint month_selected;
1106 gboolean day_selected = FALSE;
1108 GError *error = NULL;
1110 if (log_window == NULL)
1113 if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
1114 result, &dates, &error)) {
1115 DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
1117 empathy_chat_view_append_event (window->chatview_find,
1118 "Unable to retrieve messages' dates");
1122 for (l = dates; l; l = l->next) {
1125 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1136 if (g_date_get_year (d) != year_selected ||
1137 g_date_get_month (d) != month_selected) {
1141 DEBUG ("Marking date: %04u-%02u-%02u", g_date_get_year (d),
1142 g_date_get_month (d), g_date_get_day (d));
1144 gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats),
1145 g_date_get_day (d));
1151 day_selected = TRUE;
1153 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats),
1154 g_date_get_day (d));
1157 if (!day_selected) {
1158 /* Unselect the day in the calendar */
1159 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), 0);
1162 g_signal_handlers_unblock_by_func (window->calendar_chats,
1163 log_window_calendar_chats_day_selected_cb,
1167 /* Show messages of the most recent date */
1168 log_window_get_messages_for_date (window, date);
1171 g_list_foreach (dates, (GFunc) g_free, NULL);
1172 g_list_free (dates);
1177 log_window_chats_get_messages (EmpathyLogWindow *window,
1182 gboolean is_chatroom;
1183 guint year_selected;
1184 guint month_selected;
1188 if (!log_window_chats_get_selected (window, &account,
1189 &chat_id, &is_chatroom)) {
1193 g_signal_handlers_block_by_func (window->calendar_chats,
1194 log_window_calendar_chats_day_selected_cb,
1197 /* Either use the supplied date or get the last */
1199 /* Get a list of dates and show them on the calendar */
1200 tpl_log_manager_get_dates_async (window->log_manager,
1203 log_manager_got_dates_cb, (gpointer) window);
1204 /* signal unblocked at the end of the CB flow */
1206 day = g_date_get_day (date);
1207 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1214 if (g_date_get_year (date) != year_selected &&
1215 g_date_get_month (date) != month_selected) {
1219 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
1221 g_signal_handlers_unblock_by_func (window->calendar_chats,
1222 log_window_calendar_chats_day_selected_cb,
1227 /* Show messages of the selected date */
1228 log_window_get_messages_for_date (window, date);
1231 g_object_unref (account);
1236 log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
1237 EmpathyLogWindow *window)
1244 gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
1246 /* No date selected */
1249 /* We need this hear because it appears that the months start from 0 */
1252 date = g_date_new_dmy (day, month, year);
1254 DEBUG ("Currently selected date is: %04u-%02u-%02u", year, month, day);
1256 log_window_chats_get_messages (window, date);
1262 log_window_updating_calendar_month_cb (GObject *manager,
1263 GAsyncResult *result, gpointer user_data)
1265 EmpathyLogWindow *window = user_data;
1268 guint year_selected;
1269 guint month_selected;
1270 GError *error = NULL;
1272 if (log_window == NULL)
1275 if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
1276 result, &dates, &error)) {
1277 DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
1279 empathy_chat_view_append_event (window->chatview_find,
1280 "Unable to retrieve messages' dates");
1281 g_error_free (error);
1285 gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
1286 g_object_get (window->calendar_chats,
1287 "month", &month_selected,
1288 "year", &year_selected,
1291 /* We need this here because it appears that the months start from 0 */
1294 for (l = dates; l; l = l->next) {
1295 GDate *date = l->data;
1297 if (g_date_get_year (date) == year_selected &&
1298 g_date_get_month (date) == month_selected) {
1299 DEBUG ("Marking date: %04u-%02u-%02u", g_date_get_year (date),
1300 g_date_get_month (date), g_date_get_day (date));
1301 gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), g_date_get_day (date));
1305 g_list_foreach (dates, (GFunc) g_free, NULL);
1306 g_list_free (dates);
1308 DEBUG ("Currently showing month %d and year %d", month_selected,
1313 log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
1314 EmpathyLogWindow *window)
1318 gboolean is_chatroom;
1320 gtk_calendar_clear_marks (GTK_CALENDAR (calendar));
1322 if (!log_window_chats_get_selected (window, &account,
1323 &chat_id, &is_chatroom)) {
1324 DEBUG ("No chat selected to get dates for...");
1328 /* Get the log object for this contact */
1329 tpl_log_manager_get_dates_async (window->log_manager, account,
1330 chat_id, is_chatroom,
1331 log_window_updating_calendar_month_cb,
1334 g_object_unref (account);
1339 log_window_entry_chats_changed_cb (GtkWidget *entry,
1340 EmpathyLogWindow *window)
1344 str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1345 empathy_chat_view_highlight (window->chatview_chats, str, FALSE);
1348 empathy_chat_view_find_next (window->chatview_chats,
1356 log_window_entry_chats_activate_cb (GtkWidget *entry,
1357 EmpathyLogWindow *window)
1361 str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1364 empathy_chat_view_find_next (window->chatview_chats,