/** \brief Return a vector of absolute paths to files in the given path * * @param[in] path relative or absolute directory (searched recursively) * @return Any regular files in * @return if absolute directory: path * @return if relative directory: GetResourceDir() / path */ std::vector<fs::path> ListDir(const fs::path& path) { std::vector<fs::path> retval; bool is_rel = path.is_relative(); if (!is_rel && (fs::is_empty(path) || !fs::is_directory(path))) { DebugLogger() << "ListDir: File " << PathString(path) << " was not included as it is empty or not a directoy"; } else { const fs::path& default_path = is_rel ? GetResourceDir() / path : path; for (fs::recursive_directory_iterator dir_it(default_path); dir_it != fs::recursive_directory_iterator(); ++dir_it) { if (fs::is_regular_file(dir_it->status())) { retval.push_back(dir_it->path()); } else if (!fs::is_directory(dir_it->status())) { TraceLogger() << "Parse: Unknown file not included: " << PathString(dir_it->path()); } } } if (retval.empty()) { DebugLogger() << "ListDir: No files found for " << path.string(); } return retval; }
/** * フルパス名を求めます。 */ PathString getFullPath(const PathString &s) { const DWORD bufferLen = MAX_PATH; TCHAR *filePart; TCHAR buffer[bufferLen + 1]; DWORD len = GetFullPathName(s.c_str(), bufferLen, buffer, &filePart); if(len == 0 || len >= bufferLen){ return PathString(); } return PathString(buffer); }
/** * ファイルの拡張子(ドットを含む)を返します。 */ PathString getFileExtension(const PathString &s) { const PathString filename = getLastFileName(s); if(filename.empty() || filename == AUSH_NATIVE_L(".") || filename == AUSH_NATIVE_L("..")){ return PathString(); } const std::size_t pos = find_last_char(filename, is_dot()); if(pos >= filename.size()){ return PathString(); } return filename.substr(pos); }
void LoadSaveGamePreviews(const fs::path& orig_path, const std::string& extension, std::vector<FullPreview>& previews) { FullPreview data; fs::directory_iterator end_it; fs::path path = orig_path; // Relative path relative to the save directory if (path.is_relative()) { path = GetSaveDir() / path; } if (!fs::exists(path)) { ErrorLogger() << "SaveFileListBox::LoadSaveGamePreviews: Save Game directory \"" << path << "\" not found"; return; } if (!fs::is_directory(path)) { ErrorLogger() << "SaveFileListBox::LoadSaveGamePreviews: Save Game directory \"" << path << "\" was not a directory"; return; } for (fs::directory_iterator it(path); it != end_it; ++it) { try { std::string filename = PathString(it->path().filename()); if (it->path().filename().extension() == extension & !fs::is_directory(it->path())) { if (LoadSaveGamePreviewData(*it, data)) { // Add preview entry to list previews.push_back(data); } } } catch (const std::exception& e) { ErrorLogger() << "SaveFileListBox::LoadSaveGamePreviews: Failed loading preview from " << it->path() << " because: " << e.what(); } } }
void SaveFileDialog::Confirm() { Logger().debugStream() << "SaveFileDialog::Confirm: Confirming"; if(!CheckChoiceValidity()){ Logger().debugStream() << "SaveFileDialog::Confirm: Invalid choice. abort."; return; } /// Check if we chose a directory std::string choice = m_name_edit->Text(); fs::path current_dir ( m_current_dir_edit->Text() ); if ( !choice.empty() ) { fs::path chosen = current_dir / choice; if ( fs::is_directory ( chosen ) ) { Logger().debugStream() << "SaveFileDialog::Confirm: " << chosen << " is a directory. Listing content."; UpdateDirectory ( PathString ( chosen ) ); return; } else { Logger().debugStream() << "SaveFileDialog::Confirm: File " << chosen << " chosen."; } } else { Logger().debugStream() << "SaveFileDialog::Confirm: Returning no file."; } CloseClicked(); }
/// Loads preview data on all save files in a directory specidifed by path. /// @param [in] path The path of the directory /// @param [out] previews The preview datas indexed by file names void LoadSaveGamePreviews ( const fs::path& path, const std::string& extension ) { SaveGamePreviewData data; fs::directory_iterator end_it; if ( !fs::exists ( path ) ) { Logger().errorStream() << "SaveFileListBox::LoadSaveGamePreviews: Save Game directory \"" << path << "\" not found"; return; } if ( !fs::is_directory ( path ) ) { Logger().errorStream() << "SaveFileListBox::LoadSaveGamePreviews: Save Game directory \"" << path << "\" was not a directory"; return; } for ( fs::directory_iterator it ( path ); it != end_it; ++it ) { try { std::string filename = PathString ( it->path().filename() ); if ( it->path().filename().extension() == extension ) { if ( LoadSaveGamePreviewData ( *it, data ) ) { // Add preview entry to list Insert ( new SaveFileRow ( filename, data ) ); } } } catch ( const std::exception& e ) { Logger().errorStream() << "SaveFileListBox::LoadSaveGamePreviews: Failed loading preview from " << it->path() << " because: " << e.what(); } } }
void OptionsDB::Commit() { if (!m_dirty) return; boost::filesystem::ofstream ofs(GetConfigPath()); if (ofs) { XMLDoc doc; GetOptionsDB().GetXML(doc); doc.WriteDoc(ofs); m_dirty = false; } else { std::cerr << UserString("UNABLE_TO_WRITE_CONFIG_XML") << std::endl; std::cerr << PathString(GetConfigPath()) << std::endl; ErrorLogger() << UserString("UNABLE_TO_WRITE_CONFIG_XML"); ErrorLogger() << PathString(GetConfigPath()); } }
/** * フルパス名のファイル部分を除いた物を求めます。 * * chopLastFileName(getFullPath(s))とほぼ同じだと思います。 */ PathString getFullPathDir(const PathString &s) { const DWORD bufferLen = MAX_PATH; TCHAR *filePart; TCHAR buffer[bufferLen + 1]; DWORD len = GetFullPathName(s.c_str(), bufferLen, buffer, &filePart); if(len == 0 || len == bufferLen){ return PathString(); } if(filePart == NULL){ return PathString(buffer); // sがパス区切りで終わっていたり、//serverや//server/shareのようなUNC先頭。 } else{ return PathString(buffer, filePart); //ファイル部の直前までを返す。 } }
/** * パス末尾の余分なセパレータを切り落とした文字列を返します。 * * 切り落とすのは余分なセパレータであり、切り落とすことによって意味が変わってしまう場合は切り落としません。 */ PathString chopLastRedundantSeparator(const PathString &s) { if(isTerminatedByRedundantSeparator(s)){ return PathString(s, 0, s.size() - 1); } else{ return s; } }
void SaveFileDialog::BrowseDirectories() { std::vector<std::pair<std::string, std::string> > dummy; FileDlg dlg ( m_current_dir_edit->Text(), "", false, false, dummy ); dlg.SelectDirectories ( true ); dlg.Run(); if ( !dlg.Result().empty() ) { // Normalize the path by converting it into a path and back fs::path choice ( *dlg.Result().begin() ); UpdateDirectory ( PathString ( fs::canonical ( choice ) ) ); } }
std::string SaveFileDialog::Result() const { std::string filename = m_name_edit->Text(); if ( filename.empty() ) { return ""; } else { // Ensure the file has an extension std::string::size_type end = filename.length(); std::size_t ext_length = m_extension.length(); if ( filename.length() < ext_length || filename.substr ( end-ext_length, ext_length ) != m_extension ) { filename.append ( m_extension ); } fs::path current_dir ( m_current_dir_edit->Text() ); return PathString ( ( current_dir / filename ).string() ); } }
void Sound::Impl::FreeSound(const boost::filesystem::path& path) { if (!m_initialized) return; ALenum m_openal_error; std::string filename = PathString(path); std::map<std::string, ALuint>::iterator it = m_buffers.find(filename); if (it != m_buffers.end()) { alDeleteBuffers(1, &(it->second)); m_openal_error = alGetError(); if (m_openal_error != AL_NONE) ErrorLogger() << "FreeSound: OpenAL ERROR: " << alGetString(m_openal_error); else m_buffers.erase(it); /* we don't erase if there was an error, as the buffer may not have been removed - potential memory leak */ } }
void InGameMenu::Save() { Logger().debugStream() << "InGameMenu::Save"; HumanClientApp* app = HumanClientApp::GetApp(); if (!app) return; if (!app->CanSaveNow()) { Logger().errorStream() << "InGameMenu::Save aborting; Client app can't save now"; return; } const std::string SAVE_GAME_EXTENSION = HumanClientApp::GetApp()->SinglePlayerGame() ? SP_SAVE_FILE_EXTENSION : MP_SAVE_FILE_EXTENSION; std::vector<std::pair<std::string, std::string> > save_file_types; save_file_types.push_back(std::make_pair(UserString("GAME_MENU_SAVE_FILES"), "*" + SAVE_GAME_EXTENSION)); try { Logger().debugStream() << "... getting save path string"; std::string path_string = PathString(GetSaveDir()); Logger().debugStream() << "... got save path string: " << path_string; Logger().debugStream() << "... running file dialog"; FileDlg dlg(path_string, "", true, false, save_file_types); dlg.Run(); if (!dlg.Result().empty()) { if (!app->CanSaveNow()) { Logger().errorStream() << "InGameMenu::Save aborting; Client app can't save now"; throw std::runtime_error(UserString("UNABLE_TO_SAVE_NOW_TRY_AGAIN")); } Logger().debugStream() << "... initiating save"; app->SaveGame(*dlg.Result().begin()); CloseClicked(); Logger().debugStream() << "... save done"; } } catch (const std::exception& e) { Logger().errorStream() << "Exception thrown attempting save: " << e.what(); ClientUI::MessageBox(e.what(), true); } }
void Sound::Impl::PlaySound(const boost::filesystem::path& path, bool is_ui_sound/* = false*/) { if (!m_initialized || !GetOptionsDB().Get<bool>("UI.sound.enabled") || (is_ui_sound && UISoundsTemporarilyDisabled())) return; std::string filename = PathString(path); ALuint current_buffer; ALenum source_state; ALsizei ogg_freq; FILE *file = nullptr; int m_i; bool found_buffer = false; bool found_source = false; #ifdef FREEORION_WIN32 ov_callbacks callbacks = { (size_t (*)(void *, size_t, size_t, void *)) fread, (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, (int (*)(void *)) fclose, (long (*)(void *)) ftell }; #endif if (alcGetCurrentContext()) { /* First check if the sound data of the file we want to play is already buffered somewhere */ std::map<std::string, ALuint>::iterator it = m_buffers.find(filename); if (it != m_buffers.end()) { current_buffer = it->second; found_buffer = true; } else { if ((file = fopen(filename.c_str(), "rb")) != nullptr) { // make sure we CAN open it OggVorbis_File ogg_file; vorbis_info *vorbis_info; ALenum ogg_format; #ifdef FREEORION_WIN32 if (!(ov_test_callbacks(file, &ogg_file, nullptr, 0, callbacks))) // check if it's a proper ogg #else if (!(ov_test(file, &ogg_file, nullptr, 0))) // check if it's a proper ogg #endif { ov_test_open(&ogg_file); // it is, now fully open the file /* now we need to take some info we will need later */ vorbis_info = ov_info(&ogg_file, -1); if (vorbis_info->channels == 1) ogg_format = AL_FORMAT_MONO16; else ogg_format = AL_FORMAT_STEREO16; ogg_freq = vorbis_info->rate; ogg_int64_t byte_size = ov_pcm_total(&ogg_file, -1) * vorbis_info->channels * 2; if (byte_size <= 1024 * 1024 * 1024) { /* fill up the buffers and queue them up for the first time */ ALuint sound_handle; alGenBuffers(1, &sound_handle); int loop = 0; RefillBuffer(&ogg_file, ogg_format, ogg_freq, sound_handle, byte_size, loop); current_buffer = sound_handle; found_buffer = true; m_buffers.insert(std::make_pair(filename, sound_handle)); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " too big to buffer. Aborting\n"; } ov_clear(&ogg_file); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n"; } } } if (found_buffer) { /* Now that we have the buffer, we need to find a source to send it to */ for (m_i = 1; m_i < NUM_SOURCES; ++m_i) { // as we're playing sounds we start at 1. 0 is reserved for music alGetSourcei(m_sources[m_i], AL_SOURCE_STATE, &source_state); if ((source_state != AL_PLAYING) && (source_state != AL_PAUSED)) { found_source = true; alSourcei(m_sources[m_i], AL_BUFFER, current_buffer); alSourcePlay(m_sources[m_i]); break; // so that the sound won't block all the sources } } if (!found_source) ErrorLogger() << "PlaySound: Could not find aviable source - playback aborted\n"; } source_state = alGetError(); if (source_state != AL_NONE) ErrorLogger() << "PlaySound: OpenAL ERROR: " << alGetString(source_state); /* it's important to check for errors, as some functions won't work properly if * they're called when there is a unchecked previous error. */ } }
void Sound::Impl::PlayMusic(const boost::filesystem::path& path, int loops /* = 0*/) { if (!m_initialized) return; ALenum m_openal_error; std::string filename = PathString(path); FILE* m_f = nullptr; vorbis_info* vorbis_info; m_music_loops = 0; #ifdef FREEORION_WIN32 ov_callbacks callbacks = { (size_t (*)(void *, size_t, size_t, void *)) fread, (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, (int (*)(void *)) fclose, (long (*)(void *)) ftell }; #endif if (alcGetCurrentContext()) { if (m_music_name.size() > 0) StopMusic(); if ((m_f = fopen(filename.c_str(), "rb")) != nullptr) // make sure we CAN open it { #ifdef FREEORION_WIN32 if (!(ov_test_callbacks(m_f, &m_ogg_file, nullptr, 0, callbacks))) // check if it's a proper ogg #else if (!(ov_test(m_f, &m_ogg_file, nullptr, 0))) // check if it's a proper ogg #endif { ov_test_open(&m_ogg_file); // it is, now fully open the file /* now we need to take some info we will need later */ vorbis_info = ov_info(&m_ogg_file, -1); if (vorbis_info->channels == 1) m_ogg_format = AL_FORMAT_MONO16; else m_ogg_format = AL_FORMAT_STEREO16; m_ogg_freq = vorbis_info->rate; m_music_loops = loops; /* fill up the buffers and queue them up for the first time */ if (!RefillBuffer(&m_ogg_file, m_ogg_format, m_ogg_freq, m_music_buffers[0], BUFFER_SIZE, m_music_loops)) { alSourceQueueBuffers(m_sources[0], 1, &m_music_buffers[0]); // queue up the buffer if we manage to fill it if (!RefillBuffer(&m_ogg_file, m_ogg_format, m_ogg_freq, m_music_buffers[1], BUFFER_SIZE, m_music_loops)) { alSourceQueueBuffers(m_sources[0], 1, &m_music_buffers[1]); m_music_name = filename; // yup, we're playing something that takes up more than 2 buffers } else { m_music_name.clear(); // m_music_name.clear() must always be called before ov_clear. Otherwise } alSourcePlay(m_sources[0]); // play if at least one buffer is queued } else { m_music_name.clear(); // m_music_name.clear() must always be called before ov_clear. Otherwise } } else { ErrorLogger() << "PlayMusic: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n"; m_music_name.clear(); //just in case ov_clear(&m_ogg_file); } } else ErrorLogger() << "PlayMusic: unable to open file " << filename.c_str() << " I/O Error. Aborting\n"; } m_openal_error = alGetError(); if (m_openal_error != AL_NONE) ErrorLogger() << "PlayMusic: OpenAL ERROR: " << alGetString(m_openal_error); }
void HumanClientApp::Autosave() { // autosave only on appropriate turn numbers, and when enabled for current // game type (single vs. multiplayer) int autosave_turns = GetOptionsDB().Get<int>("autosave.turns"); if (autosave_turns < 1) return; // avoid divide by zero if (CurrentTurn() % autosave_turns != 0 && CurrentTurn() != 1) return; // turns divisible by autosave_turns, and first turn, have autosaves done if (m_single_player_game && !GetOptionsDB().Get<bool>("autosave.single-player")) return; if (!m_single_player_game && !GetOptionsDB().Get<bool>("autosave.multiplayer")) return; const char* legal_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-"; // get empire name, filtered for filename acceptability int client_empire_id = EmpireID(); const Empire* empire = GetEmpire(client_empire_id); std::string empire_name; if (empire) empire_name = empire->Name(); else empire_name = UserString("OBSERVER"); std::string::size_type first_good_empire_char = empire_name.find_first_of(legal_chars); if (first_good_empire_char == std::string::npos) { empire_name.clear(); } else { std::string::size_type first_bad_empire_char = empire_name.find_first_not_of(legal_chars, first_good_empire_char); empire_name = empire_name.substr(first_good_empire_char, first_bad_empire_char - first_good_empire_char); } // get player name, also filtered std::string player_name; if (empire) player_name = empire->PlayerName(); std::string::size_type first_good_player_char = player_name.find_first_of(legal_chars); if (first_good_player_char == std::string::npos) { player_name.clear(); } else { std::string::size_type first_bad_player_char = player_name.find_first_not_of(legal_chars, first_good_player_char); player_name = player_name.substr(first_good_player_char, first_bad_player_char - first_good_player_char); } // select filename extension std::string extension; if (m_single_player_game) extension = SP_SAVE_FILE_EXTENSION; else extension = MP_SAVE_FILE_EXTENSION; // Add timestamp to autosave generated files std::string datetime_str = FilenameTimestamp(); boost::filesystem::path autosave_dir_path(GetSaveDir() / "auto"); std::string save_filename = boost::io::str(boost::format("FreeOrion_%s_%s_%04d_%s%s") % player_name % empire_name % CurrentTurn() % datetime_str % extension); boost::filesystem::path save_path(autosave_dir_path / save_filename); std::string path_string = PathString(save_path); try { // ensure autosave directory exists if (!exists(autosave_dir_path)) boost::filesystem::create_directories(autosave_dir_path); } catch (const std::exception& e) { ErrorLogger() << "Autosave unable to check / create autosave directory: " << e.what(); std::cerr << "Autosave unable to check / create autosave directory: " << e.what() << std::endl; } // check for and remove excess oldest autosaves int max_autosaves = GetOptionsDB().Get<int>("autosave.limit"); RemoveOldestFiles(max_autosaves, autosave_dir_path); // create new save DebugLogger() << "Autosaving to: " << path_string; try { SaveGame(path_string); } catch (const std::exception& e) { ErrorLogger() << "Autosave failed: " << e.what(); std::cerr << "Autosave failed: " << e.what() << std::endl; } }
int mainConfigOptionsSetup(const std::vector<std::string>& args) { InitDirs((args.empty() ? "" : *args.begin())); // read and process command-line arguments, if any try { // add entries in options DB that have no other obvious place GetOptionsDB().AddFlag('h', "help", UserStringNop("OPTIONS_DB_HELP"), false); GetOptionsDB().AddFlag('g', "generate-config-xml", UserStringNop("OPTIONS_DB_GENERATE_CONFIG_XML"), false); GetOptionsDB().AddFlag('f', "fullscreen", UserStringNop("OPTIONS_DB_FULLSCREEN"), STORE_FULLSCREEN_FLAG); GetOptionsDB().Add("reset-fullscreen-size", UserStringNop("OPTIONS_DB_RESET_FSSIZE"), true); GetOptionsDB().Add<bool>("fake-mode-change", UserStringNop("OPTIONS_DB_FAKE_MODE_CHANGE"), FAKE_MODE_CHANGE_FLAG); GetOptionsDB().Add<int>("fullscreen-monitor-id", UserStringNop("OPTIONS_DB_FULLSCREEN_MONITOR_ID"), 0, RangedValidator<int>(0, 5)); GetOptionsDB().AddFlag('q', "quickstart", UserStringNop("OPTIONS_DB_QUICKSTART"), false); GetOptionsDB().AddFlag("auto-quit", UserStringNop("OPTIONS_DB_AUTO_QUIT"), false); GetOptionsDB().Add<int>("auto-advance-n-turns", UserStringNop("OPTIONS_DB_AUTO_N_TURNS"), 0, RangedValidator<int>(0, 400), false); GetOptionsDB().Add<std::string>("load", UserStringNop("OPTIONS_DB_LOAD"), "", Validator<std::string>(), false); GetOptionsDB().Add("UI.sound.music-enabled", UserStringNop("OPTIONS_DB_MUSIC_ON"), true); GetOptionsDB().Add("UI.sound.enabled", UserStringNop("OPTIONS_DB_SOUND_ON"), true); GetOptionsDB().Add<std::string>("version-string", UserStringNop("OPTIONS_DB_VERSION_STRING"), FreeOrionVersionString(), Validator<std::string>(), true); GetOptionsDB().AddFlag('r', "render-simple", UserStringNop("OPTIONS_DB_RENDER_SIMPLE"), false); // Add the keyboard shortcuts Hotkey::AddOptions(GetOptionsDB()); // read config.xml and set options entries from it, if present { XMLDoc doc; try { boost::filesystem::ifstream ifs(GetConfigPath()); if (ifs) { doc.ReadDoc(ifs); // reject config files from out-of-date version if (doc.root_node.ContainsChild("version-string") && doc.root_node.Child("version-string").Text() == FreeOrionVersionString()) { GetOptionsDB().SetFromXML(doc); } } } catch (const std::exception&) { std::cerr << UserString("UNABLE_TO_READ_CONFIG_XML") << std::endl; } } // override previously-saved and default options with command line parameters and flags GetOptionsDB().SetFromCommandLine(args); // Handle the case where the resource-dir does not exist anymore // gracefully by resetting it to the standard path into the // application bundle. This may happen if a previous installed // version of FreeOrion was residing in a different directory. if (!boost::filesystem::exists(GetResourceDir()) || !boost::filesystem::exists(GetResourceDir() / "credits.xml") || !boost::filesystem::exists(GetResourceDir() / "data" / "art" / "misc" / "missing.png")) { DebugLogger() << "Resources directory from config.xml missing or does not contain expected files. Resetting to default."; GetOptionsDB().Set<std::string>("resource-dir", ""); // double-check that resetting actually fixed things... if (!boost::filesystem::exists(GetResourceDir()) || !boost::filesystem::exists(GetResourceDir() / "credits.xml") || !boost::filesystem::exists(GetResourceDir() / "data" / "art" / "misc" / "missing.png")) { DebugLogger() << "Default Resources directory missing or does not contain expected files. Cannot start game."; throw std::runtime_error("Unable to load game resources at default location: " + PathString(GetResourceDir()) + " : Install may be broken."); } } // did the player request generation of config.xml, saving the default (or current) options to disk? if (GetOptionsDB().Get<bool>("generate-config-xml")) { try { GetOptionsDB().Commit(); } catch (const std::exception&) { std::cerr << UserString("UNABLE_TO_WRITE_CONFIG_XML") << std::endl; } } if (GetOptionsDB().Get<bool>("render-simple")) { GetOptionsDB().Set<bool>("UI.galaxy-gas-background",false); GetOptionsDB().Set<bool>("UI.galaxy-starfields", false); GetOptionsDB().Set<bool>("show-fps", true); } } catch (const std::invalid_argument& e) { std::cerr << "main() caught exception(std::invalid_argument): " << e.what() << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(3)); return 1; } catch (const std::runtime_error& e) { std::cerr << "main() caught exception(std::runtime_error): " << e.what() << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(3)); return 1; } catch (const std::exception& e) { std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(3)); return 1; } catch (...) { std::cerr << "main() caught unknown exception." << std::endl; return 1; } return 0; }
SaveFileDialog::SaveFileDialog (const std::string& extension, bool load ) : CUIWnd ( UserString ( "GAME_MENU_SAVE_FILES" ), ( GG::GUI::GetGUI()->AppWidth() - SAVE_FILE_DIALOG_WIDTH ) / 2, ( GG::GUI::GetGUI()->AppHeight() - SAVE_FILE_DIALOG_HEIGHT ) / 2, SAVE_FILE_DIALOG_WIDTH, SAVE_FILE_DIALOG_HEIGHT, GG::INTERACTIVE | GG::DRAGABLE | GG::MODAL | GG::RESIZABLE ) { m_extension = extension; m_load_only = load; boost::shared_ptr<GG::Font> font = ClientUI::GetFont(); SetMinSize ( GG::Pt ( 2*SAVE_FILE_DIALOG_MIN_WIDTH, 2*SAVE_FILE_DIALOG_MIN_HEIGHT ) ); m_layout = new GG::Layout ( GG::X0, GG::Y0, SAVE_FILE_DIALOG_WIDTH - LeftBorder() - RightBorder(), SAVE_FILE_DIALOG_HEIGHT - TopBorder() - BottomBorder(), 3, 4 ); m_layout->SetCellMargin ( SAVE_FILE_CELL_MARGIN ); m_layout->SetBorderMargin ( SAVE_FILE_CELL_MARGIN*2 ); m_file_list = new SaveFileListBox(); m_file_list->SetStyle ( GG::LIST_SINGLESEL | GG::LIST_SORTDESCENDING ); m_file_list->SetColHeaders ( new SaveFileRow() ); m_confirm_btn = new CUIButton ( UserString ( "OK" ) ); CUIButton* cancel_btn = new CUIButton ( UserString ( "CANCEL" ) ); m_name_edit = new CUIEdit ( GG::X0, GG::Y0, GG::X1, "", font ); GG::TextControl* filename_label = new GG::TextControl ( GG::X0, GG::Y0, UserString ( "SAVE_FILENAME" ), font, ClientUI::TextColor() ); GG::TextControl* directory_label = new GG::TextControl ( GG::X0, GG::Y0, UserString ( "SAVE_DIRECTORY" ), font, ClientUI::TextColor() ); m_current_dir_edit = new CUIEdit ( GG::X0, GG::Y0, GG::X1, PathString ( GetSaveDir() ), font ); m_browse_dir_btn = new CUIButton ( "..." ); m_layout->Add ( m_file_list, 0, 0, 1, 4 ); m_layout->Add ( filename_label, 1, 0, 1, 1 ); m_layout->Add ( m_name_edit, 1, 1, 1, 2 ); m_layout->Add ( m_confirm_btn, 1, 3 ); m_layout->Add ( directory_label,2, 0 ); m_layout->Add ( m_current_dir_edit, 2, 1 ); m_layout->Add ( m_browse_dir_btn, 2, 2 ); m_layout->Add ( cancel_btn, 2, 3 ); m_layout->SetRowStretch ( 0, 1.0 ); m_layout->SetMinimumRowHeight ( 1, font->TextExtent ( m_confirm_btn->Text() ).y ); m_layout->SetMinimumRowHeight ( 2, font->TextExtent ( cancel_btn->Text() ).y ); m_layout->SetMinimumColumnWidth ( 0, std::max ( font->TextExtent ( filename_label->Text() ).x, font->TextExtent ( directory_label->Text() ).x ) ); m_layout->SetColumnStretch ( 1, 1.0 ); m_layout->SetMinimumColumnWidth ( 2, m_browse_dir_btn->MinUsableSize().x + SAVE_FILE_BUTTON_MARGIN*2 ); m_layout->SetMinimumColumnWidth ( 3, std::max ( m_confirm_btn->MinUsableSize().x, cancel_btn->MinUsableSize().x ) + SAVE_FILE_BUTTON_MARGIN ); SetLayout ( m_layout ); GG::Connect ( m_confirm_btn->LeftClickedSignal, &SaveFileDialog::Confirm, this ); GG::Connect ( cancel_btn->LeftClickedSignal, &SaveFileDialog::Cancel, this ); GG::Connect ( m_file_list->SelChangedSignal, &SaveFileDialog::SelectionChanged, this ); GG::Connect ( m_file_list->DoubleClickedSignal, &SaveFileDialog::DoubleClickRow, this ); GG::Connect ( m_browse_dir_btn->LeftClickedSignal, &SaveFileDialog::BrowseDirectories, this ); GG::Connect ( m_name_edit->EditedSignal, &SaveFileDialog::FileNameEdited, this ); UpdatePreviewList(); if(!m_load_only){ m_name_edit->SetText(std::string("save-") + FilenameTimestamp()); m_name_edit->SelectAll(); } }
/** * パス末尾のファイル名部分を切り落とした文字列を返します。 * * 最後のパス区切り文字は残します。入力文字列の最後がパス区切り文字で終わっている場合は、入力文字列をそのまま返します。 */ PathString chopLastFileName(const PathString &s) { return PathString(s, 0, getLastFileNamePos(s)); }