2 Comments. Will do some testing. Diff comments:
> === added directory 'data/economy_profiles' > === added file 'data/economy_profiles/atlanteans' > --- data/economy_profiles/atlanteans 1970-01-01 00:00:00 +0000 > +++ data/economy_profiles/atlanteans 2019-05-05 05:49:29 +0000 > @@ -0,0 +1,85 @@ > +# Automatically created by Widelands bzr9094[economy-target-profiles] (Debug) > + > +[Efficiency] These names need to be translatable. I also think that the files should live under "tribes". > +blackroot_flour="1" > +atlanteans_bread="20" > +bread_paddle="0" > +buckets="0" > +coal="5" > +cornmeal="3" > +diamond="3" > +fire_tongs="1" > +fishing_net="2" > +gold="1" > +gold_ore="1" > +gold_thread="0" > +granite="10" > +hammer="0" > +hook_pole="0" > +hunting_bow="1" > +iron="5" > +iron_ore="1" > +milking_tongs="0" > +pick="1" > +planks="1" > +quartz="3" > +saw="0" > +scythe="0" > +shield_advanced="0" > +shield_steel="0" > +shovel="0" > +smoked_fish="5" > +smoked_meat="3" > +spidercloth="5" > +spider_silk="5" > +tabard="1" > +tabard_golden="0" > +trident_double="0" > +trident_heavy_double="0" > +trident_light="1" > +trident_long="0" > +trident_steel="0" > +atlanteans_horse="1" > +atlanteans_soldier="10" > + > +[Stockpile] > +blackroot_flour="20" > +atlanteans_bread="30" > +bread_paddle="1" > +buckets="2" > +coal="25" > +cornmeal="20" > +diamond="10" > +fire_tongs="1" > +fishing_net="2" > +gold="20" > +gold_ore="15" > +gold_thread="5" > +granite="30" > +hammer="2" > +hook_pole="1" > +hunting_bow="1" > +iron="25" > +iron_ore="20" > +milking_tongs="1" > +pick="3" > +planks="40" > +quartz="10" > +saw="2" > +scythe="1" > +shield_advanced="1" > +shield_steel="1" > +shovel="2" > +smoked_fish="40" > +smoked_meat="25" > +spidercloth="20" > +spider_silk="15" > +tabard="30" > +tabard_golden="1" > +trident_double="1" > +trident_heavy_double="1" > +trident_light="30" > +trident_long="1" > +trident_steel="1" > +atlanteans_horse="20" > +atlanteans_soldier="20" > > === modified file 'src/wui/economy_options_window.cc' > --- src/wui/economy_options_window.cc 2019-02-23 11:00:49 +0000 > +++ src/wui/economy_options_window.cc 2019-05-05 05:49:29 +0000 > @@ -186,35 +247,264 @@ > const Widelands::Economy::TargetQuantity& tq = is_wares > ? > > economy->ware_target_quantity(index) : > > economy->worker_target_quantity(index); > - // Don't allow negative new amount. > - if (amount >= 0 || -amount <= > static_cast<int>(tq.permanent)) { > - if (is_wares) { > - game.send_player_command(*new > Widelands::CmdSetWareTargetQuantity( > - game.get_gametime(), > player_->player_number(), serial_, index, > - tq.permanent + amount)); > - } else { > - game.send_player_command(*new > Widelands::CmdSetWorkerTargetQuantity( > - game.get_gametime(), > player_->player_number(), serial_, index, > - tq.permanent + amount)); > + // Don't allow negative new amount > + const int old_amount = static_cast<int>(tq.permanent); > + const int new_amount = std::max(0, old_amount + delta); > + if (new_amount == old_amount) { > + continue; > + } > + if (is_wares) { > + game.send_player_command(*new > Widelands::CmdSetWareTargetQuantity( > + game.get_gametime(), > player_->player_number(), serial_, index, new_amount)); > + } else { > + game.send_player_command(*new > Widelands::CmdSetWorkerTargetQuantity( > + game.get_gametime(), > player_->player_number(), serial_, index, new_amount)); > + } > + } > + } > +} > + > +void EconomyOptionsWindow::EconomyOptionsPanel::reset_target() { > + Widelands::Game& game = > dynamic_cast<Widelands::Game&>(player_->egbase()); > + const bool is_wares = type_ == Widelands::wwWARE; > + const auto& items = is_wares ? player_->tribe().wares() : > player_->tribe().workers(); > + const PredefinedTargets settings = > economy_options_window_->get_selected_target(); > + for (const Widelands::DescriptionIndex& index : items) { > + if (display_.ware_selected(index)) { > + if (is_wares) { > + game.send_player_command(*new > Widelands::CmdSetWareTargetQuantity( > + game.get_gametime(), > player_->player_number(), serial_, index, settings.wares.at(index))); > + } else { > + game.send_player_command(*new > Widelands::CmdSetWorkerTargetQuantity( > + game.get_gametime(), > player_->player_number(), serial_, index, settings.workers.at(index))); > + } > + } > + } > +} > + > +void EconomyOptionsWindow::read_targets(const std::string& select) { > + predefined_targets_.clear(); > + const Widelands::Tribes& tribes = player_->egbase().tribes(); > + const Widelands::TribeDescr& tribe = player_->tribe(); > + > + { > + PredefinedTargets t; > + for (Widelands::DescriptionIndex di : tribe.wares()) { > + const Widelands::WareDescr* descr = > tribes.get_ware_descr(di); > + if (descr->has_demand_check(tribe.name())) { > + t.wares.emplace(di, > descr->default_target_quantity(tribe.name())); > + } > + } > + for (Widelands::DescriptionIndex di : tribe.workers()) { > + const Widelands::WorkerDescr* descr = > tribes.get_worker_descr(di); > + if (descr->has_demand_check()) { > + t.workers.emplace(di, > descr->default_target_quantity()); > + } > + } > + predefined_targets_.emplace(kDefaultEconomyProfile, t); > + } > + > + std::string complete_filename = kEconomyProfilesDir + > g_fs->file_separator() + player_->tribe().name(); > + Profile profile; > + profile.read(complete_filename.c_str()); > + while (Section* section = profile.get_next_section()) { > + PredefinedTargets t; > + while (Section::Value* v = section->get_next_val()) { > + const std::string name = std::string(v->get_name()); > + Widelands::DescriptionIndex di = > tribes.ware_index(name); > + if (di == Widelands::INVALID_INDEX) { > + di = tribes.worker_index(name); > + assert(di != Widelands::INVALID_INDEX); > + t.workers.emplace(di, v->get_natural()); > + } else { > + t.wares.emplace(di, v->get_natural()); > + } > + } > + predefined_targets_.emplace(std::string(section->get_name()), > t); > + } > + > + update_profiles(select); > +} > + > +void EconomyOptionsWindow::update_profiles(const std::string& select) { > + dropdown_.clear(); > + for (const auto& pair : predefined_targets_) { > + dropdown_.add(_(pair.first), pair.first, nullptr, pair.first == > select); > + } > +} > + > +struct SaveProfileWindow : public UI::Window { > + void update_save_enabled() { > + const std::string& text = profile_name_.text(); > + if (text.empty() || text == kDefaultEconomyProfile) { > + save_.set_enabled(false); > + save_.set_tooltip(text.empty() ? _("The profile name > cannot be empty") : > + _("The default profile cannot be > overwritten")); > + } else { > + save_.set_enabled(true); > + save_.set_tooltip(_("Save the profile under this > name")); > + } > + } > + > + void table_selection_changed() { > + if (!table_.has_selection()) { > + delete_.set_enabled(false); > + delete_.set_tooltip(""); > + return; > + } > + const std::string& sel = table_[table_.selection_index()]; > + if (sel == kDefaultEconomyProfile) { > + delete_.set_tooltip(_("The default profile cannot be > deleted")); > + delete_.set_enabled(false); > + } else { > + delete_.set_tooltip(_("Delete the selected profiles")); > + delete_.set_enabled(true); > + } > + profile_name_.set_text(sel); > + update_save_enabled(); > + } > + > + void close(bool ok) { > + end_modal(ok ? UI::Panel::Returncodes::kOk : > UI::Panel::Returncodes::kBack); > + die(); > + } > + > + void update_table() { > + table_.clear(); > + for (const auto& pair : > economy_options_->get_predefined_targets()) { > + table_.add(pair.first).set_string(0, _(pair.first)); > + } > + layout(); > + } > + > + void save() { > + const std::string name = profile_name_.text(); > + assert(!name.empty()); > + assert(name != kDefaultEconomyProfile); > + for (const auto& pair : > economy_options_->get_predefined_targets()) { > + if (pair.first == name) { > + UI::WLMessageBox m(this, _("Overwrite?"), > + _("A profile with this name > already exists.\nDo you wish to replace it?"), > + > UI::WLMessageBox::MBoxType::kOkCancel); > + if (m.run<UI::Panel::Returncodes>() != > UI::Panel::Returncodes::kOk) { > + return; > } > - } > - } > - } > -} > - > -void EconomyOptionsWindow::EconomyOptionsPanel::reset_target() { > - Widelands::Game& game = > dynamic_cast<Widelands::Game&>(player_->egbase()); > - const bool is_wares = type_ == Widelands::wwWARE; > - const auto& items = is_wares ? player_->tribe().wares() : > player_->tribe().workers(); > - for (const Widelands::DescriptionIndex& index : items) { > - if (display_.ware_selected(index)) { > - if (is_wares) { > - game.send_player_command(*new > Widelands::CmdResetWareTargetQuantity( > - game.get_gametime(), > player_->player_number(), serial_, index)); > - } else { > - game.send_player_command(*new > Widelands::CmdResetWorkerTargetQuantity( > - game.get_gametime(), > player_->player_number(), serial_, index)); > - } > - } > - } > + break; > + } > + } > + economy_options_->do_create_target(name); > + close(true); > + } > + > + void delete_selected() { > + assert(table_.has_selection()); > + auto& map = economy_options_->get_predefined_targets(); > + const std::string& name = table_[table_.selection_index()]; > + assert(name != kDefaultEconomyProfile); > + for (auto it = map.begin(); it != map.end(); ++it) { > + if (it->first == name) { > + map.erase(it); > + break; > + } > + } > + economy_options_->save_targets(); > + update_table(); > + } > + > + explicit SaveProfileWindow(UI::Panel* parent, EconomyOptionsWindow* eco) > + : UI::Window(parent, "save_economy_options_profile", 0, 0, 0, 0, > _("Save Profile")), > + economy_options_(eco), > + main_box_(this, 0, 0, UI::Box::Vertical), > + table_box_(&main_box_, 0, 0, UI::Box::Vertical), > + table_(&table_box_, 0, 0, 460, 120, UI::PanelStyle::kWui), > + buttons_box_(&main_box_, 0, 0, UI::Box::Horizontal), > + profile_name_(&buttons_box_, 0, 0, 240, 0, 0, > UI::PanelStyle::kWui), > + save_(&buttons_box_, "save", 0, 0, 80, 34, > UI::ButtonStyle::kWuiPrimary, _("Save")), > + cancel_(&buttons_box_, "cancel", 0, 0, 80, 34, > UI::ButtonStyle::kWuiSecondary, _("Cancel")), > + delete_(&buttons_box_, "delete", 0, 0, 80, 34, > UI::ButtonStyle::kWuiSecondary, _("Delete")) { > + table_.add_column(200, _("Existing Profiles")); > + update_table(); > + > + > table_.selected.connect(boost::bind(&SaveProfileWindow::table_selection_changed, > this)); I think we should stop using boost::bind and use lambda functions instead. I think that's easier to read: table_.selected.connect([this] { table_selection_changed(); }); > + > profile_name_.changed.connect(boost::bind(&SaveProfileWindow::update_save_enabled, > this)); > + profile_name_.ok.connect(boost::bind(&SaveProfileWindow::save, > this)); > + > profile_name_.cancel.connect(boost::bind(&SaveProfileWindow::close, this, > false)); > + save_.sigclicked.connect(boost::bind(&SaveProfileWindow::save, > this)); > + > cancel_.sigclicked.connect(boost::bind(&SaveProfileWindow::close, this, > false)); > + > delete_.sigclicked.connect(boost::bind(&SaveProfileWindow::delete_selected, > this)); > + > + table_box_.add(&table_, UI::Box::Resizing::kFullSize); > + buttons_box_.add(&profile_name_, UI::Box::Resizing::kFullSize); > + buttons_box_.add(&save_); > + buttons_box_.add(&cancel_); > + buttons_box_.add(&delete_); > + main_box_.add(&table_box_, UI::Box::Resizing::kFullSize); > + main_box_.add(&buttons_box_, UI::Box::Resizing::kFullSize); > + set_center_panel(&main_box_); > + > + table_selection_changed(); > + update_save_enabled(); > + } > + ~SaveProfileWindow() { > + } > + > +private: > + EconomyOptionsWindow* economy_options_; > + UI::Box main_box_; > + UI::Box table_box_; > + UI::Table<const std::string&> table_; > + UI::Box buttons_box_; > + UI::EditBox profile_name_; > + UI::Button save_; > + UI::Button cancel_; > + UI::Button delete_; > +}; > + > +void EconomyOptionsWindow::create_target() { > + std::unique_ptr<SaveProfileWindow> s (new > SaveProfileWindow(get_parent(), this)); > + s->run<UI::Panel::Returncodes>(); > +} > + > +void EconomyOptionsWindow::do_create_target(const std::string& name) { > + assert(!name.empty()); > + assert(name != kDefaultEconomyProfile); > + const Widelands::Tribes& tribes = player_->egbase().tribes(); > + const Widelands::TribeDescr& tribe = player_->tribe(); > + Widelands::Economy* economy = player_->get_economy(serial_); > + PredefinedTargets t; > + for (Widelands::DescriptionIndex di : tribe.wares()) { > + if (tribes.get_ware_descr(di)->has_demand_check(tribe.name())) { > + t.wares[di] = > economy->ware_target_quantity(di).permanent; > + } > + } > + for (Widelands::DescriptionIndex di : tribe.workers()) { > + if (tribes.get_worker_descr(di)->has_demand_check()) { > + t.workers[di] = > economy->worker_target_quantity(di).permanent; > + } > + } > + predefined_targets_[name] = t; > + > + save_targets(); > + update_profiles(name); > +} > + > +void EconomyOptionsWindow::save_targets() { > + const Widelands::Tribes& tribes = player_->egbase().tribes(); > + Profile profile; > + for (const auto& pair : predefined_targets_) { > + if (pair.first == kDefaultEconomyProfile) { > + continue; > + } > + Section& section = profile.create_section(pair.first.c_str()); > + for (const auto& setting : pair.second.wares) { > + > section.set_natural(tribes.get_ware_descr(setting.first)->name().c_str(), > setting.second); > + } > + for (const auto& setting : pair.second.workers) { > + > section.set_natural(tribes.get_worker_descr(setting.first)->name().c_str(), > setting.second); > + } > + } > + > + g_fs->ensure_directory_exists(kEconomyProfilesDir); > + std::string complete_filename = kEconomyProfilesDir + > g_fs->file_separator() + player_->tribe().name(); > + profile.write(complete_filename.c_str(), false); > } -- https://code.launchpad.net/~widelands-dev/widelands/economy-target-profiles/+merge/366952 Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands. _______________________________________________ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp