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.
|
* Copyright 2016 (c) Anna Schumaker.
|
||||||
*/
|
*/
|
||||||
|
#include <core/filter.h>
|
||||||
|
#include <core/string.h>
|
||||||
#include <gui/builder.h>
|
#include <gui/builder.h>
|
||||||
#include <gui/model.h>
|
#include <gui/model.h>
|
||||||
#include <gui/queue.h>
|
#include <gui/queue.h>
|
||||||
|
@ -46,15 +48,46 @@ void __queue_disabled(GtkSwitch *enabled, GParamSpec *pspec, gpointer data)
|
||||||
Q_ENABLED);
|
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,
|
struct gui_queue *gui_queue_alloc(struct queue *queue, const gchar *text,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct gui_queue *gq = g_malloc(sizeof(struct gui_queue));
|
struct gui_queue *gq = g_malloc(sizeof(struct gui_queue));
|
||||||
|
|
||||||
gq->gq_flags = flags;
|
gq->gq_flags = flags;
|
||||||
gq->gq_text = g_strdup(text);
|
gq->gq_text = g_strdup(text);
|
||||||
gq->gq_model = gui_queue_model_new(queue);
|
gq->gq_model = gui_queue_model_new(queue);
|
||||||
gq->gq_queue = 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;
|
return gq;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +98,7 @@ void gui_queue_free(struct queue *queue)
|
||||||
struct gui_queue *gq = gui_queue(queue);
|
struct gui_queue *gq = gui_queue(queue);
|
||||||
|
|
||||||
gtk_tree_view_set_model(treeview, NULL);
|
gtk_tree_view_set_model(treeview, NULL);
|
||||||
|
set_deinit(&gq->gq_visible);
|
||||||
queue->q_private = NULL;
|
queue->q_private = NULL;
|
||||||
|
|
||||||
g_object_unref(gq->gq_model);
|
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_random = queue_has_flag(queue->gq_queue, Q_RANDOM);
|
||||||
has_repeat = queue_has_flag(queue->gq_queue, Q_REPEAT);
|
has_repeat = queue_has_flag(queue->gq_queue, Q_REPEAT);
|
||||||
is_enabled = queue_has_flag(queue->gq_queue, Q_ENABLED);
|
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);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(random), has_random);
|
||||||
|
|
|
@ -11,54 +11,25 @@ extern "C" {
|
||||||
|
|
||||||
QueueWindow :: QueueWindow(BaseObjectType *cobject,
|
QueueWindow :: QueueWindow(BaseObjectType *cobject,
|
||||||
const Glib::RefPtr<Gtk::Builder> builder)
|
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);
|
_builder->get_widget("q_treeview", q_treeview);
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueWindow :: ~QueueWindow()
|
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)
|
void QueueWindow :: init(queue *queue)
|
||||||
{
|
{
|
||||||
_queue = queue;
|
_queue = queue;
|
||||||
GtkTreeModel *model = GTK_TREE_MODEL(gui_queue(queue)->gq_model);
|
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,
|
q_treeview->signal_row_activated().connect(sigc::mem_fun(*this,
|
||||||
&QueueWindow :: on_row_activated));
|
&QueueWindow :: on_row_activated));
|
||||||
q_treeview->signal_key_press_event().connect(sigc::mem_fun(*this,
|
q_treeview->signal_key_press_event().connect(sigc::mem_fun(*this,
|
||||||
&QueueWindow :: on_key_press), false);
|
&QueueWindow :: on_key_press), false);
|
||||||
gtk_tree_view_set_model(q_treeview->gobj(), q_filter);
|
gtk_tree_view_set_model(q_treeview->gobj(), model);
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueueWindow :: on_key_press(GdkEventKey *event)
|
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,
|
void QueueWindow :: on_row_activated(const Gtk::TreePath &path,
|
||||||
Gtk::TreeViewColumn *col)
|
Gtk::TreeViewColumn *col)
|
||||||
{
|
{
|
||||||
GtkTreePath *orig = path.gobj_copy();
|
GtkTreePath *real = path.gobj_copy();
|
||||||
GtkTreePath *real = gtk_tree_model_filter_convert_path_to_child_path(
|
|
||||||
GTK_TREE_MODEL_FILTER(q_filter), orig);
|
|
||||||
struct track *track = gui_queue_model_path_get_track(
|
struct track *track = gui_queue_model_path_get_track(
|
||||||
gui_queue(_queue)->gq_model, real);
|
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]);
|
queue_selected(_queue, gtk_tree_path_get_indices(real)[0]);
|
||||||
audio_play();
|
audio_play();
|
||||||
|
|
||||||
gtk_tree_path_free(orig);
|
|
||||||
gtk_tree_path_free(real);
|
gtk_tree_path_free(real);
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,11 +139,8 @@ bool QueueTab :: on_key_press_event(const std::string &key)
|
||||||
GtkTreePath *path;
|
GtkTreePath *path;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < rows.size(); i++) {
|
for (unsigned int i = 0; i < rows.size(); i++) {
|
||||||
path = gtk_tree_model_filter_convert_path_to_child_path(
|
path = rows[i].gobj();
|
||||||
GTK_TREE_MODEL_FILTER(tab_window->q_filter),
|
|
||||||
rows[i].gobj());
|
|
||||||
ids.push_back(gtk_tree_path_get_indices(path)[0]);
|
ids.push_back(gtk_tree_path_get_indices(path)[0]);
|
||||||
gtk_tree_path_free(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = ids.size(); i > 0; i--)
|
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;
|
struct track *track;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < rows.size(); i++) {
|
for (unsigned int i = 0; i < rows.size(); i++) {
|
||||||
path = gtk_tree_model_filter_convert_path_to_child_path(
|
path = rows[i].gobj();
|
||||||
GTK_TREE_MODEL_FILTER(tab_window->q_filter),
|
|
||||||
rows[i].gobj());
|
|
||||||
track = gui_queue_model_path_get_track(gui_queue(tab_pq)->gq_model,
|
track = gui_queue_model_path_get_track(gui_queue(tab_pq)->gq_model,
|
||||||
path);
|
path);
|
||||||
ids.push_back(track->tr_dbe.dbe_index);
|
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("");
|
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()
|
static void on_new_pq()
|
||||||
{
|
{
|
||||||
Tab *tab = cur_tab();
|
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);
|
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));
|
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 */
|
/* Menu signals */
|
||||||
Glib :: wrap(GTK_MENU(gui_builder_widget("o_rc_menu")), false)->show_all();
|
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(
|
Glib :: wrap(GTK_MENU_ITEM(gui_builder_widget("o_new_pq")), false)->signal_activate().connect(
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#ifndef OCARINA_GUI_QUEUE_H
|
#ifndef OCARINA_GUI_QUEUE_H
|
||||||
#define OCARINA_GUI_QUEUE_H
|
#define OCARINA_GUI_QUEUE_H
|
||||||
|
|
||||||
|
#include <core/containers/set.h>
|
||||||
#include <core/queue.h>
|
#include <core/queue.h>
|
||||||
#include <gui/model.h>
|
#include <gui/model.h>
|
||||||
|
|
||||||
|
@ -18,7 +19,9 @@ struct gui_queue {
|
||||||
gchar *gq_text;
|
gchar *gq_text;
|
||||||
|
|
||||||
GuiQueueModel *gq_model;
|
GuiQueueModel *gq_model;
|
||||||
|
GtkTreeModel *gq_filter;
|
||||||
struct queue *gq_queue;
|
struct queue *gq_queue;
|
||||||
|
struct set gq_visible;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,19 +15,12 @@ public:
|
||||||
Glib::RefPtr<Gtk::Builder> _builder;
|
Glib::RefPtr<Gtk::Builder> _builder;
|
||||||
queue *_queue;
|
queue *_queue;
|
||||||
|
|
||||||
struct set _q_search_res;
|
|
||||||
bool _q_search_empty;
|
|
||||||
|
|
||||||
Gtk::TreeView *q_treeview;
|
Gtk::TreeView *q_treeview;
|
||||||
GtkTreeModel *q_filter;
|
|
||||||
|
|
||||||
QueueWindow(BaseObjectType *, const Glib::RefPtr<Gtk::Builder>);
|
QueueWindow(BaseObjectType *, const Glib::RefPtr<Gtk::Builder>);
|
||||||
~QueueWindow();
|
~QueueWindow();
|
||||||
void init(queue *);
|
void init(queue *);
|
||||||
|
|
||||||
void filter(std::string &);
|
|
||||||
bool filter_ids(const Gtk::TreeIter &);
|
|
||||||
|
|
||||||
bool on_key_press(GdkEventKey *);
|
bool on_key_press(GdkEventKey *);
|
||||||
void on_row_activated(const Gtk::TreePath &, Gtk::TreeViewColumn *);
|
void on_row_activated(const Gtk::TreePath &, Gtk::TreeViewColumn *);
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,6 +31,7 @@ void __playlist_selection_changed() {}
|
||||||
|
|
||||||
#ifdef TEST_NEED_QUEUE
|
#ifdef TEST_NEED_QUEUE
|
||||||
void __queue_disabled() {}
|
void __queue_disabled() {}
|
||||||
|
void __queue_filter() {}
|
||||||
void __queue_random() {}
|
void __queue_random() {}
|
||||||
void __queue_repeat() {}
|
void __queue_repeat() {}
|
||||||
#endif /* TEST_NEED_QUEUE */
|
#endif /* TEST_NEED_QUEUE */
|
||||||
|
|
|
@ -1067,6 +1067,7 @@
|
||||||
<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"/>
|
||||||
<accelerator key="slash" signal="grab-focus"/>
|
<accelerator key="slash" signal="grab-focus"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
#define TEST_NEED_PLAYLIST
|
#define TEST_NEED_PLAYLIST
|
||||||
#define TEST_NEED_SIDEBAR
|
#define TEST_NEED_SIDEBAR
|
||||||
#define TEST_NEED_WINDOW
|
#define TEST_NEED_WINDOW
|
||||||
|
#include <core/core.h>
|
||||||
|
#include <core/collection.h>
|
||||||
|
#include <core/idle.h>
|
||||||
#include <gui/builder.h>
|
#include <gui/builder.h>
|
||||||
#include <gui/queue.h>
|
#include <gui/queue.h>
|
||||||
#include <tests/gui.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 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_init = test_queue_init,
|
||||||
.qop_deinit = gui_queue_free,
|
.qop_deinit = gui_queue_free,
|
||||||
.qop_cleared = gui_queue_cleared,
|
.qop_cleared = gui_queue_cleared,
|
||||||
|
@ -29,6 +32,10 @@ static const struct queue_ops test_ops = {
|
||||||
.qop_updated = gui_queue_updated,
|
.qop_updated = gui_queue_updated,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct core_init_data init_data = {
|
||||||
|
.collection_ops = &test_ops,
|
||||||
|
};
|
||||||
|
|
||||||
static void test_queue()
|
static void test_queue()
|
||||||
{
|
{
|
||||||
GtkToggleButton *random, *repeat;
|
GtkToggleButton *random, *repeat;
|
||||||
|
@ -138,6 +145,37 @@ static void test_queue()
|
||||||
test_equal((void *)gui_queue(&q), NULL);
|
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(
|
DECLARE_UNIT_TESTS(
|
||||||
UNIT_TEST("Queue", test_queue),
|
UNIT_TEST("Queue", test_queue),
|
||||||
|
UNIT_TEST("Queue Filtering", test_filter),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue