zamotivator

Untitled

Feb 9th, 2012
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.92 KB | None | 0 0
  1. diff --git a/src/dialogs.cpp b/src/dialogs.cpp
  2. index ba99d03..efb93cb 100644
  3. --- a/src/dialogs.cpp
  4. +++ b/src/dialogs.cpp
  5. @@ -272,13 +272,13 @@ namespace {
  6. class delete_save : public gui::dialog_button_action
  7. {
  8. public:
  9. - delete_save(display& disp, gui::filter_textbox& filter, std::vector<savegame::save_info>& saves, std::vector<config*>& save_summaries) : disp_(disp), saves_(saves), summaries_(save_summaries), filter_(filter) {}
  10. + delete_save(display& disp, gui::filter_textbox& filter, std::vector<savegame::save_info>& saves) :
  11. + disp_(disp), saves_(saves), filter_(filter) {}
  12. private:
  13. gui::dialog_button_action::RESULT button_pressed(int menu_selection);
  14.  
  15. display& disp_;
  16. std::vector<savegame::save_info>& saves_;
  17. - std::vector<config*>& summaries_;
  18. gui::filter_textbox& filter_;
  19. };
  20.  
  21. @@ -298,15 +298,11 @@ gui::dialog_button_action::RESULT delete_save::button_pressed(int menu_selection
  22. filter_.delete_item(menu_selection);
  23.  
  24. // Delete the file
  25. - savegame::manager::delete_game(saves_[index].name);
  26. + savegame::delete_game(saves_[index].name());
  27.  
  28. // Remove it from the list of saves
  29. saves_.erase(saves_.begin() + index);
  30.  
  31. - if(index < summaries_.size()) {
  32. - summaries_.erase(summaries_.begin() + index);
  33. - }
  34. -
  35. return gui::DELETE_ITEM;
  36. } else {
  37. return gui::CONTINUE_DIALOG;
  38. @@ -320,12 +316,10 @@ class save_preview_pane : public gui::preview_pane
  39. public:
  40. save_preview_pane(CVideo &video, const config& game_config, gamemap* map,
  41. const std::vector<savegame::save_info>& info,
  42. - const std::vector<config*>& summaries,
  43. const gui::filter_textbox& textbox) :
  44. gui::preview_pane(video),
  45. game_config_(&game_config),
  46. map_(map), info_(&info),
  47. - summaries_(summaries),
  48. index_(0),
  49. map_cache_(),
  50. textbox_(textbox)
  51. @@ -346,7 +340,6 @@ private:
  52. const config* game_config_;
  53. gamemap* map_;
  54. const std::vector<savegame::save_info>* info_;
  55. - const std::vector<config*>& summaries_;
  56. int index_;
  57. std::map<std::string,surface> map_cache_;
  58. const gui::filter_textbox& textbox_;
  59. @@ -354,21 +347,6 @@ private:
  60.  
  61. void save_preview_pane::draw_contents()
  62. {
  63. - if (size_t(index_) >= summaries_.size() || info_->size() != summaries_.size()) {
  64. - return;
  65. - }
  66. -
  67. - std::string dummy;
  68. - const config &summary = *summaries_[index_];
  69. - if (summary["label"].empty())
  70. - {
  71. - try {
  72. - savegame::manager::load_summary((*info_)[index_].name, *summaries_[index_], &dummy);
  73. - } catch(game::load_game_failed&) {
  74. - (*summaries_[index_])["corrupt"] = true;
  75. - }
  76. - }
  77. -
  78. surface screen = video().getSurface();
  79.  
  80. SDL_Rect const &loc = location();
  81. @@ -381,6 +359,7 @@ void save_preview_pane::draw_contents()
  82.  
  83. int ypos = area.y;
  84.  
  85. + const config& summary= ((*info_)[index_]).summary();
  86. const unit_type *leader = unit_types.find(summary["leader"]);
  87. if (leader)
  88. {
  89. @@ -448,7 +427,7 @@ void save_preview_pane::draw_contents()
  90.  
  91. char time_buf[256] = {0};
  92. const savegame::save_info& save = (*info_)[index_];
  93. - tm* tm_l = localtime(&save.time_modified);
  94. + tm* tm_l = localtime(&save.modified());
  95. if (tm_l) {
  96. const size_t res = strftime(time_buf,sizeof(time_buf),
  97. (preferences::use_twelve_hour_clock_format() ? _("%a %b %d %I:%M %p %Y") : _("%a %b %d %H:%M %Y")),
  98. @@ -457,13 +436,13 @@ void save_preview_pane::draw_contents()
  99. time_buf[0] = 0;
  100. }
  101. } else {
  102. - LOG_NG << "localtime() returned null for time " << save.time_modified << ", save " << save.name;
  103. + LOG_NG << "localtime() returned null for time " << save.modified() << ", save " << save.name();
  104. }
  105.  
  106. std::stringstream str;
  107.  
  108. str << font::BOLD_TEXT << font::NULL_MARKUP
  109. - << (*info_)[index_].name << '\n' << time_buf;
  110. + << (*info_)[index_].name() << '\n' << time_buf;
  111.  
  112. const std::string& campaign_type = summary["campaign_type"];
  113. if (summary["corrupt"].to_bool()) {
  114. @@ -582,7 +561,7 @@ std::string load_game_dialog(display& disp, const config& game_config, bool* sho
  115. std::vector<savegame::save_info> games;
  116. {
  117. cursor::setter cur(cursor::WAIT);
  118. - games = savegame::manager::get_saves_list();
  119. + games = savegame::get_saves_list();
  120. }
  121.  
  122. if(games.empty()) {
  123. @@ -592,29 +571,19 @@ std::string load_game_dialog(display& disp, const config& game_config, bool* sho
  124. return "";
  125. }
  126.  
  127. - std::vector<config*> summaries;
  128. - std::vector<savegame::save_info>::const_iterator i;
  129. - //FIXME: parent_to_child is not used yet
  130. - std::map<std::string,std::string> parent_to_child;
  131. - for(i = games.begin(); i != games.end(); ++i) {
  132. - config& cfg = savegame::save_index::save_summary(i->name);
  133. - parent_to_child[cfg["parent"]] = i->name;
  134. - summaries.push_back(&cfg);
  135. - }
  136. -
  137. const events::event_context context;
  138.  
  139. std::vector<std::string> items;
  140. std::ostringstream heading;
  141. heading << HEADING_PREFIX << _("Name") << COLUMN_SEPARATOR << _("Date");
  142. items.push_back(heading.str());
  143. -
  144. + std::vector<savegame::save_info>::const_iterator i;
  145. for(i = games.begin(); i != games.end(); ++i) {
  146. - std::string name = i->name;
  147. + std::string name = i->name();
  148. utils::truncate_as_wstring(name, std::min<size_t>(name.size(), 40));
  149.  
  150. std::ostringstream str;
  151. - str << name << COLUMN_SEPARATOR << format_time_summary(i->time_modified);
  152. + str << name << COLUMN_SEPARATOR << format_time_summary(i->modified());
  153.  
  154. items.push_back(str.str());
  155. }
  156. @@ -634,7 +603,7 @@ std::string load_game_dialog(display& disp, const config& game_config, bool* sho
  157. gui::filter_textbox* filter = new gui::filter_textbox(disp.video(), _("Filter: "), items, items, 1, lmenu);
  158. lmenu.set_textbox(filter);
  159.  
  160. - save_preview_pane save_preview(disp.video(),game_config,&map_obj,games,summaries,*filter);
  161. + save_preview_pane save_preview(disp.video(),game_config,&map_obj,games,*filter);
  162. lmenu.add_pane(&save_preview);
  163. // create an option for whether the replay should be shown or not
  164. if(show_replay != NULL) {
  165. @@ -652,7 +621,7 @@ std::string load_game_dialog(display& disp, const config& game_config, bool* sho
  166. lmenu.add_button(new gui::standard_dialog_button(disp.video(),_("OK"),0,false), gui::dialog::BUTTON_STANDARD);
  167. lmenu.add_button(new gui::standard_dialog_button(disp.video(),_("Cancel"),1,true), gui::dialog::BUTTON_STANDARD);
  168.  
  169. - delete_save save_deleter(disp,*filter,games,summaries);
  170. + delete_save save_deleter(disp,*filter,games);
  171. gui::dialog_button_info delete_button(&save_deleter,_("Delete Save"));
  172.  
  173. lmenu.add_button(delete_button,
  174. @@ -662,8 +631,6 @@ std::string load_game_dialog(display& disp, const config& game_config, bool* sho
  175.  
  176. int res = lmenu.show();
  177.  
  178. - savegame::save_index::write_save_index();
  179. -
  180. if(res == -1)
  181. return "";
  182.  
  183. @@ -672,7 +639,7 @@ std::string load_game_dialog(display& disp, const config& game_config, bool* sho
  184. if(show_replay != NULL) {
  185. *show_replay = lmenu.option_checked(option_index++);
  186.  
  187. - const config& summary = *summaries[res];
  188. + const config& summary = games[res].summary();
  189. if (summary["replay"].to_bool() && !summary["snapshot"].to_bool(true)) {
  190. *show_replay = true;
  191. }
  192. @@ -681,7 +648,7 @@ std::string load_game_dialog(display& disp, const config& game_config, bool* sho
  193. *cancel_orders = lmenu.option_checked(option_index++);
  194. }
  195.  
  196. - return games[res].name;
  197. + return games[res].name();
  198. }
  199.  
  200. namespace {
  201. diff --git a/src/gui/dialogs/data_manage.cpp b/src/gui/dialogs/data_manage.cpp
  202. index e908bc5..24c0c63 100644
  203. --- a/src/gui/dialogs/data_manage.cpp
  204. +++ b/src/gui/dialogs/data_manage.cpp
  205. @@ -83,7 +83,7 @@ void tdata_manage::pre_show(CVideo& /*video*/, twindow& window)
  206.  
  207. {
  208. cursor::setter cur(cursor::WAIT);
  209. - games_ = savegame::manager::get_saves_list();
  210. + games_ = savegame::get_saves_list();
  211. }
  212. fill_game_list(window, games_);
  213.  
  214. @@ -105,7 +105,7 @@ void tdata_manage::fill_game_list(twindow& window
  215. std::map<std::string, string_map> data;
  216. string_map item;
  217.  
  218. - item["label"] = game.name;
  219. + item["label"] = game.name();
  220. data.insert(std::make_pair("filename", item));
  221.  
  222. item["label"] = game.format_time_summary();
  223. @@ -179,7 +179,7 @@ void tdata_manage::delete_button_callback(twindow& window)
  224. }
  225.  
  226. // Delete the file
  227. - savegame::manager::delete_game(games_[index].name);
  228. + savegame::delete_game(games_[index].name());
  229.  
  230. // Remove it from the list of saves
  231. games_.erase(games_.begin() + index);
  232. diff --git a/src/gui/dialogs/game_load.cpp b/src/gui/dialogs/game_load.cpp
  233. index d071c22..6d5ee86 100644
  234. --- a/src/gui/dialogs/game_load.cpp
  235. +++ b/src/gui/dialogs/game_load.cpp
  236. @@ -133,7 +133,7 @@ void tgame_load::pre_show(CVideo& /*video*/, twindow& window)
  237.  
  238. {
  239. cursor::setter cur(cursor::WAIT);
  240. - games_ = savegame::manager::get_saves_list();
  241. + games_ = savegame::get_saves_list();
  242. }
  243. fill_game_list(window, games_);
  244.  
  245. @@ -157,7 +157,7 @@ void tgame_load::fill_game_list(twindow& window
  246. std::map<std::string, string_map> data;
  247. string_map item;
  248.  
  249. - item["label"] = game.name;
  250. + item["label"] = game.name();
  251. data.insert(std::make_pair("filename", item));
  252.  
  253. item["label"] = game.format_time_summary();
  254. @@ -239,28 +239,21 @@ void tgame_load::display_savegame(twindow& window)
  255. preview_pane.set_visible(twidget::VISIBLE);
  256.  
  257. savegame::save_info& game = games_[selected_row];
  258. - filename_ = game.name;
  259. + filename_ = game.name();
  260.  
  261. - config cfg_summary;
  262. - std::string dummy;
  263. -
  264. - try {
  265. - savegame::manager::load_summary(game.name, cfg_summary, &dummy);
  266. - } catch(game::load_game_failed&) {
  267. - cfg_summary["corrupt"] = "yes";
  268. - }
  269. + const config& summary= game.summary();
  270.  
  271. find_widget<timage>(&window, "imgLeader", false).
  272. - set_label(cfg_summary["leader_image"]);
  273. + set_label(summary["leader_image"]);
  274.  
  275. find_widget<tminimap>(&window, "minimap", false).
  276. - set_map_data(cfg_summary["map_data"]);
  277. + set_map_data(summary["map_data"]);
  278.  
  279. - find_widget<tlabel>(&window, "lblScenario", false).set_label(game.name);
  280. + find_widget<tlabel>(&window, "lblScenario", false).set_label(game.name());
  281.  
  282. std::stringstream str;
  283. str << game.format_time_local();
  284. - evaluate_summary_string(str, cfg_summary);
  285. + evaluate_summary_string(str, summary);
  286.  
  287. find_widget<tlabel>(&window, "lblSummary", false).set_label(str.str());
  288.  
  289. @@ -344,7 +337,7 @@ void tgame_load::delete_button_callback(twindow& window)
  290. }
  291.  
  292. // Delete the file
  293. - savegame::manager::delete_game(games_[index].name);
  294. + savegame::delete_game(games_[index].name());
  295.  
  296. // Remove it from the list of saves
  297. games_.erase(games_.begin() + index);
  298. diff --git a/src/play_controller.cpp b/src/play_controller.cpp
  299. index 50d5cd9..9e21e45 100644
  300. --- a/src/play_controller.cpp
  301. +++ b/src/play_controller.cpp
  302. @@ -1103,7 +1103,7 @@ void play_controller::expand_autosaves(std::vector<std::string>& items)
  303. std::vector<std::string> newsaves;
  304. for (unsigned int turn = this->turn(); turn != 0; turn--) {
  305. std::string name = gamestate_.classification().label + "-" + _("Auto-Save") + lexical_cast<std::string>(turn);
  306. - if (savegame::manager::save_game_exists(name, preferences::compress_saves())) {
  307. + if (savegame::save_game_exists(name, preferences::compress_saves())) {
  308. if(preferences::compress_saves()) {
  309. newsaves.push_back(name + ".gz");
  310. } else {
  311. diff --git a/src/playcampaign.cpp b/src/playcampaign.cpp
  312. index 51bcea8..973a01a 100644
  313. --- a/src/playcampaign.cpp
  314. +++ b/src/playcampaign.cpp
  315. @@ -396,7 +396,7 @@ LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_
  316. // need to change this test.
  317. if (res == VICTORY || (io_type != IO_NONE && res == DEFEAT)) {
  318. if (preferences::delete_saves())
  319. - savegame::manager::clean_saves(gamestate.classification().label);
  320. + savegame::clean_saves(gamestate.classification().label);
  321.  
  322. if (preferences::save_replays() && end_level.replay_save) {
  323. savegame::replay_savegame save(gamestate, preferences::compress_saves());
  324. @@ -606,7 +606,7 @@ LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_
  325.  
  326. if (gamestate.classification().campaign_type == "scenario"){
  327. if (preferences::delete_saves())
  328. - savegame::manager::clean_saves(gamestate.classification().label);
  329. + savegame::clean_saves(gamestate.classification().label);
  330. }
  331. return VICTORY;
  332. }
  333. diff --git a/src/savegame.cpp b/src/savegame.cpp
  334. index 2a19dca..6fd5dcf 100644
  335. --- a/src/savegame.cpp
  336. +++ b/src/savegame.cpp
  337. @@ -132,9 +132,174 @@ static lg::log_domain log_engine("engine");
  338.  
  339. namespace savegame {
  340.  
  341. +class save_index_class
  342. +{
  343. +public:
  344. + void rebuild(const std::string& name) {
  345. + std::string filename= name;
  346. + replace_space2underbar(filename);
  347. + time_t modified= file_create_time(get_saves_dir() + "/" + filename);
  348. + rebuild(name, modified);
  349. + }
  350. + void rebuild(const std::string& name, const time_t& modified) {
  351. + log_scope("load_summary_from_file");
  352. + config& summary= data(name);
  353. + try {
  354. + config full;
  355. + std::string dummy;
  356. + read_save_file(name, full, &dummy);
  357. + ::extract_summary_from_config(full, summary);
  358. + } catch(game::load_game_failed&) {
  359. + summary["corrupt"] = true;
  360. + }
  361. + summary["mod_time"] = str_cast(static_cast<int>(modified));
  362. + write_save_index();
  363. + }
  364. + void set_modified(const std::string& name, const time_t& modified) {
  365. + modified_[name]= modified;
  366. + }
  367. + config& get(const std::string& name) {
  368. + config& result= data(name);
  369. + time_t m= modified_[name];
  370. + config::attribute_value& mod_time= result["mod_time"];
  371. + if (mod_time.empty() || static_cast<time_t>(mod_time.to_int()) != m) {
  372. + rebuild(name, m);
  373. + }
  374. + return result;
  375. + }
  376. +public:
  377. + void write_save_index() {
  378. + log_scope("write_save_index()");
  379. + try {
  380. + scoped_ostream stream = ostream_file(get_save_index_file());
  381. + if (preferences::compress_saves()) {
  382. + write_gz(*stream, data());
  383. + } else {
  384. + write(*stream, data());
  385. + }
  386. + } catch(io_exception& e) {
  387. + ERR_SAVE << "error writing to save index file: '" << e.what() << "'\n";
  388. + }
  389. + }
  390. +
  391. +public:
  392. + save_index_class() : loaded_(false) {}
  393. +private:
  394. + config& data(const std::string& name) {
  395. + std::string save= name;
  396. + /*
  397. + * All saves are .gz files now so make sure we use that name when opening
  398. + * a file. If not some parts of the code use the name with and some parts
  399. + * without the .gz suffix.
  400. + */
  401. + if(save.length() < 3 || save.substr(save.length() - 3) != ".gz") {
  402. + save += ".gz";
  403. + }
  404. +
  405. + config& cfg = data();
  406. + if (config &sv = cfg.find_child("save", "save", save)) {
  407. + return sv;
  408. + }
  409. +
  410. + config &res = cfg.add_child("save");
  411. + res["save"] = save;
  412. + return res;
  413. + }
  414. + config& data() {
  415. + if(loaded_ == false) {
  416. + try {
  417. + const std::string &filename = get_save_index_file();
  418. + scoped_istream stream = istream_file(filename);
  419. + if(is_gzip_file(filename)) {
  420. + try {
  421. + read_gz(data_, *stream);
  422. + } catch (boost::iostreams::gzip_error&) {
  423. + read(data_, *stream);
  424. + }
  425. + } else {
  426. + read(data_, *stream);
  427. + }
  428. + } catch(io_exception& e) {
  429. + ERR_SAVE << "error reading save index: '" << e.what() << "'\n";
  430. + } catch(config::error&) {
  431. + ERR_SAVE << "error parsing save index config file\n";
  432. + data_.clear();
  433. + }
  434. +
  435. + loaded_ = true;
  436. + }
  437. +
  438. + return data_;
  439. + }
  440. +private:
  441. + bool loaded_;
  442. + config data_;
  443. + std::map< std::string, time_t > modified_;
  444. +} save_index_manager;
  445. +
  446. +class filename_filter {
  447. +public:
  448. + filename_filter(const std::string& filter) : filter_(filter) {
  449. + }
  450. + bool operator()(const std::string& filename) const {
  451. + return filename.end() == std::search(filename.begin(), filename.end(),
  452. + filter_.begin(), filter_.end());
  453. + }
  454. +private:
  455. + std::string filter_;
  456. +};
  457. +
  458. +class create_save_info {
  459. +public:
  460. + create_save_info(const std::string* d= NULL) : dir(d ? *d : get_saves_dir()) {
  461. + }
  462. + save_info operator()(const std::string& filename) const {
  463. + std::string name= filename;
  464. + replace_underbar2space(name);
  465. + time_t modified= file_create_time(dir + "/" + filename);
  466. + save_index_manager.set_modified(name, modified);
  467. + return save_info(name, modified);
  468. + }
  469. + const std::string dir;
  470. +};
  471. +
  472. +/** Get a list of available saves. */
  473. +std::vector<save_info> get_saves_list(const std::string* dir, const std::string* filter)
  474. +{
  475. + create_save_info creator(dir);
  476. +
  477. + std::vector<std::string> filenames;
  478. + get_files_in_dir(creator.dir,&filenames);
  479. +
  480. + if (filter) {
  481. + filenames.erase(std::remove_if(filenames.begin(), filenames.end(),
  482. + filename_filter(*filter)));
  483. + }
  484. +
  485. + std::vector<save_info> result;
  486. + std::transform(filenames.begin(), filenames.end(),
  487. + std::back_inserter(result), creator);
  488. + return result;
  489. +}
  490. +
  491. +save_info::save_info(const std::string& n, const time_t& m) : name_(n), modified_(m) {
  492. +}
  493. +
  494. +const std::string& save_info::name() const {
  495. + return name_;
  496. +}
  497. +
  498. +const time_t& save_info::modified() const {
  499. + return modified_;
  500. +}
  501. +
  502. +const config& save_info::summary() const {
  503. + return save_index_manager.get(name());
  504. +}
  505. +
  506. const std::string save_info::format_time_local() const{
  507. char time_buf[256] = {0};
  508. - tm* tm_l = localtime(&time_modified);
  509. + tm* tm_l = localtime(&modified());
  510. if (tm_l) {
  511. const size_t res = strftime(time_buf,sizeof(time_buf),
  512. (preferences::use_twelve_hour_clock_format() ? _("%a %b %d %I:%M %p %Y") : _("%a %b %d %H:%M %Y")),
  513. @@ -143,7 +315,7 @@ const std::string save_info::format_time_local() const{
  514. time_buf[0] = 0;
  515. }
  516. } else {
  517. - LOG_SAVE << "localtime() returned null for time " << time_modified << ", save " << name;
  518. + LOG_SAVE << "localtime() returned null for time " << this->modified() << ", save " << name();
  519. }
  520.  
  521. return time_buf;
  522. @@ -151,7 +323,7 @@ const std::string save_info::format_time_local() const{
  523.  
  524. const std::string save_info::format_time_summary() const
  525. {
  526. - time_t t = time_modified;
  527. + time_t t = modified();
  528. time_t curtime = time(NULL);
  529. const struct tm* timeptr = localtime(&curtime);
  530. if(timeptr == NULL) {
  531. @@ -205,32 +377,26 @@ const std::string save_info::format_time_summary() const
  532. return buf;
  533. }
  534.  
  535. -/**
  536. - * A structure for comparing to save_info objects based on their modified time.
  537. - * If the times are equal, will order based on the name.
  538. - */
  539. -struct save_info_less_time {
  540. - bool operator()(const save_info& a, const save_info& b) const {
  541. - if (a.time_modified > b.time_modified) {
  542. - return true;
  543. - } else if (a.time_modified < b.time_modified) {
  544. - return false;
  545. +bool save_info_less_time::operator() (const save_info& a, const save_info& b) const {
  546. + if (a.modified() > b.modified()) {
  547. + return true;
  548. + } else if (a.modified() < b.modified()) {
  549. + return false;
  550. // Special funky case; for files created in the same second,
  551. // a replay file sorts less than a non-replay file. Prevents
  552. // a timing-dependent bug where it may look like, at the end
  553. // of a scenario, the replay and the autosave for the next
  554. // scenario are displayed in the wrong order.
  555. - } else if (a.name.find(_(" replay"))==std::string::npos && b.name.find(_(" replay"))!=std::string::npos) {
  556. - return true;
  557. - } else if (a.name.find(_(" replay"))!=std::string::npos && b.name.find(_(" replay"))==std::string::npos) {
  558. - return false;
  559. - } else {
  560. - return a.name > b.name;
  561. - }
  562. + } else if (a.name().find(_(" replay"))==std::string::npos && b.name().find(_(" replay"))!=std::string::npos) {
  563. + return true;
  564. + } else if (a.name().find(_(" replay"))!=std::string::npos && b.name().find(_(" replay"))==std::string::npos) {
  565. + return false;
  566. + } else {
  567. + return a.name() > b.name();
  568. }
  569. -};
  570. +}
  571.  
  572. -void manager::read_save_file(const std::string& name, config& cfg, std::string* error_log)
  573. +void read_save_file(const std::string& name, config& cfg, std::string* error_log)
  574. {
  575. std::string modified_name = name;
  576. replace_space2underbar(modified_name);
  577. @@ -272,16 +438,7 @@ void manager::read_save_file(const std::string& name, config& cfg, std::string*
  578. }
  579. }
  580.  
  581. -void manager::load_summary(const std::string& name, config& cfg_summary, std::string* error_log){
  582. - log_scope("load_game_summary");
  583. -
  584. - config cfg;
  585. - read_save_file(name,cfg,error_log);
  586. -
  587. - ::extract_summary_from_config(cfg, cfg_summary);
  588. -}
  589. -
  590. -bool manager::save_game_exists(const std::string& name, const bool compress_saves)
  591. +bool save_game_exists(const std::string& name, const bool compress_saves)
  592. {
  593. std::string fname = name;
  594. replace_space2underbar(fname);
  595. @@ -293,61 +450,36 @@ bool manager::save_game_exists(const std::string& name, const bool compress_save
  596. return file_exists(get_saves_dir() + "/" + fname);
  597. }
  598.  
  599. -std::vector<save_info> manager::get_saves_list(const std::string *dir, const std::string* filter)
  600. -{
  601. - // Don't use a reference, it seems to break on arklinux with GCC-4.3.
  602. - const std::string saves_dir = (dir) ? *dir : get_saves_dir();
  603. -
  604. - std::vector<std::string> saves;
  605. - get_files_in_dir(saves_dir,&saves);
  606. -
  607. - std::vector<save_info> res;
  608. - for(std::vector<std::string>::iterator i = saves.begin(); i != saves.end(); ++i) {
  609. - if(filter && std::search(i->begin(), i->end(), filter->begin(), filter->end()) == i->end()) {
  610. - continue;
  611. - }
  612. -
  613. - const time_t modified = file_create_time(saves_dir + "/" + *i);
  614. -
  615. - replace_underbar2space(*i);
  616. - res.push_back(save_info(*i,modified));
  617. - }
  618. -
  619. - std::sort(res.begin(),res.end(),save_info_less_time());
  620. -
  621. - return res;
  622. -}
  623. -
  624. -void manager::clean_saves(const std::string &label)
  625. +void clean_saves(const std::string &label)
  626. {
  627. std::vector<save_info> games = get_saves_list();
  628. std::string prefix = label + "-" + _("Auto-Save");
  629. std::cerr << "Cleaning saves with prefix '" << prefix << "'\n";
  630. for (std::vector<save_info>::iterator i = games.begin(); i != games.end(); ++i) {
  631. - if (i->name.compare(0, prefix.length(), prefix) == 0) {
  632. - std::cerr << "Deleting savegame '" << i->name << "'\n";
  633. - delete_game(i->name);
  634. + if (i->name().compare(0, prefix.length(), prefix) == 0) {
  635. + std::cerr << "Deleting savegame '" << i->name() << "'\n";
  636. + delete_game(i->name());
  637. }
  638. }
  639. }
  640.  
  641. -void manager::remove_old_auto_saves(const int autosavemax, const int infinite_auto_saves)
  642. +void remove_old_auto_saves(const int autosavemax, const int infinite_auto_saves)
  643. {
  644. const std::string auto_save = _("Auto-Save");
  645. int countdown = autosavemax;
  646. if (countdown == infinite_auto_saves)
  647. return;
  648.  
  649. - std::vector<save_info> games = get_saves_list(NULL, &auto_save);
  650. + std::vector<save_info> games = get_saves_list(&auto_save);
  651. for (std::vector<save_info>::iterator i = games.begin(); i != games.end(); ++i) {
  652. if (countdown-- <= 0) {
  653. - LOG_SAVE << "Deleting savegame '" << i->name << "'\n";
  654. - delete_game(i->name);
  655. + LOG_SAVE << "Deleting savegame '" << i->name() << "'\n";
  656. + delete_game(i->name());
  657. }
  658. }
  659. }
  660.  
  661. -void manager::delete_game(const std::string& name)
  662. +void delete_game(const std::string& name)
  663. {
  664. std::string modified_name = name;
  665. replace_space2underbar(modified_name);
  666. @@ -356,72 +488,6 @@ void manager::delete_game(const std::string& name)
  667. remove((get_saves_dir() + "/" + modified_name).c_str());
  668. }
  669.  
  670. -bool save_index::save_index_loaded = false;
  671. -config save_index::save_index_cfg;
  672. -
  673. -config& save_index::load()
  674. -{
  675. - if(save_index_loaded == false) {
  676. - try {
  677. - const std::string &filename = get_save_index_file();
  678. - scoped_istream stream = istream_file(filename);
  679. - if(is_gzip_file(filename)) {
  680. - try {
  681. - read_gz(save_index_cfg, *stream);
  682. - } catch (boost::iostreams::gzip_error&) {
  683. - read(save_index_cfg, *stream);
  684. - }
  685. - } else {
  686. - read(save_index_cfg, *stream);
  687. - }
  688. - } catch(io_exception& e) {
  689. - ERR_SAVE << "error reading save index: '" << e.what() << "'\n";
  690. - } catch(config::error&) {
  691. - ERR_SAVE << "error parsing save index config file\n";
  692. - save_index_cfg.clear();
  693. - }
  694. -
  695. - save_index_loaded = true;
  696. - }
  697. -
  698. - return save_index_cfg;
  699. -}
  700. -
  701. -config& save_index::save_summary(std::string save)
  702. -{
  703. - /*
  704. - * All saves are .gz files now so make sure we use that name when opening
  705. - * a file. If not some parts of the code use the name with and some parts
  706. - * without the .gz suffix.
  707. - */
  708. - if(save.length() < 3 || save.substr(save.length() - 3) != ".gz") {
  709. - save += ".gz";
  710. - }
  711. -
  712. - config& cfg = load();
  713. - if (config &sv = cfg.find_child("save", "save", save))
  714. - return sv;
  715. -
  716. - config &res = cfg.add_child("save");
  717. - res["save"] = save;
  718. - return res;
  719. -}
  720. -
  721. -void save_index::write_save_index()
  722. -{
  723. - log_scope("write_save_index()");
  724. - try {
  725. - scoped_ostream stream = ostream_file(get_save_index_file());
  726. - if (preferences::compress_saves()) {
  727. - write_gz(*stream, load());
  728. - } else {
  729. - write(*stream, load());
  730. - }
  731. - } catch(io_exception& e) {
  732. - ERR_SAVE << "error writing to save index file: '" << e.what() << "'\n";
  733. - }
  734. -}
  735. -
  736. loadgame::loadgame(display& gui, const config& game_config, game_state& gamestate)
  737. : game_config_(game_config)
  738. , gui_(gui)
  739. @@ -443,18 +509,12 @@ void loadgame::show_dialog(bool show_replay, bool cancel_orders)
  740.  
  741. if (load_dialog.get_retval() == gui2::twindow::OK){
  742. if (load_dialog.reselect_difficulty()) {
  743. + create_save_info creator;
  744. + save_info info= creator(load_dialog.filename());
  745. + const config& summary= info.summary();
  746.  
  747. - config cfg_summary;
  748. - std::string dummy;
  749. -
  750. - try {
  751. - manager::load_summary(load_dialog.filename(), cfg_summary, &dummy);
  752. - } catch(game::load_game_failed&) {
  753. - cfg_summary["corrupt"] = "yes";
  754. - }
  755. -
  756. - const std::string difficulty_descriptions = cfg_summary["campaign_difficulty_descriptions"];
  757. - const std::string difficulties = cfg_summary["campaign_difficulties"];
  758. + const std::string difficulty_descriptions = summary["campaign_difficulty_descriptions"];
  759. + const std::string difficulties = summary["campaign_difficulties"];
  760.  
  761. std::vector<std::string> difficulty_options = utils::split(difficulty_descriptions, ';');
  762. std::vector<std::string> difficulty_list = utils::split(difficulties, ',');
  763. @@ -511,7 +571,7 @@ void loadgame::load_game(
  764. throw load_game_cancelled_exception();
  765.  
  766. std::string error_log;
  767. - manager::read_save_file(filename_, load_config_, &error_log);
  768. + read_save_file(filename_, load_config_, &error_log);
  769.  
  770. if(!error_log.empty()) {
  771. try {
  772. @@ -610,7 +670,7 @@ void loadgame::load_multiplayer_game()
  773. cursor::setter cur(cursor::WAIT);
  774. log_scope("load_game");
  775.  
  776. - manager::read_save_file(filename_, load_config_, &error_log);
  777. + read_save_file(filename_, load_config_, &error_log);
  778. copy_era(load_config_);
  779.  
  780. gamestate_ = game_state(load_config_);
  781. @@ -773,7 +833,7 @@ int savegame::show_save_dialog(CVideo& video, const std::string& message, const
  782. bool savegame::check_overwrite(CVideo& video)
  783. {
  784. std::string filename = filename_;
  785. - if (manager::save_game_exists(filename, compress_saves_)) {
  786. + if (save_game_exists(filename, compress_saves_)) {
  787. std::stringstream message;
  788. message << _("Save already exists. Do you want to overwrite it?") << "\n" << _("Name: ") << filename;
  789. int retval = gui2::show_message(video, _("Overwrite?"), message.str(), gui2::tmessage::yes_no_buttons);
  790. @@ -905,20 +965,11 @@ void savegame::write_game(config_writer &out) const
  791.  
  792. void savegame::finish_save_game(const config_writer &out)
  793. {
  794. - std::string name = gamestate_.classification().label;
  795. - replace_space2underbar(name);
  796. - std::string fname(get_saves_dir() + "/" + name);
  797. -
  798. try {
  799. if(!out.good()) {
  800. throw game::save_game_failed(_("Could not write to file"));
  801. }
  802. -
  803. - config& summary = save_index::save_summary(gamestate_.classification().label);
  804. - extract_summary_data_from_save(summary);
  805. - const int mod_time = static_cast<int>(file_create_time(fname));
  806. - summary["mod_time"] = str_cast(mod_time);
  807. - save_index::write_save_index();
  808. + save_index_manager.rebuild(gamestate_.classification().label);
  809. } catch(io_exception& e) {
  810. throw game::save_game_failed(e.what());
  811. }
  812. @@ -937,75 +988,6 @@ scoped_ostream savegame::open_save_game(const std::string &label)
  813. }
  814. }
  815.  
  816. -void savegame::extract_summary_data_from_save(config& out)
  817. -{
  818. - const bool has_replay = gamestate_.replay_data.empty() == false;
  819. - bool has_snapshot(gamestate_.snapshot.child("side"));
  820. -
  821. - out["replay"] = has_replay;
  822. - out["snapshot"] = has_snapshot;
  823. -
  824. - out["label"] = gamestate_.classification().label;
  825. - out["parent"] = gamestate_.classification().parent;
  826. - out["campaign"] = gamestate_.classification().campaign;
  827. - out["campaign_type"] = gamestate_.classification().campaign_type;
  828. - out["campaign_difficulties"] = utils::join<std::vector<std::string> >(gamestate_.classification().campaign_difficulties, ",");
  829. - out["campaign_difficulty_descriptions"] = utils::join<std::vector<std::string> >
  830. - (gamestate_.classification().campaign_difficulty_descriptions, ";");
  831. - out["scenario"] = gamestate_.classification().scenario;
  832. - out["difficulty"] = gamestate_.classification().difficulty;
  833. - out["version"] = gamestate_.classification().version;
  834. - out["corrupt"] = "";
  835. -
  836. - if(has_snapshot) {
  837. - out["turn"] = gamestate_.snapshot["turn_at"];
  838. - if(gamestate_.snapshot["turns"] != "-1") {
  839. - out["turn"] = out["turn"].str() + "/" + gamestate_.snapshot["turns"].str();
  840. - }
  841. - }
  842. -
  843. - // Find the first human leader so we can display their icon in the load menu.
  844. -
  845. - /** @todo Ideally we should grab all leaders if there's more than 1 human player? */
  846. - std::string leader;
  847. -
  848. - bool shrouded = false;
  849. -
  850. - const config& snapshot = has_snapshot ? gamestate_.snapshot : gamestate_.starting_pos;
  851. - foreach (const config &side, snapshot.child_range("side"))
  852. - {
  853. - if (side["controller"] != "human") {
  854. - continue;
  855. - }
  856. - if (side["shroud"].to_bool()) {
  857. - shrouded = true;
  858. - }
  859. -
  860. - foreach (const config &u, side.child_range("unit"))
  861. - {
  862. - if (u["canrecruit"].to_bool()) {
  863. - leader = u["id"].str();
  864. - break;
  865. - }
  866. - }
  867. - }
  868. -
  869. - out["leader"] = leader;
  870. - out["map_data"] = "";
  871. -
  872. - if(!shrouded) {
  873. - if(has_snapshot) {
  874. - if (!gamestate_.snapshot.find_child("side", "shroud", "yes")) {
  875. - out["map_data"] = gamestate_.snapshot["map_data"];
  876. - }
  877. - } else if(has_replay) {
  878. - if (!gamestate_.starting_pos.find_child("side", "shroud", "yes")) {
  879. - out["map_data"] = gamestate_.starting_pos["map_data"];
  880. - }
  881. - }
  882. - }
  883. -}
  884. -
  885. scenariostart_savegame::scenariostart_savegame(game_state &gamestate, const bool compress_saves)
  886. : savegame(gamestate, compress_saves)
  887. {
  888. @@ -1055,7 +1037,7 @@ void autosave_savegame::autosave(const bool disable_autosave, const int autosave
  889.  
  890. save_game_automatic(gui_.video());
  891.  
  892. - manager::remove_old_auto_saves(autosave_max, infinite_autosaves);
  893. + remove_old_auto_saves(autosave_max, infinite_autosaves);
  894. }
  895.  
  896. void autosave_savegame::create_filename()
  897. diff --git a/src/savegame.hpp b/src/savegame.hpp
  898. index 784939b..3d8d5d5 100644
  899. --- a/src/savegame.hpp
  900. +++ b/src/savegame.hpp
  901. @@ -31,66 +31,47 @@ struct illegal_filename_exception {};
  902. namespace savegame {
  903.  
  904. /** Filename and modification date for a file list */
  905. -struct save_info {
  906. - save_info(const std::string& n, time_t t) : name(n), time_modified(t) {}
  907. - std::string name;
  908. - time_t time_modified;
  909. -
  910. +class save_info {
  911. +private:
  912. + friend class create_save_info;
  913. +private:
  914. + save_info(const std::string& name, const time_t& modified);
  915. +public:
  916. + const std::string& name() const;
  917. + const time_t& modified() const;
  918. +public:
  919. const std::string format_time_summary() const;
  920. const std::string format_time_local() const;
  921. + const config& summary() const;
  922. +private:
  923. + std::string name_;
  924. + time_t modified_;
  925. };
  926.  
  927. /**
  928. -Container for a couple of savefile manipulating methods.
  929. -Note: You are not supposed to instantiate this class.
  930. -*/
  931. -class manager
  932. -{
  933. -public:
  934. - /** Read summary information out of an existing savefile. */
  935. - static void load_summary(const std::string& name, config& cfg_summary, std::string* error_log);
  936. - /** Read the complete config information out of a savefile. */
  937. - static void read_save_file(const std::string& name, config& cfg, std::string* error_log);
  938. -
  939. - /** Returns true if there is already a savegame with that name. */
  940. - static bool save_game_exists(const std::string& name, const bool compress_saves);
  941. - /** Get a list of available saves. */
  942. - static std::vector<save_info> get_saves_list(const std::string *dir = NULL, const std::string* filter = NULL);
  943. -
  944. - /** Delete all autosaves of a certain scenario. */
  945. - static void clean_saves(const std::string &label);
  946. - /** Remove autosaves that are no longer needed (according to the autosave policy in the preferences). */
  947. - static void remove_old_auto_saves(const int autosavemax, const int infinite_auto_saves);
  948. - /** Delete a savegame. */
  949. - static void delete_game(const std::string& name);
  950. -
  951. -private:
  952. - /** Default-Constructor (don't instantiate this class) */
  953. - manager() {}
  954. + * A structure for comparing to save_info objects based on their modified time.
  955. + * If the times are equal, will order based on the name.
  956. + */
  957. +struct save_info_less_time {
  958. + bool operator()(const save_info& a, const save_info& b) const;
  959. };
  960.  
  961. -/**
  962. -Container for methods dealing with the save_index file.
  963. -Note: You are not supposed to instantiate this class.
  964. -*/
  965. -class save_index
  966. -{
  967. -public:
  968. - /** Determines/Adds the "save"-child of the summary config. */
  969. - static config& save_summary(std::string save);
  970. - /** Update the save_index file with changed savegame information. */
  971. - static void write_save_index();
  972. +std::vector<save_info> get_saves_list(const std::string* dir= NULL, const std::string* filter = NULL);
  973.  
  974. -private:
  975. - /** Default-Constructor (don't instantiate this class) */
  976. - save_index() {}
  977. +/** Read the complete config information out of a savefile. */
  978. +void read_save_file(const std::string& name, config& cfg, std::string* error_log);
  979.  
  980. - /** Read the complete config information out of the save_index file. */
  981. - static config& load();
  982. +/** Returns true if there is already a savegame with that name. */
  983. +bool save_game_exists(const std::string& name, const bool compress_saves);
  984.  
  985. - static bool save_index_loaded; /** Tells, if the save_index config has been already loaded. */
  986. - static config save_index_cfg; /** save_index config (who would have guessed that ;-). */
  987. -};
  988. +/** Delete all autosaves of a certain scenario. */
  989. +void clean_saves(const std::string &label);
  990. +
  991. +/** Remove autosaves that are no longer needed (according to the autosave policy in the preferences). */
  992. +void remove_old_auto_saves(const int autosavemax, const int infinite_auto_saves);
  993. +
  994. +/** Delete a savegame. */
  995. +void delete_game(const std::string& name);
  996.  
  997. /** The class for loading a savefile. */
  998. class loadgame
  999. @@ -212,8 +193,7 @@ private:
  1000. void finish_save_game(const config_writer &out);
  1001. /** Throws game::save_game_failed. */
  1002. scoped_ostream open_save_game(const std::string &label);
  1003. - /** Read the summary data from a savegame to display this information in the load-game dialog. */
  1004. - void extract_summary_data_from_save(config& out);
  1005. + friend class save_info;
  1006.  
  1007. game_state& gamestate_;
Advertisement
Add Comment
Please, Sign In to add comment