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 <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2016-01-20 08:33:24 -05:00
parent 4c784366d7
commit 76a6eba537
9 changed files with 88 additions and 69 deletions

View File

@ -1,6 +1,8 @@
/*
* Copyright 2016 (c) Anna Schumaker.
*/
#include <core/filter.h>
#include <core/string.h>
#include <gui/builder.h>
#include <gui/model.h>
#include <gui/queue.h>
@ -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);

View File

@ -11,54 +11,25 @@ extern "C" {
QueueWindow :: QueueWindow(BaseObjectType *cobject,
const Glib::RefPtr<Gtk::Builder> 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);
}

View File

@ -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--)

View File

@ -192,9 +192,7 @@ void Tab :: tab_selected_ids(std::vector<unsigned int> &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(

View File

@ -4,6 +4,7 @@
#ifndef OCARINA_GUI_QUEUE_H
#define OCARINA_GUI_QUEUE_H
#include <core/containers/set.h>
#include <core/queue.h>
#include <gui/model.h>
@ -18,7 +19,9 @@ struct gui_queue {
gchar *gq_text;
GuiQueueModel *gq_model;
GtkTreeModel *gq_filter;
struct queue *gq_queue;
struct set gq_visible;
};

View File

@ -15,19 +15,12 @@ public:
Glib::RefPtr<Gtk::Builder> _builder;
queue *_queue;
struct set _q_search_res;
bool _q_search_empty;
Gtk::TreeView *q_treeview;
GtkTreeModel *q_filter;
QueueWindow(BaseObjectType *, const Glib::RefPtr<Gtk::Builder>);
~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 *);
};

View File

@ -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 */

View File

@ -1067,6 +1067,7 @@
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
<property name="placeholder_text" translatable="yes">Type here to filter</property>
<signal name="search-changed" handler="__queue_filter" swapped="no"/>
<accelerator key="slash" signal="grab-focus"/>
</object>
<packing>

View File

@ -6,6 +6,9 @@
#define TEST_NEED_PLAYLIST
#define TEST_NEED_SIDEBAR
#define TEST_NEED_WINDOW
#include <core/core.h>
#include <core/collection.h>
#include <core/idle.h>
#include <gui/builder.h>
#include <gui/queue.h>
#include <tests/gui.h>
@ -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),
);