~kroq-gar78/ubuntu/precise/gnome-control-center/fix-885947

« back to all changes in this revision

Viewing changes to capplets/appearance/theme-save.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Moya
  • Date: 2011-05-17 10:47:27 UTC
  • mfrom: (0.1.11 experimental) (1.1.45 upstream)
  • Revision ID: james.westby@ubuntu.com-20110517104727-lqel6m8vhfw5jby1
Tags: 1:3.0.1.1-1ubuntu1
* Rebase on Debian, remaining Ubuntu changes:
* debian/control:
  - Build-Depend on hardening-wrapper, dpkg-dev and dh-autoreconf
  - Add dependency on ubuntu-system-service
  - Remove dependency on gnome-icon-theme-symbolic
  - Move dependency on apg, gnome-icon-theme-symbolic and accountsservice to
    be a Recommends: until we get them in main
* debian/rules:
  - Use autoreconf
  - Add binary-post-install rule for gnome-control-center-data
  - Run dh-autoreconf
* debian/gnome-control-center.dirs:
* debian/gnome-control-center.links:
  - Add a link to the control center shell for indicators
* debian/patches/00_disable-nm.patch:
  - Temporary patch to disable building with NetworkManager until we get
    the new one in the archive
* debian/patches/01_git_remove_gettext_calls.patch:
  - Remove calls to AM_GNU_GETTEXT, IT_PROG_INTLTOOL should be enough
* debian/patches/01_git_kill_warning.patch:
  - Kill warning
* debian/patches/50_ubuntu_systemwide_prefs.patch:
  - Ubuntu specific proxy preferences
* debian/patches/51_ubuntu_system_keyboard.patch:
  - Implement the global keyboard spec at https://wiki.ubuntu.com/DefaultKeyboardSettings

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2007 The GNOME Foundation
3
 
 * Written by Thomas Wood <thos@gnome.org>
4
 
 *            Jens Granseuer <jensgr@gmx.net>
5
 
 * All Rights Reserved
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; either version 2 of the License, or
10
 
 * (at your option) any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License along
18
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 
 */
21
 
 
22
 
#include "appearance.h"
23
 
 
24
 
#include <glib/gstdio.h>
25
 
#include <glib/gi18n.h>
26
 
#include <string.h>
27
 
 
28
 
#include "theme-save.h"
29
 
#include "theme-util.h"
30
 
#include "capplet-util.h"
31
 
 
32
 
static GQuark error_quark;
33
 
enum {
34
 
  INVALID_THEME_NAME
35
 
};
36
 
 
37
 
/* taken from gnome-desktop-item.c */
38
 
static gchar *
39
 
escape_string_and_dup (const gchar *s)
40
 
{
41
 
  gchar *return_value, *p;
42
 
  const gchar *q;
43
 
  int len = 0;
44
 
 
45
 
  if (s == NULL)
46
 
    return g_strdup("");
47
 
 
48
 
  q = s;
49
 
  while (*q)
50
 
    {
51
 
      len++;
52
 
      if (strchr ("\n\r\t\\", *q) != NULL)
53
 
        len++;
54
 
      q++;
55
 
    }
56
 
  return_value = p = (gchar *) g_malloc (len + 1);
57
 
  do
58
 
    {
59
 
      switch (*s)
60
 
        {
61
 
        case '\t':
62
 
          *p++ = '\\';
63
 
          *p++ = 't';
64
 
          break;
65
 
        case '\n':
66
 
          *p++ = '\\';
67
 
          *p++ = 'n';
68
 
          break;
69
 
        case '\r':
70
 
          *p++ = '\\';
71
 
          *p++ = 'r';
72
 
          break;
73
 
        case '\\':
74
 
          *p++ = '\\';
75
 
          *p++ = '\\';
76
 
          break;
77
 
        default:
78
 
          *p++ = *s;
79
 
        }
80
 
    }
81
 
  while (*s++);
82
 
  return return_value;
83
 
}
84
 
 
85
 
static gboolean
86
 
check_theme_name (const gchar  *theme_name,
87
 
                  GError      **error)
88
 
{
89
 
  if (theme_name == NULL) {
90
 
    g_set_error (error,
91
 
                 error_quark,
92
 
                 INVALID_THEME_NAME,
93
 
                 _("Theme name must be present"));
94
 
    return FALSE;
95
 
  }
96
 
  return TRUE;
97
 
}
98
 
 
99
 
static gchar *
100
 
str_remove_slash (const gchar *src)
101
 
{
102
 
  const gchar *i;
103
 
  gchar *rtn;
104
 
  gint len = 0;
105
 
  i = src;
106
 
 
107
 
  while (*i) {
108
 
    if (*i != '/')
109
 
      len++;
110
 
    i++;
111
 
  }
112
 
 
113
 
  rtn = (gchar *) g_malloc (len + 1);
114
 
  while (*src) {
115
 
    if (*src != '/') {
116
 
      *rtn = *src;
117
 
      rtn++;
118
 
    }
119
 
    src++;
120
 
  }
121
 
  *rtn = '\0';
122
 
  return rtn - len;
123
 
}
124
 
 
125
 
static gboolean
126
 
setup_directory_structure (const gchar  *theme_name,
127
 
                           GError      **error)
128
 
{
129
 
  gchar *dir, *theme_name_dir;
130
 
  gboolean retval = TRUE;
131
 
 
132
 
  theme_name_dir = str_remove_slash (theme_name);
133
 
 
134
 
  dir = g_build_filename (g_get_home_dir (), ".themes", NULL);
135
 
  if (!g_file_test (dir, G_FILE_TEST_EXISTS))
136
 
    g_mkdir (dir, 0775);
137
 
  g_free (dir);
138
 
 
139
 
  dir = g_build_filename (g_get_home_dir (), ".themes", theme_name_dir, NULL);
140
 
  if (!g_file_test (dir, G_FILE_TEST_EXISTS))
141
 
    g_mkdir (dir, 0775);
142
 
  g_free (dir);
143
 
 
144
 
  dir = g_build_filename (g_get_home_dir (), ".themes", theme_name_dir, "index.theme", NULL);
145
 
  g_free (theme_name_dir);
146
 
 
147
 
  if (g_file_test (dir, G_FILE_TEST_EXISTS)) {
148
 
    GtkDialog *dialog;
149
 
    GtkWidget *button;
150
 
    gint response;
151
 
 
152
 
    dialog = (GtkDialog *) gtk_message_dialog_new (NULL,
153
 
                                                   GTK_DIALOG_MODAL,
154
 
                                                   GTK_MESSAGE_QUESTION,
155
 
                                                   GTK_BUTTONS_CANCEL,
156
 
                                                   _("The theme already exists. Would you like to replace it?"));
157
 
    button = gtk_dialog_add_button (dialog, _("_Overwrite"), GTK_RESPONSE_ACCEPT);
158
 
    gtk_button_set_image (GTK_BUTTON (button),
159
 
                          gtk_image_new_from_stock (GTK_STOCK_SAVE, GTK_ICON_SIZE_BUTTON));
160
 
    response = gtk_dialog_run (dialog);
161
 
    gtk_widget_destroy (GTK_WIDGET (dialog));
162
 
    retval = (response != GTK_RESPONSE_CANCEL);
163
 
  }
164
 
  g_free (dir);
165
 
 
166
 
  return retval;
167
 
}
168
 
 
169
 
static gboolean
170
 
write_theme_to_disk (GnomeThemeMetaInfo  *theme_info,
171
 
                     const gchar         *theme_name,
172
 
                     const gchar         *theme_description,
173
 
                     gboolean             save_background,
174
 
                     GError             **error)
175
 
{
176
 
  gchar *dir, *theme_name_dir;
177
 
  GFile *tmp_file;
178
 
  GFile *target_file;
179
 
  GOutputStream *output;
180
 
 
181
 
  gchar *str, *current_background;
182
 
  GConfClient *client;
183
 
  const gchar *theme_header =
184
 
      "[Desktop Entry]\n"
185
 
      "Name=%s\n"
186
 
      "Type=X-GNOME-Metatheme\n"
187
 
      "Comment=%s\n"
188
 
      "\n"
189
 
      "[X-GNOME-Metatheme]\n"
190
 
      "GtkTheme=%s\n"
191
 
      "MetacityTheme=%s\n"
192
 
      "IconTheme=%s\n";
193
 
 
194
 
  theme_name_dir = str_remove_slash (theme_name);
195
 
  dir = g_build_filename (g_get_home_dir (), ".themes", theme_name_dir, "index.theme~", NULL);
196
 
  g_free (theme_name_dir);
197
 
 
198
 
  tmp_file = g_file_new_for_path (dir);
199
 
  dir [strlen (dir) - 1] = '\000';
200
 
  target_file = g_file_new_for_path (dir);
201
 
  g_free (dir);
202
 
 
203
 
  /* start making the theme file */
204
 
  str = g_strdup_printf (theme_header, theme_name, theme_description,
205
 
                         theme_info->gtk_theme_name,
206
 
                         theme_info->metacity_theme_name,
207
 
                         theme_info->icon_theme_name);
208
 
 
209
 
  output = G_OUTPUT_STREAM (g_file_replace (tmp_file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
210
 
  g_output_stream_write (output, str, strlen (str), NULL, NULL);
211
 
  g_free (str);
212
 
 
213
 
  if (theme_info->gtk_color_scheme) {
214
 
    gchar *a, *tmp;
215
 
    tmp = g_strdup (theme_info->gtk_color_scheme);
216
 
    for (a = tmp; *a != '\0'; a++)
217
 
      if (*a == '\n')
218
 
        *a = ',';
219
 
    str = g_strdup_printf ("GtkColorScheme=%s\n", tmp);
220
 
    g_output_stream_write (output, str, strlen (str), NULL, NULL);
221
 
 
222
 
    g_free (str);
223
 
    g_free (tmp);
224
 
  }
225
 
 
226
 
  if (theme_info->cursor_theme_name) {
227
 
#ifdef HAVE_XCURSOR
228
 
    str = g_strdup_printf ("CursorTheme=%s\n"
229
 
                           "CursorSize=%i\n",
230
 
                           theme_info->cursor_theme_name,
231
 
                           theme_info->cursor_size);
232
 
#else
233
 
    str = g_strdup_printf ("CursorFont=%s\n", theme_info->cursor_theme_name);
234
 
#endif
235
 
    g_output_stream_write (output, str, strlen (str), NULL, NULL);
236
 
    g_free (str);
237
 
  }
238
 
 
239
 
  if (theme_info->notification_theme_name) {
240
 
    str = g_strdup_printf ("NotificationTheme=%s\n", theme_info->notification_theme_name);
241
 
    g_output_stream_write (output, str, strlen (str), NULL, NULL);
242
 
    g_free (str);
243
 
  }
244
 
 
245
 
  if (save_background) {
246
 
    client = gconf_client_get_default ();
247
 
    current_background = gconf_client_get_string (client, BACKGROUND_KEY, NULL);
248
 
 
249
 
    if (current_background != NULL) {
250
 
      str = g_strdup_printf ("BackgroundImage=%s\n", current_background);
251
 
 
252
 
      g_output_stream_write (output, str, strlen (str), NULL, NULL);
253
 
 
254
 
      g_free (current_background);
255
 
      g_free (str);
256
 
    }
257
 
    g_object_unref (client);
258
 
  }
259
 
 
260
 
  g_file_move (tmp_file, target_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL);
261
 
  g_output_stream_close (output, NULL, NULL);
262
 
 
263
 
  g_object_unref (tmp_file);
264
 
  g_object_unref (target_file);
265
 
 
266
 
  return TRUE;
267
 
}
268
 
 
269
 
static gboolean
270
 
save_theme_to_disk (GnomeThemeMetaInfo  *theme_info,
271
 
                    const gchar         *theme_name,
272
 
                    const gchar         *theme_description,
273
 
                    gboolean             save_background,
274
 
                    GError             **error)
275
 
{
276
 
  if (!check_theme_name (theme_name, error))
277
 
    return FALSE;
278
 
 
279
 
  if (!setup_directory_structure (theme_name, error))
280
 
    return FALSE;
281
 
 
282
 
  if (!write_theme_to_disk (theme_info, theme_name, theme_description, save_background, error))
283
 
    return FALSE;
284
 
 
285
 
  return TRUE;
286
 
}
287
 
 
288
 
static void
289
 
save_dialog_response (GtkWidget      *save_dialog,
290
 
                      gint            response_id,
291
 
                      AppearanceData *data)
292
 
{
293
 
  if (response_id == GTK_RESPONSE_OK) {
294
 
    GtkWidget *entry;
295
 
    GtkWidget *text_view;
296
 
    GtkTextBuffer *buffer;
297
 
    GtkTextIter start_iter;
298
 
    GtkTextIter end_iter;
299
 
    gchar *buffer_text;
300
 
    GnomeThemeMetaInfo *theme_info;
301
 
    gchar *theme_description = NULL;
302
 
    gchar *theme_name = NULL;
303
 
    gboolean save_background;
304
 
    GError *error = NULL;
305
 
 
306
 
    entry = appearance_capplet_get_widget (data, "save_dialog_entry");
307
 
    theme_name = escape_string_and_dup (gtk_entry_get_text (GTK_ENTRY (entry)));
308
 
 
309
 
    text_view = appearance_capplet_get_widget (data, "save_dialog_textview");
310
 
    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
311
 
    gtk_text_buffer_get_start_iter (buffer, &start_iter);
312
 
    gtk_text_buffer_get_end_iter (buffer, &end_iter);
313
 
    buffer_text = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
314
 
    theme_description = escape_string_and_dup (buffer_text);
315
 
    g_free (buffer_text);
316
 
    theme_info = (GnomeThemeMetaInfo *) g_object_get_data (G_OBJECT (save_dialog), "meta-theme-info");
317
 
    save_background = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
318
 
                      appearance_capplet_get_widget (data, "save_background_checkbutton")));
319
 
 
320
 
    if (save_theme_to_disk (theme_info, theme_name, theme_description, save_background, &error)) {
321
 
      /* remove the custom theme */
322
 
      GtkTreeIter iter;
323
 
 
324
 
      if (theme_find_in_model (GTK_TREE_MODEL (data->theme_store), "__custom__", &iter))
325
 
        gtk_list_store_remove (data->theme_store, &iter);
326
 
    }
327
 
 
328
 
    g_free (theme_name);
329
 
    g_free (theme_description);
330
 
    g_clear_error (&error);
331
 
  }
332
 
 
333
 
  gtk_widget_hide (save_dialog);
334
 
}
335
 
 
336
 
static void
337
 
entry_text_changed (GtkEditable *editable,
338
 
                    AppearanceData  *data)
339
 
{
340
 
  const gchar *text;
341
 
  GtkWidget *button;
342
 
 
343
 
  text = gtk_entry_get_text (GTK_ENTRY (editable));
344
 
  button = appearance_capplet_get_widget (data, "save_dialog_save_button");
345
 
 
346
 
  gtk_widget_set_sensitive (button, text != NULL && text[0] != '\000');
347
 
}
348
 
 
349
 
void
350
 
theme_save_dialog_run (GnomeThemeMetaInfo *theme_info,
351
 
                       AppearanceData     *data)
352
 
{
353
 
  GtkWidget *entry;
354
 
  GtkWidget *text_view;
355
 
  GtkTextBuffer *text_buffer;
356
 
 
357
 
  entry = appearance_capplet_get_widget (data, "save_dialog_entry");
358
 
  text_view = appearance_capplet_get_widget (data, "save_dialog_textview");
359
 
 
360
 
  if (data->theme_save_dialog == NULL) {
361
 
    data->theme_save_dialog = appearance_capplet_get_widget (data, "theme_save_dialog");
362
 
 
363
 
    g_signal_connect (data->theme_save_dialog, "response", (GCallback) save_dialog_response, data);
364
 
    g_signal_connect (data->theme_save_dialog, "delete-event", (GCallback) gtk_true, NULL);
365
 
    g_signal_connect (entry, "changed", (GCallback) entry_text_changed, data);
366
 
 
367
 
    error_quark = g_quark_from_string ("gnome-theme-save");
368
 
    gtk_widget_set_size_request (text_view, 300, 100);
369
 
  }
370
 
 
371
 
  gtk_entry_set_text (GTK_ENTRY (entry), "");
372
 
  entry_text_changed (GTK_EDITABLE (entry), data);
373
 
  gtk_widget_grab_focus (entry);
374
 
 
375
 
  text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
376
 
  gtk_text_buffer_set_text (text_buffer, "", 0);
377
 
  g_object_set_data (G_OBJECT (data->theme_save_dialog), "meta-theme-info", theme_info);
378
 
  gtk_window_set_transient_for (GTK_WINDOW (data->theme_save_dialog),
379
 
                                GTK_WINDOW (appearance_capplet_get_widget (data, "appearance_window")));
380
 
  gtk_widget_show (data->theme_save_dialog);
381
 
}