diff --git a/data/gui/default/window/data_manage.cfg b/data/gui/default/window/data_manage.cfg
new file mode 100644
index 00000000000..96c8a07d538
--- /dev/null
+++ b/data/gui/default/window/data_manage.cfg
@@ -0,0 +1,370 @@
+#textdomain wesnoth-lib
+###
+### Definition of the window to ask for the savegame filename
+###
+
+[window]
+ id = "data_manage"
+ description = "Persistence data management dialog."
+
+ [resolution]
+ definition = "default"
+
+ automatic_placement = "true"
+ vertical_placement = "top"
+ horizontal_placement = "center"
+
+ [linked_group]
+ id = "filename"
+ fixed_width = "true"
+ [/linked_group]
+
+ [linked_group]
+ id = "date"
+ fixed_width = "true"
+ [/linked_group]
+
+ [grid]
+
+ [row]
+ grow_factor = 0
+
+ [column]
+ grow_factor = 1
+
+ border = "all"
+ border_size = 5
+ horizontal_alignment = "left"
+ [label]
+ id = "lblTitle"
+ definition = "title"
+
+ label = _ "Manage Data"
+ [/label]
+
+ [/column]
+
+ [/row]
+
+ [row]
+ grow_factor = 1
+
+ [column]
+ grow_factor = 1
+
+ horizontal_grow = "true"
+
+ [grid]
+
+ [row]
+ grow_factor = 1
+
+ [column]
+ grow_factor = 1
+
+ border = "all"
+ border_size = 5
+ horizontal_grow = "true"
+
+ [grid]
+
+ [row]
+ [column]
+ horizontal_alignment = "left"
+ border = "bottom"
+ border_size = 10
+
+ [label]
+ id = "lblChoose"
+ definition = "default"
+
+ label = _ "Choose the game to load"
+ [/label]
+
+ [/column]
+
+ [/row]
+
+ [row]
+ [column]
+ horizontal_alignment = "left"
+
+ [grid]
+
+ [row]
+
+ [column]
+ border = "right"
+ border_size = 10
+ vertical_alignment = "center"
+
+ [label]
+ id = "lblFilter"
+ definition = "default"
+
+ label = _ "Filter"
+ [/label]
+
+ [/column]
+
+ [column]
+ border = "bottom"
+ border_size = 10
+
+ [text_box]
+ id = "txtFilter"
+ definition = "default"
+ label = ""
+ [/text_box]
+
+ [/column]
+
+ [/row]
+
+ [/grid]
+
+ [/column]
+
+ [/row]
+
+ [row]
+
+ [column]
+ grow_factor = 1
+ horizontal_grow = "true"
+
+ border = "bottom"
+ border_size = 10
+
+ [listbox]
+ id = "persist_list"
+ definition = "default"
+ [header]
+
+ [row]
+
+ [column]
+ grow_factor = 1
+ horizontal_grow = "true"
+
+ [label]
+ id = "filename"
+ definition = "default"
+ linked_group = "filename"
+
+ label = _ "Name"
+ [/label]
+
+ [/column]
+
+ [column]
+ grow_factor = 1
+ horizontal_grow = "true"
+
+ [label]
+ id = "date"
+ definition = "default"
+ linked_group = "date"
+
+ label = _ "Date"
+ [/label]
+
+ [/column]
+
+ [/row]
+
+ [/header]
+
+ [list_definition]
+
+ [row]
+
+ [column]
+
+ [toggle_panel]
+ definition = "default"
+
+ return_value_id = "ok"
+ [grid]
+
+ [row]
+
+ [column]
+ grow_factor = 1
+ horizontal_grow = "true"
+
+ border = "bottom"
+ border_size = 5
+
+ [label]
+ id = "filename"
+ definition = "default"
+ linked_group = "filename"
+ [/label]
+
+ [/column]
+
+ [column]
+ grow_factor = 1
+ horizontal_grow = "true"
+
+ border = "bottom"
+ border_size = 5
+
+ [label]
+ id = "date"
+ definition = "default"
+ linked_group = "date"
+ [/label]
+
+ [/column]
+
+ [/row]
+
+ [/grid]
+
+ [/toggle_panel]
+
+ [/column]
+
+ [/row]
+
+ [/list_definition]
+
+ [/listbox]
+
+ [/column]
+
+ [/row]
+
+ [row]
+
+ [column]
+
+ [grid]
+
+ [row]
+
+ [column]
+ horizontal_alignment = "left"
+
+ border = "bottom"
+ border_size = 10
+
+ [button]
+ id = "clear"
+ definition = "default"
+
+ size_text = _ "Clear"
+ label = _ "Clear"
+ [/button]
+
+ [/column]
+
+ [column]
+ grow_factor = 1
+ horizontal_grow = "true"
+
+ border = "bottom"
+ border_size = 10
+
+ [button]
+ id = "restore"
+ definition = "default"
+
+ size_text = _ "Restore"
+ label = _ "Restore"
+ [/button]
+
+ [/column]
+
+ [column]
+ grow_factor = 1
+ horizontal_grow = "true"
+
+ border = "bottom"
+ border_size = 10
+
+ [button]
+ id = "backup"
+ definition = "default"
+
+ size_text = _ "Backup"
+ label = _ "Backup"
+ [/button]
+
+ [/column]
+
+ [/row]
+
+ [/grid]
+
+ [/column]
+
+ [/row]
+
+ [/grid]
+
+ [/column]
+
+ [/row]
+
+ [/grid]
+
+ [/column]
+
+ [/row]
+
+ [row]
+ grow_factor = 0
+
+ [column]
+ grow_factor = 1
+ horizontal_grow = "true"
+
+ [grid]
+
+ [row]
+
+ [column]
+ grow_factor = 1
+ border = "all"
+ border_size = 5
+ horizontal_alignment = "right"
+
+ [button]
+ id = "ok"
+ definition = "default"
+
+ size_text = _ "OK"
+ label = _ "OK"
+ [/button]
+
+ [/column]
+
+ [column]
+ border = "all"
+ border_size = 5
+
+ [button]
+ id = "cancel"
+ definition = "default"
+
+ label = _ "Cancel"
+ [/button]
+
+ [/column]
+
+ [/row]
+
+ [/grid]
+
+ [/column]
+
+ [/row]
+
+ [/grid]
+
+ [/resolution]
+
+[/window]
diff --git a/projectfiles/VC9/wesnoth.vcproj b/projectfiles/VC9/wesnoth.vcproj
index 7209d1c4548..a3bb5f156d4 100644
--- a/projectfiles/VC9/wesnoth.vcproj
+++ b/projectfiles/VC9/wesnoth.vcproj
@@ -1858,6 +1858,34 @@
/>
+
+
+
+
+
+
+
+
+
+
+
@@ -6989,6 +7017,10 @@
RelativePath="..\..\src\gui\dialogs\campaign_selection.hpp"
>
+
+
diff --git a/src/gui/dialogs/data_manage.cpp b/src/gui/dialogs/data_manage.cpp
new file mode 100644
index 00000000000..b9afd655162
--- /dev/null
+++ b/src/gui/dialogs/data_manage.cpp
@@ -0,0 +1,260 @@
+/* $Id$ */
+/*
+ Copyright (C) 2010 by Jody Northup
+ Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2
+ or at your option any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY.
+
+ See the COPYING file for more details.
+*/
+
+#define GETTEXT_DOMAIN "wesnoth-lib"
+
+#include "gui/dialogs/data_manage.hpp"
+
+#include "foreach.hpp"
+#include "formula_string_utils.hpp"
+#include "gettext.hpp"
+#include "gui/auxiliary/log.hpp"
+#include "gui/dialogs/field.hpp"
+#include "gui/dialogs/game_delete.hpp"
+#include "gui/dialogs/helper.hpp"
+#include "gui/widgets/button.hpp"
+#include "gui/widgets/image.hpp"
+#include "gui/widgets/label.hpp"
+#ifdef GUI2_EXPERIMENTAL_LISTBOX
+#include "gui/widgets/list.hpp"
+#else
+#include "gui/widgets/listbox.hpp"
+#endif
+#include "gui/widgets/minimap.hpp"
+#include "gui/widgets/settings.hpp"
+#include "gui/widgets/text_box.hpp"
+#include "gui/widgets/window.hpp"
+#include "language.hpp"
+#include "preferences_display.hpp"
+
+#include
+#include
+
+namespace gui2 {
+
+
+REGISTER_WINDOW(data_manage)
+
+tdata_manage::tdata_manage(const config& cache_config)
+ : txtFilter_(register_text("txtFilter", false))
+ , filename_()
+ , games_()
+ , cache_config_(cache_config)
+ , last_words_()
+{
+}
+
+void tdata_manage::pre_show(CVideo& /*video*/, twindow& window)
+{
+ assert(txtFilter_);
+
+ ttext_box* filter = find_widget(
+ &window, "txtFilter", false, true);
+ window.keyboard_capture(filter);
+ filter->set_text_changed_callback(boost::bind(
+ &tdata_manage::filter_text_changed, this, _1, _2));
+
+ tlistbox* list = find_widget(
+ &window, "persist_list", false, true);
+ window.keyboard_capture(list);
+
+#ifdef GUI2_EXPERIMENTAL_LISTBOX
+ connect_signal_notify_modified(*list, boost::bind(
+ &tdata_manage::list_item_clicked
+ , *this
+ , boost::ref(window)));
+#else
+ list->set_callback_value_change(
+ dialog_callback);
+#endif
+
+ {
+ cursor::setter cur(cursor::WAIT);
+ games_ = savegame::manager::get_saves_list();
+ }
+ fill_game_list(window, games_);
+
+ connect_signal_mouse_left_click(
+ find_widget(&window, "clear", false)
+ , boost::bind(
+ &tdata_manage::delete_button_callback
+ , this
+ , boost::ref(window)));
+
+}
+
+void tdata_manage::fill_game_list(twindow& window
+ , std::vector& games)
+{
+ tlistbox& list = find_widget(&window, "persist_list", false);
+ list.clear();
+
+ foreach(const savegame::save_info game, games) {
+ std::map data;
+ string_map item;
+
+ item["label"] = game.name;
+ data.insert(std::make_pair("filename", item));
+
+ item["label"] = game.format_time_summary();
+ data.insert(std::make_pair("date", item));
+
+ list.add_row(data);
+ }
+}
+
+void tdata_manage::list_item_clicked(twindow& window)
+{
+}
+
+bool tdata_manage::filter_text_changed(ttext_* textbox, const std::string& text)
+{
+ twindow& window = *textbox->get_window();
+
+ tlistbox& list = find_widget(&window, "persist_list", false);
+
+ const std::vector words = utils::split(text, ' ');
+
+ if (words == last_words_)
+ return false;
+ last_words_ = words;
+
+ std::vector show_items(list.get_item_count(), true);
+
+ if(!text.empty()) {
+ for(unsigned int i = 0; i < list.get_item_count(); i++) {
+ tgrid* row = list.get_row_grid(i);
+
+ tgrid::iterator it = row->begin();
+ tlabel& filename_label =
+ find_widget(*it, "filename", false);
+
+ bool found = false;
+ foreach (const std::string& word, words){
+ found = std::search(filename_label.label().str().begin()
+ , filename_label.label().str().end()
+ , word.begin(), word.end()
+ , chars_equal_insensitive)
+ != filename_label.label().str().end();
+
+ if (! found) {
+ // one word doesn't match, we don't reach words.end()
+ break;
+ }
+ }
+
+ show_items[i] = found;
+ }
+ }
+
+ list.set_row_shown(show_items);
+
+ return false;
+}
+
+void tdata_manage::post_show(twindow& window)
+{
+}
+
+
+void tdata_manage::evaluate_summary_string(std::stringstream& str
+ , const config& cfg_summary){
+
+ const std::string& campaign_type = cfg_summary["campaign_type"];
+ if (cfg_summary["corrupt"].to_bool()) {
+ str << "\n" << _("#(Invalid)");
+ } else if (!campaign_type.empty()) {
+ str << "\n";
+
+ if(campaign_type == "scenario") {
+ const std::string campaign_id = cfg_summary["campaign"];
+ const config *campaign = NULL;
+ if (!campaign_id.empty()) {
+ if (const config &c = cache_config_.find_child(
+ "campaign", "id", campaign_id))
+
+ campaign = &c;
+ }
+ utils::string_map symbols;
+ if (campaign != NULL) {
+ symbols["campaign_name"] = (*campaign)["name"];
+ } else {
+ // Fallback to nontranslatable campaign id.
+ symbols["campaign_name"] = "(" + campaign_id + ")";
+ }
+ str << vgettext("Campaign: $campaign_name", symbols);
+
+ // Display internal id for debug purposes if we didn't above
+ if (game_config::debug && (campaign != NULL)) {
+ str << '\n' << "(" << campaign_id << ")";
+ }
+ } else if(campaign_type == "multiplayer") {
+ str << _("Multiplayer");
+ } else if(campaign_type == "tutorial") {
+ str << _("Tutorial");
+ } else {
+ str << campaign_type;
+ }
+
+ str << "\n";
+
+ if (cfg_summary["replay"].to_bool() && !cfg_summary["snapshot"].to_bool(true)) {
+ str << _("replay");
+ } else if (!cfg_summary["turn"].empty()) {
+ str << _("Turn") << " " << cfg_summary["turn"];
+ } else {
+ str << _("Scenario Start");
+ }
+
+ str << "\n" << _("Difficulty: ")
+ << string_table[cfg_summary["difficulty"]];
+
+ if(!cfg_summary["version"].empty()) {
+ str << "\n" << _("Version: ") << cfg_summary["version"];
+ }
+ }
+}
+
+void tdata_manage::delete_button_callback(twindow& window)
+{
+ tlistbox& list = find_widget(&window, "persist_list", false);
+
+ const size_t index = size_t(list.get_selected_row());
+ if(index < games_.size()) {
+
+ // See if we should ask the user for deletion confirmation
+ if(preferences::ask_delete_saves()) {
+ gui2::tgame_delete dlg_delete;
+ dlg_delete.show(window.video(), 0);
+ int res = dlg_delete.get_retval();
+
+ if (res == twindow::CANCEL)
+ return;
+
+ if (dlg_delete.dont_ask_again()) {
+ preferences::set_ask_delete_saves(false);
+ }
+ }
+
+ // Delete the file
+ savegame::manager::delete_game(games_[index].name);
+
+ // Remove it from the list of saves
+ games_.erase(games_.begin() + index);
+ list.remove_row(index);
+
+ }
+}
+
+} // namespace gui2
diff --git a/src/gui/dialogs/data_manage.hpp b/src/gui/dialogs/data_manage.hpp
new file mode 100644
index 00000000000..87bb3751301
--- /dev/null
+++ b/src/gui/dialogs/data_manage.hpp
@@ -0,0 +1,65 @@
+/* $Id$ */
+/*
+ Copyright (C) 2010 by Jody Northup
+ Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2
+ or at your option any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY.
+
+ See the COPYING file for more details.
+*/
+
+#ifndef GUI_DIALOGS_MANAGE_DATA_HPP_INCLUDED
+#define GUI_DIALOGS_MANAGE_DATA_HPP_INCLUDED
+
+#include "gui/dialogs/dialog.hpp"
+#include "gui/widgets/listbox.hpp"
+#include "gui/widgets/text.hpp"
+#include "savegame.hpp"
+#include "tstring.hpp"
+
+namespace gui2 {
+
+class tdata_manage : public tdialog
+{
+public:
+ tdata_manage(const config& cache_config);
+
+ const std::string& filename() const { return filename_; }
+
+protected:
+ /** Inherited from tdialog. */
+ void pre_show(CVideo& video, twindow& window);
+
+ /** Inherited from tdialog. */
+ void post_show(twindow& window);
+
+private:
+
+ /** Inherited from tdialog, implemented by REGISTER_WINDOW. */
+ virtual const std::string& window_id() const;
+
+ bool filter_text_changed(ttext_* textbox, const std::string& text);
+ void list_item_clicked(twindow& window);
+ void delete_button_callback(twindow& window);
+
+ void evaluate_summary_string(std::stringstream& str, const config& cfg_summary);
+ void fill_game_list(twindow& window, std::vector& games);
+
+ tfield_text* txtFilter_;
+
+ std::string filename_;
+
+ std::vector games_;
+ const config& cache_config_;
+
+ std::vector last_words_;
+};
+
+}
+
+#endif
+
diff --git a/src/menu_events.cpp b/src/menu_events.cpp
index b875560fb87..e5f3f122d5e 100644
--- a/src/menu_events.cpp
+++ b/src/menu_events.cpp
@@ -33,6 +33,7 @@
#include "gui/dialogs/transient_message.hpp"
#include "gui/dialogs/wml_message.hpp"
#include "gui/dialogs/gamestate_inspector.hpp"
+#include "gui/dialogs/data_manage.hpp"
#include "gui/dialogs/unit_create.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/window.hpp"
@@ -2377,6 +2378,7 @@ class console_handler : public map_command_handler, private cha
void do_set_var();
void do_show_var();
void do_inspect();
+ void do_manage();
void do_unit();
// void do_buff();
// void do_unbuff();
@@ -2466,6 +2468,8 @@ class console_handler : public map_command_handler, private cha
_("Set the command used by the custom command hotkey"), _("[;...]"));
register_command("inspect", &console_handler::do_inspect,
_("Launch the gamestate inspector"), "", "D");
+ register_command("manage", &console_handler::do_manage,
+ _("Manage persistence data"), "", "D");
register_command("alias", &console_handler::do_set_alias,
_("Set or show alias to a command"), _("[=]"));
register_command("set_var", &console_handler::do_set_var,
@@ -3250,6 +3254,12 @@ void console_handler::do_inspect() {
inspect_dialog.show(resources::screen->video());
}
+void console_handler::do_manage() {
+ config cfg;
+ gui2::tdata_manage manager(cfg);
+ manager.show(resources::screen->video());
+}
+
void console_handler::do_unit() {
// prevent SIGSEGV due to attempt to set HP during a fight
if (events::commands_disabled > 0)