nautilus-3.6.3/libnautilus-private/nautilus-desktop-link-monitor.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found nautilus-desktop-link-monitor.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
  2 
  3    nautilus-desktop-link-monitor.c: singleton thatn manages the links
  4     
  5    Copyright (C) 2003 Red Hat, Inc.
  6   
  7    This program is free software; you can redistribute it and/or
  8    modify it under the terms of the GNU General Public License as
  9    published by the Free Software Foundation; either version 2 of the
 10    License, or (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 GNU
 15    General Public License for more details.
 16   
 17    You should have received a copy of the GNU General Public
 18    License along with this program; if not, write to the
 19    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 20    Boston, MA 02111-1307, USA.
 21   
 22    Author: Alexander Larsson <alexl@redhat.com>
 23 */
 24 
 25 #include <config.h>
 26 #include "nautilus-desktop-link-monitor.h"
 27 #include "nautilus-desktop-link.h"
 28 #include "nautilus-desktop-icon-file.h"
 29 #include "nautilus-directory.h"
 30 #include "nautilus-desktop-directory.h"
 31 #include "nautilus-global-preferences.h"
 32 
 33 #include <eel/eel-debug.h>
 34 #include <eel/eel-vfs-extensions.h>
 35 #include <eel/eel-stock-dialogs.h>
 36 #include <gtk/gtk.h>
 37 #include <glib/gi18n.h>
 38 #include <gio/gio.h>
 39 #include <libnautilus-private/nautilus-trash-monitor.h>
 40 #include <string.h>
 41 
 42 struct NautilusDesktopLinkMonitorDetails {
 43 	GVolumeMonitor *volume_monitor;
 44 	NautilusDirectory *desktop_dir;
 45 	
 46 	NautilusDesktopLink *home_link;
 47 	NautilusDesktopLink *trash_link;
 48 	NautilusDesktopLink *network_link;
 49 
 50 	gulong mount_id;
 51 	gulong unmount_id;
 52 	gulong changed_id;
 53 	
 54 	GList *mount_links;
 55 };
 56 
 57 G_DEFINE_TYPE (NautilusDesktopLinkMonitor, nautilus_desktop_link_monitor, G_TYPE_OBJECT);
 58 
 59 static NautilusDesktopLinkMonitor *the_link_monitor = NULL;
 60 
 61 void
 62 nautilus_desktop_link_monitor_shutdown (void)
 63 {
 64 	g_clear_object (&the_link_monitor);
 65 }
 66 
 67 NautilusDesktopLinkMonitor *
 68 nautilus_desktop_link_monitor_get (void)
 69 {
 70 	if (the_link_monitor == NULL) {
 71 		g_object_new (NAUTILUS_TYPE_DESKTOP_LINK_MONITOR, NULL);
 72 		eel_debug_call_at_shutdown (nautilus_desktop_link_monitor_shutdown);
 73 	}
 74 	return the_link_monitor;
 75 }
 76 
 77 static void
 78 volume_delete_dialog (GtkWidget *parent_view,
 79                       NautilusDesktopLink *link)
 80 {
 81 	GMount *mount;
 82 	char *dialog_str;
 83 	char *display_name;
 84 
 85 	mount = nautilus_desktop_link_get_mount (link);
 86 
 87 	if (mount != NULL) {
 88 		display_name = nautilus_desktop_link_get_display_name (link);
 89 		dialog_str = g_strdup_printf (_("You cannot move the volume “%s” to the trash."),
 90 					      display_name);
 91 		g_free (display_name);
 92 
 93 		if (g_mount_can_eject (mount)) {
 94 			eel_run_simple_dialog
 95 				(parent_view, 
 96 				 FALSE,
 97 				 GTK_MESSAGE_ERROR,
 98 				 dialog_str,
 99 				 _("If you want to eject the volume, please use Eject in the "
100 				   "popup menu of the volume."),
101 				 GTK_STOCK_OK, NULL);
102 		} else {
103 			eel_run_simple_dialog
104 				(parent_view, 
105 				 FALSE,
106 				 GTK_MESSAGE_ERROR,
107 				 dialog_str,
108 				 _("If you want to unmount the volume, please use Unmount Volume in the "
109 				   "popup menu of the volume."),
110 				 GTK_STOCK_OK, NULL);
111 		}
112 
113 		g_object_unref (mount);
114 		g_free (dialog_str);
115 	}
116 }
117 
118 void
119 nautilus_desktop_link_monitor_delete_link (NautilusDesktopLinkMonitor *monitor,
120 					   NautilusDesktopLink *link,
121 					   GtkWidget *parent_view)
122 {
123 	switch (nautilus_desktop_link_get_link_type (link)) {
124 	case NAUTILUS_DESKTOP_LINK_HOME:
125 	case NAUTILUS_DESKTOP_LINK_TRASH:
126 	case NAUTILUS_DESKTOP_LINK_NETWORK:
127 		/* just ignore. We don't allow you to delete these */
128 		break;
129 	default:
130 		volume_delete_dialog (parent_view, link);
131 		break;
132 	}
133 }
134 
135 static gboolean
136 volume_file_name_used (NautilusDesktopLinkMonitor *monitor,
137 		       const char *name)
138 {
139 	GList *l;
140 	char *other_name;
141 	gboolean same;
142 
143 	for (l = monitor->details->mount_links; l != NULL; l = l->next) {
144 		other_name = nautilus_desktop_link_get_file_name (l->data);
145 		same = strcmp (name, other_name) == 0;
146 		g_free (other_name);
147 
148 		if (same) {
149 			return TRUE;
150 		}
151 	}
152 
153 	return FALSE;
154 }
155 
156 char *
157 nautilus_desktop_link_monitor_make_filename_unique (NautilusDesktopLinkMonitor *monitor,
158 						    const char *filename)
159 {
160 	char *unique_name;
161 	int i;
162 	
163 	i = 2;
164 	unique_name = g_strdup (filename);
165 	while (volume_file_name_used (monitor, unique_name)) {
166 		g_free (unique_name);
167 		unique_name = g_strdup_printf ("%s.%d", filename, i++);
168 	}
169 	return unique_name;
170 }
171 
172 static gboolean
173 has_mount (NautilusDesktopLinkMonitor *monitor,
174 	   GMount                     *mount)
175 {
176 	gboolean ret;
177 	GMount *other_mount;
178 	GList *l;
179 
180 	ret = FALSE;
181 
182 	for (l = monitor->details->mount_links; l != NULL; l = l->next) {
183 		other_mount = nautilus_desktop_link_get_mount (l->data);
184 		if (mount == other_mount) {
185 			g_object_unref (other_mount);
186 			ret = TRUE;
187 			break;
188 		}
189 		g_object_unref (other_mount);
190 	}
191 
192 	return ret;
193 }
194 
195 static void
196 create_mount_link (NautilusDesktopLinkMonitor *monitor,
197 		   GMount *mount)
198 {
199 	NautilusDesktopLink *link;
200 
201 	if (has_mount (monitor, mount))
202 		return;
203 
204 	if ((!g_mount_is_shadowed (mount)) &&
205 	    g_settings_get_boolean (nautilus_desktop_preferences,
206 				    NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) {
207 		link = nautilus_desktop_link_new_from_mount (mount);
208 		monitor->details->mount_links = g_list_prepend (monitor->details->mount_links, link);
209 	}
210 }
211 
212 static void
213 remove_mount_link (NautilusDesktopLinkMonitor *monitor,
214 		   GMount *mount)
215 {
216 	GList *l;
217 	NautilusDesktopLink *link;
218 	GMount *other_mount;
219 
220 	link = NULL;
221 	for (l = monitor->details->mount_links; l != NULL; l = l->next) {
222 		other_mount = nautilus_desktop_link_get_mount (l->data);
223 		if (mount == other_mount) {
224 			g_object_unref (other_mount);
225 			link = l->data;
226 			break;
227 		}
228 		g_object_unref (other_mount);
229 	}
230 
231 	if (link) {
232 		monitor->details->mount_links = g_list_remove (monitor->details->mount_links, link);
233 		g_object_unref (link);
234 	}
235 }
236 
237 
238 
239 static void
240 mount_added_callback (GVolumeMonitor *volume_monitor,
241 		      GMount *mount, 
242 		      NautilusDesktopLinkMonitor *monitor)
243 {
244 	create_mount_link (monitor, mount);
245 }
246 
247 
248 static void
249 mount_removed_callback (GVolumeMonitor *volume_monitor,
250 			GMount *mount, 
251 			NautilusDesktopLinkMonitor *monitor)
252 {
253 	remove_mount_link (monitor, mount);
254 }
255 
256 static void
257 mount_changed_callback (GVolumeMonitor *volume_monitor,
258 			GMount *mount, 
259 			NautilusDesktopLinkMonitor *monitor)
260 {
261 	/* TODO: update the mount with other details */
262 
263 	/* remove a mount if it goes into the shadows */
264 	if (g_mount_is_shadowed (mount) && has_mount (monitor, mount)) {
265 		remove_mount_link (monitor, mount);
266 	}}
267 
268 static void
269 update_link_visibility (NautilusDesktopLinkMonitor *monitor,
270 			NautilusDesktopLink       **link_ref,
271 			NautilusDesktopLinkType     link_type,
272 			const char                 *preference_key)
273 {
274 	if (g_settings_get_boolean (nautilus_desktop_preferences, preference_key)) {
275 		if (*link_ref == NULL) {
276 			*link_ref = nautilus_desktop_link_new (link_type);
277 		}
278 	} else {
279 		if (*link_ref != NULL) {
280 			g_object_unref (*link_ref);
281 			*link_ref = NULL;
282 		}
283 	}
284 }
285 
286 static void
287 desktop_home_visible_changed (gpointer callback_data)
288 {
289 	NautilusDesktopLinkMonitor *monitor;
290 
291 	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
292 
293 	update_link_visibility (NAUTILUS_DESKTOP_LINK_MONITOR (monitor),
294 				&monitor->details->home_link,
295 				NAUTILUS_DESKTOP_LINK_HOME,
296 				NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE);
297 }
298 
299 static void
300 desktop_trash_visible_changed (gpointer callback_data)
301 {
302 	NautilusDesktopLinkMonitor *monitor;
303 
304 	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
305 
306 	update_link_visibility (NAUTILUS_DESKTOP_LINK_MONITOR (callback_data),
307 				&monitor->details->trash_link,
308 				NAUTILUS_DESKTOP_LINK_TRASH,
309 				NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE);
310 }
311 
312 static void
313 desktop_network_visible_changed (gpointer callback_data)
314 {
315 	NautilusDesktopLinkMonitor *monitor;
316 
317 	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
318 
319 	update_link_visibility (NAUTILUS_DESKTOP_LINK_MONITOR (callback_data),
320 				&monitor->details->network_link,
321 				NAUTILUS_DESKTOP_LINK_NETWORK,
322 				NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE);
323 }
324 
325 static void
326 desktop_volumes_visible_changed (gpointer callback_data)
327 {
328 	NautilusDesktopLinkMonitor *monitor;
329 	GList *l, *mounts;
330 
331 	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
332 
333 	if (g_settings_get_boolean (nautilus_desktop_preferences,
334 				    NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) {
335 		if (monitor->details->mount_links == NULL) {
336 			mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor);
337 			for (l = mounts; l != NULL; l = l->next) {
338 				create_mount_link (monitor, l->data);
339 				g_object_unref (l->data);
340 			}
341 			g_list_free (mounts);
342 		}
343 	} else {
344 		g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL);
345 		g_list_free (monitor->details->mount_links);
346 		monitor->details->mount_links = NULL;
347 	}
348 }
349 
350 static void
351 create_link_and_add_preference (NautilusDesktopLink   **link_ref,
352 				NautilusDesktopLinkType link_type,
353 				const char             *preference_key,
354 				GCallback               callback,
355 				gpointer                callback_data)
356 {
357 	char *detailed_signal;
358 
359 	if (g_settings_get_boolean (nautilus_desktop_preferences, preference_key)) {
360 		*link_ref = nautilus_desktop_link_new (link_type);
361 	}
362 
363 	detailed_signal = g_strconcat ("changed::", preference_key, NULL);
364 	g_signal_connect_swapped (nautilus_desktop_preferences,
365 				  detailed_signal,
366 				  callback, callback_data);
367 
368 	g_free (detailed_signal);
369 }
370 
371 static void
372 nautilus_desktop_link_monitor_init (NautilusDesktopLinkMonitor *monitor)
373 {
374 	GList *l, *mounts;
375 	GMount *mount;
376 
377 	monitor->details = G_TYPE_INSTANCE_GET_PRIVATE (monitor, NAUTILUS_TYPE_DESKTOP_LINK_MONITOR,
378 							NautilusDesktopLinkMonitorDetails);
379 
380 	the_link_monitor = monitor;
381 	monitor->details->volume_monitor = g_volume_monitor_get ();
382 
383 	/* We keep around a ref to the desktop dir */
384 	monitor->details->desktop_dir = nautilus_directory_get_by_uri (EEL_DESKTOP_URI);
385 
386 	/* Default links */
387 
388 	create_link_and_add_preference (&monitor->details->home_link,
389 					NAUTILUS_DESKTOP_LINK_HOME,
390 					NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE,
391 					G_CALLBACK (desktop_home_visible_changed),
392 					monitor);
393 
394 	create_link_and_add_preference (&monitor->details->trash_link,
395 					NAUTILUS_DESKTOP_LINK_TRASH,
396 					NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE,
397 					G_CALLBACK (desktop_trash_visible_changed),
398 					monitor);
399 
400 	create_link_and_add_preference (&monitor->details->network_link,
401 					NAUTILUS_DESKTOP_LINK_NETWORK,
402 					NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE,
403 					G_CALLBACK (desktop_network_visible_changed),
404 					monitor);
405 
406 	/* Mount links */
407 
408 	mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor);
409 	for (l = mounts; l != NULL; l = l->next) {
410 		mount = l->data;
411 		create_mount_link (monitor, mount);
412 		g_object_unref (mount);
413 	}
414 	g_list_free (mounts);
415 
416 	g_signal_connect_swapped (nautilus_desktop_preferences,
417 				  "changed::" NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE,
418 				  G_CALLBACK (desktop_volumes_visible_changed),
419 				  monitor);
420 
421 	monitor->details->mount_id =
422 		g_signal_connect_object (monitor->details->volume_monitor, "mount_added",
423 					 G_CALLBACK (mount_added_callback), monitor, 0);
424 	monitor->details->unmount_id =
425 		g_signal_connect_object (monitor->details->volume_monitor, "mount_removed",
426 					 G_CALLBACK (mount_removed_callback), monitor, 0);
427 	monitor->details->changed_id =
428 		g_signal_connect_object (monitor->details->volume_monitor, "mount_changed",
429 					 G_CALLBACK (mount_changed_callback), monitor, 0);
430 
431 }
432 
433 static void
434 remove_link_and_preference (NautilusDesktopLink   **link_ref,
435 			    const char             *preference_key,
436 			    GCallback               callback,
437 			    gpointer                callback_data)
438 {
439 	if (*link_ref != NULL) {
440 		g_object_unref (*link_ref);
441 		*link_ref = NULL;
442 	}
443 
444 	g_signal_handlers_disconnect_by_func (nautilus_desktop_preferences,
445 					      callback, callback_data);
446 }
447 
448 static void
449 desktop_link_monitor_finalize (GObject *object)
450 {
451 	NautilusDesktopLinkMonitor *monitor;
452 
453 	monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object);
454 
455 	g_object_unref (monitor->details->volume_monitor);
456 
457 	/* Default links */
458 
459 	remove_link_and_preference (&monitor->details->home_link,
460 				    NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE,
461 				    G_CALLBACK (desktop_home_visible_changed),
462 				    monitor);
463 
464 	remove_link_and_preference (&monitor->details->trash_link,
465 				    NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE,
466 				    G_CALLBACK (desktop_trash_visible_changed),
467 				    monitor);
468 
469 	remove_link_and_preference (&monitor->details->network_link,
470 				    NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE,
471 				    G_CALLBACK (desktop_network_visible_changed),
472 				    monitor);
473 
474 	/* Mounts */
475 
476 	g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL);
477 	g_list_free (monitor->details->mount_links);
478 	monitor->details->mount_links = NULL;
479 
480 	nautilus_directory_unref (monitor->details->desktop_dir);
481 	monitor->details->desktop_dir = NULL;
482 
483 	g_signal_handlers_disconnect_by_func (nautilus_desktop_preferences,
484 					      desktop_volumes_visible_changed,
485 					      monitor);
486 
487 	if (monitor->details->mount_id != 0) {
488 		g_source_remove (monitor->details->mount_id);
489 	}
490 	if (monitor->details->unmount_id != 0) {
491 		g_source_remove (monitor->details->unmount_id);
492 	}
493 	if (monitor->details->changed_id != 0) {
494 		g_source_remove (monitor->details->changed_id);
495 	}
496 
497 	G_OBJECT_CLASS (nautilus_desktop_link_monitor_parent_class)->finalize (object);
498 }
499 
500 static void
501 nautilus_desktop_link_monitor_class_init (NautilusDesktopLinkMonitorClass *klass)
502 {
503 	GObjectClass *object_class;
504 
505 	object_class = G_OBJECT_CLASS (klass);
506 	object_class->finalize = desktop_link_monitor_finalize;
507 
508 	g_type_class_add_private (klass, sizeof (NautilusDesktopLinkMonitorDetails));
509 }