diff --git a/capplets/appearance/ChangeLog b/capplets/appearance/ChangeLog index 5cd47b47d..ed132f934 100644 --- a/capplets/appearance/ChangeLog +++ b/capplets/appearance/ChangeLog @@ -1,3 +1,26 @@ +2007-06-14 Jens Granseuer + + * Makefile.am: + * theme-util.c: (theme_delete), (theme_model_iter_last): + * theme-util.h: new files + + * appearance.glade: default delete buttons to insensitive, + change label for "Custom" key, adjust column ids for icon view + + * appearance-style.c: (style_init), (prepare_list), + (update_color_buttons_from_settings), (theme_name_changed), + (color_button_clicked_cb), + (color_scheme_defaults_button_clicked_cb): + * appearance-themes.c: (theme_get_selected_name), + (theme_get_selected), (theme_select_iter), (theme_select_name), + (theme_is_equal), (theme_set_custom_from_theme), + (theme_changed_on_disk_cb), (theme_custom_cb), (theme_delete_cb), + (theme_details_changed_cb), (theme_color_scheme_changed_cb), + (theme_gconf_changed), (theme_postinit), (themes_init), + (themes_shutdown): + * appearance.h: improvements all around the block (metatheme + deletion now working, and custom theme working much better) + 2007-06-09 Denis Washington * appearance-style.c: (theme_name_changed): diff --git a/capplets/appearance/Makefile.am b/capplets/appearance/Makefile.am index 5edef7e78..3b01d05f6 100644 --- a/capplets/appearance/Makefile.am +++ b/capplets/appearance/Makefile.am @@ -24,6 +24,8 @@ gnome_appearance_properties_SOURCES = \ gnome-wp-utils.h \ gnome-wp-xml.c \ gnome-wp-xml.h \ + theme-util.c \ + theme-util.h \ wp-cellrenderer.c \ wp-cellrenderer.h diff --git a/capplets/appearance/appearance-style.c b/capplets/appearance/appearance-style.c index 3d421d693..17d2acbef 100644 --- a/capplets/appearance/appearance-style.c +++ b/capplets/appearance/appearance-style.c @@ -22,36 +22,12 @@ #include #include +#include "theme-util.h" #include "gtkrc-utils.h" -#include "gnome-theme-info.h" #include "gconf-property-editor.h" #include "theme-thumbnail.h" -enum ThemeType { - GTK_THEMES, - METACITY_THEMES, - ICON_THEMES, - CURSOR_THEMES, - COLOR_SCHEME -}; - -enum { - COL_THUMBNAIL, - COL_LABEL, - COL_NAME, - NUM_COLS -}; - -static const gchar *gconf_keys[] = { - "/desktop/gnome/interface/gtk_theme", - "/apps/metacity/general/theme", - "/desktop/gnome/interface/icon_theme", - "/desktop/gnome/peripherals/mouse/cursor_theme", - "/desktop/gnome/interface/gtk_color_scheme" -}; - - -static void prepare_list (AppearanceData *data, GtkWidget *list, enum ThemeType type); +static void prepare_list (AppearanceData *data, GtkWidget *list, ThemeType type); static void update_color_buttons_from_string (const gchar *color_scheme, AppearanceData *data); static void update_color_buttons_from_settings (GtkSettings *settings, AppearanceData *data); static void check_color_schemes_enabled (GtkSettings *settings, AppearanceData *data); @@ -86,9 +62,9 @@ style_init (AppearanceData *data) g_signal_connect (w, "response", (GCallback) style_response_cb, NULL); g_signal_connect (w, "delete_event", (GCallback) gtk_true, NULL); - prepare_list (data, glade_xml_get_widget (data->xml, "gtk_themes_list"), GTK_THEMES); - prepare_list (data, glade_xml_get_widget (data->xml, "window_themes_list"), METACITY_THEMES); - prepare_list (data, glade_xml_get_widget (data->xml, "icon_themes_list"), ICON_THEMES); + prepare_list (data, glade_xml_get_widget (data->xml, "gtk_themes_list"), THEME_TYPE_GTK); + prepare_list (data, glade_xml_get_widget (data->xml, "window_themes_list"), THEME_TYPE_WINDOW); + prepare_list (data, glade_xml_get_widget (data->xml, "icon_themes_list"), THEME_TYPE_ICON); w = glade_xml_get_widget (data->xml, "color_scheme_message_hbox"); gtk_widget_set_no_show_all (w, TRUE); @@ -113,34 +89,39 @@ style_init (AppearanceData *data) g_signal_connect (G_OBJECT (glade_xml_get_widget (data->xml, "selected_fg_colorbutton")), "color-set", (GCallback) color_button_clicked_cb, data); g_signal_connect (G_OBJECT (glade_xml_get_widget (data->xml, "selected_bg_colorbutton")), "color-set", (GCallback) color_button_clicked_cb, data); /* "Reset To Defaults" button */ - g_signal_connect (G_OBJECT (glade_xml_get_widget (data->xml, "color_scheme_defaults_button")), "clicked", (GCallback) color_scheme_defaults_button_clicked_cb, data); + g_signal_connect (G_OBJECT (glade_xml_get_widget (data->xml, "color_scheme_defaults_button")), "clicked", (GCallback) color_scheme_defaults_button_clicked_cb, data); } static void -prepare_list (AppearanceData *data, GtkWidget *list, enum ThemeType type) +prepare_list (AppearanceData *data, GtkWidget *list, ThemeType type) { GtkListStore *store; GList *l, *themes = NULL; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeModel *sort_model; + const gchar *key; switch (type) { - case GTK_THEMES: + case THEME_TYPE_GTK: themes = gnome_theme_info_find_by_type (GNOME_THEME_GTK_2); + key = GTK_THEME_KEY; break; - case METACITY_THEMES: + case THEME_TYPE_WINDOW: themes = gnome_theme_info_find_by_type (GNOME_THEME_METACITY); + key = METACITY_THEME_KEY; break; - case ICON_THEMES: + case THEME_TYPE_ICON: themes = gnome_theme_icon_info_find_all (); + key = ICON_THEME_KEY; break; - case CURSOR_THEMES: + case THEME_TYPE_CURSOR: themes = NULL; /* don't know what to do yet */ + key = CURSOR_THEME_KEY; default: /* we don't deal with any other type of themes here */ @@ -158,9 +139,9 @@ prepare_list (AppearanceData *data, GtkWidget *list, enum ThemeType type) GdkPixbuf *thumbnail; GtkTreeIter i; - if (type == GTK_THEMES || type == METACITY_THEMES) { + if (type == THEME_TYPE_GTK || type == THEME_TYPE_WINDOW) { name = ((GnomeThemeInfo *) l->data)->name; - } else if (type == ICON_THEMES) { + } else if (type == THEME_TYPE_ICON) { name = ((GnomeThemeIconInfo *) l->data)->name; label = ((GnomeThemeIconInfo *) l->data)->readable_name; } @@ -170,21 +151,21 @@ prepare_list (AppearanceData *data, GtkWidget *list, enum ThemeType type) switch (type) { - case GTK_THEMES: + case THEME_TYPE_GTK: thumbnail = generate_gtk_theme_thumbnail ((GnomeThemeInfo *) l->data); break; - case ICON_THEMES: + case THEME_TYPE_ICON: thumbnail = generate_icon_theme_thumbnail ((GnomeThemeIconInfo *) l->data); break; - - case METACITY_THEMES: + + case THEME_TYPE_WINDOW: thumbnail = generate_metacity_theme_thumbnail ((GnomeThemeInfo *) l->data); break; default: thumbnail = NULL; - } + } gtk_list_store_insert_with_values (store, &i, 0, COL_THUMBNAIL, thumbnail, @@ -193,6 +174,7 @@ prepare_list (AppearanceData *data, GtkWidget *list, enum ThemeType type) if (thumbnail) g_object_unref (thumbnail); } + g_list_free (themes); sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store)); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), @@ -207,7 +189,7 @@ prepare_list (AppearanceData *data, GtkWidget *list, enum ThemeType type) NULL); column = gtk_tree_view_column_new (); - gtk_tree_view_column_pack_start (column, renderer, FALSE); + gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_add_attribute (column, renderer, "pixbuf", COL_THUMBNAIL); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); @@ -218,11 +200,11 @@ prepare_list (AppearanceData *data, GtkWidget *list, enum ThemeType type) NULL); column = gtk_tree_view_column_new (); - gtk_tree_view_column_pack_start (column, renderer, FALSE); + gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_add_attribute (column, renderer, "text", COL_LABEL); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); - gconf_peditor_new_tree_view (NULL, gconf_keys[type], list, + gconf_peditor_new_tree_view (NULL, key, list, "conv-to-widget-cb", conv_to_widget_cb, "conv-from-widget-cb", conv_from_widget_cb, NULL); @@ -395,17 +377,17 @@ static void update_color_buttons_from_settings (GtkSettings *settings, AppearanceData *data) { - gchar *theme; - theme = gconf_client_get_string (data->client, gconf_keys[COLOR_SCHEME], NULL); - if (theme == NULL || strcmp (theme, "") == 0) + gchar *scheme; + scheme = gconf_client_get_string (data->client, COLOR_SCHEME_KEY, NULL); + if (scheme == NULL || strcmp (scheme, "") == 0) { - g_free (theme); gtk_widget_set_sensitive (glade_xml_get_widget (data->xml, "color_scheme_defaults_button"), FALSE); - g_object_get (G_OBJECT (settings), "gtk-color-scheme", &theme, NULL); + g_free (scheme); + g_object_get (G_OBJECT (settings), "gtk-color-scheme", &scheme, NULL); } - update_color_buttons_from_string (theme, data); - g_free (theme); + update_color_buttons_from_string (scheme, data); + g_free (scheme); } static void @@ -461,8 +443,8 @@ theme_name_changed (GObject *settings, /* manually update GtkSettings to new gtk+ theme. */ g_object_get (settings, "gtk-theme-name", ¤t_theme, NULL); - new_theme = gconf_client_get_string (data->client, gconf_keys[GTK_THEMES], NULL); - + new_theme = gconf_client_get_string (data->client, GTK_THEME_KEY, NULL); + if (strcmp (current_theme, new_theme) != 0) g_object_set (settings, "gtk-theme-name", new_theme, NULL); @@ -504,9 +486,8 @@ color_button_clicked_cb (GtkWidget *colorbutton, AppearanceData *data) new_scheme = g_strconcat (fg, bg, text, base, selected_fg, selected_bg, NULL); /* Currently we assume this has only been called when one of the colours has - * actually changed, so we don't check the original key first - */ - gconf_client_set_string (data->client, gconf_keys[COLOR_SCHEME], new_scheme, NULL); + * actually changed, so we don't check the original key first */ + gconf_client_set_string (data->client, COLOR_SCHEME_KEY, new_scheme, NULL); gtk_widget_set_sensitive (glade_xml_get_widget (data->xml, "color_scheme_defaults_button"), TRUE); @@ -522,6 +503,6 @@ color_button_clicked_cb (GtkWidget *colorbutton, AppearanceData *data) static void color_scheme_defaults_button_clicked_cb (GtkWidget *button, AppearanceData *data) { - gconf_client_set_string (data->client, gconf_keys[COLOR_SCHEME], "", NULL); + gconf_client_set_string (data->client, COLOR_SCHEME_KEY, "", NULL); gtk_widget_set_sensitive (glade_xml_get_widget (data->xml, "color_scheme_defaults_button"), FALSE); } diff --git a/capplets/appearance/appearance-themes.c b/capplets/appearance/appearance-themes.c index ffa3623f3..32156ff02 100644 --- a/capplets/appearance/appearance-themes.c +++ b/capplets/appearance/appearance-themes.c @@ -21,25 +21,14 @@ #include "appearance.h" #include "theme-thumbnail.h" #include "gnome-theme-apply.h" +#include "theme-util.h" +#include #include #include -#define GTK_THEME_KEY "/desktop/gnome/interface/gtk_theme" -#define METACITY_THEME_KEY "/apps/metacity/general/theme" -#define ICON_THEME_KEY "/desktop/gnome/interface/icon_theme" -#define COLOR_SCHEME_KEY "/desktop/gnome/interface/gtk_color_scheme" -#define LOCKDOWN_KEY "/desktop/gnome/lockdown/disable_theme_settings" - #define CUSTOM_THEME_NAME "__custom__" -enum { - COL_LABEL, - COL_THUMBNAIL, - COL_NAME, - NUM_COLS -}; - static void theme_thumbnail_done_cb (GdkPixbuf *pixbuf, AppearanceData *data); static gchar * @@ -145,41 +134,94 @@ theme_queue_for_thumbnail (GnomeThemeMetaInfo *theme, AppearanceData *data) theme_thumbnail_generate (data); } -static const GnomeThemeMetaInfo * -theme_get_selected (GtkIconView *icon_view, AppearanceData *data) +static gchar * +theme_get_selected_name (GtkIconView *icon_view, AppearanceData *data) { - GnomeThemeMetaInfo *theme = NULL; + gchar *name = NULL; GList *selected = gtk_icon_view_get_selected_items (icon_view); if (selected) { GtkTreePath *path = selected->data; GtkTreeModel *model = gtk_icon_view_get_model (icon_view); GtkTreeIter iter; - gchar *name; - if (gtk_tree_model_get_iter (model, &iter, path)) { + if (gtk_tree_model_get_iter (model, &iter, path)) gtk_tree_model_get (model, &iter, COL_NAME, &name, -1); - if (!strcmp (name, data->theme_custom->name)) { - theme = data->theme_custom; - } else { - theme = gnome_theme_meta_info_find (name); - } + g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected); + } + + return name; +} + +static const GnomeThemeMetaInfo * +theme_get_selected (GtkIconView *icon_view, AppearanceData *data) +{ + GnomeThemeMetaInfo *theme = NULL; + gchar *name = theme_get_selected_name (icon_view, data); + + if (name != NULL) { + if (!strcmp (name, data->theme_custom->name)) { + theme = data->theme_custom; + } else { + theme = gnome_theme_meta_info_find (name); } g_free (name); - g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); - g_list_free (selected); } return theme; } static void -theme_set_custom_from_selected (GtkIconView *icon_view, AppearanceData *data) +theme_select_iter (GtkIconView *icon_view, GtkTreeIter *iter) +{ + GtkTreePath *path; + + path = gtk_tree_model_get_path (gtk_icon_view_get_model (icon_view), iter); + gtk_icon_view_select_path (icon_view, path); + gtk_icon_view_scroll_to_path (icon_view, path, FALSE, 0.5, 0.0); + gtk_tree_path_free (path); +} + +static void +theme_select_name (GtkIconView *icon_view, const gchar *theme) +{ + GtkTreeIter iter; + GtkTreeModel *model = gtk_icon_view_get_model (icon_view); + + if (find_in_model (model, theme, COL_NAME, &iter)) + theme_select_iter (icon_view, &iter); +} + +static gboolean +theme_is_equal (const GnomeThemeMetaInfo *a, const GnomeThemeMetaInfo *b) +{ + if (!(a->gtk_theme_name && b->gtk_theme_name) || + strcmp (a->gtk_theme_name, b->gtk_theme_name)) + return FALSE; + + if (!(a->gtk_color_scheme && b->gtk_color_scheme) || + strcmp (a->gtk_color_scheme, b->gtk_color_scheme)) + return FALSE; + + if (!(a->icon_theme_name && b->icon_theme_name) || + strcmp (a->icon_theme_name, b->icon_theme_name)) + return FALSE; + + if (!(a->metacity_theme_name && b->metacity_theme_name) || + strcmp (a->metacity_theme_name, b->metacity_theme_name)) + return FALSE; + + return TRUE; +} + +static void +theme_set_custom_from_theme (const GnomeThemeMetaInfo *info, AppearanceData *data) { GnomeThemeMetaInfo *custom = data->theme_custom; - const GnomeThemeMetaInfo *info = theme_get_selected (icon_view, data); + GtkIconView *icon_view = GTK_ICON_VIEW (glade_xml_get_widget (data->xml, "theme_list")); GtkTreeModel *model; GtkTreeIter iter; GtkTreePath *path; @@ -227,6 +269,7 @@ theme_set_custom_from_selected (GtkIconView *icon_view, AppearanceData *data) gtk_list_store_insert_with_values (data->theme_store, &child, 0, COL_LABEL, custom->readable_name, COL_NAME, custom->name, + COL_THUMBNAIL, data->theme_icon, -1); gtk_tree_model_sort_convert_child_iter_to_iter ( GTK_TREE_MODEL_SORT (model), &iter, &child); @@ -241,15 +284,6 @@ theme_set_custom_from_selected (GtkIconView *icon_view, AppearanceData *data) theme_queue_for_thumbnail (custom, data); } -static void -theme_remove_custom (GtkIconView *icon_view, AppearanceData *data) -{ - GtkTreeIter iter; - - if (find_in_model (GTK_TREE_MODEL (data->theme_store), CUSTOM_THEME_NAME, COL_NAME, &iter)) - gtk_list_store_remove (data->theme_store, &iter); -} - /** Theme Callbacks **/ static void @@ -268,6 +302,7 @@ theme_changed_on_disk_cb (GnomeThemeType type, gtk_list_store_insert_with_values (data->theme_store, NULL, 0, COL_LABEL, meta->readable_name, COL_NAME, meta->name, + COL_THUMBNAIL, data->theme_icon, -1); theme_queue_for_thumbnail (meta, data); @@ -348,11 +383,11 @@ theme_selection_changed_cb (GtkWidget *icon_view, AppearanceData *data) static void theme_custom_cb (GtkWidget *button, AppearanceData *data) { - GtkWidget *w, *parent, *icon_view; + GtkWidget *w, *parent; /* select the "custom" metatheme */ - icon_view = glade_xml_get_widget (data->xml, "theme_list"); - theme_set_custom_from_selected (GTK_ICON_VIEW (icon_view), data); + w = glade_xml_get_widget (data->xml, "theme_list"); + theme_set_custom_from_theme (theme_get_selected (GTK_ICON_VIEW (w), data), data); w = glade_xml_get_widget (data->xml, "theme_details"); parent = glade_xml_get_widget (data->xml, "appearance_window"); @@ -369,17 +404,81 @@ theme_install_cb (GtkWidget *button, AppearanceData *data) static void theme_delete_cb (GtkWidget *button, AppearanceData *data) { + GtkIconView *icon_view = GTK_ICON_VIEW (glade_xml_get_widget (data->xml, "theme_list")); + GList *selected = gtk_icon_view_get_selected_items (icon_view); + + if (selected) { + GtkTreePath *path = selected->data; + GtkTreeModel *model = gtk_icon_view_get_model (icon_view); + GtkTreeIter iter; + gchar *name = NULL; + + if (gtk_tree_model_get_iter (model, &iter, path)) + gtk_tree_model_get (model, &iter, COL_NAME, &name, -1); + + if (name != NULL && + strcmp (name, data->theme_custom->name) && + theme_delete (name, THEME_TYPE_META)) { + /* remove theme from the model, too */ + GtkTreeIter child; + + if (gtk_tree_model_iter_next (model, &iter) || + theme_model_iter_last (model, &iter)) + theme_select_iter (icon_view, &iter); + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_sort_convert_iter_to_child_iter ( + GTK_TREE_MODEL_SORT (model), &child, &iter); + gtk_list_store_remove (data->theme_store, &child); + } + + g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected); + g_free (name); + } + + /* TODO: Delete the selected theme */ } static void -theme_details_changed_cb (GtkWidget *widget, AppearanceData *data) +theme_details_changed_cb (AppearanceData *data) { - /* load new state from gconf */ - theme_load_from_gconf (data->client, data->theme_custom); + GnomeThemeMetaInfo *gconf_theme; + const GnomeThemeMetaInfo *selected; + GtkIconView *icon_view; + gboolean done = FALSE; - /* regenerate the thumbnail image for theme */ - theme_queue_for_thumbnail (data->theme_custom, data); + /* load new state from gconf */ + gconf_theme = gnome_theme_meta_info_new (); + theme_load_from_gconf (data->client, gconf_theme); + + /* check if it's our currently selected theme */ + icon_view = GTK_ICON_VIEW (glade_xml_get_widget (data->xml, "theme_list")); + selected = theme_get_selected (icon_view, data); + + if (!selected || !(done = theme_is_equal (selected, gconf_theme))) { + /* look for a matching metatheme */ + GList *theme_list, *l; + + theme_list = gnome_theme_meta_info_find_all (); + + for (l = theme_list; l; l = l->next) { + GnomeThemeMetaInfo *info = l->data; + + if (theme_is_equal (gconf_theme, info)) { + theme_select_name (icon_view, info->name); + done = TRUE; + } + } + g_list_free (theme_list); + } + + if (!done) + /* didn't find a match, set or update custom */ + theme_set_custom_from_theme (gconf_theme, data); + + gnome_theme_meta_info_free (gconf_theme); } static void @@ -387,44 +486,30 @@ theme_color_scheme_changed_cb (GObject *settings, GParamSpec *pspec, AppearanceData *data) { - theme_details_changed_cb (NULL, data); + theme_details_changed_cb (data); } static void -theme_select_after_realize (GtkIconView *icon_view, - const gchar *theme) +theme_gconf_changed (GConfClient *client, + guint conn_id, + GConfEntry *entry, + AppearanceData *data) { - GtkTreeIter iter; - GtkTreeModel *model = gtk_icon_view_get_model (icon_view); - - if (find_in_model (model, theme, COL_NAME, &iter)) { - GtkTreePath *path = gtk_tree_model_get_path (model, &iter); - gtk_icon_view_select_path (icon_view, path); - gtk_icon_view_scroll_to_path (icon_view, path, FALSE, 0.5, 0.0); - gtk_tree_path_free (path); - } + theme_details_changed_cb (data); } -static gboolean -theme_is_equal (const GnomeThemeMetaInfo *a, const GnomeThemeMetaInfo *b) +static void +theme_postinit (GtkIconView *icon_view, AppearanceData *data) { - if (!(a->gtk_theme_name && b->gtk_theme_name) || - strcmp (a->gtk_theme_name, b->gtk_theme_name)) - return FALSE; + /* connect to individual gconf changes; we only do that now to make sure + * we don't receive any signals before the widgets have been realized */ + gconf_client_add_dir (data->client, "/apps/metacity/general", GCONF_CLIENT_PRELOAD_NONE, NULL); + gconf_client_add_dir (data->client, "/desktop/gnome/interface", GCONF_CLIENT_PRELOAD_NONE, NULL); + gconf_client_notify_add (data->client, GTK_THEME_KEY, (GConfClientNotifyFunc) theme_gconf_changed, data, NULL, NULL); + gconf_client_notify_add (data->client, METACITY_THEME_KEY, (GConfClientNotifyFunc) theme_gconf_changed, data, NULL, NULL); + gconf_client_notify_add (data->client, ICON_THEME_KEY, (GConfClientNotifyFunc) theme_gconf_changed, data, NULL, NULL); - if (!(a->gtk_color_scheme && b->gtk_color_scheme) || - strcmp (a->gtk_color_scheme, b->gtk_color_scheme)) - return FALSE; - - if (!(a->icon_theme_name && b->icon_theme_name) || - strcmp (a->icon_theme_name, b->icon_theme_name)) - return FALSE; - - if (!(a->metacity_theme_name && b->metacity_theme_name) || - strcmp (a->metacity_theme_name, b->metacity_theme_name)) - return FALSE; - - return TRUE; + g_signal_connect (gtk_settings_get_default (), "notify::gtk-color-scheme", (GCallback) theme_color_scheme_changed_cb, data); } void @@ -435,7 +520,6 @@ themes_init (AppearanceData *data) GtkListStore *theme_store; GtkTreeModel *sort_model; GnomeThemeMetaInfo *meta_theme = NULL; - GdkPixbuf *temp; /* initialise some stuff */ gnome_theme_init (NULL); @@ -443,8 +527,9 @@ themes_init (AppearanceData *data) data->theme_queue = NULL; data->theme_custom = gnome_theme_meta_info_new (); + data->theme_icon = gdk_pixbuf_new_from_file (GNOMECC_PIXMAP_DIR "/theme-thumbnailing.png", NULL); data->theme_store = theme_store = - gtk_list_store_new (NUM_COLS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING); + gtk_list_store_new (NUM_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); del_button = glade_xml_get_widget (data->xml, "theme_delete"); @@ -453,10 +538,9 @@ themes_init (AppearanceData *data) gnome_theme_info_register_theme_change ((ThemeChangedCallback) theme_changed_on_disk_cb, data); data->theme_custom->name = g_strdup (CUSTOM_THEME_NAME); - data->theme_custom->readable_name = g_strdup ("Custom"); /* FIXME: translate */ + data->theme_custom->readable_name = g_strdup (_("Custom")); theme_load_from_gconf (data->client, data->theme_custom); - temp = gdk_pixbuf_new_from_file (GNOMECC_PIXMAP_DIR "/theme-thumbnailing.png", NULL); for (l = theme_list; l; l = l->next) { GnomeThemeMetaInfo *info = l->data; @@ -466,17 +550,15 @@ themes_init (AppearanceData *data) gtk_list_store_insert_with_values (theme_store, NULL, 0, COL_LABEL, info->readable_name, COL_NAME, info->name, - COL_THUMBNAIL, temp, + COL_THUMBNAIL, data->theme_icon, -1); if (!meta_theme && theme_is_equal (data->theme_custom, info)) meta_theme = info; } + g_list_free (theme_list); - if (meta_theme) { - gtk_widget_set_sensitive (del_button, - gnome_theme_is_writable (meta_theme, GNOME_THEME_TYPE_METATHEME)); - } else { + if (!meta_theme) { /* add custom theme */ meta_theme = data->theme_custom; data->theme_queue = g_slist_prepend (data->theme_queue, meta_theme); @@ -484,21 +566,18 @@ themes_init (AppearanceData *data) gtk_list_store_insert_with_values (theme_store, NULL, 0, COL_LABEL, meta_theme->readable_name, COL_NAME, meta_theme->name, - COL_THUMBNAIL, temp, + COL_THUMBNAIL, data->theme_icon, -1); } - if (temp) - g_object_unref (temp); - w = glade_xml_get_widget (data->xml, "theme_list"); - g_signal_connect (w, "selection-changed", (GCallback) theme_selection_changed_cb, data); gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (w), GTK_SELECTION_BROWSE); sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (theme_store)); gtk_icon_view_set_model (GTK_ICON_VIEW (w), GTK_TREE_MODEL (sort_model)); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), COL_LABEL, GTK_SORT_ASCENDING); - - g_signal_connect_after (w, "realize", (GCallback) theme_select_after_realize, meta_theme->name); + g_signal_connect (w, "selection-changed", (GCallback) theme_selection_changed_cb, data); + g_signal_connect_after (w, "realize", (GCallback) theme_select_name, meta_theme->name); + g_signal_connect_after (w, "realize", (GCallback) theme_postinit, data); w = glade_xml_get_widget (data->xml, "theme_install"); gtk_button_set_image (GTK_BUTTON (w), @@ -509,13 +588,6 @@ themes_init (AppearanceData *data) g_signal_connect (glade_xml_get_widget (data->xml, "theme_custom"), "clicked", (GCallback) theme_custom_cb, data); g_signal_connect (del_button, "clicked", (GCallback) theme_delete_cb, data); - /* connect list signals in the details window */ - g_signal_connect_after (glade_xml_get_widget (data->xml, "gtk_themes_list"), "cursor-changed", (GCallback) theme_details_changed_cb, data); - g_signal_connect_after (glade_xml_get_widget (data->xml, "window_themes_list"), "cursor-changed", (GCallback) theme_details_changed_cb, data); - g_signal_connect_after (glade_xml_get_widget (data->xml, "icon_themes_list"), "cursor-changed", (GCallback) theme_details_changed_cb, data); - - g_signal_connect (gtk_settings_get_default (), "notify::gtk-color-scheme", (GCallback) theme_color_scheme_changed_cb, data); - if (is_locked_down (data->client)) { /* FIXME: determine what needs disabling */ } @@ -528,4 +600,7 @@ themes_shutdown (AppearanceData *data) { gnome_theme_meta_info_free (data->theme_custom); g_slist_free (data->theme_queue); + + if (data->theme_icon) + g_object_unref (data->theme_icon); } diff --git a/capplets/appearance/appearance.glade b/capplets/appearance/appearance.glade index e0cb307d9..4534ac0a9 100644 --- a/capplets/appearance/appearance.glade +++ b/capplets/appearance/appearance.glade @@ -640,8 +640,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 - 0 + 0 + 1 12 12 @@ -670,6 +670,7 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-delete True + False 1 @@ -680,7 +681,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - C_ustom... + C_ustomize... True @@ -1860,6 +1861,7 @@ Text only GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-delete True + False 1 @@ -2180,6 +2182,7 @@ Text only GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-delete True + False 1 @@ -2258,6 +2261,7 @@ Text only GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-delete True + False 1 @@ -2336,7 +2340,8 @@ Text only GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-delete True - + False + 1 diff --git a/capplets/appearance/appearance.h b/capplets/appearance/appearance.h index 8cdb03c2d..94ca18847 100644 --- a/capplets/appearance/appearance.h +++ b/capplets/appearance/appearance.h @@ -55,4 +55,5 @@ typedef struct { GtkListStore *theme_store; GSList *theme_queue; GnomeThemeMetaInfo *theme_custom; + GdkPixbuf *theme_icon; } AppearanceData; diff --git a/capplets/appearance/theme-util.c b/capplets/appearance/theme-util.c new file mode 100644 index 000000000..22562cd5e --- /dev/null +++ b/capplets/appearance/theme-util.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2007 The GNOME Foundation + * Written by Thomas Wood + * Jens Granseuer + * All Rights Reserved + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "appearance.h" + +#include + +#include "theme-util.h" + +gboolean +theme_delete (const gchar *name, ThemeType type) +{ + GtkWidget *confirm_dialog; + gpointer theme; + gchar *theme_dir; + gint response; + GList *uri_list; + GnomeVFSResult result; + + confirm_dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_OK_CANCEL, + _("Would you like to remove this theme?")); + response = gtk_dialog_run (GTK_DIALOG (confirm_dialog)); + gtk_widget_destroy (confirm_dialog); + if (response == GTK_RESPONSE_CANCEL) + return FALSE; + + switch (type) { + case THEME_TYPE_GTK: + theme = gnome_theme_info_find (name); + theme_dir = g_build_filename (((GnomeThemeInfo *) theme)->path, "gtk-2.0", NULL); + break; + + case THEME_TYPE_ICON: + theme = gnome_theme_icon_info_find (name); + theme_dir = g_path_get_dirname (((GnomeThemeIconInfo *) theme)->path); + break; + + case THEME_TYPE_WINDOW: + theme = gnome_theme_info_find (name); + theme_dir = g_build_filename (((GnomeThemeInfo *) theme)->path, "metacity-1", NULL); + break; + + case THEME_TYPE_META: + theme = gnome_theme_meta_info_find (name); + theme_dir = g_strdup (((GnomeThemeMetaInfo *) theme)->path); + break; + + default: + return FALSE; + } + + uri_list = g_list_prepend (NULL, gnome_vfs_uri_new (theme_dir)); + g_free (theme_dir); + + result = gnome_vfs_xfer_delete_list (uri_list, + GNOME_VFS_XFER_ERROR_MODE_ABORT, + GNOME_VFS_XFER_RECURSIVE, + NULL, NULL); + + gnome_vfs_uri_list_free (uri_list); + + if (result != GNOME_VFS_OK) { + GtkWidget *info_dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Theme cannot be deleted")); + gtk_dialog_run (GTK_DIALOG (info_dialog)); + gtk_widget_destroy (info_dialog); + return FALSE; + } + + return TRUE; +} + +gboolean +theme_model_iter_last (GtkTreeModel *model, GtkTreeIter *iter) +{ + GtkTreeIter walk, prev; + gboolean valid; + + valid = gtk_tree_model_get_iter_first (model, &walk); + + if (valid) { + do { + prev = walk; + valid = gtk_tree_model_iter_next (model, &walk); + } while (valid); + + *iter = prev; + return TRUE; + } + return FALSE; +} diff --git a/capplets/appearance/theme-util.h b/capplets/appearance/theme-util.h new file mode 100644 index 000000000..f2ca9a490 --- /dev/null +++ b/capplets/appearance/theme-util.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2007 The GNOME Foundation + * Written by Jens Granseuer + * All Rights Reserved + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define GTK_THEME_KEY "/desktop/gnome/interface/gtk_theme" +#define METACITY_THEME_KEY "/apps/metacity/general/theme" +#define ICON_THEME_KEY "/desktop/gnome/interface/icon_theme" +#define COLOR_SCHEME_KEY "/desktop/gnome/interface/gtk_color_scheme" +#define CURSOR_THEME_KEY "/desktop/gnome/peripherals/mouse/cursor_theme" +#define LOCKDOWN_KEY "/desktop/gnome/lockdown/disable_theme_settings" + +enum { + COL_THUMBNAIL, + COL_LABEL, + COL_NAME, + NUM_COLS +}; + +typedef enum { + THEME_TYPE_GTK, + THEME_TYPE_WINDOW, + THEME_TYPE_ICON, + THEME_TYPE_META, + THEME_TYPE_CURSOR +} ThemeType; + +gboolean theme_delete (const gchar *name, ThemeType type); +gboolean theme_model_iter_last (GtkTreeModel *model, GtkTreeIter *iter);