diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 1c848b60f..c2439b26f 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -590,6 +590,7 @@ void PresetCollection::reset(bool delete_files) m_presets.erase(m_presets.begin() + m_num_default_presets, m_presets.end()); this->select_preset(0); } + m_map_system_profile_renamed.clear(); } void PresetCollection::add_default_preset(const std::vector &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &preset_name) @@ -703,6 +704,11 @@ Preset& PresetCollection::load_external_preset( // Is there a preset already loaded with the name stored inside the config? std::deque::iterator it = this->find_preset_internal(original_name); bool found = it != m_presets.end() && it->name == original_name; + if (! found) { + // Try to match the original_name against the "renamed_from" profile names of loaded system profiles. + it = this->find_preset_renamed(original_name); + found = it != m_presets.end(); + } if (found && profile_print_params_same(it->config, cfg)) { // The preset exists and it matches the values stored inside config. if (select) @@ -872,24 +878,27 @@ const Preset* PresetCollection::get_selected_preset_parent() const if (this->get_selected_idx() == -1) // This preset collection has no preset activated yet. Only the get_edited_preset() is valid. return nullptr; -// const std::string &inherits = this->get_edited_preset().inherits(); -// if (inherits.empty()) -// return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; - std::string inherits = this->get_edited_preset().inherits(); - if (inherits.empty()) - { - if (this->get_selected_preset().is_system || this->get_selected_preset().is_default) - return &this->get_selected_preset(); - if (this->get_selected_preset().is_external) + const Preset &selected_preset = this->get_selected_preset(); + if (selected_preset.is_system || selected_preset.is_default) + return &selected_preset; + + const Preset &edited_preset = this->get_edited_preset(); + const std::string &inherits = edited_preset.inherits(); + const Preset *preset = nullptr; + if (inherits.empty()) { + if (selected_preset.is_external) return nullptr; - - inherits = m_type != Preset::Type::TYPE_PRINTER ? "- default -" : - this->get_edited_preset().printer_technology() == ptFFF ? - "- default FFF -" : "- default SLA -" ; + preset = &this->default_preset(m_type == Preset::Type::TYPE_PRINTER && edited_preset.printer_technology() == ptSLA ? 1 : 0); + } else + preset = this->find_preset(inherits, false); + if (preset == nullptr) { + // Resolve the "renamed_from" field. + assert(! inherits.empty()); + auto it = this->find_preset_renamed(inherits); + if (it != m_presets.end()) + preset = &(*it); } - - const Preset* preset = this->find_preset(inherits, false); return (preset == nullptr/* || preset->is_default*/ || preset->is_external) ? nullptr : preset; } @@ -900,6 +909,11 @@ const Preset* PresetCollection::get_preset_parent(const Preset& child) const // return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; return nullptr; const Preset* preset = this->find_preset(inherits, false); + if (preset == nullptr) { + auto it = this->find_preset_renamed(inherits); + if (it != m_presets.end()) + preset = &(*it); + } return (preset == nullptr/* || preset->is_default */|| preset->is_external) ? nullptr : preset; } @@ -1402,6 +1416,17 @@ std::vector PresetCollection::merge_presets(PresetCollection &&othe return duplicates; } +void PresetCollection::update_map_system_profile_renamed() +{ + m_map_system_profile_renamed.clear(); + for (Preset &preset : m_presets) + for (const std::string &renamed_from : preset.renamed_from) { + const auto [it, success] = m_map_system_profile_renamed.insert(std::pair(renamed_from, preset.name)); + if (! success) + BOOST_LOG_TRIVIAL(error) << boost::format("Preset name \"%1%\" was marked as renamed from \"%2%\", though preset name \"%3%\" was marked as renamed from \"%2%\" as well.") % preset.name % renamed_from % it->second; + } +} + std::string PresetCollection::name() const { switch (this->type()) { diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index 785f52c42..547814559 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -163,6 +163,10 @@ public: // Alias of the preset std::string alias = ""; + // List of profile names, from which this profile was renamed at some point of time. + // This list is then used to match profiles by their names when loaded from .gcode, .3mf, .amf, + // and to match the "inherits" field of user profiles with updated system profiles. + std::vector renamed_from; void save(); @@ -333,7 +337,8 @@ public: // The parent preset may be a system preset or a user preset, which will be // reflected by the UI. const Preset* get_selected_preset_parent() const; - // get parent preset for some child preset + // Get parent preset for a child preset, based on the "inherits" field of a child, + // where the "inherits" profile name is searched for in both m_presets and m_map_system_profile_renamed. const Preset* get_preset_parent(const Preset& child) const; // Return the selected preset including the user modifications. Preset& get_edited_preset() { return m_edited_preset; } @@ -465,6 +470,9 @@ protected: // Merge one vendor's presets with the other vendor's presets, report duplicates. std::vector merge_presets(PresetCollection &&other, const VendorMap &new_vendors); + // Update m_map_system_profile_renamed from loaded system profiles. + void update_map_system_profile_renamed(); + private: PresetCollection(); PresetCollection(const PresetCollection &other); @@ -490,6 +498,14 @@ private: } std::deque::const_iterator find_preset_internal(const std::string &name) const { return const_cast(this)->find_preset_internal(name); } + std::deque::iterator find_preset_renamed(const std::string &name) { + auto it_renamed = m_map_system_profile_renamed.find(name); + auto it = (it_renamed == m_map_system_profile_renamed.end()) ? m_presets.end() : this->find_preset_internal(it_renamed->second); + assert((it_renamed == m_map_system_profile_renamed.end()) || (it != m_presets.end() && it->name == it_renamed->second)); + return it; + } + std::deque::const_iterator find_preset_renamed(const std::string &name) const + { return const_cast(this)->find_preset_renamed(name); } size_t update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool unselect_if_incompatible); @@ -501,6 +517,8 @@ private: // Use deque to force the container to allocate an object per each entry, // so that the addresses of the presets don't change during resizing of the container. std::deque m_presets; + // Map from old system profile name to a current system profile name. + std::map m_map_system_profile_renamed; // Initially this preset contains a copy of the selected preset. Later on, this copy may be modified by the user. Preset m_edited_preset; // Selected preset. diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index dbfd446b1..3ede7a4e0 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -288,6 +288,11 @@ std::string PresetBundle::load_system_presets() // No config bundle loaded, reset. this->reset(false); } + this->prints .update_map_system_profile_renamed(); + this->sla_prints .update_map_system_profile_renamed(); + this->filaments .update_map_system_profile_renamed(); + this->sla_materials.update_map_system_profile_renamed(); + this->printers .update_map_system_profile_renamed(); return errors_cummulative; } @@ -1132,7 +1137,6 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla PresetCollection *presets = nullptr; std::vector *loaded = nullptr; std::string preset_name; - std::string alias_name; if (boost::starts_with(section.first, "print:")) { presets = &this->prints; loaded = &loaded_prints; @@ -1141,12 +1145,6 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla presets = &this->filaments; loaded = &loaded_filaments; preset_name = section.first.substr(9); - - for (const auto& item : section.second) - if (boost::starts_with(item.first, "alias")) { - alias_name = item.second.data(); - break; - } } else if (boost::starts_with(section.first, "sla_print:")) { presets = &this->sla_prints; loaded = &loaded_sla_prints; @@ -1155,9 +1153,6 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla presets = &this->sla_materials; loaded = &loaded_sla_materials; preset_name = section.first.substr(13); - - int end_pos = preset_name.find_first_of("0."); - alias_name = preset_name.substr(0, end_pos-1); } else if (boost::starts_with(section.first, "printer:")) { presets = &this->printers; loaded = &loaded_printers; @@ -1213,19 +1208,32 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla // Load the print, filament or printer preset. const DynamicPrintConfig *default_config = nullptr; DynamicPrintConfig config; + std::string alias_name; + std::vector renamed_from; + auto parse_config_section = [§ion, &alias_name, &renamed_from, &path](DynamicPrintConfig &config) { + for (auto &kvp : section.second) { + if (kvp.first == "alias") + alias_name = kvp.second.data(); + else if (kvp.first == "renamed_from") { + if (! unescape_strings_cstyle(kvp.second.data(), renamed_from)) { + BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The preset \"" << + section.first << "\" contains invalid \"renamed_from\" key, which is being ignored."; + } + } + config.set_deserialize(kvp.first, kvp.second.data()); + } + }; if (presets == &this->printers) { // Select the default config based on the printer_technology field extracted from kvp. DynamicPrintConfig config_src; - for (auto &kvp : section.second) - config_src.set_deserialize(kvp.first, kvp.second.data()); + parse_config_section(config_src); default_config = &presets->default_preset_for(config_src).config; config = *default_config; config.apply(config_src); } else { default_config = &presets->default_preset().config; config = *default_config; - for (auto &kvp : section.second) - config.set_deserialize(kvp.first, kvp.second.data()); + parse_config_section(config); } Preset::normalize(config); // Report configuration fields, which are misplaced into a wrong group. @@ -1304,12 +1312,22 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla loaded.vendor = vendor_profile; } - // next step of an preset name aliasing - int end_pos = preset_name.find_first_of("@"); - if (end_pos != std::string::npos) - alias_name = preset_name.substr(0, end_pos - 1); - - loaded.alias = alias_name.empty() ? preset_name : alias_name; + // Derive the profile logical name aka alias from the preset name if the alias was not stated explicitely. + if (alias_name.empty()) { + int end_pos = preset_name.find_first_of("@"); + if (end_pos != std::string::npos) { + alias_name = preset_name.substr(0, end_pos); + if (renamed_from.empty()) + // Add the preset name with the '@' character removed into the "renamed_from" list. + renamed_from.emplace_back(alias_name + preset_name.substr(end_pos + 1)); + boost::trim_right(alias_name); + } + } + if (alias_name.empty()) + loaded.alias = preset_name; + else + loaded.alias = std::move(alias_name); + loaded.renamed_from = std::move(renamed_from); ++ presets_loaded; }