Merge pull request #3218 from Ultimaker/CURA-3710_setting_visibility_preset

CURA-3710 Add preset setting visibility files
This commit is contained in:
Ian Paschal 2018-02-05 09:51:52 +01:00 committed by GitHub
commit f627c97a92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 940 additions and 56 deletions

View File

@ -1,6 +1,7 @@
# Copyright (c) 2017 Ultimaker B.V.
# Copyright (c) 2017 Ultimaker B.V.
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
#Type hinting.
from typing import Dict
from PyQt5.QtNetwork import QLocalServer
from PyQt5.QtNetwork import QLocalSocket
@ -87,6 +88,7 @@ from PyQt5.QtGui import QColor, QIcon
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType
from configparser import ConfigParser
import sys
import os.path
import numpy
@ -95,6 +97,7 @@ import os
import argparse
import json
numpy.seterr(all="ignore")
MYPY = False
@ -348,57 +351,19 @@ class CuraApplication(QtApplication):
preferences.setDefault("local_file/last_used_type", "text/x-gcode")
preferences.setDefault("general/visible_settings", """
machine_settings
resolution
layer_height
shell
wall_thickness
top_bottom_thickness
z_seam_x
z_seam_y
infill
infill_sparse_density
gradual_infill_steps
material
material_print_temperature
material_bed_temperature
material_diameter
material_flow
retraction_enable
speed
speed_print
speed_travel
acceleration_print
acceleration_travel
jerk_print
jerk_travel
travel
cooling
cool_fan_enabled
support
support_enable
support_extruder_nr
support_type
platform_adhesion
adhesion_type
adhesion_extruder_nr
brim_width
raft_airgap
layer_0_z_overlap
raft_surface_layers
dual
prime_tower_enable
prime_tower_size
prime_tower_position_x
prime_tower_position_y
meshfix
blackmagic
print_sequence
infill_mesh
cutting_mesh
experimental
""".replace("\n", ";").replace(" ", ""))
setting_visibily_preset_names = self.getVisibilitySettingPresetTypes()
preferences.setDefault("general/visible_settings_preset", setting_visibily_preset_names)
preset_setting_visibility_choice = Preferences.getInstance().getValue("general/preset_setting_visibility_choice")
default_preset_visibility_group_name = "Basic"
if preset_setting_visibility_choice == "" or preset_setting_visibility_choice is None:
if preset_setting_visibility_choice not in setting_visibily_preset_names:
preset_setting_visibility_choice = default_preset_visibility_group_name
visible_settings = self.getVisibilitySettingPreset(settings_preset_name = preset_setting_visibility_choice)
preferences.setDefault("general/visible_settings", visible_settings)
preferences.setDefault("general/preset_setting_visibility_choice", preset_setting_visibility_choice)
self.applicationShuttingDown.connect(self.saveSettings)
self.engineCreatedSignal.connect(self._onEngineCreated)
@ -410,6 +375,93 @@ class CuraApplication(QtApplication):
self.getCuraSceneController().setActiveBuildPlate(0) # Initialize
@pyqtSlot(str, result = str)
def getVisibilitySettingPreset(self, settings_preset_name) -> str:
result = self._loadPresetSettingVisibilityGroup(settings_preset_name)
formatted_preset_settings = self._serializePresetSettingVisibilityData(result)
return formatted_preset_settings
## Serialise the given preset setting visibitlity group dictionary into a string which is concatenated by ";"
#
def _serializePresetSettingVisibilityData(self, settings_data: dict) -> str:
result_string = ""
for key in settings_data:
result_string += key + ";"
for value in settings_data[key]:
result_string += value + ";"
return result_string
## Load the preset setting visibility group with the given name
#
def _loadPresetSettingVisibilityGroup(self, visibility_preset_name) -> Dict[str, str]:
preset_dir = Resources.getPath(Resources.PresetSettingVisibilityGroups)
result = {}
right_preset_found = False
for item in os.listdir(preset_dir):
file_path = os.path.join(preset_dir, item)
if not os.path.isfile(file_path):
continue
parser = ConfigParser(allow_no_value = True) # accept options without any value,
try:
parser.read([file_path])
if not parser.has_option("general", "name"):
continue
if parser["general"]["name"] == visibility_preset_name:
right_preset_found = True
for section in parser.sections():
if section == 'general':
continue
else:
section_settings = []
for option in parser[section].keys():
section_settings.append(option)
result[section] = section_settings
if right_preset_found:
break
except Exception as e:
Logger.log("e", "Failed to load setting visibility preset %s: %s", file_path, str(e))
return result
## Check visibility setting preset folder and returns available types
#
def getVisibilitySettingPresetTypes(self):
preset_dir = Resources.getPath(Resources.PresetSettingVisibilityGroups)
result = {}
for item in os.listdir(preset_dir):
file_path = os.path.join(preset_dir, item)
if not os.path.isfile(file_path):
continue
parser = ConfigParser(allow_no_value=True) # accept options without any value,
try:
parser.read([file_path])
if not parser.has_option("general", "name") and not parser.has_option("general", "weight"):
continue
result[parser["general"]["weight"]] = parser["general"]["name"]
except Exception as e:
Logger.log("e", "Failed to load setting preset %s: %s", file_path, str(e))
return result
def _onEngineCreated(self):
self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())

View File

@ -453,6 +453,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
Logger.log("w", "Workspace did not contain visible settings. Leaving visibility unchanged")
else:
global_preferences.setValue("general/visible_settings", visible_settings)
global_preferences.setValue("general/preset_setting_visibility_choice", "Custom")
categories_expanded = temp_preferences.getValue("cura/categories_expanded")
if categories_expanded is None:

View File

@ -0,0 +1,254 @@
[general]
name = Advanced
weight = 2
[machine_settings]
[resolution]
layer_height
layer_height_0
line_width
[shell]
wall_extruder_nr
wall_thickness
wall_0_wipe_dist
roofing_extruder_nr
roofing_layer_count
top_bottom_extruder_nr
top_bottom_thickness
top_bottom_pattern
top_bottom_pattern_0
skin_angles
wall_0_inset
optimize_wall_printing_order
outer_inset_first
alternate_extra_perimeter
travel_compensate_overlapping_walls_enabled
fill_perimeter_gaps
filter_out_tiny_gaps
fill_outline_gaps
xy_offset
xy_offset_layer_0
z_seam_type
z_seam_x
z_seam_y
z_seam_corner
z_seam_relative
skin_no_small_gaps_heuristic
skin_outline_count
ironing_enabled
ironing_only_highest_layer
ironing_pattern
ironing_line_spacing
ironing_flow
ironing_inset
speed_ironing
acceleration_ironing
jerk_ironing
[infill]
infill_extruder_nr
infill_sparse_density
infill_pattern
zig_zaggify_infill
infill_angles
infill_offset_x
infill_offset_y
sub_div_rad_add
infill_overlap
skin_overlap
infill_wipe_dist
infill_sparse_thickness
gradual_infill_steps
gradual_infill_step_height
infill_before_walls
min_infill_area
skin_preshrink
expand_skins_expand_distance
max_skin_angle_for_expansion
[material]
default_material_print_temperature
material_print_temperature
material_print_temperature_layer_0
material_initial_print_temperature
material_final_print_temperature
material_extrusion_cool_down_speed
default_material_bed_temperature
material_bed_temperature
material_bed_temperature_layer_0
material_diameter
material_adhesion_tendency
material_surface_energy
material_flow
retraction_enable
retract_at_layer_change
retraction_amount
retraction_speed
retraction_extra_prime_amount
retraction_min_travel
retraction_count_max
retraction_extrusion_window
material_standby_temperature
switch_extruder_retraction_amount
switch_extruder_retraction_speeds
[speed]
speed_print
speed_travel
speed_layer_0
skirt_brim_speed
max_feedrate_z_override
speed_slowdown_layers
speed_equalize_flow_enabled
speed_equalize_flow_max
acceleration_enabled
acceleration_print
acceleration_travel
acceleration_layer_0
acceleration_skirt_brim
jerk_enabled
jerk_print
jerk_travel
jerk_layer_0
jerk_skirt_brim
[travel]
retraction_combing
travel_retract_before_outer_wall
travel_avoid_other_parts
travel_avoid_distance
start_layers_at_same_position
layer_start_x
layer_start_y
retraction_hop_enabled
retraction_hop_only_when_collides
retraction_hop
retraction_hop_after_extruder_switch
[cooling]
cool_fan_enabled
cool_fan_speed
cool_min_layer_time_fan_speed_max
cool_fan_speed_0
cool_fan_full_at_height
cool_min_layer_time
cool_min_speed
cool_lift_head
[support]
support_enable
support_extruder_nr
support_type
support_angle
support_pattern
support_connect_zigzags
support_infill_rate
support_z_distance
support_xy_distance
support_xy_overrides_z
support_xy_distance_overhang
support_bottom_stair_step_height
support_bottom_stair_step_width
support_join_distance
support_offset
support_infill_sparse_thickness
gradual_support_infill_steps
gradual_support_infill_step_height
support_interface_enable
support_interface_height
support_interface_skip_height
support_interface_density
support_interface_pattern
support_use_towers
support_tower_diameter
support_minimal_diameter
support_tower_roof_angle
support_mesh_drop_down
[platform_adhesion]
prime_blob_enable
extruder_prime_pos_x
extruder_prime_pos_y
adhesion_type
adhesion_extruder_nr
skirt_line_count
skirt_gap
skirt_brim_minimal_length
brim_width
brim_outside_only
raft_margin
raft_smoothing
raft_airgap
layer_0_z_overlap
raft_surface_layers
raft_surface_thickness
raft_surface_line_width
raft_surface_line_spacing
raft_interface_thickness
raft_interface_line_width
raft_interface_line_spacing
raft_base_thickness
raft_base_line_width
raft_base_line_spacing
raft_speed
raft_acceleration
raft_jerk
raft_fan_speed
[dual]
prime_tower_enable
prime_tower_size
prime_tower_min_volume
prime_tower_position_x
prime_tower_position_y
prime_tower_flow
prime_tower_wipe_enabled
dual_pre_wipe
prime_tower_purge_volume
ooze_shield_enabled
ooze_shield_angle
ooze_shield_dist
[meshfix]
meshfix_union_all
meshfix_union_all_remove_holes
meshfix_extensive_stitching
meshfix_keep_open_polygons
multiple_mesh_overlap
carve_multiple_volumes
alternate_carve_order
remove_empty_first_layers
[blackmagic]
print_sequence
infill_mesh
infill_mesh_order
cutting_mesh
mold_enabled
mold_width
mold_roof_height
mold_angle
support_mesh
anti_overhang_mesh
magic_mesh_surface_mode
magic_spiralize
smooth_spiralized_contours
relative_extrusion
[experimental]
infill_enable_travel_optimization
material_flow_dependent_temperature
material_flow_temp_graph
meshfix_maximum_resolution
roofing_angles
roofing_pattern
slicing_tolerance
support_tree_angle
support_tree_branch_diameter
support_tree_branch_diameter_angle
support_tree_branch_distance
support_tree_collision_resolution
support_tree_enable
support_tree_wall_thickness

View File

@ -0,0 +1,66 @@
[general]
name = Basic
weight = 1
[machine_settings]
[resolution]
layer_height
[shell]
wall_thickness
top_bottom_thickness
z_seam_x
z_seam_y
[infill]
infill_sparse_density
gradual_infill_steps
[material]
material_print_temperature
material_bed_temperature
material_diameter
material_flow
retraction_enable
[speed]
speed_print
speed_travel
acceleration_print
acceleration_travel
jerk_print
jerk_travel
[travel]
[cooling]
cool_fan_enabled
[support]
support_enable
support_extruder_nr
support_type
[platform_adhesion]
adhesion_type
adhesion_extruder_nr
brim_width
raft_airgap
layer_0_z_overlap
raft_surface_layers
[dual]
prime_tower_enable
prime_tower_size
prime_tower_position_x
prime_tower_position_y
[meshfix]
[blackmagic]
print_sequence
infill_mesh
cutting_mesh
[experimental]

View File

@ -0,0 +1,285 @@
[general]
name = Expert
weight = 3
[machine_settings]
[resolution]
layer_height
layer_height_0
line_width
[shell]
wall_extruder_nr
wall_thickness
wall_0_wipe_dist
roofing_extruder_nr
roofing_layer_count
top_bottom_extruder_nr
top_bottom_thickness
top_bottom_pattern
top_bottom_pattern_0
skin_angles
wall_0_inset
optimize_wall_printing_order
outer_inset_first
alternate_extra_perimeter
travel_compensate_overlapping_walls_enabled
fill_perimeter_gaps
filter_out_tiny_gaps
fill_outline_gaps
xy_offset
xy_offset_layer_0
z_seam_type
z_seam_x
z_seam_y
z_seam_corner
z_seam_relative
skin_no_small_gaps_heuristic
skin_outline_count
ironing_enabled
ironing_only_highest_layer
ironing_pattern
ironing_line_spacing
ironing_flow
ironing_inset
speed_ironing
acceleration_ironing
jerk_ironing
[infill]
infill_extruder_nr
infill_sparse_density
infill_pattern
zig_zaggify_infill
infill_angles
infill_offset_x
infill_offset_y
sub_div_rad_add
infill_overlap
skin_overlap
infill_wipe_dist
infill_sparse_thickness
gradual_infill_steps
gradual_infill_step_height
infill_before_walls
min_infill_area
skin_preshrink
expand_skins_expand_distance
max_skin_angle_for_expansion
[material]
default_material_print_temperature
material_print_temperature
material_print_temperature_layer_0
material_initial_print_temperature
material_final_print_temperature
material_extrusion_cool_down_speed
default_material_bed_temperature
material_bed_temperature
material_bed_temperature_layer_0
material_diameter
material_adhesion_tendency
material_surface_energy
material_flow
retraction_enable
retract_at_layer_change
retraction_amount
retraction_speed
retraction_extra_prime_amount
retraction_min_travel
retraction_count_max
retraction_extrusion_window
material_standby_temperature
switch_extruder_retraction_amount
switch_extruder_retraction_speeds
[speed]
speed_print
speed_travel
speed_layer_0
skirt_brim_speed
max_feedrate_z_override
speed_slowdown_layers
speed_equalize_flow_enabled
speed_equalize_flow_max
acceleration_enabled
acceleration_print
acceleration_travel
acceleration_layer_0
acceleration_skirt_brim
jerk_enabled
jerk_print
jerk_travel
jerk_layer_0
jerk_skirt_brim
[travel]
retraction_combing
travel_retract_before_outer_wall
travel_avoid_other_parts
travel_avoid_distance
start_layers_at_same_position
layer_start_x
layer_start_y
retraction_hop_enabled
retraction_hop_only_when_collides
retraction_hop
retraction_hop_after_extruder_switch
[cooling]
cool_fan_enabled
cool_fan_speed
cool_min_layer_time_fan_speed_max
cool_fan_speed_0
cool_fan_full_at_height
cool_min_layer_time
cool_min_speed
cool_lift_head
[support]
support_enable
support_extruder_nr
support_type
support_angle
support_pattern
support_connect_zigzags
support_infill_rate
support_z_distance
support_xy_distance
support_xy_overrides_z
support_xy_distance_overhang
support_bottom_stair_step_height
support_bottom_stair_step_width
support_join_distance
support_offset
support_infill_sparse_thickness
gradual_support_infill_steps
gradual_support_infill_step_height
support_interface_enable
support_interface_height
support_interface_skip_height
support_interface_density
support_interface_pattern
support_use_towers
support_tower_diameter
support_minimal_diameter
support_tower_roof_angle
support_mesh_drop_down
[platform_adhesion]
prime_blob_enable
extruder_prime_pos_x
extruder_prime_pos_y
adhesion_type
adhesion_extruder_nr
skirt_line_count
skirt_gap
skirt_brim_minimal_length
brim_width
brim_outside_only
raft_margin
raft_smoothing
raft_airgap
layer_0_z_overlap
raft_surface_layers
raft_surface_thickness
raft_surface_line_width
raft_surface_line_spacing
raft_interface_thickness
raft_interface_line_width
raft_interface_line_spacing
raft_base_thickness
raft_base_line_width
raft_base_line_spacing
raft_speed
raft_acceleration
raft_jerk
raft_fan_speed
[dual]
prime_tower_enable
prime_tower_size
prime_tower_min_volume
prime_tower_position_x
prime_tower_position_y
prime_tower_flow
prime_tower_wipe_enabled
dual_pre_wipe
prime_tower_purge_volume
ooze_shield_enabled
ooze_shield_angle
ooze_shield_dist
[meshfix]
meshfix_union_all
meshfix_union_all_remove_holes
meshfix_extensive_stitching
meshfix_keep_open_polygons
multiple_mesh_overlap
carve_multiple_volumes
alternate_carve_order
remove_empty_first_layers
[blackmagic]
print_sequence
infill_mesh
infill_mesh_order
cutting_mesh
mold_enabled
mold_width
mold_roof_height
mold_angle
support_mesh
anti_overhang_mesh
magic_mesh_surface_mode
magic_spiralize
smooth_spiralized_contours
relative_extrusion
[experimental]
support_skip_some_zags
support_skip_zag_per_mm
draft_shield_enabled
draft_shield_dist
draft_shield_height_limitation
draft_shield_height
conical_overhang_enabled
conical_overhang_angle
coasting_enable
coasting_volume
coasting_min_volume
coasting_speed
skin_alternate_rotation
cross_infill_pocket_size
cross_infill_apply_pockets_alternatingly
spaghetti_infill_enabled
spaghetti_infill_stepped
spaghetti_max_infill_angle
spaghetti_max_height
spaghetti_inset
spaghetti_flow
spaghetti_infill_extra_volume
support_conical_enabled
support_conical_angle
support_conical_min_width
infill_hollow
magic_fuzzy_skin_enabled
magic_fuzzy_skin_thickness
magic_fuzzy_skin_point_density
flow_rate_max_extrusion_offset
flow_rate_extrusion_offset_factor
infill_enable_travel_optimization
material_flow_dependent_temperature
material_flow_temp_graph
meshfix_maximum_resolution
roofing_angles
roofing_pattern
slicing_tolerance
support_tree_angle
support_tree_branch_diameter
support_tree_branch_diameter_angle
support_tree_branch_distance
support_tree_collision_resolution
support_tree_enable
support_tree_wall_thickness

View File

@ -24,6 +24,11 @@ UM.PreferencesPage
function reset()
{
UM.Preferences.resetPreference("general/visible_settings")
// After calling this function update Setting visibility preset combobox.
// Reset should set "Basic" setting preset
visibilityPreset.setBasicPreset()
}
resetEnabled: true;
@ -72,6 +77,9 @@ UM.PreferencesPage
{
definitionsModel.setAllVisible(false)
}
// After change set "Custom" option
visibilityPreset.currentIndex = visibilityPreset.model.count - 1
}
}
}
@ -85,7 +93,8 @@ UM.PreferencesPage
top: parent.top
left: toggleVisibleSettings.right
leftMargin: UM.Theme.getSize("default_margin").width
right: parent.right
right: visibilityPreset.left
rightMargin: UM.Theme.getSize("default_margin").width
}
placeholderText: catalog.i18nc("@label:textbox", "Filter...")
@ -93,6 +102,86 @@ UM.PreferencesPage
onTextChanged: definitionsModel.filter = {"i18n_label": "*" + text}
}
ComboBox
{
property int customOptionValue: 100
function setBasicPreset()
{
var index = 0
for(var i = 0; i < presetNamesList.count; ++i)
{
if(model.get(i).text == "Basic")
{
index = i;
break;
}
}
visibilityPreset.currentIndex = index
}
id: visibilityPreset
width: 150
anchors
{
top: parent.top
right: parent.right
}
model: ListModel
{
id: presetNamesList
Component.onCompleted:
{
// returned value is Dictionary (Ex: {1:"Basic"}, The number 1 is the weight and sort by weight)
var itemsDict = UM.Preferences.getValue("general/visible_settings_preset")
var sorted = [];
for(var key in itemsDict) {
sorted[sorted.length] = key;
}
sorted.sort();
for(var i = 0; i < sorted.length; i++) {
presetNamesList.append({text: itemsDict[sorted[i]], value: i});
}
// By agreement lets "Custom" option will have value 100
presetNamesList.append({text: "Custom", value: visibilityPreset.customOptionValue});
}
}
currentIndex:
{
// Load previously selected preset.
var text = UM.Preferences.getValue("general/preset_setting_visibility_choice");
var index = 0;
for(var i = 0; i < presetNamesList.count; ++i)
{
if(model.get(i).text == text)
{
index = i;
break;
}
}
return index;
}
onActivated:
{
// TODO What to do if user is selected "Custom from Combobox" ?
if (model.get(index).text == "Custom")
return
var newVisibleSettings = CuraApplication.getVisibilitySettingPreset(model.get(index).text)
UM.Preferences.setValue("general/visible_settings", newVisibleSettings)
UM.Preferences.setValue("general/preset_setting_visibility_choice", model.get(index).text)
}
}
ScrollView
{
id: scrollView
@ -162,7 +251,18 @@ UM.PreferencesPage
{
id: settingVisibilityItem;
UM.SettingVisibilityItem { }
UM.SettingVisibilityItem {
// after changing any visibility of settings, set the preset to the "Custom" option
visibilityChangeCallback : function()
{
// If already "Custom" then don't do nothing
if (visibilityPreset.currentIndex != visibilityPreset.model.count - 1)
{
visibilityPreset.currentIndex = visibilityPreset.model.count - 1
}
}
}
}
}
}
}

View File

@ -0,0 +1,126 @@
#!/usr/bin/env python
import configparser
import json
import os
import sys
class PresetSettingsValidator:
def __init__(self, cura_dir: str):
self._cura_dir = os.path.abspath(cura_dir)
self._resource_dir = os.path.join(self._cura_dir, "resources")
self._definitions_dir = os.path.join(self._resource_dir, "definitions")
self._preset_settings_dir = os.path.join(self._resource_dir, "preset_setting_visibility_groups")
self._fdmprinter_def_path = os.path.join(self._definitions_dir, "fdmprinter.def.json")
def validate(self) -> bool:
"""
Validates the preset settings files and returns True or False indicating whether there are invalid files.
"""
if not os.path.isfile(self._fdmprinter_def_path):
raise FileNotFoundError("[%s] is not a file or doesn't exist, please make sure you have specified the correct cura directory [%s]." % (self._fdmprinter_def_path, self._cura_dir))
if not os.path.isdir(self._preset_settings_dir):
raise FileNotFoundError("[%s] is not a directory or doesn't exist, please make sure you have specified the correct cura directory [%s]." % (self._preset_settings_dir, self._cura_dir))
# parse the definition file
setting_tree_dict = self._parse_definition_file(self._fdmprinter_def_path)
has_invalid_files = False
# go through all the preset settings files
for root_dir, _, filenames in os.walk(self._preset_settings_dir):
for filename in filenames:
file_path = os.path.join(root_dir, filename)
print("Validating [%s] ..." % file_path)
incorrect_sections = []
incorrect_settings = {}
parser = configparser.ConfigParser(allow_no_value = True)
with open(file_path, "r", encoding = "utf-8") as f:
parser.read_file(f)
for key in parser:
# skip general
if key in ("general", configparser.DEFAULTSECT):
continue
if key not in setting_tree_dict:
incorrect_sections.append(key)
continue
for setting_key in parser[key]:
if setting_key not in setting_tree_dict[key]:
if setting_key not in incorrect_settings:
incorrect_settings[setting_key] = {"seen_in": [],
"should_be_in": self._should_setting_be_in(setting_tree_dict, setting_key)}
incorrect_settings[setting_key]["seen_in"].append(key)
# show results
print("==========================================")
if incorrect_sections or incorrect_settings:
has_invalid_files = True
print("[INVALID] [%s] is invalid, details below" % file_path)
# show details
for section_name in sorted(incorrect_sections):
print(" -- section name [%s] is incorrect, please check fdmprinter.def.json." % section_name)
for setting_name in sorted(incorrect_settings.keys()):
details_dict = incorrect_settings[setting_name]
msg = " -- setting [%s] is found in sections [%s], " % (setting_name, ", ".join(details_dict["seen_in"]))
if details_dict["should_be_in"] is not None:
msg += "but should be in section [%s] only." % details_dict["should_be_in"]
else:
msg += "but it cannot be found in fdmprinter.def.json"
print(msg)
else:
print("[%s] is valid" % file_path)
print("==========================================")
return not has_invalid_files
def _parse_definition_file(self, file_path: str):
with open(file_path, "r", encoding = "utf-8") as f:
def_dict = json.load(f, encoding = "utf-8")
tree_dict = {}
for key, item in def_dict.get("settings", {}).items():
setting_list = []
self._generate_tree(setting_list, item.get("children", {}))
tree_dict[key] = setting_list
return tree_dict
def _generate_tree(self, setting_list: list, setting_dict: dict):
for key, item in setting_dict.items():
setting_list.append(key)
if "children" in item:
self._generate_tree(setting_list, item["children"])
def _should_setting_be_in(self, setting_dict: dict, setting_name: str) -> str:
"""
Check which section the given setting belongs to. Returns None if the setting cannot be found.
"""
section_name = None
for key, setting_list in setting_dict.items():
if setting_name in setting_list:
section_name = key
break
return section_name
if __name__ == "__main__":
script_dir = os.path.dirname(os.path.realpath(__file__))
cura_dir = os.path.abspath(os.path.join(script_dir, ".."))
validator = PresetSettingsValidator(cura_dir)
is_everything_validate = validator.validate()
ret_code = 0 if is_everything_validate else 1
sys.exit(ret_code)