diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 4d523bc0b7..ce4e9c0995 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -1516,23 +1516,19 @@ void ConfigWizard::priv::update_materials(Technology technology) for (const auto &pair : bundles) { for (const auto &filament : pair.second.preset_bundle->filaments) { // Check if filament is already added - if (filaments.containts(&filament)) { continue; } - + if (filaments.containts(&filament)) + continue; // Iterate printers in all bundles - for (const auto &pair : bundles) { - for (const auto &printer : pair.second.preset_bundle->printers) { + // For now, we only allow the profiles to be compatible with another profiles inside the same bundle. +// for (const auto &pair : bundles) + for (const auto &printer : pair.second.preset_bundle->printers) // Filter out inapplicable printers - if (!printer.is_visible || printer.printer_technology() != ptFFF) { - continue; - } - - if (filament.is_compatible_with_printer(printer)) { + if (printer.is_visible && printer.printer_technology() == ptFFF && + is_compatible_with_printer(PresetWithVendorProfile(filament, nullptr), PresetWithVendorProfile(printer, nullptr))) { filaments.push(&filament); if (!filament.alias.empty()) aliases_fff[filament.alias].insert(filament.name); } - } - } } } } @@ -1545,23 +1541,19 @@ void ConfigWizard::priv::update_materials(Technology technology) for (const auto &pair : bundles) { for (const auto &material : pair.second.preset_bundle->sla_materials) { // Check if material is already added - if (sla_materials.containts(&material)) { continue; } - + if (sla_materials.containts(&material)) + continue; // Iterate printers in all bundles - for (const auto &pair : bundles) { - for (const auto &printer : pair.second.preset_bundle->printers) { + // For now, we only allow the profiles to be compatible with another profiles inside the same bundle. +// for (const auto &pair : bundles) + for (const auto &printer : pair.second.preset_bundle->printers) // Filter out inapplicable printers - if (!printer.is_visible || printer.printer_technology() != ptSLA) { - continue; - } - - if (material.is_compatible_with_printer(printer)) { + if (printer.is_visible && printer.printer_technology() == ptSLA && + is_compatible_with_printer(PresetWithVendorProfile(material, nullptr), PresetWithVendorProfile(printer, nullptr))) { sla_materials.push(&material); if (!material.alias.empty()) aliases_sla[material.alias].insert(material.name); } - } - } } } } diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index bb1e5478d0..1c848b60fa 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -303,60 +303,58 @@ std::string Preset::label() const return this->name + (this->is_dirty ? g_suffix_modified : ""); } -bool Preset::is_compatible_with_print(const Preset &active_print) const +bool is_compatible_with_print(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print) { - auto &condition = this->compatible_prints_condition(); - auto *compatible_prints = dynamic_cast(this->config.option("compatible_prints")); + if (preset.vendor != nullptr && preset.vendor != active_print.vendor) + // The current profile has a vendor assigned and it is different from the active print's vendor. + return false; + auto &condition = preset.preset.compatible_prints_condition(); + auto *compatible_prints = dynamic_cast(preset.preset.config.option("compatible_prints")); bool has_compatible_prints = compatible_prints != nullptr && ! compatible_prints->values.empty(); if (! has_compatible_prints && ! condition.empty()) { try { - return PlaceholderParser::evaluate_boolean_expression(condition, active_print.config); + return PlaceholderParser::evaluate_boolean_expression(condition, active_print.preset.config); } catch (const std::runtime_error &err) { //FIXME in case of an error, return "compatible with everything". - printf("Preset::is_compatible_with_print - parsing error of compatible_prints_condition %s:\n%s\n", active_print.name.c_str(), err.what()); + printf("Preset::is_compatible_with_print - parsing error of compatible_prints_condition %s:\n%s\n", active_print.preset.name.c_str(), err.what()); return true; } } - return this->is_default || active_print.name.empty() || ! has_compatible_prints || - std::find(compatible_prints->values.begin(), compatible_prints->values.end(), active_print.name) != + return preset.preset.is_default || active_print.preset.name.empty() || ! has_compatible_prints || + std::find(compatible_prints->values.begin(), compatible_prints->values.end(), active_print.preset.name) != compatible_prints->values.end(); } -bool Preset::is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const +bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer, const DynamicPrintConfig *extra_config) { - auto &condition = this->compatible_printers_condition(); - auto *compatible_printers = dynamic_cast(this->config.option("compatible_printers")); + if (preset.vendor != nullptr && preset.vendor != active_printer.vendor) + // The current profile has a vendor assigned and it is different from the active print's vendor. + return false; + auto &condition = preset.preset.compatible_printers_condition(); + auto *compatible_printers = dynamic_cast(preset.preset.config.option("compatible_printers")); bool has_compatible_printers = compatible_printers != nullptr && ! compatible_printers->values.empty(); if (! has_compatible_printers && ! condition.empty()) { try { - return PlaceholderParser::evaluate_boolean_expression(condition, active_printer.config, extra_config); + return PlaceholderParser::evaluate_boolean_expression(condition, active_printer.preset.config, extra_config); } catch (const std::runtime_error &err) { //FIXME in case of an error, return "compatible with everything". - printf("Preset::is_compatible_with_printer - parsing error of compatible_printers_condition %s:\n%s\n", active_printer.name.c_str(), err.what()); + printf("Preset::is_compatible_with_printer - parsing error of compatible_printers_condition %s:\n%s\n", active_printer.preset.name.c_str(), err.what()); return true; } } - return this->is_default || active_printer.name.empty() || ! has_compatible_printers || - std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer.name) != + return preset.preset.is_default || active_printer.preset.name.empty() || ! has_compatible_printers || + std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer.preset.name) != compatible_printers->values.end(); } -bool Preset::is_compatible_with_printer(const Preset &active_printer) const +bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer) { DynamicPrintConfig config; - config.set_key_value("printer_preset", new ConfigOptionString(active_printer.name)); - const ConfigOption *opt = active_printer.config.option("nozzle_diameter"); + config.set_key_value("printer_preset", new ConfigOptionString(active_printer.preset.name)); + const ConfigOption *opt = active_printer.preset.config.option("nozzle_diameter"); if (opt) config.set_key_value("num_extruders", new ConfigOptionInt((int)static_cast(opt)->values.size())); - return this->is_compatible_with_printer(active_printer, &config); -} - -bool Preset::update_compatible(const Preset &active_printer, const DynamicPrintConfig *extra_config, const Preset *active_print) -{ - this->is_compatible = is_compatible_with_printer(active_printer, extra_config); - if (active_print != nullptr) - this->is_compatible &= is_compatible_with_print(*active_print); - return this->is_compatible; + return is_compatible_with_printer(preset, active_printer, &config); } void Preset::set_visible_from_appconfig(const AppConfig &app_config) @@ -905,6 +903,21 @@ const Preset* PresetCollection::get_preset_parent(const Preset& child) const return (preset == nullptr/* || preset->is_default */|| preset->is_external) ? nullptr : preset; } +// Return vendor of the first parent profile, for which the vendor is defined, or null if such profile does not exist. +PresetWithVendorProfile PresetCollection::get_preset_with_vendor_profile(const Preset &preset) const +{ + const Preset *p = &preset; + const VendorProfile *v = nullptr; + do { + if (p->vendor != nullptr) { + v = p->vendor; + break; + } + p = this->get_preset_parent(*p); + } while (p != nullptr); + return PresetWithVendorProfile(preset, v); +} + const std::string& PresetCollection::get_preset_name_by_alias(const std::string& alias) const { for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) { @@ -956,19 +969,22 @@ void PresetCollection::set_default_suppressed(bool default_suppressed) } } -size_t PresetCollection::update_compatible_internal(const Preset &active_printer, const Preset *active_print, bool unselect_if_incompatible) +size_t PresetCollection::update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool unselect_if_incompatible) { DynamicPrintConfig config; - config.set_key_value("printer_preset", new ConfigOptionString(active_printer.name)); - const ConfigOption *opt = active_printer.config.option("nozzle_diameter"); + config.set_key_value("printer_preset", new ConfigOptionString(active_printer.preset.name)); + const ConfigOption *opt = active_printer.preset.config.option("nozzle_diameter"); if (opt) config.set_key_value("num_extruders", new ConfigOptionInt((int)static_cast(opt)->values.size())); for (size_t idx_preset = m_num_default_presets; idx_preset < m_presets.size(); ++ idx_preset) { bool selected = idx_preset == m_idx_selected; Preset &preset_selected = m_presets[idx_preset]; Preset &preset_edited = selected ? m_edited_preset : preset_selected; - if (! preset_edited.update_compatible(active_printer, &config, active_print) && - selected && unselect_if_incompatible) + const PresetWithVendorProfile this_preset_with_vendor_profile = this->get_preset_with_vendor_profile(preset_edited); + preset_edited.is_compatible = is_compatible_with_printer(this_preset_with_vendor_profile, active_printer, &config); + if (active_print != nullptr) + preset_edited.is_compatible &= is_compatible_with_print(this_preset_with_vendor_profile, *active_print); + if (! preset_edited.is_compatible && selected && unselect_if_incompatible) m_idx_selected = -1; if (selected) preset_selected.is_compatible = preset_edited.is_compatible; diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index bafce89c6b..d381a6637f 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -91,6 +91,17 @@ public: bool operator==(const VendorProfile &rhs) const { return this->id == rhs.id; } }; +class Preset; + +// Helper to hold a profile with its vendor definition, where the vendor definition may have been extracted from a parent system preset. +// The parent preset is only accessible through PresetCollection, therefore to allow definition of the various is_compatible_with methods +// outside of the PresetCollection, this composite is returned by PresetCollection::get_preset_with_vendor_profile() when needed. +struct PresetWithVendorProfile { + PresetWithVendorProfile(const Preset &preset, const VendorProfile *vendor) : preset(preset), vendor(vendor) {} + const Preset &preset; + const VendorProfile *vendor; +}; + // 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. @@ -161,10 +172,6 @@ public: void set_dirty(bool dirty = true) { this->is_dirty = dirty; } void reset_dirty() { this->is_dirty = false; } - bool is_compatible_with_print(const Preset &active_print) const; - bool is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const; - bool is_compatible_with_printer(const Preset &active_printer) const; - // Returns the name of the preset, from which this preset inherits. static std::string& inherits(DynamicPrintConfig &cfg) { return cfg.option("inherits", true)->value; } std::string& inherits() { return Preset::inherits(this->config); } @@ -198,9 +205,6 @@ public: // This call returns a reference, it may add a new entry into the DynamicPrintConfig. PrinterTechnology& printer_technology_ref() { return this->config.option>("printer_technology", true)->value; } - // Mark this preset as compatible if it is compatible with active_printer. - bool update_compatible(const Preset &active_printer, const DynamicPrintConfig *extra_config, const Preset *active_print = nullptr); - // Set is_visible according to application config void set_visible_from_appconfig(const AppConfig &app_config); @@ -233,6 +237,10 @@ protected: static std::string remove_suffix_modified(const std::string &name); }; +bool is_compatible_with_print (const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print); +bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer, const DynamicPrintConfig *extra_config); +bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer); + // Collections of presets of the same type (one of the Print, Filament or Printer type). class PresetCollection { @@ -329,6 +337,10 @@ public: Preset& get_edited_preset() { return m_edited_preset; } const Preset& get_edited_preset() const { return m_edited_preset; } + // Return vendor of the first parent profile, for which the vendor is defined, or null if such profile does not exist. + PresetWithVendorProfile get_preset_with_vendor_profile(const Preset &preset) const; + PresetWithVendorProfile get_edited_preset_with_vendor_profile() const { return this->get_preset_with_vendor_profile(this->get_edited_preset()); } + const std::string& get_preset_name_by_alias(const std::string& alias) const; // used to update preset_choice from Tab @@ -388,13 +400,13 @@ public: // For Print / Filament presets, disable those, which are not compatible with the printer. template - void update_compatible(const Preset &active_printer, const Preset *active_print, bool select_other_if_incompatible, PreferedCondition prefered_condition) + void update_compatible(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool select_other_if_incompatible, PreferedCondition prefered_condition) { if (this->update_compatible_internal(active_printer, active_print, select_other_if_incompatible) == (size_t)-1) // Find some other compatible preset, or the "-- default --" preset. this->select_preset(this->first_compatible_idx(prefered_condition)); } - void update_compatible(const Preset &active_printer, const Preset *active_print, bool select_other_if_incompatible) + void update_compatible(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool select_other_if_incompatible) { this->update_compatible(active_printer, active_print, select_other_if_incompatible, [](const std::string&){return true;}); } size_t num_visible() const { return std::count_if(m_presets.begin(), m_presets.end(), [](const Preset &preset){return preset.is_visible;}); } @@ -477,7 +489,7 @@ private: std::deque::const_iterator find_preset_internal(const std::string &name) const { return const_cast(this)->find_preset_internal(name); } - size_t update_compatible_internal(const Preset &active_printer, const Preset *active_print, bool unselect_if_incompatible); + size_t update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool unselect_if_incompatible); static std::vector dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type = false); diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 4a19a784e8..3a33fbb49f 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -346,55 +346,47 @@ const std::string& PresetBundle::get_preset_name_by_alias( const Preset::Type& p void PresetBundle::load_installed_filaments(AppConfig &config) { if (! config.has_section(AppConfig::SECTION_FILAMENTS)) { - std::unordered_set comp_filaments; - - for (const Preset &printer : printers) { - if (! printer.is_visible || printer.printer_technology() != ptFFF) { - continue; - } - - for (const Preset &filament : filaments) { - if (filament.is_compatible_with_printer(printer)) { - comp_filaments.insert(&filament); - } - } - } - - for (const auto &filament: comp_filaments) { + // Compatibility with the PrusaSlicer 2.1.1 and older, where the filament profiles were not installable yet. + // Find all filament profiles, which are compatible with installed printers, and act as if these filament profiles + // were installed. + std::unordered_set compatible_filaments; + for (const Preset &printer : printers) + if (printer.is_visible && printer.printer_technology() == ptFFF) { + const PresetWithVendorProfile printer_with_vendor_profile = printers.get_preset_with_vendor_profile(printer); + for (const Preset &filament : filaments) + if (is_compatible_with_printer(filaments.get_preset_with_vendor_profile(filament), printer_with_vendor_profile)) + compatible_filaments.insert(&filament); + } + // and mark these filaments as installed, therefore this code will not be executed at the next start of the application. + for (const auto &filament: compatible_filaments) config.set(AppConfig::SECTION_FILAMENTS, filament->name, "1"); - } } - for (auto &preset : filaments) { + for (auto &preset : filaments) preset.set_visible_from_appconfig(config); - } } void PresetBundle::load_installed_sla_materials(AppConfig &config) { if (! config.has_section(AppConfig::SECTION_MATERIALS)) { std::unordered_set comp_sla_materials; - - for (const Preset &printer : printers) { - if (! printer.is_visible || printer.printer_technology() != ptSLA) { - continue; - } - - for (const Preset &material : sla_materials) { - if (material.is_compatible_with_printer(printer)) { - comp_sla_materials.insert(&material); - } - } - } - - for (const auto &material: comp_sla_materials) { + // Compatibility with the PrusaSlicer 2.1.1 and older, where the SLA material profiles were not installable yet. + // Find all SLA material profiles, which are compatible with installed printers, and act as if these SLA material profiles + // were installed. + for (const Preset &printer : printers) + if (printer.is_visible && printer.printer_technology() == ptSLA) { + const PresetWithVendorProfile printer_with_vendor_profile = printers.get_preset_with_vendor_profile(printer); + for (const Preset &material : sla_materials) + if (is_compatible_with_printer(sla_materials.get_preset_with_vendor_profile(material), printer_with_vendor_profile)) + comp_sla_materials.insert(&material); + } + // and mark these SLA materials as installed, therefore this code will not be executed at the next start of the application. + for (const auto &material: comp_sla_materials) config.set(AppConfig::SECTION_MATERIALS, material->name, "1"); - } } - for (auto &preset : sla_materials) { + for (auto &preset : sla_materials) preset.set_visible_from_appconfig(config); - } } // Load selections (current print, current filaments, current printer) from config.ini @@ -1385,23 +1377,24 @@ void PresetBundle::update_multi_material_filament_presets() void PresetBundle::update_compatible(bool select_other_if_incompatible) { - const Preset &printer_preset = this->printers.get_edited_preset(); + const Preset &printer_preset = this->printers.get_edited_preset(); + const PresetWithVendorProfile printer_preset_with_vendor_profile = this->printers.get_preset_with_vendor_profile(printer_preset); switch (printer_preset.printer_technology()) { case ptFFF: { assert(printer_preset.config.has("default_print_profile")); assert(printer_preset.config.has("default_filament_profile")); - const Preset &print_preset = this->prints.get_edited_preset(); + const PresetWithVendorProfile print_preset_with_vendor_profile = this->prints.get_edited_preset_with_vendor_profile(); const std::string &prefered_print_profile = printer_preset.config.opt_string("default_print_profile"); const std::vector &prefered_filament_profiles = printer_preset.config.option("default_filament_profile")->values; prefered_print_profile.empty() ? - this->prints.update_compatible(printer_preset, nullptr, select_other_if_incompatible) : - this->prints.update_compatible(printer_preset, nullptr, select_other_if_incompatible, + this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_if_incompatible) : + this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_if_incompatible, [&prefered_print_profile](const std::string& profile_name) { return profile_name == prefered_print_profile; }); prefered_filament_profiles.empty() ? - this->filaments.update_compatible(printer_preset, &print_preset, select_other_if_incompatible) : - this->filaments.update_compatible(printer_preset, &print_preset, select_other_if_incompatible, + this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_if_incompatible) : + this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_if_incompatible, [&prefered_filament_profiles](const std::string& profile_name) { return std::find(prefered_filament_profiles.begin(), prefered_filament_profiles.end(), profile_name) != prefered_filament_profiles.end(); }); if (select_other_if_incompatible) { @@ -1433,16 +1426,16 @@ void PresetBundle::update_compatible(bool select_other_if_incompatible) { assert(printer_preset.config.has("default_sla_print_profile")); assert(printer_preset.config.has("default_sla_material_profile")); - const Preset &sla_print_preset = this->sla_prints.get_edited_preset(); - const std::string &prefered_sla_print_profile = printer_preset.config.opt_string("default_sla_print_profile"); + const PresetWithVendorProfile sla_print_preset_with_vendor_profile = this->sla_prints.get_edited_preset_with_vendor_profile(); + const std::string &prefered_sla_print_profile = printer_preset.config.opt_string("default_sla_print_profile"); (prefered_sla_print_profile.empty()) ? - this->sla_prints.update_compatible(printer_preset, nullptr, select_other_if_incompatible) : - this->sla_prints.update_compatible(printer_preset, nullptr, select_other_if_incompatible, + this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_if_incompatible) : + this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_if_incompatible, [&prefered_sla_print_profile](const std::string& profile_name){ return profile_name == prefered_sla_print_profile; }); const std::string &prefered_sla_material_profile = printer_preset.config.opt_string("default_sla_material_profile"); prefered_sla_material_profile.empty() ? - this->sla_materials.update_compatible(printer_preset, &sla_print_preset, select_other_if_incompatible) : - this->sla_materials.update_compatible(printer_preset, &sla_print_preset, select_other_if_incompatible, + this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_if_incompatible) : + this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_if_incompatible, [&prefered_sla_material_profile](const std::string& profile_name){ return profile_name == prefered_sla_material_profile; }); break; } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index ee1750c376..fc085cb327 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2755,7 +2755,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current) PrinterTechnology printer_technology = m_preset_bundle->printers.get_edited_preset().printer_technology(); PresetCollection &dependent = (printer_technology == ptFFF) ? m_preset_bundle->filaments : m_preset_bundle->sla_materials; bool old_preset_dirty = dependent.current_is_dirty(); - bool new_preset_compatible = dependent.get_edited_preset().is_compatible_with_print(*m_presets->find_preset(preset_name, true)); + bool new_preset_compatible = is_compatible_with_print(dependent.get_edited_preset_with_vendor_profile(), m_presets->get_preset_with_vendor_profile(*m_presets->find_preset(preset_name, true))); if (! canceled) canceled = old_preset_dirty && ! new_preset_compatible && ! may_discard_current_dirty_preset(&dependent, preset_name); if (! canceled) { @@ -2773,6 +2773,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current) // With the introduction of the SLA printer types, we need to support switching between // the FFF and SLA printers. const Preset &new_printer_preset = *m_presets->find_preset(preset_name, true); + const PresetWithVendorProfile new_printer_preset_with_vendor_profile = m_presets->get_preset_with_vendor_profile(new_printer_preset); PrinterTechnology old_printer_technology = m_presets->get_edited_preset().printer_technology(); PrinterTechnology new_printer_technology = new_printer_preset.printer_technology(); if (new_printer_technology == ptSLA && old_printer_technology == ptFFF && !may_switch_to_SLA_preset()) @@ -2793,7 +2794,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current) }; for (PresetUpdate &pu : updates) { pu.old_preset_dirty = (old_printer_technology == pu.technology) && pu.presets->current_is_dirty(); - pu.new_preset_compatible = (new_printer_technology == pu.technology) && pu.presets->get_edited_preset().is_compatible_with_printer(new_printer_preset); + pu.new_preset_compatible = (new_printer_technology == pu.technology) && is_compatible_with_printer(pu.presets->get_edited_preset_with_vendor_profile(), new_printer_preset_with_vendor_profile); if (!canceled) canceled = pu.old_preset_dirty && !pu.new_preset_compatible && !may_discard_current_dirty_preset(pu.presets, preset_name); }