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:
parent
4c784366d7
commit
76a6eba537
44
gui/queue.c
44
gui/queue.c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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--)
|
||||
|
|
18
gui/tabs.cpp
18
gui/tabs.cpp
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue