Physical printers: Implemented import/export to/from the ConfigBundle.

+ fixed a bug : Case sensitivity of printer's name wasn't check during the adding of a new printer,
as a result in printers list was appeared both of printers (ex. "YuSanka" and "yusanka"), but related file was just one.
This commit is contained in:
YuSanka 2020-10-01 22:48:00 +02:00
parent 94a9820661
commit 2bba0e3131
7 changed files with 140 additions and 27 deletions

View File

@ -1361,7 +1361,7 @@ const std::vector<std::string>& PhysicalPrinter::printer_options()
s_opts = {
"preset_name",
"printer_technology",
"printer_model",
// "printer_model",
"host_type",
"print_host",
"printhost_apikey",
@ -1576,6 +1576,24 @@ void PhysicalPrinterCollection::load_printers(const std::string& dir_path, const
throw Slic3r::RuntimeError(errors_cummulative);
}
void PhysicalPrinterCollection::load_printer(const std::string& path, const std::string& name, DynamicPrintConfig&& config, bool select, bool save/* = false*/)
{
auto it = this->find_printer_internal(name);
if (it == m_printers.end() || it->name != name) {
// The preset was not found. Create a new preset.
it = m_printers.emplace(it, PhysicalPrinter(name, config));
}
it->file = path;
it->config = std::move(config);
it->loaded = true;
if (select)
this->select_printer(*it);
if (save)
it->save();
}
// if there is saved user presets, contains information about "Print Host upload",
// Create default printers with this presets
// Note! "Print Host upload" options will be cleared after physical printer creations
@ -1623,12 +1641,39 @@ void PhysicalPrinterCollection::load_printers_from_presets(PrinterPresetCollecti
}
}
PhysicalPrinter* PhysicalPrinterCollection::find_printer( const std::string& name, bool first_visible_if_not_found)
PhysicalPrinter* PhysicalPrinterCollection::find_printer( const std::string& name, bool case_sensitive_search)
{
auto it = this->find_printer_internal(name);
auto it = this->find_printer_internal(name, case_sensitive_search);
// Ensure that a temporary copy is returned if the preset found is currently selected.
return (it != m_printers.end() && it->name == name) ? &this->printer(it - m_printers.begin()) :
first_visible_if_not_found ? &this->printer(0) : nullptr;
auto is_equal_name = [name, case_sensitive_search](const std::string& in_name) {
if (case_sensitive_search)
return in_name == name;
return boost::to_lower_copy<std::string>(in_name) == boost::to_lower_copy<std::string>(name);
};
if (it == m_printers.end() || !is_equal_name(it->name))
return nullptr;
return &this->printer(it - m_printers.begin());
}
std::deque<PhysicalPrinter>::iterator PhysicalPrinterCollection::find_printer_internal(const std::string& name, bool case_sensitive_search/* = true*/)
{
if (case_sensitive_search)
return Slic3r::lower_bound_by_predicate(m_printers.begin(), m_printers.end(), [&name](const auto& l) { return l.name < name; });
std::string low_name = boost::to_lower_copy<std::string>(name);
int i = 0;
for (const PhysicalPrinter& printer : m_printers) {
if (boost::to_lower_copy<std::string>(printer.name) == low_name)
break;
i++;
}
if (i == m_printers.size())
return m_printers.end();
return m_printers.begin() + i;
}
PhysicalPrinter* PhysicalPrinterCollection::find_printer_with_same_config(const DynamicPrintConfig& config)
@ -1667,10 +1712,13 @@ void PhysicalPrinterCollection::save_printer(PhysicalPrinter& edited_printer, co
it->config = std::move(edited_printer.config);
it->name = edited_printer.name;
it->preset_names = edited_printer.preset_names;
// sort printers and get new it
std::sort(m_printers.begin(), m_printers.end());
it = this->find_printer_internal(edited_printer.name);
}
else {
// Creating a new printer.
it = m_printers.insert(it, edited_printer);
it = m_printers.emplace(it, edited_printer);
}
assert(it != m_printers.end());

View File

@ -632,6 +632,8 @@ public:
// Load ini files of the particular type from the provided directory path.
void load_printers(const std::string& dir_path, const std::string& subdir);
void load_printers_from_presets(PrinterPresetCollection &printer_presets);
// Load printer from the loaded configuration
void load_printer(const std::string& path, const std::string& name, DynamicPrintConfig&& config, bool select, bool save=false);
// Save the printer under a new name. If the name is different from the old one,
// a new printer is stored into the list of printers.
@ -687,10 +689,11 @@ public:
// Return a preset by its name. If the preset is active, a temporary copy is returned.
// If a preset is not found by its name, null is returned.
PhysicalPrinter* find_printer(const std::string& name, bool first_visible_if_not_found = false);
const PhysicalPrinter* find_printer(const std::string& name, bool first_visible_if_not_found = false) const
// It is possible case (in)sensitive search
PhysicalPrinter* find_printer(const std::string& name, bool case_sensitive_search = true);
const PhysicalPrinter* find_printer(const std::string& name, bool case_sensitive_search = true) const
{
return const_cast<PhysicalPrinterCollection*>(this)->find_printer(name, first_visible_if_not_found);
return const_cast<PhysicalPrinterCollection*>(this)->find_printer(name, case_sensitive_search);
}
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
@ -701,15 +704,11 @@ public:
private:
PhysicalPrinterCollection& operator=(const PhysicalPrinterCollection& other);
// Find a preset position in the sorted list of presets.
// The "-- default -- " preset is always the first, so it needs
// to be handled differently.
// If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name.
std::deque<PhysicalPrinter>::iterator find_printer_internal(const std::string& name)
{
return Slic3r::lower_bound_by_predicate(m_printers.begin(), m_printers.end(), [&name](const auto& l) { return l.name < name; });
}
std::deque<PhysicalPrinter>::const_iterator find_printer_internal(const std::string& name) const
// Find a physical printer position in the sorted list of printers.
// The name of a printer should be unique and case insensitive
// Use this functions with case_sensitive_search = false, when you need case insensitive search
std::deque<PhysicalPrinter>::iterator find_printer_internal(const std::string& name, bool case_sensitive_search = true);
std::deque<PhysicalPrinter>::const_iterator find_printer_internal(const std::string& name, bool case_sensitive_search = true) const
{
return const_cast<PhysicalPrinterCollection*>(this)->find_printer_internal(name);
}

View File

@ -1113,16 +1113,22 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
std::vector<std::string> loaded_sla_prints;
std::vector<std::string> loaded_sla_materials;
std::vector<std::string> loaded_printers;
std::vector<std::string> loaded_physical_printers;
std::string active_print;
std::vector<std::string> active_filaments;
std::string active_sla_print;
std::string active_sla_material;
std::string active_printer;
std::string active_physical_printer;
size_t presets_loaded = 0;
size_t ph_printers_loaded = 0;
for (const auto &section : tree) {
PresetCollection *presets = nullptr;
std::vector<std::string> *loaded = nullptr;
std::string preset_name;
PhysicalPrinterCollection *ph_printers = nullptr;
std::string ph_printer_name;
if (boost::starts_with(section.first, "print:")) {
presets = &this->prints;
loaded = &loaded_prints;
@ -1143,6 +1149,10 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
presets = &this->printers;
loaded = &loaded_printers;
preset_name = section.first.substr(8);
} else if (boost::starts_with(section.first, "physical_printer:")) {
ph_printers = &this->physical_printers;
loaded = &loaded_physical_printers;
ph_printer_name = section.first.substr(17);
} else if (section.first == "presets") {
// Load the names of the active presets.
for (auto &kvp : section.second) {
@ -1161,6 +1171,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
active_sla_material = kvp.second.data();
} else if (kvp.first == "printer") {
active_printer = kvp.second.data();
}else if (kvp.first == "physical_printer") {
active_physical_printer = kvp.second.data();
}
}
} else if (section.first == "obsolete_presets") {
@ -1317,9 +1329,46 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
++ presets_loaded;
}
if (ph_printers != nullptr) {
// Load the physical printer
const DynamicPrintConfig& default_config = ph_printers->default_config();
DynamicPrintConfig config = default_config;
for (auto& kvp : section.second)
config.set_deserialize(kvp.first, kvp.second.data());
// Report configuration fields, which are misplaced into a wrong group.
std::string incorrect_keys = Preset::remove_invalid_keys(config, default_config);
if (!incorrect_keys.empty())
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The physical printer \"" <<
section.first << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
const PhysicalPrinter* ph_printer_existing = ph_printers->find_printer(ph_printer_name, false);
if (ph_printer_existing != nullptr) {
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The physical printer \"" <<
section.first << "\" has already been loaded from another Confing Bundle.";
continue;
}
// 3) Activate the presets.
// Decide a full path to this .ini file.
auto file_name = boost::algorithm::iends_with(ph_printer_name, ".ini") ? ph_printer_name : ph_printer_name + ".ini";
auto file_path = (boost::filesystem::path(data_dir())
#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
// Store the physical printers into a "presets" directory.
/ "presets"
#else
// Store the physical printers at the same location as the upstream Slic3r.
#endif
/ "physical_printer" / file_name).make_preferred();
// Load the preset into the list of presets, save it to disk.
ph_printers->load_printer(file_path.string(), ph_printer_name, std::move(config), false, flags & LOAD_CFGBNDLE_SAVE);
++ph_printers_loaded;
}
}
// 3) Activate the presets and physical printer if any exists.
if ((flags & LOAD_CFGBNDLE_SYSTEM) == 0) {
if (! active_print.empty())
prints.select_preset_by_name(active_print, true);
@ -1329,6 +1378,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
sla_materials.select_preset_by_name(active_sla_material, true);
if (! active_printer.empty())
printers.select_preset_by_name(active_printer, true);
if (! active_physical_printer.empty())
physical_printers.select_printer(active_physical_printer +" * " + active_printer);
// Activate the first filament preset.
if (! active_filaments.empty() && ! active_filaments.front().empty())
filaments.select_preset_by_name(active_filaments.front(), true);
@ -1338,7 +1389,7 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
this->update_compatible(PresetSelectCompatibleType::Never);
}
return presets_loaded;
return presets_loaded + ph_printers_loaded;
}
void PresetBundle::update_multi_material_filament_presets()
@ -1458,7 +1509,7 @@ void PresetBundle::update_compatible(PresetSelectCompatibleType select_other_pri
}
}
void PresetBundle::export_configbundle(const std::string &path, bool export_system_settings)
void PresetBundle::export_configbundle(const std::string &path, bool export_system_settings, bool export_physical_printers/* = false*/)
{
boost::nowide::ofstream c;
c.open(path, std::ios::out | std::ios::trunc);
@ -1482,6 +1533,14 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst
}
}
if (export_physical_printers) {
for (const PhysicalPrinter& ph_printer : this->physical_printers) {
c << std::endl << "[physical_printer:" << ph_printer.name << "]" << std::endl;
for (const std::string& opt_key : ph_printer.config.keys())
c << opt_key << " = " << ph_printer.config.opt_serialize(opt_key) << std::endl;
}
}
// Export the names of the active presets.
c << std::endl << "[presets]" << std::endl;
c << "print = " << this->prints.get_selected_preset_name() << std::endl;
@ -1497,6 +1556,8 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst
c << "filament" << suffix << " = " << this->filament_presets[i] << std::endl;
}
if (export_physical_printers && this->physical_printers.get_selected_idx() >= 0)
c << "physical_printer = " << this->physical_printers.get_selected_printer_name() << std::endl;
#if 0
// Export the following setting values from the provided setting repository.
static const char *settings_keys[] = { "autocenter" };

View File

@ -102,7 +102,7 @@ public:
size_t load_configbundle(const std::string &path, unsigned int flags = LOAD_CFGBNDLE_SAVE);
// Export a config bundle file containing all the presets and the names of the active presets.
void export_configbundle(const std::string &path, bool export_system_settings = false);
void export_configbundle(const std::string &path, bool export_system_settings = false, bool export_physical_printers = false);
// Enable / disable the "- default -" preset.
void set_default_suppressed(bool default_suppressed);

View File

@ -1071,6 +1071,9 @@ void MainFrame::init_menubar()
append_menu_item(export_menu, wxID_ANY, _L("Export Config &Bundle") + dots, _L("Export all presets to file"),
[this](wxCommandEvent&) { export_configbundle(); }, "export_config_bundle", nullptr,
[this]() {return true; }, this);
append_menu_item(export_menu, wxID_ANY, _L("Export Config Bundle With Physical Printers") + dots, _L("Export all presets including physical printers to file"),
[this](wxCommandEvent&) { export_configbundle(true); }, "export_config_bundle", nullptr,
[this]() {return true; }, this);
append_submenu(fileMenu, export_menu, wxID_ANY, _L("&Export"), "");
append_menu_item(fileMenu, wxID_ANY, _L("Ejec&t SD card / Flash drive") + dots + "\tCtrl+T", _L("Eject SD card / Flash drive after the G-code was exported to it."),
@ -1641,7 +1644,7 @@ bool MainFrame::load_config_file(const std::string &path)
return true;
}
void MainFrame::export_configbundle()
void MainFrame::export_configbundle(bool export_physical_printers /*= false*/)
{
if (!wxGetApp().check_unsaved_changes())
return;
@ -1663,7 +1666,7 @@ void MainFrame::export_configbundle()
// Export the config bundle.
wxGetApp().app_config->update_config_dir(get_dir_name(file));
try {
wxGetApp().preset_bundle->export_configbundle(file.ToUTF8().data());
wxGetApp().preset_bundle->export_configbundle(file.ToUTF8().data(), false, export_physical_printers);
} catch (const std::exception &ex) {
show_error(this, ex.what());
}

View File

@ -180,7 +180,7 @@ public:
void load_config_file();
// Open a config file. Return true if loaded.
bool load_config_file(const std::string &path);
void export_configbundle();
void export_configbundle(bool export_physical_printers = false);
void load_configbundle(wxString file = wxEmptyString);
void load_config(const DynamicPrintConfig& config);
// Select tab in m_tabpanel

View File

@ -468,15 +468,17 @@ void PhysicalPrinterDialog::OnOK(wxEvent& event)
}
PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers;
const PhysicalPrinter* existing = printers.find_printer(into_u8(printer_name));
const PhysicalPrinter* existing = printers.find_printer(into_u8(printer_name), false);
if (existing && into_u8(printer_name) != printers.get_selected_printer_name())
{
wxString msg_text = from_u8((boost::format(_u8L("Printer with name \"%1%\" already exists.")) % printer_name).str());
wxString msg_text = from_u8((boost::format(_u8L("Printer with name \"%1%\" already exists.")) % existing->name/*printer_name*/).str());
msg_text += "\n" + _L("Replace?");
wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO);
if (dialog.ShowModal() == wxID_NO)
return;
m_printer.name = existing->name;
}
std::set<std::string> repeat_presets;