diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index f18a1881e..6b07d761d 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -610,8 +610,6 @@ sub load_configbundle { # Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset. # Also update the platter with the new presets. -# This method is used to update the configuration from mainpulations in the 3D scene (for example moving the wipe tower), -# and to load the configuration from the config wizard. sub load_config { my ($self, $config) = @_; $_->load_config($config) foreach values %{$self->{options_tabs}}; @@ -636,31 +634,22 @@ sub config_wizard { } # Open the wizard. if (my $result = Slic3r::GUI::ConfigWizard->new($self, \@profiles, $fresh_start)->run) { - if ($result->{reset_user_profile}) { - eval { wxTheApp->{preset_bundle}->reset(1) }; - } - if (defined $result->{config}) { - # Wizard returned a config. Add the config to each of the preset types. - # Select and load the "-- default --" preset, start with the printer tab as it may revert - # the print and filament profile to the first visible one, which may have some - # printer compatibility configuration set, which we don't want to inherit. - foreach my $tab (qw(printer print filament)) { - $self->{options_tabs}->$tab->select_preset(undef, 1); + eval { + if ($result->{reset_user_profile}) { + wxTheApp->{preset_bundle}->reset(1); } - # Load the config over the previously selected defaults. - $self->load_config($result->{config}); - for my $tab (values %{$self->{options_tabs}}) { - # Save the settings under a new name, select the name. - $tab->save_preset('My Settings'); - } - } else { - # Wizard returned a name of a preset bundle bundled with the installation. Unpack it. - eval { wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $result->{preset_name} . '.ini'); }; - Slic3r::GUI::catch_error($self) and return; - # Load the currently selected preset into the GUI, update the preset selection box. - foreach my $tab (values %{$self->{options_tabs}}) { - $tab->load_current_preset; + if (defined $result->{config}) { + # Load and save the settings into print, filament and printer presets. + wxTheApp->{preset_bundle}->load_config('My Settings', $result->{config}); + } else { + # Wizard returned a name of a preset bundle bundled with the installation. Unpack it. + wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $result->{preset_name} . '.ini'); } + }; + Slic3r::GUI::catch_error($self) and return; + # Load the currently selected preset into the GUI, update the preset selection box. + foreach my $tab (values %{$self->{options_tabs}}) { + $tab->load_current_preset; } } } diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 49c999737..6af5982a3 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -350,11 +350,8 @@ void PresetCollection::save_current_preset(const std::string &new_name) } else { // Creating a new preset. Preset &preset = *m_presets.insert(it, m_edited_preset); - std::string file_name = new_name; - if (! boost::iends_with(file_name, ".ini")) - file_name += ".ini"; preset.name = new_name; - preset.file = (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); + preset.file = this->path_from_name(new_name); } // 2) Activate the saved preset. this->select_preset_by_name(new_name, true); @@ -591,4 +588,11 @@ std::string PresetCollection::name() const } } +// Generate a file path from a profile name. Add the ".ini" suffix if it is missing. +std::string PresetCollection::path_from_name(const std::string &new_name) const +{ + std::string file_name = boost::iends_with(new_name, ".ini") ? new_name : (new_name + ".ini"); + return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); +} + } // namespace Slic3r diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index b37982017..1f6a90595 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -211,6 +211,9 @@ public: // With force, the changes are reverted if the new index is the same as the old index. bool select_preset_by_name(const std::string &name, bool force); + // Generate a file path from a profile name. Add the ".ini" suffix if it is missing. + std::string path_from_name(const std::string &new_name) const; + private: PresetCollection(); PresetCollection(const PresetCollection &other); diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 645477541..decc5d00b 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -133,6 +133,7 @@ void PresetBundle::load_presets() errors_cummulative += err.what(); } this->update_multi_material_filament_presets(); + this->update_compatible_with_printer(false); if (! errors_cummulative.empty()) throw std::runtime_error(errors_cummulative); } @@ -163,8 +164,10 @@ void PresetBundle::load_selections(const AppConfig &config) this->set_filament_preset(i, remove_ini_suffix(config.get("presets", name))); } // Update visibility of presets based on their compatibility with the active printer. - // This will switch the print or filament presets to compatible if the active presets are incompatible. - this->update_compatible_with_printer(false); + // Always try to select a compatible print and filament preset to the current printer preset, + // as the application may have been closed with an active "external" preset, which does not + // exist. + this->update_compatible_with_printer(true); } // Export selections (current print, current filaments, current printer) into config.ini @@ -279,7 +282,7 @@ void PresetBundle::load_config_file(const std::string &path) config.apply(FullPrintConfig::defaults()); config.load_from_gcode(path); Preset::normalize(config); - load_config_file_config(path, std::move(config)); + load_config_file_config(path, true, std::move(config)); return; } @@ -308,7 +311,7 @@ void PresetBundle::load_config_file(const std::string &path) config.apply(FullPrintConfig::defaults()); config.load(tree); Preset::normalize(config); - load_config_file_config(path, std::move(config)); + load_config_file_config(path, true, std::move(config)); break; } case CONFIG_FILE_TYPE_CONFIG_BUNDLE: @@ -318,7 +321,7 @@ void PresetBundle::load_config_file(const std::string &path) } // Load a config file from a boost property_tree. This is a private method called from load_config_file. -void PresetBundle::load_config_file_config(const std::string &path, DynamicPrintConfig &&config) +void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config) { // The "compatible_printers" field should not have been exported into a config.ini or a G-code anyway, // but some of the alpha versions of Slic3r did. @@ -333,13 +336,17 @@ void PresetBundle::load_config_file_config(const std::string &path, DynamicPrint // 1) Create a name from the file name. // Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles. - std::string name = boost::filesystem::path(path).filename().string(); + std::string name = is_external ? boost::filesystem::path(name_or_path).filename().string() : name_or_path; // 2) If the loading succeeded, split and load the config into print / filament / printer settings. // First load the print and printer presets. for (size_t i_group = 0; i_group < 2; ++ i_group) { PresetCollection &presets = (i_group == 0) ? this->prints : this->printers; - presets.load_preset(path, name, config).is_external = true; + Preset &preset = presets.load_preset(is_external ? name_or_path : presets.path_from_name(name), name, config); + if (is_external) + preset.is_external = true; + else + preset.save(); } // 3) Now load the filaments. If there are multiple filament presets, split them and load them. @@ -347,7 +354,12 @@ void PresetBundle::load_config_file_config(const std::string &path, DynamicPrint auto *filament_diameter = dynamic_cast(config.option("filament_diameter")); size_t num_extruders = std::min(nozzle_diameter->values.size(), filament_diameter->values.size()); if (num_extruders <= 1) { - this->filaments.load_preset(path, name, config).is_external = true; + Preset &preset = this->filaments.load_preset( + is_external ? name_or_path : this->filaments.path_from_name(name), name, config); + if (is_external) + preset.is_external = true; + else + preset.save(); this->filament_presets.clear(); this->filament_presets.emplace_back(name); } else { @@ -374,11 +386,20 @@ void PresetBundle::load_config_file_config(const std::string &path, DynamicPrint suffix[0] = 0; else sprintf(suffix, " (%d)", i); + std::string new_name = name + suffix; // Load all filament presets, but only select the first one in the preset dialog. - this->filaments.load_preset(path, name + suffix, std::move(configs[i]), i == 0).is_external = true; - this->filament_presets.emplace_back(name + suffix); + Preset &preset = this->filaments.load_preset( + is_external ? name_or_path : this->filaments.path_from_name(new_name), + new_name, std::move(configs[i]), i == 0); + if (is_external) + preset.is_external = true; + else + preset.save(); + this->filament_presets.emplace_back(new_name); } } + + this->update_compatible_with_printer(false); } // Load the active configuration of a config bundle from a boost property_tree. This is a private method called from load_config_file. @@ -437,6 +458,8 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const this->update_multi_material_filament_presets(); for (size_t i = 1; i < std::min(tmp_bundle.filament_presets.size(), this->filament_presets.size()); ++ i) this->filament_presets[i] = load_one(this->filaments, tmp_bundle.filaments, tmp_bundle.filament_presets[i], false); + + this->update_compatible_with_printer(false); } // Load a config bundle file, into presets and store the loaded presets into separate files @@ -537,6 +560,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla this->update_multi_material_filament_presets(); for (size_t i = 0; i < std::min(this->filament_presets.size(), active_filaments.size()); ++ i) this->filament_presets[i] = filaments.find_preset(active_filaments[i], true)->name; + + this->update_compatible_with_printer(false); return presets_loaded; } diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp index 308785fda..df04efd73 100644 --- a/xs/src/slic3r/GUI/PresetBundle.hpp +++ b/xs/src/slic3r/GUI/PresetBundle.hpp @@ -44,6 +44,11 @@ public: DynamicPrintConfig full_config() const; + // Load user configuration and store it into the user profiles. + // This method is called by the configuration wizard. + void load_config(const std::string &name, DynamicPrintConfig config) + { this->load_config_file_config(name, false, std::move(config)); } + // Load an external config file containing the print, filament and printer presets. // Instead of a config file, a G-code may be loaded containing the full set of parameters. // In the future the configuration will likely be read from an AMF file as well. @@ -89,7 +94,10 @@ public: void update_compatible_with_printer(bool select_other_if_incompatible); private: - void load_config_file_config(const std::string &path, DynamicPrintConfig &&config); + // Load print, filament & printer presets from a config. If it is an external config, then the name is extracted from the external path. + // and the external config is just referenced, not stored into user profile directory. + // If it is not an external config, then the config will be stored into the user profile directory. + void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config); void load_config_file_config_bundle(const std::string &path, const boost::property_tree::ptree &tree); bool load_compatible_bitmaps(); diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index ed5db01e9..0e6b1504b 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -119,6 +119,14 @@ PresetCollection::arrayref() Slic3r::data_dir().c_str(), e.what()); } %}; + void load_config(const char *name, DynamicPrintConfig *config) + %code%{ + try { + THIS->load_config(name, *config); + } catch (std::exception& e) { + croak("Loading a configuration %s failed:\n%s\n", name, e.what()); + } + %}; void load_config_file(const char *path) %code%{ try {