Index: data/ui/rhythmbox-ui.xml
===================================================================
RCS file: /cvs/gnome/rhythmbox/data/ui/rhythmbox-ui.xml,v
retrieving revision 1.36
diff -u -u -r1.36 rhythmbox-ui.xml
--- data/ui/rhythmbox-ui.xml	3 Feb 2006 09:31:08 -0000	1.36
+++ data/ui/rhythmbox-ui.xml	10 Feb 2006 05:24:04 -0000
@@ -201,4 +201,9 @@
     <menuitem name="DeleteAutoPlaylistPopup" action="MusicPlaylistDeletePlaylist"/>
   </popup>
 
+  <popup name="MissingFilesViewPopup">
+    <menuitem name="DeleteMissingFilesPopup" action="EditDelete"/>
+    <menuitem name="PropertiesMissingFilesPopup" action="MusicProperties"/>
+  </popup>
+
 </ui>
Index: rhythmdb/rhythmdb-tree.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb-tree.c,v
retrieving revision 1.92
diff -u -u -r1.92 rhythmdb-tree.c
--- rhythmdb/rhythmdb-tree.c	7 Feb 2006 13:19:56 -0000	1.92
+++ rhythmdb/rhythmdb-tree.c	10 Feb 2006 05:24:12 -0000
@@ -516,6 +516,7 @@
 		case RHYTHMDB_PROP_LAST_PLAYED_STR:
 		case RHYTHMDB_PROP_PLAYBACK_ERROR:
 		case RHYTHMDB_PROP_FIRST_SEEN_STR:
+		case RHYTHMDB_PROP_LAST_SEEN_STR:
 		case RHYTHMDB_PROP_SEARCH_MATCH:
 		case RHYTHMDB_NUM_PROPERTIES:
 			g_assert_not_reached ();
@@ -879,6 +880,7 @@
 		case RHYTHMDB_PROP_LAST_PLAYED_STR:
 		case RHYTHMDB_PROP_PLAYBACK_ERROR:
 		case RHYTHMDB_PROP_FIRST_SEEN_STR:
+		case RHYTHMDB_PROP_LAST_SEEN_STR:
 		case RHYTHMDB_PROP_SEARCH_MATCH:
 		case RHYTHMDB_NUM_PROPERTIES:
 			break;
Index: rhythmdb/rhythmdb.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb.c,v
retrieving revision 1.169
diff -u -u -r1.169 rhythmdb.c
--- rhythmdb/rhythmdb.c	7 Feb 2006 13:19:56 -0000	1.169
+++ rhythmdb/rhythmdb.c	10 Feb 2006 05:24:15 -0000
@@ -1578,6 +1578,8 @@
 	set_props_from_metadata (db, entry, event->vfsinfo, event->metadata);
 
 	/* we've seen this entry */
+	rhythmdb_entry_set_visibility (db, entry, TRUE);
+	
 	g_value_init (&value, G_TYPE_ULONG);
 	g_value_set_ulong (&value, time.tv_sec);
 	rhythmdb_entry_set_internal (db, entry, TRUE, RHYTHMDB_PROP_LAST_SEEN, &value);
@@ -1634,6 +1636,7 @@
 	if (entry) {
 		rb_debug ("deleting entry for %s", event->uri);
 		rhythmdb_entry_set_visibility (db, entry, FALSE);
+		rhythmdb_commit (db);
 	}
 }
 
@@ -2607,13 +2610,25 @@
 	}
 	case RHYTHMDB_PROP_FIRST_SEEN:
 	{
-			rb_refstring_unref (entry->first_seen_str);
-
+		rb_refstring_unref (entry->first_seen_str);
 		val = eel_strdup_strftime (format, localtime ((glong*)&entry->first_seen));
 		entry->first_seen_str = rb_refstring_new_full (val, FALSE);
 		g_free (val);
 		break;
 	}
+	case RHYTHMDB_PROP_LAST_SEEN:
+	{
+		/* only store last seen time as a string for hidden entries */
+		rb_refstring_unref (entry->last_seen_str);
+		if (entry->hidden) {
+			val = eel_strdup_strftime (format, localtime ((glong*)&entry->last_seen));
+			entry->last_seen_str = rb_refstring_new_full (val, FALSE);
+			g_free (val);
+		} else {
+			entry->last_seen_str = NULL;
+		}
+		break;
+	}
 	default:
 		break;
 	}
@@ -2654,7 +2669,7 @@
 }
 
 static void
-rhythmbd_entry_move_to_trash_set_error (RhythmDB *db, RhythmDBEntry *entry,
+rhythmdb_entry_move_to_trash_set_error (RhythmDB *db, RhythmDBEntry *entry,
 				        GnomeVFSResult res)
 {
 	GValue value = { 0, };
@@ -2680,7 +2695,7 @@
 
 	uri = gnome_vfs_uri_new (entry->location);
 	if (uri == NULL) {
-		rhythmbd_entry_move_to_trash_set_error (db, entry, -1);
+		rhythmdb_entry_move_to_trash_set_error (db, entry, -1);
 		return;
 	}
 
@@ -2696,7 +2711,7 @@
 		    res == GNOME_VFS_ERROR_NOT_SUPPORTED) {
 			rhythmdb_entry_set_visibility (db, entry, FALSE);
 		} else {
-			rhythmbd_entry_move_to_trash_set_error (db, entry, -1);
+			rhythmdb_entry_move_to_trash_set_error (db, entry, -1);
 		}
 
 		gnome_vfs_uri_unref (uri);
@@ -2718,7 +2733,8 @@
 
 	shortname = gnome_vfs_uri_extract_short_name (uri);
 	if (shortname == NULL) {
-		rhythmbd_entry_move_to_trash_set_error (db, entry, -1);
+		rhythmdb_entry_move_to_trash_set_error (db, entry, -1);
+		rhythmdb_commit (db);
 		gnome_vfs_uri_unref (uri);
 		gnome_vfs_uri_unref (trash);
 		return;
@@ -2729,7 +2745,8 @@
 	gnome_vfs_uri_unref (trash);
 	g_free (shortname);
 	if (dest == NULL) {
-		rhythmbd_entry_move_to_trash_set_error (db, entry, -1);
+		rhythmdb_entry_move_to_trash_set_error (db, entry, -1);
+		rhythmdb_commit (db);
 		gnome_vfs_uri_unref (uri);
 		return;
 	}
@@ -2745,8 +2762,9 @@
 	if (res == GNOME_VFS_OK) {
 		rhythmdb_entry_set_visibility (db, entry, FALSE);
 	} else {
-		rhythmbd_entry_move_to_trash_set_error (db, entry, res);
+		rhythmdb_entry_move_to_trash_set_error (db, entry, res);
 	}
+	rhythmdb_commit (db);
 
 	gnome_vfs_uri_unref (dest);
 	gnome_vfs_uri_unref (uri);
@@ -3515,6 +3533,7 @@
 			ENUM_ENTRY (RHYTHMDB_PROP_PLAYBACK_ERROR, "Playback error string (gchararray) [playback-error]"),
 			ENUM_ENTRY (RHYTHMDB_PROP_HIDDEN, "Hidden (gboolean) [hidden]"),
 			ENUM_ENTRY (RHYTHMDB_PROP_FIRST_SEEN_STR, "Time Added to Library (gchararray) [first-seen-str]"),
+			ENUM_ENTRY (RHYTHMDB_PROP_LAST_SEEN_STR, "Last time the song was available (gchararray) [last-seen-str]"),
 			ENUM_ENTRY (RHYTHMDB_PROP_SEARCH_MATCH, "Search matching key (gchararray) [search-match]"),
 
 			ENUM_ENTRY (RHYTHMDB_PROP_STATUS, "Status of file (gulong) [status]"),
@@ -3783,6 +3802,7 @@
 	rhythmdb_entry_foreach (RHYTHMDB (data), 
 				(GFunc)entry_volume_mounted_or_unmounted, 
 				&ctxt);
+	rhythmdb_commit (RHYTHMDB (data));
 	g_free (ctxt.mount_point);
 }
 
@@ -3800,6 +3820,7 @@
 	rhythmdb_entry_foreach (RHYTHMDB (data), 
 				(GFunc)entry_volume_mounted_or_unmounted, 
 				&ctxt);
+	rhythmdb_commit (RHYTHMDB (data));
 	g_free (ctxt.mount_point);
 }
 
@@ -3842,6 +3863,8 @@
 		rhythmdb_entry_set_internal (db, entry, TRUE,
 					     RHYTHMDB_PROP_HIDDEN, &new_val);
 		g_value_unset (&new_val);
+
+		rhythmdb_entry_sync_mirrored (db, entry, RHYTHMDB_PROP_LAST_SEEN);
 	}
 	g_value_unset (&old_val);
 }
Index: rhythmdb/rhythmdb.h
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb.h,v
retrieving revision 1.67
diff -u -u -r1.67 rhythmdb.h
--- rhythmdb/rhythmdb.h	7 Feb 2006 13:19:56 -0000	1.67
+++ rhythmdb/rhythmdb.h	10 Feb 2006 05:24:15 -0000
@@ -108,6 +108,7 @@
 	RHYTHMDB_PROP_HIDDEN,
 	RHYTHMDB_PROP_PLAYBACK_ERROR,
 	RHYTHMDB_PROP_FIRST_SEEN_STR,
+	RHYTHMDB_PROP_LAST_SEEN_STR,
 	RHYTHMDB_PROP_SEARCH_MATCH,
 
 	/* Podcast properties */
@@ -202,6 +203,7 @@
 	/* cached data */
 	RBRefString *last_played_str;
 	RBRefString *first_seen_str;
+	RBRefString *last_seen_str;
 
 	/* playback error string */
 	char *playback_error;
@@ -268,6 +270,8 @@
 		return entry->playback_error;
 	case RHYTHMDB_PROP_FIRST_SEEN_STR:
 		return rb_refstring_get (entry->first_seen_str);
+	case RHYTHMDB_PROP_LAST_SEEN_STR:
+		return rb_refstring_get (entry->last_seen_str);
 	case RHYTHMDB_PROP_SEARCH_MATCH:
 		return NULL;	/* synthetic property */
 	/* Podcast properties */
Index: shell/rb-shell-player.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/shell/rb-shell-player.c,v
retrieving revision 1.213
diff -u -u -r1.213 rb-shell-player.c
--- shell/rb-shell-player.c	8 Feb 2006 13:12:39 -0000	1.213
+++ shell/rb-shell-player.c	10 Feb 2006 05:24:16 -0000
@@ -1735,6 +1735,10 @@
 
 	rb_debug  ("got entry %p activated", entry);
 
+	/* don't play hidden tracks */
+	if (rhythmdb_entry_get_boolean (entry, RHYTHMDB_PROP_HIDDEN))
+		return;
+
 	/* ensure the podcast has been downloaded */
 	if (rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TYPE) == RHYTHMDB_ENTRY_TYPE_PODCAST_POST) {
 		if (!rb_podcast_manager_entry_downloaded (entry))
Index: shell/rb-shell.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/shell/rb-shell.c,v
retrieving revision 1.385
diff -u -u -r1.385 rb-shell.c
--- shell/rb-shell.c	6 Feb 2006 10:38:44 -0000	1.385
+++ shell/rb-shell.c	10 Feb 2006 05:24:19 -0000
@@ -87,6 +87,7 @@
 #include "rb-play-queue-source.h"
 #include "eel-gconf-extensions.h"
 #include "bacon-volume.h"
+#include "rb-missing-files-source.h"
 
 #ifdef WITH_AUDIOSCROBBLER
 #include "rb-audioscrobbler.h"
@@ -393,6 +394,7 @@
 	RBIRadioSource *iradio_source;
 	RBPodcastSource *podcast_source;
 	RBPlaylistSource *queue_source;
+	RBMissingFilesSource *missing_files_source;
 
 #ifdef WITH_AUDIOSCROBBLER
 	RBAudioscrobbler *audioscrobbler;
@@ -1203,6 +1205,8 @@
 	shell->priv->podcast_source = RB_PODCAST_SOURCE (rb_podcast_source_new (shell));
 	rb_shell_append_source (shell, RB_SOURCE (shell->priv->podcast_source), NULL);
 
+	shell->priv->missing_files_source = RB_MISSING_FILES_SOURCE (rb_missing_files_source_new (shell, shell->priv->library_source));
+	rb_shell_append_source (shell, RB_SOURCE (shell->priv->missing_files_source), RB_SOURCE (shell->priv->library_source));
 
 	/* Initialize playlist manager */
 	rb_debug ("shell: creating playlist manager");
Index: sources/Makefile.am
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/Makefile.am,v
retrieving revision 1.32
diff -u -u -r1.32 Makefile.am
--- sources/Makefile.am	21 Jan 2006 23:06:10 -0000	1.32
+++ sources/Makefile.am	10 Feb 2006 05:24:19 -0000
@@ -30,7 +30,9 @@
 	rb-generic-player-source.c	\
 	rb-generic-player-source.h	\
 	rb-play-queue-source.c		\
-	rb-play-queue-source.h
+	rb-play-queue-source.h		\
+	rb-missing-files-source.c	\
+	rb-missing-files-source.h
 
 INCLUDES =						\
         -DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
Index: sources/rb-iradio-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-iradio-source.c,v
retrieving revision 1.106
diff -u -u -r1.106 rb-iradio-source.c
--- sources/rb-iradio-source.c	9 Feb 2006 15:00:54 -0000	1.106
+++ sources/rb-iradio-source.c	10 Feb 2006 05:24:20 -0000
@@ -295,12 +295,12 @@
 	source->priv->stations = rb_entry_view_new (source->priv->db, shell_player,
 						    CONF_STATE_IRADIO_SORTING,
 						    FALSE, FALSE);
-	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_TITLE);
-	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_GENRE);
-/* 	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_QUALITY); */
-	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_RATING);
-/*	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_PLAY_COUNT);*/
-	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_LAST_PLAYED);
+	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_TITLE, TRUE);
+	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_GENRE, FALSE);
+/* 	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_QUALITY, FALSE); */
+	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_RATING, FALSE);
+/*	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);*/
+	rb_entry_view_append_column (source->priv->stations, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
 	g_signal_connect_object (G_OBJECT (source->priv->stations),
 				 "sort-order-changed",
 				 G_CALLBACK (rb_iradio_source_songs_view_sort_order_changed_cb),
Index: sources/rb-library-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-library-source.c,v
retrieving revision 1.143
diff -u -u -r1.143 rb-library-source.c
--- sources/rb-library-source.c	9 Feb 2006 15:00:54 -0000	1.143
+++ sources/rb-library-source.c	10 Feb 2006 05:24:20 -0000
@@ -420,19 +420,19 @@
 	source->priv->songs = rb_entry_view_new (source->priv->db, shell_player,
 						 source->priv->sorting_key,
 						 TRUE, FALSE);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TRACK_NUMBER);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TITLE);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_GENRE);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ARTIST);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ALBUM);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_YEAR);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_DURATION);
-/* 	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_QUALITY); */
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_RATING);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_PLAY_COUNT);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_LAST_PLAYED);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TITLE, TRUE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_GENRE, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_YEAR, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_DURATION, FALSE);
+/* 	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_QUALITY, FALSE); */
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_RATING, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
 	if (rb_library_source_has_first_added_column (source))
-		rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_FIRST_SEEN);
+		rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_FIRST_SEEN, FALSE);
 
 	g_signal_connect_object (G_OBJECT (source->priv->songs), "show_popup",
 				 G_CALLBACK (rb_library_source_songs_show_popup_cb), source, 0);
Index: sources/rb-playlist-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-playlist-source.c,v
retrieving revision 1.106
diff -u -u -r1.106 rb-playlist-source.c
--- sources/rb-playlist-source.c	7 Feb 2006 13:22:32 -0000	1.106
+++ sources/rb-playlist-source.c	10 Feb 2006 05:24:20 -0000
@@ -252,16 +252,16 @@
 						    "PlaylistTrack", NULL, 0);
 	}
 
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TITLE);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_GENRE);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ARTIST);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ALBUM);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_YEAR);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_DURATION);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_RATING);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_PLAY_COUNT);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_LAST_PLAYED);
-	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_FIRST_SEEN);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TITLE, TRUE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_GENRE, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_YEAR, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_DURATION, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_RATING, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_FIRST_SEEN, FALSE);
 	rb_entry_view_set_columns_clickable (source->priv->songs, FALSE);
 
 	rb_playlist_source_setup_entry_view (source, source->priv->songs);
Index: sources/rb-podcast-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-podcast-source.c,v
retrieving revision 1.50
diff -u -u -r1.50 rb-podcast-source.c
--- sources/rb-podcast-source.c	9 Feb 2006 15:00:54 -0000	1.50
+++ sources/rb-podcast-source.c	10 Feb 2006 05:24:22 -0000
@@ -513,7 +513,7 @@
 					    (GCompareDataFunc) rb_podcast_source_post_date_cell_sort_func, 0);
 						    
 
-	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_TITLE);
+	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_TITLE, TRUE);
 	
 	/* COLUMN FEED */
 	column = gtk_tree_view_column_new ();
@@ -535,10 +535,10 @@
 					    (GCompareDataFunc) rb_podcast_source_post_feed_cell_sort_func, 0);
 
 	
-	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_DURATION);
-	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_RATING);
-	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_PLAY_COUNT);
-	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_LAST_PLAYED);
+	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_DURATION, FALSE);
+	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_RATING, FALSE);
+	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);
+	rb_entry_view_append_column (source->priv->posts, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
 
 
 	/* Status column */
Index: widgets/rb-entry-view.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/widgets/rb-entry-view.c,v
retrieving revision 1.126
diff -u -u -r1.126 rb-entry-view.c
--- widgets/rb-entry-view.c	6 Feb 2006 20:33:00 -0000	1.126
+++ widgets/rb-entry-view.c	10 Feb 2006 05:24:22 -0000
@@ -187,6 +187,8 @@
 
 static guint rb_entry_view_signals[LAST_SIGNAL] = { 0 };
 
+static GQuark rb_entry_view_column_always_visible;
+
 static gboolean
 type_ahead_search_func (GtkTreeModel *model, gint column,
 			const gchar *key, GtkTreeIter *iter,
@@ -347,6 +349,8 @@
 			      0);
 
 	g_type_class_add_private (klass, sizeof (RBEntryViewPrivate));
+
+	rb_entry_view_column_always_visible = g_quark_from_static_string ("rb_entry_view_column_always_visible");
 }
 
 static void
@@ -881,7 +885,7 @@
 }
 
 void
-rb_entry_view_append_column (RBEntryView *view, RBEntryViewColumn coltype)
+rb_entry_view_append_column (RBEntryView *view, RBEntryViewColumn coltype, gboolean always_visible)
 {
 	GtkTreeViewColumn *column;
 	GtkCellRenderer *renderer = NULL;
@@ -1049,6 +1053,27 @@
 		strings[0] = title;
 		strings[1] = rb_entry_view_get_time_date_column_sample ();
 		break;
+	case RB_ENTRY_VIEW_COL_LAST_SEEN:
+		propid = RHYTHMDB_PROP_LAST_SEEN;
+		cell_data->propid = RHYTHMDB_PROP_LAST_SEEN_STR;
+		cell_data_func = (GtkTreeCellDataFunc) rb_entry_view_string_cell_data_func;
+		sort_propid = RHYTHMDB_PROP_LAST_SEEN;
+		sort_func = (GCompareDataFunc) rhythmdb_query_model_ulong_sort_func;
+		title = _("Last _Seen");	/* ? */
+		key = "LastSeen";
+		strings[0] = title;
+		strings[1] = rb_entry_view_get_time_date_column_sample ();
+		break;
+	case RB_ENTRY_VIEW_COL_LOCATION:
+		propid = RHYTHMDB_PROP_LOCATION;
+		cell_data->propid = RHYTHMDB_PROP_LOCATION;
+		cell_data_func = (GtkTreeCellDataFunc) rb_entry_view_string_cell_data_func;
+		sort_propid = RHYTHMDB_PROP_LOCATION;
+		sort_func = (GCompareDataFunc) rhythmdb_query_model_location_sort_func;
+		title = _("L_ocation");		/* ? */
+		key = "Location";
+		ellipsize = TRUE;
+		break;
 	default:
 		g_assert_not_reached ();
 		propid = -1;
@@ -1085,7 +1110,13 @@
 	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
 	gtk_tree_view_column_set_clickable (column, TRUE);
 
+	if (always_visible)
+		g_object_set_qdata (G_OBJECT (column), 
+				    rb_entry_view_column_always_visible, 
+				    GINT_TO_POINTER (1));
+
 	g_hash_table_insert (view->priv->propid_column_map, GINT_TO_POINTER (propid), column);
+
 	rb_entry_view_append_column_custom (view, column, title, key, sort_func, sort_propid);
 }
 
@@ -1703,11 +1734,12 @@
 {
 	gboolean visible;
 
-	/* title is always visible */
-	if (propid == RHYTHMDB_PROP_TITLE)
-		return;
+	if (g_object_get_qdata (G_OBJECT (column), 
+				rb_entry_view_column_always_visible) == GINT_TO_POINTER (1))
+		visible = TRUE;
+	else
+		visible = (g_list_find (visible_props, GINT_TO_POINTER (propid)) != NULL);
 
-	visible = (g_list_find (visible_props, GINT_TO_POINTER (propid)) != NULL);
 	gtk_tree_view_column_set_visible (column, visible);
 }
 
Index: widgets/rb-entry-view.h
===================================================================
RCS file: /cvs/gnome/rhythmbox/widgets/rb-entry-view.h,v
retrieving revision 1.30
diff -u -u -r1.30 rb-entry-view.h
--- widgets/rb-entry-view.h	29 Jan 2006 09:45:25 -0000	1.30
+++ widgets/rb-entry-view.h	10 Feb 2006 05:24:22 -0000
@@ -52,7 +52,9 @@
 	RB_ENTRY_VIEW_COL_PLAY_COUNT,
 	RB_ENTRY_VIEW_COL_YEAR,
 	RB_ENTRY_VIEW_COL_LAST_PLAYED,
-	RB_ENTRY_VIEW_COL_FIRST_SEEN
+	RB_ENTRY_VIEW_COL_FIRST_SEEN,
+	RB_ENTRY_VIEW_COL_LAST_SEEN,
+	RB_ENTRY_VIEW_COL_LOCATION
 } RBEntryViewColumn;
 
 typedef enum {
@@ -93,7 +95,8 @@
 							 const char *sort_key, gboolean drag_source, 
 							 gboolean drag_dest);
 
-void		rb_entry_view_append_column		(RBEntryView *view, RBEntryViewColumn coltype);
+void		rb_entry_view_append_column		(RBEntryView *view, 
+							 RBEntryViewColumn coltype, gboolean always_visible);
 
 void		rb_entry_view_append_column_custom	(RBEntryView *view, GtkTreeViewColumn *column,
 							 const char *title, const char *key,
--- /dev/null	2006-02-10 09:27:13.757321776 +1100
+++ sources/rb-missing-files-source.c	2006-02-10 16:09:54.000000000 +1100
@@ -0,0 +1,385 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ *  Copyright (C) 2006  Jonathan Matthew <jonathan@kaolin.wh9.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ * This source lists files rhythmbox cannot find, and maybe tries to stop 
+ * you from trying to play them.
+ */
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "rb-entry-view.h"
+#include "rb-search-entry.h"
+#include "rb-missing-files-source.h"
+#include "rb-song-info.h"
+#include "rb-util.h"
+#include "rb-debug.h"
+
+
+static void rb_missing_files_source_class_init (RBMissingFilesSourceClass *klass);
+static void rb_missing_files_source_init (RBMissingFilesSource *source);
+static GObject *rb_missing_files_source_constructor (GType type, guint n_construct_properties,
+						     GObjectConstructParam *construct_properties);
+static void rb_missing_files_source_dispose (GObject *object);
+static void rb_missing_files_source_set_property (GObject *object,
+						  guint prop_id,
+						  const GValue *value,
+						  GParamSpec *pspec);
+static void rb_missing_files_source_get_property (GObject *object,
+						  guint prop_id,
+						  GValue *value,
+						  GParamSpec *pspec);
+
+static RBEntryView *impl_get_entry_view (RBSource *source);
+static void impl_song_properties (RBSource *source);
+static void impl_delete (RBSource *source);
+
+static void rb_missing_files_source_row_deleted_cb (GtkTreeModel *model,
+						    GtkTreePath *path,
+						    RBMissingFilesSource *source);
+static void rb_missing_files_source_row_inserted_cb (GtkTreeModel *model,
+						     GtkTreePath *path,
+						     GtkTreeIter *iter,
+						     RBMissingFilesSource *source);
+static void rb_missing_files_source_songs_show_popup_cb (RBEntryView *view,
+							 RBMissingFilesSource *source);
+static void rb_missing_files_source_songs_sort_order_changed_cb (RBEntryView *view, 
+								 RBMissingFilesSource *source); 
+
+#define MISSING_FILES_SOURCE_SONGS_POPUP_PATH "/MissingFilesViewPopup"
+
+struct RBMissingFilesSourcePrivate
+{
+	RhythmDB *db;
+	RhythmDBQueryModel *model;
+	RBEntryView *view;
+	RhythmDBEntryType entry_type;
+
+	GtkWidget *vbox;
+	GdkPixbuf *pixbuf;
+	GtkActionGroup *action_group;
+};
+
+enum
+{
+	PROP_0,
+	PROP_ENTRY_TYPE
+};
+
+G_DEFINE_TYPE (RBMissingFilesSource, rb_missing_files_source, RB_TYPE_SOURCE);
+
+static void
+rb_missing_files_source_class_init (RBMissingFilesSourceClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	RBSourceClass *source_class = RB_SOURCE_CLASS (klass);
+
+	object_class->dispose = rb_missing_files_source_dispose;
+	object_class->constructor = rb_missing_files_source_constructor;
+
+	object_class->set_property = rb_missing_files_source_set_property;
+	object_class->get_property = rb_missing_files_source_get_property;
+
+	source_class->impl_can_browse = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_get_entry_view = impl_get_entry_view;
+	source_class->impl_can_rename = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_search = (RBSourceFeatureFunc) rb_false_function;
+
+	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_delete = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_can_move_to_trash = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_copy = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_add_to_queue = (RBSourceFeatureFunc) rb_false_function;
+
+	source_class->impl_delete = impl_delete;
+
+	source_class->impl_song_properties = impl_song_properties;
+	source_class->impl_try_playlist = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_pause = (RBSourceFeatureFunc) rb_false_function;
+
+	source_class->impl_have_url = (RBSourceFeatureFunc) rb_false_function;
+	
+	g_object_class_install_property (object_class,
+					 PROP_ENTRY_TYPE,
+					 g_param_spec_uint ("entry-type",
+							    "Entry type",
+							    "Type of the entries which should be displayed by this source",
+							    0,
+							    G_MAXINT,
+							    RHYTHMDB_ENTRY_TYPE_SONG,
+							    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	
+	g_type_class_add_private (klass, sizeof (RBMissingFilesSourcePrivate));
+}
+
+static void
+rb_missing_files_source_init (RBMissingFilesSource *source)
+{
+	gint size;
+	GdkPixbuf *pixbuf;
+
+	source->priv = G_TYPE_INSTANCE_GET_PRIVATE (source, RB_TYPE_MISSING_FILES_SOURCE, RBMissingFilesSourcePrivate);
+
+	gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &size, NULL);
+	pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+					   GTK_STOCK_MISSING_IMAGE,
+					   size,
+					   0, NULL);
+	rb_source_set_pixbuf (RB_SOURCE (source), pixbuf);
+	if (pixbuf != NULL) {
+		g_object_unref (pixbuf);
+	}
+}
+
+static GObject *
+rb_missing_files_source_constructor (GType type, guint n_construct_properties,
+				     GObjectConstructParam *construct_properties)
+{
+	GObject *shell_player;
+	RBMissingFilesSource *source;
+	RBMissingFilesSourceClass *klass;
+	RBShell *shell;
+	GPtrArray *query;
+
+	klass = RB_MISSING_FILES_SOURCE_CLASS (g_type_class_peek (RB_TYPE_MISSING_FILES_SOURCE));
+
+	source = RB_MISSING_FILES_SOURCE (G_OBJECT_CLASS (rb_missing_files_source_parent_class)->
+			constructor (type, n_construct_properties, construct_properties));
+
+	g_object_get (G_OBJECT (source), "shell", &shell, NULL);
+	g_object_get (G_OBJECT (shell), "db", &source->priv->db, NULL);
+	shell_player = rb_shell_get_player (shell);
+	g_object_unref (G_OBJECT (shell));
+	
+	/* construct real query */
+	query = rhythmdb_query_parse (source->priv->db,
+				      RHYTHMDB_QUERY_PROP_EQUALS,
+				      	RHYTHMDB_PROP_TYPE,
+					source->priv->entry_type,
+				      RHYTHMDB_QUERY_PROP_EQUALS,
+				      	RHYTHMDB_PROP_HIDDEN,
+					TRUE,
+				      RHYTHMDB_QUERY_END);
+	source->priv->model = rhythmdb_query_model_new (source->priv->db, query,
+							NULL, 0, FALSE);
+	g_ptr_array_free (query, TRUE);
+
+	g_object_set (G_OBJECT (source->priv->model), "show-hidden", TRUE, NULL);
+
+	g_signal_connect_object (G_OBJECT (source->priv->model), "row-deleted",
+				 G_CALLBACK (rb_missing_files_source_row_deleted_cb),
+				 source, 0);
+	g_signal_connect_object (G_OBJECT (source->priv->model), "row-inserted",
+				 G_CALLBACK (rb_missing_files_source_row_inserted_cb),
+				 source, 0);
+
+	/* set up entry view */
+	source->priv->vbox = gtk_vbox_new (FALSE, 5);
+
+	gtk_container_add (GTK_CONTAINER (source), source->priv->vbox);
+
+	source->priv->view = rb_entry_view_new (source->priv->db, shell_player, 
+						NULL, FALSE, FALSE);
+
+	rb_entry_view_set_model (source->priv->view, source->priv->model);
+
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
+/*	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_GENRE, FALSE); */
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
+	/*
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_YEAR, FALSE);
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_DURATION, FALSE);
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_RATING, FALSE);
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_FIRST_SEEN, FALSE); */
+
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LOCATION, TRUE);
+	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LAST_SEEN, TRUE);
+	rb_entry_view_set_columns_clickable (source->priv->view, TRUE);
+	
+	gtk_box_pack_start_defaults (GTK_BOX (source->priv->vbox), GTK_WIDGET (source->priv->view));
+	g_signal_connect_object (G_OBJECT (source->priv->view), "show_popup",
+				 G_CALLBACK (rb_missing_files_source_songs_show_popup_cb), source, 0);
+	g_signal_connect_object (G_OBJECT (source->priv->view), "sort-order-changed",
+				 G_CALLBACK (rb_missing_files_source_songs_sort_order_changed_cb), source, 0);
+		
+	gtk_widget_show_all (GTK_WIDGET (source));
+
+	/* use a fake model for the source's query model property, so we can't try to play
+	 * any of the hidden entries.
+	 */
+	g_object_set (G_OBJECT (source), 
+		      "query-model", rhythmdb_query_model_new_empty (source->priv->db), 
+		      NULL);
+
+	return G_OBJECT (source);
+}
+
+static void
+rb_missing_files_source_dispose (GObject *object)
+{
+	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (object);
+
+	if (source->priv->db) {
+		g_object_unref (G_OBJECT (source->priv->db));
+		source->priv->db = NULL;
+	}
+	if (source->priv->model) {
+		g_object_unref (G_OBJECT (source->priv->model));
+		source->priv->model = NULL;
+	}
+
+	G_OBJECT_CLASS (rb_missing_files_source_parent_class)->dispose (object);
+}
+
+
+static RBEntryView *
+impl_get_entry_view (RBSource *asource)
+{
+	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (asource);
+	return source->priv->view;
+}
+
+static void 
+rb_missing_files_source_set_property (GObject *object,
+				      guint prop_id,
+				      const GValue *value,
+				      GParamSpec *pspec)
+{
+	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (object);
+
+	switch (prop_id)
+	{
+	case PROP_ENTRY_TYPE:
+		source->priv->entry_type = g_value_get_uint (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void 
+rb_missing_files_source_get_property (GObject *object,
+				      guint prop_id,
+				      GValue *value,
+				      GParamSpec *pspec)
+{
+	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (object);
+
+	switch (prop_id)
+	{
+	case PROP_ENTRY_TYPE:
+		g_value_set_uint (value, source->priv->entry_type);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+RBSource *
+rb_missing_files_source_new (RBShell *shell,
+			     RBLibrarySource *library)
+{
+	RBSource *source;
+	RhythmDBEntryType entry_type;
+
+	g_object_get (G_OBJECT (library), "entry-type", &entry_type, NULL);
+	source = RB_SOURCE (g_object_new (RB_TYPE_MISSING_FILES_SOURCE,
+					  "name", _("Missing Files"),
+					  "entry-type", entry_type,
+					  "shell", shell,
+					  "visibility", FALSE,
+					  NULL));
+	return source;
+}
+
+static void
+_update_visibility (RBMissingFilesSource *source, int adjust)
+{
+	gint count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (source->priv->model), NULL) + adjust;
+	g_object_set (G_OBJECT (source), "visibility", (count > 0), NULL);
+}
+
+static void
+rb_missing_files_source_row_deleted_cb (GtkTreeModel *model,
+				        GtkTreePath *path,
+					RBMissingFilesSource *source)
+{
+	_update_visibility (source, -1);
+}
+
+static void
+rb_missing_files_source_row_inserted_cb (GtkTreeModel *model,
+				         GtkTreePath *path,
+					 GtkTreeIter *iter,
+					 RBMissingFilesSource *source)
+{
+	_update_visibility (source, 0);
+}
+
+static void 
+rb_missing_files_source_songs_show_popup_cb (RBEntryView *view,
+					     RBMissingFilesSource *source)
+{
+	_rb_source_show_popup (RB_SOURCE (source), MISSING_FILES_SOURCE_SONGS_POPUP_PATH);
+}
+
+static void 
+impl_song_properties (RBSource *asource)
+{
+	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (asource);
+	GtkWidget *song_info = NULL;
+
+	g_return_if_fail (source->priv->view != NULL);
+
+	song_info = rb_song_info_new (asource, NULL);
+	if (song_info)
+		gtk_widget_show_all (song_info);
+	else
+		rb_debug ("failed to create dialog, or no selection!");
+}
+
+static void
+impl_delete (RBSource *asource)
+{
+	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (asource);
+	GList *sel, *tem;
+
+	sel = rb_entry_view_get_selected_entries (source->priv->view);
+	for (tem = sel; tem != NULL; tem = tem->next) {
+		rhythmdb_entry_delete (source->priv->db, tem->data);
+		rhythmdb_commit (source->priv->db);
+	}
+	g_list_free (sel);
+}
+
+static void 
+rb_missing_files_source_songs_sort_order_changed_cb (RBEntryView *view, 
+						     RBMissingFilesSource *source)
+{
+	rb_entry_view_resort_model (view);
+}
--- /dev/null	2006-02-10 09:27:13.757321776 +1100
+++ sources/rb-missing-files-source.h	2006-02-10 16:05:31.000000000 +1100
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2006  Jonathan Matthew  <jonathan@kaolin.wh9.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __RB_MISSING_FILES_SOURCE_H
+#define __RB_MISSING_FILES_SOURCE_H
+
+#include "rb-shell.h"
+#include "rb-source.h"
+#include "rb-library-source.h"
+
+G_BEGIN_DECLS
+
+#define RB_TYPE_MISSING_FILES_SOURCE         (rb_missing_files_source_get_type ())
+#define RB_MISSING_FILES_SOURCE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_MISSING_FILES_SOURCE, RBMissingFilesSource))
+#define RB_MISSING_FILES_SOURCE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_MISSING_FILES_SOURCE, RBMissingFilesSourceClass))
+#define RB_IS_MISSING_FILES_SOURCE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_MISSING_FILES_SOURCE))
+#define RB_IS_MISSING_FILES_SOURCE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_MISSING_FILES_SOURCE))
+#define RB_MISSING_FILES_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_MISSING_FILES_SOURCE, RBMissingFilesSourceClass))
+
+typedef struct RBMissingFilesSourcePrivate RBMissingFilesSourcePrivate;
+
+typedef struct
+{
+	RBSource parent;
+
+	RBMissingFilesSourcePrivate *priv;
+} RBMissingFilesSource;
+
+typedef struct
+{
+	RBSourceClass parent;
+	GdkPixbuf *pixbuf;
+} RBMissingFilesSourceClass;
+
+typedef gboolean (*RBMissingFilesSourceFeatureFunc) (RBMissingFilesSource *source);
+
+GType		rb_missing_files_source_get_type		(void);
+
+RBSource *      rb_missing_files_source_new			(RBShell *shell,
+								 RBLibrarySource *library_source);
+
+G_END_DECLS
+
+#endif /* __RB_MISSING_FILES_SOURCE_H */
+
