dc3e770c28
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
371 lines
8.4 KiB
C++
371 lines
8.4 KiB
C++
/*
|
|
* Copyright 2014 (c) Anna Schumaker.
|
|
*/
|
|
#include <core/callback.h>
|
|
#include <core/deck.h>
|
|
#include <gui/tabs.h>
|
|
|
|
#include <map>
|
|
|
|
|
|
static unsigned int q_col_width[] = { 20, 300, 60, 100, 100, 45, 100, 60, 1 };
|
|
|
|
static class QueueColumns : public Gtk::TreeModelColumnRecord {
|
|
public:
|
|
QueueColumns()
|
|
{ add(q_col_track); add(q_col_title); add(q_col_length);
|
|
add(q_col_artist); add(q_col_album); add(q_col_year);
|
|
add(q_col_genre); add(q_col_count); add(q_col_played);
|
|
add(q_col_path); }
|
|
|
|
Gtk::TreeModelColumn<unsigned int> q_col_track;
|
|
Gtk::TreeModelColumn<std::string> q_col_title;
|
|
Gtk::TreeModelColumn<std::string> q_col_length;
|
|
Gtk::TreeModelColumn<std::string> q_col_artist;
|
|
Gtk::TreeModelColumn<std::string> q_col_album;
|
|
Gtk::TreeModelColumn<unsigned int> q_col_year;
|
|
Gtk::TreeModelColumn<std::string> q_col_genre;
|
|
Gtk::TreeModelColumn<unsigned int> q_col_count;
|
|
Gtk::TreeModelColumn<std::string> q_col_played;
|
|
Gtk::TreeModelColumn<std::string> q_col_path;
|
|
} queue_cols;
|
|
|
|
|
|
|
|
class QueueTab : public Tab {
|
|
private:
|
|
/**
|
|
* Queue tab widgets
|
|
*/
|
|
Gtk::HBox q_tab_box;
|
|
Gtk::Label q_tab_number;
|
|
Gtk::Label q_tab_size;
|
|
Gtk::Button q_tab_close;
|
|
|
|
|
|
/**
|
|
* Queue page widgets
|
|
*/
|
|
Gtk::VBox q_vbox;
|
|
|
|
/**
|
|
* Toolbar widgets
|
|
*/
|
|
Gtk::HBox q_toolbar_box;
|
|
Gtk::SearchEntry q_search;
|
|
Gtk::ToggleButton q_random;
|
|
Gtk::ToggleButton q_repeat;
|
|
Gtk::Switch q_switch;
|
|
|
|
/* Treeview widgets */
|
|
Gtk::ScrolledWindow q_window;
|
|
Gtk::TreeView q_treeview;
|
|
|
|
|
|
public:
|
|
QueueTab(Queue *, unsigned int num);
|
|
~QueueTab();
|
|
|
|
/**
|
|
* Helper functions
|
|
*/
|
|
void setup_treeview();
|
|
void on_post_init();
|
|
bool on_key_press_event(const std::string &);
|
|
void tab_set_size();
|
|
void queue_set_number(unsigned int);
|
|
void on_tab_reordered();
|
|
void on_move_queue(int);
|
|
void queue_set_sensitive(bool);
|
|
|
|
/**
|
|
* GTK-MM Callbacks
|
|
*/
|
|
void on_close_clicked();
|
|
void on_switch_changed();
|
|
};
|
|
|
|
static std::map<Gtk::Widget *, QueueTab *> queue_mapping;
|
|
|
|
|
|
QueueTab :: QueueTab(Queue *pq, unsigned int num)
|
|
: Tab(pq)
|
|
{
|
|
/*
|
|
* Create our tab widget
|
|
*/
|
|
q_tab_number.set_alignment(0, 0.5);
|
|
q_tab_size.set_justify(Gtk::JUSTIFY_CENTER);
|
|
|
|
q_tab_close.set_image_from_icon_name("window-close", Gtk::ICON_SIZE_MENU);
|
|
q_tab_close.set_relief(Gtk::RELIEF_NONE);
|
|
q_tab_close.set_alignment(1, 0.5);
|
|
q_tab_close.signal_clicked().connect(sigc::mem_fun(*this,
|
|
&QueueTab::on_close_clicked));
|
|
|
|
q_tab_box.pack_start(q_tab_number, false, true);
|
|
q_tab_box.pack_start(q_tab_size, true, true);
|
|
q_tab_box.pack_start(q_tab_close, false, true);
|
|
|
|
tab_set_size();
|
|
queue_set_number(num);
|
|
q_tab_box.show_all();
|
|
|
|
|
|
/*
|
|
* Now set up the toolbar
|
|
*/
|
|
q_repeat.set_image_from_icon_name("media-playlist-repeat", Gtk::ICON_SIZE_BUTTON);
|
|
q_random.set_image_from_icon_name("media-playlist-shuffle", Gtk::ICON_SIZE_BUTTON);
|
|
|
|
q_toolbar_box.set_margin_left(5);
|
|
q_toolbar_box.set_margin_right(5);
|
|
q_toolbar_box.set_spacing(5);
|
|
q_toolbar_box.set_homogeneous(false);
|
|
|
|
q_toolbar_box.pack_start(q_search, true, true);
|
|
q_toolbar_box.pack_start(q_switch, false, true);
|
|
q_toolbar_box.pack_start(q_repeat, false, true);
|
|
q_toolbar_box.pack_start(q_random, false, true);
|
|
|
|
|
|
/*
|
|
* And the treeview with scrolled window
|
|
*/
|
|
q_window.set_shadow_type(Gtk::SHADOW_IN);
|
|
q_window.set_margin_left(5);
|
|
q_window.set_margin_right(5);
|
|
q_window.set_margin_bottom(5);
|
|
q_window.add(q_treeview);
|
|
setup_treeview();
|
|
|
|
|
|
/*
|
|
* Fill in the page!
|
|
*/
|
|
|
|
q_vbox.set_margin_left(1);
|
|
q_vbox.set_margin_right(1);
|
|
q_vbox.set_homogeneous(false);
|
|
q_vbox.pack_start(q_toolbar_box, false, true, 2);
|
|
q_vbox.pack_start(q_window, true, true);
|
|
|
|
|
|
/*
|
|
* Set generic tab widgets
|
|
*/
|
|
|
|
tab_random = &q_random;
|
|
tab_repeat = &q_repeat;
|
|
tab_search = &q_search;
|
|
tab_size = &q_tab_size;
|
|
tab_treeview = &q_treeview;
|
|
tab_widget = &q_vbox;
|
|
|
|
tab_finish_init();
|
|
queue_mapping[tab_widget] = this;
|
|
|
|
gui :: get_widget<Gtk::Notebook>("o_notebook")->insert_page(q_vbox, q_tab_box, num);
|
|
gui :: get_widget<Gtk::Notebook>("o_notebook")->set_tab_reorderable(q_vbox);
|
|
q_vbox.show_all();
|
|
}
|
|
|
|
QueueTab :: ~QueueTab()
|
|
{
|
|
queue_mapping.erase(tab_widget);
|
|
tab_unmap();
|
|
gui :: get_widget<Gtk::Notebook>("o_notebook")->remove_page(q_vbox);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
*
|
|
* Queue tab helper functions
|
|
*
|
|
*/
|
|
|
|
void QueueTab :: setup_treeview()
|
|
{
|
|
q_treeview.append_column("#", queue_cols.q_col_track);
|
|
q_treeview.append_column("Title", queue_cols.q_col_title);
|
|
q_treeview.append_column("Length", queue_cols.q_col_length);
|
|
q_treeview.append_column("Artist", queue_cols.q_col_artist);
|
|
q_treeview.append_column("Album", queue_cols.q_col_album);
|
|
q_treeview.append_column("Year", queue_cols.q_col_year);
|
|
q_treeview.append_column("Genre", queue_cols.q_col_genre);
|
|
q_treeview.append_column("Count", queue_cols.q_col_count);
|
|
q_treeview.append_column("Played", queue_cols.q_col_played);
|
|
|
|
q_treeview.set_tooltip_column(9);
|
|
q_treeview.set_rules_hint();
|
|
q_treeview.set_enable_search(false);
|
|
q_treeview.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
|
|
q_treeview.set_rubber_banding();
|
|
|
|
std::vector<Gtk::TreeViewColumn *> columns = q_treeview.get_columns();
|
|
for (unsigned int i = 0; i < columns.size(); i++) {
|
|
columns[i]->set_resizable();
|
|
columns[i]->set_fixed_width(q_col_width[i]);
|
|
columns[i]->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED);
|
|
columns[i]->set_clickable();
|
|
}
|
|
|
|
}
|
|
|
|
void QueueTab :: on_post_init()
|
|
{
|
|
tab_init_random();
|
|
tab_init_repeat();
|
|
|
|
bool active = (tab_pq->has_flag(Q_ENABLED));
|
|
q_switch.set_active(active);
|
|
q_switch.property_active().signal_changed().connect(
|
|
sigc::mem_fun(*this, &QueueTab :: on_switch_changed));
|
|
queue_set_sensitive(active);
|
|
}
|
|
|
|
bool QueueTab :: on_key_press_event(const std::string &key)
|
|
{
|
|
std::vector<unsigned int> ids;
|
|
|
|
if (key != "Delete")
|
|
return Tab :: on_key_press_event(key);
|
|
|
|
/*
|
|
* tab_selected_ids() returns track_ids and not
|
|
* playlist_ids,so we can't use it here =(
|
|
*/
|
|
Glib::RefPtr<Gtk::TreeSelection> sel = tab_treeview->get_selection();
|
|
std::vector<Gtk::TreeModel::Path> rows = sel->get_selected_rows();
|
|
Gtk::TreeModel::Path path;
|
|
|
|
for (unsigned int i = 0; i < rows.size(); i++) {
|
|
path = tab_filter->convert_path_to_child_path(rows[i]);
|
|
ids.push_back(path[0]);
|
|
}
|
|
|
|
for (unsigned int i = ids.size(); i > 0; i--)
|
|
tab_pq->del(ids[i-1]);
|
|
return true;
|
|
}
|
|
|
|
void QueueTab :: tab_set_size()
|
|
{
|
|
std::stringstream ss;
|
|
ss << "<span size='x-large'>" << tab_pq->size() << "</span>";
|
|
q_tab_size.set_markup(ss.str());
|
|
}
|
|
|
|
void QueueTab :: queue_set_number(unsigned int num)
|
|
{
|
|
std::stringstream ss;
|
|
ss << "<span size='x-large'>" << num << ". </span>";
|
|
q_tab_number.set_markup(ss.str());
|
|
}
|
|
|
|
void QueueTab :: on_tab_reordered()
|
|
{
|
|
queue_set_number(tab_page_num());
|
|
}
|
|
|
|
void QueueTab :: on_move_queue(int num)
|
|
{
|
|
deck :: move(tab_pq, num);
|
|
}
|
|
|
|
void QueueTab :: queue_set_sensitive(bool sensitive)
|
|
{
|
|
q_tab_number.set_sensitive(sensitive);
|
|
q_tab_size.set_sensitive(sensitive);
|
|
q_treeview.set_sensitive(sensitive);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
*
|
|
* Gtk-MM Callback Functions
|
|
*
|
|
*/
|
|
|
|
void QueueTab :: on_close_clicked()
|
|
{
|
|
deck :: destroy(tab_pq);
|
|
}
|
|
|
|
void QueueTab :: on_switch_changed()
|
|
{
|
|
if (q_switch.get_active()) {
|
|
tab_pq->set_flag(Q_ENABLED);
|
|
queue_set_sensitive(true);
|
|
} else {
|
|
tab_pq->unset_flag(Q_ENABLED);
|
|
queue_set_sensitive(false);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
*
|
|
* Global functions
|
|
*
|
|
*/
|
|
static void renumber_queues()
|
|
{
|
|
std::map<Gtk::Widget *, QueueTab *>::iterator it;
|
|
for (it = queue_mapping.begin(); it != queue_mapping.end(); it++)
|
|
it->second->on_tab_reordered();
|
|
}
|
|
|
|
void on_pq_created(Queue *pq, unsigned int num)
|
|
{
|
|
QueueTab *tab = new QueueTab(pq, num);
|
|
tab->on_post_init();
|
|
}
|
|
|
|
static void on_pq_removed(Queue *pq)
|
|
{
|
|
Tab *tab = find_tab(pq);
|
|
if (tab) {
|
|
delete tab;
|
|
renumber_queues();
|
|
}
|
|
}
|
|
|
|
static void on_page_reordered(Gtk::Widget *page, int num)
|
|
{
|
|
Gtk::Notebook *notebook = gui :: get_widget<Gtk::Notebook>("o_notebook");
|
|
|
|
if ((unsigned int)num >= deck :: get_queues().size()) {
|
|
notebook->reorder_child(*page, deck::get_queues().size() - 1);
|
|
return;
|
|
}
|
|
|
|
std::map<Gtk::Widget *, QueueTab *>::iterator it;
|
|
it = queue_mapping.find(page);
|
|
if (it != queue_mapping.end()) {
|
|
it->second->on_move_queue(num);
|
|
renumber_queues();
|
|
}
|
|
}
|
|
|
|
void init_queue_tabs()
|
|
{
|
|
struct Callbacks *cb = get_callbacks();
|
|
cb->on_pq_removed = on_pq_removed;
|
|
|
|
Gtk::Notebook *notebook = gui :: get_widget<Gtk::Notebook>("o_notebook");
|
|
notebook->signal_page_reordered().connect(sigc::ptr_fun(on_page_reordered));
|
|
}
|
|
|
|
void post_init_queue_tabs()
|
|
{
|
|
std::list<TempQueue>::iterator it;
|
|
unsigned int i = 0;
|
|
|
|
for (it = deck :: get_queues().begin(); it != deck :: get_queues().end(); it++)
|
|
on_pq_created(&(*it), i++);
|
|
}
|