Updated Slovenian translation
[nautilus.git] / libnautilus-private / nautilus-directory-background.c
blobb5798cb30607e84b86117da0f49371dc1589b34a
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
3 /*
4 nautilus-directory-background.c: Helper for the background of a widget
5 that is viewing a particular location.
7 Copyright (C) 2000 Eazel, Inc.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public
20 License along with this program; if not, write to the
21 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.
24 Author: Darin Adler <darin@bentspoon.com>
27 #include <config.h>
28 #include "nautilus-directory-background.h"
30 #include <eel/eel-gdk-extensions.h>
31 #include <eel/eel-gtk-extensions.h>
32 #include <eel/eel-background.h>
33 #include "nautilus-dnd.h"
34 #include "nautilus-global-preferences.h"
35 #include "nautilus-metadata.h"
36 #include "nautilus-file-attributes.h"
37 #include <gtk/gtkmain.h>
38 #include <libbackground/preferences.h>
40 static void background_changed_callback (EelBackground *background,
41 GdkDragAction action,
42 NautilusFile *file);
43 static void background_reset_callback (EelBackground *background,
44 NautilusFile *file);
46 static void saved_settings_changed_callback (NautilusFile *file,
47 EelBackground *background);
49 static void nautilus_file_background_receive_gconf_changes (EelBackground *background);
51 static void nautilus_file_background_write_desktop_settings (char *color,
52 char *image,
53 EelBackgroundImagePlacement placement);
54 static void nautilus_file_background_theme_changed (gpointer user_data);
56 void
57 nautilus_connect_desktop_background_to_file_metadata (NautilusIconContainer *icon_container,
58 NautilusFile *file)
60 EelBackground *background;
62 background = eel_get_widget_background (GTK_WIDGET (icon_container));
64 eel_background_set_desktop (background, GTK_WIDGET (icon_container), TRUE);
66 /* Strictly speaking, we don't need to know about metadata changes, since
67 * the desktop setting aren't stored there. But, hooking up to metadata
68 * changes is actually a small part of what this fn does, and we do need
69 * the other stuff (hooked up to background & theme changes, initialize
70 * the background). Being notified of metadata changes on the file is a
71 * waste, but won't hurt, so I don't think it's worth refactoring the fn
72 * at this point.
74 nautilus_connect_background_to_file_metadata (GTK_WIDGET (icon_container), file, NAUTILUS_DND_ACTION_SET_AS_FOLDER_BACKGROUND);
76 nautilus_file_background_receive_gconf_changes (background);
79 static void
80 nautilus_file_background_get_default_settings (char **color,
81 char **image,
82 EelBackgroundImagePlacement *placement)
84 gboolean background_set;
86 background_set = eel_preferences_get_boolean
87 (NAUTILUS_PREFERENCES_BACKGROUND_SET);
89 if (background_set && color) {
90 *color = eel_preferences_get (NAUTILUS_PREFERENCES_BACKGROUND_COLOR);
93 if (background_set && image) {
94 *image = eel_preferences_get (NAUTILUS_PREFERENCES_BACKGROUND_FILENAME);
97 if (placement) {
98 *placement = EEL_BACKGROUND_TILED;
103 static void
104 nautilus_file_background_read_desktop_settings (char **color,
105 char **image,
106 EelBackgroundImagePlacement *placement)
108 char *end_color;
109 char *start_color;
110 gboolean use_gradient;
111 gboolean is_horizontal;
113 BGPreferences *prefs;
115 prefs = BG_PREFERENCES (bg_preferences_new ());
117 bg_preferences_load (prefs);
119 if (prefs->wallpaper_enabled) {
120 if (prefs->wallpaper_filename != NULL &&
121 prefs->wallpaper_filename [0] != '\0') {
122 *image = g_filename_to_uri (prefs->wallpaper_filename, NULL, NULL);
123 } else {
124 *image = NULL;
127 else {
128 *image = NULL;
131 switch (prefs->wallpaper_type) {
132 default:
133 g_assert_not_reached ();
135 /* case WPTYPE_EMBOSSED:*/
136 /* FIXME bugzilla.gnome.org 42193: we don't support embossing.
137 * Just treat it as centered - ugh.
139 case WPTYPE_CENTERED:
140 *placement = EEL_BACKGROUND_CENTERED;
141 break;
142 case WPTYPE_TILED:
143 *placement = EEL_BACKGROUND_TILED;
144 break;
145 case WPTYPE_STRETCHED:
146 *placement = EEL_BACKGROUND_SCALED;
147 break;
148 case WPTYPE_SCALED:
149 *placement = EEL_BACKGROUND_SCALED_ASPECT;
150 break;
151 case WPTYPE_ZOOM:
152 *placement = EEL_BACKGROUND_ZOOM;
153 break;
156 end_color = eel_gdk_rgb_to_color_spec (eel_gdk_color_to_rgb (prefs->color2));
157 start_color = eel_gdk_rgb_to_color_spec (eel_gdk_color_to_rgb (prefs->color1));
158 use_gradient = prefs->gradient_enabled;
159 is_horizontal = (prefs->orientation == ORIENTATION_HORIZ);
161 if (use_gradient) {
162 *color = eel_gradient_new (start_color, end_color, is_horizontal);
163 } else {
164 *color = g_strdup (start_color);
167 g_free (start_color);
168 g_free (end_color);
170 g_object_unref (prefs);
173 static void
174 nautilus_file_background_write_desktop_settings (char *color, char *image, EelBackgroundImagePlacement placement)
176 char *end_color;
177 char *start_color;
178 char *original_filename;
180 wallpaper_type_t wallpaper_align;
181 BGPreferences *prefs;
183 prefs = BG_PREFERENCES (bg_preferences_new ());
184 bg_preferences_load (prefs);
186 if (color != NULL) {
187 start_color = eel_gradient_get_start_color_spec (color);
188 gdk_color_parse (start_color, prefs->color1);
189 g_free (start_color);
191 /* if color is not a gradient, this ends up writing same as start_color */
192 end_color = eel_gradient_get_end_color_spec (color);
193 gdk_color_parse (end_color, prefs->color2);
194 g_free (end_color);
196 if (eel_gradient_is_gradient (color)) {
197 prefs->gradient_enabled = TRUE;
198 prefs->orientation = eel_gradient_is_horizontal (color) ? ORIENTATION_HORIZ : ORIENTATION_VERT;
199 } else {
200 prefs->gradient_enabled = FALSE;
201 prefs->orientation = ORIENTATION_SOLID;
203 } else {
204 /* We set it to white here because that's how backgrounds with a NULL color
205 * are drawn by Nautilus - due to usage of eel_gdk_color_parse_with_white_default.
207 gdk_color_parse ("#FFFFFF", prefs->color1);
208 gdk_color_parse ("#FFFFFF", prefs->color2);
209 prefs->gradient_enabled = FALSE;
210 prefs->orientation = ORIENTATION_SOLID;
213 original_filename = prefs->wallpaper_filename;
214 if (image != NULL) {
215 prefs->wallpaper_filename = g_filename_from_uri (image, NULL, NULL);
216 prefs->wallpaper_enabled = TRUE;
217 switch (placement) {
218 case EEL_BACKGROUND_TILED:
219 wallpaper_align = WPTYPE_TILED;
220 break;
221 case EEL_BACKGROUND_CENTERED:
222 wallpaper_align = WPTYPE_CENTERED;
223 break;
224 case EEL_BACKGROUND_SCALED:
225 wallpaper_align = WPTYPE_STRETCHED;
226 break;
227 case EEL_BACKGROUND_SCALED_ASPECT:
228 wallpaper_align = WPTYPE_SCALED;
229 break;
230 case EEL_BACKGROUND_ZOOM:
231 wallpaper_align = WPTYPE_ZOOM;
232 break;
233 default:
234 g_assert_not_reached ();
235 wallpaper_align = WPTYPE_TILED;
236 break;
239 prefs->wallpaper_type = wallpaper_align;
240 } else {
241 prefs->wallpaper_enabled = FALSE;
242 prefs->wallpaper_filename = g_strdup (original_filename);
244 g_free (original_filename);
246 bg_preferences_save (prefs);
247 g_object_unref (prefs);
250 static void
251 nautilus_file_background_write_desktop_default_settings (void)
253 /* We just unset all the gconf keys so they go back to
254 * defaults
256 GConfClient *client;
257 GConfChangeSet *set;
259 client = gconf_client_get_default ();
260 set = gconf_change_set_new ();
262 /* the list of keys here has to be kept in sync with libgnome
263 * schemas, which isn't the most maintainable thing ever.
265 gconf_change_set_unset (set, "/desktop/gnome/background/picture_options");
266 gconf_change_set_unset (set, "/desktop/gnome/background/picture_filename");
267 gconf_change_set_unset (set, "/desktop/gnome/background/picture_opacity");
268 gconf_change_set_unset (set, "/desktop/gnome/background/primary_color");
269 gconf_change_set_unset (set, "/desktop/gnome/background/secondary_color");
270 gconf_change_set_unset (set, "/desktop/gnome/background/color_shading_type");
272 /* this isn't atomic yet so it'll be a bit inefficient, but
273 * someday it might be atomic.
275 gconf_client_commit_change_set (client, set, FALSE, NULL);
277 gconf_change_set_unref (set);
279 g_object_unref (G_OBJECT (client));
282 static int
283 call_settings_changed (EelBackground *background)
285 NautilusFile *file;
286 file = g_object_get_data (G_OBJECT (background), "eel_background_file");
287 if (file) {
288 saved_settings_changed_callback (file, background);
290 g_object_set_data (G_OBJECT (background), "desktop_gconf_notification_timeout", GUINT_TO_POINTER (0));
291 return FALSE;
294 static void
295 desktop_background_destroyed_callback (EelBackground *background, void *georgeWBush)
297 guint notification_id;
298 guint notification_timeout_id;
300 notification_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (background), "desktop_gconf_notification"));
301 eel_gconf_notification_remove (notification_id);
303 notification_timeout_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (background), "desktop_gconf_notification_timeout"));
304 if (notification_timeout_id != 0) {
305 g_source_remove (notification_timeout_id);
309 static void
310 desktop_background_gconf_notify_cb (GConfClient *client, guint notification_id, GConfEntry *entry, gpointer data)
312 EelBackground *background;
313 guint notification_timeout_id;
315 background = EEL_BACKGROUND (data);
317 * Wallpaper capplet changes picture, background color and placement with
318 * gconf_change_set API, but unfortunately, this operation is not atomic in
319 * GConf as it should be. So we update background after small timeout to
320 * let GConf change all values.
322 notification_timeout_id = g_timeout_add (300, (GSourceFunc) call_settings_changed, background);
324 g_object_set_data (G_OBJECT (background), "desktop_gconf_notification_timeout", GUINT_TO_POINTER (notification_timeout_id));
327 static void
328 nautilus_file_background_receive_gconf_changes (EelBackground *background)
330 guint notification_id;
332 eel_gconf_monitor_add ("/desktop/gnome/background");
333 notification_id = eel_gconf_notification_add ("/desktop/gnome/background", desktop_background_gconf_notify_cb, background);
335 g_object_set_data (G_OBJECT (background), "desktop_gconf_notification", GUINT_TO_POINTER (notification_id));
337 g_signal_connect (background, "destroy",
338 G_CALLBACK (desktop_background_destroyed_callback), NULL);
341 /* return true if the background is not in the default state */
342 gboolean
343 nautilus_file_background_is_set (EelBackground *background)
345 char *color;
346 char *image;
348 gboolean is_set;
350 color = eel_background_get_color (background);
351 image = eel_background_get_image_uri (background);
353 is_set = (color || image);
355 g_free (color);
356 g_free (image);
358 return is_set;
361 /* handle the background changed signal */
362 static void
363 background_changed_callback (EelBackground *background,
364 GdkDragAction action,
365 NautilusFile *file)
367 char *color;
368 char *image;
370 g_assert (EEL_IS_BACKGROUND (background));
371 g_assert (NAUTILUS_IS_FILE (file));
372 g_assert (g_object_get_data (G_OBJECT (background), "eel_background_file") == file);
375 color = eel_background_get_color (background);
376 image = eel_background_get_image_uri (background);
378 if (eel_background_is_desktop (background)) {
379 nautilus_file_background_write_desktop_settings (color, image, eel_background_get_image_placement (background));
380 } else {
381 /* Block the other handler while we are writing metadata so it doesn't
382 * try to change the background.
384 g_signal_handlers_block_by_func (
385 file, G_CALLBACK (saved_settings_changed_callback), background);
387 if (action != NAUTILUS_DND_ACTION_SET_AS_FOLDER_BACKGROUND && action != NAUTILUS_DND_ACTION_SET_AS_GLOBAL_BACKGROUND) {
388 GdkDragAction default_drag_action;
390 default_drag_action = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (background), "default_drag_action"));
393 action = default_drag_action;
396 if (action == NAUTILUS_DND_ACTION_SET_AS_GLOBAL_BACKGROUND) {
397 nautilus_file_set_metadata (file,
398 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR,
399 NULL,
400 NULL);
402 nautilus_file_set_metadata (file,
403 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE,
404 NULL,
405 NULL);
407 eel_preferences_set
408 (NAUTILUS_PREFERENCES_BACKGROUND_COLOR, color ? color : "");
409 eel_preferences_set
410 (NAUTILUS_PREFERENCES_BACKGROUND_FILENAME, image ? image : "");
411 eel_preferences_set_boolean
412 (NAUTILUS_PREFERENCES_BACKGROUND_SET, TRUE);
413 } else {
414 nautilus_file_set_metadata (file,
415 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR,
416 NULL,
417 color);
419 nautilus_file_set_metadata (file,
420 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE,
421 NULL,
422 image);
425 /* Unblock the handler. */
426 g_signal_handlers_unblock_by_func (
427 file, G_CALLBACK (saved_settings_changed_callback), background);
430 g_free (color);
431 g_free (image);
434 static void
435 initialize_background_from_settings (NautilusFile *file,
436 EelBackground *background)
438 char *color;
439 char *image;
440 EelBackgroundImagePlacement placement;
442 g_assert (NAUTILUS_IS_FILE (file));
443 g_assert (EEL_IS_BACKGROUND (background));
444 g_assert (g_object_get_data (G_OBJECT (background), "eel_background_file")
445 == file);
447 if (eel_background_is_desktop (background)) {
448 nautilus_file_background_read_desktop_settings (&color, &image, &placement);
449 } else {
450 color = nautilus_file_get_metadata (file,
451 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR,
452 NULL);
453 image = nautilus_file_get_metadata (file,
454 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE,
455 NULL);
456 placement = EEL_BACKGROUND_TILED; /* non-tiled only avail for desktop, at least for now */
458 /* if there's none, read the default from the theme */
459 if (color == NULL && image == NULL) {
460 nautilus_file_background_get_default_settings
461 (&color, &image, &placement);
465 /* Block the other handler while we are responding to changes
466 * in the metadata so it doesn't try to change the metadata.
468 g_signal_handlers_block_by_func
469 (background,
470 G_CALLBACK (background_changed_callback),
471 file);
473 eel_background_set_color (background, color);
474 if (eel_background_is_desktop(background)) {
475 eel_background_set_image_uri_sync (background, image);
477 else {
478 eel_background_set_image_uri (background, image);
480 eel_background_set_image_placement (background, placement);
482 /* Unblock the handler. */
483 g_signal_handlers_unblock_by_func
484 (background,
485 G_CALLBACK (background_changed_callback),
486 file);
488 g_free (color);
489 g_free (image);
492 /* handle the file changed signal */
493 static void
494 saved_settings_changed_callback (NautilusFile *file,
495 EelBackground *background)
497 initialize_background_from_settings (file, background);
500 /* handle the theme changing */
501 static void
502 nautilus_file_background_theme_changed (gpointer user_data)
504 NautilusFile *file;
505 EelBackground *background;
507 background = EEL_BACKGROUND (user_data);
508 file = g_object_get_data (G_OBJECT (background), "eel_background_file");
509 if (file) {
510 saved_settings_changed_callback (file, background);
514 /* handle the background reset signal by setting values from the current theme */
515 static void
516 background_reset_callback (EelBackground *background,
517 NautilusFile *file)
519 char *color;
520 char *image;
522 if (eel_background_is_desktop (background)) {
523 nautilus_file_background_write_desktop_default_settings ();
524 } else {
525 /* Block the other handler while we are writing metadata so it doesn't
526 * try to change the background.
528 g_signal_handlers_block_by_func (
529 file,
530 G_CALLBACK (saved_settings_changed_callback),
531 background);
533 color = nautilus_file_get_metadata (file,
534 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR,
535 NULL);
536 image = nautilus_file_get_metadata (file,
537 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE,
538 NULL);
539 if (!color && !image) {
540 eel_preferences_set_boolean (NAUTILUS_PREFERENCES_BACKGROUND_SET,
541 FALSE);
542 } else {
543 /* reset the metadata */
544 nautilus_file_set_metadata (file,
545 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR,
546 NULL,
547 NULL);
549 nautilus_file_set_metadata (file,
550 NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE,
551 NULL,
552 NULL);
554 g_free (color);
555 g_free (image);
557 /* Unblock the handler. */
558 g_signal_handlers_unblock_by_func (
559 file,
560 G_CALLBACK (saved_settings_changed_callback),
561 background);
564 saved_settings_changed_callback (file, background);
567 /* handle the background destroyed signal */
568 static void
569 background_destroyed_callback (EelBackground *background,
570 NautilusFile *file)
572 g_signal_handlers_disconnect_by_func
573 (file,
574 G_CALLBACK (saved_settings_changed_callback), background);
575 nautilus_file_monitor_remove (file, background);
576 eel_preferences_remove_callback (NAUTILUS_PREFERENCES_THEME,
577 nautilus_file_background_theme_changed,
578 background);
579 eel_preferences_remove_callback (NAUTILUS_PREFERENCES_BACKGROUND_SET,
580 nautilus_file_background_theme_changed,
581 background);
582 eel_preferences_remove_callback (NAUTILUS_PREFERENCES_BACKGROUND_COLOR,
583 nautilus_file_background_theme_changed,
584 background);
585 eel_preferences_remove_callback (NAUTILUS_PREFERENCES_BACKGROUND_FILENAME,
586 nautilus_file_background_theme_changed,
587 background);
590 /* key routine that hooks up a background and location */
591 void
592 nautilus_connect_background_to_file_metadata (GtkWidget *widget,
593 NautilusFile *file,
594 GdkDragAction default_drag_action)
596 EelBackground *background;
597 gpointer old_file;
599 /* Get at the background object we'll be connecting. */
600 background = eel_get_widget_background (widget);
602 /* Check if it is already connected. */
603 old_file = g_object_get_data (G_OBJECT (background), "eel_background_file");
604 if (old_file == file) {
605 return;
608 /* Disconnect old signal handlers. */
609 if (old_file != NULL) {
610 g_assert (NAUTILUS_IS_FILE (old_file));
611 g_signal_handlers_disconnect_by_func
612 (background,
613 G_CALLBACK (background_changed_callback), old_file);
614 g_signal_handlers_disconnect_by_func
615 (background,
616 G_CALLBACK (background_destroyed_callback), old_file);
617 g_signal_handlers_disconnect_by_func
618 (background,
619 G_CALLBACK (background_reset_callback), old_file);
620 g_signal_handlers_disconnect_by_func
621 (old_file,
622 G_CALLBACK (saved_settings_changed_callback), background);
623 nautilus_file_monitor_remove (old_file, background);
624 eel_preferences_remove_callback (NAUTILUS_PREFERENCES_THEME,
625 nautilus_file_background_theme_changed,
626 background);
627 eel_preferences_remove_callback (NAUTILUS_PREFERENCES_BACKGROUND_SET,
628 nautilus_file_background_theme_changed,
629 background);
630 eel_preferences_remove_callback (NAUTILUS_PREFERENCES_BACKGROUND_COLOR,
631 nautilus_file_background_theme_changed,
632 background);
633 eel_preferences_remove_callback (NAUTILUS_PREFERENCES_BACKGROUND_FILENAME,
634 nautilus_file_background_theme_changed,
635 background);
639 /* Attach the new directory. */
640 nautilus_file_ref (file);
641 g_object_set_data_full (G_OBJECT (background), "eel_background_file",
642 file, (GDestroyNotify) nautilus_file_unref);
644 g_object_set_data (G_OBJECT (background), "default_drag_action", GINT_TO_POINTER (default_drag_action));
646 /* Connect new signal handlers. */
647 if (file != NULL) {
648 g_signal_connect_object (background, "settings_changed",
649 G_CALLBACK (background_changed_callback), file, 0);
650 g_signal_connect_object (background, "destroy",
651 G_CALLBACK (background_destroyed_callback), file, 0);
652 g_signal_connect_object (background, "reset",
653 G_CALLBACK (background_reset_callback), file, 0);
654 g_signal_connect_object (file, "changed",
655 G_CALLBACK (saved_settings_changed_callback), background, 0);
657 /* arrange to receive file metadata */
658 nautilus_file_monitor_add (file,
659 background,
660 NAUTILUS_FILE_ATTRIBUTE_METADATA);
662 /* arrange for notification when the theme changes */
663 eel_preferences_add_callback (NAUTILUS_PREFERENCES_THEME,
664 nautilus_file_background_theme_changed, background);
665 eel_preferences_add_callback (NAUTILUS_PREFERENCES_BACKGROUND_SET,
666 nautilus_file_background_theme_changed, background);
667 eel_preferences_add_callback (NAUTILUS_PREFERENCES_BACKGROUND_COLOR,
668 nautilus_file_background_theme_changed, background);
669 eel_preferences_add_callback (NAUTILUS_PREFERENCES_BACKGROUND_FILENAME,
670 nautilus_file_background_theme_changed, background);
673 /* Update the background based on the file metadata. */
674 initialize_background_from_settings (file, background);