From 39d87f98f89e1cb0866c85342b741cc4ff61cd4f Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Mon, 22 Aug 2016 09:12:13 -0400 Subject: [PATCH] gui/filter: Move playlist filtering into filter.c Implements #75: Move treeview filter to a new layer Signed-off-by: Anna Schumaker --- gui/filter.c | 68 +++++++++++++++++++++++++++++- gui/queue.c | 91 +--------------------------------------- include/gui/filter.h | 8 ++++ include/gui/queue.h | 2 - share/ocarina/ocarina.ui | 5 ++- tests/gui/filter.c | 9 ++++ 6 files changed, 88 insertions(+), 95 deletions(-) diff --git a/gui/filter.c b/gui/filter.c index 4fe5479d..8a36b406 100644 --- a/gui/filter.c +++ b/gui/filter.c @@ -1,10 +1,12 @@ /* * Copyright 2016 (c) Anna Schumaker. */ +#include #include #include -static GtkTreeModelFilter *filter_model = NULL; +static GtkTreeModelFilter *filter_model = NULL; +static gchar **filter_search = NULL; static inline GtkTreePath *__gui_filter_convert_path(GtkTreePath *path) @@ -13,11 +15,75 @@ static inline GtkTreePath *__gui_filter_convert_path(GtkTreePath *path) path); } +static inline gboolean __gui_filter_match_token(struct track *track, + const gchar *token, + unsigned int how) +{ + switch (how) { + case GUI_FILTER_ALBUM: + return album_match_token(track->tr_album, token); + case GUI_FILTER_ARTIST: + return artist_match_token(track->tr_album->al_artist, token); + case GUI_FILTER_GENRE: + return genre_match_token(track->tr_album->al_genre, token); + case GUI_FILTER_TITLE: + return track_match_token(track, token); + case GUI_FILTER_DEFAULT: + return track_match_token(track, token) || + album_match_token(track->tr_album, token) || + artist_match_token(track->tr_album->al_artist, token) || + genre_match_token(track->tr_album->al_genre, token); + default: + return false; + } +} + +static gboolean __gui_filter_visible_func(GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + struct track *track; + unsigned int i, how = gtk_combo_box_get_active(gui_filter_how()); + + if (!filter_search) + return TRUE; + + track = gui_model_iter_get_track(iter); + for (i = 0; filter_search[i]; i++) { + if (!__gui_filter_match_token(track, filter_search[i], how)) + return FALSE; + } + return TRUE; +} + +void __gui_filter_search_changed(GtkSearchEntry *search, gpointer data) +{ + const gchar *text = gtk_entry_get_text(GTK_ENTRY(search)); + + if (!gui_model_get_playlist()) + return; + if (strlen(text) > 0) + filter_search = g_str_tokenize_and_fold(text, NULL, NULL); + gtk_tree_model_filter_refilter(gui_filter_get()); + + g_strfreev(filter_search); + filter_search = NULL; +} + +void __gui_filter_how_changed(int n) +{ + __gui_filter_search_changed(gui_filter_search(), NULL); +} + void gui_filter_init() { GtkTreeModel *model = GTK_TREE_MODEL(gui_model_get()); GtkTreeModel *filter = gtk_tree_model_filter_new(model, NULL); filter_model = GTK_TREE_MODEL_FILTER(filter); + + gtk_tree_model_filter_set_visible_func(filter_model, + __gui_filter_visible_func, + NULL, NULL); } void gui_filter_deinit() diff --git a/gui/queue.c b/gui/queue.c index a421b4a2..b3ec6c04 100644 --- a/gui/queue.c +++ b/gui/queue.c @@ -11,15 +11,6 @@ static struct gui_queue *gq_queue = NULL; -enum gq_filter_how { - GQ_FILTER_DEFAULT, - GQ_FILTER_ALBUM, - GQ_FILTER_ARTIST, - GQ_FILTER_GENRE, - GQ_FILTER_TITLE, -}; - - static void __queue_toggle_flag(bool active, GtkWidget *widget, enum queue_flags flag) { @@ -44,78 +35,8 @@ void __queue_random(GtkToggleButton *button, gpointer data) } } -static gboolean __queue_visible_func(GtkTreeModel *model, GtkTreeIter *iter, - gpointer data) -{ - struct track *track; - unsigned int i; - gchar *token; - bool match; - - if (!gq_queue || !gq_queue->gq_search) - return TRUE; - - track = gui_model_iter_get_track(iter); - - for (i = 0; gq_queue->gq_search[i]; i++) { - token = gq_queue->gq_search[i]; - - switch (gq_queue->gq_active) { - case GQ_FILTER_ALBUM: - match = album_match_token(track->tr_album, token); - break; - case GQ_FILTER_ARTIST: - match = artist_match_token(track->tr_album->al_artist, token); - break; - case GQ_FILTER_GENRE: - match = genre_match_token(track->tr_album->al_genre, token); - break; - case GQ_FILTER_TITLE: - match = track_match_token(track, token); - break; - default: /* GQ_FILTER_DEFAULT */ - match = track_match_token(track, token) || - album_match_token(track->tr_album, token) || - artist_match_token(track->tr_album->al_artist, token) || - genre_match_token(track->tr_album->al_genre, token); - } - - if (!match) - return false; - } - - return TRUE; -} - -void __queue_filter(GtkSearchEntry *entry, gpointer data) -{ - const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry)); - - if (!gq_queue) - return; - if (gq_queue->gq_search) { - g_strfreev(gq_queue->gq_search); - gq_queue->gq_search = NULL; - } - if (strlen(text) > 0) { - gq_queue->gq_search = g_str_tokenize_and_fold(text, NULL, NULL); - gq_queue->gq_active = gtk_combo_box_get_active(gui_filter_how()); - } - - gtk_tree_model_filter_refilter(gui_filter_get()); - gui_view_scroll(); -} - -void __queue_filter_how_changed(int n) -{ - __queue_filter(gui_filter_search(), NULL); -} - void gui_queue_init(void) { - gtk_tree_model_filter_set_visible_func(gui_filter_get(), - __queue_visible_func, - NULL, NULL); } struct gui_queue *gui_queue_alloc(struct playlist *playlist, struct queue *queue, @@ -125,7 +46,6 @@ struct gui_queue *gui_queue_alloc(struct playlist *playlist, struct queue *queue gq->gq_flags = flags; gq->gq_text = g_strdup(text); - gq->gq_search = NULL; gq->gq_playlist = playlist; gq->gq_queue = queue; @@ -140,8 +60,6 @@ void gui_queue_free(struct queue *queue) if (gq_queue == gq) gui_view_set_playlist(NULL); - if (gq->gq_search) - g_strfreev(gq->gq_search); g_free(gq->gq_text); g_free(gq); } @@ -151,7 +69,6 @@ void gui_queue_show(struct gui_queue *queue) GtkButton *random = GTK_BUTTON(gui_builder_widget("o_random")); GtkEntry *search = GTK_ENTRY(gui_filter_search()); bool has_random = false; - gchar *text; gq_queue = queue; @@ -165,11 +82,5 @@ void gui_queue_show(struct gui_queue *queue) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(random), has_random); gtk_widget_set_sensitive(GTK_WIDGET(search), queue != NULL); - - if (queue && queue->gq_search) { - text = g_strjoinv(" ", queue->gq_search); - gtk_entry_set_text(search, text); - g_free(text); - } else - gtk_entry_set_text(search, ""); + gtk_entry_set_text(search, ""); } diff --git a/include/gui/filter.h b/include/gui/filter.h index fa4fac20..f26750cd 100644 --- a/include/gui/filter.h +++ b/include/gui/filter.h @@ -5,6 +5,14 @@ #define OCARINA_GUI_FILTER_H #include +enum gui_filter_how { + GUI_FILTER_DEFAULT, + GUI_FILTER_ALBUM, + GUI_FILTER_ARTIST, + GUI_FILTER_GENRE, + GUI_FILTER_TITLE, +}; + /* Called to initialize the filter model. */ void gui_filter_init(); diff --git a/include/gui/queue.h b/include/gui/queue.h index c9f2ef62..fed83956 100644 --- a/include/gui/queue.h +++ b/include/gui/queue.h @@ -13,9 +13,7 @@ enum gui_queue_flags { struct gui_queue { unsigned int gq_flags; - unsigned int gq_active; gchar *gq_text; - gchar **gq_search; struct playlist *gq_playlist; struct queue *gq_queue; diff --git a/share/ocarina/ocarina.ui b/share/ocarina/ocarina.ui index 87c7a79a..04895cc0 100644 --- a/share/ocarina/ocarina.ui +++ b/share/ocarina/ocarina.ui @@ -834,7 +834,7 @@ audio-volume-medium Genre Title - + False @@ -851,7 +851,8 @@ audio-volume-medium False False Type here to filter - + + diff --git a/tests/gui/filter.c b/tests/gui/filter.c index cd0d8512..5ea3b511 100644 --- a/tests/gui/filter.c +++ b/tests/gui/filter.c @@ -71,6 +71,15 @@ void test_filter() } g_assert_null(gui_filter_path_get_track(path)); gtk_tree_path_free(path); + + gtk_entry_set_text(GTK_ENTRY(gui_filter_search()), "Hyrule"); + g_assert_cmpuint(gtk_tree_model_iter_n_children(model, NULL), ==, 13); + + gtk_combo_box_set_active(gui_filter_how(), GUI_FILTER_TITLE); + g_assert_cmpuint(gtk_tree_model_iter_n_children(model, NULL), ==, 2); + + gtk_combo_box_set_active(gui_filter_how(), GUI_FILTER_DEFAULT); + g_assert_cmpuint(gtk_tree_model_iter_n_children(model, NULL), ==, 13); } int main(int argc, char **argv)