hythmbox-2.98/sources/rb-missing-files-source.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found rb-missing-files-source.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found rb-missing-files-source.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
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
  2 /*
  3  *  Copyright (C) 2006  Jonathan Matthew <jonathan@kaolin.wh9.net>
  4  *
  5  *  This program is free software; you can redistribute it and/or modify
  6  *  it under the terms of the GNU General Public License as published by
  7  *  the Free Software Foundation; either version 2 of the License, or
  8  *  (at your option) any later version.
  9  *
 10  *  The Rhythmbox authors hereby grant permission for non-GPL compatible
 11  *  GStreamer plugins to be used and distributed together with GStreamer
 12  *  and Rhythmbox. This permission is above and beyond the permissions granted
 13  *  by the GPL license by which Rhythmbox is covered. If you modify this code
 14  *  you may extend this exception to your version of the code, but you are not
 15  *  obligated to do so. If you do not wish to do so, delete this exception
 16  *  statement from your version.
 17  *
 18  *  This program is distributed in the hope that it will be useful,
 19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21  *  GNU General Public License for more details.
 22  *
 23  *  You should have received a copy of the GNU General Public License
 24  *  along with this program; if not, write to the Free Software
 25  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
 26  *
 27  */
 28 
 29 #include "config.h"
 30 
 31 #include <gtk/gtk.h>
 32 #include <glib/gi18n.h>
 33 
 34 #include "rb-entry-view.h"
 35 #include "rb-missing-files-source.h"
 36 #include "rb-song-info.h"
 37 #include "rb-util.h"
 38 #include "rb-debug.h"
 39 
 40 /**
 41  * SECTION:rb-missing-files-source
 42  * @short_description: source displaying files missing from the library
 43  *
 44  * This source displays files that rhythmbox cannot find at the expected
 45  * locations.  On startup, it does a file access check for every file
 46  * in the library, hiding those that fail.  This source sets up a
 47  * query model that matches only hidden entries.  It displays the file
 48  * location and the last time the file was successfully accessed.
 49  *
 50  * The source only displayed in the source list when there are hidden
 51  * entries to show.
 52  */
 53 
 54 static void rb_missing_files_source_class_init (RBMissingFilesSourceClass *klass);
 55 static void rb_missing_files_source_init (RBMissingFilesSource *source);
 56 static void rb_missing_files_source_constructed (GObject *object);
 57 static void rb_missing_files_source_dispose (GObject *object);
 58 static void rb_missing_files_source_set_property (GObject *object,
 59 						  guint prop_id,
 60 						  const GValue *value,
 61 						  GParamSpec *pspec);
 62 static void rb_missing_files_source_get_property (GObject *object,
 63 						  guint prop_id,
 64 						  GValue *value,
 65 						  GParamSpec *pspec);
 66 
 67 static RBEntryView *impl_get_entry_view (RBSource *source);
 68 static void impl_song_properties (RBSource *source);
 69 static void impl_delete (RBSource *source);
 70 static void impl_get_status (RBDisplayPage *page, char **text, char **progress_text, float *progress);
 71 
 72 static void rb_missing_files_source_songs_show_popup_cb (RBEntryView *view,
 73 							 gboolean over_entry,
 74 							 RBMissingFilesSource *source);
 75 static void rb_missing_files_source_songs_sort_order_changed_cb (GObject *object,
 76 								 GParamSpec *pspec,
 77 								 RBMissingFilesSource *source);
 78 
 79 #define MISSING_FILES_SOURCE_SONGS_POPUP_PATH "/MissingFilesViewPopup"
 80 
 81 struct RBMissingFilesSourcePrivate
 82 {
 83 	RhythmDB *db;
 84 	RBEntryView *view;
 85 };
 86 
 87 G_DEFINE_TYPE (RBMissingFilesSource, rb_missing_files_source, RB_TYPE_SOURCE);
 88 
 89 static void
 90 rb_missing_files_source_class_init (RBMissingFilesSourceClass *klass)
 91 {
 92 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 93 	RBDisplayPageClass *page_class = RB_DISPLAY_PAGE_CLASS (klass);
 94 	RBSourceClass *source_class = RB_SOURCE_CLASS (klass);
 95 
 96 	object_class->dispose = rb_missing_files_source_dispose;
 97 	object_class->constructed = rb_missing_files_source_constructed;
 98 
 99 	object_class->set_property = rb_missing_files_source_set_property;
100 	object_class->get_property = rb_missing_files_source_get_property;
101 
102 	page_class->get_status = impl_get_status;
103 
104 	source_class->impl_get_entry_view = impl_get_entry_view;
105 	source_class->impl_can_rename = (RBSourceFeatureFunc) rb_false_function;
106 
107 	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
108 	source_class->impl_can_delete = (RBSourceFeatureFunc) rb_true_function;
109 	source_class->impl_can_move_to_trash = (RBSourceFeatureFunc) rb_false_function;
110 	source_class->impl_can_copy = (RBSourceFeatureFunc) rb_false_function;
111 	source_class->impl_can_add_to_queue = (RBSourceFeatureFunc) rb_false_function;
112 
113 	source_class->impl_delete = impl_delete;
114 
115 	source_class->impl_song_properties = impl_song_properties;
116 	source_class->impl_try_playlist = (RBSourceFeatureFunc) rb_false_function;
117 	source_class->impl_can_pause = (RBSourceFeatureFunc) rb_false_function;
118 
119 	g_type_class_add_private (klass, sizeof (RBMissingFilesSourcePrivate));
120 }
121 
122 static void
123 rb_missing_files_source_init (RBMissingFilesSource *source)
124 {
125 	gint size;
126 	GdkPixbuf *pixbuf;
127 
128 	source->priv = G_TYPE_INSTANCE_GET_PRIVATE (source, RB_TYPE_MISSING_FILES_SOURCE, RBMissingFilesSourcePrivate);
129 
130 	gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL);
131 	pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
132 					   "dialog-warning",
133 					   size,
134 					   0, NULL);
135 	g_object_set (source, "pixbuf", pixbuf, NULL);
136 	if (pixbuf != NULL) {
137 		g_object_unref (pixbuf);
138 	}
139 }
140 
141 static void
142 rb_missing_files_source_constructed (GObject *object)
143 {
144 	GObject *shell_player;
145 	RBMissingFilesSource *source;
146 	RBShell *shell;
147 	GPtrArray *query;
148 	RhythmDBQueryModel *model;
149 	RhythmDBEntryType *entry_type;
150 
151 	RB_CHAIN_GOBJECT_METHOD (rb_missing_files_source_parent_class, constructed, object);
152 	source = RB_MISSING_FILES_SOURCE (object);
153 
154 	g_object_get (source,
155 		      "shell", &shell,
156 		      "entry-type", &entry_type,
157 		      NULL);
158 	g_object_get (shell,
159 		      "db", &source->priv->db,
160 		      "shell-player", &shell_player,
161 		      NULL);
162 	g_object_unref (shell);
163 
164 	/* construct real query */
165 	query = rhythmdb_query_parse (source->priv->db,
166 				      RHYTHMDB_QUERY_PROP_EQUALS,
167 				      	RHYTHMDB_PROP_TYPE,
168 					entry_type,
169 				      RHYTHMDB_QUERY_PROP_EQUALS,
170 				      	RHYTHMDB_PROP_HIDDEN,
171 					TRUE,
172 				      RHYTHMDB_QUERY_END);
173 	g_object_unref (entry_type);
174 
175 	model = rhythmdb_query_model_new (source->priv->db, query,
176 					  NULL, NULL, NULL, FALSE);
177 
178 	rhythmdb_query_free (query);
179 
180 	g_object_set (model, "show-hidden", TRUE, NULL);
181 
182 	/* set up entry view */
183 	source->priv->view = rb_entry_view_new (source->priv->db, shell_player,
184 						FALSE, FALSE);
185 	g_object_unref (shell_player);
186 
187 	rb_entry_view_set_model (source->priv->view, model);
188 
189 	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
190 	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
191 /*	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_GENRE, FALSE); */
192 	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
193 	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
194 	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LOCATION, TRUE);
195 	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LAST_SEEN, TRUE);
196 
197 	rb_entry_view_set_columns_clickable (source->priv->view, TRUE);
198 
199 	gtk_container_add (GTK_CONTAINER (source), GTK_WIDGET (source->priv->view));
200 	g_signal_connect_object (source->priv->view, "show_popup",
201 				 G_CALLBACK (rb_missing_files_source_songs_show_popup_cb), source, 0);
202 	g_signal_connect_object (source->priv->view, "notify::sort-order",
203 				 G_CALLBACK (rb_missing_files_source_songs_sort_order_changed_cb), source, 0);
204 
205 	gtk_widget_show_all (GTK_WIDGET (source));
206 
207 	g_object_set (source, "query-model", model, NULL);
208 	g_object_unref (model);
209 }
210 
211 static void
212 rb_missing_files_source_dispose (GObject *object)
213 {
214 	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (object);
215 
216 	if (source->priv->db != NULL) {
217 		g_object_unref (source->priv->db);
218 		source->priv->db = NULL;
219 	}
220 
221 	G_OBJECT_CLASS (rb_missing_files_source_parent_class)->dispose (object);
222 }
223 
224 static RBEntryView *
225 impl_get_entry_view (RBSource *asource)
226 {
227 	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (asource);
228 	return source->priv->view;
229 }
230 
231 static void
232 rb_missing_files_source_set_property (GObject *object,
233 				      guint prop_id,
234 				      const GValue *value,
235 				      GParamSpec *pspec)
236 {
237 	/*RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (object);*/
238 
239 	switch (prop_id)
240 	{
241 	default:
242 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
243 		break;
244 	}
245 }
246 
247 static void
248 rb_missing_files_source_get_property (GObject *object,
249 				      guint prop_id,
250 				      GValue *value,
251 				      GParamSpec *pspec)
252 {
253 	/*RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (object);*/
254 
255 	switch (prop_id)
256 	{
257 	default:
258 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
259 		break;
260 	}
261 }
262 
263 /**
264  * rb_missing_files_source_new:
265  * @shell: the #RBShell instance
266  * @library: the #RBLibrarySource instance
267  *
268  * Creates the missing files source.  It extracts the
269  * entry type from the library source instance, so it
270  * currently only works for files in the library, but
271  * it would be trivial to make it use any source type
272  * that did file access checks for its contents.
273  * 
274  * Return value: the #RBMissingFilesSource
275  */
276 RBSource *
277 rb_missing_files_source_new (RBShell *shell,
278 			     RBLibrarySource *library)
279 {
280 	RBSource *source;
281 	RhythmDBEntryType *entry_type;
282 
283 	g_object_get (library, "entry-type", &entry_type, NULL);
284 	source = RB_SOURCE (g_object_new (RB_TYPE_MISSING_FILES_SOURCE,
285 					  "name", _("Missing Files"),
286 					  "entry-type", entry_type,
287 					  "shell", shell,
288 					  "visibility", FALSE,
289 					  "hidden-when-empty", TRUE,
290 					  NULL));
291 	g_object_unref (entry_type);
292 	return source;
293 }
294 
295 static void
296 rb_missing_files_source_songs_show_popup_cb (RBEntryView *view,
297 					     gboolean over_entry,
298 					     RBMissingFilesSource *source)
299 {
300 	if (over_entry)
301 		_rb_display_page_show_popup (RB_DISPLAY_PAGE (source), MISSING_FILES_SOURCE_SONGS_POPUP_PATH);
302 }
303 
304 static void
305 impl_song_properties (RBSource *asource)
306 {
307 	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (asource);
308 	GtkWidget *song_info = NULL;
309 
310 	g_return_if_fail (source->priv->view != NULL);
311 
312 	song_info = rb_song_info_new (asource, NULL);
313 	if (song_info)
314 		gtk_widget_show_all (song_info);
315 	else
316 		rb_debug ("failed to create dialog, or no selection!");
317 }
318 
319 static void
320 impl_delete (RBSource *asource)
321 {
322 	RBMissingFilesSource *source = RB_MISSING_FILES_SOURCE (asource);
323 	GList *sel, *tem;
324 
325 	sel = rb_entry_view_get_selected_entries (source->priv->view);
326 	for (tem = sel; tem != NULL; tem = tem->next) {
327 		rhythmdb_entry_delete (source->priv->db, tem->data);
328 		rhythmdb_commit (source->priv->db);
329 	}
330 
331 	g_list_foreach (sel, (GFunc)rhythmdb_entry_unref, NULL);
332 	g_list_free (sel);
333 }
334 
335 static void
336 rb_missing_files_source_songs_sort_order_changed_cb (GObject *object,
337 						     GParamSpec *pspec,
338 						     RBMissingFilesSource *source)
339 {
340 	rb_entry_view_resort_model (RB_ENTRY_VIEW (object));
341 }
342 
343 static void
344 impl_get_status (RBDisplayPage *page, char **text, char **progress_text, float *progress)
345 {
346 	RhythmDBQueryModel *model;
347 	gint count;
348 
349 	g_object_get (page, "query-model", &model, NULL);
350 	count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL);
351 	g_object_unref (model);
352 
353 	*text = g_strdup_printf (ngettext ("%d missing file", "%d missing files", count),
354 				 count);
355 }