mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-07 15:51:08 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2a845db1e | ||
|
|
a38e6c61f2 | ||
|
|
f9ddb23804 | ||
|
|
ff8aebe76f | ||
|
|
a56d1bf33e | ||
|
|
662a8e340d | ||
|
|
6639a32b0c | ||
|
|
1ec195a221 |
@@ -4,15 +4,17 @@ OrcaSlicer — open-source C++17 3D slicer. wxWidgets GUI, CMake build system.
|
||||
|
||||
## Build Commands
|
||||
|
||||
Build the Release configuration unless asked otherwise.
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
cmake --build build/arm64 --config RelWithDebInfo --target all --
|
||||
cmake --build build/arm64 --config Release --target all --
|
||||
|
||||
# Linux
|
||||
cmake --build build --config RelWithDebInfo --target all --
|
||||
cmake --build build --config Release --target all --
|
||||
|
||||
# Windows (replace %build_type% with Debug/Release/RelWithDebInfo)
|
||||
cmake --build . --config %build_type% --target ALL_BUILD -- -m
|
||||
# Windows
|
||||
cmake --build . --config Release --target ALL_BUILD -- -m
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
@@ -311,7 +311,7 @@ function CreatePrinterBlock(OneModel)
|
||||
|
||||
return '<div class="PrinterBlock" onClick="ChooseModel(\''+vendor+'\',\''+OneModel['model']+'\')">'+
|
||||
' <div class="PImg">'+
|
||||
' <img class="ModelThumbnail" src="' + OneModel['cover'] + '" />'+
|
||||
' <img class="ModelThumbnail" src="' + OneModel['cover'] + '" onerror="this.onerror=null;this.src=\'../img/printer-dummy.png\';"/>'+
|
||||
' </div>'+
|
||||
' <div class="PrinterInfoMark">?</div>'+
|
||||
' <div class="PrinterInfo">'+
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -4,5 +4,10 @@
|
||||
<dict>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<!-- The Bambu network plug-in's code protector rewrites one of its own signed code pages
|
||||
after loading. Under the hardened runtime macOS kills the process when that page is
|
||||
paged back in; this lets it run, as Bambu Studio's signature does. -->
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -3618,6 +3618,9 @@ int CLI::run(int argc, char **argv)
|
||||
{
|
||||
if (opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "model_id" || opt_key == "dev_model_name" || opt_key == "filament_settings_id")
|
||||
continue;
|
||||
// rebuilt from every filament after this loop
|
||||
if (filament_dev_options.find(opt_key) != filament_dev_options.end())
|
||||
continue;
|
||||
ConfigOption *opt = m_print_config.option(opt_key, true);
|
||||
if (opt == nullptr) {
|
||||
// opt_key does not exist in this ConfigBase and it cannot be created, because it is not defined by this->def().
|
||||
@@ -3681,6 +3684,14 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
// The stored values cannot be told apart per filament, so they are kept as they are unless every slot has a config.
|
||||
std::vector<const DynamicPrintConfig *> filament_configs(filament_count, nullptr);
|
||||
for (size_t index = 0; index < load_filaments_config.size(); index++)
|
||||
if (load_filaments_index[index] >= 1 && load_filaments_index[index] <= filament_count)
|
||||
filament_configs[load_filaments_index[index] - 1] = &load_filaments_config[index];
|
||||
if (std::find(filament_configs.begin(), filament_configs.end(), nullptr) == filament_configs.end())
|
||||
set_filament_dev_options(m_print_config, filament_configs);
|
||||
|
||||
if (m_print_config.option<ConfigOptionStrings>("filament_extruder_variant")) {
|
||||
std::vector<int>& filament_self_indice = m_print_config.option<ConfigOptionInts>("filament_self_index", true)->values;
|
||||
int index_size = m_print_config.option<ConfigOptionStrings>("filament_extruder_variant")->size();
|
||||
|
||||
@@ -5,5 +5,10 @@
|
||||
<!-- for dynamic loading of libraries without signature validation. Used for 3dconnection drivers.-->
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<!-- The Bambu network plug-in's code protector rewrites one of its own signed code pages
|
||||
after loading. Under the hardened runtime macOS kills the process when that page is
|
||||
paged back in; this lets it run, as Bambu Studio's signature does. -->
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -10822,6 +10822,22 @@ void normalize_filament_values_to_variants(DynamicPrintConfig &config)
|
||||
}
|
||||
}
|
||||
|
||||
void set_filament_dev_options(DynamicPrintConfig &config, const std::vector<const DynamicPrintConfig *> &filament_configs)
|
||||
{
|
||||
for (const std::string &key : filament_dev_options) {
|
||||
if (std::none_of(filament_configs.begin(), filament_configs.end(), [&key](const DynamicPrintConfig *filament) { return filament->has(key); }))
|
||||
continue;
|
||||
const ConfigOption *default_value = print_config_def.get(key)->default_value.get();
|
||||
auto *dst = static_cast<ConfigOptionVectorBase *>(config.option(key, true));
|
||||
dst->clear();
|
||||
for (const DynamicPrintConfig *filament : filament_configs) {
|
||||
const auto *src = static_cast<const ConfigOptionVectorBase *>(filament->has(key) ? filament->option(key) : default_value);
|
||||
if (!src->empty())
|
||||
dst->append(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//used for object/region config
|
||||
//use the smallest of multiple to single
|
||||
@@ -11520,12 +11536,18 @@ void DynamicPrintConfig::update_non_diff_values_to_base_config(DynamicPrintConfi
|
||||
int cur_variant_count = cur_extruder_variants.size();
|
||||
int target_variant_count = target_extruder_variants.size();
|
||||
|
||||
// A base variant this config does not list (the base gained it after the config was saved, or the
|
||||
// config lists none) takes this config's first variant of the same extruder, as a user preset's
|
||||
// values do in update_diff_values_to_child_config. Left unmatched, the base's value would silently
|
||||
// replace the user's.
|
||||
variant_index.resize(target_variant_count, -1);
|
||||
if (cur_variant_count == 0) {
|
||||
// Defensive: target_variant_count may be 0 if the preset doesn't carry extruder_variant_name.
|
||||
// In that case keep variant_index empty and let the downstream size checks produce a useful error.
|
||||
if (!variant_index.empty())
|
||||
variant_index[0] = 0;
|
||||
// This config's one value belongs to the extruder of the base's first variant.
|
||||
variant_index = map_variant_indices(target_extruder_variants, target_extruder_ids, {},
|
||||
target_extruder_ids.empty() ? std::vector<int>() : std::vector<int>{target_extruder_ids[0]});
|
||||
}
|
||||
else if ((cur_extruder_ids.size() > 0) && cur_variant_count != cur_extruder_ids.size()){
|
||||
//should not happen
|
||||
@@ -11538,18 +11560,7 @@ void DynamicPrintConfig::update_non_diff_values_to_base_config(DynamicPrintConfi
|
||||
%extruder_variant_name %target_variant_count %extruder_id_name %target_extruder_ids.size();
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < target_variant_count; i++)
|
||||
{
|
||||
for (int j = 0; j < cur_variant_count; j++)
|
||||
{
|
||||
if ((target_extruder_variants[i] == cur_extruder_variants[j])
|
||||
&&(target_extruder_ids.empty() || (target_extruder_ids[i] == cur_extruder_ids[j])))
|
||||
{
|
||||
variant_index[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
variant_index = map_variant_indices(target_extruder_variants, target_extruder_ids, cur_extruder_variants, cur_extruder_ids);
|
||||
}
|
||||
|
||||
for (auto& opt : keys) {
|
||||
@@ -11574,6 +11585,13 @@ void DynamicPrintConfig::update_non_diff_values_to_base_config(DynamicPrintConfi
|
||||
if (cur_variant_count > target_variant_count)
|
||||
continue;
|
||||
|
||||
// The variant lists are the base's layout itself, which every other value is
|
||||
// carried onto: a variant this config lacks keeps its own name and id.
|
||||
if (opt == extruder_id_name || opt == extruder_variant_name) {
|
||||
opt_src->set(opt_target);
|
||||
continue;
|
||||
}
|
||||
|
||||
int stride = 1;
|
||||
if (key_set2.find(opt) != key_set2.end())
|
||||
stride = 2;
|
||||
|
||||
@@ -928,6 +928,11 @@ void normalize_filament_values_to_variants(DynamicPrintConfig &config);
|
||||
|
||||
extern std::set<std::string> filament_dev_options;
|
||||
|
||||
// Orca: a filament_dev_options option holds several values per filament, and how many is up to the
|
||||
// filament preset, so one filament's values cannot be replaced in place. This rebuilds each option from
|
||||
// filament_configs, one config per filament in slot order, as the filaments' values one after another.
|
||||
void set_filament_dev_options(DynamicPrintConfig &config, const std::vector<const DynamicPrintConfig *> &filament_configs);
|
||||
|
||||
extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector<int> variant_index, std::set<std::string>& key_set1, int stride = 1);
|
||||
extern void compute_filament_override_value(const std::string& opt_key, const ConfigOption *opt_old_machine, const ConfigOption *opt_new_machine, const ConfigOption *opt_new_filament, const DynamicPrintConfig& new_full_config,
|
||||
t_config_option_keys& diff_keys, DynamicPrintConfig& filament_overrides, std::vector<int>& f_map_indices);
|
||||
|
||||
@@ -974,8 +974,8 @@ bool AMSMaterialsSetting::Show(bool show)
|
||||
|
||||
static void _collect_filament_info(const wxString& shown_name,
|
||||
const Preset& filament,
|
||||
unordered_map<wxString, wxString>& query_filament_vendors,
|
||||
unordered_map<wxString, wxString>& query_filament_types)
|
||||
std::unordered_map<wxString, wxString>& query_filament_vendors,
|
||||
std::unordered_map<wxString, wxString>& query_filament_types)
|
||||
{
|
||||
query_filament_vendors[shown_name] = filament.config.get_filament_vendor();
|
||||
query_filament_types[shown_name] = filament.config.get_filament_type();
|
||||
|
||||
@@ -856,14 +856,14 @@ void AuxiliaryPanel::Split(const std::string &src, const std::string &separator,
|
||||
dest.clear();
|
||||
index = str.find_first_of(separator, start);
|
||||
do {
|
||||
if (index != string::npos) {
|
||||
if (index != std::string::npos) {
|
||||
substring = str.substr(start, index - start);
|
||||
dest.push_back(substring);
|
||||
start = index + separator.size();
|
||||
index = str.find(separator, start);
|
||||
if (start == string::npos) break;
|
||||
if (start == std::string::npos) break;
|
||||
}
|
||||
} while (index != string::npos);
|
||||
} while (index != std::string::npos);
|
||||
|
||||
// the last part
|
||||
substring = str.substr(start);
|
||||
|
||||
@@ -1307,7 +1307,7 @@ void CalibrationPresetPage::stripWhiteSpace(std::string& str)
|
||||
{
|
||||
if (str == "") { return; }
|
||||
|
||||
string::iterator cur_it;
|
||||
std::string::iterator cur_it;
|
||||
cur_it = str.begin();
|
||||
|
||||
while (cur_it != str.end()) {
|
||||
@@ -2597,7 +2597,7 @@ void CalibrationPresetPage::update_multi_extruder_filament_combobox(const std::s
|
||||
int ams_id_int = 0;
|
||||
try {
|
||||
if (!ams_id.empty())
|
||||
ams_id_int = stoi(ams_id.c_str());
|
||||
ams_id_int = std::stoi(ams_id.c_str());
|
||||
|
||||
} catch (...) {}
|
||||
|
||||
@@ -2685,7 +2685,7 @@ void CalibrationPresetPage::update_filament_combobox(std::string ams_id)
|
||||
int ams_id_int = 0;
|
||||
try {
|
||||
if (!ams_id.empty())
|
||||
ams_id_int = stoi(ams_id.c_str());
|
||||
ams_id_int = std::stoi(ams_id.c_str());
|
||||
|
||||
} catch (...) {}
|
||||
|
||||
|
||||
@@ -347,7 +347,7 @@ static std::string get_curr_timestmp()
|
||||
// return timestampString;
|
||||
}
|
||||
|
||||
static void get_filament_compatible_printer(Preset* preset, vector<std::string>& printers)
|
||||
static void get_filament_compatible_printer(Preset* preset, std::vector<std::string>& printers)
|
||||
{
|
||||
auto compatible_printers = dynamic_cast<ConfigOptionStrings *>(preset->config.option("compatible_printers"));
|
||||
if (compatible_printers == nullptr) return;
|
||||
@@ -1581,7 +1581,7 @@ void CreateFilamentPresetDialog::sort_printer_by_nozzle(std::vector<std::pair<st
|
||||
{
|
||||
std::unordered_map<std::string, float> nozzle_diameter = nozzle_diameter_map;
|
||||
std::sort(printer_name_to_filament_preset.begin(), printer_name_to_filament_preset.end(),
|
||||
[&nozzle_diameter](const std::pair<string, T> &a, const std::pair<string, T> &b) {
|
||||
[&nozzle_diameter](const std::pair<std::string, T> &a, const std::pair<std::string, T> &b) {
|
||||
size_t nozzle_index_a = a.first.find(" nozzle");
|
||||
size_t nozzle_index_b = b.first.find(" nozzle");
|
||||
if (nozzle_index_a == std::string::npos || nozzle_index_b == std::string::npos) return a.first < b.first;
|
||||
@@ -3143,7 +3143,7 @@ void CreatePrinterPresetDialog::set_current_visible_printer()
|
||||
|
||||
wxArrayString CreatePrinterPresetDialog::printer_preset_sort_with_nozzle_diameter(const VendorProfile &vendor_profile, float nozzle_diameter)
|
||||
{
|
||||
std::vector<pair<float, std::string>> preset_sort;
|
||||
std::vector<std::pair<float, std::string>> preset_sort;
|
||||
|
||||
auto get_nozzle_size_for_printer_model = [this](const std::string & model_name) -> size_t {
|
||||
auto iter = m_printer_name_to_preset.find(model_name);
|
||||
@@ -4964,7 +4964,7 @@ wxBoxSizer *CreatePresetForPrinterDialog::create_selected_filament_preset_sizer(
|
||||
|
||||
m_selected_printer->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) {
|
||||
wxString printer_name = m_selected_printer->GetStringSelection();
|
||||
std::unordered_map<string, std::vector<std::shared_ptr<Preset>>>::iterator filament_iter = m_printer_compatible_filament_presets.find(into_u8(printer_name));
|
||||
std::unordered_map<std::string, std::vector<std::shared_ptr<Preset>>>::iterator filament_iter = m_printer_compatible_filament_presets.find(into_u8(printer_name));
|
||||
if (m_printer_compatible_filament_presets.end() != filament_iter) {
|
||||
filament_choice_to_filament_preset.clear();
|
||||
wxArrayString filament_choices;
|
||||
|
||||
@@ -160,7 +160,7 @@ DevAms::~DevAms()
|
||||
m_trays.clear();
|
||||
}
|
||||
|
||||
static unordered_map<int, wxString> s_ams_display_formats = {
|
||||
static std::unordered_map<int, wxString> s_ams_display_formats = {
|
||||
{DevAms::AMS, "AMS-%d"},
|
||||
{DevAms::AMS_LITE, "AMS Lite-%d"},
|
||||
{DevAms::N3F, "AMS 2 PRO-%d"},
|
||||
|
||||
@@ -250,7 +250,7 @@ int DevNozzleMappingCtrl::CtrlGetAutoNozzleMappingV1(Slic3r::GUI::Plater* plater
|
||||
|
||||
void DevNozzleMappingCtrl::ParseAutoNozzleMapping(const json& print_jj)
|
||||
{
|
||||
if (print_jj.contains("command") && print_jj["command"].get<string>() == "get_auto_nozzle_mapping") {
|
||||
if (print_jj.contains("command") && print_jj["command"].get<std::string>() == "get_auto_nozzle_mapping") {
|
||||
if (print_jj.contains("sequence_id") && print_jj["sequence_id"] == m_sequence_id) {
|
||||
Clear();
|
||||
DevJsonValParser::ParseVal(print_jj, "result", m_result);
|
||||
|
||||
@@ -426,7 +426,7 @@ void DevNozzleSystem::ClearNozzles()
|
||||
|
||||
// ---- parsing ----------------------------------------------------------------------------------------
|
||||
|
||||
static unordered_map<string, NozzleFlowType> _str2_nozzle_flow_type = {
|
||||
static std::unordered_map<std::string, NozzleFlowType> _str2_nozzle_flow_type = {
|
||||
{"S", NozzleFlowType::S_FLOW},
|
||||
{"H", NozzleFlowType::H_FLOW},
|
||||
{"A", NozzleFlowType::S_FLOW},
|
||||
@@ -436,7 +436,7 @@ static unordered_map<string, NozzleFlowType> _str2_nozzle_flow_type = {
|
||||
{"B", NozzleFlowType::E_FLOW}, // E3D High Flow -> nvtE3DHighFlow
|
||||
};
|
||||
|
||||
static unordered_map<string, NozzleType> _str2_nozzle_type = {
|
||||
static std::unordered_map<std::string, NozzleType> _str2_nozzle_type = {
|
||||
{"00", NozzleType::ntStainlessSteel},
|
||||
{"01", NozzleType::ntHardenedSteel},
|
||||
{"05", NozzleType::ntTungstenCarbide}
|
||||
|
||||
@@ -368,7 +368,7 @@ wxString DeviceErrorDialog::parse_error_level(int error_code)
|
||||
}
|
||||
}
|
||||
|
||||
static const std::unordered_set<string> s_jump_liveview_error_codes = { "0300-8003", "0300-8002", "0300-800A"};
|
||||
static const std::unordered_set<std::string> s_jump_liveview_error_codes = { "0300-8003", "0300-8002", "0300-800A"};
|
||||
wxString DeviceErrorDialog::show_error_code(int error_code)
|
||||
{
|
||||
if (m_error_code == error_code) { return wxEmptyString;}
|
||||
|
||||
@@ -110,6 +110,7 @@ using json = nlohmann::json;
|
||||
class wxWindow;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#define CALI_DEBUG
|
||||
#define MINUTE_30 1800000 //ms
|
||||
@@ -3103,7 +3104,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
||||
DevFirmwareVersionInfo ver_info;
|
||||
ver_info.name = (*it)["name"].get<std::string>();
|
||||
if ((*it).contains("product_name"))
|
||||
ver_info.product_name = wxString::FromUTF8((*it)["product_name"].get<string>());
|
||||
ver_info.product_name = wxString::FromUTF8((*it)["product_name"].get<std::string>());
|
||||
if ((*it).contains("sw_ver"))
|
||||
ver_info.sw_ver = (*it)["sw_ver"].get<std::string>();
|
||||
if ((*it).contains("sw_new_ver"))
|
||||
|
||||
@@ -294,8 +294,8 @@ wxDataViewItem EditGCodeDialog::add_presets_placeholders()
|
||||
|
||||
|
||||
// Orca: create subgroups from the pages of the tabs
|
||||
auto init_from_tab = [this, full_config](wxDataViewItem parent, Tab* tab, const set<string>& preset_keys){
|
||||
set extra_keys(preset_keys);
|
||||
auto init_from_tab = [this, full_config](wxDataViewItem parent, Tab* tab, const std::set<std::string>& preset_keys){
|
||||
std::set extra_keys(preset_keys);
|
||||
for (const auto& page : tab->m_pages) {
|
||||
// ORCA: Pull icons from tabs for subgroups, icons are hidden on tabs
|
||||
std::string icon_name = "empty"; // use empty icon if not defined
|
||||
@@ -549,7 +549,7 @@ void ParamsNode::RefreshSearch(const wxString& search_text)
|
||||
|
||||
if (GetEnabledChildren().empty())
|
||||
if (auto pos = text.find(search_text); IsParamNode() && pos != wxString::npos) {
|
||||
m_highlight_index = make_unique<pair<int, int>>(pos, search_text.Len());
|
||||
m_highlight_index = make_unique<std::pair<int, int>>(pos, search_text.Len());
|
||||
Enable();
|
||||
} else {
|
||||
Disable();
|
||||
|
||||
@@ -702,11 +702,11 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||
set_value(str, true);
|
||||
}
|
||||
} else if (m_opt.opt_key == "sparse_infill_rotate_template" || m_opt.opt_key == "solid_infill_rotate_template") {
|
||||
string ustr(str.utf8_string());
|
||||
std::string ustr(str.utf8_string());
|
||||
if (!ConfigOptionFloats::validate_string(ustr)) {
|
||||
string v;
|
||||
std::string v;
|
||||
std::smatch match;
|
||||
string ps = (m_opt.opt_key == "sparse_infill_rotate_template") ?
|
||||
std::string ps = (m_opt.opt_key == "sparse_infill_rotate_template") ?
|
||||
u8"[BT][!]?|[#][\\d]+[!]?|[+\\-]?[\\d.]+[%]?[*]?[\\d]*[/NnZz$LlUuQq~^|#]?[+\\-]?[\\d.]*[%#\'\"cm]?[m]?[BT]?[!*]?" :
|
||||
u8"[#][\\d]+[!]?|[+\\-]?[\\d.]+[%]?[*]?[\\d]*[/NnZz$LlUuQq~^|#]?[+\\-]?[\\d.]*[%#\'\"cm]?[m]?[!*]?";
|
||||
|
||||
@@ -729,7 +729,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||
}
|
||||
break;
|
||||
} else if (m_opt.opt_key == "extra_solid_infills") {
|
||||
string ustr(str.utf8_string());
|
||||
std::string ustr(str.utf8_string());
|
||||
// New rule: accept either interval form (N or N#K) or explicit list (e.g. 1,7,9), with optional quotes.
|
||||
const std::regex rx_interval(u8R"(^\s*['"]?\s*\d+\s*(?:#\s*\d*)?\s*['"]?\s*$)");
|
||||
// List entries may be plain numbers or number with optional #K count, e.g., 5, 9#2, 18
|
||||
|
||||
@@ -94,6 +94,8 @@
|
||||
#include "slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp"
|
||||
#include "slic3r/GUI/PartPlate.hpp"
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
namespace Slic3r { class PrintBase; }
|
||||
|
||||
|
||||
@@ -3184,7 +3186,7 @@ void GCodeViewer::render_legend_color_arr_recommen(float window_padding)
|
||||
float ams_item_height = 0;
|
||||
float filament_group_item_align_width = 0;
|
||||
{
|
||||
float three_words_width = imgui.calc_text_size(std::string_view("ABC")).x;
|
||||
float three_words_width = imgui.calc_text_size("ABC"sv).x;
|
||||
const int line_capacity = 4;
|
||||
|
||||
for (const auto& extruder_filaments : {m_left_extruder_filament,m_right_extruder_filament })
|
||||
|
||||
@@ -177,6 +177,8 @@ extern wxPopupWindow* wxCurrentPopupWindow;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
static constexpr const float TRACKBALLSIZE = 0.8f;
|
||||
|
||||
static Slic3r::ColorRGBA DEFAULT_BG_LIGHT_COLOR = { 0.906f, 0.906f, 0.906f, 1.0f };
|
||||
|
||||
@@ -9040,7 +9040,7 @@ std::map<std::string, std::string> GUI_App::get_delete_cache_presets_lock()
|
||||
|
||||
void GUI_App::process_delete_presets()
|
||||
{
|
||||
std::map<string, string> delete_cache_presets = get_delete_cache_presets_lock();
|
||||
std::map<std::string, std::string> delete_cache_presets = get_delete_cache_presets_lock();
|
||||
for (auto it = delete_cache_presets.begin(); it != delete_cache_presets.end();) {
|
||||
if (it->first.empty()) continue;
|
||||
std::string del_setting_id = it->first;
|
||||
@@ -10068,7 +10068,7 @@ bool is_soluble_filament(int extruder_id)
|
||||
return support_option->get_at(0);
|
||||
};
|
||||
|
||||
bool has_filaments(const std::vector<string>& model_filaments) {
|
||||
bool has_filaments(const std::vector<std::string>& model_filaments) {
|
||||
auto &filament_presets = Slic3r::GUI::wxGetApp().preset_bundle->filament_presets;
|
||||
if (!Slic3r::GUI::wxGetApp().plater()) return false;
|
||||
auto model_objects = Slic3r::GUI::wxGetApp().plater()->model().objects;
|
||||
@@ -10103,7 +10103,7 @@ bool is_support_filament(int extruder_id, bool strict_check)
|
||||
Slic3r::ConfigOptionBools *support_option = dynamic_cast<Slic3r::ConfigOptionBools *>(filament->config.option("filament_is_support"));
|
||||
|
||||
if(!strict_check &&(filament_type == "PETG" || filament_type == "PLA")) {
|
||||
std::vector<string> model_filaments;
|
||||
std::vector<std::string> model_filaments;
|
||||
if (filament_type == "PETG")
|
||||
model_filaments.emplace_back("PLA");
|
||||
else {
|
||||
|
||||
@@ -1108,7 +1108,7 @@ void ObjectList::update_name_column_width() const
|
||||
}
|
||||
}
|
||||
|
||||
GetColumn(colName)->SetWidth(max(0, client_size.x - (others_width)*em));
|
||||
GetColumn(colName)->SetWidth(std::max(0, client_size.x - (others_width)*em));
|
||||
}
|
||||
|
||||
void ObjectList::set_filament_column_hidden(const bool hide) const
|
||||
@@ -3970,7 +3970,7 @@ wxDataViewItem ObjectList::add_settings_item(wxDataViewItem parent_item, const D
|
||||
if (config->opt_float("layer_height") == object_cfg->opt_float("layer_height")) {
|
||||
SettingsFactory::Bundle new_cat_options;
|
||||
for (auto cat_opt : cat_options) {
|
||||
std::vector<string> temp;
|
||||
std::vector<std::string> temp;
|
||||
for (auto value : cat_opt.second) {
|
||||
if (value != "layer_height")
|
||||
temp.push_back(value);
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#define MAX_NUM 9999.99
|
||||
#define MAX_SIZE std::string_view{"9999.99"}
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
namespace GUI
|
||||
|
||||
@@ -33,7 +33,7 @@ static const char* HMS_LOCAL_IMG_PATH = "hms/local_image";
|
||||
|
||||
// the local HMS info
|
||||
// Orca: dev-id-type set trimmed to the devices Orca ships local HMS images for
|
||||
static unordered_set<string> package_dev_id_types {"094", "239", "093", "22E"};
|
||||
static std::unordered_set<std::string> package_dev_id_types {"094", "239", "093", "22E"};
|
||||
|
||||
// Orca: HMS should be disabled when stealth mode is on or networking is not installed
|
||||
static bool should_disable_hms()
|
||||
@@ -345,17 +345,17 @@ wxString HMSQuery::query_hms_msg(const std::string& dev_id, const std::string& l
|
||||
return _query_hms_msg(dev_id.substr(0, 3), long_error_code, lang_code);
|
||||
}
|
||||
|
||||
string HMSQuery::get_dev_id_type(const MachineObject* obj) const
|
||||
std::string HMSQuery::get_dev_id_type(const MachineObject* obj) const
|
||||
{
|
||||
if (obj)
|
||||
{
|
||||
return obj->get_dev_id().substr(0, 3);
|
||||
}
|
||||
|
||||
return string();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
wxString HMSQuery::_query_hms_msg(const string& dev_id_type, const string& long_error_code, const string& lang_code)
|
||||
wxString HMSQuery::_query_hms_msg(const std::string& dev_id_type, const std::string& long_error_code, const std::string& lang_code)
|
||||
{
|
||||
if (long_error_code.empty())
|
||||
{
|
||||
@@ -426,9 +426,9 @@ wxString HMSQuery::_query_hms_msg(const string& dev_id_type, const string& long_
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
bool HMSQuery::_is_internal_error(const string &dev_id_type,
|
||||
const string &error_code,
|
||||
const string &lang_code)
|
||||
bool HMSQuery::_is_internal_error(const std::string &dev_id_type,
|
||||
const std::string &error_code,
|
||||
const std::string &lang_code)
|
||||
{
|
||||
init_hms_info(dev_id_type);
|
||||
auto iter = m_hms_info_jsons.find(dev_id_type);
|
||||
|
||||
@@ -335,7 +335,7 @@ void PrintJob::process(Ctl &ctl)
|
||||
auto origin_profile_id = model_info->metadata_items.find(BBL_DESIGNER_PROFILE_ID_TAG);
|
||||
if (origin_profile_id != model_info->metadata_items.end()) {
|
||||
try {
|
||||
params.origin_profile_id = stoi(origin_profile_id->second.c_str());
|
||||
params.origin_profile_id = std::stoi(origin_profile_id->second.c_str());
|
||||
}
|
||||
catch(...) {}
|
||||
}
|
||||
|
||||
@@ -536,12 +536,12 @@ void NotificationManager::PopNotification::count_lines()
|
||||
return;
|
||||
|
||||
// handle with marks
|
||||
if (pos_start == string::npos && pos_end == string::npos) {
|
||||
if (pos_start == std::string::npos && pos_end == std::string::npos) {
|
||||
pos_start = text.find(error_start);
|
||||
if (pos_start != string::npos) {
|
||||
if (pos_start != std::string::npos) {
|
||||
text.erase(pos_start, error_start.length());
|
||||
pos_end = text.find(error_end);
|
||||
if (pos_end != string::npos) {
|
||||
if (pos_end != std::string::npos) {
|
||||
text.erase(pos_end, error_end.length());
|
||||
}
|
||||
}
|
||||
@@ -675,7 +675,7 @@ void NotificationManager::PopNotification::bbl_render_block_notif_text(ImGuiWrap
|
||||
if (m_text1.size() > m_endlines[i])
|
||||
last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
|
||||
|
||||
if (pos_start != string::npos && pos_end != string::npos && m_endlines[i] - line.length() >= pos_start && m_endlines[i] <= pos_end) {
|
||||
if (pos_start != std::string::npos && pos_end != std::string::npos && m_endlines[i] - line.length() >= pos_start && m_endlines[i] <= pos_end) {
|
||||
push_style_color(ImGuiCol_Text, m_ErrorColor, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
imgui.text(line.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
@@ -737,7 +737,7 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
|
||||
if (m_text1.size() > m_endlines[i])
|
||||
last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
|
||||
|
||||
if (pos_start != string::npos && pos_end != string::npos&& m_endlines[i] - line.length() >= pos_start && m_endlines[i] <= pos_end) {
|
||||
if (pos_start != std::string::npos && pos_end != std::string::npos&& m_endlines[i] - line.length() >= pos_start && m_endlines[i] <= pos_end) {
|
||||
push_style_color(ImGuiCol_Text, m_ErrorColor, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
imgui.text(line.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
@@ -86,7 +86,7 @@ PartSkipDialog::PartSkipDialog(wxWindow *parent) : DPIDialog(parent, wxID_ANY, _
|
||||
{
|
||||
std::time_t t = std::time(0);
|
||||
std::stringstream buf;
|
||||
buf << put_time(std::localtime(&t), "%a_%b_%d_%H_%M_%S/");
|
||||
buf << std::put_time(std::localtime(&t), "%a_%b_%d_%H_%M_%S/");
|
||||
m_timestamp = buf.str();
|
||||
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
@@ -402,7 +402,7 @@ std::string PartSkipDialog::create_tmp_path()
|
||||
return tmp_path;
|
||||
}
|
||||
|
||||
bool PartSkipDialog::is_local_file_existed(const std::vector<string> &local_paths)
|
||||
bool PartSkipDialog::is_local_file_existed(const std::vector<std::string> &local_paths)
|
||||
{
|
||||
for (auto path : local_paths) {
|
||||
if (!std::filesystem::exists(path)) { return false; }
|
||||
@@ -703,8 +703,8 @@ void PartSkipDialog::InitDialogUI()
|
||||
m_parts_state.clear();
|
||||
m_parts_name.clear();
|
||||
|
||||
string pick_img = m_local_paths[0];
|
||||
string slice_info = m_local_paths[2];
|
||||
std::string pick_img = m_local_paths[0];
|
||||
std::string slice_info = m_local_paths[2];
|
||||
|
||||
m_switch_drag_btn->SetIcon("canvas_drag");
|
||||
m_switch_drag_btn->SetBackgroundColor(*wxWHITE);
|
||||
|
||||
@@ -139,11 +139,11 @@ private:
|
||||
boost::shared_ptr<PrinterFileSystem> m_file_sys;
|
||||
std::string m_timestamp;
|
||||
std::string m_tmp_path;
|
||||
std::vector<string> m_local_paths;
|
||||
std::vector<string> m_target_paths;
|
||||
std::vector<std::string> m_local_paths;
|
||||
std::vector<std::string> m_target_paths;
|
||||
std::string create_tmp_path();
|
||||
|
||||
bool is_local_file_existed(const std::vector<string> &local_paths);
|
||||
bool is_local_file_existed(const std::vector<std::string> &local_paths);
|
||||
|
||||
void DownloadPartsFile();
|
||||
void OnFileSystemEvent(wxCommandEvent &event);
|
||||
|
||||
@@ -357,7 +357,7 @@ wxDEFINE_EVENT(EVT_NOTICE_FULL_SCREEN_CHANGED, IntEvent);
|
||||
#define PRINTER_PANEL_RADIUS (6) // ORCA
|
||||
#define BTN_SYNC_SIZE (wxSize(FromDIP(96), FromDIP(98)))
|
||||
|
||||
static string get_diameter_string(float diameter)
|
||||
static std::string get_diameter_string(float diameter)
|
||||
{
|
||||
std::ostringstream stream; // ORCA ensure 0.25 returned as 0.25. previous code returned as 0.2 because of std::setprecision(1)
|
||||
stream << std::fixed << std::setprecision(2) << diameter; // Use 2 decimals to capture 0.25 / 0.15 reliably
|
||||
@@ -6323,7 +6323,7 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn)
|
||||
}
|
||||
|
||||
// BBS:Record consumables information before synchronization
|
||||
std::vector<string> color_before_sync;
|
||||
std::vector<std::string> color_before_sync;
|
||||
std::vector<bool> is_support_before;
|
||||
DynamicPrintConfig& project_config = wxGetApp().preset_bundle->project_config;
|
||||
ConfigOptionStrings* color_opt = project_config.option<ConfigOptionStrings>("filament_colour");
|
||||
@@ -12762,7 +12762,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
||||
Vec3d old_plate_pos = old_plate->get_center_origin();
|
||||
|
||||
// BBS: Save the model in the current platelist
|
||||
std::vector<vector<int> > plate_object;
|
||||
std::vector<std::vector<int> > plate_object;
|
||||
for (size_t i = 0; i < old_plate_list.get_plate_count(); ++i) {
|
||||
PartPlate* plate = old_plate_list.get_plate(i);
|
||||
std::vector<int> obj_idxs;
|
||||
@@ -17975,7 +17975,7 @@ bool Plater::load_files(const wxArrayString& filenames)
|
||||
|
||||
// Orca: Iters through given paths and imports files from zip then remove zip from paths
|
||||
// returns true if zip files were found
|
||||
auto handle_zips = [this](vector<fs::path>& paths) { // NOLINT(*-no-recursion) - Recursion is intended and should be managed properly
|
||||
auto handle_zips = [this](std::vector<fs::path>& paths) { // NOLINT(*-no-recursion) - Recursion is intended and should be managed properly
|
||||
bool res = false;
|
||||
for (auto it = paths.begin(); it != paths.end();) {
|
||||
if (boost::algorithm::iends_with(it->string(), ".zip")) {
|
||||
|
||||
@@ -378,7 +378,7 @@ wxBoxSizer *PreferencesDialog::create_item_combobox(wxString title, wxString too
|
||||
|
||||
auto current_setting = app_config->get(param);
|
||||
if (!current_setting.empty()) {
|
||||
auto compare = [current_setting](string possible_setting) { return current_setting == possible_setting; };
|
||||
auto compare = [current_setting](std::string possible_setting) { return current_setting == possible_setting; };
|
||||
auto iterator = find_if(config_name_index.begin(), config_name_index.end(), compare);
|
||||
if (iterator != config_name_index.end())
|
||||
current_index = static_cast<unsigned int>(iterator - config_name_index.begin());
|
||||
@@ -1714,7 +1714,7 @@ void PreferencesDialog::create_items()
|
||||
g_sizer->Add(create_item_title(_L("Project")), 1, wxEXPAND);
|
||||
|
||||
std::vector<wxString> projectLoadSettingsBehaviourOptions = {_L("Load All"), _L("Ask When Relevant"), _L("Always Ask"), _L("Load Geometry Only")};
|
||||
std::vector<string> projectLoadSettingsConfigOptions = { OPTION_PROJECT_LOAD_BEHAVIOUR_LOAD_ALL, OPTION_PROJECT_LOAD_BEHAVIOUR_ASK_WHEN_RELEVANT, OPTION_PROJECT_LOAD_BEHAVIOUR_ALWAYS_ASK, OPTION_PROJECT_LOAD_BEHAVIOUR_LOAD_GEOMETRY };
|
||||
std::vector<std::string> projectLoadSettingsConfigOptions = { OPTION_PROJECT_LOAD_BEHAVIOUR_LOAD_ALL, OPTION_PROJECT_LOAD_BEHAVIOUR_ASK_WHEN_RELEVANT, OPTION_PROJECT_LOAD_BEHAVIOUR_ALWAYS_ASK, OPTION_PROJECT_LOAD_BEHAVIOUR_LOAD_GEOMETRY };
|
||||
auto item_project_load = create_item_combobox(_L("Load behavior"), _L("Should printer/filament/process settings be loaded when opening a 3MF file?"), SETTING_PROJECT_LOAD_BEHAVIOUR, projectLoadSettingsBehaviourOptions, projectLoadSettingsConfigOptions);
|
||||
g_sizer->Add(item_project_load);
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ void ProjectPanel::on_reload(wxCommandEvent& evt)
|
||||
}
|
||||
|
||||
bool has_content = false;
|
||||
for (const string& v : {
|
||||
for (const std::string& v : {
|
||||
update_type,
|
||||
license,
|
||||
model_name,
|
||||
|
||||
@@ -182,7 +182,7 @@ std::string get_nozzle_volume_type_cloud_string(NozzleVolumeType nozzle_volume_t
|
||||
static int s_nozzle_mapping_last_request_time = 0;
|
||||
|
||||
std::vector<wxString> SelectMachineDialog::MACHINE_BED_TYPE_STRING;
|
||||
std::vector<string> SelectMachineDialog::MachineBedTypeString;
|
||||
std::vector<std::string> SelectMachineDialog::MachineBedTypeString;
|
||||
void SelectMachineDialog::init_machine_bed_types()
|
||||
{
|
||||
if (MACHINE_BED_TYPE_STRING.size() == 0) {
|
||||
@@ -2748,8 +2748,8 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event)
|
||||
std::vector<ConfirmBeforeSendInfo> confirm_text;
|
||||
|
||||
// check more than one using in same external spool
|
||||
std::unordered_set<string> main_external_spool_filas;
|
||||
std::unordered_set<string> deputy_external_spool_filas;
|
||||
std::unordered_set<std::string> main_external_spool_filas;
|
||||
std::unordered_set<std::string> deputy_external_spool_filas;
|
||||
for (const auto& mapping_info : m_ams_mapping_result) {
|
||||
if (mapping_info.ams_id == VIRTUAL_AMS_MAIN_ID_STR){
|
||||
main_external_spool_filas.insert(mapping_info.filament_id);
|
||||
@@ -5239,7 +5239,7 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_)
|
||||
|
||||
/*Check high temperture slicing*/
|
||||
if (m_print_type == PrintFromType::FROM_NORMAL) {
|
||||
std::set<string> high_temp_filaments;
|
||||
std::set<std::string> high_temp_filaments;
|
||||
std::unordered_set<int> known_fila_soften_extruders;
|
||||
std::unordered_set<int> unknown_fila_soften_extruders;
|
||||
auto preset_full_config = wxGetApp().preset_bundle->full_config();
|
||||
|
||||
@@ -337,7 +337,7 @@ private:
|
||||
wxColour m_colour_bold_color{wxColour(38, 46, 48)};
|
||||
StateColor m_btn_bg_enable;
|
||||
|
||||
std::unordered_map<string, PrintOption*> m_checkbox_list;
|
||||
std::unordered_map<std::string, PrintOption*> m_checkbox_list;
|
||||
std::list<PrintOption*> m_checkbox_list_order;
|
||||
|
||||
std::shared_ptr<int> m_token = std::make_shared<int>(0);
|
||||
|
||||
@@ -126,7 +126,7 @@ void SendToPrinterDialog::stripWhiteSpace(std::string& str)
|
||||
{
|
||||
if (str == "") { return; }
|
||||
|
||||
string::iterator cur_it;
|
||||
std::string::iterator cur_it;
|
||||
cur_it = str.begin();
|
||||
|
||||
while (cur_it != str.end()) {
|
||||
|
||||
@@ -171,7 +171,7 @@ public:
|
||||
std::string current_nozzle_loc = "";
|
||||
wxColour m_colour;
|
||||
|
||||
string m_file_name;
|
||||
std::string m_file_name;
|
||||
bool m_ams_loading{false};
|
||||
void doRender(wxDC &dc);
|
||||
ExtruderImage(wxWindow *parent, wxWindowID id, int nozzle_num, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
@@ -244,7 +244,7 @@ protected:
|
||||
{
|
||||
wxString local_image_url; //local image path
|
||||
std::string img_url_paths; // oss url path
|
||||
vector<wxPanel *> image_broad;
|
||||
std::vector<wxPanel *> image_broad;
|
||||
bool is_selected;
|
||||
bool is_uploaded; // load
|
||||
wxBoxSizer * image_tb_broad = nullptr;
|
||||
|
||||
@@ -1576,7 +1576,7 @@ bool SyncAmsInfoDialog::is_nozzle_type_match(DevExtderSystem data, wxString &err
|
||||
}
|
||||
}
|
||||
|
||||
vector<int> map_extruders = {1, 0};
|
||||
std::vector<int> map_extruders = {1, 0};
|
||||
|
||||
// The default two extruders are left, right, but the order of the extruders on the machine is right, left.
|
||||
std::vector<std::string> flow_type_of_machine;
|
||||
@@ -1676,7 +1676,7 @@ void SyncAmsInfoDialog::stripWhiteSpace(std::string &str)
|
||||
{
|
||||
if (str == "") { return; }
|
||||
|
||||
string::iterator cur_it;
|
||||
std::string::iterator cur_it;
|
||||
cur_it = str.begin();
|
||||
|
||||
while (cur_it != str.end()) {
|
||||
|
||||
@@ -2257,7 +2257,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
|
||||
string opt_key_without_idx = opt_key.substr(0, opt_key.find('#'));
|
||||
std::string opt_key_without_idx = opt_key.substr(0, opt_key.find('#'));
|
||||
|
||||
if (opt_key_without_idx == "long_retractions_when_cut") {
|
||||
unsigned char activate = boost::any_cast<unsigned char>(value);
|
||||
|
||||
@@ -1682,13 +1682,13 @@ int GuideFrame::SaveProfileData()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StringReplace(string &strBase, string strSrc, string strDes)
|
||||
void StringReplace(std::string &strBase, std::string strSrc, std::string strDes)
|
||||
{
|
||||
string::size_type pos = 0;
|
||||
string::size_type srcLen = strSrc.size();
|
||||
string::size_type desLen = strDes.size();
|
||||
std::string::size_type pos = 0;
|
||||
std::string::size_type srcLen = strSrc.size();
|
||||
std::string::size_type desLen = strDes.size();
|
||||
pos = strBase.find(strSrc, pos);
|
||||
while ((pos != string::npos)) {
|
||||
while ((pos != std::string::npos)) {
|
||||
strBase.replace(pos, srcLen, strDes);
|
||||
pos = strBase.find(strSrc, (pos + desLen));
|
||||
}
|
||||
|
||||
@@ -1052,7 +1052,7 @@ void AMSControl::UpdateAms(const std::string &series_name,
|
||||
/*update humidity popup*/
|
||||
if (m_percent_humidity_dry_popup->IsShown())
|
||||
{
|
||||
string target_id = m_percent_humidity_dry_popup->get_owner_ams_id();
|
||||
std::string target_id = m_percent_humidity_dry_popup->get_owner_ams_id();
|
||||
for (const auto& the_info : ams_info)
|
||||
{
|
||||
if (target_id == the_info.ams_id)
|
||||
|
||||
@@ -63,7 +63,7 @@ protected:
|
||||
|
||||
std::string m_dev_id;
|
||||
std::vector<std::vector<std::string>> m_item_ids{ {}, {} };
|
||||
std::vector<std::pair<string, string>> pair_id;
|
||||
std::vector<std::pair<std::string, std::string>> pair_id;
|
||||
|
||||
int m_total_ext_count = 1;
|
||||
AMSextruder *m_extruder{nullptr};
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
std::tuple<bool, bool> isFilaSwitchReady();
|
||||
void show_switcher_status(bool show);
|
||||
|
||||
void UpdatePassRoad(string ams_id, AMSPassRoadType type, AMSPassRoadSTEP step);
|
||||
void UpdatePassRoad(std::string ams_id, AMSPassRoadType type, AMSPassRoadSTEP step);
|
||||
void CreateAms();
|
||||
void CreateAmsDoubleNozzle(const std::string &series_name, const std::string& printer_type);
|
||||
void CreateAmsSingleNozzle(const std::string &series_name, const std::string &printer_type);
|
||||
|
||||
@@ -634,7 +634,7 @@ void AMSextruderImage::doRender(wxDC &dc)
|
||||
}
|
||||
|
||||
|
||||
AMSextruderImage::AMSextruderImage(wxWindow *parent, wxWindowID id, string file_name, const wxSize& size, const wxPoint &pos)
|
||||
AMSextruderImage::AMSextruderImage(wxWindow *parent, wxWindowID id, std::string file_name, const wxSize& size, const wxPoint &pos)
|
||||
{
|
||||
wxWindow::Create(parent, id, pos, size);
|
||||
SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
||||
@@ -823,7 +823,7 @@ void SwitcherImage::doRender(wxDC &dc)
|
||||
Layout();
|
||||
}
|
||||
|
||||
SwitcherImage::SwitcherImage(wxWindow *parent, wxWindowID id, string file_name, const wxSize& size, const wxPoint &pos)
|
||||
SwitcherImage::SwitcherImage(wxWindow *parent, wxWindowID id, std::string file_name, const wxSize& size, const wxPoint &pos)
|
||||
{
|
||||
wxWindow::Create(parent, id, pos, size);
|
||||
SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
||||
@@ -899,7 +899,7 @@ void AMSextruder::OnAmsLoading(bool load, int nozzle_id, wxColour col /*= AMS_CO
|
||||
}
|
||||
|
||||
/*return true if something is updated*/
|
||||
bool AMSextruder::updateNozzleNum(int nozzle_num, const string& series_name)
|
||||
bool AMSextruder::updateNozzleNum(int nozzle_num, const std::string& series_name)
|
||||
{
|
||||
if (m_nozzle_num == nozzle_num && m_series_name == series_name) return false;
|
||||
m_series_name = series_name;
|
||||
|
||||
@@ -393,10 +393,10 @@ public:
|
||||
bool m_show_state = {false};
|
||||
wxColour m_colour;
|
||||
ScalableBitmap m_ams_extruder;
|
||||
string m_file_name;
|
||||
std::string m_file_name;
|
||||
bool m_ams_loading{ false };
|
||||
void doRender(wxDC &dc);
|
||||
AMSextruderImage(wxWindow *parent, wxWindowID id, string file_name, const wxSize& size, const wxPoint &pos = wxDefaultPosition);
|
||||
AMSextruderImage(wxWindow *parent, wxWindowID id, std::string file_name, const wxSize& size, const wxPoint &pos = wxDefaultPosition);
|
||||
~AMSextruderImage();
|
||||
};
|
||||
|
||||
@@ -444,10 +444,10 @@ public:
|
||||
bool m_show_state = {false};
|
||||
wxColour m_colour;
|
||||
ScalableBitmap m_switcher;
|
||||
string m_file_name;
|
||||
std::string m_file_name;
|
||||
// bool m_ams_loading{ false };
|
||||
void doRender(wxDC &dc);
|
||||
SwitcherImage(wxWindow *parent, wxWindowID id, string file_name, const wxSize& size, const wxPoint &pos = wxDefaultPosition);
|
||||
SwitcherImage(wxWindow *parent, wxWindowID id, std::string file_name, const wxSize& size, const wxPoint &pos = wxDefaultPosition);
|
||||
~SwitcherImage();
|
||||
};
|
||||
|
||||
@@ -456,7 +456,7 @@ class AMSextruder : public wxWindow
|
||||
{
|
||||
private:
|
||||
int m_nozzle_num = -1;
|
||||
string m_series_name;
|
||||
std::string m_series_name;
|
||||
|
||||
public:
|
||||
void TurnOn(wxColour col);
|
||||
@@ -466,7 +466,7 @@ public:
|
||||
void msw_rescale();
|
||||
void has_ams(bool hams) {m_has_vams = hams; Refresh();};
|
||||
void no_ams_mode(bool mode) {m_none_ams_mode = mode; Refresh();};
|
||||
bool updateNozzleNum(int nozzle_num, const std::string& series_name = string());
|
||||
bool updateNozzleNum(int nozzle_num, const std::string& series_name = std::string());
|
||||
|
||||
bool m_none_ams_mode{true};
|
||||
bool m_has_vams{false};
|
||||
|
||||
@@ -596,7 +596,8 @@ PrintParams_Legacy BBLNetworkPlugin::as_legacy(PrintParams& param)
|
||||
}
|
||||
|
||||
// Every PrintParams field except the four the 02.08.01 series added
|
||||
// (task_timelapse_use_internal, extruder_cali_manual_mode, svc_context, slicer_uid).
|
||||
// (task_timelapse_use_internal, extruder_cali_manual_mode, svc_context, slicer_uid) and the
|
||||
// queue_plate_id 02.08.02 appended.
|
||||
PrintParams_0203 BBLNetworkPlugin::as_0203(PrintParams& param)
|
||||
{
|
||||
PrintParams_0203 p;
|
||||
|
||||
@@ -336,6 +336,7 @@ struct PrintParams {
|
||||
bool try_emmc_print;
|
||||
std::string svc_context;
|
||||
std::string slicer_uid;
|
||||
std::string queue_plate_id;
|
||||
};
|
||||
|
||||
struct TaskQueryParams
|
||||
@@ -412,7 +413,7 @@ enum class NetworkAbi {
|
||||
Unsupported, // no generation in this build can call it - never dispatch through it
|
||||
Legacy, // 01.10.01: PrintParams_Legacy; send_message/send_message_to_printer take no flag
|
||||
V0203, // 02.03.00: PrintParams_0203; bind takes no dev_model
|
||||
Current, // 02.08.01: the layouts and signatures this build declares directly
|
||||
Current, // 02.08.04: the layouts and signatures this build declares directly
|
||||
};
|
||||
|
||||
struct NetworkLibraryVersion {
|
||||
@@ -425,10 +426,12 @@ struct NetworkLibraryVersion {
|
||||
};
|
||||
|
||||
// Every row names the generation that can call it, so a series can never be offered without a
|
||||
// host-side ABI for it. Series with no generation - 02.01.01, 02.00.02 and older - must stay out;
|
||||
// is_supported_network_version() is the gate that keeps them from loading.
|
||||
// host-side ABI for it. Series with no generation - 02.08.01 (whose PrintParams lacks the
|
||||
// queue_plate_id that 02.08.02 appended, and whose malformed bind table macOS 27 refuses to
|
||||
// load), 02.01.01, 02.00.02 and older - must stay out; is_supported_network_version() is the
|
||||
// gate that keeps them from loading.
|
||||
static const NetworkLibraryVersion AVAILABLE_NETWORK_VERSIONS[] = {
|
||||
{"02.08.01", "02.08.01", nullptr, true, nullptr, NetworkAbi::Current},
|
||||
{"02.08.04", "02.08.04", nullptr, true, nullptr, NetworkAbi::Current},
|
||||
{"02.03.00", "02.03.00", nullptr, false,
|
||||
"An older plug-in series. Features that need newer plug-in support, such as print-failure "
|
||||
"snapshots in the device error dialog, are unavailable.", NetworkAbi::V0203},
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
class json_diff
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -197,6 +197,7 @@ bool CloudPluginService::download_cloud_plugin(PluginDescriptor& entry,
|
||||
Http http = Http::get(download_url);
|
||||
http.timeout_connect(30)
|
||||
.timeout_max(300)
|
||||
.tls_verify(true)
|
||||
.on_complete([&body, &http_status](std::string response_body, unsigned status) {
|
||||
body = std::move(response_body);
|
||||
http_status = status;
|
||||
|
||||
@@ -346,20 +346,8 @@ std::vector<std::string> PluginAuditManager::default_denied_path_keywords()
|
||||
// must never be able to reach a secret, a certificate, or a configuration file just because
|
||||
// it happens to live inside an otherwise-allowed root (e.g. the bundled TLS client cert at
|
||||
// resources_dir()/cert/..., which would become reachable the moment resources_dir() is
|
||||
// granted as a read-only allowed root). Match as whole path components, not substrings, so
|
||||
// imports such as numpy/__config__.py and stdlib configparser.py remain usable.
|
||||
return {"secret", "secrets", "cert", "certs", "certificate", "certificates", "conf", "config"};
|
||||
}
|
||||
|
||||
static bool has_denied_config_extension(std::string name)
|
||||
{
|
||||
const size_t stream_pos = name.find(':');
|
||||
if (stream_pos != std::string::npos)
|
||||
name.erase(stream_pos);
|
||||
|
||||
const boost::filesystem::path path(name);
|
||||
const std::string extension = path.extension().string();
|
||||
return extension == ".conf" || extension == ".ini";
|
||||
// granted as a read-only allowed root).
|
||||
return {"secret", "cert", "conf"};
|
||||
}
|
||||
|
||||
bool PluginAuditManager::is_denied_path_keyword(const boost::filesystem::path& candidate) const
|
||||
@@ -384,7 +372,7 @@ bool PluginAuditManager::is_denied_path_keyword(const boost::filesystem::path& c
|
||||
continue;
|
||||
std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
for (const auto& keyword : m_denied_path_keywords) {
|
||||
if (name == keyword || (keyword == "conf" && has_denied_config_extension(name)))
|
||||
if (name.find(keyword) != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -808,8 +796,7 @@ bool persist_permission(const std::string& plugin_key,
|
||||
|
||||
int report_denied(PluginAuditManager& mgr,
|
||||
const std::string& event_name,
|
||||
const AuditDecision& decision,
|
||||
const std::string& target = {})
|
||||
const AuditDecision& decision)
|
||||
{
|
||||
AuditViolation violation;
|
||||
violation.plugin_key = mgr.current_plugin();
|
||||
@@ -817,13 +804,7 @@ int report_denied(PluginAuditManager& mgr,
|
||||
violation.reason = decision.reason;
|
||||
mgr.report_violation(violation);
|
||||
|
||||
std::string message = "Plugin attempted audited operation \"" + event_name + "\" without permission";
|
||||
if (!decision.reason.empty())
|
||||
message += ": " + decision.reason;
|
||||
if (!target.empty())
|
||||
message += ": " + target;
|
||||
|
||||
PyErr_SetString(PyExc_PermissionError, message.c_str());
|
||||
PyErr_SetString(PyExc_PermissionError, "Plugin attempted an audited operation without permission");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -935,7 +916,7 @@ int PluginAuditManager::audit_hook(const char* event, PyObject* args, void* user
|
||||
if (fs_category) {
|
||||
for (const auto& target : targets) {
|
||||
if (mgr->is_denied_path(boost::filesystem::path(target)))
|
||||
return PluginAuditDetail::report_denied(*mgr, event_name, {false, "denied path"}, target);
|
||||
return PluginAuditDetail::report_denied(*mgr, event_name, {false, "denied path"});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// Via pybind11 so this file requests the same python3xx.lib as everything else.
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <pybind11/conduit/wrap_include_python_h.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -102,20 +103,22 @@ public:
|
||||
bool is_denied_filename(const boost::filesystem::path& candidate) const;
|
||||
|
||||
// --- denied-path-keyword registry ---
|
||||
// Keywords that categorically deny a path if ANY component matches one case-insensitively --
|
||||
// e.g. a "secrets" subfolder, a "certificates" folder, a "conf"/"config" directory, or a
|
||||
// .conf/.ini file anywhere the plugin can otherwise reach, including inside an allowed root.
|
||||
// This is broader than the exact-name is_denied_filename registry, but it is not a substring
|
||||
// match: importable modules such as numpy/__config__.py, configparser.py, sysconfig.py, or
|
||||
// user folders such as "Conference" and "Concert" are unrelated names and must stay promptable.
|
||||
// Keywords that categorically deny a path if ANY of its components (directory or file
|
||||
// name), not just the base name, contains one case-insensitively -- e.g. a "secrets"
|
||||
// subfolder, a "certificates" folder, or a "conf"/"config" file anywhere the plugin can
|
||||
// otherwise reach, including inside an allowed root. This is intentionally broader and
|
||||
// fuzzier than the exact-name is_denied_filename registry: it exists to categorically rule
|
||||
// out whole classes of sensitive paths (secrets, certificates, config) rather than name
|
||||
// specific known files, at the cost of over-blocking an unrelated name that happens to
|
||||
// contain the keyword -- the fail-safe direction, same rationale as is_denied_filename.
|
||||
void add_denied_path_keyword(const std::string& keyword);
|
||||
|
||||
// The list install_hook() seeds into the keyword registry. Exposed so tests seed the exact
|
||||
// same set without a live interpreter.
|
||||
static std::vector<std::string> default_denied_path_keywords();
|
||||
|
||||
// True when any component of candidate's (canonicalized) path matches a registered keyword,
|
||||
// case-insensitively. A registered "conf" keyword also blocks .conf/.ini file components.
|
||||
// True when any component of candidate's (canonicalized) path contains a registered
|
||||
// keyword, case-insensitively.
|
||||
bool is_denied_path_keyword(const boost::filesystem::path& candidate) const;
|
||||
|
||||
// is_denied_filename(candidate) || is_denied_path_keyword(candidate). Convenience for
|
||||
|
||||
@@ -538,6 +538,110 @@ SCENARIO("update_diff_values_to_child_config keeps a child's values on variants
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("update_non_diff_values_to_base_config keeps a project's changed values on variants it does not list",
|
||||
"[Config][Variant]") {
|
||||
std::set<std::string> no_keys;
|
||||
auto variants = [](std::initializer_list<std::string> names) { return new Slic3r::ConfigOptionStrings(names); };
|
||||
|
||||
GIVEN("A filament base with three variants") {
|
||||
Slic3r::DynamicPrintConfig base;
|
||||
base.set_key_value("filament_extruder_variant",
|
||||
variants({"Direct Drive Standard", "Bowden Standard", "Direct Drive High Flow"}));
|
||||
base.set_deserialize_strict("nozzle_temperature", "220,220,220");
|
||||
|
||||
WHEN("the project was saved when the base had only its first variant") {
|
||||
Slic3r::DynamicPrintConfig project;
|
||||
project.set_key_value("filament_extruder_variant", variants({"Direct Drive Standard"}));
|
||||
project.set_deserialize_strict("nozzle_temperature", "199");
|
||||
|
||||
AND_WHEN("the project lists the value as changed") {
|
||||
project.update_non_diff_values_to_base_config(base, project.keys(), {"nozzle_temperature"}, "", "filament_extruder_variant",
|
||||
Slic3r::filament_options_with_variant, no_keys);
|
||||
THEN("the project's value applies to every variant") {
|
||||
REQUIRE(project.opt_serialize("nozzle_temperature") == "199,199,199");
|
||||
}
|
||||
}
|
||||
AND_WHEN("the project does not list the value as changed") {
|
||||
project.update_non_diff_values_to_base_config(base, project.keys(), {}, "", "filament_extruder_variant",
|
||||
Slic3r::filament_options_with_variant, no_keys);
|
||||
THEN("the base's values replace it") {
|
||||
REQUIRE(project.opt_serialize("nozzle_temperature") == "220,220,220");
|
||||
}
|
||||
}
|
||||
}
|
||||
WHEN("the project lists every variant, in another order") {
|
||||
Slic3r::DynamicPrintConfig project;
|
||||
project.set_key_value("filament_extruder_variant",
|
||||
variants({"Bowden Standard", "Direct Drive High Flow", "Direct Drive Standard"}));
|
||||
project.set_deserialize_strict("nozzle_temperature", "190,205,199");
|
||||
project.update_non_diff_values_to_base_config(base, project.keys(), {"nozzle_temperature"}, "", "filament_extruder_variant",
|
||||
Slic3r::filament_options_with_variant, no_keys);
|
||||
THEN("each variant keeps its own value") {
|
||||
REQUIRE(project.opt_serialize("nozzle_temperature") == "199,190,205");
|
||||
}
|
||||
}
|
||||
WHEN("the project lists no variants") {
|
||||
Slic3r::DynamicPrintConfig project;
|
||||
project.set_deserialize_strict("nozzle_temperature", "199");
|
||||
project.update_non_diff_values_to_base_config(base, project.keys(), {"nozzle_temperature"}, "", "filament_extruder_variant",
|
||||
Slic3r::filament_options_with_variant, no_keys);
|
||||
THEN("the project's value applies to every variant") {
|
||||
REQUIRE(project.opt_serialize("nozzle_temperature") == "199,199,199");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A two-extruder printer base with two variants per extruder") {
|
||||
Slic3r::DynamicPrintConfig base;
|
||||
base.set_key_value("printer_extruder_variant",
|
||||
variants({"Direct Drive Standard", "Direct Drive High Flow", "Direct Drive Standard", "Direct Drive High Flow"}));
|
||||
base.set_key_value("printer_extruder_id", new Slic3r::ConfigOptionInts({1, 1, 2, 2}));
|
||||
base.set_deserialize_strict("retraction_length", "0.8,0.8,0.8,0.8");
|
||||
|
||||
WHEN("the project lists only the Standard variant of each extruder") {
|
||||
Slic3r::DynamicPrintConfig project;
|
||||
project.set_key_value("printer_extruder_variant", variants({"Direct Drive Standard", "Direct Drive Standard"}));
|
||||
project.set_key_value("printer_extruder_id", new Slic3r::ConfigOptionInts({1, 2}));
|
||||
project.set_deserialize_strict("retraction_length", "1.1,2.2");
|
||||
project.update_non_diff_values_to_base_config(base, project.keys(), {"retraction_length"}, "printer_extruder_id", "printer_extruder_variant",
|
||||
Slic3r::printer_options_with_variant_1,
|
||||
Slic3r::printer_options_with_variant_2);
|
||||
THEN("each extruder's High Flow variant takes that extruder's value") {
|
||||
REQUIRE(project.opt_serialize("retraction_length") == "1.1,1.1,2.2,2.2");
|
||||
}
|
||||
}
|
||||
WHEN("the project lists only the Standard variant of each extruder, and the variant lists as changed") {
|
||||
Slic3r::DynamicPrintConfig project;
|
||||
project.set_key_value("printer_extruder_variant", variants({"Direct Drive Standard", "Direct Drive Standard"}));
|
||||
project.set_key_value("printer_extruder_id", new Slic3r::ConfigOptionInts({1, 2}));
|
||||
project.set_deserialize_strict("machine_max_speed_x", "300,100,400,150");
|
||||
base.set_deserialize_strict("machine_max_speed_x", "500,200,500,200,500,200,500,200");
|
||||
project.update_non_diff_values_to_base_config(base, project.keys(),
|
||||
{"machine_max_speed_x", "printer_extruder_id", "printer_extruder_variant"},
|
||||
"printer_extruder_id", "printer_extruder_variant",
|
||||
Slic3r::printer_options_with_variant_1,
|
||||
Slic3r::printer_options_with_variant_2);
|
||||
THEN("the variant lists are the base's") {
|
||||
REQUIRE(project.opt_serialize("printer_extruder_variant") == base.opt_serialize("printer_extruder_variant"));
|
||||
REQUIRE(project.opt_serialize("printer_extruder_id") == "1,1,2,2");
|
||||
}
|
||||
THEN("each extruder's High Flow variant takes that extruder's pair of limits") {
|
||||
REQUIRE(project.opt_serialize("machine_max_speed_x") == "300,100,300,100,400,150,400,150");
|
||||
}
|
||||
}
|
||||
WHEN("the project lists no variants") {
|
||||
Slic3r::DynamicPrintConfig project;
|
||||
project.set_deserialize_strict("retraction_length", "1.1");
|
||||
project.update_non_diff_values_to_base_config(base, project.keys(), {"retraction_length"}, "printer_extruder_id", "printer_extruder_variant",
|
||||
Slic3r::printer_options_with_variant_1,
|
||||
Slic3r::printer_options_with_variant_2);
|
||||
THEN("only the first extruder's variants take the project's value") {
|
||||
REQUIRE(project.opt_serialize("retraction_length") == "1.1,1.1,0.8,0.8");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SCENARIO("DynamicPrintConfig JSON serialization", "[Config]") {
|
||||
// WHEN("DynamicPrintConfig is serialized and deserialized") {
|
||||
// auto now = std::chrono::high_resolution_clock::now();
|
||||
|
||||
@@ -799,3 +799,30 @@ TEST_CASE("A per-variant filament option read with a single value gives it to ev
|
||||
config.load_from_ini_string("pressure_advance = 0.021", ForwardCompatibilitySubstitutionRule::Disable);
|
||||
REQUIRE(config.option<ConfigOptionFloats>("pressure_advance")->values == std::vector<double>({0.021, 0.021, 0.021}));
|
||||
}
|
||||
|
||||
// The device drying options hold several values per filament, as many as each filament preset gives.
|
||||
TEST_CASE("The device drying options are rebuilt as each filament's values in slot order", "[Config]")
|
||||
{
|
||||
DynamicPrintConfig two_values, one_value, no_value;
|
||||
two_values.option<ConfigOptionStrings>("filament_dev_ams_drying_ams_limitations", true)->values = {"1", "0"};
|
||||
two_values.option<ConfigOptionFloats>("filament_dev_ams_drying_temperature", true)->values = {45., 45., 55., 55.};
|
||||
one_value.option<ConfigOptionStrings>("filament_dev_ams_drying_ams_limitations", true)->values = {"1"};
|
||||
one_value.option<ConfigOptionFloats>("filament_dev_ams_drying_temperature", true)->values = {65., 65., 75., 75.};
|
||||
|
||||
// values a project stored for three other filaments
|
||||
DynamicPrintConfig config;
|
||||
config.option<ConfigOptionStrings>("filament_dev_ams_drying_ams_limitations", true)->values = {"0", "0", "0"};
|
||||
config.option<ConfigOptionFloats>("filament_dev_chamber_drying_time", true)->values = {12., 8., 12.};
|
||||
|
||||
set_filament_dev_options(config, {&two_values, &one_value, &two_values});
|
||||
REQUIRE(config.option<ConfigOptionStrings>("filament_dev_ams_drying_ams_limitations")->values ==
|
||||
std::vector<std::string>({"1", "0", "1", "1", "0"}));
|
||||
REQUIRE(config.option<ConfigOptionFloats>("filament_dev_ams_drying_temperature")->values ==
|
||||
std::vector<double>({45., 45., 55., 55., 65., 65., 75., 75., 45., 45., 55., 55.}));
|
||||
// an option no filament defines keeps the stored values
|
||||
REQUIRE(config.option<ConfigOptionFloats>("filament_dev_chamber_drying_time")->values == std::vector<double>({12., 8., 12.}));
|
||||
|
||||
// a filament without the option takes the option's default
|
||||
set_filament_dev_options(config, {&two_values, &no_value});
|
||||
REQUIRE(config.option<ConfigOptionStrings>("filament_dev_ams_drying_ams_limitations")->values == std::vector<std::string>({"1", "0", ""}));
|
||||
}
|
||||
|
||||
@@ -6228,8 +6228,9 @@ TEST_CASE("A per-variant project value maps onto its base preset's variant layou
|
||||
base_finder(&base, calls));
|
||||
CHECK(config.option<ConfigOptionStrings>("print_extruder_variant")->values ==
|
||||
std::vector<std::string>{"Direct Drive Standard", "Direct Drive High Flow"});
|
||||
// The listed key keeps the project's Standard value and takes High Flow from the base.
|
||||
check_double_vector(config.option<ConfigOptionFloats>("outer_wall_speed")->values, {100., 300.});
|
||||
// The listed key keeps the project's Standard value, and High Flow, which the project does not
|
||||
// list, takes it too, as a user preset's value does.
|
||||
check_double_vector(config.option<ConfigOptionFloats>("outer_wall_speed")->values, {100., 100.});
|
||||
check_double_vector(config.option<ConfigOptionFloats>("inner_wall_speed")->values, {250., 350.});
|
||||
}
|
||||
|
||||
|
||||
@@ -78,31 +78,34 @@ TEST_CASE("Series and managed classification", "[NetworkVersions]")
|
||||
|
||||
TEST_CASE_METHOD(PluginFolderFixture, "Managed builds fold into the series; customs are surfaced", "[NetworkVersions]")
|
||||
{
|
||||
add_plugin("02.08.01.55"); // managed, same series -> folded into the 02.08.01 row
|
||||
add_plugin("02.08.04.60"); // managed, same series -> folded into the 02.08.04 row
|
||||
add_plugin("02.09.00.10"); // managed, unknown series -> not listed
|
||||
add_plugin("02.08.01.55"); // managed, series this build no longer has an ABI for -> not listed
|
||||
add_plugin("02.03.00.62"); // managed, older whitelisted series -> folded into 02.03.00
|
||||
add_plugin("02.01.01.52"); // managed, series with no ABI in this build -> not listed
|
||||
add_plugin("02.08.01_custom"); // custom, whitelisted series -> listed under it
|
||||
add_plugin("02.08.01.52-dev"); // custom (dash-suffixed), whitelisted series -> listed
|
||||
add_plugin("02.08.04_custom"); // custom, whitelisted series -> listed under it
|
||||
add_plugin("02.08.04.52-dev"); // custom (dash-suffixed), whitelisted series -> listed
|
||||
|
||||
auto versions = get_all_available_versions();
|
||||
|
||||
// The specific managed build never gets its own row - the series represents it.
|
||||
REQUIRE(count_version(versions, "02.08.01.55") == 0);
|
||||
REQUIRE(count_version(versions, "02.08.01") == 1);
|
||||
REQUIRE(count_version(versions, "02.08.04.60") == 0);
|
||||
REQUIRE(count_version(versions, "02.08.04") == 1);
|
||||
REQUIRE(count_version(versions, "02.09.00.10") == 0);
|
||||
REQUIRE(count_version(versions, "02.08.01.55") == 0);
|
||||
REQUIRE(count_version(versions, "02.08.01") == 0);
|
||||
REQUIRE(count_version(versions, "02.03.00.62") == 0);
|
||||
REQUIRE(count_version(versions, "02.03.00") == 1);
|
||||
REQUIRE(count_version(versions, "02.01.01.52") == 0);
|
||||
// Custom-named builds are distinct files kept under their own name.
|
||||
REQUIRE(count_version(versions, "02.08.01_custom") == 1);
|
||||
REQUIRE(count_version(versions, "02.08.01.52-dev") == 1);
|
||||
REQUIRE(count_version(versions, "02.08.04_custom") == 1);
|
||||
REQUIRE(count_version(versions, "02.08.04.52-dev") == 1);
|
||||
|
||||
// Newest series first, its customs nested under it (suffix sort: "" < ".52-dev" < "_custom"),
|
||||
// then older series, legacy last.
|
||||
REQUIRE(versions[0].version == "02.08.01");
|
||||
REQUIRE(versions[1].version == "02.08.01.52-dev");
|
||||
REQUIRE(versions[2].version == "02.08.01_custom");
|
||||
REQUIRE(versions[0].version == "02.08.04");
|
||||
REQUIRE(versions[1].version == "02.08.04.52-dev");
|
||||
REQUIRE(versions[2].version == "02.08.04_custom");
|
||||
REQUIRE(versions[3].version == "02.03.00");
|
||||
REQUIRE(versions.back().version == BAMBU_NETWORK_AGENT_VERSION_LEGACY);
|
||||
|
||||
@@ -111,9 +114,9 @@ TEST_CASE_METHOD(PluginFolderFixture, "Managed builds fold into the series; cust
|
||||
REQUIRE_FALSE(versions[3].is_latest);
|
||||
|
||||
// Customs sort/render nested under their series (non-empty suffix, base = the series).
|
||||
REQUIRE(versions[1].base_version == "02.08.01");
|
||||
REQUIRE(versions[1].base_version == "02.08.04");
|
||||
REQUIRE_FALSE(versions[1].suffix.empty());
|
||||
REQUIRE(versions[2].base_version == "02.08.01");
|
||||
REQUIRE(versions[2].base_version == "02.08.04");
|
||||
REQUIRE_FALSE(versions[2].suffix.empty());
|
||||
|
||||
// "(Latest)" is the series row, never a nested custom build.
|
||||
@@ -123,20 +126,20 @@ TEST_CASE_METHOD(PluginFolderFixture, "Managed builds fold into the series; cust
|
||||
REQUIRE_FALSE(versions[2].is_latest);
|
||||
|
||||
// The stored default that drives download and update-check decisions is now the series.
|
||||
REQUIRE(std::string(get_latest_network_version()) == "02.08.01");
|
||||
REQUIRE(std::string(get_latest_network_version()) == "02.08.04");
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(PluginFolderFixture, "Only the loaded series is marked installed", "[NetworkVersions]")
|
||||
{
|
||||
add_plugin("02.08.01.55");
|
||||
add_plugin("02.08.01_custom");
|
||||
add_plugin("02.08.04.60");
|
||||
add_plugin("02.08.04_custom");
|
||||
|
||||
// The loaded plug-in reports its full build (02.08.01.55); the series row is what gets marked.
|
||||
// The loaded plug-in reports its full build (02.08.04.60); the series row is what gets marked.
|
||||
{
|
||||
auto versions = get_all_available_versions("02.08.01.55");
|
||||
auto versions = get_all_available_versions("02.08.04.60");
|
||||
int marked = 0;
|
||||
for (const auto& info : versions)
|
||||
if (info.is_loaded) { ++marked; REQUIRE(info.version == "02.08.01"); }
|
||||
if (info.is_loaded) { ++marked; REQUIRE(info.version == "02.08.04"); }
|
||||
REQUIRE(marked == 1);
|
||||
}
|
||||
|
||||
@@ -152,10 +155,10 @@ TEST_CASE_METHOD(PluginFolderFixture, "Only the loaded series is marked installe
|
||||
|
||||
// A loaded custom build matches its own row, never the bare series.
|
||||
{
|
||||
auto versions = get_all_available_versions("02.08.01_custom");
|
||||
auto versions = get_all_available_versions("02.08.04_custom");
|
||||
int marked = 0;
|
||||
for (const auto& info : versions)
|
||||
if (info.is_loaded) { ++marked; REQUIRE(info.version == "02.08.01_custom"); }
|
||||
if (info.is_loaded) { ++marked; REQUIRE(info.version == "02.08.04_custom"); }
|
||||
REQUIRE(marked == 1);
|
||||
}
|
||||
|
||||
@@ -167,11 +170,11 @@ TEST_CASE_METHOD(PluginFolderFixture, "Only the loaded series is marked installe
|
||||
TEST_CASE("Only whitelisted series pass the load gate", "[NetworkVersions]")
|
||||
{
|
||||
// Each whitelisted series, its builds, and custom-named builds of that series.
|
||||
REQUIRE(is_supported_network_version("02.08.01"));
|
||||
REQUIRE(is_supported_network_version("02.08.01.52"));
|
||||
REQUIRE(is_supported_network_version("02.08.01.55"));
|
||||
REQUIRE(is_supported_network_version("02.08.01_custom"));
|
||||
REQUIRE(is_supported_network_version("02.08.01.52-dev"));
|
||||
REQUIRE(is_supported_network_version("02.08.04"));
|
||||
REQUIRE(is_supported_network_version("02.08.04.52"));
|
||||
REQUIRE(is_supported_network_version("02.08.04.60"));
|
||||
REQUIRE(is_supported_network_version("02.08.04_custom"));
|
||||
REQUIRE(is_supported_network_version("02.08.04.52-dev"));
|
||||
REQUIRE(is_supported_network_version("02.03.00"));
|
||||
REQUIRE(is_supported_network_version("02.03.00.62"));
|
||||
REQUIRE(is_supported_network_version("02.03.00.70"));
|
||||
@@ -179,6 +182,9 @@ TEST_CASE("Only whitelisted series pass the load gate", "[NetworkVersions]")
|
||||
REQUIRE(is_supported_network_version(BAMBU_NETWORK_AGENT_VERSION_LEGACY));
|
||||
|
||||
// Series whitelisted by previous Orca releases that no generation here can call.
|
||||
REQUIRE_FALSE(is_supported_network_version("02.08.01"));
|
||||
REQUIRE_FALSE(is_supported_network_version("02.08.01.55"));
|
||||
REQUIRE_FALSE(is_supported_network_version("02.08.01_custom"));
|
||||
REQUIRE_FALSE(is_supported_network_version("02.01.01.52"));
|
||||
REQUIRE_FALSE(is_supported_network_version("02.00.02.50"));
|
||||
|
||||
@@ -198,9 +204,9 @@ TEST_CASE("Each version resolves to the ABI generation that can call it", "[Netw
|
||||
{
|
||||
// The generation is keyed on the series, so every build of a series - including the
|
||||
// custom-named ones - resolves to the same one.
|
||||
CHECK(network_plugin_abi("02.08.01") == NetworkAbi::Current);
|
||||
CHECK(network_plugin_abi("02.08.01.55") == NetworkAbi::Current);
|
||||
CHECK(network_plugin_abi("02.08.01.52-dev") == NetworkAbi::Current);
|
||||
CHECK(network_plugin_abi("02.08.04") == NetworkAbi::Current);
|
||||
CHECK(network_plugin_abi("02.08.04.60") == NetworkAbi::Current);
|
||||
CHECK(network_plugin_abi("02.08.04.52-dev") == NetworkAbi::Current);
|
||||
CHECK(network_plugin_abi("02.03.00") == NetworkAbi::V0203);
|
||||
CHECK(network_plugin_abi("02.03.00.62") == NetworkAbi::V0203);
|
||||
CHECK(network_plugin_abi("02.03.00_custom") == NetworkAbi::V0203);
|
||||
@@ -208,6 +214,7 @@ TEST_CASE("Each version resolves to the ABI generation that can call it", "[Netw
|
||||
|
||||
// Anything the load gate rejects must dispatch through nothing at all, rather than
|
||||
// defaulting to a layout it does not share.
|
||||
CHECK(network_plugin_abi("02.08.01.55") == NetworkAbi::Unsupported);
|
||||
CHECK(network_plugin_abi("02.01.01.52") == NetworkAbi::Unsupported);
|
||||
CHECK(network_plugin_abi("02.00.02.50") == NetworkAbi::Unsupported);
|
||||
CHECK(network_plugin_abi("02.09.00.10") == NetworkAbi::Unsupported);
|
||||
@@ -234,7 +241,7 @@ TEST_CASE_METHOD(PluginFolderFixture, "Legacy series never adopts discovered bui
|
||||
// With nothing else on disk, the series holds "(Latest)" even though its library is
|
||||
// not installed.
|
||||
for (const auto& info : versions) {
|
||||
if (info.version == "02.08.01") {
|
||||
if (info.version == "02.08.04") {
|
||||
REQUIRE(info.is_latest);
|
||||
REQUIRE_FALSE(info.is_loaded);
|
||||
}
|
||||
|
||||
@@ -222,19 +222,18 @@ TEST_CASE("Plugin audit denies secret/certificate/config-like paths by keyword",
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/resources/certificates/ca.pem")));
|
||||
}
|
||||
|
||||
SECTION("a 'conf'/'config' directory or config file component is denied")
|
||||
SECTION("a 'conf'/'config' directory or file component is denied")
|
||||
{
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/plugin/conf/settings.json")));
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/plugin/config/settings.json")));
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/plugin/plugin.conf")));
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/plugin/plugin.ini")));
|
||||
}
|
||||
|
||||
SECTION("matching is case-insensitive")
|
||||
{
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/plugin/SECRETS/token.txt")));
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/resources/Certificates/ca.pem")));
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/plugin/PLUGIN.CONF")));
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/resources/CertBundle/ca.pem")));
|
||||
CHECK(mgr.is_denied_path_keyword(fs::path("/plugin/CONFIG.JSON")));
|
||||
}
|
||||
|
||||
SECTION("matching is not limited to the base name -- any ancestor component counts")
|
||||
@@ -246,14 +245,6 @@ TEST_CASE("Plugin audit denies secret/certificate/config-like paths by keyword",
|
||||
{
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/plugin/output/model.gcode")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/plugin/storage/state.json")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/python/packages/cp312/numpy/__config__.py")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/python/packages/cp312/numpy/_core/_ufunc_config.py")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/python/Lib/configparser.py")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/python/Lib/sysconfig.py")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/python/Lib/logging/config.py")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/python/packages/cp312/certifi/cacert.pem")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/users/Conference/output.txt")));
|
||||
CHECK_FALSE(mgr.is_denied_path_keyword(fs::path("/users/Concert/output.txt")));
|
||||
}
|
||||
|
||||
SECTION("an empty path is not denied")
|
||||
|
||||
Reference in New Issue
Block a user