bool FeFilterEditMenu::save( FeConfigContext &ctx ) { if (( m_display ) && ( m_index >= 0 )) { FeFilter *f = m_display->get_filter( m_index ); std::string name = ctx.opt_list[0].get_value(); f->set_name( name ); int sort_pos = ctx.opt_list.size() - 4; FeRomInfo::Index sort_by = (FeRomInfo::Index)ctx.opt_list[ sort_pos ].get_vindex(); f->set_sort_by( sort_by ); // // TODO - make reverse order configurable from the config menu // // right now we just arbitrarily sort players, playcount and playtime in "reverse" order so // higher values are first. // bool reverse_order( false ); if (( sort_by == FeRomInfo::Players ) || ( sort_by == FeRomInfo::PlayedCount ) || ( sort_by == FeRomInfo::PlayedTime )) reverse_order = true; f->set_reverse_order( reverse_order ); std::string limit_str = ctx.opt_list[ sort_pos + 1 ].get_value(); int list_limit = as_int( limit_str ); f->set_list_limit( list_limit ); } return true; }
bool FeFilterEditMenu::on_option_select( FeConfigContext &ctx, FeBaseConfigMenu *& submenu ) { if ( !m_display ) return true; FeMenuOpt &o = ctx.curr_opt(); FeFilter *f = m_display->get_filter( m_index ); if (( o.opaque >= 100 ) || ( o.opaque == 1 ) || ( o.opaque == 2 )) { int r_index=0; if (( o.opaque == 1 ) || ( o.opaque == 2 )) { bool is_exception = ( o.opaque == 2 ); std::vector<FeRule> &rules = f->get_rules(); rules.push_back( FeRule() ); rules.back().set_is_exception( is_exception ); r_index = rules.size() - 1; ctx.save_req=true; } else r_index = o.opaque - 100; m_rule_menu.set_rule_index( f, r_index ); submenu=&m_rule_menu; } else if ( o.opaque == 3 ) { // "Delete this Filter" if ( ctx.confirm_dialog( "Delete filter '$1'?", f->get_name() ) == false ) return false; m_display->delete_filter( m_index ); m_display=NULL; m_index=-1; ctx.save_req=true; } return true; }
bool FeRomList::fix_filters( FeDisplayInfo &display, FeRomInfo::Index target ) { bool retval = false; for ( int i=0; i<display.get_filter_count(); i++ ) { FeFilter *f = display.get_filter( i ); ASSERT( f ); if ( f->test_for_target( target ) ) { m_filtered_list[i].clear(); retval = true; for ( FeRomInfoListType::iterator itr=m_list.begin(); itr!=m_list.end(); ++itr ) { if ( f->apply_filter( *itr ) ) m_filtered_list[i].push_back( &( *itr ) ); } } } return retval; }
void FeDisplayEditMenu::get_options( FeConfigContext &ctx ) { ctx.set_style( FeConfigContext::EditList, "Display Edit" ); if ( m_display ) { ctx.add_optl( Opt::EDIT, "Name", m_display->get_info( FeDisplayInfo::Name ), "_help_display_name" ); ctx.add_optl( Opt::LIST, "Layout", m_display->get_info( FeDisplayInfo::Layout ), "_help_display_layout" ); std::vector<std::string> layouts; ctx.fe_settings.get_layouts_list( layouts ); ctx.back_opt().append_vlist( layouts ); ctx.add_optl( Opt::LIST, "Collection/Rom List", m_display->get_info( FeDisplayInfo::Romlist ), "_help_display_romlist" ); std::vector<std::string> romlists; ctx.fe_settings.get_romlists_list( romlists ); ctx.back_opt().append_vlist( romlists ); std::vector<std::string> bool_opts( 2 ); ctx.fe_settings.get_resource( "Yes", bool_opts[0] ); ctx.fe_settings.get_resource( "No", bool_opts[1] ); ctx.add_optl( Opt::LIST, "Show in Cycle", m_display->show_in_cycle() ? bool_opts[0] : bool_opts[1], "_help_display_in_cycle" ); ctx.back_opt().append_vlist( bool_opts ); ctx.add_optl( Opt::LIST, "Show in Menu", m_display->show_in_menu() ? bool_opts[0] : bool_opts[1], "_help_display_in_menu" ); ctx.back_opt().append_vlist( bool_opts ); FeFilter *f = m_display->get_filter( -1 ); std::string filter_desc; if ( f->get_rule_count() < 1 ) ctx.fe_settings.get_resource( "Empty", filter_desc ); else ctx.fe_settings.get_resource( "$1 Rule(s)", as_str(f->get_rule_count()), filter_desc ); ctx.add_optl( Opt::SUBMENU, "Global Filter", filter_desc, "_help_display_global_filter" ); ctx.back_opt().opaque = 9; std::vector<std::string> filters; m_display->get_filters_list( filters ); int i=0; for ( std::vector<std::string>::iterator itr=filters.begin(); itr != filters.end(); ++itr ) { ctx.add_optl( Opt::SUBMENU, "Filter", (*itr), "_help_display_filter" ); ctx.back_opt().opaque = 100 + i; i++; } ctx.add_optl( Opt::SUBMENU, "Add Filter", "", "_help_display_add_filter" ); ctx.back_opt().opaque = 1; ctx.add_optl( Opt::SUBMENU, "Layout Options", "", "_help_display_layout_options" ); ctx.back_opt().opaque = 2; ctx.add_optl( Opt::EXIT, "Delete this Display", "", "_help_display_delete" ); ctx.back_opt().opaque = 3; } FeBaseConfigMenu::get_options( ctx ); }
void FeFilterEditMenu::get_options( FeConfigContext &ctx ) { ctx.set_style( FeConfigContext::EditList, "Filter Edit" ); if ( m_display ) { FeFilter *f = m_display->get_filter( m_index ); if ( m_index < 0 ) { std::string gf; ctx.fe_settings.get_resource( "Global Filter", gf ); ctx.add_optl( Opt::INFO, "Filter Name", gf, "_help_filter_name" ); } else { ctx.add_optl( Opt::EDIT, "Filter Name", f->get_name(), "_help_filter_name" ); } int i=0; std::vector<FeRule> &rules = f->get_rules(); for ( std::vector<FeRule>::const_iterator itr=rules.begin(); itr != rules.end(); ++itr ) { std::string rule_str; FeRomInfo::Index t = (*itr).get_target(); if ( t != FeRomInfo::LAST_INDEX ) { ctx.fe_settings.get_resource( FeRomInfo::indexStrings[t], rule_str ); FeRule::FilterComp c = (*itr).get_comp(); if ( c != FeRule::LAST_COMPARISON ) { std::string comp_str; ctx.fe_settings.get_resource( FeRule::filterCompDisplayStrings[c], comp_str ); rule_str += " "; rule_str += comp_str; rule_str += " "; rule_str += (*itr).get_what(); } } if ( (*itr).is_exception() ) ctx.add_optl( Opt::SUBMENU, "Exception", rule_str, "_help_filter_exception" ); else ctx.add_optl( Opt::SUBMENU, "Rule", rule_str, "_help_filter_rule" ); ctx.back_opt().opaque = 100 + i; i++; } ctx.add_optl(Opt::SUBMENU,"Add Rule","","_help_filter_add_rule"); ctx.back_opt().opaque = 1; ctx.add_optl(Opt::SUBMENU,"Add Exception","","_help_filter_add_exception"); ctx.back_opt().opaque = 2; if ( m_index >= 0 ) // don't add the following options for the global filter { std::string no_sort_str, sort_val; ctx.fe_settings.get_resource( "No Sort", no_sort_str ); if ( f->get_sort_by() != FeRomInfo::LAST_INDEX ) sort_val = FeRomInfo::indexStrings[f->get_sort_by()]; else sort_val = no_sort_str; std::vector< std::string > targets; i=0; while ( FeRomInfo::indexStrings[i] != 0 ) { targets.push_back( std::string() ); ctx.fe_settings.get_resource( FeRomInfo::indexStrings[i], targets.back() ); i++; } targets.push_back( no_sort_str ); ctx.add_optl( Opt::LIST, "Sort By", sort_val, "_help_filter_sort_by" ); ctx.back_opt().append_vlist( targets ); ctx.add_optl( Opt::EDIT, "List Limit", as_str( f->get_list_limit() ), "_help_filter_list_limit" ); ctx.add_optl(Opt::EXIT,"Delete this Filter","","_help_filter_delete"); ctx.back_opt().opaque = 3; } } FeBaseConfigMenu::get_options( ctx ); }
bool FeSettings::build_romlist( const std::vector< FeImportTask > &task_list, const std::string &output_name, FeFilter &filter, bool full ) { FeRomInfoListType total_romlist; std::string best_name, list_name, path; for ( std::vector<FeImportTask>::const_iterator itr=task_list.begin(); itr < task_list.end(); ++itr ) { if ( (*itr).task_type == FeImportTask::BuildRomlist ) { // Build romlist task std::cout << "*** Generating Collection/Rom List" << std::endl; FeEmulatorInfo *emu = m_rl.get_emulator( (*itr).emulator_name ); if ( emu == NULL ) { std::cout << "Error: Invalid -build-rom-list target: " << (*itr).emulator_name << std::endl; } else { FeRomInfoListType romlist; best_name = emu->get_info( FeEmulatorInfo::Name ); FeImporterContext ctx( *emu, romlist ); build_basic_romlist( ctx ); apply_xml_import( ctx ); apply_import_extras( ctx ); apply_emulator_name( best_name, romlist ); total_romlist.splice( total_romlist.end(), romlist ); } } else if ( (*itr).task_type == FeImportTask::ImportRomlist ) { // import romlist from file task std::cout << "*** Importing Collection/Rom List" << std::endl; FeRomInfoListType romlist; std::string emu_name; if ( (*itr).emulator_name.empty() ) { // deduce the emulator name from the filename provided size_t my_start = (*itr).file_name.find_last_of( "\\/" ); if ( my_start == std::string::npos ) // if there is no / we start at the beginning my_start = 0; else my_start += 1; size_t my_end = (*itr).file_name.find_last_of( "." ); if ( my_end != std::string::npos ) emu_name = (*itr).file_name.substr( my_start, my_end - my_start ); } else emu_name = (*itr).emulator_name; best_name = emu_name; if ( tail_compare( (*itr).file_name, ".txt" ) ) { // Attract-Mode format list // FeRomList temp_list( m_config_path ); temp_list.load_from_file( (*itr).file_name, ";" ); FeRomInfoListType &entries = temp_list.get_list(); for ( FeRomInfoListType::iterator itr = entries.begin(); itr != entries.end(); ++itr ) romlist.push_back( *itr ); } else if ( tail_compare( (*itr).file_name, ".lst" ) ) { // Mamewah/Wahcade! format list // import_mamewah( (*itr).file_name, emu_name, romlist ); } else if ( tail_compare( (*itr).file_name, ".xml" ) ) { // HyperSpin format list // FeHyperSpinXMLParser my_parser( romlist ); if ( my_parser.parse( (*itr).file_name ) ) apply_emulator_name( emu_name, romlist ); } else { std::cerr << "Error: Unsupported --import-rom-list file: " << (*itr).file_name << std::endl; } std::cout << "[Import " << (*itr).file_name << "] - Imported " << romlist.size() << " entries." << std::endl; FeEmulatorInfo *emu = m_rl.get_emulator( emu_name ); if ( emu == NULL ) { std::cout << "Warning: The emulator specified with --import-rom-list was not found: " << emu_name << std::endl; } else { FeImporterContext ctx( *emu, romlist ); apply_import_extras( ctx ); } total_romlist.splice( total_romlist.end(), romlist ); } else // scrape artwork { FeEmulatorInfo *emu = m_rl.get_emulator( (*itr).emulator_name ); if ( emu == NULL ) return false; std::cout << "*** Scraping artwork for: " << (*itr).emulator_name << std::endl; FeRomInfoListType romlist; std::string fn = get_config_dir() + FE_ROMLIST_SUBDIR + (*itr).emulator_name + FE_ROMLIST_FILE_EXTENSION; FeImporterContext ctx( *emu, romlist ); if ( file_exists( fn ) ) { FeRomList loader( get_config_dir() ); loader.load_from_file( fn, ";" ); ctx.romlist.swap( loader.get_list() ); } else { build_basic_romlist( ctx ); apply_xml_import( ctx ); } ctx.scrape_art = true; confirm_directory( get_config_dir(), FE_SCRAPER_SUBDIR ); // do the mamedb scraper first (which only does anything for mame) followed // by the more general thegamesdb scraper. mamedb_scraper( ctx ); thegamesdb_scraper( ctx ); std::cout << "*** Scraping done." << std::endl; } } // return now if all we did was scrape artwork if ( total_romlist.empty() ) return true; total_romlist.sort( FeRomListSorter() ); // strip duplicate entries std::cout << " - Removing any duplicate entries..." << std::endl; total_romlist.unique(); // Apply the specified filter if ( filter.get_rule_count() > 0 ) { std::cout << " - Applying filter..." << std::endl; filter.init(); FeRomInfoListType::iterator last_it=total_romlist.begin(); for ( FeRomInfoListType::iterator it=total_romlist.begin(); it!=total_romlist.end(); ) { if ( filter.apply_filter( *it ) ) { if ( last_it != it ) it = total_romlist.erase( last_it, it ); else ++it; last_it = it; } else ++it; } if ( last_it != total_romlist.end() ) total_romlist.erase( last_it, total_romlist.end() ); } if ( task_list.size() > 1 ) best_name = "multi"; path = get_config_dir(); confirm_directory( path, FE_ROMLIST_SUBDIR ); path += FE_ROMLIST_SUBDIR; // if we weren't given a specific output name, then we come up with a name // that doesn't exist already // if ( output_name.empty() ) get_available_filename( path, best_name, FE_ROMLIST_FILE_EXTENSION, list_name ); else list_name = path + output_name + FE_ROMLIST_FILE_EXTENSION; write_romlist( list_name, total_romlist ); return true; }
bool FeRomList::load_romlist( const std::string &path, const std::string &romlist_name, const std::string &user_path, const std::string &stat_path, FeDisplayInfo &display ) { m_user_path = user_path; m_romlist_name = romlist_name; m_list.clear(); m_filtered_list.clear(); m_availability_checked = false; m_global_filter_ptr = NULL; m_global_filtered_out_count = 0; FeFilter *first_filter = display.get_global_filter(); if ( first_filter ) { first_filter->init(); if ( !first_filter->test_for_target( FeRomInfo::FileIsAvailable ) && !first_filter->test_for_target( FeRomInfo::Favourite ) && !first_filter->test_for_target( FeRomInfo::Tags ) ) { // If the global filter doesn't care about file availability, // favourites or tags then we can apply it right up front when we // load the romlist. We signal this by setting m_global_filter_ptr m_global_filter_ptr = first_filter; first_filter = NULL; } } sf::Clock load_timer; bool retval = FeBaseConfigurable::load_from_file( path + m_romlist_name + FE_ROMLIST_FILE_EXTENSION, ";" ); // // Create rom name to romlist entry lookup map // std::map < std::string, FeRomInfo * > rom_map; std::map < std::string, FeRomInfo * >::iterator rm_itr; for ( FeRomInfoListType::iterator itr = m_list.begin(); itr != m_list.end(); ++itr ) rom_map[ (*itr).get_info( FeRomInfo::Romname ) ] = &(*itr); // // Load favourites // m_extra_favs.clear(); m_fav_changed=false; std::string load_name( m_user_path + m_romlist_name + FE_FAVOURITE_FILE_EXTENSION ); std::ifstream myfile( load_name.c_str() ); if ( myfile.is_open() ) { while ( myfile.good() ) { size_t pos=0; std::string line, name; getline( myfile, line ); token_helper( line, pos, name ); if ( !name.empty() ) { rm_itr = rom_map.find( name ); if ( rm_itr != rom_map.end() ) (*rm_itr).second->set_info( FeRomInfo::Favourite, "1" ); else m_extra_favs.insert( name ); } } myfile.close(); } // // Load tags // m_tags.clear(); m_extra_tags.clear(); m_tags_changed=false; load_name = m_user_path + m_romlist_name + "/"; if ( directory_exists( load_name ) ) { std::vector<std::string> temp_tags; get_basename_from_extension( temp_tags, load_name, FE_FAVOURITE_FILE_EXTENSION ); for ( std::vector<std::string>::iterator itr=temp_tags.begin(); itr!=temp_tags.end(); ++itr ) { if ( (*itr).empty() ) continue; std::ifstream myfile( std::string(load_name + (*itr) + FE_FAVOURITE_FILE_EXTENSION).c_str() ); if ( !myfile.is_open() ) continue; std::map<std::string, bool>::iterator itt = m_tags.begin(); itt = m_tags.insert( itt, std::pair<std::string,bool>( (*itr), false ) ); while ( myfile.good() ) { size_t pos=0; std::string line, rname; getline( myfile, line ); token_helper( line, pos, rname ); if ( !rname.empty() ) { rm_itr = rom_map.find( rname ); if ( rm_itr != rom_map.end() ) (*rm_itr).second->append_tag( (*itt).first.c_str() ); else m_extra_tags.insert( std::pair<std::string,const char*>(rname, (*itt).first.c_str() ) ); } } myfile.close(); } } // Apply global filter if it hasn't been applied already if ( first_filter ) { if ( first_filter->test_for_target( FeRomInfo::FileIsAvailable ) ) get_file_availability(); FeRomInfoListType::iterator last_it=m_list.begin(); for ( FeRomInfoListType::iterator it=m_list.begin(); it!=m_list.end(); ) { if ( first_filter->apply_filter( *it ) ) { if ( last_it != it ) it = m_list.erase( last_it, it ); else ++it; last_it = it; } else { // // This rom is being filtered out and we may need to keep track of a few things // // 1. Track if this is a favourite... // if ( !(*it).get_info( FeRomInfo::Favourite ).empty() ) m_extra_favs.insert( (*it).get_info( FeRomInfo::Romname ) ); // // 2. Track if this rom has tags we'll need to keep // if ( !(*it).get_info( FeRomInfo::Tags ).empty() ) { const std::string &name = (*it).get_info( FeRomInfo::Romname ); const std::string &tags = (*it).get_info( FeRomInfo::Tags ); const char sep[] = { FE_TAGS_SEP, 0 }; size_t pos=0; while ( pos < tags.size() ) { std::string one_tag; token_helper( tags, pos, one_tag, sep ); std::map<std::string, bool>::iterator itt = m_tags.find( one_tag ); if ( itt != m_tags.end() ) m_extra_tags.insert( std::pair<std::string,const char *>( name, (*itt).first.c_str() ) ); } } m_global_filtered_out_count++; ++it; } } if ( last_it != m_list.end() ) m_list.erase( last_it, m_list.end() ); } std::cout << " - Loaded master romlist '" << m_romlist_name << "' in " << load_timer.getElapsedTime().asMilliseconds() << " ms (" << m_list.size() << " entries kept, " << m_global_filtered_out_count << " discarded)" << std::endl; load_timer.restart(); // // Apply filters // int filters_count = display.get_filter_count(); // // If the display doesn't have any filters configured, we create a single "filter" in the romlist object // with every romlist entry in it // if ( filters_count == 0 ) filters_count = 1; m_filtered_list.reserve( filters_count ); for ( int i=0; i<filters_count; i++ ) { m_filtered_list.push_back( std::vector< FeRomInfo *>() ); FeFilter *f = display.get_filter( i ); if ( f ) { if ( f->get_size() > 0 ) // if this is non zero then we've loaded before and know how many to expect m_filtered_list[i].reserve( f->get_size() ); if ( f->test_for_target( FeRomInfo::FileIsAvailable ) ) get_file_availability(); f->init(); for ( FeRomInfoListType::iterator itr=m_list.begin(); itr!=m_list.end(); ++itr ) if ( f->apply_filter( *itr ) ) m_filtered_list[i].push_back( &( *itr ) ); } else // no filter situation, so we just add the entire list... { m_filtered_list[i].reserve( m_list.size() ); for ( FeRomInfoListType::iterator itr=m_list.begin(); itr!=m_list.end(); ++itr ) m_filtered_list[i].push_back( &( *itr ) ); } // // make sure stats are loaded for the roms we will be showing // if ( !stat_path.empty() ) { for ( std::vector< FeRomInfo * >::iterator itf=m_filtered_list[i].begin(); itf!=m_filtered_list[i].end(); ++itf ) (*itf)->load_stats( stat_path ); // this will just return if stats are already loaded for the rom } if ( f ) { // track the size of the filtered list in our filter info object f->set_size( m_filtered_list[i].size() ); // // Sort and/or prune now if configured for this filter // FeRomInfo::Index sort_by=f->get_sort_by(); bool rev = f->get_reverse_order(); int list_limit = f->get_list_limit(); if ( sort_by != FeRomInfo::LAST_INDEX ) { std::stable_sort( m_filtered_list[i].begin(), m_filtered_list[i].end(), FeRomListSorter2( sort_by, rev ) ); } else if ( rev != false ) std::reverse( m_filtered_list[i].begin(), m_filtered_list[i].end() ); if (( list_limit != 0 ) && ( (int)m_filtered_list[i].size() > abs( list_limit ) )) { if ( list_limit > 0 ) m_filtered_list[i].erase( m_filtered_list[i].begin() + list_limit, m_filtered_list[i].end() ); else m_filtered_list[i].erase( m_filtered_list[i].begin(), m_filtered_list[i].end() + list_limit ); } } } std::cout << " - Constructed " << filters_count << " filters in " << load_timer.getElapsedTime().asMilliseconds() << " ms (" << filters_count * m_list.size() << " comparisons)" << std::endl; return retval; }