/* $Id$ */ /* * Cantus Tag Editor * Copyright © 2002-2004 by Samuel Abels * Copyright © 2007 by Tim Huetz * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see **/ #ifdef HAVE_CONFIG_H # include #endif #include //#define _DEBUG_ /* Split a string that is delimited by any of the chars in "delimiters" * into a list. */ static std::list explode(std::string string, const char *delimiters) { std::list strlist; char *buf = NULL; if (string == "") return strlist; char *stringcp = strdup(string.c_str()); std::string str; /* Init strtok. */ if (!(buf = strtok(stringcp, delimiters))) return strlist; str = buf; strlist.push_back(str); /* Split into pieces. */ int i = 0; while ((buf = strtok(NULL, delimiters))) { str = buf; if (str.find_first_not_of(' ') == -1) continue; str = str.substr(str.find_first_not_of(' '), str.find_first_not_of(' ') - str.find_last_not_of(' ')); strlist.push_back(str); } free(stringcp); return(strlist); } /****************************************************************************** * Constructor/Destructor ******************************************************************************/ GenreSelector::GenreSelector(bool allow_multiple) : toplevel(2, 1), button(Gtk::Stock::CLOSE) { select_multiple = allow_multiple; lock_events = FALSE; set_title(_("Cantus - Genre Selector")); toplevel.set_border_width(6); toplevel.set_row_spacing(0, 12); toplevel.attach(scrolled, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); scrolled.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); scrolled.add(genrebox); button.set_size_request(-1, 35); toplevel.attach(button, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL); add(toplevel); set_size_request(200, 350); set_genres(genre); show_all(); button.signal_clicked().connect(signal_button_close_clicked); } GenreSelector::~GenreSelector() { #ifdef _DEBUG_ printf("GenreSelector::~GenreSelector(): Called.\n"); #endif } /****************************************************************************** * Public ******************************************************************************/ /* Defines all genres that are in the list. */ void GenreSelector::set_genres(char **genrelist) { genres.clear(); int i = -1; while (genrelist[++i]) genres[genrelist[i]] = NULL; update(); } /* Updates all genres in the GUI. */ void GenreSelector::update(void) { // Clear the GUI (remove all widgets). Glib::ListHandle list = genrebox.get_children(); Glib::ListHandle::iterator iter = list.begin(); while (iter != list.end()) { genrebox.remove(**iter); delete *iter; iter++; } // Fill the GUI (add widgets). std::map::iterator mapiter = genres.begin(); RadioButtonGroup group; while (mapiter != genres.end()) { CheckButton *check = NULL; if (select_multiple) check = new CheckButton(mapiter->first); else check = new RadioButton(group, mapiter->first); check->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &GenreSelector::on_selection_changed), mapiter->first)); genres[mapiter->first] = check; genrebox.pack_start(*check); mapiter++; } genrebox.show_all(); } /* Clears the genrelist. */ void GenreSelector::clear(void) { genres.clear(); update(); } /* Defines all genres that are selected. */ void GenreSelector::set_selected_genres(std::string genrestring) { #ifdef _DEBUG_ printf("GenreSelector::set_selected_genres(string): %s.\n", genrestring.c_str()); #endif set_selected_genres(explode(genrestring, ",")); } /* Defines all genres that are selected. */ void GenreSelector::set_selected_genres(std::list selectedgenres) { #ifdef _DEBUG_ printf("GenreSelector::set_selected_genres(list): Called.\n"); #endif unselect_all(); list::iterator iter = selectedgenres.begin(); while (iter != selectedgenres.end()) { if (select_genre(*iter) && !select_multiple) return; iter++; } } /* Select the Genre with the given name. Returns TRUE if anything was selected. */ bool GenreSelector::select_genre(string genre) { #ifdef _DEBUG_ printf("GenreSelector::select_genre(): %s.\n", genre.c_str()); #endif selected.push_back(genre); if (genres.find(genre) == genres.end()) return FALSE; lock_events = TRUE; genres[genre]->set_active(); lock_events = FALSE; return TRUE; } /* Unselect all genres. */ void GenreSelector::unselect_all(void) { #ifdef _DEBUG_ printf("GenreSelector::unselect_all(): Called.\n"); #endif lock_events = TRUE; list::iterator iter = selected.begin(); while (iter != selected.end()) { if (genres.find(*iter) != genres.end()) genres[*iter]->set_active(FALSE); iter++; } lock_events = FALSE; selected.clear(); } /* Returns an array containing pointers to all selected genres. */ string GenreSelector::get_selected_genres(void) { #ifdef _DEBUG_ printf("GenreSelector::get_selected_genres(): Called.\n"); #endif list::iterator iter = selected.begin(); string genrestr; if (iter == selected.end()) return ""; genrestr = *iter; iter++; while (iter != selected.end()) { genrestr.append(", "); genrestr.append(*iter); iter++; } return genrestr; } /* Defines whether or not multiple genres can be selected at once. */ void GenreSelector::set_select_multiple(bool allowed) { select_multiple = allowed; update(); } /* Defines whether or not the widgets are sensitive. */ void GenreSelector::set_sensitive(bool allowed) { toplevel.set_sensitive(allowed); } /****************************************************************************** * Private ******************************************************************************/ void GenreSelector::on_selection_changed(std::string genre) { if (lock_events == TRUE) return; #ifdef _DEBUG_ printf("GenreSelector::on_selection_changed(): %s.\n", genre.c_str()); #endif if (genres[genre]->get_active()) selected.push_back(genre); else { std::list::iterator iter = selected.begin(); while (iter != selected.end()) { if (*iter != genre) { iter++; continue; } selected.erase(iter); break; } } signal_selection_changed.emit(selected); }