No issues found
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 |
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 }