From 76a6eba537a15cd28857fd0e51eb4fa67929100e Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Wed, 20 Jan 2016 08:33:24 -0500 Subject: [PATCH] gui/queue: Add functions to filter the currently displayed queue And remove the ability to filter from the C++ code. Signed-off-by: Anna Schumaker --- gui/queue.c | 44 ++++++++++++++++++++++++++++++++---- gui/queue/window.cpp | 38 +++---------------------------- gui/queue_tab.cpp | 5 +--- gui/tabs.cpp | 18 +-------------- include/gui/queue.h | 3 +++ include/gui/queue/window.h | 7 ------ include/tests/gui.h | 1 + share/ocarina/ocarina6.glade | 1 + tests/gui/queue.c | 40 +++++++++++++++++++++++++++++++- 9 files changed, 88 insertions(+), 69 deletions(-) diff --git a/gui/queue.c b/gui/queue.c index 514ac0b3..b02a0e07 100644 --- a/gui/queue.c +++ b/gui/queue.c @@ -1,6 +1,8 @@ /* * Copyright 2016 (c) Anna Schumaker. */ +#include +#include #include #include #include @@ -46,15 +48,46 @@ void __queue_disabled(GtkSwitch *enabled, GParamSpec *pspec, gpointer data) Q_ENABLED); } +static gboolean __queue_visible_func(GtkTreeModel *model, GtkTreeIter *iter, + gpointer data) +{ + struct track *track; + + if (!gq_queue || (strlen(gtk_entry_get_text(GTK_ENTRY(data))) == 0)) + return TRUE; + + track = gui_queue_model_iter_get_track(gq_queue->gq_model, iter); + return set_has(&gq_queue->gq_visible, track->tr_dbe.dbe_index); +} + +void __queue_filter(GtkSearchEntry *entry, gpointer data) +{ + const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry)); + + if (!gq_queue) + return; + if (strlen(text) > 0) + filter_search(text, &gq_queue->gq_visible); + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(gq_queue->gq_filter)); +} + struct gui_queue *gui_queue_alloc(struct queue *queue, const gchar *text, unsigned int flags) { struct gui_queue *gq = g_malloc(sizeof(struct gui_queue)); - gq->gq_flags = flags; - gq->gq_text = g_strdup(text); - gq->gq_model = gui_queue_model_new(queue); - gq->gq_queue = queue; + gq->gq_flags = flags; + gq->gq_text = g_strdup(text); + gq->gq_model = gui_queue_model_new(queue); + gq->gq_filter = gtk_tree_model_filter_new( + GTK_TREE_MODEL(gq->gq_model), NULL); + gq->gq_queue = queue; + + set_init(&gq->gq_visible); + gtk_tree_model_filter_set_visible_func( + GTK_TREE_MODEL_FILTER(gq->gq_filter), + __queue_visible_func, + gui_builder_object("o_search"), NULL); return gq; } @@ -65,6 +98,7 @@ void gui_queue_free(struct queue *queue) struct gui_queue *gq = gui_queue(queue); gtk_tree_view_set_model(treeview, NULL); + set_deinit(&gq->gq_visible); queue->q_private = NULL; g_object_unref(gq->gq_model); @@ -91,7 +125,7 @@ void gui_queue_show(struct gui_queue *queue) has_random = queue_has_flag(queue->gq_queue, Q_RANDOM); has_repeat = queue_has_flag(queue->gq_queue, Q_REPEAT); is_enabled = queue_has_flag(queue->gq_queue, Q_ENABLED); - gtk_tree_view_set_model(view, GTK_TREE_MODEL(queue->gq_model)); + gtk_tree_view_set_model(view, queue->gq_filter); } gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(random), has_random); diff --git a/gui/queue/window.cpp b/gui/queue/window.cpp index 1b3ddfbb..f8dda1d2 100644 --- a/gui/queue/window.cpp +++ b/gui/queue/window.cpp @@ -11,54 +11,25 @@ extern "C" { QueueWindow :: QueueWindow(BaseObjectType *cobject, const Glib::RefPtr builder) - : Gtk::ScrolledWindow(cobject), _builder(builder), _q_search_empty(true) + : Gtk::ScrolledWindow(cobject), _builder(builder) { - _q_search_res = SET_INIT(); _builder->get_widget("q_treeview", q_treeview); } QueueWindow :: ~QueueWindow() { - set_deinit(&_q_search_res); -} - -int queue_window_filter_ids(GtkTreeModel *model, GtkTreeIter *iter, - gpointer data) -{ - QueueWindow *window = (QueueWindow *)data; - struct queue *queue = window->_queue; - struct track *track; - - if (window->_q_search_empty) - return true; - - track = gui_queue_model_iter_get_track(gui_queue(queue)->gq_model, iter); - return set_has(&window->_q_search_res, track->tr_dbe.dbe_index); } void QueueWindow :: init(queue *queue) { _queue = queue; GtkTreeModel *model = GTK_TREE_MODEL(gui_queue(queue)->gq_model); - q_filter = gtk_tree_model_filter_new(model, NULL); - - gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(q_filter), - queue_window_filter_ids, - this, NULL); q_treeview->signal_row_activated().connect(sigc::mem_fun(*this, &QueueWindow :: on_row_activated)); q_treeview->signal_key_press_event().connect(sigc::mem_fun(*this, &QueueWindow :: on_key_press), false); - gtk_tree_view_set_model(q_treeview->gobj(), q_filter); -} - -void QueueWindow :: filter(std::string &text) -{ - _q_search_empty = (text.find_first_not_of(" \t") == std::string::npos); - if (!_q_search_empty) - filter_search(text.c_str(), &_q_search_res); - gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(q_filter)); + gtk_tree_view_set_model(q_treeview->gobj(), model); } bool QueueWindow :: on_key_press(GdkEventKey *event) @@ -72,9 +43,7 @@ bool QueueWindow :: on_key_press(GdkEventKey *event) void QueueWindow :: on_row_activated(const Gtk::TreePath &path, Gtk::TreeViewColumn *col) { - GtkTreePath *orig = path.gobj_copy(); - GtkTreePath *real = gtk_tree_model_filter_convert_path_to_child_path( - GTK_TREE_MODEL_FILTER(q_filter), orig); + GtkTreePath *real = path.gobj_copy(); struct track *track = gui_queue_model_path_get_track( gui_queue(_queue)->gq_model, real); @@ -82,6 +51,5 @@ void QueueWindow :: on_row_activated(const Gtk::TreePath &path, queue_selected(_queue, gtk_tree_path_get_indices(real)[0]); audio_play(); - gtk_tree_path_free(orig); gtk_tree_path_free(real); } diff --git a/gui/queue_tab.cpp b/gui/queue_tab.cpp index 29408fbc..454b1a5b 100644 --- a/gui/queue_tab.cpp +++ b/gui/queue_tab.cpp @@ -139,11 +139,8 @@ bool QueueTab :: on_key_press_event(const std::string &key) GtkTreePath *path; for (unsigned int i = 0; i < rows.size(); i++) { - path = gtk_tree_model_filter_convert_path_to_child_path( - GTK_TREE_MODEL_FILTER(tab_window->q_filter), - rows[i].gobj()); + path = rows[i].gobj(); ids.push_back(gtk_tree_path_get_indices(path)[0]); - gtk_tree_path_free(path); } for (unsigned int i = ids.size(); i > 0; i--) diff --git a/gui/tabs.cpp b/gui/tabs.cpp index 9c27197b..9b086f54 100644 --- a/gui/tabs.cpp +++ b/gui/tabs.cpp @@ -192,9 +192,7 @@ void Tab :: tab_selected_ids(std::vector &ids) struct track *track; for (unsigned int i = 0; i < rows.size(); i++) { - path = gtk_tree_model_filter_convert_path_to_child_path( - GTK_TREE_MODEL_FILTER(tab_window->q_filter), - rows[i].gobj()); + path = rows[i].gobj(); track = gui_queue_model_path_get_track(gui_queue(tab_pq)->gq_model, path); ids.push_back(track->tr_dbe.dbe_index); @@ -401,16 +399,6 @@ static void on_switch_page(Gtk::Widget *page, int num) Glib :: wrap(GTK_LABEL(gui_builder_widget("o_queue_time")), false)->set_text(""); } -static void on_search_changed() -{ - Gtk::SearchEntry *search = Glib :: wrap(GTK_SEARCH_ENTRY(gui_builder_widget("o_search")), false); - std::string text = search->get_text(); - Tab *tab = cur_tab(); - - if (tab) - tab->tab_window->filter(text); -} - static void on_new_pq() { Tab *tab = cur_tab(); @@ -481,10 +469,6 @@ void init_tabs() struct Gtk::Notebook *notebook = Glib :: wrap(GTK_NOTEBOOK(gui_builder_widget("o_notebook")), false); notebook->signal_switch_page().connect(sigc::ptr_fun(on_switch_page)); - /* Search signals */ - Gtk::SearchEntry *search = Glib :: wrap(GTK_SEARCH_ENTRY(gui_builder_widget("o_search")), false); - search->signal_search_changed().connect(sigc::ptr_fun(on_search_changed)); - /* Menu signals */ Glib :: wrap(GTK_MENU(gui_builder_widget("o_rc_menu")), false)->show_all(); Glib :: wrap(GTK_MENU_ITEM(gui_builder_widget("o_new_pq")), false)->signal_activate().connect( diff --git a/include/gui/queue.h b/include/gui/queue.h index 9c40ee53..70a1fe96 100644 --- a/include/gui/queue.h +++ b/include/gui/queue.h @@ -4,6 +4,7 @@ #ifndef OCARINA_GUI_QUEUE_H #define OCARINA_GUI_QUEUE_H +#include #include #include @@ -18,7 +19,9 @@ struct gui_queue { gchar *gq_text; GuiQueueModel *gq_model; + GtkTreeModel *gq_filter; struct queue *gq_queue; + struct set gq_visible; }; diff --git a/include/gui/queue/window.h b/include/gui/queue/window.h index ae14f45d..6d2539d5 100644 --- a/include/gui/queue/window.h +++ b/include/gui/queue/window.h @@ -15,19 +15,12 @@ public: Glib::RefPtr _builder; queue *_queue; - struct set _q_search_res; - bool _q_search_empty; - Gtk::TreeView *q_treeview; - GtkTreeModel *q_filter; QueueWindow(BaseObjectType *, const Glib::RefPtr); ~QueueWindow(); void init(queue *); - void filter(std::string &); - bool filter_ids(const Gtk::TreeIter &); - bool on_key_press(GdkEventKey *); void on_row_activated(const Gtk::TreePath &, Gtk::TreeViewColumn *); }; diff --git a/include/tests/gui.h b/include/tests/gui.h index 6de47bd5..6b2115c5 100644 --- a/include/tests/gui.h +++ b/include/tests/gui.h @@ -31,6 +31,7 @@ void __playlist_selection_changed() {} #ifdef TEST_NEED_QUEUE void __queue_disabled() {} +void __queue_filter() {} void __queue_random() {} void __queue_repeat() {} #endif /* TEST_NEED_QUEUE */ diff --git a/share/ocarina/ocarina6.glade b/share/ocarina/ocarina6.glade index 66218950..cf70c503 100644 --- a/share/ocarina/ocarina6.glade +++ b/share/ocarina/ocarina6.glade @@ -1067,6 +1067,7 @@ False False Type here to filter + diff --git a/tests/gui/queue.c b/tests/gui/queue.c index db89d98b..916b1984 100644 --- a/tests/gui/queue.c +++ b/tests/gui/queue.c @@ -6,6 +6,9 @@ #define TEST_NEED_PLAYLIST #define TEST_NEED_SIDEBAR #define TEST_NEED_WINDOW +#include +#include +#include #include #include #include @@ -19,7 +22,7 @@ static void *test_queue_init(struct queue *queue) static void test_queue_save(struct queue *queue, unsigned int row) {} -static const struct queue_ops test_ops = { +static struct queue_ops test_ops = { .qop_init = test_queue_init, .qop_deinit = gui_queue_free, .qop_cleared = gui_queue_cleared, @@ -29,6 +32,10 @@ static const struct queue_ops test_ops = { .qop_updated = gui_queue_updated, }; +struct core_init_data init_data = { + .collection_ops = &test_ops, +}; + static void test_queue() { GtkToggleButton *random, *repeat; @@ -138,6 +145,37 @@ static void test_queue() test_equal((void *)gui_queue(&q), NULL); } +static void test_filter() +{ + struct gui_queue *gq; + GtkEntry *search; + int argc = 0; + + search = GTK_ENTRY(gui_builder_widget("o_search")); + + core_init(&argc, NULL, &init_data); + collection_add("tests/Music/Hyrule Symphony"); + while (idle_run_task() == true) {} + gq = gui_queue(collection_get_queue()); + + gui_queue_show(gq); + + test_not_equal((void *)gq, NULL); + test_not_equal((void *)gq->gq_filter, NULL); + test_equal(gtk_tree_model_iter_n_children(gq->gq_filter, NULL), 13); + + gtk_entry_set_text(search, "zelda"); + g_signal_emit_by_name(search, "search-changed"); + test_equal(gtk_tree_model_iter_n_children(gq->gq_filter, NULL), 2); + + gtk_entry_set_text(search, ""); + g_signal_emit_by_name(search, "search-changed"); + test_equal(gtk_tree_model_iter_n_children(gq->gq_filter, NULL), 13); + + core_deinit(); +} + DECLARE_UNIT_TESTS( UNIT_TEST("Queue", test_queue), + UNIT_TEST("Queue Filtering", test_filter), );