aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>2011-04-20 16:32:56 +0800
committerEmilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>2011-06-09 19:34:48 +0800
commit346d5c25eae1e9bab5ab36cd66885d6bfbe0d262 (patch)
treeb80b8c03936ec0eed7ad58043ed011b8054e7c1c
parent04d3b8f34e0cab394ac143b9323bd3d00a8abee7 (diff)
downloadgsoc2013-empathy-346d5c25eae1e9bab5ab36cd66885d6bfbe0d262.tar
gsoc2013-empathy-346d5c25eae1e9bab5ab36cd66885d6bfbe0d262.tar.gz
gsoc2013-empathy-346d5c25eae1e9bab5ab36cd66885d6bfbe0d262.tar.bz2
gsoc2013-empathy-346d5c25eae1e9bab5ab36cd66885d6bfbe0d262.tar.lz
gsoc2013-empathy-346d5c25eae1e9bab5ab36cd66885d6bfbe0d262.tar.xz
gsoc2013-empathy-346d5c25eae1e9bab5ab36cd66885d6bfbe0d262.tar.zst
gsoc2013-empathy-346d5c25eae1e9bab5ab36cd66885d6bfbe0d262.zip
Complete rewrite of the history window
https://bugzilla.gnome.org/show_bug.cgi?id=619866 Conflicts: libempathy-gtk/empathy-log-window.c libempathy-gtk/empathy-log-window.ui
-rw-r--r--libempathy-gtk/empathy-log-window.c2697
-rw-r--r--libempathy-gtk/empathy-log-window.h12
-rw-r--r--libempathy-gtk/empathy-log-window.ui430
3 files changed, 1855 insertions, 1284 deletions
diff --git a/libempathy-gtk/empathy-log-window.c b/libempathy-gtk/empathy-log-window.c
index 6dc3b3f5e..3af0729a4 100644
--- a/libempathy-gtk/empathy-log-window.c
+++ b/libempathy-gtk/empathy-log-window.c
@@ -1,7 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2006-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2011 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
@@ -20,6 +19,7 @@
*
* Authors: Martyn Russell <martyn@imendio.com>
* Xavier Claessens <xclaesse@gmail.com>
+ * Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
*/
#include "config.h"
@@ -30,9 +30,15 @@
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
-#include <telepathy-glib/account-manager.h>
-#include <telepathy-logger/log-manager.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/proxy-subclass.h>
+#include <telepathy-logger/telepathy-logger.h>
+#include <telepathy-logger/call-event.h>
+
+#include <extensions/extensions.h>
+
+#include <libempathy/action-chain-internal.h>
#include <libempathy/empathy-chatroom-manager.h>
#include <libempathy/empathy-chatroom.h>
#include <libempathy/empathy-message.h>
@@ -41,148 +47,181 @@
#include "empathy-log-window.h"
#include "empathy-account-chooser.h"
+#include "empathy-call-utils.h"
#include "empathy-chat-view.h"
+#include "empathy-contact-dialogs.h"
+#include "empathy-images.h"
#include "empathy-theme-manager.h"
#include "empathy-ui-utils.h"
#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
#include <libempathy/empathy-debug.h>
-typedef struct {
- GtkWidget *window;
-
- GtkWidget *notebook;
-
- GtkWidget *entry_find;
- GtkWidget *button_find;
- GtkWidget *treeview_find;
- GtkWidget *scrolledwindow_find;
- EmpathyChatView *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;
- EmpathyChatView *chatview_chats;
-
- gchar *last_find;
-
- TplLogManager *log_manager;
-
- /* Those are only used while waiting for the account chooser to be ready */
- TpAccount *selected_account;
- gchar *selected_chat_id;
- gboolean selected_is_chatroom;
+typedef struct
+{
+ GtkWidget *window;
+
+ GtkWidget *button_profile;
+ GtkWidget *button_chat;
+ GtkWidget *button_call;
+ GtkWidget *button_video;
+
+ GtkWidget *search_entry;
+
+ GtkWidget *treeview_who;
+ GtkWidget *treeview_what;
+ GtkWidget *treeview_when;
+
+ GtkWidget *scrolledwindow_events;
+ EmpathyChatView *chatview_events;
+
+ GtkWidget *account_chooser;
+
+ gchar *last_find;
+
+ TplActionChain *chain;
+ TplLogManager *log_manager;
+
+ /* List of owned TplLogSearchHits, free with tpl_log_search_hit_free */
+ GList *hits;
+
+ /* Only used while waiting for the account chooser to be ready */
+ TpAccount *selected_account;
+ gchar *selected_chat_id;
+ gboolean selected_is_chatroom;
} EmpathyLogWindow;
static void log_window_destroy_cb (GtkWidget *widget,
EmpathyLogWindow *window);
-static void log_window_entry_find_changed_cb (GtkWidget *entry,
- EmpathyLogWindow *window);
-static void log_window_find_changed_cb (GtkTreeSelection *selection,
- EmpathyLogWindow *window);
-static void log_window_find_populate (EmpathyLogWindow *window,
- const gchar *search_criteria);
-static void log_window_find_setup (EmpathyLogWindow *window);
-static void log_window_button_find_clicked_cb (GtkWidget *widget,
- EmpathyLogWindow *window);
-static void log_window_entry_find_activate_cb (GtkWidget *widget,
- EmpathyLogWindow *window);
-static void log_window_button_next_clicked_cb (GtkWidget *widget,
- EmpathyLogWindow *window);
-static void log_window_button_previous_clicked_cb (GtkWidget *widget,
+static void log_window_search_entry_changed_cb (GtkWidget *entry,
EmpathyLogWindow *window);
-static void log_window_button_close_clicked_cb (GtkWidget *widget,
+static void log_window_search_entry_activate_cb (GtkWidget *widget,
EmpathyLogWindow *window);
-static void log_window_chats_changed_cb (GtkTreeSelection *selection,
- EmpathyLogWindow *window);
-static void log_window_chats_populate (EmpathyLogWindow *window);
-static void log_window_chats_setup (EmpathyLogWindow *window);
+static void log_window_who_populate (EmpathyLogWindow *window);
+static void log_window_who_setup (EmpathyLogWindow *window);
+static void log_window_when_setup (EmpathyLogWindow *window);
+static void log_window_what_setup (EmpathyLogWindow *window);
static void log_window_chats_accounts_changed_cb (GtkWidget *combobox,
EmpathyLogWindow *window);
static void log_window_chats_set_selected (EmpathyLogWindow *window);
-static gboolean log_window_chats_get_selected (EmpathyLogWindow *window,
- TpAccount **account,
- TplEntity **target);
static void log_window_chats_get_messages (EmpathyLogWindow *window,
- GDate *date_to_show);
-static void log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
- EmpathyLogWindow *window);
-static void log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
- EmpathyLogWindow *window);
-static void log_window_entry_chats_changed_cb (GtkWidget *entry,
+ gboolean force_get_dates);
+static void log_window_when_changed_cb (GtkTreeSelection *selection,
EmpathyLogWindow *window);
-static void log_window_entry_chats_activate_cb (GtkWidget *entry,
+static void log_window_delete_menu_clicked_cb (GtkMenuItem *menuitem,
EmpathyLogWindow *window);
-enum {
- COL_FIND_ACCOUNT_ICON,
- COL_FIND_ACCOUNT_NAME,
- COL_FIND_ACCOUNT,
- COL_FIND_CHAT_NAME,
- COL_FIND_TARGET,
- COL_FIND_DATE,
- COL_FIND_DATE_READABLE,
- COL_FIND_COUNT
+static void
+empathy_account_chooser_filter_has_logs (TpAccount *account,
+ EmpathyAccountChooserFilterResultCallback callback,
+ gpointer callback_data,
+ gpointer user_data);
+
+enum
+{
+ COL_TYPE_ANY,
+ COL_TYPE_SEPARATOR,
+ COL_TYPE_NORMAL
};
-enum {
- COL_CHAT_ICON,
- COL_CHAT_NAME,
- COL_CHAT_ACCOUNT,
- COL_CHAT_TARGET,
- COL_CHAT_COUNT
+enum
+{
+ COL_WHO_TYPE,
+ COL_WHO_ICON,
+ COL_WHO_NAME,
+ COL_WHO_ACCOUNT,
+ COL_WHO_TARGET,
+ COL_WHO_COUNT
};
-static EmpathyLogWindow *log_window = NULL;
+enum
+{
+ COL_WHAT_TYPE,
+ COL_WHAT_SUBTYPE,
+ COL_WHAT_TEXT,
+ COL_WHAT_ICON,
+ COL_WHAT_EXPANDER,
+ COL_WHAT_COUNT
+};
-static void
-account_manager_prepared_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
+enum
{
- TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
- EmpathyLogWindow *window = user_data;
- guint account_num;
- GList *accounts;
- GError *error = NULL;
+ COL_WHEN_DATE,
+ COL_WHEN_TEXT,
+ COL_WHEN_ICON,
+ COL_WHEN_COUNT
+};
- if (log_window == NULL)
- return;
+#define CALENDAR_ICON "stock_calendar"
- if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
- DEBUG ("Failed to prepare account manager: %s", error->message);
- g_error_free (error);
- return;
- }
+typedef enum
+{
+ EVENT_CALL_INCOMING = 1 << 0,
+ EVENT_CALL_OUTGOING = 1 << 1,
+ EVENT_CALL_MISSED = 1 << 2,
+ EVENT_CALL_ALL = 1 << 3,
+} EventSubtype;
- accounts = tp_account_manager_get_valid_accounts (account_manager);
- account_num = g_list_length (accounts);
- g_list_free (accounts);
+static EmpathyLogWindow *log_window = NULL;
- 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);
- }
+static gboolean has_element;
+
+#ifndef _date_copy
+#define _date_copy(d) g_date_new_julian (g_date_get_julian (d))
+#endif
+
+typedef struct
+{
+ EmpathyLogWindow *window;
+ TpAccount *account;
+ TplEntity *entity;
+ GDate *date;
+ TplEventTypeMask event_mask;
+ EventSubtype subtype;
+} Ctx;
+
+static Ctx *
+ctx_new (EmpathyLogWindow *window,
+ TpAccount *account,
+ TplEntity *entity,
+ GDate *date,
+ TplEventTypeMask event_mask,
+ EventSubtype subtype)
+{
+ Ctx *ctx = g_slice_new0 (Ctx);
+
+ ctx->window = window;
+ if (account != NULL)
+ ctx->account = g_object_ref (account);
+ if (entity != NULL)
+ ctx->entity = g_object_ref (entity);
+ if (date != NULL)
+ ctx->date = _date_copy (date);
+ ctx->event_mask = event_mask;
+ ctx->subtype = subtype;
+
+ return ctx;
+}
+
+static void
+ctx_free (Ctx *ctx)
+{
+ tp_clear_object (&ctx->account);
+ tp_clear_object (&ctx->entity);
+ if (ctx->date != NULL)
+ g_date_free (ctx->date);
+
+ g_slice_free (Ctx, ctx);
}
static void
account_chooser_ready_cb (EmpathyAccountChooser *chooser,
EmpathyLogWindow *window)
{
- gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), 1);
-
/* We'll display the account once the model has been populate with the chats
* of this account. */
empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (
- window->account_chooser_chats), window->selected_account);
+ window->account_chooser), window->selected_account);
}
static void
@@ -191,7 +230,7 @@ select_account_once_ready (EmpathyLogWindow *self,
const gchar *chat_id,
gboolean is_chatroom)
{
- EmpathyAccountChooser *account_chooser = EMPATHY_ACCOUNT_CHOOSER (self->account_chooser_chats);
+ EmpathyAccountChooser *account_chooser = EMPATHY_ACCOUNT_CHOOSER (self->account_chooser);
tp_clear_object (&self->selected_account);
self->selected_account = g_object_ref (account);
@@ -209,742 +248,1063 @@ select_account_once_ready (EmpathyLogWindow *self,
G_CALLBACK (account_chooser_ready_cb), self);
}
-GtkWidget *
-empathy_log_window_show (TpAccount *account,
- const gchar *chat_id,
- gboolean is_chatroom,
- GtkWindow *parent)
+static void
+toolbutton_profile_clicked (GtkToolButton *toolbutton,
+ EmpathyLogWindow *window)
{
- TpAccountManager *account_manager;
- GtkBuilder *gui;
- gchar *filename;
- EmpathyLogWindow *window;
- EmpathyThemeManager *theme_mgr;
-
- if (log_window != NULL) {
- gtk_window_present (GTK_WINDOW (log_window->window));
-
- if (account != NULL && chat_id != NULL) {
- gtk_notebook_set_current_page (GTK_NOTEBOOK (log_window->notebook), 1);
- select_account_once_ready (log_window, account, chat_id, is_chatroom);
- }
+ GtkTreeView *view;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ TpAccount *account;
+ TplEntity *target;
+ EmpathyContact *contact;
+ gint type;
- return log_window->window;
- }
+ g_return_if_fail (window != NULL);
- log_window = g_new0 (EmpathyLogWindow, 1);
- log_window->log_manager = tpl_log_manager_dup_singleton ();
-
- window = log_window;
-
- filename = empathy_file_lookup ("empathy-log-window.ui",
- "libempathy-gtk");
- gui = empathy_builder_get_file (filename,
- "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);
- g_free (filename);
-
- empathy_builder_connect (gui, window,
- "log_window", "destroy", log_window_destroy_cb,
- "entry_find", "changed", log_window_entry_find_changed_cb,
- "entry_find", "activate", log_window_entry_find_activate_cb,
- "button_previous", "clicked", log_window_button_previous_clicked_cb,
- "button_next", "clicked", log_window_button_next_clicked_cb,
- "button_close", "clicked", log_window_button_close_clicked_cb,
- "button_close2", "clicked", log_window_button_close_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 (gui);
-
- g_object_add_weak_pointer (G_OBJECT (window->window),
- (gpointer) &log_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 EmpathyChatView */
- theme_mgr = empathy_theme_manager_dup_singleton ();
- window->chatview_find = empathy_theme_manager_create_view (theme_mgr);
- gtk_container_add (GTK_CONTAINER (window->scrolledwindow_find),
- GTK_WIDGET (window->chatview_find));
- gtk_widget_show (GTK_WIDGET (window->chatview_find));
-
- /* Configure Contacts EmpathyChatView */
- window->chatview_chats = empathy_theme_manager_create_view (theme_mgr);
- gtk_container_add (GTK_CONTAINER (window->scrolledwindow_chats),
- GTK_WIDGET (window->chatview_chats));
- gtk_widget_show (GTK_WIDGET (window->chatview_chats));
- g_object_unref (theme_mgr);
-
- /* Account chooser for chats */
- window->account_chooser_chats = empathy_account_chooser_new ();
-
- 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 */
- account_manager = tp_account_manager_dup ();
- tp_account_manager_prepare_async (account_manager, NULL,
- account_manager_prepared_cb, window);
- g_object_unref (account_manager);
-
- /* Search List */
- log_window_find_setup (window);
-
- /* Contacts */
- log_window_chats_setup (window);
- log_window_chats_populate (window);
-
- if (account != NULL && chat_id != NULL)
- select_account_once_ready (window, account, chat_id, is_chatroom);
-
- if (parent != NULL) {
- gtk_window_set_transient_for (GTK_WINDOW (window->window),
- GTK_WINDOW (parent));
- }
+ view = GTK_TREE_VIEW (log_window->treeview_who);
+ selection = gtk_tree_view_get_selection (view);
- gtk_widget_show (window->window);
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ COL_WHO_ACCOUNT, &account,
+ COL_WHO_TARGET, &target,
+ COL_WHO_TYPE, &type,
+ -1);
+ }
- return window->window;
-}
+ g_return_if_fail (type == COL_TYPE_NORMAL);
-static void
-log_window_destroy_cb (GtkWidget *widget,
- EmpathyLogWindow *window)
-{
- g_free (window->last_find);
- g_object_unref (window->log_manager);
- tp_clear_object (&window->selected_account);
- g_free (window->selected_chat_id);
+ contact = empathy_contact_from_tpl_contact (account, target);
+ empathy_contact_information_dialog_show (contact,
+ GTK_WINDOW (window->window));
- g_free (window);
+ g_object_unref (contact);
+ g_object_unref (account);
+ g_object_unref (target);
}
-/*
- * Search code.
- */
static void
-log_window_entry_find_changed_cb (GtkWidget *entry,
- EmpathyLogWindow *window)
+toolbutton_chat_clicked (GtkToolButton *toolbutton,
+ EmpathyLogWindow *window)
{
- const gchar *str;
- gboolean is_sensitive = TRUE;
+ GtkTreeView *view;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ TpAccount *account;
+ TplEntity *target;
+ EmpathyContact *contact;
+ gint type;
+
+ g_return_if_fail (window != NULL);
+
+ view = GTK_TREE_VIEW (log_window->treeview_who);
+ selection = gtk_tree_view_get_selection (view);
- str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ COL_WHO_ACCOUNT, &account,
+ COL_WHO_TARGET, &target,
+ COL_WHO_TYPE, &type,
+ -1);
+ }
- is_sensitive &= !EMP_STR_EMPTY (str);
- is_sensitive &=
- !window->last_find ||
- (window->last_find && tp_strdiff (window->last_find, str));
+ g_return_if_fail (type == COL_TYPE_NORMAL);
- gtk_widget_set_sensitive (window->button_find, is_sensitive);
+ contact = empathy_contact_from_tpl_contact (account, target);
+ empathy_dispatcher_chat_with_contact (contact,
+ gtk_get_current_event_time ());
+
+ g_object_unref (contact);
+ g_object_unref (account);
+ g_object_unref (target);
}
static void
-got_events_for_date_cb (GObject *manager,
- GAsyncResult *result,
- gpointer user_data)
+toolbutton_av_clicked (GtkToolButton *toolbutton,
+ EmpathyLogWindow *window)
{
- EmpathyLogWindow *window = user_data;
- GList *messages;
- GList *l;
- gboolean can_do_previous;
- gboolean can_do_next;
- GError *error = NULL;
+ GtkTreeView *view;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ TpAccount *account;
+ gchar *contact;
+ gint type;
+ gboolean video;
- if (log_window == NULL)
- return;
+ g_return_if_fail (window != NULL);
- if (!tpl_log_manager_get_events_for_date_finish (TPL_LOG_MANAGER (manager),
- result, &messages, &error)) {
- DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
- error->message);
- empathy_chat_view_append_event (window->chatview_find,
- "Unable to retrieve messages for the selected date");
- g_error_free (error);
- return;
- }
+ view = GTK_TREE_VIEW (log_window->treeview_who);
+ selection = gtk_tree_view_get_selection (view);
- for (l = messages; l; l = l->next) {
- EmpathyMessage *message;
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ COL_WHO_ACCOUNT, &account,
+ COL_WHO_NAME, &contact,
+ COL_WHO_TYPE, &type,
+ -1);
+ }
- g_assert (TPL_IS_EVENT (l->data));
+ g_return_if_fail (type == COL_TYPE_NORMAL);
- message = empathy_message_from_tpl_log_event (l->data);
- g_object_unref (l->data);
- empathy_chat_view_append_message (window->chatview_find, message);
- g_object_unref (message);
- }
- g_list_free (messages);
-
- /* Scroll to the most recent messages */
- empathy_chat_view_scroll (window->chatview_find, TRUE);
-
- /* Highlight and find messages */
- empathy_chat_view_highlight (window->chatview_find,
- window->last_find,
- FALSE);
- empathy_chat_view_find_next (window->chatview_find,
- window->last_find,
- TRUE,
- FALSE);
- empathy_chat_view_find_abilities (window->chatview_find,
- window->last_find,
- FALSE,
- &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);
+ video = (GTK_WIDGET (toolbutton) == window->button_video);
+
+ empathy_call_new_with_streams (contact, account,
+ TRUE, video, gtk_get_current_event_time ());
+
+ g_free (contact);
+ g_object_unref (account);
}
-static GDate *
-gdate_from_str (const gchar *str)
+GtkWidget *
+empathy_log_window_show (TpAccount *account,
+ const gchar *chat_id,
+ gboolean is_chatroom,
+ GtkWindow *parent)
{
- guint u;
- guint day, month, year;
+ EmpathyAccountChooser *account_chooser;
+ GtkBuilder *gui;
+ gchar *filename;
+ EmpathyLogWindow *window;
+ EmpathyThemeManager *theme_mgr;
+ GtkWidget *vbox, *accounts, *search, *label, *quit;
+
+ if (log_window != NULL)
+ {
+ gtk_window_present (GTK_WINDOW (log_window->window));
+
+ if (account != NULL && chat_id != NULL)
+ select_account_once_ready (log_window, account, chat_id, is_chatroom);
+
+ return log_window->window;
+ }
+
+ log_window = g_new0 (EmpathyLogWindow, 1);
+ log_window->chain = _tpl_action_chain_new_async (NULL, NULL, NULL);
+
+ log_window->log_manager = tpl_log_manager_dup_singleton ();
+
+ window = log_window;
+
+ filename = empathy_file_lookup ("empathy-log-window.ui", "libempathy-gtk");
+ gui = empathy_builder_get_file (filename,
+ "log_window", &window->window,
+ "toolbutton_profile", &window->button_profile,
+ "toolbutton_chat", &window->button_chat,
+ "toolbutton_call", &window->button_call,
+ "toolbutton_video", &window->button_video,
+ "toolbutton_accounts", &accounts,
+ "toolbutton_search", &search,
+ "imagemenuitem_quit", &quit,
+ "treeview_who", &window->treeview_who,
+ "treeview_what", &window->treeview_what,
+ "treeview_when", &window->treeview_when,
+ "scrolledwindow_events", &window->scrolledwindow_events,
+ NULL);
+ g_free (filename);
+
+ empathy_builder_connect (gui, window,
+ "log_window", "destroy", log_window_destroy_cb,
+ "toolbutton_profile", "clicked", toolbutton_profile_clicked,
+ "toolbutton_chat", "clicked", toolbutton_chat_clicked,
+ "toolbutton_call", "clicked", toolbutton_av_clicked,
+ "toolbutton_video", "clicked", toolbutton_av_clicked,
+ "imagemenuitem_delete", "activate", log_window_delete_menu_clicked_cb,
+ NULL);
+
+ g_object_unref (gui);
+
+ g_object_add_weak_pointer (G_OBJECT (window->window),
+ (gpointer) &log_window);
+
+ g_signal_connect_swapped (quit, "activate",
+ G_CALLBACK (gtk_widget_destroy), window->window);
+
+ /* Configure Contacts EmpathyChatView */
+ theme_mgr = empathy_theme_manager_dup_singleton ();
+ window->chatview_events = empathy_theme_manager_create_view (theme_mgr);
+ gtk_container_add (GTK_CONTAINER (window->scrolledwindow_events),
+ GTK_WIDGET (window->chatview_events));
+ gtk_widget_show (GTK_WIDGET (window->chatview_events));
+ g_object_unref (theme_mgr);
+
+ /* Account chooser for chats */
+ vbox = gtk_vbox_new (FALSE, 3);
+
+ window->account_chooser = empathy_account_chooser_new ();
+ account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
+ empathy_account_chooser_set_has_all_option (account_chooser, TRUE);
+ empathy_account_chooser_set_filter (account_chooser,
+ empathy_account_chooser_filter_has_logs, NULL);
+
+ g_signal_connect (window->account_chooser, "changed",
+ G_CALLBACK (log_window_chats_accounts_changed_cb),
+ window);
- if (sscanf (str, "%u", &u) != 1)
- return NULL;
+ label = gtk_label_new (_("Show"));
- day = (u % 100);
- month = ((u / 100) % 100);
- year = (u / 10000);
+ gtk_box_pack_start (GTK_BOX (vbox),
+ window->account_chooser,
+ FALSE, FALSE, 0);
- if (!g_date_valid_dmy (day, month, year))
- return NULL;
+ gtk_box_pack_start (GTK_BOX (vbox),
+ label,
+ FALSE, FALSE, 0);
- return g_date_new_dmy (day, month, year);
-}
+ gtk_widget_show_all (vbox);
+ gtk_container_add (GTK_CONTAINER (accounts), vbox);
-static void
-log_window_find_changed_cb (GtkTreeSelection *selection,
- EmpathyLogWindow *window)
-{
- GtkTreeView *view;
- GtkTreeModel *model;
- GtkTreeIter iter;
- TpAccount *account;
- TplEntity *target;
- gchar *date;
- GDate *gdate;
-
- /* Get selected information */
- view = GTK_TREE_VIEW (window->treeview_find);
- model = gtk_tree_view_get_model (view);
+ /* Search entry */
+ vbox = gtk_vbox_new (FALSE, 3);
- 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);
+ window->search_entry = gtk_entry_new ();
+ gtk_entry_set_icon_from_stock (GTK_ENTRY (window->search_entry),
+ GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND);
- empathy_chat_view_clear (window->chatview_find);
+ label = gtk_label_new (_("Search"));
- return;
- }
+ gtk_box_pack_start (GTK_BOX (vbox),
+ window->search_entry,
+ FALSE, FALSE, 0);
- gtk_widget_set_sensitive (window->button_previous, TRUE);
- gtk_widget_set_sensitive (window->button_next, TRUE);
+ gtk_box_pack_start (GTK_BOX (vbox),
+ label,
+ FALSE, FALSE, 0);
- gtk_tree_model_get (model, &iter,
- COL_FIND_ACCOUNT, &account,
- COL_FIND_TARGET, &target,
- COL_FIND_DATE, &date,
- -1);
+ gtk_widget_show_all (vbox);
+ gtk_container_add (GTK_CONTAINER (search), vbox);
- /* Clear all current messages shown in the textview */
- empathy_chat_view_clear (window->chatview_find);
+ g_signal_connect (window->search_entry, "changed",
+ G_CALLBACK (log_window_search_entry_changed_cb),
+ window);
+
+ g_signal_connect (window->search_entry, "activate",
+ G_CALLBACK (log_window_search_entry_activate_cb),
+ window);
- /* Turn off scrolling temporarily */
- empathy_chat_view_scroll (window->chatview_find, FALSE);
+ /* Contacts */
+ log_window_who_setup (window);
+ log_window_what_setup (window);
+ log_window_when_setup (window);
- /* Get messages */
- gdate = gdate_from_str (date);
+ log_window_who_populate (window);
- if (gdate != NULL) {
- tpl_log_manager_get_events_for_date_async (window->log_manager,
- account,
- target,
- TPL_EVENT_MASK_TEXT,
- gdate,
- got_events_for_date_cb,
- window);
+ if (account != NULL && chat_id != NULL)
+ select_account_once_ready (window, account, chat_id, is_chatroom);
- g_date_free (gdate);
- }
+ if (parent != NULL)
+ gtk_window_set_transient_for (GTK_WINDOW (window->window),
+ GTK_WINDOW (parent));
- g_object_unref (account);
- g_object_unref (target);
- g_free (date);
-}
+ gtk_widget_show (window->window);
+ return window->window;
+}
static void
-log_manager_searched_new_cb (GObject *manager,
- GAsyncResult *result,
- gpointer user_data)
+log_window_destroy_cb (GtkWidget *widget,
+ EmpathyLogWindow *window)
{
- GList *hits;
- GList *l;
- GtkTreeIter iter;
- GtkListStore *store = user_data;
- GError *error = NULL;
-
- if (log_window == NULL)
- return;
+ g_free (window->last_find);
+ _tpl_action_chain_free (window->chain);
+ g_object_unref (window->log_manager);
+ tp_clear_object (&window->selected_account);
+ g_free (window->selected_chat_id);
- if (!tpl_log_manager_search_finish (TPL_LOG_MANAGER (manager), result,
- &hits, &error)) {
- DEBUG ("%s. Aborting", error->message);
- g_error_free (error);
- return;
- }
+ g_free (window);
+}
- for (l = hits; l; l = l->next) {
- TplLogSearchHit *hit;
- const gchar *account_name;
- const gchar *account_icon;
- gchar date_readable[255];
- gchar tmp[255];
-
- hit = l->data;
-
- /* Protect against invalid data (corrupt or old log files. */
- if (hit->account == NULL || hit->target == NULL) {
- continue;
- }
-
- g_date_strftime (date_readable, sizeof (date_readable),
- EMPATHY_DATE_FORMAT_DISPLAY_SHORT, hit->date);
-
- g_date_strftime (tmp, sizeof (tmp),
- "%Y%m%d", hit->date);
-
- account_name = tp_account_get_display_name (hit->account);
- account_icon = tp_account_get_icon_name (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, tpl_entity_get_alias (hit->target),
- COL_FIND_TARGET, hit->target,
- COL_FIND_DATE, tmp,
- COL_FIND_DATE_READABLE, date_readable,
- -1);
-
- /* FIXME: Update COL_FIND_CHAT_NAME */
- if (tpl_entity_get_entity_type (hit->target) == TPL_ENTITY_ROOM) {
- } else {
- }
- }
+static gboolean
+log_window_chats_get_selected (EmpathyLogWindow *window,
+ TpAccount **account,
+ TplEntity **target,
+ GDate **date,
+ TplEventTypeMask *event_mask,
+ EventSubtype *subtype)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ TplEntity *targ;
+ TpAccount *acc = NULL;
+ TplEventTypeMask ev = 0;
+ EventSubtype st = 0;
+ GDate *d = NULL;
+
+ view = GTK_TREE_VIEW (window->treeview_who);
+ 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_WHO_ACCOUNT, &acc,
+ COL_WHO_TARGET, &targ,
+ -1);
+
+ view = GTK_TREE_VIEW (window->treeview_what);
+ model = gtk_tree_view_get_model (view);
+ selection = gtk_tree_view_get_selection (view);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ COL_WHAT_TYPE, &ev,
+ COL_WHAT_SUBTYPE, &st,
+ -1);
+ }
+
+ view = GTK_TREE_VIEW (window->treeview_when);
+ model = gtk_tree_view_get_model (view);
+ selection = gtk_tree_view_get_selection (view);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ COL_WHEN_DATE, &d,
+ -1);
+ }
+
+ if (account != NULL)
+ *account = acc ? g_object_ref (acc) : NULL;
+
+ if (target != NULL)
+ *target = targ ? g_object_ref (targ) : NULL;
+
+ if (date != NULL)
+ *date = d;
+
+ if (event_mask != NULL)
+ *event_mask = ev;
+
+ if (subtype != NULL)
+ *subtype = st;
+
+ tp_clear_object (&acc);
+ tp_clear_object (&targ);
+
+ return TRUE;
+}
- if (hits != NULL) {
- tpl_log_manager_search_free (hits);
- }
+static gboolean
+account_equal (TpAccount *a,
+ TpAccount *b)
+{
+ return g_str_equal (tp_proxy_get_object_path (a),
+ tp_proxy_get_object_path (b));
}
-static void
-log_window_find_populate (EmpathyLogWindow *window,
- const gchar *search_criteria)
+static gboolean
+entity_equal (TplEntity *a,
+ TplEntity *b)
{
- GtkTreeView *view;
- GtkTreeModel *model;
- GtkListStore *store;
+ return g_str_equal (tpl_entity_get_identifier (a),
+ tpl_entity_get_identifier (b));
+}
- view = GTK_TREE_VIEW (window->treeview_find);
- model = gtk_tree_view_get_model (view);
- store = GTK_LIST_STORE (model);
+static gboolean
+model_has_entity (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ TplLogSearchHit *hit = data;
+ TplEntity *e;
+ TpAccount *a;
+
+ gtk_tree_model_get (model, iter,
+ COL_WHO_TARGET, &e,
+ COL_WHO_ACCOUNT, &a,
+ -1);
+
+ if (e != NULL && entity_equal (hit->target, e) &&
+ a != NULL && account_equal (hit->account, a))
+ {
+ has_element = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
- empathy_chat_view_clear (window->chatview_find);
+static gboolean
+model_has_date (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GDate *date = data;
+ GDate *d;
- gtk_list_store_clear (store);
+ gtk_tree_model_get (model, iter,
+ COL_WHEN_DATE, &d,
+ -1);
- if (EMP_STR_EMPTY (search_criteria)) {
- /* Just clear the search. */
- return;
- }
+ if (!g_date_compare (date, d))
+ {
+ has_element = TRUE;
+ return TRUE;
+ }
- tpl_log_manager_search_async (window->log_manager,
- search_criteria, TPL_EVENT_MASK_TEXT,
- log_manager_searched_new_cb, (gpointer) store);
+ return FALSE;
}
static void
-log_window_find_setup (EmpathyLogWindow *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 */
- TP_TYPE_ACCOUNT, /* account */
- G_TYPE_STRING, /* chat name */
- TPL_TYPE_ENTITY, /* target */
- 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);
-}
+get_events_for_date (TplActionChain *chain, gpointer user_data);
static void
-start_find_search (EmpathyLogWindow *window)
+populate_events_from_search_hits (TpAccount *account,
+ TplEntity *target,
+ GDate *date)
{
- const gchar *str;
+ TplEventTypeMask event_mask;
+ EventSubtype subtype;
+ GDate *anytime;
+ GList *l;
- str = gtk_entry_get_text (GTK_ENTRY (window->entry_find));
+ if (!log_window_chats_get_selected (log_window,
+ NULL, NULL, NULL, &event_mask, &subtype))
+ return;
- /* Don't find the same crap again */
- if (window->last_find && !tp_strdiff (window->last_find, str)) {
- return;
- }
+ anytime = g_date_new_dmy (2, 1, -1);
- g_free (window->last_find);
- window->last_find = g_strdup (str);
+ for (l = log_window->hits; l != NULL; l = l->next)
+ {
+ TplLogSearchHit *hit = l->data;
- log_window_find_populate (window, str);
-}
+ /* Protect against invalid data (corrupt or old log files). */
+ if (hit->account == NULL || hit->target == NULL)
+ continue;
-static void
-log_window_button_find_clicked_cb (GtkWidget *widget,
- EmpathyLogWindow *window)
-{
- start_find_search (window);
+ if (!account_equal (hit->account, account) ||
+ !entity_equal (hit->target, target))
+ continue;
+
+ if (g_date_compare (date, anytime) == 0 ||
+ g_date_compare (date, hit->date) == 0)
+ {
+ Ctx *ctx;
+
+ ctx = ctx_new (log_window, hit->account, hit->target, hit->date,
+ event_mask, subtype);
+ _tpl_action_chain_append (log_window->chain,
+ get_events_for_date, ctx);
+ }
+ }
+
+ _tpl_action_chain_start (log_window->chain);
+
+ g_date_free (anytime);
}
static void
-log_window_entry_find_activate_cb (GtkWidget *entry,
- EmpathyLogWindow *self)
+populate_dates_from_search_hits (TpAccount *account,
+ TplEntity *target)
{
- start_find_search (self);
+ GList *l;
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkListStore *store;
+ GtkTreeIter iter;
+
+ if (log_window == NULL)
+ return;
+
+ view = GTK_TREE_VIEW (log_window->treeview_when);
+ model = gtk_tree_view_get_model (view);
+ store = GTK_LIST_STORE (model);
+
+ for (l = log_window->hits; l != NULL; l = l->next)
+ {
+ TplLogSearchHit *hit = l->data;
+
+ /* Protect against invalid data (corrupt or old log files). */
+ if (hit->account == NULL || hit->target == NULL)
+ continue;
+
+ if (!account_equal (hit->account, account) ||
+ !entity_equal (hit->target, target))
+ continue;
+
+ /* Add the date if it's not already there */
+ has_element = FALSE;
+ gtk_tree_model_foreach (model, model_has_date, hit->date);
+ if (!has_element)
+ {
+ gchar *text = g_strdup_printf ("%02d/%02d/%d",
+ g_date_get_day (hit->date),
+ g_date_get_month (hit->date),
+ g_date_get_year (hit->date));
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHEN_DATE, hit->date,
+ COL_WHEN_TEXT, text,
+ COL_WHEN_ICON, CALENDAR_ICON,
+ -1);
+ }
+ }
+
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHEN_DATE, g_date_new_dmy (1, 1, -1),
+ COL_WHEN_TEXT, "separator",
+ -1);
+
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHEN_DATE, g_date_new_dmy (2, 1, -1),
+ COL_WHEN_TEXT, _("Anytime"),
+ -1);
+ }
}
static void
-log_window_button_next_clicked_cb (GtkWidget *widget,
- EmpathyLogWindow *window)
+populate_entities_from_search_hits (void)
{
- if (window->last_find) {
- gboolean can_do_previous;
- gboolean can_do_next;
-
- empathy_chat_view_find_next (window->chatview_find,
- window->last_find,
- FALSE,
- FALSE);
- empathy_chat_view_find_abilities (window->chatview_find,
- window->last_find,
- FALSE,
- &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);
- }
+ EmpathyAccountChooser *account_chooser;
+ TpAccount *account;
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkListStore *store;
+ GList *l;
+
+ view = GTK_TREE_VIEW (log_window->treeview_who);
+ model = gtk_tree_view_get_model (view);
+ store = GTK_LIST_STORE (model);
+
+ gtk_list_store_clear (store);
+
+ account_chooser = EMPATHY_ACCOUNT_CHOOSER (log_window->account_chooser);
+ account = empathy_account_chooser_get_account (account_chooser);
+
+ for (l = log_window->hits; l; l = l->next)
+ {
+ TplLogSearchHit *hit = l->data;
+
+ /* Protect against invalid data (corrupt or old log files). */
+ if (hit->account == NULL || hit->target == NULL)
+ continue;
+
+ /* Filter based on the selected account */
+ if (account != NULL && !account_equal (account, hit->account))
+ continue;
+
+ /* Add the entity if it's not already there */
+ has_element = FALSE;
+ gtk_tree_model_foreach (model, model_has_entity, hit);
+ if (!has_element)
+ {
+ TplEntityType type = tpl_entity_get_entity_type (hit->target);
+ gboolean room = type == TPL_ENTITY_ROOM;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHO_TYPE, COL_TYPE_NORMAL,
+ COL_WHO_ICON, room ? EMPATHY_IMAGE_GROUP_MESSAGE
+ : EMPATHY_IMAGE_AVATAR_DEFAULT,
+ COL_WHO_NAME, tpl_entity_get_alias (hit->target),
+ COL_WHO_ACCOUNT, hit->account,
+ COL_WHO_TARGET, hit->target,
+ -1);
+ }
+ }
+
+#if 0
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHO_TYPE, COL_TYPE_SEPARATOR,
+ COL_WHO_NAME, "separator",
+ -1);
+
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHO_TYPE, COL_TYPE_ANY,
+ COL_WHO_NAME, _("Anyone"),
+ -1);
+ }
+#endif
}
static void
-log_window_button_previous_clicked_cb (GtkWidget *widget,
- EmpathyLogWindow *window)
+log_manager_searched_new_cb (GObject *manager,
+ GAsyncResult *result,
+ gpointer user_data)
{
- if (window->last_find) {
- gboolean can_do_previous;
- gboolean can_do_next;
-
- empathy_chat_view_find_previous (window->chatview_find,
- window->last_find,
- FALSE,
- FALSE);
- empathy_chat_view_find_abilities (window->chatview_find,
- window->last_find,
- FALSE,
- &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);
- }
+ GList *hits;
+ GtkTreeView *view;
+ GtkTreeSelection *selection;
+ GError *error = NULL;
+
+ if (log_window == NULL)
+ return;
+
+ if (!tpl_log_manager_search_finish (TPL_LOG_MANAGER (manager),
+ result, &hits, &error))
+ {
+ DEBUG ("%s. Aborting", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ tp_clear_pointer (&log_window->hits, tpl_log_manager_search_free);
+ log_window->hits = hits;
+
+ populate_entities_from_search_hits ();
+
+ /* FIXME: select old entity if still available, and populate the dates */
+ //populate_dates_from_search_hits (NULL, NULL);
+
+ view = GTK_TREE_VIEW (log_window->treeview_when);
+ selection = gtk_tree_view_get_selection (view);
+
+ g_signal_handlers_unblock_by_func (selection,
+ log_window_when_changed_cb,
+ log_window);
}
-static void
-log_window_button_close_clicked_cb (GtkWidget *widget,
- EmpathyLogWindow *window)
+#if 0
+static gboolean
+search_results_filter_entities (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
{
- gtk_widget_destroy (window->window);
-}
+ TpAccount *account, *selected_account;
+ gboolean visible = FALSE;
-/*
- * Chats Code
- */
+ if (log_window->hits == NULL)
+ return TRUE;
-static void
-log_window_chats_changed_cb (GtkTreeSelection *selection,
- EmpathyLogWindow *window)
-{
- gboolean selected;
+ if (!log_window_chats_get_selected (log_window, &selected_account,
+ NULL, NULL, NULL, NULL))
+
+ gtk_tree_model_get (model, iter,
+ COL_WHO_ACCOUNT, &account,
+ -1);
- /* The calendar has to be sensitive only if there is something selected */
- selected = log_window_chats_get_selected (window, NULL, NULL);
- gtk_widget_set_sensitive (window->calendar_chats, selected);
+ if (selected_account == NULL ||
+ account_equal (account, selected_account))
+ visible = TRUE;
- /* Use last date by default */
- gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
+ g_object_unref (account);
+ g_object_unref (selected_account);
- log_window_chats_get_messages (window, NULL);
+ return visible;
}
+#endif
static void
-log_manager_got_entities_cb (GObject *manager,
- GAsyncResult *result,
- gpointer user_data)
+log_window_find_populate (EmpathyLogWindow *window,
+ const gchar *search_criteria)
{
- GList *entities;
- GList *l;
- GtkTreeView *view;
- GtkTreeModel *model;
- GtkTreeSelection *selection;
- GtkListStore *store;
- GtkTreeIter iter;
- GError *error = NULL;
- gboolean select_account = FALSE;
- TpAccount *account = user_data;
-
- if (log_window == NULL)
- goto out;
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkListStore *store;
- if (!tpl_log_manager_get_entities_finish (TPL_LOG_MANAGER (manager),
- result, &entities, &error)) {
- DEBUG ("%s. Aborting", error->message);
- g_error_free (error);
- goto out;
- }
+ empathy_chat_view_clear (window->chatview_events);
- view = GTK_TREE_VIEW (log_window->treeview_chats);
- model = gtk_tree_view_get_model (view);
- selection = gtk_tree_view_get_selection (view);
- store = GTK_LIST_STORE (model);
+ view = GTK_TREE_VIEW (window->treeview_who);
+ model = gtk_tree_view_get_model (view);
+ store = GTK_LIST_STORE (model);
- for (l = entities; l; l = l->next) {
- TplEntity *entity;
+ gtk_list_store_clear (store);
- entity = TPL_ENTITY (l->data);
+ view = GTK_TREE_VIEW (window->treeview_when);
+ model = gtk_tree_view_get_model (view);
+ store = GTK_LIST_STORE (model);
+ selection = gtk_tree_view_get_selection (view);
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter,
- COL_CHAT_ICON, "empathy-available", /* FIXME */
- COL_CHAT_NAME, tpl_entity_get_alias (entity),
- COL_CHAT_ACCOUNT, account,
- COL_CHAT_TARGET, entity,
- -1);
+ gtk_list_store_clear (store);
- if (log_window->selected_account != NULL &&
- !tp_strdiff (tp_proxy_get_object_path (account),
- tp_proxy_get_object_path (log_window->selected_account)))
- select_account = TRUE;
+ if (EMP_STR_EMPTY (search_criteria))
+ {
+ tp_clear_pointer (&window->hits, tpl_log_manager_search_free);
+ log_window_who_populate (window);
+ return;
+ }
- /* FIXME: Update COL_CHAT_ICON/NAME */
- if (tpl_entity_get_entity_type (entity) == TPL_ENTITY_ROOM) {
- } else {
- }
- }
- g_list_free_full (entities, g_object_unref);
+ g_signal_handlers_block_by_func (selection,
+ log_window_when_changed_cb,
+ window);
+
+ tpl_log_manager_search_async (window->log_manager,
+ search_criteria, TPL_EVENT_MASK_ANY,
+ log_manager_searched_new_cb, NULL);
+}
+
+static void
+start_find_search (EmpathyLogWindow *window)
+{
+ const gchar *str;
- /* Unblock signals */
- g_signal_handlers_unblock_by_func (selection,
- log_window_chats_changed_cb,
- log_window);
+ str = gtk_entry_get_text (GTK_ENTRY (window->search_entry));
- /* We display the selected account if we populate the model with chats from
- * this account. */
- if (select_account)
- log_window_chats_set_selected (log_window);
+ /* Don't find the same crap again */
+ if (window->last_find && !tp_strdiff (window->last_find, str))
+ return;
-out:
- g_object_unref (account);
+ g_free (window->last_find);
+ window->last_find = g_strdup (str);
+
+ log_window_find_populate (window, str);
}
static void
-log_window_chats_populate (EmpathyLogWindow *window)
+log_window_search_entry_changed_cb (GtkWidget *entry,
+ EmpathyLogWindow *window)
{
- EmpathyAccountChooser *account_chooser;
- TpAccount *account;
+ /* FIXME: live search ? */
+}
- GtkTreeView *view;
- GtkTreeModel *model;
- GtkTreeSelection *selection;
- GtkListStore *store;
+static void
+log_window_search_entry_activate_cb (GtkWidget *entry,
+ EmpathyLogWindow *self)
+{
+ start_find_search (self);
+}
- account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
- account = empathy_account_chooser_dup_account (account_chooser);
+/*
+ * Chats Code
+ */
- 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);
+static void
+log_window_who_changed_cb (GtkTreeSelection *selection,
+ EmpathyLogWindow *window)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gint type;
+ gboolean someone = FALSE;
+
+g_print ("log_window_who_changed_cb\n");
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter,
+ COL_WHO_TYPE, &type,
+ -1);
+
+ someone = (type == COL_TYPE_NORMAL);
+ }
+
+ gtk_widget_set_sensitive (window->button_profile, someone);
+ gtk_widget_set_sensitive (window->button_chat, someone);
+ gtk_widget_set_sensitive (window->button_call, someone);
+ gtk_widget_set_sensitive (window->button_video, someone);
+
+ /* The contact changed, so the dates need to be updated */
+ log_window_chats_get_messages (window, TRUE);
+}
- if (account == NULL) {
- gtk_list_store_clear (store);
- return;
- }
+static void
+log_manager_got_entities_cb (GObject *manager,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Ctx *ctx = user_data;
+ GList *entities;
+ GList *l;
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GError *error = NULL;
+ gboolean select_account = FALSE;
- /* Block signals to stop the logs being retrieved prematurely */
- g_signal_handlers_block_by_func (selection,
- log_window_chats_changed_cb,
- window);
+ if (log_window == NULL)
+ goto out;
- gtk_list_store_clear (store);
+ if (!tpl_log_manager_get_entities_finish (TPL_LOG_MANAGER (manager),
+ result, &entities, &error))
+ {
+ DEBUG ("%s. Aborting", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ view = GTK_TREE_VIEW (ctx->window->treeview_who);
+ 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_who_changed_cb, ctx->window);
+
+ for (l = entities; l; l = l->next)
+ {
+ TplEntity *entity = TPL_ENTITY (l->data);
+ TplEntityType type = tpl_entity_get_entity_type (entity);
+ gboolean room = type == TPL_ENTITY_ROOM;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHO_TYPE, COL_TYPE_NORMAL,
+ COL_WHO_ICON, room ? EMPATHY_IMAGE_GROUP_MESSAGE
+ : EMPATHY_IMAGE_AVATAR_DEFAULT,
+ COL_WHO_NAME, tpl_entity_get_alias (entity),
+ COL_WHO_ACCOUNT, ctx->account,
+ COL_WHO_TARGET, entity,
+ -1);
+
+ if (ctx->window->selected_account != NULL &&
+ !tp_strdiff (tp_proxy_get_object_path (ctx->account),
+ tp_proxy_get_object_path (ctx->window->selected_account)))
+ select_account = TRUE;
+ }
+ g_list_free_full (entities, g_object_unref);
+
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ gint type;
+
+ gtk_tree_model_get (model, &iter,
+ COL_WHO_TYPE, &type,
+ -1);
+
+ if (type != COL_TYPE_ANY)
+ {
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHO_TYPE, COL_TYPE_SEPARATOR,
+ COL_WHO_NAME, "separator",
+ -1);
+
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHO_TYPE, COL_TYPE_ANY,
+ COL_WHO_NAME, _("Anyone"),
+ -1);
+ }
+ }
+
+ /* Select 'Anyone' by default */
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ /* Unblock signals */
+ g_signal_handlers_unblock_by_func (selection,
+ log_window_who_changed_cb,
+ ctx->window);
+
+ /* We display the selected account if we populate the model with chats from
+ * this account. */
+ if (select_account)
+ log_window_chats_set_selected (ctx->window);
- /* Pass the account reference to the callback */
- tpl_log_manager_get_entities_async (window->log_manager, account,
- log_manager_got_entities_cb, account);
+out:
+ _tpl_action_chain_continue (log_window->chain);
+ ctx_free (ctx);
}
static void
-log_window_chats_setup (EmpathyLogWindow *window)
+get_entities_for_account (TplActionChain *chain, gpointer user_data)
{
- 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);
+ Ctx *ctx = user_data;
- /* new store */
- store = gtk_list_store_new (COL_CHAT_COUNT,
- G_TYPE_STRING, /* icon */
- G_TYPE_STRING, /* name */
- TP_TYPE_ACCOUNT, /* account */
- TPL_TYPE_ENTITY); /* target */
+g_print ("get_entities_for_account\n");
+ tpl_log_manager_get_entities_async (ctx->window->log_manager, ctx->account,
+ log_manager_got_entities_cb, ctx);
+}
- model = GTK_TREE_MODEL (store);
- sortable = GTK_TREE_SORTABLE (store);
+static void
+log_window_who_populate (EmpathyLogWindow *window)
+{
+ EmpathyAccountChooser *account_chooser;
+ TpAccount *account;
+ gboolean all_accounts;
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkListStore *store;
+ Ctx *ctx;
+
+ if (window->hits != NULL)
+ {
+ populate_entities_from_search_hits ();
+ return;
+ }
+
+ account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
+ account = empathy_account_chooser_dup_account (account_chooser);
+ all_accounts = empathy_account_chooser_has_all_selected (account_chooser);
- gtk_tree_view_set_model (view, model);
+ view = GTK_TREE_VIEW (window->treeview_who);
+ model = gtk_tree_view_get_model (view);
+ selection = gtk_tree_view_get_selection (view);
+ store = GTK_LIST_STORE (model);
- /* new column */
- column = gtk_tree_view_column_new ();
+ /* Block signals to stop the logs being retrieved prematurely */
+ g_signal_handlers_block_by_func (selection,
+ log_window_who_changed_cb,
+ window);
+
+ gtk_list_store_clear (store);
- 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);
+ /* Unblock signals */
+ g_signal_handlers_unblock_by_func (selection,
+ log_window_who_changed_cb,
+ window);
- 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);
+ if (!all_accounts && account == NULL)
+ {
+ return;
+ }
+ else if (!all_accounts)
+ {
+ ctx = ctx_new (window, account, NULL, NULL, 0, 0);
+ _tpl_action_chain_append (window->chain, get_entities_for_account, ctx);
+ }
+ else
+ {
+ TpAccountManager *manager;
+ GList *accounts, *l;
+
+ manager = empathy_account_chooser_get_account_manager (account_chooser);
+ accounts = tp_account_manager_get_valid_accounts (manager);
+
+ for (l = accounts; l != NULL; l = l->next)
+ {
+ account = l->data;
+
+ ctx = ctx_new (window, account, NULL, NULL, 0, 0);
+ _tpl_action_chain_append (window->chain,
+ get_entities_for_account, ctx);
+ }
+
+ g_list_free (accounts);
+ }
+ _tpl_action_chain_start (window->chain);
+}
+
+static gint
+sort_by_name (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ gchar *name1, *name2;
+ gint type1, type2;
+ gint ret;
+
+ gtk_tree_model_get (model, a,
+ COL_WHO_TYPE, &type1,
+ COL_WHO_NAME, &name1,
+ -1);
+
+ gtk_tree_model_get (model, b,
+ COL_WHO_TYPE, &type2,
+ COL_WHO_NAME, &name2,
+ -1);
+
+ if (type1 == COL_TYPE_ANY)
+ ret = -1;
+ else if (type2 == COL_TYPE_ANY)
+ ret = 1;
+ else if (type1 == COL_TYPE_SEPARATOR)
+ ret = -1;
+ else if (type2 == COL_TYPE_SEPARATOR)
+ ret = 1;
+ else
+ ret = g_strcmp0 (name1, name2);
+
+ g_free (name1);
+ g_free (name2);
+
+ return ret;
+}
- gtk_tree_view_append_column (view, column);
+static gboolean
+who_row_is_separator (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gint type;
- /* 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);
+ gtk_tree_model_get (model, iter,
+ COL_WHO_TYPE, &type,
+ -1);
- /* set up signals */
- g_signal_connect (selection, "changed",
- G_CALLBACK (log_window_chats_changed_cb),
- window);
+ return (type == COL_TYPE_SEPARATOR);
+}
- g_object_unref (store);
+static void
+log_window_who_setup (EmpathyLogWindow *window)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeSortable *sortable;
+ GtkTreeViewColumn *column;
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+
+ view = GTK_TREE_VIEW (window->treeview_who);
+ selection = gtk_tree_view_get_selection (view);
+
+ /* new store */
+ store = gtk_list_store_new (COL_WHO_COUNT,
+ G_TYPE_INT, /* type */
+ G_TYPE_STRING, /* icon */
+ G_TYPE_STRING, /* name */
+ TP_TYPE_ACCOUNT, /* account */
+ TPL_TYPE_ENTITY); /* target */
+
+ 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 ();
+ gtk_tree_view_column_set_title (column, _("Who"));
+
+ 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_WHO_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_WHO_NAME);
+
+ gtk_tree_view_append_column (view, column);
+
+ /* set up treeview properties */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_row_separator_func (view, who_row_is_separator,
+ NULL, NULL);
+
+ gtk_tree_sortable_set_sort_column_id (sortable,
+ COL_WHO_NAME,
+ GTK_SORT_ASCENDING);
+ gtk_tree_sortable_set_sort_func (sortable,
+ COL_WHO_NAME, sort_by_name,
+ NULL, NULL);
+
+ /* set up signals */
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (log_window_who_changed_cb), window);
+
+ g_object_unref (store);
}
static void
@@ -952,12 +1312,9 @@ log_window_chats_accounts_changed_cb (GtkWidget *combobox,
EmpathyLogWindow *window)
{
/* Clear all current messages shown in the textview */
- empathy_chat_view_clear (window->chatview_chats);
+ empathy_chat_view_clear (window->chatview_events);
- log_window_chats_populate (window);
-
- /* No chat is selected as we just changed the account */
- gtk_widget_set_sensitive (window->calendar_chats, FALSE);
+ log_window_who_populate (window);
}
static void
@@ -970,7 +1327,7 @@ log_window_chats_set_selected (EmpathyLogWindow *window)
GtkTreePath *path;
gboolean ok;
- view = GTK_TREE_VIEW (window->treeview_chats);
+ view = GTK_TREE_VIEW (window->treeview_who);
model = gtk_tree_view_get_model (view);
selection = gtk_tree_view_get_selection (view);
@@ -985,8 +1342,8 @@ log_window_chats_set_selected (EmpathyLogWindow *window)
gboolean this_is_chatroom;
gtk_tree_model_get (model, &iter,
- COL_CHAT_ACCOUNT, &this_account,
- COL_CHAT_TARGET, &this_target,
+ COL_WHO_ACCOUNT, &this_account,
+ COL_WHO_TARGET, &this_target,
-1);
this_chat_id = tpl_entity_get_identifier (this_target);
@@ -1012,43 +1369,257 @@ log_window_chats_set_selected (EmpathyLogWindow *window)
tp_clear_pointer (&window->selected_chat_id, g_free);
}
+static gint
+sort_by_date (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ GDate *date1, *date2;
+
+ gtk_tree_model_get (model, a,
+ COL_WHEN_DATE, &date1,
+ -1);
+
+ gtk_tree_model_get (model, b,
+ COL_WHEN_DATE, &date2,
+ -1);
+
+ return g_date_compare (date1, date2);
+}
+
static gboolean
-log_window_chats_get_selected (EmpathyLogWindow *window,
- TpAccount **account,
- TplEntity **target)
+when_row_is_separator (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
{
- GtkTreeView *view;
- GtkTreeModel *model;
- GtkTreeSelection *selection;
- GtkTreeIter iter;
- TplEntity *targ;
- TpAccount *acc = NULL;
-
- view = GTK_TREE_VIEW (window->treeview_chats);
- model = gtk_tree_view_get_model (view);
- selection = gtk_tree_view_get_selection (view);
+ gchar *when;
+ gboolean ret;
- if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
- return FALSE;
- }
+ gtk_tree_model_get (model, iter,
+ COL_WHEN_TEXT, &when,
+ -1);
- gtk_tree_model_get (model, &iter,
- COL_CHAT_ACCOUNT, &acc,
- COL_CHAT_TARGET, &targ,
- -1);
+ ret = g_str_equal (when, "separator");
+ g_free (when);
+ return ret;
+}
- if (account != NULL) {
- *account = g_object_ref (acc);
- }
+static void
+log_window_when_changed_cb (GtkTreeSelection *selection,
+ EmpathyLogWindow *window)
+{
+g_print ("log_window_when_changed_cb\n");
+ log_window_chats_get_messages (window, FALSE);
+}
- if (target != NULL) {
- *target = g_object_ref (targ);
- }
+static void
+log_window_when_setup (EmpathyLogWindow *window)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeSortable *sortable;
+ GtkTreeViewColumn *column;
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+
+ view = GTK_TREE_VIEW (window->treeview_when);
+ selection = gtk_tree_view_get_selection (view);
+
+ /* new store */
+ store = gtk_list_store_new (COL_WHEN_COUNT,
+ G_TYPE_DATE, /* date */
+ G_TYPE_STRING, /* stringified date */
+ G_TYPE_STRING); /* icon */
+
+ 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 ();
+ gtk_tree_view_column_set_title (column, _("When"));
+
+ 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_WHEN_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_WHEN_TEXT);
+
+ gtk_tree_view_append_column (view, column);
+
+ /* set up treeview properties */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_row_separator_func (view, when_row_is_separator,
+ NULL, NULL);
+ gtk_tree_sortable_set_sort_column_id (sortable,
+ COL_WHEN_DATE,
+ GTK_SORT_DESCENDING);
+ gtk_tree_sortable_set_sort_func (sortable,
+ COL_WHEN_DATE, sort_by_date,
+ NULL, NULL);
+
+ /* set up signals */
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (log_window_when_changed_cb),
+ window);
+
+ g_object_unref (store);
+}
+
+static gboolean
+what_row_is_separator (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gint type;
+
+ gtk_tree_model_get (model, iter,
+ COL_WHAT_TYPE, &type,
+ -1);
+
+ return (type == -1);
+}
- g_object_unref (acc);
- g_object_unref (targ);
+static void
+log_window_what_changed_cb (GtkTreeSelection *selection,
+ EmpathyLogWindow *window)
+{
+g_print ("log_window_what_changed_cb\n");
+ /* The dates need to be updated if we're not searching */
+ log_window_chats_get_messages (window, window->hits == NULL);
+}
+
+static gboolean
+log_window_what_collapse_row_cb (GtkTreeView *tree_view,
+ GtkTreeIter *iter,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ /* Reject collapsing */
+ return TRUE;
+}
+
+struct event
+{
+ gint type;
+ EventSubtype subtype;
+ const gchar *icon;
+ const gchar *text;
+};
+
+static void
+log_window_what_setup (EmpathyLogWindow *window)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeSortable *sortable;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter, parent;
+ GtkTreeStore *store;
+ GtkCellRenderer *cell;
+ guint i;
+ struct event events [] = {
+ { TPL_EVENT_MASK_ANY, 0, NULL, _("Anything") },
+ { -1, 0, NULL, "separator" },
+ { TPL_EVENT_MASK_TEXT, 0, "stock_text_justify", _("Text chats") },
+ { TPL_EVENT_MASK_CALL, EVENT_CALL_ALL, "call-start", _("Calls") }
+ };
+ struct event call_events [] = {
+ { TPL_EVENT_MASK_CALL, EVENT_CALL_INCOMING, "call-start", _("Incoming calls") },
+ { TPL_EVENT_MASK_CALL, EVENT_CALL_OUTGOING, "call-start", _("Outgoing calls") },
+ { TPL_EVENT_MASK_CALL, EVENT_CALL_MISSED, "call-stop", _("Missed calls") }
+ };
+
+ view = GTK_TREE_VIEW (window->treeview_what);
+ selection = gtk_tree_view_get_selection (view);
+
+ /* new store */
+ store = gtk_tree_store_new (COL_WHAT_COUNT,
+ G_TYPE_INT, /* history type */
+ G_TYPE_INT, /* history subtype */
+ G_TYPE_STRING, /* stringified history type */
+ G_TYPE_STRING, /* icon */
+ G_TYPE_BOOLEAN); /* expander (hidden) */
+
+ 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 ();
+ gtk_tree_view_column_set_title (column, _("What"));
+
+ 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_WHAT_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_WHAT_TEXT);
+
+ gtk_tree_view_append_column (view, column);
+
+ /* set up treeview properties */
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_show_expanders (view, FALSE);
+ gtk_tree_view_set_level_indentation (view, 12);
+ gtk_tree_view_expand_all (view);
+ gtk_tree_view_set_row_separator_func (view, what_row_is_separator,
+ NULL, NULL);
+
+ /* populate */
+ for (i = 0; i < G_N_ELEMENTS (events); i++)
+ {
+ gtk_tree_store_append (store, &iter, NULL);
+ gtk_tree_store_set (store, &iter,
+ COL_WHAT_TYPE, events[i].type,
+ COL_WHAT_SUBTYPE, events[i].subtype,
+ COL_WHAT_TEXT, events[i].text,
+ COL_WHAT_ICON, events[i].icon,
+ -1);
+ }
+
+ gtk_tree_model_iter_nth_child (model, &parent, NULL, 3);
+ for (i = 0; i < G_N_ELEMENTS (call_events); i++)
+ {
+ gtk_tree_store_append (store, &iter, &parent);
+ gtk_tree_store_set (store, &iter,
+ COL_WHAT_TYPE, call_events[i].type,
+ COL_WHAT_SUBTYPE, call_events[i].subtype,
+ COL_WHAT_TEXT, call_events[i].text,
+ COL_WHAT_ICON, call_events[i].icon,
+ -1);
+ }
+
+ gtk_tree_view_expand_all (view);
+
+ /* select 'Anything' */
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ /* set up signals */
+ g_signal_connect (view, "test-collapse-row",
+ G_CALLBACK (log_window_what_collapse_row_cb),
+ NULL);
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (log_window_what_changed_cb),
+ window);
- return TRUE;
+ g_object_unref (store);
}
static void
@@ -1056,335 +1627,465 @@ log_window_got_messages_for_date_cb (GObject *manager,
GAsyncResult *result,
gpointer user_data)
{
- EmpathyLogWindow *window = user_data;
+ Ctx *ctx = user_data;
GList *events;
GList *l;
GError *error = NULL;
if (log_window == NULL)
- return;
+ goto out;
if (!tpl_log_manager_get_events_for_date_finish (TPL_LOG_MANAGER (manager),
- result, &events, &error)) {
+ result, &events, &error))
+ {
DEBUG ("Unable to retrieve messages for the selected date: %s. Aborting",
error->message);
- empathy_chat_view_append_event (window->chatview_find,
+ empathy_chat_view_append_event (log_window->chatview_events,
"Unable to retrieve messages for the selected date");
g_error_free (error);
- return;
- }
-
- for (l = events; l; l = l->next) {
- EmpathyMessage *message = empathy_message_from_tpl_log_event (l->data);
- g_object_unref (l->data);
- empathy_chat_view_append_message (window->chatview_chats,
- message);
+ goto out;
+ }
+
+ for (l = events; l; l = l->next)
+ {
+ TplEvent *event = l->data;
+ EmpathyMessage *message = empathy_message_from_tpl_log_event (event);
+ gboolean append = TRUE;
+
+ if (TPL_IS_CALL_EVENT (l->data)
+ && ctx->event_mask & TPL_EVENT_MASK_CALL)
+ {
+ TplCallEvent *call = l->data;
+
+ append = FALSE;
+
+ if (ctx->subtype & EVENT_CALL_ALL)
+ append = TRUE;
+ else
+ {
+ TplCallEndReason reason = tpl_call_event_get_end_reason (call);
+ TplEntity *sender = tpl_event_get_sender (event);
+ TplEntity *receiver = tpl_event_get_receiver (event);
+
+ if (reason == TPL_CALL_END_REASON_NO_ANSWER)
+ {
+ if (ctx->subtype & EVENT_CALL_MISSED)
+ append = TRUE;
+ }
+ else if (ctx->subtype & EVENT_CALL_OUTGOING
+ && tpl_entity_get_entity_type (sender) == TPL_ENTITY_SELF)
+ append = TRUE;
+ else if (ctx->subtype & EVENT_CALL_INCOMING
+ && tpl_entity_get_entity_type (receiver) == TPL_ENTITY_SELF)
+ append = TRUE;
+ }
+ }
+
+ if (append)
+ empathy_chat_view_append_message (log_window->chatview_events,
+ message);
+
+ g_object_unref (event);
g_object_unref (message);
- }
+ }
g_list_free (events);
- /* Turn back on scrolling */
- empathy_chat_view_scroll (window->chatview_find, TRUE);
+ out:
+ ctx_free (ctx);
- /* Give the search entry main focus */
- gtk_widget_grab_focus (window->entry_chats);
+ _tpl_action_chain_continue (log_window->chain);
}
+static void
+get_events_for_date (TplActionChain *chain, gpointer user_data)
+{
+ Ctx *ctx = user_data;
+
+g_print ("get_events_for_date\n");
+ tpl_log_manager_get_events_for_date_async (ctx->window->log_manager,
+ ctx->account, ctx->entity, ctx->event_mask,
+ ctx->date,
+ log_window_got_messages_for_date_cb,
+ ctx);
+}
static void
log_window_get_messages_for_date (EmpathyLogWindow *window,
- GDate *date)
+ GDate *date)
{
TpAccount *account;
TplEntity *target;
+ TplEventTypeMask event_mask;
+ EventSubtype subtype;
+ GDate *anytime, *separator;
- if (!log_window_chats_get_selected (window, &account, &target)) {
- return;
- }
-
- /* Clear all current messages shown in the textview */
- empathy_chat_view_clear (window->chatview_chats);
+ if (!log_window_chats_get_selected (window,
+ &account, &target, NULL, &event_mask, &subtype))
+ return;
- /* Turn off scrolling temporarily */
- empathy_chat_view_scroll (window->chatview_find, FALSE);
+ anytime = g_date_new_dmy (2, 1, -1);
+ separator = g_date_new_dmy (1, 1, -1);
/* Get events */
- tpl_log_manager_get_events_for_date_async (window->log_manager,
- account, target, TPL_EVENT_MASK_TEXT,
- date,
- log_window_got_messages_for_date_cb,
- (gpointer) window);
+ if (g_date_compare (date, anytime) != 0)
+ {
+ Ctx *ctx;
+
+ ctx = ctx_new (window, account, target, date, event_mask, subtype);
+ _tpl_action_chain_append (window->chain, get_events_for_date, ctx);
+ }
+ else
+ {
+ GtkTreeView *view = GTK_TREE_VIEW (window->treeview_when);
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ GtkTreeIter iter;
+ gboolean next;
+ GDate *d;
+
+ for (next = gtk_tree_model_get_iter_first (model, &iter);
+ next;
+ next = gtk_tree_model_iter_next (model, &iter))
+ {
+ Ctx *ctx;
+
+ gtk_tree_model_get (model, &iter,
+ COL_WHEN_DATE, &d,
+ -1);
+
+ if (g_date_compare (d, anytime) == 0 ||
+ g_date_compare (d, separator) == 0)
+ continue;
+
+ ctx = ctx_new (window, account, target, d, event_mask, subtype);
+ _tpl_action_chain_append (window->chain, get_events_for_date, ctx);
+ }
+ }
+
+ _tpl_action_chain_start (window->chain);
g_object_unref (account);
g_object_unref (target);
+ g_date_free (separator);
+ g_date_free (anytime);
}
static void
log_manager_got_dates_cb (GObject *manager,
- GAsyncResult *result,
- gpointer user_data)
+ GAsyncResult *result,
+ gpointer user_data)
{
- EmpathyLogWindow *window = user_data;
- GList *dates;
- GList *l;
- guint year_selected;
- guint month_selected;
- gboolean day_selected = FALSE;
- GDate *date = NULL;
- GError *error = NULL;
+ Ctx *ctx = user_data;
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GList *dates;
+ GList *l;
+ GDate *date = NULL;
+ GError *error = NULL;
- if (log_window == NULL)
- return;
+ g_return_if_fail (log_window != NULL);
if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
- result, &dates, &error)) {
- DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
- error->message);
- empathy_chat_view_append_event (window->chatview_find,
- "Unable to retrieve messages' dates");
- return;
- }
-
- for (l = dates; l; l = l->next) {
- GDate *d = l->data;
-
- gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
- &year_selected,
- &month_selected,
- NULL);
-
- month_selected++;
-
- if (!l->next) {
- date = d;
- }
-
- if (g_date_get_year (d) != year_selected ||
- g_date_get_month (d) != month_selected) {
- continue;
- }
-
- DEBUG ("Marking date: %04u-%02u-%02u", g_date_get_year (d),
- g_date_get_month (d), g_date_get_day (d));
-
- gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats),
- g_date_get_day (d));
-
- if (l->next) {
- continue;
- }
-
- day_selected = TRUE;
+ result, &dates, &error))
+ {
+ DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
+ error->message);
+ empathy_chat_view_append_event (log_window->chatview_events,
+ _("Unable to retrieve messages' dates"));
+ goto out;
+ }
+
+ view = GTK_TREE_VIEW (log_window->treeview_when);
+ model = gtk_tree_view_get_model (view);
+ store = GTK_LIST_STORE (model);
+ selection = gtk_tree_view_get_selection (view);
+
+ for (l = dates; l != NULL; l = l->next)
+ {
+ gchar *text;
+
+ date = l->data;
+ text = g_strdup_printf ("%02d/%02d/%d",
+ g_date_get_day (date),
+ g_date_get_month (date),
+ g_date_get_year (date));
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHEN_DATE, date,
+ COL_WHEN_TEXT, text,
+ COL_WHEN_ICON, CALENDAR_ICON,
+ -1);
+
+ g_free (text);
+ }
+
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHEN_DATE, g_date_new_dmy (1, 1, -1),
+ COL_WHEN_TEXT, "separator",
+ -1);
+
+ gtk_list_store_prepend (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_WHEN_DATE, g_date_new_dmy (2, 1, -1),
+ COL_WHEN_TEXT, _("Anytime"),
+ -1);
+ }
+
+ /* Show messages of the most recent date */
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ g_list_free_full (dates, g_free);
+ out:
+ ctx_free (ctx);
+ _tpl_action_chain_continue (log_window->chain);
+}
- gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats),
- g_date_get_day (d));
- }
+static void
+get_dates_for_entity (TplActionChain *chain, gpointer user_data)
+{
+ Ctx *ctx = user_data;
+g_print ("get_dates_for_entity\n");
+ tpl_log_manager_get_dates_async (ctx->window->log_manager,
+ ctx->account, ctx->entity, ctx->event_mask,
+ log_manager_got_dates_cb, ctx);
+}
- if (!day_selected) {
- /* Unselect the day in the calendar */
- gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), 0);
- }
+static void
+log_window_chats_get_messages (EmpathyLogWindow *window,
+ gboolean force_get_dates)
+{
+ TpAccount *account;
+ TplEntity *target;
+ TplEventTypeMask event_mask;
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkListStore *store;
+ GtkTreeSelection *selection;
+ GDate *date;
+
+ if (!log_window_chats_get_selected (window, &account, &target,
+ &date, &event_mask, NULL))
+ return;
- g_signal_handlers_unblock_by_func (window->calendar_chats,
- log_window_calendar_chats_day_selected_cb,
- window);
+ view = GTK_TREE_VIEW (window->treeview_when);
+ selection = gtk_tree_view_get_selection (view);
+ model = gtk_tree_view_get_model (view);
+ store = GTK_LIST_STORE (model);
- if (date != NULL) {
- /* Show messages of the most recent date */
+ /* Clear all current messages shown in the textview */
+ empathy_chat_view_clear (window->chatview_events);
+
+ /* If there's a search use the returned hits */
+ if (window->hits != NULL)
+ {
+ if (force_get_dates)
+ {
+ gtk_list_store_clear (store);
+ populate_dates_from_search_hits (account, target);
+ }
+ else
+ populate_events_from_search_hits (account, target, date);
+ }
+ /* Either use the supplied date or get the last */
+ else if (force_get_dates || date == NULL)
+ {
+ g_signal_handlers_block_by_func (selection,
+ log_window_when_changed_cb,
+ window);
+
+ gtk_list_store_clear (store);
+
+ g_signal_handlers_unblock_by_func (selection,
+ log_window_when_changed_cb,
+ window);
+
+ /* Get a list of dates and show them on the treeview */
+ if (target != NULL)
+ {
+ Ctx *ctx = ctx_new (window, account, target, NULL, event_mask, 0);
+ _tpl_action_chain_append (window->chain, get_dates_for_entity, ctx);
+ _tpl_action_chain_start (window->chain);
+ }
+ else
+ {
+ /* FIXME: get dates for all entities ? */
+ }
+ }
+ else
+ {
+ /* Show messages of the selected date */
log_window_get_messages_for_date (window, date);
- }
+ }
- g_list_foreach (dates, (GFunc) g_free, NULL);
- g_list_free (dates);
+ tp_clear_object (&account);
+ tp_clear_object (&target);
}
+typedef struct {
+ EmpathyAccountChooserFilterResultCallback callback;
+ gpointer user_data;
+} FilterCallbackData;
static void
-log_window_chats_get_messages (EmpathyLogWindow *window,
- GDate *date)
+got_entities (GObject *manager,
+ GAsyncResult *result,
+ gpointer user_data)
{
- TpAccount *account;
- TplEntity *target;
- guint year_selected;
- guint month_selected;
- guint day;
-
+ FilterCallbackData *data = user_data;
+ GList *entities;
+ GError *error;
- if (!log_window_chats_get_selected (window, &account, &target)) {
- 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 */
- if (date == NULL) {
- /* Get a list of dates and show them on the calendar */
- tpl_log_manager_get_dates_async (window->log_manager,
- account, target, TPL_EVENT_MASK_TEXT,
- log_manager_got_dates_cb, (gpointer) window);
- /* signal unblocked at the end of the CB flow */
+ if (!tpl_log_manager_get_entities_finish (TPL_LOG_MANAGER (manager), result, &entities, &error)) {
+ DEBUG ("Could not get entities: %s", error->message);
+ g_error_free (error);
+ data->callback (FALSE, data->user_data);
} else {
- day = g_date_get_day (date);
- gtk_calendar_get_date (GTK_CALENDAR (window->calendar_chats),
- &year_selected,
- &month_selected,
- NULL);
+ data->callback (entities != NULL, data->user_data);
- month_selected++;
+ g_list_free_full (entities, g_object_unref);
+ }
- if (g_date_get_year (date) != year_selected &&
- g_date_get_month (date) != month_selected) {
- day = 0;
- }
+ g_slice_free (FilterCallbackData, data);
+}
- gtk_calendar_select_day (GTK_CALENDAR (window->calendar_chats), day);
+static void
+empathy_account_chooser_filter_has_logs (TpAccount *account,
+ EmpathyAccountChooserFilterResultCallback callback,
+ gpointer callback_data,
+ gpointer user_data)
+{
+ TplLogManager *manager = tpl_log_manager_dup_singleton ();
+ FilterCallbackData *cb_data = g_slice_new0 (FilterCallbackData);
- g_signal_handlers_unblock_by_func (window->calendar_chats,
- log_window_calendar_chats_day_selected_cb,
- window);
- }
+ cb_data->callback = callback;
+ cb_data->user_data = callback_data;
- if (date != NULL) {
- /* Show messages of the selected date */
- log_window_get_messages_for_date (window, date);
- }
+ tpl_log_manager_get_entities_async (manager, account, got_entities, cb_data);
- g_object_unref (account);
- g_object_unref (target);
+ g_object_unref (manager);
}
static void
-log_window_calendar_chats_day_selected_cb (GtkWidget *calendar,
- EmpathyLogWindow *window)
+log_window_logger_clear_account_cb (TpProxy *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
{
- guint year;
- guint month;
- guint day;
- GDate *date;
-
- gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
- if (day == 0)
- /* No date selected */
- return;
-
- /* We need this hear because it appears that the months start from 0 */
- month++;
-
- date = g_date_new_dmy (day, month, year);
+ EmpathyLogWindow *window = user_data;
- DEBUG ("Currently selected date is: %04u-%02u-%02u", year, month, day);
+ if (error != NULL)
+ g_warning ("Error when clearing logs: %s", error->message);
- log_window_chats_get_messages (window, date);
+ /* Refresh the log viewer so the logs are cleared if the account
+ * has been deleted */
+ empathy_chat_view_clear (window->chatview_events);
+ log_window_who_populate (window);
- g_date_free (date);
+ /* Re-filter the account chooser so the accounts without logs get greyed out */
+ empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser),
+ empathy_account_chooser_filter_has_logs, NULL);
}
static void
-log_window_updating_calendar_month_cb (GObject *manager,
- GAsyncResult *result, gpointer user_data)
+log_window_clear_logs_chooser_select_account (EmpathyAccountChooser *chooser,
+ EmpathyLogWindow *window)
{
- EmpathyLogWindow *window = user_data;
- GList *dates;
- GList *l;
- guint year_selected;
- guint month_selected;
- GError *error = NULL;
+ empathy_account_chooser_set_account (chooser,
+ empathy_account_chooser_get_account (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser)));
+}
- if (log_window == NULL)
- return;
+static void
+log_window_delete_menu_clicked_cb (GtkMenuItem *menuitem,
+ EmpathyLogWindow *window)
+{
+ GtkWidget *dialog, *content_area, *hbox, *label;
+ EmpathyAccountChooser *account_chooser;
+ gint response_id;
+ TpDBusDaemon *bus;
+ TpProxy *logger;
+ GError *error = NULL;
- if (!tpl_log_manager_get_dates_finish (TPL_LOG_MANAGER (manager),
- result, &dates, &error)) {
- DEBUG ("Unable to retrieve messages' dates: %s. Aborting",
- error->message);
- empathy_chat_view_append_event (window->chatview_find,
- "Unable to retrieve messages' dates");
- g_error_free (error);
- return;
- }
+ account_chooser = (EmpathyAccountChooser *) empathy_account_chooser_new ();
+ empathy_account_chooser_set_has_all_option (account_chooser, TRUE);
+ empathy_account_chooser_set_filter (account_chooser, empathy_account_chooser_filter_has_logs, NULL);
- gtk_calendar_clear_marks (GTK_CALENDAR (window->calendar_chats));
- g_object_get (window->calendar_chats,
- "month", &month_selected,
- "year", &year_selected,
- NULL);
+ /* Select the same account as in the history window */
+ if (empathy_account_chooser_is_ready (account_chooser))
+ log_window_clear_logs_chooser_select_account (account_chooser, window);
+ else
+ g_signal_connect (account_chooser, "ready",
+ G_CALLBACK (log_window_clear_logs_chooser_select_account), window);
- /* We need this here because it appears that the months start from 0 */
- month_selected++;
+ dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (window->window),
+ GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ _("Are you sure you want to delete all logs of previous conversations?"));
- for (l = dates; l; l = l->next) {
- GDate *date = l->data;
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Clear All"), GTK_RESPONSE_APPLY,
+ NULL);
- if (g_date_get_year (date) == year_selected &&
- g_date_get_month (date) == month_selected) {
- DEBUG ("Marking date: %04u-%02u-%02u", g_date_get_year (date),
- g_date_get_month (date), g_date_get_day (date));
- gtk_calendar_mark_day (GTK_CALENDAR (window->calendar_chats), g_date_get_day (date));
- }
- }
+ content_area = gtk_message_dialog_get_message_area (
+ GTK_MESSAGE_DIALOG (dialog));
- g_list_foreach (dates, (GFunc) g_free, NULL);
- g_list_free (dates);
+ hbox = gtk_hbox_new (FALSE, 6);
+ label = gtk_label_new (_("Delete from:"));
+ gtk_box_pack_start (GTK_BOX (hbox), label,
+ FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (account_chooser),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (content_area), hbox,
+ FALSE, FALSE, 0);
- DEBUG ("Currently showing month %d and year %d", month_selected,
- year_selected);
-}
+ gtk_widget_show_all (hbox);
-static void
-log_window_calendar_chats_month_changed_cb (GtkWidget *calendar,
- EmpathyLogWindow *window)
-{
- TpAccount *account;
- TplEntity *target;
+ response_id = gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_calendar_clear_marks (GTK_CALENDAR (calendar));
+ if (response_id != GTK_RESPONSE_APPLY)
+ goto out;
- if (!log_window_chats_get_selected (window, &account, &target)) {
- DEBUG ("No chat selected to get dates for...");
- return;
+ bus = tp_dbus_daemon_dup (&error);
+ if (error != NULL) {
+ g_warning ("Could not delete logs: %s", error->message);
+ g_error_free (error);
+ goto out;
}
- /* Get the log object for this contact */
- tpl_log_manager_get_dates_async (window->log_manager, account, target,
- TPL_EVENT_MASK_TEXT,
- log_window_updating_calendar_month_cb,
- (gpointer) window);
+ logger = g_object_new (TP_TYPE_PROXY,
+ "bus-name", "org.freedesktop.Telepathy.Logger",
+ "object-path", "/org/freedesktop/Telepathy/Logger",
+ "dbus-daemon", bus,
+ NULL);
+ g_object_unref (bus);
- g_object_unref (account);
- g_object_unref (target);
-}
+ tp_proxy_add_interface_by_id (logger, EMP_IFACE_QUARK_LOGGER);
-static void
-log_window_entry_chats_changed_cb (GtkWidget *entry,
- EmpathyLogWindow *window)
-{
- const gchar *str;
+ if (empathy_account_chooser_has_all_selected (account_chooser)) {
+ DEBUG ("Deleting logs for all the accounts");
- str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
- empathy_chat_view_highlight (window->chatview_chats, str, FALSE);
-
- if (str != NULL) {
- empathy_chat_view_find_next (window->chatview_chats,
- str,
- TRUE,
- FALSE);
- }
-}
-
-static void
-log_window_entry_chats_activate_cb (GtkWidget *entry,
- EmpathyLogWindow *window)
-{
- const gchar *str;
+ emp_cli_logger_call_clear (logger, -1,
+ log_window_logger_clear_account_cb,
+ window, NULL, G_OBJECT (window->window));
+ } else {
+ TpAccount *account = empathy_account_chooser_get_account (account_chooser);
- str = gtk_entry_get_text (GTK_ENTRY (window->entry_chats));
+ DEBUG ("Deleting logs for %s", tp_proxy_get_object_path (account));
- if (str != NULL) {
- empathy_chat_view_find_next (window->chatview_chats,
- str,
- FALSE,
- FALSE);
+ emp_cli_logger_call_clear_account (logger, -1,
+ tp_proxy_get_object_path (account),
+ log_window_logger_clear_account_cb,
+ window, NULL, G_OBJECT (window->window));
}
+
+ g_object_unref (logger);
+ out:
+ gtk_widget_destroy (dialog);
}
diff --git a/libempathy-gtk/empathy-log-window.h b/libempathy-gtk/empathy-log-window.h
index def0d846b..373f48c36 100644
--- a/libempathy-gtk/empathy-log-window.h
+++ b/libempathy-gtk/empathy-log-window.h
@@ -1,7 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2006-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2011 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
@@ -20,6 +19,7 @@
*
* Authors: Martyn Russell <martyn@imendio.com>
* Xavier Claessens <xclaesse@gmail.com>
+ * Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
*/
#ifndef __EMPATHY_LOG_WINDOW_H__
@@ -29,10 +29,10 @@
G_BEGIN_DECLS
-GtkWidget * empathy_log_window_show (TpAccount *account,
- const gchar *chat_id,
- gboolean chatroom,
- GtkWindow *parent);
+GtkWidget * empathy_log_window_show (TpAccount *account,
+ const gchar *chat_id,
+ gboolean chatroom,
+ GtkWindow *parent);
G_END_DECLS
diff --git a/libempathy-gtk/empathy-log-window.ui b/libempathy-gtk/empathy-log-window.ui
index a0cbcdcfa..5acca02f5 100644
--- a/libempathy-gtk/empathy-log-window.ui
+++ b/libempathy-gtk/empathy-log-window.ui
@@ -1,266 +1,183 @@
<?xml version="1.0"?>
<interface>
- <!-- interface-requires gtk+ 2.12 -->
- <!-- interface-naming-policy toplevel-contextual -->
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="log_window">
- <property name="title" translatable="yes">Previous Conversations</property>
- <property name="role">log</property>
- <property name="default_width">640</property>
- <property name="default_height">450</property>
- <property name="icon_name">document-open-recent</property>
+ <property name="title" translatable="yes">History</property>
+ <property name="default_width">800</property>
+ <property name="default_height">600</property>
<child>
- <object class="GtkNotebook" id="notebook">
+ <object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="border_width">2</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkVBox" id="vbox192">
+ <object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
- <property name="border_width">12</property>
- <property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox144">
+ <object class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkLabel" id="label628">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="Searching *for* something">_For:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">entry_find</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entry_find">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="activates_default">True</property>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button_find">
- <property name="label">gtk-find</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu1">
<property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="receives_default">False</property>
- <property name="use_stock">True</property>
- <property name="focus_on_click">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkVPaned" id="vpaned1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="position">120</property>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow14">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
<child>
- <object class="GtkTreeView" id="treeview_find">
+ <object class="GtkImageMenuItem" id="imagemenuitem_quit">
+ <property name="label">gtk-quit</property>
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="enable_search">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
</object>
</child>
</object>
- <packing>
- <property name="resize">False</property>
- <property name="shrink">True</property>
- </packing>
</child>
- <child>
- <object class="GtkVBox" id="vbox215">
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu2">
<property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow_find">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="shadow_type">in</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
<child>
- <object class="GtkHBox" id="hbox171">
+ <object class="GtkImageMenuItem" id="imagemenuitem_delete">
+ <property name="label">Delete All History...</property>
<property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <placeholder/>
- </child>
- <child>
- <object class="GtkButton" id="button_next">
- <property name="label" translatable="yes">Find Next</property>
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="image">image1</property>
- <property name="focus_on_click">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button_previous">
- <property name="label" translatable="yes">Find Previous</property>
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="image">image2</property>
- <property name="focus_on_click">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button_close">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- <property name="focus_on_click">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
+ <property name="image">image1</property>
+ <property name="use_stock">False</property>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
- <packing>
- <property name="resize">True</property>
- <property name="shrink">True</property>
- </packing>
</child>
</object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
</child>
</object>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label595">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="Tab Label">Search</property>
- </object>
<packing>
- <property name="tab_fill">False</property>
+ <property name="expand">False</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkTable" id="table7">
+ <object class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
- <property name="border_width">12</property>
- <property name="n_rows">3</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">6</property>
- <property name="row_spacing">6</property>
+ <property name="toolbar_style">both</property>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_profile">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Profile</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-dialog-info</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_chat">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Chat</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-edit</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_call">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Call</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">audio-input-microphone</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="toolbutton_video">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Video</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">camera-video</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem" id="toolbutton_sep1">
+ <property name="visible">True</property>
+ <property name="draw">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
<child>
- <object class="GtkVBox" id="vbox_chats">
+ <object class="GtkToolItem" id="toolbutton_accounts">
<property name="visible">True</property>
- <property name="spacing">6</property>
<child>
<placeholder/>
</child>
</object>
<packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
</packing>
</child>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow_chats">
+ <object class="GtkSeparatorToolItem" id="toolbutton_sep2">
+ <property name="visible">True</property>
+ <property name="draw">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolbutton_search">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="shadow_type">in</property>
<child>
<placeholder/>
</child>
</object>
<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>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
</packing>
</child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVPaned" id="vpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkVBox" id="vbox191">
+ <object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
- <property name="spacing">6</property>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow13">
- <property name="width_request">150</property>
+ <object class="GtkScrolledWindow" id="scrolledwindow_who">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
+ <property name="hscrollbar_policy">automatic</property>
<child>
- <object class="GtkTreeView" id="treeview_chats">
+ <object class="GtkTreeView" id="treeview_who">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="headers_visible">False</property>
</object>
</child>
</object>
@@ -269,104 +186,61 @@
</packing>
</child>
<child>
- <object class="GtkCalendar" id="calendar_chats">
+ <object class="GtkScrolledWindow" id="scrolledwindow_what">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="sensitive">False</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_what">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox143">
- <property name="visible">True</property>
- <property name="spacing">6</property>
<child>
- <object class="GtkImage" id="image247">
- <property name="visible">True</property>
- <property name="stock">gtk-find</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entry_chats">
+ <object class="GtkScrolledWindow" id="scrolledwindow_when">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="activates_default">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_when">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
</object>
<packing>
- <property name="position">1</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="resize">False</property>
+ <property name="shrink">True</property>
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox2">
+ <object class="GtkScrolledWindow" id="scrolledwindow_events">
<property name="visible">True</property>
- <property name="spacing">12</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
<child>
<placeholder/>
</child>
- <child>
- <object class="GtkButton" id="button_close2">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">1</property>
- </packing>
- </child>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"></property>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
</packing>
</child>
- <child>
- <placeholder/>
- </child>
</object>
<packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label596">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="Tab Label">Conversations</property>
- </object>
- <packing>
- <property name="position">1</property>
- <property name="tab_fill">False</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
@@ -374,10 +248,6 @@
</object>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
- <property name="stock">gtk-go-forward</property>
- </object>
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="stock">gtk-go-back</property>
+ <property name="stock">gtk-missing-image</property>
</object>
</interface>