]> git.0d.be Git - empathy.git/commitdiff
Adium: Let user select theme variant in preferences
authorXavier Claessens <xclaesse@gmail.com>
Tue, 3 May 2011 09:27:21 +0000 (11:27 +0200)
committerXavier Claessens <xclaesse@gmail.com>
Tue, 7 Jun 2011 15:34:19 +0000 (17:34 +0200)
Fixes bug #585474

data/org.gnome.Empathy.gschema.xml.in
libempathy-gtk/empathy-theme-adium.c
libempathy-gtk/empathy-theme-adium.h
libempathy-gtk/empathy-theme-manager.c
libempathy/empathy-gsettings.h
src/empathy-preferences.c
src/empathy-preferences.ui

index 799cc7294f1f99ae150433f2b5066b8363740c54..50b3005fa7022d1091ddfffeb42930da4d6c1b7d 100644 (file)
@@ -183,6 +183,11 @@ present them to the user immediately.</_description>
       <_summary>Chat window theme</_summary>
       <_description>The theme that is used to display the conversation in chat windows.</_description>
     </key>
+    <key name="theme-variant" type="s">
+      <default>''</default>
+      <_summary>Chat window theme variant</_summary>
+      <_description>The theme variant that is used to display the conversation in chat windows.</_description>
+    </key>
     <key name="adium-path" type="s">
       <default>''</default>
       <_summary>Path of the Adium theme to use</_summary>
index b0bd09ab9460bbb64069c3b57448b2b703315251..0370b90551ccb8fda272160c32fdcc5fab651e1f 100644 (file)
@@ -69,6 +69,8 @@ typedef struct {
        gboolean              has_focus;
        gboolean              has_unread_message;
        gboolean              allow_scrolling;
+       gchar                *variant;
+       gboolean              in_construction;
 } EmpathyThemeAdiumPriv;
 
 struct _EmpathyAdiumData {
@@ -104,10 +106,12 @@ struct _EmpathyAdiumData {
 };
 
 static void theme_adium_iface_init (EmpathyChatViewIface *iface);
+static gchar * adium_info_dup_path_for_variant (GHashTable *info, const gchar *variant);
 
 enum {
        PROP_0,
        PROP_ADIUM_DATA,
+       PROP_VARIANT,
 };
 
 G_DEFINE_TYPE_WITH_CODE (EmpathyThemeAdium, empathy_theme_adium,
@@ -229,6 +233,27 @@ string_with_format (const gchar *format,
        return g_string_free (result, FALSE);
 }
 
+static void
+theme_adium_load_template (EmpathyThemeAdium *theme)
+{
+       EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
+       gchar                 *basedir_uri;
+       gchar                 *variant_path;
+       gchar                 *template;
+
+       priv->pages_loading++;
+       basedir_uri = g_strconcat ("file://", priv->data->basedir, NULL);
+       variant_path = adium_info_dup_path_for_variant (priv->data->info,
+               priv->variant);
+       template = string_with_format (priv->data->template_html,
+               variant_path, NULL);
+       webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (theme),
+                                         template, basedir_uri);
+       g_free (basedir_uri);
+       g_free (variant_path);
+       g_free (template);
+}
+
 static void
 theme_adium_match_newline (const gchar *text,
                           gssize len,
@@ -1018,14 +1043,8 @@ static void
 theme_adium_clear (EmpathyChatView *view)
 {
        EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
-       gchar *basedir_uri;
 
-       priv->pages_loading++;
-       basedir_uri = g_strconcat ("file://", priv->data->basedir, NULL);
-       webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (view),
-                                         priv->data->template_html,
-                                         basedir_uri);
-       g_free (basedir_uri);
+       theme_adium_load_template (EMPATHY_THEME_ADIUM (view));
 
        /* Clear last contact to avoid trying to add a 'joined'
         * message when we don't have an insertion point. */
@@ -1503,7 +1522,6 @@ static void
 theme_adium_constructed (GObject *object)
 {
        EmpathyThemeAdiumPriv *priv = GET_PRIV (object);
-       gchar                 *basedir_uri;
        const gchar           *font_family = NULL;
        gint                   font_size = 0;
        WebKitWebView         *webkit_view = WEBKIT_WEB_VIEW (object);
@@ -1534,13 +1552,9 @@ theme_adium_constructed (GObject *object)
                          object);
 
        /* Load template */
-       priv->pages_loading = 1;
+       theme_adium_load_template (EMPATHY_THEME_ADIUM (object));
 
-       basedir_uri = g_strconcat ("file://", priv->data->basedir, NULL);
-       webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (object),
-                                         priv->data->template_html,
-                                         basedir_uri);
-       g_free (basedir_uri);
+       priv->in_construction = FALSE;
 }
 
 static void
@@ -1555,6 +1569,9 @@ theme_adium_get_property (GObject    *object,
        case PROP_ADIUM_DATA:
                g_value_set_boxed (value, priv->data);
                break;
+       case PROP_VARIANT:
+               g_value_set_string (value, priv->variant);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                break;
@@ -1567,6 +1584,7 @@ theme_adium_set_property (GObject      *object,
                          const GValue *value,
                          GParamSpec   *pspec)
 {
+       EmpathyThemeAdium *theme = EMPATHY_THEME_ADIUM (object);
        EmpathyThemeAdiumPriv *priv = GET_PRIV (object);
 
        switch (param_id) {
@@ -1574,6 +1592,9 @@ theme_adium_set_property (GObject      *object,
                g_assert (priv->data == NULL);
                priv->data = g_value_dup_boxed (value);
                break;
+       case PROP_VARIANT:
+               empathy_theme_adium_set_variant (theme, g_value_get_string (value));
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                break;
@@ -1603,6 +1624,15 @@ empathy_theme_adium_class_init (EmpathyThemeAdiumClass *klass)
                                                              G_PARAM_CONSTRUCT_ONLY |
                                                              G_PARAM_READWRITE |
                                                              G_PARAM_STATIC_STRINGS));
+       g_object_class_install_property (object_class,
+                                        PROP_VARIANT,
+                                        g_param_spec_string ("variant",
+                                                             "The theme variant",
+                                                             "Variant name for the theme",
+                                                             NULL,
+                                                             G_PARAM_CONSTRUCT |
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_STATIC_STRINGS));
 
        g_type_class_add_private (object_class, sizeof (EmpathyThemeAdiumPriv));
 }
@@ -1615,6 +1645,7 @@ empathy_theme_adium_init (EmpathyThemeAdium *theme)
 
        theme->priv = priv;
 
+       priv->in_construction = TRUE;
        g_queue_init (&priv->message_queue);
        priv->allow_scrolling = TRUE;
        priv->smiley_manager = empathy_smiley_manager_dup_singleton ();
@@ -1636,15 +1667,49 @@ empathy_theme_adium_init (EmpathyThemeAdium *theme)
 }
 
 EmpathyThemeAdium *
-empathy_theme_adium_new (EmpathyAdiumData *data)
+empathy_theme_adium_new (EmpathyAdiumData *data,
+                        const gchar *variant)
 {
        g_return_val_if_fail (data != NULL, NULL);
 
        return g_object_new (EMPATHY_TYPE_THEME_ADIUM,
                             "adium-data", data,
+                            "variant", variant,
                             NULL);
 }
 
+void
+empathy_theme_adium_set_variant (EmpathyThemeAdium *theme,
+                                const gchar *variant)
+{
+       EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
+       gchar *variant_path;
+       gchar *script;
+
+       if (!tp_strdiff (priv->variant, variant)) {
+               return;
+       }
+
+       g_free (priv->variant);
+       priv->variant = g_strdup (variant);
+
+       if (priv->in_construction) {
+               return;
+       }
+
+       DEBUG ("Update view with variant: '%s'", variant);
+       variant_path = adium_info_dup_path_for_variant (priv->data->info,
+               priv->variant);
+       script = g_strdup_printf ("setStylesheet(\"mainStyle\",\"%s\");", variant_path);
+
+       webkit_web_view_execute_script (WEBKIT_WEB_VIEW (theme), script);
+
+       g_free (variant_path);
+       g_free (script);
+
+       g_object_notify (G_OBJECT (theme), "variant");
+}
+
 gboolean
 empathy_adium_path_is_valid (const gchar *path)
 {
@@ -1717,33 +1782,31 @@ adium_info_get_no_variant_name (GHashTable *info)
        return name ? name : _("Normal");
 }
 
-static const gchar *
-adium_info_get_default_or_first_variant (GHashTable *info)
-{
-       const gchar *name;
-       GPtrArray *variants;
-
-       name = empathy_adium_info_get_default_variant (info);
-       if (name != NULL) {
-               return name;
-       }
-
-       variants = empathy_adium_info_get_available_variants (info);
-       g_assert (variants->len > 0);
-       return g_ptr_array_index (variants, 0);
-}
-
 static gchar *
 adium_info_dup_path_for_variant (GHashTable *info,
                                 const gchar *variant)
 {
        guint version = adium_info_get_version (info);
        const gchar *no_variant = adium_info_get_no_variant_name (info);
+       GPtrArray *variants;
+       guint i;
 
        if (version <= 2 && !tp_strdiff (variant, no_variant)) {
                return g_strdup ("main.css");
        }
 
+       /* Verify the variant exists, fallback to the first one */
+       variants = empathy_adium_info_get_available_variants (info);
+       for (i = 0; i < variants->len; i++) {
+               if (!tp_strdiff (variant, g_ptr_array_index (variants, i))) {
+                       break;
+               }
+       }
+       if (i == variants->len) {
+               DEBUG ("Variant %s does not exist", variant);
+               variant = g_ptr_array_index (variants, 0);
+       }
+
        return g_strdup_printf ("Variants/%s.css", variant);
 
 }
@@ -1827,7 +1890,6 @@ empathy_adium_data_new_with_info (const gchar *path, GHashTable *info)
        EmpathyAdiumData *data;
        gchar            *template_html = NULL;
        gchar            *footer_html = NULL;
-       gchar            *variant_path;
        gchar            *tmp;
 
        g_return_val_if_fail (empathy_adium_path_is_valid (path), NULL);
@@ -1928,15 +1990,12 @@ empathy_adium_data_new_with_info (const gchar *path, GHashTable *info)
                g_free (tmp);
        }
 
-       variant_path = adium_info_dup_path_for_variant (info,
-               adium_info_get_default_or_first_variant (info));
-
        /* Old custom templates had only 4 parameters.
         * New templates have 5 parameters */
        if (data->version <= 2 && data->custom_template) {
                tmp = string_with_format (template_html,
                        data->basedir,
-                       variant_path,
+                       "%@", /* Leave variant unset */
                        "", /* The header */
                        footer_html ? footer_html : "",
                        NULL);
@@ -1944,7 +2003,7 @@ empathy_adium_data_new_with_info (const gchar *path, GHashTable *info)
                tmp = string_with_format (template_html,
                        data->basedir,
                        data->version <= 2 ? "" : "@import url( \"main.css\" );",
-                       variant_path,
+                       "%@", /* Leave variant unset */
                        "", /* The header */
                        footer_html ? footer_html : "",
                        NULL);
@@ -1954,7 +2013,6 @@ empathy_adium_data_new_with_info (const gchar *path, GHashTable *info)
 
        g_free (template_html);
        g_free (footer_html);
-       g_free (variant_path);
 
        return data;
 }
index d0ad0170d9ba7b9fcbf525088938c194cefc7b03..1c01b7b37e5858565c0e7d91acfbfe212c3e310b 100644 (file)
@@ -49,7 +49,10 @@ struct _EmpathyThemeAdiumClass {
 };
 
 GType              empathy_theme_adium_get_type (void) G_GNUC_CONST;
-EmpathyThemeAdium *empathy_theme_adium_new      (EmpathyAdiumData *data);
+EmpathyThemeAdium *empathy_theme_adium_new      (EmpathyAdiumData *data,
+                                                const gchar *variant);
+void               empathy_theme_adium_set_variant (EmpathyThemeAdium *theme,
+                                                   const gchar *variant);
 
 gboolean           empathy_adium_path_is_valid (const gchar *path);
 
index 0dcb40a705af588ca89322cd80ae2d3f25e68143..d50154b4184d42be15cd841e84c12876b7ac475b 100644 (file)
 typedef struct {
        GSettings   *gsettings_chat;
        gchar       *name;
-       gchar       *adium_path;
        GtkSettings *settings;
        GList       *boxes_views;
        guint        emit_changed_idle;
+       gboolean     in_constructor;
+
+#ifdef HAVE_WEBKIT
+       EmpathyAdiumData *adium_data;
+       gchar *adium_variant;
+       /* list of weakref to EmpathyThemeAdium objects */
+       GList *adium_views;
+#endif
 } EmpathyThemeManagerPriv;
 
 enum {
@@ -74,6 +81,57 @@ static const gchar *themes[] = {
 
 G_DEFINE_TYPE (EmpathyThemeManager, empathy_theme_manager, G_TYPE_OBJECT);
 
+static gboolean
+theme_manager_emit_changed_idle_cb (gpointer manager)
+{
+       EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
+       const gchar *adium_path = NULL;
+
+       if (priv->adium_data) {
+               adium_path = empathy_adium_data_get_path (priv->adium_data);
+       }
+       DEBUG ("Emit theme-changed with: name='%s' adium_path='%s' "
+              "adium_variant='%s'", priv->name, adium_path,
+              priv->adium_variant);
+
+       g_signal_emit (manager, signals[THEME_CHANGED], 0, NULL);
+       priv->emit_changed_idle = 0;
+
+       return FALSE;
+}
+
+static void
+theme_manager_emit_changed (EmpathyThemeManager *manager)
+{
+       EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
+
+       /* We emit the signal in idle callback to be sure we emit it only once
+        * in the case both the name and adium_path changed */
+       if (priv->emit_changed_idle == 0 && !priv->in_constructor) {
+               priv->emit_changed_idle = g_idle_add (
+                       theme_manager_emit_changed_idle_cb, manager);
+       }
+}
+
+static void
+theme_manager_view_weak_notify_cb (gpointer data,
+                                   GObject *where_the_object_was)
+{
+       GList **list = data;
+       *list = g_list_remove (*list, where_the_object_was);
+}
+
+static void
+clear_list_of_views (GList **views)
+{
+       while (*views) {
+               g_object_weak_unref ((*views)->data,
+                                    theme_manager_view_weak_notify_cb,
+                                    views);
+               *views = g_list_delete_link (*views, *views);
+       }
+}
+
 static void
 theme_manager_gdk_color_to_hex (GdkColor *gdk_color, gchar *str_color)
 {
@@ -135,15 +193,6 @@ theme_manager_create_irc_view (EmpathyThemeManager *manager)
        return theme;
 }
 
-static void
-theme_manager_boxes_weak_notify_cb (gpointer data,
-                                   GObject *where_the_object_was)
-{
-       EmpathyThemeManagerPriv *priv = GET_PRIV (data);
-
-       priv->boxes_views = g_list_remove (priv->boxes_views, where_the_object_was);
-}
-
 static EmpathyThemeBoxes *
 theme_manager_create_boxes_view (EmpathyThemeManager *manager)
 {
@@ -153,8 +202,8 @@ theme_manager_create_boxes_view (EmpathyThemeManager *manager)
        theme = empathy_theme_boxes_new ();
        priv->boxes_views = g_list_prepend (priv->boxes_views, theme);
        g_object_weak_ref (G_OBJECT (theme),
-                          theme_manager_boxes_weak_notify_cb,
-                          manager);
+                          theme_manager_view_weak_notify_cb,
+                          &priv->boxes_views);
 
        return theme;
 }
@@ -320,6 +369,88 @@ theme_manager_update_boxes_theme (EmpathyThemeManager *manager,
        }
 }
 
+#ifdef HAVE_WEBKIT
+static EmpathyThemeAdium *
+theme_manager_create_adium_view (EmpathyThemeManager *manager)
+{
+       EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
+       EmpathyThemeAdium *theme;
+
+       theme = empathy_theme_adium_new (priv->adium_data, priv->adium_variant);
+       priv->adium_views = g_list_prepend (priv->adium_views, theme);
+       g_object_weak_ref (G_OBJECT (theme),
+                          theme_manager_view_weak_notify_cb,
+                          &priv->adium_views);
+
+       return theme;
+}
+
+static void
+theme_manager_notify_adium_path_cb (GSettings   *gsettings_chat,
+                                   const gchar *key,
+                                   gpointer     user_data)
+{
+       EmpathyThemeManager     *manager = EMPATHY_THEME_MANAGER (user_data);
+       EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
+       const gchar             *current_path = NULL;
+       gchar                   *new_path;
+
+       new_path = g_settings_get_string (gsettings_chat, key);
+
+       if (priv->adium_data != NULL) {
+               current_path = empathy_adium_data_get_path (priv->adium_data);
+       }
+
+       /* If path did not really changed, ignore */
+       if (!tp_strdiff (current_path, new_path)) {
+               g_free (new_path);
+               return;
+       }
+
+       /* If path does not really contains an adium path, ignore */
+       if (!empathy_adium_path_is_valid (new_path)) {
+               DEBUG ("Invalid theme path set: %s", new_path);
+               g_free (new_path);
+               return;
+       }
+
+       /* Load new theme data, we can stop tracking existing views since we
+        * won't be able to change them live anymore */
+       clear_list_of_views (&priv->adium_views);
+       tp_clear_pointer (&priv->adium_data, empathy_adium_data_unref);
+       priv->adium_data = empathy_adium_data_new (new_path);
+
+       theme_manager_emit_changed (manager);
+
+       g_free (new_path);
+}
+
+static void
+theme_manager_notify_adium_variant_cb (GSettings   *gsettings_chat,
+                                      const gchar *key,
+                                      gpointer     user_data)
+{
+       EmpathyThemeManager     *manager = EMPATHY_THEME_MANAGER (user_data);
+       EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
+       gchar                   *new_variant;
+       GList                   *l;
+
+       new_variant = g_settings_get_string (gsettings_chat, key);
+       if (!tp_strdiff (priv->adium_variant, new_variant)) {
+               g_free (new_variant);
+               return;
+       }
+
+       g_free (priv->adium_variant);
+       priv->adium_variant = new_variant;
+
+       for (l = priv->adium_views; l; l = l->next) {
+               empathy_theme_adium_set_variant (EMPATHY_THEME_ADIUM (l->data),
+                       priv->adium_variant);
+       }
+}
+#endif /* HAVE_WEBKIT */
+
 EmpathyChatView *
 empathy_theme_manager_create_view (EmpathyThemeManager *manager)
 {
@@ -331,33 +462,8 @@ empathy_theme_manager_create_view (EmpathyThemeManager *manager)
        DEBUG ("Using theme %s", priv->name);
 
 #ifdef HAVE_WEBKIT
-       if (strcmp (priv->name, "adium") == 0)  {
-               if (empathy_adium_path_is_valid (priv->adium_path)) {
-                       static EmpathyAdiumData *data = NULL;
-                       EmpathyThemeAdium *theme_adium;
-
-                       if (data &&
-                           !tp_strdiff (empathy_adium_data_get_path (data),
-                                        priv->adium_path)) {
-                               /* Theme did not change, reuse data */
-                               theme_adium = empathy_theme_adium_new (data);
-                               return EMPATHY_CHAT_VIEW (theme_adium);
-                       }
-
-                       /* Theme changed, drop old data if any and
-                        * load a new one */
-                       if (data) {
-                               empathy_adium_data_unref (data);
-                               data = NULL;
-                       }
-
-                       data = empathy_adium_data_new (priv->adium_path);
-                       theme_adium = empathy_theme_adium_new (data);
-                       return EMPATHY_CHAT_VIEW (theme_adium);
-               } else {
-                       /* The adium path is not valid, fallback to classic theme */
-                       return EMPATHY_CHAT_VIEW (theme_manager_create_irc_view (manager));
-               }
+       if (strcmp (priv->name, "adium") == 0 && priv->adium_data != NULL)  {
+               return EMPATHY_CHAT_VIEW (theme_manager_create_adium_view (manager));
        }
 #endif
 
@@ -394,7 +500,6 @@ theme_manager_ensure_theme_exists (const gchar *name)
 }
 
 typedef enum {
-       THEME_TYPE_UNSET,
        THEME_TYPE_IRC,
        THEME_TYPE_BOXED,
        THEME_TYPE_ADIUM,
@@ -403,9 +508,7 @@ typedef enum {
 static ThemeType
 theme_type (const gchar *name)
 {
-       if (name == NULL) {
-               return THEME_TYPE_UNSET;
-       } else if (!tp_strdiff (name, "classic")) {
+       if (!tp_strdiff (name, "classic")) {
                return THEME_TYPE_IRC;
        } else if (!tp_strdiff (name, "adium")) {
                return THEME_TYPE_ADIUM;
@@ -414,30 +517,6 @@ theme_type (const gchar *name)
        }
 }
 
-static gboolean
-theme_manager_emit_changed_idle_cb (gpointer manager)
-{
-       EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
-
-       g_signal_emit (manager, signals[THEME_CHANGED], 0, NULL);
-       priv->emit_changed_idle = 0;
-
-       return FALSE;
-}
-
-static void
-theme_manager_emit_changed (EmpathyThemeManager *manager)
-{
-       EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
-
-       /* We emit the signal in idle callback to be sure we emit it only once
-        * in the case both the name and adium_path changed */
-       if (priv->emit_changed_idle == 0) {
-               priv->emit_changed_idle = g_idle_add (
-                       theme_manager_emit_changed_idle_cb, manager);
-       }
-}
-
 static void
 theme_manager_notify_name_cb (GSettings   *gsettings_chat,
                              const gchar *key,
@@ -478,42 +557,12 @@ theme_manager_notify_name_cb (GSettings   *gsettings_chat,
                }
        }
 
-       /* Do not emit theme-changed if theme type didn't change, or if it was
-        * unset (the manager is under construction). If theme changed from a
-        * boxed to another boxed, all view are updated in place. If theme
-        * changed from an adium to another adium, the signal will be emited
-        * from theme_manager_notify_adium_path_cb ()
+       /* Do not emit theme-changed if theme type didn't change. If theme
+        * changed from a boxed to another boxed, all view are updated in place.
+        * If theme changed from an adium to another adium, the signal will be
+        * emited from theme_manager_notify_adium_path_cb ()
         */
-       if (old_type != new_type && old_type != THEME_TYPE_UNSET) {
-               theme_manager_emit_changed (manager);
-       }
-}
-
-static void
-theme_manager_notify_adium_path_cb (GSettings   *gsettings_chat,
-                                   const gchar *key,
-                                   gpointer     user_data)
-{
-       EmpathyThemeManager     *manager = EMPATHY_THEME_MANAGER (user_data);
-       EmpathyThemeManagerPriv *priv = GET_PRIV (manager);
-       gchar                   *adium_path = NULL;
-       gboolean                 was_set;
-
-       adium_path = g_settings_get_string (gsettings_chat, key);
-
-       if (!tp_strdiff (priv->adium_path, adium_path)) {
-               g_free (adium_path);
-               return;
-       }
-
-       was_set = (priv->adium_path != NULL);
-
-       g_free (priv->adium_path);
-       priv->adium_path = adium_path;
-
-       /* Do not emit the signal if path was not set yet (the manager is under
-        * construction) */
-       if (was_set) {
+       if (old_type != new_type) {
                theme_manager_emit_changed (manager);
        }
 }
@@ -522,23 +571,22 @@ static void
 theme_manager_finalize (GObject *object)
 {
        EmpathyThemeManagerPriv *priv = GET_PRIV (object);
-       GList                   *l;
 
        g_object_unref (priv->gsettings_chat);
        g_free (priv->name);
-       g_free (priv->adium_path);
-
-       for (l = priv->boxes_views; l; l = l->next) {
-               g_object_weak_unref (G_OBJECT (l->data),
-                                    theme_manager_boxes_weak_notify_cb,
-                                    object);
-       }
-       g_list_free (priv->boxes_views);
 
        if (priv->emit_changed_idle != 0) {
                g_source_remove (priv->emit_changed_idle);
        }
 
+       clear_list_of_views (&priv->boxes_views);
+
+#ifdef HAVE_WEBKIT
+       clear_list_of_views (&priv->adium_views);
+       g_free (priv->adium_variant);
+       tp_clear_pointer (&priv->adium_data, empathy_adium_data_unref);
+#endif
+
        G_OBJECT_CLASS (empathy_theme_manager_parent_class)->finalize (object);
 }
 
@@ -569,6 +617,7 @@ empathy_theme_manager_init (EmpathyThemeManager *manager)
                EMPATHY_TYPE_THEME_MANAGER, EmpathyThemeManagerPriv);
 
        manager->priv = priv;
+       priv->in_constructor = TRUE;
 
        priv->gsettings_chat = g_settings_new (EMPATHY_PREFS_CHAT_SCHEMA);
 
@@ -581,7 +630,8 @@ empathy_theme_manager_init (EmpathyThemeManager *manager)
                                      EMPATHY_PREFS_CHAT_THEME,
                                      manager);
 
-       /* Take the adium path and track changes */
+#ifdef HAVE_WEBKIT
+       /* Take the adium path/variant and track changes */
        g_signal_connect (priv->gsettings_chat,
                          "changed::" EMPATHY_PREFS_CHAT_ADIUM_PATH,
                          G_CALLBACK (theme_manager_notify_adium_path_cb),
@@ -589,6 +639,16 @@ empathy_theme_manager_init (EmpathyThemeManager *manager)
        theme_manager_notify_adium_path_cb (priv->gsettings_chat,
                                            EMPATHY_PREFS_CHAT_ADIUM_PATH,
                                            manager);
+
+       g_signal_connect (priv->gsettings_chat,
+                         "changed::" EMPATHY_PREFS_CHAT_THEME_VARIANT,
+                         G_CALLBACK (theme_manager_notify_adium_variant_cb),
+                         manager);
+       theme_manager_notify_adium_variant_cb (priv->gsettings_chat,
+                                              EMPATHY_PREFS_CHAT_THEME_VARIANT,
+                                              manager);
+#endif
+       priv->in_constructor = FALSE;
 }
 
 EmpathyThemeManager *
index 8d24e8b5e27771eaddba3bc85955df3aaae93ec9..60726d17e05eacb3da970840780f7ad756f97a57 100644 (file)
@@ -55,6 +55,7 @@ G_BEGIN_DECLS
 #define EMPATHY_PREFS_CHAT_SHOW_SMILEYS            "graphical-smileys"
 #define EMPATHY_PREFS_CHAT_SHOW_CONTACTS_IN_ROOMS  "show-contacts-in-rooms"
 #define EMPATHY_PREFS_CHAT_THEME                   "theme"
+#define EMPATHY_PREFS_CHAT_THEME_VARIANT           "theme-variant"
 #define EMPATHY_PREFS_CHAT_ADIUM_PATH              "adium-path"
 #define EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES "spell-checker-languages"
 #define EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED   "spell-checker-enabled"
index f90724c7ff44f1b309918b1febf626f35bd38ea4..9aa21e8b016eb390352204f0920f4264c10f75c7 100644 (file)
@@ -85,6 +85,8 @@ struct _EmpathyPreferencesPriv {
 
        GtkWidget *vbox_chat_theme;
        GtkWidget *combobox_chat_theme;
+       GtkWidget *combobox_chat_theme_variant;
+       GtkWidget *hbox_chat_theme_variant;
        GtkWidget *sw_chat_theme_preview;
        EmpathyChatView *chat_theme_preview;
        EmpathyThemeManager *theme_manager;
@@ -127,9 +129,16 @@ enum {
        COL_THEME_NAME,
        COL_THEME_IS_ADIUM,
        COL_THEME_ADIUM_PATH,
+       COL_THEME_ADIUM_INFO,
        COL_THEME_COUNT
 };
 
+enum {
+       COL_VARIANT_NAME,
+       COL_VARIANT_DEFAULT,
+       COL_VARIANT_COUNT
+};
+
 enum {
        COL_SOUND_ENABLED,
        COL_SOUND_NAME,
@@ -733,6 +742,156 @@ preferences_preview_theme_changed_cb (EmpathyThemeManager *manager,
        g_object_unref (dbus);
 }
 
+static void
+preferences_theme_variant_changed_cb (GtkComboBox        *combo,
+                                     EmpathyPreferences *preferences)
+{
+       EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
+       GtkTreeIter   iter;
+
+       if (gtk_combo_box_get_active_iter (combo, &iter)) {
+               GtkTreeModel *model;
+               gchar        *name;
+
+               model = gtk_combo_box_get_model (combo);
+               gtk_tree_model_get (model, &iter,
+                                   COL_VARIANT_NAME, &name,
+                                   -1);
+
+               g_settings_set_string (priv->gsettings_chat,
+                                      EMPATHY_PREFS_CHAT_THEME_VARIANT,
+                                      name);
+
+               g_free (name);
+       }
+}
+
+static void
+preferences_theme_variant_notify_cb (GSettings   *gsettings,
+                                    const gchar *key,
+                                    gpointer     user_data)
+{
+       EmpathyPreferences *preferences = user_data;
+       EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
+       GtkComboBox        *combo;
+       gchar              *conf_name;
+       GtkTreeModel       *model;
+       GtkTreeIter         iter;
+       GtkTreeIter         default_iter;
+       gboolean            found_default = FALSE;
+       gboolean            found = FALSE;
+       gboolean            ok;
+
+       conf_name = g_settings_get_string (gsettings, EMPATHY_PREFS_CHAT_THEME_VARIANT);
+       combo = GTK_COMBO_BOX (priv->combobox_chat_theme_variant);
+       model = gtk_combo_box_get_model (combo);
+
+       for (ok = gtk_tree_model_get_iter_first (model, &iter);
+            ok && !found;
+            ok = gtk_tree_model_iter_next (model, &iter)) {
+               gchar *name;
+               gboolean is_default;
+
+               gtk_tree_model_get (model, &iter,
+                                   COL_VARIANT_NAME, &name,
+                                   COL_VARIANT_DEFAULT, &is_default,
+                                   -1);
+
+               if (!tp_strdiff (name, conf_name)) {
+                       found = TRUE;
+                       gtk_combo_box_set_active_iter (combo, &iter);
+               }
+               if (is_default) {
+                       found_default = TRUE;
+                       default_iter = iter;
+               }
+
+               g_free (name);
+       }
+
+       /* Fallback to the first one. */
+       if (!found) {
+               if (found_default) {
+                       gtk_combo_box_set_active_iter (combo, &default_iter);
+               } else if (gtk_tree_model_get_iter_first (model, &iter)) {
+                       gtk_combo_box_set_active_iter (combo, &iter);
+               }
+       }
+
+       g_free (conf_name);
+}
+
+static void
+preferences_theme_variants_fill (EmpathyPreferences *preferences,
+                                GHashTable         *info)
+{
+       EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
+       GtkTreeModel *model;
+       GtkListStore *store;
+       GPtrArray    *variants;
+       const gchar  *default_variant;
+       guint         i;
+
+       model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->combobox_chat_theme_variant));
+       store = GTK_LIST_STORE (model);
+       gtk_list_store_clear (store);
+
+       variants = empathy_adium_info_get_available_variants (info);
+       default_variant = empathy_adium_info_get_default_variant (info);
+       for (i = 0; i < variants->len; i++) {
+               gchar *name = g_ptr_array_index (variants, i);
+
+               gtk_list_store_insert_with_values (store, NULL, -1,
+                       COL_VARIANT_NAME, name,
+                       COL_VARIANT_DEFAULT, !tp_strdiff (name, default_variant),
+                       -1);
+       }
+
+       /* Select the variant from the GSetting key */
+       preferences_theme_variant_notify_cb (priv->gsettings_chat,
+                                            EMPATHY_PREFS_CHAT_THEME_VARIANT,
+                                            preferences);
+}
+
+static void
+preferences_theme_variants_setup (EmpathyPreferences *preferences)
+{
+       EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
+       GtkComboBox   *combo;
+       GtkCellLayout *cell_layout;
+       GtkCellRenderer *renderer;
+       GtkListStore  *store;
+
+       combo = GTK_COMBO_BOX (priv->combobox_chat_theme_variant);
+       cell_layout = GTK_CELL_LAYOUT (combo);
+
+       /* Create the model */
+       store = gtk_list_store_new (COL_VARIANT_COUNT,
+                                   G_TYPE_STRING,      /* name */
+                                   G_TYPE_BOOLEAN);    /* is default */
+       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+               COL_VARIANT_NAME, GTK_SORT_ASCENDING);
+
+       /* Add cell renderer */
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start (cell_layout, renderer, TRUE);
+       gtk_cell_layout_set_attributes (cell_layout, renderer,
+               "text", COL_VARIANT_NAME, NULL);
+
+       gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
+       g_object_unref (store);
+
+       g_signal_connect (combo, "changed",
+                         G_CALLBACK (preferences_theme_variant_changed_cb),
+                         preferences);
+
+       /* Track changes of the GSetting key */
+       g_signal_connect (priv->gsettings_chat,
+                         "changed::" EMPATHY_PREFS_CHAT_THEME_VARIANT,
+                         G_CALLBACK (preferences_theme_variant_notify_cb),
+                         preferences);
+}
+
 static void
 preferences_theme_changed_cb (GtkComboBox        *combo,
                              EmpathyPreferences *preferences)
@@ -745,12 +904,14 @@ preferences_theme_changed_cb (GtkComboBox        *combo,
                gboolean      is_adium;
                gchar        *name;
                gchar        *path;
+               GHashTable   *info;
 
                model = gtk_combo_box_get_model (combo);
                gtk_tree_model_get (model, &iter,
                                    COL_THEME_IS_ADIUM, &is_adium,
                                    COL_THEME_NAME, &name,
                                    COL_THEME_ADIUM_PATH, &path,
+                                   COL_THEME_ADIUM_INFO, &info,
                                    -1);
 
                g_settings_set_string (priv->gsettings_chat,
@@ -760,10 +921,14 @@ preferences_theme_changed_cb (GtkComboBox        *combo,
                        g_settings_set_string (priv->gsettings_chat,
                                               EMPATHY_PREFS_CHAT_ADIUM_PATH,
                                               path);
+                       preferences_theme_variants_fill (preferences, info);
+                       gtk_widget_show (priv->hbox_chat_theme_variant);
+               } else {
+                       gtk_widget_hide (priv->hbox_chat_theme_variant);
                }
-
                g_free (name);
                g_free (path);
+               tp_clear_pointer (&info, g_hash_table_unref);
        }
 }
 
@@ -833,6 +998,8 @@ preferences_themes_setup (EmpathyPreferences *preferences)
        GList         *adium_themes;
        gint           i;
 
+       preferences_theme_variants_setup (preferences);
+
        combo = GTK_COMBO_BOX (priv->combobox_chat_theme);
        cell_layout = GTK_CELL_LAYOUT (combo);
 
@@ -841,7 +1008,8 @@ preferences_themes_setup (EmpathyPreferences *preferences)
                                    G_TYPE_STRING,      /* Display name */
                                    G_TYPE_STRING,      /* Theme name */
                                    G_TYPE_BOOLEAN,     /* Is an Adium theme */
-                                   G_TYPE_STRING);     /* Adium theme path */
+                                   G_TYPE_STRING,      /* Adium theme path */
+                                   G_TYPE_HASH_TABLE); /* Adium theme info */
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
                COL_THEME_VISIBLE_NAME, GTK_SORT_ASCENDING);
 
@@ -871,6 +1039,7 @@ preferences_themes_setup (EmpathyPreferences *preferences)
                                COL_THEME_NAME, "adium",
                                COL_THEME_IS_ADIUM, TRUE,
                                COL_THEME_ADIUM_PATH, path,
+                               COL_THEME_ADIUM_INFO, info,
                                -1);
                }
                g_hash_table_unref (info);
@@ -972,6 +1141,8 @@ empathy_preferences_init (EmpathyPreferences *preferences)
                "checkbutton_show_contacts_in_rooms", &priv->checkbutton_show_contacts_in_rooms,
                "vbox_chat_theme", &priv->vbox_chat_theme,
                "combobox_chat_theme", &priv->combobox_chat_theme,
+               "combobox_chat_theme_variant", &priv->combobox_chat_theme_variant,
+               "hbox_chat_theme_variant", &priv->hbox_chat_theme_variant,
                "sw_chat_theme_preview", &priv->sw_chat_theme_preview,
                "checkbutton_separate_chat_windows", &priv->checkbutton_separate_chat_windows,
                "checkbutton_events_notif_area", &priv->checkbutton_events_notif_area,
index 6bc17b761ed8ec28230c3f430c2e14f70e5a4e8e..2549d51add4b1d86b036f055f7f44fcaceafe12d 100644 (file)
                             <property name="position">1</property>
                           </packing>
                         </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="hbox_chat_theme_variant">
-                        <property name="visible">False</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">12</property>
                         <child>
-                          <object class="GtkLabel" id="label4">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">Theme Variant:</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">combobox_chat_theme_variant</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkComboBox" id="combobox_chat_theme_variant">
-                            <property name="visible">True</property>
+                          <object class="GtkBox" id="hbox_chat_theme_variant">
                             <property name="can_focus">False</property>
+                            <property name="spacing">12</property>
+                            <child>
+                              <object class="GtkLabel" id="label4">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="label" translatable="yes">Variant:</property>
+                                <property name="use_underline">True</property>
+                                <property name="mnemonic_widget">combobox_chat_theme_variant</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkComboBox" id="combobox_chat_theme_variant">
+                                <property name="visible">True</property>
+                                <property name="can_focus">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="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
                           </packing>
                         </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">True</property>
-                        <property name="position">1</property>
+                        <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
                       <packing>
                         <property name="expand">True</property>
                         <property name="fill">True</property>
-                        <property name="position">2</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                   </object>