Feature/enhance profile validator (#4278)

* check more profile issues

* 1

* update ci/cd

* update name
This commit is contained in:
SoftFever 2024-03-01 21:27:12 +08:00 committed by GitHub
parent 01b0c87471
commit 2b6937acbe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 223 additions and 49 deletions

View file

@ -244,7 +244,16 @@ jobs:
./BuildLinux.sh -isr ./BuildLinux.sh -isr
mv -n ./build/OrcaSlicer_Linux_V${{ env.ver_pure }}.AppImage ./build/OrcaSlicer_Linux_${{ env.ver }}.AppImage mv -n ./build/OrcaSlicer_Linux_V${{ env.ver_pure }}.AppImage ./build/OrcaSlicer_Linux_${{ env.ver }}.AppImage
chmod +x ./build/OrcaSlicer_Linux_${{ env.ver }}.AppImage chmod +x ./build/OrcaSlicer_Linux_${{ env.ver }}.AppImage
- name: Build orca_custom_preset_tests
if: github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-20.04'
working-directory: ${{ github.workspace }}/build/src
shell: bash
run: |
OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -g 1
cd ${{ github.workspace }}/resources/profiles
zip -r orca_custom_preset_tests.zip user/
- name: Upload artifacts Ubuntu - name: Upload artifacts Ubuntu
if: inputs.os == 'ubuntu-20.04' if: inputs.os == 'ubuntu-20.04'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
@ -262,3 +271,14 @@ jobs:
asset_name: OrcaSlicer_Linux_${{ env.ver }}.AppImage asset_name: OrcaSlicer_Linux_${{ env.ver }}.AppImage
asset_content_type: application/octet-stream asset_content_type: application/octet-stream
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
- name: Deploy orca_custom_preset_tests
if: github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-20.04'
uses: WebFreak001/deploy-nightly@v3.0.0
with:
upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ${{ github.workspace }}/resources/profiles/orca_custom_preset_tests.zip
asset_name: orca_custom_preset_tests
asset_content_type: application/octet-stream
max_releases: 1

View file

@ -1,4 +1,4 @@
name: Check locale name: Check profiles
on: on:
pull_request: pull_request:
branches: branches:
@ -19,12 +19,21 @@ jobs:
- name: Download - name: Download
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
run: | run: |
curl -LJO https://github.com/SoftFever/Orca_tools/releases/download/1/OrcaSlicer_profile_validator_ubuntu curl -LJO https://github.com/SoftFever/Orca_tools/releases/download/1/OrcaSlicer_profile_validator
chmod +x ./OrcaSlicer_profile_validator_ubuntu chmod +x ./OrcaSlicer_profile_validator
# validate profiles # validate profiles
- name: validate profiles - name: validate system profiles
run: | run: |
./OrcaSlicer_profile_validator_ubuntu -p ${{ github.workspace }}/resources/profiles -l 2 ./OrcaSlicer_profile_validator_ubuntu -p ${{ github.workspace }}/resources/profiles -l 2
- name: validate custom presets
working-directory: ${{ github.workspace }}
run: |
curl -LJO https://github.com/SoftFever/OrcaSlicer/releases/download/nightly-builds/orca_custom_preset_tests.zip
unzip ./orca_custom_preset_tests.zip -d ${{ github.workspace }}/resources/profiles
./OrcaSlicer_profile_validator_ubuntu -p ${{ github.workspace }}/resources/profiles -l 2

1
.gitignore vendored
View file

@ -32,3 +32,4 @@ src/OrcaSlicer-doc/
**/filament_full/ **/filament_full/
/deps/DL_CACHE/ /deps/DL_CACHE/
/deps/DL_CACHE /deps/DL_CACHE
resources/profiles/user/default

View file

@ -227,13 +227,16 @@ then
# cmake # cmake
pushd build pushd build
echo -e "cmake .. -DCMAKE_PREFIX_PATH=\"$PWD/../deps/build/destdir/usr/local\" -DSLIC3R_STATIC=1 ${BUILD_ARGS}" echo -e "cmake .. -DCMAKE_PREFIX_PATH=\"$PWD/../deps/build/destdir/usr/local\" -DSLIC3R_STATIC=1 -DORCA_TOOLS=ON ${BUILD_ARGS}"
cmake .. -DCMAKE_PREFIX_PATH="$PWD/../deps/build/destdir/usr/local" -DSLIC3R_STATIC=1 ${BUILD_ARGS} cmake .. -DCMAKE_PREFIX_PATH="$PWD/../deps/build/destdir/usr/local" -DSLIC3R_STATIC=1 ${BUILD_ARGS} -DORCA_TOOLS=ON
echo "done" echo "done"
# make Slic3r # make Slic3r
echo "[8/9] Building Slic3r..." echo "[8/9] Building Slic3r..."
make -j$NCORES OrcaSlicer # Slic3r make -j$NCORES OrcaSlicer # Slic3r
# make OrcaSlicer_profile_validator
make -j$NCORES OrcaSlicer_profile_validator
popd popd
./run_gettext.sh ./run_gettext.sh
echo "done" echo "done"

View file

@ -116,8 +116,6 @@
"deretraction_speed": [ "deretraction_speed": [
"40" "40"
], ],
"bridge_speed": "25",
"internal_bridge_speed" : "70",
"silent_mode": "0", "silent_mode": "0",
"single_extruder_multi_material": "1", "single_extruder_multi_material": "1",
"change_filament_gcode": "", "change_filament_gcode": "",

View file

@ -1,5 +1,4 @@
{ {
"bbl_calib_mark_logo": "1",
"setting_id": "GM003", "setting_id": "GM003",
"name": "Kingroon KP3S PRO S1 0.4 nozzle", "name": "Kingroon KP3S PRO S1 0.4 nozzle",
"instantiation": "true", "instantiation": "true",

View file

@ -1,6 +1,5 @@
{ {
"type": "machine", "type": "machine",
"bbl_calib_mark_logo": "1",
"name": "fdm_machine_common", "name": "fdm_machine_common",
"auxiliary_fan": "0", "auxiliary_fan": "0",
"fan_kickstart": "0", "fan_kickstart": "0",

View file

@ -11,7 +11,6 @@
"auxiliary_fan": "0", "auxiliary_fan": "0",
"remaining_times": "1", "remaining_times": "1",
"single_extruder_multi_material": "0", "single_extruder_multi_material": "0",
"single_extruder_multi_material_priming": "0",
"purge_in_prime_tower": "0", "purge_in_prime_tower": "0",
"enable_filament_ramming": "0", "enable_filament_ramming": "0",
"nozzle_volume": "0", "nozzle_volume": "0",

View file

@ -1,22 +1,93 @@
#include "libslic3r/Preset.hpp"
#include "libslic3r/Config.hpp"
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include "libslic3r/Print.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <iostream> #include <iostream>
#include <string>
using namespace Slic3r; using namespace Slic3r;
namespace po = boost::program_options; namespace po = boost::program_options;
void generate_custom_presets(PresetBundle* preset_bundle, AppConfig& app_config)
{
struct cus_preset
{
std::string name;
std::string parent_name;
};
// create user presets
auto createCustomPrinters = [&](Preset::Type type) {
std::vector<cus_preset> custom_preset;
PresetCollection* collection = nullptr;
if (type == Preset::TYPE_PRINT)
collection = &preset_bundle->prints;
else if (type == Preset::TYPE_FILAMENT)
collection = &preset_bundle->filaments;
else if (type == Preset::TYPE_PRINTER)
collection = &preset_bundle->printers;
else
return;
custom_preset.reserve(collection->size());
for (auto& parent : collection->get_presets()) {
if (!parent.is_system)
continue;
auto new_name = parent.name + "_orca_test";
if (parent.vendor)
new_name = parent.vendor->name + "_" + new_name;
custom_preset.push_back({new_name, parent.name});
}
for (auto p : custom_preset) {
// Creating a new preset.
auto parent = collection->find_preset(p.parent_name);
if (type == Preset::TYPE_FILAMENT)
parent->config.set_key_value("filament_start_gcode",
new ConfigOptionStrings({"this_is_orca_test_filament_start_gcode_mock"}));
else if (type == Preset::TYPE_PRINT)
parent->config.set_key_value("filename_format", new ConfigOptionString("this_is_orca_test_filename_format_mock"));
else if (type == Preset::TYPE_PRINTER)
parent->config.set_key_value("machine_start_gcode",
new ConfigOptionString("this_is_orca_test_machine_start_gcode_mock"));
collection->save_current_preset(p.name, false, false, parent);
}
};
createCustomPrinters(Preset::TYPE_PRINTER);
createCustomPrinters(Preset::TYPE_FILAMENT);
createCustomPrinters(Preset::TYPE_PRINT);
std::string user_sub_folder = DEFAULT_USER_FOLDER_NAME;
const std::string dir_user_presets = data_dir() + "/" + PRESET_USER_DIR + "/" + user_sub_folder;
fs::path user_folder(data_dir() + "/" + PRESET_USER_DIR);
if (!fs::exists(user_folder))
fs::create_directory(user_folder);
fs::path folder(dir_user_presets);
if (!fs::exists(folder))
fs::create_directory(folder);
std::vector<std::string> need_to_delete_list; // store setting ids of preset
preset_bundle->prints.save_user_presets(dir_user_presets, PRESET_PRINT_NAME, need_to_delete_list);
preset_bundle->filaments.save_user_presets(dir_user_presets, PRESET_FILAMENT_NAME, need_to_delete_list);
preset_bundle->printers.save_user_presets(dir_user_presets, PRESET_PRINTER_NAME, need_to_delete_list);
std::cout << "Custom presets generated successfully" << std::endl;
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
po::options_description desc("Allowed options"); po::options_description desc("Orca Profile Validator\nUsage");
// clang-format off
desc.add_options()("help,h", "help") desc.add_options()("help,h", "help")
("path,p", po::value<std::string>()->default_value("../../../resources/profiles"), "profile folder") ("path,p", po::value<std::string>()->default_value("../../../resources/profiles"), "profile folder")
("vendor,v", po::value<std::string>()->default_value(""), ("vendor,v", po::value<std::string>()->default_value(""), "Vendor name. Optional, all profiles present in the folder will be validated if not specified")
"Vendor name. Optional, all profiles present in the folder will be validated if not specified") ("generate_presets,g", po::value<bool>()->default_value(false), "Generate user presets for mock test")
("log_level,l", po::value<int>()->default_value(2), ("log_level,l", po::value<int>()->default_value(2), "Log level. Optional, default is 2 (warning). Higher values produce more detailed logs.");
"Log level. Optional, default is 2 (warning). Higher values produce more detailed logs."); // clang-format on
po::variables_map vm; po::variables_map vm;
try { try {
@ -34,9 +105,10 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
std::string path = vm["path"].as<std::string>(); std::string path = vm["path"].as<std::string>();
std::string vendor = vm["vendor"].as<std::string>(); std::string vendor = vm["vendor"].as<std::string>();
int log_level = vm["log_level"].as<int>(); int log_level = vm["log_level"].as<int>();
bool generate_user_preset = vm["generate_presets"].as<bool>();
// check if path is valid, and return error if not // check if path is valid, and return error if not
if (!fs::exists(path) || !fs::is_directory(path)) { if (!fs::exists(path) || !fs::is_directory(path)) {
@ -44,20 +116,29 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
// std::cout<<"path: "<<path<<std::endl; // std::cout<<"path: "<<path<<std::endl;
// std::cout<<"vendor: "<<vendor<<std::endl; // std::cout<<"vendor: "<<vendor<<std::endl;
// std::cout<<"log_level: "<<log_level<<std::endl; // std::cout<<"log_level: "<<log_level<<std::endl;
set_data_dir(path); set_data_dir(path);
auto user_dir = fs::path(Slic3r::data_dir()) / PRESET_USER_DIR;
user_dir.make_preferred();
if (!fs::exists(user_dir))
fs::create_directory(user_dir);
set_logging_level(log_level); set_logging_level(log_level);
auto preset_bundle = new PresetBundle(); auto preset_bundle = new PresetBundle();
preset_bundle->setup_directories(); // preset_bundle->setup_directories();
preset_bundle->set_is_validation_mode(true); preset_bundle->set_is_validation_mode(true);
preset_bundle->set_vendor_to_validate(vendor); preset_bundle->set_vendor_to_validate(vendor);
preset_bundle->set_default_suppressed(true); preset_bundle->set_default_suppressed(true);
AppConfig app_config; AppConfig app_config;
app_config.set("preset_folder", "default");
if(generate_user_preset)
preset_bundle->remove_user_presets_directory("default");
try { try {
auto preset_substitutions = preset_bundle->load_presets(app_config, ForwardCompatibilitySubstitutionRule::EnableSystemSilent); auto preset_substitutions = preset_bundle->load_presets(app_config, ForwardCompatibilitySubstitutionRule::EnableSystemSilent);
@ -66,6 +147,17 @@ int main(int argc, char* argv[])
std::cout << "Validation failed" << std::endl; std::cout << "Validation failed" << std::endl;
return 1; return 1;
} }
if (generate_user_preset) {
generate_custom_presets(preset_bundle, app_config);
return 0;
}
if (preset_bundle->has_errors()) {
std::cout << "Validation failed" << std::endl;
return 1;
}
std::cout << "Validation completed successfully" << std::endl; std::cout << "Validation completed successfully" << std::endl;
return 0; return 0;
} }

View file

@ -1122,6 +1122,7 @@ void PresetCollection::load_presets(
if (fs::exists(file_path)) if (fs::exists(file_path))
fs::remove(file_path); fs::remove(file_path);
BOOST_LOG_TRIVIAL(error) << boost::format("parse config %1% failed")%preset.file; BOOST_LOG_TRIVIAL(error) << boost::format("parse config %1% failed")%preset.file;
++m_errors;
continue; continue;
} }
@ -1159,6 +1160,7 @@ void PresetCollection::load_presets(
auto inherits_config2 = dynamic_cast<ConfigOptionString *>(inherits_config); auto inherits_config2 = dynamic_cast<ConfigOptionString *>(inherits_config);
if ((inherits_config2 && !inherits_config2->value.empty()) && !preset.is_custom_defined()) { if ((inherits_config2 && !inherits_config2->value.empty()) && !preset.is_custom_defined()) {
BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file; BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file;
++m_errors;
continue; continue;
} }
// Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field. // Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field.
@ -1169,9 +1171,12 @@ void PresetCollection::load_presets(
Preset::normalize(preset.config); Preset::normalize(preset.config);
// Report configuration fields, which are misplaced into a wrong group. // Report configuration fields, which are misplaced into a wrong group.
std::string incorrect_keys = Preset::remove_invalid_keys(preset.config, default_preset.config); std::string incorrect_keys = Preset::remove_invalid_keys(preset.config, default_preset.config);
if (!incorrect_keys.empty()) if (!incorrect_keys.empty()) {
BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << ++m_errors;
preset.file << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed"; BOOST_LOG_TRIVIAL(error)
<< "Error in a preset file: The preset \"" << preset.file
<< "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
}
preset.loaded = true; preset.loaded = true;
//BBS: add some workaround for previous incorrect settings //BBS: add some workaround for previous incorrect settings
if ((!preset.setting_id.empty())&&(preset.setting_id == preset.base_id)) if ((!preset.setting_id.empty())&&(preset.setting_id == preset.base_id))
@ -1179,6 +1184,7 @@ void PresetCollection::load_presets(
//BBS: add config related logs //BBS: add config related logs
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(", preset type %1%, name %2%, path %3%, is_system %4%, is_default %5% is_visible %6%")%Preset::get_type_string(m_type) %preset.name %preset.file %preset.is_system %preset.is_default %preset.is_visible; BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(", preset type %1%, name %2%, path %3%, is_system %4%, is_default %5% is_visible %6%")%Preset::get_type_string(m_type) %preset.name %preset.file %preset.is_system %preset.is_default %preset.is_visible;
} catch (const std::ifstream::failure &err) { } catch (const std::ifstream::failure &err) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << boost::format("The user-config cannot be loaded: %1%. Reason: %2%")%preset.file %err.what(); BOOST_LOG_TRIVIAL(error) << boost::format("The user-config cannot be loaded: %1%. Reason: %2%")%preset.file %err.what();
fs::path file_path(preset.file); fs::path file_path(preset.file);
if (fs::exists(file_path)) if (fs::exists(file_path))
@ -1188,6 +1194,7 @@ void PresetCollection::load_presets(
fs::remove(file_path); fs::remove(file_path);
//throw Slic3r::RuntimeError(std::string("The selected preset cannot be loaded: ") + preset.file + "\n\tReason: " + err.what()); //throw Slic3r::RuntimeError(std::string("The selected preset cannot be loaded: ") + preset.file + "\n\tReason: " + err.what());
} catch (const std::runtime_error &err) { } catch (const std::runtime_error &err) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << boost::format("Failed loading the user-config file: %1%. Reason: %2%")%preset.file %err.what(); BOOST_LOG_TRIVIAL(error) << boost::format("Failed loading the user-config file: %1%. Reason: %2%")%preset.file %err.what();
//throw Slic3r::RuntimeError(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what()); //throw Slic3r::RuntimeError(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what());
fs::path file_path(preset.file); fs::path file_path(preset.file);
@ -1252,6 +1259,7 @@ int PresetCollection::get_differed_values_to_update(Preset& preset, std::map<std
{ {
if (preset.is_system || preset.is_default || preset.is_project_embedded) { if (preset.is_system || preset.is_default || preset.is_project_embedded) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" Error: not a user preset! Should not happen, name %1%") %preset.name; BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" Error: not a user preset! Should not happen, name %1%") %preset.name;
++m_errors;
return -1; return -1;
} }
@ -1351,9 +1359,11 @@ void PresetCollection::load_project_embedded_presets(std::vector<Preset*>& proje
Preset::normalize(preset->config); Preset::normalize(preset->config);
// Report configuration fields, which are misplaced into a wrong group. // Report configuration fields, which are misplaced into a wrong group.
std::string incorrect_keys = Preset::remove_invalid_keys(preset->config, default_preset.config); std::string incorrect_keys = Preset::remove_invalid_keys(preset->config, default_preset.config);
if (! incorrect_keys.empty()) if (!incorrect_keys.empty()) {
BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << ++m_errors;
preset->name << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed"; BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << preset->name
<< "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
}
preset->loaded = true; preset->loaded = true;
presets_loaded.emplace_back(*preset); presets_loaded.emplace_back(*preset);
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(", %1% got preset, name %2%, path %3%, is_system %4%, is_default %5% is_visible %6%")%Preset::get_type_string(m_type) %preset->name %preset->file %preset->is_system %preset->is_default %preset->is_visible; BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(", %1% got preset, name %2%, path %3%, is_system %4%, is_default %5% is_visible %6%")%Preset::get_type_string(m_type) %preset->name %preset->file %preset->is_system %preset->is_default %preset->is_visible;
@ -1533,6 +1543,7 @@ void PresetCollection::save_user_presets(const std::string& dir_path, const std:
} }
Preset* parent_preset = this->find_preset(inherits, false, true); Preset* parent_preset = this->find_preset(inherits, false, true);
if (!parent_preset) { if (!parent_preset) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find parent preset for %1% , inherits %2%")%preset->name %inherits; BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find parent preset for %1% , inherits %2%")%preset->name %inherits;
continue; continue;
} }
@ -1680,9 +1691,11 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
Preset::normalize(new_config); Preset::normalize(new_config);
// Report configuration fields, which are misplaced into a wrong group. // Report configuration fields, which are misplaced into a wrong group.
std::string incorrect_keys = Preset::remove_invalid_keys(new_config, default_preset.config); std::string incorrect_keys = Preset::remove_invalid_keys(new_config, default_preset.config);
if (! incorrect_keys.empty()) if (!incorrect_keys.empty()) {
BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << ++m_errors;
name << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed"; BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << name
<< "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
}
if (need_update) { if (need_update) {
if (iter->name == m_edited_preset.name && iter->is_dirty) { if (iter->name == m_edited_preset.name && iter->is_dirty) {
// Keep modifies when update from remote // Keep modifies when update from remote
@ -2800,9 +2813,13 @@ void PresetCollection::update_map_system_profile_renamed()
for (Preset &preset : m_presets) for (Preset &preset : m_presets)
for (const std::string &renamed_from : preset.renamed_from) { for (const std::string &renamed_from : preset.renamed_from) {
const auto [it, success] = m_map_system_profile_renamed.insert(std::pair<std::string, std::string>(renamed_from, preset.name)); const auto [it, success] = m_map_system_profile_renamed.insert(std::pair<std::string, std::string>(renamed_from, preset.name));
if (! success) if (!success) {
BOOST_LOG_TRIVIAL(error) << boost::format("Preset name \"%1%\" was marked as renamed from \"%2%\", though preset name \"%3%\" was marked as renamed from \"%2%\" as well.") % preset.name % renamed_from % it->second; ++m_errors;
} BOOST_LOG_TRIVIAL(error) << boost::format("Preset name \"%1%\" was marked as renamed from \"%2%\", though preset name "
"\"%3%\" was marked as renamed from \"%2%\" as well.") %
preset.name % renamed_from % it->second;
}
}
} }
std::string PresetCollection::name() const std::string PresetCollection::name() const

View file

@ -770,6 +770,9 @@ private:
//BBS: mutex //BBS: mutex
std::mutex m_mutex; std::mutex m_mutex;
// Orca: used for validation only
int m_errors = 0;
}; };
// Printer supports the FFF and SLA technologies, with different set of configuration values, // Printer supports the FFF and SLA technologies, with different set of configuration values,

View file

@ -831,17 +831,21 @@ bool PresetBundle::import_json_presets(PresetsConfigSubstitutions & s
// Report configuration fields, which are misplaced into a wrong group. // Report configuration fields, which are misplaced into a wrong group.
const Preset &default_preset = collection->default_preset_for(new_config); const Preset &default_preset = collection->default_preset_for(new_config);
std::string incorrect_keys = Preset::remove_invalid_keys(preset.config, default_preset.config); std::string incorrect_keys = Preset::remove_invalid_keys(preset.config, default_preset.config);
if (!incorrect_keys.empty()) if (!incorrect_keys.empty()) {
BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << preset.file << "\" contains the following incorrect keys: " << incorrect_keys ++m_errors;
<< ", which were removed"; BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << preset.file
<< "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
}
if (!config_substitutions.empty()) if (!config_substitutions.empty())
substitutions.push_back({name, collection->type(), PresetConfigSubstitutions::Source::UserFile, file, std::move(config_substitutions)}); substitutions.push_back({name, collection->type(), PresetConfigSubstitutions::Source::UserFile, file, std::move(config_substitutions)});
preset.save(inherit_preset ? &inherit_preset->config : nullptr); preset.save(inherit_preset ? &inherit_preset->config : nullptr);
result.push_back(file); result.push_back(file);
} catch (const std::ifstream::failure &err) { } catch (const std::ifstream::failure &err) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << boost::format("The config cannot be loaded: %1%. Reason: %2%") % file % err.what(); BOOST_LOG_TRIVIAL(error) << boost::format("The config cannot be loaded: %1%. Reason: %2%") % file % err.what();
} catch (const std::runtime_error &err) { } catch (const std::runtime_error &err) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << boost::format("Failed importing config file: %1%. Reason: %2%") % file % err.what(); BOOST_LOG_TRIVIAL(error) << boost::format("Failed importing config file: %1%. Reason: %2%") % file % err.what();
} }
return true; return true;
@ -945,6 +949,7 @@ void PresetBundle::update_system_preset_setting_ids(std::map<std::string, std::m
Preset* preset = preset_collection->find_preset(name, false, true); Preset* preset = preset_collection->find_preset(name, false, true);
if (preset) { if (preset) {
if (!preset->setting_id.empty() && (preset->setting_id.compare(setting_id) != 0)) { if (!preset->setting_id.empty() && (preset->setting_id.compare(setting_id) != 0)) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << boost::format("name %1%, local setting_id %2% is different with remote id %3%") BOOST_LOG_TRIVIAL(error) << boost::format("name %1%, local setting_id %2% is different with remote id %3%")
%preset->name %preset->setting_id %setting_id; %preset->name %preset->setting_id %setting_id;
} }
@ -3156,7 +3161,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
std::vector<std::pair<std::string, std::string>> process_subfiles; std::vector<std::pair<std::string, std::string>> process_subfiles;
std::vector<std::pair<std::string, std::string>> filament_subfiles; std::vector<std::pair<std::string, std::string>> filament_subfiles;
std::vector<std::pair<std::string, std::string>> machine_subfiles; std::vector<std::pair<std::string, std::string>> machine_subfiles;
auto get_name_and_subpath = [](json::iterator& it, std::vector<std::pair<std::string, std::string>>& subfile_map) { auto get_name_and_subpath = [this](json::iterator& it, std::vector<std::pair<std::string, std::string>>& subfile_map) {
if (it.value().is_array()) { if (it.value().is_array()) {
for (auto iter1 = it.value().begin(); iter1 != it.value().end(); iter1++) { for (auto iter1 = it.value().begin(); iter1 != it.value().end(); iter1++) {
if (iter1.value().is_object()) { if (iter1.value().is_object()) {
@ -3170,18 +3175,21 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
} }
} }
else { else {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": invalid value type for " << iter2.key(); BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": invalid value type for " << iter2.key();
} }
} }
if (!name.empty() && !subpath.empty()) if (!name.empty() && !subpath.empty())
subfile_map.push_back(std::make_pair(name, subpath)); subfile_map.push_back(std::make_pair(name, subpath));
} else {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": invalid type for " << iter1.key();
} }
else
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": invalid type for " << iter1.key();
} }
} else {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": invalid type for " << it.key();
} }
else
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": invalid type for " << it.key();
}; };
try { try {
boost::nowide::ifstream ifs(root_file); boost::nowide::ifstream ifs(root_file);
@ -3279,6 +3287,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
model.variants.emplace_back(VendorProfile::PrinterVariant(variant_name)); model.variants.emplace_back(VendorProfile::PrinterVariant(variant_name));
} }
} else { } else {
++m_errors;
BOOST_LOG_TRIVIAL(error)<< __FUNCTION__ << boost::format(": invalid nozzle_diameters %1% for Vendor %1%") % nozzle_diameters % vendor_name; BOOST_LOG_TRIVIAL(error)<< __FUNCTION__ << boost::format(": invalid nozzle_diameters %1% for Vendor %1%") % nozzle_diameters % vendor_name;
} }
} }
@ -3313,6 +3322,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
// An empty material was inserted into the list of default materials. Remove it. // An empty material was inserted into the list of default materials. Remove it.
model.default_materials.erase(model.default_materials.begin()); model.default_materials.erase(model.default_materials.begin());
} else { } else {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(": invalid default_materials %1% for Vendor %1%") % default_materials_field % vendor_name; BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(": invalid default_materials %1% for Vendor %1%") % default_materials_field % vendor_name;
} }
} }
@ -3340,9 +3350,8 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
// 3) paste the process/filament/print configs // 3) paste the process/filament/print configs
PresetCollection *presets = nullptr; PresetCollection *presets = nullptr;
size_t presets_loaded = 0; size_t presets_loaded = 0;
bool _validation_mode = validation_mode;
auto parse_subfile = [path, vendor_name, presets_loaded, current_vendor_profile, _validation_mode]( auto parse_subfile = [this, path, vendor_name, presets_loaded, current_vendor_profile](
ConfigSubstitutionContext& substitution_context, ConfigSubstitutionContext& substitution_context,
PresetsConfigSubstitutions& substitutions, PresetsConfigSubstitutions& substitutions,
LoadConfigBundleAttributes& flags, LoadConfigBundleAttributes& flags,
@ -3368,6 +3377,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
DynamicPrintConfig config_src; DynamicPrintConfig config_src;
config_src.load_from_json(subfile, substitution_context, false, key_values, reason); config_src.load_from_json(subfile, substitution_context, false, key_values, reason);
if (!reason.empty()) { if (!reason.empty()) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": load config file "<<subfile<<" Failed!"; BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": load config file "<<subfile<<" Failed!";
return reason; return reason;
} }
@ -3394,6 +3404,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
} }
} }
else { else {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": can not find inherits "<<inherits<<" for " << preset_name; BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": can not find inherits "<<inherits<<" for " << preset_name;
//throw ConfigurationError(format("can not find inherits %1% for %2%", inherits, preset_name)); //throw ConfigurationError(format("can not find inherits %1% for %2%", inherits, preset_name));
reason = "Can not find inherits: " + inherits; reason = "Can not find inherits: " + inherits;
@ -3423,6 +3434,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
Preset::normalize(config); Preset::normalize(config);
} }
catch(nlohmann::detail::parse_error &err) { catch(nlohmann::detail::parse_error &err) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<< subfile <<" got a nlohmann::detail::parse_error, reason = " << err.what(); BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<< subfile <<" got a nlohmann::detail::parse_error, reason = " << err.what();
reason = std::string("json parse error") + err.what(); reason = std::string("json parse error") + err.what();
return reason; return reason;
@ -3430,15 +3442,18 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
// Report configuration fields, which are misplaced into a wrong group. // Report configuration fields, which are misplaced into a wrong group.
std::string incorrect_keys = Preset::remove_invalid_keys(config, *default_config); std::string incorrect_keys = Preset::remove_invalid_keys(config, *default_config);
if (! incorrect_keys.empty()) if (!incorrect_keys.empty()) {
BOOST_LOG_TRIVIAL(error)<< __FUNCTION__ << ": The config " << ++m_errors;
subfile << " contains incorrect keys: " << incorrect_keys << ", which were removed"; BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": The config " << subfile << " contains incorrect keys: " << incorrect_keys
<< ", which were removed";
}
if (presets_collection->type() == Preset::TYPE_PRINTER) { if (presets_collection->type() == Preset::TYPE_PRINTER) {
// Filter out printer presets, which are not mentioned in the vendor profile. // Filter out printer presets, which are not mentioned in the vendor profile.
// These presets are considered not installed. // These presets are considered not installed.
auto printer_model = config.opt_string("printer_model"); auto printer_model = config.opt_string("printer_model");
if (printer_model.empty()) { if (printer_model.empty()) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" << BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
preset_name << "\" defines no printer model, it will be ignored."; preset_name << "\" defines no printer model, it will be ignored.";
reason = std::string("can not find printer_model"); reason = std::string("can not find printer_model");
@ -3446,6 +3461,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
} }
auto printer_variant = config.opt_string("printer_variant"); auto printer_variant = config.opt_string("printer_variant");
if (printer_variant.empty()) { if (printer_variant.empty()) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" << BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
preset_name << "\" defines no printer variant, it will be ignored."; preset_name << "\" defines no printer variant, it will be ignored.";
reason = std::string("can not find printer_variant"); reason = std::string("can not find printer_variant");
@ -3455,6 +3471,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
[&](const VendorProfile::PrinterModel &m) { return m.id == printer_model; } [&](const VendorProfile::PrinterModel &m) { return m.id == printer_model; }
); );
if (it_model == current_vendor_profile->models.end()) { if (it_model == current_vendor_profile->models.end()) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" << BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
preset_name << "\" defines invalid printer model \"" << printer_model << "\", it will be ignored."; preset_name << "\" defines invalid printer model \"" << printer_model << "\", it will be ignored.";
reason = std::string("can not find printer model in vendor profile"); reason = std::string("can not find printer model in vendor profile");
@ -3462,6 +3479,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
} }
auto it_variant = it_model->variant(printer_variant); auto it_variant = it_model->variant(printer_variant);
if (it_variant == nullptr) { if (it_variant == nullptr) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" << BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
preset_name << "\" defines invalid printer variant \"" << printer_variant << "\", it will be ignored."; preset_name << "\" defines invalid printer variant \"" << printer_variant << "\", it will be ignored.";
reason = std::string("can not find printer_variant in vendor profile"); reason = std::string("can not find printer_variant in vendor profile");
@ -3470,6 +3488,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
} }
const Preset *preset_existing = presets_collection->find_preset(preset_name, false); const Preset *preset_existing = presets_collection->find_preset(preset_name, false);
if (preset_existing != nullptr) { if (preset_existing != nullptr) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" << BOOST_LOG_TRIVIAL(error) << "Error in a Vendor Config Bundle \"" << path << "\": The printer preset \"" <<
preset_name << "\" has already been loaded from another Config Bundle."; preset_name << "\" has already been loaded from another Config Bundle.";
reason = std::string("duplicated defines"); reason = std::string("duplicated defines");
@ -3477,7 +3496,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
} }
auto file_path = (boost::filesystem::path(data_dir()) /PRESET_SYSTEM_DIR/ vendor_name / subfile_iter.second).make_preferred(); auto file_path = (boost::filesystem::path(data_dir()) /PRESET_SYSTEM_DIR/ vendor_name / subfile_iter.second).make_preferred();
if(_validation_mode) if(validation_mode)
file_path = (boost::filesystem::path(data_dir()) / vendor_name / subfile_iter.second).make_preferred(); file_path = (boost::filesystem::path(data_dir()) / vendor_name / subfile_iter.second).make_preferred();
// Load the preset into the list of presets, save it to disk. // Load the preset into the list of presets, save it to disk.
@ -3491,6 +3510,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << loaded.name << " load filament_id: " << filament_id; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << loaded.name << " load filament_id: " << filament_id;
if (presets_collection->type() == Preset::TYPE_FILAMENT) { if (presets_collection->type() == Preset::TYPE_FILAMENT) {
if (filament_id.empty() && "Template" != vendor_name) { if (filament_id.empty() && "Template" != vendor_name) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": can not find filament_id for " << preset_name; BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": can not find filament_id for " << preset_name;
//throw ConfigurationError(format("can not find inherits %1% for %2%", inherits, preset_name)); //throw ConfigurationError(format("can not find inherits %1% for %2%", inherits, preset_name));
reason = "Can not find filament_id for " + preset_name; reason = "Can not find filament_id for " + preset_name;
@ -3539,6 +3559,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
{ {
std::string reason = parse_subfile(substitution_context, substitutions, flags, subfile, configs, filament_id_maps, presets, presets_loaded); std::string reason = parse_subfile(substitution_context, substitutions, flags, subfile, configs, filament_id_maps, presets, presets_loaded);
if (!reason.empty()) { if (!reason.empty()) {
++m_errors;
//parse error //parse error
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second; std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse process setting from %1%") % subfile_path; BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse process setting from %1%") % subfile_path;
@ -3554,6 +3575,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
{ {
std::string reason = parse_subfile(substitution_context, substitutions, flags, subfile, configs, filament_id_maps, presets, presets_loaded); std::string reason = parse_subfile(substitution_context, substitutions, flags, subfile, configs, filament_id_maps, presets, presets_loaded);
if (!reason.empty()) { if (!reason.empty()) {
++m_errors;
//parse error //parse error
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second; std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse filament setting from %1%") % subfile_path; BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse filament setting from %1%") % subfile_path;
@ -3569,6 +3591,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
{ {
std::string reason = parse_subfile(substitution_context, substitutions, flags, subfile, configs, filament_id_maps, presets, presets_loaded); std::string reason = parse_subfile(substitution_context, substitutions, flags, subfile, configs, filament_id_maps, presets, presets_loaded);
if (!reason.empty()) { if (!reason.empty()) {
++m_errors;
//parse error //parse error
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second; std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse printer setting from %1%") % subfile_path; BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse printer setting from %1%") % subfile_path;

View file

@ -264,6 +264,14 @@ public:
return { Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL }; return { Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL };
} }
// Orca: for validation only
bool has_errors() const
{
if (m_errors != 0 || printers.m_errors != 0 || filaments.m_errors != 0 || prints.m_errors != 0)
return true;
return false;
}
private: private:
//std::pair<PresetsConfigSubstitutions, std::string> load_system_presets(ForwardCompatibilitySubstitutionRule compatibility_rule); //std::pair<PresetsConfigSubstitutions, std::string> load_system_presets(ForwardCompatibilitySubstitutionRule compatibility_rule);
//BBS: add json related logic //BBS: add json related logic
@ -288,8 +296,11 @@ private:
DynamicPrintConfig full_fff_config() const; DynamicPrintConfig full_fff_config() const;
DynamicPrintConfig full_sla_config() const; DynamicPrintConfig full_sla_config() const;
// Orca: used for validation only
bool validation_mode = false; bool validation_mode = false;
std::string vendor_to_validate = ""; std::string vendor_to_validate = "";
int m_errors = 0;
}; };
ENABLE_ENUM_BITMASK_OPERATORS(PresetBundle::LoadConfigBundleAttribute) ENABLE_ENUM_BITMASK_OPERATORS(PresetBundle::LoadConfigBundleAttribute)