1 | /* |
---|
2 | * Copyright (C) 1999 Dave Camp <dave@davec.dhs.org> |
---|
3 | * |
---|
4 | * This program is free software; you can redistribute it and/or modify |
---|
5 | * it under the terms of the GNU General Public License as published by |
---|
6 | * the Free Software Foundation; either version 2 of the License, or |
---|
7 | * (at your option) any later version. |
---|
8 | * |
---|
9 | * This program is distributed in the hope that it will be useful, |
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | * GNU General Public License for more details. |
---|
13 | * |
---|
14 | * You should have received a copy of the GNU General Public License |
---|
15 | * along with this program; if not, write to the Free Software |
---|
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
17 | * |
---|
18 | */ |
---|
19 | |
---|
20 | #include <config.h> |
---|
21 | #include <gnome.h> |
---|
22 | #include <string.h> |
---|
23 | #include <dirent.h> |
---|
24 | #include <limits.h> |
---|
25 | #include <ctype.h> |
---|
26 | |
---|
27 | #include <gconf/gconf-client.h> |
---|
28 | #include <panel-applet-gconf.h> |
---|
29 | #include <libgnomeui/gnome-help.h> |
---|
30 | #include "geyes.h" |
---|
31 | |
---|
32 | #define NUM_THEME_DIRECTORIES 2 |
---|
33 | #define HIG_IDENTATION " " |
---|
34 | |
---|
35 | gchar *theme_directories[NUM_THEME_DIRECTORIES]; |
---|
36 | |
---|
37 | void |
---|
38 | theme_dirs_create (void) |
---|
39 | { |
---|
40 | static gboolean themes_created = FALSE; |
---|
41 | |
---|
42 | if (themes_created == TRUE) |
---|
43 | return; |
---|
44 | |
---|
45 | theme_directories[0] = g_strdup (GEYES_THEMES_DIR); |
---|
46 | theme_directories[1] = g_strdup_printf ("%s/.gnome2/geyes-themes/", g_get_home_dir()); |
---|
47 | |
---|
48 | themes_created = TRUE; |
---|
49 | } |
---|
50 | |
---|
51 | static void |
---|
52 | parse_theme_file (EyesApplet *eyes_applet, FILE *theme_file) |
---|
53 | { |
---|
54 | gchar line_buf [512]; /* prolly overkill */ |
---|
55 | gchar *token; |
---|
56 | fgets (line_buf, 512, theme_file); |
---|
57 | while (!feof (theme_file)) { |
---|
58 | token = strtok (line_buf, "="); |
---|
59 | if (strncmp (token, "wall-thickness", |
---|
60 | strlen ("wall-thickness")) == 0) { |
---|
61 | token += strlen ("wall-thickness"); |
---|
62 | while (!isdigit (*token)) { |
---|
63 | token++; |
---|
64 | } |
---|
65 | sscanf (token, "%d", &eyes_applet->wall_thickness); |
---|
66 | } else if (strncmp (token, "num-eyes", strlen ("num-eyes")) == 0) { |
---|
67 | token += strlen ("num-eyes"); |
---|
68 | while (!isdigit (*token)) { |
---|
69 | token++; |
---|
70 | } |
---|
71 | sscanf (token, "%d", &eyes_applet->num_eyes); |
---|
72 | if (eyes_applet->num_eyes > MAX_EYES) |
---|
73 | eyes_applet->num_eyes = MAX_EYES; |
---|
74 | } else if (strncmp (token, "eye-pixmap", strlen ("eye-pixmap")) == 0) { |
---|
75 | token = strtok (NULL, "\""); |
---|
76 | token = strtok (NULL, "\""); |
---|
77 | if (eyes_applet->eye_filename != NULL) |
---|
78 | g_free (eyes_applet->eye_filename); |
---|
79 | eyes_applet->eye_filename = g_strdup_printf ("%s%s", |
---|
80 | eyes_applet->theme_dir, |
---|
81 | token); |
---|
82 | } else if (strncmp (token, "pupil-pixmap", strlen ("pupil-pixmap")) == 0) { |
---|
83 | token = strtok (NULL, "\""); |
---|
84 | token = strtok (NULL, "\""); |
---|
85 | if (eyes_applet->pupil_filename != NULL) |
---|
86 | g_free (eyes_applet->pupil_filename); |
---|
87 | eyes_applet->pupil_filename |
---|
88 | = g_strdup_printf ("%s%s", |
---|
89 | eyes_applet->theme_dir, |
---|
90 | token); |
---|
91 | } |
---|
92 | fgets (line_buf, 512, theme_file); |
---|
93 | } |
---|
94 | } |
---|
95 | |
---|
96 | int |
---|
97 | load_theme (EyesApplet *eyes_applet, const gchar *theme_dir) |
---|
98 | { |
---|
99 | GtkWidget *dialog; |
---|
100 | |
---|
101 | FILE* theme_file; |
---|
102 | gchar *file_name; |
---|
103 | |
---|
104 | eyes_applet->theme_dir = g_strdup_printf ("%s/", theme_dir); |
---|
105 | |
---|
106 | file_name = g_strdup_printf("%s%s",theme_dir,"/config"); |
---|
107 | theme_file = fopen (file_name, "r"); |
---|
108 | if (theme_file == NULL) { |
---|
109 | g_free (eyes_applet->theme_dir); |
---|
110 | eyes_applet->theme_dir = g_strdup_printf (GEYES_THEMES_DIR "Default-tiny/"); |
---|
111 | g_free (file_name); |
---|
112 | file_name = g_strdup (GEYES_THEMES_DIR "Default-tiny/config"); |
---|
113 | theme_file = fopen (file_name, "r"); |
---|
114 | } |
---|
115 | |
---|
116 | /* if it's still NULL we've got a major problem */ |
---|
117 | if (theme_file == NULL) { |
---|
118 | dialog = gtk_message_dialog_new_with_markup (NULL, |
---|
119 | GTK_DIALOG_DESTROY_WITH_PARENT, |
---|
120 | GTK_MESSAGE_ERROR, |
---|
121 | GTK_BUTTONS_OK, |
---|
122 | "<b>%s</b>\n\n%s", |
---|
123 | _("Can not launch the eyes applet."), |
---|
124 | _("There was a fatal error while trying to load the theme.")); |
---|
125 | |
---|
126 | gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); |
---|
127 | |
---|
128 | gtk_dialog_run (GTK_DIALOG (dialog)); |
---|
129 | gtk_widget_destroy (dialog); |
---|
130 | |
---|
131 | gtk_widget_destroy (GTK_WIDGET (eyes_applet->applet)); |
---|
132 | |
---|
133 | return FALSE; |
---|
134 | } |
---|
135 | |
---|
136 | parse_theme_file (eyes_applet, theme_file); |
---|
137 | fclose (theme_file); |
---|
138 | |
---|
139 | eyes_applet->theme_name = g_strdup (theme_dir); |
---|
140 | |
---|
141 | if (eyes_applet->eye_image) |
---|
142 | g_object_unref (eyes_applet->eye_image); |
---|
143 | eyes_applet->eye_image = gdk_pixbuf_new_from_file (eyes_applet->eye_filename, NULL); |
---|
144 | if (eyes_applet->pupil_image) |
---|
145 | g_object_unref (eyes_applet->pupil_image); |
---|
146 | eyes_applet->pupil_image = gdk_pixbuf_new_from_file (eyes_applet->pupil_filename, NULL); |
---|
147 | |
---|
148 | eyes_applet->eye_height = gdk_pixbuf_get_height (eyes_applet->eye_image); |
---|
149 | eyes_applet->eye_width = gdk_pixbuf_get_width (eyes_applet->eye_image); |
---|
150 | eyes_applet->pupil_height = gdk_pixbuf_get_height (eyes_applet->pupil_image); |
---|
151 | eyes_applet->pupil_width = gdk_pixbuf_get_width (eyes_applet->pupil_image); |
---|
152 | |
---|
153 | g_free (file_name); |
---|
154 | |
---|
155 | return TRUE; |
---|
156 | } |
---|
157 | |
---|
158 | static void |
---|
159 | destroy_theme (EyesApplet *eyes_applet) |
---|
160 | { |
---|
161 | /* Dunno about this - to unref or not to unref? */ |
---|
162 | if (eyes_applet->eye_image != NULL) { |
---|
163 | gdk_pixbuf_unref (eyes_applet->eye_image); |
---|
164 | eyes_applet->eye_image = NULL; |
---|
165 | } |
---|
166 | if (eyes_applet->pupil_image != NULL) { |
---|
167 | gdk_pixbuf_unref (eyes_applet->pupil_image); |
---|
168 | eyes_applet->pupil_image = NULL; |
---|
169 | } |
---|
170 | |
---|
171 | g_free (eyes_applet->theme_dir); |
---|
172 | g_free (eyes_applet->theme_name); |
---|
173 | } |
---|
174 | |
---|
175 | static gboolean |
---|
176 | key_writable (PanelApplet *applet, const char *key) |
---|
177 | { |
---|
178 | gboolean writable; |
---|
179 | char *fullkey; |
---|
180 | static GConfClient *client = NULL; |
---|
181 | |
---|
182 | if (client == NULL) |
---|
183 | client = gconf_client_get_default (); |
---|
184 | |
---|
185 | fullkey = panel_applet_gconf_get_full_key (applet, key); |
---|
186 | |
---|
187 | writable = gconf_client_key_is_writable (client, fullkey, NULL); |
---|
188 | |
---|
189 | g_free (fullkey); |
---|
190 | |
---|
191 | return writable; |
---|
192 | } |
---|
193 | |
---|
194 | static void |
---|
195 | theme_selected_cb (GtkTreeSelection *selection, gpointer data) |
---|
196 | { |
---|
197 | EyesApplet *eyes_applet = data; |
---|
198 | GtkTreeModel *model; |
---|
199 | GtkTreeIter iter; |
---|
200 | gchar *theme; |
---|
201 | gchar *theme_dir; |
---|
202 | |
---|
203 | if (!gtk_tree_selection_get_selected (selection, &model, &iter)) |
---|
204 | return; |
---|
205 | |
---|
206 | gtk_tree_model_get (model, &iter, 0, &theme, -1); |
---|
207 | |
---|
208 | g_return_if_fail (theme); |
---|
209 | |
---|
210 | theme_dir = g_strdup_printf ("%s/", theme); |
---|
211 | if (!g_ascii_strncasecmp (theme_dir, eyes_applet->theme_dir, strlen (theme_dir))) { |
---|
212 | g_free (theme_dir); |
---|
213 | return; |
---|
214 | } |
---|
215 | g_free (theme_dir); |
---|
216 | |
---|
217 | destroy_eyes (eyes_applet); |
---|
218 | destroy_theme (eyes_applet); |
---|
219 | load_theme (eyes_applet, theme); |
---|
220 | setup_eyes (eyes_applet); |
---|
221 | |
---|
222 | panel_applet_gconf_set_string ( |
---|
223 | eyes_applet->applet, "theme_path", theme, NULL); |
---|
224 | |
---|
225 | g_free (theme); |
---|
226 | } |
---|
227 | |
---|
228 | static void |
---|
229 | phelp_cb (GtkDialog *dialog) |
---|
230 | { |
---|
231 | GError *error = NULL; |
---|
232 | |
---|
233 | gnome_help_display_on_screen ( |
---|
234 | "geyes", "geyes-settings", |
---|
235 | gtk_window_get_screen (GTK_WINDOW (dialog)), |
---|
236 | &error); |
---|
237 | |
---|
238 | if (error) { /* FIXME: the user needs to see this */ |
---|
239 | g_warning ("help error: %s\n", error->message); |
---|
240 | g_error_free (error); |
---|
241 | error = NULL; |
---|
242 | } |
---|
243 | } |
---|
244 | |
---|
245 | static void |
---|
246 | presponse_cb (GtkDialog *dialog, gint id, gpointer data) |
---|
247 | { |
---|
248 | EyesApplet *eyes_applet = data; |
---|
249 | if(id == GTK_RESPONSE_HELP){ |
---|
250 | phelp_cb (dialog); |
---|
251 | return; |
---|
252 | } |
---|
253 | |
---|
254 | |
---|
255 | gtk_widget_destroy (GTK_WIDGET (dialog)); |
---|
256 | |
---|
257 | eyes_applet->prop_box.pbox = NULL; |
---|
258 | } |
---|
259 | |
---|
260 | void |
---|
261 | properties_cb (BonoboUIComponent *uic, |
---|
262 | EyesApplet *eyes_applet, |
---|
263 | const gchar *verbname) |
---|
264 | { |
---|
265 | GtkWidget *pbox, *hbox; |
---|
266 | GtkWidget *vbox, *indent; |
---|
267 | GtkWidget *categories_vbox; |
---|
268 | GtkWidget *category_vbox, *control_vbox; |
---|
269 | GtkWidget *tree; |
---|
270 | GtkWidget *scrolled; |
---|
271 | GtkWidget *label; |
---|
272 | GtkListStore *model; |
---|
273 | GtkTreeViewColumn *column; |
---|
274 | GtkCellRenderer *cell; |
---|
275 | GtkTreeSelection *selection; |
---|
276 | GtkTreeIter iter; |
---|
277 | DIR *dfd; |
---|
278 | struct dirent *dp; |
---|
279 | int i; |
---|
280 | #ifdef PATH_MAX |
---|
281 | gchar filename [PATH_MAX]; |
---|
282 | #else |
---|
283 | gchar *filename; |
---|
284 | #endif |
---|
285 | gchar *title; |
---|
286 | |
---|
287 | if (eyes_applet->prop_box.pbox) { |
---|
288 | gtk_window_set_screen ( |
---|
289 | GTK_WINDOW (eyes_applet->prop_box.pbox), |
---|
290 | gtk_widget_get_screen (GTK_WIDGET (eyes_applet->applet))); |
---|
291 | gtk_window_present (GTK_WINDOW (eyes_applet->prop_box.pbox)); |
---|
292 | return; |
---|
293 | } |
---|
294 | |
---|
295 | pbox = gtk_dialog_new_with_buttons (_("Geyes Preferences"), NULL, |
---|
296 | GTK_DIALOG_DESTROY_WITH_PARENT, |
---|
297 | GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, |
---|
298 | GTK_STOCK_HELP, GTK_RESPONSE_HELP, |
---|
299 | NULL); |
---|
300 | |
---|
301 | gtk_window_set_screen (GTK_WINDOW (pbox), |
---|
302 | gtk_widget_get_screen (GTK_WIDGET (eyes_applet->applet))); |
---|
303 | |
---|
304 | gtk_widget_set_size_request (GTK_WIDGET (pbox), 300, 200); |
---|
305 | gtk_window_set_resizable (GTK_WINDOW (pbox), FALSE); |
---|
306 | gtk_dialog_set_default_response(GTK_DIALOG (pbox), GTK_RESPONSE_CLOSE); |
---|
307 | gtk_dialog_set_has_separator (GTK_DIALOG (pbox), FALSE); |
---|
308 | gtk_container_set_border_width (GTK_CONTAINER (pbox), 5); |
---|
309 | gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (pbox)->vbox), 2); |
---|
310 | |
---|
311 | g_signal_connect (pbox, "response", |
---|
312 | G_CALLBACK (presponse_cb), |
---|
313 | eyes_applet); |
---|
314 | |
---|
315 | vbox = gtk_vbox_new (FALSE, 0); |
---|
316 | gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); |
---|
317 | gtk_widget_show (vbox); |
---|
318 | |
---|
319 | gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pbox)->vbox), vbox, |
---|
320 | TRUE, TRUE, 0); |
---|
321 | |
---|
322 | categories_vbox = gtk_vbox_new (FALSE, 18); |
---|
323 | gtk_box_pack_start (GTK_BOX (vbox), categories_vbox, TRUE, TRUE, 0); |
---|
324 | gtk_widget_show (categories_vbox); |
---|
325 | |
---|
326 | category_vbox = gtk_vbox_new (FALSE, 6); |
---|
327 | gtk_box_pack_start (GTK_BOX (categories_vbox), category_vbox, TRUE, TRUE, 0); |
---|
328 | gtk_widget_show (category_vbox); |
---|
329 | |
---|
330 | title = g_strconcat ("<span weight=\"bold\">", _("Themes"), "</span>", NULL); |
---|
331 | label = gtk_label_new (_(title)); |
---|
332 | gtk_label_set_use_markup (GTK_LABEL (label), TRUE); |
---|
333 | gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); |
---|
334 | gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); |
---|
335 | gtk_box_pack_start (GTK_BOX (category_vbox), label, FALSE, FALSE, 0); |
---|
336 | g_free (title); |
---|
337 | |
---|
338 | hbox = gtk_hbox_new (FALSE, 0); |
---|
339 | gtk_box_pack_start (GTK_BOX (category_vbox), hbox, TRUE, TRUE, 0); |
---|
340 | gtk_widget_show (hbox); |
---|
341 | |
---|
342 | indent = gtk_label_new (HIG_IDENTATION); |
---|
343 | gtk_label_set_justify (GTK_LABEL (indent), GTK_JUSTIFY_LEFT); |
---|
344 | gtk_box_pack_start (GTK_BOX (hbox), indent, FALSE, FALSE, 0); |
---|
345 | gtk_widget_show (indent); |
---|
346 | |
---|
347 | control_vbox = gtk_vbox_new (FALSE, 6); |
---|
348 | gtk_box_pack_start (GTK_BOX (hbox), control_vbox, TRUE, TRUE, 0); |
---|
349 | gtk_widget_show (control_vbox); |
---|
350 | |
---|
351 | label = gtk_label_new_with_mnemonic (_("_Select a theme:")); |
---|
352 | gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); |
---|
353 | gtk_box_pack_start (GTK_BOX (control_vbox), label, FALSE, FALSE, 0); |
---|
354 | |
---|
355 | scrolled = gtk_scrolled_window_new (NULL, NULL); |
---|
356 | gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); |
---|
357 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), |
---|
358 | GTK_POLICY_AUTOMATIC, |
---|
359 | GTK_POLICY_AUTOMATIC); |
---|
360 | |
---|
361 | model = gtk_list_store_new (1, G_TYPE_STRING); |
---|
362 | tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); |
---|
363 | gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree), FALSE); |
---|
364 | gtk_label_set_mnemonic_widget (GTK_LABEL (label), tree); |
---|
365 | g_object_unref (model); |
---|
366 | |
---|
367 | gtk_container_add (GTK_CONTAINER (scrolled), tree); |
---|
368 | |
---|
369 | cell = gtk_cell_renderer_text_new (); |
---|
370 | column = gtk_tree_view_column_new_with_attributes ("not used", cell, |
---|
371 | "text", 0, NULL); |
---|
372 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); |
---|
373 | |
---|
374 | selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)); |
---|
375 | g_signal_connect (selection, "changed", |
---|
376 | G_CALLBACK (theme_selected_cb), |
---|
377 | eyes_applet); |
---|
378 | |
---|
379 | if ( ! key_writable (eyes_applet->applet, "theme_path")) { |
---|
380 | gtk_widget_set_sensitive (tree, FALSE); |
---|
381 | gtk_widget_set_sensitive (label, FALSE); |
---|
382 | } |
---|
383 | |
---|
384 | for (i = 0; i < NUM_THEME_DIRECTORIES; i++) { |
---|
385 | if ((dfd = opendir (theme_directories[i])) != NULL) { |
---|
386 | while ((dp = readdir (dfd)) != NULL) { |
---|
387 | if (dp->d_name[0] != '.') { |
---|
388 | gchar *elems[2] = {NULL, NULL }; |
---|
389 | gchar *theme_dir; |
---|
390 | elems[0] = filename; |
---|
391 | #ifdef PATH_MAX |
---|
392 | strcpy (filename, |
---|
393 | theme_directories[i]); |
---|
394 | strcat (filename, dp->d_name); |
---|
395 | #else |
---|
396 | asprintf (&filename, theme_directories[i], dp->d_name); |
---|
397 | #endif |
---|
398 | gtk_list_store_insert (model, &iter, 0); |
---|
399 | gtk_list_store_set (model, &iter, 0, &filename, -1); |
---|
400 | theme_dir = g_strdup_printf ("%s/", filename); |
---|
401 | |
---|
402 | if (!g_ascii_strncasecmp (eyes_applet->theme_dir, theme_dir, strlen (theme_dir))) { |
---|
403 | GtkTreePath *path; |
---|
404 | path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), |
---|
405 | &iter); |
---|
406 | gtk_tree_view_set_cursor (GTK_TREE_VIEW (tree), |
---|
407 | path, |
---|
408 | NULL, |
---|
409 | FALSE); |
---|
410 | gtk_tree_path_free (path); |
---|
411 | } |
---|
412 | g_free (theme_dir); |
---|
413 | } |
---|
414 | } |
---|
415 | closedir (dfd); |
---|
416 | } |
---|
417 | } |
---|
418 | #ifndef PATH_MAX |
---|
419 | g_free (filename); |
---|
420 | #endif |
---|
421 | |
---|
422 | gtk_box_pack_start (GTK_BOX (control_vbox), scrolled, TRUE, TRUE, 0); |
---|
423 | |
---|
424 | gtk_widget_show_all (pbox); |
---|
425 | |
---|
426 | eyes_applet->prop_box.pbox = pbox; |
---|
427 | |
---|
428 | return; |
---|
429 | } |
---|
430 | |
---|
431 | |
---|