#include "gnome-theme-info.h" #include "gnome-theme-save.h" #include "gnome-theme-manager.h" #include "capplet-util.h" #include #include "gnome-theme-save-data.c" static GQuark error_quark; enum { INVALID_THEME_NAME }; /* taken from gnome-desktop-item.c */ static char * 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 gchar *theme_name, GError **error) { if (theme_name == NULL) { g_set_error (error, error_quark, INVALID_THEME_NAME, _("Theme name must be present")); return FALSE; } return TRUE; } static gboolean setup_directory_structure (const gchar *theme_name, GError **error) { gchar *dir; GnomeVFSURI *uri; dir = g_build_filename (g_get_home_dir (), ".themes", NULL); uri = gnome_vfs_uri_new (dir); if (!gnome_vfs_uri_exists (uri)) gnome_vfs_make_directory_for_uri (uri, 0775); gnome_vfs_uri_unref (uri); g_free (dir); dir = g_build_filename (g_get_home_dir (), ".themes", theme_name, NULL); uri = gnome_vfs_uri_new (dir); if (!gnome_vfs_uri_exists (uri)) gnome_vfs_make_directory_for_uri (uri, 0775); else { GtkDialog *dialog; gint response; dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, _("The theme already exists. Would you like to replace it ?")); response = gtk_dialog_run(dialog); gtk_widget_destroy(dialog); if (response == GTK_RESPONSE_CANCEL) return FALSE; } gnome_vfs_uri_unref (uri); g_free (dir); return TRUE; } static gboolean write_theme_to_disk (GnomeThemeMetaInfo *meta_theme_info, const gchar *theme_name, const gchar *theme_description, GError **error) { gchar *dir; GnomeVFSURI *uri; GnomeVFSURI *target_uri; GnomeVFSHandle *handle = NULL; GnomeVFSFileSize bytes_written; gchar *str; dir = g_build_filename (g_get_home_dir (), ".themes", theme_name, "index.theme~", NULL); uri = gnome_vfs_uri_new (dir); dir [strlen (dir) - 1] = '\000'; target_uri = gnome_vfs_uri_new (dir); g_free (dir); gnome_vfs_create_uri (&handle, uri, GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_WRITE, FALSE, 0644); gnome_vfs_truncate_handle (handle, 0); /* start making the theme file */ str = g_strdup_printf (theme_header, theme_name, theme_description); gnome_vfs_write (handle, str, strlen (str), &bytes_written); g_free (str); str = g_strdup_printf ("GtkTheme=%s\n", meta_theme_info->gtk_theme_name); gnome_vfs_write (handle, str, strlen (str), &bytes_written); g_free (str); str = g_strdup_printf ("MetacityTheme=%s\n", meta_theme_info->metacity_theme_name); gnome_vfs_write (handle, str, strlen (str), &bytes_written); g_free (str); str = g_strdup_printf ("IconTheme=%s\n", meta_theme_info->icon_theme_name); gnome_vfs_write (handle, str, strlen (str), &bytes_written); g_free (str); gnome_vfs_close (handle); gnome_vfs_move_uri (uri, target_uri, TRUE); gnome_vfs_uri_unref (uri); gnome_vfs_uri_unref (target_uri); return TRUE; } static gboolean save_theme_to_disk (GnomeThemeMetaInfo *meta_theme_info, const gchar *theme_name, const gchar *theme_description, GError **error) { if (! check_theme_name (theme_name, error)) return FALSE; if (! setup_directory_structure (theme_name, error)) return FALSE; if (! write_theme_to_disk (meta_theme_info, theme_name, theme_description, error)) return FALSE; return TRUE; } static void save_dialog_response (GtkWidget *save_dialog, gint response_id, gpointer data) { GnomeThemeMetaInfo *meta_theme_info; char *theme_description = NULL; char *theme_name = NULL; GError *error = NULL; if (response_id == GTK_RESPONSE_OK) { GladeXML *dialog; GtkWidget *entry; GtkWidget *text_view; GtkTextBuffer *buffer; GtkTextIter start_iter; GtkTextIter end_iter; gchar *buffer_text; dialog = gnome_theme_manager_get_theme_dialog (); entry = WID ("save_dialog_entry"); theme_name = escape_string_and_dup (gtk_entry_get_text (GTK_ENTRY (entry))); text_view = WID ("save_dialog_textview"); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (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); meta_theme_info = (GnomeThemeMetaInfo *) g_object_get_data (G_OBJECT (save_dialog), "meta-theme-info"); if (! save_theme_to_disk (meta_theme_info, theme_name, theme_description, &error)) { goto out; } } out: g_clear_error (&error); gtk_widget_hide (save_dialog); g_free (theme_name); g_free (theme_description); } static inline gboolean is_valid_theme_char (char c) { static const gchar *invalid_chars = "/?'\"\\|*."; const char *p; for (p = invalid_chars; *p != '\000'; p++) if (c == *p) return FALSE; return TRUE; } static void entry_text_filter (GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer data) { gint i; for (i = 0; i < length; i ++) { if (! is_valid_theme_char (text[i])) { g_signal_stop_emission_by_name (editable, "insert_text"); return; } } } static void entry_text_changed (GtkEditable *editable, gpointer data) { GladeXML *dialog = (GladeXML *) data; const gchar *text; text = gtk_entry_get_text (GTK_ENTRY (editable)); if (text != NULL && text[0] != '\000') gtk_widget_set_sensitive (WID ("save_dialog_save_button"), TRUE); else gtk_widget_set_sensitive (WID ("save_dialog_save_button"), FALSE); } void gnome_theme_save_show_dialog (GtkWidget *parent, GnomeThemeMetaInfo *meta_theme_info) { static GtkWidget *save_dialog = NULL; GladeXML *dialog; GtkWidget *entry; GtkWidget *text_view; GtkTextBuffer *text_buffer; dialog = gnome_theme_manager_get_theme_dialog (); entry = WID ("save_dialog_entry"); text_view = WID ("save_dialog_textview"); if (save_dialog == NULL) { save_dialog = WID ("save_dialog"); g_assert (save_dialog); g_signal_connect (G_OBJECT (save_dialog), "response", G_CALLBACK (save_dialog_response), NULL); g_signal_connect (G_OBJECT (save_dialog), "delete-event", G_CALLBACK (gtk_true), NULL); g_signal_connect (G_OBJECT (entry), "insert_text", G_CALLBACK (entry_text_filter), NULL); g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (entry_text_changed), dialog); error_quark = g_quark_from_string ("gnome-theme-save"); gtk_widget_set_size_request (text_view, 300, 100); } gtk_entry_set_text (GTK_ENTRY (entry), ""); entry_text_changed (GTK_EDITABLE (entry), dialog); gtk_widget_grab_focus (entry); text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view)); gtk_text_buffer_set_text (text_buffer, "", strlen ("")); g_object_set_data (G_OBJECT (save_dialog), "meta-theme-info", meta_theme_info); gtk_window_set_transient_for (GTK_WINDOW (save_dialog), GTK_WINDOW (parent)); gtk_widget_show (save_dialog); }