diff --git a/changelog b/changelog index fc5ed3a3fd45..e51ff68d4355 100644 --- a/changelog +++ b/changelog @@ -20,6 +20,10 @@ Version 1.11.15+dev: * User interface: * Fixed bug #22095: An assertion failure in the gamestate inspector. * Fixed bug #22144: An assertion failure with empty labels in a listbox. + * The :inspect dialog now uses the same function as saved games to generate + WML in text form instead of a simplified version. + * Added a button to copy the currently displayed content from the :inspect + dialog to clipboard. * WML engine: * Fixed a regression in 1.11.14 causing WML parser/preprocessor errors to not interrupt the game load sequence or display an error message in-game, diff --git a/data/gui/default/window/gamestate_inspector.cfg b/data/gui/default/window/gamestate_inspector.cfg index 44df78989578..c69a78549a70 100644 --- a/data/gui/default/window/gamestate_inspector.cfg +++ b/data/gui/default/window/gamestate_inspector.cfg @@ -204,29 +204,54 @@ [column] grow_factor = 6 - border = "all" - border_size = 5 vertical_alignment = "top" horizontal_alignment = "left" [grid] [row] [column] - # - # Emulate the listbox headers' top/bottom padding - # here relative to the scroll_label below. - # - border = "top,bottom" - border_size = 5 - horizontal_alignment = "left" - [label] - definition = "default" - label = _ "Contents" - [/label] + horizontal_grow = "true" + [grid] + [row] + [column] + # + # Emulate the listbox headers' top/bottom padding + # here relative to the scroll_label below. + # + border = "top,left,right" + border_size = 5 + horizontal_alignment = "left" + + [label] + definition = "default" + label = _ "Contents" + [/label] + [/column] + + [column] + border = "top,left,right" + border_size = 5 + horizontal_alignment = "right" + + [button] + id = "copy" + definition = "action_copy" + label = _ "clipboard^Copy" + # FIXME: tooltips cause weird interactions with map + # labels while running a GUI2 dialog, so let's + # not use a tooltip yet. + #tooltip = _ "Copy this report to clipboard" + [/button] + [/column] + [/row] + [/grid] [/column] [/row] [row] [column] + border = "left,bottom,right" + border_size = 5 horizontal_alignment = "left" + [scroll_label] id = "inspect" definition = "default" diff --git a/src/gui/dialogs/gamestate_inspector.cpp b/src/gui/dialogs/gamestate_inspector.cpp index 566e4470e38a..a39734de0695 100644 --- a/src/gui/dialogs/gamestate_inspector.cpp +++ b/src/gui/dialogs/gamestate_inspector.cpp @@ -26,6 +26,9 @@ #endif #include "gui/widgets/settings.hpp" #include "gui/widgets/window.hpp" + +#include "clipboard.hpp" +#include "serialization/parser.hpp" // for write() #include "utils/foreach.tpp" #include "../../gamestatus.hpp" @@ -37,6 +40,18 @@ #include #include +namespace +{ + +inline std::string config_to_string(const config& cfg) +{ + std::ostringstream s; + write(s, cfg); + return s.str(); +} + +} + namespace gui2 { @@ -59,6 +74,9 @@ namespace gui2 * inspect & & control & m & * The state of the variable or event. $ * + * copy & & button & m & + * A button to copy the state to clipboard. $ + * * @end{table} */ @@ -70,7 +88,7 @@ static void inspect_ai(twindow& window, int side) NEW_find_widget( &window, "inspect", - false).set_label(ai_cfg.debug()); + false).set_label(config_to_string(ai_cfg.debug)); } */ @@ -107,6 +125,7 @@ class tgamestate_inspector::model , stuff_types_list() , inspect() , inspector_name() + , copy_button() { name = cfg["name"].str(); } @@ -118,6 +137,7 @@ class tgamestate_inspector::model tlistbox* stuff_types_list; tcontrol* inspect; tcontrol* inspector_name; + tbutton* copy_button; void clear_stuff_list() @@ -245,7 +265,7 @@ class variable_mode_controller : public single_mode_controller FOREACH(const AUTO & c, vars.all_children_range()) { if(selected == i) { - model_.set_inspect_window_text(c.cfg.debug()); + model_.set_inspect_window_text(config_to_string(c.cfg)); return; } i++; @@ -319,7 +339,9 @@ class unit_mode_controller : public single_mode_controller if(selected == i) { config c_unit; u->write(c_unit); - model_.set_inspect_window_text(c_unit.debug()); + std::ostringstream cfg_str; + write(cfg_str, c_unit); + model_.set_inspect_window_text(cfg_str.str()); return; } i++; @@ -377,7 +399,7 @@ class team_mode_controller : public single_mode_controller : config(); c.clear_children("ai"); c.clear_children("village"); - model_.set_inspect_window_text(c.debug()); + model_.set_inspect_window_text(config_to_string(c)); return; } @@ -389,7 +411,7 @@ class team_mode_controller : public single_mode_controller if(selected == 2) { model_.set_inspect_window_text( - ai::manager::to_config(side_).debug()); + config_to_string(ai::manager::to_config(side_))); return; } @@ -429,7 +451,7 @@ class team_mode_controller : public single_mode_controller u.write(c_unit); c.add_child("unit", c_unit); } - model_.set_inspect_window_text(c.debug()); + model_.set_inspect_window_text(config_to_string(c)); return; } @@ -559,6 +581,11 @@ class tgamestate_inspector::controller c->update_view_from_model(); // TODO: 'activate' } + void handle_copy_button_clicked() + { + copy_to_clipboard(model_.inspect->label(), false); + } + private: model& model_; @@ -595,6 +622,11 @@ class tgamestate_inspector::view window.invalidate_layout(); // workaround for assertion failure } + void handle_copy_button_clicked(twindow& /*window*/) + { + controller_.handle_copy_button_clicked(); + } + void bind(twindow& window) { @@ -605,6 +637,8 @@ class tgamestate_inspector::view model_.inspect = find_widget(&window, "inspect", false, true); model_.inspector_name = &find_widget(&window, "inspector_name", false); + model_.copy_button + = &find_widget(&window, "copy", false); #ifdef GUI2_EXPERIMENTAL_LISTBOX connect_signal_notify_modified( @@ -634,6 +668,12 @@ class tgamestate_inspector::view &tgamestate_inspector::view:: handle_stuff_types_list_item_clicked>); #endif + + connect_signal_mouse_left_click( + *model_.copy_button, + boost::bind(&tgamestate_inspector::view::handle_copy_button_clicked, + this, + boost::ref(window))); } private: