1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-desktop-link.c: Class that handles the links on the desktop
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., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Author: Alexander Larsson <alexl@redhat.com>
23 */
24
25 #include <config.h>
26 #include <glib/gi18n.h>
27 #include <gio/gio.h>
28 #include <string.h>
29
30 #include "caja-desktop-link.h"
31 #include "caja-desktop-link-monitor.h"
32 #include "caja-desktop-icon-file.h"
33 #include "caja-directory-private.h"
34 #include "caja-desktop-directory.h"
35 #include "caja-icon-names.h"
36 #include "caja-file-utilities.h"
37 #include "caja-trash-monitor.h"
38 #include "caja-global-preferences.h"
39
40 struct _CajaDesktopLinkPrivate
41 {
42 CajaDesktopLinkType type;
43 char *filename;
44 char *display_name;
45 GFile *activation_location;
46 GIcon *icon;
47
48 CajaDesktopIconFile *icon_file;
49
50 GObject *signal_handler_obj;
51 gulong signal_handler;
52
53 /* Just for mount icons: */
54 GMount *mount;
55 };
56
G_DEFINE_TYPE_WITH_PRIVATE(CajaDesktopLink,caja_desktop_link,G_TYPE_OBJECT)57 G_DEFINE_TYPE_WITH_PRIVATE (CajaDesktopLink, caja_desktop_link, G_TYPE_OBJECT)
58
59 static void
60 create_icon_file (CajaDesktopLink *link)
61 {
62 link->details->icon_file = caja_desktop_icon_file_new (link);
63 }
64
65 static void
caja_desktop_link_changed(CajaDesktopLink * link)66 caja_desktop_link_changed (CajaDesktopLink *link)
67 {
68 if (link->details->icon_file != NULL)
69 {
70 caja_desktop_icon_file_update (link->details->icon_file);
71 }
72 }
73
74 static void
mount_changed_callback(GMount * mount,CajaDesktopLink * link)75 mount_changed_callback (GMount *mount, CajaDesktopLink *link)
76 {
77 g_free (link->details->display_name);
78 if (link->details->activation_location)
79 {
80 g_object_unref (link->details->activation_location);
81 }
82 if (link->details->icon)
83 {
84 g_object_unref (link->details->icon);
85 }
86
87 link->details->display_name = g_mount_get_name (mount);
88 link->details->activation_location = g_mount_get_default_location (mount);
89 link->details->icon = g_mount_get_icon (mount);
90
91 caja_desktop_link_changed (link);
92 }
93
94 static void
caja_desktop_link_ensure_display_name(CajaDesktopLink * link)95 caja_desktop_link_ensure_display_name (CajaDesktopLink *link)
96 {
97 if (link->details->display_name[0] == 0) {
98 g_free (link->details->display_name);
99
100 switch (link->details->type)
101 {
102 case CAJA_DESKTOP_LINK_HOME:
103 /* Translators: If it's hard to compose a good home
104 * icon name from the user name, you can use a string without
105 * an "%s" here, in which case the home icon name will not
106 * include the user's name, which should be fine. To avoid a
107 * warning, put "%.0s" somewhere in the string, which will
108 * match the user name string passed by the C code, but not
109 * put the user name in the final string.
110 */
111 link->details->display_name = g_strdup_printf (_("%s's Home"), g_get_user_name ());
112 break;
113 case CAJA_DESKTOP_LINK_COMPUTER:
114 link->details->display_name = g_strdup (_("Computer"));
115 break;
116 case CAJA_DESKTOP_LINK_NETWORK:
117 link->details->display_name = g_strdup (_("Network Servers"));
118 break;
119 case CAJA_DESKTOP_LINK_TRASH:
120 link->details->display_name = g_strdup (_("Trash"));
121 break;
122 default:
123 case CAJA_DESKTOP_LINK_MOUNT:
124 g_assert_not_reached();
125 }
126 }
127 }
128
129 static void
trash_state_changed_callback(CajaTrashMonitor * trash_monitor,gboolean state,gpointer callback_data)130 trash_state_changed_callback (CajaTrashMonitor *trash_monitor,
131 gboolean state,
132 gpointer callback_data)
133 {
134 CajaDesktopLink *link;
135
136 link = CAJA_DESKTOP_LINK (callback_data);
137 g_assert (link->details->type == CAJA_DESKTOP_LINK_TRASH);
138
139 if (link->details->icon)
140 {
141 g_object_unref (link->details->icon);
142 }
143 link->details->icon = caja_trash_monitor_get_icon ();
144
145 caja_desktop_link_changed (link);
146 }
147
148 static void
home_name_changed(gpointer callback_data)149 home_name_changed (gpointer callback_data)
150 {
151 CajaDesktopLink *link;
152
153 link = CAJA_DESKTOP_LINK (callback_data);
154 g_assert (link->details->type == CAJA_DESKTOP_LINK_HOME);
155
156 g_free (link->details->display_name);
157
158 link->details->display_name = g_settings_get_string (caja_desktop_preferences,
159 CAJA_PREFERENCES_DESKTOP_HOME_NAME);
160
161 caja_desktop_link_ensure_display_name (link);
162 caja_desktop_link_changed (link);
163 }
164
165 static void
computer_name_changed(gpointer callback_data)166 computer_name_changed (gpointer callback_data)
167 {
168 CajaDesktopLink *link;
169
170 link = CAJA_DESKTOP_LINK (callback_data);
171 g_assert (link->details->type == CAJA_DESKTOP_LINK_COMPUTER);
172
173 g_free (link->details->display_name);
174 link->details->display_name = g_settings_get_string (caja_desktop_preferences, CAJA_PREFERENCES_DESKTOP_COMPUTER_NAME);
175
176 caja_desktop_link_ensure_display_name (link);
177 caja_desktop_link_changed (link);
178 }
179
180 static void
trash_name_changed(gpointer callback_data)181 trash_name_changed (gpointer callback_data)
182 {
183 CajaDesktopLink *link;
184
185 link = CAJA_DESKTOP_LINK (callback_data);
186 g_assert (link->details->type == CAJA_DESKTOP_LINK_TRASH);
187
188 g_free (link->details->display_name);
189 link->details->display_name = g_settings_get_string (caja_desktop_preferences, CAJA_PREFERENCES_DESKTOP_TRASH_NAME);
190
191 caja_desktop_link_ensure_display_name (link);
192 caja_desktop_link_changed (link);
193 }
194
195 static void
network_name_changed(gpointer callback_data)196 network_name_changed (gpointer callback_data)
197 {
198 CajaDesktopLink *link;
199
200 link = CAJA_DESKTOP_LINK (callback_data);
201 g_assert (link->details->type == CAJA_DESKTOP_LINK_NETWORK);
202
203 g_free (link->details->display_name);
204 link->details->display_name = g_settings_get_string (caja_desktop_preferences, CAJA_PREFERENCES_DESKTOP_NETWORK_NAME);
205
206 caja_desktop_link_ensure_display_name (link);
207 caja_desktop_link_changed (link);
208 }
209
210 CajaDesktopLink *
caja_desktop_link_new(CajaDesktopLinkType type)211 caja_desktop_link_new (CajaDesktopLinkType type)
212 {
213 CajaDesktopLink *link;
214
215 link = CAJA_DESKTOP_LINK (g_object_new (CAJA_TYPE_DESKTOP_LINK, NULL));
216
217 link->details->type = type;
218 switch (type)
219 {
220 case CAJA_DESKTOP_LINK_HOME:
221 link->details->filename = g_strdup ("home");
222 link->details->display_name = g_settings_get_string (caja_desktop_preferences, CAJA_PREFERENCES_DESKTOP_HOME_NAME);
223 link->details->activation_location = g_file_new_for_path (g_get_home_dir ());
224 link->details->icon = g_themed_icon_new (CAJA_ICON_HOME);
225
226 g_signal_connect_swapped (caja_desktop_preferences,
227 "changed::" CAJA_PREFERENCES_DESKTOP_HOME_NAME,
228 G_CALLBACK (home_name_changed),
229 link);
230
231 break;
232
233 case CAJA_DESKTOP_LINK_COMPUTER:
234 link->details->filename = g_strdup ("computer");
235 link->details->display_name = g_settings_get_string (caja_desktop_preferences, CAJA_PREFERENCES_DESKTOP_COMPUTER_NAME);
236 link->details->activation_location = g_file_new_for_uri ("computer:///");
237 /* TODO: This might need a different icon: */
238 link->details->icon = g_themed_icon_new (CAJA_ICON_COMPUTER);
239
240 g_signal_connect_swapped (caja_desktop_preferences,
241 "changed::" CAJA_PREFERENCES_DESKTOP_COMPUTER_NAME,
242 G_CALLBACK (computer_name_changed),
243 link);
244
245 break;
246
247 case CAJA_DESKTOP_LINK_TRASH:
248 link->details->filename = g_strdup ("trash");
249 link->details->display_name = g_settings_get_string (caja_desktop_preferences, CAJA_PREFERENCES_DESKTOP_TRASH_NAME);
250 link->details->activation_location = g_file_new_for_uri (EEL_TRASH_URI);
251 link->details->icon = caja_trash_monitor_get_icon ();
252
253 g_signal_connect_swapped (caja_desktop_preferences,
254 "changed::" CAJA_PREFERENCES_DESKTOP_TRASH_NAME,
255 G_CALLBACK (trash_name_changed),
256 link);
257 link->details->signal_handler_obj = G_OBJECT (caja_trash_monitor_get ());
258 link->details->signal_handler =
259 g_signal_connect_object (caja_trash_monitor_get (), "trash_state_changed",
260 G_CALLBACK (trash_state_changed_callback), link, 0);
261 break;
262
263 case CAJA_DESKTOP_LINK_NETWORK:
264 link->details->filename = g_strdup ("network");
265 link->details->display_name = g_settings_get_string (caja_desktop_preferences, CAJA_PREFERENCES_DESKTOP_NETWORK_NAME);
266 link->details->activation_location = g_file_new_for_uri ("network:///");
267 link->details->icon = g_themed_icon_new (CAJA_ICON_NETWORK);
268
269 g_signal_connect_swapped (caja_desktop_preferences,
270 "changed::" CAJA_PREFERENCES_DESKTOP_NETWORK_NAME,
271 G_CALLBACK (network_name_changed),
272 link);
273 break;
274
275 default:
276 case CAJA_DESKTOP_LINK_MOUNT:
277 g_assert_not_reached();
278 }
279
280 caja_desktop_link_ensure_display_name (link);
281 create_icon_file (link);
282
283 return link;
284 }
285
286 CajaDesktopLink *
caja_desktop_link_new_from_mount(GMount * mount)287 caja_desktop_link_new_from_mount (GMount *mount)
288 {
289 CajaDesktopLink *link;
290 GVolume *volume;
291 char *name, *filename;
292
293 link = CAJA_DESKTOP_LINK (g_object_new (CAJA_TYPE_DESKTOP_LINK, NULL));
294
295 link->details->type = CAJA_DESKTOP_LINK_MOUNT;
296
297 link->details->mount = g_object_ref (mount);
298
299 /* We try to use the drive name to get somewhat stable filenames
300 for metadata */
301 volume = g_mount_get_volume (mount);
302 if (volume != NULL)
303 {
304 name = g_volume_get_name (volume);
305 g_object_unref (volume);
306 }
307 else
308 {
309 name = g_mount_get_name (mount);
310 }
311
312 /* Replace slashes in name */
313 filename = g_strconcat (g_strdelimit (name, "/", '-'), ".volume", NULL);
314 link->details->filename =
315 caja_desktop_link_monitor_make_filename_unique (caja_desktop_link_monitor_get (),
316 filename);
317 g_free (filename);
318 g_free (name);
319
320 link->details->display_name = g_mount_get_name (mount);
321
322 link->details->activation_location = g_mount_get_default_location (mount);
323 link->details->icon = g_mount_get_icon (mount);
324
325 link->details->signal_handler_obj = G_OBJECT (mount);
326 link->details->signal_handler =
327 g_signal_connect (mount, "changed",
328 G_CALLBACK (mount_changed_callback), link);
329
330 create_icon_file (link);
331
332 return link;
333 }
334
335 GMount *
caja_desktop_link_get_mount(CajaDesktopLink * link)336 caja_desktop_link_get_mount (CajaDesktopLink *link)
337 {
338 if (link->details->mount)
339 {
340 return g_object_ref (link->details->mount);
341 }
342 return NULL;
343 }
344
345 CajaDesktopLinkType
caja_desktop_link_get_link_type(CajaDesktopLink * link)346 caja_desktop_link_get_link_type (CajaDesktopLink *link)
347 {
348 return link->details->type;
349 }
350
351 char *
caja_desktop_link_get_file_name(CajaDesktopLink * link)352 caja_desktop_link_get_file_name (CajaDesktopLink *link)
353 {
354 return g_strdup (link->details->filename);
355 }
356
357 char *
caja_desktop_link_get_display_name(CajaDesktopLink * link)358 caja_desktop_link_get_display_name (CajaDesktopLink *link)
359 {
360 return g_strdup (link->details->display_name);
361 }
362
363 GIcon *
caja_desktop_link_get_icon(CajaDesktopLink * link)364 caja_desktop_link_get_icon (CajaDesktopLink *link)
365 {
366 if (link->details->icon != NULL)
367 {
368 return g_object_ref (link->details->icon);
369 }
370 return NULL;
371 }
372
373 GFile *
caja_desktop_link_get_activation_location(CajaDesktopLink * link)374 caja_desktop_link_get_activation_location (CajaDesktopLink *link)
375 {
376 if (link->details->activation_location)
377 {
378 return g_object_ref (link->details->activation_location);
379 }
380 return NULL;
381 }
382
383 char *
caja_desktop_link_get_activation_uri(CajaDesktopLink * link)384 caja_desktop_link_get_activation_uri (CajaDesktopLink *link)
385 {
386 if (link->details->activation_location)
387 {
388 return g_file_get_uri (link->details->activation_location);
389 }
390 return NULL;
391 }
392
393
394 gboolean
caja_desktop_link_get_date(CajaDesktopLink * link,CajaDateType date_type,time_t * date)395 caja_desktop_link_get_date (CajaDesktopLink *link,
396 CajaDateType date_type,
397 time_t *date)
398 {
399 return FALSE;
400 }
401
402 gboolean
caja_desktop_link_can_rename(CajaDesktopLink * link)403 caja_desktop_link_can_rename (CajaDesktopLink *link)
404 {
405 return (link->details->type == CAJA_DESKTOP_LINK_HOME ||
406 link->details->type == CAJA_DESKTOP_LINK_TRASH ||
407 link->details->type == CAJA_DESKTOP_LINK_NETWORK ||
408 link->details->type == CAJA_DESKTOP_LINK_COMPUTER);
409 }
410
411 gboolean
caja_desktop_link_rename(CajaDesktopLink * link,const char * name)412 caja_desktop_link_rename (CajaDesktopLink *link,
413 const char *name)
414 {
415 switch (link->details->type)
416 {
417 case CAJA_DESKTOP_LINK_HOME:
418 g_settings_set_string (caja_desktop_preferences,
419 CAJA_PREFERENCES_DESKTOP_HOME_NAME,
420 name);
421 break;
422 case CAJA_DESKTOP_LINK_COMPUTER:
423 g_settings_set_string (caja_desktop_preferences,
424 CAJA_PREFERENCES_DESKTOP_COMPUTER_NAME,
425 name);
426 break;
427 case CAJA_DESKTOP_LINK_TRASH:
428 g_settings_set_string (caja_desktop_preferences,
429 CAJA_PREFERENCES_DESKTOP_TRASH_NAME,
430 name);
431 break;
432 case CAJA_DESKTOP_LINK_NETWORK:
433 g_settings_set_string (caja_desktop_preferences,
434 CAJA_PREFERENCES_DESKTOP_NETWORK_NAME,
435 name);
436 break;
437 default:
438 g_assert_not_reached ();
439 /* FIXME: Do we want volume renaming?
440 * We didn't support that before. */
441 break;
442 }
443
444 return TRUE;
445 }
446
447 static void
caja_desktop_link_init(CajaDesktopLink * link)448 caja_desktop_link_init (CajaDesktopLink *link)
449 {
450 link->details = caja_desktop_link_get_instance_private (link);
451 }
452
453 static void
desktop_link_finalize(GObject * object)454 desktop_link_finalize (GObject *object)
455 {
456 CajaDesktopLink *link;
457
458 link = CAJA_DESKTOP_LINK (object);
459
460 if (link->details->signal_handler != 0)
461 {
462 if (g_signal_handler_is_connected(link->details->signal_handler_obj,
463 link->details->signal_handler)){
464 g_signal_handler_disconnect (link->details->signal_handler_obj,
465 link->details->signal_handler);
466 }
467 }
468
469 if (link->details->icon_file != NULL)
470 {
471 caja_desktop_icon_file_remove (link->details->icon_file);
472 caja_file_unref (CAJA_FILE (link->details->icon_file));
473 link->details->icon_file = NULL;
474 }
475
476 if (link->details->type == CAJA_DESKTOP_LINK_HOME)
477 {
478 g_signal_handlers_disconnect_by_func (caja_desktop_preferences,
479 home_name_changed,
480 link);
481 }
482
483 if (link->details->type == CAJA_DESKTOP_LINK_COMPUTER)
484 {
485 g_signal_handlers_disconnect_by_func (caja_desktop_preferences,
486 computer_name_changed,
487 link);
488 }
489
490 if (link->details->type == CAJA_DESKTOP_LINK_TRASH)
491 {
492 g_signal_handlers_disconnect_by_func (caja_desktop_preferences,
493 trash_name_changed,
494 link);
495 }
496
497 if (link->details->type == CAJA_DESKTOP_LINK_NETWORK)
498 {
499 g_signal_handlers_disconnect_by_func (caja_desktop_preferences,
500 network_name_changed,
501 link);
502 }
503
504 if (link->details->type == CAJA_DESKTOP_LINK_MOUNT)
505 {
506 g_object_unref (link->details->mount);
507 }
508
509 g_free (link->details->filename);
510 g_free (link->details->display_name);
511 if (link->details->activation_location)
512 {
513 g_object_unref (link->details->activation_location);
514 }
515 if (link->details->icon)
516 {
517 g_object_unref (link->details->icon);
518 }
519
520 G_OBJECT_CLASS (caja_desktop_link_parent_class)->finalize (object);
521 }
522
523 static void
caja_desktop_link_class_init(CajaDesktopLinkClass * klass)524 caja_desktop_link_class_init (CajaDesktopLinkClass *klass)
525 {
526 GObjectClass *object_class;
527
528 object_class = G_OBJECT_CLASS (klass);
529
530 object_class->finalize = desktop_link_finalize;
531 }
532