add initial support for installing themes, includes support for packages
2007-06-16 Jens Granseuer <jensgr@gmx.net> * Makefile.am: * appearance-style.c: (prepare_list): * appearance-themes.c: (theme_install_cb), (theme_delete_cb), (theme_details_changed_cb): * theme-installer.c: (cleanup_tmp_dir), (file_theme_type), (missing_utility_message_dialog), (transfer_done_tgz_tbz), (transfer_done_archive), (gnome_theme_install_real), (transfer_done_cb), (gnome_theme_install_from_uri), (gnome_theme_installer_run): * theme-installer.h: add initial support for installing themes, includes support for packages containing more than one theme (bug #409624) svn path=/trunk/; revision=7730
This commit is contained in:
parent
c8e0000859
commit
dbc58d64cb
6 changed files with 674 additions and 8 deletions
|
@ -1,3 +1,18 @@
|
|||
2007-06-16 Jens Granseuer <jensgr@gmx.net>
|
||||
|
||||
* Makefile.am:
|
||||
* appearance-style.c: (prepare_list):
|
||||
* appearance-themes.c: (theme_install_cb), (theme_delete_cb),
|
||||
(theme_details_changed_cb):
|
||||
* theme-installer.c: (cleanup_tmp_dir), (file_theme_type),
|
||||
(missing_utility_message_dialog), (transfer_done_tgz_tbz),
|
||||
(transfer_done_archive), (gnome_theme_install_real),
|
||||
(transfer_done_cb), (gnome_theme_install_from_uri),
|
||||
(gnome_theme_installer_run):
|
||||
* theme-installer.h: add initial support for installing themes,
|
||||
includes support for packages containing more than one theme
|
||||
(bug #409624)
|
||||
|
||||
2007-06-15 Jens Granseuer <jensgr@gmx.net>
|
||||
|
||||
* appearance-desktop.c: (wp_props_load_wallpaper),
|
||||
|
|
|
@ -24,6 +24,8 @@ gnome_appearance_properties_SOURCES = \
|
|||
gnome-wp-utils.h \
|
||||
gnome-wp-xml.c \
|
||||
gnome-wp-xml.h \
|
||||
theme-installer.c \
|
||||
theme-installer.h \
|
||||
theme-util.c \
|
||||
theme-util.h \
|
||||
wp-cellrenderer.c \
|
||||
|
@ -42,11 +44,11 @@ dist_glade_DATA = appearance.glade
|
|||
|
||||
pixmapdir = $(pkgdatadir)/pixmaps
|
||||
dist_pixmap_DATA = \
|
||||
theme-thumbnailing.png \
|
||||
subpixel-bgr.png \
|
||||
subpixel-rgb.png \
|
||||
subpixel-vbgr.png \
|
||||
subpixel-vrgb.png
|
||||
subpixel-vrgb.png \
|
||||
theme-thumbnailing.png
|
||||
|
||||
wallpaperdir = $(datadir)/gnome-background-properties
|
||||
|
||||
|
|
|
@ -127,8 +127,6 @@ prepare_list (AppearanceData *data, GtkWidget *list, ThemeType type)
|
|||
/* we don't deal with any other type of themes here */
|
||||
return;
|
||||
}
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
store = gtk_list_store_new (NUM_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "appearance.h"
|
||||
#include "theme-thumbnail.h"
|
||||
#include "gnome-theme-apply.h"
|
||||
#include "theme-installer.h"
|
||||
#include "theme-util.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
@ -398,7 +399,8 @@ theme_custom_cb (GtkWidget *button, AppearanceData *data)
|
|||
static void
|
||||
theme_install_cb (GtkWidget *button, AppearanceData *data)
|
||||
{
|
||||
/* TODO: Install a new theme */
|
||||
gnome_theme_installer_run (
|
||||
GTK_WINDOW (glade_xml_get_widget (data->xml, "appearance_window")), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -436,9 +438,6 @@ theme_delete_cb (GtkWidget *button, AppearanceData *data)
|
|||
g_list_free (selected);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Delete the selected theme */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -469,6 +468,7 @@ theme_details_changed_cb (AppearanceData *data)
|
|||
if (theme_is_equal (gconf_theme, info)) {
|
||||
theme_select_name (icon_view, info->name);
|
||||
done = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_list_free (theme_list);
|
||||
|
|
623
capplets/appearance/theme-installer.c
Normal file
623
capplets/appearance/theme-installer.c
Normal file
|
@ -0,0 +1,623 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The GNOME Foundation
|
||||
* Written by Thomas Wood <thos@gnome.org>
|
||||
* Jens Granseuer <jensgr@gmx.net>
|
||||
* 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 <string.h>
|
||||
#include <libwindow-settings/gnome-wm-manager.h>
|
||||
#include <libgnomevfs/gnome-vfs-async-ops.h>
|
||||
#include <libgnomevfs/gnome-vfs-ops.h>
|
||||
#include <libgnomevfs/gnome-vfs-utils.h>
|
||||
|
||||
#include "gnome-theme-info.h"
|
||||
#include "capplet-util.h"
|
||||
#include "activate-settings-daemon.h"
|
||||
#include "gconf-property-editor.h"
|
||||
#include "file-transfer-dialog.h"
|
||||
#include "theme-installer.h"
|
||||
#include "theme-util.h"
|
||||
|
||||
enum {
|
||||
THEME_INVALID,
|
||||
THEME_ICON,
|
||||
THEME_GNOME,
|
||||
THEME_GTK,
|
||||
THEME_ENGINE,
|
||||
THEME_METACITY
|
||||
};
|
||||
|
||||
enum {
|
||||
TARGZ,
|
||||
TARBZ,
|
||||
DIRECTORY
|
||||
};
|
||||
|
||||
static void
|
||||
cleanup_tmp_dir (const gchar *tmp_dir)
|
||||
{
|
||||
if (gnome_vfs_remove_directory (tmp_dir) == GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY) {
|
||||
GList *list;
|
||||
|
||||
list = g_list_prepend (NULL, gnome_vfs_uri_new (tmp_dir));
|
||||
gnome_vfs_xfer_delete_list (list, GNOME_VFS_XFER_RECURSIVE,
|
||||
GNOME_VFS_XFER_ERROR_MODE_ABORT, NULL, NULL);
|
||||
gnome_vfs_uri_list_free (list);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
file_theme_type (const gchar *dir)
|
||||
{
|
||||
gchar *filename = NULL;
|
||||
GnomeVFSURI *src_uri = NULL;
|
||||
gboolean exists;
|
||||
|
||||
if (!dir) return THEME_INVALID;
|
||||
|
||||
filename = g_build_filename (dir, "index.theme", NULL);
|
||||
src_uri = gnome_vfs_uri_new (filename);
|
||||
g_free (filename);
|
||||
exists = gnome_vfs_uri_exists (src_uri);
|
||||
gnome_vfs_uri_unref (src_uri);
|
||||
|
||||
if (exists) {
|
||||
GPatternSpec *pattern = NULL;
|
||||
gchar *file_contents = NULL;
|
||||
gint file_size;
|
||||
gchar *uri;
|
||||
gboolean match;
|
||||
|
||||
uri = gnome_vfs_get_uri_from_local_path (filename);
|
||||
gnome_vfs_read_entire_file (uri, &file_size, &file_contents);
|
||||
g_free (uri);
|
||||
|
||||
pattern = g_pattern_spec_new ("*[Icon Theme]*");
|
||||
match = g_pattern_match_string (pattern, file_contents);
|
||||
g_pattern_spec_free (pattern);
|
||||
|
||||
if (match)
|
||||
return THEME_ICON;
|
||||
|
||||
pattern = g_pattern_spec_new ("*[X-GNOME-Metatheme]*");
|
||||
match = g_pattern_match_string (pattern, file_contents);
|
||||
g_pattern_spec_free (pattern);
|
||||
|
||||
if (match)
|
||||
return THEME_GNOME;
|
||||
}
|
||||
|
||||
filename = g_build_filename (dir, "gtk-2.0", "gtkrc", NULL);
|
||||
src_uri = gnome_vfs_uri_new (filename);
|
||||
g_free (filename);
|
||||
exists = gnome_vfs_uri_exists (src_uri);
|
||||
gnome_vfs_uri_unref (src_uri);
|
||||
|
||||
if (exists)
|
||||
return THEME_GTK;
|
||||
|
||||
filename = g_build_filename (dir, "metacity-1", "metacity-theme-1.xml", NULL);
|
||||
src_uri = gnome_vfs_uri_new (filename);
|
||||
g_free (filename);
|
||||
exists = gnome_vfs_uri_exists (src_uri);
|
||||
gnome_vfs_uri_unref (src_uri);
|
||||
|
||||
if (exists)
|
||||
return THEME_METACITY;
|
||||
|
||||
filename = g_build_filename (dir, "configure.in", NULL);
|
||||
src_uri = gnome_vfs_uri_new (filename);
|
||||
g_free (filename);
|
||||
exists = gnome_vfs_uri_exists (src_uri);
|
||||
gnome_vfs_uri_unref (src_uri);
|
||||
|
||||
if (exists)
|
||||
return THEME_ENGINE;
|
||||
|
||||
return THEME_INVALID;
|
||||
}
|
||||
|
||||
static void
|
||||
transfer_cancel_cb (GtkWidget *dlg, gchar *path)
|
||||
{
|
||||
gnome_vfs_unlink (path);
|
||||
g_free (path);
|
||||
gtk_widget_destroy (dlg);
|
||||
}
|
||||
|
||||
static void
|
||||
missing_utility_message_dialog (const gchar *utility)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
||||
_("Cannot install theme.\nThe %s utility is not installed."), utility);
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
/* this works around problems when doing fork/exec in a threaded app
|
||||
* with some locks being held/waited on in different threads.
|
||||
*
|
||||
* we do the idle callback so that the async xfer has finished and
|
||||
* cleaned up its vfs job. otherwise it seems the slave thread gets
|
||||
* woken up and it removes itself from the job queue before it is
|
||||
* supposed to. very strange.
|
||||
*
|
||||
* see bugzilla.gnome.org #86141 for details
|
||||
*/
|
||||
static gboolean
|
||||
transfer_done_tgz_tbz (const gchar *util, const gchar *tmp_dir, const gchar *archive)
|
||||
{
|
||||
gboolean rc;
|
||||
int status;
|
||||
gchar *command, *filename, *zip, *tar;
|
||||
|
||||
if (!(zip = g_find_program_in_path (util))) {
|
||||
missing_utility_message_dialog (util);
|
||||
return FALSE;
|
||||
}
|
||||
if (!(tar = g_find_program_in_path ("tar"))) {
|
||||
missing_utility_message_dialog ("tar");
|
||||
g_free (zip);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
filename = g_shell_quote (archive);
|
||||
|
||||
/* this should be something more clever and nonblocking */
|
||||
command = g_strdup_printf ("sh -c 'cd \"%s\"; %s -d -c < \"%s\" | %s xf - '",
|
||||
tmp_dir, zip, filename, tar);
|
||||
g_free (zip);
|
||||
g_free (tar);
|
||||
g_free (filename);
|
||||
|
||||
rc = (g_spawn_command_line_sync (command, NULL, NULL, &status, NULL) && status == 0);
|
||||
g_free (command);
|
||||
|
||||
if (rc == FALSE) {
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
||||
_("Cannot install theme.\nThere was a problem while extracting the theme."));
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transfer_done_archive (gint filetype, const gchar *tmp_dir, const gchar *archive)
|
||||
{
|
||||
if (filetype == TARGZ)
|
||||
return transfer_done_tgz_tbz ("gzip", tmp_dir, archive);
|
||||
else if (filetype == TARBZ)
|
||||
return transfer_done_tgz_tbz ("bzip2", tmp_dir, archive);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnome_theme_install_real (gint filetype, const gchar *tmp_dir, const gchar *theme_name)
|
||||
{
|
||||
gboolean success = TRUE;
|
||||
GtkWidget *dialog, *apply_button;
|
||||
int xfer_options;
|
||||
GnomeVFSURI *theme_source_dir, *theme_dest_dir;
|
||||
gint theme_type;
|
||||
gchar *user_message = NULL;
|
||||
gchar *target_dir = NULL;
|
||||
|
||||
/* What type of theme it is ? */
|
||||
theme_type = file_theme_type (tmp_dir);
|
||||
if (theme_type == THEME_ICON) {
|
||||
target_dir = g_build_path (G_DIR_SEPARATOR_S,
|
||||
g_get_home_dir (), ".icons",
|
||||
theme_name, NULL);
|
||||
} else if (theme_type == THEME_GNOME) {
|
||||
target_dir = g_build_path (G_DIR_SEPARATOR_S,
|
||||
g_get_home_dir (), ".themes",
|
||||
theme_name, NULL);
|
||||
user_message = g_strdup_printf (_("GNOME Theme %s correctly installed"),
|
||||
theme_name);
|
||||
} else if (theme_type == THEME_METACITY ||
|
||||
theme_type == THEME_GTK) {
|
||||
target_dir = g_build_path (G_DIR_SEPARATOR_S,
|
||||
g_get_home_dir (), ".themes",
|
||||
theme_name, NULL);
|
||||
} else if (theme_type == THEME_ENGINE) {
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("The theme is an engine. You need to compile it."));
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
return FALSE;
|
||||
} else {
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("The file format is invalid"));
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* see if there is an icon theme lurking in this package */
|
||||
if (theme_type == THEME_GNOME)
|
||||
{
|
||||
gchar *path;
|
||||
|
||||
path = g_build_path (G_DIR_SEPARATOR_S,
|
||||
tmp_dir, "icons", NULL);
|
||||
if (g_file_test (path, G_FILE_TEST_IS_DIR)
|
||||
&& (file_theme_type (path) == THEME_ICON))
|
||||
{
|
||||
gchar *new_path;
|
||||
|
||||
new_path = g_build_path (G_DIR_SEPARATOR_S,
|
||||
g_get_home_dir (),
|
||||
".icons",
|
||||
theme_name, NULL);
|
||||
/* XXX: make some noise if we couldn't install it? */
|
||||
gnome_vfs_move (path, new_path, FALSE);
|
||||
g_free (new_path);
|
||||
}
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
/* Move the dir to the target dir */
|
||||
theme_source_dir = gnome_vfs_uri_new (tmp_dir);
|
||||
theme_dest_dir = gnome_vfs_uri_new (target_dir);
|
||||
|
||||
xfer_options = GNOME_VFS_XFER_DELETE_ITEMS | GNOME_VFS_XFER_RECURSIVE;
|
||||
if (filetype != DIRECTORY)
|
||||
xfer_options |= GNOME_VFS_XFER_REMOVESOURCE;
|
||||
|
||||
if (gnome_vfs_xfer_uri (theme_source_dir, theme_dest_dir, xfer_options,
|
||||
GNOME_VFS_XFER_ERROR_MODE_ABORT,
|
||||
GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
|
||||
NULL, NULL) != GNOME_VFS_OK) {
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("Installation Failed"));
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
success = FALSE;
|
||||
} else {
|
||||
/* Ask to apply theme (if we can) */
|
||||
if (theme_type == THEME_GTK || theme_type == THEME_METACITY || theme_type == THEME_ICON)
|
||||
{
|
||||
/* TODO: currently cannot apply "gnome themes" */
|
||||
gchar *str;
|
||||
|
||||
str = g_strdup_printf(_("The theme \"%s\" has been installed."), theme_name);
|
||||
user_message = g_strdup_printf("<span weight=\"bold\" size=\"larger\">%s</span>", str);
|
||||
g_free (str);
|
||||
|
||||
dialog = gtk_message_dialog_new_with_markup (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_NONE, user_message);
|
||||
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("Would you like to apply it now, or keep your current theme?"));
|
||||
|
||||
gtk_dialog_add_button (GTK_DIALOG (dialog), _("Keep Current Theme"), GTK_RESPONSE_CLOSE);
|
||||
|
||||
apply_button = gtk_button_new_with_label (_("Apply New Theme"));
|
||||
gtk_button_set_image (GTK_BUTTON (apply_button), gtk_image_new_from_stock (GTK_STOCK_APPLY, GTK_ICON_SIZE_BUTTON));
|
||||
gtk_dialog_add_action_widget (GTK_DIALOG (dialog), apply_button, GTK_RESPONSE_APPLY);
|
||||
GTK_WIDGET_SET_FLAGS (apply_button, GTK_CAN_DEFAULT);
|
||||
gtk_widget_show (apply_button);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY);
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_APPLY)
|
||||
{
|
||||
/* apply theme here! */
|
||||
GConfClient *gconf_client;
|
||||
const gchar *gconf_key;
|
||||
|
||||
switch (theme_type)
|
||||
{
|
||||
case THEME_GTK:
|
||||
gconf_key = GTK_THEME_KEY;
|
||||
break;
|
||||
case THEME_METACITY:
|
||||
gconf_key = METACITY_THEME_KEY;
|
||||
break;
|
||||
case THEME_ICON:
|
||||
gconf_key = ICON_THEME_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
gconf_client = gconf_client_get_default ();
|
||||
gconf_client_set_string (gconf_client, gconf_key, theme_name, NULL);
|
||||
g_object_unref (gconf_client);
|
||||
}
|
||||
} else {
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
user_message);
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
}
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
g_free (user_message);
|
||||
g_free (target_dir);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
transfer_done_cb (GtkWidget *dlg, gchar *path)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
gint filetype;
|
||||
|
||||
/* XXX: path should be on the local filesystem by now? */
|
||||
|
||||
if (dlg)
|
||||
gtk_widget_destroy (dlg);
|
||||
|
||||
if (g_str_has_suffix (path, ".tar.gz") || g_str_has_suffix (path, ".tgz") || g_str_has_suffix(path, ".gtp"))
|
||||
filetype = TARGZ;
|
||||
else if (g_str_has_suffix (path, ".tar.bz2"))
|
||||
filetype = TARBZ;
|
||||
else if (g_file_test (path, G_FILE_TEST_IS_DIR))
|
||||
filetype = DIRECTORY;
|
||||
else {
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("This theme is not in a supported format."));
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
g_free (path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (filetype == DIRECTORY) {
|
||||
gchar *name = g_path_get_basename (path);
|
||||
gnome_theme_install_real (filetype, path, name);
|
||||
g_free (name);
|
||||
} else {
|
||||
/* Create a temp directory and uncompress file there */
|
||||
GDir *dir;
|
||||
const gchar *name;
|
||||
gchar *tmp_dir;
|
||||
gboolean ok;
|
||||
|
||||
tmp_dir = g_strdup_printf ("%s/.themes/.theme-%u",
|
||||
g_get_home_dir (),
|
||||
g_random_int ());
|
||||
|
||||
if ((gnome_vfs_make_directory (tmp_dir, 0700)) != GNOME_VFS_OK) {
|
||||
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("Failed to create temporary directory"));
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
g_free (tmp_dir);
|
||||
g_free (path);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!transfer_done_archive (filetype, tmp_dir, path) ||
|
||||
((dir = g_dir_open (tmp_dir, 0, NULL)) == NULL))
|
||||
{
|
||||
cleanup_tmp_dir (tmp_dir);
|
||||
g_free (tmp_dir);
|
||||
g_free (path);
|
||||
return;
|
||||
}
|
||||
|
||||
gnome_vfs_unlink (path);
|
||||
|
||||
ok = TRUE;
|
||||
for (name = g_dir_read_name (dir); name && ok;
|
||||
name = g_dir_read_name (dir))
|
||||
{
|
||||
gchar *theme_dir;
|
||||
|
||||
theme_dir = g_build_path (G_DIR_SEPARATOR_S,
|
||||
tmp_dir, name, NULL);
|
||||
|
||||
if (g_file_test (theme_dir, G_FILE_TEST_IS_DIR))
|
||||
ok = gnome_theme_install_real (filetype, theme_dir, name);
|
||||
|
||||
g_free (theme_dir);
|
||||
}
|
||||
g_dir_close (dir);
|
||||
|
||||
cleanup_tmp_dir (tmp_dir);
|
||||
g_free (tmp_dir);
|
||||
}
|
||||
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
void
|
||||
gnome_theme_install_from_uri (gchar *filename, GtkWindow *parent)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
gchar *path, *base;
|
||||
GList *src, *target;
|
||||
GnomeVFSURI *uri;
|
||||
gchar *temppath;
|
||||
const gchar *template;
|
||||
|
||||
if (filename == NULL || strlen (filename) <= 0) {
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("No theme file location specified to install"));
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
return;
|
||||
}
|
||||
|
||||
/* see if someone dropped a directory */
|
||||
if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
|
||||
transfer_done_cb (NULL, filename);
|
||||
return;
|
||||
}
|
||||
|
||||
/* we can't tell if this is an icon theme yet, so just make a
|
||||
* temporary copy in .themes */
|
||||
path = g_build_filename (g_get_home_dir (), ".themes", NULL);
|
||||
|
||||
if (access (path, X_OK | W_OK) != 0) {
|
||||
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("Insufficient permissions to install the theme in:\n%s"), path);
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
g_free (path);
|
||||
return;
|
||||
}
|
||||
g_free (path);
|
||||
|
||||
/* To avoid the copy of /root/.themes to /root/.themes/.themes
|
||||
* which causes an infinite loop. The user asks to transfer the all
|
||||
* contents of a folder, to a folder under itself. So ignore the
|
||||
* situation.
|
||||
*/
|
||||
temppath = g_build_filename (filename, ".themes", NULL);
|
||||
if (!strcmp (temppath, path)) {
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("%s is the path where the theme files will be installed. This can not be selected as the source location"), filename);
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
g_free (temppath);
|
||||
return;
|
||||
}
|
||||
g_free (temppath);
|
||||
|
||||
uri = gnome_vfs_uri_new (filename);
|
||||
base = gnome_vfs_uri_extract_short_name (uri);
|
||||
src = g_list_append (NULL, uri);
|
||||
|
||||
if (g_str_has_suffix (base, ".tar.gz") || g_str_has_suffix (base, ".tgz") || g_str_has_suffix (base, ".gtp"))
|
||||
template = "gnome-theme-%d.gtp";
|
||||
else if (g_str_has_suffix (base, ".tar.bz2"))
|
||||
template = "gnome-theme-%d.tar.bz2";
|
||||
else {
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
_("The file format is invalid."));
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
g_free (base);
|
||||
gnome_vfs_uri_list_unref (src);
|
||||
return;
|
||||
}
|
||||
g_free (base);
|
||||
|
||||
do {
|
||||
gchar *file_tmp;
|
||||
|
||||
file_tmp = g_strdup_printf (template, rand ());
|
||||
path = g_build_filename (g_get_home_dir (), ".themes", file_tmp, NULL);
|
||||
g_free (file_tmp);
|
||||
} while (g_file_test (path, G_FILE_TEST_EXISTS));
|
||||
|
||||
|
||||
target = g_list_append (NULL, gnome_vfs_uri_new (path));
|
||||
|
||||
dialog = file_transfer_dialog_new_with_parent (parent);
|
||||
file_transfer_dialog_wrap_async_xfer (FILE_TRANSFER_DIALOG (dialog),
|
||||
src, target,
|
||||
GNOME_VFS_XFER_RECURSIVE,
|
||||
GNOME_VFS_XFER_ERROR_MODE_QUERY,
|
||||
GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
|
||||
GNOME_VFS_PRIORITY_DEFAULT);
|
||||
gnome_vfs_uri_list_unref (src);
|
||||
gnome_vfs_uri_list_unref (target);
|
||||
g_signal_connect (G_OBJECT (dialog), "cancel",
|
||||
G_CALLBACK (transfer_cancel_cb), path);
|
||||
g_signal_connect (G_OBJECT (dialog), "done",
|
||||
G_CALLBACK (transfer_done_cb), path);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
void
|
||||
gnome_theme_installer_run (GtkWindow *parent, gchar *filename)
|
||||
{
|
||||
static gboolean running_theme_install = FALSE;
|
||||
static gchar old_folder[512] = "";
|
||||
GtkWidget *dialog;
|
||||
gchar *filename_selected, *folder;
|
||||
GtkFileFilter *filter;
|
||||
|
||||
if (running_theme_install)
|
||||
return;
|
||||
|
||||
running_theme_install = TRUE;
|
||||
|
||||
if (filename == NULL)
|
||||
filename = old_folder;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new (_("Select Theme"), parent, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_set_name (filter, _("Theme Packages"));
|
||||
gtk_file_filter_add_mime_type (filter, "application/x-bzip-compressed-tar");
|
||||
gtk_file_filter_add_mime_type (filter, "application/x-compressed-tar");
|
||||
gtk_file_filter_add_mime_type (filter, "application/x-gnome-theme-package");
|
||||
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_set_name (filter, _("All Files"));
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
|
||||
|
||||
if (strcmp (old_folder, ""))
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), old_folder);
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
filename_selected = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
gnome_theme_install_from_uri (filename_selected, parent);
|
||||
g_free (filename_selected);
|
||||
}
|
||||
|
||||
folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
|
||||
g_strlcpy (old_folder, folder, 255);
|
||||
g_free (folder);
|
||||
|
||||
/* FIXME: refresh GUI from disk here */
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
|
||||
running_theme_install = FALSE;
|
||||
}
|
28
capplets/appearance/theme-installer.h
Normal file
28
capplets/appearance/theme-installer.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The GNOME Foundation
|
||||
* Written by Thomas Wood <thos@gnome.org>
|
||||
* Jens Granseuer <jensgr@gmx.net>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef THEME_INSTALLER_H
|
||||
#define THEME_INSTALLER_H
|
||||
|
||||
void gnome_theme_install_from_uri (gchar * filename, GtkWindow *parent);
|
||||
void gnome_theme_installer_run (GtkWindow *parent, gchar *filename);
|
||||
|
||||
#endif /* THEME_INSTALLER_H */
|
Loading…
Add table
Add a link
Reference in a new issue