nautilus-3.6.3/src/nautilus-bookmark-list.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2 
  3 /*
  4  * Nautilus
  5  *
  6  * Copyright (C) 1999, 2000 Eazel, Inc.
  7  *
  8  * Nautilus is free software; you can redistribute it and/or
  9  * modify it under the terms of the GNU General Public License as
 10  * published by the Free Software Foundation; either version 2 of the
 11  * License, or (at your option) any later version.
 12  *
 13  * Nautilus is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  * General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU General Public License
 19  * along with this program; if not, write to the Free Software
 20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 21  *
 22  * Authors: John Sullivan <sullivan@eazel.com>
 23  */
 24 
 25 /* nautilus-bookmark-list.c - implementation of centralized list of bookmarks.
 26  */
 27 
 28 #include <config.h>
 29 #include "nautilus-bookmark-list.h"
 30 
 31 #include <libnautilus-private/nautilus-file-utilities.h>
 32 #include <libnautilus-private/nautilus-file.h>
 33 #include <libnautilus-private/nautilus-icon-names.h>
 34 
 35 #include <gio/gio.h>
 36 #include <string.h>
 37 
 38 #define MAX_BOOKMARK_LENGTH 80
 39 #define LOAD_JOB 1
 40 #define SAVE_JOB 2
 41 
 42 enum {
 43 	CHANGED,
 44 	LAST_SIGNAL
 45 };
 46 
 47 static guint signals[LAST_SIGNAL];
 48 
 49 /* forward declarations */
 50 
 51 static void        nautilus_bookmark_list_load_file     (NautilusBookmarkList *bookmarks);
 52 static void        nautilus_bookmark_list_save_file     (NautilusBookmarkList *bookmarks);
 53 
 54 G_DEFINE_TYPE(NautilusBookmarkList, nautilus_bookmark_list, G_TYPE_OBJECT)
 55 
 56 static NautilusBookmark *
 57 new_bookmark_from_uri (const char *uri, const char *label)
 58 {
 59 	NautilusBookmark *new_bookmark;
 60 	GFile *location;
 61 
 62 	location = NULL;
 63 	if (uri) {
 64 		location = g_file_new_for_uri (uri);
 65 	}
 66 	
 67 	new_bookmark = NULL;
 68 
 69 	if (location) {
 70 		new_bookmark = nautilus_bookmark_new (location, label);
 71 		g_object_unref (location);
 72 	}
 73 
 74 	return new_bookmark;
 75 }
 76 
 77 static GFile *
 78 nautilus_bookmark_list_get_legacy_file (void)
 79 {
 80 	char *filename;
 81 	GFile *file;
 82 
 83 	filename = g_build_filename (g_get_home_dir (),
 84 				     ".gtk-bookmarks",
 85 				     NULL);
 86 	file = g_file_new_for_path (filename);
 87 
 88 	g_free (filename);
 89 
 90 	return file;
 91 }
 92 
 93 static GFile *
 94 nautilus_bookmark_list_get_file (void)
 95 {
 96 	char *filename;
 97 	GFile *file;
 98 
 99 	filename = g_build_filename (g_get_user_config_dir (),
100 				     "gtk-3.0",
101 				     "bookmarks",
102 				     NULL);
103 	file = g_file_new_for_path (filename);
104 
105 	g_free (filename);
106 
107 	return file;
108 }
109 
110 /* Initialization.  */
111 
112 static void
113 bookmark_in_list_changed_callback (NautilusBookmark     *bookmark,
114 				   NautilusBookmarkList *bookmarks)
115 {
116 	g_assert (NAUTILUS_IS_BOOKMARK (bookmark));
117 	g_assert (NAUTILUS_IS_BOOKMARK_LIST (bookmarks));
118 
119 	/* save changes to the list */
120 	nautilus_bookmark_list_save_file (bookmarks);
121 }
122 
123 static void
124 bookmark_in_list_notify (GObject *object,
125 			 GParamSpec *pspec,
126 			 NautilusBookmarkList *bookmarks)
127 {
128 	/* emit the changed signal without saving, as only appearance properties changed */
129 	g_signal_emit (bookmarks, signals[CHANGED], 0);
130 }
131 
132 static void
133 stop_monitoring_bookmark (NautilusBookmarkList *bookmarks,
134 			  NautilusBookmark     *bookmark)
135 {
136 	g_signal_handlers_disconnect_by_func (bookmark,
137 					      bookmark_in_list_changed_callback,
138 					      bookmarks);
139 }
140 
141 static void
142 stop_monitoring_one (gpointer data, gpointer user_data)
143 {
144 	g_assert (NAUTILUS_IS_BOOKMARK (data));
145 	g_assert (NAUTILUS_IS_BOOKMARK_LIST (user_data));
146 
147 	stop_monitoring_bookmark (NAUTILUS_BOOKMARK_LIST (user_data), 
148 				  NAUTILUS_BOOKMARK (data));
149 }
150 
151 static void
152 clear (NautilusBookmarkList *bookmarks)
153 {
154 	g_list_foreach (bookmarks->list, stop_monitoring_one, bookmarks);
155 	g_list_free_full (bookmarks->list, g_object_unref);
156 	bookmarks->list = NULL;
157 }
158 
159 static void
160 do_finalize (GObject *object)
161 {
162 	if (NAUTILUS_BOOKMARK_LIST (object)->monitor != NULL) {
163 		g_file_monitor_cancel (NAUTILUS_BOOKMARK_LIST (object)->monitor);
164 		NAUTILUS_BOOKMARK_LIST (object)->monitor = NULL;
165 	}
166 
167 	g_queue_free (NAUTILUS_BOOKMARK_LIST (object)->pending_ops);
168 
169 	clear (NAUTILUS_BOOKMARK_LIST (object));
170 
171 	G_OBJECT_CLASS (nautilus_bookmark_list_parent_class)->finalize (object);
172 }
173 
174 static void
175 nautilus_bookmark_list_class_init (NautilusBookmarkListClass *class)
176 {
177 	GObjectClass *object_class = G_OBJECT_CLASS (class);
178 
179 	object_class->finalize = do_finalize;
180 
181 	signals[CHANGED] =
182 		g_signal_new ("changed",
183 		              G_TYPE_FROM_CLASS (object_class),
184 		              G_SIGNAL_RUN_LAST,
185 		              G_STRUCT_OFFSET (NautilusBookmarkListClass, 
186 					       changed),
187 		              NULL, NULL,
188 		              g_cclosure_marshal_VOID__VOID,
189 		              G_TYPE_NONE, 0);
190 }
191 
192 static void
193 bookmark_monitor_changed_cb (GFileMonitor      *monitor,
194 			     GFile             *child,
195 			     GFile             *other_file,
196 			     GFileMonitorEvent  eflags,
197 			     gpointer           user_data)
198 {
199 	if (eflags == G_FILE_MONITOR_EVENT_CHANGED ||
200 	    eflags == G_FILE_MONITOR_EVENT_CREATED) {
201 		g_return_if_fail (NAUTILUS_IS_BOOKMARK_LIST (NAUTILUS_BOOKMARK_LIST (user_data)));
202 		nautilus_bookmark_list_load_file (NAUTILUS_BOOKMARK_LIST (user_data));
203 	}
204 }
205 
206 static void
207 nautilus_bookmark_list_init (NautilusBookmarkList *bookmarks)
208 {
209 	GFile *file;
210 
211 	bookmarks->pending_ops = g_queue_new ();
212 
213 	nautilus_bookmark_list_load_file (bookmarks);
214 
215 	file = nautilus_bookmark_list_get_file ();
216 	bookmarks->monitor = g_file_monitor_file (file, 0, NULL, NULL);
217 	g_file_monitor_set_rate_limit (bookmarks->monitor, 1000);
218 
219 	g_signal_connect (bookmarks->monitor, "changed",
220 			  G_CALLBACK (bookmark_monitor_changed_cb), bookmarks);
221 
222 	g_object_unref (file);
223 }
224 
225 static void
226 insert_bookmark_internal (NautilusBookmarkList *bookmarks,
227 			  NautilusBookmark     *bookmark,
228 			  int                   index)
229 {
230 	bookmarks->list = g_list_insert (bookmarks->list, bookmark, index);
231 
232 	g_signal_connect_object (bookmark, "contents-changed",
233 				 G_CALLBACK (bookmark_in_list_changed_callback), bookmarks, 0);
234 	g_signal_connect_object (bookmark, "notify::icon",
235 				 G_CALLBACK (bookmark_in_list_notify), bookmarks, 0);
236 	g_signal_connect_object (bookmark, "notify::name",
237 				 G_CALLBACK (bookmark_in_list_notify), bookmarks, 0);
238 }
239 
240 /**
241  * nautilus_bookmark_list_append:
242  *
243  * Append a bookmark to a bookmark list.
244  * @bookmarks: NautilusBookmarkList to append to.
245  * @bookmark: Bookmark to append a copy of.
246  **/
247 void
248 nautilus_bookmark_list_append (NautilusBookmarkList *bookmarks, 
249 			       NautilusBookmark     *bookmark)
250 {
251 	g_return_if_fail (NAUTILUS_IS_BOOKMARK_LIST (bookmarks));
252 	g_return_if_fail (NAUTILUS_IS_BOOKMARK (bookmark));
253 
254 	insert_bookmark_internal (bookmarks, 
255 				  nautilus_bookmark_copy (bookmark), 
256 				  -1);
257 
258 	nautilus_bookmark_list_save_file (bookmarks);
259 }
260 
261 /**
262  * nautilus_bookmark_list_contains:
263  *
264  * Check whether a bookmark with matching name and url is already in the list.
265  * @bookmarks: NautilusBookmarkList to check contents of.
266  * @bookmark: NautilusBookmark to match against.
267  * 
268  * Return value: TRUE if matching bookmark is in list, FALSE otherwise
269  **/
270 gboolean
271 nautilus_bookmark_list_contains (NautilusBookmarkList *bookmarks, 
272 				 NautilusBookmark     *bookmark)
273 {
274 	g_return_val_if_fail (NAUTILUS_IS_BOOKMARK_LIST (bookmarks), FALSE);
275 	g_return_val_if_fail (NAUTILUS_IS_BOOKMARK (bookmark), FALSE);
276 
277 	return g_list_find_custom (bookmarks->list,
278 				   (gpointer)bookmark, 
279 				   nautilus_bookmark_compare_with) 
280 		!= NULL;
281 }
282 
283 /**
284  * nautilus_bookmark_list_delete_item_at:
285  * 
286  * Delete the bookmark at the specified position.
287  * @bookmarks: the list of bookmarks.
288  * @index: index, must be less than length of list.
289  **/
290 void
291 nautilus_bookmark_list_delete_item_at (NautilusBookmarkList *bookmarks, 
292 				       guint                 index)
293 {
294 	GList *doomed;
295 
296 	g_return_if_fail (NAUTILUS_IS_BOOKMARK_LIST (bookmarks));
297 	g_return_if_fail (index < g_list_length (bookmarks->list));
298 
299 	doomed = g_list_nth (bookmarks->list, index);
300 	bookmarks->list = g_list_remove_link (bookmarks->list, doomed);
301 
302 	g_assert (NAUTILUS_IS_BOOKMARK (doomed->data));
303 	stop_monitoring_bookmark (bookmarks, NAUTILUS_BOOKMARK (doomed->data));
304 	g_object_unref (doomed->data);
305 
306 	g_list_free_1 (doomed);
307 
308 	nautilus_bookmark_list_save_file (bookmarks);
309 }
310 
311 /**
312  * nautilus_bookmark_list_move_item:
313  *
314  * Move the item from the given position to the destination.
315  * @index: the index of the first bookmark.
316  * @destination: the index of the second bookmark.
317  **/
318 void
319 nautilus_bookmark_list_move_item (NautilusBookmarkList *bookmarks,
320 				  guint index,
321 				  guint destination)
322 {
323 	GList *bookmark_item;
324 
325 	if (index == destination) {
326 		return;
327 	}
328 
329 	bookmark_item = g_list_nth (bookmarks->list, index);
330 	bookmarks->list = g_list_remove_link (bookmarks->list,
331 					      bookmark_item);
332 
333 	bookmarks->list = g_list_insert (bookmarks->list,
334 					 bookmark_item->data,
335 					 destination);
336 
337 	nautilus_bookmark_list_save_file (bookmarks);
338 }
339 
340 /**
341  * nautilus_bookmark_list_delete_items_with_uri:
342  * 
343  * Delete all bookmarks with the given uri.
344  * @bookmarks: the list of bookmarks.
345  * @uri: The uri to match.
346  **/
347 void
348 nautilus_bookmark_list_delete_items_with_uri (NautilusBookmarkList *bookmarks, 
349 				      	      const char           *uri)
350 {
351 	GList *node, *next;
352 	gboolean list_changed;
353 	char *bookmark_uri;
354 
355 	g_return_if_fail (NAUTILUS_IS_BOOKMARK_LIST (bookmarks));
356 	g_return_if_fail (uri != NULL);
357 
358 	list_changed = FALSE;
359 	for (node = bookmarks->list; node != NULL;  node = next) {
360 		next = node->next;
361 
362 		bookmark_uri = nautilus_bookmark_get_uri (NAUTILUS_BOOKMARK (node->data));
363 		if (g_strcmp0 (bookmark_uri, uri) == 0) {
364 			bookmarks->list = g_list_remove_link (bookmarks->list, node);
365 			stop_monitoring_bookmark (bookmarks, NAUTILUS_BOOKMARK (node->data));
366 			g_object_unref (node->data);
367 			g_list_free_1 (node);
368 			list_changed = TRUE;
369 		}
370 		g_free (bookmark_uri);
371 	}
372 
373 	if (list_changed) {
374 		nautilus_bookmark_list_save_file (bookmarks);
375 	}
376 }
377 
378 /**
379  * nautilus_bookmark_list_insert_item:
380  * 
381  * Insert a bookmark at a specified position.
382  * @bookmarks: the list of bookmarks.
383  * @index: the position to insert the bookmark at.
384  * @new_bookmark: the bookmark to insert a copy of.
385  **/
386 void
387 nautilus_bookmark_list_insert_item (NautilusBookmarkList *bookmarks,
388 				    NautilusBookmark     *new_bookmark,
389 				    guint                 index)
390 {
391 	g_return_if_fail (NAUTILUS_IS_BOOKMARK_LIST (bookmarks));
392 	g_return_if_fail (index <= g_list_length (bookmarks->list));
393 
394 	insert_bookmark_internal (bookmarks,
395 				  nautilus_bookmark_copy (new_bookmark), 
396 				  index);
397 
398 	nautilus_bookmark_list_save_file (bookmarks);
399 }
400 
401 /**
402  * nautilus_bookmark_list_item_at:
403  * 
404  * Get the bookmark at the specified position.
405  * @bookmarks: the list of bookmarks.
406  * @index: index, must be less than length of list.
407  * 
408  * Return value: the bookmark at position @index in @bookmarks.
409  **/
410 NautilusBookmark *
411 nautilus_bookmark_list_item_at (NautilusBookmarkList *bookmarks, guint index)
412 {
413 	g_return_val_if_fail (NAUTILUS_IS_BOOKMARK_LIST (bookmarks), NULL);
414 	g_return_val_if_fail (index < g_list_length (bookmarks->list), NULL);
415 
416 	return NAUTILUS_BOOKMARK (g_list_nth_data (bookmarks->list, index));
417 }
418 
419 /**
420  * nautilus_bookmark_list_item_with_uri:
421  *
422  * Get the bookmark with the specified URI, if any
423  * @bookmarks: the list of bookmarks.
424  * @uri: an URI
425  *
426  * Return value: the bookmark with URI @uri, or %NULL.
427  **/
428 NautilusBookmark *
429 nautilus_bookmark_list_item_with_uri (NautilusBookmarkList *bookmarks,
430 				      const gchar	   *uri)
431 {
432 	GList *node;
433 	gchar *bookmark_uri;
434 	NautilusBookmark *bookmark;
435 	gboolean found = FALSE;
436 
437 	g_return_val_if_fail (NAUTILUS_IS_BOOKMARK_LIST (bookmarks), NULL);
438 	g_return_val_if_fail (uri != NULL, NULL);
439 
440 	for (node = bookmarks->list; node != NULL; node = node->next) {
441 		bookmark = node->data;
442 		bookmark_uri = nautilus_bookmark_get_uri (bookmark);
443 
444 		if (g_strcmp0 (uri, bookmark_uri) == 0) {
445 			found = TRUE;
446 		}
447 
448 		g_free (bookmark_uri);
449 
450 		if (found) {
451 			return bookmark;
452 		}
453 	}
454 
455 	return NULL;
456 }
457 
458 /**
459  * nautilus_bookmark_list_length:
460  * 
461  * Get the number of bookmarks in the list.
462  * @bookmarks: the list of bookmarks.
463  * 
464  * Return value: the length of the bookmark list.
465  **/
466 guint
467 nautilus_bookmark_list_length (NautilusBookmarkList *bookmarks)
468 {
469 	g_return_val_if_fail (NAUTILUS_IS_BOOKMARK_LIST(bookmarks), 0);
470 
471 	return g_list_length (bookmarks->list);
472 }
473 
474 static void
475 process_next_op (NautilusBookmarkList *bookmarks);
476 
477 static void
478 op_processed_cb (NautilusBookmarkList *self)
479 {
480 	g_queue_pop_tail (self->pending_ops);
481 
482 	if (!g_queue_is_empty (self->pending_ops)) {
483 		process_next_op (self);
484 	}
485 }
486 
487 static void
488 load_callback (GObject *source,
489 	       GAsyncResult *res,
490 	       gpointer user_data)
491 {
492 	NautilusBookmarkList *self = NAUTILUS_BOOKMARK_LIST (source);
493 	gchar *contents;
494 	char **lines;
495 	int i;
496 
497 	contents = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
498 
499 	if (contents == NULL) {
500 		return;
501 	}
502 
503 	lines = g_strsplit (contents, "\n", -1);
504 	for (i = 0; lines[i]; i++) {
505 		/* Ignore empty or invalid lines that cannot be parsed properly */
506 		if (lines[i][0] != '\0' && lines[i][0] != ' ') {
507 			/* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */
508 			/* we must seperate the bookmark uri and the potential label */
509 			char *space, *label;
510 
511 			label = NULL;
512 			space = strchr (lines[i], ' ');
513 			if (space) {
514 				*space = '\0';
515 				label = g_strdup (space + 1);
516 			}
517 
518 			insert_bookmark_internal (self, new_bookmark_from_uri (lines[i], label), -1);
519 			g_free (label);
520 		}
521 	}
522 
523 	g_signal_emit (self, signals[CHANGED], 0);
524 	op_processed_cb (self);
525 
526 	g_strfreev (lines);
527 }
528 
529 static void
530 load_io_thread (GSimpleAsyncResult *result,
531 		GObject *object,
532 		GCancellable *cancellable)
533 {
534 	GFile *file;
535 	gchar *contents;
536 	GError *error = NULL;
537 
538 	file = nautilus_bookmark_list_get_file ();
539 	if (!g_file_query_exists (file, NULL)) {
540 		g_object_unref (file);
541 		file = nautilus_bookmark_list_get_legacy_file ();
542 	}
543 
544 	g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
545 	g_object_unref (file);
546 
547 	if (error != NULL) {
548 		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
549 			g_warning ("Could not load bookmark file: %s\n", error->message);
550 		}
551 		g_error_free (error);
552 	} else {
553 		g_simple_async_result_set_op_res_gpointer (result, contents, g_free);
554 	}
555 }
556 
557 static void
558 load_file_async (NautilusBookmarkList *self)
559 {
560 	GSimpleAsyncResult *result;
561 
562 	/* Wipe out old list. */
563 	clear (self);
564 
565 	result = g_simple_async_result_new (G_OBJECT (self), 
566 					    load_callback, NULL, NULL);
567 	g_simple_async_result_run_in_thread (result, load_io_thread,
568 					     G_PRIORITY_DEFAULT, NULL);
569 	g_object_unref (result);
570 }
571 
572 static void
573 save_callback (GObject *source,
574 	       GAsyncResult *res,
575 	       gpointer user_data)
576 {
577 	NautilusBookmarkList *self = NAUTILUS_BOOKMARK_LIST (source);
578 	GFile *file;
579 
580 	/* re-enable bookmark file monitoring */
581 	file = nautilus_bookmark_list_get_file ();
582 	self->monitor = g_file_monitor_file (file, 0, NULL, NULL);
583 	g_object_unref (file);
584 
585 	g_file_monitor_set_rate_limit (self->monitor, 1000);
586 	g_signal_connect (self->monitor, "changed",
587 			  G_CALLBACK (bookmark_monitor_changed_cb), self);
588 
589 	op_processed_cb (self);
590 }
591 
592 static void
593 save_io_thread (GSimpleAsyncResult *result,
594 		GObject *object,
595 		GCancellable *cancellable)
596 {
597 	gchar *contents, *path;
598 	GFile *parent, *file;
599 	GError *error = NULL;
600 
601 	file = nautilus_bookmark_list_get_file ();
602 	parent = g_file_get_parent (file);
603 	path = g_file_get_path (parent);
604 	g_mkdir_with_parents (path, 0700);
605 	g_free (path);
606 	g_object_unref (parent);
607 
608 	contents = g_simple_async_result_get_op_res_gpointer (result);
609 	g_file_replace_contents (file, 
610 				 contents, strlen (contents),
611 				 NULL, FALSE, 0, NULL,
612 				 NULL, &error);
613 
614 	if (error != NULL) {
615 		g_warning ("Unable to replace contents of the bookmarks file: %s",
616 			   error->message);
617 		g_error_free (error);
618 	}
619 
620 	g_object_unref (file);
621 }
622 
623 static void
624 save_file_async (NautilusBookmarkList *self)
625 {
626 	GSimpleAsyncResult *result;
627 	GString *bookmark_string;
628 	gchar *contents;
629 	GList *l;
630 
631 	bookmark_string = g_string_new (NULL);
632 
633 	/* temporarily disable bookmark file monitoring when writing file */
634 	if (self->monitor != NULL) {
635 		g_file_monitor_cancel (self->monitor);
636 		self->monitor = NULL;
637 	}
638 
639 	for (l = self->list; l; l = l->next) {
640 		NautilusBookmark *bookmark;
641 
642 		bookmark = NAUTILUS_BOOKMARK (l->data);
643 
644 		/* make sure we save label if it has one for compatibility with GTK 2.7 and 2.8 */
645 		if (nautilus_bookmark_get_has_custom_name (bookmark)) {
646 			const char *label;
647 			char *uri;
648 			label = nautilus_bookmark_get_name (bookmark);
649 			uri = nautilus_bookmark_get_uri (bookmark);
650 			g_string_append_printf (bookmark_string,
651 						"%s %s\n", uri, label);
652 			g_free (uri);
653 		} else {
654 			char *uri;
655 			uri = nautilus_bookmark_get_uri (bookmark);
656 			g_string_append_printf (bookmark_string, "%s\n", uri);
657 			g_free (uri);
658 		}
659 	}
660 
661 	result = g_simple_async_result_new (G_OBJECT (self),
662 					    save_callback, NULL, NULL);
663 	contents = g_string_free (bookmark_string, FALSE);
664 	g_simple_async_result_set_op_res_gpointer (result, contents, g_free);
665 
666 	g_simple_async_result_run_in_thread (result, save_io_thread,
667 					     G_PRIORITY_DEFAULT, NULL);
668 	g_object_unref (result);
669 }
670 
671 static void
672 process_next_op (NautilusBookmarkList *bookmarks)
673 {
674 	gint op;
675 
676 	op = GPOINTER_TO_INT (g_queue_peek_tail (bookmarks->pending_ops));
677 
678 	if (op == LOAD_JOB) {
679 		load_file_async (bookmarks);
680 	} else {
681 		save_file_async (bookmarks);
682 	}
683 }
684 
685 /**
686  * nautilus_bookmark_list_load_file:
687  * 
688  * Reads bookmarks from file, clobbering contents in memory.
689  * @bookmarks: the list of bookmarks to fill with file contents.
690  **/
691 static void
692 nautilus_bookmark_list_load_file (NautilusBookmarkList *bookmarks)
693 {
694 	g_queue_push_head (bookmarks->pending_ops, GINT_TO_POINTER (LOAD_JOB));
695 
696 	if (g_queue_get_length (bookmarks->pending_ops) == 1) {
697 		process_next_op (bookmarks);
698 	}
699 }
700 
701 /**
702  * nautilus_bookmark_list_save_file:
703  * 
704  * Save bookmarks to disk.
705  * @bookmarks: the list of bookmarks to save.
706  **/
707 static void
708 nautilus_bookmark_list_save_file (NautilusBookmarkList *bookmarks)
709 {
710 	g_signal_emit (bookmarks, signals[CHANGED], 0);
711 
712 	g_queue_push_head (bookmarks->pending_ops, GINT_TO_POINTER (SAVE_JOB));
713 
714 	if (g_queue_get_length (bookmarks->pending_ops) == 1) {
715 		process_next_op (bookmarks);
716 	}
717 }
718 
719 /**
720  * nautilus_bookmark_list_new:
721  * 
722  * Create a new bookmark_list, with contents read from disk.
723  * 
724  * Return value: A pointer to the new widget.
725  **/
726 NautilusBookmarkList *
727 nautilus_bookmark_list_new (void)
728 {
729 	NautilusBookmarkList *list;
730 
731 	list = NAUTILUS_BOOKMARK_LIST (g_object_new (NAUTILUS_TYPE_BOOKMARK_LIST, NULL));
732 
733 	return list;
734 }