diff --git a/repos/gems/src/app/sculpt_manager/model/component.h b/repos/gems/src/app/sculpt_manager/model/component.h index f857cc7d5e..e68be1b7e2 100644 --- a/repos/gems/src/app/sculpt_manager/model/component.h +++ b/repos/gems/src/app/sculpt_manager/model/component.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace Sculpt { struct Component; } @@ -44,7 +45,18 @@ struct Sculpt::Component : Noncopyable affinity_space.height() }; Priority priority = Priority::DEFAULT; - bool blueprint_known = false; + struct Blueprint_info + { + bool known; + bool pkg_avail; + bool content_complete; + + bool uninstalled() const { return known && !pkg_avail; } + bool ready_to_deploy() const { return known && pkg_avail && content_complete; } + bool incomplete() const { return known && pkg_avail && !content_complete; } + }; + + Blueprint_info blueprint_info { }; List_model routes { }; Route pd_route { "" }; @@ -65,6 +77,49 @@ struct Sculpt::Component : Noncopyable ); } + struct Construction_info : Interface + { + struct With : Interface { virtual void with(Component const &) const = 0; }; + + virtual void _with_construction(With const &) const = 0; + + template + void with_construction(FN const &fn) const + { + struct _With : With { + FN const &_fn; + _With(FN const &fn) : _fn(fn) { } + void with(Component const &c) const override { _fn(c); } + }; + _with_construction(_With(fn)); + } + }; + + struct Construction_action : Interface + { + virtual void new_construction(Path const &pkg, Info const &info) = 0; + + struct Apply_to : Interface { virtual void apply_to(Component &) = 0; }; + + virtual void _apply_to_construction(Apply_to &) = 0; + + template + void apply_to_construction(FN const &fn) + { + struct _Apply_to : Apply_to { + FN const &_fn; + _Apply_to(FN const &fn) : _fn(fn) { } + void apply_to(Component &c) override { _fn(c); } + } apply_fn(fn); + + _apply_to_construction(apply_fn); + } + + virtual void discard_construction() = 0; + virtual void launch_construction() = 0; + virtual void trigger_pkg_download() = 0; + }; + Component(Allocator &alloc, Path const &path, Info const &info, Affinity::Space const space) : @@ -78,11 +133,18 @@ struct Sculpt::Component : Noncopyable void try_apply_blueprint(Xml_node blueprint) { - blueprint.for_each_sub_node("pkg", [&] (Xml_node pkg) { + blueprint_info = { }; + + blueprint.for_each_sub_node([&] (Xml_node pkg) { if (path != pkg.attribute_value("path", Path())) return; + if (pkg.has_type("missing")) { + blueprint_info.known = true; + return; + } + pkg.with_optional_sub_node("runtime", [&] (Xml_node runtime) { ram = runtime.attribute_value("ram", Number_of_bytes()); @@ -92,7 +154,11 @@ struct Sculpt::Component : Noncopyable _update_routes_from_xml(requires); }); }); - blueprint_known = true; + blueprint_info = { + .known = true, + .pkg_avail = !blueprint_missing(blueprint, path), + .content_complete = !blueprint_rom_missing(blueprint, path) + }; }); } diff --git a/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc b/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc index 05c4725c8b..48ae3f360b 100644 --- a/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc +++ b/repos/gems/src/app/sculpt_manager/view/popup_dialog.cc @@ -243,7 +243,7 @@ void Popup_dialog::_gen_menu_elements(Xml_generator &xml, Xml_node const &depot_ * inconsistent with the content contained in * the pkg's archives. */ - if (!_pkg_missing && _pkg_rom_missing) { + if (_blueprint_info.incomplete()) { _gen_info_label(xml, "pad2", ""); _gen_info_label(xml, "path", component.path); _gen_info_label(xml, "pad3", ""); @@ -254,7 +254,7 @@ void Popup_dialog::_gen_menu_elements(Xml_generator &xml, Xml_node const &depot_ /* * Package is missing but can be installed */ - else if (_pkg_missing && _nic_ready()) { + else if (_blueprint_info.uninstalled() && _nic_ready()) { _gen_pkg_info(xml, component); _gen_info_label(xml, "pad2", ""); @@ -273,7 +273,7 @@ void Popup_dialog::_gen_menu_elements(Xml_generator &xml, Xml_node const &depot_ * Package is missing and we cannot do anything * about it */ - else if (_pkg_missing) { + else if (_blueprint_info.uninstalled()) { _gen_info_label(xml, "pad2", ""); _gen_info_label(xml, "path", component.path); _gen_info_label(xml, "pad3", ""); @@ -398,7 +398,6 @@ void Popup_dialog::click(Action &action) _construction_name = action.new_construction(path, info); _state = PKG_REQUESTED; - _pkg_missing = false; _depot_query.trigger_depot_query(); } } diff --git a/repos/gems/src/app/sculpt_manager/view/popup_dialog.h b/repos/gems/src/app/sculpt_manager/view/popup_dialog.h index 8ad791372c..2762e9199e 100644 --- a/repos/gems/src/app/sculpt_manager/view/popup_dialog.h +++ b/repos/gems/src/app/sculpt_manager/view/popup_dialog.h @@ -39,7 +39,8 @@ namespace Sculpt { struct Popup_dialog; } struct Sculpt::Popup_dialog : Dialog { - using Depot_users = Attached_rom_dataspace; + using Depot_users = Attached_rom_dataspace; + using Blueprint_info = Component::Blueprint_info; Env &_env; @@ -132,8 +133,7 @@ struct Sculpt::Popup_dialog : Dialog typedef Depot::Archive::User User; User _selected_user { }; - bool _pkg_missing = false; - bool _pkg_rom_missing = false; + Blueprint_info _blueprint_info { }; Component::Name _construction_name { }; @@ -338,7 +338,7 @@ struct Sculpt::Popup_dialog : Dialog reset(); } - if (_pkg_missing && _install_item.activated("install")) { + if (!_blueprint_info.pkg_avail && _install_item.activated("install")) { _construction_info.with_construction([&] (Component const &component) { action.trigger_download(component.path); _install_item.reset(); @@ -412,11 +412,11 @@ struct Sculpt::Popup_dialog : Dialog construction.affinity_location, construction.priority); - _pkg_rom_missing = blueprint_rom_missing(blueprint, construction.path); - _pkg_missing = blueprint_missing (blueprint, construction.path); - construction.try_apply_blueprint(blueprint); - if (construction.blueprint_known && !_pkg_missing && !_pkg_rom_missing) + + _blueprint_info = construction.blueprint_info; + + if (_blueprint_info.ready_to_deploy()) _state = PKG_SHOWN; _refresh.refresh_popup_dialog(); @@ -427,7 +427,7 @@ struct Sculpt::Popup_dialog : Dialog if (_state == DEPOT_SELECTION) return true; - return _state >= PKG_REQUESTED && (_pkg_missing || _pkg_rom_missing); + return _state >= PKG_REQUESTED && !_blueprint_info.ready_to_deploy(); } bool interested_in_file_operations() const