diff --git a/gui/playlist.c b/gui/playlist.c
index 1583ab83..1de4cadc 100644
--- a/gui/playlist.c
+++ b/gui/playlist.c
@@ -148,7 +148,7 @@ bool __playlist_keypress(GtkTreeView *treeview, GdkEventKey *event,
goto out;
if (playlist_delete(__playlist_type(&child), name))
- gtk_tree_store_remove(GTK_TREE_STORE(model), &child);
+ gtk_tree_store_remove(p_store, &child);
g_free(name);
out:
g_list_free_full(rows, (GDestroyNotify)gtk_tree_path_free);
@@ -193,7 +193,8 @@ static gboolean __playlist_visible_func(GtkTreeModel *model, GtkTreeIter *iter,
return true;
name = __playlist_name(iter);
- show = !playlist_get_queue(__playlist_type(iter), name) ||
+ show = __playlist_type(iter) == PL_USER ||
+ !playlist_get_queue(__playlist_type(iter), name) ||
(playlist_size(__playlist_type(iter), name) > 0);
g_free(name);
return show;
@@ -253,6 +254,8 @@ static void *__playlist_init(struct queue *queue, void *data)
gui_playlist_add_artist(artist_find(playlist->pl_name));
p_filter_enable = true;
}
+ if (p_init_done && playlist->pl_type == PL_USER)
+ gui_playlist_add_user(playlist);
return gui_queue_alloc(playlist, queue, playlist->pl_name, flags);
}
@@ -276,18 +279,29 @@ static void __playlist_cleared(struct queue *queue, unsigned int n)
static bool __playlist_erase(struct queue *queue, struct track *track)
{
- if (string_match(gui_playlist_cur(), "Collection"))
- playlist_add(PL_SYSTEM, "Hidden", track);
- else if (string_match(gui_playlist_cur(), "Favorites") ||
- string_match(gui_playlist_cur(), "Hidden") ||
- string_match(gui_playlist_cur(), "Queued Tracks"))
- playlist_remove(PL_SYSTEM, gui_playlist_cur(), track);
+ enum playlist_type_t type = gui_queue(queue)->gq_playlist->pl_type;
+ const gchar *name = gui_queue(queue)->gq_playlist->pl_name;
+
+ switch (type) {
+ case PL_SYSTEM:
+ if (string_match(name, "Collection"))
+ name = "Hidden";
+ else if (!string_match(name, "Favorites") &&
+ !string_match(name, "Hidden") &&
+ !string_match(name, "Queued Tracks"))
+ break;
+ case PL_USER:
+ playlist_remove(type, name, track);
+ default:
+ break;
+ };
+
return false;
}
bool __gui_playlist_init_idle()
{
- struct db_entry *artist, *next;
+ struct db_entry *dbe, *next;
GtkTreeSelection *selection;
GtkTreeModel *filter;
GtkTreeIter iter;
@@ -299,8 +313,11 @@ bool __gui_playlist_init_idle()
gtk_tree_selection_select_iter(selection, &iter);
p_filter_enable = false;
- db_for_each(artist, next, artist_db_get())
- gui_playlist_add_artist(ARTIST(artist));
+ db_for_each(dbe, next, artist_db_get())
+ gui_playlist_add_artist(ARTIST(dbe));
+
+ db_for_each(dbe, next, pl_user_db_get())
+ gui_playlist_add_user(&USER_PLAYLIST(dbe)->pl_playlist);
p_filter_enable = true;
p_init_done = true;
@@ -333,10 +350,15 @@ void gui_playlist_init()
__playlist_set(&parent, "History", "document-open-recent", PL_SYSTEM);
__playlist_set_size(&parent, "History");
- /* Add "Playlist" header. */
+ /* Add "User Playlists" header. */
gtk_tree_store_insert(p_store, &parent, NULL, -1);
gtk_tree_store_insert(p_store, &parent, NULL, -1);
- __playlist_set(&parent, "Playlists", "emblem-documents", 0);
+ __playlist_set(&parent, "User Playlists", "emblem-documents", 0);
+
+ /* Add "System Playlists" header. */
+ gtk_tree_store_insert(p_store, &parent, NULL, -1);
+ gtk_tree_store_insert(p_store, &parent, NULL, -1);
+ __playlist_set(&parent, "System Playlists", "emblem-system", 0);
/* Add playlists. */
__playlist_add(&parent, "Favorites", "emblem-favorite", PL_SYSTEM);
@@ -417,6 +439,43 @@ void gui_playlist_add_artist(struct artist *artist)
__playlist_add(&parent, artist->ar_name, "system-users", PL_ARTIST);
}
+void gui_playlist_add_user(struct playlist *playlist)
+{
+ GtkTreeIter parent, sibling, iter;
+ gchar *name;
+ bool match;
+
+ gtk_tree_model_get_iter_first(GTK_TREE_MODEL(p_store), &parent);
+ do {
+ name = __playlist_name(&parent);
+ match = string_match(name, "User Playlists");
+ g_free(name);
+
+ if (match)
+ break;
+ } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(p_store), &parent));
+
+ if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(p_store), &sibling, &parent)) {
+ __playlist_add(&parent, playlist->pl_name, "text-x-generic", PL_USER);
+ return;
+ }
+
+ do {
+ name = __playlist_name(&sibling);
+ match = g_utf8_collate(name, playlist->pl_name) >= 0;
+ g_free(name);
+
+ if (match) {
+ gtk_tree_store_insert_before(p_store, &iter, &parent, &sibling);
+ __playlist_set(&iter, playlist->pl_name, "text-x-generic", PL_USER);
+ __playlist_set_size(&iter, playlist->pl_name);
+ return;
+ }
+ } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(p_store), &sibling));
+
+ __playlist_add(&parent, playlist->pl_name, "text-x-generic", PL_USER);
+}
+
struct queue_ops playlist_ops = {
.qop_init = __playlist_init,
.qop_deinit = gui_queue_free,
diff --git a/include/gui/playlist.h b/include/gui/playlist.h
index be0deb24..20368d77 100644
--- a/include/gui/playlist.h
+++ b/include/gui/playlist.h
@@ -18,6 +18,9 @@ void gui_playlist_add_library(struct library *);
/* Called to add an artist playlist. */
void gui_playlist_add_artist(struct artist *);
+/* Called to add a user playlist. */
+void gui_playlist_add_user(struct playlist *);
+
/* Playlist operations passed to core_init() */
extern struct queue_ops playlist_ops;
diff --git a/tests/gui/playlist.c b/tests/gui/playlist.c
index 73326968..98a1089d 100644
--- a/tests/gui/playlist.c
+++ b/tests/gui/playlist.c
@@ -9,7 +9,9 @@
#include
#include
-struct core_init_data init_data;
+struct core_init_data init_data = {
+ .playlist_ops = &playlist_ops,
+};
static void test_playlist_sidebar()
{
@@ -31,6 +33,9 @@ static void test_playlist_sidebar()
playlist_add(PL_SYSTEM, "History", track_get(0));
playlist_add(PL_SYSTEM, "Favorites", track_get(0));
playlist_add(PL_SYSTEM, "Hidden", track_get(1));
+
+ playlist_new(PL_USER, "Test");
+ playlist_add(PL_USER, "Test", track_get(0));
gtk_tree_model_filter_refilter(filter);
gtk_tree_view_expand_all(treeview);
@@ -59,6 +64,21 @@ static void test_playlist_sidebar()
gtk_tree_selection_select_path(selection, path);
g_assert_cmpuint(gtk_tree_selection_count_selected_rows(selection), ==, 0);
+ gtk_tree_path_down(path);
+ gtk_tree_selection_select_path(selection, path);
+ g_assert_cmpuint(gtk_tree_selection_count_selected_rows(selection), ==, 1);
+ g_assert_cmpstr(gui_playlist_cur(), ==, "Test");
+
+ gtk_tree_path_up(path);
+ gtk_tree_path_next(path);
+ gtk_tree_selection_unselect_all(selection);
+ gtk_tree_selection_select_path(selection, path);
+ g_assert_cmpuint(gtk_tree_selection_count_selected_rows(selection), ==, 0);
+
+ gtk_tree_path_next(path);
+ gtk_tree_selection_select_path(selection, path);
+ g_assert_cmpuint(gtk_tree_selection_count_selected_rows(selection), ==, 0);
+
gtk_tree_path_down(path);
gtk_tree_selection_select_path(selection, path);
g_assert_cmpuint(gtk_tree_selection_count_selected_rows(selection), ==, 1);
@@ -95,7 +115,7 @@ int main(int argc, char **argv)
g_test_add_func("/Gui/Playlist/Sidebar", test_playlist_sidebar);
ret = g_test_run();
- gui_builder_deinit();
core_deinit();
+ gui_builder_deinit();
return ret;
}