WIP: ConfigWizard: 3rd party bundle installation roughly done
This commit is contained in:
parent
dba9925c4e
commit
235b659cf9
11 changed files with 493 additions and 215 deletions
|
@ -393,9 +393,9 @@ const Snapshot& SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot:
|
|||
// Read the active config bundle, parse the config version.
|
||||
PresetBundle bundle;
|
||||
bundle.load_configbundle((data_dir / "vendor" / (cfg.name + ".ini")).string(), PresetBundle::LOAD_CFGBUNDLE_VENDOR_ONLY);
|
||||
for (const VendorProfile &vp : bundle.vendors)
|
||||
if (vp.id == cfg.name)
|
||||
cfg.version.config_version = vp.config_version;
|
||||
for (const auto &vp : bundle.vendors)
|
||||
if (vp.second.id == cfg.name)
|
||||
cfg.version.config_version = vp.second.config_version;
|
||||
// Fill-in the min/max slic3r version from the config index, if possible.
|
||||
try {
|
||||
// Load the config index for the vendor.
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <numeric>
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
@ -25,7 +26,7 @@
|
|||
#include <wx/debug.h>
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
// #include "PresetBundle.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "slic3r/Config/Snapshot.hpp"
|
||||
|
@ -40,6 +41,92 @@ using Config::Snapshot;
|
|||
using Config::SnapshotDB;
|
||||
|
||||
|
||||
// Configuration data structures extensions needed for the wizard
|
||||
|
||||
Bundle::Bundle(fs::path source_path, bool is_in_resources, bool is_prusa_bundle)
|
||||
: source_path(std::move(source_path))
|
||||
, preset_bundle(new PresetBundle)
|
||||
, vendor_profile(nullptr)
|
||||
, is_in_resources(is_in_resources)
|
||||
, is_prusa_bundle(is_prusa_bundle)
|
||||
{
|
||||
// XXX: consider removing path <-> string juggling
|
||||
preset_bundle->load_configbundle(this->source_path.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
|
||||
auto first_vendor = preset_bundle->vendors.begin();
|
||||
wxCHECK_RET(first_vendor != preset_bundle->vendors.end(), "Failed to load preset bundle");
|
||||
vendor_profile = &first_vendor->second;
|
||||
}
|
||||
|
||||
Bundle::Bundle(Bundle &&other)
|
||||
: source_path(std::move(source_path))
|
||||
, preset_bundle(std::move(other.preset_bundle))
|
||||
, vendor_profile(other.vendor_profile)
|
||||
, is_in_resources(other.is_in_resources)
|
||||
, is_prusa_bundle(other.is_prusa_bundle)
|
||||
{
|
||||
other.vendor_profile = nullptr;
|
||||
}
|
||||
|
||||
BundleMap BundleMap::load()
|
||||
{
|
||||
BundleMap res;
|
||||
|
||||
// XXX: Keep Prusa bundle separate? (Probably no - keep same codepaths)
|
||||
|
||||
const auto vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / "vendor").make_preferred();
|
||||
const auto rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
||||
|
||||
// XXX
|
||||
// const auto prusa_bundle_vendor = (vendor_dir / PRUSA_BUNDLE).replace_extension(".ini");
|
||||
// const auto prusa_bundle = boost::filesystem::exists(prusa_bundle_vendor) ? prusa_bundle_vendor
|
||||
// : (rsrc_vendor_dir / PRUSA_BUNDLE).replace_extension(".ini");
|
||||
auto prusa_bundle_path = (vendor_dir / PresetBundle::PRUSA_BUNDLE).replace_extension(".ini");
|
||||
auto prusa_bundle_rsrc = false;
|
||||
if (! boost::filesystem::exists(prusa_bundle_path)) {
|
||||
prusa_bundle_path = (rsrc_vendor_dir / PresetBundle::PRUSA_BUNDLE).replace_extension(".ini");
|
||||
prusa_bundle_rsrc = true;
|
||||
}
|
||||
Bundle prusa_bundle(std::move(prusa_bundle_path), prusa_bundle_rsrc, true);
|
||||
res.emplace(PresetBundle::PRUSA_BUNDLE, std::move(prusa_bundle));
|
||||
|
||||
// Load the other bundles in the datadir/vendor directory
|
||||
// and then additionally from resources/profiles.
|
||||
bool is_in_resources = false;
|
||||
for (auto dir : { &vendor_dir, &rsrc_vendor_dir }) {
|
||||
for (const auto &dir_entry : boost::filesystem::directory_iterator(*dir)) {
|
||||
if (Slic3r::is_ini_file(dir_entry)) {
|
||||
std::string id = dir_entry.path().stem().string(); // stem() = filename() without the trailing ".ini" part
|
||||
|
||||
// Don't load this bundle if we've already loaded it.
|
||||
if (res.find(id) != res.end()) { continue; }
|
||||
|
||||
Bundle bundle(dir_entry.path(), is_in_resources);
|
||||
res.emplace(std::move(id), std::move(bundle));
|
||||
}
|
||||
}
|
||||
|
||||
is_in_resources = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Bundle& BundleMap::prusa_bundle()
|
||||
{
|
||||
auto it = find(PresetBundle::PRUSA_BUNDLE);
|
||||
if (it == end()) {
|
||||
throw std::runtime_error("ConfigWizard: Internal error in BundleMap: PRUSA_BUNDLE not loaded");
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const Bundle& BundleMap::prusa_bundle() const
|
||||
{
|
||||
return const_cast<BundleMap*>(this)->prusa_bundle();
|
||||
}
|
||||
|
||||
|
||||
// Printer model picker GUI control
|
||||
|
||||
struct PrinterPickerEvent : public wxEvent
|
||||
|
@ -65,6 +152,8 @@ struct PrinterPickerEvent : public wxEvent
|
|||
|
||||
wxDEFINE_EVENT(EVT_PRINTER_PICK, PrinterPickerEvent);
|
||||
|
||||
const std::string PrinterPicker::PRINTER_PLACEHOLDER = "printer_placeholder.png";
|
||||
|
||||
PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig, const ModelFilter &filter)
|
||||
: wxPanel(parent)
|
||||
, vendor_id(vendor.id)
|
||||
|
@ -96,6 +185,17 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||
if (wxFileExists(bitmap_file)) {
|
||||
bitmap.LoadFile(bitmap_file, wxBITMAP_TYPE_PNG);
|
||||
bitmap_width = bitmap.GetWidth();
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Can't find bitmap file `%1%` for vendor `%2%`, printer `%3%`, using placeholder icon instead")
|
||||
% bitmap_file
|
||||
% vendor.id
|
||||
% model.id;
|
||||
|
||||
const wxString placeholder_file = GUI::from_u8(Slic3r::var(PRINTER_PLACEHOLDER));
|
||||
if (wxFileExists(placeholder_file)) {
|
||||
bitmap.LoadFile(placeholder_file, wxBITMAP_TYPE_PNG);
|
||||
bitmap_width = bitmap.GetWidth();
|
||||
}
|
||||
}
|
||||
|
||||
auto *title = new wxStaticText(this, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||
|
@ -135,7 +235,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||
auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name);
|
||||
i == 0 ? cboxes.push_back(cbox) : cboxes_alt.push_back(cbox);
|
||||
|
||||
bool enabled = appconfig.get_variant("PrusaResearch", model_id, variant.name);
|
||||
bool enabled = appconfig.get_variant(vendor.id, model_id, variant.name);
|
||||
cbox->SetValue(enabled);
|
||||
|
||||
variants_sizer->Add(cbox, 0, wxBOTTOM, 3);
|
||||
|
@ -295,12 +395,13 @@ ConfigWizardPage::ConfigWizardPage(ConfigWizard *parent, wxString title, wxStrin
|
|||
|
||||
ConfigWizardPage::~ConfigWizardPage() {}
|
||||
|
||||
void ConfigWizardPage::append_text(wxString text)
|
||||
wxStaticText* ConfigWizardPage::append_text(wxString text)
|
||||
{
|
||||
auto *widget = new wxStaticText(this, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||
widget->Wrap(WRAP_WIDTH);
|
||||
widget->SetMinSize(wxSize(WRAP_WIDTH, -1));
|
||||
append(widget);
|
||||
return widget;
|
||||
}
|
||||
|
||||
void ConfigWizardPage::append_spacer(int space)
|
||||
|
@ -320,34 +421,42 @@ PageWelcome::PageWelcome(ConfigWizard *parent)
|
|||
_(L("Welcome to the %s Configuration Wizard"))
|
||||
#endif
|
||||
, SLIC3R_APP_NAME), _(L("Welcome")))
|
||||
, cbox_reset(nullptr)
|
||||
, welcome_text(append_text(wxString::Format(
|
||||
_(L("Hello, welcome to %s! This %s helps you with the initial configuration; just a few settings and you will be ready to print.")),
|
||||
SLIC3R_APP_NAME,
|
||||
ConfigWizard::name())
|
||||
))
|
||||
, cbox_reset(append(
|
||||
new wxCheckBox(this, wxID_ANY, _(L("Remove user profiles - install from scratch (a snapshot will be taken beforehand)")))
|
||||
))
|
||||
{
|
||||
if (wizard_p()->run_reason == ConfigWizard::RR_DATA_EMPTY) {
|
||||
wxString::Format(_(L("Run %s")), ConfigWizard::name());
|
||||
append_text(wxString::Format(
|
||||
_(L("Hello, welcome to %s! This %s helps you with the initial configuration; just a few settings and you will be ready to print.")),
|
||||
SLIC3R_APP_NAME,
|
||||
ConfigWizard::name())
|
||||
);
|
||||
} else {
|
||||
cbox_reset = new wxCheckBox(this, wxID_ANY, _(L("Remove user profiles - install from scratch (a snapshot will be taken beforehand)")));
|
||||
append(cbox_reset);
|
||||
}
|
||||
welcome_text->Hide();
|
||||
cbox_reset->Hide();
|
||||
}
|
||||
|
||||
Show();
|
||||
void PageWelcome::set_run_reason(ConfigWizard::RunReason run_reason)
|
||||
{
|
||||
const bool data_empty = run_reason == ConfigWizard::RR_DATA_EMPTY;
|
||||
welcome_text->Show(data_empty);
|
||||
cbox_reset->Show(!data_empty);
|
||||
}
|
||||
|
||||
|
||||
PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology)
|
||||
PagePrinters::PagePrinters(ConfigWizard *parent,
|
||||
wxString title,
|
||||
wxString shortname,
|
||||
const VendorProfile &vendor,
|
||||
unsigned indent,
|
||||
Technology technology)
|
||||
: ConfigWizardPage(parent, std::move(title), std::move(shortname), indent)
|
||||
, technology(technology)
|
||||
, install(false) // only used for 3rd party vendors
|
||||
{
|
||||
enum {
|
||||
COL_SIZE = 200,
|
||||
};
|
||||
|
||||
bool check_first_variant = technology == T_FFF && wizard_p()->check_first_variant();
|
||||
|
||||
AppConfig &appconfig = this->wizard_p()->appconfig_new;
|
||||
AppConfig *appconfig = &this->wizard_p()->appconfig_new;
|
||||
|
||||
const auto families = vendor.families();
|
||||
for (const auto &family : families) {
|
||||
|
@ -362,16 +471,10 @@ PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortn
|
|||
}
|
||||
|
||||
const auto picker_title = family.empty() ? wxString() : wxString::Format(_(L("%s Family")), family);
|
||||
auto *picker = new PrinterPicker(this, vendor, picker_title, MAX_COLS, appconfig, filter);
|
||||
auto *picker = new PrinterPicker(this, vendor, picker_title, MAX_COLS, *appconfig, filter);
|
||||
|
||||
if (check_first_variant) {
|
||||
// Select the default (first) model/variant on the Prusa vendor
|
||||
picker->select_one(0, true);
|
||||
check_first_variant = false;
|
||||
}
|
||||
|
||||
picker->Bind(EVT_PRINTER_PICK, [this, &appconfig](const PrinterPickerEvent &evt) {
|
||||
appconfig.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
|
||||
picker->Bind(EVT_PRINTER_PICK, [this, appconfig](const PrinterPickerEvent &evt) {
|
||||
appconfig->set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
|
||||
wizard_p()->on_printer_pick(this);
|
||||
});
|
||||
|
||||
|
@ -404,6 +507,15 @@ bool PagePrinters::any_selected() const
|
|||
return false;
|
||||
}
|
||||
|
||||
void PagePrinters::set_run_reason(ConfigWizard::RunReason run_reason)
|
||||
{
|
||||
if (technology == T_FFF
|
||||
&& (run_reason == ConfigWizard::RR_DATA_EMPTY || run_reason == ConfigWizard::RR_DATA_LEGACY)
|
||||
&& printer_pickers.size() > 0) {
|
||||
printer_pickers[0]->select_one(0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::string PageMaterials::EMPTY;
|
||||
|
||||
|
@ -619,48 +731,26 @@ PageUpdate::PageUpdate(ConfigWizard *parent)
|
|||
PageVendors::PageVendors(ConfigWizard *parent)
|
||||
: ConfigWizardPage(parent, _(L("Other Vendors")), _(L("Other Vendors")))
|
||||
{
|
||||
append_text(wxString::Format(_(L("Pick another vendor supported by %s:")), SLIC3R_APP_NAME));
|
||||
|
||||
|
||||
// FIXME: persistence: this doesn't reload choices
|
||||
|
||||
|
||||
append_text(wxString::Format(_(L("Pick another vendor supported by %s: (FIXME: this text)")), SLIC3R_APP_NAME));
|
||||
|
||||
auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
boldfont.SetWeight(wxFONTWEIGHT_BOLD);
|
||||
|
||||
AppConfig &appconfig = this->wizard_p()->appconfig_new;
|
||||
wxArrayString choices_vendors;
|
||||
for (const auto &pair : wizard_p()->bundles) {
|
||||
const VendorProfile *vendor = pair.second.vendor_profile;
|
||||
if (vendor->id == PresetBundle::PRUSA_BUNDLE) { continue; }
|
||||
|
||||
for (const auto vendor_pair : wizard_p()->vendors) {
|
||||
const auto &vendor = vendor_pair.second;
|
||||
if (vendor.id == "PrusaResearch") { continue; }
|
||||
|
||||
auto *picker = new PrinterPicker(this, vendor, "", MAX_COLS, appconfig);
|
||||
picker->Hide();
|
||||
pickers.push_back(picker);
|
||||
choices_vendors.Add(vendor.name);
|
||||
|
||||
picker->Bind(EVT_PRINTER_PICK, [this, &appconfig](const PrinterPickerEvent &evt) {
|
||||
appconfig.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
|
||||
auto *cbox = new wxCheckBox(this, wxID_ANY, vendor->name);
|
||||
cbox->Bind(wxEVT_CHECKBOX, [=](wxCommandEvent &event) {
|
||||
wizard_p()->on_3rdparty_install(vendor, cbox->IsChecked());
|
||||
});
|
||||
}
|
||||
|
||||
auto *vendor_picker = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices_vendors);
|
||||
if (choices_vendors.GetCount() > 0) {
|
||||
vendor_picker->SetSelection(0);
|
||||
on_vendor_pick(0);
|
||||
}
|
||||
|
||||
vendor_picker->Bind(wxEVT_CHOICE, [this](wxCommandEvent &evt) {
|
||||
this->on_vendor_pick(evt.GetInt());
|
||||
});
|
||||
|
||||
append(vendor_picker);
|
||||
for (PrinterPicker *picker : pickers) { this->append(picker); }
|
||||
}
|
||||
|
||||
void PageVendors::on_vendor_pick(size_t i)
|
||||
{
|
||||
for (PrinterPicker *picker : pickers) { picker->Hide(); }
|
||||
if (i < pickers.size()) {
|
||||
pickers[i]->Show();
|
||||
parent->Layout();
|
||||
append(cbox);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -954,12 +1044,15 @@ void ConfigWizardIndex::go_to(size_t i)
|
|||
}
|
||||
}
|
||||
|
||||
void ConfigWizardIndex::go_to(ConfigWizardPage *page)
|
||||
void ConfigWizardIndex::go_to(const ConfigWizardPage *page)
|
||||
{
|
||||
if (page == nullptr) { return; }
|
||||
|
||||
for (size_t i = 0; i < items.size(); i++) {
|
||||
if (items[i].page == page) { go_to(i); }
|
||||
if (items[i].page == page) {
|
||||
go_to(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1121,21 +1214,25 @@ static const std::unordered_map<std::string, std::pair<std::string, std::string>
|
|||
|
||||
void ConfigWizard::priv::load_pages()
|
||||
{
|
||||
const auto former_active = index->active_item();
|
||||
wxWindowUpdateLocker freeze_guard(q);
|
||||
(void)freeze_guard;
|
||||
|
||||
const ConfigWizardPage *former_active = index->active_page();
|
||||
|
||||
index->clear();
|
||||
|
||||
index->add_page(page_welcome);
|
||||
|
||||
// Printers
|
||||
index->add_page(page_fff);
|
||||
index->add_page(page_msla);
|
||||
|
||||
index->add_page(page_filaments);
|
||||
if (any_sla_selected) {
|
||||
index->add_page(page_sla_materials);
|
||||
index->add_page(page_vendors);
|
||||
for (const auto &pair : pages_3rdparty) {
|
||||
PagePrinters *page = pair.second;
|
||||
if (page->install) { index->add_page(page); }
|
||||
}
|
||||
|
||||
index->add_page(page_custom);
|
||||
|
||||
if (page_custom->custom_wanted()) {
|
||||
index->add_page(page_firmware);
|
||||
index->add_page(page_bed);
|
||||
|
@ -1143,6 +1240,10 @@ void ConfigWizard::priv::load_pages()
|
|||
index->add_page(page_temps);
|
||||
}
|
||||
|
||||
// Filaments & Materials
|
||||
if (any_fff_selected) { index->add_page(page_filaments); }
|
||||
if (any_sla_selected) { index->add_page(page_sla_materials); }
|
||||
|
||||
index->add_page(page_update);
|
||||
|
||||
index->go_to(former_active); // Will restore the active item/page if possible
|
||||
|
@ -1173,66 +1274,75 @@ void ConfigWizard::priv::init_dialog_size()
|
|||
q->SetSize(window_rect);
|
||||
}
|
||||
|
||||
bool ConfigWizard::priv::check_first_variant() const
|
||||
{
|
||||
return run_reason == RR_DATA_EMPTY || run_reason == RR_DATA_LEGACY;
|
||||
}
|
||||
|
||||
void ConfigWizard::priv::load_vendors()
|
||||
{
|
||||
const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor";
|
||||
const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles";
|
||||
// const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor";
|
||||
// const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles";
|
||||
|
||||
PresetBundle bundle;
|
||||
// PresetBundle bundle;
|
||||
// bundle.load_available_system_presets();
|
||||
bundles = BundleMap::load();
|
||||
|
||||
// Load vendors from the "vendors" directory in datadir
|
||||
// XXX: The VendorProfile is loaded twice here, ditto below
|
||||
for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir)) {
|
||||
if (Slic3r::is_ini_file(dir_entry)) {
|
||||
try {
|
||||
bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
|
||||
// // Load vendors from the "vendors" directory in datadir
|
||||
// // XXX: The VendorProfile is loaded twice here, ditto below
|
||||
// for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir)) {
|
||||
// if (Slic3r::is_ini_file(dir_entry)) {
|
||||
// try {
|
||||
// bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
|
||||
|
||||
auto vp = VendorProfile::from_ini(dir_entry.path());
|
||||
vendors[vp.id] = std::move(vp);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what();
|
||||
}
|
||||
// auto vp = VendorProfile::from_ini(dir_entry.path());
|
||||
// vendors[vp.id] = std::move(vp);
|
||||
// }
|
||||
// catch (const std::exception& e) {
|
||||
// BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Additionally load up vendors from the application resources directory, but only those not seen in the datadir
|
||||
// for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir)) {
|
||||
// if (Slic3r::is_ini_file(dir_entry)) {
|
||||
// const auto id = dir_entry.path().stem().string();
|
||||
|
||||
// if (vendors.find(id) == vendors.end()) {
|
||||
// try {
|
||||
// bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
|
||||
|
||||
// auto vp = VendorProfile::from_ini(dir_entry.path());
|
||||
// vendors_rsrc[vp.id] = dir_entry.path().filename().string();
|
||||
// vendors[vp.id] = std::move(vp);
|
||||
// }
|
||||
// catch (const std::exception& e) {
|
||||
// BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Move materials to our Materials container:
|
||||
// for (auto &&f : bundle.filaments) {
|
||||
// f.vendor = nullptr;
|
||||
// filaments.presets.push_back(std::move(f));
|
||||
// filaments.types.insert(Materials::get_filament_type(f));
|
||||
// }
|
||||
// for (auto &&m : bundle.sla_materials) {
|
||||
// m.vendor = nullptr;
|
||||
// sla_materials.presets.push_back(std::move(m));
|
||||
// sla_materials.types.insert(Materials::get_material_type(m));
|
||||
// }
|
||||
for (auto &pair : bundles) {
|
||||
for (auto &&f : pair.second.preset_bundle->filaments) {
|
||||
f.vendor = nullptr;
|
||||
filaments.presets.push_back(std::move(f));
|
||||
filaments.types.insert(Materials::get_filament_type(f));
|
||||
}
|
||||
}
|
||||
|
||||
// Additionally load up vendors from the application resources directory, but only those not seen in the datadir
|
||||
for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir)) {
|
||||
if (Slic3r::is_ini_file(dir_entry)) {
|
||||
const auto id = dir_entry.path().stem().string();
|
||||
|
||||
if (vendors.find(id) == vendors.end()) {
|
||||
try {
|
||||
bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
|
||||
|
||||
auto vp = VendorProfile::from_ini(dir_entry.path());
|
||||
vendors_rsrc[vp.id] = dir_entry.path().filename().string();
|
||||
vendors[vp.id] = std::move(vp);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what();
|
||||
}
|
||||
}
|
||||
for (auto &&m : pair.second.preset_bundle->sla_materials) {
|
||||
m.vendor = nullptr;
|
||||
sla_materials.presets.push_back(std::move(m));
|
||||
sla_materials.types.insert(Materials::get_material_type(m));
|
||||
}
|
||||
}
|
||||
|
||||
// Move materials to our Materials container:
|
||||
for (auto &&f : bundle.filaments) {
|
||||
f.vendor = nullptr;
|
||||
filaments.presets.push_back(std::move(f));
|
||||
filaments.types.insert(Materials::get_filament_type(f));
|
||||
}
|
||||
for (auto &&m : bundle.sla_materials) {
|
||||
m.vendor = nullptr;
|
||||
sla_materials.presets.push_back(std::move(m));
|
||||
sla_materials.types.insert(Materials::get_material_type(m));
|
||||
}
|
||||
|
||||
// Load up the set of vendors / models / variants the user has had enabled up till now
|
||||
AppConfig *app_config = wxGetApp().app_config;
|
||||
if (! app_config->legacy_datadir()) {
|
||||
|
@ -1251,11 +1361,14 @@ void ConfigWizard::priv::load_vendors()
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: This'll be done differently, cf. the design document
|
||||
// Load up the materials enabled till now,
|
||||
// apply defaults from vendor profiles if there are no selections yet.
|
||||
bundle.init_materials_selection(*app_config);
|
||||
wxCHECK_RET(app_config->has_section(AppConfig::SECTION_FILAMENTS) && app_config->has_section(AppConfig::SECTION_MATERIALS),
|
||||
"Failed to initialize default material selections");
|
||||
// bundle.init_materials_selection(*app_config);
|
||||
|
||||
// XXX: ?
|
||||
// wxCHECK_RET(app_config->has_section(AppConfig::SECTION_FILAMENTS) && app_config->has_section(AppConfig::SECTION_MATERIALS),
|
||||
// "Failed to initialize default material selections");
|
||||
appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, app_config->get_section(AppConfig::SECTION_FILAMENTS));
|
||||
appconfig_new.set_section(AppConfig::SECTION_MATERIALS, app_config->get_section(AppConfig::SECTION_MATERIALS));
|
||||
}
|
||||
|
@ -1263,6 +1376,7 @@ void ConfigWizard::priv::load_vendors()
|
|||
void ConfigWizard::priv::add_page(ConfigWizardPage *page)
|
||||
{
|
||||
hscroll_sizer->Add(page, 0, wxEXPAND);
|
||||
all_pages.push_back(page);
|
||||
}
|
||||
|
||||
void ConfigWizard::priv::enable_next(bool enable)
|
||||
|
@ -1281,6 +1395,27 @@ void ConfigWizard::priv::set_start_page(ConfigWizard::StartPage start_page)
|
|||
}
|
||||
}
|
||||
|
||||
void ConfigWizard::priv::create_3rdparty_pages()
|
||||
{
|
||||
for (const auto &pair : bundles) {
|
||||
const VendorProfile *vendor = pair.second.vendor_profile;
|
||||
if (vendor->id == PresetBundle::PRUSA_BUNDLE) { continue; }
|
||||
|
||||
auto *page = new PagePrinters(q, vendor->name, vendor->name, *vendor, 1, T_ANY);
|
||||
add_page(page);
|
||||
|
||||
pages_3rdparty.insert({vendor->id, page});
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigWizard::priv::set_run_reason(RunReason run_reason)
|
||||
{
|
||||
this->run_reason = run_reason;
|
||||
for (auto &page : all_pages) {
|
||||
page->set_run_reason(run_reason);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigWizard::priv::on_custom_setup()
|
||||
{
|
||||
load_pages();
|
||||
|
@ -1288,23 +1423,43 @@ void ConfigWizard::priv::on_custom_setup()
|
|||
|
||||
void ConfigWizard::priv::on_printer_pick(PagePrinters *page)
|
||||
{
|
||||
if (page == page_msla) {
|
||||
const bool any_sla_selected_new = page->any_selected();
|
||||
if (any_sla_selected != any_sla_selected_new) {
|
||||
any_sla_selected = any_sla_selected_new;
|
||||
load_pages();
|
||||
}
|
||||
if (page_msla->any_selected() != any_sla_selected ||
|
||||
page_fff->any_selected() != any_fff_selected) {
|
||||
any_fff_selected = page_fff->any_selected();
|
||||
any_sla_selected = page_msla->any_selected();
|
||||
|
||||
load_pages();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigWizard::priv::on_3rdparty_install(const VendorProfile *vendor, bool install)
|
||||
{
|
||||
auto it = pages_3rdparty.find(vendor->id);
|
||||
wxCHECK_RET(it != pages_3rdparty.end(), "Internal error: GUI page not found for 3rd party vendor profile");
|
||||
PagePrinters *page = it->second;
|
||||
page->install = install;
|
||||
page->Layout();
|
||||
|
||||
load_pages();
|
||||
}
|
||||
|
||||
void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater)
|
||||
{
|
||||
const auto enabled_vendors = appconfig_new.vendors();
|
||||
|
||||
// Install bundles from resources if needed:
|
||||
std::vector<std::string> install_bundles;
|
||||
for (const auto &vendor_rsrc : vendors_rsrc) {
|
||||
const auto vendor = enabled_vendors.find(vendor_rsrc.first);
|
||||
for (const auto &pair : bundles) {
|
||||
if (! pair.second.is_in_resources) { continue; }
|
||||
|
||||
if (pair.second.is_prusa_bundle) {
|
||||
// Always install Prusa bundle, because it has a lot of filaments/materials
|
||||
// likely to be referenced by other profiles.
|
||||
install_bundles.emplace_back(pair.first);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto vendor = enabled_vendors.find(pair.first);
|
||||
if (vendor == enabled_vendors.end()) { continue; }
|
||||
|
||||
size_t size_sum = 0;
|
||||
|
@ -1312,7 +1467,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
|
||||
if (size_sum > 0) {
|
||||
// This vendor needs to be installed
|
||||
install_bundles.emplace_back(vendor_rsrc.second);
|
||||
install_bundles.emplace_back(pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1370,17 +1525,18 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
// The default is the first selected printer model (one with at least 1 variant selected).
|
||||
// The default is only applied by load_presets() if the user doesn't have a (visible) printer
|
||||
// selected already.
|
||||
const auto vendor_prusa = vendors.find("PrusaResearch");
|
||||
const auto config_prusa = enabled_vendors.find("PrusaResearch");
|
||||
if (vendor_prusa != vendors.end() && config_prusa != enabled_vendors.end()) {
|
||||
for (const auto &model : vendor_prusa->second.models) {
|
||||
const auto model_it = config_prusa->second.find(model.id);
|
||||
if (model_it != config_prusa->second.end() && model_it->second.size() > 0) {
|
||||
preferred_model = model.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// const auto vendor_prusa = bundle.vendors.find("PrusaResearch");
|
||||
// const auto config_prusa = enabled_vendors.find("PrusaResearch");
|
||||
// if (vendor_prusa != bundle.vendors.end() && config_prusa != enabled_vendors.end()) {
|
||||
// for (const auto &model : vendor_prusa->second.models) {
|
||||
// const auto model_it = config_prusa->second.find(model.id);
|
||||
// if (model_it != config_prusa->second.end() && model_it->second.size() > 0) {
|
||||
// preferred_model = model.id;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
preset_bundle->load_presets(*app_config, preferred_model);
|
||||
|
||||
|
@ -1398,10 +1554,11 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
preset_bundle->export_selections(*app_config);
|
||||
}
|
||||
|
||||
|
||||
// Public
|
||||
|
||||
ConfigWizard::ConfigWizard()
|
||||
: DPIDialog(nullptr, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
ConfigWizard::ConfigWizard(wxWindow *parent)
|
||||
: DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
, p(new priv(this))
|
||||
{
|
||||
this->SetFont(wxGetApp().normal_font());
|
||||
|
@ -1441,17 +1598,16 @@ ConfigWizard::ConfigWizard()
|
|||
p->btnsizer->Add(p->btn_finish, 0, wxLEFT, BTN_SPACING);
|
||||
p->btnsizer->Add(p->btn_cancel, 0, wxLEFT, BTN_SPACING);
|
||||
|
||||
const auto &vendors = p->vendors;
|
||||
const auto vendor_prusa_it = vendors.find("PrusaResearch");
|
||||
wxCHECK_RET(vendor_prusa_it != vendors.cend(), "Vendor PrusaResearch not found");
|
||||
const VendorProfile &vendor_prusa = vendor_prusa_it->second;
|
||||
const auto prusa_it = p->bundles.find("PrusaResearch");
|
||||
wxCHECK_RET(prusa_it != p->bundles.cend(), "Vendor PrusaResearch not found");
|
||||
const VendorProfile *vendor_prusa = prusa_it->second.vendor_profile;
|
||||
|
||||
p->add_page(p->page_welcome = new PageWelcome(this));
|
||||
|
||||
p->page_fff = new PagePrinters(this, _(L("Prusa FFF Technology Printers")), "Prusa FFF", vendor_prusa, 0, T_FFF);
|
||||
p->page_fff = new PagePrinters(this, _(L("Prusa FFF Technology Printers")), "Prusa FFF", *vendor_prusa, 0, T_FFF);
|
||||
p->add_page(p->page_fff);
|
||||
|
||||
p->page_msla = new PagePrinters(this, _(L("Prusa MSLA Technology Printers")), "Prusa MSLA", vendor_prusa, 0, T_SLA);
|
||||
p->page_msla = new PagePrinters(this, _(L("Prusa MSLA Technology Printers")), "Prusa MSLA", *vendor_prusa, 0, T_SLA);
|
||||
p->add_page(p->page_msla);
|
||||
|
||||
p->add_page(p->page_filaments = new PageMaterials(this, &p->filaments,
|
||||
|
@ -1467,7 +1623,10 @@ ConfigWizard::ConfigWizard()
|
|||
p->add_page(p->page_diams = new PageDiameters(this));
|
||||
p->add_page(p->page_temps = new PageTemperatures(this));
|
||||
|
||||
p->create_3rdparty_pages();
|
||||
|
||||
p->any_sla_selected = p->page_msla->any_selected();
|
||||
p->any_fff_selected = p->page_fff->any_selected();
|
||||
p->load_pages();
|
||||
|
||||
vsizer->Add(topsizer, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
|
||||
|
@ -1514,7 +1673,7 @@ bool ConfigWizard::run(RunReason reason, StartPage start_page)
|
|||
|
||||
GUI_App &app = wxGetApp();
|
||||
|
||||
p->run_reason = reason;
|
||||
p->set_run_reason(reason);
|
||||
p->set_start_page(start_page);
|
||||
|
||||
if (ShowModal() == wxID_OK) {
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
SP_MATERIALS,
|
||||
};
|
||||
|
||||
ConfigWizard();
|
||||
ConfigWizard(wxWindow *parent);
|
||||
ConfigWizard(ConfigWizard &&) = delete;
|
||||
ConfigWizard(const ConfigWizard &) = delete;
|
||||
ConfigWizard &operator=(ConfigWizard &&) = delete;
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "slic3r/Utils/PresetUpdater.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "Preset.hpp"
|
||||
// #include "Preset.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "BedShapeDialog.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
@ -43,13 +44,70 @@ enum {
|
|||
ROW_SPACING = 75,
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Configuration data structures extensions needed for the wizard
|
||||
|
||||
enum Technology {
|
||||
// Bitflag equivalent of PrinterTechnology
|
||||
T_FFF = 0x1,
|
||||
T_SLA = 0x2,
|
||||
T_Any = ~0,
|
||||
T_ANY = ~0,
|
||||
};
|
||||
|
||||
struct Materials
|
||||
{
|
||||
Technology technology;
|
||||
std::vector<Preset> presets;
|
||||
std::set<std::string> types;
|
||||
|
||||
Materials(Technology technology) : technology(technology) {}
|
||||
|
||||
const std::string& appconfig_section() const;
|
||||
const std::string& get_type(Preset &preset) const;
|
||||
const std::string& get_vendor(Preset &preset) const;
|
||||
|
||||
template<class F> void filter_presets(const std::string &type, const std::string &vendor, F cb) {
|
||||
for (Preset &preset : presets) {
|
||||
if ((type.empty() || get_type(preset) == type) && (vendor.empty() || get_vendor(preset) == vendor)) {
|
||||
cb(preset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const std::string UNKNOWN;
|
||||
static const std::string& get_filament_type(const Preset &preset);
|
||||
static const std::string& get_filament_vendor(const Preset &preset);
|
||||
static const std::string& get_material_type(Preset &preset);
|
||||
static const std::string& get_material_vendor(const Preset &preset);
|
||||
};
|
||||
|
||||
struct Bundle
|
||||
{
|
||||
fs::path source_path; // XXX: not needed?
|
||||
std::unique_ptr<PresetBundle> preset_bundle;
|
||||
VendorProfile *vendor_profile;
|
||||
const bool is_in_resources;
|
||||
const bool is_prusa_bundle;
|
||||
|
||||
Bundle(fs::path source_path, bool is_in_resources, bool is_prusa_bundle = false);
|
||||
Bundle(Bundle &&other);
|
||||
|
||||
const std::string& vendor_id() const { return vendor_profile->id; }
|
||||
};
|
||||
|
||||
struct BundleMap: std::unordered_map<std::string, Bundle>
|
||||
{
|
||||
static BundleMap load();
|
||||
|
||||
Bundle& prusa_bundle();
|
||||
const Bundle& prusa_bundle() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// GUI elements
|
||||
|
||||
typedef std::function<bool(const VendorProfile::PrinterModel&)> ModelFilter;
|
||||
|
||||
struct PrinterPicker: wxPanel
|
||||
|
@ -79,6 +137,8 @@ struct PrinterPicker: wxPanel
|
|||
|
||||
int get_width() const { return width; }
|
||||
const std::vector<int>& get_button_indexes() { return m_button_indexes; }
|
||||
|
||||
static const std::string PRINTER_PLACEHOLDER;
|
||||
private:
|
||||
int width;
|
||||
std::vector<int> m_button_indexes;
|
||||
|
@ -97,65 +157,50 @@ struct ConfigWizardPage: wxPanel
|
|||
virtual ~ConfigWizardPage();
|
||||
|
||||
template<class T>
|
||||
void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10)
|
||||
T* append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10)
|
||||
{
|
||||
content->Add(thing, proportion, flag, border);
|
||||
return thing;
|
||||
}
|
||||
|
||||
void append_text(wxString text);
|
||||
wxStaticText* append_text(wxString text);
|
||||
void append_spacer(int space);
|
||||
|
||||
ConfigWizard::priv *wizard_p() const { return parent->p.get(); }
|
||||
|
||||
virtual void apply_custom_config(DynamicPrintConfig &config) {}
|
||||
virtual void set_run_reason(ConfigWizard::RunReason run_reason) {}
|
||||
};
|
||||
|
||||
struct PageWelcome: ConfigWizardPage
|
||||
{
|
||||
wxStaticText *welcome_text;
|
||||
wxCheckBox *cbox_reset;
|
||||
|
||||
PageWelcome(ConfigWizard *parent);
|
||||
|
||||
bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; }
|
||||
|
||||
virtual void set_run_reason(ConfigWizard::RunReason run_reason) override;
|
||||
};
|
||||
|
||||
struct PagePrinters: ConfigWizardPage
|
||||
{
|
||||
std::vector<PrinterPicker *> printer_pickers;
|
||||
Technology technology;
|
||||
bool install;
|
||||
|
||||
PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology);
|
||||
PagePrinters(ConfigWizard *parent,
|
||||
wxString title,
|
||||
wxString shortname,
|
||||
const VendorProfile &vendor,
|
||||
unsigned indent, Technology technology);
|
||||
|
||||
void select_all(bool select, bool alternates = false);
|
||||
int get_width() const;
|
||||
bool any_selected() const;
|
||||
};
|
||||
|
||||
|
||||
struct Materials
|
||||
{
|
||||
Technology technology;
|
||||
std::vector<Preset> presets;
|
||||
std::set<std::string> types;
|
||||
|
||||
Materials(Technology technology) : technology(technology) {}
|
||||
|
||||
const std::string& appconfig_section() const;
|
||||
const std::string& get_type(Preset &preset) const;
|
||||
const std::string& get_vendor(Preset &preset) const;
|
||||
|
||||
template<class F> void filter_presets(const std::string &type, const std::string &vendor, F cb) {
|
||||
for (Preset &preset : presets) {
|
||||
if ((type.empty() || get_type(preset) == type) && (vendor.empty() || get_vendor(preset) == vendor)) {
|
||||
cb(preset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const std::string UNKNOWN;
|
||||
static const std::string& get_filament_type(const Preset &preset);
|
||||
static const std::string& get_filament_vendor(const Preset &preset);
|
||||
static const std::string& get_material_type(Preset &preset);
|
||||
static const std::string& get_material_vendor(const Preset &preset);
|
||||
virtual void set_run_reason(ConfigWizard::RunReason run_reason) override;
|
||||
};
|
||||
|
||||
// Here we extend wxListBox and wxCheckListBox
|
||||
|
@ -232,11 +277,11 @@ struct PageUpdate: ConfigWizardPage
|
|||
|
||||
struct PageVendors: ConfigWizardPage
|
||||
{
|
||||
std::vector<PrinterPicker*> pickers;
|
||||
// std::vector<PrinterPicker*> pickers;
|
||||
|
||||
PageVendors(ConfigWizard *parent);
|
||||
|
||||
void on_vendor_pick(size_t i);
|
||||
// void on_vendor_pick(size_t i);
|
||||
};
|
||||
|
||||
struct PageFirmware: ConfigWizardPage
|
||||
|
@ -290,7 +335,7 @@ public:
|
|||
void go_prev();
|
||||
void go_next();
|
||||
void go_to(size_t i);
|
||||
void go_to(ConfigWizardPage *page);
|
||||
void go_to(const ConfigWizardPage *page);
|
||||
|
||||
void clear();
|
||||
void msw_rescale();
|
||||
|
@ -328,16 +373,24 @@ private:
|
|||
wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent);
|
||||
|
||||
|
||||
|
||||
// ConfigWizard private data
|
||||
|
||||
struct ConfigWizard::priv
|
||||
{
|
||||
ConfigWizard *q;
|
||||
ConfigWizard::RunReason run_reason = RR_USER;
|
||||
AppConfig appconfig_new; // Backing for vendor/model/variant and material selections in the GUI
|
||||
std::unordered_map<std::string, VendorProfile> vendors;
|
||||
// std::unordered_map<std::string, VendorProfile> vendors;
|
||||
// PresetBundle bundle; // XXX: comment
|
||||
BundleMap bundles; // XXX: comment
|
||||
Materials filaments; // Holds available filament presets and their types & vendors
|
||||
Materials sla_materials; // Ditto for SLA materials
|
||||
std::unordered_map<std::string, std::string> vendors_rsrc; // List of bundles to install from resources
|
||||
// std::set<const VendorProfile*> install_3rdparty;
|
||||
// XXX: rm: (?)
|
||||
// std::unordered_map<std::string, std::string> vendors_rsrc; // List of bundles to install from resources
|
||||
std::unique_ptr<DynamicPrintConfig> custom_config; // Backing for custom printer definition
|
||||
bool any_fff_selected; // Used to decide whether to display Filaments page
|
||||
bool any_sla_selected; // Used to decide whether to display SLA Materials page
|
||||
|
||||
wxScrolledWindow *hscroll = nullptr;
|
||||
|
@ -359,6 +412,7 @@ struct ConfigWizard::priv
|
|||
PageCustom *page_custom = nullptr;
|
||||
PageUpdate *page_update = nullptr;
|
||||
PageVendors *page_vendors = nullptr; // XXX: ?
|
||||
std::map<std::string, PagePrinters*> pages_3rdparty;
|
||||
|
||||
// Custom setup pages
|
||||
PageFirmware *page_firmware = nullptr;
|
||||
|
@ -366,6 +420,9 @@ struct ConfigWizard::priv
|
|||
PageDiameters *page_diams = nullptr;
|
||||
PageTemperatures *page_temps = nullptr;
|
||||
|
||||
// Pointers to all pages (regardless or whether currently part of the ConfigWizardIndex)
|
||||
std::vector<ConfigWizardPage*> all_pages;
|
||||
|
||||
priv(ConfigWizard *q)
|
||||
: q(q)
|
||||
, filaments(T_FFF)
|
||||
|
@ -376,14 +433,16 @@ struct ConfigWizard::priv
|
|||
void load_pages();
|
||||
void init_dialog_size();
|
||||
|
||||
bool check_first_variant() const;
|
||||
void load_vendors();
|
||||
void add_page(ConfigWizardPage *page);
|
||||
void enable_next(bool enable);
|
||||
void set_start_page(ConfigWizard::StartPage start_page);
|
||||
void create_3rdparty_pages();
|
||||
void set_run_reason(RunReason run_reason);
|
||||
|
||||
void on_custom_setup();
|
||||
void on_printer_pick(PagePrinters *page);
|
||||
void on_3rdparty_install(const VendorProfile *vendor, bool install); // XXX: ?
|
||||
|
||||
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater);
|
||||
|
||||
|
|
|
@ -1059,8 +1059,10 @@ void GUI_App::open_web_page_localized(const std::string &http_address)
|
|||
|
||||
bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page)
|
||||
{
|
||||
wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null");
|
||||
|
||||
if (! m_wizard) {
|
||||
m_wizard.reset(new ConfigWizard());
|
||||
m_wizard = new ConfigWizard(mainframe);
|
||||
}
|
||||
|
||||
const bool res = m_wizard->run(reason, start_page);
|
||||
|
|
|
@ -98,7 +98,7 @@ class GUI_App : public wxApp
|
|||
|
||||
std::unique_ptr<ImGuiWrapper> m_imgui;
|
||||
std::unique_ptr<PrintHostJobQueue> m_printhost_job_queue;
|
||||
std::unique_ptr<ConfigWizard> m_wizard;
|
||||
ConfigWizard* m_wizard; // Managed by wxWindow tree
|
||||
|
||||
public:
|
||||
bool OnInit() override;
|
||||
|
|
|
@ -1318,7 +1318,7 @@ bool PresetCollection::select_preset_by_name_strict(const std::string &name)
|
|||
}
|
||||
|
||||
// Merge one vendor's presets with the other vendor's presets, report duplicates.
|
||||
std::vector<std::string> PresetCollection::merge_presets(PresetCollection &&other, const std::set<VendorProfile> &new_vendors)
|
||||
std::vector<std::string> PresetCollection::merge_presets(PresetCollection &&other, const VendorMap &new_vendors)
|
||||
{
|
||||
std::vector<std::string> duplicates;
|
||||
for (Preset &preset : other.m_presets) {
|
||||
|
@ -1329,9 +1329,9 @@ std::vector<std::string> PresetCollection::merge_presets(PresetCollection &&othe
|
|||
if (it == m_presets.end() || it->name != preset.name) {
|
||||
if (preset.vendor != nullptr) {
|
||||
// Re-assign a pointer to the vendor structure in the new PresetBundle.
|
||||
auto it = new_vendors.find(*preset.vendor);
|
||||
auto it = new_vendors.find(preset.vendor->id);
|
||||
assert(it != new_vendors.end());
|
||||
preset.vendor = &(*it);
|
||||
preset.vendor = &it->second;
|
||||
}
|
||||
this->m_presets.emplace(it, std::move(preset));
|
||||
} else
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define slic3r_Preset_hpp_
|
||||
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/property_tree/ptree_fwd.hpp>
|
||||
|
@ -89,6 +91,12 @@ public:
|
|||
bool operator==(const VendorProfile &rhs) const { return this->id == rhs.id; }
|
||||
};
|
||||
|
||||
// Note: it is imporant that map is used here rather than unordered_map,
|
||||
// because we need iterators to not be invalidated,
|
||||
// because Preset and the ConfigWizard hold pointers to VendorProfiles.
|
||||
// XXX: maybe set is enough (cf. changes in Wizard)
|
||||
typedef std::map<std::string, VendorProfile> VendorMap;
|
||||
|
||||
class Preset
|
||||
{
|
||||
public:
|
||||
|
@ -435,7 +443,7 @@ protected:
|
|||
bool select_preset_by_name_strict(const std::string &name);
|
||||
|
||||
// Merge one vendor's presets with the other vendor's presets, report duplicates.
|
||||
std::vector<std::string> merge_presets(PresetCollection &&other, const std::set<VendorProfile> &new_vendors);
|
||||
std::vector<std::string> merge_presets(PresetCollection &&other, const VendorMap &new_vendors);
|
||||
|
||||
private:
|
||||
PresetCollection();
|
||||
|
|
|
@ -41,6 +41,8 @@ static std::vector<std::string> s_project_options {
|
|||
"wiping_volumes_matrix"
|
||||
};
|
||||
|
||||
const char *PresetBundle::PRUSA_BUNDLE = "PrusaResearch";
|
||||
|
||||
PresetBundle::PresetBundle() :
|
||||
prints(Preset::TYPE_PRINT, Preset::print_options(), static_cast<const HostConfig&>(FullPrintConfig::defaults())),
|
||||
filaments(Preset::TYPE_FILAMENT, Preset::filament_options(), static_cast<const HostConfig&>(FullPrintConfig::defaults())),
|
||||
|
@ -244,6 +246,48 @@ void PresetBundle::load_presets(AppConfig &config, const std::string &preferred_
|
|||
this->load_selections(config, preferred_model_id);
|
||||
}
|
||||
|
||||
// FIXME: Comment
|
||||
// XXX: rm
|
||||
void PresetBundle::load_available_system_presets()
|
||||
{
|
||||
const auto vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / "vendor").make_preferred();
|
||||
const auto rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
||||
|
||||
const auto prusa_bundle_vendor = (vendor_dir / PRUSA_BUNDLE).replace_extension(".ini");
|
||||
const auto prusa_bundle = boost::filesystem::exists(prusa_bundle_vendor) ? prusa_bundle_vendor
|
||||
: (rsrc_vendor_dir / PRUSA_BUNDLE).replace_extension(".ini");
|
||||
|
||||
// Reset this PresetBundle and load the Prusa bundle first.
|
||||
this->load_configbundle(prusa_bundle.string(), LOAD_CFGBNDLE_SYSTEM);
|
||||
|
||||
// Load the other bundles in the datadir/vendor directory
|
||||
// and then additionally from resources/profiles.
|
||||
for (auto dir : { &vendor_dir, &rsrc_vendor_dir }) {
|
||||
for (const auto &dir_entry : boost::filesystem::directory_iterator(*dir)) {
|
||||
if (Slic3r::is_ini_file(dir_entry)) {
|
||||
std::string id = dir_entry.path().stem().string(); // stem() = filename() without the trailing ".ini" part
|
||||
|
||||
// Don't load this bundle if we've already loaded it.
|
||||
// Note that this takes care of not loading the PRUSA_BUNDLE which was loaded upfront
|
||||
// as well as bundles with the same name (id) in rsrc_vendor_dir as in vendor_dir.
|
||||
if (vendors.find(id) != vendors.end()) { continue; }
|
||||
|
||||
PresetBundle other;
|
||||
other.load_configbundle(dir_entry.path().string(), LOAD_CFGBNDLE_SYSTEM);
|
||||
|
||||
std::vector<std::string> duplicates = this->merge_presets(std::move(other));
|
||||
if (! duplicates.empty()) {
|
||||
std::string msg = "Vendor configuration file " + id + " contains the following presets with names used by other vendors: ";
|
||||
for (size_t i = 0; i < duplicates.size(); ++ i) {
|
||||
if (i > 0) { msg += ", "; }
|
||||
msg += duplicates[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load system presets into this PresetBundle.
|
||||
// For each vendor, there will be a single PresetBundle loaded.
|
||||
std::string PresetBundle::load_system_presets()
|
||||
|
@ -414,14 +458,14 @@ void PresetBundle::export_selections(AppConfig &config)
|
|||
void PresetBundle::init_materials_selection(AppConfig &config) const {
|
||||
if (! config.has_section(AppConfig::SECTION_FILAMENTS)) {
|
||||
for (const auto &vendor : this->vendors) {
|
||||
for (const auto &profile : vendor.default_filaments) {
|
||||
for (const auto &profile : vendor.second.default_filaments) {
|
||||
config.set(AppConfig::SECTION_FILAMENTS, profile, "1");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! config.has_section(AppConfig::SECTION_MATERIALS)) {
|
||||
for (const auto &vendor : this->vendors) {
|
||||
for (const auto &profile : vendor.default_sla_materials) {
|
||||
for (const auto &profile : vendor.second.default_sla_materials) {
|
||||
config.set(AppConfig::SECTION_MATERIALS, profile, "1");
|
||||
}
|
||||
}
|
||||
|
@ -1061,7 +1105,7 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
|
|||
auto vp = VendorProfile::from_ini(tree, path);
|
||||
if (vp.num_variants() == 0)
|
||||
return 0;
|
||||
vendor_profile = &(*this->vendors.insert(vp).first);
|
||||
vendor_profile = &this->vendors.insert({vp.id, vp}).first->second;
|
||||
}
|
||||
|
||||
if (flags & LOAD_CFGBUNDLE_VENDOR_ONLY) {
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#include "AppConfig.hpp"
|
||||
#include "Preset.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
class wxWindow;
|
||||
|
@ -56,7 +58,8 @@ public:
|
|||
|
||||
// There will be an entry for each system profile loaded,
|
||||
// and the system profiles will point to the VendorProfile instances owned by PresetBundle::vendors.
|
||||
std::set<VendorProfile> vendors;
|
||||
// std::set<VendorProfile> vendors;
|
||||
VendorMap vendors;
|
||||
|
||||
struct ObsoletePresets {
|
||||
std::vector<std::string> prints;
|
||||
|
@ -135,6 +138,9 @@ public:
|
|||
|
||||
void load_default_preset_bitmaps(wxWindow *window);
|
||||
|
||||
void load_available_system_presets(); // XXX: name XXX: retval (VendorMap stored internally)
|
||||
|
||||
static const char *PRUSA_BUNDLE;
|
||||
private:
|
||||
std::string load_system_presets();
|
||||
// Merge one vendor's presets with the other vendor's presets, report duplicates.
|
||||
|
|
|
@ -153,7 +153,7 @@ struct PresetUpdater::priv
|
|||
bool get_file(const std::string &url, const fs::path &target_path) const;
|
||||
void prune_tmps() const;
|
||||
void sync_version() const;
|
||||
void sync_config(const std::set<VendorProfile> vendors);
|
||||
void sync_config(const VendorMap vendors);
|
||||
|
||||
void check_install_indices() const;
|
||||
Updates get_config_updates() const;
|
||||
|
@ -266,7 +266,7 @@ void PresetUpdater::priv::sync_version() const
|
|||
|
||||
// Download vendor indices. Also download new bundles if an index indicates there's a new one available.
|
||||
// Both are saved in cache.
|
||||
void PresetUpdater::priv::sync_config(const std::set<VendorProfile> vendors)
|
||||
void PresetUpdater::priv::sync_config(const VendorMap vendors)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "Syncing configuration cache";
|
||||
|
||||
|
@ -276,13 +276,13 @@ void PresetUpdater::priv::sync_config(const std::set<VendorProfile> vendors)
|
|||
for (auto &index : index_db) {
|
||||
if (cancel) { return; }
|
||||
|
||||
const auto vendor_it = vendors.find(VendorProfile(index.vendor()));
|
||||
const auto vendor_it = vendors.find(index.vendor());
|
||||
if (vendor_it == vendors.end()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "No such vendor: " << index.vendor();
|
||||
continue;
|
||||
}
|
||||
|
||||
const VendorProfile &vendor = *vendor_it;
|
||||
const VendorProfile &vendor = vendor_it->second;
|
||||
if (vendor.config_update_url.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Vendor has no config_update_url: " << vendor.name;
|
||||
continue;
|
||||
|
@ -574,7 +574,7 @@ void PresetUpdater::sync(PresetBundle *preset_bundle)
|
|||
// Copy the whole vendors data for use in the background thread
|
||||
// Unfortunatelly as of C++11, it needs to be copied again
|
||||
// into the closure (but perhaps the compiler can elide this).
|
||||
std::set<VendorProfile> vendors = preset_bundle->vendors;
|
||||
VendorMap vendors = preset_bundle->vendors;
|
||||
|
||||
p->thread = std::move(std::thread([this, vendors]() {
|
||||
this->p->prune_tmps();
|
||||
|
@ -691,8 +691,8 @@ void PresetUpdater::install_bundles_rsrc(std::vector<std::string> bundles, bool
|
|||
BOOST_LOG_TRIVIAL(info) << boost::format("Installing %1% bundles from resources ...") % bundles.size();
|
||||
|
||||
for (const auto &bundle : bundles) {
|
||||
auto path_in_rsrc = p->rsrc_path / bundle;
|
||||
auto path_in_vendors = p->vendor_path / bundle;
|
||||
auto path_in_rsrc = (p->rsrc_path / bundle).replace_extension(".ini");
|
||||
auto path_in_vendors = (p->vendor_path / bundle).replace_extension(".ini");
|
||||
updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", "");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue