/* * Copyright 2014 (c) Anna Schumaker. */ extern "C" { #include #include #include #include #include #include #include } #include #include #include static std::map queue_mapping; static compare_t sort_fields[] = { COMPARE_TRACK, COMPARE_TITLE, COMPARE_LENGTH, COMPARE_ARTIST, COMPARE_ALBUM, COMPARE_YEAR, COMPARE_GENRE, COMPARE_COUNT, COMPARE_PLAYED }; static void *tempq_init(struct queue *queue) { struct gui_queue *gq = gui_queue_alloc(queue, "Queued Tracks", GQ_CAN_RANDOM | GQ_CAN_REPEAT | GQ_CAN_DISABLE); queue->q_private = gq; on_pq_created(queue, tempq_index(queue)); gui_sidebar_add(gq); return gq; } static void tempq_added(struct queue *queue, unsigned int pos) { Tab *tab = find_tab(queue); if (tab) { tab->on_track_added(pos); tempq_save(queue, Q_ENABLED); } gui_queue_added(queue, pos); } static bool tempq_erase(struct queue *queue, struct track *track) { return true; } static void tempq_removed(struct queue *queue, unsigned int pos) { find_tab(queue)->on_track_removed(pos); tempq_save(queue, Q_ENABLED); gui_queue_removed(queue, pos); } struct queue_ops tempq_ops = { tempq_init, gui_queue_free, tempq_added, tempq_erase, tempq_removed, gui_queue_cleared, tempq_save, gui_queue_updated, }; /** * * Tab class basics * */ Tab :: Tab(queue *pq) : tab_sorting_count(0), tab_pq(pq), tab_label(NULL) { queue_mapping[tab_pq] = this; tab_builder = Gtk::Builder::create(); tab_builder->add_from_file(gui :: share_file("QueueWindow.ui")); tab_builder->get_widget_derived("QueueWindow", tab_window); tab_window->init(tab_pq); for (unsigned int i = 0; i < tab_window->q_treeview->get_n_columns(); i++) tab_window->q_treeview->get_column(i)->signal_clicked().connect( sigc::bind (sigc::mem_fun( *this, &Tab::on_column_clicked), i)); tab_vbox.set_margin_start(1); tab_vbox.set_margin_end(1); tab_vbox.set_homogeneous(false); tab_vbox.show(); } Tab :: ~Tab() {} /** * * QNotifier implementation. * */ void Tab :: on_track_added(unsigned int row) { tab_label->set_size(); } void Tab :: on_track_removed(unsigned int row) { tab_label->set_size(); } /** * * Tab internal helper functions * */ int Tab :: tab_page_num() { Gtk::Notebook *notebook = Glib :: wrap(GTK_NOTEBOOK(gui_builder_widget("o_notebook")), false); return notebook->page_num(tab_vbox); } bool Tab :: tab_is_cur() { Gtk::Notebook *notebook = Glib :: wrap(GTK_NOTEBOOK(gui_builder_widget("o_notebook")), false); return notebook->page_num(tab_vbox) == notebook->get_current_page(); } void Tab :: tab_display_sorting() { std::string text = ""; if ((tab_sorting_count > 0) && tab_is_cur()) text = "Sorting within " + tab_sorting_title; Glib :: wrap(GTK_LABEL(gui_builder_widget("o_sorting_indicator")), false)->set_text(text); } void Tab :: tab_dec_sort_count() { tab_sorting_count--; tab_display_sorting(); } void Tab :: tab_unmap() { queue_mapping.erase(tab_pq); } /** * * GTK-MM callback functions * */ void Tab :: on_column_clicked(unsigned int col) { if (tab_sorting_count == 0) { tab_sorting_title = tab_window->q_treeview->get_column(col)->get_title(); queue_sort(tab_pq, sort_fields[col], true); } else queue_sort(tab_pq, sort_fields[col], false); tab_sorting_count++; tab_display_sorting(); Glib::signal_timeout().connect_seconds_once( sigc::mem_fun(*this, &Tab::tab_dec_sort_count), 2); } /** * * Global functions * */ Tab *find_tab(queue *pq) { std::map::iterator it; it = queue_mapping.find(pq); if (it != queue_mapping.end()) return it->second; return NULL; } static Tab *find_tab(int num) { std::map::iterator it; for (it = queue_mapping.begin(); it != queue_mapping.end(); it++) { if (it->second->tab_page_num() == num) return it->second; } return NULL; } static void on_switch_page(Gtk::Widget *page, int num) { Tab *tab = find_tab(num); if (tab) { tab->tab_display_sorting(); } else Glib :: wrap(GTK_LABEL(gui_builder_widget("o_queue_time")), false)->set_text(""); } static bool on_window_key_pressed(GdkEventKey *event) { Gtk::Notebook *notebook = Glib :: wrap(GTK_NOTEBOOK(gui_builder_widget("o_notebook")), false); std::string key = gdk_keyval_name(event->keyval); if (key.size() >= 3) { if (key.substr(0, 3) == "KP_") key = key.substr(3); } if (key >= "0" && key <= "9") { unsigned int n = atoi(key.c_str()); if (n < tempq_count()) notebook->set_current_page(n); } else if (key == "c") notebook->set_current_page(tempq_count()); else if (key == "h") notebook->set_current_page(tempq_count() + 1); else if (key == "m") notebook->set_current_page(tempq_count() + 3); else if (key == "p") notebook->set_current_page(tempq_count() + 2); else return false; return true; } void init_tabs() { Gtk::Window *window = Glib :: wrap(GTK_WINDOW(gui_builder_widget("o_window")), false); /* Notebook signals */ 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)); /* Initialize other tabs */ init_history_tab(); init_collection_tab(); init_queue_tabs(); /* Setup keyboard shortcuts */ window->signal_key_press_event().connect(sigc::ptr_fun(on_window_key_pressed)); } void post_init_tabs() { post_init_queue_tabs(); unsigned int tab = 0; for (tab = 0; tab < tempq_count(); tab++) { if (queue_has_flag(tempq_get(tab), Q_ENABLED)) break; } Glib :: wrap(GTK_NOTEBOOK(gui_builder_widget("o_notebook")), false)->set_current_page(tab); } void cleanup_tabs() { while (queue_mapping.size() > 0) delete queue_mapping.begin()->second; }