summaryrefslogtreecommitdiff
path: root/capplets/appearance/theme-save.c
diff options
context:
space:
mode:
Diffstat (limited to 'capplets/appearance/theme-save.c')
-rw-r--r--capplets/appearance/theme-save.c381
1 files changed, 381 insertions, 0 deletions
diff --git a/capplets/appearance/theme-save.c b/capplets/appearance/theme-save.c
new file mode 100644
index 00000000..f4981468
--- /dev/null
+++ b/capplets/appearance/theme-save.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2007 The MATE Foundation
+ * Written by Thomas Wood <[email protected]>
+ * Jens Granseuer <[email protected]>
+ * 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 <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "theme-save.h"
+#include "theme-util.h"
+#include "capplet-util.h"
+
+static GQuark error_quark;
+enum {
+ INVALID_THEME_NAME
+};
+
+/* taken from mate-desktop-item.c */
+static gchar *
+escape_string_and_dup (const gchar *s)
+{
+ gchar *return_value, *p;
+ const gchar *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 = (gchar *) 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 gchar *
+str_remove_slash (const gchar *src)
+{
+ const gchar *i;
+ gchar *rtn;
+ gint len = 0;
+ i = src;
+
+ while (*i) {
+ if (*i != '/')
+ len++;
+ i++;
+ }
+
+ rtn = (gchar *) g_malloc (len + 1);
+ while (*src) {
+ if (*src != '/') {
+ *rtn = *src;
+ rtn++;
+ }
+ src++;
+ }
+ *rtn = '\0';
+ return rtn - len;
+}
+
+static gboolean
+setup_directory_structure (const gchar *theme_name,
+ GError **error)
+{
+ gchar *dir, *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 *dialog;
+ GtkWidget *button;
+ gint response;
+
+ dialog = (GtkDialog *) gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_CANCEL,
+ _("The theme already exists. Would you like to replace it?"));
+ button = gtk_dialog_add_button (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 (dialog);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ retval = (response != GTK_RESPONSE_CANCEL);
+ }
+ g_free (dir);
+
+ return retval;
+}
+
+static gboolean
+write_theme_to_disk (MateThemeMetaInfo *theme_info,
+ const gchar *theme_name,
+ const gchar *theme_description,
+ gboolean save_background,
+ GError **error)
+{
+ gchar* dir;
+ gchar* theme_name_dir;
+ GFile* tmp_file;
+ GFile* target_file;
+ GOutputStream* output;
+
+ gchar* str;
+ gchar* current_background;
+
+ MateConfClient* client;
+ const gchar* 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->marco_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) {
+ gchar *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 = mateconf_client_get_default ();
+ current_background = mateconf_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 (MateThemeMetaInfo *theme_info,
+ const gchar *theme_name,
+ const gchar *theme_description,
+ gboolean save_background,
+ 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 (theme_info, theme_name, theme_description, save_background, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+save_dialog_response (GtkWidget *save_dialog,
+ gint response_id,
+ AppearanceData *data)
+{
+ if (response_id == GTK_RESPONSE_OK) {
+ GtkWidget *entry;
+ GtkWidget *text_view;
+ GtkTextBuffer *buffer;
+ GtkTextIter start_iter;
+ GtkTextIter end_iter;
+ gchar *buffer_text;
+ MateThemeMetaInfo *theme_info;
+ gchar *theme_description = NULL;
+ gchar *theme_name = NULL;
+ gboolean save_background;
+ GError *error = NULL;
+
+ entry = appearance_capplet_get_widget (data, "save_dialog_entry");
+ theme_name = escape_string_and_dup (gtk_entry_get_text (GTK_ENTRY (entry)));
+
+ text_view = appearance_capplet_get_widget (data, "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);
+ theme_info = (MateThemeMetaInfo *) g_object_get_data (G_OBJECT (save_dialog), "meta-theme-info");
+ save_background = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+ appearance_capplet_get_widget (data, "save_background_checkbutton")));
+
+ if (save_theme_to_disk (theme_info, theme_name, theme_description, save_background, &error)) {
+ /* remove the custom theme */
+ GtkTreeIter iter;
+
+ if (theme_find_in_model (GTK_TREE_MODEL (data->theme_store), "__custom__", &iter))
+ gtk_list_store_remove (data->theme_store, &iter);
+ }
+
+ g_free (theme_name);
+ g_free (theme_description);
+ g_clear_error (&error);
+ }
+
+ gtk_widget_hide (save_dialog);
+}
+
+static void
+entry_text_changed (GtkEditable *editable,
+ AppearanceData *data)
+{
+ const gchar *text;
+ GtkWidget *button;
+
+ text = gtk_entry_get_text (GTK_ENTRY (editable));
+ button = appearance_capplet_get_widget (data, "save_dialog_save_button");
+
+ gtk_widget_set_sensitive (button, text != NULL && text[0] != '\000');
+}
+
+void
+theme_save_dialog_run (MateThemeMetaInfo *theme_info,
+ AppearanceData *data)
+{
+ GtkWidget *entry;
+ GtkWidget *text_view;
+ GtkTextBuffer *text_buffer;
+
+ entry = appearance_capplet_get_widget (data, "save_dialog_entry");
+ text_view = appearance_capplet_get_widget (data, "save_dialog_textview");
+
+ if (data->theme_save_dialog == NULL) {
+ data->theme_save_dialog = appearance_capplet_get_widget (data, "theme_save_dialog");
+
+ g_signal_connect (data->theme_save_dialog, "response", (GCallback) save_dialog_response, data);
+ g_signal_connect (data->theme_save_dialog, "delete-event", (GCallback) gtk_true, NULL);
+ g_signal_connect (entry, "changed", (GCallback) entry_text_changed, data);
+
+ error_quark = g_quark_from_string ("mate-theme-save");
+ gtk_widget_set_size_request (text_view, 300, 100);
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (entry), "");
+ entry_text_changed (GTK_EDITABLE (entry), data);
+ gtk_widget_grab_focus (entry);
+
+ text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+ gtk_text_buffer_set_text (text_buffer, "", 0);
+ g_object_set_data (G_OBJECT (data->theme_save_dialog), "meta-theme-info", theme_info);
+ gtk_window_set_transient_for (GTK_WINDOW (data->theme_save_dialog),
+ GTK_WINDOW (appearance_capplet_get_widget (data, "appearance_window")));
+ gtk_widget_show (data->theme_save_dialog);
+}