/* * Copyright 2014 (c) Anna Schumaker. */ #include #include #include #include #include #include #include #include #include #include #include #include class OcarinaPage; static std::map tab_map; static std::list tab_types; static unsigned int sort_timeout_count = 0; static class SidebarColumns : public Gtk::TreeModelColumnRecord { public: SidebarColumns() { add(sb_col_name); } Gtk::TreeModelColumn sb_col_name; } sb_cols; 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 q_col_track; Gtk::TreeModelColumn q_col_title; Gtk::TreeModelColumn q_col_length; Gtk::TreeModelColumn q_col_artist; Gtk::TreeModelColumn q_col_album; Gtk::TreeModelColumn q_col_year; Gtk::TreeModelColumn q_col_genre; Gtk::TreeModelColumn q_col_count; Gtk::TreeModelColumn q_col_played; Gtk::TreeModelColumn q_col_path; } queue_cols; static unsigned int q_col_width[] = { 20, 300, 60, 100, 100, 45, 100, 60, 1 }; static sort_t q_col_sorts[] = { SORT_TRACK, SORT_TITLE, SORT_LENGTH, SORT_ARTIST, SORT_ALBUM, SORT_YEAR, SORT_GENRE, SORT_COUNT, SORT_PLAYED }; static void dec_sort_timeout() { if (sort_timeout_count > 0) sort_timeout_count--; if (sort_timeout_count == 0) { Gtk::Label *label; get_builder()->get_widget("o_sorting_indicator", label); label->set_text(""); } } static Gtk::Widget *get_menu_widget(const std::string &name) { Gtk::Widget *widget; get_builder()->get_widget(name, widget); return widget; } static void prepare_rc_menu() { unsigned int size = deck::size(); /* Set widgets visible */ switch (size) { case 10: get_menu_widget("o_pq_9")->show(); case 9: get_menu_widget("o_pq_8")->show(); case 8: get_menu_widget("o_pq_7")->show(); case 7: get_menu_widget("o_pq_6")->show(); case 6: get_menu_widget("o_pq_5")->show(); case 5: get_menu_widget("o_pq_4")->show(); case 4: get_menu_widget("o_pq_3")->show(); case 3: get_menu_widget("o_pq_2")->show(); case 2: get_menu_widget("o_pq_1")->show(); case 1: get_menu_widget("o_pq_0")->show(); get_menu_widget("o_add_to_pq")->show(); default: if (size != 10) get_menu_widget("o_new_pq")->show(); break; } /* Set widgets invisible */ switch (size) { case 0: get_menu_widget("o_add_to_pq")->hide(); get_menu_widget("o_pq_0")->hide(); case 1: get_menu_widget("o_pq_1")->hide(); case 2: get_menu_widget("o_pq_2")->hide(); case 3: get_menu_widget("o_pq_3")->hide(); case 4: get_menu_widget("o_pq_4")->hide(); case 5: get_menu_widget("o_pq_5")->hide(); case 6: get_menu_widget("o_pq_6")->hide(); case 7: get_menu_widget("o_pq_7")->hide(); case 8: get_menu_widget("o_pq_8")->hide(); case 9: get_menu_widget("o_pq_9")->hide(); break; case 10: get_menu_widget("o_new_pq")->hide(); }; } /* * Tab class definition */ class OcarinaTab : public Gtk::HBox { public: OcarinaTab(); ~OcarinaTab(); virtual void set_size(unsigned int) = 0; virtual void set_number(unsigned int) = 0; }; OcarinaTab::OcarinaTab() {} OcarinaTab::~OcarinaTab() {} class PresetTab : public OcarinaTab { public: Gtk::Label name_label; Gtk::Label size_label; Gtk::Image tab_icon; Gtk::VBox box; PresetTab(const std::string &, const std::string &); ~PresetTab(); void set_size(unsigned int); void set_number(unsigned int); }; PresetTab::PresetTab(const std::string &name, const std::string &icon) : name_label("" + name + "", 0.5, 0.5), size_label("0", 0.5, 0.5) { tab_icon.set_from_icon_name(icon, Gtk::ICON_SIZE_MENU); tab_icon.set_alignment(0, 0.5); name_label.set_use_markup(); name_label.set_margin_right(1); name_label.set_justify(Gtk::JUSTIFY_CENTER); size_label.set_justify(Gtk::JUSTIFY_CENTER); set_spacing(5); box.pack_start(name_label); box.pack_start(size_label); pack_start(tab_icon); pack_start(box); show_all(); } PresetTab::~PresetTab() {} void PresetTab::set_number(unsigned int num) {} void PresetTab::set_size(unsigned int size) { std::stringstream ss; ss << size; size_label.set_text(ss.str()); } class PQTab : public OcarinaTab { public: Gtk::Label number_label; Gtk::Label size_label; Gtk::Image close_icon; Gtk::Button close_button; PQTab(); ~PQTab(); void set_size(unsigned int); void set_number(unsigned int); }; PQTab::PQTab() : number_label("0", 0, 0.5), size_label("0", 0.5, 0.5) { close_icon.set_from_icon_name("window-close", Gtk::ICON_SIZE_MENU); close_button.set_image(close_icon); close_button.set_relief(Gtk::RELIEF_NONE); number_label.set_justify(Gtk::JUSTIFY_CENTER); pack_start(number_label, false, false); pack_start(size_label, true, true); pack_start(close_button, false, false); show_all(); } PQTab::~PQTab() {} void PQTab::set_size(unsigned int size) { std::stringstream ss; ss << "" << size << ""; size_label.set_markup(ss.str()); } void PQTab::set_number(unsigned int num) { std::stringstream ss; ss << "" << num << ". "; number_label.set_markup(ss.str()); } class ManagerTab : public OcarinaTab { public: Gtk::Label name_label; Gtk::Image tab_icon; ManagerTab(const std::string &, const std::string &); ~ManagerTab(); void set_size(unsigned int); void set_number(unsigned int); }; ManagerTab::ManagerTab(const std::string &name, const std::string &icon) : name_label(name, 0.5, 0.5) { name_label.set_justify(Gtk::JUSTIFY_CENTER); tab_icon.set_from_icon_name(icon, Gtk::ICON_SIZE_MENU); tab_icon.set_alignment(0, 0.5); set_spacing(5); pack_start(tab_icon); pack_start(name_label); show_all(); } ManagerTab::~ManagerTab() {} void ManagerTab::set_size(unsigned int) {} void ManagerTab::set_number(unsigned int) {} /* * Ocarina class definition */ class OcarinaPage : public Gtk::VBox { private: unsigned int init_flags; Gtk::Notebook *notebook; OcarinaTab *tab; /* Filter state */ std::set visible_ids; /* Page widgets */ Gtk::HBox page_toolbar; Gtk::SearchEntry page_entry; Gtk::ToggleButton page_repeat; Gtk::ScrolledWindow page_scroll; Gtk::HBox page_viewbox; Gtk::TreeView page_view; /* Sidebar widgets */ Glib::RefPtr sb_store; Gtk::TreeView sb_view; Gtk::ScrolledWindow sb_scroll; void setup_common(Playqueue *, unsigned int, bool); void setup_toolbar(); void setup_sidebar(); void setup_treeview(); void setup_columns(); void set_tab_size(); public: Gtk::ToggleButton page_random; Glib::RefPtr model; Glib::RefPtr filter; OcarinaPage(const std::string &, const std::string &, Playqueue *, unsigned int); OcarinaPage(Playqueue *, unsigned int, unsigned int); OcarinaPage(const std::string &, const std::string &, Playqueue *); ~OcarinaPage(); bool is_current_tab(); void check_pq_flags(); void queue_selected(bool); void on_close_clicked(); void on_row_inserted(unsigned int); void on_row_deleted(unsigned int); void on_row_changed(unsigned int); void on_runtime_changed(); void on_random_toggled(); void on_repeat_toggled(); void on_row_activated(const Gtk::TreePath &, Gtk::TreeViewColumn *); void on_column_clicked(unsigned int); void on_entry_changed(); bool on_entry_key_released(GdkEventKey *); bool on_filter_visible(const Gtk::TreeIter &); void on_page_renumbered(); bool on_add_to_pq(unsigned int); bool on_delete_selected(); bool on_favorite_selected(); bool on_view_key_pressed(GdkEventKey *); void on_sidebar_cursor_changed(); bool on_sidebar_clicked(GdkEventButton *); bool on_view_button_pressed(GdkEventButton *); void on_focus_search(); }; OcarinaPage::OcarinaPage(const std::string &name, const std::string &icon, Playqueue *pq, unsigned int flags) : init_flags(flags) { tab = new PresetTab(name, icon); setup_common(pq, 0, false); } OcarinaPage::OcarinaPage(Playqueue *pq, unsigned int flags, unsigned int pg) : init_flags(flags) { PQTab *pqt = new PQTab(); tab = pqt; pqt->close_button.signal_clicked().connect(sigc::mem_fun(*this, &OcarinaPage::on_close_clicked)); setup_common(pq, pg, false); notebook->set_tab_reorderable(*this); } OcarinaPage::OcarinaPage(const std::string &name, const std::string &icon, Playqueue *pq) : init_flags(0) { ManagerTab *man_tab = new ManagerTab(name, icon); tab = man_tab; setup_common(pq, 0, true); } OcarinaPage::~OcarinaPage() { notebook->remove_page(*this); tab_map.erase(model->queue); } void OcarinaPage::setup_common(Playqueue *pq, unsigned int pg, bool sidebar) { get_builder()->get_widget("o_notebook", notebook); model = Glib::RefPtr(new PlayqueueModel(pq)); filter = Gtk::TreeModelFilter::create(model); filter->set_visible_func(sigc::mem_fun(*this, &OcarinaPage::on_filter_visible)); set_margin_left(1); set_margin_right(1); set_spacing(1); setup_toolbar(); if (sidebar == true) setup_sidebar(); setup_treeview(); pack_start(page_viewbox); show_all(); /* Add to notebook */ notebook->insert_page(*this, *tab, pg); tab_map[pq] = this; set_tab_size(); } void OcarinaPage::setup_toolbar() { page_toolbar.set_spacing(5); page_toolbar.pack_start(page_entry); page_toolbar.set_margin_left(5); page_toolbar.set_margin_right(5); /* Set up entry */ page_entry.set_margin_top(5); page_entry.set_margin_bottom(5); page_entry.signal_changed().connect(sigc::mem_fun(*this, &OcarinaPage::on_entry_changed)); page_entry.signal_key_release_event().connect(sigc::mem_fun(*this, &OcarinaPage::on_entry_key_released)); /* Make buttons */ if (init_flags & PQ_RANDOM) { page_random.set_image_from_icon_name("media-playlist-shuffle"); page_toolbar.pack_start(page_random, false, false); } if (init_flags & PQ_REPEAT) { page_repeat.set_image_from_icon_name("media-playlist-repeat"); page_toolbar.pack_start(page_repeat, false, false); } pack_start(page_toolbar, false, false); } void OcarinaPage::setup_sidebar() { Gtk::TreeModel::Row row; sb_store = Gtk::ListStore::create(sb_cols); sb_view.append_column("Playlists", sb_cols.sb_col_name); sb_view.set_model(sb_store); sb_view.get_selection()->set_mode(Gtk::SELECTION_BROWSE); sb_view.signal_cursor_changed().connect(sigc::mem_fun(*this, &OcarinaPage::on_sidebar_cursor_changed)); sb_view.signal_button_press_event().connect(sigc::mem_fun(*this, &OcarinaPage::on_sidebar_clicked), false); row = *(sb_store->append()); row[sb_cols.sb_col_name] = "Favorites"; row = *(sb_store->append()); row[sb_cols.sb_col_name] = "Banned"; sb_view.set_cursor(Gtk::TreePath("0")); sb_scroll.set_shadow_type(Gtk::SHADOW_IN); sb_scroll.set_margin_left(5); sb_scroll.set_margin_bottom(5); sb_scroll.add(sb_view); page_viewbox.pack_start(sb_scroll, false, false); } void OcarinaPage::setup_treeview() { /* Make page content */ page_view.append_column("#", queue_cols.q_col_track); page_view.append_column("Title", queue_cols.q_col_title); page_view.append_column("Length", queue_cols.q_col_length); page_view.append_column("Artist", queue_cols.q_col_artist); page_view.append_column("Album", queue_cols.q_col_album); page_view.append_column("Year", queue_cols.q_col_year); page_view.append_column("Genre", queue_cols.q_col_genre); page_view.append_column("Count", queue_cols.q_col_count); page_view.append_column("Played", queue_cols.q_col_played); page_view.set_tooltip_column(9); page_view.signal_row_activated().connect(sigc::mem_fun(*this, &OcarinaPage::on_row_activated)); page_view.signal_key_press_event().connect(sigc::mem_fun(*this, &OcarinaPage::on_view_key_pressed)); page_view.signal_button_press_event().connect(sigc::mem_fun(*this, &OcarinaPage::on_view_button_pressed), false); page_view.set_model(filter); page_view.set_rules_hint(); page_view.set_enable_search(false); page_view.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); page_view.set_rubber_banding(); page_scroll.set_shadow_type(Gtk::SHADOW_IN); page_scroll.set_margin_left(5); page_scroll.set_margin_right(5); page_scroll.set_margin_bottom(5); page_scroll.add(page_view); setup_columns(); page_viewbox.pack_start(page_scroll, true, true); }; void OcarinaPage::setup_columns() { std::vector columns = page_view.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(); columns[i]->signal_clicked().connect(sigc::bind ( sigc::mem_fun(*this, &OcarinaPage::on_column_clicked), i)); } } bool OcarinaPage::is_current_tab() { return notebook->page_num(*this) == notebook->get_current_page(); } void OcarinaPage::check_pq_flags() { if (init_flags & PQ_RANDOM) { page_random.set_active(model->queue->get_flags() & PQ_RANDOM); page_random.signal_toggled().connect(sigc::mem_fun(*this, &OcarinaPage::on_random_toggled)); } if (init_flags & PQ_REPEAT) { page_repeat.set_active(model->queue->get_flags() & PQ_REPEAT); page_repeat.signal_toggled().connect(sigc::mem_fun(*this, &OcarinaPage::on_repeat_toggled)); } } void OcarinaPage::set_tab_size() { tab->set_size(model->queue->size()); } void OcarinaPage::queue_selected(bool random) { Playqueue *pq; unsigned int track_id; std::vector::iterator it; Glib::RefPtr sel = page_view.get_selection(); if (sel->count_selected_rows() == 0) return; pq = deck::create(random); std::vector rows = sel->get_selected_rows(); for (it = rows.begin(); it != rows.end(); it++) { track_id = model->path_to_id(filter->convert_path_to_child_path(*it)); pq->add(track_id); } } void OcarinaPage::on_close_clicked() { deck :: remove(notebook->page_num(*this)); } void OcarinaPage::on_row_inserted(unsigned int row) { model->on_row_inserted(row); set_tab_size(); if (is_current_tab()) on_runtime_changed(); } void OcarinaPage::on_row_deleted(unsigned int row) { model->on_row_deleted(row); set_tab_size(); if (is_current_tab()) on_runtime_changed(); } void OcarinaPage::on_row_changed(unsigned int row) { model->on_row_changed(row); if (is_current_tab()) on_runtime_changed(); } void OcarinaPage::on_runtime_changed() { Gtk::Label *label; get_builder()->get_widget("o_queue_time", label); label->set_text(model->queue->get_length_str()); } void OcarinaPage::on_random_toggled() { if (page_random.get_active()) model->queue->set_flag(PQ_RANDOM); else model->queue->unset_flag(PQ_RANDOM); } void OcarinaPage::on_repeat_toggled() { if (page_repeat.get_active()) model->queue->set_flag(PQ_REPEAT); else model->queue->unset_flag(PQ_REPEAT); } void OcarinaPage::on_row_activated(const Gtk::TreePath &path, Gtk::TreeViewColumn *col) { Gtk::TreePath model_path = filter->convert_path_to_child_path(path); model->on_path_selected(model_path); } void OcarinaPage::on_column_clicked(unsigned int col_index) { Gtk::Label *sorting; get_builder()->get_widget("o_sorting_indicator", sorting); if (sort_timeout_count == 0) { sorting->set_text("Sorting within " + page_view.get_column(col_index)->get_title()); model->queue->reset_sort(q_col_sorts[col_index]); } else model->queue->add_sort(q_col_sorts[col_index]); sort_timeout_count++; Glib::signal_timeout().connect_seconds_once( sigc::ptr_fun(dec_sort_timeout), 2); } void OcarinaPage::on_entry_changed() { filter :: search(page_entry.get_text(), visible_ids); filter->refilter(); } bool OcarinaPage::on_entry_key_released(GdkEventKey *event) { std::string key = gdk_keyval_name(event->keyval); return key == "space"; } bool OcarinaPage::on_filter_visible(const Gtk::TreeIter &iter) { unsigned int pq_id; std::set::iterator it; if (page_entry.get_text().size() == 0) return true; pq_id = model->iter_to_id(iter); return visible_ids.find(model->queue->operator[](pq_id)) != visible_ids.end(); } void OcarinaPage::on_page_renumbered() { tab->set_number(notebook->page_num(*this)); } bool OcarinaPage::on_add_to_pq(unsigned int n) { if (n >= deck :: size()) return true; Glib::RefPtr sel = page_view.get_selection(); if (sel->count_selected_rows() == 0) return true; Playqueue *pq = deck :: get(n); std::vector::iterator it; std::vector rows = sel->get_selected_rows(); for (it = rows.begin(); it != rows.end(); it++) { unsigned int track_id = model->path_to_id(filter->convert_path_to_child_path(*it)); pq->add(track_id); } return true; } bool OcarinaPage::on_delete_selected() { Glib::RefPtr sel = page_view.get_selection(); if (sel->count_selected_rows() == 0) return true; if ((unsigned int)notebook->page_num(*this) >= deck :: size()) return true; std::vector::reverse_iterator it; std::vector rows = sel->get_selected_rows(); for (it = rows.rbegin(); it != rows.rend(); it++) { unsigned int id = filter->convert_path_to_child_path(*it)[0]; model->queue->del(id); } return true; } bool OcarinaPage::on_favorite_selected() { Glib::RefPtr sel = page_view.get_selection(); if (sel->count_selected_rows() == 0) return true; std::vector::iterator it; std::vector rows = sel->get_selected_rows(); for (it = rows.begin(); it != rows.end(); it++) { unsigned int id = model->path_to_id(filter->convert_path_to_child_path(*it)); playlist :: add("Favorites", id); } return true; } bool OcarinaPage::on_view_key_pressed(GdkEventKey *event) { 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()); return on_add_to_pq(n); } else if (key == "f") return on_favorite_selected(); else if (key == "Delete") return on_delete_selected(); return false; } void OcarinaPage::on_sidebar_cursor_changed() { Gtk::TreePath path; Gtk::TreeViewColumn *col; sb_view.get_cursor(path, col); Gtk::TreeModel::Row row = *(sb_store->get_iter(path)); playlist :: select(row[sb_cols.sb_col_name]); } bool OcarinaPage::on_sidebar_clicked(GdkEventButton *button) { if (button->button != 3) return false; return true; } bool OcarinaPage::on_view_button_pressed(GdkEventButton *button) { Gtk::Menu *menu; get_builder()->get_widget("o_rc_menu", menu); if (button->button != 3) return false; prepare_rc_menu(); menu->popup(button->button, button->time); return true; } void OcarinaPage::on_focus_search() { page_entry.grab_focus(); } /* * Do stuff with tabs */ static TabFuncs *find_tab_funcs(Playqueue *pq) { std::list::iterator tab_it; for (tab_it = tab_types.begin(); tab_it != tab_types.end(); tab_it++) { if ((*tab_it)->has_queue(pq)) return *tab_it; } return NULL; } static void on_track_added(Playqueue *pq, unsigned int row) { std::map::iterator it; it = tab_map.find(pq); if (it != tab_map.end()) it->second->on_row_inserted(row); struct TabFuncs *tab; tab = find_tab_funcs(pq); if (tab) tab->track_added(pq, row); } static void on_track_deleted(Playqueue *pq, unsigned int row) { std::map::iterator it; it = tab_map.find(pq); if (it != tab_map.end()) it->second->on_row_deleted(row); struct TabFuncs *tab; tab = find_tab_funcs(pq); if (tab) tab->track_deleted(pq, row); } static void on_track_changed(Playqueue *pq, unsigned int row) { std::map::iterator it; it = tab_map.find(pq); if (it != tab_map.end()) it->second->on_row_changed(row); } static void on_switch_page(Gtk::Widget *page, int num) { Gtk::Label *label; Gtk::Notebook *notebook; OcarinaPage *tab = (OcarinaPage *)page; get_builder()->get_widget("o_queue_time", label); get_builder()->get_widget("o_notebook", notebook); if (num >= notebook->get_n_pages() - 4) label->hide(); else { tab->on_runtime_changed(); label->show(); } sort_timeout_count = 0; } static void renumber_pqs() { std::map::iterator it; for (it = tab_map.begin(); it != tab_map.end(); it++) it->second->on_page_renumbered(); } static void on_page_reordered(Gtk::Widget *page, int num) { Gtk::Notebook *notebook; OcarinaPage *tab = (OcarinaPage *)page; get_builder()->get_widget("o_notebook", notebook); if ((unsigned int)num >= deck :: size()) notebook->reorder_child(*page, deck::size() - 1); else { deck :: move(tab->model->queue, num); renumber_pqs(); } } static void on_pq_created(Playqueue *pq, unsigned int num) { OcarinaPage *page = new OcarinaPage(pq, PQ_RANDOM | PQ_REPEAT, num); page->check_pq_flags(); renumber_pqs(); } static void on_pq_removed(Playqueue *pq) { std::map::iterator it; it = tab_map.find(pq); if (it != tab_map.end()) delete it->second; renumber_pqs(); } void queue_selected(bool random) { std::map::iterator it; if (deck :: size() >= 10) return; for (it = tab_map.begin(); it != tab_map.end(); it++) { if (it->second->is_current_tab()) { it->second->queue_selected(random); return; } } } /*static void on_new_queue() { queue_selected(false); } static void on_add_to_queue(unsigned int num) { std::map::iterator it; for (it = tab_map.begin(); it != tab_map.end(); it++) { if (it->second->is_current_tab()) { it->second->on_add_to_pq(num); return; } } } static void init_menu_item(const std::string &name, unsigned int num) { Glib::RefPtrmenu = Glib::RefPtr::cast_static(get_builder()->get_object(name)); menu->signal_activate().connect(sigc::bind ( sigc::ptr_fun(on_add_to_queue), num)); }*/ void focus_tab_search() { std::map::iterator it; for (it = tab_map.begin(); it != tab_map.end(); it++) { if (it->second->is_current_tab()) { it->second->on_focus_search(); return; } } } void init_tabs() { Gtk::Notebook *notebook; get_builder()->get_widget("o_notebook", notebook); new OcarinaPage("Playlist\nManager", "emblem-documents", playlist::get_pq()); new OcarinaPage("History", "document-open-recent", audio::get_recent_pq(), 0); new OcarinaPage("Collection", "media-optical", deck::get_library_pq(), PQ_RANDOM); get_callbacks()->on_pq_created = on_pq_created; get_callbacks()->on_pq_removed = on_pq_removed; get_callbacks()->on_queue_track_add = on_track_added; get_callbacks()->on_queue_track_del = on_track_deleted; get_callbacks()->on_queue_track_changed = on_track_changed; /*Glib::RefPtr new_pq = Glib::RefPtr::cast_static(get_builder()->get_object("o_new_pq")); new_pq->signal_activate().connect(sigc::ptr_fun(on_new_queue)); init_menu_item("o_pq_0", 0); init_menu_item("o_pq_1", 1); init_menu_item("o_pq_2", 2); init_menu_item("o_pq_3", 3); init_menu_item("o_pq_4", 4); init_menu_item("o_pq_5", 5); init_menu_item("o_pq_6", 6); init_menu_item("o_pq_7", 7); init_menu_item("o_pq_8", 8); init_menu_item("o_pq_9", 9);*/ tab_types.push_back(init_collection_tab()); tab_types.push_back(init_history_tab()); tab_types.push_back(init_playlist_tab()); notebook->signal_switch_page().connect(sigc::ptr_fun(on_switch_page)); notebook->signal_page_reordered().connect(sigc::ptr_fun(on_page_reordered)); notebook->set_current_page(0); } void init_tabs2() { std::map::iterator it; for (it = tab_map.begin(); it != tab_map.end(); it++) it->second->check_pq_flags(); std::list::iterator tab_it; for (tab_it = tab_types.begin(); tab_it != tab_types.end(); tab_it++) (*tab_it)->init_late(); } void cleanup_tabs() { while (tab_map.size() > 0) delete tab_map.begin()->second; std::list::iterator it; for (it = tab_types.begin(); it != tab_types.end(); it++) (*it)->cleanup(); }