preset updater: updating common profiles

experimental: changed values in profile files for testing purpose and added own common profiles. Should not go to master.

updating common profiles

common profiles downloading

common profiles: updating common_filaments and common_materials bundles, keeping track of needed versions (just like common bundle) and having one bundle that is always present (without version in filename). Deleting all unnesesary common bundles in vendor directory

loading star common profiles into system profiles

loading star common profiles into system profiles

load non-star common profiles into system profiles for flatening alg


load common bundle info if missing
This commit is contained in:
David Kocik 2022-01-24 16:35:26 +01:00
parent 0e173e3f82
commit 2b45731cff
10 changed files with 1103 additions and 8 deletions

View File

@ -14,6 +14,8 @@ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/Prus
# also the first model installed & the first nozzle installed will be activated after install.
# Printer model name will be shown by the installation wizard.
common_version = 0.0.1
[printer_model:ENDER3]
name = Creality Ender-3
variants = 0.4

View File

@ -0,0 +1,195 @@
[vendor]
name = common
config_version = 0.0.1
[print:*common_print*]
avoid_crossing_perimeters = 0
bridge_acceleration = 1000
bridge_angle = 0
bridge_flow_ratio = 0.8
bridge_speed = 20
brim_width = 0
clip_multipart_objects = 1
compatible_printers =
complete_objects = 0
default_acceleration = 1000
dont_support_bridges = 1
elefant_foot_compensation = 0.2
ensure_vertical_shell_thickness = 1
external_fill_pattern = rectilinear
external_perimeters_first = 0
external_perimeter_extrusion_width = 0.45
extra_perimeters = 0
extruder_clearance_height = 20
extruder_clearance_radius = 45
extrusion_width = 0.45
fill_angle = 45
fill_density = 20%
fill_pattern = cubic
first_layer_acceleration = 1000
first_layer_extrusion_width = 0.42
first_layer_height = 0.2
first_layer_speed = 20
gap_fill_speed = 40
gcode_comments = 0
infill_every_layers = 1
infill_extruder = 1
infill_extrusion_width = 0.45
infill_first = 0
infill_only_where_needed = 0
infill_overlap = 25%
interface_shells = 0
max_print_speed = 100
max_volumetric_extrusion_rate_slope_negative = 0
max_volumetric_extrusion_rate_slope_positive = 0
max_volumetric_speed = 0
min_skirt_length = 4
notes =
overhangs = 0
only_retract_when_crossing_perimeters = 0
ooze_prevention = 0
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
perimeters = 2
perimeter_extruder = 1
perimeter_extrusion_width = 0.45
post_process =
print_settings_id =
raft_layers = 0
resolution = 0
seam_position = nearest
single_extruder_multi_material_priming = 1
skirts = 1
skirt_distance = 2
skirt_height = 3
small_perimeter_speed = 25
solid_infill_below_area = 0
solid_infill_every_layers = 0
solid_infill_extruder = 1
solid_infill_extrusion_width = 0.45
spiral_vase = 0
standby_temperature_delta = -5
support_material = 0
support_material_extruder = 0
support_material_extrusion_width = 0.35
support_material_interface_extruder = 0
support_material_angle = 0
support_material_buildplate_only = 0
support_material_enforce_layers = 0
support_material_contact_distance = 0.1
support_material_interface_contact_loops = 0
support_material_interface_layers = 2
support_material_interface_spacing = 0.2
support_material_interface_speed = 100%
support_material_pattern = rectilinear
support_material_spacing = 2
support_material_speed = 50
support_material_synchronize_layers = 0
support_material_threshold = 55
support_material_with_sheath = 0
support_material_xy_spacing = 50%
thin_walls = 0
top_infill_extrusion_width = 0.45
top_solid_infill_speed = 40
travel_speed = 180
wipe_tower = 1
wipe_tower_bridging = 10
wipe_tower_rotation_angle = 0
wipe_tower_width = 60
wipe_tower_x = 170
wipe_tower_y = 140
xy_size_compensation = 0
top_solid_min_thickness = 0.6
bottom_solid_min_thickness = 0.5
[filament:common_filament]
cooling = 1
compatible_printers =
# For now, all but selected filaments are disabled for the MMU 2.0
compatible_printers_condition = ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
end_filament_gcode = "; Filament-specific end gcode"
extrusion_multiplier = 1
filament_loading_speed = 28
filament_loading_speed_start = 3
filament_unloading_speed = 90
filament_unloading_speed_start = 100
filament_toolchange_delay = 0
filament_cooling_moves = 4
filament_cooling_initial_speed = 2.2
filament_cooling_final_speed = 3.4
filament_load_time = 0
filament_unload_time = 0
filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
filament_minimal_purge_on_wipe_tower = 15
filament_cost = 0
filament_density = 0
filament_diameter = 1.75
filament_notes = ""
filament_settings_id = ""
filament_soluble = 0
min_print_speed = 15
slowdown_below_layer_time = 20
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/}0.2{elsif printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif} ; Filament gcode"
[printer:*common_printer*]
printer_technology = FFF
bed_shape = 0x0,250x0,250x210,0x210
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]\n\n
between_objects_gcode =
deretract_speed = 0
end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
extruder_offset = 0x0
gcode_flavor = marlin
silent_mode = 0
remaining_times = 1
machine_max_acceleration_e = 10000
machine_max_acceleration_extruding = 2000
machine_max_acceleration_retracting = 1500
machine_max_acceleration_x = 9000
machine_max_acceleration_y = 9000
machine_max_acceleration_z = 500
machine_max_feedrate_e = 120
machine_max_feedrate_x = 500
machine_max_feedrate_y = 500
machine_max_feedrate_z = 12
machine_max_jerk_e = 2.5
machine_max_jerk_x = 10
machine_max_jerk_y = 10
machine_max_jerk_z = 0.2
machine_min_extruding_rate = 0
machine_min_travel_rate = 0
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
max_layer_height = 0.25
min_layer_height = 0.07
max_print_height = 200
nozzle_diameter = 0.4
octoprint_apikey =
octoprint_host =
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\n
printer_settings_id =
retract_before_travel = 1
retract_before_wipe = 0%
retract_layer_change = 1
retract_length = 0.8
retract_length_toolchange = 4
retract_lift = 0.6
retract_lift_above = 0
retract_lift_below = 199
retract_restart_extra = 0
retract_restart_extra_toolchange = 0
retract_speed = 35
serial_port =
serial_speed = 250000
single_extruder_multi_material = 0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.2.3 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
toolchange_gcode =
use_firmware_retraction = 0
use_relative_e_distances = 1
use_volumetric_e = 0
variable_layer_height = 1
wipe = 1
z_offset = 0
printer_model = MK2S
printer_variant = 0.4
default_print_profile = 0.15mm OPTIMAL
default_filament_profile = Prusament PLA

View File

@ -0,0 +1,195 @@
[vendor]
name = common
config_version = 0.0.2
[print:*common*]
avoid_crossing_perimeters = 0
bridge_acceleration = 1000
bridge_angle = 0
bridge_flow_ratio = 0.8
bridge_speed = 20
brim_width = 0
clip_multipart_objects = 1
compatible_printers =
complete_objects = 0
default_acceleration = 1000
dont_support_bridges = 1
elefant_foot_compensation = 0.2
ensure_vertical_shell_thickness = 1
external_fill_pattern = rectilinear
external_perimeters_first = 0
external_perimeter_extrusion_width = 0.45
extra_perimeters = 0
extruder_clearance_height = 20
extruder_clearance_radius = 45
extrusion_width = 0.45
fill_angle = 45
fill_density = 20%
fill_pattern = cubic
first_layer_acceleration = 1000
first_layer_extrusion_width = 0.42
first_layer_height = 0.2
first_layer_speed = 20
gap_fill_speed = 40
gcode_comments = 0
infill_every_layers = 1
infill_extruder = 1
infill_extrusion_width = 0.45
infill_first = 0
infill_only_where_needed = 0
infill_overlap = 25%
interface_shells = 0
max_print_speed = 100
max_volumetric_extrusion_rate_slope_negative = 0
max_volumetric_extrusion_rate_slope_positive = 0
max_volumetric_speed = 0
min_skirt_length = 4
notes =
overhangs = 0
only_retract_when_crossing_perimeters = 0
ooze_prevention = 0
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
perimeters = 2
perimeter_extruder = 1
perimeter_extrusion_width = 0.45
post_process =
print_settings_id =
raft_layers = 0
resolution = 0
seam_position = nearest
single_extruder_multi_material_priming = 1
skirts = 1
skirt_distance = 2
skirt_height = 3
small_perimeter_speed = 25
solid_infill_below_area = 0
solid_infill_every_layers = 0
solid_infill_extruder = 1
solid_infill_extrusion_width = 0.45
spiral_vase = 0
standby_temperature_delta = -5
support_material = 0
support_material_extruder = 0
support_material_extrusion_width = 0.35
support_material_interface_extruder = 0
support_material_angle = 0
support_material_buildplate_only = 0
support_material_enforce_layers = 0
support_material_contact_distance = 0.1
support_material_interface_contact_loops = 0
support_material_interface_layers = 2
support_material_interface_spacing = 0.2
support_material_interface_speed = 100%
support_material_pattern = rectilinear
support_material_spacing = 2
support_material_speed = 50
support_material_synchronize_layers = 0
support_material_threshold = 55
support_material_with_sheath = 0
support_material_xy_spacing = 50%
thin_walls = 0
top_infill_extrusion_width = 0.45
top_solid_infill_speed = 40
travel_speed = 180
wipe_tower = 1
wipe_tower_bridging = 10
wipe_tower_rotation_angle = 0
wipe_tower_width = 60
wipe_tower_x = 170
wipe_tower_y = 140
xy_size_compensation = 0
top_solid_min_thickness = 0.6
bottom_solid_min_thickness = 0.5
[filament:common]
cooling = 1
compatible_printers =
# For now, all but selected filaments are disabled for the MMU 2.0
compatible_printers_condition = ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
end_filament_gcode = "; Filament-specific end gcode"
extrusion_multiplier = 1
filament_loading_speed = 28
filament_loading_speed_start = 3
filament_unloading_speed = 90
filament_unloading_speed_start = 100
filament_toolchange_delay = 0
filament_cooling_moves = 4
filament_cooling_initial_speed = 2.2
filament_cooling_final_speed = 3.4
filament_load_time = 0
filament_unload_time = 0
filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
filament_minimal_purge_on_wipe_tower = 15
filament_cost = 0
filament_density = 0
filament_diameter = 1.75
filament_notes = ""
filament_settings_id = ""
filament_soluble = 0
min_print_speed = 15
slowdown_below_layer_time = 20
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/}0.2{elsif printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif} ; Filament gcode"
[printer:*common*]
printer_technology = FFF
bed_shape = 0x0,250x0,250x210,0x210
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]\n\n
between_objects_gcode =
deretract_speed = 0
end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
extruder_offset = 0x0
gcode_flavor = marlin
silent_mode = 0
remaining_times = 1
machine_max_acceleration_e = 10000
machine_max_acceleration_extruding = 2000
machine_max_acceleration_retracting = 1500
machine_max_acceleration_x = 9000
machine_max_acceleration_y = 9000
machine_max_acceleration_z = 500
machine_max_feedrate_e = 120
machine_max_feedrate_x = 500
machine_max_feedrate_y = 500
machine_max_feedrate_z = 12
machine_max_jerk_e = 2.5
machine_max_jerk_x = 10
machine_max_jerk_y = 10
machine_max_jerk_z = 0.2
machine_min_extruding_rate = 0
machine_min_travel_rate = 0
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
max_layer_height = 0.25
min_layer_height = 0.07
max_print_height = 200
nozzle_diameter = 0.4
octoprint_apikey =
octoprint_host =
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\n
printer_settings_id =
retract_before_travel = 1
retract_before_wipe = 0%
retract_layer_change = 1
retract_length = 0.8
retract_length_toolchange = 4
retract_lift = 0.6
retract_lift_above = 0
retract_lift_below = 199
retract_restart_extra = 0
retract_restart_extra_toolchange = 0
retract_speed = 35
serial_port =
serial_speed = 250000
single_extruder_multi_material = 0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.2.3 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
toolchange_gcode =
use_firmware_retraction = 0
use_relative_e_distances = 1
use_volumetric_e = 0
variable_layer_height = 1
wipe = 1
z_offset = 0
printer_model = MK2S
printer_variant = 0.4
default_print_profile = 0.15mm OPTIMAL
default_filament_profile = Prusament PLA

View File

@ -0,0 +1,4 @@
min_slic3r_version = 2.2.0-alpha3
0.0.3 test3
0.0.2 test2
0.0.1 test1

View File

@ -127,6 +127,7 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
const auto &vendor_section = get_or_throw(tree, "vendor")->second;
res.name = get_or_throw(vendor_section, "name")->second.data();
// Load config version
auto config_version_str = get_or_throw(vendor_section, "config_version")->second.data();
auto config_version = Semver::parse(config_version_str);
if (! config_version) {
@ -135,6 +136,51 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
res.config_version = std::move(*config_version);
}
// Load common profile version
try {
auto common_version_str = get_or_throw(vendor_section, "common_version")->second.data();
auto common_version = Semver::parse(common_version_str);
if (!common_version) {
BOOST_LOG_TRIVIAL(info) << boost::format("Vendor bundle: `%1%`: Does not uses common profile.") % id;
}
else {
res.using_common_base_profile = true;
res.common_base_version = std::move(*common_version);
}
} catch (const std::runtime_error &err){
BOOST_LOG_TRIVIAL(info) << boost::format("Vendor bundle: `%1%`: Does not uses common profile. (exception thrown)") % id;
}
// Load common filaments profile version
try {
auto common_version_str = get_or_throw(vendor_section, "common_filaments_version")->second.data();
auto common_version = Semver::parse(common_version_str);
if (!common_version) {
BOOST_LOG_TRIVIAL(info) << boost::format("Vendor bundle: `%1%`: Does not uses common filaments profile.") % id;
}
else {
res.using_common_filaments_profile = true;
res.common_filaments_version = std::move(*common_version);
}
}
catch (const std::runtime_error& err) {
BOOST_LOG_TRIVIAL(info) << boost::format("Vendor bundle: `%1%`: Does not uses common filaments profile. (exception thrown)") % id;
}
// Load common materials profile version
try {
auto common_version_str = get_or_throw(vendor_section, "common_materials_version")->second.data();
auto common_version = Semver::parse(common_version_str);
if (!common_version) {
BOOST_LOG_TRIVIAL(info) << boost::format("Vendor bundle: `%1%`: Does not uses common materials profile.") % id;
}
else {
res.using_common_materials_profile = true;
res.common_materials_version = std::move(*common_version);
}
}
catch (const std::runtime_error& err) {
BOOST_LOG_TRIVIAL(info) << boost::format("Vendor bundle: `%1%`: Does not uses common materials profile. (exception thrown)") % id;
}
// Load URLs
const auto config_update_url = vendor_section.find("config_update_url");
if (config_update_url != vendor_section.not_found()) {

View File

@ -34,6 +34,12 @@ public:
Semver config_version;
std::string config_update_url;
std::string changelog_url;
Semver common_base_version;
Semver common_filaments_version;
Semver common_materials_version;
bool using_common_base_profile { false };
bool using_common_filaments_profile{ false };
bool using_common_materials_profile{ false };
struct PrinterVariant {
PrinterVariant() {}

View File

@ -133,6 +133,13 @@ PresetBundle& PresetBundle::operator=(const PresetBundle &rhs)
return *this;
}
PresetBundle::PresetBundle(const std::vector<CommonBundleInfo>& ctr) : PresetBundle()
{
for (const auto & tr : ctr)
{
common_bundles.emplace_back(tr);
}
}
void PresetBundle::reset(bool delete_files)
{
@ -1235,6 +1242,25 @@ static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, co
flatten_configbundle_hierarchy(tree, "printer", preset_bundle ? preset_bundle->printers.system_preset_names() : std::vector<std::string>());
}
static void print_ptree(const boost::property_tree::ptree& tree)
{
BOOST_LOG_TRIVIAL(error) << "";
for (const auto& section : tree) {
BOOST_LOG_TRIVIAL(error) <<section.first<<" " << section.second.size();
//print_ptree(section.second, depth+1);
}
}
void PresetBundle::create_common_bundles_info(boost::filesystem::path dir)
{
//const auto printer_dir = fs::path(Slic3r::data_dir()) / "printer";
for (const auto& dir_entry : boost::filesystem::directory_iterator(dir)) {
if (Slic3r::is_ini_file(dir_entry))
if (dir_entry.path().filename().string().substr(0,6) == "common")
load_common_configbundle(dir_entry.path().string());
}
}
// Load a config bundle file, into presets and store the loaded presets into separate files
// of the local configuration directory.
std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_configbundle(
@ -1263,7 +1289,11 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_configbundle(
const VendorProfile *vendor_profile = nullptr;
if (flags.has(LoadConfigBundleAttribute::LoadSystem) || flags.has(LoadConfigBundleAttribute::LoadVendorOnly)) {
auto vp = VendorProfile::from_ini(tree, path);
if (vp.models.size() == 0) {
if (vp.name == "common" || vp.name == "common_filaments" || vp.name == "common_materials"){ // common profiles should be already loaded
//return load_common_configbundle(path, flags, tree, vp);
//return 0;
}
else if (vp.models.size() == 0) {
BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: No printer model defined.") % path;
return std::make_pair(PresetsConfigSubstitutions{}, 0);
} else if (vp.num_variants() == 0) {
@ -1276,6 +1306,39 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_configbundle(
if (flags.has(LoadConfigBundleAttribute::LoadVendorOnly))
return std::make_pair(PresetsConfigSubstitutions{}, 0);
// 1.1) If common profile is being inherited, find ptree of such common profile and branch it into current tree
std::vector<std::string> branches_to_remove;
auto branch_common = [this, vendor_profile](std::vector<std::string>& branches_to_remove, pt::ptree& tree)->bool{
for (const auto& cbn : common_bundles) {
if (cbn.name == "common" && cbn.version == vendor_profile->common_base_version) {
boost::nowide::ifstream path(cbn.path);
pt::ptree ctr;
pt::read_ini(path, ctr);
for (const auto& section : ctr) {
if (section.first != "vendor") {
if (section.first.back() != '*')
//star profiles are marked to be removed after flatening
branches_to_remove.emplace_back(section.first);
tree.add_child(section.first, section.second);
}
}
return true;
}
}
return false;
};
if (flags & LOAD_CFGBNDLE_SYSTEM)
{
if (vendor_profile->using_common_base_profile) {
if(!branch_common(branches_to_remove, tree)) {
this->create_common_bundles_info(std::move(boost::filesystem::path(path).parent_path()));
if (!branch_common(branches_to_remove, tree))
BOOST_LOG_TRIVIAL(error) << "Common profile bundle not found for profile " << path;
}
}
}
// 1.5) Flatten the config bundle by applying the inheritance rules. Internal profiles (with names starting with '*') are removed.
// If loading a user config bundle, do not flatten with the system profiles, but keep the "inherits" flag intact.
flatten_configbundle_hierarchy(tree, flags.has(LoadConfigBundleAttribute::LoadSystem) ? nullptr : this);
@ -1371,7 +1434,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_configbundle(
continue;
if (presets != nullptr) {
// Load the print, filament or printer preset.
const DynamicPrintConfig *default_config = nullptr;
const DynamicPrintConfig *default_config = nullptr;
DynamicPrintConfig config;
std::string alias_name;
std::vector<std::string> renamed_from;
@ -1576,6 +1639,290 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_configbundle(
return std::make_pair(std::move(substitutions), presets_loaded + ph_printers_loaded);
}
size_t PresetBundle::load_common_configbundle(const std::string& path)
{
namespace pt = boost::property_tree;
pt::ptree tree;
boost::nowide::ifstream ifs(path);
try {
pt::read_ini(ifs, tree);
}
catch (const boost::property_tree::ini_parser::ini_parser_error& err) {
throw Slic3r::RuntimeError(format("Failed loading config bundle \"%1%\"\nError: \"%2%\" at line %3%", path, err.message(), err.line()).c_str());
}
const VendorProfile* vendor_profile = nullptr;
auto vp = VendorProfile::from_ini(tree, path);
// return if not common profile
// TODO: should save tree for later load?
if (vp.name != "common" && vp.name != "common_filaments" && vp.name != "common_materials")
return 0;
PresetBundle::CommonBundleInfo tr(vp.name, vp.config_version, path);
common_bundles.emplace_back(tr);
/*
const VendorProfile* vendor_profile = &this->vendors.insert({ vp.id, vp }).first->second;
// FIXME
// Follows copied code from load_configbundle
print_ptree(tree);
// 1.5) Flatten the config bundle by applying the inheritance rules. Internal profiles (with names starting with '*') are removed.
// If loading a user config bundle, do not flatten with the system profiles, but keep the "inherits" flag intact.
flatten_configbundle_hierarchy(tree, ((flags & LOAD_CFGBNDLE_SYSTEM) == 0) ? this : nullptr);
// 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
// Parse the obsolete preset names, to be deleted when upgrading from the old configuration structure.
std::vector<std::string> loaded_prints;
std::vector<std::string> loaded_filaments;
std::vector<std::string> loaded_sla_prints;
std::vector<std::string> loaded_sla_materials;
std::vector<std::string> loaded_printers;
std::string active_print;
std::vector<std::string> active_filaments;
std::string active_sla_print;
std::string active_sla_material;
std::string active_printer;
size_t presets_loaded = 0;
for (const auto& section : tree) {
PresetCollection* presets = nullptr;
std::vector<std::string>* loaded = nullptr;
std::string preset_name;
if (boost::starts_with(section.first, "print:")) {
presets = &this->prints;
loaded = &loaded_prints;
preset_name = section.first.substr(6);
}
else if (boost::starts_with(section.first, "filament:")) {
presets = &this->filaments;
loaded = &loaded_filaments;
preset_name = section.first.substr(9);
}
else if (boost::starts_with(section.first, "sla_print:")) {
presets = &this->sla_prints;
loaded = &loaded_sla_prints;
preset_name = section.first.substr(10);
}
else if (boost::starts_with(section.first, "sla_material:")) {
presets = &this->sla_materials;
loaded = &loaded_sla_materials;
preset_name = section.first.substr(13);
}
else if (boost::starts_with(section.first, "printer:")) {
presets = &this->printers;
loaded = &loaded_printers;
preset_name = section.first.substr(8);
}
else if (section.first == "presets") {
// Load the names of the active presets.
for (auto& kvp : section.second) {
if (kvp.first == "print") {
active_print = kvp.second.data();
}
else if (boost::starts_with(kvp.first, "filament")) {
int idx = 0;
if (kvp.first == "filament" || sscanf(kvp.first.c_str(), "filament_%d", &idx) == 1) {
if (int(active_filaments.size()) <= idx)
active_filaments.resize(idx + 1, std::string());
active_filaments[idx] = kvp.second.data();
}
}
else if (kvp.first == "sla_print") {
active_sla_print = kvp.second.data();
}
else if (kvp.first == "sla_material") {
active_sla_material = kvp.second.data();
}
else if (kvp.first == "printer") {
active_printer = kvp.second.data();
}
}
}
else if (section.first == "obsolete_presets") {
// Parse the names of obsolete presets. These presets will be deleted from user's
// profile directory on installation of this vendor preset.
for (auto& kvp : section.second) {
std::vector<std::string>* dst = nullptr;
if (kvp.first == "print")
dst = &this->obsolete_presets.prints;
else if (kvp.first == "filament")
dst = &this->obsolete_presets.filaments;
else if (kvp.first == "sla_print")
dst = &this->obsolete_presets.sla_prints;
else if (kvp.first == "sla_material")
dst = &this->obsolete_presets.sla_materials;
else if (kvp.first == "printer")
dst = &this->obsolete_presets.printers;
if (dst)
unescape_strings_cstyle(kvp.second.data(), *dst);
}
}
else if (section.first == "settings") {
// Load the settings.
for (auto& kvp : section.second) {
if (kvp.first == "autocenter") {
}
}
}
else
// Ignore an unknown section.
continue;
if (presets != nullptr) {
// Load the print, filament or printer preset.
const DynamicPrintConfig* default_config = nullptr;
DynamicPrintConfig config;
std::string alias_name;
std::vector<std::string> renamed_from;
auto parse_config_section = [&section, &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;
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;
parse_config_section(config);
}
Preset::normalize(config);
// Report configuration fields, which are misplaced into a wrong group.
std::string incorrect_keys = Preset::remove_invalid_keys(config, *default_config);
if (!incorrect_keys.empty())
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
section.first << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
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 = std::find_if(vendor_profile->models.cbegin(), vendor_profile->models.cend(),
[&](const VendorProfile::PrinterModel& m) { return m.id == 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;
}
}
else if ((flags & LOAD_CFGBNDLE_SYSTEM) == 0) {
// This is a user config bundle.
const Preset* existing = presets->find_preset(preset_name, false);
if (existing != nullptr) {
if (existing->is_system) {
assert(existing->vendor != nullptr);
BOOST_LOG_TRIVIAL(error) << "Error in a user provided Config Bundle \"" << path << "\": The " << presets->name() << " preset \"" <<
existing->name << "\" is a system preset of vendor " << existing->vendor->name << " and it will be ignored.";
continue;
}
else {
assert(existing->vendor == nullptr);
BOOST_LOG_TRIVIAL(trace) << "A " << presets->name() << " preset \"" << existing->name << "\" was overwritten with a preset from user Config Bundle \"" << path << "\"";
}
}
else {
BOOST_LOG_TRIVIAL(trace) << "A new " << presets->name() << " preset \"" << preset_name << "\" was imported from user Config Bundle \"" << path << "\"";
}
}
// 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())
#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
// Store the print/filament/printer presets into a "presets" directory.
/ "presets"
#else
// Store the print/filament/printer presets at the same location as the upstream Slic3r.
#endif
/ presets->section_name() / file_name).make_preferred();
// Load the preset into the list of presets, save it to disk.
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;
}
// Derive the profile logical name aka alias from the preset name if the alias was not stated explicitely.
if (alias_name.empty()) {
size_t 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;
}
}
// 3) Activate the presets.
if ((flags & LOAD_CFGBNDLE_SYSTEM) == 0) {
if (!active_print.empty())
prints.select_preset_by_name(active_print, true);
if (!active_sla_print.empty())
sla_materials.select_preset_by_name(active_sla_print, true);
if (!active_sla_material.empty())
sla_materials.select_preset_by_name(active_sla_material, 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(PresetSelectCompatibleType::Never);
}
*/
return 1;
}
void PresetBundle::update_multi_material_filament_presets()
{
if (printers.get_edited_preset().printer_technology() != ptFFF)

View File

@ -9,16 +9,28 @@
#include <unordered_map>
#include <boost/filesystem/path.hpp>
namespace Slic3r {
// Bundle of Print + Filament + Printer presets.
class PresetBundle
{
struct CommonBundleInfo
{
std::string name;
Semver version;
//boost::property_tree::ptree tree;
std::string path;
CommonBundleInfo(const std::string& n, const Semver& v, /*boost::property_tree::ptree t,*/ const std::string& p) : name(n), version(v),/* tree(t),*/ path(p) {}
};
public:
PresetBundle();
PresetBundle(const PresetBundle &rhs);
PresetBundle& operator=(const PresetBundle &rhs);
PresetBundle(const std::vector<CommonBundleInfo> &ctr);
// Remove all the presets but the "-- default --".
// Optionally remove all the files referenced by the presets from the user profile directory.
void reset(bool delete_files);
@ -174,6 +186,11 @@ private:
DynamicPrintConfig full_fff_config() const;
DynamicPrintConfig full_sla_config() const;
// common profiles bundles
std::vector<CommonBundleInfo> common_bundles;
};
ENABLE_ENUM_BITMASK_OPERATORS(PresetBundle::LoadConfigBundleAttribute)

View File

@ -2580,6 +2580,12 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
continue;
}
if (pair.second.vendor_profile->name == "common_filaments" || pair.second.vendor_profile->name == "common_materials") {
// Always install common bundles
install_bundles.emplace_back(pair.first);
continue;
}
const auto vendor = enabled_vendors.find(pair.first);
if (vendor == enabled_vendors.end()) { continue; }

View File

@ -133,6 +133,9 @@ struct Updates
{
std::vector<Incompat> incompats;
std::vector<Update> updates;
std::vector<Semver> common_base_versions;
std::vector<Semver> common_filaments_versions;
std::vector<Semver> common_materials_versions;
};
@ -157,6 +160,8 @@ struct PresetUpdater::priv
bool has_waiting_updates { false };
Updates waiting_updates;
const std::vector<std::string> common_profile_names = { "common", "common_filaments", "common_materials" };
priv();
void set_download_prefs(AppConfig *app_config);
@ -165,11 +170,15 @@ struct PresetUpdater::priv
void sync_version() const;
void parse_version_string(const std::string& body) const;
void sync_config(const VendorMap vendors);
void sync_common_config(const VendorMap vendors, CommonProfileType type);
void update_common_index(const VendorProfile& vendor, Index& index);
void check_install_indices() const;
Updates get_config_updates(const Semver& old_slic3r_version) const;
bool perform_updates(Updates &&updates, bool snapshot = true) const;
void set_waiting_updates(Updates u);
void check_common_profiles(const std::vector<Semver>& versions, CommonProfileType type) const;
void delete_obsolete_common_profiles(CommonProfileType type) const;
};
PresetUpdater::priv::priv()
@ -423,8 +432,125 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors)
if (! get_file(bundle_url, bundle_path)) { continue; }
if (cancel) { return; }
}
sync_common_config(vendors, CommonProfileType::Base);
sync_common_config(vendors, CommonProfileType::Filaments);
sync_common_config(vendors, CommonProfileType::Materials);
}
// Download common index and ini files
void PresetUpdater::priv::sync_common_config(const VendorMap vendors, CommonProfileType type)
{
// Get common index
auto index_it = std::find_if(index_db.begin(), index_db.end(), [this, type](const Index& i) { return i.vendor() == common_profile_names[type]; });
if (index_it == index_db.end())
return;
Index& index = *index_it;
// Get all versions of common profiles that are in vendor profiles in cache.
std::vector<Semver> common_versions;
for (const auto idx : index_db) {
auto bundle_path = vendor_path / (idx.vendor() + ".ini");
if (!fs::exists(bundle_path))
continue;
const auto vp = VendorProfile::from_ini(bundle_path, false);
if (type == Base && vp.using_common_base_profile && std::find(common_versions.begin(), common_versions.end(), vp.common_base_version) == common_versions.end())
common_versions.push_back(vp.common_base_version);
else if (type == Filaments && vp.using_common_filaments_profile && std::find(common_versions.begin(), common_versions.end(), vp.common_filaments_version) == common_versions.end())
common_versions.push_back(vp.common_filaments_version);
else if (type == Materials && vp.using_common_materials_profile && std::find(common_versions.begin(), common_versions.end(), vp.common_materials_version) == common_versions.end())
common_versions.push_back(vp.common_materials_version);
}
// Get any common profil from vendors
auto it = vendors.begin();
for (; it != vendors.end(); ++it) {
if (it->second.name == common_profile_names[type])
break;
}
if (it == vendors.end())
return;
// To download index, any common profile is suitable
const VendorProfile& vendor = it->second;
// Update index if needed
update_common_index(vendor, index);
// Download all common_versions that are not in cache folder and are supported according to index
for (const auto version : common_versions) {
auto index_with_version = index.find(version);
// Skip unsupported profiles- will backfire later though
if(!(*index_with_version).is_current_slic3r_supported()) {
BOOST_LOG_TRIVIAL(error) << format("Version of common profile %1%, not supproted by this version of Slicer yet required by some vendor profile.");
continue;
}
// Skip profiles already present in vendor path
/*const auto vendor_path = rsrc_path / (vendor.name + "." + version.to_string() + ".ini");
if (fs::exists(vendor_path))
continue;
*/
const auto bundle_url = format("%1%/%2%.ini", vendor.config_update_url, version.to_string());
const auto bundle_path = cache_path / (vendor.name + "." + version.to_string() + ".ini");
BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for common config version: " << version;
// FIXME: try or if?
try {
if(!get_file(bundle_url, bundle_path))
BOOST_LOG_TRIVIAL(error) << format("Could not download common ini from %1%", bundle_url);
} catch (const std::exception& /* err */) {
}
}
}
void PresetUpdater::priv::update_common_index(const VendorProfile& vendor, Index& index)
{
// Download a fresh index
BOOST_LOG_TRIVIAL(info) << "Downloading index for common profiles";
const auto idx_url = vendor.config_update_url + "/" + INDEX_FILENAME;
const std::string idx_path = (cache_path / (vendor.name + ".idx")).string();
const std::string idx_path_temp = idx_path + "-update";
//check if idx_url is leading to our site
if (!boost::starts_with(idx_url, "http://files.prusa3d.com/wp-content/uploads/repository/")) {
BOOST_LOG_TRIVIAL(warning) << "unsafe url path for vendor \"" << vendor.name << "\" rejected: " << idx_url;
return;
}
if (!get_file(idx_url, idx_path_temp)) {
BOOST_LOG_TRIVIAL(error) << format("Could not download index for common profiles from %1%", idx_url);
return;
}
if (cancel)
return;
// Load the fresh index up
{
Index new_index;
try {
new_index.load(idx_path_temp);
}
catch (const std::exception& /* err */) {
BOOST_LOG_TRIVIAL(error) << format("Could not load downloaded index %1% for common profiles: invalid index?", idx_path_temp);
return;
}
if (new_index.version() < index.version()) {
BOOST_LOG_TRIVIAL(warning) << format("The downloaded index %1% for common profiles is older than the active one. Ignoring the downloaded index.", idx_path_temp, vendor.name);
return;
}
Slic3r::rename_file(idx_path_temp, idx_path);
try {
index.load(idx_path);
}
catch (const std::exception& /* err */) {
BOOST_LOG_TRIVIAL(error) << format("Could not load downloaded index %1% for common profiles: invalid index?", idx_path, vendor.name);
return;
}
}
}
// Install indicies from resources. Only installs those that are either missing or older than in resources.
void PresetUpdater::priv::check_install_indices() const
{
@ -465,6 +591,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
auto bundle_path = vendor_path / (idx.vendor() + ".ini");
auto bundle_path_idx = vendor_path / idx.path().filename();
if (! fs::exists(bundle_path)) {
BOOST_LOG_TRIVIAL(info) << format("Confing bundle not installed for vendor %1%, skipping: ", idx.vendor());
continue;
@ -518,6 +645,13 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
if (recommended->config_version == vp.config_version) {
// The recommended config bundle is already installed.
// Add common config version
if (vp.using_common_base_profile && std::find(updates.common_base_versions.begin(), updates.common_base_versions.end(), vp.common_base_version) == updates.common_base_versions.end())
updates.common_base_versions.push_back(vp.common_base_version);
if (vp.using_common_filaments_profile && std::find(updates.common_filaments_versions.begin(), updates.common_filaments_versions.end(), vp.common_filaments_version) == updates.common_filaments_versions.end())
updates.common_filaments_versions.push_back(vp.common_filaments_version);
if (vp.using_common_materials_profile && std::find(updates.common_materials_versions.begin(), updates.common_materials_versions.end(), vp.common_materials_version) == updates.common_materials_versions.end())
updates.common_materials_versions.push_back(vp.common_materials_version);
continue;
}
@ -533,8 +667,12 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
// Config bundle inside the cache directory.
fs::path path_in_cache = cache_path / (idx.vendor() + ".ini");
if (idx.vendor() == common_profile_names[CommonProfileType::Filaments] || idx.vendor() == common_profile_names[CommonProfileType::Materials])
path_in_cache = cache_path / (idx.vendor() + "." + (*idx.recommended()).config_version.to_string() + ".ini");
// Config bundle inside the resources directory.
fs::path path_in_rsrc = rsrc_path / (idx.vendor() + ".ini");
if (idx.vendor() == common_profile_names[CommonProfileType::Filaments] || idx.vendor() == common_profile_names[CommonProfileType::Materials])
path_in_rsrc = rsrc_path / (idx.vendor() + "." + (*idx.recommended()).config_version.to_string() + ".ini");
// Config index inside the resources directory.
fs::path path_idx_in_rsrc = rsrc_path / (idx.vendor() + ".idx");
@ -551,6 +689,13 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
new_update = Update(std::move(path_in_cache), std::move(bundle_path), *recommended, vp.name, vp.changelog_url, current_not_supported);
// and install the config index from the cache into vendor's directory.
bundle_path_idx_to_install = idx.path();
// store common config version needed for current profile (until update is performed)
if (vp.using_common_base_profile && std::find(updates.common_base_versions.begin(), updates.common_base_versions.end(), vp.common_base_version) == updates.common_base_versions.end())
updates.common_base_versions.push_back(vp.common_base_version);
if (vp.using_common_filaments_profile && std::find(updates.common_filaments_versions.begin(), updates.common_filaments_versions.end(), vp.common_filaments_version) == updates.common_filaments_versions.end())
updates.common_filaments_versions.push_back(vp.common_filaments_version);
if (vp.using_common_materials_profile && std::find(updates.common_materials_versions.begin(), updates.common_materials_versions.end(), vp.common_materials_version) == updates.common_materials_versions.end())
updates.common_materials_versions.push_back(vp.common_materials_version);
found = true;
}
} catch (const std::exception &ex) {
@ -579,7 +724,14 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
recommended = rsrc_idx.recommended();
if (recommended != rsrc_idx.end() && recommended->config_version == rsrc_vp.config_version && recommended->config_version > vp.config_version) {
new_update = Update(std::move(path_in_rsrc), std::move(bundle_path), *recommended, vp.name, vp.changelog_url, current_not_supported);
bundle_path_idx_to_install = path_idx_in_rsrc;
bundle_path_idx_to_install = path_idx_in_rsrc;
// store common config version needed for current profile (until update is performed)
if (vp.using_common_base_profile && std::find(updates.common_base_versions.begin(), updates.common_base_versions.end(), vp.common_base_version) == updates.common_base_versions.end())
updates.common_base_versions.push_back(vp.common_base_version);
if (vp.using_common_filaments_profile && std::find(updates.common_filaments_versions.begin(), updates.common_filaments_versions.end(), vp.common_filaments_version) == updates.common_filaments_versions.end())
updates.common_filaments_versions.push_back(vp.common_filaments_version);
if (vp.using_common_materials_profile && std::find(updates.common_materials_versions.begin(), updates.common_materials_versions.end(), vp.common_materials_version) == updates.common_materials_versions.end())
updates.common_materials_versions.push_back(vp.common_materials_version);
found = true;
} else {
BOOST_LOG_TRIVIAL(warning) << format("The recommended config version for vendor `%1%` in resources does not match the recommended\n"
@ -674,6 +826,17 @@ bool PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
// Throw when parsing invalid configuration. Only valid configuration is supposed to be provided over the air.
bundle.load_configbundle(update.source.string(), PresetBundle::LoadConfigBundleAttribute::LoadSystem, ForwardCompatibilitySubstitutionRule::Disable);
// Add version of common profile to common versions
if(!bundle.vendors.empty() && (*bundle.vendors.begin()).second.using_common_base_profile &&
std::find(updates.common_base_versions.begin(), updates.common_base_versions.end(), (*bundle.vendors.begin()).second.common_base_version) == updates.common_base_versions.end())
updates.common_base_versions.push_back((*bundle.vendors.begin()).second.common_base_version);
if (!bundle.vendors.empty() && (*bundle.vendors.begin()).second.using_common_filaments_profile &&
std::find(updates.common_filaments_versions.begin(), updates.common_filaments_versions.end(), (*bundle.vendors.begin()).second.common_filaments_version) == updates.common_filaments_versions.end())
updates.common_filaments_versions.push_back((*bundle.vendors.begin()).second.common_filaments_version);
if (!bundle.vendors.empty() && (*bundle.vendors.begin()).second.using_common_materials_profile &&
std::find(updates.common_materials_versions.begin(), updates.common_materials_versions.end(), (*bundle.vendors.begin()).second.common_materials_version) == updates.common_materials_versions.end())
updates.common_materials_versions.push_back((*bundle.vendors.begin()).second.common_materials_version);
BOOST_LOG_TRIVIAL(info) << format("Deleting %1% conflicting presets", bundle.prints.size() + bundle.filaments.size() + bundle.printers.size());
auto preset_remover = [](const Preset &preset) {
@ -708,12 +871,113 @@ bool PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
return true;
}
void PresetUpdater::priv::set_waiting_updates(Updates u)
void PresetUpdater::priv::set_waiting_updates(Updates u)
{
waiting_updates = u;
has_waiting_updates = true;
}
void PresetUpdater::priv::check_common_profiles(const std::vector<Semver>& versions, CommonProfileType type) const
{
if (versions.empty())
return;
Index common_idx;
//find idx
bool idx_found = false;
for (const auto idx : index_db) {
if (idx.vendor() == common_profile_names[type])
{
idx_found = true;
common_idx = idx;
break;
}
}
if (!idx_found) {
BOOST_LOG_TRIVIAL(error) << "Common idx not found!";
return;
}
for (const auto& version : versions) {
BOOST_LOG_TRIVIAL(error) << "Version of common profile needed: " << version;
auto index_with_version = common_idx.find(version);
// check if compatible with slicer version
// FIXME: How do we want to have this signaled??
assert((*index_with_version).is_current_slic3r_supported());
/*
if (!(*index_with_version).is_current_slic3r_supported())
{
// if not compatible with slicer version -> logic error -> explode
BOOST_LOG_TRIVIAL(error) << "aszdglkjinbsdrflgijkbnaserljkihgnbseuriojhngblseurt";
}
*/
// find if version is present at vendor folder
const fs::path path_in_vendor = vendor_path / (common_profile_names[type]+ "." + version.to_string() + ".ini");
if (!fs::exists(path_in_vendor)) {
// if not at vendor folder - find it
BOOST_LOG_TRIVIAL(error) << "Common profile not present: " << version;
// Update from rsrc
fs::path path_in_rsrc = rsrc_path / (common_profile_names[type] + "." + version.to_string() + ".ini");
fs::path path_target = vendor_path / (common_profile_names[type] + "." + version.to_string() + ".ini");
//assert(fs::exists(path_in_rsrc));
if(!fs::exists(path_in_rsrc)){
continue;
}
Update update(std::move(path_in_rsrc), std::move(path_target), *index_with_version, common_profile_names[type], "", true);
// install
update.install();
PresetBundle bundle;
bundle.load_configbundle(update.source.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
}
}
delete_obsolete_common_profiles(type);
}
void PresetUpdater::priv::delete_obsolete_common_profiles(CommonProfileType type) const
{
// Get all versions needed by ini files in vendor folder
// There might be no need for this cycle if we are sure we get all versions from Updates
std::vector<Semver> current_versions;
for (const auto idx : index_db) {
auto bundle_path = vendor_path / (idx.vendor() + ".ini");
if (!fs::exists(bundle_path))
continue;
auto vp = VendorProfile::from_ini(bundle_path, false);
// If idx is common profile - keep current version
if (idx.vendor() == common_profile_names[type] && std::find(current_versions.begin(), current_versions.end(), vp.config_version) == current_versions.end())
current_versions.push_back(vp.config_version);
// Else find if common profile is needed
else if (type == CommonProfileType::Base && vp.using_common_base_profile && std::find(current_versions.begin(), current_versions.end(), vp.common_base_version) == current_versions.end())
current_versions.push_back(vp.common_base_version);
else if (type == CommonProfileType::Filaments && vp.using_common_filaments_profile && std::find(current_versions.begin(), current_versions.end(), vp.common_filaments_version) == current_versions.end())
current_versions.push_back(vp.common_filaments_version);
else if (type == CommonProfileType::Materials && vp.using_common_materials_profile && std::find(current_versions.begin(), current_versions.end(), vp.common_materials_version) == current_versions.end())
current_versions.push_back(vp.common_materials_version);
}
// List all common profiles of type and delete those with wrong version
std::string errors_cummulative;
for (auto& dir_entry : boost::filesystem::directory_iterator(vendor_path)) {
// Filter .ini files of type
std::string filename = dir_entry.path().filename().string();
if (filename.compare(filename.size() - 4, 4, ".ini") != 0)
continue;
if (filename.compare(0,common_profile_names[type].size() + 1, common_profile_names[type] + ".") != 0)
continue;
auto vp = VendorProfile::from_ini(dir_entry, false);
if (std::find(current_versions.begin(), current_versions.end(), vp.config_version) == current_versions.end())
{
fs::remove(dir_entry);
}
}
}
PresetUpdater::PresetUpdater() :
p(new priv())
{}
@ -908,7 +1172,9 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3
} else {
BOOST_LOG_TRIVIAL(info) << "No configuration updates available.";
}
p->check_common_profiles(updates.common_base_versions, CommonProfileType::Base);
p->check_common_profiles(updates.common_filaments_versions, CommonProfileType::Filaments);
p->check_common_profiles(updates.common_materials_versions, CommonProfileType::Materials);
return R_NOOP;
}
@ -919,9 +1185,18 @@ bool PresetUpdater::install_bundles_rsrc(std::vector<std::string> bundles, bool
BOOST_LOG_TRIVIAL(info) << format("Installing %1% bundles from resources ...", bundles.size());
for (const auto &bundle : bundles) {
auto path_in_rsrc = (p->rsrc_path / bundle).replace_extension(".ini");
auto path_in_vendors = (p->vendor_path / bundle).replace_extension(".ini");
updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", "");
if(bundle.compare(0, p->common_profile_names[CommonProfileType::Filaments].length(), p->common_profile_names[CommonProfileType::Filaments]) == 0||
bundle.compare(0, p->common_profile_names[CommonProfileType::Materials].length(), p->common_profile_names[CommonProfileType::Materials]) == 0) {
auto path_in_rsrc = p->rsrc_path / (bundle + ".ini");
// without version offset
auto path_in_vendors = p->vendor_path / (bundle.substr(0,bundle.find_first_of('.')) + ".ini");
updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", "");
} else {
auto path_in_rsrc = (p->rsrc_path / bundle).replace_extension(".ini");
auto path_in_vendors = (p->vendor_path / bundle).replace_extension(".ini");
updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", "");
}
}
return p->perform_updates(std::move(updates), snapshot);
@ -959,4 +1234,6 @@ bool PresetUpdater::version_check_enabled() const
return p->enabled_version_check;
}
}