aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy-gtk')
-rw-r--r--libempathy-gtk/Makefile.am33
-rw-r--r--libempathy-gtk/empathy-avatar-chooser.c4
-rw-r--r--libempathy-gtk/empathy-chat-text-view.c28
-rw-r--r--libempathy-gtk/empathy-chat.c2
-rw-r--r--libempathy-gtk/empathy-conf.h1
-rw-r--r--libempathy-gtk/empathy-location-manager.c10
-rw-r--r--libempathy-gtk/empathy-profile-chooser.c425
-rw-r--r--libempathy-gtk/empathy-profile-chooser.h51
-rw-r--r--libempathy-gtk/empathy-smiley-manager.c83
-rw-r--r--libempathy-gtk/empathy-smiley-manager.h9
-rw-r--r--libempathy-gtk/empathy-theme-adium.c831
-rw-r--r--libempathy-gtk/empathy-theme-adium.h56
-rw-r--r--libempathy-gtk/empathy-theme-manager.c55
-rw-r--r--libempathy-gtk/empathy-theme.c408
-rw-r--r--libempathy-gtk/empathy-ui-utils.c23
-rw-r--r--libempathy-gtk/empathy-ui-utils.h9
16 files changed, 1360 insertions, 668 deletions
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am
index 80c9a792d..2a4438e57 100644
--- a/libempathy-gtk/Makefile.am
+++ b/libempathy-gtk/Makefile.am
@@ -10,6 +10,7 @@ AM_CPPFLAGS = \
$(ENCHANT_CFLAGS) \
$(LIBCHAMPLAIN_CFLAGS) \
$(GEOCLUE_CFLAGS) \
+ $(WEBKIT_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED)
@@ -73,6 +74,7 @@ libempathy_gtk_la_LIBADD = \
$(ENCHANT_LIBS) \
$(LIBCHAMPLAIN_LIBS) \
$(GEOCLUE_LIBS) \
+ $(WEBKIT_LIBS) \
$(top_builddir)/libempathy/libempathy.la
libempathy_gtk_la_LDFLAGS = \
@@ -118,14 +120,6 @@ libempathy_gtk_headers = \
empathy-theme-manager.h \
empathy-ui-utils.h
-if HAVE_GEOCLUE
-libempathy_gtk_handwritten_source += \
- empathy-location-manager.c
-
-libempathy_gtk_headers += \
- empathy-location-manager.h
-endif
-
check_c_sources = \
$(libempathy_gtk_handwritten_source) \
$(libempathy_gtk_headers)
@@ -218,6 +212,29 @@ pkgconfig_DATA = libempathy-gtk.pc
EXTRA_DIST = \
$(ui_DATA)
+if HAVE_GEOCLUE
+libempathy_gtk_handwritten_source += \
+ empathy-location-manager.c
+
+libempathy_gtk_headers += \
+ empathy-location-manager.h
+else
+EXTRA_DIST += \
+ empathy-location-manager.c \
+ empathy-location-manager.h
+endif
+
+if HAVE_WEBKIT
+libempathy_gtk_handwritten_source += \
+ empathy-theme-adium.c
+libempathy_gtk_headers += \
+ empathy-theme-adium.h
+else
+EXTRA_DIST += \
+ empathy-theme-adium.c \
+ empathy-theme-adium.h
+endif
+
CLEANFILES = \
$(BUILT_SOURCES) \
stamp-empathy-gtk-enum-types.h
diff --git a/libempathy-gtk/empathy-avatar-chooser.c b/libempathy-gtk/empathy-avatar-chooser.c
index 0f4311e07..8c005a029 100644
--- a/libempathy-gtk/empathy-avatar-chooser.c
+++ b/libempathy-gtk/empathy-avatar-chooser.c
@@ -555,7 +555,7 @@ avatar_chooser_maybe_convert_and_scale (EmpathyAvatarChooser *chooser,
/* Takes ownership of new_mime_type and converted_image_data */
avatar = empathy_avatar_new (converted_image_data,
- converted_image_size, new_mime_type, NULL);
+ converted_image_size, new_mime_type, NULL, NULL);
return avatar;
}
@@ -598,7 +598,7 @@ avatar_chooser_set_image_from_data (EmpathyAvatarChooser *chooser,
}
/* avatar takes ownership of data and mime_type */
- avatar = empathy_avatar_new (data, size, mime_type, NULL);
+ avatar = empathy_avatar_new (data, size, mime_type, NULL, NULL);
avatar_chooser_set_image (chooser, avatar, pixbuf, set_locally);
}
diff --git a/libempathy-gtk/empathy-chat-text-view.c b/libempathy-gtk/empathy-chat-text-view.c
index 8874b7ace..95e67b714 100644
--- a/libempathy-gtk/empathy-chat-text-view.c
+++ b/libempathy-gtk/empathy-chat-text-view.c
@@ -231,12 +231,6 @@ chat_text_view_notify_system_font_cb (EmpathyConf *conf,
}
static void
-chat_text_view_clear_view_cb (GtkMenuItem *menuitem, EmpathyChatTextView *view)
-{
- empathy_chat_view_clear (EMPATHY_CHAT_VIEW (view));
-}
-
-static void
chat_text_view_open_address_cb (GtkMenuItem *menuitem, const gchar *url)
{
empathy_url_show (GTK_WIDGET (menuitem), url);
@@ -256,8 +250,8 @@ chat_text_view_copy_address_cb (GtkMenuItem *menuitem, const gchar *url)
static void
chat_text_view_populate_popup (EmpathyChatTextView *view,
- GtkMenu *menu,
- gpointer user_data)
+ GtkMenu *menu,
+ gpointer user_data)
{
EmpathyChatTextViewPriv *priv;
GtkTextTagTable *table;
@@ -271,7 +265,7 @@ chat_text_view_populate_popup (EmpathyChatTextView *view,
/* Clear menu item */
if (gtk_text_buffer_get_char_count (priv->buffer) > 0) {
- item = gtk_menu_item_new ();
+ item = gtk_separator_menu_item_new ();
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
@@ -279,10 +273,9 @@ chat_text_view_populate_popup (EmpathyChatTextView *view,
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
- g_signal_connect (item,
- "activate",
- G_CALLBACK (chat_text_view_clear_view_cb),
- view);
+ g_signal_connect_swapped (item, "activate",
+ G_CALLBACK (empathy_chat_view_clear),
+ view);
}
/* Link context menu items */
@@ -316,21 +309,19 @@ chat_text_view_populate_popup (EmpathyChatTextView *view,
"url", str,
(GDestroyNotify) g_free);
- item = gtk_menu_item_new ();
+ item = gtk_separator_menu_item_new ();
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Address"));
- g_signal_connect (item,
- "activate",
+ g_signal_connect (item, "activate",
G_CALLBACK (chat_text_view_copy_address_cb),
str);
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
item = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
- g_signal_connect (item,
- "activate",
+ g_signal_connect (item, "activate",
G_CALLBACK (chat_text_view_open_address_cb),
str);
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
@@ -576,6 +567,7 @@ chat_text_view_finalize (GObject *object)
if (priv->scroll_timeout) {
g_source_remove (priv->scroll_timeout);
}
+ g_object_unref (priv->smiley_manager);
G_OBJECT_CLASS (empathy_chat_text_view_parent_class)->finalize (object);
}
diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c
index 248fd116d..0fb77f24c 100644
--- a/libempathy-gtk/empathy-chat.c
+++ b/libempathy-gtk/empathy-chat.c
@@ -1217,7 +1217,7 @@ chat_set_show_contacts (EmpathyChat *chat, gboolean show)
store = empathy_contact_list_store_new (EMPATHY_CONTACT_LIST (priv->tp_chat));
priv->contact_list_view = GTK_WIDGET (empathy_contact_list_view_new (store,
- EMPATHY_CONTACT_LIST_FEATURE_NONE,
+ EMPATHY_CONTACT_LIST_FEATURE_CONTACT_TOOLTIP,
EMPATHY_CONTACT_FEATURE_CHAT |
EMPATHY_CONTACT_FEATURE_CALL |
EMPATHY_CONTACT_FEATURE_LOG |
diff --git a/libempathy-gtk/empathy-conf.h b/libempathy-gtk/empathy-conf.h
index 07026df5c..47949139e 100644
--- a/libempathy-gtk/empathy-conf.h
+++ b/libempathy-gtk/empathy-conf.h
@@ -60,6 +60,7 @@ struct _EmpathyConfClass {
#define EMPATHY_PREFS_POPUPS_WHEN_AVAILABLE EMPATHY_PREFS_PATH "/notifications/popups_when_available"
#define EMPATHY_PREFS_CHAT_SHOW_SMILEYS EMPATHY_PREFS_PATH "/conversation/graphical_smileys"
#define EMPATHY_PREFS_CHAT_THEME EMPATHY_PREFS_PATH "/conversation/theme"
+#define EMPATHY_PREFS_CHAT_ADIUM_PATH EMPATHY_PREFS_PATH "/conversation/adium_path"
#define EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES EMPATHY_PREFS_PATH "/conversation/spell_checker_languages"
#define EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED EMPATHY_PREFS_PATH "/conversation/spell_checker_enabled"
#define EMPATHY_PREFS_CHAT_NICK_COMPLETION_CHAR EMPATHY_PREFS_PATH "/conversation/nick_completion_char"
diff --git a/libempathy-gtk/empathy-location-manager.c b/libempathy-gtk/empathy-location-manager.c
index fb804315c..1b76e2e1d 100644
--- a/libempathy-gtk/empathy-location-manager.c
+++ b/libempathy-gtk/empathy-location-manager.c
@@ -302,7 +302,10 @@ address_changed_cb (GeoclueAddress *address,
g_hash_table_remove (priv->location, EMPATHY_LOCATION_POSTAL_CODE);
if (g_hash_table_size (details) == 0)
- return;
+ {
+ DEBUG ("\t - (Empty)");
+ return;
+ }
g_hash_table_iter_init (&iter, details);
while (g_hash_table_iter_next (&iter, &key, &value))
@@ -449,8 +452,11 @@ update_resources (EmpathyLocationManager *location_manager)
DEBUG ("Updating resources %d", priv->resources);
+ /* As per Geoclue bug #15126, using NONE results in no address
+ * being found as geoclue-manual report an empty address with
+ * accuracy = NONE */
if (!geoclue_master_client_set_requirements (priv->gc_client,
- GEOCLUE_ACCURACY_LEVEL_NONE, 0, TRUE, priv->resources,
+ GEOCLUE_ACCURACY_LEVEL_COUNTRY, 0, TRUE, priv->resources,
NULL))
{
DEBUG ("set_requirements failed");
diff --git a/libempathy-gtk/empathy-profile-chooser.c b/libempathy-gtk/empathy-profile-chooser.c
index 14965741c..b3cbf90d0 100644
--- a/libempathy-gtk/empathy-profile-chooser.c
+++ b/libempathy-gtk/empathy-profile-chooser.c
@@ -1,6 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/*
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors: Xavier Claessens <xclaesse@gmail.com>
+ * Jonny Lamb <jonny.lamb@collabora.co.uk>
*/
#include <config.h>
@@ -27,6 +28,8 @@
#include <libmissioncontrol/mc-profile.h>
#include <libmissioncontrol/mc-protocol.h>
+#include <libempathy/empathy-utils.h>
+
#include "empathy-profile-chooser.h"
#include "empathy-ui-utils.h"
@@ -34,112 +37,277 @@
* SECTION:empathy-profile-chooser
* @title: EmpathyProfileChooser
* @short_description: A widget used to choose from a list of profiles
- * @include: libempathy-gtk/empathy-account-chooser.h
+ * @include: libempathy-gtk/empathy-profile-chooser.h
*
- * #EmpathyProfileChooser is a widget which provides a chooser of available
+ * #EmpathyProfileChooser is a widget which extends #GtkComboBox to provides a
+ * chooser of available profiles.
+ */
+
+/**
+ * EmpathyProfileChooser:
+ * @parent: parent object
+ *
+ * Widget which extends #GtkComboBox to provide a chooser of available
* profiles.
*/
-enum {
- COL_ICON,
- COL_LABEL,
- COL_PROFILE,
- COL_COUNT
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyProfileChooser)
+typedef struct
+{
+ GtkListStore *store;
+ gboolean dispose_run;
+} EmpathyProfileChooserPriv;
+
+enum
+{
+ COL_ICON,
+ COL_LABEL,
+ COL_PROFILE,
+ COL_COUNT
};
+G_DEFINE_TYPE (EmpathyProfileChooser, empathy_profile_chooser,
+ GTK_TYPE_COMBO_BOX);
+
+static gint
+profile_chooser_sort_profile_value (McProfile *profile)
+{
+ guint i;
+ const gchar *profile_name;
+ const gchar *names[] = {
+ "jabber",
+ "salut",
+ "gtalk",
+ NULL
+ };
+
+ profile_name = mc_profile_get_unique_name (profile);
+
+ for (i = 0 ; names[i]; i++)
+ {
+ if (strcmp (profile_name, names[i]) == 0)
+ return i;
+ }
+
+ return i;
+}
+
+static gint
+profile_chooser_sort_func (GtkTreeModel *model,
+ GtkTreeIter *iter_a,
+ GtkTreeIter *iter_b,
+ gpointer user_data)
+{
+ McProfile *profile_a;
+ McProfile *profile_b;
+ gint cmp;
+
+ gtk_tree_model_get (model, iter_a,
+ COL_PROFILE, &profile_a,
+ -1);
+ gtk_tree_model_get (model, iter_b,
+ COL_PROFILE, &profile_b,
+ -1);
+
+ cmp = profile_chooser_sort_profile_value (profile_a);
+ cmp -= profile_chooser_sort_profile_value (profile_b);
+ if (cmp == 0)
+ {
+ cmp = strcmp (mc_profile_get_display_name (profile_a),
+ mc_profile_get_display_name (profile_b));
+ }
+
+ g_object_unref (profile_a);
+ g_object_unref (profile_b);
+
+ return cmp;
+}
+
+static void
+profile_chooser_constructed (GObject *object)
+{
+ EmpathyProfileChooser *profile_chooser;
+ EmpathyProfileChooserPriv *priv;
+
+ GList *profiles, *l, *seen;
+ GtkCellRenderer *renderer;
+ GtkTreeIter iter;
+ gboolean iter_set = FALSE;
+ McManager *btf_cm;
+
+ priv = GET_PRIV (object);
+ profile_chooser = EMPATHY_PROFILE_CHOOSER (object);
+
+ /* set up combo box with new store */
+ priv->store = gtk_list_store_new (COL_COUNT,
+ G_TYPE_STRING, /* Icon name */
+ G_TYPE_STRING, /* Label */
+ MC_TYPE_PROFILE); /* Profile */
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (object),
+ GTK_TREE_MODEL (priv->store));
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), renderer, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), renderer,
+ "icon-name", COL_ICON,
+ NULL);
+ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), renderer,
+ "text", COL_LABEL,
+ NULL);
+
+ btf_cm = mc_manager_lookup ("butterfly");
+ profiles = mc_profiles_list ();
+ seen = NULL;
+ for (l = profiles; l; l = g_list_next (l))
+ {
+ McProfile *profile;
+ McProtocol *protocol;
+ const gchar *unique_name;
+
+ profile = l->data;
+
+ /* Check if the CM is installed, otherwise skip that profile.
+ * Workaround SF bug #1688779 */
+ protocol = mc_profile_get_protocol (profile);
+ if (!protocol)
+ continue;
+
+ g_object_unref (protocol);
+
+ /* Skip MSN-Haze if we have butterfly */
+ unique_name = mc_profile_get_unique_name (profile);
+ if (btf_cm && strcmp (unique_name, "msn-haze") == 0)
+ continue;
+
+ if (g_list_find_custom (seen, unique_name, (GCompareFunc) strcmp))
+ continue;
+
+ seen = g_list_append (seen, (char *) unique_name);
+
+ gtk_list_store_insert_with_values (priv->store, &iter, 0,
+ COL_ICON, mc_profile_get_icon_name (profile),
+ COL_LABEL, mc_profile_get_display_name (profile),
+ COL_PROFILE, profile,
+ -1);
+ iter_set = TRUE;
+ }
+
+ g_list_free (seen);
+
+ if (btf_cm)
+ g_object_unref (btf_cm);
+
+ /* Set the profile sort function */
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->store),
+ COL_PROFILE,
+ profile_chooser_sort_func,
+ NULL, NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
+ COL_PROFILE,
+ GTK_SORT_ASCENDING);
+
+ if (iter_set)
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (object), &iter);
+
+ mc_profiles_free_list (profiles);
+
+ if (G_OBJECT_CLASS (empathy_profile_chooser_parent_class)->constructed)
+ G_OBJECT_CLASS (empathy_profile_chooser_parent_class)->constructed (object);
+}
+
+static void
+empathy_profile_chooser_init (EmpathyProfileChooser *profile_chooser)
+{
+ EmpathyProfileChooserPriv *priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (profile_chooser,
+ EMPATHY_TYPE_PROFILE_CHOOSER, EmpathyProfileChooserPriv);
+
+ priv->dispose_run = FALSE;
+
+ profile_chooser->priv = priv;
+}
+
+static void
+profile_chooser_dispose (GObject *object)
+{
+ EmpathyProfileChooser *profile_chooser = EMPATHY_PROFILE_CHOOSER (object);
+ EmpathyProfileChooserPriv *priv = GET_PRIV (profile_chooser);
+
+ if (priv->dispose_run)
+ return;
+
+ priv->dispose_run = TRUE;
+
+ if (priv->store)
+ {
+ g_object_unref (priv->store);
+ priv->store = NULL;
+ }
+
+ (G_OBJECT_CLASS (empathy_profile_chooser_parent_class)->dispose) (object);
+}
+
+static void
+empathy_profile_chooser_class_init (EmpathyProfileChooserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = profile_chooser_constructed;
+ object_class->dispose = profile_chooser_dispose;
+
+ g_type_class_add_private (object_class, sizeof (EmpathyProfileChooserPriv));
+}
+
/**
* empathy_profile_chooser_dup_selected:
- * @widget: an #EmpathyProfileChooser
+ * @profile_chooser: an #EmpathyProfileChooser
*
- * Returns a new reference to the selected #McProfile in @widget. The returned
- * #McProfile should be unrefed with g_object_unref() when finished with.
+ * Returns a new reference to the selected #McProfile in @profile_chooser. The
+ * returned #McProfile should be unrefed with g_object_unref() when finished
+ * with.
*
* Return value: a new reference to the selected #McProfile
*/
McProfile *
-empathy_profile_chooser_dup_selected (GtkWidget *widget)
+empathy_profile_chooser_dup_selected (EmpathyProfileChooser *profile_chooser)
{
- GtkTreeModel *model;
- GtkTreeIter iter;
- McProfile *profile = NULL;
-
- model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
- gtk_tree_model_get (model, &iter,
- COL_PROFILE, &profile,
- -1);
- }
-
- return profile;
+ EmpathyProfileChooserPriv *priv = GET_PRIV (profile_chooser);
+ GtkTreeIter iter;
+ McProfile *profile = NULL;
+
+ g_return_val_if_fail (EMPATHY_IS_PROFILE_CHOOSER (profile_chooser), NULL);
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (profile_chooser), &iter))
+ {
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+ COL_PROFILE, &profile,
+ -1);
+ }
+
+ return profile;
}
/**
* empathy_profile_chooser_n_profiles:
- * @widget: an #EmpathyProfileChooser
+ * @profile_chooser: an #EmpathyProfileChooser
*
- * Returns the number of profiles in @widget.
+ * Returns the number of profiles in @profile_chooser.
*
- * Return value: the number of profiles in @widget
+ * Return value: the number of profiles in @profile_chooser
*/
gint
-empathy_profile_chooser_n_profiles (GtkWidget *widget)
+empathy_profile_chooser_n_profiles (EmpathyProfileChooser *profile_chooser)
{
- GtkTreeModel *model;
+ EmpathyProfileChooserPriv *priv = GET_PRIV (profile_chooser);
- model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
-
- return gtk_tree_model_iter_n_children (model, NULL);
-}
+ g_return_val_if_fail (EMPATHY_IS_PROFILE_CHOOSER (profile_chooser), 0);
-static gint
-profile_chooser_sort_profile_value (McProfile *profile)
-{
- guint i;
- const gchar *profile_name;
- const gchar *names[] = {"jabber",
- "salut",
- "gtalk",
- NULL};
-
- profile_name = mc_profile_get_unique_name (profile);
-
- for (i = 0 ; names[i]; i++) {
- if (strcmp (profile_name, names[i]) == 0) {
- return i;
- }
- }
-
- return i;
-}
-
-static gint
-profile_chooser_sort_func (GtkTreeModel *model,
- GtkTreeIter *iter_a,
- GtkTreeIter *iter_b,
- gpointer user_data)
-{
- McProfile *profile_a;
- McProfile *profile_b;
- gint cmp;
-
- gtk_tree_model_get (model, iter_a,
- COL_PROFILE, &profile_a,
- -1);
- gtk_tree_model_get (model, iter_b,
- COL_PROFILE, &profile_b,
- -1);
-
- cmp = profile_chooser_sort_profile_value (profile_a);
- cmp -= profile_chooser_sort_profile_value (profile_b);
- if (cmp == 0) {
- cmp = strcmp (mc_profile_get_display_name (profile_a),
- mc_profile_get_display_name (profile_b));
- }
-
- g_object_unref (profile_a);
- g_object_unref (profile_b);
-
- return cmp;
+ return gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->store), NULL);
}
/**
@@ -152,94 +320,5 @@ profile_chooser_sort_func (GtkTreeModel *model,
GtkWidget *
empathy_profile_chooser_new (void)
{
- GList *profiles, *l, *seen;
- GtkListStore *store;
- GtkCellRenderer *renderer;
- GtkWidget *combo_box;
- GtkTreeIter iter;
- gboolean iter_set = FALSE;
- McManager *btf_cm;
-
- /* set up combo box with new store */
- store = gtk_list_store_new (COL_COUNT,
- G_TYPE_STRING, /* Icon name */
- G_TYPE_STRING, /* Label */
- MC_TYPE_PROFILE); /* Profile */
- combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
-
-
- renderer = gtk_cell_renderer_pixbuf_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, FALSE);
- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer,
- "icon-name", COL_ICON,
- NULL);
- g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer,
- "text", COL_LABEL,
- NULL);
-
- btf_cm = mc_manager_lookup ("butterfly");
- profiles = mc_profiles_list ();
- seen = NULL;
- for (l = profiles; l; l = l->next) {
- McProfile *profile;
- McProtocol *protocol;
- const gchar *unique_name;
-
- profile = l->data;
-
- /* Check if the CM is installed, otherwise skip that profile.
- * Workaround SF bug #1688779 */
- protocol = mc_profile_get_protocol (profile);
- if (!protocol) {
- continue;
- }
- g_object_unref (protocol);
-
- /* Skip MSN-Haze if we have butterfly */
- unique_name = mc_profile_get_unique_name (profile);
- if (btf_cm && strcmp (unique_name, "msn-haze") == 0) {
- continue;
- }
-
- if (g_list_find_custom (seen, unique_name, (GCompareFunc) strcmp)) {
- continue;
- }
- seen = g_list_append (seen, (char *) unique_name);
-
- gtk_list_store_insert_with_values (store, &iter, 0,
- COL_ICON, mc_profile_get_icon_name (profile),
- COL_LABEL, mc_profile_get_display_name (profile),
- COL_PROFILE, profile,
- -1);
- iter_set = TRUE;
- }
-
- g_list_free (seen);
-
- if (btf_cm) {
- g_object_unref (btf_cm);
- }
-
- /* Set the profile sort function */
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
- COL_PROFILE,
- profile_chooser_sort_func,
- NULL, NULL);
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
- COL_PROFILE,
- GTK_SORT_ASCENDING);
-
- if (iter_set) {
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
- }
-
- mc_profiles_free_list (profiles);
- g_object_unref (store);
-
- return combo_box;
+ return GTK_WIDGET (g_object_new (EMPATHY_TYPE_PROFILE_CHOOSER, NULL));
}
-
diff --git a/libempathy-gtk/empathy-profile-chooser.h b/libempathy-gtk/empathy-profile-chooser.h
index 74c761cc4..37d7241a9 100644
--- a/libempathy-gtk/empathy-profile-chooser.h
+++ b/libempathy-gtk/empathy-profile-chooser.h
@@ -1,6 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/*
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,18 +17,53 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors: Xavier Claessens <xclaesse@gmail.com>
+ * Jonny Lamb <jonny.lamb@collabora.co.uk
*/
-#ifndef __EMPATHY_PROTOCOL_CHOOSER_H__
-#define __EMPATHY_PROTOCOL_CHOOSER_H__
+#ifndef __EMPATHY_PROFILE_CHOOSER_H__
+#define __EMPATHY_PROFILE_CHOOSER_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
#include <libmissioncontrol/mc-profile.h>
G_BEGIN_DECLS
-GtkWidget * empathy_profile_chooser_new (void);
-McProfile * empathy_profile_chooser_dup_selected (GtkWidget *widget);
-gint empathy_profile_chooser_n_profiles (GtkWidget *widget);
+#define EMPATHY_TYPE_PROFILE_CHOOSER (empathy_profile_chooser_get_type ())
+#define EMPATHY_PROFILE_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \
+ EMPATHY_TYPE_PROFILE_CHOOSER, EmpathyProfileChooser))
+#define EMPATHY_PROFILE_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \
+ EMPATHY_TYPE_PROFILE_CHOOSER, EmpathyProfileChooserClass))
+#define EMPATHY_IS_PROFILE_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
+ EMPATHY_TYPE_PROFILE_CHOOSER))
+#define EMPATHY_IS_PROFILE_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \
+ EMPATHY_TYPE_PROFILE_CHOOSER))
+#define EMPATHY_PROFILE_CHOOSER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), \
+ EMPATHY_TYPE_PROFILE_CHOOSER, EmpathyProfileChooserClass))
+
+typedef struct _EmpathyProfileChooser EmpathyProfileChooser;
+typedef struct _EmpathyProfileChooserClass EmpathyProfileChooserClass;
+
+struct _EmpathyProfileChooser
+{
+ GtkComboBox parent;
+
+ /*<private>*/
+ gpointer priv;
+};
+
+struct _EmpathyProfileChooserClass
+{
+ GtkComboBoxClass parent_class;
+};
+
+GType empathy_profile_chooser_get_type (void) G_GNUC_CONST;
+GtkWidget * empathy_profile_chooser_new (void);
+McProfile * empathy_profile_chooser_dup_selected (
+ EmpathyProfileChooser *profile_chooser);
+gint empathy_profile_chooser_n_profiles (
+ EmpathyProfileChooser *profile_chooser);
G_END_DECLS
-#endif /* __EMPATHY_PROTOCOL_CHOOSER_H__ */
+#endif /* __EMPATHY_PROFILE_CHOOSER_H__ */
diff --git a/libempathy-gtk/empathy-smiley-manager.c b/libempathy-gtk/empathy-smiley-manager.c
index a729a2929..c504d4cdb 100644
--- a/libempathy-gtk/empathy-smiley-manager.c
+++ b/libempathy-gtk/empathy-smiley-manager.c
@@ -37,9 +37,10 @@ typedef struct {
} EmpathySmileyManagerPriv;
struct _SmileyManagerTree {
- gunichar c;
- GdkPixbuf *pixbuf;
- GSList *childrens;
+ gunichar c;
+ GdkPixbuf *pixbuf;
+ const gchar *path;
+ GSList *childrens;
};
G_DEFINE_TYPE (EmpathySmileyManager, empathy_smiley_manager, G_TYPE_OBJECT);
@@ -55,6 +56,7 @@ smiley_manager_tree_new (gunichar c)
tree->c = c;
tree->pixbuf = NULL;
tree->childrens = NULL;
+ tree->path = NULL;
return tree;
}
@@ -81,7 +83,7 @@ smiley_manager_tree_free (SmileyManagerTree *tree)
/* Note: This function takes the ownership of str */
static EmpathySmiley *
-smiley_new (GdkPixbuf *pixbuf, gchar *str)
+smiley_new (GdkPixbuf *pixbuf, gchar *str, const gchar *path)
{
EmpathySmiley *smiley;
@@ -90,6 +92,7 @@ smiley_new (GdkPixbuf *pixbuf, gchar *str)
smiley->pixbuf = g_object_ref (pixbuf);
}
smiley->str = str;
+ smiley->path = path;
return smiley;
}
@@ -112,9 +115,16 @@ static void
smiley_manager_finalize (GObject *object)
{
EmpathySmileyManagerPriv *priv = GET_PRIV (object);
+ GSList *l;
smiley_manager_tree_free (priv->tree);
- g_slist_foreach (priv->smileys, (GFunc) empathy_smiley_free, NULL);
+ for (l = priv->smileys; l; l = l->next) {
+ EmpathySmiley *smiley = l->data;
+
+ /* The smiley got the ownership of the path */
+ g_free ((gchar*) smiley->path);
+ empathy_smiley_free (smiley);
+ }
g_slist_free (priv->smileys);
}
@@ -201,8 +211,9 @@ smiley_manager_tree_find_or_insert_child (SmileyManagerTree *tree, gunichar c)
static void
smiley_manager_tree_insert (SmileyManagerTree *tree,
- GdkPixbuf *smiley,
- const gchar *str)
+ GdkPixbuf *pixbuf,
+ const gchar *str,
+ const gchar *path)
{
SmileyManagerTree *child;
@@ -210,28 +221,32 @@ smiley_manager_tree_insert (SmileyManagerTree *tree,
str = g_utf8_next_char (str);
if (*str) {
- smiley_manager_tree_insert (child, smiley, str);
+ smiley_manager_tree_insert (child, pixbuf, str, path);
return;
}
- child->pixbuf = g_object_ref (smiley);
+ child->pixbuf = g_object_ref (pixbuf);
+ child->path = path;
}
static void
smiley_manager_add_valist (EmpathySmileyManager *manager,
- GdkPixbuf *smiley,
+ GdkPixbuf *pixbuf,
+ gchar *path,
const gchar *first_str,
va_list var_args)
{
EmpathySmileyManagerPriv *priv = GET_PRIV (manager);
const gchar *str;
+ EmpathySmiley *smiley;
for (str = first_str; str; str = va_arg (var_args, gchar*)) {
- smiley_manager_tree_insert (priv->tree, smiley, str);
+ smiley_manager_tree_insert (priv->tree, pixbuf, str, path);
}
- priv->smileys = g_slist_prepend (priv->smileys,
- smiley_new (smiley, g_strdup (first_str)));
+ /* We give the ownership of path to the smiley */
+ smiley = smiley_new (pixbuf, g_strdup (first_str), path);
+ priv->smileys = g_slist_prepend (priv->smileys, smiley);
}
void
@@ -240,40 +255,26 @@ empathy_smiley_manager_add (EmpathySmileyManager *manager,
const gchar *first_str,
...)
{
- GdkPixbuf *smiley;
+ GdkPixbuf *pixbuf;
va_list var_args;
g_return_if_fail (EMPATHY_IS_SMILEY_MANAGER (manager));
g_return_if_fail (!EMP_STR_EMPTY (icon_name));
g_return_if_fail (!EMP_STR_EMPTY (first_str));
- smiley = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
- if (smiley) {
+ pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
+ if (pixbuf) {
+ gchar *path;
+
va_start (var_args, first_str);
- smiley_manager_add_valist (manager, smiley, first_str, var_args);
+ path = empathy_filename_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
+ smiley_manager_add_valist (manager, pixbuf, path, first_str, var_args);
va_end (var_args);
- g_object_unref (smiley);
+ g_object_unref (pixbuf);
}
}
void
-empathy_smiley_manager_add_from_pixbuf (EmpathySmileyManager *manager,
- GdkPixbuf *smiley,
- const gchar *first_str,
- ...)
-{
- va_list var_args;
-
- g_return_if_fail (EMPATHY_IS_SMILEY_MANAGER (manager));
- g_return_if_fail (GDK_IS_PIXBUF (smiley));
- g_return_if_fail (!EMP_STR_EMPTY (first_str));
-
- va_start (var_args, first_str);
- smiley_manager_add_valist (manager, smiley, first_str, var_args);
- va_end (var_args);
-}
-
-void
empathy_smiley_manager_load (EmpathySmileyManager *manager)
{
g_return_if_fail (EMPATHY_IS_SMILEY_MANAGER (manager));
@@ -320,7 +321,9 @@ empathy_smiley_manager_parse (EmpathySmileyManager *manager,
if (cur_tree == priv->tree) {
if (child) {
if (t > cur_str) {
- smiley = smiley_new (NULL, g_strndup (cur_str, t - cur_str));
+ smiley = smiley_new (NULL,
+ g_strndup (cur_str, t - cur_str),
+ NULL);
smileys = g_slist_prepend (smileys, smiley);
}
cur_str = t;
@@ -335,7 +338,9 @@ empathy_smiley_manager_parse (EmpathySmileyManager *manager,
continue;
}
- smiley = smiley_new (cur_tree->pixbuf, g_strndup (cur_str, t - cur_str));
+ smiley = smiley_new (cur_tree->pixbuf,
+ g_strndup (cur_str, t - cur_str),
+ cur_tree->path);
smileys = g_slist_prepend (smileys, smiley);
if (cur_tree->pixbuf) {
cur_str = t;
@@ -350,7 +355,9 @@ empathy_smiley_manager_parse (EmpathySmileyManager *manager,
}
}
- smiley = smiley_new (cur_tree->pixbuf, g_strndup (cur_str, t - cur_str));
+ smiley = smiley_new (cur_tree->pixbuf,
+ g_strndup (cur_str, t - cur_str),
+ cur_tree->path);
smileys = g_slist_prepend (smileys, smiley);
return g_slist_reverse (smileys);
diff --git a/libempathy-gtk/empathy-smiley-manager.h b/libempathy-gtk/empathy-smiley-manager.h
index 5eaf4b283..dc7428c3b 100644
--- a/libempathy-gtk/empathy-smiley-manager.h
+++ b/libempathy-gtk/empathy-smiley-manager.h
@@ -48,8 +48,9 @@ struct _EmpathySmileyManagerClass {
};
typedef struct {
- GdkPixbuf *pixbuf;
- gchar *str;
+ GdkPixbuf *pixbuf;
+ gchar *str;
+ const gchar *path;
} EmpathySmiley;
typedef void (*EmpathySmileyMenuFunc) (EmpathySmileyManager *manager,
@@ -63,10 +64,6 @@ void empathy_smiley_manager_add (EmpathySmileyManag
const gchar *icon_name,
const gchar *first_str,
...);
-void empathy_smiley_manager_add_from_pixbuf (EmpathySmileyManager *manager,
- GdkPixbuf *smiley,
- const gchar *first_str,
- ...);
GSList * empathy_smiley_manager_get_all (EmpathySmileyManager *manager);
GSList * empathy_smiley_manager_parse (EmpathySmileyManager *manager,
const gchar *text);
diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c
new file mode 100644
index 000000000..1f0c043aa
--- /dev/null
+++ b/libempathy-gtk/empathy-theme-adium.c
@@ -0,0 +1,831 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008-2009 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include <webkit/webkitnetworkrequest.h>
+
+#include <libempathy/empathy-time.h>
+#include <libempathy/empathy-utils.h>
+
+#include "empathy-theme-adium.h"
+#include "empathy-smiley-manager.h"
+#include "empathy-conf.h"
+#include "empathy-ui-utils.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_CHAT
+#include <libempathy/empathy-debug.h>
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyThemeAdium)
+
+typedef struct {
+ EmpathySmileyManager *smiley_manager;
+ EmpathyContact *last_contact;
+ gboolean page_loaded;
+ GList *message_queue;
+ gchar *path;
+ gchar *default_avatar_filename;
+ gchar *template_html;
+ gchar *basedir;
+ gchar *in_content_html;
+ gsize in_content_len;
+ gchar *in_nextcontent_html;
+ gsize in_nextcontent_len;
+ gchar *out_content_html;
+ gsize out_content_len;
+ gchar *out_nextcontent_html;
+ gsize out_nextcontent_len;
+ gchar *status_html;
+ gsize status_len;
+} EmpathyThemeAdiumPriv;
+
+static void theme_adium_iface_init (EmpathyChatViewIface *iface);
+
+enum {
+ PROP_0,
+ PROP_PATH,
+};
+
+G_DEFINE_TYPE_WITH_CODE (EmpathyThemeAdium, empathy_theme_adium,
+ WEBKIT_TYPE_WEB_VIEW,
+ G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CHAT_VIEW,
+ theme_adium_iface_init));
+
+static void
+theme_adium_load (EmpathyThemeAdium *theme)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
+ gchar *file;
+ gchar *template_html = NULL;
+ gsize template_len;
+ GString *string;
+ gchar **strv = NULL;
+ gchar *css_path;
+ guint len = 0;
+ guint i = 0;
+ gchar *basedir_uri;
+
+ priv->basedir = g_strconcat (priv->path, G_DIR_SEPARATOR_S "Contents" G_DIR_SEPARATOR_S "Resources" G_DIR_SEPARATOR_S, NULL);
+ basedir_uri = g_strconcat ("file://", priv->basedir, NULL);
+
+ /* Load html files */
+ file = g_build_filename (priv->basedir, "Incoming", "Content.html", NULL);
+ g_file_get_contents (file, &priv->in_content_html, &priv->in_content_len, NULL);
+ g_free (file);
+
+ file = g_build_filename (priv->basedir, "Incoming", "NextContent.html", NULL);
+ g_file_get_contents (file, &priv->in_nextcontent_html, &priv->in_nextcontent_len, NULL);
+ g_free (file);
+
+ file = g_build_filename (priv->basedir, "Outgoing", "Content.html", NULL);
+ g_file_get_contents (file, &priv->out_content_html, &priv->out_content_len, NULL);
+ g_free (file);
+
+ file = g_build_filename (priv->basedir, "Outgoing", "NextContent.html", NULL);
+ g_file_get_contents (file, &priv->out_nextcontent_html, &priv->out_nextcontent_len, NULL);
+ g_free (file);
+
+ file = g_build_filename (priv->basedir, "Status.html", NULL);
+ g_file_get_contents (file, &priv->status_html, &priv->status_len, NULL);
+ g_free (file);
+
+ css_path = g_build_filename (priv->basedir, "main.css", NULL);
+
+ /* There is 2 formats for Template.html: The old one has 4 parameters,
+ * the new one has 5 parameters. */
+ file = g_build_filename (priv->basedir, "Template.html", NULL);
+ if (g_file_get_contents (file, &template_html, &template_len, NULL)) {
+ strv = g_strsplit (template_html, "%@", -1);
+ len = g_strv_length (strv);
+ }
+ g_free (file);
+
+ if (len != 5 && len != 6) {
+ /* Either the theme has no template or it don't have the good
+ * number of parameters. Fallback to use our own template. */
+ g_free (template_html);
+ g_strfreev (strv);
+
+ file = empathy_file_lookup ("Template.html", "data");
+ g_file_get_contents (file, &template_html, &template_len, NULL);
+ g_free (file);
+ strv = g_strsplit (template_html, "%@", -1);
+ len = g_strv_length (strv);
+ }
+
+ /* Replace %@ with the needed information in the template html. */
+ string = g_string_sized_new (template_len);
+ g_string_append (string, strv[i++]);
+ g_string_append (string, priv->basedir);
+ g_string_append (string, strv[i++]);
+ if (len == 6) {
+ /* We include main.css by default */
+ g_string_append_printf (string, "@import url(\"%s\");", css_path);
+ g_string_append (string, strv[i++]);
+ /* FIXME: We should set the variant css here */
+ g_string_append (string, "");
+ } else {
+ /* FIXME: We should set main.css OR the variant css */
+ g_string_append (string, css_path);
+ }
+ g_string_append (string, strv[i++]);
+ g_string_append (string, ""); /* We don't want header */
+ g_string_append (string, strv[i++]);
+ g_string_append (string, ""); /* FIXME: We don't support footer yet */
+ g_string_append (string, strv[i++]);
+ priv->template_html = g_string_free (string, FALSE);
+
+ /* Load the template */
+ webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (theme),
+ priv->template_html, basedir_uri);
+
+ g_free (basedir_uri);
+ g_free (template_html);
+ g_free (css_path);
+ g_strfreev (strv);
+}
+
+static WebKitNavigationResponse
+theme_adium_navigation_requested_cb (WebKitWebView *view,
+ WebKitWebFrame *frame,
+ WebKitNetworkRequest *request,
+ gpointer user_data)
+{
+ const gchar *uri;
+
+ uri = webkit_network_request_get_uri (request);
+ empathy_url_show (GTK_WIDGET (view), uri);
+
+ return WEBKIT_NAVIGATION_RESPONSE_IGNORE;
+}
+
+static void
+theme_adium_populate_popup_cb (WebKitWebView *view,
+ GtkMenu *menu,
+ gpointer user_data)
+{
+ GtkWidget *item;
+
+ /* Remove default menu items */
+ gtk_container_foreach (GTK_CONTAINER (menu),
+ (GtkCallback) gtk_widget_destroy, NULL);
+
+ /* Select all item */
+ item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ g_signal_connect_swapped (item, "activate",
+ G_CALLBACK (webkit_web_view_select_all),
+ view);
+
+ /* Copy menu item */
+ if (webkit_web_view_can_copy_clipboard (view)) {
+ item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ g_signal_connect_swapped (item, "activate",
+ G_CALLBACK (webkit_web_view_copy_clipboard),
+ view);
+ }
+
+ /* Clear menu item */
+ item = gtk_separator_menu_item_new ();
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ g_signal_connect_swapped (item, "activate",
+ G_CALLBACK (empathy_chat_view_clear),
+ view);
+
+ /* FIXME: Add open_link and copy_link when those bugs are fixed:
+ * https://bugs.webkit.org/show_bug.cgi?id=16092
+ * https://bugs.webkit.org/show_bug.cgi?id=16562
+ */
+}
+
+static gchar *
+theme_adium_parse_body (EmpathyThemeAdium *theme,
+ const gchar *text)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
+ gboolean use_smileys = FALSE;
+ GSList *smileys, *l;
+ GString *string;
+ gint i;
+ GRegex *uri_regex;
+ GMatchInfo *match_info;
+ gboolean match;
+ gchar *ret = NULL;
+ gint prev;
+
+ empathy_conf_get_bool (empathy_conf_get (),
+ EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
+ &use_smileys);
+
+ if (use_smileys) {
+ /* Replace smileys by a <img/> tag */
+ string = g_string_sized_new (strlen (text));
+ smileys = empathy_smiley_manager_parse (priv->smiley_manager, text);
+ for (l = smileys; l; l = l->next) {
+ EmpathySmiley *smiley;
+
+ smiley = l->data;
+ if (smiley->path) {
+ g_string_append_printf (string,
+ "<abbr title='%s'><img src=\"%s\"/ alt=\"%s\"/></abbr>",
+ smiley->str, smiley->path, smiley->str);
+ } else {
+ gchar *str;
+
+ str = g_markup_escape_text (smiley->str, -1);
+ g_string_append (string, str);
+ g_free (str);
+ }
+ empathy_smiley_free (smiley);
+ }
+ g_slist_free (smileys);
+
+ g_free (ret);
+ text = ret = g_string_free (string, FALSE);
+ }
+
+ /* Add <a href></a> arround links */
+ uri_regex = empathy_uri_regex_dup_singleton ();
+ match = g_regex_match (uri_regex, text, 0, &match_info);
+ if (match) {
+ gint last = 0;
+ gint s = 0, e = 0;
+
+ string = g_string_sized_new (strlen (text));
+ do {
+ g_match_info_fetch_pos (match_info, 0, &s, &e);
+
+ if (s > last) {
+ /* Append the text between last link (or the
+ * start of the message) and this link */
+ g_string_append_len (string, text + last, s - last);
+ }
+
+ /* Append the link inside <a href=""></a> tag */
+ g_string_append (string, "<a href=\"");
+ g_string_append_len (string, text + s, e - s);
+ g_string_append (string, "\">");
+ g_string_append_len (string, text + s, e - s);
+ g_string_append (string, "</a>");
+
+ last = e;
+ } while (g_match_info_next (match_info, NULL));
+
+ if (e < strlen (text)) {
+ /* Append the text after the last link */
+ g_string_append_len (string, text + e, strlen (text) - e);
+ }
+
+ g_free (ret);
+ text = ret = g_string_free (string, FALSE);
+ }
+ g_match_info_free (match_info);
+ g_regex_unref (uri_regex);
+
+ /* Replace \n by <br/> */
+ string = NULL;
+ prev = 0;
+ for (i = 0; text[i] != '\0'; i++) {
+ if (text[i] == '\n') {
+ if (!string ) {
+ string = g_string_sized_new (strlen (text));
+ }
+ g_string_append_len (string, text + prev, i - prev);
+ g_string_append (string, "<br/>");
+ prev = i + 1;
+ }
+ }
+ if (string) {
+ g_string_append (string, text + prev);
+ g_free (ret);
+ text = ret = g_string_free (string, FALSE);
+ }
+
+ return ret;
+}
+
+static void
+escape_and_append_len (GString *string, const gchar *str, gint len)
+{
+ while (*str != '\0' && len != 0) {
+ switch (*str) {
+ case '\\':
+ /* \ becomes \\ */
+ g_string_append (string, "\\\\");
+ break;
+ case '\"':
+ /* " becomes \" */
+ g_string_append (string, "\\\"");
+ break;
+ case '\n':
+ /* Remove end of lines */
+ break;
+ default:
+ g_string_append_c (string, *str);
+ }
+
+ str++;
+ len--;
+ }
+}
+
+static gboolean
+theme_adium_match (const gchar **str, const gchar *match)
+{
+ gint len;
+
+ len = strlen (match);
+ if (strncmp (*str, match, len) == 0) {
+ *str += len - 1;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+theme_adium_append_html (EmpathyThemeAdium *theme,
+ const gchar *func,
+ const gchar *html, gsize len,
+ const gchar *message,
+ const gchar *avatar_filename,
+ const gchar *name,
+ time_t timestamp)
+{
+ GString *string;
+ const gchar *cur = NULL;
+ gchar *script;
+
+ /* Make some search-and-replace in the html code */
+ string = g_string_sized_new (len + strlen (message));
+ g_string_append_printf (string, "%s(\"", func);
+ for (cur = html; *cur != '\0'; cur++) {
+ const gchar *replace = NULL;
+ gchar *dup_replace = NULL;
+
+ if (theme_adium_match (&cur, "%message%")) {
+ replace = message;
+ } else if (theme_adium_match (&cur, "%userIconPath%")) {
+ replace = avatar_filename;
+ } else if (theme_adium_match (&cur, "%sender%")) {
+ replace = name;
+ } else if (theme_adium_match (&cur, "%time")) {
+ gchar *format = NULL;
+ gchar *end;
+
+ /* Time can be in 2 formats:
+ * %time% or %time{strftime format}%
+ * Extract the time format if provided. */
+ if (cur[1] == '{') {
+ cur += 2;
+ end = strstr (cur, "}%");
+ if (!end) {
+ /* Invalid string */
+ continue;
+ }
+ format = g_strndup (cur, end - cur);
+ cur = end + 1;
+ } else {
+ cur++;
+ }
+
+ dup_replace = empathy_time_to_string_local (timestamp,
+ format ? format : EMPATHY_TIME_FORMAT_DISPLAY_SHORT);
+ replace = dup_replace;
+ g_free (format);
+ } else {
+ escape_and_append_len (string, cur, 1);
+ continue;
+ }
+
+ /* Here we have a replacement to make */
+ escape_and_append_len (string, replace, -1);
+ g_free (dup_replace);
+ }
+ g_string_append (string, "\")");
+
+ script = g_string_free (string, FALSE);
+ webkit_web_view_execute_script (WEBKIT_WEB_VIEW (theme), script);
+ g_free (script);
+}
+
+static void
+theme_adium_append_message (EmpathyChatView *view,
+ EmpathyMessage *msg)
+{
+ EmpathyThemeAdium *theme = EMPATHY_THEME_ADIUM (view);
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
+ EmpathyContact *sender;
+ gchar *dup_body = NULL;
+ const gchar *body;
+ const gchar *name;
+ EmpathyAvatar *avatar;
+ const gchar *avatar_filename = NULL;
+ time_t timestamp;
+ gchar *html = NULL;
+ gsize len = 0;
+ const gchar *func;
+
+ if (!priv->page_loaded) {
+ priv->message_queue = g_list_prepend (priv->message_queue,
+ g_object_ref (msg));
+ return;
+ }
+
+ /* Get information */
+ sender = empathy_message_get_sender (msg);
+ timestamp = empathy_message_get_timestamp (msg);
+ body = empathy_message_get_body (msg);
+ dup_body = theme_adium_parse_body (theme, body);
+ if (dup_body) {
+ body = dup_body;
+ }
+ name = empathy_contact_get_name (sender);
+
+ /* If this is a /me, append an event */
+ if (empathy_message_get_tptype(msg) == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION) {
+ gchar *str;
+
+ str = g_strdup_printf ("%s %s", name, body);
+ empathy_chat_view_append_event (view, str);
+ g_free (str);
+ g_free (dup_body);
+ return;
+ }
+
+ /* Get the avatar filename, or a fallback */
+ avatar = empathy_contact_get_avatar (sender);
+ if (avatar) {
+ avatar_filename = avatar->filename;
+ }
+ if (!avatar_filename) {
+ if (!priv->default_avatar_filename) {
+ priv->default_avatar_filename =
+ empathy_filename_from_icon_name ("stock_person",
+ GTK_ICON_SIZE_DIALOG);
+ }
+ avatar_filename = priv->default_avatar_filename;
+ }
+
+ /* Get the right html/func to add the message */
+ if (priv->last_contact == sender) {
+ func = "appendNextMessage";
+ if (empathy_contact_is_user (sender)) {
+ html = priv->out_nextcontent_html;
+ len = priv->out_nextcontent_len;
+ }
+ if (!html) {
+ html = priv->in_nextcontent_html;
+ len = priv->in_nextcontent_len;
+ }
+ }
+ if (!html) {
+ func = "appendMessage";
+ if (empathy_contact_is_user (sender)) {
+ html = priv->out_content_html;
+ len = priv->out_content_len;
+ }
+ if (!html) {
+ html = priv->in_content_html;
+ len = priv->in_content_len;
+ }
+ }
+
+ theme_adium_append_html (theme, func, html, len, body, avatar_filename,
+ name, timestamp);
+
+ /* Keep the sender of the last displayed message */
+ if (priv->last_contact) {
+ g_object_unref (priv->last_contact);
+ }
+ priv->last_contact = g_object_ref (sender);
+
+ g_free (dup_body);
+}
+
+static void
+theme_adium_append_event (EmpathyChatView *view,
+ const gchar *str)
+{
+ EmpathyThemeAdium *theme = EMPATHY_THEME_ADIUM (view);
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
+
+ if (priv->status_html) {
+ theme_adium_append_html (theme, "appendMessage",
+ priv->status_html, priv->status_len,
+ str, NULL, NULL,
+ empathy_time_get_current ());
+ }
+
+ /* There is no last contact */
+ if (priv->last_contact) {
+ g_object_unref (priv->last_contact);
+ priv->last_contact = NULL;
+ }
+}
+
+static void
+theme_adium_scroll (EmpathyChatView *view,
+ gboolean allow_scrolling)
+{
+ /* FIXME: Is it possible? I guess we need a js function, but I don't
+ * see any... */
+}
+
+static void
+theme_adium_scroll_down (EmpathyChatView *view)
+{
+ webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view), "scrollToBottom()");
+}
+
+static gboolean
+theme_adium_get_has_selection (EmpathyChatView *view)
+{
+ return webkit_web_view_has_selection (WEBKIT_WEB_VIEW (view));
+}
+
+static void
+theme_adium_clear (EmpathyChatView *view)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
+ gchar *basedir_uri;
+
+ priv->page_loaded = FALSE;
+ basedir_uri = g_strconcat ("file://", priv->basedir, NULL);
+ webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (view),
+ priv->template_html, basedir_uri);
+ g_free (basedir_uri);
+}
+
+static gboolean
+theme_adium_find_previous (EmpathyChatView *view,
+ const gchar *search_criteria,
+ gboolean new_search)
+{
+ return webkit_web_view_search_text (WEBKIT_WEB_VIEW (view),
+ search_criteria, FALSE,
+ FALSE, TRUE);
+}
+
+static gboolean
+theme_adium_find_next (EmpathyChatView *view,
+ const gchar *search_criteria,
+ gboolean new_search)
+{
+ return webkit_web_view_search_text (WEBKIT_WEB_VIEW (view),
+ search_criteria, FALSE,
+ TRUE, TRUE);
+}
+
+static void
+theme_adium_find_abilities (EmpathyChatView *view,
+ const gchar *search_criteria,
+ gboolean *can_do_previous,
+ gboolean *can_do_next)
+{
+ /* FIXME: Does webkit provide an API for that? We have wrap=true in
+ * find_next and find_previous to work around this problem. */
+ if (can_do_previous)
+ *can_do_previous = TRUE;
+ if (can_do_next)
+ *can_do_next = TRUE;
+}
+
+static void
+theme_adium_highlight (EmpathyChatView *view,
+ const gchar *text)
+{
+ webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (view));
+ webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (view),
+ text, FALSE, 0);
+ webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (view),
+ TRUE);
+}
+
+static void
+theme_adium_copy_clipboard (EmpathyChatView *view)
+{
+ webkit_web_view_copy_clipboard (WEBKIT_WEB_VIEW (view));
+}
+
+static void
+theme_adium_iface_init (EmpathyChatViewIface *iface)
+{
+ iface->append_message = theme_adium_append_message;
+ iface->append_event = theme_adium_append_event;
+ iface->scroll = theme_adium_scroll;
+ iface->scroll_down = theme_adium_scroll_down;
+ iface->get_has_selection = theme_adium_get_has_selection;
+ iface->clear = theme_adium_clear;
+ iface->find_previous = theme_adium_find_previous;
+ iface->find_next = theme_adium_find_next;
+ iface->find_abilities = theme_adium_find_abilities;
+ iface->highlight = theme_adium_highlight;
+ iface->copy_clipboard = theme_adium_copy_clipboard;
+}
+
+static void
+theme_adium_load_finished_cb (WebKitWebView *view,
+ WebKitWebFrame *frame,
+ gpointer user_data)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
+ EmpathyChatView *chat_view = EMPATHY_CHAT_VIEW (view);
+
+ DEBUG ("Page loaded");
+ priv->page_loaded = TRUE;
+
+ /* Display queued messages */
+ priv->message_queue = g_list_reverse (priv->message_queue);
+ while (priv->message_queue) {
+ EmpathyMessage *message = priv->message_queue->data;
+
+ theme_adium_append_message (chat_view, message);
+ priv->message_queue = g_list_remove (priv->message_queue, message);
+ g_object_unref (message);
+ }
+}
+
+static void
+theme_adium_finalize (GObject *object)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (object);
+
+ g_free (priv->basedir);
+ g_free (priv->template_html);
+ g_free (priv->in_content_html);
+ g_free (priv->in_nextcontent_html);
+ g_free (priv->out_content_html);
+ g_free (priv->out_nextcontent_html);
+ g_free (priv->default_avatar_filename);
+ g_free (priv->path);
+
+ G_OBJECT_CLASS (empathy_theme_adium_parent_class)->finalize (object);
+}
+
+static void
+theme_adium_dispose (GObject *object)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (object);
+
+ if (priv->smiley_manager) {
+ g_object_unref (priv->smiley_manager);
+ priv->smiley_manager = NULL;
+ }
+
+ if (priv->last_contact) {
+ g_object_unref (priv->last_contact);
+ priv->last_contact = NULL;
+ }
+
+ G_OBJECT_CLASS (empathy_theme_adium_parent_class)->dispose (object);
+}
+
+static void
+theme_adium_constructed (GObject *object)
+{
+ theme_adium_load (EMPATHY_THEME_ADIUM (object));
+}
+
+static void
+theme_adium_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (object);
+
+ switch (param_id) {
+ case PROP_PATH:
+ g_value_set_string (value, priv->path);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
+static void
+theme_adium_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyThemeAdiumPriv *priv = GET_PRIV (object);
+
+ switch (param_id) {
+ case PROP_PATH:
+ g_free (priv->path);
+ priv->path = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
+static void
+empathy_theme_adium_class_init (EmpathyThemeAdiumClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = theme_adium_finalize;
+ object_class->dispose = theme_adium_dispose;
+ object_class->constructed = theme_adium_constructed;
+ object_class->get_property = theme_adium_get_property;
+ object_class->set_property = theme_adium_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_PATH,
+ g_param_spec_string ("path",
+ "The theme path",
+ "Path to the adium theme",
+ g_get_home_dir (),
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE));
+
+
+ g_type_class_add_private (object_class, sizeof (EmpathyThemeAdiumPriv));
+}
+
+static void
+empathy_theme_adium_init (EmpathyThemeAdium *theme)
+{
+ EmpathyThemeAdiumPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (theme,
+ EMPATHY_TYPE_THEME_ADIUM, EmpathyThemeAdiumPriv);
+
+ theme->priv = priv;
+
+ priv->smiley_manager = empathy_smiley_manager_dup_singleton ();
+
+ g_signal_connect (theme, "load-finished",
+ G_CALLBACK (theme_adium_load_finished_cb),
+ NULL);
+ g_signal_connect (theme, "navigation-requested",
+ G_CALLBACK (theme_adium_navigation_requested_cb),
+ NULL);
+ g_signal_connect (theme, "populate-popup",
+ G_CALLBACK (theme_adium_populate_popup_cb),
+ NULL);
+}
+
+EmpathyThemeAdium *
+empathy_theme_adium_new (const gchar *path)
+{
+ g_return_val_if_fail (empathy_theme_adium_is_valid (path), NULL);
+
+ return g_object_new (EMPATHY_TYPE_THEME_ADIUM,
+ "path", path,
+ NULL);
+}
+
+gboolean
+empathy_theme_adium_is_valid (const gchar *path)
+{
+ gboolean ret;
+ gchar *file;
+
+ /* We ship a default Template.html as fallback if there is any problem
+ * with the one inside the theme. The only other required file is
+ * Content.html for incoming messages (outgoing fallback to use
+ * incoming). */
+ file = g_build_filename (path, "Contents", "Resources", "Incoming",
+ "Content.html", NULL);
+ ret = g_file_test (file, G_FILE_TEST_EXISTS);
+ g_free (file);
+
+ return ret;
+}
+
diff --git a/libempathy-gtk/empathy-theme-adium.h b/libempathy-gtk/empathy-theme-adium.h
new file mode 100644
index 000000000..b62675680
--- /dev/null
+++ b/libempathy-gtk/empathy-theme-adium.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008-2009 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_THEME_ADIUM_H__
+#define __EMPATHY_THEME_ADIUM_H__
+
+#include <webkit/webkitwebview.h>
+
+#include "empathy-chat-view.h"
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_THEME_ADIUM (empathy_theme_adium_get_type ())
+#define EMPATHY_THEME_ADIUM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_THEME_ADIUM, EmpathyThemeAdium))
+#define EMPATHY_THEME_ADIUM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_THEME_ADIUM, EmpathyThemeAdiumClass))
+#define EMPATHY_IS_THEME_ADIUM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_THEME_ADIUM))
+#define EMPATHY_IS_THEME_ADIUM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_THEME_ADIUM))
+#define EMPATHY_THEME_ADIUM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_THEME_ADIUM, EmpathyThemeAdiumClass))
+
+typedef struct _EmpathyThemeAdium EmpathyThemeAdium;
+typedef struct _EmpathyThemeAdiumClass EmpathyThemeAdiumClass;
+
+struct _EmpathyThemeAdium {
+ WebKitWebView parent;
+ gpointer priv;
+};
+
+struct _EmpathyThemeAdiumClass {
+ WebKitWebViewClass parent_class;
+};
+
+GType empathy_theme_adium_get_type (void) G_GNUC_CONST;
+EmpathyThemeAdium *empathy_theme_adium_new (const gchar *path);
+gboolean empathy_theme_adium_is_valid (const gchar *path);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_THEME_ADIUM_H__ */
diff --git a/libempathy-gtk/empathy-theme-manager.c b/libempathy-gtk/empathy-theme-manager.c
index 0186b5eb7..c6da8ea68 100644
--- a/libempathy-gtk/empathy-theme-manager.c
+++ b/libempathy-gtk/empathy-theme-manager.c
@@ -38,6 +38,10 @@
#include "empathy-theme-boxes.h"
#include "empathy-theme-irc.h"
+#ifdef HAVE_WEBKIT
+#include "empathy-theme-adium.h"
+#endif
+
#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
#include <libempathy/empathy-debug.h>
@@ -45,6 +49,8 @@
typedef struct {
gchar *name;
guint name_notify_id;
+ gchar *adium_path;
+ guint adium_path_notify_id;
GtkSettings *settings;
GList *boxes_views;
} EmpathyThemeManagerPriv;
@@ -61,6 +67,9 @@ static const gchar *themes[] = {
"simple", N_("Simple"),
"clean", N_("Clean"),
"blue", N_("Blue"),
+#ifdef HAVE_WEBKIT
+ "adium", N_("Adium"),
+#endif
NULL
};
@@ -198,7 +207,7 @@ theme_manager_update_boxes_tags (EmpathyThemeBoxes *theme,
"pixels-above-lines", 4,
NULL);
TAG_SET ("paragraph-background", "paragraph-background-set", text_background);
- TAG_SET ("foreground", "foreground-set",highlight_foreground);
+ TAG_SET ("foreground", "foreground-set", highlight_foreground);
empathy_chat_text_view_tag_set (view, EMPATHY_CHAT_TEXT_VIEW_TAG_SPACING,
"size", 3000,
@@ -318,6 +327,17 @@ empathy_theme_manager_create_view (EmpathyThemeManager *manager)
DEBUG ("Using theme %s", priv->name);
+#ifdef HAVE_WEBKIT
+ if (strcmp (priv->name, "adium") == 0) {
+ if (empathy_theme_adium_is_valid (priv->adium_path)) {
+ return EMPATHY_CHAT_VIEW (empathy_theme_adium_new (priv->adium_path));
+ } else {
+ /* The adium path is not valid, fallback to classic theme */
+ return EMPATHY_CHAT_VIEW (theme_manager_create_irc_view (manager));
+ }
+ }
+#endif
+
if (strcmp (priv->name, "classic") == 0) {
return EMPATHY_CHAT_VIEW (theme_manager_create_irc_view (manager));
}
@@ -404,6 +424,27 @@ theme_manager_notify_name_cb (EmpathyConf *conf,
}
static void
+theme_manager_notify_adium_path_cb (EmpathyConf *conf,
+ const gchar *key,
+ gpointer user_data)
+{
+ EmpathyThemeManager *manager = EMPATHY_THEME_MANAGER (user_data);
+ EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
+ gchar *adium_path = NULL;
+
+ if (!empathy_conf_get_string (conf, key, &adium_path) ||
+ !tp_strdiff (priv->adium_path, adium_path)) {
+ g_free (adium_path);
+ return;
+ }
+
+ g_free (priv->adium_path);
+ priv->adium_path = adium_path;
+
+ g_signal_emit (manager, signals[THEME_CHANGED], 0, NULL);
+}
+
+static void
theme_manager_finalize (GObject *object)
{
EmpathyThemeManagerPriv *priv = GET_PRIV (object);
@@ -411,6 +452,8 @@ theme_manager_finalize (GObject *object)
empathy_conf_notify_remove (empathy_conf_get (), priv->name_notify_id);
g_free (priv->name);
+ empathy_conf_notify_remove (empathy_conf_get (), priv->adium_path_notify_id);
+ g_free (priv->adium_path);
for (l = priv->boxes_views; l; l = l->next) {
g_object_weak_unref (G_OBJECT (l->data),
@@ -460,6 +503,16 @@ empathy_theme_manager_init (EmpathyThemeManager *manager)
EMPATHY_PREFS_CHAT_THEME,
manager);
+ /* Take the adium path and track changes */
+ priv->adium_path_notify_id =
+ empathy_conf_notify_add (empathy_conf_get (),
+ EMPATHY_PREFS_CHAT_ADIUM_PATH,
+ theme_manager_notify_adium_path_cb,
+ manager);
+ theme_manager_notify_adium_path_cb (empathy_conf_get (),
+ EMPATHY_PREFS_CHAT_ADIUM_PATH,
+ manager);
+
/* Track GTK color changes */
priv->settings = gtk_settings_get_default ();
g_signal_connect_swapped (priv->settings, "notify::color-hash",
diff --git a/libempathy-gtk/empathy-theme.c b/libempathy-gtk/empathy-theme.c
deleted file mode 100644
index ca4f66663..000000000
--- a/libempathy-gtk/empathy-theme.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2007 Imendio AB
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#include <string.h>
-#include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
-
-#include <libempathy/empathy-utils.h>
-
-#include "empathy-chat.h"
-#include "empathy-conf.h"
-#include "empathy-theme.h"
-#include "empathy-smiley-manager.h"
-
-/* Number of seconds between timestamps when using normal mode, 5 minutes. */
-#define TIMESTAMP_INTERVAL 300
-
-#define SCHEMES "(https?|ftps?|nntp|news|javascript|about|ghelp|apt|telnet|"\
- "file|webcal|mailto)"
-#define BODY "([^\\ ]+)"
-#define END_BODY "([^\\ ]*[^,;\?><()\\ \"\\.])"
-#define URI_REGEX "("SCHEMES"://"END_BODY")" \
- "|((mailto:)?"BODY"@"BODY"\\."END_BODY")"\
- "|((www|ftp)\\."END_BODY")"
-static GRegex *uri_regex = NULL;
-
-#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTheme)
-
-typedef struct {
- EmpathySmileyManager *smiley_manager;
- gboolean show_avatars;
-} EmpathyThemePriv;
-
-static void theme_finalize (GObject *object);
-static void theme_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec);
-static void theme_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec);
-
-
-G_DEFINE_TYPE (EmpathyTheme, empathy_theme, G_TYPE_OBJECT);
-
-enum {
- PROP_0,
- PROP_SHOW_AVATARS
-};
-
-static void
-empathy_theme_class_init (EmpathyThemeClass *class)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (class);
-
- object_class->finalize = theme_finalize;
- object_class->get_property = theme_get_property;
- object_class->set_property = theme_set_property;
-
- class->update_view = NULL;
- class->append_message = NULL;
- class->append_event = NULL;
- class->append_timestamp = NULL;
- class->append_spacing = NULL;
-
- g_object_class_install_property (object_class,
- PROP_SHOW_AVATARS,
- g_param_spec_boolean ("show-avatars",
- "", "",
- TRUE,
- G_PARAM_READWRITE));
-
- g_type_class_add_private (object_class, sizeof (EmpathyThemePriv));
-}
-
-static void
-empathy_theme_init (EmpathyTheme *theme)
-{
- EmpathyThemePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (theme,
- EMPATHY_TYPE_THEME, EmpathyThemePriv);
-
- theme->priv = priv;
- priv->smiley_manager = empathy_smiley_manager_dup_singleton ();
-}
-
-static void
-theme_finalize (GObject *object)
-{
- EmpathyThemePriv *priv;
-
- priv = GET_PRIV (object);
-
- if (priv->smiley_manager) {
- g_object_unref (priv->smiley_manager);
- }
-
- (G_OBJECT_CLASS (empathy_theme_parent_class)->finalize) (object);
-}
-
-static void
-theme_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec)
-{
- EmpathyThemePriv *priv;
-
- priv = GET_PRIV (object);
-
- switch (param_id) {
- case PROP_SHOW_AVATARS:
- g_value_set_boolean (value, priv->show_avatars);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- }
-}
-
-static void
-theme_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- EmpathyThemePriv *priv;
-
- priv = GET_PRIV (object);
-
- switch (param_id) {
- case PROP_SHOW_AVATARS:
- empathy_theme_set_show_avatars (EMPATHY_THEME (object),
- g_value_get_boolean (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- }
-}
-
-void
-empathy_theme_maybe_append_date_and_time (EmpathyTheme *theme,
- EmpathyChatView *view,
- EmpathyMessage *message)
-{
- time_t timestamp;
- GDate *date, *last_date;
- gboolean append_date, append_time;
-
- date = empathy_message_get_date_and_time (message, &timestamp);
-
- last_date = g_date_new ();
- g_date_set_time_t (last_date, empathy_chat_view_get_last_timestamp (view));
-
- append_date = FALSE;
- append_time = FALSE;
-
- if (g_date_compare (date, last_date) > 0) {
- append_date = TRUE;
- append_time = TRUE;
- }
-
- g_date_free (last_date);
- g_date_free (date);
-
- if (empathy_chat_view_get_last_timestamp (view) + TIMESTAMP_INTERVAL < timestamp) {
- append_time = TRUE;
- }
-
- if (append_time || append_date) {
- empathy_theme_append_timestamp (theme, view, message,
- append_date, append_time);
- }
-}
-
-void
-empathy_theme_update_view (EmpathyTheme *theme,
- EmpathyChatView *view)
-{
- if (!EMPATHY_THEME_GET_CLASS(theme)->update_view) {
- g_error ("Theme must override update_view");
- }
-
- EMPATHY_THEME_GET_CLASS(theme)->update_view (theme, view);
-}
-
-void
-empathy_theme_append_message (EmpathyTheme *theme,
- EmpathyChatView *view,
- EmpathyMessage *message)
-{
- if (!EMPATHY_THEME_GET_CLASS(theme)->append_message) {
- g_warning ("Theme should override append_message");
- return;
- }
-
- EMPATHY_THEME_GET_CLASS(theme)->append_message (theme, view, message);
-}
-
-static void
-theme_insert_text_with_emoticons (GtkTextBuffer *buf,
- GtkTextIter *iter,
- const gchar *str,
- EmpathySmileyManager *smiley_manager)
-{
- gboolean use_smileys = FALSE;
- GSList *smileys, *l;
-
- empathy_conf_get_bool (empathy_conf_get (),
- EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
- &use_smileys);
-
- if (!use_smileys) {
- gtk_text_buffer_insert (buf, iter, str, -1);
- return;
- }
-
- smileys = empathy_smiley_manager_parse (smiley_manager, str);
- for (l = smileys; l; l = l->next) {
- EmpathySmiley *smiley;
-
- smiley = l->data;
- if (smiley->pixbuf) {
- gtk_text_buffer_insert_pixbuf (buf, iter, smiley->pixbuf);
- } else {
- gtk_text_buffer_insert (buf, iter, smiley->str, -1);
- }
- empathy_smiley_free (smiley);
- }
- g_slist_free (smileys);
-}
-
-void
-empathy_theme_append_text (EmpathyTheme *theme,
- EmpathyChatView *view,
- const gchar *body,
- const gchar *tag,
- const gchar *link_tag)
-{
- EmpathyThemePriv *priv;
- GtkTextBuffer *buffer;
- GtkTextIter start_iter, end_iter;
- GtkTextMark *mark;
- GtkTextIter iter;
- GMatchInfo *match_info;
- gboolean match;
- gint last = 0;
- gint s = 0, e = 0;
- gchar *tmp;
-
- priv = GET_PRIV (theme);
- buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-
- gtk_text_buffer_get_end_iter (buffer, &start_iter);
- mark = gtk_text_buffer_create_mark (buffer, NULL, &start_iter, TRUE);
-
- if (!uri_regex) {
- uri_regex = g_regex_new (URI_REGEX, 0, 0, NULL);
- }
-
- for (match = g_regex_match (uri_regex, body, 0, &match_info); match;
- match = g_match_info_next (match_info, NULL)) {
- if (!g_match_info_fetch_pos (match_info, 0, &s, &e))
- continue;
-
- if (s > last) {
- tmp = empathy_substring (body, last, s);
-
- gtk_text_buffer_get_end_iter (buffer, &iter);
- theme_insert_text_with_emoticons (buffer,
- &iter,
- tmp,
- priv->smiley_manager);
- g_free (tmp);
- }
-
- tmp = empathy_substring (body, s, e);
-
- gtk_text_buffer_get_end_iter (buffer, &iter);
- if (!link_tag) {
- gtk_text_buffer_insert (buffer, &iter,
- tmp, -1);
- } else {
- gtk_text_buffer_insert_with_tags_by_name (buffer,
- &iter,
- tmp,
- -1,
- link_tag,
- "link",
- NULL);
- }
-
- g_free (tmp);
- last = e;
- }
- g_match_info_free (match_info);
-
- if (last < strlen (body)) {
- gtk_text_buffer_get_end_iter (buffer, &iter);
- theme_insert_text_with_emoticons (buffer,
- &iter,
- body + last,
- priv->smiley_manager);
- }
-
- gtk_text_buffer_get_end_iter (buffer, &iter);
- gtk_text_buffer_insert (buffer, &iter, "\n", 1);
-
- /* Apply the style to the inserted text. */
- gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, mark);
- gtk_text_buffer_get_end_iter (buffer, &end_iter);
-
- gtk_text_buffer_apply_tag_by_name (buffer,
- tag,
- &start_iter,
- &end_iter);
-
- gtk_text_buffer_delete_mark (buffer, mark);
-}
-
-void
-empathy_theme_append_event (EmpathyTheme *theme,
- EmpathyChatView *view,
- const gchar *str)
-{
- if (!EMPATHY_THEME_GET_CLASS(theme)->append_event) {
- return;
- }
-
- EMPATHY_THEME_GET_CLASS(theme)->append_event (theme, view, str);
-}
-
-void
-empathy_theme_append_spacing (EmpathyTheme *theme,
- EmpathyChatView *view)
-{
- if (!EMPATHY_THEME_GET_CLASS(theme)->append_spacing) {
- return;
- }
-
- EMPATHY_THEME_GET_CLASS(theme)->append_spacing (theme, view);
-}
-
-
-void
-empathy_theme_append_timestamp (EmpathyTheme *theme,
- EmpathyChatView *view,
- EmpathyMessage *message,
- gboolean show_date,
- gboolean show_time)
-{
- if (!EMPATHY_THEME_GET_CLASS(theme)->append_timestamp) {
- return;
- }
-
- EMPATHY_THEME_GET_CLASS(theme)->append_timestamp (theme, view,
- message, show_date,
- show_time);
-}
-
-gboolean
-empathy_theme_get_show_avatars (EmpathyTheme *theme)
-{
- EmpathyThemePriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_THEME (theme), FALSE);
-
- priv = GET_PRIV (theme);
-
- return priv->show_avatars;
-}
-
-void
-empathy_theme_set_show_avatars (EmpathyTheme *theme, gboolean show)
-{
- EmpathyThemePriv *priv;
-
- g_return_if_fail (EMPATHY_IS_THEME (theme));
-
- priv = GET_PRIV (theme);
-
- priv->show_avatars = show;
-
- g_object_notify (G_OBJECT (theme), "show-avatars");
-}
-
diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c
index f30c58aad..cf423de41 100644
--- a/libempathy-gtk/empathy-ui-utils.c
+++ b/libempathy-gtk/empathy-ui-utils.c
@@ -558,6 +558,29 @@ empathy_pixbuf_from_icon_name (const gchar *icon_name,
return empathy_pixbuf_from_icon_name_sized (icon_name, size);
}
+gchar *
+empathy_filename_from_icon_name (const gchar *icon_name,
+ GtkIconSize icon_size)
+{
+ GtkIconTheme *icon_theme;
+ GtkIconInfo *icon_info;
+ gint w, h;
+ gint size = 48;
+ gchar *ret;
+
+ icon_theme = gtk_icon_theme_get_default ();
+
+ if (gtk_icon_size_lookup (icon_size, &w, &h)) {
+ size = (w + h) / 2;
+ }
+
+ icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size, 0);
+ ret = g_strdup (gtk_icon_info_get_filename (icon_info));
+ gtk_icon_info_free (icon_info);
+
+ return ret;
+}
+
/* Stolen from GtkSourceView, hence the weird intendation. Please keep it like
* that to make it easier to apply changes from the original code.
*/
diff --git a/libempathy-gtk/empathy-ui-utils.h b/libempathy-gtk/empathy-ui-utils.h
index 4d58fedcf..60d48f3c4 100644
--- a/libempathy-gtk/empathy-ui-utils.h
+++ b/libempathy-gtk/empathy-ui-utils.h
@@ -90,12 +90,15 @@ GdkPixbuf * empathy_pixbuf_from_avatar_scaled (EmpathyAvatar *avata
GdkPixbuf * empathy_pixbuf_avatar_from_contact_scaled (EmpathyContact *contact,
gint width,
gint height);
-GdkPixbuf * empathy_pixbuf_scale_down_if_necessary (GdkPixbuf *pixbuf,
+GdkPixbuf * empathy_pixbuf_scale_down_if_necessary (GdkPixbuf *pixbuf,
gint max_size);
-GdkPixbuf * empathy_pixbuf_from_icon_name (const gchar *icon_name,
+GdkPixbuf * empathy_pixbuf_from_icon_name (const gchar *icon_name,
GtkIconSize icon_size);
-GdkPixbuf * empathy_pixbuf_from_icon_name_sized (const gchar *icon_name,
+GdkPixbuf * empathy_pixbuf_from_icon_name_sized (const gchar *icon_name,
gint size);
+gchar * empathy_filename_from_icon_name (const gchar *icon_name,
+ GtkIconSize icon_size);
+
/* Text view */
gboolean empathy_text_iter_forward_search (const GtkTextIter*iter,
const gchar *str,