Renamed the "compatible_printers_condition" and "inherits" vectors

to "compatible_printers_condition_cummulative" and "inherits_cummulative"
when storing to AMF/3MF/Config files.

Improved escaping of strings stored / loaded from config files.
This commit is contained in:
bubnikv 2018-06-28 20:13:01 +02:00
parent 80b430ad94
commit 26b003073b
8 changed files with 76 additions and 84 deletions

View File

@ -20,6 +20,7 @@
namespace Slic3r {
// Escape \n, \r and \\
std::string escape_string_cstyle(const std::string &str)
{
// Allocate a buffer twice the input string length,
@ -28,9 +29,15 @@ std::string escape_string_cstyle(const std::string &str)
char *outptr = out.data();
for (size_t i = 0; i < str.size(); ++ i) {
char c = str[i];
if (c == '\n' || c == '\r') {
if (c == '\r') {
(*outptr ++) = '\\';
(*outptr ++) = 'r';
} else if (c == '\n') {
(*outptr ++) = '\\';
(*outptr ++) = 'n';
} else if (c == '\\') {
(*outptr ++) = '\\';
(*outptr ++) = '\\';
} else
(*outptr ++) = c;
}
@ -69,7 +76,10 @@ std::string escape_strings_cstyle(const std::vector<std::string> &strs)
if (c == '\\' || c == '"') {
(*outptr ++) = '\\';
(*outptr ++) = c;
} else if (c == '\n' || c == '\r') {
} else if (c == '\r') {
(*outptr ++) = '\\';
(*outptr ++) = 'r';
} else if (c == '\n') {
(*outptr ++) = '\\';
(*outptr ++) = 'n';
} else
@ -84,6 +94,7 @@ std::string escape_strings_cstyle(const std::vector<std::string> &strs)
return std::string(out.data(), outptr - out.data());
}
// Unescape \n, \r and \\
bool unescape_string_cstyle(const std::string &str, std::string &str_out)
{
std::vector<char> out(str.size(), 0);
@ -94,8 +105,12 @@ bool unescape_string_cstyle(const std::string &str, std::string &str_out)
if (++ i == str.size())
return false;
c = str[i];
if (c == 'n')
if (c == 'r')
(*outptr ++) = '\r';
else if (c == 'n')
(*outptr ++) = '\n';
else
(*outptr ++) = c;
} else
(*outptr ++) = c;
}
@ -134,7 +149,9 @@ bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &o
if (++ i == str.size())
return false;
c = str[i];
if (c == 'n')
if (c == 'r')
c = '\r';
else if (c == 'n')
c = '\n';
}
buf.push_back(c);

View File

@ -1422,7 +1422,7 @@ void GCode::append_full_config(const Print& print, std::string& str)
for (const char *key : {
"print_settings_id", "filament_settings_id", "printer_settings_id",
"printer_model", "printer_variant", "default_print_profile", "default_filament_profile",
"compatible_printers_condition", "inherits" }) {
"compatible_printers_condition_cummulative", "inherits_cummulative" }) {
const ConfigOption *opt = full_config.option(key);
if (opt != nullptr)
str += std::string("; ") + key + " = " + opt->serialize() + "\n";

View File

@ -147,15 +147,17 @@ PrintConfigDef::PrintConfigDef()
def->label = L("Compatible printers");
def->default_value = new ConfigOptionStrings();
// The following value is defined as a vector of strings, so it could
// collect the "inherits" values over the print and filaments profiles
// when storing into a project file (AMF, 3MF, Config ...)
def = this->add("compatible_printers_condition", coStrings);
def = this->add("compatible_printers_condition", coString);
def->label = L("Compatible printers condition");
def->tooltip = L("A boolean expression using the configuration values of an active printer profile. "
"If this expression evaluates to true, this profile is considered compatible "
"with the active printer profile.");
def->default_value = new ConfigOptionStrings { "" };
def->default_value = new ConfigOptionString();
// The following value is to be stored into the project file (AMF, 3MF, Config ...)
// and it contains a sum of "compatible_printers_condition" values over the print and filament profiles.
def = this->add("compatible_printers_condition_cummulative", coStrings);
def->default_value = new ConfigOptionStrings();
def = this->add("complete_objects", coBool);
def->label = L("Complete individual objects");
@ -822,15 +824,17 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->default_value = new ConfigOptionFloat(80);
// The following value is defined as a vector of strings, so it could
// collect the "inherits" values over the print and filaments profiles
// when storing into a project file (AMF, 3MF, Config ...)
def = this->add("inherits", coStrings);
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 ConfigOptionStrings { "" };
def->default_value = new ConfigOptionString();
// The following value is to be stored into the project file (AMF, 3MF, Config ...)
// and it contains a sum of "inherits" values over the print and filament profiles.
def = this->add("inherits_cummulative", coStrings);
def->default_value = new ConfigOptionStrings();
def = this->add("interface_shells", coBool);
def->label = L("Interface shells");

View File

@ -180,7 +180,7 @@ void Preset::normalize(DynamicPrintConfig &config)
size_t n = (nozzle_diameter == nullptr) ? 1 : nozzle_diameter->values.size();
const auto &defaults = FullPrintConfig::defaults();
for (const std::string &key : Preset::filament_options()) {
if (key == "compatible_printers" || key == "compatible_printers_condition" || key == "inherits")
if (key == "compatible_printers")
continue;
auto *opt = config.option(key, false);
assert(opt != nullptr);
@ -459,8 +459,8 @@ Preset& PresetCollection::load_external_preset(
DynamicPrintConfig cfg(this->default_preset().config);
cfg.apply_only(config, cfg.keys(), true);
// Is there a preset already loaded with the name stored inside the config?
std::deque<Preset>::iterator it = original_name.empty() ? m_presets.end() : this->find_preset_internal(original_name);
if (it != m_presets.end() && profile_print_params_same(it->config, cfg)) {
std::deque<Preset>::iterator it = this->find_preset_internal(original_name);
if (it != m_presets.end() && it->name == original_name && profile_print_params_same(it->config, cfg)) {
// The preset exists and it matches the values stored inside config.
if (select)
this->select_preset(it - m_presets.begin());
@ -490,7 +490,7 @@ Preset& PresetCollection::load_external_preset(
}
new_name = name + suffix;
it = this->find_preset_internal(new_name);
if (it == m_presets.end())
if (it == m_presets.end() || it->name != new_name)
// Unique profile name. Insert a new profile.
break;
if (profile_print_params_same(it->config, cfg)) {
@ -851,17 +851,6 @@ std::vector<std::string> PresetCollection::dirty_options(const Preset *edited, c
return changed;
}
std::vector<std::string> PresetCollection::system_equal_options() const
{
const Preset *edited = &this->get_edited_preset();
const Preset *reference = this->get_selected_preset_parent();
std::vector<std::string> equal;
if (edited != nullptr && reference != nullptr) {
equal = reference->config.equal(edited->config);
}
return equal;
}
// Select a new preset. This resets all the edits done to the currently selected preset.
// If the preset with index idx does not exist, a first visible preset is selected.
Preset& PresetCollection::select_preset(size_t idx)

View File

@ -140,24 +140,12 @@ public:
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)
{
auto option = cfg.option<ConfigOptionStrings>("inherits", true);
if (option->values.empty())
option->values.emplace_back(std::string());
return option->values.front();
}
static std::string& inherits(DynamicPrintConfig &cfg) { return cfg.option<ConfigOptionString>("inherits", true)->value; }
std::string& inherits() { return Preset::inherits(this->config); }
const std::string& inherits() const { return Preset::inherits(const_cast<Preset*>(this)->config); }
// Returns the "compatible_printers_condition".
static std::string& compatible_printers_condition(DynamicPrintConfig &cfg)
{
auto option = cfg.option<ConfigOptionStrings>("compatible_printers_condition", true);
if (option->values.empty())
option->values.emplace_back(std::string());
return option->values.front();
}
static std::string& compatible_printers_condition(DynamicPrintConfig &cfg) { return cfg.option<ConfigOptionString>("compatible_printers_condition", true)->value; }
std::string& compatible_printers_condition() { return Preset::compatible_printers_condition(this->config); }
const std::string& compatible_printers_condition() const { return Preset::compatible_printers_condition(const_cast<Preset*>(this)->config); }
@ -343,8 +331,6 @@ public:
// Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ.
std::vector<std::string> current_different_from_parent_options(const bool is_printer_type = false) const
{ return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent(), is_printer_type); }
// Compare the content of get_selected_preset() with get_selected_preset_parent() configs, return the list of keys where they equal.
std::vector<std::string> system_equal_options() const;
// Update the choice UI from the list of presets.
// If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
@ -380,9 +366,10 @@ private:
PresetCollection(const PresetCollection &other);
PresetCollection& operator=(const PresetCollection &other);
// Find a preset in the sorted list of presets.
// 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<Preset>::iterator find_preset_internal(const std::string &name)
{
Preset key(m_type, name);

View File

@ -59,9 +59,6 @@ PresetBundle::PresetBundle() :
// "compatible_printers", "compatible_printers_condition", "inherits",
// "print_settings_id", "filament_settings_id", "printer_settings_id",
// "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile"
//
//FIXME Rename "compatible_printers" and "compatible_printers_condition", as they are defined in both print and filament profiles,
// therefore they are clashing when generating a a config file, G-code or AMF/3MF.
// Create the ID config keys, as they are not part of the Static print config classes.
this->prints.default_preset().config.optptr("print_settings_id", true);
@ -77,7 +74,7 @@ PresetBundle::PresetBundle() :
this->printers.default_preset().config.optptr("printer_model", true);
this->printers.default_preset().config.optptr("printer_variant", true);
this->printers.default_preset().config.optptr("default_print_profile", true);
this->printers.default_preset().config.optptr("default_filament_profile", true);
this->printers.default_preset().config.option<ConfigOptionStrings>("default_filament_profile", true)->values = { "" };
this->printers.default_preset().inherits();
// Load the default preset bitmaps.
@ -411,7 +408,7 @@ DynamicPrintConfig PresetBundle::full_config() const
std::vector<const ConfigOption*> filament_opts(num_extruders, nullptr);
// loop through options and apply them to the resulting config.
for (const t_config_option_key &key : this->filaments.default_preset().config.keys()) {
if (key == "compatible_printers" || key == "compatible_printers_condition" || key == "inherits")
if (key == "compatible_printers")
continue;
// Get a destination option.
ConfigOption *opt_dst = out.option(key, false);
@ -462,8 +459,8 @@ DynamicPrintConfig PresetBundle::full_config() const
if (nonempty)
out.set_key_value(key, new ConfigOptionStrings(std::move(values)));
};
add_if_some_non_empty(std::move(compatible_printers_condition), "compatible_printers_condition");
add_if_some_non_empty(std::move(inherits), "inherits");
add_if_some_non_empty(std::move(compatible_printers_condition), "compatible_printers_condition_cummulative");
add_if_some_non_empty(std::move(inherits), "inherits_cummulative");
return out;
}
@ -544,17 +541,15 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
size_t num_extruders = std::min(config.option<ConfigOptionFloats>("nozzle_diameter" )->values.size(),
config.option<ConfigOptionFloats>("filament_diameter")->values.size());
// Make a copy of the "compatible_printers_condition" and "inherits" vectors, which
// Make a copy of the "compatible_printers_condition_cummulative" and "inherits_cummulative" vectors, which
// accumulate values over all presets (print, filaments, printers).
// These values will be distributed into their particular presets when loading.
auto *compatible_printers_condition = config.option<ConfigOptionStrings>("compatible_printers_condition", true);
auto *inherits = config.option<ConfigOptionStrings>("inherits", true);
std::vector<std::string> compatible_printers_condition_values = std::move(compatible_printers_condition->values);
std::vector<std::string> inherits_values = std::move(inherits->values);
if (compatible_printers_condition_values.empty())
compatible_printers_condition_values.emplace_back(std::string());
if (inherits_values.empty())
inherits_values.emplace_back(std::string());
std::vector<std::string> compatible_printers_condition_values = std::move(config.option<ConfigOptionStrings>("compatible_printers_condition_cummulative", true)->values);
std::vector<std::string> inherits_values = std::move(config.option<ConfigOptionStrings>("inherits_cummulative", true)->values);
std::string &compatible_printers_condition = Preset::compatible_printers_condition(config);
std::string &inherits = Preset::inherits(config);
compatible_printers_condition_values.resize(num_extruders + 2, std::string());
inherits_values.resize(num_extruders + 2, std::string());
// 1) Create a name from the file name.
// Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles.
@ -566,29 +561,25 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
PresetCollection &presets = (i_group == 0) ? this->prints : this->printers;
// Split the "compatible_printers_condition" and "inherits" values one by one from a single vector to the print & printer profiles.
size_t idx = (i_group == 0) ? 0 : num_extruders + 1;
inherits->values = { (idx < inherits_values.size()) ? inherits_values[idx] : "" };
if (i_group == 0)
compatible_printers_condition->values = { compatible_printers_condition_values.front() };
inherits = inherits_values[idx];
compatible_printers_condition = compatible_printers_condition_values[idx];
if (is_external)
presets.load_external_preset(name_or_path, name,
config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id"),
config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id", true),
config);
else
presets.load_preset(presets.path_from_name(name), name, config).save();
}
// Update the "compatible_printers_condition" and "inherits" vectors, so their number matches the number of extruders.
compatible_printers_condition_values.erase(compatible_printers_condition_values.begin());
inherits_values.erase(inherits_values.begin());
compatible_printers_condition_values.resize(num_extruders, std::string());
inherits_values.resize(num_extruders, std::string());
compatible_printers_condition->values = std::move(compatible_printers_condition_values);
inherits->values = std::move(inherits_values);
// 3) Now load the filaments. If there are multiple filament presets, split them and load them.
const ConfigOptionStrings *old_filament_profile_names = config.option<ConfigOptionStrings>("filament_settings_id", false);
assert(old_filament_profile_names != nullptr);
auto old_filament_profile_names = config.option<ConfigOptionStrings>("filament_settings_id", true);
old_filament_profile_names->values.resize(num_extruders, std::string());
config.option<ConfigOptionStrings>("default_filament_profile", true)->values.resize(num_extruders, std::string());
if (num_extruders <= 1) {
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
inherits = inherits_values[1];
compatible_printers_condition = compatible_printers_condition_values[1];
if (is_external)
this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config);
else
@ -614,12 +605,16 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
// Load the configs into this->filaments and make them active.
this->filament_presets.clear();
for (size_t i = 0; i < configs.size(); ++ i) {
DynamicPrintConfig &cfg = configs[i];
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
cfg.opt_string("compatible_printers_condition", true) = compatible_printers_condition_values[i + 1];
cfg.opt_string("inherits", true) = inherits_values[i + 1];
// Load all filament presets, but only select the first one in the preset dialog.
Preset *loaded = nullptr;
if (is_external)
loaded = &this->filaments.load_external_preset(name_or_path, name,
(i < old_filament_profile_names->values.size()) ? old_filament_profile_names->values[i] : "",
std::move(configs[i]), i == 0);
std::move(cfg), i == 0);
else {
// Used by the config wizard when creating a custom setup.
// Therefore this block should only be called for a single extruder.
@ -630,7 +625,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
sprintf(suffix, "%d", i);
std::string new_name = name + suffix;
loaded = &this->filaments.load_preset(this->filaments.path_from_name(new_name),
new_name, std::move(configs[i]), i == 0);
new_name, std::move(cfg), i == 0);
loaded->save();
}
this->filament_presets.emplace_back(loaded->name);

View File

@ -803,7 +803,7 @@ void Tab::reload_compatible_printers_widget()
bool has_any = !m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
has_any ? m_compatible_printers_btn->Enable() : m_compatible_printers_btn->Disable();
m_compatible_printers_checkbox->SetValue(!has_any);
get_field("compatible_printers_condition", 0)->toggle(!has_any);
get_field("compatible_printers_condition")->toggle(!has_any);
}
void TabPrint::build()
@ -1014,7 +1014,7 @@ void TabPrint::build()
};
optgroup->append_line(line, &m_colored_Label);
option = optgroup->get_option("compatible_printers_condition", 0);
option = optgroup->get_option("compatible_printers_condition");
option.opt.full_width = true;
optgroup->append_single_option_line(option);
@ -1365,7 +1365,7 @@ void TabFilament::build()
};
optgroup->append_line(line, &m_colored_Label);
option = optgroup->get_option("compatible_printers_condition", 0);
option = optgroup->get_option("compatible_printers_condition");
option.opt.full_width = true;
optgroup->append_single_option_line(option);
@ -2240,7 +2240,7 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox
// All printers have been made compatible with this preset.
if ((*checkbox)->GetValue())
load_key_value("compatible_printers", std::vector<std::string> {});
get_field("compatible_printers_condition", 0)->toggle((*checkbox)->GetValue());
get_field("compatible_printers_condition")->toggle((*checkbox)->GetValue());
update_changed_ui();
}) );

View File

@ -172,7 +172,7 @@ protected:
std::vector<std::string> m_reload_dependent_tabs = {};
enum OptStatus { osSystemValue = 1, osInitValue = 2 };
std::map<std::string, int> m_options_list;
int m_opt_status_value;
int m_opt_status_value = 0;
t_icon_descriptions m_icon_descriptions = {};