[gnome-control-center/extensible-shell] [appearance] Port theme page code to the extension
- From: William Jon McCann <mccann src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-control-center/extensible-shell] [appearance] Port theme page code to the extension
- Date: Wed, 27 Jan 2010 00:46:43 +0000 (UTC)
commit e63e737f556de9d24bc8fb35391af7e9de58d1bc
Author: William Jon McCann <jmccann redhat com>
Date: Tue Jan 26 03:37:26 2010 -0500
[appearance] Port theme page code to the extension
capplets/appearance/Makefile.am | 26 +-
capplets/appearance/cc-appearance-panel.c | 60 +-
capplets/appearance/cc-background-page.c | 4 +
capplets/appearance/cc-theme-page.c | 1651 ++++++++++++++++++++++++++++
capplets/appearance/cc-theme-page.h | 55 +
capplets/appearance/cc-theme-save-dialog.c | 540 +++++++++
capplets/appearance/cc-theme-save-dialog.h | 62 +
capplets/appearance/data/appearance.ui | 2 +-
capplets/appearance/theme-util.c | 390 ++++----
capplets/appearance/theme-util.h | 17 +-
10 files changed, 2574 insertions(+), 233 deletions(-)
---
diff --git a/capplets/appearance/Makefile.am b/capplets/appearance/Makefile.am
index 514fd77..585ca34 100644
--- a/capplets/appearance/Makefile.am
+++ b/capplets/appearance/Makefile.am
@@ -33,22 +33,28 @@ libappearance_common_la_SOURCES = \
ccmodulesdir = $(EXTENSIONSDIR)
ccmodules_LTLIBRARIES = libappearance.la
-libappearance_la_SOURCES = \
- appearance-module.c \
- cc-backgrounds-monitor.h \
- cc-backgrounds-monitor.c \
- cc-background-item.h \
- cc-background-item.c \
- cc-background-page.h \
- cc-background-page.c \
- cc-appearance-panel.h \
- cc-appearance-panel.c
+libappearance_la_SOURCES = \
+ appearance-module.c \
+ cc-backgrounds-monitor.h \
+ cc-backgrounds-monitor.c \
+ cc-background-item.h \
+ cc-background-item.c \
+ cc-background-page.h \
+ cc-background-page.c \
+ cc-theme-save-dialog.h \
+ cc-theme-save-dialog.c \
+ cc-theme-page.h \
+ cc-theme-page.c \
+ cc-appearance-panel.h \
+ cc-appearance-panel.c \
+ $(NULL)
libappearance_la_LDFLAGS = \
$(EXTENSION_LIBTOOL_FLAGS) \
$(NULL)
libappearance_la_LIBADD = \
+ libappearance-common.la \
$(EXTENSION_LIBS) \
$(EXTENSION_COMMON_LIBS) \
$(NULL)
diff --git a/capplets/appearance/cc-appearance-panel.c b/capplets/appearance/cc-appearance-panel.c
index dece94f..2e8c716 100644
--- a/capplets/appearance/cc-appearance-panel.c
+++ b/capplets/appearance/cc-appearance-panel.c
@@ -30,19 +30,10 @@
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnomeui/gnome-desktop-thumbnail.h>
+#include "cc-theme-page.h"
#include "cc-background-page.h"
#include "cc-appearance-panel.h"
-#include "gconf-property-editor.h"
-#if 0
-#include "appearance-desktop.h"
-#include "appearance-font.h"
-#include "appearance-themes.h"
-#include "appearance-style.h"
-#endif
-#include "theme-installer.h"
-#include "theme-thumbnail.h"
-
#define CC_APPEARANCE_PANEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_APPEARANCE_PANEL, CcAppearancePanelPrivate))
#define WID(s) GTK_WIDGET (gtk_builder_get_object (builder, s))
@@ -50,6 +41,7 @@
struct CcAppearancePanelPrivate
{
GtkWidget *notebook;
+ CcPage *theme_page;
CcPage *background_page;
};
@@ -113,16 +105,48 @@ install_theme (CcAppearancePanel *panel,
#endif
static void
+on_notebook_switch_page (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ guint page_num,
+ CcAppearancePanel *panel)
+{
+ if (page_num == 0) {
+ g_object_set (panel,
+ "current-page",
+ panel->priv->theme_page,
+ NULL);
+ } else {
+ g_object_set (panel,
+ "current-page",
+ panel->priv->background_page,
+ NULL);
+ }
+}
+
+static void
setup_panel (CcAppearancePanel *panel)
{
GtkWidget *label;
char *display_name;
panel->priv->notebook = gtk_notebook_new ();
+ g_signal_connect (panel->priv->notebook,
+ "switch-page",
+ G_CALLBACK (on_notebook_switch_page),
+ panel);
+
gtk_container_add (GTK_CONTAINER (panel), panel->priv->notebook);
gtk_widget_show (panel->priv->notebook);
- /* FIXME: load pages */
+ panel->priv->theme_page = cc_theme_page_new ();
+ g_object_get (panel->priv->theme_page,
+ "display-name", &display_name,
+ NULL);
+ label = gtk_label_new (display_name);
+ g_free (display_name);
+ gtk_notebook_append_page (GTK_NOTEBOOK (panel->priv->notebook), GTK_WIDGET (panel->priv->theme_page), label);
+ gtk_widget_show (GTK_WIDGET (panel->priv->theme_page));
+
panel->priv->background_page = cc_background_page_new ();
g_object_get (panel->priv->background_page,
"display-name", &display_name,
@@ -133,7 +157,7 @@ setup_panel (CcAppearancePanel *panel)
gtk_widget_show (GTK_WIDGET (panel->priv->background_page));
g_object_set (panel,
- "current-page", panel->priv->background_page,
+ "current-page", panel->priv->theme_page,
NULL);
}
@@ -153,8 +177,6 @@ cc_appearance_panel_constructor (GType type,
"id", "gnome-appearance-properties.desktop",
NULL);
- //theme_thumbnail_factory_init (0, NULL);
-
setup_panel (appearance_panel);
return G_OBJECT (appearance_panel);
@@ -181,17 +203,7 @@ cc_appearance_panel_class_finalize (CcAppearancePanelClass *klass)
static void
cc_appearance_panel_init (CcAppearancePanel *panel)
{
- GConfClient *client;
-
panel->priv = CC_APPEARANCE_PANEL_GET_PRIVATE (panel);
-
- client = gconf_client_get_default ();
- gconf_client_add_dir (client,
- "/desktop/gnome/peripherals/appearance",
- GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
- gconf_client_add_dir (client, "/desktop/gnome/interface",
- GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
- g_object_unref (client);
}
static void
diff --git a/capplets/appearance/cc-background-page.c b/capplets/appearance/cc-background-page.c
index 54324fb..b76b38f 100644
--- a/capplets/appearance/cc-background-page.c
+++ b/capplets/appearance/cc-background-page.c
@@ -1818,6 +1818,10 @@ cc_background_page_finalize (GObject *object)
g_object_unref (page->priv->monitor);
}
+ if (page->priv->thumb_factory != NULL) {
+ g_object_unref (page->priv->thumb_factory);
+ }
+
G_OBJECT_CLASS (cc_background_page_parent_class)->finalize (object);
}
diff --git a/capplets/appearance/cc-theme-page.c b/capplets/appearance/cc-theme-page.c
new file mode 100644
index 0000000..c2d7dbc
--- /dev/null
+++ b/capplets/appearance/cc-theme-page.c
@@ -0,0 +1,1651 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+#include <gconf/gconf-client.h>
+
+#include "cc-theme-page.h"
+
+#include "gtkrc-utils.h"
+#include <libwindow-settings/gnome-wm-manager.h>
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnomeui/gnome-desktop-thumbnail.h>
+
+#include "theme-util.h"
+#include "gnome-theme-info.h"
+#include "theme-thumbnail.h"
+#include "gnome-theme-apply.h"
+#include "theme-installer.h"
+#include "cc-theme-save-dialog.h"
+
+#define CC_THEME_PAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_THEME_PAGE, CcThemePagePrivate))
+
+#define WID(s) GTK_WIDGET (gtk_builder_get_object (builder, s))
+#define CUSTOM_THEME_NAME "__custom__"
+
+#define APPEARANCE_KEY_DIR "/apps/control-center/appearance"
+#define MORE_THEMES_URL_KEY APPEARANCE_KEY_DIR "/more_themes_url"
+#define KEY_METACITY_GENERAL_DIR "/apps/metacity/general"
+#define KEY_GNOME_INTERFACE_DIR "/desktop/gnome/interface"
+
+enum {
+ RESPONSE_APPLY_BG,
+ RESPONSE_REVERT_FONT,
+ RESPONSE_APPLY_FONT,
+ RESPONSE_INSTALL_ENGINE
+};
+
+enum {
+ TARGET_URI_LIST,
+ TARGET_NS_URL
+};
+
+static const GtkTargetEntry drop_types[] = {
+ {"text/uri-list", 0, TARGET_URI_LIST},
+ {"_NETSCAPE_URL", 0, TARGET_NS_URL}
+};
+
+struct CcThemePagePrivate
+{
+ GtkWidget *icon_view;
+ GtkListStore *store;
+ GnomeThemeMetaInfo *custom_info;
+ GdkPixbuf *icon;
+ GtkWidget *save_dialog;
+ GtkWidget *list_vbox;
+ GtkWidget *info_bar;
+ GtkWidget *message_label;
+ GtkWidget *apply_background_button;
+ GtkWidget *revert_font_button;
+ GtkWidget *apply_font_button;
+ GtkWidget *install_button;
+ GtkWidget *delete_button;
+ GtkWidget *save_button;
+ GtkWidget *info_icon;
+ GtkWidget *error_icon;
+ GtkWidget *theme_details;
+ char *revert_application_font;
+ char *revert_documents_font;
+ char *revert_desktop_font;
+ char *revert_windowtitle_font;
+ char *revert_monospace_font;
+
+ GnomeDesktopThumbnailFactory *thumb_factory;
+};
+
+enum {
+ PROP_0,
+};
+
+static void cc_theme_page_class_init (CcThemePageClass *klass);
+static void cc_theme_page_init (CcThemePage *theme_page);
+static void cc_theme_page_finalize (GObject *object);
+
+G_DEFINE_TYPE (CcThemePage, cc_theme_page, CC_TYPE_PAGE)
+
+static void message_area_update (CcThemePage *page);
+
+static void
+cc_theme_page_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_theme_page_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static time_t
+get_mtime (const char *name)
+{
+ GnomeThemeMetaInfo *theme;
+ time_t mtime = -1;
+
+ theme = gnome_theme_meta_info_find (name);
+ if (theme != NULL) {
+ GFile *file;
+ GFileInfo *file_info;
+
+ file = g_file_new_for_path (theme->path);
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ g_object_unref (file);
+
+ if (file_info != NULL) {
+ mtime = g_file_info_get_attribute_uint64 (file_info,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED);
+ g_object_unref (file_info);
+ }
+ }
+
+ return mtime;
+}
+
+static void
+thumbnail_update (CcThemePage *page,
+ GdkPixbuf *pixbuf,
+ char *theme_name,
+ gboolean cache)
+{
+ GtkTreeIter iter;
+
+ /* find item in model and update thumbnail */
+ if (!pixbuf)
+ return;
+
+ if (theme_find_in_model (GTK_TREE_MODEL (page->priv->store), theme_name, &iter)) {
+ time_t mtime;
+
+ gtk_list_store_set (page->priv->store,
+ &iter,
+ COL_THUMBNAIL, pixbuf,
+ -1);
+
+ /* cache thumbnail */
+ if (cache && (mtime = get_mtime (theme_name)) != -1) {
+ gchar *path;
+
+ /* try to share thumbs with nautilus, use themes:/// */
+ path = g_strconcat ("themes:///", theme_name, NULL);
+
+ gnome_desktop_thumbnail_factory_save_thumbnail (page->priv->thumb_factory,
+ pixbuf,
+ path,
+ mtime);
+
+ g_free (path);
+ }
+ }
+}
+
+static GdkPixbuf *
+get_thumbnail_from_cache (CcThemePage *page,
+ GnomeThemeMetaInfo *info)
+{
+ GdkPixbuf *thumb = NULL;
+ char *path;
+ char *thumb_filename;
+ time_t mtime;
+
+ if (info == page->priv->custom_info)
+ return NULL;
+
+ mtime = get_mtime (info->name);
+ if (mtime == -1)
+ return NULL;
+
+ /* try to share thumbs with nautilus, use themes:/// */
+ path = g_strconcat ("themes:///", info->name, NULL);
+ thumb_filename = gnome_desktop_thumbnail_factory_lookup (page->priv->thumb_factory,
+ path,
+ mtime);
+ g_free (path);
+
+ if (thumb_filename != NULL) {
+ thumb = gdk_pixbuf_new_from_file (thumb_filename, NULL);
+ g_free (thumb_filename);
+ }
+
+ return thumb;
+}
+
+static void
+on_thumbnail_done (GdkPixbuf *pixbuf,
+ char *theme_name,
+ CcThemePage *page)
+{
+ thumbnail_update (page, pixbuf, theme_name, TRUE);
+}
+
+static void
+thumbnail_generate (CcThemePage *page,
+ GnomeThemeMetaInfo *info)
+{
+ GdkPixbuf *thumb;
+
+ thumb = get_thumbnail_from_cache (page, info);
+
+ if (thumb != NULL) {
+ thumbnail_update (page, thumb, info->name, FALSE);
+ g_object_unref (thumb);
+ } else {
+ generate_meta_theme_thumbnail_async (info,
+ (ThemeThumbnailFunc) on_thumbnail_done,
+ page,
+ NULL);
+ }
+}
+
+static void
+thumbnail_generate_iter (GnomeThemeMetaInfo *info,
+ CcThemePage *page)
+{
+ thumbnail_generate (page, info);
+}
+
+static void
+on_theme_changed_on_disk (GnomeThemeCommonInfo *theme,
+ GnomeThemeChangeType change_type,
+ GnomeThemeElement element_type,
+ CcThemePage *page)
+{
+ GnomeThemeMetaInfo *meta;
+
+ if (theme->type != GNOME_THEME_TYPE_METATHEME) {
+ return;
+ }
+ meta = (GnomeThemeMetaInfo *) theme;
+
+ if (change_type == GNOME_THEME_CHANGE_CREATED) {
+ gtk_list_store_insert_with_values (page->priv->store,
+ NULL,
+ 0,
+ COL_LABEL, meta->readable_name,
+ COL_NAME, meta->name,
+ COL_THUMBNAIL, page->priv->icon,
+ -1);
+ thumbnail_generate (page, meta);
+
+ } else if (change_type == GNOME_THEME_CHANGE_DELETED) {
+ GtkTreeIter iter;
+
+ if (theme_find_in_model (GTK_TREE_MODEL (page->priv->store), meta->name, &iter))
+ gtk_list_store_remove (page->priv->store, &iter);
+
+ } else if (change_type == GNOME_THEME_CHANGE_CHANGED) {
+ thumbnail_generate (page, meta);
+ }
+}
+
+/* Find out if the lockdown key has been set. Currently returns false on error... */
+static gboolean
+is_locked_down (GConfClient *client)
+{
+ return gconf_client_get_bool (client, LOCKDOWN_KEY, NULL);
+}
+
+static GnomeThemeMetaInfo *
+theme_load_from_gconf (GConfClient *client)
+{
+ GnomeThemeMetaInfo *theme;
+ char *scheme;
+
+ theme = gnome_theme_meta_info_new ();
+
+ theme->gtk_theme_name = gconf_client_get_string (client,
+ GTK_THEME_KEY,
+ NULL);
+ if (theme->gtk_theme_name == NULL)
+ theme->gtk_theme_name = g_strdup ("Clearlooks");
+
+ scheme = gconf_client_get_string (client,
+ COLOR_SCHEME_KEY,
+ NULL);
+ if (scheme == NULL || !strcmp (scheme, "")) {
+ g_free (scheme);
+ scheme = gtkrc_get_color_scheme_for_theme (theme->gtk_theme_name);
+ }
+ theme->gtk_color_scheme = scheme;
+
+ theme->metacity_theme_name = gconf_client_get_string (client,
+ METACITY_THEME_KEY,
+ NULL);
+ if (theme->metacity_theme_name == NULL)
+ theme->metacity_theme_name = g_strdup ("Clearlooks");
+
+ theme->icon_theme_name = gconf_client_get_string (client,
+ ICON_THEME_KEY,
+ NULL);
+ if (theme->icon_theme_name == NULL)
+ theme->icon_theme_name = g_strdup ("gnome");
+
+ theme->notification_theme_name = gconf_client_get_string (client,
+ NOTIFICATION_THEME_KEY,
+ NULL);
+
+ theme->cursor_theme_name = gconf_client_get_string (client,
+ CURSOR_THEME_KEY,
+ NULL);
+#ifdef HAVE_XCURSOR
+ theme->cursor_size = gconf_client_get_int (client,
+ CURSOR_SIZE_KEY,
+ NULL);
+#endif
+ if (theme->cursor_theme_name == NULL)
+ theme->cursor_theme_name = g_strdup ("default");
+
+ theme->application_font = gconf_client_get_string (client,
+ APPLICATION_FONT_KEY,
+ NULL);
+
+ return theme;
+}
+
+static gboolean
+theme_is_equal (const GnomeThemeMetaInfo *a,
+ const GnomeThemeMetaInfo *b)
+{
+ gboolean a_set;
+ gboolean b_set;
+
+ if (!(a->gtk_theme_name != NULL && b->gtk_theme_name != NULL)
+ || strcmp (a->gtk_theme_name, b->gtk_theme_name) != 0)
+ return FALSE;
+
+ if (!(a->icon_theme_name != NULL && b->icon_theme_name != NULL)
+ || strcmp (a->icon_theme_name, b->icon_theme_name) != 0)
+ return FALSE;
+
+ if (!(a->metacity_theme_name != NULL && b->metacity_theme_name != NULL)
+ || strcmp (a->metacity_theme_name, b->metacity_theme_name) != 0)
+ return FALSE;
+
+ if (!(a->cursor_theme_name != NULL && b->cursor_theme_name != NULL)
+ || strcmp (a->cursor_theme_name, b->cursor_theme_name) != 0)
+ return FALSE;
+
+ if (a->cursor_size != b->cursor_size)
+ return FALSE;
+
+ a_set = a->gtk_color_scheme && strcmp (a->gtk_color_scheme, "");
+ b_set = b->gtk_color_scheme && strcmp (b->gtk_color_scheme, "");
+ if ((a_set != b_set)
+ || (a_set
+ && !gnome_theme_color_scheme_equal (a->gtk_color_scheme, b->gtk_color_scheme)))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gint
+theme_list_sort_func (GnomeThemeMetaInfo *a,
+ GnomeThemeMetaInfo *b)
+{
+ return strcmp (a->readable_name, b->readable_name);
+}
+
+static gint
+theme_store_sort_func (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ CcThemePage *page)
+{
+ char *a_name;
+ char *a_label;
+ int rc;
+
+ gtk_tree_model_get (model, a, COL_NAME, &a_name, COL_LABEL, &a_label, -1);
+
+ if (strcmp (a_name, CUSTOM_THEME_NAME) == 0) {
+ rc = -1;
+ } else {
+ char *b_name;
+ char *b_label;
+
+ gtk_tree_model_get (model, b, COL_NAME, &b_name, COL_LABEL, &b_label, -1);
+
+ if (strcmp (b_name, CUSTOM_THEME_NAME) == 0) {
+ rc = 1;
+ } else {
+ char *a_case;
+ char *b_case;
+
+ a_case = g_utf8_casefold (a_label, -1);
+ b_case = g_utf8_casefold (b_label, -1);
+ rc = g_utf8_collate (a_case, b_case);
+ g_free (a_case);
+ g_free (b_case);
+ }
+
+ g_free (b_name);
+ g_free (b_label);
+ }
+
+ g_free (a_name);
+ g_free (a_label);
+
+ return rc;
+}
+
+static char *
+get_selected_theme_name (CcThemePage *page)
+{
+ char *name;
+ GList *selected;
+
+ name = NULL;
+ selected = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (page->priv->icon_view));
+
+ if (selected != NULL) {
+ GtkTreePath *path;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ path = selected->data;
+ model = gtk_icon_view_get_model (GTK_ICON_VIEW (page->priv->icon_view));
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ gtk_tree_model_get (model, &iter, COL_NAME, &name, -1);
+ }
+
+ g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (selected);
+ }
+
+ return name;
+}
+
+static const GnomeThemeMetaInfo *
+get_selected_theme (CcThemePage *page)
+{
+ GnomeThemeMetaInfo *theme = NULL;
+ char *name;
+
+ name = get_selected_theme_name (page);
+
+ if (name != NULL) {
+ if (strcmp (name, page->priv->custom_info->name) == 0) {
+ theme = page->priv->custom_info;
+ } else {
+ theme = gnome_theme_meta_info_find (name);
+ }
+
+ g_free (name);
+ }
+
+ return theme;
+}
+
+
+static void
+on_info_bar_response (GtkWidget *w,
+ int response_id,
+ CcThemePage *page)
+{
+ const GnomeThemeMetaInfo *theme;
+ char *tmpfont;
+ char *engine_path;
+ GConfClient *client;
+
+ theme = get_selected_theme (page);
+ if (theme == NULL)
+ return;
+
+ client = gconf_client_get_default ();
+
+ switch (response_id) {
+ case RESPONSE_APPLY_BG:
+ gconf_client_set_string (client,
+ BACKGROUND_KEY,
+ theme->background_image,
+ NULL);
+ break;
+
+ case RESPONSE_REVERT_FONT:
+ if (page->priv->revert_application_font != NULL) {
+ gconf_client_set_string (client,
+ APPLICATION_FONT_KEY,
+ page->priv->revert_application_font,
+ NULL);
+ g_free (page->priv->revert_application_font);
+ page->priv->revert_application_font = NULL;
+ }
+
+ if (page->priv->revert_documents_font != NULL) {
+ gconf_client_set_string (client,
+ DOCUMENTS_FONT_KEY,
+ page->priv->revert_documents_font,
+ NULL);
+ g_free (page->priv->revert_documents_font);
+ page->priv->revert_documents_font = NULL;
+ }
+
+ if (page->priv->revert_desktop_font != NULL) {
+ gconf_client_set_string (client,
+ DESKTOP_FONT_KEY,
+ page->priv->revert_desktop_font,
+ NULL);
+ g_free (page->priv->revert_desktop_font);
+ page->priv->revert_desktop_font = NULL;
+ }
+
+ if (page->priv->revert_windowtitle_font != NULL) {
+ gconf_client_set_string (client,
+ WINDOWTITLE_FONT_KEY,
+ page->priv->revert_windowtitle_font,
+ NULL);
+ g_free (page->priv->revert_windowtitle_font);
+ page->priv->revert_windowtitle_font = NULL;
+ }
+
+ if (page->priv->revert_monospace_font != NULL) {
+ gconf_client_set_string (client,
+ MONOSPACE_FONT_KEY,
+ page->priv->revert_monospace_font,
+ NULL);
+ g_free (page->priv->revert_monospace_font);
+ page->priv->revert_monospace_font = NULL;
+ }
+ break;
+
+ case RESPONSE_APPLY_FONT:
+ if (theme->application_font) {
+ tmpfont = gconf_client_get_string (client,
+ APPLICATION_FONT_KEY,
+ NULL);
+ if (tmpfont != NULL) {
+ g_free (page->priv->revert_application_font);
+
+ if (strcmp (theme->application_font, tmpfont) == 0) {
+ g_free (tmpfont);
+ page->priv->revert_application_font = NULL;
+ } else
+ page->priv->revert_application_font = tmpfont;
+ }
+ gconf_client_set_string (client,
+ APPLICATION_FONT_KEY,
+ theme->application_font,
+ NULL);
+ }
+
+ if (theme->documents_font) {
+ tmpfont = gconf_client_get_string (client,
+ DOCUMENTS_FONT_KEY,
+ NULL);
+ if (tmpfont != NULL) {
+ g_free (page->priv->revert_documents_font);
+
+ if (strcmp (theme->documents_font, tmpfont) == 0) {
+ g_free (tmpfont);
+ page->priv->revert_documents_font = NULL;
+ } else
+ page->priv->revert_documents_font = tmpfont;
+ }
+ gconf_client_set_string (client,
+ DOCUMENTS_FONT_KEY,
+ theme->documents_font,
+ NULL);
+ }
+
+ if (theme->desktop_font) {
+ tmpfont = gconf_client_get_string (client,
+ DESKTOP_FONT_KEY,
+ NULL);
+ if (tmpfont != NULL) {
+ g_free (page->priv->revert_desktop_font);
+
+ if (strcmp (theme->desktop_font, tmpfont) == 0) {
+ g_free (tmpfont);
+ page->priv->revert_desktop_font = NULL;
+ } else
+ page->priv->revert_desktop_font = tmpfont;
+ }
+ gconf_client_set_string (client,
+ DESKTOP_FONT_KEY,
+ theme->desktop_font,
+ NULL);
+ }
+
+ if (theme->windowtitle_font) {
+ tmpfont = gconf_client_get_string (client,
+ WINDOWTITLE_FONT_KEY,
+ NULL);
+ if (tmpfont != NULL) {
+ g_free (page->priv->revert_windowtitle_font);
+
+ if (strcmp (theme->windowtitle_font, tmpfont) == 0) {
+ g_free (tmpfont);
+ page->priv->revert_windowtitle_font = NULL;
+ } else
+ page->priv->revert_windowtitle_font = tmpfont;
+ }
+ gconf_client_set_string (client,
+ WINDOWTITLE_FONT_KEY,
+ theme->windowtitle_font,
+ NULL);
+ }
+
+ if (theme->monospace_font) {
+ tmpfont = gconf_client_get_string (client,
+ MONOSPACE_FONT_KEY,
+ NULL);
+ if (tmpfont != NULL) {
+ g_free (page->priv->revert_monospace_font);
+
+ if (strcmp (theme->monospace_font, tmpfont) == 0) {
+ g_free (tmpfont);
+ page->priv->revert_monospace_font = NULL;
+ } else
+ page->priv->revert_monospace_font = tmpfont;
+ }
+ gconf_client_set_string (client,
+ MONOSPACE_FONT_KEY,
+ theme->monospace_font, NULL);
+ }
+ break;
+
+ case RESPONSE_INSTALL_ENGINE:
+ engine_path = gtk_theme_info_missing_engine (theme->gtk_theme_name, FALSE);
+ if (engine_path != NULL) {
+ theme_install_file (GTK_WINDOW (gtk_widget_get_toplevel (page->priv->install_button)),
+ engine_path);
+ g_free (engine_path);
+ }
+
+ message_area_update (page);
+
+ break;
+ }
+
+ g_object_unref (client);
+}
+
+static void
+message_area_update (CcThemePage *page)
+{
+ const GnomeThemeMetaInfo *theme;
+ gboolean show_apply_background = FALSE;
+ gboolean show_apply_font = FALSE;
+ gboolean show_revert_font = FALSE;
+ gboolean show_error;
+ const char *message;
+ char *font;
+ GError *error = NULL;
+ GConfClient *client;
+
+ theme = get_selected_theme (page);
+
+ if (theme == NULL) {
+ if (page->priv->info_bar != NULL)
+ gtk_widget_hide (page->priv->info_bar);
+ return;
+ }
+
+ show_error = !gnome_theme_meta_info_validate (theme, &error);
+
+ client = gconf_client_get_default ();
+ if (!show_error) {
+ if (theme->background_image != NULL) {
+ char *background;
+
+ background = gconf_client_get_string (client, BACKGROUND_KEY, NULL);
+ show_apply_background =
+ (!background || strcmp (theme->background_image, background) != 0);
+ g_free (background);
+ }
+
+ if (theme->application_font) {
+ font = gconf_client_get_string (client, APPLICATION_FONT_KEY, NULL);
+ show_apply_font = (!font || strcmp (theme->application_font, font) != 0);
+ g_free (font);
+ }
+
+ if (!show_apply_font && theme->documents_font) {
+ font = gconf_client_get_string (client, DOCUMENTS_FONT_KEY, NULL);
+ show_apply_font = (!font || strcmp (theme->application_font, font) != 0);
+ g_free (font);
+ }
+
+ if (!show_apply_font && theme->desktop_font) {
+ font = gconf_client_get_string (client, DESKTOP_FONT_KEY, NULL);
+ show_apply_font = (!font || strcmp (theme->application_font, font) != 0);
+ g_free (font);
+ }
+
+ if (!show_apply_font && theme->windowtitle_font) {
+ font = gconf_client_get_string (client, WINDOWTITLE_FONT_KEY, NULL);
+ show_apply_font = (!font || strcmp (theme->application_font, font) != 0);
+ g_free (font);
+ }
+
+ if (!show_apply_font && theme->monospace_font) {
+ font = gconf_client_get_string (client, MONOSPACE_FONT_KEY, NULL);
+ show_apply_font = (!font || strcmp (theme->application_font, font) != 0);
+ g_free (font);
+ }
+
+ show_revert_font = (page->priv->revert_application_font != NULL
+ || page->priv->revert_documents_font != NULL
+ || page->priv->revert_desktop_font != NULL
+ || page->priv->revert_windowtitle_font != NULL
+ || page->priv->revert_monospace_font != NULL);
+ }
+ g_object_unref (client);
+
+ if (page->priv->info_bar == NULL) {
+ GtkWidget *hbox;
+
+ if (!show_apply_background
+ && !show_revert_font
+ && !show_apply_font
+ && !show_error)
+ return;
+
+ page->priv->info_bar = gtk_info_bar_new ();
+ gtk_widget_set_no_show_all (page->priv->info_bar, TRUE);
+
+ g_signal_connect (page->priv->info_bar,
+ "response",
+ (GCallback) on_info_bar_response,
+ page);
+
+ page->priv->apply_background_button = gtk_info_bar_add_button (GTK_INFO_BAR (page->priv->info_bar),
+ _("Apply Background"),
+ RESPONSE_APPLY_BG);
+ page->priv->apply_font_button = gtk_info_bar_add_button (GTK_INFO_BAR (page->priv->info_bar),
+ _("Apply Font"),
+ RESPONSE_APPLY_FONT);
+ page->priv->revert_font_button = gtk_info_bar_add_button (GTK_INFO_BAR (page->priv->info_bar),
+ _("Revert Font"),
+ RESPONSE_REVERT_FONT);
+ page->priv->install_button = gtk_info_bar_add_button (GTK_INFO_BAR (page->priv->info_bar),
+ _("Install"),
+ RESPONSE_INSTALL_ENGINE);
+
+ page->priv->message_label = gtk_label_new (NULL);
+ gtk_widget_show (page->priv->message_label);
+ gtk_label_set_line_wrap (GTK_LABEL (page->priv->message_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (page->priv->message_label), 0.0, 0.5);
+
+ hbox = gtk_info_bar_get_content_area (GTK_INFO_BAR (page->priv->info_bar));
+ page->priv->info_icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO,
+ GTK_ICON_SIZE_DIALOG);
+ page->priv->error_icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (page->priv->info_icon), 0.5, 0);
+ gtk_misc_set_alignment (GTK_MISC (page->priv->error_icon), 0.5, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), page->priv->info_icon, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), page->priv->error_icon, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), page->priv->message_label, TRUE, TRUE, 0);
+
+ gtk_box_pack_start (GTK_BOX (page->priv->list_vbox), page->priv->info_bar, FALSE, FALSE, 0);
+ }
+
+ if (show_error)
+ message = error->message;
+ else if (show_apply_background
+ && show_apply_font
+ && show_revert_font)
+ message = _("The current theme suggests a background and a font. Also, the last applied font suggestion can be reverted.");
+ else if (show_apply_background
+ && show_revert_font)
+ message = _("The current theme suggests a background. Also, the last applied font suggestion can be reverted.");
+ else if (show_apply_background
+ && show_apply_font)
+ message = _("The current theme suggests a background and a font.");
+ else if (show_apply_font
+ && show_revert_font)
+ message = _("The current theme suggests a font. Also, the last applied font suggestion can be reverted.");
+ else if (show_apply_background)
+ message = _("The current theme suggests a background.");
+ else if (show_revert_font)
+ message = _("The last applied font suggestion can be reverted.");
+ else if (show_apply_font)
+ message = _("The current theme suggests a font.");
+ else
+ message = NULL;
+
+ if (show_apply_background)
+ gtk_widget_show (page->priv->apply_background_button);
+ else
+ gtk_widget_hide (page->priv->apply_background_button);
+
+ if (show_apply_font)
+ gtk_widget_show (page->priv->apply_font_button);
+ else
+ gtk_widget_hide (page->priv->apply_font_button);
+
+ if (show_revert_font)
+ gtk_widget_show (page->priv->revert_font_button);
+ else
+ gtk_widget_hide (page->priv->revert_font_button);
+
+ if (show_error
+ && g_error_matches (error,
+ GNOME_THEME_ERROR,
+ GNOME_THEME_ERROR_GTK_ENGINE_NOT_AVAILABLE)
+ && packagekit_available ())
+ gtk_widget_show (page->priv->install_button);
+ else
+ gtk_widget_hide (page->priv->install_button);
+
+ if (show_error
+ || show_apply_background
+ || show_apply_font
+ || show_revert_font) {
+ gtk_widget_show (page->priv->info_bar);
+ gtk_widget_queue_draw (page->priv->info_bar);
+
+ if (show_error) {
+ gtk_widget_show (page->priv->error_icon);
+ gtk_widget_hide (page->priv->info_icon);
+ } else {
+ gtk_widget_show (page->priv->info_icon);
+ gtk_widget_hide (page->priv->error_icon);
+ }
+ } else {
+ gtk_widget_hide (page->priv->info_bar);
+ }
+
+ gtk_label_set_text (GTK_LABEL (page->priv->message_label), message);
+ g_clear_error (&error);
+}
+
+static void
+on_theme_selection_changed (GtkWidget *icon_view,
+ CcThemePage *page)
+{
+ GList *selection;
+ GnomeThemeMetaInfo *theme = NULL;
+ gboolean is_custom = FALSE;
+
+ selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (icon_view));
+
+ if (selection != NULL) {
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ char *name;
+
+ model = gtk_icon_view_get_model (GTK_ICON_VIEW (icon_view));
+ gtk_tree_model_get_iter (model, &iter, selection->data);
+ gtk_tree_model_get (model, &iter, COL_NAME, &name, -1);
+
+ is_custom = (strcmp (name, CUSTOM_THEME_NAME) == 0);
+
+ if (is_custom) {
+ theme = page->priv->custom_info;
+ } else {
+ theme = gnome_theme_meta_info_find (name);
+ }
+
+ if (theme) {
+ gnome_meta_theme_set (theme);
+ message_area_update (page);
+ }
+
+ g_free (name);
+ g_list_foreach (selection, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (selection);
+ }
+
+ gtk_widget_set_sensitive (page->priv->delete_button,
+ theme_is_writable (theme));
+ gtk_widget_set_sensitive (page->priv->save_button,
+ is_custom);
+}
+
+static void
+select_iter (CcThemePage *page,
+ GtkTreeIter *iter)
+{
+ GtkTreePath *path;
+ GtkIconView *icon_view;
+
+ icon_view = GTK_ICON_VIEW (page->priv->icon_view);
+ 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
+select_name (CcThemePage *page,
+ const char *theme)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ model = gtk_icon_view_get_model (GTK_ICON_VIEW (page->priv->icon_view));
+
+ if (theme_find_in_model (model, theme, &iter))
+ select_iter (page, &iter);
+}
+
+static void
+load_model (CcThemePage *page)
+{
+ GList *theme_list;
+ GList *l;
+ GnomeThemeMetaInfo *meta_theme;
+
+ /* set up theme list */
+ theme_list = gnome_theme_meta_info_find_all ();
+ gnome_theme_info_register_theme_change ((ThemeChangedCallback) on_theme_changed_on_disk,
+ page);
+ for (l = theme_list; l; l = l->next) {
+ GnomeThemeMetaInfo *info = l->data;
+
+ gtk_list_store_insert_with_values (page->priv->store,
+ NULL,
+ 0,
+ COL_LABEL, info->readable_name,
+ COL_NAME, info->name,
+ COL_THUMBNAIL, page->priv->icon,
+ -1);
+
+ if (meta_theme == NULL
+ && theme_is_equal (page->priv->custom_info, info))
+ meta_theme = info;
+ }
+
+ if (meta_theme == NULL) {
+ /* add custom theme */
+ meta_theme = page->priv->custom_info;
+
+ gtk_list_store_insert_with_values (page->priv->store,
+ NULL,
+ 0,
+ COL_LABEL, meta_theme->readable_name,
+ COL_NAME, meta_theme->name,
+ COL_THUMBNAIL, page->priv->icon,
+ -1);
+
+ thumbnail_generate (page, meta_theme);
+ }
+
+ select_name (page, meta_theme->name);
+
+ theme_list = g_list_sort (theme_list, (GCompareFunc) theme_list_sort_func);
+
+ g_list_foreach (theme_list, (GFunc) thumbnail_generate_iter, page);
+ g_list_free (theme_list);
+}
+
+
+static void
+on_theme_custom_clicked (GtkWidget *button,
+ CcThemePage *page)
+{
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (page));
+ if (!GTK_WIDGET_TOPLEVEL (toplevel)) {
+ toplevel = NULL;
+ }
+
+ gtk_window_set_transient_for (GTK_WINDOW (page->priv->theme_details),
+ GTK_WINDOW (toplevel));
+ gtk_widget_show_all (page->priv->theme_details);
+}
+
+static void
+on_theme_save_clicked (GtkWidget *button,
+ CcThemePage *page)
+{
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (page));
+ if (!GTK_WIDGET_TOPLEVEL (toplevel)) {
+ toplevel = NULL;
+ }
+
+ cc_theme_save_dialog_set_theme_info (CC_THEME_SAVE_DIALOG (page->priv->save_dialog),
+ page->priv->custom_info);
+
+ gtk_window_set_transient_for (GTK_WINDOW (page->priv->save_dialog),
+ GTK_WINDOW (toplevel));
+ gtk_widget_show_all (page->priv->save_dialog);
+}
+
+static void
+on_theme_install_clicked (GtkWidget *button,
+ CcThemePage *page)
+{
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (page));
+ if (!GTK_WIDGET_TOPLEVEL (toplevel)) {
+ toplevel = NULL;
+ }
+
+ gnome_theme_installer_run (GTK_WINDOW (toplevel), NULL);
+}
+
+static void
+on_theme_delete_clicked (GtkWidget *button,
+ CcThemePage *page)
+
+{
+ GList *selected;
+ GtkTreePath *path;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ char *name = NULL;
+
+ selected = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (page->priv->icon_view));
+
+ if (selected == NULL) {
+ return;
+ }
+
+ path = selected->data;
+ model = gtk_icon_view_get_model (GTK_ICON_VIEW (page->priv->icon_view));
+
+ if (gtk_tree_model_get_iter (model, &iter, path))
+ gtk_tree_model_get (model, &iter, COL_NAME, &name, -1);
+
+ if (name != NULL
+ && strcmp (name, page->priv->custom_info->name) != 0
+ && 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)) {
+ select_iter (page, &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 (page->priv->store, &child);
+ }
+
+ g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (selected);
+ g_free (name);
+}
+
+static void
+on_theme_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ CcThemePage *page)
+{
+ char **uris;
+ GtkWidget *toplevel;
+
+ if (!(info == TARGET_URI_LIST || info == TARGET_NS_URL))
+ return;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (page));
+ if (!GTK_WIDGET_TOPLEVEL (toplevel)) {
+ toplevel = NULL;
+ }
+
+ uris = g_uri_list_extract_uris ((char *) selection_data->data);
+
+ if (uris != NULL && uris[0] != NULL) {
+ GFile *f;
+ f = g_file_new_for_uri (uris[0]);
+ gnome_theme_install (f, GTK_WINDOW (toplevel));
+ g_object_unref (f);
+ }
+
+ g_strfreev (uris);
+}
+
+static char *
+get_default_string_from_key (GConfClient *client,
+ const char *key)
+{
+ GConfValue *value;
+ char *str = NULL;
+
+ value = gconf_client_get_default_from_schema (client, key, NULL);
+
+ if (value) {
+ if (value->type == GCONF_VALUE_STRING)
+ str = gconf_value_to_string (value);
+ gconf_value_free (value);
+ }
+
+ return str;
+}
+
+static void
+set_custom_from_theme (CcThemePage *page,
+ const GnomeThemeMetaInfo *info)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GConfClient *client;
+
+ if (info == page->priv->custom_info)
+ return;
+
+ client = gconf_client_get_default ();
+
+ /* if info is not NULL, we'll copy those theme settings over */
+ if (info != NULL) {
+ g_free (page->priv->custom_info->gtk_theme_name);
+ g_free (page->priv->custom_info->icon_theme_name);
+ g_free (page->priv->custom_info->metacity_theme_name);
+ g_free (page->priv->custom_info->gtk_color_scheme);
+ g_free (page->priv->custom_info->cursor_theme_name);
+ g_free (page->priv->custom_info->application_font);
+ page->priv->custom_info->gtk_color_scheme = NULL;
+ page->priv->custom_info->application_font = NULL;
+
+ /* these settings are guaranteed to be non-NULL */
+ page->priv->custom_info->gtk_theme_name = g_strdup (info->gtk_theme_name);
+ page->priv->custom_info->icon_theme_name = g_strdup (info->icon_theme_name);
+ page->priv->custom_info->metacity_theme_name = g_strdup (info->metacity_theme_name);
+ page->priv->custom_info->cursor_theme_name = g_strdup (info->cursor_theme_name);
+ page->priv->custom_info->cursor_size = info->cursor_size;
+
+ /* these can be NULL */
+ if (info->gtk_color_scheme)
+ page->priv->custom_info->gtk_color_scheme = g_strdup (info->gtk_color_scheme);
+ else
+ page->priv->custom_info->gtk_color_scheme = get_default_string_from_key (client, COLOR_SCHEME_KEY);
+
+ if (info->application_font)
+ page->priv->custom_info->application_font = g_strdup (info->application_font);
+ else
+ page->priv->custom_info->application_font = get_default_string_from_key (client, APPLICATION_FONT_KEY);
+ }
+
+ /* select the custom theme */
+ model = gtk_icon_view_get_model (GTK_ICON_VIEW (page->priv->icon_view));
+ if (!theme_find_in_model (model, page->priv->custom_info->name, &iter)) {
+ GtkTreeIter child;
+
+ gtk_list_store_insert_with_values (page->priv->store,
+ &child,
+ 0,
+ COL_LABEL, page->priv->custom_info->readable_name,
+ COL_NAME, page->priv->custom_info->name,
+ COL_THUMBNAIL, page->priv->icon,
+ -1);
+ gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (model),
+ &iter,
+ &child);
+ }
+
+ path = gtk_tree_model_get_path (model, &iter);
+ gtk_icon_view_select_path (GTK_ICON_VIEW (page->priv->icon_view), path);
+ gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (page->priv->icon_view), path, FALSE, 0.5, 0.0);
+ gtk_tree_path_free (path);
+
+ /* update the theme thumbnail */
+ thumbnail_generate (page, page->priv->custom_info);
+
+ g_object_unref (client);
+}
+
+static void
+theme_details_changed (CcThemePage *page)
+{
+ GnomeThemeMetaInfo *gconf_theme;
+ const GnomeThemeMetaInfo *selected;
+ gboolean done = FALSE;
+ GConfClient *client;
+
+ client = gconf_client_get_default ();
+
+ /* load new state from gconf */
+ gconf_theme = theme_load_from_gconf (client);
+
+ /* check if it's our currently selected theme */
+ selected = get_selected_theme (page);
+
+ if (!selected || !(done = theme_is_equal (selected, gconf_theme))) {
+ /* look for a matching metatheme */
+ GList *theme_list;
+ GList *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)) {
+ select_name (page, info->name);
+ done = TRUE;
+ break;
+ }
+ }
+ g_list_free (theme_list);
+ }
+
+ if (!done) {
+ /* didn't find a match, set or update custom */
+ set_custom_from_theme (page, gconf_theme);
+ }
+
+ gnome_theme_meta_info_free (gconf_theme);
+ g_object_unref (client);
+}
+
+static void
+on_theme_setting_changed (GObject *settings,
+ GParamSpec *pspec,
+ CcThemePage *page)
+{
+ theme_details_changed (page);
+}
+
+static void
+on_theme_gconf_changed (GConfClient *client,
+ guint conn_id,
+ GConfEntry *entry,
+ CcThemePage *page)
+{
+ theme_details_changed (page);
+}
+
+static void
+on_background_or_font_changed (GConfEngine *conf,
+ guint cnxn_id,
+ GConfEntry *entry,
+ CcThemePage *page)
+{
+ message_area_update (page);
+}
+
+
+static void
+setup_page (CcThemePage *page)
+{
+ GtkBuilder *builder;
+ GtkWidget *widget;
+ GError *error;
+ GtkWidget *w;
+ GtkTreeModel *sort_model;
+ GtkCellRenderer *renderer;
+ GtkSettings *settings;
+ char *url;
+ GConfClient *client;
+
+ client = gconf_client_get_default ();
+
+ builder = gtk_builder_new ();
+
+ error = NULL;
+ gtk_builder_add_from_file (builder,
+ GNOMECC_UI_DIR
+ "/appearance.ui",
+ &error);
+ if (error != NULL) {
+ g_error (_("Could not load user interface file: %s"),
+ error->message);
+ g_error_free (error);
+ return;
+ }
+
+
+ /* initialize some stuff */
+ gnome_theme_init ();
+ gnome_wm_manager_init ();
+
+ page->priv->custom_info = gnome_theme_meta_info_new ();
+ page->priv->icon = gdk_pixbuf_new_from_file (GNOMECC_PIXMAP_DIR "/theme-thumbnailing.png", NULL);
+ page->priv->store = gtk_list_store_new (NUM_COLS,
+ GDK_TYPE_PIXBUF,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+
+ page->priv->icon_view = WID ("theme_list");
+ page->priv->list_vbox = WID ("theme_list_vbox");
+ page->priv->theme_details = WID ("theme_details");
+ page->priv->save_dialog = cc_theme_save_dialog_new ();
+
+ page->priv->custom_info = theme_load_from_gconf (client);
+ page->priv->custom_info->name = g_strdup (CUSTOM_THEME_NAME);
+ page->priv->custom_info->readable_name = g_strdup_printf ("<i>%s</i>", _("Custom"));
+
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer,
+ "xpad", 5,
+ "ypad", 5,
+ "xalign", 0.5,
+ "yalign", 1.0,
+ NULL);
+ gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (page->priv->icon_view),
+ renderer,
+ FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (page->priv->icon_view),
+ renderer,
+ "pixbuf",
+ COL_THUMBNAIL,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer,
+ "alignment", PANGO_ALIGN_CENTER,
+ "wrap-mode", PANGO_WRAP_WORD_CHAR,
+ "wrap-width", gtk_icon_view_get_item_width (GTK_ICON_VIEW (page->priv->icon_view)),
+ "width", gtk_icon_view_get_item_width (GTK_ICON_VIEW (page->priv->icon_view)),
+ "xalign", 0.0,
+ "yalign", 0.0,
+ NULL);
+ gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (page->priv->icon_view), renderer, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (page->priv->icon_view),
+ renderer,
+ "markup", COL_LABEL,
+ NULL);
+
+ sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (page->priv->store));
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sort_model),
+ COL_LABEL,
+ (GtkTreeIterCompareFunc) theme_store_sort_func,
+ page,
+ NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
+ COL_LABEL,
+ GTK_SORT_ASCENDING);
+ gtk_icon_view_set_model (GTK_ICON_VIEW (page->priv->icon_view),
+ GTK_TREE_MODEL (sort_model));
+
+ g_signal_connect (page->priv->icon_view,
+ "selection-changed",
+ (GCallback) on_theme_selection_changed,
+ page);
+
+ w = WID ("theme_install");
+ gtk_button_set_image (GTK_BUTTON (w),
+ gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (w,
+ "clicked",
+ (GCallback) on_theme_install_clicked,
+ page);
+
+ page->priv->save_button = WID ("theme_save");
+ gtk_button_set_image (GTK_BUTTON (page->priv->save_button),
+ gtk_image_new_from_stock (GTK_STOCK_SAVE_AS,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (page->priv->save_button,
+ "clicked",
+ (GCallback) on_theme_save_clicked,
+ page);
+
+ w = WID ("theme_custom");
+ gtk_button_set_image (GTK_BUTTON (w),
+ gtk_image_new_from_stock (GTK_STOCK_EDIT,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (w,
+ "clicked",
+ (GCallback) on_theme_custom_clicked,
+ page);
+
+ page->priv->delete_button = WID ("theme_delete");
+ g_signal_connect (page->priv->delete_button,
+ "clicked",
+ (GCallback) on_theme_delete_clicked,
+ page);
+
+ w = WID ("theme_vbox");
+ gtk_drag_dest_set (w,
+ GTK_DEST_DEFAULT_ALL,
+ drop_types,
+ G_N_ELEMENTS (drop_types),
+ GDK_ACTION_COPY
+ | GDK_ACTION_LINK
+ | GDK_ACTION_MOVE);
+ g_signal_connect (w,
+ "drag-data-received",
+ (GCallback) on_theme_drag_data_received,
+ page);
+ if (is_locked_down (client))
+ gtk_widget_set_sensitive (w, FALSE);
+
+ w = WID ("more_themes_linkbutton");
+ url = gconf_client_get_string (client,
+ MORE_THEMES_URL_KEY,
+ NULL);
+ if (url != NULL && url[0] != '\0') {
+ gtk_link_button_set_uri (GTK_LINK_BUTTON (w), url);
+ gtk_widget_show (w);
+ } else {
+ gtk_widget_hide (w);
+ }
+ g_free (url);
+
+ /* listen to gconf changes, too */
+ gconf_client_add_dir (client,
+ KEY_METACITY_GENERAL_DIR,
+ GCONF_CLIENT_PRELOAD_NONE,
+ NULL);
+ gconf_client_add_dir (client,
+ KEY_GNOME_INTERFACE_DIR,
+ GCONF_CLIENT_PRELOAD_NONE,
+ NULL);
+ gconf_client_notify_add (client,
+ METACITY_THEME_KEY,
+ (GConfClientNotifyFunc) on_theme_gconf_changed,
+ page,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ CURSOR_THEME_KEY,
+ (GConfClientNotifyFunc) on_theme_gconf_changed,
+ page,
+ NULL,
+ NULL);
+#ifdef HAVE_XCURSOR
+ gconf_client_notify_add (client,
+ CURSOR_SIZE_KEY,
+ (GConfClientNotifyFunc) on_theme_gconf_changed,
+ page,
+ NULL,
+ NULL);
+#endif
+ gconf_client_notify_add (client,
+ BACKGROUND_KEY,
+ (GConfClientNotifyFunc) on_background_or_font_changed,
+ page,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ APPLICATION_FONT_KEY,
+ (GConfClientNotifyFunc) on_background_or_font_changed,
+ page,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ DOCUMENTS_FONT_KEY,
+ (GConfClientNotifyFunc) on_background_or_font_changed,
+ page,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ DESKTOP_FONT_KEY,
+ (GConfClientNotifyFunc) on_background_or_font_changed,
+ page,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ WINDOWTITLE_FONT_KEY,
+ (GConfClientNotifyFunc) on_background_or_font_changed,
+ page,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ MONOSPACE_FONT_KEY,
+ (GConfClientNotifyFunc) on_background_or_font_changed,
+ page,
+ NULL,
+ NULL);
+
+ settings = gtk_settings_get_default ();
+ g_signal_connect (settings,
+ "notify::gtk-color-scheme",
+ (GCallback) on_theme_setting_changed,
+ page);
+ g_signal_connect (settings,
+ "notify::gtk-theme-name",
+ (GCallback) on_theme_setting_changed,
+ page);
+ g_signal_connect (settings,
+ "notify::gtk-icon-theme-name",
+ (GCallback) on_theme_setting_changed,
+ page);
+
+
+ widget = WID ("theme_vbox");
+ gtk_widget_reparent (widget, GTK_WIDGET (page));
+ gtk_widget_show (widget);
+
+ g_object_unref (client);
+ g_object_unref (builder);
+}
+
+static GObject *
+cc_theme_page_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ CcThemePage *theme_page;
+
+ theme_page = CC_THEME_PAGE (G_OBJECT_CLASS (cc_theme_page_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ g_object_set (theme_page,
+ "display-name", _("Theme"),
+ "id", "theme",
+ NULL);
+
+ setup_page (theme_page);
+
+ return G_OBJECT (theme_page);
+}
+
+static void
+start_working (CcThemePage *page)
+{
+ static gboolean once = FALSE;
+
+ if (!once) {
+ load_model (page);
+ once = TRUE;
+ }
+}
+
+static void
+stop_working (CcThemePage *page)
+{
+
+}
+
+static void
+cc_theme_page_active_changed (CcPage *base_page,
+ gboolean is_active)
+{
+ CcThemePage *page = CC_THEME_PAGE (base_page);
+
+ if (is_active)
+ start_working (page);
+ else
+ stop_working (page);
+
+ CC_PAGE_CLASS (cc_theme_page_parent_class)->active_changed (base_page, is_active);
+
+}
+
+static void
+cc_theme_page_class_init (CcThemePageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPageClass *page_class = CC_PAGE_CLASS (klass);
+
+ object_class->get_property = cc_theme_page_get_property;
+ object_class->set_property = cc_theme_page_set_property;
+ object_class->constructor = cc_theme_page_constructor;
+ object_class->finalize = cc_theme_page_finalize;
+
+ page_class->active_changed = cc_theme_page_active_changed;
+
+ g_type_class_add_private (klass, sizeof (CcThemePagePrivate));
+}
+
+static void
+cc_theme_page_init (CcThemePage *page)
+{
+ page->priv = CC_THEME_PAGE_GET_PRIVATE (page);
+
+ page->priv->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
+
+}
+
+static void
+cc_theme_page_finalize (GObject *object)
+{
+ CcThemePage *page;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CC_IS_THEME_PAGE (object));
+
+ page = CC_THEME_PAGE (object);
+
+ g_return_if_fail (page->priv != NULL);
+
+ gnome_theme_meta_info_free (page->priv->custom_info);
+
+ if (page->priv->icon != NULL)
+ g_object_unref (page->priv->icon);
+ if (page->priv->save_dialog != NULL)
+ gtk_widget_destroy (page->priv->save_dialog);
+
+ g_free (page->priv->revert_application_font);
+ g_free (page->priv->revert_documents_font);
+ g_free (page->priv->revert_desktop_font);
+ g_free (page->priv->revert_windowtitle_font);
+ g_free (page->priv->revert_monospace_font);
+
+ if (page->priv->thumb_factory != NULL) {
+ g_object_unref (page->priv->thumb_factory);
+ }
+
+ G_OBJECT_CLASS (cc_theme_page_parent_class)->finalize (object);
+}
+
+CcPage *
+cc_theme_page_new (void)
+{
+ GObject *object;
+
+ object = g_object_new (CC_TYPE_THEME_PAGE, NULL);
+
+ return CC_PAGE (object);
+}
diff --git a/capplets/appearance/cc-theme-page.h b/capplets/appearance/cc-theme-page.h
new file mode 100644
index 0000000..fb31246
--- /dev/null
+++ b/capplets/appearance/cc-theme-page.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __CC_THEME_PAGE_H
+#define __CC_THEME_PAGE_H
+
+#include <gtk/gtk.h>
+#include "cc-page.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_THEME_PAGE (cc_theme_page_get_type ())
+#define CC_THEME_PAGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CC_TYPE_THEME_PAGE, CcThemePage))
+#define CC_THEME_PAGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CC_TYPE_THEME_PAGE, CcThemePageClass))
+#define CC_IS_THEME_PAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CC_TYPE_THEME_PAGE))
+#define CC_IS_THEME_PAGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CC_TYPE_THEME_PAGE))
+#define CC_THEME_PAGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CC_TYPE_THEME_PAGE, CcThemePageClass))
+
+typedef struct CcThemePagePrivate CcThemePagePrivate;
+
+typedef struct
+{
+ CcPage parent;
+ CcThemePagePrivate *priv;
+} CcThemePage;
+
+typedef struct
+{
+ CcPageClass parent_class;
+} CcThemePageClass;
+
+GType cc_theme_page_get_type (void);
+
+CcPage * cc_theme_page_new (void);
+
+G_END_DECLS
+
+#endif /* __CC_THEME_PAGE_H */
diff --git a/capplets/appearance/cc-theme-save-dialog.c b/capplets/appearance/cc-theme-save-dialog.c
new file mode 100644
index 0000000..c7af236
--- /dev/null
+++ b/capplets/appearance/cc-theme-save-dialog.c
@@ -0,0 +1,540 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 William Jon McCann
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glib/gstdio.h>
+#include <gconf/gconf-client.h>
+
+#include "cc-theme-save-dialog.h"
+
+#define CC_THEME_SAVE_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_THEME_SAVE_DIALOG, CcThemeSaveDialogPrivate))
+
+#define WID(s) GTK_WIDGET (gtk_builder_get_object (builder, s))
+#define BACKGROUND_KEY "/desktop/gnome/background/picture_filename"
+
+struct CcThemeSaveDialogPrivate
+{
+ GtkWidget *entry;
+ GtkWidget *text_view;
+ GtkWidget *save_button;
+ GtkWidget *save_background_checkbutton;
+ GnomeThemeMetaInfo *info;
+};
+
+enum {
+ PROP_0,
+};
+
+static void cc_theme_save_dialog_class_init (CcThemeSaveDialogClass *klass);
+static void cc_theme_save_dialog_init (CcThemeSaveDialog *theme_save_dialog);
+static void cc_theme_save_dialog_finalize (GObject *object);
+
+G_DEFINE_TYPE (CcThemeSaveDialog, cc_theme_save_dialog, GTK_TYPE_DIALOG)
+
+enum {
+ INVALID_THEME_NAME
+};
+
+GQuark
+cc_theme_save_dialog_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (error_quark == 0)
+ error_quark = g_quark_from_static_string ("cc-theme-save-dialog");
+
+ return error_quark;
+}
+
+void
+cc_theme_save_dialog_set_theme_info (CcThemeSaveDialog *dialog,
+ GnomeThemeMetaInfo *info)
+{
+ g_return_if_fail (CC_IS_THEME_SAVE_DIALOG (dialog));
+ dialog->priv->info = info;
+}
+
+static void
+cc_theme_save_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CcThemeSaveDialog *self;
+
+ self = CC_THEME_SAVE_DIALOG (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+cc_theme_save_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/* taken from gnome-desktop-item.c */
+static gchar *
+escape_string_and_dup (const char *s)
+{
+ char *return_value, *p;
+ const char *q;
+ int len = 0;
+
+ if (s == NULL)
+ return g_strdup("");
+
+ q = s;
+ while (*q) {
+ len++;
+ if (strchr ("\n\r\t\\", *q) != NULL)
+ len++;
+ q++;
+ }
+ return_value = p = (char *) g_malloc (len + 1);
+ do {
+ switch (*s) {
+ case '\t':
+ *p++ = '\\';
+ *p++ = 't';
+ break;
+ case '\n':
+ *p++ = '\\';
+ *p++ = 'n';
+ break;
+ case '\r':
+ *p++ = '\\';
+ *p++ = 'r';
+ break;
+ case '\\':
+ *p++ = '\\';
+ *p++ = '\\';
+ break;
+ default:
+ *p++ = *s;
+ }
+ }
+ while (*s++);
+ return return_value;
+}
+
+static gboolean
+check_theme_name (const char *theme_name,
+ GError **error)
+{
+ if (theme_name == NULL) {
+ g_set_error (error,
+ CC_THEME_SAVE_DIALOG_ERROR,
+ INVALID_THEME_NAME,
+ _("Theme name must be present"));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static char *
+str_remove_slash (const char *src)
+{
+ const char *i;
+ char *rtn;
+ gint len = 0;
+ i = src;
+
+ while (*i) {
+ if (*i != '/')
+ len++;
+ i++;
+ }
+
+ rtn = (char *) g_malloc (len + 1);
+ while (*src) {
+ if (*src != '/') {
+ *rtn = *src;
+ rtn++;
+ }
+ src++;
+ }
+ *rtn = '\0';
+ return rtn - len;
+}
+
+static gboolean
+setup_directory_structure (CcThemeSaveDialog *dialog,
+ const char *theme_name,
+ GError **error)
+{
+ char *dir;
+ char *theme_name_dir;
+ gboolean retval = TRUE;
+
+ theme_name_dir = str_remove_slash (theme_name);
+
+ dir = g_build_filename (g_get_home_dir (), ".themes", NULL);
+ if (!g_file_test (dir, G_FILE_TEST_EXISTS))
+ g_mkdir (dir, 0775);
+ g_free (dir);
+
+ dir = g_build_filename (g_get_home_dir (), ".themes", theme_name_dir, NULL);
+ if (!g_file_test (dir, G_FILE_TEST_EXISTS))
+ g_mkdir (dir, 0775);
+ g_free (dir);
+
+ dir = g_build_filename (g_get_home_dir (), ".themes", theme_name_dir, "index.theme", NULL);
+ g_free (theme_name_dir);
+
+ if (g_file_test (dir, G_FILE_TEST_EXISTS)) {
+ GtkDialog *ask_dialog;
+ GtkWidget *button;
+ int response;
+
+ ask_dialog = (GtkDialog *) gtk_message_dialog_new (GTK_WINDOW (dialog),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_CANCEL,
+ _("The theme already exists. Would you like to replace it?"));
+ button = gtk_dialog_add_button (ask_dialog,
+ _("_Overwrite"),
+ GTK_RESPONSE_ACCEPT);
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_SAVE, GTK_ICON_SIZE_BUTTON));
+ response = gtk_dialog_run (ask_dialog);
+ gtk_widget_destroy (GTK_WIDGET (ask_dialog));
+ retval = (response != GTK_RESPONSE_CANCEL);
+ }
+ g_free (dir);
+
+ return retval;
+}
+
+static gboolean
+write_theme_to_disk (CcThemeSaveDialog *dialog,
+ GnomeThemeMetaInfo *theme_info,
+ const char *theme_name,
+ const char *theme_description,
+ gboolean save_background,
+ GError **error)
+{
+ char *dir;
+ char *theme_name_dir;
+ GFile *tmp_file;
+ GFile *target_file;
+ GOutputStream *output;
+ char *str;
+ char *current_background;
+ GConfClient *client;
+ const char *theme_header =
+ "[Desktop Entry]\n"
+ "Name=%s\n"
+ "Type=X-GNOME-Metatheme\n"
+ "Comment=%s\n"
+ "\n"
+ "[X-GNOME-Metatheme]\n"
+ "GtkTheme=%s\n"
+ "MetacityTheme=%s\n"
+ "IconTheme=%s\n";
+
+ theme_name_dir = str_remove_slash (theme_name);
+ dir = g_build_filename (g_get_home_dir (), ".themes", theme_name_dir, "index.theme~", NULL);
+ g_free (theme_name_dir);
+
+ tmp_file = g_file_new_for_path (dir);
+ dir [strlen (dir) - 1] = '\000';
+ target_file = g_file_new_for_path (dir);
+ g_free (dir);
+
+ /* start making the theme file */
+ str = g_strdup_printf (theme_header,
+ theme_name,
+ theme_description,
+ theme_info->gtk_theme_name,
+ theme_info->metacity_theme_name,
+ theme_info->icon_theme_name);
+
+ output = G_OUTPUT_STREAM (g_file_replace (tmp_file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
+ g_output_stream_write (output, str, strlen (str), NULL, NULL);
+ g_free (str);
+
+ if (theme_info->gtk_color_scheme) {
+ char *a, *tmp;
+ tmp = g_strdup (theme_info->gtk_color_scheme);
+ for (a = tmp; *a != '\0'; a++)
+ if (*a == '\n')
+ *a = ',';
+ str = g_strdup_printf ("GtkColorScheme=%s\n", tmp);
+ g_output_stream_write (output, str, strlen (str), NULL, NULL);
+
+ g_free (str);
+ g_free (tmp);
+ }
+
+ if (theme_info->cursor_theme_name) {
+#ifdef HAVE_XCURSOR
+ str = g_strdup_printf ("CursorTheme=%s\n"
+ "CursorSize=%i\n",
+ theme_info->cursor_theme_name,
+ theme_info->cursor_size);
+#else
+ str = g_strdup_printf ("CursorFont=%s\n", theme_info->cursor_theme_name);
+#endif
+ g_output_stream_write (output, str, strlen (str), NULL, NULL);
+ g_free (str);
+ }
+
+ if (theme_info->notification_theme_name) {
+ str = g_strdup_printf ("NotificationTheme=%s\n", theme_info->notification_theme_name);
+ g_output_stream_write (output, str, strlen (str), NULL, NULL);
+ g_free (str);
+ }
+
+ if (save_background) {
+ client = gconf_client_get_default ();
+ current_background = gconf_client_get_string (client, BACKGROUND_KEY, NULL);
+
+ if (current_background != NULL) {
+ str = g_strdup_printf ("BackgroundImage=%s\n", current_background);
+
+ g_output_stream_write (output, str, strlen (str), NULL, NULL);
+
+ g_free (current_background);
+ g_free (str);
+ }
+ g_object_unref (client);
+ }
+
+ g_file_move (tmp_file, target_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL);
+ g_output_stream_close (output, NULL, NULL);
+
+ g_object_unref (tmp_file);
+ g_object_unref (target_file);
+
+ return TRUE;
+}
+
+static gboolean
+save_theme_to_disk (CcThemeSaveDialog *dialog,
+ GnomeThemeMetaInfo *theme_info,
+ const char *theme_name,
+ const char *theme_description,
+ gboolean save_background,
+ GError **error)
+{
+ if (!check_theme_name (theme_name, error))
+ return FALSE;
+
+ if (!setup_directory_structure (dialog, theme_name, error))
+ return FALSE;
+
+ if (!write_theme_to_disk (dialog, theme_info, theme_name, theme_description, save_background, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+do_save (CcThemeSaveDialog *dialog)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start_iter;
+ GtkTextIter end_iter;
+ char *buffer_text;
+ char *theme_description = NULL;
+ char *theme_name = NULL;
+ gboolean save_background;
+ GError *error = NULL;
+ gboolean ret;
+
+ ret = FALSE;
+ theme_name = escape_string_and_dup (gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry)));
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->priv->text_view));
+
+ gtk_text_buffer_get_start_iter (buffer, &start_iter);
+ gtk_text_buffer_get_end_iter (buffer, &end_iter);
+ buffer_text = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
+ theme_description = escape_string_and_dup (buffer_text);
+ g_free (buffer_text);
+
+ save_background = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->save_background_checkbutton));
+
+ ret = save_theme_to_disk (dialog, dialog->priv->info, theme_name, theme_description, save_background, &error);
+ g_free (theme_name);
+ g_free (theme_description);
+ g_clear_error (&error);
+
+ return ret;
+}
+
+static void
+cc_theme_save_dialog_response (GtkDialog *dialog,
+ gint response_id)
+{
+ switch (response_id) {
+ case GTK_RESPONSE_OK:
+ if (!do_save (CC_THEME_SAVE_DIALOG (dialog))) {
+ g_signal_stop_emission_by_name (dialog, "response");
+ gtk_dialog_response (dialog, GTK_RESPONSE_CANCEL);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+on_entry_text_changed (GtkEditable *editable,
+ CcThemeSaveDialog *dialog)
+
+{
+ const char *text;
+
+ text = gtk_entry_get_text (GTK_ENTRY (editable));
+
+ gtk_widget_set_sensitive (dialog->priv->save_button,
+ text != NULL && text[0] != '\000');
+}
+
+static GObject *
+cc_theme_save_dialog_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ CcThemeSaveDialog *dialog;
+ GtkBuilder *builder;
+ GtkWidget *widget;
+ GtkWidget *box;
+ GtkTextBuffer *text_buffer;
+ GError *error;
+
+ dialog = CC_THEME_SAVE_DIALOG (G_OBJECT_CLASS (cc_theme_save_dialog_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+
+ builder = gtk_builder_new ();
+
+ error = NULL;
+ gtk_builder_add_from_file (builder,
+ GNOMECC_UI_DIR
+ "/appearance.ui",
+ &error);
+ if (error != NULL) {
+ g_error (_("Could not load user interface file: %s"),
+ error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+
+ dialog->priv->entry = WID ("save_dialog_entry");
+ dialog->priv->text_view = WID ("save_dialog_textview");
+ dialog->priv->save_background_checkbutton = WID ("save_background_checkbutton");
+
+ g_signal_connect (dialog->priv->entry,
+ "changed",
+ (GCallback) on_entry_text_changed,
+ dialog);
+
+ gtk_widget_set_size_request (dialog->priv->text_view, 300, 100);
+
+ text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->priv->text_view));
+ gtk_text_buffer_set_text (text_buffer, "", 0);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ dialog->priv->save_button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_SAVE, GTK_RESPONSE_OK);
+
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), "");
+ on_entry_text_changed (GTK_EDITABLE (dialog->priv->entry), dialog);
+ gtk_widget_grab_focus (dialog->priv->entry);
+
+ widget = WID ("save_dialog_table");
+ box = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_widget_reparent (widget, box);
+ gtk_widget_show (widget);
+
+ g_object_unref (builder);
+
+ return G_OBJECT (dialog);
+}
+
+static void
+cc_theme_save_dialog_class_init (CcThemeSaveDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+
+ object_class->get_property = cc_theme_save_dialog_get_property;
+ object_class->set_property = cc_theme_save_dialog_set_property;
+ object_class->constructor = cc_theme_save_dialog_constructor;
+ object_class->finalize = cc_theme_save_dialog_finalize;
+
+ dialog_class->response = cc_theme_save_dialog_response;
+
+ g_type_class_add_private (klass, sizeof (CcThemeSaveDialogPrivate));
+}
+
+static void
+cc_theme_save_dialog_init (CcThemeSaveDialog *dialog)
+{
+ dialog->priv = CC_THEME_SAVE_DIALOG_GET_PRIVATE (dialog);
+}
+
+static void
+cc_theme_save_dialog_finalize (GObject *object)
+{
+ CcThemeSaveDialog *theme_save_dialog;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CC_IS_THEME_SAVE_DIALOG (object));
+
+ theme_save_dialog = CC_THEME_SAVE_DIALOG (object);
+
+ g_return_if_fail (theme_save_dialog->priv != NULL);
+
+ G_OBJECT_CLASS (cc_theme_save_dialog_parent_class)->finalize (object);
+}
+
+GtkWidget *
+cc_theme_save_dialog_new (void)
+{
+ GObject *object;
+
+ object = g_object_new (CC_TYPE_THEME_SAVE_DIALOG,
+ NULL);
+
+ return GTK_WIDGET (object);
+}
diff --git a/capplets/appearance/cc-theme-save-dialog.h b/capplets/appearance/cc-theme-save-dialog.h
new file mode 100644
index 0000000..dadf9a6
--- /dev/null
+++ b/capplets/appearance/cc-theme-save-dialog.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 William Jon McCann
+ *
+ * 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.
+ *
+ */
+
+#ifndef __CC_THEME_SAVE_DIALOG_H
+#define __CC_THEME_SAVE_DIALOG_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gnome-theme-info.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_THEME_SAVE_DIALOG (cc_theme_save_dialog_get_type ())
+#define CC_THEME_SAVE_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CC_TYPE_THEME_SAVE_DIALOG, CcThemeSaveDialog))
+#define CC_THEME_SAVE_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CC_TYPE_THEME_SAVE_DIALOG, CcThemeSaveDialogClass))
+#define CC_IS_THEME_SAVE_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CC_TYPE_THEME_SAVE_DIALOG))
+#define CC_IS_THEME_SAVE_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CC_TYPE_THEME_SAVE_DIALOG))
+#define CC_THEME_SAVE_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CC_TYPE_THEME_SAVE_DIALOG, CcThemeSaveDialogClass))
+
+typedef struct CcThemeSaveDialogPrivate CcThemeSaveDialogPrivate;
+
+typedef struct
+{
+ GtkDialog parent;
+ CcThemeSaveDialogPrivate *priv;
+} CcThemeSaveDialog;
+
+typedef struct
+{
+ GtkDialogClass parent_class;
+} CcThemeSaveDialogClass;
+
+#define CC_THEME_SAVE_DIALOG_ERROR (cc_theme_save_dialog_error_quark ())
+
+GType cc_theme_save_dialog_get_type (void);
+GQuark cc_theme_save_dialog_error_quark (void);
+
+GtkWidget * cc_theme_save_dialog_new (void);
+void cc_theme_save_dialog_set_theme_info (CcThemeSaveDialog *dialog,
+ GnomeThemeMetaInfo *info);
+
+G_END_DECLS
+
+#endif /* __CC_THEME_SAVE_DIALOG_H */
diff --git a/capplets/appearance/data/appearance.ui b/capplets/appearance/data/appearance.ui
index 505bd36..f924330 100644
--- a/capplets/appearance/data/appearance.ui
+++ b/capplets/appearance/data/appearance.ui
@@ -2451,7 +2451,7 @@
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
- <object class="GtkTable" id="table3">
+ <object class="GtkTable" id="save_dialog_table">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="n_rows">3</property>
diff --git a/capplets/appearance/theme-util.c b/capplets/appearance/theme-util.c
index 461b904..564bb0d 100644
--- a/capplets/appearance/theme-util.c
+++ b/capplets/appearance/theme-util.c
@@ -1,4 +1,5 @@
-/*
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
* Copyright (C) 2007 The GNOME Foundation
* Written by Thomas Wood <thos gnome org>
* Jens Granseuer <jensgr gmx net>
@@ -32,229 +33,234 @@
gboolean
theme_is_writable (const gpointer theme)
{
- GnomeThemeCommonInfo *info = theme;
- GFile *file;
- GFileInfo *file_info;
- gboolean writable;
+ GnomeThemeCommonInfo *info = theme;
+ GFile *file;
+ GFileInfo *file_info;
+ gboolean writable;
- if (info == NULL || info->path == NULL)
- return FALSE;
+ if (info == NULL || info->path == NULL)
+ return FALSE;
- file = g_file_new_for_path (info->path);
- file_info = g_file_query_info (file,
- G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
- G_FILE_QUERY_INFO_NONE,
- NULL, NULL);
- g_object_unref (file);
+ file = g_file_new_for_path (info->path);
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ g_object_unref (file);
- if (file_info == NULL)
- return FALSE;
+ if (file_info == NULL)
+ return FALSE;
- writable = g_file_info_get_attribute_boolean (file_info,
- G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
- g_object_unref (file_info);
+ writable = g_file_info_get_attribute_boolean (file_info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+ g_object_unref (file_info);
- return writable;
+ return writable;
}
gboolean
-theme_delete (const gchar *name, ThemeType type)
+theme_delete (const char *name,
+ ThemeType type)
{
- gboolean rc;
- GtkDialog *dialog;
- gchar *theme_dir;
- gint response;
- GnomeThemeCommonInfo *theme;
- GFile *dir;
- gboolean del_empty_parent;
-
- dialog = (GtkDialog *) gtk_message_dialog_new (NULL,
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_CANCEL,
- _("Would you like to delete this theme?"));
- gtk_dialog_add_button (dialog, GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT);
- response = gtk_dialog_run (dialog);
- gtk_widget_destroy (GTK_WIDGET (dialog));
- if (response != GTK_RESPONSE_ACCEPT)
- return FALSE;
-
- /* Most theme types are put into separate subdirectories. For those
- we want to delete those directories as well. */
- del_empty_parent = TRUE;
-
- switch (type) {
- case THEME_TYPE_GTK:
- theme = (GnomeThemeCommonInfo *) gnome_theme_info_find (name);
- theme_dir = g_build_filename (theme->path, "gtk-2.0", NULL);
- break;
-
- case THEME_TYPE_ICON:
- theme = (GnomeThemeCommonInfo *) gnome_theme_icon_info_find (name);
- theme_dir = g_path_get_dirname (theme->path);
- del_empty_parent = FALSE;
- break;
-
- case THEME_TYPE_WINDOW:
- theme = (GnomeThemeCommonInfo *) gnome_theme_info_find (name);
- theme_dir = g_build_filename (theme->path, "metacity-1", NULL);
- break;
-
- case THEME_TYPE_META:
- theme = (GnomeThemeCommonInfo *) gnome_theme_meta_info_find (name);
- theme_dir = g_strdup (theme->path);
- break;
-
- case THEME_TYPE_CURSOR:
- theme = (GnomeThemeCommonInfo *) gnome_theme_cursor_info_find (name);
- theme_dir = g_build_filename (theme->path, "cursors", NULL);
- break;
-
- default:
- return FALSE;
- }
-
- dir = g_file_new_for_path (theme_dir);
- g_free (theme_dir);
-
- if (!capplet_file_delete_recursive (dir, NULL)) {
- 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);
- rc = FALSE;
- } else {
- if (del_empty_parent) {
- /* also delete empty parent directories */
- GFile *parent = g_file_get_parent (dir);
- g_file_delete (parent, NULL, NULL);
- g_object_unref (parent);
- }
- rc = TRUE;
- }
-
- g_object_unref (dir);
- return rc;
+ gboolean rc;
+ GtkDialog *dialog;
+ gchar *theme_dir;
+ gint response;
+ GnomeThemeCommonInfo *theme;
+ GFile *dir;
+ gboolean del_empty_parent;
+
+ dialog = (GtkDialog *) gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_CANCEL,
+ _("Would you like to delete this theme?"));
+ gtk_dialog_add_button (dialog, GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT);
+ response = gtk_dialog_run (dialog);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ if (response != GTK_RESPONSE_ACCEPT)
+ return FALSE;
+
+ /* Most theme types are put into separate subdirectories. For those
+ we want to delete those directories as well. */
+ del_empty_parent = TRUE;
+
+ switch (type) {
+ case THEME_TYPE_GTK:
+ theme = (GnomeThemeCommonInfo *) gnome_theme_info_find (name);
+ theme_dir = g_build_filename (theme->path, "gtk-2.0", NULL);
+ break;
+
+ case THEME_TYPE_ICON:
+ theme = (GnomeThemeCommonInfo *) gnome_theme_icon_info_find (name);
+ theme_dir = g_path_get_dirname (theme->path);
+ del_empty_parent = FALSE;
+ break;
+
+ case THEME_TYPE_WINDOW:
+ theme = (GnomeThemeCommonInfo *) gnome_theme_info_find (name);
+ theme_dir = g_build_filename (theme->path, "metacity-1", NULL);
+ break;
+
+ case THEME_TYPE_META:
+ theme = (GnomeThemeCommonInfo *) gnome_theme_meta_info_find (name);
+ theme_dir = g_strdup (theme->path);
+ break;
+
+ case THEME_TYPE_CURSOR:
+ theme = (GnomeThemeCommonInfo *) gnome_theme_cursor_info_find (name);
+ theme_dir = g_build_filename (theme->path, "cursors", NULL);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ dir = g_file_new_for_path (theme_dir);
+ g_free (theme_dir);
+
+ if (!capplet_file_delete_recursive (dir, NULL)) {
+ 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);
+ rc = FALSE;
+ } else {
+ if (del_empty_parent) {
+ /* also delete empty parent directories */
+ GFile *parent = g_file_get_parent (dir);
+ g_file_delete (parent, NULL, NULL);
+ g_object_unref (parent);
+ }
+ rc = TRUE;
+ }
+
+ g_object_unref (dir);
+ return rc;
}
gboolean
-theme_model_iter_last (GtkTreeModel *model, GtkTreeIter *iter)
+theme_model_iter_last (GtkTreeModel *model,
+ GtkTreeIter *iter)
{
- GtkTreeIter walk, prev;
- gboolean valid;
+ GtkTreeIter walk, prev;
+ gboolean valid;
- valid = gtk_tree_model_get_iter_first (model, &walk);
+ valid = gtk_tree_model_get_iter_first (model, &walk);
- if (valid) {
- do {
- prev = walk;
- valid = gtk_tree_model_iter_next (model, &walk);
- } while (valid);
+ if (valid) {
+ do {
+ prev = walk;
+ valid = gtk_tree_model_iter_next (model, &walk);
+ } while (valid);
- *iter = prev;
- return TRUE;
- }
- return FALSE;
+ *iter = prev;
+ return TRUE;
+ }
+ return FALSE;
}
gboolean
-theme_find_in_model (GtkTreeModel *model, const gchar *name, GtkTreeIter *iter)
+theme_find_in_model (GtkTreeModel *model,
+ const char *name,
+ GtkTreeIter *iter)
{
- GtkTreeIter walk;
- gboolean valid;
- gchar *test;
-
- if (!name)
- return FALSE;
-
- for (valid = gtk_tree_model_get_iter_first (model, &walk); valid;
- valid = gtk_tree_model_iter_next (model, &walk))
- {
- gtk_tree_model_get (model, &walk, COL_NAME, &test, -1);
-
- if (test) {
- gint cmp = strcmp (test, name);
- g_free (test);
-
- if (!cmp) {
- if (iter)
- *iter = walk;
- return TRUE;
- }
- }
- }
-
- return FALSE;
+ GtkTreeIter walk;
+ gboolean valid;
+ gchar *test;
+
+ if (!name)
+ return FALSE;
+
+ for (valid = gtk_tree_model_get_iter_first (model, &walk); valid;
+ valid = gtk_tree_model_iter_next (model, &walk))
+ {
+ gtk_tree_model_get (model, &walk, COL_NAME, &test, -1);
+
+ if (test) {
+ gint cmp = strcmp (test, name);
+ g_free (test);
+
+ if (!cmp) {
+ if (iter)
+ *iter = walk;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
}
gboolean
packagekit_available (void)
{
- DBusGConnection *connection;
- DBusGProxy *proxy;
- gboolean available = FALSE;
+ DBusGConnection *connection;
+ DBusGProxy *proxy;
+ gboolean available = FALSE;
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
- if (connection == NULL) {
- return FALSE;
- }
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+ if (connection == NULL) {
+ return FALSE;
+ }
- proxy = dbus_g_proxy_new_for_name (connection,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
+ proxy = dbus_g_proxy_new_for_name (connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
- org_freedesktop_DBus_name_has_owner (proxy,
- "org.freedesktop.PackageKit",
- &available,
- NULL);
+ org_freedesktop_DBus_name_has_owner (proxy,
+ "org.freedesktop.PackageKit",
+ &available,
+ NULL);
- g_object_unref (proxy);
- dbus_g_connection_unref (connection);
+ g_object_unref (proxy);
+ dbus_g_connection_unref (connection);
- return available;
+ return available;
}
void
-theme_install_file (GtkWindow *parent, const gchar *path)
+theme_install_file (GtkWindow *parent,
+ const char *path)
{
- DBusGConnection *connection;
- DBusGProxy *proxy;
- GError *error = NULL;
- gboolean ret;
-
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
- if (connection == NULL) {
- g_warning ("Could not get session bus");
- return;
- }
-
- proxy = dbus_g_proxy_new_for_name (connection,
- "org.freedesktop.PackageKit",
- "/org/freedesktop/PackageKit",
- "org.freedesktop.PackageKit");
-
-
- ret = dbus_g_proxy_call (proxy, "InstallProvideFile", &error,
- G_TYPE_STRING, path,
- G_TYPE_INVALID, G_TYPE_INVALID);
-
- g_object_unref (proxy);
-
- if (!ret) {
- GtkWidget *dialog = gtk_message_dialog_new (NULL,
- GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("Could not install theme engine"));
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- g_error_free (error);
- }
- dbus_g_connection_unref (connection);
+ DBusGConnection *connection;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ gboolean ret;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+ if (connection == NULL) {
+ g_warning ("Could not get session bus");
+ return;
+ }
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.PackageKit",
+ "/org/freedesktop/PackageKit",
+ "org.freedesktop.PackageKit");
+
+
+ ret = dbus_g_proxy_call (proxy, "InstallProvideFile", &error,
+ G_TYPE_STRING, path,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+
+ g_object_unref (proxy);
+
+ if (!ret) {
+ GtkWidget *dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Could not install theme engine"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+ }
+ dbus_g_connection_unref (connection);
}
diff --git a/capplets/appearance/theme-util.h b/capplets/appearance/theme-util.h
index b6f453b..8716f9e 100644
--- a/capplets/appearance/theme-util.h
+++ b/capplets/appearance/theme-util.h
@@ -53,12 +53,17 @@ typedef enum {
THEME_TYPE_CURSOR
} ThemeType;
-gboolean theme_is_writable (const gpointer theme);
-gboolean theme_delete (const gchar *name, ThemeType type);
+gboolean theme_is_writable (const gpointer theme);
+gboolean theme_delete (const gchar *name,
+ ThemeType type);
-gboolean theme_model_iter_last (GtkTreeModel *model, GtkTreeIter *iter);
-gboolean theme_find_in_model (GtkTreeModel *model, const gchar *name, GtkTreeIter *iter);
+gboolean theme_model_iter_last (GtkTreeModel *model,
+ GtkTreeIter *iter);
+gboolean theme_find_in_model (GtkTreeModel *model,
+ const gchar *name,
+ GtkTreeIter *iter);
-void theme_install_file (GtkWindow *parent, const gchar *path);
-gboolean packagekit_available (void);
+void theme_install_file (GtkWindow *parent,
+ const gchar *path);
+gboolean packagekit_available (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]