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)