gui/filter: Move playlist filtering into filter.c
Implements #75: Move treeview filter to a new layer Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
b9916706f1
commit
39d87f98f8
68
gui/filter.c
68
gui/filter.c
|
@ -1,10 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2016 (c) Anna Schumaker.
|
* Copyright 2016 (c) Anna Schumaker.
|
||||||
*/
|
*/
|
||||||
|
#include <core/string.h>
|
||||||
#include <gui/filter.h>
|
#include <gui/filter.h>
|
||||||
#include <gui/model.h>
|
#include <gui/model.h>
|
||||||
|
|
||||||
static GtkTreeModelFilter *filter_model = NULL;
|
static GtkTreeModelFilter *filter_model = NULL;
|
||||||
|
static gchar **filter_search = NULL;
|
||||||
|
|
||||||
|
|
||||||
static inline GtkTreePath *__gui_filter_convert_path(GtkTreePath *path)
|
static inline GtkTreePath *__gui_filter_convert_path(GtkTreePath *path)
|
||||||
|
@ -13,11 +15,75 @@ static inline GtkTreePath *__gui_filter_convert_path(GtkTreePath *path)
|
||||||
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()
|
void gui_filter_init()
|
||||||
{
|
{
|
||||||
GtkTreeModel *model = GTK_TREE_MODEL(gui_model_get());
|
GtkTreeModel *model = GTK_TREE_MODEL(gui_model_get());
|
||||||
GtkTreeModel *filter = gtk_tree_model_filter_new(model, NULL);
|
GtkTreeModel *filter = gtk_tree_model_filter_new(model, NULL);
|
||||||
filter_model = GTK_TREE_MODEL_FILTER(filter);
|
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()
|
void gui_filter_deinit()
|
||||||
|
|
91
gui/queue.c
91
gui/queue.c
|
@ -11,15 +11,6 @@
|
||||||
|
|
||||||
static struct gui_queue *gq_queue = NULL;
|
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,
|
static void __queue_toggle_flag(bool active, GtkWidget *widget,
|
||||||
enum queue_flags flag)
|
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)
|
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,
|
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_flags = flags;
|
||||||
gq->gq_text = g_strdup(text);
|
gq->gq_text = g_strdup(text);
|
||||||
gq->gq_search = NULL;
|
|
||||||
gq->gq_playlist = playlist;
|
gq->gq_playlist = playlist;
|
||||||
gq->gq_queue = queue;
|
gq->gq_queue = queue;
|
||||||
|
|
||||||
|
@ -140,8 +60,6 @@ void gui_queue_free(struct queue *queue)
|
||||||
|
|
||||||
if (gq_queue == gq)
|
if (gq_queue == gq)
|
||||||
gui_view_set_playlist(NULL);
|
gui_view_set_playlist(NULL);
|
||||||
if (gq->gq_search)
|
|
||||||
g_strfreev(gq->gq_search);
|
|
||||||
g_free(gq->gq_text);
|
g_free(gq->gq_text);
|
||||||
g_free(gq);
|
g_free(gq);
|
||||||
}
|
}
|
||||||
|
@ -151,7 +69,6 @@ void gui_queue_show(struct gui_queue *queue)
|
||||||
GtkButton *random = GTK_BUTTON(gui_builder_widget("o_random"));
|
GtkButton *random = GTK_BUTTON(gui_builder_widget("o_random"));
|
||||||
GtkEntry *search = GTK_ENTRY(gui_filter_search());
|
GtkEntry *search = GTK_ENTRY(gui_filter_search());
|
||||||
bool has_random = false;
|
bool has_random = false;
|
||||||
gchar *text;
|
|
||||||
|
|
||||||
gq_queue = queue;
|
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_toggle_button_set_active(GTK_TOGGLE_BUTTON(random), has_random);
|
||||||
gtk_widget_set_sensitive(GTK_WIDGET(search), queue != NULL);
|
gtk_widget_set_sensitive(GTK_WIDGET(search), queue != NULL);
|
||||||
|
gtk_entry_set_text(search, "");
|
||||||
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, "");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,14 @@
|
||||||
#define OCARINA_GUI_FILTER_H
|
#define OCARINA_GUI_FILTER_H
|
||||||
#include <gui/builder.h>
|
#include <gui/builder.h>
|
||||||
|
|
||||||
|
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. */
|
/* Called to initialize the filter model. */
|
||||||
void gui_filter_init();
|
void gui_filter_init();
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,7 @@ enum gui_queue_flags {
|
||||||
|
|
||||||
struct gui_queue {
|
struct gui_queue {
|
||||||
unsigned int gq_flags;
|
unsigned int gq_flags;
|
||||||
unsigned int gq_active;
|
|
||||||
gchar *gq_text;
|
gchar *gq_text;
|
||||||
gchar **gq_search;
|
|
||||||
|
|
||||||
struct playlist *gq_playlist;
|
struct playlist *gq_playlist;
|
||||||
struct queue *gq_queue;
|
struct queue *gq_queue;
|
||||||
|
|
|
@ -834,7 +834,7 @@ audio-volume-medium</property>
|
||||||
<item translatable="yes">Genre</item>
|
<item translatable="yes">Genre</item>
|
||||||
<item translatable="yes">Title</item>
|
<item translatable="yes">Title</item>
|
||||||
</items>
|
</items>
|
||||||
<signal name="changed" handler="__queue_filter_how_changed" swapped="no"/>
|
<signal name="changed" handler="__gui_filter_how_changed" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -851,7 +851,8 @@ audio-volume-medium</property>
|
||||||
<property name="primary_icon_activatable">False</property>
|
<property name="primary_icon_activatable">False</property>
|
||||||
<property name="primary_icon_sensitive">False</property>
|
<property name="primary_icon_sensitive">False</property>
|
||||||
<property name="placeholder_text" translatable="yes">Type here to filter</property>
|
<property name="placeholder_text" translatable="yes">Type here to filter</property>
|
||||||
<signal name="search-changed" handler="__queue_filter" swapped="no"/>
|
<signal name="search-changed" handler="__gui_filter_search_changed" swapped="no"/>
|
||||||
|
<signal name="search-changed" handler="gui_view_scroll" after="yes" swapped="no"/>
|
||||||
<accelerator key="slash" signal="grab-focus"/>
|
<accelerator key="slash" signal="grab-focus"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
|
|
|
@ -71,6 +71,15 @@ void test_filter()
|
||||||
}
|
}
|
||||||
g_assert_null(gui_filter_path_get_track(path));
|
g_assert_null(gui_filter_path_get_track(path));
|
||||||
gtk_tree_path_free(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)
|
int main(int argc, char **argv)
|
||||||
|
|
Loading…
Reference in New Issue