100
82
gpointer user_data);
101
static void rb_playlist_source_add_list_uri (RBPlaylistSource *source,
103
static void rb_playlist_source_do_query (RBPlaylistSource *source,
108
static void rb_playlist_source_row_inserted (GtkTreeModel *treemodel,
111
RBPlaylistSource *source);
112
static void rb_playlist_source_non_entry_dropped (GtkTreeModel *model,
114
RBPlaylistSource *source);
85
static void rb_playlist_source_row_deleted (GtkTreeModel *model,
87
RBPlaylistSource *playlist);
88
static void default_show_entry_view_popup (RBPlaylistSource *source,
90
static void rb_playlist_source_entry_added_cb (RhythmDB *db, RhythmDBEntry *entry,
91
RBPlaylistSource *source);
92
static void rb_playlist_source_track_cell_data_func (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
93
GtkTreeModel *tree_model, GtkTreeIter *iter,
94
RBPlaylistSource *source);
116
96
#define PLAYLIST_SOURCE_SONGS_POPUP_PATH "/PlaylistViewPopup"
117
97
#define PLAYLIST_SOURCE_POPUP_PATH "/PlaylistSourcePopup"
118
#define PLAYLIST_SOURCE_AUTOMATIC_POPUP_PATH "/SmartPlaylistSourcePopup"
120
99
struct RBPlaylistSourcePrivate
127
103
GHashTable *entries;
129
105
RhythmDBEntryType entry_type;
130
106
RhythmDBQueryModel *model;
131
gboolean query_resetting;
134
GdkPixbuf *normal_pixbuf;
135
GdkPixbuf *smartypants_pixbuf;
137
110
RBEntryView *songs;
164
138
RBSourceClass *source_class = RB_SOURCE_CLASS (klass);
166
140
object_class->dispose = rb_playlist_source_dispose;
141
object_class->finalize = rb_playlist_source_finalize;
167
142
object_class->constructor = rb_playlist_source_constructor;
169
144
object_class->set_property = rb_playlist_source_set_property;
170
145
object_class->get_property = rb_playlist_source_get_property;
172
source_class->impl_get_status = impl_get_status;
173
147
source_class->impl_get_browser_key = impl_get_browser_key;
174
source_class->impl_get_pixbuf = impl_get_pixbuf;
175
148
source_class->impl_get_entry_view = impl_get_entry_view;
176
149
source_class->impl_can_rename = (RBSourceFeatureFunc) rb_true_function;
177
150
source_class->impl_can_search = (RBSourceFeatureFunc) rb_false_function;
178
source_class->impl_can_cut = impl_can_cut;
151
source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
179
152
source_class->impl_can_copy = (RBSourceFeatureFunc) rb_true_function;
180
source_class->impl_can_delete = impl_can_cut;
181
source_class->impl_cut = impl_cut;
182
source_class->impl_paste = impl_paste;
183
source_class->impl_delete = impl_delete;
153
source_class->impl_can_delete = (RBSourceFeatureFunc) rb_false_function;
154
source_class->impl_can_add_to_queue = (RBSourceFeatureFunc) rb_true_function;
155
source_class->impl_can_move_to_trash = (RBSourceFeatureFunc) rb_true_function;
156
source_class->impl_move_to_trash = impl_move_to_trash;
184
157
source_class->impl_song_properties = impl_song_properties;
185
158
source_class->impl_can_pause = (RBSourceFeatureFunc) rb_true_function;
186
159
source_class->impl_have_url = (RBSourceFeatureFunc) rb_false_function;
187
source_class->impl_receive_drag = impl_receive_drag;
188
160
source_class->impl_show_popup = impl_show_popup;
190
g_object_class_install_property (object_class,
192
g_param_spec_boolean ("automatic",
194
"whether this playlist is a smartypants",
196
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
162
klass->impl_show_entry_view_popup = default_show_entry_view_popup;
198
164
g_object_class_install_property (object_class,
200
g_param_spec_object ("query-model",
202
"query model for the playlist",
203
RHYTHMDB_TYPE_QUERY_MODEL,
166
g_param_spec_object ("db",
204
170
G_PARAM_READABLE));
206
171
g_object_class_install_property (object_class,
208
173
g_param_spec_boolean ("dirty",
262
214
constructor (type, n_construct_properties, construct_properties));
264
216
g_object_get (G_OBJECT (source), "shell", &shell, NULL);
265
g_object_get (RB_SHELL (shell), "db", &source->priv->db, NULL);
217
g_object_get (G_OBJECT (shell), "db", &source->priv->db, NULL);
218
shell_player = rb_shell_get_player (shell);
266
219
g_object_unref (G_OBJECT (shell));
268
g_signal_connect_object (G_OBJECT (source->priv->db), "entry_added",
269
G_CALLBACK (rb_playlist_source_entry_added_cb),
271
g_signal_connect_object (G_OBJECT (source->priv->db), "entry_restored",
272
G_CALLBACK (rb_playlist_source_entry_added_cb),
275
221
source->priv->vbox = gtk_vbox_new (FALSE, 5);
277
223
gtk_container_add (GTK_CONTAINER (source), source->priv->vbox);
279
source->priv->model = rhythmdb_query_model_new_empty (source->priv->db);
281
225
source->priv->entries = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
283
source->priv->songs = rb_entry_view_new (source->priv->db, NULL, TRUE, TRUE);
285
/* watch these to find out when things were dropping into the entry view */
286
g_signal_connect_object (G_OBJECT (source->priv->model), "row-inserted",
287
G_CALLBACK (rb_playlist_source_row_inserted),
289
g_signal_connect_object (G_OBJECT (source->priv->model), "non-entry-dropped",
290
G_CALLBACK (rb_playlist_source_non_entry_dropped),
293
rb_entry_view_set_model (source->priv->songs, RHYTHMDB_QUERY_MODEL (source->priv->model));
227
g_signal_connect_object (G_OBJECT (source->priv->db), "entry_added",
228
G_CALLBACK (rb_playlist_source_entry_added_cb),
230
g_signal_connect_object (G_OBJECT (source->priv->db), "entry_restored",
231
G_CALLBACK (rb_playlist_source_entry_added_cb),
234
source->priv->songs = rb_entry_view_new (source->priv->db, shell_player,
237
rb_playlist_source_set_query_model (source, rhythmdb_query_model_new_empty (source->priv->db));
240
const char *title = _("Trac_k");
241
const char *strings[3] = {0};
296
243
GtkTreeViewColumn *column = gtk_tree_view_column_new ();
297
244
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
298
245
gtk_tree_view_column_pack_start (column, renderer, TRUE);
300
247
gtk_tree_view_column_set_clickable (column, TRUE);
248
gtk_tree_view_column_set_resizable (column, TRUE);
249
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
253
rb_entry_view_set_fixed_column_width (source->priv->songs, column, renderer,
301
255
gtk_tree_view_column_set_cell_data_func (column, renderer,
302
256
(GtkTreeCellDataFunc)
303
257
rb_playlist_source_track_cell_data_func,
305
rb_entry_view_append_column_custom (source->priv->songs, column,
306
_("Trac_k"), "PlaylistTrack", NULL, NULL);
259
rb_entry_view_append_column_custom (source->priv->songs, column, title,
260
"PlaylistTrack", NULL, NULL);
309
263
rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TITLE);
316
270
rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_PLAY_COUNT);
317
271
rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_LAST_PLAYED);
318
272
rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_FIRST_SEEN);
320
g_signal_connect_object (G_OBJECT (source->priv->songs), "show_popup",
321
G_CALLBACK (rb_playlist_source_songs_show_popup_cb), source, 0);
322
g_signal_connect_object (G_OBJECT (source->priv->songs), "sort-order-changed",
323
G_CALLBACK (rb_playlist_source_songs_sort_order_changed_cb), source, 0);
325
g_signal_connect_object (G_OBJECT (source->priv->songs), "drag_data_received",
326
G_CALLBACK (rb_playlist_source_drop_cb), source, 0);
327
gtk_drag_dest_set (GTK_WIDGET (source->priv->songs), GTK_DEST_DEFAULT_ALL,
328
target_uri, G_N_ELEMENTS (target_uri), GDK_ACTION_COPY);
331
GtkIconTheme *theme = gtk_icon_theme_get_default();
334
gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &size, NULL);
335
source->priv->normal_pixbuf = gtk_icon_theme_load_icon (theme,
339
source->priv->smartypants_pixbuf = gtk_icon_theme_load_icon (theme,
340
"stock_smart-playlist",
345
273
rb_entry_view_set_columns_clickable (source->priv->songs, FALSE);
346
source->priv->query_resetting = FALSE;
275
rb_playlist_source_setup_entry_view (source, source->priv->songs);
348
277
gtk_box_pack_start_defaults (GTK_BOX (source->priv->vbox), GTK_WIDGET (source->priv->songs));
350
279
gtk_widget_show_all (GTK_WIDGET (source));
352
281
return G_OBJECT (source);
356
rb_playlist_source_songs_show_popup_cb (RBEntryView *view,
357
RBPlaylistSource *playlist_view)
359
_rb_source_show_popup (RB_SOURCE (playlist_view),
360
PLAYLIST_SOURCE_SONGS_POPUP_PATH);
364
rb_playlist_source_init (RBPlaylistSource *source)
366
source->priv = g_new0 (RBPlaylistSourcePrivate, 1);
370
285
rb_playlist_source_dispose (GObject *object)
372
RBPlaylistSource *source;
373
source = RB_PLAYLIST_SOURCE (object);
376
g_hash_table_destroy (source->priv->entries);
287
RBPlaylistSource *source = RB_PLAYLIST_SOURCE (object);
288
if (source->priv->db) {
377
289
g_object_unref (source->priv->db);
378
g_free (source->priv->title);
380
g_free (source->priv);
290
source->priv->db = NULL;
384
293
G_OBJECT_CLASS (rb_playlist_source_parent_class)->dispose (object);
297
rb_playlist_source_finalize (GObject *object)
299
RBPlaylistSource *source;
301
g_return_if_fail (object != NULL);
302
g_return_if_fail (RB_IS_PLAYLIST_SOURCE (object));
304
source = RB_PLAYLIST_SOURCE (object);
305
g_return_if_fail (source->priv != NULL);
307
g_hash_table_destroy (source->priv->entries);
309
g_free (source->priv->title);
312
G_OBJECT_CLASS (rb_playlist_source_parent_class)->finalize (object);
388
316
rb_playlist_source_set_property (GObject *object,
390
318
const GValue *value,
444
rb_playlist_source_new (RBShell *shell, gboolean automatic, gboolean local, RhythmDBEntryType entry_type)
448
source = RB_SOURCE (g_object_new (RB_TYPE_PLAYLIST_SOURCE,
449
"name", _("Unknown"),
451
"automatic", automatic,
453
"entry-type", entry_type,
460
rb_playlist_source_entry_added_cb (RhythmDB *db, RhythmDBEntry *entry,
461
RBPlaylistSource *source)
463
const char *location;
465
if (source->priv->automatic)
468
location = entry->location;
469
if (g_hash_table_lookup (source->priv->entries, location)) {
470
rhythmdb_query_model_add_entry (source->priv->model, entry);
471
source->priv->dirty = TRUE;
476
rb_playlist_source_set_query (RBPlaylistSource *source,
481
const char *sort_key,
484
g_assert (source->priv->automatic);
486
source->priv->query_resetting = TRUE;
488
/* playlists that aren't limited, with a particular sort order, are user-orderable */
489
rb_entry_view_set_columns_clickable (source->priv->songs, (limit_count == 0 && limit_mb == 0));
490
rb_entry_view_set_sorting_order (source->priv->songs, sort_key, sort_direction);
492
rb_playlist_source_do_query (source, query, limit_count, limit_mb, limit_time);
493
rhythmdb_query_free (query);
494
source->priv->query_resetting = FALSE;
498
rb_playlist_source_get_query (RBPlaylistSource *source,
503
const char **sort_key,
504
gint *sort_direction)
506
g_assert (source->priv->automatic);
508
g_object_get (G_OBJECT (source->priv->model),
510
"max-count", limit_count,
511
"max-size", limit_mb,
512
"max-time", limit_time,
515
rb_entry_view_get_sorting_order (source->priv->songs, sort_key, sort_direction);
519
impl_get_status (RBSource *asource)
522
RBPlaylistSource *source = RB_PLAYLIST_SOURCE (asource);
525
status = rhythmdb_compute_status_normal (rb_entry_view_get_num_entries (source->priv->songs),
526
rb_entry_view_get_duration (source->priv->songs),
527
rb_entry_view_get_total_size (source->priv->songs));
366
default_show_entry_view_popup (RBPlaylistSource *source, RBEntryView *view)
368
_rb_source_show_popup (RB_SOURCE (source), PLAYLIST_SOURCE_SONGS_POPUP_PATH);
372
rb_playlist_source_songs_show_popup_cb (RBEntryView *view,
373
RBPlaylistSource *source)
375
RBPlaylistSourceClass *klass = RB_PLAYLIST_SOURCE_GET_CLASS (source);
376
if (klass->impl_show_entry_view_popup)
377
klass->impl_show_entry_view_popup (source, view);
531
381
static const char *
532
382
impl_get_browser_key (RBSource *source)
599
416
g_return_if_fail (source->priv->songs != NULL);
601
song_info = rb_song_info_new (source->priv->songs);
418
song_info = rb_song_info_new (asource, NULL);
603
420
gtk_widget_show_all (song_info);
605
422
rb_debug ("failed to create dialog, or no selection!");
608
static RhythmDBPropType
609
rb_playlist_source_drag_atom_to_prop (GdkAtom smasher)
611
if (smasher == gdk_atom_intern ("text/x-rhythmbox-album", TRUE))
612
return RHYTHMDB_PROP_ALBUM;
613
else if (smasher == gdk_atom_intern ("text/x-rhythmbox-artist", TRUE))
614
return RHYTHMDB_PROP_ARTIST;
615
else if (smasher == gdk_atom_intern ("text/x-rhythmbox-genre", TRUE))
616
return RHYTHMDB_PROP_GENRE;
618
g_assert_not_reached ();
624
impl_receive_drag (RBSource *asource, GtkSelectionData *data)
627
RBPlaylistSource *source = RB_PLAYLIST_SOURCE (asource);
629
if (data->type == gdk_atom_intern ("text/uri-list", TRUE)) {
630
list = gnome_vfs_uri_list_parse ((char *) data->data);
633
rb_playlist_source_add_list_uri (source, list);
638
GPtrArray *subquery = NULL;
639
gchar **names = g_strsplit ((char *)data->data, "\r\n", 0);
640
guint propid = rb_playlist_source_drag_atom_to_prop (data->type);
643
for (i=0; names[i]; i++) {
644
if (subquery == NULL)
645
subquery = rhythmdb_query_parse (source->priv->db,
646
RHYTHMDB_QUERY_PROP_EQUALS,
651
rhythmdb_query_append (source->priv->db,
653
RHYTHMDB_QUERY_DISJUNCTION,
654
RHYTHMDB_QUERY_PROP_EQUALS,
663
RhythmDBEntryType qtype = RHYTHMDB_ENTRY_TYPE_SONG;
666
if (source->priv->entry_type != -1)
667
qtype = source->priv->entry_type;
669
query = rhythmdb_query_parse (source->priv->db,
670
RHYTHMDB_QUERY_PROP_EQUALS,
673
RHYTHMDB_QUERY_SUBQUERY,
676
rb_playlist_source_set_query (source, query, 0, 0, 0, NULL, 0);
684
426
impl_show_popup (RBSource *asource)
686
RBPlaylistSource *source = RB_PLAYLIST_SOURCE (asource);
688
if (source->priv->automatic) {
689
_rb_source_show_popup (RB_SOURCE (asource), PLAYLIST_SOURCE_AUTOMATIC_POPUP_PATH);
691
_rb_source_show_popup (RB_SOURCE (asource), PLAYLIST_SOURCE_POPUP_PATH);
428
_rb_source_show_popup (asource, PLAYLIST_SOURCE_POPUP_PATH);
714
450
if (target == GDK_NONE)
717
impl_receive_drag (RB_SOURCE (source), data);
453
rb_source_receive_drag (RB_SOURCE (source), data);
719
455
gtk_drag_finish (context, TRUE, FALSE, time);
725
rb_playlist_source_add_location_swapped (const char *uri, RBPlaylistSource *source)
727
rb_playlist_source_add_location (source, uri);
731
rb_playlist_source_add_location (RBPlaylistSource *source,
732
const char *location)
734
RhythmDBEntry *entry;
736
entry = rhythmdb_entry_lookup_by_location (source->priv->db, location);
738
source->priv->entry_type != -1 &&
739
rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TYPE) != source->priv->entry_type) {
740
rb_debug ("attempting to add an entry of the wrong type to playlist");
744
if (rb_uri_is_directory (location)) {
745
rb_uri_handle_recursively (location,
746
(GFunc) rb_playlist_source_add_location_swapped,
750
if (g_hash_table_lookup (source->priv->entries, location)) {
754
g_hash_table_insert (source->priv->entries,
755
g_strdup (location), GINT_TO_POINTER (1));
758
rhythmdb_query_model_add_entry (source->priv->model, entry);
760
source->priv->dirty = TRUE;
766
rb_playlist_source_add_locations (RBPlaylistSource *source,
771
for (l = locations; l; l = l->next) {
772
const gchar *uri = (const gchar *)l->data;
774
rb_playlist_source_add_location (RB_PLAYLIST_SOURCE (source),
781
rb_playlist_source_remove_location (RBPlaylistSource *source,
782
const char *location)
784
RhythmDBEntry *entry;
786
g_return_if_fail (g_hash_table_lookup (source->priv->entries, location) != NULL);
788
g_hash_table_remove (source->priv->entries, location);
789
entry = rhythmdb_entry_lookup_by_location (source->priv->db, location);
793
removed = rhythmdb_query_model_remove_entry (source->priv->model, entry);
794
g_assert (removed); /* if this fails, the model and the playlist are out of sync */
795
source->priv->dirty = TRUE;
800
rb_playlist_source_add_entry (RBPlaylistSource *source,
801
RhythmDBEntry *entry)
803
rb_playlist_source_add_location (source, entry->location);
807
rb_playlist_source_remove_entry (RBPlaylistSource *source,
808
RhythmDBEntry *entry)
810
rb_playlist_source_remove_location (source, entry->location);
814
rb_playlist_source_add_list_uri (RBPlaylistSource *source,
817
GList *i, *uri_list = NULL;
819
g_return_if_fail (list != NULL);
821
for (i = list; i != NULL; i = g_list_next (i))
822
uri_list = g_list_prepend (uri_list, gnome_vfs_uri_to_string ((const GnomeVFSURI *) i->data, 0));
823
uri_list = g_list_reverse (uri_list);
825
gnome_vfs_uri_list_free (list);
827
if (uri_list == NULL)
830
for (i = uri_list; i != NULL; i = i->next) {
833
rhythmdb_add_uri (source->priv->db, uri);
834
rb_playlist_source_add_location (source, uri);
840
g_list_free (uri_list);
844
459
playlist_iter_func (GtkTreeModel *model, GtkTreeIter *iter, char **uri, char **title, gpointer user_data)
923
555
rb_playlist_source_new_from_xml (RBShell *shell,
926
RBPlaylistSource *source;
930
source = RB_PLAYLIST_SOURCE (rb_playlist_source_new (shell, FALSE, TRUE, RHYTHMDB_ENTRY_TYPE_SONG));
932
561
tmp = xmlGetProp (node, RB_PLAYLIST_TYPE);
933
562
if (!xmlStrcmp (tmp, RB_PLAYLIST_AUTOMATIC))
934
source->priv->automatic = TRUE;
563
source = rb_auto_playlist_source_new_from_xml (shell, node);
564
else if (!xmlStrcmp (tmp, RB_PLAYLIST_STATIC))
565
source = rb_static_playlist_source_new_from_xml (shell, node);
567
g_assert_not_reached ();
937
569
tmp = xmlGetProp (node, RB_PLAYLIST_NAME);
938
570
g_object_set (G_OBJECT (source), "name", tmp, NULL);
941
if (source->priv->automatic) {
943
gint limit_count = 0, limit_mb = 0, limit_time = 0;
944
gchar *sort_key = NULL;
945
gint sort_direction = 0;
947
child = node->children;
948
while (xmlNodeIsText (child))
951
query = rhythmdb_query_deserialize (source->priv->db, child);
952
tmp = xmlGetProp (node, RB_PLAYLIST_LIMIT_COUNT);
953
if (!tmp) /* Backwards compatibility */
954
tmp = xmlGetProp (node, RB_PLAYLIST_LIMIT);
956
limit_count = atoi ((char*) tmp);
959
tmp = xmlGetProp (node, RB_PLAYLIST_LIMIT_SIZE);
961
limit_mb = atoi ((char*) tmp);
964
tmp = xmlGetProp (node, RB_PLAYLIST_LIMIT_TIME);
966
limit_time = atoi ((char*) tmp);
970
sort_key = (gchar*) xmlGetProp (node, RB_PLAYLIST_SORT_KEY);
971
if (sort_key && *sort_key) {
972
tmp = xmlGetProp (node, RB_PLAYLIST_SORT_DIRECTION);
974
sort_direction = atoi ((char*) tmp);
983
rb_playlist_source_set_query (source, query,
991
for (child = node->children; child; child = child->next) {
994
if (xmlNodeIsText (child))
997
if (xmlStrcmp (child->name, RB_PLAYLIST_LOCATION))
1000
location = xmlNodeGetContent (child);
1001
rb_playlist_source_add_location (source,
1006
return RB_SOURCE (source);
1012
579
xmlNodePtr node;
581
RBPlaylistSourceClass *klass = RB_PLAYLIST_SOURCE_GET_CLASS (source);
1016
583
node = xmlNewChild (parent_node, NULL, RB_PLAYLIST_PLAYLIST, NULL);
1017
584
g_object_get (G_OBJECT (source), "name", &name, NULL);
1018
585
xmlSetProp (node, RB_PLAYLIST_NAME, name);
1019
xmlSetProp (node, RB_PLAYLIST_TYPE, source->priv->automatic ? RB_PLAYLIST_AUTOMATIC : RB_PLAYLIST_STATIC);
1021
if (!source->priv->automatic) {
1022
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (source->priv->model),
1026
xmlNodePtr child_node = xmlNewChild (node, NULL, RB_PLAYLIST_LOCATION, NULL);
1027
RhythmDBEntry *entry;
1030
gtk_tree_model_get (GTK_TREE_MODEL (source->priv->model), &iter, 0, &entry, -1);
1032
encoded = xmlEncodeEntitiesReentrant (NULL, BAD_CAST entry->location);
1034
xmlNodeSetContent (child_node, encoded);
1036
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (source->priv->model),
1040
guint max_count, max_size_mb, max_time;
1041
const gchar *sort_key;
1042
gint sort_direction;
1045
rb_playlist_source_get_query (source,
1047
&max_count, &max_size_mb, &max_time,
1048
&sort_key, &sort_direction);
1049
temp_str = g_strdup_printf ("%d", max_count);
1050
xmlSetProp (node, RB_PLAYLIST_LIMIT_COUNT, BAD_CAST temp_str);
1052
temp_str = g_strdup_printf ("%d", max_size_mb);
1053
xmlSetProp (node, RB_PLAYLIST_LIMIT_SIZE, BAD_CAST temp_str);
1055
temp_str = g_strdup_printf ("%d", max_time);
1056
xmlSetProp (node, RB_PLAYLIST_LIMIT_TIME, BAD_CAST temp_str);
1059
if (sort_key && *sort_key) {
1060
xmlSetProp (node, RB_PLAYLIST_SORT_KEY, BAD_CAST sort_key);
1061
temp_str = g_strdup_printf ("%d", sort_direction);
1062
xmlSetProp (node, RB_PLAYLIST_SORT_DIRECTION, BAD_CAST temp_str);
1066
rhythmdb_query_serialize (source->priv->db, query, node);
588
klass->impl_save_contents_to_xml (source, node);
1069
590
source->priv->dirty = FALSE;
1073
rb_playlist_source_songs_sort_order_changed_cb (RBEntryView *view, RBPlaylistSource *source)
1076
guint limit_count, limit_mb, limit_time;
1078
g_assert (source->priv->automatic);
1080
/* don't process this if we are in the middle of setting a query */
1081
if (source->priv->query_resetting)
1083
rb_debug ("sort order changed");
1085
/* need to re-run query with the same settings*/
1086
g_object_get (G_OBJECT (source->priv->model),
1088
"max-count", &limit_count,
1089
"max-size", &limit_mb,
1090
"max-size", &limit_time,
1093
rb_playlist_source_do_query (source, query, limit_count, limit_mb, limit_time);
1094
rhythmdb_query_free (query);
1098
rb_playlist_source_do_query (RBPlaylistSource *source,
1104
g_assert (source->priv->automatic);
1106
source->priv->model = g_object_new (RHYTHMDB_TYPE_QUERY_MODEL,
1107
"db", source->priv->db,
1108
"max-count", limit_count,
1109
"max-size", limit_mb,
1110
"max-time", limit_time,
1113
rb_entry_view_set_model (source->priv->songs, source->priv->model);
1114
rhythmdb_do_full_query_async_parsed (source->priv->db, GTK_TREE_MODEL (source->priv->model), query);
1116
/* emit notification the the property has changed */
1117
g_object_notify (G_OBJECT (source), "query-model");
1121
rb_playlist_source_non_entry_dropped (GtkTreeModel *model,
1123
RBPlaylistSource *source)
1125
rb_playlist_source_add_location (source, uri);
1129
rb_playlist_source_row_inserted (GtkTreeModel *model,
1132
RBPlaylistSource *source)
1134
RhythmDBEntry *entry;
1136
gtk_tree_model_get (model, iter, 0, &entry, -1);
1138
rb_playlist_source_add_location (source, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
595
rb_playlist_source_row_deleted (GtkTreeModel *model,
597
RBPlaylistSource *source)
599
RhythmDBEntry *entry =
600
rhythmdb_query_model_tree_path_to_entry (RHYTHMDB_QUERY_MODEL (model),
602
g_hash_table_remove (source->priv->entries, entry->location);
606
rb_playlist_source_entry_added_cb (RhythmDB *db,
607
RhythmDBEntry *entry,
608
RBPlaylistSource *source)
610
const char *location;
612
location = entry->location;
613
if (g_hash_table_lookup (source->priv->entries, location)) {
614
rhythmdb_query_model_add_entry (source->priv->model, entry, -1);
615
source->priv->dirty = TRUE;
620
rb_playlist_source_track_cell_data_func (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
621
GtkTreeModel *tree_model, GtkTreeIter *iter,
622
RBPlaylistSource *source)
627
gtk_tree_model_get (tree_model, iter, 1, &val, -1);
630
str = g_strdup_printf ("%d", val);
634
g_object_set (G_OBJECT (renderer), "text", str, NULL);
639
rb_playlist_source_setup_entry_view (RBPlaylistSource *source,
640
RBEntryView *entry_view)
642
g_signal_connect_object (G_OBJECT (entry_view), "show_popup",
643
G_CALLBACK (rb_playlist_source_songs_show_popup_cb), source, 0);
644
g_signal_connect_object (G_OBJECT (entry_view), "drag_data_received",
645
G_CALLBACK (rb_playlist_source_drop_cb), source, 0);
646
gtk_drag_dest_set (GTK_WIDGET (entry_view), GTK_DEST_DEFAULT_ALL,
647
target_uri, G_N_ELEMENTS (target_uri), GDK_ACTION_COPY);
651
rb_playlist_source_set_query_model (RBPlaylistSource *source,
652
RhythmDBQueryModel *model)
654
if (source->priv->model) {
655
/* if the query model is replaced, the set of entries in
656
* the playlist will change, so we should mark the playlist dirty.
658
source->priv->dirty = TRUE;
659
g_signal_handlers_disconnect_by_func (G_OBJECT (source->priv->model),
660
G_CALLBACK (rb_playlist_source_row_deleted),
662
g_object_unref (source->priv->model);
664
source->priv->model = model;
667
g_object_ref (G_OBJECT (model));
668
g_signal_connect_object (G_OBJECT (source->priv->model), "row_deleted",
669
G_CALLBACK (rb_playlist_source_row_deleted), source, 0);
672
rb_entry_view_set_model (source->priv->songs, RHYTHMDB_QUERY_MODEL (source->priv->model));
674
g_object_set (G_OBJECT (source), "query-model", source->priv->model, NULL);
678
rb_playlist_source_get_db (RBPlaylistSource *source)
680
return source->priv->db;
684
rb_playlist_source_get_query_model (RBPlaylistSource *source)
686
return source->priv->model;
690
rb_playlist_source_mark_dirty (RBPlaylistSource *source)
692
source->priv->dirty = TRUE;
696
rb_playlist_source_location_in_map (RBPlaylistSource *source,
697
const char *location)
699
return (g_hash_table_lookup (source->priv->entries, location) != NULL);
703
rb_playlist_source_add_to_map (RBPlaylistSource *source,
704
const char *location)
706
if (g_hash_table_lookup (source->priv->entries, location)) {
710
g_hash_table_insert (source->priv->entries,
711
g_strdup (location), GINT_TO_POINTER (1));