diff options
author | Xavier Claessens <xclaesse@gmail.com> | 2007-06-14 05:58:16 +0800 |
---|---|---|
committer | Xavier Claessens <xclaesse@src.gnome.org> | 2007-06-14 05:58:16 +0800 |
commit | 4ce14ebec31f60a4a6bdd781f88607731912f557 (patch) | |
tree | 0ee31695ccdd06cae5f5b09bf5098707528b1dd3 /libempathy-gtk | |
parent | e24e8894479c1b69364faeb315ab0d0dbf7989f1 (diff) | |
download | gsoc2013-empathy-4ce14ebec31f60a4a6bdd781f88607731912f557.tar gsoc2013-empathy-4ce14ebec31f60a4a6bdd781f88607731912f557.tar.gz gsoc2013-empathy-4ce14ebec31f60a4a6bdd781f88607731912f557.tar.bz2 gsoc2013-empathy-4ce14ebec31f60a4a6bdd781f88607731912f557.tar.lz gsoc2013-empathy-4ce14ebec31f60a4a6bdd781f88607731912f557.tar.xz gsoc2013-empathy-4ce14ebec31f60a4a6bdd781f88607731912f557.tar.zst gsoc2013-empathy-4ce14ebec31f60a4a6bdd781f88607731912f557.zip |
New window for viewing logs.
2007-06-13 Xavier Claessens <xclaesse@gmail.com>
* libempathy-gtk/Makefile.am:
* libempathy-gtk/gossip-log-window.glade:
* libempathy-gtk/gossip-log-window.h:
* libempathy-gtk/gossip-log-window.c:
* libempathy/empathy-log-manager.c:
* libempathy/empathy-log-manager.h:
* libempathy-gtk/gossip-chat.c:
* libempathy-gtk/empathy-main-window.c: New window for viewing logs.
* libempathy-gtk/gossip-chat-view.c: Do not use smooth scroll when
resizing the view.
* libempathy-gtk/gossip-contact-list-store.c: Do not set active
contacts when creating the store, and when contact groups changed.
* src/empathy-main.c: Fix warning when using command-line options.
* libempathy/empathy-tp-contact-list.c: Check if we have an aliasing
iface before setting the alias of a contact.
* TODO: Updated.
* data/jabber.profile: Ignore ssl errors by default. This is a security
vulnerability but we don't really have the choice.
* libempathy/gossip-contact.h:
* libempathy/gossip-contact.c: Add a "is-user" property to know if
it's our self contact.
* libempathy/gossip-message.h:
* libempathy/gossip-message.c: Add a "receiver" property like that we
have our self contact for nick highlight.
svn path=/trunk/; revision=148
Diffstat (limited to 'libempathy-gtk')
-rw-r--r-- | libempathy-gtk/Makefile.am | 2 | ||||
-rw-r--r-- | libempathy-gtk/empathy-contact-widget.c | 5 | ||||
-rw-r--r-- | libempathy-gtk/empathy-main-window.c | 3 | ||||
-rw-r--r-- | libempathy-gtk/gossip-chat-view.c | 54 | ||||
-rw-r--r-- | libempathy-gtk/gossip-chat.c | 25 | ||||
-rw-r--r-- | libempathy-gtk/gossip-contact-list-store.c | 42 | ||||
-rw-r--r-- | libempathy-gtk/gossip-log-window.c | 1153 | ||||
-rw-r--r-- | libempathy-gtk/gossip-log-window.glade | 470 | ||||
-rw-r--r-- | libempathy-gtk/gossip-log-window.h | 39 |
9 files changed, 1735 insertions, 58 deletions
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am index 6a6c7203c..113b37c3a 100644 --- a/libempathy-gtk/Makefile.am +++ b/libempathy-gtk/Makefile.am @@ -39,6 +39,7 @@ libempathy_gtk_la_SOURCES = \ gossip-account-chooser.c gossip-account-chooser.h \ gossip-new-chatroom-dialog.c gossip-new-chatroom-dialog.h \ gossip-chatrooms-window.c gossip-chatrooms-window.h \ + gossip-log-window.c gossip-log-window.h \ gossip-ui-utils.c gossip-ui-utils.h libempathy_gtk_la_LIBADD = \ @@ -61,6 +62,7 @@ glade_DATA = \ gossip-group-chat.glade \ gossip-chatrooms-window.glade \ gossip-spell-dialog.glade \ + gossip-log-window.glade \ gossip-chat.glade dtddir = $(datadir)/empathy diff --git a/libempathy-gtk/empathy-contact-widget.c b/libempathy-gtk/empathy-contact-widget.c index e93117b36..ac43700d0 100644 --- a/libempathy-gtk/empathy-contact-widget.c +++ b/libempathy-gtk/empathy-contact-widget.c @@ -148,10 +148,7 @@ empathy_contact_widget_new (GossipContact *contact, information = g_slice_new0 (EmpathyContactWidget); information->editable = editable; if (contact) { - GossipContact *user_contact; - - user_contact = gossip_contact_get_user (contact); - information->is_user = gossip_contact_equal (contact, user_contact); + information->is_user = gossip_contact_is_user (contact); information->can_change_contact = FALSE; } else { information->is_user = FALSE; diff --git a/libempathy-gtk/empathy-main-window.c b/libempathy-gtk/empathy-main-window.c index 7f8693278..0e7b1fdda 100644 --- a/libempathy-gtk/empathy-main-window.c +++ b/libempathy-gtk/empathy-main-window.c @@ -50,6 +50,7 @@ #include "gossip-about-dialog.h" #include "gossip-new-chatroom-dialog.h" #include "gossip-chatrooms-window.h" +#include "gossip-log-window.h" #define DEBUG_DOMAIN "MainWindow" @@ -533,7 +534,7 @@ static void main_window_chat_history_cb (GtkWidget *widget, EmpathyMainWindow *window) { - //gossip_log_window_show (NULL, NULL); + gossip_log_window_show (NULL, NULL, FALSE, GTK_WINDOW (window->window)); } static void diff --git a/libempathy-gtk/gossip-chat-view.c b/libempathy-gtk/gossip-chat-view.c index 9fea2fbf1..e8db2628b 100644 --- a/libempathy-gtk/gossip-chat-view.c +++ b/libempathy-gtk/gossip-chat-view.c @@ -79,7 +79,7 @@ struct _GossipChatViewPriv { BlockType last_block_type; gboolean allow_scrolling; - guint scroll_src; + guint scroll_timeout; GTimer *scroll_time; gboolean is_group_chat; @@ -350,8 +350,8 @@ chat_view_finalize (GObject *object) if (priv->scroll_time) { g_timer_destroy (priv->scroll_time); } - if (priv->scroll_src) { - g_source_remove (priv->scroll_src); + if (priv->scroll_timeout) { + g_source_remove (priv->scroll_timeout); } G_OBJECT_CLASS (gossip_chat_view_parent_class)->finalize (object); @@ -382,7 +382,10 @@ chat_view_size_allocate (GtkWidget *widget, GTK_WIDGET_CLASS (gossip_chat_view_parent_class)->size_allocate (widget, alloc); if (down) { - gossip_chat_view_scroll_down (GOSSIP_CHAT_VIEW (widget)); + GtkAdjustment *adj; + + adj = GTK_TEXT_VIEW (widget)->vadjustment; + gtk_adjustment_set_value (adj, adj->upper - adj->page_size); } } @@ -1059,7 +1062,6 @@ chat_view_maybe_append_fancy_header (GossipChatView *view, { GossipChatViewPriv *priv; GossipContact *sender; - GossipContact *my_contact; const gchar *name; gboolean header; GtkTextIter iter; @@ -1075,9 +1077,8 @@ chat_view_maybe_append_fancy_header (GossipChatView *view, priv = GET_PRIV (view); sender = gossip_message_get_sender (msg); - my_contact = gossip_contact_get_user (sender); name = gossip_contact_get_name (sender); - from_self = gossip_contact_equal (sender, my_contact); + from_self = gossip_contact_is_user (sender); gossip_debug (DEBUG_DOMAIN, "Maybe add fancy header"); @@ -1186,7 +1187,6 @@ chat_view_append_irc_action (GossipChatView *view, GossipMessage *msg) { GossipChatViewPriv *priv; - GossipContact *my_contact; GossipContact *sender; const gchar *name; GtkTextIter iter; @@ -1199,11 +1199,9 @@ chat_view_append_irc_action (GossipChatView *view, gossip_debug (DEBUG_DOMAIN, "Add IRC action"); sender = gossip_message_get_sender (msg); - my_contact = gossip_contact_get_user (sender); name = gossip_contact_get_name (sender); - /* Skip the "/me ". */ - if (gossip_contact_equal (sender, my_contact)) { + if (gossip_contact_is_user (sender)) { tag = "irc-action-self"; } else { tag = "irc-action-other"; @@ -1236,7 +1234,6 @@ chat_view_append_fancy_action (GossipChatView *view, { GossipChatViewPriv *priv; GossipContact *sender; - GossipContact *my_contact; const gchar *name; const gchar *body; GtkTextIter iter; @@ -1249,10 +1246,9 @@ chat_view_append_fancy_action (GossipChatView *view, gossip_debug (DEBUG_DOMAIN, "Add fancy action"); sender = gossip_message_get_sender (msg); - my_contact = gossip_contact_get_user (sender); name = gossip_contact_get_name (sender); - if (gossip_contact_equal (sender, my_contact)) { + if (gossip_contact_is_user (sender)) { tag = "fancy-action-self"; line_tag = "fancy-line-self"; } else { @@ -1280,7 +1276,6 @@ chat_view_append_irc_message (GossipChatView *view, { GossipChatViewPriv *priv; GossipContact *sender; - GossipContact *my_contact; const gchar *name; const gchar *body; const gchar *nick_tag; @@ -1294,10 +1289,9 @@ chat_view_append_irc_message (GossipChatView *view, body = gossip_message_get_body (msg); sender = gossip_message_get_sender (msg); - my_contact = gossip_contact_get_user (sender); name = gossip_contact_get_name (sender); - if (gossip_contact_equal (sender, my_contact)) { + if (gossip_contact_is_user (sender)) { nick_tag = "irc-nick-self"; body_tag = "irc-body-self"; } else { @@ -1338,16 +1332,14 @@ chat_view_append_fancy_message (GossipChatView *view, { GossipChatViewPriv *priv; GossipContact *sender; - GossipContact *my_contact; const gchar *body; const gchar *tag; priv = GET_PRIV (view); sender = gossip_message_get_sender (msg); - my_contact = gossip_contact_get_user (sender); - if (gossip_contact_equal (sender, my_contact)) { + if (gossip_contact_is_user (sender)) { tag = "fancy-body-self"; } else { tag = "fancy-body-other"; @@ -1441,7 +1433,6 @@ gossip_chat_view_append_message (GossipChatView *view, { GossipChatViewPriv *priv; GossipContact *sender; - GossipContact *my_contact; const gchar *body; gboolean scroll_down; @@ -1480,14 +1471,12 @@ gossip_chat_view_append_message (GossipChatView *view, } } - my_contact = gossip_contact_get_user (sender); - /* Reset the last inserted contact. */ if (priv->last_contact) { g_object_unref (priv->last_contact); } - if (gossip_contact_equal (my_contact, sender)) { + if (gossip_contact_is_user (sender)) { priv->last_block_type = BLOCK_TYPE_SELF; priv->last_contact = NULL; } else { @@ -1658,7 +1647,7 @@ chat_view_scroll_cb (GossipChatView *view) gtk_adjustment_set_value (adj, max_val); g_timer_destroy (priv->scroll_time); priv->scroll_time = NULL; - priv->scroll_src = 0; + priv->scroll_timeout = 0; return FALSE; } @@ -1683,16 +1672,15 @@ gossip_chat_view_scroll_down (GossipChatView *view) gossip_debug (DEBUG_DOMAIN, "Scrolling down"); if (priv->scroll_time) { - g_timer_destroy (priv->scroll_time); + g_timer_reset (priv->scroll_time); + } else { + priv->scroll_time = g_timer_new(); } - if (priv->scroll_src) { - g_source_remove (priv->scroll_src); + if (!priv->scroll_timeout) { + priv->scroll_timeout = g_timeout_add (SCROLL_DELAY, + (GSourceFunc) chat_view_scroll_cb, + view); } - - priv->scroll_time = g_timer_new(); - priv->scroll_src = g_timeout_add (SCROLL_DELAY, - (GSourceFunc) chat_view_scroll_cb, - view); } gboolean diff --git a/libempathy-gtk/gossip-chat.c b/libempathy-gtk/gossip-chat.c index 0f6335617..657535d5a 100644 --- a/libempathy-gtk/gossip-chat.c +++ b/libempathy-gtk/gossip-chat.c @@ -341,9 +341,8 @@ static void chat_send (GossipChat *chat, const gchar *msg) { - GossipChatPriv *priv; - GossipMessage *message; - GossipContact *own_contact; + GossipChatPriv *priv; + GossipMessage *message; priv = GET_PRIV (chat); @@ -361,9 +360,7 @@ chat_send (GossipChat *chat, /* FIXME: add here something to let group/privrate chat handle * some special messages */ - own_contact = empathy_contact_manager_get_user (priv->manager, chat->account); message = gossip_message_new (msg); - gossip_message_set_sender (message, own_contact); empathy_tp_chat_send (priv->tp_chat, message); @@ -415,6 +412,7 @@ chat_message_received_cb (EmpathyTpChat *tp_chat, if (timestamp >= priv->time_joined) { empathy_log_manager_add_message (priv->log_manager, gossip_chat_get_id (chat), + gossip_chat_is_group_chat (chat), message); } @@ -1035,14 +1033,12 @@ chat_state_changed_cb (EmpathyTpChat *tp_chat, GossipChat *chat) { GossipChatPriv *priv; - GossipContact *own_contact; GList *l; gboolean was_composing; priv = GET_PRIV (chat); - own_contact = gossip_contact_get_user (contact); - if (gossip_contact_equal (own_contact, contact)) { + if (gossip_contact_is_user (contact)) { /* We don't care about our own chat state */ return; } @@ -1112,7 +1108,8 @@ chat_add_logs (GossipChat *chat) /* Add messages from last conversation */ messages = empathy_log_manager_get_last_messages (priv->log_manager, chat->account, - gossip_chat_get_id (chat)); + gossip_chat_get_id (chat), + gossip_chat_is_group_chat (chat)); num_messages = g_list_length (messages); for (l = messages, i = 0; l; l = l->next, i++) { @@ -1498,7 +1495,7 @@ gossip_chat_should_play_sound (GossipChat *chat) gboolean gossip_chat_should_highlight_nick (GossipMessage *message) { - GossipContact *my_contact; + GossipContact *contact; const gchar *msg, *to; gchar *cf_msg, *cf_to; gchar *ch; @@ -1515,8 +1512,12 @@ gossip_chat_should_highlight_nick (GossipMessage *message) return FALSE; } - my_contact = gossip_contact_get_user (gossip_message_get_sender (message)); - to = gossip_contact_get_name (my_contact); + contact = gossip_message_get_receiver (message); + if (!contact || !gossip_contact_is_user (contact)) { + return FALSE; + } + + to = gossip_contact_get_name (contact); if (!to) { return FALSE; } diff --git a/libempathy-gtk/gossip-contact-list-store.c b/libempathy-gtk/gossip-contact-list-store.c index 4a5b5506e..887ce13e4 100644 --- a/libempathy-gtk/gossip-contact-list-store.c +++ b/libempathy-gtk/gossip-contact-list-store.c @@ -57,6 +57,7 @@ struct _GossipContactListStorePriv { gboolean is_compact; gboolean show_active; GossipContactListStoreSort sort_criterium; + guint inhibit_active; GossipContactGroupsFunc get_contact_groups; gpointer get_contact_groups_data; @@ -92,6 +93,7 @@ static void contact_list_store_set_property (GObject const GValue *value, GParamSpec *pspec); static void contact_list_store_setup (GossipContactListStore *store); +static gboolean contact_list_store_inibit_active_cb (GossipContactListStore *store); static void contact_list_store_contact_added_cb (EmpathyContactList *list_iface, GossipContact *contact, GossipContactListStore *store); @@ -231,9 +233,9 @@ gossip_contact_list_store_init (GossipContactListStore *store) priv = GET_PRIV (store); - priv->is_compact = FALSE; - priv->show_active = TRUE; - priv->show_avatars = TRUE; + priv->inhibit_active = g_timeout_add (1000, + (GSourceFunc) contact_list_store_inibit_active_cb, + store); } static void @@ -249,6 +251,10 @@ contact_list_store_finalize (GObject *object) g_object_unref (priv->list); } + if (priv->inhibit_active) { + g_source_remove (priv->inhibit_active); + } + G_OBJECT_CLASS (gossip_contact_list_store_parent_class)->finalize (object); } @@ -320,7 +326,6 @@ gossip_contact_list_store_new (EmpathyContactList *list_iface) GossipContactListStore *store; GossipContactListStorePriv *priv; GList *contacts, *l; - gboolean show_active; g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list_iface), NULL); @@ -340,9 +345,7 @@ gossip_contact_list_store_new (EmpathyContactList *list_iface) G_CALLBACK (contact_list_store_contact_removed_cb), store); - /* Add contacts already created. Do not highlight them. */ - show_active = priv->show_active; - priv->show_active = FALSE; + /* Add contacts already created. */ contacts = empathy_contact_list_get_members (priv->list); for (l = contacts; l; l = l->next) { GossipContact *contact; @@ -354,7 +357,6 @@ gossip_contact_list_store_new (EmpathyContactList *list_iface) g_object_unref (contact); } g_list_free (contacts); - priv->show_active = show_active; return store; } @@ -681,6 +683,14 @@ void gossip_contact_list_store_update_contact_groups (GossipContactListStore *store, GossipContact *contact) { + GossipContactListStorePriv *priv; + gboolean show_active; + + g_return_if_fail (GOSSIP_IS_CONTACT_LIST_STORE (store)); + g_return_if_fail (GOSSIP_IS_CONTACT (contact)); + + priv = GET_PRIV (store); + gossip_debug (DEBUG_DOMAIN, "Contact:'%s' updating groups", gossip_contact_get_name (contact)); @@ -688,8 +698,11 @@ gossip_contact_list_store_update_contact_groups (GossipContactListStore *store, * would have to check the groups already set up for each * contact and then see what has been updated. */ + show_active = priv->show_active; + priv->show_active = FALSE; contact_list_store_remove_contact (store, contact); contact_list_store_add_contact (store, contact); + priv->show_active = show_active; } static void @@ -726,6 +739,19 @@ contact_list_store_setup (GossipContactListStore *store) gossip_contact_list_store_set_sort_criterium (store, priv->sort_criterium); } +static gboolean +contact_list_store_inibit_active_cb (GossipContactListStore *store) +{ + GossipContactListStorePriv *priv; + + priv = GET_PRIV (store); + + priv->show_active = TRUE; + priv->inhibit_active = 0; + + return FALSE; +} + static void contact_list_store_contact_added_cb (EmpathyContactList *list_iface, GossipContact *contact, 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); + } +} + diff --git a/libempathy-gtk/gossip-log-window.glade b/libempathy-gtk/gossip-log-window.glade new file mode 100644 index 000000000..4309a3544 --- /dev/null +++ b/libempathy-gtk/gossip-log-window.glade @@ -0,0 +1,470 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="log_window"> + <property name="title" translatable="yes">View Previous Conversations</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">640</property> + <property name="default_height">450</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="icon_name">gtk-justify-left</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + + <child> + <widget class="GtkNotebook" id="notebook"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_tabs">True</property> + <property name="show_border">True</property> + <property name="tab_pos">GTK_POS_TOP</property> + <property name="scrollable">False</property> + <property name="enable_popup">False</property> + + <child> + <widget class="GtkVBox" id="vbox192"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox144"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkLabel" id="label628"> + <property name="visible">True</property> + <property name="label" translatable="yes">_For:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">entry_find</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entry_find"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button_find"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-find</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVPaned" id="vpaned1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">120</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow14"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="treeview_find"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">True</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">False</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox215"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow_find"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox171"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <placeholder/> + </child> + + <child> + <widget class="GtkButton" id="button_next"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="label">gtk-media-next</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button_previous"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="label">gtk-media-previous</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label595"> + <property name="visible">True</property> + <property name="label" translatable="yes">Search</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table7"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox143"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkImage" id="image247"> + <property name="visible">True</property> + <property name="stock">gtk-find</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entry_chats"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox191"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow13"> + <property name="width_request">150</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="treeview_chats"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkCalendar" id="calendar_chats"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="display_options">GTK_CALENDAR_SHOW_HEADING|GTK_CALENDAR_SHOW_DAY_NAMES</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow_chats"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox_chats"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label596"> + <property name="visible">True</property> + <property name="label" translatable="yes">Conversations</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/libempathy-gtk/gossip-log-window.h b/libempathy-gtk/gossip-log-window.h new file mode 100644 index 000000000..7801072fd --- /dev/null +++ b/libempathy-gtk/gossip-log-window.h @@ -0,0 +1,39 @@ +/* -*- 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> + */ + +#ifndef __GOSSIP_LOG_WINDOW_H__ +#define __GOSSIP_LOG_WINDOW_H__ + +#include <libmissioncontrol/mc-account.h> + +G_BEGIN_DECLS + +void gossip_log_window_show (McAccount *account, + const gchar *chat_id, + gboolean chatroom, + GtkWindow *parent); + +G_END_DECLS + +#endif /* __GOSSIP_LOG_WINDOW_H__ */ |