Introduced the system profiles.

The Config Wizard now just copies the Vendor's Config Bundle
into user_dir/vendor/ directory and Slic3r uses the configs
from the bundles found in user_dir/vendor directly.
This commit is contained in:
bubnikv 2018-03-09 16:37:33 +01:00
parent 4e58c9dab9
commit f55becd43c
15 changed files with 318 additions and 11138 deletions

View file

@ -185,7 +185,7 @@ void ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys
// This is only possible if other is of DynamicConfig type.
if (ignore_nonexistent)
continue;
throw UnknownOptionException();
throw UnknownOptionException(opt_key);
}
const ConfigOption *other_opt = other.option(opt_key);
if (other_opt != nullptr)
@ -232,7 +232,7 @@ bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, con
// Try to deserialize the option by its name.
const ConfigDef *def = this->def();
if (def == nullptr)
throw NoDefinitionException();
throw NoDefinitionException(opt_key);
const ConfigOptionDef *optdef = def->get(opt_key);
if (optdef == nullptr) {
// If we didn't find an option, look for any other option having this as an alias.
@ -248,7 +248,7 @@ bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, con
break;
}
if (optdef == nullptr)
throw UnknownOptionException();
throw UnknownOptionException(opt_key);
}
if (! optdef->shortcut.empty()) {
@ -278,7 +278,7 @@ double ConfigBase::get_abs_value(const t_config_option_key &opt_key) const
// Get option definition.
const ConfigDef *def = this->def();
if (def == nullptr)
throw NoDefinitionException();
throw NoDefinitionException(opt_key);
const ConfigOptionDef *opt_def = def->get(opt_key);
assert(opt_def != nullptr);
// Compute absolute value over the absolute value of the base option.
@ -468,7 +468,7 @@ ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool cre
// Try to create a new ConfigOption.
const ConfigDef *def = this->def();
if (def == nullptr)
throw NoDefinitionException();
throw NoDefinitionException(opt_key);
const ConfigOptionDef *optdef = def->get(opt_key);
if (optdef == nullptr)
// throw std::runtime_error(std::string("Invalid option name: ") + opt_key);

View file

@ -1232,17 +1232,22 @@ protected:
};
/// Specialization of std::exception to indicate that an unknown config option has been encountered.
class UnknownOptionException : public std::exception
{
class UnknownOptionException : public std::runtime_error {
public:
const char* what() const noexcept override { return "Unknown config option"; }
UnknownOptionException() :
std::runtime_error("Unknown option exception") {}
UnknownOptionException(const std::string &opt_key) :
std::runtime_error(std::string("Unknown option exception: ") + opt_key) {}
};
/// Indicate that the ConfigBase derived class does not provide config definition (the method def() returns null).
class NoDefinitionException : public std::exception
class NoDefinitionException : public std::runtime_error
{
public:
const char* what() const noexcept override { return "No config definition"; }
NoDefinitionException() :
std::runtime_error("No definition exception") {}
NoDefinitionException(const std::string &opt_key) :
std::runtime_error(std::string("No definition exception: ") + opt_key) {}
};
}

View file

@ -176,6 +176,18 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->default_value = new ConfigOptionFloat(0);
def = this->add("default_filament_profile", coStrings);
def->label = L("Default filament profile");
def->tooltip = L("Default filament profile associated with the current printer profile. "
"On selection of the current printer profile, this filament profile will be activated.");
def->default_value = new ConfigOptionStrings();
def = this->add("default_print_profile", coString);
def->label = L("Default print profile");
def->tooltip = L("Default print profile associated with the current printer profile. "
"On selection of the current printer profile, this print profile will be activated.");
def->default_value = new ConfigOptionString();
def = this->add("disable_fan_first_layers", coInts);
def->label = L("Disable fan for the first");
def->tooltip = L("You can set this to a positive value to disable fan at all "
@ -753,6 +765,13 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->default_value = new ConfigOptionFloat(80);
def = this->add("inherits", coString);
def->label = L("Inherits profile");
def->tooltip = L("Name of the profile, from which this profile inherits.");
def->full_width = true;
def->height = 50;
def->default_value = new ConfigOptionString("");
def = this->add("interface_shells", coBool);
def->label = L("Interface shells");
def->tooltip = L("Force the generation of solid shells between adjacent materials/volumes. "
@ -1017,6 +1036,11 @@ PrintConfigDef::PrintConfigDef()
def->height = 60;
def->default_value = new ConfigOptionStrings{ "" };
def = this->add("printer_model", coString);
def->label = L("Printer type");
def->tooltip = L("Type of the printer.");
def->default_value = new ConfigOptionString();
def = this->add("printer_notes", coString);
def->label = L("Printer notes");
def->tooltip = L("You can put your notes regarding the printer here.");
@ -1026,6 +1050,16 @@ PrintConfigDef::PrintConfigDef()
def->height = 130;
def->default_value = new ConfigOptionString("");
def = this->add("printer_vendor", coString);
def->label = L("Printer vendor");
def->tooltip = L("Name of the printer vendor.");
def->default_value = new ConfigOptionString();
def = this->add("printer_variant", coString);
def->label = L("Printer variant");
def->tooltip = L("Name of the printer variant. For example, the printer variants may be differentiated by a nozzle diameter.");
def->default_value = new ConfigOptionString();
def = this->add("print_settings_id", coString);
def->default_value = new ConfigOptionString("");

View file

@ -200,7 +200,7 @@ const std::vector<std::string>& Preset::print_options()
"top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects",
"elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
"wipe_tower_width", "wipe_tower_per_color_wipe",
"compatible_printers", "compatible_printers_condition"
"compatible_printers", "compatible_printers_condition", "inherits"
};
return s_opts;
}
@ -213,7 +213,7 @@ const std::vector<std::string>& Preset::filament_options()
"first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed",
"disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode",
"end_filament_gcode",
"compatible_printers", "compatible_printers_condition"
"compatible_printers", "compatible_printers_condition", "inherits"
};
return s_opts;
}
@ -226,7 +226,7 @@ const std::vector<std::string>& Preset::printer_options()
"bed_shape", "z_offset", "gcode_flavor", "use_relative_e_distances", "serial_port", "serial_speed",
"octoprint_host", "octoprint_apikey", "octoprint_cafile", "use_firmware_retraction", "use_volumetric_e", "variable_layer_height",
"single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode",
"between_objects_gcode", "printer_notes"
"between_objects_gcode", "printer_vendor", "printer_model", "printer_variant", "printer_notes", "default_print_profile", "default_filament_profile", "inherits",
};
s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end());
}
@ -269,7 +269,7 @@ void PresetCollection::reset(bool delete_files)
if (delete_files) {
// Erase the preset files.
for (Preset &preset : m_presets)
if (! preset.is_default && ! preset.is_external)
if (! preset.is_default && ! preset.is_external && ! preset.is_system)
boost::nowide::remove(preset.file.c_str());
}
// Don't use m_presets.resize() here as it requires a default constructor for Preset.
@ -284,7 +284,6 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri
{
boost::filesystem::path dir = boost::filesystem::canonical(boost::filesystem::path(dir_path) / subdir).make_preferred();
m_dir_path = dir.string();
m_presets.erase(m_presets.begin()+1, m_presets.end());
t_config_option_keys keys = this->default_preset().config.keys();
std::string errors_cummulative;
for (auto &dir_entry : boost::filesystem::directory_iterator(dir))
@ -292,6 +291,10 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri
std::string name = dir_entry.path().filename().string();
// Remove the .ini suffix.
name.erase(name.size() - 4);
if (this->find_preset(name, false)) {
errors_cummulative += "The user preset \"" + name + "\" cannot be loaded. A system preset of the same name has already been loaded.";
continue;
}
try {
Preset preset(m_type, name, false);
preset.file = dir_entry.path().string();
@ -364,7 +367,7 @@ void PresetCollection::delete_current_preset()
const Preset &selected = this->get_selected_preset();
if (selected.is_default)
return;
if (! selected.is_external) {
if (! selected.is_external && ! selected.is_system) {
// Erase the preset file.
boost::nowide::remove(selected.file.c_str());
}

View file

@ -23,6 +23,46 @@ enum ConfigFileType
extern ConfigFileType guess_config_file_type(const boost::property_tree::ptree &tree);
class VendorProfile
{
public:
std::string name;
std::string id;
std::string config_version;
std::string config_update_url;
struct PrinterVariant {
PrinterVariant() {}
PrinterVariant(const std::string &name) : name(name) {}
std::string name;
bool enabled = true;
};
struct PrinterModel {
PrinterModel() {}
PrinterModel(const std::string &name) : name(name) {}
std::string name;
bool enabled = true;
std::vector<PrinterVariant> variants;
PrinterVariant* variant(const std::string &name) {
for (auto &v : this->variants)
if (v.name == name)
return &v;
return nullptr;
}
const PrinterVariant* variant(const std::string &name) const { return const_cast<PrinterModel*>(this)->variant(name); }
bool operator< (const PrinterModel &rhs) const { return this->name < rhs.name; }
bool operator==(const PrinterModel &rhs) const { return this->name == rhs.name; }
};
std::set<PrinterModel> models;
size_t num_variants() const { size_t n = 0; for (auto &model : models) n += model.variants.size(); return n; }
bool operator< (const VendorProfile &rhs) const { return this->id < rhs.id; }
bool operator==(const VendorProfile &rhs) const { return this->id == rhs.id; }
};
class Preset
{
public:
@ -44,6 +84,8 @@ public:
// External preset points to a configuration, which has been loaded but not imported
// into the Slic3r default configuration location.
bool is_external = false;
// System preset is read-only.
bool is_system = false;
// Preset is visible, if it is compatible with the active Printer.
// Also the "default" preset is only visible, if it is the only preset in the list.
bool is_visible = true;
@ -55,9 +97,14 @@ public:
// Name of the preset, usually derived form the file name.
std::string name;
// File name of the preset. This could be a Print / Filament / Printer preset,
// or a Configuration file bundling the Print + Filament + Printer presets (in that case is_external will be true),
// or a Configuration file bundling the Print + Filament + Printer presets (in that case is_external and possibly is_system will be true),
// or it could be a G-code (again, is_external will be true).
std::string file;
// A user profile may inherit its settings either from a system profile, or from a user profile.
// A system profile shall never derive from any other profile, as the system profile hierarchy is being flattened during loading.
std::string inherits;
// If this is a system profile, then there should be a vendor data available to display at the UI.
const VendorProfile *vendor = nullptr;
// Has this profile been loaded?
bool loaded = false;

View file

@ -51,6 +51,14 @@ PresetBundle::PresetBundle() :
this->filaments.preset(0).config.optptr("compatible_printers_condition", true);
this->prints.preset(0).config.optptr("compatible_printers", true);
this->prints.preset(0).config.optptr("compatible_printers_condition", true);
// Create the "inherits" keys.
this->prints.preset(0).config.optptr("inherits", true);
this->filaments.preset(0).config.optptr("inherits", true);
this->printers.preset(0).config.optptr("inherits", true);
// Create the "printer_vendor", "printer_model" and "printer_variant" keys.
this->printers.preset(0).config.optptr("printer_vendor", true);
this->printers.preset(0).config.optptr("printer_model", true);
this->printers.preset(0).config.optptr("printer_variant", true);
this->prints .load_bitmap_default("cog.png");
this->filaments.load_bitmap_default("spool.png");
@ -84,7 +92,8 @@ void PresetBundle::setup_directories()
{
boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
std::initializer_list<boost::filesystem::path> paths = {
data_dir,
data_dir,
data_dir / "vendor",
#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
// Store the print/filament/printer presets into a "presets" directory.
data_dir / "presets",
@ -107,10 +116,12 @@ void PresetBundle::setup_directories()
}
}
void PresetBundle::load_presets()
void PresetBundle::load_presets(const AppConfig &config)
{
std::string errors_cummulative;
const std::string dir_path = data_dir()
// First load the vendor specific system presets.
std::string errors_cummulative = this->load_system_presets();
const std::string dir_user_presets = data_dir()
#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
// Store the print/filament/printer presets into a "presets" directory.
+ "/presets"
@ -119,17 +130,17 @@ void PresetBundle::load_presets()
#endif
;
try {
this->prints.load_presets(dir_path, "print");
this->prints.load_presets(dir_user_presets, "print");
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
}
try {
this->filaments.load_presets(dir_path, "filament");
this->filaments.load_presets(dir_user_presets, "filament");
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
}
try {
this->printers.load_presets(dir_path, "printer");
this->printers.load_presets(dir_user_presets, "printer");
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
}
@ -137,6 +148,31 @@ void PresetBundle::load_presets()
this->update_compatible_with_printer(false);
if (! errors_cummulative.empty())
throw std::runtime_error(errors_cummulative);
this->load_selections(config);
}
// Load system presets into this PresetBundle.
// For each vendor, there will be a single PresetBundle loaded.
std::string PresetBundle::load_system_presets()
{
// Here the vendor specific read only Config Bundles are stored.
boost::filesystem::path dir = (boost::filesystem::path(data_dir()) / "vendor").make_preferred();
std::string errors_cummulative;
for (auto &dir_entry : boost::filesystem::directory_iterator(dir))
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini")) {
std::string name = dir_entry.path().filename().string();
// Remove the .ini suffix.
name.erase(name.size() - 4);
try {
// Load the config bundle, flatten it.
this->load_configbundle(dir_entry.path().string(), LOAD_CFGBNDLE_SYSTEM);
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
errors_cummulative += "\n";
}
}
return errors_cummulative;
}
static inline std::string remove_ini_suffix(const std::string &name)
@ -147,6 +183,14 @@ static inline std::string remove_ini_suffix(const std::string &name)
return out;
}
// Set the "enabled" flag for printer vendors, printer models and printer variants
// based on the user configuration.
// If the "vendor" section is missing, enable all models and variants of the particular vendor.
void PresetBundle::load_installed_printers(const AppConfig &config)
{
// m_storage
}
// Load selections (current print, current filaments, current printer) from config.ini
// This is done just once on application start up.
void PresetBundle::load_selections(const AppConfig &config)
@ -594,11 +638,54 @@ static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree)
flatten_configbundle_hierarchy(tree, "printer");
}
static void load_vendor_profile(const boost::property_tree::ptree &tree, VendorProfile &vendor_profile)
{
const std::string printer_model_key = "printer_model:";
for (auto &section : tree)
if (section.first == "vendor") {
// Load the names of the active presets.
for (auto &kvp : section.second) {
if (kvp.first == "name")
vendor_profile.name = kvp.second.data();
else if (kvp.first == "id")
vendor_profile.id = kvp.second.data();
else if (kvp.first == "config_version")
vendor_profile.config_version = kvp.second.data();
else if (kvp.first == "config_update_url")
vendor_profile.config_update_url = kvp.second.data();
}
} else if (boost::starts_with(section.first, printer_model_key)) {
VendorProfile::PrinterModel model;
model.name = section.first.substr(printer_model_key.size());
section.second.get<std::string>("variants", "");
std::vector<std::string> variants;
if (Slic3r::unescape_strings_cstyle(section.second.get<std::string>("variants", ""), variants)) {
for (const std::string &variant_name : variants) {
if (model.variant(variant_name) == nullptr)
model.variants.emplace_back(VendorProfile::PrinterVariant(variant_name));
}
} else {
// Log error?
}
if (! model.name.empty() && ! model.variants.empty())
vendor_profile.models.insert(model);
}
}
// Load a config bundle file, into presets and store the loaded presets into separate files
// of the local configuration directory.
void PresetBundle::install_vendor_configbundle(const std::string &src_path0)
{
boost::filesystem::path src_path(src_path0);
boost::filesystem::copy_file(src_path, (boost::filesystem::path(data_dir()) / "vendor" / src_path.filename()).make_preferred(), boost::filesystem::copy_option::overwrite_if_exists);
}
// Load a config bundle file, into presets and store the loaded presets into separate files
// of the local configuration directory.
size_t PresetBundle::load_configbundle(const std::string &path, unsigned int flags)
{
if (flags & LOAD_CFGBNDLE_RESET_USER_PROFILE)
if (flags & (LOAD_CFGBNDLE_RESET_USER_PROFILE | LOAD_CFGBNDLE_SYSTEM))
// Reset this bundle, delete user profile files if LOAD_CFGBNDLE_SAVE.
this->reset(flags & LOAD_CFGBNDLE_SAVE);
// 1) Read the complete config file into a boost::property_tree.
@ -609,6 +696,17 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
// Flatten the config bundle by applying the inheritance rules. Internal profiles (with names starting with '*') are removed.
flatten_configbundle_hierarchy(tree);
const VendorProfile *vendor_profile = nullptr;
if (flags & LOAD_CFGBNDLE_SYSTEM) {
VendorProfile vp;
load_vendor_profile(tree, vp);
if (vp.name.empty())
throw std::runtime_error(std::string("Vendor Config Bundle is not valid: Missing vendor name key."));
if (vp.num_variants() == 0)
return 0;
vendor_profile = &(*this->vendors.insert(vp).first);
}
// 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
std::vector<std::string> loaded_prints;
std::vector<std::string> loaded_filaments;
@ -622,15 +720,15 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
std::vector<std::string> *loaded = nullptr;
std::string preset_name;
if (boost::starts_with(section.first, "print:")) {
presets = &prints;
presets = &this->prints;
loaded = &loaded_prints;
preset_name = section.first.substr(6);
} else if (boost::starts_with(section.first, "filament:")) {
presets = &filaments;
presets = &this->filaments;
loaded = &loaded_filaments;
preset_name = section.first.substr(9);
} else if (boost::starts_with(section.first, "printer:")) {
presets = &printers;
presets = &this->printers;
loaded = &loaded_printers;
preset_name = section.first.substr(8);
} else if (section.first == "presets") {
@ -664,6 +762,40 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
for (auto &kvp : section.second)
config.set_deserialize(kvp.first, kvp.second.data());
Preset::normalize(config);
if ((flags & LOAD_CFGBNDLE_SYSTEM) && presets == &printers) {
// Filter out printer presets, which are not mentioned in the vendor profile.
// These presets are considered not installed.
auto printer_model = config.opt_string("printer_model");
if (printer_model.empty()) {
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
section.first << "\" defines no printer model, it will be ignored.";
continue;
}
auto printer_variant = config.opt_string("printer_variant");
if (printer_variant.empty()) {
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
section.first << "\" defines no printer variant, it will be ignored.";
continue;
}
auto it_model = vendor_profile->models.find(VendorProfile::PrinterModel(printer_model));
if (it_model == vendor_profile->models.end()) {
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
section.first << "\" defines invalid printer model \"" << printer_model << "\", it will be ignored.";
continue;
}
auto it_variant = it_model->variant(printer_variant);
if (it_variant == nullptr) {
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
section.first << "\" defines invalid printer variant \"" << printer_variant << "\", it will be ignored.";
continue;
}
const Preset *preset_existing = presets->find_preset(section.first, false);
if (preset_existing != nullptr) {
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
section.first << "\" has already been loaded from another Confing Bundle.";
continue;
}
}
// Decide a full path to this .ini file.
auto file_name = boost::algorithm::iends_with(preset_name, ".ini") ? preset_name : preset_name + ".ini";
auto file_path = (boost::filesystem::path(data_dir())
@ -678,24 +810,29 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
Preset &loaded = presets->load_preset(file_path.string(), preset_name, std::move(config), false);
if (flags & LOAD_CFGBNDLE_SAVE)
loaded.save();
if (flags & LOAD_CFGBNDLE_SYSTEM) {
loaded.is_system = true;
loaded.vendor = vendor_profile;
}
++ presets_loaded;
}
}
// 3) Activate the presets.
if (! active_print.empty())
prints.select_preset_by_name(active_print, true);
if (! active_printer.empty())
printers.select_preset_by_name(active_printer, true);
// Activate the first filament preset.
if (! active_filaments.empty() && ! active_filaments.front().empty())
filaments.select_preset_by_name(active_filaments.front(), true);
if ((flags & LOAD_CFGBNDLE_SYSTEM) == 0) {
if (! active_print.empty())
prints.select_preset_by_name(active_print, true);
if (! active_printer.empty())
printers.select_preset_by_name(active_printer, true);
// Activate the first filament preset.
if (! active_filaments.empty() && ! active_filaments.front().empty())
filaments.select_preset_by_name(active_filaments.front(), true);
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);
}
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;
}

View file

@ -4,6 +4,8 @@
#include "AppConfig.hpp"
#include "Preset.hpp"
#include <set>
namespace Slic3r {
class PlaceholderParser;
@ -22,11 +24,10 @@ public:
void setup_directories();
// Load ini files of all types (print, filament, printer) from Slic3r::data_dir() / presets.
void load_presets();
// Load selections (current print, current filaments, current printer) from config.ini
// This is done just once on application start up.
void load_selections(const AppConfig &config);
void load_presets(const AppConfig &config);
// Export selections (current print, current filaments, current printer) into config.ini
void export_selections(AppConfig &config);
// Export selections (current print, current filaments, current printer) into a placeholder parser.
@ -39,6 +40,10 @@ public:
// extruders.size() should be the same as printers.get_edited_preset().config.nozzle_diameter.size()
std::vector<std::string> filament_presets;
// 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;
bool has_defauls_only() const
{ return prints.size() <= 1 && filaments.size() <= 1 && printers.size() <= 1; }
@ -69,11 +74,16 @@ public:
// Save the profiles, which have been loaded.
LOAD_CFGBNDLE_SAVE = 1,
// Delete all old config profiles before loading.
LOAD_CFGBNDLE_RESET_USER_PROFILE = 2
LOAD_CFGBNDLE_RESET_USER_PROFILE = 2,
// Load a system config bundle.
LOAD_CFGBNDLE_SYSTEM = 4,
};
// Load the config bundle, store it to the user profile directory by default.
size_t load_configbundle(const std::string &path, unsigned int flags = LOAD_CFGBNDLE_SAVE);
// Install the Vendor specific config bundle into user's directory.
void install_vendor_configbundle(const std::string &src_path);
// Export a config bundle file containing all the presets and the names of the active presets.
void export_configbundle(const std::string &path); // , const DynamicPrintConfig &settings);
@ -99,6 +109,17 @@ public:
void update_compatible_with_printer(bool select_other_if_incompatible);
private:
std::string load_system_presets();
// Set the "enabled" flag for printer vendors, printer models and printer variants
// based on the user configuration.
// If the "vendor" section is missing, enable all models and variants of the particular vendor.
void load_installed_printers(const AppConfig &config);
// Load selections (current print, current filaments, current printer) from config.ini
// This is done just once on application start up.
void load_selections(const AppConfig &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.

View file

@ -1352,7 +1352,7 @@ void Tab::load_current_preset()
auto preset = m_presets->get_edited_preset();
// try{
// local $SIG{ __WARN__ } = Slic3r::GUI::warning_catcher($self);
preset.is_default ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true);
(preset.is_default || preset.is_system) ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true);
update();
// For the printer profile, generate the extruder pages.
on_preset_loaded();
@ -1557,7 +1557,7 @@ void Tab::save_preset(std::string name /*= ""*/)
std::vector<std::string> values;
for (size_t i = 0; i < m_presets->size(); ++i) {
const Preset &preset = m_presets->preset(i);
if (preset.is_default || preset.is_external)
if (preset.is_default || preset.is_system || preset.is_external)
continue;
values.push_back(preset.name);
}
@ -1571,6 +1571,15 @@ void Tab::save_preset(std::string name /*= ""*/)
show_error(this, _(L("The supplied name is empty. It can't be saved.")));
return;
}
const Preset *existing = m_presets->find_preset(name, false);
if (existing && (existing->is_default || existing->is_system)) {
show_error(this, _(L("Cannot overwrite a system profile.")));
return;
}
if (existing && (existing->is_external)) {
show_error(this, _(L("Cannot overwrite an external.")));
return;
}
}
// Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini
@ -1670,7 +1679,7 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox
for (size_t idx = 0; idx < printers->size(); ++idx)
{
Preset& preset = printers->preset(idx);
if (!preset.is_default && !preset.is_external)
if (!preset.is_default && !preset.is_external && !preset.is_system)
presets.Add(preset.name);
}

View file

@ -12,6 +12,7 @@
bool default() %code%{ RETVAL = THIS->is_default; %};
bool external() %code%{ RETVAL = THIS->is_external; %};
bool system() %code%{ RETVAL = THIS->is_system; %};
bool visible() %code%{ RETVAL = THIS->is_visible; %};
bool dirty() %code%{ RETVAL = THIS->is_dirty; %};
bool compatible() %code%{ RETVAL = THIS->is_compatible; %};
@ -110,10 +111,10 @@ PresetCollection::arrayref()
croak("Cannot create configuration directories:\n%s\n", e.what());
}
%};
void load_presets()
void load_presets(AppConfig *config)
%code%{
try {
THIS->load_presets();
THIS->load_presets(*config);
} catch (std::exception& e) {
croak("Loading of Slic3r presets from %s failed.\n\n%s\n",
Slic3r::data_dir().c_str(), e.what());
@ -143,6 +144,14 @@ PresetCollection::arrayref()
croak("Loading of a config bundle %s failed:\n%s\n", path, e.what());
}
%};
void install_vendor_configbundle(const char *path)
%code%{
try {
THIS->install_vendor_configbundle(path);
} catch (std::exception& e) {
croak("Installing a vendor config bundle %s failed:\n%s\n", path, e.what());
}
%};
void export_configbundle(char *path)
%code%{
try {
@ -154,7 +163,6 @@ PresetCollection::arrayref()
void set_default_suppressed(bool default_suppressed);
void load_selections (AppConfig *config) %code%{ THIS->load_selections(*config); %};
void export_selections(AppConfig *config) %code%{ THIS->export_selections(*config); %};
void export_selections_pp(PlaceholderParser *pp) %code%{ THIS->export_selections(*pp); %};