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