aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk/gossip-log-window.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy-gtk/gossip-log-window.c')
-rw-r--r--libempathy-gtk/gossip-log-window.c1153
1 files changed, 1153 insertions, 0 deletions
diff --git a/libempathy-gtk/gossip-log-window.c b/libempathy-gtk/gossip-log-window.c
new file mode 100644
index 000000000..3ec7cdb1d
--- /dev/null
+++ b/libempathy-gtk/gossip-log-window.c
@@ -0,0 +1,1153 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Martyn Russell <martyn@imendio.com>
+ * Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+#include <libempathy/empathy-log-manager.h>
+#include <libempathy/gossip-chatroom-manager.h>
+#include <libempathy/gossip-chatroom.h>
+#include <libempathy/gossip-message.h>
+#include <libempathy/gossip-debug.h>
+#include <libempathy/gossip-utils.h>
+#include <libempathy/gossip-time.h>
+
+#include "gossip-log-window.h"
+#include "gossip-account-chooser.h"
+#include "gossip-chat-view.h"
+#include "gossip-ui-utils.h"
+
+#define DEBUG_DOMAIN "LogWindow"
+
+typedef struct {
+ GtkWidget *window;
+
+ GtkWidget *notebook;
+
+ GtkWidget *entry_find;
+ GtkWidget *button_find;
+ GtkWidget *treeview_find;
+ GtkWidget *scrolledwindow_find;
+ GossipChatView *chatview_find;
+ GtkWidget *button_previous;
+ GtkWidget *button_next;
+
+ GtkWidget *vbox_chats;
+ GtkWidget *account_chooser_chats;
+ GtkWidget *entry_chats;
+ GtkWidget *calendar_chats;
+ GtkWidget *treeview_chats;
+ GtkWidget *scrolledwindow_chats;
+ GossipChatView *chatview_chats;
+
+ gchar *last_find;
+
+ EmpathyLogManager *log_manager;
+} GossipLogWindow;
+
+static void
+log_window_destroy_cb (GtkWidget *widget,
+ GossipLogWindow *window);
+static void
+log_window_entry_find_changed_cb (GtkWidget *entry,
+ GossipLogWindow *window);
+static void
+log_window_find_changed_cb (GtkTreeSelection *selection,
+ GossipLogWindow *window);
+static void
+log_window_find_populate (GossipLogWindow *window,
+ const gchar *search_criteria);
+static void
+log_window_find_setup (GossipLogWindow *window);
+static void
+log_window_button_find_clicked_cb (GtkWidget *widget,
+ GossipLogWindow *window);
+static void
+log_window_button_next_clicked_cb (GtkWidget *widget,
+ GossipLogWindow *window);
+static void
+log_window_button_previous_clicked_cb (GtkWidget *widget,
+ GossipLogWindow *window);
+static void
+log_window_chats_changed_cb (GtkTreeSelection *selection,
+ GossipLogWindow *window);
+static void
+log_window_chats_populate (GossipLogWindow *window);
+static void
+log_window_chats_setup (GossipLogWindow *window);
+static void
+log_window_chats_accounts_changed_cb (GtkWidget *combobox,
+ GossipLogWindow *window);
+static void
+log_window_chats_new_message_cb (GossipContact *own_contact,
+ GossipMessage *message,
+ GossipLogWindow *window);
+//static gboolean
+//log_window_chats_is_today_selected (GossipLogWindow *window);
+static void
+log_window_chats_set_selected (GossipLogWindow *window,
+ McAccount *account,
+ const gchar *chat_id,
+ gboolean is_chatroom);
+static gboolean
+log_window_chats_get_selected (GossipLogWindow *window,
+ McAccount **account,
+ gchar **chat_id,
+ gboolean *is_chatroom);
+static void
+log_window_chats_get_messages (GossipLogWindow *window,
+ const gchar *date_to_show);
+static void
+log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
+ GossipLogWindow *window);
+static void
+log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
+ GossipLogWindow *window);
+static void
+log_window_entry_chats_changed_cb (GtkWidget *entry,
+ GossipLogWindow *window);
+static void
+log_window_entry_chats_activate_cb (GtkWidget *entry,
+ GossipLogWindow *window);
+
+enum {
+ COL_FIND_ACCOUNT_ICON,
+ COL_FIND_ACCOUNT_NAME,
+ COL_FIND_ACCOUNT,
+ COL_FIND_CHAT_NAME,
+ COL_FIND_CHAT_ID,
+ COL_FIND_IS_CHATROOM,
+ COL_FIND_DATE,
+ COL_FIND_DATE_READABLE,
+ COL_FIND_COUNT
+};
+
+enum {
+ COL_CHAT_ICON,
+ COL_CHAT_NAME,
+ COL_CHAT_ACCOUNT,
+ COL_CHAT_ID,
+ COL_CHAT_IS_CHATROOM,
+ COL_CHAT_COUNT
+};
+
+void
+gossip_log_window_show (McAccount *account,
+ const gchar *chat_id,
+ gboolean is_chatroom,
+ GtkWindow *parent)
+{
+ static GossipLogWindow *window = NULL;
+ GossipAccountChooser *account_chooser;
+ GList *accounts;
+ gint account_num;
+ GladeXML *glade;
+
+ if (window) {
+ gtk_window_present (GTK_WINDOW (window->window));
+
+ if (account && chat_id) {
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
+ log_window_chats_set_selected (window, account,
+ chat_id, is_chatroom);
+ }
+
+ return;
+ }
+
+ window = g_new0 (GossipLogWindow, 1);
+ window->log_manager = empathy_log_manager_new ();
+
+ glade = gossip_glade_get_file ("gossip-log-window.glade",
+ "log_window",
+ NULL,
+ "log_window", &window->window,
+ "notebook", &window->notebook,
+ "entry_find", &window->entry_find,
+ "button_find", &window->button_find,
+ "treeview_find", &window->treeview_find,
+ "scrolledwindow_find", &window->scrolledwindow_find,
+ "button_previous", &window->button_previous,
+ "button_next", &window->button_next,
+ "entry_chats", &window->entry_chats,
+ "calendar_chats", &window->calendar_chats,
+ "vbox_chats", &window->vbox_chats,
+ "treeview_chats", &window->treeview_chats,
+ "scrolledwindow_chats", &window->scrolledwindow_chats,
+ NULL);
+ gossip_glade_connect (glade,
+ window,
+ "log_window", "destroy", log_window_destroy_cb,
+ "entry_find", "changed", log_window_entry_find_changed_cb,
+ "button_previous", "clicked", log_window_button_previous_clicked_cb,
+ "button_next", "clicked", log_window_button_next_clicked_cb,
+ "button_find", "clicked", log_window_button_find_clicked_cb,
+ "entry_chats", "changed", log_window_entry_chats_changed_cb,
+ "entry_chats", "activate", log_window_entry_chats_activate_cb,
+ NULL);
+
+ g_object_unref (glade);
+
+ g_object_add_weak_pointer (G_OBJECT (window->window),
+ (gpointer) &window);
+
+ /* We set this up here so we can block it when needed. */
+ g_signal_connect (window->calendar_chats, "day-selected",
+ G_CALLBACK (log_window_calendar_chats_day_selected_cb),
+ window);
+ g_signal_connect (window->calendar_chats, "month-changed",
+ G_CALLBACK (log_window_calendar_chats_month_changed_cb),
+ window);
+
+ /* Configure Search GossipChatView */
+ window->chatview_find = gossip_chat_view_new ();
+ gtk_container_add (GTK_CONTAINER (window->scrolledwindow_find),
+ GTK_WIDGET (window->chatview_find));
+ gtk_widget_show (GTK_WIDGET (window->chatview_find));
+
+ /* Configure Contacts GossipChatView */
+ window->chatview_chats = gossip_chat_view_new ();
+ gtk_container_add (GTK_CONTAINER (window->scrolledwindow_chats),
+ GTK_WIDGET (window->chatview_chats));
+ gtk_widget_show (GTK_WIDGET (window->chatview_chats));
+
+ /* Account chooser for chats */
+ window->account_chooser_chats = gossip_account_chooser_new ();
+ account_chooser = GOSSIP_ACCOUNT_CHOOSER (window->account_chooser_chats);
+ gossip_account_chooser_set_can_select_all (account_chooser, TRUE);
+
+ gtk_box_pack_start (GTK_BOX (window->vbox_chats),
+ window->account_chooser_chats,
+ FALSE, TRUE, 0);
+
+ g_signal_connect (window->account_chooser_chats, "changed",
+ G_CALLBACK (log_window_chats_accounts_changed_cb),
+ window);
+
+ /* Populate */
+ accounts = mc_accounts_list ();
+ account_num = g_list_length (accounts);
+ mc_accounts_list_free (accounts);
+
+ if (account_num > 1) {
+ gtk_widget_show (window->vbox_chats);
+ gtk_widget_show (window->account_chooser_chats);
+ } else {
+ gtk_widget_hide (window->vbox_chats);
+ gtk_widget_hide (window->account_chooser_chats);
+ }
+
+ /* Search List */
+ log_window_find_setup (window);
+
+ /* Contacts */
+ log_window_chats_setup (window);
+ log_window_chats_populate (window);
+
+ /* Select chat */
+ if (account && chat_id) {
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
+ log_window_chats_set_selected (window, account,
+ chat_id, is_chatroom);
+ }
+
+ if (parent) {
+ gtk_window_set_transient_for (GTK_WINDOW (window->window),
+ GTK_WINDOW (parent));
+ }
+
+ gtk_widget_show (window->window);
+}
+
+static void
+log_window_destroy_cb (GtkWidget *widget,
+ GossipLogWindow *window)
+{
+ g_signal_handlers_disconnect_by_func (window->log_manager,
+ log_window_chats_new_message_cb,
+ window);
+
+ g_free (window->last_find);
+ g_object_unref (window->log_manager);
+
+ g_free (window);
+}
+
+/*
+ * Search code.
+ */
+static void
+log_window_entry_find_changed_cb (GtkWidget *entry,
+ GossipLogWindow *window)
+{
+ const gchar *str;
+ gboolean is_sensitive = TRUE;
+
+ str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
+
+ is_sensitive &= !G_STR_EMPTY (str);
+ is_sensitive &=
+ !window->last_find ||
+ (window->last_find && strcmp (window->last_find, str) != 0);
+
+ gtk_widget_set_sensitive (window->button_find, is_sensitive);
+}
+
+static void
+log_window_find_changed_cb (GtkTreeSelection *selection,
+ GossipLogWindow *window)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ McAccount *account;
+ gchar *chat_id;
+ gboolean is_chatroom;
+ gchar *date;
+ GossipMessage *message;
+ GList *messages;
+ GList *l;
+ gboolean can_do_previous;
+ gboolean can_do_next;
+
+ /* Get selected information */
+ view = GTK_TREE_VIEW (window->treeview_find);
+ model = gtk_tree_view_get_model (view);
+
+ if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ gtk_widget_set_sensitive (window->button_previous, FALSE);
+ gtk_widget_set_sensitive (window->button_next, FALSE);
+
+ gossip_chat_view_clear (window->chatview_find);
+
+ return;
+ }
+
+ gtk_widget_set_sensitive (window->button_previous, TRUE);
+ gtk_widget_set_sensitive (window->button_next, TRUE);
+
+ gtk_tree_model_get (model, &iter,
+ COL_FIND_ACCOUNT, &account,
+ COL_FIND_CHAT_ID, &chat_id,
+ COL_FIND_IS_CHATROOM, &is_chatroom,
+ COL_FIND_DATE, &date,
+ -1);
+
+ /* Clear all current messages shown in the textview */
+ gossip_chat_view_clear (window->chatview_find);
+
+ /* Turn off scrolling temporarily */
+ gossip_chat_view_scroll (window->chatview_find, FALSE);
+
+ /* Get messages */
+ messages = empathy_log_manager_get_messages_for_date (window->log_manager,
+ account,
+ chat_id,
+ is_chatroom,
+ date);
+ g_object_unref (account);
+ g_free (date);
+ g_free (chat_id);
+
+ for (l = messages; l; l = l->next) {
+ message = l->data;
+ gossip_chat_view_append_message (window->chatview_find, message);
+ g_object_unref (message);
+ }
+ g_list_free (messages);
+
+ /* Scroll to the most recent messages */
+ gossip_chat_view_scroll (window->chatview_find, TRUE);
+
+ /* Highlight and find messages */
+ gossip_chat_view_highlight (window->chatview_find,
+ window->last_find);
+ gossip_chat_view_find_next (window->chatview_find,
+ window->last_find,
+ TRUE);
+ gossip_chat_view_find_abilities (window->chatview_find,
+ window->last_find,
+ &can_do_previous,
+ &can_do_next);
+ gtk_widget_set_sensitive (window->button_previous, can_do_previous);
+ gtk_widget_set_sensitive (window->button_next, can_do_next);
+ gtk_widget_set_sensitive (window->button_find, FALSE);
+}
+
+static void
+log_window_find_populate (GossipLogWindow *window,
+ const gchar *search_criteria)
+{
+ GList *hits, *l;
+
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkListStore *store;
+ GtkTreeIter iter;
+
+ view = GTK_TREE_VIEW (window->treeview_find);
+ model = gtk_tree_view_get_model (view);
+ selection = gtk_tree_view_get_selection (view);
+ store = GTK_LIST_STORE (model);
+
+ gossip_chat_view_clear (window->chatview_find);
+
+ gtk_list_store_clear (store);
+
+ if (G_STR_EMPTY (search_criteria)) {
+ /* Just clear the search. */
+ return;
+ }
+
+ hits = empathy_log_manager_search_new (window->log_manager, search_criteria);
+
+ for (l = hits; l; l = l->next) {
+ EmpathyLogSearchHit *hit;
+ const gchar *account_name;
+ const gchar *account_icon;
+ gchar *date_readable;
+
+ hit = l->data;
+
+ /* Protect against invalid data (corrupt or old log files. */
+ if (!hit->account || !hit->chat_id) {
+ continue;
+ }
+
+ date_readable = empathy_log_manager_get_date_readable (hit->date);
+ account_name = mc_account_get_display_name (hit->account);
+ account_icon = gossip_icon_name_from_account (hit->account);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_FIND_ACCOUNT_ICON, account_icon,
+ COL_FIND_ACCOUNT_NAME, account_name,
+ COL_FIND_ACCOUNT, hit->account,
+ COL_FIND_CHAT_NAME, hit->chat_id, /* FIXME */
+ COL_FIND_CHAT_ID, hit->chat_id,
+ COL_FIND_IS_CHATROOM, hit->is_chatroom,
+ COL_FIND_DATE, hit->date,
+ COL_FIND_DATE_READABLE, date_readable,
+ -1);
+
+ g_free (date_readable);
+
+ /* FIXME: Update COL_FIND_CHAT_NAME */
+ if (hit->is_chatroom) {
+ } else {
+ }
+ }
+
+ if (hits) {
+ empathy_log_manager_search_free (hits);
+ }
+}
+
+static void
+log_window_find_setup (GossipLogWindow *window)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeSortable *sortable;
+ GtkTreeViewColumn *column;
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+ gint offset;
+
+ view = GTK_TREE_VIEW (window->treeview_find);
+ selection = gtk_tree_view_get_selection (view);
+
+ /* New store */
+ store = gtk_list_store_new (COL_FIND_COUNT,
+ G_TYPE_STRING, /* account icon name */
+ G_TYPE_STRING, /* account name */
+ MC_TYPE_ACCOUNT, /* account */
+ G_TYPE_STRING, /* chat name */
+ G_TYPE_STRING, /* chat id */
+ G_TYPE_BOOLEAN, /* is chatroom */
+ G_TYPE_STRING, /* date */
+ G_TYPE_STRING); /* date_readable */
+
+ model = GTK_TREE_MODEL (store);
+ sortable = GTK_TREE_SORTABLE (store);
+
+ gtk_tree_view_set_model (view, model);
+
+ /* New column */
+ column = gtk_tree_view_column_new ();
+
+ cell = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, cell, FALSE);
+ gtk_tree_view_column_add_attribute (column, cell,
+ "icon-name",
+ COL_FIND_ACCOUNT_ICON);
+
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, cell, TRUE);
+ gtk_tree_view_column_add_attribute (column, cell,
+ "text",
+ COL_FIND_ACCOUNT_NAME);
+
+ gtk_tree_view_column_set_title (column, _("Account"));
+ gtk_tree_view_append_column (view, column);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_clickable (column, TRUE);
+
+ cell = gtk_cell_renderer_text_new ();
+ offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Conversation"),
+ cell, "text", COL_FIND_CHAT_NAME,
+ NULL);
+
+ column = gtk_tree_view_get_column (view, offset - 1);
+ gtk_tree_view_column_set_sort_column_id (column, COL_FIND_CHAT_NAME);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_clickable (column, TRUE);
+
+ cell = gtk_cell_renderer_text_new ();
+ offset = gtk_tree_view_insert_column_with_attributes (view, -1, _("Date"),
+ cell, "text", COL_FIND_DATE_READABLE,
+ NULL);
+
+ column = gtk_tree_view_get_column (view, offset - 1);
+ gtk_tree_view_column_set_sort_column_id (column, COL_FIND_DATE);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_clickable (column, TRUE);
+
+ /* Set up treeview properties */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ gtk_tree_sortable_set_sort_column_id (sortable,
+ COL_FIND_DATE,
+ GTK_SORT_ASCENDING);
+
+ /* Set up signals */
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (log_window_find_changed_cb),
+ window);
+
+ g_object_unref (store);
+}
+
+static void
+log_window_button_find_clicked_cb (GtkWidget *widget,
+ GossipLogWindow *window)
+{
+ const gchar *str;
+
+ str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
+
+ /* Don't find the same crap again */
+ if (window->last_find && strcmp (window->last_find, str) == 0) {
+ return;
+ }
+
+ g_free (window->last_find);
+ window->last_find = g_strdup (str);
+
+ log_window_find_populate (window, str);
+}
+
+static void
+log_window_button_next_clicked_cb (GtkWidget *widget,
+ GossipLogWindow *window)
+{
+ if (window->last_find) {
+ gboolean can_do_previous;
+ gboolean can_do_next;
+
+ gossip_chat_view_find_next (window->chatview_find,
+ window->last_find,
+ FALSE);
+ gossip_chat_view_find_abilities (window->chatview_find,
+ window->last_find,
+ &can_do_previous,
+ &can_do_next);
+ gtk_widget_set_sensitive (window->button_previous, can_do_previous);
+ gtk_widget_set_sensitive (window->button_next, can_do_next);
+ }
+}
+
+static void
+log_window_button_previous_clicked_cb (GtkWidget *widget,
+ GossipLogWindow *window)
+{
+ if (window->last_find) {
+ gboolean can_do_previous;
+ gboolean can_do_next;
+
+ gossip_chat_view_find_previous (window->chatview_find,
+ window->last_find,
+ FALSE);
+ gossip_chat_view_find_abilities (window->chatview_find,
+ window->last_find,
+ &can_do_previous,
+ &can_do_next);
+ gtk_widget_set_sensitive (window->button_previous, can_do_previous);
+ gtk_widget_set_sensitive (window->button_next, can_do_next);
+ }
+}
+
+/*
+ * Chats Code
+ */
+
+static void
+log_window_chats_changed_cb (GtkTreeSelection *selection,
+ GossipLogWindow *window)
+{
+ /* Use last date by default */
+ gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
+
+ log_window_chats_get_messages (window, NULL);
+}
+
+static void
+log_window_chats_populate (GossipLogWindow *window)
+{
+ GossipAccountChooser *account_chooser;
+ McAccount *account;
+ GList *chats, *l;
+
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkListStore *store;
+ GtkTreeIter iter;
+
+ account_chooser = GOSSIP_ACCOUNT_CHOOSER (window->account_chooser_chats);
+ account = gossip_account_chooser_get_account (account_chooser);
+
+ view = GTK_TREE_VIEW (window->treeview_chats);
+ model = gtk_tree_view_get_model (view);
+ selection = gtk_tree_view_get_selection (view);
+ store = GTK_LIST_STORE (model);
+
+ /* Block signals to stop the logs being retrieved prematurely */
+ g_signal_handlers_block_by_func (selection,
+ log_window_chats_changed_cb,
+ window);
+
+ gtk_list_store_clear (store);
+
+ chats = empathy_log_manager_get_chats (window->log_manager, account);
+ for (l = chats; l; l = l->next) {
+ EmpathyLogSearchHit *hit;
+
+ hit = l->data;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_CHAT_ICON, "empathy-available",
+ COL_CHAT_NAME, hit->chat_id,
+ COL_CHAT_ACCOUNT, account,
+ COL_CHAT_ID, hit->chat_id,
+ COL_CHAT_IS_CHATROOM, hit->is_chatroom,
+ -1);
+
+ /* FIXME: Update COL_CHAT_ICON/NAME */
+ if (hit->is_chatroom) {
+ } else {
+ }
+ }
+ empathy_log_manager_search_free (chats);
+
+ /* Unblock signals */
+ g_signal_handlers_unblock_by_func (selection,
+ log_window_chats_changed_cb,
+ window);
+
+
+ g_object_unref (account);
+}
+
+static void
+log_window_chats_setup (GossipLogWindow *window)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeSortable *sortable;
+ GtkTreeViewColumn *column;
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+
+ view = GTK_TREE_VIEW (window->treeview_chats);
+ selection = gtk_tree_view_get_selection (view);
+
+ /* new store */
+ store = gtk_list_store_new (COL_CHAT_COUNT,
+ G_TYPE_STRING, /* icon */
+ G_TYPE_STRING, /* name */
+ MC_TYPE_ACCOUNT, /* account */
+ G_TYPE_STRING, /* id */
+ G_TYPE_BOOLEAN); /* is chatroom */
+
+ model = GTK_TREE_MODEL (store);
+ sortable = GTK_TREE_SORTABLE (store);
+
+ gtk_tree_view_set_model (view, model);
+
+ /* new column */
+ column = gtk_tree_view_column_new ();
+
+ cell = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, cell, FALSE);
+ gtk_tree_view_column_add_attribute (column, cell,
+ "icon-name",
+ COL_CHAT_ICON);
+
+ cell = gtk_cell_renderer_text_new ();
+ g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_pack_start (column, cell, TRUE);
+ gtk_tree_view_column_add_attribute (column, cell,
+ "text",
+ COL_CHAT_NAME);
+
+ gtk_tree_view_append_column (view, column);
+
+ /* set up treeview properties */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ gtk_tree_sortable_set_sort_column_id (sortable,
+ COL_CHAT_NAME,
+ GTK_SORT_ASCENDING);
+
+ /* set up signals */
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (log_window_chats_changed_cb),
+ window);
+
+ g_object_unref (store);
+}
+
+static void
+log_window_chats_accounts_changed_cb (GtkWidget *combobox,
+ GossipLogWindow *window)
+{
+ /* Clear all current messages shown in the textview */
+ gossip_chat_view_clear (window->chatview_chats);
+
+ log_window_chats_populate (window);
+}
+
+static void
+log_window_chats_new_message_cb (GossipContact *own_contact,
+ GossipMessage *message,
+ GossipLogWindow *window)
+{
+ gossip_chat_view_append_message (window->chatview_chats, message);
+
+ /* Scroll to the most recent messages */
+ gossip_chat_view_scroll_down (window->chatview_chats);
+}
+
+#if 0
+static gboolean
+log_window_chats_is_today_selected (GossipLogWindow *window)
+{
+ GossipTime t;
+ gchar *timestamp;
+ guint year_selected;
+ guint year;
+ guint month;
+ guint month_selected;
+ guint day;
+ guint day_selected;
+ gboolean selected;
+
+ t = gossip_time_get_current ();
+ timestamp = gossip_time_to_string_local (t, "%Y%m%d");
+
+ sscanf (timestamp, "%4d%2d%2d", &year, &month, &day);
+
+ gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
+ &year_selected,
+ &month_selected,
+ &day_selected);
+
+ /* Hack since this starts at 0 */
+ month_selected++;
+
+ selected = (day_selected == day &&
+ month_selected == month &&
+ year_selected == year);
+
+ g_free (timestamp);
+
+ return selected;
+}
+#endif
+
+static void
+log_window_chats_set_selected (GossipLogWindow *window,
+ McAccount *account,
+ const gchar *chat_id,
+ gboolean is_chatroom)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ gboolean ok;
+
+ view = GTK_TREE_VIEW (window->treeview_chats);
+ model = gtk_tree_view_get_model (view);
+ selection = gtk_tree_view_get_selection (view);
+
+ if (!gtk_tree_model_get_iter_first (model, &iter)) {
+ return;
+ }
+
+ for (ok = TRUE; ok; ok = gtk_tree_model_iter_next (model, &iter)) {
+ McAccount *this_account;
+ gchar *this_chat_id;
+ gboolean this_is_chatroom;
+
+ gtk_tree_model_get (model, &iter,
+ COL_CHAT_ACCOUNT, &this_account,
+ COL_CHAT_ID, &this_chat_id,
+ COL_CHAT_IS_CHATROOM, &this_is_chatroom,
+ -1);
+
+ if (gossip_account_equal (this_account, account) &&
+ strcmp (this_chat_id, chat_id) == 0 &&
+ this_is_chatroom == is_chatroom) {
+ gtk_tree_selection_select_iter (selection, &iter);
+ path = gtk_tree_model_get_path (model, &iter);
+ gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, 0.5, 0.0);
+ gtk_tree_path_free (path);
+ g_object_unref (this_account);
+ g_free (this_chat_id);
+ break;
+ }
+
+ g_object_unref (this_account);
+ g_free (this_chat_id);
+ }
+}
+
+static gboolean
+log_window_chats_get_selected (GossipLogWindow *window,
+ McAccount **account,
+ gchar **chat_id,
+ gboolean *is_chatroom)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ gchar *id = NULL;
+ McAccount *acc = NULL;
+ gboolean room = FALSE;
+
+ view = GTK_TREE_VIEW (window->treeview_chats);
+ model = gtk_tree_view_get_model (view);
+ selection = gtk_tree_view_get_selection (view);
+
+ if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ return FALSE;
+ }
+
+ gtk_tree_model_get (model, &iter,
+ COL_CHAT_ACCOUNT, &acc,
+ COL_CHAT_ID, &id,
+ COL_CHAT_IS_CHATROOM, &room,
+ -1);
+
+ if (chat_id) {
+ *chat_id = id;
+ } else {
+ g_free (id);
+ }
+ if (account) {
+ *account = acc;
+ } else {
+ g_object_unref (acc);
+ }
+ if (is_chatroom) {
+ *is_chatroom = room;
+ }
+
+ return TRUE;
+}
+
+static void
+log_window_chats_get_messages (GossipLogWindow *window,
+ const gchar *date_to_show)
+{
+ McAccount *account;
+ gchar *chat_id;
+ gboolean is_chatroom;
+ GossipMessage *message;
+ GList *messages;
+ GList *dates = NULL;
+ GList *l;
+ const gchar *date;
+ guint year_selected;
+ guint year;
+ guint month;
+ guint month_selected;
+ guint day;
+
+ if (!log_window_chats_get_selected (window, &account,
+ &chat_id, &is_chatroom)) {
+ return;
+ }
+
+ g_signal_handlers_block_by_func (window->calendar_chats,
+ log_window_calendar_chats_day_selected_cb,
+ window);
+
+ /* Either use the supplied date or get the last */
+ date = date_to_show;
+ if (!date) {
+ gboolean day_selected = FALSE;
+
+ /* Get a list of dates and show them on the calendar */
+ dates = empathy_log_manager_get_dates (window->log_manager,
+ account, chat_id,
+ is_chatroom);
+
+ for (l = dates; l; l = l->next) {
+ const gchar *str;
+
+ str = l->data;
+ if (!str) {
+ continue;
+ }
+
+ sscanf (str, "%4d%2d%2d", &year, &month, &day);
+ gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
+ &year_selected,
+ &month_selected,
+ NULL);
+
+ month_selected++;
+
+ if (!l->next) {
+ date = str;
+ }
+
+ if (year != year_selected || month != month_selected) {
+ continue;
+ }
+
+
+ gossip_debug (DEBUG_DOMAIN, "Marking date:'%s'", str);
+ gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), day);
+
+ if (l->next) {
+ continue;
+ }
+
+ day_selected = TRUE;
+
+ gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
+ }
+
+ if (!day_selected) {
+ /* Unselect the day in the calendar */
+ gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), 0);
+ }
+ } else {
+ sscanf (date, "%4d%2d%2d", &year, &month, &day);
+ gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
+ &year_selected,
+ &month_selected,
+ NULL);
+
+ month_selected++;
+
+ if (year != year_selected && month != month_selected) {
+ day = 0;
+ }
+
+ gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
+ }
+ g_signal_handlers_unblock_by_func (window->calendar_chats,
+ log_window_calendar_chats_day_selected_cb,
+ window);
+
+ /* Clear all current messages shown in the textview */
+ gossip_chat_view_clear (window->chatview_chats);
+
+ /* Turn off scrolling temporarily */
+ gossip_chat_view_scroll (window->chatview_find, FALSE);
+
+ /* Get messages */
+ messages = empathy_log_manager_get_messages_for_date (window->log_manager,
+ account, chat_id,
+ is_chatroom,
+ date);
+
+ for (l = messages; l; l = l->next) {
+ message = l->data;
+
+ gossip_chat_view_append_message (window->chatview_chats,
+ message);
+ g_object_unref (message);
+ }
+ g_list_free (messages);
+
+ g_list_foreach (dates, (GFunc) g_free, NULL);
+ g_list_free (dates);
+
+ g_object_unref (account);
+ g_free (chat_id);
+
+ /* Turn back on scrolling */
+ gossip_chat_view_scroll (window->chatview_find, TRUE);
+
+ /* Scroll to the most recent messages */
+ gossip_chat_view_scroll_down (window->chatview_chats);
+
+ /* Give the search entry main focus */
+ gtk_widget_grab_focus (window->entry_chats);
+}
+
+static void
+log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
+ GossipLogWindow *window)
+{
+ guint year;
+ guint month;
+ guint day;
+
+ gchar *date;
+
+ gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
+
+ /* We need this hear because it appears that the months start from 0 */
+ month++;
+
+ date = g_strdup_printf ("%4.4d%2.2d%2.2d", year, month, day);
+
+ gossip_debug (DEBUG_DOMAIN, "Currently selected date is:'%s'", date);
+
+ log_window_chats_get_messages (window, date);
+
+ g_free (date);
+}
+
+static void
+log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
+ GossipLogWindow *window)
+{
+ McAccount *account;
+ gchar *chat_id;
+ gboolean is_chatroom;
+ guint year_selected;
+ guint month_selected;
+
+ GList *dates;
+ GList *l;
+
+ gtk_calendar_clear_marks (GTK_CALENDAR (calendar));
+
+ if (!log_window_chats_get_selected (window, &account,
+ &chat_id, &is_chatroom)) {
+ gossip_debug (DEBUG_DOMAIN, "No chat selected to get dates for...");
+ return;
+ }
+
+ g_object_get (calendar,
+ "month", &month_selected,
+ "year", &year_selected,
+ NULL);
+
+ /* We need this hear because it appears that the months start from 0 */
+ month_selected++;
+
+ /* Get the log object for this contact */
+ dates = empathy_log_manager_get_dates (window->log_manager, account,
+ chat_id, is_chatroom);
+ g_object_unref (account);
+ g_free (chat_id);
+
+ for (l = dates; l; l = l->next) {
+ const gchar *str;
+ guint year;
+ guint month;
+ guint day;
+
+ str = l->data;
+ if (!str) {
+ continue;
+ }
+
+ sscanf (str, "%4d%2d%2d", &year, &month, &day);
+
+ if (year == year_selected && month == month_selected) {
+ gossip_debug (DEBUG_DOMAIN, "Marking date:'%s'", str);
+ gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), day);
+ }
+ }
+
+ g_list_foreach (dates, (GFunc) g_free, NULL);
+ g_list_free (dates);
+
+ gossip_debug (DEBUG_DOMAIN,
+ "Currently showing month %d and year %d",
+ month_selected, year_selected);
+}
+
+static void
+log_window_entry_chats_changed_cb (GtkWidget *entry,
+ GossipLogWindow *window)
+{
+ const gchar *str;
+
+ str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
+ gossip_chat_view_highlight (window->chatview_chats, str);
+
+ if (str) {
+ gossip_chat_view_find_next (window->chatview_chats,
+ str,
+ TRUE);
+ }
+}
+
+static void
+log_window_entry_chats_activate_cb (GtkWidget *entry,
+ GossipLogWindow *window)
+{
+ const gchar *str;
+
+ str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
+
+ if (str) {
+ gossip_chat_view_find_next (window->chatview_chats,
+ str,
+ FALSE);
+ }
+}
+