]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-log-window.c
Merge commit 'staz/dnd'
[empathy.git] / libempathy-gtk / empathy-log-window.c
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.
5  *
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.
10  *
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.
15  *
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
20  *
21  * Authors: Martyn Russell <martyn@imendio.com>
22  *          Xavier Claessens <xclaesse@gmail.com>
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28 #include <stdlib.h>
29
30 #include <glib/gi18n-lib.h>
31 #include <gtk/gtk.h>
32
33 #include <telepathy-glib/account-manager.h>
34 #ifdef ENABLE_TPL
35 #include <telepathy-logger/log-manager.h>
36 #endif /* ENABLE_TPL */
37
38 #ifndef ENABLE_TPL
39 #include <libempathy/empathy-log-manager.h>
40 #endif /* ENABLE_TPL */
41 #include <libempathy/empathy-chatroom-manager.h>
42 #include <libempathy/empathy-chatroom.h>
43 #include <libempathy/empathy-message.h>
44 #include <libempathy/empathy-utils.h>
45 #include <libempathy/empathy-time.h>
46
47 #include "empathy-log-window.h"
48 #include "empathy-account-chooser.h"
49 #include "empathy-chat-view.h"
50 #include "empathy-theme-manager.h"
51 #include "empathy-ui-utils.h"
52
53 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
54 #include <libempathy/empathy-debug.h>
55
56 typedef struct {
57         GtkWidget         *window;
58
59         GtkWidget         *notebook;
60
61         GtkWidget         *entry_find;
62         GtkWidget         *button_find;
63         GtkWidget         *treeview_find;
64         GtkWidget         *scrolledwindow_find;
65         EmpathyChatView    *chatview_find;
66         GtkWidget         *button_previous;
67         GtkWidget         *button_next;
68
69         GtkWidget         *vbox_chats;
70         GtkWidget         *account_chooser_chats;
71         GtkWidget         *entry_chats;
72         GtkWidget         *calendar_chats;
73         GtkWidget         *treeview_chats;
74         GtkWidget         *scrolledwindow_chats;
75         EmpathyChatView    *chatview_chats;
76
77         gchar             *last_find;
78
79 #ifndef ENABLE_TPL
80         EmpathyLogManager *log_manager;
81 #else
82         TplLogManager     *log_manager;
83 #endif /* ENABLE_TPL */
84
85         /* Those are only used while waiting for the account chooser to be ready */
86         TpAccount         *selected_account;
87         gchar             *selected_chat_id;
88         gboolean          selected_is_chatroom;
89 } EmpathyLogWindow;
90
91 static void     log_window_destroy_cb                      (GtkWidget        *widget,
92                                                             EmpathyLogWindow *window);
93 static void     log_window_entry_find_changed_cb           (GtkWidget        *entry,
94                                                             EmpathyLogWindow *window);
95 static void     log_window_find_changed_cb                 (GtkTreeSelection *selection,
96                                                             EmpathyLogWindow *window);
97 static void     log_window_find_populate                   (EmpathyLogWindow *window,
98                                                             const gchar      *search_criteria);
99 static void     log_window_find_setup                      (EmpathyLogWindow *window);
100 static void     log_window_button_find_clicked_cb          (GtkWidget        *widget,
101                                                             EmpathyLogWindow *window);
102 static void     log_window_button_next_clicked_cb          (GtkWidget        *widget,
103                                                             EmpathyLogWindow *window);
104 static void     log_window_button_previous_clicked_cb      (GtkWidget        *widget,
105                                                             EmpathyLogWindow *window);
106 static void     log_window_chats_changed_cb                (GtkTreeSelection *selection,
107                                                             EmpathyLogWindow *window);
108 static void     log_window_chats_populate                  (EmpathyLogWindow *window);
109 static void     log_window_chats_setup                     (EmpathyLogWindow *window);
110 static void     log_window_chats_accounts_changed_cb       (GtkWidget        *combobox,
111                                                             EmpathyLogWindow *window);
112 static void     log_window_chats_set_selected              (EmpathyLogWindow *window,
113                                                             TpAccount        *account,
114                                                             const gchar      *chat_id,
115                                                             gboolean          is_chatroom);
116 static gboolean log_window_chats_get_selected              (EmpathyLogWindow *window,
117                                                             TpAccount       **account,
118                                                             gchar           **chat_id,
119                                                             gboolean         *is_chatroom);
120 static void     log_window_chats_get_messages              (EmpathyLogWindow *window,
121                                                             const gchar      *date_to_show);
122 static void     log_window_calendar_chats_day_selected_cb  (GtkWidget        *calendar,
123                                                             EmpathyLogWindow *window);
124 static void     log_window_calendar_chats_month_changed_cb (GtkWidget        *calendar,
125                                                             EmpathyLogWindow *window);
126 static void     log_window_entry_chats_changed_cb          (GtkWidget        *entry,
127                                                             EmpathyLogWindow *window);
128 static void     log_window_entry_chats_activate_cb         (GtkWidget        *entry,
129                                                             EmpathyLogWindow *window);
130
131 enum {
132         COL_FIND_ACCOUNT_ICON,
133         COL_FIND_ACCOUNT_NAME,
134         COL_FIND_ACCOUNT,
135         COL_FIND_CHAT_NAME,
136         COL_FIND_CHAT_ID,
137         COL_FIND_IS_CHATROOM,
138         COL_FIND_DATE,
139         COL_FIND_DATE_READABLE,
140         COL_FIND_COUNT
141 };
142
143 enum {
144         COL_CHAT_ICON,
145         COL_CHAT_NAME,
146         COL_CHAT_ACCOUNT,
147         COL_CHAT_ID,
148         COL_CHAT_IS_CHATROOM,
149         COL_CHAT_COUNT
150 };
151
152 static void
153 account_manager_prepared_cb (GObject *source_object,
154                              GAsyncResult *result,
155                              gpointer user_data)
156 {
157         TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
158         EmpathyLogWindow *window = user_data;
159         guint account_num;
160         GList *accounts;
161         GError *error = NULL;
162
163         if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
164                 DEBUG ("Failed to prepare account manager: %s", error->message);
165                 g_error_free (error);
166                 return;
167         }
168
169         accounts = tp_account_manager_get_valid_accounts (account_manager);
170         account_num = g_list_length (accounts);
171         g_list_free (accounts);
172
173         if (account_num > 1) {
174                 gtk_widget_show (window->vbox_chats);
175                 gtk_widget_show (window->account_chooser_chats);
176         } else {
177                 gtk_widget_hide (window->vbox_chats);
178                 gtk_widget_hide (window->account_chooser_chats);
179         }
180 }
181
182 static void
183 account_chooser_ready_cb (EmpathyAccountChooser *chooser,
184                         EmpathyLogWindow *window)
185 {
186         gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
187         log_window_chats_set_selected (window, window->selected_account,
188                                        window->selected_chat_id, window->selected_is_chatroom);
189 }
190
191 GtkWidget *
192 empathy_log_window_show (TpAccount  *account,
193                         const gchar *chat_id,
194                         gboolean     is_chatroom,
195                         GtkWindow   *parent)
196 {
197         static EmpathyLogWindow *window = NULL;
198         EmpathyAccountChooser   *account_chooser;
199         TpAccountManager        *account_manager;
200         GtkBuilder             *gui;
201         gchar                  *filename;
202
203         if (window) {
204                 gtk_window_present (GTK_WINDOW (window->window));
205
206                 if (account && chat_id) {
207                         gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
208                         log_window_chats_set_selected (window, account,
209                                                        chat_id, is_chatroom);
210                 }
211
212                 return window->window;
213         }
214
215         window = g_new0 (EmpathyLogWindow, 1);
216 #ifndef ENABLE_TPL
217         window->log_manager = empathy_log_manager_dup_singleton ();
218 #else
219         window->log_manager = tpl_log_manager_dup_singleton ();
220 #endif /* ENABLE_TPL */
221
222         filename = empathy_file_lookup ("empathy-log-window.ui",
223                                         "libempathy-gtk");
224         gui = empathy_builder_get_file (filename,
225                                        "log_window", &window->window,
226                                        "notebook", &window->notebook,
227                                        "entry_find", &window->entry_find,
228                                        "button_find", &window->button_find,
229                                        "treeview_find", &window->treeview_find,
230                                        "scrolledwindow_find", &window->scrolledwindow_find,
231                                        "button_previous", &window->button_previous,
232                                        "button_next", &window->button_next,
233                                        "entry_chats", &window->entry_chats,
234                                        "calendar_chats", &window->calendar_chats,
235                                        "vbox_chats", &window->vbox_chats,
236                                        "treeview_chats", &window->treeview_chats,
237                                        "scrolledwindow_chats", &window->scrolledwindow_chats,
238                                        NULL);
239         g_free (filename);
240
241         empathy_builder_connect (gui, window,
242                               "log_window", "destroy", log_window_destroy_cb,
243                               "entry_find", "changed", log_window_entry_find_changed_cb,
244                               "button_previous", "clicked", log_window_button_previous_clicked_cb,
245                               "button_next", "clicked", log_window_button_next_clicked_cb,
246                               "button_find", "clicked", log_window_button_find_clicked_cb,
247                               "entry_chats", "changed", log_window_entry_chats_changed_cb,
248                               "entry_chats", "activate", log_window_entry_chats_activate_cb,
249                               NULL);
250
251         g_object_unref (gui);
252
253         g_object_add_weak_pointer (G_OBJECT (window->window),
254                                    (gpointer) &window);
255
256         /* We set this up here so we can block it when needed. */
257         g_signal_connect (window->calendar_chats, "day-selected",
258                           G_CALLBACK (log_window_calendar_chats_day_selected_cb),
259                           window);
260         g_signal_connect (window->calendar_chats, "month-changed",
261                           G_CALLBACK (log_window_calendar_chats_month_changed_cb),
262                           window);
263
264         /* Configure Search EmpathyChatView */
265         window->chatview_find = empathy_theme_manager_create_view (empathy_theme_manager_get ());
266         gtk_container_add (GTK_CONTAINER (window->scrolledwindow_find),
267                            GTK_WIDGET (window->chatview_find));
268         gtk_widget_show (GTK_WIDGET (window->chatview_find));
269
270         /* Configure Contacts EmpathyChatView */
271         window->chatview_chats = empathy_theme_manager_create_view (empathy_theme_manager_get ());
272         gtk_container_add (GTK_CONTAINER (window->scrolledwindow_chats),
273                            GTK_WIDGET (window->chatview_chats));
274         gtk_widget_show (GTK_WIDGET (window->chatview_chats));
275
276         /* Account chooser for chats */
277         window->account_chooser_chats = empathy_account_chooser_new ();
278         account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
279
280         gtk_box_pack_start (GTK_BOX (window->vbox_chats),
281                             window->account_chooser_chats,
282                             FALSE, TRUE, 0);
283
284         g_signal_connect (window->account_chooser_chats, "changed",
285                           G_CALLBACK (log_window_chats_accounts_changed_cb),
286                           window);
287
288         /* Populate */
289         account_manager = tp_account_manager_dup ();
290         tp_account_manager_prepare_async (account_manager, NULL,
291                                           account_manager_prepared_cb, window);
292         g_object_unref (account_manager);
293
294         /* Search List */
295         log_window_find_setup (window);
296
297         /* Contacts */
298         log_window_chats_setup (window);
299         log_window_chats_populate (window);
300
301         if (account && chat_id) {
302                 window->selected_account = account;
303                 window->selected_chat_id = g_strdup (chat_id);
304                 window->selected_is_chatroom = is_chatroom;
305
306                 if (empathy_account_chooser_is_ready (account_chooser))
307                         account_chooser_ready_cb (account_chooser, window);
308                 else
309                         /* Chat will be selected once the account chooser is ready */
310                         g_signal_connect (account_chooser, "ready",
311                                           G_CALLBACK (account_chooser_ready_cb), window);
312         }
313
314         if (parent) {
315                 gtk_window_set_transient_for (GTK_WINDOW (window->window),
316                                               GTK_WINDOW (parent));
317         }
318
319         gtk_widget_show (window->window);
320
321         return window->window;
322 }
323
324 static void
325 log_window_destroy_cb (GtkWidget       *widget,
326                        EmpathyLogWindow *window)
327 {
328         g_free (window->last_find);
329         g_object_unref (window->log_manager);
330         g_free (window->selected_chat_id);
331
332         g_free (window);
333 }
334
335 /*
336  * Search code.
337  */
338 static void
339 log_window_entry_find_changed_cb (GtkWidget       *entry,
340                                   EmpathyLogWindow *window)
341 {
342         const gchar *str;
343         gboolean     is_sensitive = TRUE;
344
345         str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
346
347         is_sensitive &= !EMP_STR_EMPTY (str);
348         is_sensitive &=
349                 !window->last_find ||
350                 (window->last_find && strcmp (window->last_find, str) != 0);
351
352         gtk_widget_set_sensitive (window->button_find, is_sensitive);
353 }
354
355 #ifdef ENABLE_TPL
356 static void
357 got_messages_for_date_cb (GObject *manager,
358                        GAsyncResult *result,
359                        gpointer user_data)
360 {
361         EmpathyLogWindow *window = user_data;
362         GList         *messages;
363         GList         *l;
364         gboolean       can_do_previous;
365         gboolean       can_do_next;
366         GError        *error = NULL;
367
368         messages = tpl_log_manager_get_messages_for_date_async_finish (result, &error);
369
370         if (error != NULL) {
371                         DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
372                                         error->message);
373                         empathy_chat_view_append_event (window->chatview_find,
374                                         "Unable to retrieve messages for the selected date");
375                         g_error_free (error);
376                         return;
377         }
378
379         for (l = messages; l; l = l->next) {
380                         EmpathyMessage *message;
381
382                         g_assert (TPL_IS_LOG_ENTRY (l->data));
383
384                         message = empathy_message_from_tpl_log_entry (l->data);
385                         g_object_unref (l->data);
386                         empathy_chat_view_append_message (window->chatview_find, message);
387                         g_object_unref (message);
388         }
389         g_list_free (messages);
390
391         /* Scroll to the most recent messages */
392         empathy_chat_view_scroll (window->chatview_find, TRUE);
393
394         /* Highlight and find messages */
395         empathy_chat_view_highlight (window->chatview_find,
396                         window->last_find,
397                         FALSE);
398         empathy_chat_view_find_next (window->chatview_find,
399                         window->last_find,
400                         TRUE,
401                         FALSE);
402         empathy_chat_view_find_abilities (window->chatview_find,
403                         window->last_find,
404                         FALSE,
405                         &can_do_previous,
406                         &can_do_next);
407         gtk_widget_set_sensitive (window->button_previous, can_do_previous);
408         gtk_widget_set_sensitive (window->button_next, can_do_next);
409         gtk_widget_set_sensitive (window->button_find, FALSE);
410 }
411 #endif /* ENABLE_TPL */
412
413 static void
414 log_window_find_changed_cb (GtkTreeSelection *selection,
415                             EmpathyLogWindow  *window)
416 {
417         GtkTreeView   *view;
418         GtkTreeModel  *model;
419         GtkTreeIter    iter;
420         TpAccount     *account;
421         gchar         *chat_id;
422         gboolean       is_chatroom;
423         gchar         *date;
424 #ifndef ENABLE_TPL
425         EmpathyMessage *message;
426         GList         *messages;
427         GList         *l;
428         gboolean       can_do_previous;
429         gboolean       can_do_next;
430 #endif /* ENABLE_TPL */
431
432         /* Get selected information */
433         view = GTK_TREE_VIEW (window->treeview_find);
434         model = gtk_tree_view_get_model (view);
435
436         if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
437                 gtk_widget_set_sensitive (window->button_previous, FALSE);
438                 gtk_widget_set_sensitive (window->button_next, FALSE);
439
440                 empathy_chat_view_clear (window->chatview_find);
441
442                 return;
443         }
444
445         gtk_widget_set_sensitive (window->button_previous, TRUE);
446         gtk_widget_set_sensitive (window->button_next, TRUE);
447
448         gtk_tree_model_get (model, &iter,
449                             COL_FIND_ACCOUNT, &account,
450                             COL_FIND_CHAT_ID, &chat_id,
451                             COL_FIND_IS_CHATROOM, &is_chatroom,
452                             COL_FIND_DATE, &date,
453                             -1);
454
455         /* Clear all current messages shown in the textview */
456         empathy_chat_view_clear (window->chatview_find);
457
458         /* Turn off scrolling temporarily */
459         empathy_chat_view_scroll (window->chatview_find, FALSE);
460
461         /* Get messages */
462 #ifndef ENABLE_TPL
463         messages = empathy_log_manager_get_messages_for_date (window->log_manager,
464                                                               account,
465                                                               chat_id,
466                                                               is_chatroom,
467                                                               date);
468 #else
469         tpl_log_manager_get_messages_for_date_async (window->log_manager,
470                                                               account,
471                                                               chat_id,
472                                                               is_chatroom,
473                                                               date,
474                                                               got_messages_for_date_cb,
475                                                               window);
476 #endif /* ENABLE_TPL */
477         g_object_unref (account);
478         g_free (date);
479         g_free (chat_id);
480
481 #ifndef ENABLE_TPL
482         for (l = messages; l; l = l->next) {
483                 message = l->data;
484                 empathy_chat_view_append_message (window->chatview_find, message);
485                 g_object_unref (message);
486         }
487         g_list_free (messages);
488
489         /* Scroll to the most recent messages */
490         empathy_chat_view_scroll (window->chatview_find, TRUE);
491
492         /* Highlight and find messages */
493         empathy_chat_view_highlight (window->chatview_find,
494                                     window->last_find, FALSE);
495         empathy_chat_view_find_next (window->chatview_find,
496                                     window->last_find,
497                                     TRUE,
498                                     FALSE);
499         empathy_chat_view_find_abilities (window->chatview_find,
500                                          window->last_find,
501                                          FALSE,
502                                          &can_do_previous,
503                                          &can_do_next);
504         gtk_widget_set_sensitive (window->button_previous, can_do_previous);
505         gtk_widget_set_sensitive (window->button_next, can_do_next);
506         gtk_widget_set_sensitive (window->button_find, FALSE);
507 #endif /* ENABLE_TPL */
508 }
509
510
511 #ifdef ENABLE_TPL
512 static void
513 log_manager_searched_new_cb (GObject *manager,
514                              GAsyncResult *result,
515                              gpointer user_data)
516 {
517         GList               *hits;
518         GList               *l;
519         GtkTreeIter          iter;
520         GtkListStore        *store = user_data;
521         GError              *error = NULL;
522
523         hits = tpl_log_manager_search_new_async_finish (result, &error);
524
525         if (error != NULL) {
526                         DEBUG ("%s. Aborting", error->message);
527                         g_error_free (error);
528                         return;
529         }
530
531         for (l = hits; l; l = l->next) {
532                         TplLogSearchHit *hit;
533                         const gchar         *account_name;
534                         const gchar         *account_icon;
535                         gchar               *date_readable;
536
537                         hit = l->data;
538
539                         /* Protect against invalid data (corrupt or old log files. */
540                         if (!hit->account || !hit->chat_id) {
541                                         continue;
542                         }
543
544                         date_readable = tpl_log_manager_get_date_readable (hit->date);
545                         account_name = tp_account_get_display_name (hit->account);
546                         account_icon = tp_account_get_icon_name (hit->account);
547
548                         gtk_list_store_append (store, &iter);
549                         gtk_list_store_set (store, &iter,
550                                         COL_FIND_ACCOUNT_ICON, account_icon,
551                                         COL_FIND_ACCOUNT_NAME, account_name,
552                                         COL_FIND_ACCOUNT, hit->account,
553                                         COL_FIND_CHAT_NAME, hit->chat_id, /* FIXME */
554                                         COL_FIND_CHAT_ID, hit->chat_id,
555                                         COL_FIND_IS_CHATROOM, hit->is_chatroom,
556                                         COL_FIND_DATE, hit->date,
557                                         COL_FIND_DATE_READABLE, date_readable,
558                                         -1);
559
560                         g_free (date_readable);
561
562                         /* FIXME: Update COL_FIND_CHAT_NAME */
563                         if (hit->is_chatroom) {
564                         } else {
565                         }
566         }
567
568         if (hits) {
569                         tpl_log_manager_search_free (hits);
570         }
571 }
572 #endif /* ENABLE_TPL */
573
574
575 static void
576 log_window_find_populate (EmpathyLogWindow *window,
577                           const gchar     *search_criteria)
578 {
579 #ifndef ENABLE_TPL
580         GList              *hits, *l;
581
582 #endif /* ENABLE_TPL */
583         GtkTreeView        *view;
584         GtkTreeModel       *model;
585         GtkTreeSelection   *selection;
586         GtkListStore       *store;
587 #ifndef ENABLE_TPL
588         GtkTreeIter         iter;
589 #endif /* ENABLE_TPL */
590
591         view = GTK_TREE_VIEW (window->treeview_find);
592         model = gtk_tree_view_get_model (view);
593         selection = gtk_tree_view_get_selection (view);
594         store = GTK_LIST_STORE (model);
595
596         empathy_chat_view_clear (window->chatview_find);
597
598         gtk_list_store_clear (store);
599
600         if (EMP_STR_EMPTY (search_criteria)) {
601                 /* Just clear the search. */
602                 return;
603         }
604
605 #ifdef ENABLE_TPL
606         tpl_log_manager_search_new_async (window->log_manager, search_criteria,
607                         log_manager_searched_new_cb, (gpointer) store);
608 #else
609         hits = empathy_log_manager_search_new (window->log_manager, search_criteria);
610
611         for (l = hits; l; l = l->next) {
612                 EmpathyLogSearchHit *hit;
613                 const gchar         *account_name;
614                 const gchar         *account_icon;
615                 gchar               *date_readable;
616
617                 hit = l->data;
618
619                 /* Protect against invalid data (corrupt or old log files. */
620                 if (!hit->account || !hit->chat_id) {
621                         continue;
622                 }
623
624                 date_readable = empathy_log_manager_get_date_readable (hit->date);
625                 account_name = tp_account_get_display_name (hit->account);
626                 account_icon = tp_account_get_icon_name (hit->account);
627
628                 gtk_list_store_append (store, &iter);
629                 gtk_list_store_set (store, &iter,
630                                     COL_FIND_ACCOUNT_ICON, account_icon,
631                                     COL_FIND_ACCOUNT_NAME, account_name,
632                                     COL_FIND_ACCOUNT, hit->account,
633                                     COL_FIND_CHAT_NAME, hit->chat_id, /* FIXME */
634                                     COL_FIND_CHAT_ID, hit->chat_id,
635                                     COL_FIND_IS_CHATROOM, hit->is_chatroom,
636                                     COL_FIND_DATE, hit->date,
637                                     COL_FIND_DATE_READABLE, date_readable,
638                                     -1);
639
640                 g_free (date_readable);
641
642                 /* FIXME: Update COL_FIND_CHAT_NAME */
643                 if (hit->is_chatroom) {
644                 } else {
645                 }
646         }
647
648         if (hits) {
649                 empathy_log_manager_search_free (hits);
650         }
651 #endif /* ENABLE_TPL */
652 }
653
654 static void
655 log_window_find_setup (EmpathyLogWindow *window)
656 {
657         GtkTreeView       *view;
658         GtkTreeModel      *model;
659         GtkTreeSelection  *selection;
660         GtkTreeSortable   *sortable;
661         GtkTreeViewColumn *column;
662         GtkListStore      *store;
663         GtkCellRenderer   *cell;
664         gint               offset;
665
666         view = GTK_TREE_VIEW (window->treeview_find);
667         selection = gtk_tree_view_get_selection (view);
668
669         /* New store */
670         store = gtk_list_store_new (COL_FIND_COUNT,
671                                     G_TYPE_STRING,          /* account icon name */
672                                     G_TYPE_STRING,          /* account name */
673                                     TP_TYPE_ACCOUNT,        /* account */
674                                     G_TYPE_STRING,          /* chat name */
675                                     G_TYPE_STRING,          /* chat id */
676                                     G_TYPE_BOOLEAN,         /* is chatroom */
677                                     G_TYPE_STRING,          /* date */
678                                     G_TYPE_STRING);         /* date_readable */
679
680         model = GTK_TREE_MODEL (store);
681         sortable = GTK_TREE_SORTABLE (store);
682
683         gtk_tree_view_set_model (view, model);
684
685         /* New column */
686         column = gtk_tree_view_column_new ();
687
688         cell = gtk_cell_renderer_pixbuf_new ();
689         gtk_tree_view_column_pack_start (column, cell, FALSE);
690         gtk_tree_view_column_add_attribute (column, cell,
691                                             "icon-name",
692                                             COL_FIND_ACCOUNT_ICON);
693
694         cell = gtk_cell_renderer_text_new ();
695         gtk_tree_view_column_pack_start (column, cell, TRUE);
696         gtk_tree_view_column_add_attribute (column, cell,
697                                             "text",
698                                             COL_FIND_ACCOUNT_NAME);
699
700         gtk_tree_view_column_set_title (column, _("Account"));
701         gtk_tree_view_append_column (view, column);
702
703         gtk_tree_view_column_set_resizable (column, TRUE);
704         gtk_tree_view_column_set_clickable (column, TRUE);
705
706         cell = gtk_cell_renderer_text_new ();
707         offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Conversation"),
708                                                               cell, "text", COL_FIND_CHAT_NAME,
709                                                               NULL);
710
711         column = gtk_tree_view_get_column (view, offset - 1);
712         gtk_tree_view_column_set_sort_column_id (column, COL_FIND_CHAT_NAME);
713         gtk_tree_view_column_set_resizable (column, TRUE);
714         gtk_tree_view_column_set_clickable (column, TRUE);
715
716         cell = gtk_cell_renderer_text_new ();
717         offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Date"),
718                                                               cell, "text", COL_FIND_DATE_READABLE,
719                                                               NULL);
720
721         column = gtk_tree_view_get_column (view, offset - 1);
722         gtk_tree_view_column_set_sort_column_id (column, COL_FIND_DATE);
723         gtk_tree_view_column_set_resizable (column, TRUE);
724         gtk_tree_view_column_set_clickable (column, TRUE);
725
726         /* Set up treeview properties */
727         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
728         gtk_tree_sortable_set_sort_column_id (sortable,
729                                               COL_FIND_DATE,
730                                               GTK_SORT_ASCENDING);
731
732         /* Set up signals */
733         g_signal_connect (selection, "changed",
734                           G_CALLBACK (log_window_find_changed_cb),
735                           window);
736
737         g_object_unref (store);
738 }
739
740 static void
741 log_window_button_find_clicked_cb (GtkWidget       *widget,
742                                    EmpathyLogWindow *window)
743 {
744         const gchar *str;
745
746         str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
747
748         /* Don't find the same crap again */
749         if (window->last_find && strcmp (window->last_find, str) == 0) {
750                 return;
751         }
752
753         g_free (window->last_find);
754         window->last_find = g_strdup (str);
755
756         log_window_find_populate (window, str);
757 }
758
759 static void
760 log_window_button_next_clicked_cb (GtkWidget       *widget,
761                                    EmpathyLogWindow *window)
762 {
763         if (window->last_find) {
764                 gboolean can_do_previous;
765                 gboolean can_do_next;
766
767                 empathy_chat_view_find_next (window->chatview_find,
768                                             window->last_find,
769                                             FALSE,
770                                             FALSE);
771                 empathy_chat_view_find_abilities (window->chatview_find,
772                                                  window->last_find,
773                                                  FALSE,
774                                                  &can_do_previous,
775                                                  &can_do_next);
776                 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
777                 gtk_widget_set_sensitive (window->button_next, can_do_next);
778         }
779 }
780
781 static void
782 log_window_button_previous_clicked_cb (GtkWidget       *widget,
783                                        EmpathyLogWindow *window)
784 {
785         if (window->last_find) {
786                 gboolean can_do_previous;
787                 gboolean can_do_next;
788
789                 empathy_chat_view_find_previous (window->chatview_find,
790                                                 window->last_find,
791                                                 FALSE,
792                                                 FALSE);
793                 empathy_chat_view_find_abilities (window->chatview_find,
794                                                  window->last_find,
795                                                  FALSE,
796                                                  &can_do_previous,
797                                                  &can_do_next);
798                 gtk_widget_set_sensitive (window->button_previous, can_do_previous);
799                 gtk_widget_set_sensitive (window->button_next, can_do_next);
800         }
801 }
802
803 /*
804  * Chats Code
805  */
806
807 static void
808 log_window_chats_changed_cb (GtkTreeSelection *selection,
809                              EmpathyLogWindow  *window)
810 {
811         /* Use last date by default */
812         gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
813
814         log_window_chats_get_messages (window, NULL);
815 }
816
817 #ifdef ENABLE_TPL
818 static void
819 log_manager_got_chats_cb (GObject *manager,
820                        GAsyncResult *result,
821                        gpointer user_data)
822 {
823         EmpathyLogWindow      *window = user_data;
824         GList                 *chats;
825         GList                 *l;
826         EmpathyAccountChooser *account_chooser;
827         TpAccount             *account;
828         GtkTreeView           *view;
829         GtkTreeModel          *model;
830         GtkTreeSelection      *selection;
831         GtkListStore          *store;
832         GtkTreeIter            iter;
833         GError                *error = NULL;
834
835         chats = tpl_log_manager_get_chats_async_finish (result, &error);
836
837         if (error != NULL) {
838                         DEBUG ("%s. Aborting", error->message);
839                         g_error_free (error);
840                         return;
841         }
842
843         account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
844         account = empathy_account_chooser_dup_account (account_chooser);
845
846         view = GTK_TREE_VIEW (window->treeview_chats);
847         model = gtk_tree_view_get_model (view);
848         selection = gtk_tree_view_get_selection (view);
849         store = GTK_LIST_STORE (model);
850
851         for (l = chats; l; l = l->next) {
852                         TplLogSearchHit *hit;
853
854                         hit = l->data;
855
856                         gtk_list_store_append (store, &iter);
857                         gtk_list_store_set (store, &iter,
858                                         COL_CHAT_ICON, "empathy-available", /* FIXME */
859                                         COL_CHAT_NAME, hit->chat_id,
860                                         COL_CHAT_ACCOUNT, account,
861                                         COL_CHAT_ID, hit->chat_id,
862                                         COL_CHAT_IS_CHATROOM, hit->is_chatroom,
863                                         -1);
864
865                         /* FIXME: Update COL_CHAT_ICON/NAME */
866                         if (hit->is_chatroom) {
867                         } else {
868                         }
869         }
870         tpl_log_manager_search_free (chats);
871
872         /* Unblock signals */
873         g_signal_handlers_unblock_by_func (selection,
874                         log_window_chats_changed_cb,
875                         window);
876
877         g_object_unref (account);
878 }
879 #endif /* ENABLE_TPL */
880
881
882 static void
883 log_window_chats_populate (EmpathyLogWindow *window)
884 {
885         EmpathyAccountChooser *account_chooser;
886         TpAccount             *account;
887 #ifndef ENABLE_TPL
888         GList                *chats, *l;
889 #endif /* ENABLE_TPL */
890
891         GtkTreeView          *view;
892         GtkTreeModel         *model;
893         GtkTreeSelection     *selection;
894         GtkListStore         *store;
895 #ifndef ENABLE_TPL
896         GtkTreeIter           iter;
897 #endif /* ENABLE_TPL */
898
899         account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
900         account = empathy_account_chooser_dup_account (account_chooser);
901
902         view = GTK_TREE_VIEW (window->treeview_chats);
903         model = gtk_tree_view_get_model (view);
904         selection = gtk_tree_view_get_selection (view);
905         store = GTK_LIST_STORE (model);
906
907         if (account == NULL) {
908                 gtk_list_store_clear (store);
909                 return;
910         }
911
912         /* Block signals to stop the logs being retrieved prematurely */
913         g_signal_handlers_block_by_func (selection,
914                                          log_window_chats_changed_cb,
915                                          window);
916
917         gtk_list_store_clear (store);
918
919 #ifdef ENABLE_TPL
920         tpl_log_manager_get_chats_async (window->log_manager, account,
921                         log_manager_got_chats_cb, (gpointer) window);
922 #else
923         chats = empathy_log_manager_get_chats (window->log_manager, account);
924         for (l = chats; l; l = l->next) {
925                 EmpathyLogSearchHit *hit;
926
927                 hit = l->data;
928
929                 gtk_list_store_append (store, &iter);
930                 gtk_list_store_set (store, &iter,
931                                     COL_CHAT_ICON, "empathy-available", /* FIXME */
932                                     COL_CHAT_NAME, hit->chat_id,
933                                     COL_CHAT_ACCOUNT, account,
934                                     COL_CHAT_ID, hit->chat_id,
935                                     COL_CHAT_IS_CHATROOM, hit->is_chatroom,
936                                     -1);
937
938                 /* FIXME: Update COL_CHAT_ICON/NAME */
939                 if (hit->is_chatroom) {
940                 } else {
941                 }
942         }
943         empathy_log_manager_search_free (chats);
944
945         /* Unblock signals */
946         g_signal_handlers_unblock_by_func (selection,
947                                            log_window_chats_changed_cb,
948                                            window);
949
950
951         g_object_unref (account);
952 #endif /* ENABLE_TPL */
953 }
954
955 static void
956 log_window_chats_setup (EmpathyLogWindow *window)
957 {
958         GtkTreeView       *view;
959         GtkTreeModel      *model;
960         GtkTreeSelection  *selection;
961         GtkTreeSortable   *sortable;
962         GtkTreeViewColumn *column;
963         GtkListStore      *store;
964         GtkCellRenderer   *cell;
965
966         view = GTK_TREE_VIEW (window->treeview_chats);
967         selection = gtk_tree_view_get_selection (view);
968
969         /* new store */
970         store = gtk_list_store_new (COL_CHAT_COUNT,
971                                     G_TYPE_STRING,        /* icon */
972                                     G_TYPE_STRING,        /* name */
973                                     TP_TYPE_ACCOUNT,      /* account */
974                                     G_TYPE_STRING,        /* id */
975                                     G_TYPE_BOOLEAN);      /* is chatroom */
976
977         model = GTK_TREE_MODEL (store);
978         sortable = GTK_TREE_SORTABLE (store);
979
980         gtk_tree_view_set_model (view, model);
981
982         /* new column */
983         column = gtk_tree_view_column_new ();
984
985         cell = gtk_cell_renderer_pixbuf_new ();
986         gtk_tree_view_column_pack_start (column, cell, FALSE);
987         gtk_tree_view_column_add_attribute (column, cell,
988                                             "icon-name",
989                                             COL_CHAT_ICON);
990
991         cell = gtk_cell_renderer_text_new ();
992         g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
993         gtk_tree_view_column_pack_start (column, cell, TRUE);
994         gtk_tree_view_column_add_attribute (column, cell,
995                                             "text",
996                                             COL_CHAT_NAME);
997
998         gtk_tree_view_append_column (view, column);
999
1000         /* set up treeview properties */
1001         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
1002         gtk_tree_sortable_set_sort_column_id (sortable,
1003                                               COL_CHAT_NAME,
1004                                               GTK_SORT_ASCENDING);
1005
1006         /* set up signals */
1007         g_signal_connect (selection, "changed",
1008                           G_CALLBACK (log_window_chats_changed_cb),
1009                           window);
1010
1011         g_object_unref (store);
1012 }
1013
1014 static void
1015 log_window_chats_accounts_changed_cb (GtkWidget       *combobox,
1016                                       EmpathyLogWindow *window)
1017 {
1018         /* Clear all current messages shown in the textview */
1019         empathy_chat_view_clear (window->chatview_chats);
1020
1021         log_window_chats_populate (window);
1022 }
1023
1024 static void
1025 log_window_chats_set_selected  (EmpathyLogWindow *window,
1026                                 TpAccount        *account,
1027                                 const gchar     *chat_id,
1028                                 gboolean         is_chatroom)
1029 {
1030         EmpathyAccountChooser *account_chooser;
1031         GtkTreeView          *view;
1032         GtkTreeModel         *model;
1033         GtkTreeSelection     *selection;
1034         GtkTreeIter           iter;
1035         GtkTreePath          *path;
1036         gboolean              ok;
1037
1038         account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
1039         empathy_account_chooser_set_account (account_chooser, account);
1040
1041         view = GTK_TREE_VIEW (window->treeview_chats);
1042         model = gtk_tree_view_get_model (view);
1043         selection = gtk_tree_view_get_selection (view);
1044
1045         if (!gtk_tree_model_get_iter_first (model, &iter)) {
1046                 return;
1047         }
1048
1049         for (ok = TRUE; ok; ok = gtk_tree_model_iter_next (model, &iter)) {
1050                 TpAccount *this_account;
1051                 gchar     *this_chat_id;
1052                 gboolean   this_is_chatroom;
1053
1054                 gtk_tree_model_get (model, &iter,
1055                                     COL_CHAT_ACCOUNT, &this_account,
1056                                     COL_CHAT_ID, &this_chat_id,
1057                                     COL_CHAT_IS_CHATROOM, &this_is_chatroom,
1058                                     -1);
1059
1060                 if (this_account == account &&
1061                     strcmp (this_chat_id, chat_id) == 0 &&
1062                     this_is_chatroom == is_chatroom) {
1063                         gtk_tree_selection_select_iter (selection, &iter);
1064                         path = gtk_tree_model_get_path (model, &iter);
1065                         gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
1066                         gtk_tree_path_free (path);
1067                         g_object_unref (this_account);
1068                         g_free (this_chat_id);
1069                         break;
1070                 }
1071
1072                 g_object_unref (this_account);
1073                 g_free (this_chat_id);
1074         }
1075 }
1076
1077 static gboolean
1078 log_window_chats_get_selected (EmpathyLogWindow  *window,
1079                                TpAccount       **account,
1080                                gchar           **chat_id,
1081                                gboolean         *is_chatroom)
1082 {
1083         GtkTreeView      *view;
1084         GtkTreeModel     *model;
1085         GtkTreeSelection *selection;
1086         GtkTreeIter       iter;
1087         gchar            *id = NULL;
1088         TpAccount        *acc = NULL;
1089         gboolean          room = FALSE;
1090
1091         view = GTK_TREE_VIEW (window->treeview_chats);
1092         model = gtk_tree_view_get_model (view);
1093         selection = gtk_tree_view_get_selection (view);
1094
1095         if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
1096                 return FALSE;
1097         }
1098
1099         gtk_tree_model_get (model, &iter,
1100                             COL_CHAT_ACCOUNT, &acc,
1101                             COL_CHAT_ID, &id,
1102                             COL_CHAT_IS_CHATROOM, &room,
1103                             -1);
1104
1105         if (chat_id) {
1106                 *chat_id = id;
1107         } else {
1108                 g_free (id);
1109         }
1110         if (account) {
1111                 *account = acc;
1112         } else {
1113                 g_object_unref (acc);
1114         }
1115         if (is_chatroom) {
1116                 *is_chatroom = room;
1117         }
1118
1119         return TRUE;
1120 }
1121
1122 #ifdef ENABLE_TPL
1123 static void
1124 log_window_got_messages_for_date_cb (GObject *manager,
1125     GAsyncResult *result,
1126     gpointer user_data)
1127 {
1128   EmpathyLogWindow *window = user_data;
1129   GList *messages;
1130   GList *l;
1131   GError *error = NULL;
1132
1133   messages = tpl_log_manager_get_messages_for_date_async_finish (result, &error);
1134
1135   if (error != NULL) {
1136       DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
1137           error->message);
1138       empathy_chat_view_append_event (window->chatview_find,
1139           "Unable to retrieve messages for the selected date");
1140       g_error_free (error);
1141       return;
1142   }
1143
1144   for (l = messages; l; l = l->next) {
1145       EmpathyMessage *message = empathy_message_from_tpl_log_entry (l->data);
1146       g_object_unref (l->data);
1147       empathy_chat_view_append_message (window->chatview_chats,
1148           message);
1149       g_object_unref (message);
1150   }
1151   g_list_free (messages);
1152
1153   /* Turn back on scrolling */
1154   empathy_chat_view_scroll (window->chatview_find, TRUE);
1155
1156   /* Give the search entry main focus */
1157   gtk_widget_grab_focus (window->entry_chats);
1158 }
1159
1160
1161 static void
1162 log_window_get_messages_for_date (EmpathyLogWindow *window,
1163                                  const gchar *date)
1164 {
1165   TpAccount *account;
1166   gchar *chat_id;
1167   gboolean is_chatroom;
1168
1169   gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
1170
1171   if (!log_window_chats_get_selected (window, &account,
1172         &chat_id, &is_chatroom)) {
1173       return;
1174   }
1175
1176   /* Clear all current messages shown in the textview */
1177   empathy_chat_view_clear (window->chatview_chats);
1178
1179   /* Turn off scrolling temporarily */
1180   empathy_chat_view_scroll (window->chatview_find, FALSE);
1181
1182   /* Get messages */
1183   tpl_log_manager_get_messages_for_date_async (window->log_manager,
1184       account, chat_id,
1185       is_chatroom,
1186       date,
1187       log_window_got_messages_for_date_cb,
1188       (gpointer) window);
1189 }
1190
1191 static void
1192 log_manager_got_dates_cb (GObject *manager,
1193                           GAsyncResult *result,
1194                           gpointer user_data)
1195 {
1196   EmpathyLogWindow *window = user_data;
1197   GList         *dates;
1198   GList         *l;
1199   guint          year_selected;
1200   guint          year;
1201   guint          month;
1202   guint          month_selected;
1203   guint          day;
1204   gboolean       day_selected = FALSE;
1205   const gchar   *date = NULL;
1206   GError        *error = NULL;
1207
1208   dates = tpl_log_manager_get_dates_async_finish (result, &error);
1209
1210   if (error != NULL) {
1211     DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
1212         error->message);
1213     empathy_chat_view_append_event (window->chatview_find,
1214         "Unable to retrieve messages' dates");
1215       return;
1216   }
1217
1218   for (l = dates; l; l = l->next) {
1219       const gchar *str;
1220
1221       str = l->data;
1222       if (!str) {
1223           continue;
1224       }
1225
1226       sscanf (str, "%4d%2d%2d", &year, &month, &day);
1227       gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1228           &year_selected,
1229           &month_selected,
1230           NULL);
1231
1232       month_selected++;
1233
1234       if (!l->next) {
1235           date = str;
1236       }
1237
1238       if (year != year_selected || month != month_selected) {
1239           continue;
1240       }
1241
1242       DEBUG ("Marking date:'%s'", str);
1243       gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), day);
1244
1245       if (l->next) {
1246           continue;
1247       }
1248
1249       day_selected = TRUE;
1250
1251       gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
1252   }
1253
1254   if (!day_selected) {
1255       /* Unselect the day in the calendar */
1256       gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), 0);
1257   }
1258
1259   g_signal_handlers_unblock_by_func (window->calendar_chats,
1260       log_window_calendar_chats_day_selected_cb,
1261       window);
1262
1263   if (date) {
1264       log_window_get_messages_for_date (window, date);
1265   }
1266
1267   g_list_foreach (dates, (GFunc) g_free, NULL);
1268   g_list_free (dates);
1269 }
1270
1271
1272 static void
1273 log_window_chats_get_messages (EmpathyLogWindow *window,
1274                                const gchar     *date_to_show)
1275 {
1276         TpAccount     *account;
1277         gchar         *chat_id;
1278         gboolean       is_chatroom;
1279         const gchar   *date;
1280         guint          year_selected;
1281         guint          year;
1282         guint          month;
1283         guint          month_selected;
1284         guint          day;
1285
1286
1287         if (!log_window_chats_get_selected (window, &account,
1288                                             &chat_id, &is_chatroom)) {
1289                 return;
1290         }
1291
1292         g_signal_handlers_block_by_func (window->calendar_chats,
1293                                          log_window_calendar_chats_day_selected_cb,
1294                                          window);
1295
1296         /* Either use the supplied date or get the last */
1297         date = date_to_show;
1298         if (!date) {
1299                 /* Get a list of dates and show them on the calendar */
1300                 tpl_log_manager_get_dates_async (window->log_manager,
1301                                                        account, chat_id,
1302                                                        is_chatroom,
1303                                                        log_manager_got_dates_cb, (gpointer) window);
1304     /* signal unblocked at the end of the CB flow */
1305         } else {
1306                 sscanf (date, "%4d%2d%2d", &year, &month, &day);
1307                 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1308                                 &year_selected,
1309                                 &month_selected,
1310                                 NULL);
1311
1312                 month_selected++;
1313
1314                 if (year != year_selected && month != month_selected) {
1315                         day = 0;
1316                 }
1317
1318                 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
1319
1320     g_signal_handlers_unblock_by_func (window->calendar_chats,
1321         log_window_calendar_chats_day_selected_cb,
1322         window);
1323         }
1324
1325         if (date) {
1326       log_window_get_messages_for_date (window, date);
1327         }
1328
1329         g_object_unref (account);
1330         g_free (chat_id);
1331 }
1332
1333 #else
1334
1335 static void
1336 log_window_chats_get_messages (EmpathyLogWindow *window,
1337                                const gchar     *date_to_show)
1338 {
1339         TpAccount     *account;
1340         gchar         *chat_id;
1341         gboolean       is_chatroom;
1342         EmpathyMessage *message;
1343         GList         *messages;
1344         GList         *dates = NULL;
1345         GList         *l;
1346         const gchar   *date;
1347         guint          year_selected;
1348         guint          year;
1349         guint          month;
1350         guint          month_selected;
1351         guint          day;
1352
1353         if (!log_window_chats_get_selected (window, &account,
1354                                             &chat_id, &is_chatroom)) {
1355                 return;
1356         }
1357
1358         g_signal_handlers_block_by_func (window->calendar_chats,
1359                                          log_window_calendar_chats_day_selected_cb,
1360                                          window);
1361
1362         /* Either use the supplied date or get the last */
1363         date = date_to_show;
1364         if (!date) {
1365                 gboolean day_selected = FALSE;
1366
1367                 /* Get a list of dates and show them on the calendar */
1368                 dates = empathy_log_manager_get_dates (window->log_manager,
1369                                                        account, chat_id,
1370                                                        is_chatroom);
1371
1372                 for (l = dates; l; l = l->next) {
1373                         const gchar *str;
1374
1375                         str = l->data;
1376                         if (!str) {
1377                                 continue;
1378                         }
1379
1380                         sscanf (str, "%4d%2d%2d", &year, &month, &day);
1381                         gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1382                                                &year_selected,
1383                                                &month_selected,
1384                                                NULL);
1385
1386                         month_selected++;
1387
1388                         if (!l->next) {
1389                                 date = str;
1390                         }
1391
1392                         if (year != year_selected || month != month_selected) {
1393                                 continue;
1394                         }
1395
1396
1397                         DEBUG ("Marking date:'%s'", str);
1398                         gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), day);
1399
1400                         if (l->next) {
1401                                 continue;
1402                         }
1403
1404                         day_selected = TRUE;
1405
1406                         gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
1407                 }
1408
1409                 if (!day_selected) {
1410                         /* Unselect the day in the calendar */
1411                         gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), 0);
1412                 }
1413         } else {
1414                 sscanf (date, "%4d%2d%2d", &year, &month, &day);
1415                 gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
1416                                        &year_selected,
1417                                        &month_selected,
1418                                        NULL);
1419
1420                 month_selected++;
1421
1422                 if (year != year_selected && month != month_selected) {
1423                         day = 0;
1424                 }
1425
1426                 gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
1427         }
1428
1429         g_signal_handlers_unblock_by_func (window->calendar_chats,
1430                                            log_window_calendar_chats_day_selected_cb,
1431                                            window);
1432
1433         if (!date) {
1434                 goto OUT;
1435         }
1436
1437         /* Clear all current messages shown in the textview */
1438         empathy_chat_view_clear (window->chatview_chats);
1439
1440         /* Turn off scrolling temporarily */
1441         empathy_chat_view_scroll (window->chatview_find, FALSE);
1442
1443         /* Get messages */
1444         messages = empathy_log_manager_get_messages_for_date (window->log_manager,
1445                                                               account, chat_id,
1446                                                               is_chatroom,
1447                                                               date);
1448
1449         for (l = messages; l; l = l->next) {
1450                 message = l->data;
1451
1452                 empathy_chat_view_append_message (window->chatview_chats,
1453                                                  message);
1454                 g_object_unref (message);
1455         }
1456         g_list_free (messages);
1457
1458         /* Turn back on scrolling */
1459         empathy_chat_view_scroll (window->chatview_find, TRUE);
1460
1461         /* Give the search entry main focus */
1462         gtk_widget_grab_focus (window->entry_chats);
1463
1464 OUT:
1465         g_list_foreach (dates, (GFunc) g_free, NULL);
1466         g_list_free (dates);
1467         g_object_unref (account);
1468         g_free (chat_id);
1469 }
1470
1471 #endif /* ENABLE_TPL */
1472
1473 static void
1474 log_window_calendar_chats_day_selected_cb (GtkWidget       *calendar,
1475                                            EmpathyLogWindow *window)
1476 {
1477         guint  year;
1478         guint  month;
1479         guint  day;
1480
1481         gchar *date;
1482
1483         gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
1484
1485         /* We need this hear because it appears that the months start from 0 */
1486         month++;
1487
1488         date = g_strdup_printf ("%4.4d%2.2d%2.2d", year, month, day);
1489
1490         DEBUG ("Currently selected date is:'%s'", date);
1491
1492         log_window_chats_get_messages (window, date);
1493
1494         g_free (date);
1495 }
1496
1497
1498 #ifdef ENABLE_TPL
1499 static void
1500 log_window_updating_calendar_month_cb (GObject *manager,
1501                 GAsyncResult *result, gpointer user_data)
1502 {
1503         EmpathyLogWindow *window = user_data;
1504         GList                                   *dates;
1505         GList                                   *l;
1506         guint                                    year_selected;
1507         guint                                    month_selected;
1508         GError                          *error = NULL;
1509
1510         dates = tpl_log_manager_get_dates_async_finish (result, &error);
1511
1512         if (error != NULL) {
1513                         DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
1514                                         error->message);
1515                         empathy_chat_view_append_event (window->chatview_find,
1516                                         "Unable to retrieve messages' dates");
1517                         g_error_free (error);
1518                         return;
1519         }
1520
1521         gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
1522         g_object_get (window->calendar_chats,
1523                         "month", &month_selected,
1524                         "year", &year_selected,
1525                         NULL);
1526
1527         /* We need this here because it appears that the months start from 0 */
1528         month_selected++;
1529
1530         for (l = dates; l; l = l->next) {
1531                         const gchar *str;
1532                         guint        year;
1533                         guint        month;
1534                         guint        day;
1535
1536                         str = l->data;
1537                         if (!str) {
1538                                         continue;
1539                         }
1540
1541                         sscanf (str, "%4d%2d%2d", &year, &month, &day);
1542
1543                         if (year == year_selected && month == month_selected) {
1544                                         DEBUG ("Marking date:'%s'", str);
1545                                         gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), day);
1546                         }
1547         }
1548
1549         g_list_foreach (dates, (GFunc) g_free, NULL);
1550         g_list_free (dates);
1551
1552         DEBUG ("Currently showing month %d and year %d", month_selected,
1553                         year_selected);
1554 }
1555 #endif /* ENABLE_TPL */
1556
1557
1558 static void
1559 log_window_calendar_chats_month_changed_cb (GtkWidget       *calendar,
1560                                             EmpathyLogWindow *window)
1561 {
1562         TpAccount     *account;
1563         gchar         *chat_id;
1564         gboolean       is_chatroom;
1565 #ifndef ENABLE_TPL
1566         guint          year_selected;
1567         guint          month_selected;
1568
1569         GList         *dates;
1570         GList         *l;
1571 #endif /* ENABLE_TPL */
1572
1573         gtk_calendar_clear_marks (GTK_CALENDAR (calendar));
1574
1575         if (!log_window_chats_get_selected (window, &account,
1576                                             &chat_id, &is_chatroom)) {
1577                 DEBUG ("No chat selected to get dates for...");
1578                 return;
1579         }
1580
1581         /* Get the log object for this contact */
1582 #ifdef ENABLE_TPL
1583         tpl_log_manager_get_dates_async (window->log_manager, account,
1584                                                chat_id, is_chatroom,
1585                                                log_window_updating_calendar_month_cb,
1586                                                (gpointer) window);
1587 #else
1588         dates = empathy_log_manager_get_dates (window->log_manager, account,
1589                                                chat_id, is_chatroom);
1590
1591         g_object_get (calendar,
1592                       "month", &month_selected,
1593                       "year", &year_selected,
1594                       NULL);
1595
1596         /* We need this here because it appears that the months start from 0 */
1597         month_selected++;
1598
1599         for (l = dates; l; l = l->next) {
1600                 const gchar *str;
1601                 guint        year;
1602                 guint        month;
1603                 guint        day;
1604
1605                 str = l->data;
1606                 if (!str) {
1607                         continue;
1608                 }
1609
1610                 sscanf (str, "%4d%2d%2d", &year, &month, &day);
1611
1612                 if (year == year_selected && month == month_selected) {
1613                         DEBUG ("Marking date:'%s'", str);
1614                         gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), day);
1615                 }
1616         }
1617
1618         g_list_foreach (dates, (GFunc) g_free, NULL);
1619         g_list_free (dates);
1620
1621         DEBUG ("Currently showing month %d and year %d", month_selected,
1622                 year_selected);
1623 #endif /* ENABLE_TPL */
1624
1625         g_object_unref (account);
1626         g_free (chat_id);
1627 }
1628
1629 static void
1630 log_window_entry_chats_changed_cb (GtkWidget       *entry,
1631                                    EmpathyLogWindow *window)
1632 {
1633         const gchar *str;
1634
1635         str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1636         empathy_chat_view_highlight (window->chatview_chats, str, FALSE);
1637
1638         if (str) {
1639                 empathy_chat_view_find_next (window->chatview_chats,
1640                                             str,
1641                                             TRUE,
1642                                             FALSE);
1643         }
1644 }
1645
1646 static void
1647 log_window_entry_chats_activate_cb (GtkWidget       *entry,
1648                                     EmpathyLogWindow *window)
1649 {
1650         const gchar *str;
1651
1652         str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
1653
1654         if (str) {
1655                 empathy_chat_view_find_next (window->chatview_chats,
1656                                             str,
1657                                             FALSE,
1658                                             FALSE);
1659         }
1660 }
1661