Updated German help translation
[empathy/ppotvin.git] / libempathy-gtk / empathy-log-window.c
blob09b3abd342a61c89601c269aa8b14bb8ebeabf74
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
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>
25 #include "config.h"
27 #include <string.h>
28 #include <stdlib.h>
30 #include <glib/gi18n-lib.h>
31 #include <gtk/gtk.h>
33 #include <telepathy-glib/account-manager.h>
35 #include <libempathy/empathy-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>
51 typedef struct {
52 GtkWidget *window;
54 GtkWidget *notebook;
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;
72 gchar *last_find;
74 EmpathyLogManager *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;
80 } EmpathyLogWindow;
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_button_next_clicked_cb (GtkWidget *widget,
94 EmpathyLogWindow *window);
95 static void log_window_button_previous_clicked_cb (GtkWidget *widget,
96 EmpathyLogWindow *window);
97 static void log_window_chats_changed_cb (GtkTreeSelection *selection,
98 EmpathyLogWindow *window);
99 static void log_window_chats_populate (EmpathyLogWindow *window);
100 static void log_window_chats_setup (EmpathyLogWindow *window);
101 static void log_window_chats_accounts_changed_cb (GtkWidget *combobox,
102 EmpathyLogWindow *window);
103 static void log_window_chats_set_selected (EmpathyLogWindow *window,
104 TpAccount *account,
105 const gchar *chat_id,
106 gboolean is_chatroom);
107 static gboolean log_window_chats_get_selected (EmpathyLogWindow *window,
108 TpAccount **account,
109 gchar **chat_id,
110 gboolean *is_chatroom);
111 static void log_window_chats_get_messages (EmpathyLogWindow *window,
112 const gchar *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);
122 enum {
123 COL_FIND_ACCOUNT_ICON,
124 COL_FIND_ACCOUNT_NAME,
125 COL_FIND_ACCOUNT,
126 COL_FIND_CHAT_NAME,
127 COL_FIND_CHAT_ID,
128 COL_FIND_IS_CHATROOM,
129 COL_FIND_DATE,
130 COL_FIND_DATE_READABLE,
131 COL_FIND_COUNT
134 enum {
135 COL_CHAT_ICON,
136 COL_CHAT_NAME,
137 COL_CHAT_ACCOUNT,
138 COL_CHAT_ID,
139 COL_CHAT_IS_CHATROOM,
140 COL_CHAT_COUNT
143 static void
144 account_manager_prepared_cb (GObject *source_object,
145 GAsyncResult *result,
146 gpointer user_data)
148 TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
149 EmpathyLogWindow *window = user_data;
150 guint account_num;
151 GList *accounts;
152 GError *error = NULL;
154 if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
155 DEBUG ("Failed to prepare account manager: %s", error->message);
156 g_error_free (error);
157 return;
160 accounts = tp_account_manager_get_valid_accounts (account_manager);
161 account_num = g_list_length (accounts);
162 g_list_free (accounts);
164 if (account_num > 1) {
165 gtk_widget_show (window->vbox_chats);
166 gtk_widget_show (window->account_chooser_chats);
167 } else {
168 gtk_widget_hide (window->vbox_chats);
169 gtk_widget_hide (window->account_chooser_chats);
173 static void
174 account_chooser_ready_cb (EmpathyAccountChooser *chooser,
175 EmpathyLogWindow *window)
177 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
178 log_window_chats_set_selected (window, window->selected_account,
179 window->selected_chat_id, window->selected_is_chatroom);
182 GtkWidget *
183 empathy_log_window_show (TpAccount *account,
184 const gchar *chat_id,
185 gboolean is_chatroom,
186 GtkWindow *parent)
188 static EmpathyLogWindow *window = NULL;
189 EmpathyAccountChooser *account_chooser;
190 TpAccountManager *account_manager;
191 GtkBuilder *gui;
192 gchar *filename;
194 if (window) {
195 gtk_window_present (GTK_WINDOW (window->window));
197 if (account && chat_id) {
198 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
199 log_window_chats_set_selected (window, account,
200 chat_id, is_chatroom);
203 return window->window;
206 window = g_new0 (EmpathyLogWindow, 1);
207 window->log_manager = empathy_log_manager_dup_singleton ();
209 filename = empathy_file_lookup ("empathy-log-window.ui",
210 "libempathy-gtk");
211 gui = empathy_builder_get_file (filename,
212 "log_window", &window->window,
213 "notebook", &window->notebook,
214 "entry_find", &window->entry_find,
215 "button_find", &window->button_find,
216 "treeview_find", &window->treeview_find,
217 "scrolledwindow_find", &window->scrolledwindow_find,
218 "button_previous", &window->button_previous,
219 "button_next", &window->button_next,
220 "entry_chats", &window->entry_chats,
221 "calendar_chats", &window->calendar_chats,
222 "vbox_chats", &window->vbox_chats,
223 "treeview_chats", &window->treeview_chats,
224 "scrolledwindow_chats", &window->scrolledwindow_chats,
225 NULL);
226 g_free (filename);
228 empathy_builder_connect (gui, window,
229 "log_window", "destroy", log_window_destroy_cb,
230 "entry_find", "changed", log_window_entry_find_changed_cb,
231 "button_previous", "clicked", log_window_button_previous_clicked_cb,
232 "button_next", "clicked", log_window_button_next_clicked_cb,
233 "button_find", "clicked", log_window_button_find_clicked_cb,
234 "entry_chats", "changed", log_window_entry_chats_changed_cb,
235 "entry_chats", "activate", log_window_entry_chats_activate_cb,
236 NULL);
238 g_object_unref (gui);
240 g_object_add_weak_pointer (G_OBJECT (window->window),
241 (gpointer) &window);
243 /* We set this up here so we can block it when needed. */
244 g_signal_connect (window->calendar_chats, "day-selected",
245 G_CALLBACK (log_window_calendar_chats_day_selected_cb),
246 window);
247 g_signal_connect (window->calendar_chats, "month-changed",
248 G_CALLBACK (log_window_calendar_chats_month_changed_cb),
249 window);
251 /* Configure Search EmpathyChatView */
252 window->chatview_find = empathy_theme_manager_create_view (empathy_theme_manager_get ());
253 gtk_container_add (GTK_CONTAINER (window->scrolledwindow_find),
254 GTK_WIDGET (window->chatview_find));
255 gtk_widget_show (GTK_WIDGET (window->chatview_find));
257 /* Configure Contacts EmpathyChatView */
258 window->chatview_chats = empathy_theme_manager_create_view (empathy_theme_manager_get ());
259 gtk_container_add (GTK_CONTAINER (window->scrolledwindow_chats),
260 GTK_WIDGET (window->chatview_chats));
261 gtk_widget_show (GTK_WIDGET (window->chatview_chats));
263 /* Account chooser for chats */
264 window->account_chooser_chats = empathy_account_chooser_new ();
265 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
267 gtk_box_pack_start (GTK_BOX (window->vbox_chats),
268 window->account_chooser_chats,
269 FALSE, TRUE, 0);
271 g_signal_connect (window->account_chooser_chats, "changed",
272 G_CALLBACK (log_window_chats_accounts_changed_cb),
273 window);
275 /* Populate */
276 account_manager = tp_account_manager_dup ();
277 tp_account_manager_prepare_async (account_manager, NULL,
278 account_manager_prepared_cb, window);
279 g_object_unref (account_manager);
281 /* Search List */
282 log_window_find_setup (window);
284 /* Contacts */
285 log_window_chats_setup (window);
286 log_window_chats_populate (window);
288 if (account && chat_id) {
289 window->selected_account = account;
290 window->selected_chat_id = g_strdup (chat_id);
291 window->selected_is_chatroom = is_chatroom;
293 if (empathy_account_chooser_is_ready (account_chooser))
294 account_chooser_ready_cb (account_chooser, window);
295 else
296 /* Chat will be selected once the account chooser is ready */
297 g_signal_connect (account_chooser, "ready",
298 G_CALLBACK (account_chooser_ready_cb), window);
301 if (parent) {
302 gtk_window_set_transient_for (GTK_WINDOW (window->window),
303 GTK_WINDOW (parent));
306 gtk_widget_show (window->window);
308 return window->window;
311 static void
312 log_window_destroy_cb (GtkWidget *widget,
313 EmpathyLogWindow *window)
315 g_free (window->last_find);
316 g_object_unref (window->log_manager);
317 g_free (window->selected_chat_id);
319 g_free (window);
323 * Search code.
325 static void
326 log_window_entry_find_changed_cb (GtkWidget *entry,
327 EmpathyLogWindow *window)
329 const gchar *str;
330 gboolean is_sensitive = TRUE;
332 str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
334 is_sensitive &= !EMP_STR_EMPTY (str);
335 is_sensitive &=
336 !window->last_find ||
337 (window->last_find && strcmp (window->last_find, str) != 0);
339 gtk_widget_set_sensitive (window->button_find, is_sensitive);
342 static void
343 log_window_find_changed_cb (GtkTreeSelection *selection,
344 EmpathyLogWindow *window)
346 GtkTreeView *view;
347 GtkTreeModel *model;
348 GtkTreeIter iter;
349 TpAccount *account;
350 gchar *chat_id;
351 gboolean is_chatroom;
352 gchar *date;
353 EmpathyMessage *message;
354 GList *messages;
355 GList *l;
356 gboolean can_do_previous;
357 gboolean can_do_next;
359 /* Get selected information */
360 view = GTK_TREE_VIEW (window->treeview_find);
361 model = gtk_tree_view_get_model (view);
363 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
364 gtk_widget_set_sensitive (window->button_previous, FALSE);
365 gtk_widget_set_sensitive (window->button_next, FALSE);
367 empathy_chat_view_clear (window->chatview_find);
369 return;
372 gtk_widget_set_sensitive (window->button_previous, TRUE);
373 gtk_widget_set_sensitive (window->button_next, TRUE);
375 gtk_tree_model_get (model, &iter,
376 COL_FIND_ACCOUNT, &account,
377 COL_FIND_CHAT_ID, &chat_id,
378 COL_FIND_IS_CHATROOM, &is_chatroom,
379 COL_FIND_DATE, &date,
380 -1);
382 /* Clear all current messages shown in the textview */
383 empathy_chat_view_clear (window->chatview_find);
385 /* Turn off scrolling temporarily */
386 empathy_chat_view_scroll (window->chatview_find, FALSE);
388 /* Get messages */
389 messages = empathy_log_manager_get_messages_for_date (window->log_manager,
390 account,
391 chat_id,
392 is_chatroom,
393 date);
394 g_object_unref (account);
395 g_free (date);
396 g_free (chat_id);
398 for (l = messages; l; l = l->next) {
399 message = 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,
410 window->last_find);
411 empathy_chat_view_find_next (window->chatview_find,
412 window->last_find,
413 TRUE);
414 empathy_chat_view_find_abilities (window->chatview_find,
415 window->last_find,
416 &can_do_previous,
417 &can_do_next);
418 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
419 gtk_widget_set_sensitive (window->button_next, can_do_next);
420 gtk_widget_set_sensitive (window->button_find, FALSE);
423 static void
424 log_window_find_populate (EmpathyLogWindow *window,
425 const gchar *search_criteria)
427 GList *hits, *l;
429 GtkTreeView *view;
430 GtkTreeModel *model;
431 GtkTreeSelection *selection;
432 GtkListStore *store;
433 GtkTreeIter iter;
435 view = GTK_TREE_VIEW (window->treeview_find);
436 model = gtk_tree_view_get_model (view);
437 selection = gtk_tree_view_get_selection (view);
438 store = GTK_LIST_STORE (model);
440 empathy_chat_view_clear (window->chatview_find);
442 gtk_list_store_clear (store);
444 if (EMP_STR_EMPTY (search_criteria)) {
445 /* Just clear the search. */
446 return;
449 hits = empathy_log_manager_search_new (window->log_manager, search_criteria);
451 for (l = hits; l; l = l->next) {
452 EmpathyLogSearchHit *hit;
453 const gchar *account_name;
454 const gchar *account_icon;
455 gchar *date_readable;
457 hit = l->data;
459 /* Protect against invalid data (corrupt or old log files. */
460 if (!hit->account || !hit->chat_id) {
461 continue;
464 date_readable = empathy_log_manager_get_date_readable (hit->date);
465 account_name = tp_account_get_display_name (hit->account);
466 account_icon = tp_account_get_icon_name (hit->account);
468 gtk_list_store_append (store, &iter);
469 gtk_list_store_set (store, &iter,
470 COL_FIND_ACCOUNT_ICON, account_icon,
471 COL_FIND_ACCOUNT_NAME, account_name,
472 COL_FIND_ACCOUNT, hit->account,
473 COL_FIND_CHAT_NAME, hit->chat_id, /* FIXME */
474 COL_FIND_CHAT_ID, hit->chat_id,
475 COL_FIND_IS_CHATROOM, hit->is_chatroom,
476 COL_FIND_DATE, hit->date,
477 COL_FIND_DATE_READABLE, date_readable,
478 -1);
480 g_free (date_readable);
482 /* FIXME: Update COL_FIND_CHAT_NAME */
483 if (hit->is_chatroom) {
484 } else {
488 if (hits) {
489 empathy_log_manager_search_free (hits);
493 static void
494 log_window_find_setup (EmpathyLogWindow *window)
496 GtkTreeView *view;
497 GtkTreeModel *model;
498 GtkTreeSelection *selection;
499 GtkTreeSortable *sortable;
500 GtkTreeViewColumn *column;
501 GtkListStore *store;
502 GtkCellRenderer *cell;
503 gint offset;
505 view = GTK_TREE_VIEW (window->treeview_find);
506 selection = gtk_tree_view_get_selection (view);
508 /* New store */
509 store = gtk_list_store_new (COL_FIND_COUNT,
510 G_TYPE_STRING, /* account icon name */
511 G_TYPE_STRING, /* account name */
512 TP_TYPE_ACCOUNT, /* account */
513 G_TYPE_STRING, /* chat name */
514 G_TYPE_STRING, /* chat id */
515 G_TYPE_BOOLEAN, /* is chatroom */
516 G_TYPE_STRING, /* date */
517 G_TYPE_STRING); /* date_readable */
519 model = GTK_TREE_MODEL (store);
520 sortable = GTK_TREE_SORTABLE (store);
522 gtk_tree_view_set_model (view, model);
524 /* New column */
525 column = gtk_tree_view_column_new ();
527 cell = gtk_cell_renderer_pixbuf_new ();
528 gtk_tree_view_column_pack_start (column, cell, FALSE);
529 gtk_tree_view_column_add_attribute (column, cell,
530 "icon-name",
531 COL_FIND_ACCOUNT_ICON);
533 cell = gtk_cell_renderer_text_new ();
534 gtk_tree_view_column_pack_start (column, cell, TRUE);
535 gtk_tree_view_column_add_attribute (column, cell,
536 "text",
537 COL_FIND_ACCOUNT_NAME);
539 gtk_tree_view_column_set_title (column, _("Account"));
540 gtk_tree_view_append_column (view, column);
542 gtk_tree_view_column_set_resizable (column, TRUE);
543 gtk_tree_view_column_set_clickable (column, TRUE);
545 cell = gtk_cell_renderer_text_new ();
546 offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Conversation"),
547 cell, "text", COL_FIND_CHAT_NAME,
548 NULL);
550 column = gtk_tree_view_get_column (view, offset - 1);
551 gtk_tree_view_column_set_sort_column_id (column, COL_FIND_CHAT_NAME);
552 gtk_tree_view_column_set_resizable (column, TRUE);
553 gtk_tree_view_column_set_clickable (column, TRUE);
555 cell = gtk_cell_renderer_text_new ();
556 offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Date"),
557 cell, "text", COL_FIND_DATE_READABLE,
558 NULL);
560 column = gtk_tree_view_get_column (view, offset - 1);
561 gtk_tree_view_column_set_sort_column_id (column, COL_FIND_DATE);
562 gtk_tree_view_column_set_resizable (column, TRUE);
563 gtk_tree_view_column_set_clickable (column, TRUE);
565 /* Set up treeview properties */
566 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
567 gtk_tree_sortable_set_sort_column_id (sortable,
568 COL_FIND_DATE,
569 GTK_SORT_ASCENDING);
571 /* Set up signals */
572 g_signal_connect (selection, "changed",
573 G_CALLBACK (log_window_find_changed_cb),
574 window);
576 g_object_unref (store);
579 static void
580 log_window_button_find_clicked_cb (GtkWidget *widget,
581 EmpathyLogWindow *window)
583 const gchar *str;
585 str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
587 /* Don't find the same crap again */
588 if (window->last_find && strcmp (window->last_find, str) == 0) {
589 return;
592 g_free (window->last_find);
593 window->last_find = g_strdup (str);
595 log_window_find_populate (window, str);
598 static void
599 log_window_button_next_clicked_cb (GtkWidget *widget,
600 EmpathyLogWindow *window)
602 if (window->last_find) {
603 gboolean can_do_previous;
604 gboolean can_do_next;
606 empathy_chat_view_find_next (window->chatview_find,
607 window->last_find,
608 FALSE);
609 empathy_chat_view_find_abilities (window->chatview_find,
610 window->last_find,
611 &can_do_previous,
612 &can_do_next);
613 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
614 gtk_widget_set_sensitive (window->button_next, can_do_next);
618 static void
619 log_window_button_previous_clicked_cb (GtkWidget *widget,
620 EmpathyLogWindow *window)
622 if (window->last_find) {
623 gboolean can_do_previous;
624 gboolean can_do_next;
626 empathy_chat_view_find_previous (window->chatview_find,
627 window->last_find,
628 FALSE);
629 empathy_chat_view_find_abilities (window->chatview_find,
630 window->last_find,
631 &can_do_previous,
632 &can_do_next);
633 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
634 gtk_widget_set_sensitive (window->button_next, can_do_next);
639 * Chats Code
642 static void
643 log_window_chats_changed_cb (GtkTreeSelection *selection,
644 EmpathyLogWindow *window)
646 /* Use last date by default */
647 gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
649 log_window_chats_get_messages (window, NULL);
652 static void
653 log_window_chats_populate (EmpathyLogWindow *window)
655 EmpathyAccountChooser *account_chooser;
656 TpAccount *account;
657 GList *chats, *l;
659 GtkTreeView *view;
660 GtkTreeModel *model;
661 GtkTreeSelection *selection;
662 GtkListStore *store;
663 GtkTreeIter iter;
665 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
666 account = empathy_account_chooser_dup_account (account_chooser);
668 view = GTK_TREE_VIEW (window->treeview_chats);
669 model = gtk_tree_view_get_model (view);
670 selection = gtk_tree_view_get_selection (view);
671 store = GTK_LIST_STORE (model);
673 if (account == NULL) {
674 gtk_list_store_clear (store);
675 return;
678 /* Block signals to stop the logs being retrieved prematurely */
679 g_signal_handlers_block_by_func (selection,
680 log_window_chats_changed_cb,
681 window);
683 gtk_list_store_clear (store);
685 chats = empathy_log_manager_get_chats (window->log_manager, account);
686 for (l = chats; l; l = l->next) {
687 EmpathyLogSearchHit *hit;
689 hit = l->data;
691 gtk_list_store_append (store, &iter);
692 gtk_list_store_set (store, &iter,
693 COL_CHAT_ICON, "empathy-available", /* FIXME */
694 COL_CHAT_NAME, hit->chat_id,
695 COL_CHAT_ACCOUNT, account,
696 COL_CHAT_ID, hit->chat_id,
697 COL_CHAT_IS_CHATROOM, hit->is_chatroom,
698 -1);
700 /* FIXME: Update COL_CHAT_ICON/NAME */
701 if (hit->is_chatroom) {
702 } else {
705 empathy_log_manager_search_free (chats);
707 /* Unblock signals */
708 g_signal_handlers_unblock_by_func (selection,
709 log_window_chats_changed_cb,
710 window);
713 g_object_unref (account);
716 static void
717 log_window_chats_setup (EmpathyLogWindow *window)
719 GtkTreeView *view;
720 GtkTreeModel *model;
721 GtkTreeSelection *selection;
722 GtkTreeSortable *sortable;
723 GtkTreeViewColumn *column;
724 GtkListStore *store;
725 GtkCellRenderer *cell;
727 view = GTK_TREE_VIEW (window->treeview_chats);
728 selection = gtk_tree_view_get_selection (view);
730 /* new store */
731 store = gtk_list_store_new (COL_CHAT_COUNT,
732 G_TYPE_STRING, /* icon */
733 G_TYPE_STRING, /* name */
734 TP_TYPE_ACCOUNT, /* account */
735 G_TYPE_STRING, /* id */
736 G_TYPE_BOOLEAN); /* is chatroom */
738 model = GTK_TREE_MODEL (store);
739 sortable = GTK_TREE_SORTABLE (store);
741 gtk_tree_view_set_model (view, model);
743 /* new column */
744 column = gtk_tree_view_column_new ();
746 cell = gtk_cell_renderer_pixbuf_new ();
747 gtk_tree_view_column_pack_start (column, cell, FALSE);
748 gtk_tree_view_column_add_attribute (column, cell,
749 "icon-name",
750 COL_CHAT_ICON);
752 cell = gtk_cell_renderer_text_new ();
753 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
754 gtk_tree_view_column_pack_start (column, cell, TRUE);
755 gtk_tree_view_column_add_attribute (column, cell,
756 "text",
757 COL_CHAT_NAME);
759 gtk_tree_view_append_column (view, column);
761 /* set up treeview properties */
762 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
763 gtk_tree_sortable_set_sort_column_id (sortable,
764 COL_CHAT_NAME,
765 GTK_SORT_ASCENDING);
767 /* set up signals */
768 g_signal_connect (selection, "changed",
769 G_CALLBACK (log_window_chats_changed_cb),
770 window);
772 g_object_unref (store);
775 static void
776 log_window_chats_accounts_changed_cb (GtkWidget *combobox,
777 EmpathyLogWindow *window)
779 /* Clear all current messages shown in the textview */
780 empathy_chat_view_clear (window->chatview_chats);
782 log_window_chats_populate (window);
785 static void
786 log_window_chats_set_selected (EmpathyLogWindow *window,
787 TpAccount *account,
788 const gchar *chat_id,
789 gboolean is_chatroom)
791 EmpathyAccountChooser *account_chooser;
792 GtkTreeView *view;
793 GtkTreeModel *model;
794 GtkTreeSelection *selection;
795 GtkTreeIter iter;
796 GtkTreePath *path;
797 gboolean ok;
799 account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
800 empathy_account_chooser_set_account (account_chooser, account);
802 view = GTK_TREE_VIEW (window->treeview_chats);
803 model = gtk_tree_view_get_model (view);
804 selection = gtk_tree_view_get_selection (view);
806 if (!gtk_tree_model_get_iter_first (model, &iter)) {
807 return;
810 for (ok = TRUE; ok; ok = gtk_tree_model_iter_next (model, &iter)) {
811 TpAccount *this_account;
812 gchar *this_chat_id;
813 gboolean this_is_chatroom;
815 gtk_tree_model_get (model, &iter,
816 COL_CHAT_ACCOUNT, &this_account,
817 COL_CHAT_ID, &this_chat_id,
818 COL_CHAT_IS_CHATROOM, &this_is_chatroom,
819 -1);
821 if (this_account == account &&
822 strcmp (this_chat_id, chat_id) == 0 &&
823 this_is_chatroom == is_chatroom) {
824 gtk_tree_selection_select_iter (selection, &iter);
825 path = gtk_tree_model_get_path (model, &iter);
826 gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
827 gtk_tree_path_free (path);
828 g_object_unref (this_account);
829 g_free (this_chat_id);
830 break;
833 g_object_unref (this_account);
834 g_free (this_chat_id);
838 static gboolean
839 log_window_chats_get_selected (EmpathyLogWindow *window,
840 TpAccount **account,
841 gchar **chat_id,
842 gboolean *is_chatroom)
844 GtkTreeView *view;
845 GtkTreeModel *model;
846 GtkTreeSelection *selection;
847 GtkTreeIter iter;
848 gchar *id = NULL;
849 TpAccount *acc = NULL;
850 gboolean room = FALSE;
852 view = GTK_TREE_VIEW (window->treeview_chats);
853 model = gtk_tree_view_get_model (view);
854 selection = gtk_tree_view_get_selection (view);
856 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
857 return FALSE;
860 gtk_tree_model_get (model, &iter,
861 COL_CHAT_ACCOUNT, &acc,
862 COL_CHAT_ID, &id,
863 COL_CHAT_IS_CHATROOM, &room,
864 -1);
866 if (chat_id) {
867 *chat_id = id;
868 } else {
869 g_free (id);
871 if (account) {
872 *account = acc;
873 } else {
874 g_object_unref (acc);
876 if (is_chatroom) {
877 *is_chatroom = room;
880 return TRUE;
883 static void
884 log_window_chats_get_messages (EmpathyLogWindow *window,
885 const gchar *date_to_show)
887 TpAccount *account;
888 gchar *chat_id;
889 gboolean is_chatroom;
890 EmpathyMessage *message;
891 GList *messages;
892 GList *dates = NULL;
893 GList *l;
894 const gchar *date;
895 guint year_selected;
896 guint year;
897 guint month;
898 guint month_selected;
899 guint day;
901 if (!log_window_chats_get_selected (window, &account,
902 &chat_id, &is_chatroom)) {
903 return;
906 g_signal_handlers_block_by_func (window->calendar_chats,
907 log_window_calendar_chats_day_selected_cb,
908 window);
910 /* Either use the supplied date or get the last */
911 date = date_to_show;
912 if (!date) {
913 gboolean day_selected = FALSE;
915 /* Get a list of dates and show them on the calendar */
916 dates = empathy_log_manager_get_dates (window->log_manager,
917 account, chat_id,
918 is_chatroom);
920 for (l = dates; l; l = l->next) {
921 const gchar *str;
923 str = l->data;
924 if (!str) {
925 continue;
928 sscanf (str, "%4d%2d%2d", &year, &month, &day);
929 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
930 &year_selected,
931 &month_selected,
932 NULL);
934 month_selected++;
936 if (!l->next) {
937 date = str;
940 if (year != year_selected || month != month_selected) {
941 continue;
945 DEBUG ("Marking date:'%s'", str);
946 gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), day);
948 if (l->next) {
949 continue;
952 day_selected = TRUE;
954 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
957 if (!day_selected) {
958 /* Unselect the day in the calendar */
959 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), 0);
961 } else {
962 sscanf (date, "%4d%2d%2d", &year, &month, &day);
963 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
964 &year_selected,
965 &month_selected,
966 NULL);
968 month_selected++;
970 if (year != year_selected && month != month_selected) {
971 day = 0;
974 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
977 g_signal_handlers_unblock_by_func (window->calendar_chats,
978 log_window_calendar_chats_day_selected_cb,
979 window);
981 if (!date) {
982 goto OUT;
985 /* Clear all current messages shown in the textview */
986 empathy_chat_view_clear (window->chatview_chats);
988 /* Turn off scrolling temporarily */
989 empathy_chat_view_scroll (window->chatview_find, FALSE);
991 /* Get messages */
992 messages = empathy_log_manager_get_messages_for_date (window->log_manager,
993 account, chat_id,
994 is_chatroom,
995 date);
997 for (l = messages; l; l = l->next) {
998 message = l->data;
1000 empathy_chat_view_append_message (window->chatview_chats,
1001 message);
1002 g_object_unref (message);
1004 g_list_free (messages);
1006 /* Turn back on scrolling */
1007 empathy_chat_view_scroll (window->chatview_find, TRUE);
1009 /* Give the search entry main focus */
1010 gtk_widget_grab_focus (window->entry_chats);
1012 OUT:
1013 g_list_foreach (dates, (GFunc) g_free, NULL);
1014 g_list_free (dates);
1015 g_object_unref (account);
1016 g_free (chat_id);
1019 static void
1020 log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
1021 EmpathyLogWindow *window)
1023 guint year;
1024 guint month;
1025 guint day;
1027 gchar *date;
1029 gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
1031 /* We need this hear because it appears that the months start from 0 */
1032 month++;
1034 date = g_strdup_printf ("%4.4d%2.2d%2.2d", year, month, day);
1036 DEBUG ("Currently selected date is:'%s'", date);
1038 log_window_chats_get_messages (window, date);
1040 g_free (date);
1043 static void
1044 log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
1045 EmpathyLogWindow *window)
1047 TpAccount *account;
1048 gchar *chat_id;
1049 gboolean is_chatroom;
1050 guint year_selected;
1051 guint month_selected;
1053 GList *dates;
1054 GList *l;
1056 gtk_calendar_clear_marks (GTK_CALENDAR (calendar));
1058 if (!log_window_chats_get_selected (window, &account,
1059 &chat_id, &is_chatroom)) {
1060 DEBUG ("No chat selected to get dates for...");
1061 return;
1064 g_object_get (calendar,
1065 "month", &month_selected,
1066 "year", &year_selected,
1067 NULL);
1069 /* We need this hear because it appears that the months start from 0 */
1070 month_selected++;
1072 /* Get the log object for this contact */
1073 dates = empathy_log_manager_get_dates (window->log_manager, account,
1074 chat_id, is_chatroom);
1075 g_object_unref (account);
1076 g_free (chat_id);
1078 for (l = dates; l; l = l->next) {
1079 const gchar *str;
1080 guint year;
1081 guint month;
1082 guint day;
1084 str = l->data;
1085 if (!str) {
1086 continue;
1089 sscanf (str, "%4d%2d%2d", &year, &month, &day);
1091 if (year == year_selected && month == month_selected) {
1092 DEBUG ("Marking date:'%s'", str);
1093 gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), day);
1097 g_list_foreach (dates, (GFunc) g_free, NULL);
1098 g_list_free (dates);
1100 DEBUG ("Currently showing month %d and year %d", month_selected,
1101 year_selected);
1104 static void
1105 log_window_entry_chats_changed_cb (GtkWidget *entry,
1106 EmpathyLogWindow *window)
1108 const gchar *str;
1110 str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1111 empathy_chat_view_highlight (window->chatview_chats, str);
1113 if (str) {
1114 empathy_chat_view_find_next (window->chatview_chats,
1115 str,
1116 TRUE);
1120 static void
1121 log_window_entry_chats_activate_cb (GtkWidget *entry,
1122 EmpathyLogWindow *window)
1124 const gchar *str;
1126 str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1128 if (str) {
1129 empathy_chat_view_find_next (window->chatview_chats,
1130 str,
1131 FALSE);