1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2006 Jonathan Matthew <jonathan@kaolin.wh9.net>
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.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 * This source lists files rhythmbox cannot find, and maybe tries to stop
23 * you from trying to play them.
28 #include <glib/gi18n.h>
30 #include "rb-entry-view.h"
31 #include "rb-missing-files-source.h"
32 #include "rb-song-info.h"
37 static void rb_missing_files_source_class_init (RBMissingFilesSourceClass
*klass
);
38 static void rb_missing_files_source_init (RBMissingFilesSource
*source
);
39 static GObject
*rb_missing_files_source_constructor (GType type
, guint n_construct_properties
,
40 GObjectConstructParam
*construct_properties
);
41 static void rb_missing_files_source_dispose (GObject
*object
);
42 static void rb_missing_files_source_set_property (GObject
*object
,
46 static void rb_missing_files_source_get_property (GObject
*object
,
51 static RBEntryView
*impl_get_entry_view (RBSource
*source
);
52 static void impl_song_properties (RBSource
*source
);
53 static void impl_delete (RBSource
*source
);
54 static void impl_get_status (RBSource
*source
, char **text
, char **progress_text
, float *progress
);
56 static void rb_missing_files_source_songs_show_popup_cb (RBEntryView
*view
,
58 RBMissingFilesSource
*source
);
59 static void rb_missing_files_source_songs_sort_order_changed_cb (RBEntryView
*view
,
60 RBMissingFilesSource
*source
);
62 #define MISSING_FILES_SOURCE_SONGS_POPUP_PATH "/MissingFilesViewPopup"
64 struct RBMissingFilesSourcePrivate
67 RhythmDBQueryModel
*model
;
69 RhythmDBEntryType entry_type
;
78 G_DEFINE_TYPE (RBMissingFilesSource
, rb_missing_files_source
, RB_TYPE_SOURCE
);
81 rb_missing_files_source_class_init (RBMissingFilesSourceClass
*klass
)
83 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
84 RBSourceClass
*source_class
= RB_SOURCE_CLASS (klass
);
86 object_class
->dispose
= rb_missing_files_source_dispose
;
87 object_class
->constructor
= rb_missing_files_source_constructor
;
89 object_class
->set_property
= rb_missing_files_source_set_property
;
90 object_class
->get_property
= rb_missing_files_source_get_property
;
92 source_class
->impl_can_browse
= (RBSourceFeatureFunc
) rb_false_function
;
93 source_class
->impl_get_entry_view
= impl_get_entry_view
;
94 source_class
->impl_can_rename
= (RBSourceFeatureFunc
) rb_false_function
;
95 source_class
->impl_can_search
= (RBSourceFeatureFunc
) rb_false_function
;
97 source_class
->impl_can_cut
= (RBSourceFeatureFunc
) rb_false_function
;
98 source_class
->impl_can_delete
= (RBSourceFeatureFunc
) rb_true_function
;
99 source_class
->impl_can_move_to_trash
= (RBSourceFeatureFunc
) rb_false_function
;
100 source_class
->impl_can_copy
= (RBSourceFeatureFunc
) rb_false_function
;
101 source_class
->impl_can_add_to_queue
= (RBSourceFeatureFunc
) rb_false_function
;
103 source_class
->impl_delete
= impl_delete
;
105 source_class
->impl_song_properties
= impl_song_properties
;
106 source_class
->impl_try_playlist
= (RBSourceFeatureFunc
) rb_false_function
;
107 source_class
->impl_can_pause
= (RBSourceFeatureFunc
) rb_false_function
;
109 source_class
->impl_have_url
= (RBSourceFeatureFunc
) rb_false_function
;
110 source_class
->impl_get_status
= impl_get_status
;
113 g_object_class_install_property (object_class
,
115 g_param_spec_pointer ("entry-type",
117 "Type of the entries which should be displayed by this source",
118 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
120 g_type_class_add_private (klass
, sizeof (RBMissingFilesSourcePrivate
));
124 rb_missing_files_source_init (RBMissingFilesSource
*source
)
129 source
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (source
, RB_TYPE_MISSING_FILES_SOURCE
, RBMissingFilesSourcePrivate
);
131 gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR
, &size
, NULL
);
132 pixbuf
= gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
133 GTK_STOCK_MISSING_IMAGE
,
136 rb_source_set_pixbuf (RB_SOURCE (source
), pixbuf
);
137 if (pixbuf
!= NULL
) {
138 g_object_unref (pixbuf
);
141 source
->priv
->entry_type
= RHYTHMDB_ENTRY_TYPE_SONG
;
145 rb_missing_files_source_constructor (GType type
, guint n_construct_properties
,
146 GObjectConstructParam
*construct_properties
)
148 GObject
*shell_player
;
149 RBMissingFilesSource
*source
;
150 RBMissingFilesSourceClass
*klass
;
154 klass
= RB_MISSING_FILES_SOURCE_CLASS (g_type_class_peek (RB_TYPE_MISSING_FILES_SOURCE
));
156 source
= RB_MISSING_FILES_SOURCE (G_OBJECT_CLASS (rb_missing_files_source_parent_class
)->
157 constructor (type
, n_construct_properties
, construct_properties
));
159 g_object_get (G_OBJECT (source
), "shell", &shell
, NULL
);
160 g_object_get (G_OBJECT (shell
), "db", &source
->priv
->db
, NULL
);
161 shell_player
= rb_shell_get_player (shell
);
162 g_object_unref (G_OBJECT (shell
));
164 /* construct real query */
165 query
= rhythmdb_query_parse (source
->priv
->db
,
166 RHYTHMDB_QUERY_PROP_EQUALS
,
168 source
->priv
->entry_type
,
169 RHYTHMDB_QUERY_PROP_EQUALS
,
170 RHYTHMDB_PROP_HIDDEN
,
173 source
->priv
->model
= rhythmdb_query_model_new (source
->priv
->db
, query
,
174 NULL
, NULL
, NULL
, FALSE
);
175 g_ptr_array_free (query
, TRUE
);
177 g_object_set (G_OBJECT (source
->priv
->model
), "show-hidden", TRUE
, NULL
);
178 _rb_source_hide_when_empty (RB_SOURCE (source
), source
->priv
->model
);
180 /* set up entry view */
181 source
->priv
->view
= rb_entry_view_new (source
->priv
->db
, shell_player
,
184 rb_entry_view_set_model (source
->priv
->view
, source
->priv
->model
);
186 rb_entry_view_append_column (source
->priv
->view
, RB_ENTRY_VIEW_COL_TRACK_NUMBER
, FALSE
);
187 rb_entry_view_append_column (source
->priv
->view
, RB_ENTRY_VIEW_COL_TITLE
, TRUE
);
188 /* rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_GENRE, FALSE); */
189 rb_entry_view_append_column (source
->priv
->view
, RB_ENTRY_VIEW_COL_ARTIST
, FALSE
);
190 rb_entry_view_append_column (source
->priv
->view
, RB_ENTRY_VIEW_COL_ALBUM
, FALSE
);
191 rb_entry_view_append_column (source
->priv
->view
, RB_ENTRY_VIEW_COL_LOCATION
, TRUE
);
192 rb_entry_view_append_column (source
->priv
->view
, RB_ENTRY_VIEW_COL_LAST_SEEN
, TRUE
);
194 rb_entry_view_set_columns_clickable (source
->priv
->view
, TRUE
);
196 gtk_container_add (GTK_CONTAINER (source
), GTK_WIDGET (source
->priv
->view
));
197 g_signal_connect_object (G_OBJECT (source
->priv
->view
), "show_popup",
198 G_CALLBACK (rb_missing_files_source_songs_show_popup_cb
), source
, 0);
199 g_signal_connect_object (G_OBJECT (source
->priv
->view
), "sort-order-changed",
200 G_CALLBACK (rb_missing_files_source_songs_sort_order_changed_cb
), source
, 0);
202 gtk_widget_show_all (GTK_WIDGET (source
));
204 /* use a fake model for the source's query model property, so we can't try to play
205 * any of the hidden entries.
207 g_object_set (G_OBJECT (source
),
208 "query-model", rhythmdb_query_model_new_empty (source
->priv
->db
),
211 return G_OBJECT (source
);
215 rb_missing_files_source_dispose (GObject
*object
)
217 RBMissingFilesSource
*source
= RB_MISSING_FILES_SOURCE (object
);
219 if (source
->priv
->db
) {
220 g_object_unref (G_OBJECT (source
->priv
->db
));
221 source
->priv
->db
= NULL
;
223 if (source
->priv
->model
) {
224 g_object_unref (G_OBJECT (source
->priv
->model
));
225 source
->priv
->model
= NULL
;
228 G_OBJECT_CLASS (rb_missing_files_source_parent_class
)->dispose (object
);
233 impl_get_entry_view (RBSource
*asource
)
235 RBMissingFilesSource
*source
= RB_MISSING_FILES_SOURCE (asource
);
236 return source
->priv
->view
;
240 rb_missing_files_source_set_property (GObject
*object
,
245 RBMissingFilesSource
*source
= RB_MISSING_FILES_SOURCE (object
);
249 case PROP_ENTRY_TYPE
:
250 source
->priv
->entry_type
= g_value_get_pointer (value
);
253 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
259 rb_missing_files_source_get_property (GObject
*object
,
264 RBMissingFilesSource
*source
= RB_MISSING_FILES_SOURCE (object
);
268 case PROP_ENTRY_TYPE
:
269 g_value_set_pointer (value
, source
->priv
->entry_type
);
272 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
278 rb_missing_files_source_new (RBShell
*shell
,
279 RBLibrarySource
*library
)
282 RhythmDBEntryType entry_type
;
284 g_object_get (G_OBJECT (library
), "entry-type", &entry_type
, NULL
);
285 source
= RB_SOURCE (g_object_new (RB_TYPE_MISSING_FILES_SOURCE
,
286 "name", _("Missing Files"),
287 "entry-type", entry_type
,
295 rb_missing_files_source_songs_show_popup_cb (RBEntryView
*view
,
297 RBMissingFilesSource
*source
)
300 _rb_source_show_popup (RB_SOURCE (source
), MISSING_FILES_SOURCE_SONGS_POPUP_PATH
);
304 impl_song_properties (RBSource
*asource
)
306 RBMissingFilesSource
*source
= RB_MISSING_FILES_SOURCE (asource
);
307 GtkWidget
*song_info
= NULL
;
309 g_return_if_fail (source
->priv
->view
!= NULL
);
311 song_info
= rb_song_info_new (asource
, NULL
);
313 gtk_widget_show_all (song_info
);
315 rb_debug ("failed to create dialog, or no selection!");
319 impl_delete (RBSource
*asource
)
321 RBMissingFilesSource
*source
= RB_MISSING_FILES_SOURCE (asource
);
324 sel
= rb_entry_view_get_selected_entries (source
->priv
->view
);
325 for (tem
= sel
; tem
!= NULL
; tem
= tem
->next
) {
326 rhythmdb_entry_delete (source
->priv
->db
, tem
->data
);
327 rhythmdb_commit (source
->priv
->db
);
333 rb_missing_files_source_songs_sort_order_changed_cb (RBEntryView
*view
,
334 RBMissingFilesSource
*source
)
336 rb_entry_view_resort_model (view
);
340 impl_get_status (RBSource
*asource
, char **text
, char **progress_text
, float *progress
)
342 RBMissingFilesSource
*source
= RB_MISSING_FILES_SOURCE (asource
);
345 count
= gtk_tree_model_iter_n_children (GTK_TREE_MODEL (source
->priv
->model
), NULL
);
346 *text
= g_strdup_printf (ngettext ("%d missing file", "%d missing files", count
),