From 269b52487ed28e42daf7e2716117c4d3d27bc2fa Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Wed, 22 Nov 2017 17:15:47 +0100 Subject: [PATCH 001/371] CuraApplication/UM.MeshBuilder: Removing _reloadMeshFinished If this commit gets merged into Uranium, then _reloadMeshFinished is not needed anymore. https://github.com/Ultimaker/Uranium/commit/31bff5b9b9797fb5654ea8ed74a51fff42600e1d The function has been moved, so reloading a mesh after a file has been modified is possible. --- cura/CuraApplication.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index b3e6caed4e..996a1ffd9a 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1151,7 +1151,7 @@ class CuraApplication(QtApplication): if file_name: job = ReadMeshJob(file_name) job._node = node - job.finished.connect(self._reloadMeshFinished) + job.finished.connect(node._reloadJobFinished) job.start() else: Logger.log("w", "Unable to reload data because we don't have a filename.") @@ -1278,14 +1278,6 @@ class CuraApplication(QtApplication): fileLoaded = pyqtSignal(str) - def _reloadMeshFinished(self, job): - # TODO; This needs to be fixed properly. We now make the assumption that we only load a single mesh! - mesh_data = job.getResult()[0].getMeshData() - if mesh_data: - job._node.setMeshData(mesh_data) - else: - Logger.log("w", "Could not find a mesh in reloaded node.") - def _openFile(self, filename): self.readLocalFile(QUrl.fromLocalFile(filename)) From abe9c204a9e97b753fa4812f7e49f165c3b21913 Mon Sep 17 00:00:00 2001 From: krios-fabteam Date: Mon, 29 Jan 2018 16:41:21 +0100 Subject: [PATCH 002/371] added tpu qualities default fan value for abs set to false changed M728 with M300 in start and end gcode --- resources/definitions/fabtotum.def.json | 4 ++-- .../fabtotum/fabtotum_abs_fast.inst.cfg | 4 ++-- .../fabtotum/fabtotum_abs_high.inst.cfg | 4 ++-- .../fabtotum/fabtotum_abs_normal.inst.cfg | 4 ++-- .../fabtotum/fabtotum_tpu_fast.inst.cfg | 24 +++++++++++++++++++ .../fabtotum/fabtotum_tpu_high.inst.cfg | 24 +++++++++++++++++++ .../fabtotum/fabtotum_tpu_normal.inst.cfg | 24 +++++++++++++++++++ 7 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg create mode 100644 resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg create mode 100644 resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg diff --git a/resources/definitions/fabtotum.def.json b/resources/definitions/fabtotum.def.json index 87ce11a35c..751db3d80c 100644 --- a/resources/definitions/fabtotum.def.json +++ b/resources/definitions/fabtotum.def.json @@ -21,10 +21,10 @@ "overrides": { "machine_name": { "default_value": "FABtotum Personal Fabricator" }, "machine_start_gcode": { - "default_value": ";Layer height: {layer_height}\n;Walls: {wall_thickness}\n;Fill: {infill_sparse_density}\n;Top\\Bottom Thickness: {top_bottom_thickness}\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nG4 S1 ;1 millisecond pause to buffer the bep bep \nM728 ;FAB bep bep (start the print, go check the oozing and skirt lines adesion) \nG4 S1 ;1 second pause to reach the printer (run fast)\nG92 E0 ;zero the extruded length \nG1 F200 E35 ;slowly extrude 35mm of filament to clean the nozzle and build up extrusion pressure \nG92 E0 ;zero the extruded length again \nG1 F{speed_travel} ;Set travel speed \n;print" + "default_value": ";Layer height: {layer_height}\n;Walls: {wall_thickness}\n;Fill: {infill_sparse_density}\n;Top\\Bottom Thickness: {top_bottom_thickness}\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nG4 S1 ;1 millisecond pause to buffer the bep bep \nM300 ;FAB bep bep (start the print, go check the oozing and skirt lines adesion) \nG4 S1 ;1 second pause to reach the printer (run fast)\nG92 E0 ;zero the extruded length \nG1 F200 E35 ;slowly extrude 35mm of filament to clean the nozzle and build up extrusion pressure \nG92 E0 ;zero the extruded length again \nG1 F{speed_travel} ;Set travel speed \n;print" }, "machine_end_gcode": { - "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-3 X+5 Y+5 F5000 ;move Z up a bit and retract filament even more\n;end of the print\nM84 ;steppers off\nG90 ;absolute positioning\nM728 ;FAB bep bep (end print)" + "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-3 X+5 Y+5 F5000 ;move Z up a bit and retract filament even more\n;end of the print\nM84 ;steppers off\nG90 ;absolute positioning\nM300 ;FAB bep bep (end print)" }, "gantry_height": { "default_value": 55 }, "machine_width": { "default_value": 214 }, diff --git a/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg index 245997a27e..756ed3746c 100644 --- a/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg @@ -5,7 +5,7 @@ name = Fast Quality [metadata] type = quality -setting_version = 4 +setting_version = 3 material = fabtotum_abs quality_type = fast weight = -1 @@ -14,7 +14,7 @@ weight = -1 adhesion_type = raft layer_height = 0.2 layer_height_0 = 0.2 -cool_fan_enabled = True +cool_fan_enabled = False cool_fan_full_at_height = 0.4 cool_fan_speed = 50 cool_fan_speed_max = 50 diff --git a/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg index 26300eec7d..60f5d9df3e 100644 --- a/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg @@ -5,7 +5,7 @@ name = High Quality [metadata] type = quality -setting_version = 4 +setting_version = 3 material = fabtotum_abs quality_type = high weight = 1 @@ -14,7 +14,7 @@ weight = 1 adhesion_type = raft layer_height = 0.1 layer_height_0 = 0.1 -cool_fan_enabled = True +cool_fan_enabled = False cool_fan_full_at_height = 0.2 cool_fan_speed = 50 cool_fan_speed_max = 50 diff --git a/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg index 53d20c8cbc..ec4d76c89b 100644 --- a/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg @@ -5,7 +5,7 @@ name = Normal Quality [metadata] type = quality -setting_version = 4 +setting_version = 3 material = fabtotum_abs quality_type = normal weight = 0 @@ -14,7 +14,7 @@ weight = 0 adhesion_type = raft layer_height = 0.15 layer_height_0 = 0.15 -cool_fan_enabled = True +cool_fan_enabled = False cool_fan_full_at_height = 0.3 cool_fan_speed = 50 cool_fan_speed_max = 50 diff --git a/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg new file mode 100644 index 0000000000..bf8ba4bbe6 --- /dev/null +++ b/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 2 +definition = fabtotum +name = Fast Quality + +[metadata] +type = quality +setting_version = 3 +material = fabtotum_tpu +quality_type = fast +weight = -1 + +[values] +adhesion_type = skirt +layer_height = 0.2 +layer_height_0 = 0.2 +cool_fan_enabled = True +cool_fan_full_at_height = 0.4 +cool_fan_speed = 100 +cool_fan_speed_max = 100 +cool_fan_speed_min = 100 +cool_min_layer_time = 5 +cool_min_speed = 20 + diff --git a/resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg b/resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg new file mode 100644 index 0000000000..12e4418490 --- /dev/null +++ b/resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 2 +definition = fabtotum +name = High Quality + +[metadata] +type = quality +setting_version = 3 +material = fabtotum_tpu +quality_type = high +weight = 1 + +[values] +adhesion_type = skirt +layer_height = 0.1 +layer_height_0 = 0.1 +cool_fan_enabled = True +cool_fan_full_at_height = 0.2 +cool_fan_speed = 100 +cool_fan_speed_max = 100 +cool_fan_speed_min = 100 +cool_min_layer_time = 5 +cool_min_speed = 20 + diff --git a/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg new file mode 100644 index 0000000000..07709e2db8 --- /dev/null +++ b/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 2 +definition = fabtotum +name = Normal Quality + +[metadata] +type = quality +setting_version = 3 +material = fabtotum_TPU +quality_type = normal +weight = 0 + +[values] +adhesion_type = skirt +layer_height = 0.15 +layer_height_0 = 0.15 +cool_fan_enabled = True +cool_fan_full_at_height = 0.3 +cool_fan_speed = 100 +cool_fan_speed_max = 100 +cool_fan_speed_min = 100 +cool_min_layer_time = 5 +cool_min_speed = 20 + From 5386de3182176944666d5ebee380bd10dd66cafd Mon Sep 17 00:00:00 2001 From: krios-fabteam Date: Mon, 29 Jan 2018 16:45:35 +0100 Subject: [PATCH 003/371] fixed setting version --- resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg | 2 +- resources/quality/fabtotum/fabtotum_abs_high.inst.cfg | 2 +- resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg | 2 +- resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg | 2 +- resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg | 2 +- resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg index 756ed3746c..3182efdb62 100644 --- a/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg @@ -5,7 +5,7 @@ name = Fast Quality [metadata] type = quality -setting_version = 3 +setting_version = 4 material = fabtotum_abs quality_type = fast weight = -1 diff --git a/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg index 60f5d9df3e..ea56d0092f 100644 --- a/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg @@ -5,7 +5,7 @@ name = High Quality [metadata] type = quality -setting_version = 3 +setting_version = 4 material = fabtotum_abs quality_type = high weight = 1 diff --git a/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg index ec4d76c89b..1085b2b1cc 100644 --- a/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg @@ -5,7 +5,7 @@ name = Normal Quality [metadata] type = quality -setting_version = 3 +setting_version = 4 material = fabtotum_abs quality_type = normal weight = 0 diff --git a/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg index bf8ba4bbe6..6026079e53 100644 --- a/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg @@ -5,7 +5,7 @@ name = Fast Quality [metadata] type = quality -setting_version = 3 +setting_version = 4 material = fabtotum_tpu quality_type = fast weight = -1 diff --git a/resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg b/resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg index 12e4418490..315a56015d 100644 --- a/resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_tpu_high.inst.cfg @@ -5,7 +5,7 @@ name = High Quality [metadata] type = quality -setting_version = 3 +setting_version = 4 material = fabtotum_tpu quality_type = high weight = 1 diff --git a/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg index 07709e2db8..75a8430166 100644 --- a/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg @@ -5,7 +5,7 @@ name = Normal Quality [metadata] type = quality -setting_version = 3 +setting_version = 4 material = fabtotum_TPU quality_type = normal weight = 0 From 64f0f5db425a403b04c4462a3fde93ed8f2c8563 Mon Sep 17 00:00:00 2001 From: angelo-fabteam Date: Tue, 30 Jan 2018 09:24:11 +0100 Subject: [PATCH 004/371] Added speed print definition --- resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg index 75a8430166..3ce1592e70 100644 --- a/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_tpu_normal.inst.cfg @@ -12,6 +12,7 @@ weight = 0 [values] adhesion_type = skirt +speed_print = 80 layer_height = 0.15 layer_height_0 = 0.15 cool_fan_enabled = True From 0f48bf03a5278b1f70f22b14c762a5942a611ba8 Mon Sep 17 00:00:00 2001 From: angelo-fabteam Date: Tue, 30 Jan 2018 09:30:39 +0100 Subject: [PATCH 005/371] Added speed print definition --- resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg index 6026079e53..d8ee095d61 100644 --- a/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_tpu_fast.inst.cfg @@ -12,6 +12,7 @@ weight = -1 [values] adhesion_type = skirt +speed_print = 80 layer_height = 0.2 layer_height_0 = 0.2 cool_fan_enabled = True From c83f983440259081d9b9919352b5431548333e04 Mon Sep 17 00:00:00 2001 From: krios-fabteam Date: Tue, 30 Jan 2018 09:49:17 +0100 Subject: [PATCH 006/371] added speed print to fabtotum qualities --- resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg | 1 + resources/quality/fabtotum/fabtotum_abs_high.inst.cfg | 1 + resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg | 1 + resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg | 2 +- resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg | 2 +- resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg | 2 +- resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg | 1 + resources/quality/fabtotum/fabtotum_pla_high.inst.cfg | 1 + resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg | 1 + 9 files changed, 9 insertions(+), 3 deletions(-) diff --git a/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg index 3182efdb62..fe68b4a76e 100644 --- a/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg @@ -12,6 +12,7 @@ weight = -1 [values] adhesion_type = raft +speed_print = 80 layer_height = 0.2 layer_height_0 = 0.2 cool_fan_enabled = False diff --git a/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg index ea56d0092f..dd1f58a59a 100644 --- a/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg @@ -12,6 +12,7 @@ weight = 1 [values] adhesion_type = raft +speed_print = 45 layer_height = 0.1 layer_height_0 = 0.1 cool_fan_enabled = False diff --git a/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg index 1085b2b1cc..31c588c498 100644 --- a/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg @@ -12,6 +12,7 @@ weight = 0 [values] adhesion_type = raft +speed_print = 60 layer_height = 0.15 layer_height_0 = 0.15 cool_fan_enabled = False diff --git a/resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg index 22bbcbeaeb..86eb5326e0 100644 --- a/resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg @@ -44,7 +44,7 @@ skirt_gap = 1.5 skirt_line_count = 5 speed_infill = =speed_print speed_layer_0 = 25 -speed_print = 50 +speed_print = 30 speed_topbottom = 40 speed_travel = 200 speed_wall_0 = 40 diff --git a/resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg b/resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg index a625bd715f..8585323537 100644 --- a/resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg @@ -44,7 +44,7 @@ skirt_gap = 1.5 skirt_line_count = 5 speed_infill = =speed_print speed_layer_0 = 25 -speed_print = 50 +speed_print = 30 speed_topbottom = 40 speed_travel = 200 speed_wall_0 = 40 diff --git a/resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg index b05d30c5c6..99ab0e10cb 100644 --- a/resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg @@ -44,7 +44,7 @@ skirt_gap = 1.5 skirt_line_count = 5 speed_infill = =speed_print speed_layer_0 = 25 -speed_print = 50 +speed_print = 30 speed_topbottom = 40 speed_travel = 200 speed_wall_0 = 40 diff --git a/resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg index 1f1c93961b..5b4cb737ff 100644 --- a/resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg @@ -12,6 +12,7 @@ weight = -1 [values] adhesion_type = skirt +speed_print = 80 layer_height = 0.2 layer_height_0 = 0.2 cool_fan_enabled = True diff --git a/resources/quality/fabtotum/fabtotum_pla_high.inst.cfg b/resources/quality/fabtotum/fabtotum_pla_high.inst.cfg index 9cd067703c..e427372010 100644 --- a/resources/quality/fabtotum/fabtotum_pla_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_pla_high.inst.cfg @@ -12,6 +12,7 @@ weight = 1 [values] adhesion_type = skirt +speed_print = 45 layer_height = 0.1 layer_height_0 = 0.1 cool_fan_enabled = True diff --git a/resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg index 5b5125c4e5..ee22d8fa9a 100644 --- a/resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg @@ -12,6 +12,7 @@ weight = 0 [values] adhesion_type = skirt +speed_print = 60 layer_height = 0.15 layer_height_0 = 0.15 cool_fan_enabled = True From f9a0b1db50df91bc6f9b3a3e0c9f4c1c1048806a Mon Sep 17 00:00:00 2001 From: Orel Date: Thu, 1 Feb 2018 09:40:43 +0100 Subject: [PATCH 007/371] Enhance Dagoma DiscoEasy200 profile and add Dagoma Neva stuff (profile and mesh). --- .../definitions/dagoma_discoeasy200.def.json | 17 ++++- resources/definitions/dagoma_neva.def.json | 69 ++++++++++++++++++ resources/meshes/neva.stl | Bin 0 -> 334484 bytes 3 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 resources/definitions/dagoma_neva.def.json create mode 100644 resources/meshes/neva.stl diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json index 9bcc2402f2..1674801b5e 100644 --- a/resources/definitions/dagoma_discoeasy200.def.json +++ b/resources/definitions/dagoma_discoeasy200.def.json @@ -7,7 +7,6 @@ "author": "Dagoma", "manufacturer": "Dagoma", "file_formats": "text/x-gcode", - "icon": "icon_discoeasy200.png", "platform": "discoeasy200.stl", "platform_offset": [ 105, -59, 280] }, @@ -39,13 +38,25 @@ "default_value": 10 }, "machine_start_gcode": { - "default_value": ";Gcode by Cura\nG90 ;absolute positioning\nM106 S250 ;fan on for the palpeur\nG28 X Y\nG1 X50\nM109 S180\nG28\nM104 S{material_print_temperature_layer_0}\n;Activation palpeur\n;bloc palpeur\nG29 ;Auto level\nM107 ;start with the fan off\nG1 X100 Y20 F3000\nG1 Z0.5\nM109 S{material_print_temperature_layer_0}\nM82 ;set extruder to absolute mode\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 Z3\nG1 F6000" + "default_value": ";Gcode by Cura\nG90\nM106 S250\nG28 X Y\nG1 X50\nM109 S180\nG28\nM104 S{material_print_temperature_layer_0}\nG29\nM107\nG1 X100 Y20 F3000\nG1 Z0.5\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E10\nG92 E0\nG1 Z3\nG1 F6000\n" }, "machine_end_gcode": { - "default_value": "M104 S0\nM106 S255 ;start fan full power\nM140 S0 ;heated bed heater off (if you have it)\n;Home machine\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+3 F3000 ;move Z up a bit and retract filament even more\nG90\nG28 X Y\n;Ventilation forcee\nM107 ;stop fan\n;Shut down motor\nM84 ;shut down motors" + "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 F3000\nG90\nG28 X Y\nM107\nM84\n" }, "material_diameter": { "default_value": 1.75 + }, + "speed_print": { + "default_value": 60 + }, + "speed_travel": { + "default_value": 100 + }, + "retraction_amount": { + "default_value": 3.5 + }, + "retraction_speed": { + "default_value": 50 } } } diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json new file mode 100644 index 0000000000..430d2f6ab1 --- /dev/null +++ b/resources/definitions/dagoma_neva.def.json @@ -0,0 +1,69 @@ +{ + "id": "Dagoma_neva", + "name": "Dagoma NEVA", + "version": 2, + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "Dagoma", + "manufacturer": "Dagoma", + "file_formats": "text/x-gcode", + "platform": "neva.stl", + "platform_offset": [ 0, 0, 0] + }, + "overrides": { + "machine_width": { + "default_value": 195.55 + }, + "machine_height": { + "default_value": 205 + }, + "machine_depth": { + "default_value": 195.55 + }, + "machine_center_is_zero": { + "default_value": true + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "machine_head_with_fans_polygon": { + "default_value": [ + [17, 40], + [17, -70], + [-17, -70], + [17, 40] + ] + }, + "gantry_height": { + "default_value": 0 + }, + "machine_shape": { + "default_value": "elliptic" + }, + "machine_gcode_flavor": { + "default_value": "RepRap" + }, + "machine_start_gcode": { + "default_value": ";Gcode by Cura\nG90\nG28\nM109 S100\nG29\nM104 S{material_print_temperature_layer_0}\nG0 X0 Y-85\nG0 Z0.26\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n" + }, + "machine_end_gcode": { + "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n" + }, + "material_diameter": { + "default_value": 1.75 + }, + "speed_print": { + "default_value": 40 + }, + "speed_travel": { + "default_value": 120 + }, + "retraction_amount": { + "default_value": 3.8 + }, + "retraction_speed": { + "default_value": 60 + } + } +} diff --git a/resources/meshes/neva.stl b/resources/meshes/neva.stl new file mode 100644 index 0000000000000000000000000000000000000000..72ec185bd9320bc10fa3f7c0fa3c205aabb63e0a GIT binary patch literal 334484 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 Y!FyODM#yN#Sd+*H)`c|iTV0a=1NfM=g8%>k literal 0 HcmV?d00001 From 5688a99ece4abf84ea1afcbf4d3e263a6881e2c3 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 1 Feb 2018 21:00:28 +0800 Subject: [PATCH 008/371] update fdmprinter.def.json.po for cura 3.2 --- resources/i18n/zh_TW/fdmprinter.def.json.po | 74 ++++++++++----------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/resources/i18n/zh_TW/fdmprinter.def.json.po b/resources/i18n/zh_TW/fdmprinter.def.json.po index 7c9d882750..d12b05d56a 100644 --- a/resources/i18n/zh_TW/fdmprinter.def.json.po +++ b/resources/i18n/zh_TW/fdmprinter.def.json.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: Cura 3.1\n" "Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n" "POT-Creation-Date: 2017-08-02 16:53+0000\n" -"PO-Revision-Date: 2017-11-25 00:31+0800\n" +"PO-Revision-Date: 2018-02-01 20:58+0800\n" "Last-Translator: Zhang Heh Ji \n" "Language-Team: TEAM\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.0.4\n" +"X-Generator: Poedit 2.0.6\n" #: fdmprinter.def.json msgctxt "machine_settings label" @@ -353,12 +353,12 @@ msgstr "Repetier" #: fdmprinter.def.json msgctxt "machine_firmware_retract label" msgid "Firmware Retraction" -msgstr "" +msgstr "韌體回抽" #: fdmprinter.def.json msgctxt "machine_firmware_retract description" msgid "Whether to use firmware retract commands (G10/G11) instead of using the E property in G1 commands to retract the material." -msgstr "" +msgstr "是否使用韌體回抽命令(G10/G11)取代 G1 命令的 E 參數來回抽線材。" #: fdmprinter.def.json msgctxt "machine_disallowed_areas label" @@ -1053,12 +1053,12 @@ msgstr "全部填充" #: fdmprinter.def.json msgctxt "filter_out_tiny_gaps label" msgid "Filter Out Tiny Gaps" -msgstr "" +msgstr "濾除微小間隙" #: fdmprinter.def.json msgctxt "filter_out_tiny_gaps description" msgid "Filter out tiny gaps to reduce blobs on outside of model." -msgstr "" +msgstr "濾除微小間隙以減少模型外側的斑點 。" #: fdmprinter.def.json msgctxt "fill_outline_gaps label" @@ -1443,7 +1443,7 @@ msgstr "填充 X 軸偏移" #: fdmprinter.def.json msgctxt "infill_offset_x description" msgid "The infill pattern is moved this distance along the X axis." -msgstr "" +msgstr "填充樣式在 X 軸方向平移此距離。" #: fdmprinter.def.json msgctxt "infill_offset_y label" @@ -1453,7 +1453,7 @@ msgstr "填充 Y 軸偏移" #: fdmprinter.def.json msgctxt "infill_offset_y description" msgid "The infill pattern is moved this distance along the Y axis." -msgstr "" +msgstr "填充樣式在 Y 軸方向平移此距離。" #: fdmprinter.def.json msgctxt "sub_div_rad_add label" @@ -1473,7 +1473,7 @@ msgstr "填充重疊百分比" #: fdmprinter.def.json msgctxt "infill_overlap description" msgid "The amount of overlap between the infill and the walls as a percentage of the infill line width. A slight overlap allows the walls to connect firmly to the infill." -msgstr "" +msgstr "填充與牆壁的重疊量佔填充線寬的百分比。輕微的重疊能讓填充與牆壁牢固地連接。" #: fdmprinter.def.json msgctxt "infill_overlap_mm label" @@ -1493,7 +1493,7 @@ msgstr "表層重疊百分比" #: fdmprinter.def.json msgctxt "skin_overlap description" msgid "The amount of overlap between the skin and the walls as a percentage of the skin line width. A slight overlap allows the walls to connect firmly to the skin. This is a percentage of the average line widths of the skin lines and the innermost wall." -msgstr "" +msgstr "表層與牆壁的重疊量佔表層線寬的百分比。輕微的重疊能讓填充與表層牢固地連接。這是表層線寬和最內層牆壁線寬平均的百分比。" #: fdmprinter.def.json msgctxt "skin_overlap_mm label" @@ -1723,7 +1723,7 @@ msgstr "列印平台溫度" #: fdmprinter.def.json msgctxt "material_bed_temperature description" msgid "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted." -msgstr "" +msgstr "設定列印平台的溫度。如果設定為 0,就不會加熱列印平台。" #: fdmprinter.def.json msgctxt "material_bed_temperature_layer_0 label" @@ -4267,82 +4267,82 @@ msgstr "實驗性!" #: fdmprinter.def.json msgctxt "support_tree_enable label" msgid "Tree Support" -msgstr "" +msgstr "樹狀支撐" #: fdmprinter.def.json msgctxt "support_tree_enable description" msgid "Generate a tree-like support with branches that support your print. This may reduce material usage and print time, but greatly increases slicing time." -msgstr "" +msgstr "產生帶有樹枝樹狀支撐結構支撐你的模型。這可能可以減少耗材的使用和列印的時間,但會大大的增加切片時間。" #: fdmprinter.def.json msgctxt "support_tree_angle label" msgid "Tree Support Branch Angle" -msgstr "" +msgstr "樹狀支撐樹枝角度" #: fdmprinter.def.json msgctxt "support_tree_angle description" msgid "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach." -msgstr "" +msgstr "樹枝的角度。使用較小的角度讓樹枝較垂直且較平穩。使用較大的角度則可以支撐較大的範圍。" #: fdmprinter.def.json msgctxt "support_tree_branch_distance label" msgid "Tree Support Branch Distance" -msgstr "" +msgstr "樹狀支撐樹枝距離" #: fdmprinter.def.json msgctxt "support_tree_branch_distance description" msgid "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove." -msgstr "" +msgstr "樹支與模型接觸的點與點之間的間隔距離。較小的距離會讓支撐和模型有較多的接觸點,會有較佳的懸垂但支撐也較難移除。" #: fdmprinter.def.json msgctxt "support_tree_branch_diameter label" msgid "Tree Support Branch Diameter" -msgstr "" +msgstr "樹狀支撐樹枝直徑" #: fdmprinter.def.json msgctxt "support_tree_branch_diameter description" msgid "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this." -msgstr "" +msgstr "樹狀支撐中最細樹枝的直徑。越粗的樹枝越堅固。底部的樹枝會比這更粗。" #: fdmprinter.def.json msgctxt "support_tree_branch_diameter_angle label" msgid "Tree Support Branch Diameter Angle" -msgstr "" +msgstr "樹狀支撐樹枝外徑角度" #: fdmprinter.def.json msgctxt "support_tree_branch_diameter_angle description" msgid "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support." -msgstr "" +msgstr "樹枝向底部逐漸變粗時,外徑變化的角度。設為 0 可讓整條樹枝的粗細一致, 而有點角度可增加樹狀支撐的穩定性。" #: fdmprinter.def.json msgctxt "support_tree_collision_resolution label" msgid "Tree Support Collision Resolution" -msgstr "" +msgstr "樹狀支撐碰撞計算精度" #: fdmprinter.def.json msgctxt "support_tree_collision_resolution description" msgid "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically." -msgstr "" +msgstr "計算避免碰撞模型的計算精度。設定較低的值可產生較精確的樹狀支撐,這樣的支撐問題較少但會嚴重的增加切片所需的時間。" #: fdmprinter.def.json msgctxt "support_tree_wall_thickness label" msgid "Tree Support Wall Thickness" -msgstr "" +msgstr "樹狀支撐牆厚" #: fdmprinter.def.json msgctxt "support_tree_wall_thickness description" msgid "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily." -msgstr "" +msgstr "樹狀支撐樹枝的牆壁厚度。較厚的牆壁需要花較長的時間列印,但較不易倒下。" #: fdmprinter.def.json msgctxt "support_tree_wall_count label" msgid "Tree Support Wall Line Count" -msgstr "" +msgstr "樹狀支撐牆壁線條數量" #: fdmprinter.def.json msgctxt "support_tree_wall_count description" msgid "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily." -msgstr "" +msgstr "樹狀支撐樹枝牆壁的圈數。較厚的牆壁需要花較長的時間列印,但較不易倒下。" #: fdmprinter.def.json msgctxt "slicing_tolerance label" @@ -4417,12 +4417,12 @@ msgstr "當頂部表層採用線條或鋸齒狀的列印樣式時使用的整數 #: fdmprinter.def.json msgctxt "infill_enable_travel_optimization label" msgid "Infill Travel Optimization" -msgstr "" +msgstr "填充空跑最佳化" #: fdmprinter.def.json msgctxt "infill_enable_travel_optimization description" msgid "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased." -msgstr "" +msgstr "當功能啟用時,填充線條的列印順序會對降低空跑距離做最佳化。所能減少的空跑時間取決於模型、填充樣式、填充密度等。請注意,對於有很多小型填充區域的模型,切片時間可能會大量增加。" #: fdmprinter.def.json msgctxt "material_flow_dependent_temperature label" @@ -5056,42 +5056,42 @@ msgstr "噴頭和水平下行線之間的距離。較大的間隙會讓斜下行 #: fdmprinter.def.json msgctxt "adaptive_layer_height_enabled label" msgid "Use adaptive layers" -msgstr "" +msgstr "使用適應層高" #: fdmprinter.def.json msgctxt "adaptive_layer_height_enabled description" msgid "Adaptive layers computes the layer heights depending on the shape of the model." -msgstr "" +msgstr "適應層高會依據模型的形狀計算列印的層高。" #: fdmprinter.def.json msgctxt "adaptive_layer_height_variation label" msgid "Adaptive layers maximum variation" -msgstr "" +msgstr "適應層高最大變化量" #: fdmprinter.def.json msgctxt "adaptive_layer_height_variation description" msgid "The maximum allowed height different from the base layer height in mm." -msgstr "" +msgstr "允許與層高基礎值相差的最大值(以毫米為單位)。" #: fdmprinter.def.json msgctxt "adaptive_layer_height_variation_step label" msgid "Adaptive layers variation step size" -msgstr "" +msgstr "適應層高變化幅度" #: fdmprinter.def.json msgctxt "adaptive_layer_height_variation_step description" msgid "The difference in height of the next layer height compared to the previous one." -msgstr "" +msgstr "下一列印層與前一列印層的層高差。" #: fdmprinter.def.json msgctxt "adaptive_layer_height_threshold label" msgid "Adaptive layers threshold" -msgstr "" +msgstr "適應層高門檻值" #: fdmprinter.def.json msgctxt "adaptive_layer_height_threshold description" msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer." -msgstr "" +msgstr "決定是否使用較小層高的門檻值。此值會與一層中最陡坡度的 tan 值做比較。" #: fdmprinter.def.json msgctxt "command_line_settings label" From 5fcb80532fd4a287f2b347dec6f865b75daaeb8c Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 4 Feb 2018 11:19:55 +0800 Subject: [PATCH 009/371] update cura.po for cura 3.2 --- resources/i18n/zh_TW/cura.po | 243 +++++++++++++++++++---------------- 1 file changed, 133 insertions(+), 110 deletions(-) diff --git a/resources/i18n/zh_TW/cura.po b/resources/i18n/zh_TW/cura.po index b884b13a19..7d4cca2681 100644 --- a/resources/i18n/zh_TW/cura.po +++ b/resources/i18n/zh_TW/cura.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: Cura 3.1\n" "Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n" "POT-Creation-Date: 2017-08-02 16:53+0000\n" -"PO-Revision-Date: 2017-11-28 23:48+0800\n" +"PO-Revision-Date: 2018-02-04 11:18+0800\n" "Last-Translator: Zhang Heh Ji \n" "Language-Team: TEAM\n" "Language: zh_TW\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 2.0.4\n" +"X-Generator: Poedit 2.0.6\n" #: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:26 msgctxt "@action" @@ -189,7 +189,7 @@ msgstr "印表機韌體" #: /home/ruben/Projects/Cura/plugins/PrepareStage/__init__.py:12 msgctxt "@item:inmenu" msgid "Prepare" -msgstr "" +msgstr "準備" #: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:23 msgctxt "@action:button Preceded by 'Ready to'." @@ -562,7 +562,7 @@ msgstr "使用瀏覽器開啟列印作業介面。" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:239 msgctxt "@label Printer name" msgid "Unknown" -msgstr "" +msgstr "未知" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:505 #, python-brace-format @@ -597,7 +597,7 @@ msgstr "透過網路連接" #: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12 msgctxt "@item:inmenu" msgid "Monitor" -msgstr "" +msgstr "監控" #: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66 #, python-brace-format @@ -624,7 +624,7 @@ msgstr "無法存取更新資訊。" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:579 msgctxt "@info:status" msgid "SolidWorks reported errors, while opening your file. We recommend to solve these issues inside SolidWorks itself." -msgstr "" +msgstr "SolidWorks 在開啟檔案時回報了錯誤。建議在 SolidWorks 內部解決這些問題。" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:591 msgctxt "@info:status" @@ -633,6 +633,9 @@ msgid "" "\n" " Thanks!." msgstr "" +"在你的繪圖找不到模型。請你再次檢查它的內容並確認裡面有一個零件或組件。\n" +"\n" +"謝謝。" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:595 msgctxt "@info:status" @@ -641,6 +644,9 @@ msgid "" "\n" "Sorry!" msgstr "" +"在你的繪圖找到了超過一個的零件或組件。我們目前只支援一個零件或組件的繪圖。\n" +"\n" +"抱歉!" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:25 msgctxt "@item:inlistbox" @@ -655,7 +661,7 @@ msgstr "SolidWorks 組件檔案" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:33 msgctxt "@item:inlistbox" msgid "SolidWorks drawing file" -msgstr "" +msgstr "SolidWorks 繪圖檔案" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:48 msgctxt "@info:status" @@ -666,6 +672,11 @@ msgid "" "With kind regards\n" " - Thomas Karl Pietrowski" msgstr "" +"親愛的客戶,\n" +"我們無法在您的系統上找到有效安裝的 SolidWorks。這表示未安裝 SolidWorks,或者您沒有擁有有效的授權。請確認 SolidWorks 本身是可以正常執行的,或是聯絡您的技術部門處理。\n" +"\n" +"順頌 時祺\n" +" - Thomas Karl Pietrowski" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:57 msgctxt "@info:status" @@ -676,6 +687,11 @@ msgid "" "With kind regards\n" " - Thomas Karl Pietrowski" msgstr "" +"親愛的客戶,\n" +"您目前正在 Windows 以外的作業系統上執行此外掛。此外掛只能在有安裝有效授權 SolidWorks 的 Windows 上執行。請在有安裝 SolidWorks 的 windows 電腦上安裝此外掛。\n" +"\n" +"順頌 時祺\n" +" - Thomas Karl Pietrowski" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:70 msgid "Configure" @@ -683,7 +699,7 @@ msgstr "設定" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:71 msgid "Installation guide for SolidWorks macro" -msgstr "" +msgstr "SolidWorks 巨集的安裝指南" # Added manually to fix a string that was changed after string freeze. #: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14 @@ -708,7 +724,7 @@ msgstr "修改 G-Code 檔案" #: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43 msgctxt "@info" msgid "Cura collects anonymized usage statistics." -msgstr "" +msgstr "Cura 以匿名方式蒐集使用狀況統計資料。" #: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:46 msgctxt "@info:title" @@ -718,22 +734,22 @@ msgstr "收集資料中" #: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48 msgctxt "@action:button" msgid "Allow" -msgstr "" +msgstr "允許" #: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49 msgctxt "@action:tooltip" msgid "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing." -msgstr "" +msgstr "允許 Cura 以匿名方式傳送使用狀況統計資料,用來協助 Cura 的未來改善工作。你的部份偏好設定和參數,Cura 的版本及你切片模型的雜湊值會被傳送。" #: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:50 msgctxt "@action:button" msgid "Disable" -msgstr "" +msgstr "關閉" #: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51 msgctxt "@action:tooltip" msgid "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences." -msgstr "" +msgstr "不允許 Cura 傳送匿名的使用狀況統計資料。你可以在偏好設定中再次啟用此功能。" #: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14 msgctxt "@item:inlistbox" @@ -743,7 +759,7 @@ msgstr "Cura 15.04 列印參數" #: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/__init__.py:15 msgctxt "@item:inlistbox" msgid "Blender file" -msgstr "" +msgstr "Blender 檔案" #: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/CadIntegrationUtils/CommonReader.py:199 msgctxt "@info:status" @@ -751,6 +767,8 @@ msgid "" "Could not export using \"{}\" quality!\n" "Felt back to \"{}\"." msgstr "" +"無法使用 \"{}\" 品質導出!\n" +"覆蓋回 \"{}\"。" #: /home/ruben/Projects/Cura/plugins/GCodeProfileReader/__init__.py:14 #: /home/ruben/Projects/Cura/plugins/GCodeReader/__init__.py:14 @@ -937,12 +955,12 @@ msgstr "Cura 列印參數" #: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12 msgctxt "@item:inmenu" msgid "Profile Assistant" -msgstr "" +msgstr "參數助手" #: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17 msgctxt "@item:inlistbox" msgid "Profile Assistant" -msgstr "" +msgstr "參數助手" #: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:30 msgctxt "@item:inlistbox" @@ -1140,13 +1158,13 @@ msgstr "無法從 {0} 匯入列印參數:{1} or !" msgid "This profile {0} contains incorrect data, could not import it." -msgstr "" +msgstr "此列印參數 {0} 含有錯誤的資料,無法導入。" #: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:240 #, python-brace-format msgctxt "@info:status Don't translate the XML tags or !" msgid "The machine defined in profile {0} doesn't match with your current machine, could not import it." -msgstr "" +msgstr "列印參數 {0} 中的機器設定與你目前的機器不相符,無法導入。" #: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274 #, python-brace-format @@ -1158,7 +1176,7 @@ msgstr "已成功匯入列印參數 {0}" #, python-brace-format msgctxt "@info:status" msgid "File {0} does not contain any valid profile." -msgstr "" +msgstr "檔案 {0} 內未含有效的列印參數。" #: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:280 #, python-brace-format @@ -1186,7 +1204,7 @@ msgstr "無法為目前設定找到品質類型 {0}。" #, python-brace-format msgctxt "@label" msgid "Group #{group_nr}" -msgstr "" +msgstr "群組 #{group_nr}" #: /home/ruben/Projects/Cura/cura/BuildVolume.py:100 msgctxt "@info:status" @@ -1246,6 +1264,9 @@ msgid "" "

Please use the \"Send report\" button to post a bug report automatically to our servers

\n" " " msgstr "" +"

發生致命錯誤。請將錯誤報告傳送給我們以便修正此問題。

\n" +"

請使用\"送出報告\"按鈕自動發送一份問題報告給我們的伺服器

\n" +" " #: /home/ruben/Projects/Cura/cura/CrashHandler.py:102 msgctxt "@title:groupbox" @@ -1260,32 +1281,32 @@ msgstr "未知" #: /home/ruben/Projects/Cura/cura/CrashHandler.py:112 msgctxt "@label Cura version number" msgid "Cura version" -msgstr "" +msgstr "Cura 版本" #: /home/ruben/Projects/Cura/cura/CrashHandler.py:113 msgctxt "@label Type of platform" msgid "Platform" -msgstr "" +msgstr "平台" #: /home/ruben/Projects/Cura/cura/CrashHandler.py:114 msgctxt "@label" msgid "Qt version" -msgstr "" +msgstr "Qt 版本" #: /home/ruben/Projects/Cura/cura/CrashHandler.py:115 msgctxt "@label" msgid "PyQt version" -msgstr "" +msgstr "PyQt 版本" #: /home/ruben/Projects/Cura/cura/CrashHandler.py:116 msgctxt "@label OpenGL version" msgid "OpenGL" -msgstr "" +msgstr "OpenGL" #: /home/ruben/Projects/Cura/cura/CrashHandler.py:133 msgctxt "@label" msgid "not yet initialised
" -msgstr "" +msgstr "尚未初始化
" #: /home/ruben/Projects/Cura/cura/CrashHandler.py:136 #, python-brace-format @@ -1308,7 +1329,7 @@ msgstr "
  • OpenGL 渲染器:{renderer}
  • " #: /home/ruben/Projects/Cura/cura/CrashHandler.py:147 msgctxt "@title:groupbox" msgid "Error traceback" -msgstr "" +msgstr "錯誤追溯" #: /home/ruben/Projects/Cura/cura/CrashHandler.py:214 msgctxt "@title:groupbox" @@ -1519,7 +1540,7 @@ msgstr "噴頭孔徑" #: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:393 msgctxt "@label" msgid "Compatible material diameter" -msgstr "" +msgstr "相容的耗材直徑" #: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:395 msgctxt "@tooltip" @@ -1664,12 +1685,12 @@ msgstr "類型" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:233 msgctxt "@label Printer name" msgid "Ultimaker 3" -msgstr "" +msgstr "Ultimaker 3" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:236 msgctxt "@label Printer name" msgid "Ultimaker 3 Extended" -msgstr "" +msgstr "Ultimaker 3 Extended" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:252 msgctxt "@label" @@ -1736,7 +1757,7 @@ msgstr "%1 未設定成管理一組連線的 Ultimaker 3 印表機的主機" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml:55 msgctxt "@label link to connect manager" msgid "Add/Remove printers" -msgstr "" +msgstr "新增/移除印表機" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/OpenPanelButton.qml:14 msgctxt "@info:tooltip" @@ -1776,7 +1797,7 @@ msgstr "與印表機的連接中斷" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47 msgctxt "@label Printer status" msgid "Unknown" -msgstr "" +msgstr "未知" #: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:257 msgctxt "@label:status" @@ -1872,62 +1893,62 @@ msgstr "啟用設定" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:21 msgctxt "@title:window" msgid "SolidWorks: Export wizard" -msgstr "" +msgstr "SolidWorks: 導出精靈" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:45 #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:140 msgctxt "@action:label" msgid "Quality:" -msgstr "" +msgstr "品質:" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:78 #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:179 msgctxt "@option:curaSolidworksStlQuality" msgid "Fine (3D-printing)" -msgstr "" +msgstr "精細 (3D-printing)" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:79 #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:180 msgctxt "@option:curaSolidworksStlQuality" msgid "Coarse (3D-printing)" -msgstr "" +msgstr "粗糙 (3D-printing)" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:80 #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:181 msgctxt "@option:curaSolidworksStlQuality" msgid "Fine (SolidWorks)" -msgstr "" +msgstr "精細 (SolidWorks)" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:81 #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:182 msgctxt "@option:curaSolidworksStlQuality" msgid "Coarse (SolidWorks)" -msgstr "" +msgstr "粗糙 (SolidWorks)" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:94 msgctxt "@text:window" msgid "Show this dialog again" -msgstr "" +msgstr "再次顯示這個對話框" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:104 msgctxt "@action:button" msgid "Continue" -msgstr "" +msgstr "繼續" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:116 msgctxt "@action:button" msgid "Abort" -msgstr "" +msgstr "取消" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:21 msgctxt "@title:window" msgid "How to install Cura SolidWorks macro" -msgstr "" +msgstr "如何安裝 Cura SolidWorks 巨集" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:62 msgctxt "@description:label" msgid "Steps:" -msgstr "" +msgstr "步驟:" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:140 msgctxt "@action:button" @@ -1935,101 +1956,103 @@ msgid "" "Open the directory\n" "with macro and icon" msgstr "" +"使用巨集和圖示\n" +"開啟目錄" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:160 msgctxt "@description:label" msgid "Instructions:" -msgstr "" +msgstr "操作說明:" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:202 msgctxt "@action:playpause" msgid "Play" -msgstr "" +msgstr "播放" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:206 msgctxt "@action:playpause" msgid "Pause" -msgstr "" +msgstr "暫停" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:268 msgctxt "@action:button" msgid "Previous Step" -msgstr "" +msgstr "前一步" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:283 msgctxt "@action:button" msgid "Done" -msgstr "" +msgstr "完成" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:287 msgctxt "@action:button" msgid "Next Step" -msgstr "" +msgstr "下一步" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:21 msgctxt "@title:window" msgid "SolidWorks plugin: Configuration" -msgstr "" +msgstr "SolidWorks 外掛:設定" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:39 msgctxt "@title:tab" msgid "Conversion settings" -msgstr "" +msgstr "轉換設定" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:66 msgctxt "@label" msgid "First choice:" -msgstr "" +msgstr "第一選擇:" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:86 msgctxt "@text:menu" msgid "Latest installed version (Recommended)" -msgstr "" +msgstr "最新安裝的版本(建議)" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:95 msgctxt "@text:menu" msgid "Default version" -msgstr "" +msgstr "預設的版本" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:193 msgctxt "@label" msgid "Show wizard before opening SolidWorks files" -msgstr "" +msgstr "開啟 SolidWorks 檔案時顯示精靈" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:203 msgctxt "@label" msgid "Automatically rotate opened file into normed orientation" -msgstr "" +msgstr "自動將開啟的檔案旋轉到正常方向" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:210 msgctxt "@title:tab" msgid "Installation(s)" -msgstr "" +msgstr "安裝" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:284 msgctxt "@label" msgid "COM service found" -msgstr "" +msgstr "找到 COM 服務" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:295 msgctxt "@label" msgid "Executable found" -msgstr "" +msgstr "找到可執行檔案" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:306 msgctxt "@label" msgid "COM starting" -msgstr "" +msgstr "COM 啟動中" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:317 msgctxt "@label" msgid "Revision number" -msgstr "" +msgstr "版本號碼" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:328 msgctxt "@label" msgid "Functions available" -msgstr "" +msgstr "可用功能" #: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:341 #: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:264 @@ -2215,32 +2238,32 @@ msgstr "平滑" #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:38 msgctxt "@label" msgid "Mesh Type" -msgstr "" +msgstr "網格類型" #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:69 msgctxt "@label" msgid "Normal model" -msgstr "" +msgstr "普通模型" #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:76 msgctxt "@label" msgid "Print as support" -msgstr "" +msgstr "做為支撐" #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:84 msgctxt "@label" msgid "Don't support overlap with other models" -msgstr "" +msgstr "不支援與其他模型重疊" #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:92 msgctxt "@label" msgid "Modify settings for overlap with other models" -msgstr "" +msgstr "修改其他模型的重疊設定" #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:100 msgctxt "@label" msgid "Modify settings for infill of other models" -msgstr "" +msgstr "修改其他模型的填充設定" #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:333 msgctxt "@action:button" @@ -2742,7 +2765,7 @@ msgstr "保留" #: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:222 msgctxt "@action:button" msgid "Create New Profile" -msgstr "創建新的列印參數" +msgstr "建立新的列印參數" #: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:44 msgctxt "@title" @@ -3098,27 +3121,27 @@ msgstr "(匿名)發送列印資訊" #: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:674 msgctxt "@label" msgid "Experimental" -msgstr "" +msgstr "實驗功能" #: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:680 msgctxt "@info:tooltip" msgid "Use multi build plate functionality" -msgstr "" +msgstr "使用多列印平台功能" #: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:685 msgctxt "@option:check" msgid "Use multi build plate functionality (restart required)" -msgstr "" +msgstr "使用多列印平台功能(需重啟軟體)" #: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:694 msgctxt "@info:tooltip" msgid "Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)" -msgstr "" +msgstr "新載入的模型要擺放在列印平台上嗎?必需與多列印平台功能一起使用(實驗功能)" #: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699 msgctxt "@option:check" msgid "Do not arrange objects on load" -msgstr "" +msgstr "載入時不要擺放物件" #: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:15 #: /home/ruben/Projects/Cura/resources/qml/Cura.qml:514 @@ -3189,7 +3212,7 @@ msgstr "自訂列印參數" #: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:64 msgctxt "@label" msgid "Create" -msgstr "創建" +msgstr "建立" #: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:80 msgctxt "@label" @@ -3246,7 +3269,7 @@ msgstr "重命名列印參數" #: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:271 msgctxt "@title:window" msgid "Create Profile" -msgstr "創建列印參數" +msgstr "建立列印參數" #: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:285 msgctxt "@title:window" @@ -3287,7 +3310,7 @@ msgstr "印表機:%1" #: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:150 msgctxt "@action:button" msgid "Create" -msgstr "創建" +msgstr "建立" #: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:160 msgctxt "@action:button" @@ -3531,7 +3554,7 @@ msgstr "影響因素" #: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:156 msgctxt "@label" msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders." -msgstr "" +msgstr "這個設定是所有擠出機共用的。修改它會同時更動到所有擠出機的值。" #: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:159 msgctxt "@label" @@ -3582,7 +3605,7 @@ msgstr "00 小時 00 分" #: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:359 msgctxt "@tooltip" msgid "Time specification" -msgstr "" +msgstr "時間規格" #: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:441 msgctxt "@label" @@ -3639,12 +3662,12 @@ msgstr "檢視(&V)" #: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:37 msgctxt "@action:inmenu menubar:view" msgid "&Camera position" -msgstr "" +msgstr "視角位置(&C)" #: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:52 msgctxt "@action:inmenu menubar:view" msgid "&Build plate" -msgstr "" +msgstr "列印平台(&B)" #: /home/ruben/Projects/Cura/resources/qml/Menus/NozzleMenu.qml:40 msgctxt "@title:menuitem %1 is the nozzle currently loaded in the printer" @@ -3812,27 +3835,27 @@ msgstr "退出(&Q)" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:114 msgctxt "@action:inmenu menubar:view" msgid "&3D View" -msgstr "" +msgstr "立體圖(&3)" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121 msgctxt "@action:inmenu menubar:view" msgid "&Front View" -msgstr "" +msgstr "前視圖(&F)" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:128 msgctxt "@action:inmenu menubar:view" msgid "&Top View" -msgstr "" +msgstr "上視圖(&T)" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:135 msgctxt "@action:inmenu menubar:view" msgid "&Left Side View" -msgstr "" +msgstr "左視圖(&L)" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142 msgctxt "@action:inmenu menubar:view" msgid "&Right Side View" -msgstr "" +msgstr "右視圖(&R)" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:149 msgctxt "@action:inmenu" @@ -3867,7 +3890,7 @@ msgstr "捨棄目前更改(&D)" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:197 msgctxt "@action:inmenu menubar:profile" msgid "&Create profile from current settings/overrides..." -msgstr "從目前設定 / 覆寫值創建列印參數(&C)…" +msgstr "從目前設定 / 覆寫值建立列印參數(&C)…" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203 msgctxt "@action:inmenu menubar:profile" @@ -3955,17 +3978,17 @@ msgstr "重新載入所有模型(&L)" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:351 msgctxt "@action:inmenu menubar:edit" msgid "Arrange All Models To All Build Plates" -msgstr "" +msgstr "將所有模型排列到所有列印平台上" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:358 msgctxt "@action:inmenu menubar:edit" msgid "Arrange All Models" -msgstr "編位所有的模型" +msgstr "排列所有模型" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366 msgctxt "@action:inmenu menubar:edit" msgid "Arrange Selection" -msgstr "為所選模型編位" +msgstr "排列所選模型" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:373 msgctxt "@action:inmenu menubar:edit" @@ -4015,7 +4038,7 @@ msgstr "安裝外掛..." #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:438 msgctxt "@action:inmenu menubar:view" msgid "Expand/Collapse Sidebar" -msgstr "" +msgstr "展開/收合側邊欄" #: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:26 msgctxt "@label:PrintjobStatus" @@ -4050,12 +4073,12 @@ msgstr "切片無法使用" #: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171 msgctxt "@info:tooltip" msgid "Slice current printjob" -msgstr "" +msgstr "對目前列印工作進行切片" #: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171 msgctxt "@info:tooltip" msgid "Cancel slicing process" -msgstr "" +msgstr "取消進行中的切片程序" #: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183 msgctxt "@label:Printjob" @@ -4111,7 +4134,7 @@ msgstr "另存為(&A)…" #: /home/ruben/Projects/Cura/resources/qml/Cura.qml:139 msgctxt "@title:menu menubar:file" msgid "Save &Project..." -msgstr "" +msgstr "儲存專案...(&P)" #: /home/ruben/Projects/Cura/resources/qml/Cura.qml:162 msgctxt "@title:menu menubar:toplevel" @@ -4349,7 +4372,7 @@ msgstr "耗材" #: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:352 msgctxt "@label" msgid "Check compatibility" -msgstr "" +msgstr "檢查相容性" #: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:372 msgctxt "@tooltip" @@ -4359,17 +4382,17 @@ msgstr "點擊查看 Ultimaker.com 上的耗材相容性。" #: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:211 msgctxt "@option:check" msgid "See only current build plate" -msgstr "" +msgstr "只顯示目前的列印平台" #: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:227 msgctxt "@action:button" msgid "Arrange to all build plates" -msgstr "" +msgstr "擺放到所有的列印平台" #: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:247 msgctxt "@action:button" msgid "Arrange current build plate" -msgstr "" +msgstr "擺放到目前的列印平台" #: MachineSettingsAction/plugin.json msgctxt "description" @@ -4444,7 +4467,7 @@ msgstr "更新日誌" #: ProfileFlattener/plugin.json msgctxt "description" msgid "Create a flattend quality changes profile." -msgstr "創建一份合併品質變化列印參數。" +msgstr "建立一份合併品質變化列印參數。" #: ProfileFlattener/plugin.json msgctxt "name" @@ -4464,22 +4487,22 @@ msgstr "USB 連線列印" #: PrepareStage/plugin.json msgctxt "description" msgid "Provides a prepare stage in Cura." -msgstr "" +msgstr "在 cura 提供一個準備介面。" #: PrepareStage/plugin.json msgctxt "name" msgid "Prepare Stage" -msgstr "" +msgstr "準備介面" #: CuraLiveScriptingPlugin/plugin.json msgctxt "description" msgid "Provides an edit window for direct script editing." -msgstr "" +msgstr "提供一個直接編輯描述檔的編輯視窗。" #: CuraLiveScriptingPlugin/plugin.json msgctxt "name" msgid "Live scripting tool" -msgstr "" +msgstr "即時描述檔工具" #: RemovableDriveOutputDevice/plugin.json msgctxt "description" @@ -4504,12 +4527,12 @@ msgstr "UM3 網路連接" #: MonitorStage/plugin.json msgctxt "description" msgid "Provides a monitor stage in Cura." -msgstr "" +msgstr "在 cura 提供一個監控介面。" #: MonitorStage/plugin.json msgctxt "name" msgid "Monitor Stage" -msgstr "" +msgstr "監控介面" #: FirmwareUpdateChecker/plugin.json msgctxt "description" @@ -4524,7 +4547,7 @@ msgstr "韌體更新檢查" #: CuraSolidWorksPlugin/plugin.json msgctxt "description" msgid "Gives you the possibility to open certain files using SolidWorks itself. Conversion is done by this plugin and additional optimizations." -msgstr "" +msgstr "讓你可以使用 SolidWorks 開啟某些檔案。此外掛會完成轉換和最佳化的工作。" #: CuraSolidWorksPlugin/plugin.json msgctxt "name" @@ -4594,12 +4617,12 @@ msgstr "舊版 Cura 列印參數讀取器" #: CuraBlenderPlugin/plugin.json msgctxt "description" msgid "Helps to open Blender files directly in Cura." -msgstr "" +msgstr "協助你直接在 Cura 中打開 Blender 檔案。" #: CuraBlenderPlugin/plugin.json msgctxt "name" msgid "Blender Integration (experimental)" -msgstr "" +msgstr "Blender 整合(實驗功能)" #: GCodeProfileReader/plugin.json msgctxt "description" @@ -4764,12 +4787,12 @@ msgstr "Cura 列印參數寫入器" #: CuraPrintProfileCreator/plugin.json msgctxt "description" msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI." -msgstr "" +msgstr "允許耗材製造商使用下拉式 UI 建立新的耗材和品質設定參數。" #: CuraPrintProfileCreator/plugin.json msgctxt "name" msgid "Print Profile Assistant" -msgstr "" +msgstr "列印參數設定助手" #: 3MFWriter/plugin.json msgctxt "description" From f535ed29adb45a004951431071b503c21c71162c Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 7 Feb 2018 15:31:09 +0100 Subject: [PATCH 010/371] Slight meshfix resolution change By changing the meshfix resolution from 0.01 to 0.04 mm, we change the minimum out wall line pieces and can have a more continuous printhead movement. Also decreases Gcode size by around 30% for very high detail models. --- resources/definitions/ultimaker3.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index e7b9b6255e..76fa24b01c 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -109,6 +109,7 @@ "material_bed_temperature": { "maximum_value": "115" }, "material_bed_temperature_layer_0": { "maximum_value": "115" }, "material_standby_temperature": { "value": "100" }, + "meshfix_maximum_resolution": { "value": "0.04" }, "multiple_mesh_overlap": { "value": "0" }, "prime_tower_enable": { "default_value": true }, "raft_airgap": { "value": "0" }, From ca83089eff9f9ed3b8a37b1d593993662cb27e0c Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 7 Feb 2018 15:32:59 +0100 Subject: [PATCH 011/371] Combing to "No Skin" This will remove the lines "printed" on top of flat top surfaces. For all UM3(e) profiles. --- resources/definitions/ultimaker3.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 76fa24b01c..cb8159b6b4 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -121,6 +121,7 @@ "raft_margin": { "value": "10" }, "raft_surface_layers": { "value": "1" }, "retraction_amount": { "value": "2" }, + "retraction_combing": { "default_value": "noskin" }, "retraction_count_max": { "value": "10" }, "retraction_extrusion_window": { "value": "1" }, "retraction_hop": { "value": "2" }, From bc0a4cdc1722b389e7fcea12834b2caaf0facf72 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 7 Feb 2018 15:35:09 +0100 Subject: [PATCH 012/371] Initial layer line width increase Increasing the initial layer line width both increases print speed, and results in more reliable bed adhesion. --- resources/definitions/ultimaker3.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index cb8159b6b4..562a56d652 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -90,6 +90,7 @@ "infill_overlap": { "value": "0" }, "infill_pattern": { "value": "'triangles'" }, "infill_wipe_dist": { "value": "0" }, + "initial_layer_line_width_factor": { "value": "120" }, "jerk_enabled": { "value": "True" }, "jerk_layer_0": { "value": "jerk_topbottom" }, "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" }, From 34c0a09047133c7e2b1758cd135c5aa80c6a1e1c Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 7 Feb 2018 15:37:05 +0100 Subject: [PATCH 013/371] Optimize wall printing order This setting will make a lot of more prints more logical in printing order, especially when many small features are printed. --- resources/definitions/ultimaker3.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 562a56d652..a503cb7739 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -112,6 +112,7 @@ "material_standby_temperature": { "value": "100" }, "meshfix_maximum_resolution": { "value": "0.04" }, "multiple_mesh_overlap": { "value": "0" }, + "optimize_wall_printing_order": { "value": "True" }, "prime_tower_enable": { "default_value": true }, "raft_airgap": { "value": "0" }, "raft_base_thickness": { "value": "0.3" }, From 014c2628bb868d161816136d26b0db4c4669a195 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 7 Feb 2018 15:57:33 +0100 Subject: [PATCH 014/371] PLA 0.4mm profiles Infill thickness change and Fast Quality Speedup Increasing the speed of the Fast Quality prints, and slightly reducing the Infill Line Width. --- .../quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg | 7 ++++--- .../quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg | 1 + .../quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg | 1 + .../ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/resources/quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg index 8c6e7bd782..a32d9268d3 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg @@ -13,6 +13,7 @@ setting_version = 4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height cool_fan_speed_max = =cool_fan_speed +infill_line_width = =round(line_width * 0.42 / 0.35, 2) machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 material_print_temperature = =default_material_print_temperature + 5 @@ -20,9 +21,9 @@ material_standby_temperature = 100 prime_tower_enable = False skin_overlap = 20 speed_layer_0 = 20 -speed_topbottom = =math.ceil(speed_print * 35 / 70) -speed_wall = =math.ceil(speed_print * 50 / 70) -speed_wall_0 = =math.ceil(speed_wall * 35 / 50) +speed_topbottom = =math.ceil(speed_print * 40 / 70) +speed_wall = =math.ceil(speed_print * 55 / 70) +speed_wall_0 = =math.ceil(speed_wall * 45 / 50) top_bottom_thickness = 1 wall_thickness = 1 diff --git a/resources/quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg index db441015a8..30b7d44d4e 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg @@ -13,6 +13,7 @@ setting_version = 4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height cool_fan_speed_max = =cool_fan_speed +infill_line_width = =round(line_width * 0.42 / 0.35, 2) machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 material_standby_temperature = 100 diff --git a/resources/quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg index 61807490e9..da62ce2e3f 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg @@ -14,6 +14,7 @@ setting_version = 4 cool_fan_full_at_height = =layer_height_0 + 2 * layer_height cool_fan_speed_max = =cool_fan_speed cool_min_speed = 10 +infill_line_width = =round(line_width * 0.42 / 0.35, 2) machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 material_print_temperature = =default_material_print_temperature - 5 diff --git a/resources/quality/ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg index d7254b854d..04707735f5 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg @@ -14,6 +14,7 @@ setting_version = 4 cool_fan_full_at_height = =layer_height_0 + 2 * layer_height cool_fan_speed_max = =cool_fan_speed cool_min_speed = 7 +infill_line_width = =round(line_width * 0.42 / 0.35, 2) machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 material_standby_temperature = 100 From 97c96ab2da07e3c397f309d7501a1ec237c7d7f5 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 7 Feb 2018 16:09:57 +0100 Subject: [PATCH 015/371] PLA 0.8mm Faster printing Optimization for faster printing with the 0.8mm profiles for PLA. Also removed retract at layer change for less artifacts, and changed infill pattern to triangular for more unity between profiles. --- .../quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg | 6 ++++-- .../ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg | 6 ++++-- .../ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg index 3c4303e017..09e8539b03 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg @@ -15,8 +15,8 @@ cool_fan_full_at_height = =layer_height_0 + 2 * layer_height cool_fan_speed_max = =100 cool_min_speed = 2 gradual_infill_step_height = =3 * layer_height -infill_line_width = =round(line_width * 0.535 / 0.75, 2) -infill_pattern = cubic +infill_line_width = =round(line_width * 0.65 / 0.75, 2) +infill_pattern = triangles line_width = =machine_nozzle_size * 0.9375 machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 @@ -25,6 +25,8 @@ material_initial_print_temperature = =max(-273.15, material_print_temperature - material_print_temperature = =default_material_print_temperature + 10 material_standby_temperature = 100 prime_tower_enable = True +retract_at_layer_change = False +speed_print = 45 support_angle = 70 support_line_width = =line_width * 0.75 support_pattern = ='triangles' diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg index 5509f42aae..2217dee344 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg @@ -15,8 +15,8 @@ cool_fan_full_at_height = =layer_height_0 + 2 * layer_height cool_fan_speed_max = =100 cool_min_speed = 2 gradual_infill_step_height = =3 * layer_height -infill_line_width = =round(line_width * 0.535 / 0.75, 2) -infill_pattern = cubic +infill_line_width = =round(line_width * 0.65 / 0.75, 2) +infill_pattern = triangles layer_height = 0.4 line_width = =machine_nozzle_size * 0.9375 machine_nozzle_cool_down_speed = 0.75 @@ -27,6 +27,8 @@ material_print_temperature = =default_material_print_temperature + 15 material_standby_temperature = 100 prime_tower_enable = True raft_margin = 10 +retract_at_layer_change = False +speed_print = 45 support_angle = 70 support_line_width = =line_width * 0.75 support_pattern = ='triangles' diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg index 645c3fe3ef..0bd3f9751a 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg @@ -15,8 +15,8 @@ cool_fan_full_at_height = =layer_height_0 + 2 * layer_height cool_fan_speed_max = =100 cool_min_speed = 2 gradual_infill_step_height = =3 * layer_height -infill_line_width = =round(line_width * 0.535 / 0.75, 2) -infill_pattern = cubic +infill_line_width = =round(line_width * 0.65 / 0.75, 2) +infill_pattern = triangles layer_height = 0.3 line_width = =machine_nozzle_size * 0.9375 machine_nozzle_cool_down_speed = 0.75 @@ -26,6 +26,8 @@ material_initial_print_temperature = =max(-273.15, material_print_temperature - material_print_temperature = =default_material_print_temperature + 10 material_standby_temperature = 100 prime_tower_enable = True +retract_at_layer_change = False +speed_print = 45 support_angle = 70 support_line_width = =line_width * 0.75 support_pattern = ='triangles' From ece88bd54dfb852cd86d28db1bb203ada748c7c1 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 7 Feb 2018 16:14:00 +0100 Subject: [PATCH 016/371] Cross3D infill for TPU Flexibility Changed infill to Cross3D 10% (no gradual) for a more isotropic flexibility of parts. Cross3D also prints without travels (if possible) and looks great. --- .../quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg | 5 ++--- .../quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg | 5 ++--- .../quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg | 5 ++--- .../quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg | 5 ++--- .../ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg | 5 ++--- .../ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg | 5 ++--- 6 files changed, 12 insertions(+), 18 deletions(-) diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg index 6116dc1bda..f6828f88fb 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg @@ -18,11 +18,10 @@ cool_fan_speed_max = 100 cool_min_layer_time_fan_speed_max = 6 cool_min_speed = 4 gradual_infill_step_height = =5 * layer_height -gradual_infill_steps = 4 infill_line_width = =round(line_width * 0.38 / 0.38, 2) infill_overlap = 0 -infill_pattern = tetrahedral -infill_sparse_density = 96 +infill_pattern = cross_3d +infill_sparse_density = 10 infill_wipe_dist = 0.1 jerk_enabled = True jerk_print = 25 diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg index 1da5d0fec8..80be26d24c 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg @@ -18,11 +18,10 @@ cool_fan_speed_max = 100 cool_min_layer_time_fan_speed_max = 6 cool_min_speed = 4 gradual_infill_step_height = =5 * layer_height -gradual_infill_steps = 4 infill_line_width = =round(line_width * 0.38 / 0.38, 2) infill_overlap = 0 -infill_pattern = tetrahedral -infill_sparse_density = 96 +infill_pattern = cross_3d +infill_sparse_density = 10 infill_wipe_dist = 0.1 jerk_enabled = True jerk_print = 25 diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg index 1938e1c26c..53044e1805 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg @@ -18,11 +18,10 @@ cool_fan_speed_max = 100 cool_min_layer_time_fan_speed_max = 6 cool_min_speed = 4 gradual_infill_step_height = =5 * layer_height -gradual_infill_steps = 4 infill_line_width = =round(line_width * 0.38 / 0.38, 2) infill_overlap = 0 -infill_pattern = tetrahedral -infill_sparse_density = 96 +infill_pattern = cross_3d +infill_sparse_density = 10 infill_wipe_dist = 0.1 jerk_enabled = True jerk_print = 25 diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg index 726ab82867..d5d7479a0e 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg @@ -15,11 +15,10 @@ brim_width = 8.75 cool_min_layer_time_fan_speed_max = 6 top_skin_expand_distance = =line_width * 2 gradual_infill_step_height = =4 * layer_height -gradual_infill_steps = 5 infill_before_walls = True infill_line_width = =round(line_width * 0.7 / 0.8, 2) -infill_pattern = tetrahedral -infill_sparse_density = 80 +infill_pattern = cross_3d +infill_sparse_density = 10 jerk_prime_tower = =math.ceil(jerk_print * 25 / 25) jerk_support = =math.ceil(jerk_print * 25 / 25) jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg index 269725daa9..86c6a3df77 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg @@ -15,11 +15,10 @@ brim_width = 8.75 cool_min_layer_time_fan_speed_max = 6 top_skin_expand_distance = =line_width * 2 gradual_infill_step_height = =4 * layer_height -gradual_infill_steps = 5 infill_before_walls = True infill_line_width = =round(line_width * 0.7 / 0.8, 2) -infill_pattern = tetrahedral -infill_sparse_density = 80 +infill_pattern = cross_3d +infill_sparse_density = 10 jerk_prime_tower = =math.ceil(jerk_print * 25 / 25) jerk_support = =math.ceil(jerk_print * 25 / 25) jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg index dd1737433a..8af3edcddd 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg @@ -15,11 +15,10 @@ brim_width = 8.75 cool_min_layer_time_fan_speed_max = 6 top_skin_expand_distance = =line_width * 2 gradual_infill_step_height = =4 * layer_height -gradual_infill_steps = 5 infill_before_walls = True infill_line_width = =round(line_width * 0.7 / 0.8, 2) -infill_pattern = tetrahedral -infill_sparse_density = 80 +infill_pattern = cross_3d +infill_sparse_density = 10 jerk_prime_tower = =math.ceil(jerk_print * 25 / 25) jerk_support = =math.ceil(jerk_print * 25 / 25) jerk_wall_0 = =math.ceil(jerk_wall * 15 / 25) From 4f6362f3f527f01125cc3eef47b6a9d035465be1 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Wed, 7 Feb 2018 16:51:49 +0100 Subject: [PATCH 017/371] PLA 0.8mm speeds respecified Fixed speeds after breaking them in the previous commit (97c96ab) --- .../quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg | 4 ++++ .../ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg | 4 ++++ .../quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg index 09e8539b03..8b3c3e56c6 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg @@ -27,6 +27,10 @@ material_standby_temperature = 100 prime_tower_enable = True retract_at_layer_change = False speed_print = 45 +speed_topbottom = =math.ceil(speed_print * 35 / 45) +speed_wall = =math.ceil(speed_print * 40 / 45) +speed_wall_x = =speed_wall +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) support_angle = 70 support_line_width = =line_width * 0.75 support_pattern = ='triangles' diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg index 2217dee344..2fe8f7c6f9 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg @@ -29,6 +29,10 @@ prime_tower_enable = True raft_margin = 10 retract_at_layer_change = False speed_print = 45 +speed_topbottom = =math.ceil(speed_print * 35 / 45) +speed_wall = =math.ceil(speed_print * 40 / 45) +speed_wall_x = =speed_wall +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) support_angle = 70 support_line_width = =line_width * 0.75 support_pattern = ='triangles' diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg index 0bd3f9751a..9072e0c60f 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg @@ -28,6 +28,10 @@ material_standby_temperature = 100 prime_tower_enable = True retract_at_layer_change = False speed_print = 45 +speed_topbottom = =math.ceil(speed_print * 35 / 45) +speed_wall = =math.ceil(speed_print * 40 / 45) +speed_wall_x = =speed_wall +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) support_angle = 70 support_line_width = =line_width * 0.75 support_pattern = ='triangles' From b6c48e7fb9611968a33f355d4ec65284ce70d331 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Thu, 8 Feb 2018 08:58:48 +0100 Subject: [PATCH 018/371] Replaced tabs by spaces Thanks Aldo! --- resources/definitions/ultimaker3.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index a503cb7739..826960a621 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -90,7 +90,7 @@ "infill_overlap": { "value": "0" }, "infill_pattern": { "value": "'triangles'" }, "infill_wipe_dist": { "value": "0" }, - "initial_layer_line_width_factor": { "value": "120" }, + "initial_layer_line_width_factor": { "value": "120" }, "jerk_enabled": { "value": "True" }, "jerk_layer_0": { "value": "jerk_topbottom" }, "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" }, @@ -110,7 +110,7 @@ "material_bed_temperature": { "maximum_value": "115" }, "material_bed_temperature_layer_0": { "maximum_value": "115" }, "material_standby_temperature": { "value": "100" }, - "meshfix_maximum_resolution": { "value": "0.04" }, + "meshfix_maximum_resolution": { "value": "0.04" }, "multiple_mesh_overlap": { "value": "0" }, "optimize_wall_printing_order": { "value": "True" }, "prime_tower_enable": { "default_value": true }, From 1b17aee88f6af37fe779679f5ea8a606e6610190 Mon Sep 17 00:00:00 2001 From: uBuild-3D <32798910+uBuild-3D@users.noreply.github.com> Date: Thu, 8 Feb 2018 19:30:14 +0200 Subject: [PATCH 019/371] Create ubuild-3d_mr_bot_280.def.json Machine definition of MrBot280 3D printer by www.ubuild-3d.com Thanks --- .../definitions/ubuild-3d_mr_bot_280.def.json | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 resources/definitions/ubuild-3d_mr_bot_280.def.json diff --git a/resources/definitions/ubuild-3d_mr_bot_280.def.json b/resources/definitions/ubuild-3d_mr_bot_280.def.json new file mode 100644 index 0000000000..7f9069370c --- /dev/null +++ b/resources/definitions/ubuild-3d_mr_bot_280.def.json @@ -0,0 +1,49 @@ +{ + "id": "ubuild-3d_mr_bot_280", + "version": 2, + "name": "uBuild-3D Mr Bot 280", + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "uBuild-3D", + "manufacturer": "uBuild-3D", + "category": "Other", + "file_formats": "text/x-gcode", + "icon": "icon_uBuild-3D", + "platform": "mr_bot_280_platform.stl", + "has_materials": true + }, + + "overrides": { + "machine_name": { "default_value": "Mr Bot 280" }, + "machine_heated_bed": { "default_value": true }, + "machine_width": { "default_value": 275 }, + "machine_height": { "default_value": 275 }, + "machine_depth": { "default_value": 275 }, + "machine_center_is_zero": { "default_value": false }, + "material_diameter": { "default_value": 1.75 }, + "material_bed_temperature": { "default_value": 70 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "layer_height": { "default_value": 0.2 }, + "layer_height_0": { "default_value": 0.1 }, + "retraction_amount": { "default_value": 2 }, + "retraction_speed": { "default_value": 50 }, + "retraction_retract_speed": { "default_value": 50 }, + "retraction_prime_speed": { "default_value": 30 }, + "adhesion_type": { "default_value": "skirt" }, + "machine_nozzle_heat_up_speed": { "default_value": 2 }, + "machine_nozzle_cool_down_speed": { "default_value": 2 }, + "machine_head_with_fans_polygon": { "default_value": [[-20,20],[10,10],[10,10],[10,10]] }, + "gantry_height": { "default_value": 275 }, + "machine_max_feedrate_z": { "default_value": 15 }, + "machine_max_feedrate_e": { "default_value": 60 }, + "machine_max_acceleration_z": { "default_value": 1000 }, + "machine_acceleration": { "default_value": 2000 }, + "machine_max_jerk_xy": { "default_value": 20 }, + "machine_max_jerk_z": { "default_value": 0.4 }, + "machine_max_jerk_e": { "default_value": 5 }, + "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + "machine_start_gcode": { "default_value": "G21 ; set units to millimeters\nG90 ; use absolute positioning\nM82 ; absolute extrusion mode\nM140 S{material_bed_temperature} ; set bed temp\nM104 S{material_print_temperature} ; set extruder temp\nG28 ; home X, Y and Z\nG29 ; probe sequence (for auto-leveling)\nG1 Z15 F600 ; go to Z15 position\nG1 X0 Y-20 F10000 ; go to X0 Y-20 position\nM190 S{material_bed_temperature} ; wait for bed temp\nM109 S{material_print_temperature} ; wait for extruder temp\nG92 E0 ; reset extruder distance position\nG1 E25 F100 ; extrude 25mm of material\nG92 E0 ; reset extruder distance position\nM117 Printing..." }, + "machine_end_gcode": { "default_value": "M400 ; wait for moves to finish\nG92 Z0 E0 ; reset Z position\nG1 E-2 F9000 ; retract material\nG1 Z2 ; get extruder out of the way\nM104 S0 ; turn off extruder\nG1 Y285 F3000 ; present finished print\nM140 S0 ; turn off bed\nM84 ; disable motors\nM117 Print complete" } + } +} From 9ea3117d3f0ff88e579a589ef300b75f2e7d898c Mon Sep 17 00:00:00 2001 From: krios-fabteam Date: Mon, 12 Feb 2018 09:34:43 +0100 Subject: [PATCH 020/371] fixed start/end gcode by removing unuseful lines --- resources/definitions/fabtotum.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fabtotum.def.json b/resources/definitions/fabtotum.def.json index 751db3d80c..1f5d9dab0b 100644 --- a/resources/definitions/fabtotum.def.json +++ b/resources/definitions/fabtotum.def.json @@ -21,10 +21,10 @@ "overrides": { "machine_name": { "default_value": "FABtotum Personal Fabricator" }, "machine_start_gcode": { - "default_value": ";Layer height: {layer_height}\n;Walls: {wall_thickness}\n;Fill: {infill_sparse_density}\n;Top\\Bottom Thickness: {top_bottom_thickness}\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nG4 S1 ;1 millisecond pause to buffer the bep bep \nM300 ;FAB bep bep (start the print, go check the oozing and skirt lines adesion) \nG4 S1 ;1 second pause to reach the printer (run fast)\nG92 E0 ;zero the extruded length \nG1 F200 E35 ;slowly extrude 35mm of filament to clean the nozzle and build up extrusion pressure \nG92 E0 ;zero the extruded length again \nG1 F{speed_travel} ;Set travel speed \n;print" + "default_value": ";Layer height: {layer_height}\n;Walls: {wall_thickness}\n;Fill: {infill_sparse_density}\n;Top\\Bottom Thickness: {top_bottom_thickness}\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nG4 S1 ;1 millisecond pause to buffer the bep bep \nM300 S2 ;FAB bep bep (start the print, go check the oozing and skirt lines adesion) \nG4 S1 ;1 second pause to reach the printer (run fast)\nG92 E0 ;zero the extruded length \nG1 F200 E35 ;slowly extrude 35mm of filament to clean the nozzle and build up extrusion pressure \nG92 E0 ;zero the extruded length again \n;print" }, "machine_end_gcode": { - "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-3 X+5 Y+5 F5000 ;move Z up a bit and retract filament even more\n;end of the print\nM84 ;steppers off\nG90 ;absolute positioning\nM300 ;FAB bep bep (end print)" + "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-3 X+5 Y+5 F5000 ;move Z up a bit and retract filament even more\n;end of the print\nM84 ;steppers off\nG90 ;absolute positioning\nM300 S2 ;FAB bep bep (end print)" }, "gantry_height": { "default_value": 55 }, "machine_width": { "default_value": 214 }, From 2f37bd4b7318930a5bd0b5a8791c02bcb41cbbdf Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 15 Feb 2018 12:53:14 +0100 Subject: [PATCH 021/371] Add native rendering to Print Setup Label CURA-4941 --- resources/qml/Sidebar.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index f1cbfbcc60..57a8e8beaa 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -126,6 +126,7 @@ Rectangle { id: settingsModeLabel text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox", "Print Setup disabled\nG-code files cannot be modified") + renderType: Text.NativeRendering anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width anchors.top: hideSettings ? machineSelection.bottom : headerSeparator.bottom From f11a1341ee52069f47d9fbca5d2e043b7ff3b17d Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 15 Feb 2018 13:27:13 +0100 Subject: [PATCH 022/371] Fix rounded values in qml files --- plugins/ChangeLogPlugin/ChangeLog.qml | 4 ++-- resources/qml/AboutDialog.qml | 4 ++-- resources/qml/Preferences/MachinesPage.qml | 4 ++-- resources/qml/Preferences/ProfileTab.qml | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/ChangeLogPlugin/ChangeLog.qml b/plugins/ChangeLogPlugin/ChangeLog.qml index 512687f15a..f7715efb98 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.qml +++ b/plugins/ChangeLogPlugin/ChangeLog.qml @@ -11,8 +11,8 @@ import UM 1.1 as UM UM.Dialog { id: base - minimumWidth: (UM.Theme.getSize("modal_window_minimum").width * 0.75) | 0 - minimumHeight: (UM.Theme.getSize("modal_window_minimum").height * 0.75) | 0 + minimumWidth: Math.round(UM.Theme.getSize("modal_window_minimum").width * 0.75) | 0 + minimumHeight: Math.round(UM.Theme.getSize("modal_window_minimum").height * 0.75) | 0 width: minimumWidth height: minimumHeight title: catalog.i18nc("@label", "Changelog") diff --git a/resources/qml/AboutDialog.qml b/resources/qml/AboutDialog.qml index 30e540e80a..2c40aa4500 100644 --- a/resources/qml/AboutDialog.qml +++ b/resources/qml/AboutDialog.qml @@ -22,8 +22,8 @@ UM.Dialog Image { id: logo - width: (base.minimumWidth * 0.85) | 0 - height: (width * (1/4.25)) | 0 + width: Math.round(base.minimumWidth * 0.85) | 0 + height: Math.round(width * (1/4.25)) | 0 source: UM.Theme.getImage("logo") diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index 889dfa8d5b..597820f67b 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -160,7 +160,7 @@ UM.ManagementPage } Label { - width: (parent.width * 0.7) | 0 + width: Math.round(parent.width * 0.7) | 0 text: machineInfo.printerConnected ? machineInfo.connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.") visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId wrapMode: Text.WordWrap @@ -171,7 +171,7 @@ UM.ManagementPage visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId && machineInfo.printerAcceptsCommands } Label { - width: (parent.width * 0.7) | 0 + width: Math.round(parent.width * 0.7) | 0 text: { if(!machineInfo.printerConnected || !machineInfo.printerAcceptsCommands) { diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml index acebea3500..ee61feac34 100644 --- a/resources/qml/Preferences/ProfileTab.qml +++ b/resources/qml/Preferences/ProfileTab.qml @@ -51,14 +51,14 @@ Tab { role: "label" title: catalog.i18nc("@title:column", "Setting") - width: (parent.width * 0.4) | 0 + width: Math.round(parent.width * 0.4) | 0 delegate: itemDelegate } TableViewColumn { role: "profile_value" title: catalog.i18nc("@title:column", "Profile") - width: (parent.width * 0.18) | 0 + width: Math.round(parent.width * 0.18) | 0 delegate: itemDelegate } TableViewColumn @@ -66,14 +66,14 @@ Tab role: "user_value" title: catalog.i18nc("@title:column", "Current"); visible: quality == Cura.MachineManager.globalQualityId - width: (parent.width * 0.18) | 0 + width: Math.round(parent.width * 0.18) | 0 delegate: itemDelegate } TableViewColumn { role: "unit" title: catalog.i18nc("@title:column", "Unit") - width: (parent.width * 0.14) | 0 + width: Math.round(parent.width * 0.14) | 0 delegate: itemDelegate } From e7df8efe4daf2ea0783d45471358ed20a156e72c Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 15 Feb 2018 13:34:37 +0100 Subject: [PATCH 023/371] CURA-4698 Change value of setting as indicated by materials team --- .../quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg index 58e7fdc688..ccc558530e 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg @@ -33,7 +33,7 @@ multiple_mesh_overlap = 0 prime_tower_enable = False prime_tower_size = 16 prime_tower_wipe_enabled = True -retraction_count_max = 6 +retraction_count_max = 45 retraction_extra_prime_amount = 0.2 retraction_extrusion_window = 6.5 retraction_hop = 2 From 037298cf03792427d5304c99e270ac331947b8e2 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 15 Feb 2018 13:53:45 +0100 Subject: [PATCH 024/371] Tweaked the snapshot images to make it look prettier --- cura/PreviewPass.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cura/PreviewPass.py b/cura/PreviewPass.py index af42b59b78..b5b46f447c 100644 --- a/cura/PreviewPass.py +++ b/cura/PreviewPass.py @@ -17,6 +17,17 @@ MYPY = False if MYPY: from UM.Scene.Camera import Camera + +# Make color brighter by normalizing it (maximum factor 2.5 brighter) +def prettier_color(l): + maximum = max(l[:3]) + if maximum > 0: + factor = min(1 / maximum, 2.5) + else: + factor = 1.0 + return [min(i * factor, 1.0) for i in l] + + ## A render pass subclass that renders slicable objects with default parameters. # It uses the active camera by default, but it can be overridden to use a different camera. # @@ -41,6 +52,9 @@ class PreviewPass(RenderPass): if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader")) self._shader.setUniformValue("u_overhangAngle", 1.0) + self._shader.setUniformValue("u_ambientColor", [0.1, 0.1, 0.1, 1.0]) + self._shader.setUniformValue("u_specularColor", [0.6, 0.6, 0.6, 1.0]) + self._shader.setUniformValue("u_shininess", 20.0) self._gl.glClearColor(0.0, 0.0, 0.0, 0.0) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) @@ -52,7 +66,7 @@ class PreviewPass(RenderPass): for node in DepthFirstIterator(self._scene.getRoot()): if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible(): uniforms = {} - uniforms["diffuse_color"] = node.getDiffuseColor() + uniforms["diffuse_color"] = prettier_color(node.getDiffuseColor()) batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms) self.bind() From 38e84b962d634ab5575c0c4a8b1c39b8482605fc Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 15 Feb 2018 14:19:45 +0100 Subject: [PATCH 025/371] Make the large text a little bigger CURA-4790 --- resources/themes/cura-light/theme.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 2aa3037085..b7ab0000de 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -5,12 +5,12 @@ "fonts": { "large": { - "size": 1.25, + "size": 1.35, "bold": true, "family": "Noto Sans" }, "large_nonbold": { - "size": 1.25, + "size": 1.35, "family": "Noto Sans" }, "default": { From a2fde9f5f2f6a75f4d4cf02efd1b2baf584ab359 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 15 Feb 2018 14:58:58 +0100 Subject: [PATCH 026/371] Revert "Fix rounded values in qml files" This reverts commit f11a1341ee52069f47d9fbca5d2e043b7ff3b17d. --- plugins/ChangeLogPlugin/ChangeLog.qml | 4 ++-- resources/qml/AboutDialog.qml | 4 ++-- resources/qml/Preferences/MachinesPage.qml | 4 ++-- resources/qml/Preferences/ProfileTab.qml | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/ChangeLogPlugin/ChangeLog.qml b/plugins/ChangeLogPlugin/ChangeLog.qml index f7715efb98..512687f15a 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.qml +++ b/plugins/ChangeLogPlugin/ChangeLog.qml @@ -11,8 +11,8 @@ import UM 1.1 as UM UM.Dialog { id: base - minimumWidth: Math.round(UM.Theme.getSize("modal_window_minimum").width * 0.75) | 0 - minimumHeight: Math.round(UM.Theme.getSize("modal_window_minimum").height * 0.75) | 0 + minimumWidth: (UM.Theme.getSize("modal_window_minimum").width * 0.75) | 0 + minimumHeight: (UM.Theme.getSize("modal_window_minimum").height * 0.75) | 0 width: minimumWidth height: minimumHeight title: catalog.i18nc("@label", "Changelog") diff --git a/resources/qml/AboutDialog.qml b/resources/qml/AboutDialog.qml index 2c40aa4500..30e540e80a 100644 --- a/resources/qml/AboutDialog.qml +++ b/resources/qml/AboutDialog.qml @@ -22,8 +22,8 @@ UM.Dialog Image { id: logo - width: Math.round(base.minimumWidth * 0.85) | 0 - height: Math.round(width * (1/4.25)) | 0 + width: (base.minimumWidth * 0.85) | 0 + height: (width * (1/4.25)) | 0 source: UM.Theme.getImage("logo") diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index 597820f67b..889dfa8d5b 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -160,7 +160,7 @@ UM.ManagementPage } Label { - width: Math.round(parent.width * 0.7) | 0 + width: (parent.width * 0.7) | 0 text: machineInfo.printerConnected ? machineInfo.connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.") visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId wrapMode: Text.WordWrap @@ -171,7 +171,7 @@ UM.ManagementPage visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId && machineInfo.printerAcceptsCommands } Label { - width: Math.round(parent.width * 0.7) | 0 + width: (parent.width * 0.7) | 0 text: { if(!machineInfo.printerConnected || !machineInfo.printerAcceptsCommands) { diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml index ee61feac34..acebea3500 100644 --- a/resources/qml/Preferences/ProfileTab.qml +++ b/resources/qml/Preferences/ProfileTab.qml @@ -51,14 +51,14 @@ Tab { role: "label" title: catalog.i18nc("@title:column", "Setting") - width: Math.round(parent.width * 0.4) | 0 + width: (parent.width * 0.4) | 0 delegate: itemDelegate } TableViewColumn { role: "profile_value" title: catalog.i18nc("@title:column", "Profile") - width: Math.round(parent.width * 0.18) | 0 + width: (parent.width * 0.18) | 0 delegate: itemDelegate } TableViewColumn @@ -66,14 +66,14 @@ Tab role: "user_value" title: catalog.i18nc("@title:column", "Current"); visible: quality == Cura.MachineManager.globalQualityId - width: Math.round(parent.width * 0.18) | 0 + width: (parent.width * 0.18) | 0 delegate: itemDelegate } TableViewColumn { role: "unit" title: catalog.i18nc("@title:column", "Unit") - width: Math.round(parent.width * 0.14) | 0 + width: (parent.width * 0.14) | 0 delegate: itemDelegate } From 06ec77e0120dab132a0cdfd3090d0c712b9514b2 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 15 Feb 2018 15:23:17 +0100 Subject: [PATCH 027/371] Better readability in PreviewPass --- cura/PreviewPass.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cura/PreviewPass.py b/cura/PreviewPass.py index b5b46f447c..de21a5dc86 100644 --- a/cura/PreviewPass.py +++ b/cura/PreviewPass.py @@ -19,13 +19,14 @@ if MYPY: # Make color brighter by normalizing it (maximum factor 2.5 brighter) -def prettier_color(l): - maximum = max(l[:3]) +# color_list is a list of 4 elements: [r, g, b, a], each element is a float 0..1 +def prettier_color(color_list): + maximum = max(color_list[:3]) if maximum > 0: factor = min(1 / maximum, 2.5) else: factor = 1.0 - return [min(i * factor, 1.0) for i in l] + return [min(i * factor, 1.0) for i in color_list] ## A render pass subclass that renders slicable objects with default parameters. From c508e77fe2e18152d4af056d7a6b835856955a44 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 15 Feb 2018 15:49:06 +0100 Subject: [PATCH 028/371] Improved the text --- cura/CrashHandler.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index 4d8cb6f54d..24df54b74e 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -13,9 +13,8 @@ import ssl import urllib.request import urllib.error import shutil -import sys -from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR +from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QFile from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox, QCheckBox, QPushButton from UM.Application import Application @@ -23,6 +22,7 @@ from UM.Logger import Logger from UM.View.GL.OpenGL import OpenGL from UM.i18n import i18nCatalog from UM.Platform import Platform +from UM.Resources import Resources catalog = i18nCatalog("cura") @@ -91,6 +91,7 @@ class CrashHandler: label = QLabel() label.setText(catalog.i18nc("@label crash message", """

    A fatal error has occurred.

    Unfortunately, Cura encountered an unrecoverable error during start up. It was possibly caused by some incorrect configuration files. We suggest to backup and reset your configuration.

    +

    Your backup can be found in your Configuration folder.

    Please send us this Crash Report to fix the problem.

    """)) label.setWordWrap(True) From 86b31c3a6c31632af75b8a1071831081e4c38afb Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 16 Feb 2018 09:12:42 +0100 Subject: [PATCH 029/371] Fix: in 3.0 version we did not save quality type under extruder.cfg in project for custom fdm pritners. For this case during deserializing share quality stack between global and extruder's stacks CURA-4966 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index a2e02fa9d4..8291ca3b52 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -775,6 +775,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Ensure a unique ID and name stack.setMetaDataEntry("id", new_id) + # Keep same quality between extruders and global stack + stack.quality = global_stack.quality + self._container_registry.addContainer(stack) extruder_stacks_added.append(stack) containers_added.append(stack) From 735dac6a4a9ee6572d4255eb237e1639c9ef78bf Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 16 Feb 2018 09:15:06 +0100 Subject: [PATCH 030/371] Modify debug message to show the correct/useful information --- cura/Settings/CuraContainerRegistry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 148ed6fe59..e26dab7399 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -235,7 +235,7 @@ class CuraContainerRegistry(ContainerRegistry): if not expected_machine_definition: expected_machine_definition = global_container_stack.definition.getId() if expected_machine_definition is not None and profile_definition is not None and profile_definition != expected_machine_definition: - Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name) + Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition) return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} doesn't match with your current machine, could not import it.", file_name)} From 85059882fedd73525ccae1a59287b3614bf7609a Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 16 Feb 2018 11:01:02 +0100 Subject: [PATCH 031/371] CURA-4959 Add buildplate information to the summary when saving a project file. - The activeVariantNames now returns only the names of the variants in the extruder stacks. --- cura/Settings/MachineManager.py | 3 ++- resources/qml/WorkspaceSummaryDialog.qml | 25 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7e0e67a7e0..cc5c4aa539 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -559,7 +559,8 @@ class MachineManager(QObject): def activeVariantNames(self) -> List[str]: result = [] - active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() + # Just return the variants in the extruder stack(s). For the variant in the global stack, use activeVariantBuildplateName + active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() if active_stacks is not None: for stack in active_stacks: variant_container = stack.variant diff --git a/resources/qml/WorkspaceSummaryDialog.qml b/resources/qml/WorkspaceSummaryDialog.qml index d5cc416f39..a05dee5a9a 100644 --- a/resources/qml/WorkspaceSummaryDialog.qml +++ b/resources/qml/WorkspaceSummaryDialog.qml @@ -120,6 +120,31 @@ UM.Dialog width: (parent.width / 3) | 0 } } + Column + { + width: parent.width + visible: Cura.MachineManager.hasVariantBuildplates + Item // Spacer + { + height: spacerHeight + width: height + } + Row + { + width: parent.width + height: childrenRect.height + Label + { + text: catalog.i18nc("@action:label", "Build plate") + width: (parent.width / 3) | 0 + } + Label + { + text: Cura.MachineManager.activeVariantBuildplateName + width: (parent.width / 3) | 0 + } + } + } Repeater { From 4a0a9f521c1a0a2d957b18acbd60dcf3d66bc5b9 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 16 Feb 2018 11:13:40 +0100 Subject: [PATCH 032/371] Bumped the required version numbers down again, as they should specifcy a min version number. As the summary describes; We should use *min* version numbers. If we have a higher version installed as defined, it will have the bugfixes and not the features. Increasing version nr should therefore only be done if we want new features. --- resources/qml/PrintMonitor.qml | 2 +- resources/qml/SaveButton.qml | 2 +- resources/qml/Settings/SettingCheckBox.qml | 4 ++-- resources/qml/Settings/SettingItem.qml | 4 ++-- resources/qml/SidebarContents.qml | 2 +- resources/qml/SidebarHeader.qml | 2 +- resources/qml/SidebarTooltip.qml | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 95b17e9abe..0841144043 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 import QtQuick.Layouts 1.1 diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index bd43b25db7..0369f492b4 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 import QtQuick.Layouts 1.1 diff --git a/resources/qml/Settings/SettingCheckBox.qml b/resources/qml/Settings/SettingCheckBox.qml index d8105e2ae1..d37754d27c 100644 --- a/resources/qml/Settings/SettingCheckBox.qml +++ b/resources/qml/Settings/SettingCheckBox.qml @@ -1,9 +1,9 @@ // Copyright (c) 2018 Ultimaker B.V. // Uranium is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Layouts 1.2 -import QtQuick.Controls 2.1 +import QtQuick.Controls 2.0 import UM 1.2 as UM diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index b2535d6b41..013371e528 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -1,9 +1,9 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Layouts 1.2 -import QtQuick.Controls 2.1 +import QtQuick.Controls 2.0 import UM 1.1 as UM import Cura 1.0 as Cura diff --git a/resources/qml/SidebarContents.qml b/resources/qml/SidebarContents.qml index e15fabd89b..0b19bfe3c1 100644 --- a/resources/qml/SidebarContents.qml +++ b/resources/qml/SidebarContents.qml @@ -1,7 +1,7 @@ // Copyright (c) 2016 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 import QtQuick.Layouts 1.1 diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index 6c4731931e..d43b8d3752 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 diff --git a/resources/qml/SidebarTooltip.qml b/resources/qml/SidebarTooltip.qml index 6756763c8a..29199481f6 100644 --- a/resources/qml/SidebarTooltip.qml +++ b/resources/qml/SidebarTooltip.qml @@ -1,7 +1,7 @@ // Copyright (c) 2015 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 import QtQuick.Layouts 1.1 From f89793095078da6588941d005e35b3ace8e7495d Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 16 Feb 2018 11:48:08 +0100 Subject: [PATCH 033/371] Fix: Allow connection button for other printers CURA-4962 --- plugins/UM3NetworkPrinting/UM3InfoComponents.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/UM3InfoComponents.qml b/plugins/UM3NetworkPrinting/UM3InfoComponents.qml index 18b481a6ed..5a9cc096e7 100644 --- a/plugins/UM3NetworkPrinting/UM3InfoComponents.qml +++ b/plugins/UM3NetworkPrinting/UM3InfoComponents.qml @@ -10,7 +10,8 @@ Item { id: base - property bool isUM3: Cura.MachineManager.activeQualityDefinitionId == "ultimaker3" + property string activeQualityDefinitionId: Cura.MachineManager.activeQualityDefinitionId + property bool isUM3: activeQualityDefinitionId == "ultimaker3" || activeQualityDefinitionId.match("ultimaker_") != null property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands property bool authenticationRequested: printerConnected && (Cura.MachineManager.printerOutputDevices[0].authenticationState == 2 || Cura.MachineManager.printerOutputDevices[0].authenticationState == 5) // AuthState.AuthenticationRequested or AuthenticationReceived. From 744313af273ed34a5796d3970c3915f68abaedc7 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 16 Feb 2018 14:01:46 +0100 Subject: [PATCH 034/371] CURA-4946 Add the quality_definition metadata entry to the gcode so when parsing, the quality definition is taken into account instead of the definition. The message when importing a profile to a different machine, now shows the expected machine and the current machine definition id.!! --- cura/Settings/CuraContainerRegistry.py | 17 ++++++++++++----- plugins/GCodeWriter/GCodeWriter.py | 5 +++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index e26dab7399..be5a10e293 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -228,16 +228,23 @@ class CuraContainerRegistry(ContainerRegistry): Logger.log("e", "Incorrect profile [%s]. Could not find global profile", file_name) return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "This profile {0} contains incorrect data, could not import it.", file_name)} - profile_definition = global_profile.getMetaDataEntry("definition") - expected_machine_definition = "fdmprinter" + + # In a profile we can have the quality_definition metadata, but if not, we get the definition + profile_definition = global_profile.getMetaDataEntry("quality_definition") + if not profile_definition: + profile_definition = global_profile.getMetaDataEntry("definition") + + # The expected machine definition may be the quality_definition if defined or the current definition id + expected_machine_definition = None if parseBool(global_container_stack.getMetaDataEntry("has_machine_quality", "False")): expected_machine_definition = global_container_stack.getMetaDataEntry("quality_definition") - if not expected_machine_definition: - expected_machine_definition = global_container_stack.definition.getId() + if not expected_machine_definition: + expected_machine_definition = global_container_stack.definition.getId() + if expected_machine_definition is not None and profile_definition is not None and profile_definition != expected_machine_definition: Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition) return { "status": "error", - "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} doesn't match with your current machine, could not import it.", file_name)} + "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it.", file_name, profile_definition, expected_machine_definition)} name_seed = os.path.splitext(os.path.basename(file_name))[0] new_name = self.uniqueName(name_seed) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index d06332bec1..368942fd08 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -5,6 +5,7 @@ from UM.Mesh.MeshWriter import MeshWriter from UM.Logger import Logger from UM.Application import Application from UM.Settings.InstanceContainer import InstanceContainer +from UM.Util import parseBool from cura.Settings.ExtruderManager import ExtruderManager @@ -120,6 +121,10 @@ class GCodeWriter(MeshWriter): if flat_global_container.getMetaDataEntry("quality_type", None) is None: flat_global_container.addMetaDataEntry("quality_type", stack.quality.getMetaDataEntry("quality_type", "normal")) + # Ensure that quality_definition is set. (Can happen if we have empty quality changes). + if parseBool(stack.getMetaDataEntry("has_machine_quality", "False")): + flat_global_container.addMetaDataEntry("quality_definition", stack.getMetaDataEntry("quality_definition")) + serialized = flat_global_container.serialize() data = {"global_quality": serialized} From b3d0438daa109490ebbdb8fed0b09a3a0280693a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Feb 2018 16:13:09 +0100 Subject: [PATCH 035/371] WIP: Update variant files - Remove "author" from "metadata" section - Add "hardware_type" for variants that don't have it - Reformat "metadata" section to have the following order: - setting_version - type - hardware_type --- resources/variants/cartesio_0.25.inst.cfg | 3 +-- resources/variants/cartesio_0.4.inst.cfg | 3 +-- resources/variants/cartesio_0.8.inst.cfg | 3 +-- resources/variants/fabtotum_hyb35.inst.cfg | 3 +-- resources/variants/fabtotum_lite04.inst.cfg | 3 +-- resources/variants/fabtotum_lite06.inst.cfg | 3 +-- resources/variants/fabtotum_pro02.inst.cfg | 3 +-- resources/variants/fabtotum_pro04.inst.cfg | 3 +-- resources/variants/fabtotum_pro06.inst.cfg | 3 +-- resources/variants/fabtotum_pro08.inst.cfg | 3 +-- resources/variants/gmax15plus_025_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_04_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_05_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_05_jhead.inst.cfg | 4 ++-- resources/variants/gmax15plus_06_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_08_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_10_jhead.inst.cfg | 4 ++-- resources/variants/gmax15plus_dual_025_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_dual_04_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_dual_05_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_dual_05_jhead.inst.cfg | 4 ++-- resources/variants/gmax15plus_dual_06_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_dual_08_e3d.inst.cfg | 4 ++-- resources/variants/gmax15plus_dual_10_jhead.inst.cfg | 4 ++-- resources/variants/imade3d_jellybox_0.4.inst.cfg | 3 +-- resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg | 3 +-- resources/variants/ultimaker2_0.25.inst.cfg | 5 ++--- resources/variants/ultimaker2_0.4.inst.cfg | 3 +-- resources/variants/ultimaker2_0.6.inst.cfg | 3 +-- resources/variants/ultimaker2_0.8.inst.cfg | 3 +-- resources/variants/ultimaker2_extended_0.25.inst.cfg | 3 +-- resources/variants/ultimaker2_extended_0.4.inst.cfg | 3 +-- resources/variants/ultimaker2_extended_0.6.inst.cfg | 3 +-- resources/variants/ultimaker2_extended_0.8.inst.cfg | 3 +-- resources/variants/ultimaker2_extended_plus_0.25.inst.cfg | 3 +-- resources/variants/ultimaker2_extended_plus_0.4.inst.cfg | 3 +-- resources/variants/ultimaker2_extended_plus_0.6.inst.cfg | 3 +-- resources/variants/ultimaker2_extended_plus_0.8.inst.cfg | 3 +-- resources/variants/ultimaker2_plus_0.25.inst.cfg | 3 +-- resources/variants/ultimaker2_plus_0.4.inst.cfg | 3 +-- resources/variants/ultimaker2_plus_0.6.inst.cfg | 3 +-- resources/variants/ultimaker2_plus_0.8.inst.cfg | 3 +-- resources/variants/ultimaker3_aa0.25.inst.cfg | 3 +-- resources/variants/ultimaker3_aa0.8.inst.cfg | 3 +-- resources/variants/ultimaker3_aa04.inst.cfg | 4 +--- resources/variants/ultimaker3_bb0.8.inst.cfg | 3 +-- resources/variants/ultimaker3_bb04.inst.cfg | 5 ++--- resources/variants/ultimaker3_extended_aa0.25.inst.cfg | 4 +--- resources/variants/ultimaker3_extended_aa0.8.inst.cfg | 3 +-- resources/variants/ultimaker3_extended_aa04.inst.cfg | 3 +-- resources/variants/ultimaker3_extended_bb0.8.inst.cfg | 3 +-- resources/variants/ultimaker3_extended_bb04.inst.cfg | 5 ++--- 52 files changed, 69 insertions(+), 109 deletions(-) diff --git a/resources/variants/cartesio_0.25.inst.cfg b/resources/variants/cartesio_0.25.inst.cfg index 0cc01093f2..2272aebde5 100644 --- a/resources/variants/cartesio_0.25.inst.cfg +++ b/resources/variants/cartesio_0.25.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = cartesio [metadata] -author = Cartesio -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/cartesio_0.4.inst.cfg b/resources/variants/cartesio_0.4.inst.cfg index 9920e699f5..bd3302da03 100644 --- a/resources/variants/cartesio_0.4.inst.cfg +++ b/resources/variants/cartesio_0.4.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = cartesio [metadata] -author = Cartesio -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/cartesio_0.8.inst.cfg b/resources/variants/cartesio_0.8.inst.cfg index 8031a9fa31..eda8248584 100644 --- a/resources/variants/cartesio_0.8.inst.cfg +++ b/resources/variants/cartesio_0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = cartesio [metadata] -author = Cartesio -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/fabtotum_hyb35.inst.cfg b/resources/variants/fabtotum_hyb35.inst.cfg index e8fa13cc0d..6d699f6df8 100644 --- a/resources/variants/fabtotum_hyb35.inst.cfg +++ b/resources/variants/fabtotum_hyb35.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = fabtotum [metadata] -author = FABtotum -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/fabtotum_lite04.inst.cfg b/resources/variants/fabtotum_lite04.inst.cfg index 7264abbdda..5d376de4a1 100644 --- a/resources/variants/fabtotum_lite04.inst.cfg +++ b/resources/variants/fabtotum_lite04.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = fabtotum [metadata] -author = FABtotum -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/fabtotum_lite06.inst.cfg b/resources/variants/fabtotum_lite06.inst.cfg index 0ad33ca332..0181461613 100644 --- a/resources/variants/fabtotum_lite06.inst.cfg +++ b/resources/variants/fabtotum_lite06.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = fabtotum [metadata] -author = FABtotum -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/fabtotum_pro02.inst.cfg b/resources/variants/fabtotum_pro02.inst.cfg index d83618b712..c63ed6d982 100644 --- a/resources/variants/fabtotum_pro02.inst.cfg +++ b/resources/variants/fabtotum_pro02.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = fabtotum [metadata] -author = FABtotum -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/fabtotum_pro04.inst.cfg b/resources/variants/fabtotum_pro04.inst.cfg index 4f2a622887..6fc2d7c4f7 100644 --- a/resources/variants/fabtotum_pro04.inst.cfg +++ b/resources/variants/fabtotum_pro04.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = fabtotum [metadata] -author = FABtotum -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/fabtotum_pro06.inst.cfg b/resources/variants/fabtotum_pro06.inst.cfg index aa44e762ba..bf48b91965 100644 --- a/resources/variants/fabtotum_pro06.inst.cfg +++ b/resources/variants/fabtotum_pro06.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = fabtotum [metadata] -author = FABtotum -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/fabtotum_pro08.inst.cfg b/resources/variants/fabtotum_pro08.inst.cfg index 597d23275e..83f13ef8fc 100644 --- a/resources/variants/fabtotum_pro08.inst.cfg +++ b/resources/variants/fabtotum_pro08.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = fabtotum [metadata] -author = FABtotum -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/gmax15plus_025_e3d.inst.cfg b/resources/variants/gmax15plus_025_e3d.inst.cfg index 0500a63638..88730e6722 100644 --- a/resources/variants/gmax15plus_025_e3d.inst.cfg +++ b/resources/variants/gmax15plus_025_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.25 diff --git a/resources/variants/gmax15plus_04_e3d.inst.cfg b/resources/variants/gmax15plus_04_e3d.inst.cfg index 514893a8a5..f107d2ab16 100644 --- a/resources/variants/gmax15plus_04_e3d.inst.cfg +++ b/resources/variants/gmax15plus_04_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.4 diff --git a/resources/variants/gmax15plus_05_e3d.inst.cfg b/resources/variants/gmax15plus_05_e3d.inst.cfg index 2579409d5a..72081a4b3d 100644 --- a/resources/variants/gmax15plus_05_e3d.inst.cfg +++ b/resources/variants/gmax15plus_05_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.5 diff --git a/resources/variants/gmax15plus_05_jhead.inst.cfg b/resources/variants/gmax15plus_05_jhead.inst.cfg index ca107c9559..ca086fca96 100644 --- a/resources/variants/gmax15plus_05_jhead.inst.cfg +++ b/resources/variants/gmax15plus_05_jhead.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.5 diff --git a/resources/variants/gmax15plus_06_e3d.inst.cfg b/resources/variants/gmax15plus_06_e3d.inst.cfg index eb709f1487..bbb5d18df1 100644 --- a/resources/variants/gmax15plus_06_e3d.inst.cfg +++ b/resources/variants/gmax15plus_06_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.6 diff --git a/resources/variants/gmax15plus_08_e3d.inst.cfg b/resources/variants/gmax15plus_08_e3d.inst.cfg index 093bce99c0..944420e064 100644 --- a/resources/variants/gmax15plus_08_e3d.inst.cfg +++ b/resources/variants/gmax15plus_08_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.8 diff --git a/resources/variants/gmax15plus_10_jhead.inst.cfg b/resources/variants/gmax15plus_10_jhead.inst.cfg index 977469e304..832861a98a 100644 --- a/resources/variants/gmax15plus_10_jhead.inst.cfg +++ b/resources/variants/gmax15plus_10_jhead.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.5 diff --git a/resources/variants/gmax15plus_dual_025_e3d.inst.cfg b/resources/variants/gmax15plus_dual_025_e3d.inst.cfg index b083174beb..b80074479e 100644 --- a/resources/variants/gmax15plus_dual_025_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_025_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus_dual [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.25 diff --git a/resources/variants/gmax15plus_dual_04_e3d.inst.cfg b/resources/variants/gmax15plus_dual_04_e3d.inst.cfg index f1a95f4f2a..3f25835e3a 100644 --- a/resources/variants/gmax15plus_dual_04_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_04_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus_dual [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.4 diff --git a/resources/variants/gmax15plus_dual_05_e3d.inst.cfg b/resources/variants/gmax15plus_dual_05_e3d.inst.cfg index dd148f8082..c7dccfd7c7 100644 --- a/resources/variants/gmax15plus_dual_05_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_05_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus_dual [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.5 diff --git a/resources/variants/gmax15plus_dual_05_jhead.inst.cfg b/resources/variants/gmax15plus_dual_05_jhead.inst.cfg index 7e038a3980..0cffafee3b 100644 --- a/resources/variants/gmax15plus_dual_05_jhead.inst.cfg +++ b/resources/variants/gmax15plus_dual_05_jhead.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus_dual [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.5 diff --git a/resources/variants/gmax15plus_dual_06_e3d.inst.cfg b/resources/variants/gmax15plus_dual_06_e3d.inst.cfg index 93cf21780f..a0dc450ec0 100644 --- a/resources/variants/gmax15plus_dual_06_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_06_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus_dual [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.6 diff --git a/resources/variants/gmax15plus_dual_08_e3d.inst.cfg b/resources/variants/gmax15plus_dual_08_e3d.inst.cfg index 3088113f27..547cee823d 100644 --- a/resources/variants/gmax15plus_dual_08_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_08_e3d.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus_dual [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.8 diff --git a/resources/variants/gmax15plus_dual_10_jhead.inst.cfg b/resources/variants/gmax15plus_dual_10_jhead.inst.cfg index a526cc676e..a565c073af 100644 --- a/resources/variants/gmax15plus_dual_10_jhead.inst.cfg +++ b/resources/variants/gmax15plus_dual_10_jhead.inst.cfg @@ -4,9 +4,9 @@ version = 2 definition = gmax15plus_dual [metadata] -author = gcreate -type = variant setting_version = 4 +type = variant +hardware_type = nozzle [values] machine_nozzle_size = 0.5 diff --git a/resources/variants/imade3d_jellybox_0.4.inst.cfg b/resources/variants/imade3d_jellybox_0.4.inst.cfg index c37a2ecabf..cb20dadbf7 100644 --- a/resources/variants/imade3d_jellybox_0.4.inst.cfg +++ b/resources/variants/imade3d_jellybox_0.4.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = imade3d_jellybox [metadata] -author = IMADE3D -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg b/resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg index c3e63aab34..95b696f432 100644 --- a/resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg +++ b/resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = imade3d_jellybox [metadata] -author = IMADE3D -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_0.25.inst.cfg b/resources/variants/ultimaker2_0.25.inst.cfg index aee83e2483..2b1b04f123 100644 --- a/resources/variants/ultimaker2_0.25.inst.cfg +++ b/resources/variants/ultimaker2_0.25.inst.cfg @@ -4,12 +4,11 @@ version = 2 definition = ultimaker2 [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] machine_nozzle_size = 0.25 machine_nozzle_tip_outer_diameter = 0.8 -raft_airgap = 0.25 \ No newline at end of file +raft_airgap = 0.25 diff --git a/resources/variants/ultimaker2_0.4.inst.cfg b/resources/variants/ultimaker2_0.4.inst.cfg index fe128137d9..8886992f6f 100644 --- a/resources/variants/ultimaker2_0.4.inst.cfg +++ b/resources/variants/ultimaker2_0.4.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2 [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_0.6.inst.cfg b/resources/variants/ultimaker2_0.6.inst.cfg index 7fea2fbb22..42de9d3ee8 100644 --- a/resources/variants/ultimaker2_0.6.inst.cfg +++ b/resources/variants/ultimaker2_0.6.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2 [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_0.8.inst.cfg b/resources/variants/ultimaker2_0.8.inst.cfg index 5f1176b7ec..df2ca88ba2 100644 --- a/resources/variants/ultimaker2_0.8.inst.cfg +++ b/resources/variants/ultimaker2_0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2 [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_extended_0.25.inst.cfg b/resources/variants/ultimaker2_extended_0.25.inst.cfg index e705327cf8..f04a28e5ba 100644 --- a/resources/variants/ultimaker2_extended_0.25.inst.cfg +++ b/resources/variants/ultimaker2_extended_0.25.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_extended [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_extended_0.4.inst.cfg b/resources/variants/ultimaker2_extended_0.4.inst.cfg index d486ed4f4e..c54202750a 100644 --- a/resources/variants/ultimaker2_extended_0.4.inst.cfg +++ b/resources/variants/ultimaker2_extended_0.4.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_extended [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_extended_0.6.inst.cfg b/resources/variants/ultimaker2_extended_0.6.inst.cfg index f9dd4d4e69..67176632aa 100644 --- a/resources/variants/ultimaker2_extended_0.6.inst.cfg +++ b/resources/variants/ultimaker2_extended_0.6.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_extended [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_extended_0.8.inst.cfg b/resources/variants/ultimaker2_extended_0.8.inst.cfg index ee56b6d194..61917309ef 100644 --- a/resources/variants/ultimaker2_extended_0.8.inst.cfg +++ b/resources/variants/ultimaker2_extended_0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_extended [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_extended_plus_0.25.inst.cfg b/resources/variants/ultimaker2_extended_plus_0.25.inst.cfg index f23406fec3..6386d71f50 100644 --- a/resources/variants/ultimaker2_extended_plus_0.25.inst.cfg +++ b/resources/variants/ultimaker2_extended_plus_0.25.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_extended_plus [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_extended_plus_0.4.inst.cfg b/resources/variants/ultimaker2_extended_plus_0.4.inst.cfg index c0b1c6ab79..1426f733cc 100644 --- a/resources/variants/ultimaker2_extended_plus_0.4.inst.cfg +++ b/resources/variants/ultimaker2_extended_plus_0.4.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_extended_plus [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_extended_plus_0.6.inst.cfg b/resources/variants/ultimaker2_extended_plus_0.6.inst.cfg index 6ef64bed5f..5ea4072022 100644 --- a/resources/variants/ultimaker2_extended_plus_0.6.inst.cfg +++ b/resources/variants/ultimaker2_extended_plus_0.6.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_extended_plus [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_extended_plus_0.8.inst.cfg b/resources/variants/ultimaker2_extended_plus_0.8.inst.cfg index 2f890d0827..69b2b9b0d0 100644 --- a/resources/variants/ultimaker2_extended_plus_0.8.inst.cfg +++ b/resources/variants/ultimaker2_extended_plus_0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_extended_plus [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_plus_0.25.inst.cfg b/resources/variants/ultimaker2_plus_0.25.inst.cfg index 1c4688568d..2b40656cf4 100644 --- a/resources/variants/ultimaker2_plus_0.25.inst.cfg +++ b/resources/variants/ultimaker2_plus_0.25.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_plus [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_plus_0.4.inst.cfg b/resources/variants/ultimaker2_plus_0.4.inst.cfg index 00a4ef47dd..0aaf4f4e5a 100644 --- a/resources/variants/ultimaker2_plus_0.4.inst.cfg +++ b/resources/variants/ultimaker2_plus_0.4.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_plus [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_plus_0.6.inst.cfg b/resources/variants/ultimaker2_plus_0.6.inst.cfg index 4dceab70d0..7988a949bc 100644 --- a/resources/variants/ultimaker2_plus_0.6.inst.cfg +++ b/resources/variants/ultimaker2_plus_0.6.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_plus [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker2_plus_0.8.inst.cfg b/resources/variants/ultimaker2_plus_0.8.inst.cfg index e1bbddb823..1a7824b0b1 100644 --- a/resources/variants/ultimaker2_plus_0.8.inst.cfg +++ b/resources/variants/ultimaker2_plus_0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker2_plus [metadata] -author = Ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker3_aa0.25.inst.cfg b/resources/variants/ultimaker3_aa0.25.inst.cfg index 2d2d893202..8f06e73f91 100644 --- a/resources/variants/ultimaker3_aa0.25.inst.cfg +++ b/resources/variants/ultimaker3_aa0.25.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3 [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker3_aa0.8.inst.cfg b/resources/variants/ultimaker3_aa0.8.inst.cfg index 402190c357..218c1ea3bf 100644 --- a/resources/variants/ultimaker3_aa0.8.inst.cfg +++ b/resources/variants/ultimaker3_aa0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3 [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker3_aa04.inst.cfg b/resources/variants/ultimaker3_aa04.inst.cfg index 0163024fa4..2964ab74a0 100644 --- a/resources/variants/ultimaker3_aa04.inst.cfg +++ b/resources/variants/ultimaker3_aa04.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3 [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] @@ -40,4 +39,3 @@ switch_extruder_prime_speed = =switch_extruder_retraction_speeds switch_extruder_retraction_amount = =machine_heat_zone_length top_bottom_thickness = 1.2 wall_thickness = 1.3 - diff --git a/resources/variants/ultimaker3_bb0.8.inst.cfg b/resources/variants/ultimaker3_bb0.8.inst.cfg index 017da649a0..03b38f225c 100644 --- a/resources/variants/ultimaker3_bb0.8.inst.cfg +++ b/resources/variants/ultimaker3_bb0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3 [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker3_bb04.inst.cfg b/resources/variants/ultimaker3_bb04.inst.cfg index 93b2025031..78d201318d 100644 --- a/resources/variants/ultimaker3_bb04.inst.cfg +++ b/resources/variants/ultimaker3_bb04.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3 [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] @@ -47,4 +46,4 @@ support_line_width = =round(line_width * 0.4 / 0.35, 2) support_offset = 3 support_xy_distance = =round(wall_line_width_0 * 0.75, 2) support_xy_distance_overhang = =wall_line_width_0 / 2 -switch_extruder_retraction_amount = 12 \ No newline at end of file +switch_extruder_retraction_amount = 12 diff --git a/resources/variants/ultimaker3_extended_aa0.25.inst.cfg b/resources/variants/ultimaker3_extended_aa0.25.inst.cfg index 04d7a7990a..f45d90b762 100644 --- a/resources/variants/ultimaker3_extended_aa0.25.inst.cfg +++ b/resources/variants/ultimaker3_extended_aa0.25.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3_extended [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] @@ -38,4 +37,3 @@ support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_line_width_x = 0.23 wall_thickness = 1.3 - diff --git a/resources/variants/ultimaker3_extended_aa0.8.inst.cfg b/resources/variants/ultimaker3_extended_aa0.8.inst.cfg index 3e1b3ed3de..1f5709e504 100644 --- a/resources/variants/ultimaker3_extended_aa0.8.inst.cfg +++ b/resources/variants/ultimaker3_extended_aa0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3_extended [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker3_extended_aa04.inst.cfg b/resources/variants/ultimaker3_extended_aa04.inst.cfg index 94bee65b5d..4d9d2b4646 100644 --- a/resources/variants/ultimaker3_extended_aa04.inst.cfg +++ b/resources/variants/ultimaker3_extended_aa04.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3_extended [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker3_extended_bb0.8.inst.cfg b/resources/variants/ultimaker3_extended_bb0.8.inst.cfg index e1086535ec..752083f42a 100644 --- a/resources/variants/ultimaker3_extended_bb0.8.inst.cfg +++ b/resources/variants/ultimaker3_extended_bb0.8.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3_extended [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] diff --git a/resources/variants/ultimaker3_extended_bb04.inst.cfg b/resources/variants/ultimaker3_extended_bb04.inst.cfg index a995acf77c..1ceaf58c5b 100644 --- a/resources/variants/ultimaker3_extended_bb04.inst.cfg +++ b/resources/variants/ultimaker3_extended_bb04.inst.cfg @@ -4,9 +4,8 @@ version = 2 definition = ultimaker3_extended [metadata] -author = ultimaker -type = variant setting_version = 4 +type = variant hardware_type = nozzle [values] @@ -47,4 +46,4 @@ support_line_width = =round(line_width * 0.4 / 0.35, 2) support_offset = 3 support_xy_distance = =round(wall_line_width_0 * 0.75, 2) support_xy_distance_overhang = =wall_line_width_0 / 2 -switch_extruder_retraction_amount = 12 \ No newline at end of file +switch_extruder_retraction_amount = 12 From 86eb9b925f3bc8e63e51b820e193c789e2feba2e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 7 Feb 2018 14:15:51 +0100 Subject: [PATCH 036/371] WIP: Use variant_name in metadata for XMLMaterialProfile --- .../XmlMaterialProfile/XmlMaterialProfile.py | 64 +++++-------------- 1 file changed, 15 insertions(+), 49 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index f0d016025e..a7d9a7be26 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -618,16 +618,9 @@ class XmlMaterialProfile(InstanceContainer): hotends = machine.iterfind("./um:hotend", self.__namespaces) for hotend in hotends: - hotend_id = hotend.get("id") - if hotend_id is None: - continue - - variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = hotend_id) - if not variant_containers: - # It is not really properly defined what "ID" is so also search for variants by name. - variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = hotend_id) - - if not variant_containers: + # The "id" field for hotends in material profiles are actually + hotend_name = hotend.get("id") + if hotend_name is None: continue hotend_compatibility = machine_compatibility @@ -643,20 +636,20 @@ class XmlMaterialProfile(InstanceContainer): else: Logger.log("d", "Unsupported material setting %s", key) - new_hotend_id = self.getId() + "_" + machine_id + "_" + hotend_id.replace(" ", "_") + new_hotend_specific_material_id = self.getId() + "_" + machine_id + "_" + hotend_name.replace(" ", "_") # Same as machine compatibility, keep the derived material containers consistent with the parent material - if ContainerRegistry.getInstance().isLoaded(new_hotend_id): - new_hotend_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_id)[0] + if ContainerRegistry.getInstance().isLoaded(new_hotend_specific_material_id): + new_hotend_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_specific_material_id)[0] is_new_material = False else: - new_hotend_material = XmlMaterialProfile(new_hotend_id) + new_hotend_material = XmlMaterialProfile(new_hotend_specific_material_id) is_new_material = True new_hotend_material.setMetaData(copy.deepcopy(self.getMetaData())) - new_hotend_material.getMetaData()["id"] = new_hotend_id + new_hotend_material.getMetaData()["id"] = new_hotend_specific_material_id new_hotend_material.getMetaData()["name"] = self.getName() - new_hotend_material.getMetaData()["variant"] = variant_containers[0]["id"] + new_hotend_material.getMetaData()["variant_name"] = hotend_name new_hotend_material.setDefinition(machine_id) # Don't use setMetadata, as that overrides it for all materials with same base file new_hotend_material.getMetaData()["compatible"] = hotend_compatibility @@ -833,39 +826,30 @@ class XmlMaterialProfile(InstanceContainer): buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_map["buildplate_recommended"] for hotend in machine.iterfind("./um:hotend", cls.__namespaces): - hotend_id = hotend.get("id") - if hotend_id is None: + hotend_name = hotend.get("id") + if hotend_name is None: continue - variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = hotend_id) - if not variant_containers: - # It is not really properly defined what "ID" is so also search for variants by name. - variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = hotend_id) - hotend_compatibility = machine_compatibility for entry in hotend.iterfind("./um:setting", cls.__namespaces): key = entry.get("key") if key == "hardware compatible": hotend_compatibility = cls._parseCompatibleValue(entry.text) - new_hotend_id = container_id + "_" + machine_id + "_" + hotend_id.replace(" ", "_") + new_hotend_specific_material_id = container_id + "_" + machine_id + "_" + hotend_name.replace(" ", "_") # Same as machine compatibility, keep the derived material containers consistent with the parent material - found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_hotend_id) + found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_hotend_specific_material_id) if found_materials: new_hotend_material_metadata = found_materials[0] else: new_hotend_material_metadata = {} new_hotend_material_metadata.update(base_metadata) - if variant_containers: - new_hotend_material_metadata["variant"] = variant_containers[0]["id"] - else: - new_hotend_material_metadata["variant"] = hotend_id - _with_missing_variants.append(new_hotend_material_metadata) + new_hotend_material_metadata["variant_name"] = hotend_name new_hotend_material_metadata["compatible"] = hotend_compatibility new_hotend_material_metadata["machine_manufacturer"] = machine_manufacturer - new_hotend_material_metadata["id"] = new_hotend_id + new_hotend_material_metadata["id"] = new_hotend_specific_material_id new_hotend_material_metadata["definition"] = machine_id if buildplate_map["buildplate_compatible"]: new_hotend_material_metadata["buildplate_compatible"] = buildplate_map["buildplate_compatible"] @@ -992,21 +976,3 @@ def _indent(elem, level = 0): # before the last } def _tag_without_namespace(element): return element.tag[element.tag.rfind("}") + 1:] - -#While loading XML profiles, some of these profiles don't know what variant -#they belong to. We'd like to search by the machine ID and the variant's -#name, but we don't know the variant's ID. Not all variants have been loaded -#yet so we can't run a filter on the name and machine. The ID is unknown -#so we can't lazily load the variant either. So we have to wait until all -#the rest is loaded properly and then assign the correct variant to the -#material files that were missing it. -_with_missing_variants = [] -def _fillMissingVariants(): - registry = ContainerRegistry.getInstance() - for variant_metadata in _with_missing_variants: - variants = registry.findContainersMetadata(definition = variant_metadata["definition"], name = variant_metadata["variant"]) - if not variants: - Logger.log("w", "Could not find variant for variant-specific material {material_id}.".format(material_id = variant_metadata["id"])) - continue - variant_metadata["variant"] = variants[0]["id"] -ContainerRegistry.allMetadataLoaded.connect(_fillMissingVariants) From 55bdc0c85340478547273d35a02fe0964f45b70e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 6 Feb 2018 16:27:01 +0100 Subject: [PATCH 037/371] WIP: Create VariantManager --- cura/CuraApplication.py | 11 +++ cura/Machines/ContainerNode.py | 34 ++++++++ cura/Machines/VariantManager.py | 81 +++++++++++++++++++ cura/Machines/__init__.py | 0 cura/Settings/MachineManager.py | 20 +++++ cura/Settings/NozzleModel.py | 47 +++++++++++ .../XmlMaterialProfile/XmlMaterialProfile.py | 20 +++-- resources/qml/Menus/NozzleMenu.qml | 51 ++++++------ 8 files changed, 228 insertions(+), 36 deletions(-) create mode 100644 cura/Machines/ContainerNode.py create mode 100644 cura/Machines/VariantManager.py create mode 100644 cura/Machines/__init__.py create mode 100644 cura/Settings/NozzleModel.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 07b3aab60c..d209b90909 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -59,6 +59,8 @@ from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.UserProfilesModel import UserProfilesModel from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager +from cura.Machines.VariantManager import VariantManager + from . import PlatformPhysics from . import BuildVolume @@ -233,6 +235,9 @@ class CuraApplication(QtApplication): if kwargs["parsed_command_line"].get("trigger_early_crash", False): assert not "This crash is triggered by the trigger_early_crash command line argument." + # new stuff + self._variant_manager = VariantManager(ContainerRegistry.getInstance()) + self.default_theme = "cura-light" self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png"))) @@ -707,6 +712,9 @@ class CuraApplication(QtApplication): return False return True + def getVariantManager(self): + return self._variant_manager + def preRun(self): # Last check for unknown commandline arguments parser = self.getCommandlineParser() @@ -723,6 +731,9 @@ class CuraApplication(QtApplication): def run(self): self.preRun() + container_registry = ContainerRegistry.getInstance() + self._variant_manager.initialize() + # Check if we should run as single instance or not self._setUpSingleInstanceServer() diff --git a/cura/Machines/ContainerNode.py b/cura/Machines/ContainerNode.py new file mode 100644 index 0000000000..b9ebaa698a --- /dev/null +++ b/cura/Machines/ContainerNode.py @@ -0,0 +1,34 @@ +from typing import Optional + +from collections import OrderedDict + +from UM.Logger import Logger + + +## A metadata / container combination. Use getContainer to get the container corresponding to the metadata +class ContainerNode: + def __init__(self, metadata = None): + self.metadata = metadata + self.container = None + self.children_map = OrderedDict() + + def getChildNode(self, child_key: str) -> Optional["QualityNode"]: + return self.children_map.get(child_key) + + def getContainer(self) -> "InstanceContainer": + if self.metadata is None: + raise RuntimeError("Cannot get container for a QualityNode without metadata") + + if self.container is None: + container_id = self.metadata["id"] + Logger.log("d", "Lazy-loading container [%s]", container_id) + from UM.Settings.ContainerRegistry import ContainerRegistry + container_list = ContainerRegistry.getInstance().findInstanceContainers(id = container_id) + if not container_list: + raise RuntimeError("Failed to lazy-load container [%s], cannot find it" % container_id) + self.container = container_list[0] + + return self.container + + def __str__(self): + return "ContainerNode[%s]" % self.metadata.get("id") diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py new file mode 100644 index 0000000000..1f9f0288ac --- /dev/null +++ b/cura/Machines/VariantManager.py @@ -0,0 +1,81 @@ +from typing import Optional + +from UM.Logger import Logger +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.InstanceContainer import InstanceContainer + +from cura.Machines.ContainerNode import ContainerNode +from cura.Settings.GlobalStack import GlobalStack + + +class VariantType: + BUILD_PLATE = "buildplate" + NOZZLE = "nozzle" + + +ALL_VARIANT_TYPES = (VariantType.BUILD_PLATE, VariantType.NOZZLE) + + +# +# VariantManager is THE place to look for a specific variant. It maintains a variant lookup table with the following +# structure: +# +# [machine_definition_id] -> [variant_type] -> [variant_name] -> ContainerNode(metadata / container) +# Example: "ultimaker3" -> "buildplate" -> "Glass" (if present) -> ContainerNode +# -> ... +# -> "nozzle" -> "AA 0.4" +# -> "BB 0.8" +# -> ... +# +# Note that the "container" field is not loaded in the beginning because it would defeat the purpose of lazy-loading. +# A container is loaded when getVariant() is called to load a variant InstanceContainer. +# +class VariantManager: + + def __init__(self, container_registry): + self._container_registry = container_registry # type: ContainerRegistry + + self._machine_to_variant_dict_map = {} # -> + + self._exclude_variant_id_list = ["empty_variant"] + + # + # Initializes the VariantManager including: + # - initializing the variant lookup table based on the metadata in ContainerRegistry. + # + def initialize(self): + # Cache all variants from the container registry to a variant map for better searching and organization. + variant_metadata_list = self._container_registry.findContainersMetadata(type = "variant") + for variant_metadata in variant_metadata_list: + if variant_metadata["id"] in self._exclude_variant_id_list: + Logger.log("d", "Exclude variant [%s]", variant_metadata["id"]) + continue + + variant_name = variant_metadata["name"] + variant_definition = variant_metadata["definition"] + if variant_definition not in self._machine_to_variant_dict_map: + self._machine_to_variant_dict_map[variant_definition] = {} + #for variant_type in ALL_VARIANT_TYPES: + # self._machine_to_variant_dict_map[variant_definition][variant_type] = {} + + variant_type = variant_metadata["hardware_type"] + #variant_dict = self._machine_to_variant_dict_map[variant_definition][variant_type] + variant_dict = self._machine_to_variant_dict_map[variant_definition] + if variant_name in variant_dict: + # ERROR: duplicated variant name. + raise RuntimeError("Found duplicated variant name [%s], type [%s] for machine [%s]" % + (variant_name, variant_type, variant_definition)) + + variant_dict[variant_name] = ContainerNode(metadata = variant_metadata) + + # + # Gets the variant InstanceContainer with the given information. + # Almost the same as getVariantMetadata() except that this returns an InstanceContainer if present. + # + def getVariant(self, machine_type_name: str, variant_name: str, + variant_type: Optional[str] = None) -> Optional["InstanceContainer"]: + return self._machine_to_variant_dict_map[machine_type_name].get(variant_name) + + def getVariantNodes(self, machine: "GlobalStack"): + machine_type_name = machine.definition.getId() + return self._machine_to_variant_dict_map.get(machine_type_name) diff --git a/cura/Machines/__init__.py b/cura/Machines/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index cc5c4aa539..719f90bdd1 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1490,3 +1490,23 @@ class MachineManager(QObject): stacks = ExtruderManager.getInstance().getActiveExtruderStacks() stacks.append(self._global_container_stack) return [ s.containersChanged for s in stacks ] + + # New + @pyqtSlot(str, "QVariant") + def setVariantGroup(self, position, container_node): + Logger.log("d", "---------------- container = [%s]", container_node) + position = str(position) + self.blurSettings.emit() + with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): + self._global_container_stack.extruders[position].variant = container_node.getContainer() + + @pyqtSlot("QVariant") + def handleQualityGroup(self, quality_group): + Logger.log("d", "---------------- qg = [%s]", quality_group.name) + self.blurSettings.emit() + with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): + self._global_container_stack.quality = quality_group.node_for_global.getContainer() + self._global_container_stack.qualityChanges = self._empty_quality_changes_container + for position, node in quality_group.nodes_for_extruders.items(): + self._global_container_stack.extruders[position].quality = node.getContainer() + self._global_container_stack.extruders[position].qualityChanges = self._empty_quality_changes_container diff --git a/cura/Settings/NozzleModel.py b/cura/Settings/NozzleModel.py new file mode 100644 index 0000000000..3ad28f3287 --- /dev/null +++ b/cura/Settings/NozzleModel.py @@ -0,0 +1,47 @@ +from PyQt5.QtCore import Qt + +from UM.Application import Application +from UM.Qt.ListModel import ListModel + + +class NozzleModel(ListModel): + IdRole = Qt.UserRole + 1 + HotendNameRole = Qt.UserRole + 2 + ContainerNodeRole = Qt.UserRole + 3 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.IdRole, "id") + self.addRoleName(self.HotendNameRole, "hotend_name") + self.addRoleName(self.ContainerNodeRole, "container_node") + + Application.getInstance().globalContainerStackChanged.connect(self._update) + Application.getInstance().getMachineManager().activeVariantChanged.connect(self._update) + Application.getInstance().getMachineManager().activeStackChanged.connect(self._update) + Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update) + + def _update(self): + self.items.clear() + + variant_manager = Application.getInstance()._variant_manager + active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + if active_global_stack is None: + self.setItems([]) + return + + variant_group_dict = variant_manager.getVariantNodes(active_global_stack) + if not variant_group_dict: + self.setItems([]) + return + + item_list = [] + for hotend_name, container_node in sorted(variant_group_dict.items(), key = lambda i: i[0]): + item = {"id": hotend_name, + "hotend_name": hotend_name, + "container_node": container_node + } + + item_list.append(item) + + self.setItems(item_list) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index a7d9a7be26..54aaedb8f9 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -590,15 +590,14 @@ class XmlMaterialProfile(InstanceContainer): if buildplate_id is None: continue - variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata( - id = buildplate_id) - if not variant_containers: - # It is not really properly defined what "ID" is so also search for variants by name. - variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata( - definition = machine_id, name = buildplate_id) - - if not variant_containers: + from cura.Machines.VariantManager import VariantType + variant_manager = CuraApplication.getInstance().getVariantManager() + variant_node = variant_manager.getVariant(machine_id, VariantType.BUILD_PLATE, buildplate_id) + if not variant_node: continue + variant_metadata = variant_node.metadata + + # TODO: check if build plate variant exists buildplate_compatibility = machine_compatibility buildplate_recommended = machine_compatibility @@ -623,6 +622,11 @@ class XmlMaterialProfile(InstanceContainer): if hotend_name is None: continue + variant_manager = CuraApplication.getInstance().getVariantManager() + variant_node = variant_manager.getVariant(machine_id, hotend_name) + if not variant_node: + continue + hotend_compatibility = machine_compatibility hotend_setting_values = {} settings = hotend.iterfind("./um:setting", self.__namespaces) diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index 81db20a79d..6d554218a1 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -29,38 +29,33 @@ Menu return true; } - MenuItem + // TODO: single instance?? + Cura.NozzleModel { - id: automaticNozzle - text: - { - if(visible) - { - var nozzleName = Cura.MachineManager.printerOutputDevices[0].hotendIds[extruderIndex]; - return catalog.i18nc("@title:menuitem %1 is the nozzle currently loaded in the printer", "Automatic: %1").arg(nozzleName); - } - return ""; - } - visible: printerConnected && Cura.MachineManager.printerOutputDevices[0].hotendIds != undefined && Cura.MachineManager.printerOutputDevices[0].hotendIds.length > extruderIndex && !isClusterPrinter - onTriggered: - { - var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; - Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); - var hotendId = Cura.MachineManager.printerOutputDevices[0].hotendIds[extruderIndex]; - var itemIndex = nozzleInstantiator.model.find("name", hotendId); - if(itemIndex > -1) - { - Cura.MachineManager.setActiveVariant(nozzleInstantiator.model.getItem(itemIndex).id); - } - Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); - } + id: nozzleModel } - MenuSeparator + Instantiator { - visible: automaticNozzle.visible - } + model: nozzleModel + MenuItem + { + text: model.hotend_name + checkable: true + checked: Cura.MachineManager.activeVariantId == model.hotend_name + exclusiveGroup: group + onTriggered: { + var position = Cura.ExtruderManager.activeExtruderIndex; + Cura.MachineManager.setVariantGroup(position, model.container_node); + } + visible: true + } + + onObjectAdded: menu.insertItem(index, object); + onObjectRemoved: menu.removeItem(object); + } + /* Instantiator { id: nozzleInstantiator @@ -96,7 +91,7 @@ Menu } onObjectAdded: menu.insertItem(index, object) onObjectRemoved: menu.removeItem(object) - } + } */ ExclusiveGroup { id: group } } From f0d9fba2f5fdde7a3ad03657f8ce83d49502a489 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 7 Feb 2018 14:49:46 +0100 Subject: [PATCH 038/371] WIP: Create MaterialManager --- cura/CuraApplication.py | 10 +- cura/Machines/MaterialManager.py | 277 ++++++++++++++++++++ cura/Settings/ContainerManager.py | 38 ++- cura/Settings/MachineManager.py | 8 + cura/Settings/MaterialsModel.py | 181 ++++++++++++- resources/qml/Menus/MaterialMenu.qml | 118 +-------- resources/qml/Preferences/MaterialsPage.qml | 2 +- 7 files changed, 504 insertions(+), 130 deletions(-) create mode 100644 cura/Machines/MaterialManager.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index d209b90909..7812024422 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -53,7 +53,7 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator from cura.Settings.ProfilesModel import ProfilesModel -from cura.Settings.MaterialsModel import MaterialsModel +from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.UserProfilesModel import UserProfilesModel @@ -734,6 +734,10 @@ class CuraApplication(QtApplication): container_registry = ContainerRegistry.getInstance() self._variant_manager.initialize() + from cura.Machines.MaterialManager import MaterialManager + self._material_manager = MaterialManager(container_registry) + self._material_manager.initialize() + # Check if we should run as single instance or not self._setUpSingleInstanceServer() @@ -914,6 +918,10 @@ class CuraApplication(QtApplication): qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") qmlRegisterSingletonType(ProfilesModel, "Cura", 1, 0, "ProfilesModel", ProfilesModel.createProfilesModel) + + qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") + qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") + qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") qmlRegisterType(QualityAndUserProfilesModel, "Cura", 1, 0, "QualityAndUserProfilesModel") qmlRegisterType(UserProfilesModel, "Cura", 1, 0, "UserProfilesModel") diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py new file mode 100644 index 0000000000..596da50fb2 --- /dev/null +++ b/cura/Machines/MaterialManager.py @@ -0,0 +1,277 @@ +from typing import Optional + +from PyQt5.Qt import QTimer, QObject, pyqtSignal + +from UM.Logger import Logger +from UM.Settings import ContainerRegistry +from UM.Settings import InstanceContainer + +from cura.Machines.ContainerNode import ContainerNode + + +class MaterialGroup: + __slots__ = ("name", "root_material_node", "derived_material_node_list") + + def __init__(self, name: str): + self.name = name + self.root_material_node = None + self.derived_material_node_list = [] + + +class MaterialNode(ContainerNode): + __slots__ = ("material_map", "children_map") + + def __init__(self, metadata: Optional[dict] = None): + super().__init__(metadata = metadata) + self.material_map = {} + self.children_map = {} + + +class MaterialManager(QObject): + + materialsUpdated = pyqtSignal() # Emitted whenever the material lookup tables are updated. + + def __init__(self, container_registry, parent = None): + super().__init__(parent) + self._container_registry = container_registry # type: ContainerRegistry + + self._fallback_materials_map = dict() # material_type -> generic material metadata + self._material_group_map = dict() # root_material_id -> MaterialGroup + self._diameter_machine_variant_material_map = dict() # diameter -> dict(machine_definition_id -> MaterialNode) + + # The machine definition ID for the non-machine-specific materials. + # This is used as the last fallback option if the given machine-specific material(s) cannot be found. + self._default_machine_definition_id = "fdmprinter" + + self._update_timer = QTimer(self) + self._update_timer.setInterval(300) + self._update_timer.setSingleShot(True) + self._update_timer.timeout.connect(self._updateTables) + + self._container_registry.containerMetaDataChanged.connect(self._onContainerMetadataChanged) + self._container_registry.containerAdded.connect(self._onContainerMetadataChanged) + self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged) + + def initialize(self): + # Find all materials and put them in a matrix for quick search. + material_metadata_list = self._container_registry.findContainersMetadata(type = "material") + + self._material_group_map = {} + self._diameter_machine_variant_material_map = {} + + # Table #1 + # root_material_id -> MaterialGroup + for material_metadata in material_metadata_list: + material_id = material_metadata["id"] + # We don't store empty material in the lookup tables + if material_id == "empty_material": + continue + + root_material_id = material_metadata.get("base_file") + if root_material_id not in self._material_group_map: + self._material_group_map[root_material_id] = MaterialGroup(root_material_id) + group = self._material_group_map[root_material_id] + + # We only add root materials here + if material_id == root_material_id: + group.root_material_node = MaterialNode(material_metadata) + else: + new_node = MaterialNode(material_metadata) + group.derived_material_node_list.append(new_node) + + # Table #2 + # Lookup table for material type -> fallback material metadata + grouped_by_type_dict = dict() + for root_material_id, material_node in self._material_group_map.items(): + material_type = material_node.root_material_node.metadata["material"] + if material_type not in grouped_by_type_dict: + grouped_by_type_dict[material_type] = {"generic": None, + "others": []} + brand = material_node.root_material_node.metadata["brand"] + if brand.lower() == "generic": + grouped_by_type_dict[material_type] = material_node.root_material_node.metadata + self._fallback_materials_map = grouped_by_type_dict + + # Table #3 + # "machine" -> "variant_name" -> "root material ID" -> specific material InstanceContainer + # Construct the "machine" -> "variant" -> "root material ID" -> specific material InstanceContainer + for material_metadata in material_metadata_list: + # We don't store empty material in the lookup tables + if material_metadata["id"] == "empty_material": + continue + + root_material_id = material_metadata["base_file"] + definition = material_metadata["definition"] + approximate_diameter = material_metadata["approximate_diameter"] + + if approximate_diameter not in self._diameter_machine_variant_material_map: + self._diameter_machine_variant_material_map[approximate_diameter] = {} + + machine_variant_material_map = self._diameter_machine_variant_material_map[approximate_diameter] + if definition not in machine_variant_material_map: + machine_variant_material_map[definition] = MaterialNode() + + machine_node = machine_variant_material_map[definition] + variant_name = material_metadata.get("variant_name") + if not variant_name: + # if there is no variant, this material is for the machine, so put its metadata in the machine node. + machine_node.material_map[root_material_id] = MaterialNode(material_metadata) + else: + # this material is variant-specific, so we save it in a variant-specific node under the + # machine-specific node + if variant_name not in machine_node.children_map: + machine_node.children_map[variant_name] = MaterialNode() + + variant_node = machine_node.children_map[variant_name] + if root_material_id not in variant_node.material_map: + variant_node.material_map[root_material_id] = MaterialNode(material_metadata) + else: + # Sanity check: make sure we don't have duplicated variant-specific materials for the same machine + raise RuntimeError("Found duplicate variant name [%s] for machine [%s] in material [%s]" % + (variant_name, definition, material_metadata["id"])) + + self.materialsUpdated.emit() + + def _updateTables(self): + self.initialize() + + def _onContainerMetadataChanged(self, container): + self._onContainerChanged(container) + + def _onContainerChanged(self, container): + container_type = container.getMetaDataEntry("type") + if container_type != "material": + return + + # TODO: update the cache table + self._update_timer.start() + + def getMaterialGroup(self, root_material_id: str) -> Optional[MaterialGroup]: + return self._material_group_map.get(root_material_id) + + def _test_metadata(self): + # print all metadata + import os + with open("c:/workspace/guid_map.txt", "w", encoding = "utf-8") as f: + for machine_id, node in self._guid_to_root_materials_map.items(): + f.write((" - %s -> %s" % (machine_id, node.metadata["id"])) + os.linesep) + + if False: + with open("c:/workspace/material_map.txt", "w", encoding = "utf-8") as f: + for machine_id in self._machine_variant_material_map: + f.write((" -> %s" % machine_id) + os.linesep) + + test_cases = [{"machine": "ultimaker3", "variant": "AA 0.4", "material": "generic_pla", "diameter": 2.85}, + {"machine": "ultimaker2_plus", "variant": None, "material": "generic_abs", "diameter": 2.85}, + {"machine": "fdmprinter", "variant": None, "material": "generic_cpe", "diameter": 2.85}, + {"machine": "fdmprinter", "variant": None, "material": "generic_abs_175", "diameter": 2.85}, + {"machine": "fdmprinter", "variant": None, "material": "generic_nylon", "diameter": 1.75}, + {"machine": "fdmprinter", "variant": None, "material": "generic_nylon_175", "diameter": 1.75}, + ] + for tc in test_cases: + result = self.getMaterialNode( + tc['machine'], + tc['variant'], + tc['diameter'], + tc['material']) + tc['result_id'] = result.getContainer().getId() if result else "None" + Logger.log("d", "!!!!!!!! MaterialManager test: %s", tc) + + # test available materials + with open("c:/workspace/test.txt", "w", encoding="utf-8") as f: + for tc in test_cases: + result = self.getAvailableMaterials(tc['machine'], + tc['variant'], + tc['diameter']) + f.write("--- [%s] [%s] [%s]:" % (tc['machine'], tc['variant'], tc['diameter']) + "\n") + for r, md in result.items(): + f.write(" - %s -> %s" % (r, md["id"]) + "\n") + + # + # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup. + # + def getAvailableMaterials(self, machine_definition_id: str, variant_name: Optional[str], diameter: float) -> dict: + # round the diameter to get the approximate diameter + rounded_diameter = str(round(diameter)) + if rounded_diameter not in self._diameter_machine_variant_material_map: + Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s])", diameter, rounded_diameter) + return {} + + # If there are variant materials, get the variant material + machine_variant_material_map = self._diameter_machine_variant_material_map[rounded_diameter] + machine_node = machine_variant_material_map.get(machine_definition_id) + variant_node = None + if machine_node is None: + machine_node = machine_variant_material_map.get(self._default_machine_definition_id) + if variant_name is not None and machine_node is not None: + variant_node = machine_node.getChildNode(variant_name) + + # Fallback mechanism of finding materials: + # 1. variant-specific material + # 2. machine-specific material + # 3. generic material (for fdmprinter) + material_id_metadata_dict = {} + if variant_node is not None: + material_id_metadata_dict = {mid: node for mid, node in variant_node.material_map.items()} + + # Fallback: machine-specific materials, including "fdmprinter" + if not material_id_metadata_dict: + if machine_node is not None: + material_id_metadata_dict = {mid: node for mid, node in machine_node.material_map.items()} + + return material_id_metadata_dict + + # + # Gets MaterialNode for the given extruder and machine with the given material name. + # Returns None if: + # 1. the given machine doesn't have materials; + # 2. cannot find any material InstanceContainers with the given settings. + # + def getMaterial(self, machine_definition_id: str, variant_name: Optional[str], diameter: float, root_material_id: str) -> Optional["InstanceContainer"]: + # round the diameter to get the approximate diameter + rounded_diameter = str(round(diameter)) + if rounded_diameter not in self._diameter_machine_variant_material_map: + Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s]) for root material id [%s]", + diameter, rounded_diameter, root_material_id) + return None + + # If there are variant materials, get the variant material + machine_variant_material_map = self._diameter_machine_variant_material_map[rounded_diameter] + machine_node = machine_variant_material_map.get(machine_definition_id) + variant_node = None + + # Fallback for "fdmprinter" if the machine-specific materials cannot be found + if machine_node is None: + machine_node = machine_variant_material_map.get(self._default_machine_definition_id) + if machine_node is not None and variant_name is not None: + variant_node = machine_node.getChildNode(variant_name) + + # Fallback mechanism of finding materials: + # 1. variant-specific material + # 2. machine-specific material + # 3. generic material (for fdmprinter) + material_node = None + if variant_node is not None: + if root_material_id in variant_node.material_map: + material_node = variant_node.material_map.get(root_material_id) + + # Fallback: machine-specific materials, including "fdmprinter" + if material_node is None: + if machine_node is not None: + material_node = machine_node.material_map.get(root_material_id) + + return material_node + + # + # Used by QualityManager. Built-in quality profiles may be based on generic material IDs such as "generic_pla". + # For materials such as ultimaker_pla_orange, no quality profiles may be found, so we should fall back to use + # the generic material IDs to search for qualities. + # + # This function returns the generic root material ID for the given material type, where material types are "PLA", + # "ABS", etc. + # + def getFallbackMaterialForType(self, material_type: str) -> dict: + # For safety + if material_type not in self._fallback_materials_map: + raise RuntimeError("Material type [%s] is not in the fallback materials table." % material_type) + return self._fallback_materials_map[material_type] diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index d2e8410dde..4c92eed845 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -766,22 +766,20 @@ class ContainerManager(QObject): # \return \type{str} the id of the newly created container. @pyqtSlot(str, result = str) def duplicateMaterial(self, material_id: str) -> str: - original = self._container_registry.findContainersMetadata(id = material_id) - if not original: + assert material_id + + from cura.CuraApplication import CuraApplication + material_manager = CuraApplication.getInstance()._material_manager + + material_group = material_manager.getMaterialGroup(material_id) + if not material_group: Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id) return "" - original = original[0] - base_container_id = original.get("base_file") - base_container = self._container_registry.findContainers(id = base_container_id) - if not base_container: - Logger.log("d", "Unable to duplicate the material with id {material_id}, because base_file {base_container_id} doesn't exist.".format(material_id = material_id, base_container_id = base_container_id)) - return "" - base_container = base_container[0] - - #We'll copy all containers with the same base. - #This way the correct variant and machine still gets assigned when loading the copy of the material. - containers_to_copy = self._container_registry.findInstanceContainers(base_file = base_container_id) + base_container = material_group.root_material_node.getContainer() + containers_to_copy = [] + for node in material_group.derived_material_node_list: + containers_to_copy.append(node.getContainer()) # Ensure all settings are saved. Application.getInstance().saveSettings() @@ -802,9 +800,9 @@ class ContainerManager(QObject): new_id = new_base_id if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": new_id += "_" + container_to_copy.getMetaDataEntry("definition") - if container_to_copy.getMetaDataEntry("variant"): - variant = self._container_registry.findContainers(id = container_to_copy.getMetaDataEntry("variant"))[0] - new_id += "_" + variant.getName().replace(" ", "_") + if container_to_copy.getMetaDataEntry("variant_name"): + variant_name = container_to_copy.getMetaDataEntry("variant_name") + new_id += "_" + variant_name.replace(" ", "_") if current_id == material_id: clone_of_original = new_id @@ -826,13 +824,7 @@ class ContainerManager(QObject): # check if the given material has a base file (i.e. was shipped by default) base_file = self.getContainerMetaDataEntry(material_id, "base_file") - - if base_file == "": - # there is no base file, so duplicate by ID - return self.duplicateMaterial(material_id) - else: - # there is a base file, so duplicate the original material - return self.duplicateMaterial(base_file) + return self.duplicateMaterial(base_file) ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 719f90bdd1..1fa4a602bc 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1237,6 +1237,14 @@ class MachineManager(QObject): return self.getQualityVariantId(self._global_container_stack.definition, variant) return "" + @pyqtProperty(str, notify = activeVariantChanged) + def activeQualityVariantName(self) -> str: + if self._active_container_stack: + variant = self._active_container_stack.variant + if variant.getId() != "empty_variant": + return variant.getName() + return "" + ## Get the Variant ID to use to select quality profiles for variants of the specified definitions # This is normally the id of the variant itself, but machines can specify a different definition # to inherit qualities from, which has consequences for the variant to use as well diff --git a/cura/Settings/MaterialsModel.py b/cura/Settings/MaterialsModel.py index c4b0329336..ad3256ba32 100644 --- a/cura/Settings/MaterialsModel.py +++ b/cura/Settings/MaterialsModel.py @@ -2,10 +2,189 @@ # Cura is released under the terms of the LGPLv3 or higher. from typing import Any, List +from PyQt5.QtCore import Qt + + +from UM.Logger import Logger +from UM.Qt.ListModel import ListModel from UM.Settings.ContainerRegistry import ContainerRegistry #To listen for changes to the materials. from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel #We're extending this class. -## A model that shows a list of currently valid materials. + +def getAvailableMaterials(): + from cura.CuraApplication import CuraApplication + machine_manager = CuraApplication.getInstance().getMachineManager() + extruder_manager = CuraApplication.getInstance().getExtruderManager() + + material_manager = CuraApplication.getInstance()._material_manager + + active_global_stack = machine_manager._global_container_stack + active_extruder_stack = extruder_manager.getActiveExtruderStack() + + if active_global_stack is None or active_extruder_stack is None: + Logger.log("d", "Active global stack [%s] or extruder stack [%s] is None, setting material list to empty.", + active_global_stack, active_extruder_stack) + return + + machine_definition_id = active_global_stack.definition.getId() + variant_name = None + if active_extruder_stack.variant.getId() != "empty_variant": + variant_name = active_extruder_stack.variant.getName() + diameter = active_extruder_stack.getProperty("material_diameter", "value") + + # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. + result_dict = material_manager.getAvailableMaterials(machine_definition_id, variant_name, diameter) + return result_dict + + +class BaseMaterialsModel(ListModel): + RootMaterialIdRole = Qt.UserRole + 1 + IdRole = Qt.UserRole + 2 + NameRole = Qt.UserRole + 3 + BrandRole = Qt.UserRole + 4 + MaterialRole = Qt.UserRole + 5 + ColorRole = Qt.UserRole + 6 + ContainerNodeRole = Qt.UserRole + 6 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.RootMaterialIdRole, "root_material_id") + self.addRoleName(self.IdRole, "id") + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.BrandRole, "brand") + self.addRoleName(self.MaterialRole, "material") + self.addRoleName(self.ColorRole, "color_name") + self.addRoleName(self.ContainerNodeRole, "container_node") + + +class GenericMaterialsModel(BaseMaterialsModel): + + def __init__(self, parent = None): + super().__init__(parent) + + from cura.CuraApplication import CuraApplication + machine_manager = CuraApplication.getInstance().getMachineManager() + extruder_manager = CuraApplication.getInstance().getExtruderManager() + material_manager = CuraApplication.getInstance()._material_manager + + machine_manager.globalContainerChanged.connect(self._update) + extruder_manager.activeExtruderChanged.connect(self._update) + material_manager.materialsUpdated.connect(self._update) + + def _update(self): + item_list = [] + result_dict = getAvailableMaterials() + if result_dict is None: + self.setItems([]) + return + + for root_material_id, container_node in result_dict.items(): + metadata = container_node.metadata + # Only add results for generic materials + if metadata["brand"].lower() != "generic": + continue + + item = {"root_material_id": root_material_id, + "id": metadata["id"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "container_node": container_node + } + item_list.append(item) + + # Sort the item list by material name alphabetically + item_list = sorted(item_list, key = lambda d: d["name"]) + + self.setItems(item_list) + + +class MaterialsModelGroupedByType(ListModel): + NameRole = Qt.UserRole + 1 + ColorsRole = Qt.UserRole + 2 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.ColorsRole, "colors") + + +## Brand --> Material Type -> list of materials +class BrandMaterialsModel(ListModel): + NameRole = Qt.UserRole + 1 + MaterialsRole = Qt.UserRole + 2 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.MaterialsRole, "materials") + + from cura.CuraApplication import CuraApplication + machine_manager = CuraApplication.getInstance().getMachineManager() + extruder_manager = CuraApplication.getInstance().getExtruderManager() + material_manager = CuraApplication.getInstance()._material_manager + + machine_manager.globalContainerChanged.connect(self._update) + extruder_manager.activeExtruderChanged.connect(self._update) + material_manager.materialsUpdated.connect(self._update) + + def _update(self): + brand_item_list = [] + result_dict = getAvailableMaterials() + if result_dict is None: + self.setItems([]) + return + + brand_group_dict = {} + for root_material_id, container_node in result_dict.items(): + metadata = container_node.metadata + brand = metadata["brand"] + # Only add results for generic materials + if brand.lower() == "generic": + continue + + if brand not in brand_group_dict: + brand_group_dict[brand] = {} + + material_type = metadata["material"] + if material_type not in brand_group_dict[brand]: + brand_group_dict[brand][material_type] = [] + + item = {"root_material_id": root_material_id, + "id": metadata["id"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "container_node": container_node + } + brand_group_dict[brand][material_type].append(item) + + for brand, material_dict in brand_group_dict.items(): + brand_item = {"name": brand, + "materials": MaterialsModelGroupedByType(self)} # TODO + + material_type_item_list = [] + for material_type, material_list in material_dict.items(): + material_type_item = {"name": material_type, + "colors": BaseMaterialsModel(self)} + material_type_item["colors"].clear() + material_type_item["colors"].setItems(material_list) + + material_type_item_list.append(material_type_item) + + brand_item["materials"].setItems(material_type_item_list) + + brand_item_list.append(brand_item) + + self.setItems(brand_item_list) + + +## A model that shows a list of currently valid materials. Used by management page. class MaterialsModel(InstanceContainersModel): def __init__(self, parent = None): super().__init__(parent) diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 3d04649f11..111e5ab6af 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -1,8 +1,8 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick 2.8 +import QtQuick.Controls 1.4 import UM 1.2 as UM import Cura 1.0 as Cura @@ -29,16 +29,6 @@ Menu return true; } - UM.SettingPropertyProvider - { - id: materialDiameterProvider - - containerStackId: Cura.ExtruderManager.activeExtruderStackId - key: "material_diameter" - watchedProperties: [ "value" ] - storeIndex: 5 - } - MenuItem { id: automaticMaterial @@ -83,12 +73,16 @@ Menu exclusiveGroup: group onTriggered: { + + const container_id = model.id; // This workaround is done because of the application menus for materials and variants for multiextrusion printers. // The extruder menu would always act on the correspoding extruder only, instead of acting on the extruder selected in the UI. + var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; - Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); - Cura.MachineManager.setActiveMaterial(model.id); - Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); + //Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); + //Cura.MachineManager.setActiveMaterial(container_id); + //Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); + Cura.MachineManager.setMaterial(activeExtruderIndex, model.container_node); } } onObjectAdded: menu.insertItem(index, object) @@ -126,11 +120,12 @@ Menu exclusiveGroup: group onTriggered: { + const container_id = model.id; // This workaround is done because of the application menus for materials and variants for multiextrusion printers. // The extruder menu would always act on the correspoding extruder only, instead of acting on the extruder selected in the UI. var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); - Cura.MachineManager.setActiveMaterial(model.id); + Cura.MachineManager.setActiveMaterial(container_id); Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); } } @@ -146,105 +141,20 @@ Menu onObjectRemoved: menu.removeItem(object) } - ListModel + Cura.GenericMaterialsModel { id: genericMaterialsModel - Component.onCompleted: populateMenuModels() + //Component.onCompleted: populateMenuModels() } - ListModel + Cura.BrandMaterialsModel { id: brandModel } - //: Model used to populate the brandModel - Cura.MaterialsModel - { - id: materialsModel - filter: materialFilter() - onModelReset: populateMenuModels() - onDataChanged: populateMenuModels() - } - ExclusiveGroup { id: group } MenuSeparator { } MenuItem { action: Cura.Actions.manageMaterials } - - function materialFilter() - { - var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() }; - if(Cura.MachineManager.filterMaterialsByMachine) - { - result.definition = Cura.MachineManager.activeQualityDefinitionId; - if(Cura.MachineManager.hasVariants) - { - result.variant = Cura.MachineManager.activeQualityVariantId; - } - } - else - { - result.definition = "fdmprinter"; - result.compatible = true; //NB: Only checks for compatibility in global version of material, but we don't have machine-specific materials anyway. - } - return result; - } - - function populateMenuModels() - { - // Create a structure of unique brands and their material-types - genericMaterialsModel.clear() - brandModel.clear(); - - var items = materialsModel.items; - var materialsByBrand = {}; - for (var i in items) { - var brandName = items[i]["metadata"]["brand"]; - var materialName = items[i]["metadata"]["material"]; - - if (brandName == "Generic") - { - // Add to top section - var materialId = items[i].id; - genericMaterialsModel.append({ - id: materialId, - name: items[i].name - }); - } - else - { - // Add to per-brand, per-material menu - if (!materialsByBrand.hasOwnProperty(brandName)) - { - materialsByBrand[brandName] = {}; - } - if (!materialsByBrand[brandName].hasOwnProperty(materialName)) - { - materialsByBrand[brandName][materialName] = []; - } - materialsByBrand[brandName][materialName].push({ - id: items[i].id, - name: items[i].name - }); - } - } - - for (var brand in materialsByBrand) - { - var materialsByBrandModel = []; - var materials = materialsByBrand[brand]; - for (var material in materials) - { - materialsByBrandModel.push({ - name: material, - colors: materials[material] - }) - } - brandModel.append({ - name: brand, - materials: materialsByBrandModel - }); - } - } } diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 22814683ad..3a72f66cfc 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -30,7 +30,7 @@ UM.ManagementPage result.definition = Cura.MachineManager.activeQualityDefinitionId; if(Cura.MachineManager.hasVariants) { - result.variant = Cura.MachineManager.activeQualityVariantId; + result.variant_name = Cura.MachineManager.activeQualityVariantName; } } else From 0505b16ffb55c243fa3641ab8296b7e0f45b78e0 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Feb 2018 13:54:16 +0100 Subject: [PATCH 039/371] WIP: Update quality profiles - Add a new field "variant" in "metadata" section for quality profiles. "material" will only contain values such as "generic_abs", and "variant" will contain values such as "0.25 mm", "AA 0.4", etc. - Reformat "metadata" section to have the following order: - setting_version - type - quality_type - weight - global_quality - material - variant --- resources/quality/abax_pri3/apri3_pla_fast.inst.cfg | 10 +++++----- resources/quality/abax_pri3/apri3_pla_high.inst.cfg | 10 +++++----- resources/quality/abax_pri3/apri3_pla_normal.inst.cfg | 10 +++++----- resources/quality/abax_pri5/apri5_pla_fast.inst.cfg | 10 +++++----- resources/quality/abax_pri5/apri5_pla_high.inst.cfg | 10 +++++----- resources/quality/abax_pri5/apri5_pla_normal.inst.cfg | 10 +++++----- resources/quality/abax_titan/atitan_pla_fast.inst.cfg | 10 +++++----- resources/quality/abax_titan/atitan_pla_high.inst.cfg | 11 ++++++----- .../quality/abax_titan/atitan_pla_normal.inst.cfg | 10 +++++----- .../anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg | 4 ++-- .../anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg | 4 ++-- .../anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg | 4 ++-- .../builder_premium/bp_BVOH_Coarse_Quality.inst.cfg | 5 ++--- .../builder_premium/bp_BVOH_High_Quality.inst.cfg | 6 +++--- .../builder_premium/bp_BVOH_Normal_Quality.inst.cfg | 6 +++--- .../bp_Innoflex60_Coarse_Quality.inst.cfg | 5 ++--- .../bp_Innoflex60_High_Quality.inst.cfg | 6 +++--- .../bp_Innoflex60_Normal_Quality.inst.cfg | 6 +++--- .../builder_premium/bp_PET_Coarse_Quality.inst.cfg | 5 ++--- .../builder_premium/bp_PET_High_Quality.inst.cfg | 6 +++--- .../builder_premium/bp_PET_Normal_Quality.inst.cfg | 6 +++--- .../builder_premium/bp_PLA_Coarse_Quality.inst.cfg | 5 ++--- .../builder_premium/bp_PLA_High_Quality.inst.cfg | 6 +++--- .../builder_premium/bp_PLA_Normal_Quality.inst.cfg | 6 +++--- .../builder_premium/bp_PVA_Coarse_Quality.inst.cfg | 5 ++--- .../builder_premium/bp_PVA_High_Quality.inst.cfg | 6 +++--- .../builder_premium/bp_PVA_Normal_Quality.inst.cfg | 6 +++--- .../builder_premium/bp_global_Coarse_Quality.inst.cfg | 4 ++-- .../builder_premium/bp_global_High_Quality.inst.cfg | 4 ++-- .../builder_premium/bp_global_Normal_Quality.inst.cfg | 4 ++-- .../cartesio/abs/cartesio_0.25_abs_high.inst.cfg | 5 +++-- .../cartesio/abs/cartesio_0.25_abs_normal.inst.cfg | 5 +++-- .../cartesio/abs/cartesio_0.4_abs_high.inst.cfg | 5 +++-- .../cartesio/abs/cartesio_0.4_abs_normal.inst.cfg | 5 +++-- .../cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg | 5 +++-- .../abs/cartesio_0.8_abs_extra_coarse.inst.cfg | 5 +++-- .../cartesio/abs/cartesio_0.8_abs_high.inst.cfg | 5 +++-- .../cartesio/abs/cartesio_0.8_abs_normal.inst.cfg | 5 +++-- .../arnitel/cartesio_0.4_arnitel2045_high.inst.cfg | 5 +++-- .../arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg | 5 +++-- .../cartesio/cartesio_global_Coarse_Quality.inst.cfg | 4 ++-- .../cartesio_global_Extra_Coarse_Quality.inst.cfg | 4 ++-- .../cartesio/cartesio_global_High_Quality.inst.cfg | 4 ++-- .../cartesio/cartesio_global_Normal_Quality.inst.cfg | 4 ++-- .../cartesio/hips/cartesio_0.25_hips_high.inst.cfg | 5 +++-- .../cartesio/hips/cartesio_0.25_hips_normal.inst.cfg | 5 +++-- .../cartesio/hips/cartesio_0.4_hips_high.inst.cfg | 5 +++-- .../cartesio/hips/cartesio_0.4_hips_normal.inst.cfg | 5 +++-- .../cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg | 5 +++-- .../hips/cartesio_0.8_hips_extra_coarse.inst.cfg | 5 +++-- .../cartesio/hips/cartesio_0.8_hips_high.inst.cfg | 5 +++-- .../cartesio/hips/cartesio_0.8_hips_normal.inst.cfg | 5 +++-- .../cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg | 5 +++-- .../nylon/cartesio_0.25_nylon_normal.inst.cfg | 5 +++-- .../cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg | 5 +++-- .../cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg | 5 +++-- .../cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg | 5 +++-- .../nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg | 5 +++-- .../cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg | 5 +++-- .../cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg | 5 +++-- .../cartesio/pc/cartesio_0.25_pc_high.inst.cfg | 5 +++-- .../cartesio/pc/cartesio_0.25_pc_normal.inst.cfg | 5 +++-- .../quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg | 5 +++-- .../cartesio/pc/cartesio_0.4_pc_normal.inst.cfg | 5 +++-- .../cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg | 5 +++-- .../cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg | 5 +++-- .../quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg | 5 +++-- .../cartesio/pc/cartesio_0.8_pc_normal.inst.cfg | 5 +++-- .../cartesio/petg/cartesio_0.25_petg_high.inst.cfg | 5 +++-- .../cartesio/petg/cartesio_0.25_petg_normal.inst.cfg | 5 +++-- .../cartesio/petg/cartesio_0.4_petg_high.inst.cfg | 5 +++-- .../cartesio/petg/cartesio_0.4_petg_normal.inst.cfg | 5 +++-- .../cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg | 5 +++-- .../petg/cartesio_0.8_petg_extra_coarse.inst.cfg | 5 +++-- .../cartesio/petg/cartesio_0.8_petg_high.inst.cfg | 5 +++-- .../cartesio/petg/cartesio_0.8_petg_normal.inst.cfg | 5 +++-- .../cartesio/pla/cartesio_0.25_pla_high.inst.cfg | 5 +++-- .../cartesio/pla/cartesio_0.25_pla_normal.inst.cfg | 5 +++-- .../cartesio/pla/cartesio_0.4_pla_high.inst.cfg | 5 +++-- .../cartesio/pla/cartesio_0.4_pla_normal.inst.cfg | 5 +++-- .../cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg | 5 +++-- .../pla/cartesio_0.8_pla_extra_coarse.inst.cfg | 5 +++-- .../cartesio/pla/cartesio_0.8_pla_high.inst.cfg | 5 +++-- .../cartesio/pla/cartesio_0.8_pla_normal.inst.cfg | 5 +++-- .../cartesio/pva/cartesio_0.25_pva_high.inst.cfg | 5 +++-- .../cartesio/pva/cartesio_0.25_pva_normal.inst.cfg | 5 +++-- .../cartesio/pva/cartesio_0.4_pva_high.inst.cfg | 5 +++-- .../cartesio/pva/cartesio_0.4_pva_normal.inst.cfg | 5 +++-- .../cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg | 5 +++-- .../pva/cartesio_0.8_pva_extra_coarse.inst.cfg | 5 +++-- .../cartesio/pva/cartesio_0.8_pva_high.inst.cfg | 5 +++-- .../cartesio/pva/cartesio_0.8_pva_normal.inst.cfg | 5 +++-- resources/quality/coarse.inst.cfg | 4 ++-- .../quality/deltacomb/deltacomb_abs_fast.inst.cfg | 5 ++--- .../quality/deltacomb/deltacomb_abs_high.inst.cfg | 5 ++--- .../quality/deltacomb/deltacomb_abs_normal.inst.cfg | 4 ++-- .../quality/deltacomb/deltacomb_nylon_fast.inst.cfg | 4 ++-- .../quality/deltacomb/deltacomb_nylon_high.inst.cfg | 4 ++-- .../quality/deltacomb/deltacomb_nylon_normal.inst.cfg | 5 ++--- .../quality/deltacomb/deltacomb_pla_fast.inst.cfg | 5 ++--- .../quality/deltacomb/deltacomb_pla_high.inst.cfg | 5 ++--- .../quality/deltacomb/deltacomb_pla_normal.inst.cfg | 4 ++-- resources/quality/draft.inst.cfg | 5 ++--- resources/quality/extra_coarse.inst.cfg | 4 ++-- resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg | 5 ++--- resources/quality/fabtotum/fabtotum_abs_high.inst.cfg | 5 ++--- .../quality/fabtotum/fabtotum_abs_normal.inst.cfg | 5 ++--- .../quality/fabtotum/fabtotum_nylon_fast.inst.cfg | 6 +++--- .../quality/fabtotum/fabtotum_nylon_high.inst.cfg | 6 +++--- .../quality/fabtotum/fabtotum_nylon_normal.inst.cfg | 5 ++--- resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg | 5 ++--- resources/quality/fabtotum/fabtotum_pla_high.inst.cfg | 5 ++--- .../quality/fabtotum/fabtotum_pla_normal.inst.cfg | 5 ++--- .../gmax15plus/gmax15plus_pla_dual_normal.inst.cfg | 2 +- .../gmax15plus/gmax15plus_pla_dual_thick.inst.cfg | 2 +- .../gmax15plus/gmax15plus_pla_dual_thin.inst.cfg | 2 +- .../gmax15plus_pla_dual_very_thick.inst.cfg | 2 +- .../quality/gmax15plus/gmax15plus_pla_normal.inst.cfg | 4 +--- .../quality/gmax15plus/gmax15plus_pla_thick.inst.cfg | 4 ++-- .../quality/gmax15plus/gmax15plus_pla_thin.inst.cfg | 4 ++-- .../gmax15plus/gmax15plus_pla_very_thick.inst.cfg | 4 ++-- resources/quality/high.inst.cfg | 4 ++-- .../imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg | 9 +++++---- .../generic_petg_0.4_coarse_2-fans.inst.cfg | 9 +++++---- .../imade3d_jellybox/generic_petg_0.4_medium.inst.cfg | 9 +++++---- .../generic_petg_0.4_medium_2-fans.inst.cfg | 9 +++++---- .../imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg | 9 +++++---- .../generic_pla_0.4_coarse_2-fans.inst.cfg | 9 +++++---- .../imade3d_jellybox/generic_pla_0.4_fine.inst.cfg | 9 +++++---- .../generic_pla_0.4_fine_2-fans.inst.cfg | 9 +++++---- .../imade3d_jellybox/generic_pla_0.4_medium.inst.cfg | 9 +++++---- .../generic_pla_0.4_medium_2-fans.inst.cfg | 9 +++++---- .../generic_pla_0.4_ultrafine.inst.cfg | 9 +++++---- .../generic_pla_0.4_ultrafine_2-fans.inst.cfg | 9 +++++---- .../quality/kemiq_q2/kemiq_q2_beta_abs_draft.inst.cfg | 4 ++-- .../kemiq_q2/kemiq_q2_beta_abs_extra_fine.inst.cfg | 4 ++-- .../quality/kemiq_q2/kemiq_q2_beta_abs_fine.inst.cfg | 4 ++-- .../quality/kemiq_q2/kemiq_q2_beta_abs_low.inst.cfg | 4 ++-- .../kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg | 4 ++-- .../quality/kemiq_q2/kemiq_q2_beta_pla_draft.inst.cfg | 4 ++-- .../kemiq_q2/kemiq_q2_beta_pla_extra_fine.inst.cfg | 8 ++++---- .../quality/kemiq_q2/kemiq_q2_beta_pla_fine.inst.cfg | 4 ++-- .../quality/kemiq_q2/kemiq_q2_beta_pla_low.inst.cfg | 4 ++-- .../kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg | 4 ++-- .../quality/kemiq_q2/kemiq_q2_gama_pla_draft.inst.cfg | 4 ++-- .../kemiq_q2/kemiq_q2_gama_pla_extra_fine.inst.cfg | 8 ++++---- .../quality/kemiq_q2/kemiq_q2_gama_pla_fine.inst.cfg | 4 ++-- .../quality/kemiq_q2/kemiq_q2_gama_pla_low.inst.cfg | 4 ++-- .../kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg | 4 ++-- resources/quality/low.inst.cfg | 4 ++-- .../malyan_m200/abs/malyan_m200_abs_draft.inst.cfg | 6 +++--- .../malyan_m200/abs/malyan_m200_abs_fast.inst.cfg | 6 +++--- .../malyan_m200/abs/malyan_m200_abs_high.inst.cfg | 6 +++--- .../malyan_m200/abs/malyan_m200_abs_normal.inst.cfg | 6 +++--- .../abs/malyan_m200_abs_superdraft.inst.cfg | 6 +++--- .../abs/malyan_m200_abs_thickerdraft.inst.cfg | 6 +++--- .../malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg | 6 +++--- .../abs/malyan_m200_abs_verydraft.inst.cfg | 6 +++--- .../quality/malyan_m200/malyan_m200_0.04375.inst.cfg | 6 +++--- .../quality/malyan_m200/malyan_m200_0.0875.inst.cfg | 6 +++--- .../quality/malyan_m200/malyan_m200_0.13125.inst.cfg | 6 +++--- .../quality/malyan_m200/malyan_m200_0.175.inst.cfg | 8 ++++---- .../quality/malyan_m200/malyan_m200_0.21875.inst.cfg | 6 +++--- .../quality/malyan_m200/malyan_m200_0.2625.inst.cfg | 6 +++--- .../quality/malyan_m200/malyan_m200_0.30625.inst.cfg | 6 +++--- .../quality/malyan_m200/malyan_m200_0.35.inst.cfg | 8 ++++---- .../malyan_m200_global_Draft_Quality.inst.cfg | 8 ++++---- .../malyan_m200_global_Fast_Quality.inst.cfg | 8 ++++---- .../malyan_m200_global_High_Quality.inst.cfg | 8 ++++---- .../malyan_m200_global_Normal_Quality.inst.cfg | 8 ++++---- .../malyan_m200_global_SuperDraft_Quality.inst.cfg | 8 ++++---- .../malyan_m200_global_ThickerDraft_Quality.inst.cfg | 8 ++++---- .../malyan_m200_global_Ultra_Quality.inst.cfg | 8 ++++---- .../malyan_m200_global_VeryDraft_Quality.inst.cfg | 8 ++++---- .../malyan_m200/petg/malyan_m200_petg_draft.inst.cfg | 4 ++-- .../malyan_m200/petg/malyan_m200_petg_fast.inst.cfg | 4 ++-- .../malyan_m200/petg/malyan_m200_petg_high.inst.cfg | 4 ++-- .../malyan_m200/petg/malyan_m200_petg_normal.inst.cfg | 4 ++-- .../petg/malyan_m200_petg_superdraft.inst.cfg | 4 ++-- .../petg/malyan_m200_petg_thickerdraft.inst.cfg | 4 ++-- .../malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg | 4 ++-- .../petg/malyan_m200_petg_verydraft.inst.cfg | 4 ++-- .../malyan_m200/pla/malyan_m200_pla_draft.inst.cfg | 6 +++--- .../malyan_m200/pla/malyan_m200_pla_fast.inst.cfg | 6 +++--- .../malyan_m200/pla/malyan_m200_pla_high.inst.cfg | 6 +++--- .../malyan_m200/pla/malyan_m200_pla_normal.inst.cfg | 6 +++--- .../pla/malyan_m200_pla_superdraft.inst.cfg | 6 +++--- .../pla/malyan_m200_pla_thickerdraft.inst.cfg | 6 +++--- .../malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg | 6 +++--- .../pla/malyan_m200_pla_verydraft.inst.cfg | 6 +++--- .../abs/monoprice_select_mini_v2_abs_draft.inst.cfg | 6 +++--- .../abs/monoprice_select_mini_v2_abs_fast.inst.cfg | 6 +++--- .../abs/monoprice_select_mini_v2_abs_high.inst.cfg | 6 +++--- .../abs/monoprice_select_mini_v2_abs_normal.inst.cfg | 6 +++--- .../monoprice_select_mini_v2_abs_superdraft.inst.cfg | 6 +++--- ...monoprice_select_mini_v2_abs_thickerdraft.inst.cfg | 6 +++--- .../abs/monoprice_select_mini_v2_abs_ultra.inst.cfg | 6 +++--- .../monoprice_select_mini_v2_abs_verydraft.inst.cfg | 6 +++--- ...price_select_mini_v2_global_Draft_Quality.inst.cfg | 8 ++++---- ...oprice_select_mini_v2_global_Fast_Quality.inst.cfg | 8 ++++---- ...oprice_select_mini_v2_global_High_Quality.inst.cfg | 8 ++++---- ...rice_select_mini_v2_global_Normal_Quality.inst.cfg | 8 ++++---- ..._select_mini_v2_global_SuperDraft_Quality.inst.cfg | 8 ++++---- ...elect_mini_v2_global_ThickerDraft_Quality.inst.cfg | 8 ++++---- ...price_select_mini_v2_global_Ultra_Quality.inst.cfg | 8 ++++---- ...e_select_mini_v2_global_VeryDraft_Quality.inst.cfg | 8 ++++---- .../monoprice_select_mini_v2_nylon_draft.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_nylon_fast.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_nylon_high.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_nylon_normal.inst.cfg | 4 ++-- ...monoprice_select_mini_v2_nylon_superdraft.inst.cfg | 4 ++-- ...noprice_select_mini_v2_nylon_thickerdraft.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_nylon_ultra.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_nylon_verydraft.inst.cfg | 4 ++-- .../pc/monoprice_select_mini_v2_pc_draft.inst.cfg | 6 +++--- .../pc/monoprice_select_mini_v2_pc_fast.inst.cfg | 6 +++--- .../pc/monoprice_select_mini_v2_pc_high.inst.cfg | 6 +++--- .../pc/monoprice_select_mini_v2_pc_normal.inst.cfg | 6 +++--- .../monoprice_select_mini_v2_pc_superdraft.inst.cfg | 6 +++--- .../monoprice_select_mini_v2_pc_thickerdraft.inst.cfg | 6 +++--- .../pc/monoprice_select_mini_v2_pc_ultra.inst.cfg | 6 +++--- .../pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg | 6 +++--- .../petg/monoprice_select_mini_v2_petg_draft.inst.cfg | 4 ++-- .../petg/monoprice_select_mini_v2_petg_fast.inst.cfg | 4 ++-- .../petg/monoprice_select_mini_v2_petg_high.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_petg_normal.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_petg_superdraft.inst.cfg | 4 ++-- ...onoprice_select_mini_v2_petg_thickerdraft.inst.cfg | 4 ++-- .../petg/monoprice_select_mini_v2_petg_ultra.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_petg_verydraft.inst.cfg | 4 ++-- .../pla/monoprice_select_mini_v2_pla_draft.inst.cfg | 4 ++-- .../pla/monoprice_select_mini_v2_pla_fast.inst.cfg | 4 ++-- .../pla/monoprice_select_mini_v2_pla_high.inst.cfg | 4 ++-- .../pla/monoprice_select_mini_v2_pla_normal.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_pla_superdraft.inst.cfg | 4 ++-- ...monoprice_select_mini_v2_pla_thickerdraft.inst.cfg | 4 ++-- .../pla/monoprice_select_mini_v2_pla_ultra.inst.cfg | 4 ++-- .../monoprice_select_mini_v2_pla_verydraft.inst.cfg | 4 ++-- resources/quality/normal.inst.cfg | 4 ++-- .../quality/peopoly_moai/peopoly_moai_high.inst.cfg | 6 +++--- .../quality/peopoly_moai/peopoly_moai_max.inst.cfg | 6 +++--- .../quality/peopoly_moai/peopoly_moai_normal.inst.cfg | 6 +++--- .../tevo_blackwidow/tevo_blackwidow_draft.inst.cfg | 4 ++-- .../tevo_blackwidow/tevo_blackwidow_high.inst.cfg | 4 ++-- .../tevo_blackwidow/tevo_blackwidow_normal.inst.cfg | 4 ++-- resources/quality/ultimaker2/um2_draft.inst.cfg | 2 +- resources/quality/ultimaker2/um2_high.inst.cfg | 2 +- resources/quality/ultimaker2/um2_low.inst.cfg | 2 +- resources/quality/ultimaker2/um2_normal.inst.cfg | 2 +- .../quality/ultimaker2_plus/pla_0.25_normal.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/pla_0.4_fast.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/pla_0.4_high.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/pla_0.4_normal.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/pla_0.6_normal.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/pla_0.8_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_abs_0.4_high.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpep_0.4_draft.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpep_0.4_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpep_0.6_draft.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpep_0.6_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpep_0.8_draft.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_cpep_0.8_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_nylon_0.25_high.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_nylon_0.25_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_nylon_0.4_fast.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_nylon_0.4_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_nylon_0.6_fast.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_nylon_0.6_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_nylon_0.8_draft.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_nylon_0.8_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pc_0.25_high.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pc_0.25_normal.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/um2p_pc_0.4_fast.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pc_0.4_normal.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/um2p_pc_0.6_fast.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pc_0.6_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pc_0.8_draft.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pc_0.8_normal.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/um2p_pp_0.4_fast.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pp_0.4_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg | 10 +++++----- .../quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_tpu_0.25_high.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_tpu_0.4_normal.inst.cfg | 10 +++++----- .../ultimaker2_plus/um2p_tpu_0.6_fast.inst.cfg | 10 +++++----- .../ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg | 6 +++--- .../um3_aa0.25_Nylon_Normal_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.25_PLA_Normal_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_ABS_Draft_Print.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_ABS_Fast_Print.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_BAM_Draft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_BAM_Fast_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_CPEP_Draft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_CPEP_Fast_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_CPEP_High_Quality.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_CPEP_Normal_Quality.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_CPE_Draft_Print.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_CPE_Fast_Print.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_CPE_High_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_CPE_Normal_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_Nylon_Draft_Print.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_Nylon_Fast_Print.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_Nylon_High_Quality.inst.cfg | 6 +++--- .../um3_aa0.4_Nylon_Normal_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_PC_Draft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_PC_Fast_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_PC_High_Quality.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_PC_Normal_Quality.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg | 6 +++--- .../ultimaker3/um3_aa0.4_PP_Draft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.4_PP_Fast_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.4_PP_Normal_Quality.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_ABS_Draft_Print.inst.cfg | 5 +++-- .../um3_aa0.8_ABS_Superdraft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.8_ABS_Verydraft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg | 7 ++++--- .../um3_aa0.8_CPEP_Superdraft_Print.inst.cfg | 7 ++++--- .../um3_aa0.8_CPEP_Verydraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_CPE_Draft_Print.inst.cfg | 5 +++-- .../um3_aa0.8_CPE_Superdraft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.8_CPE_Verydraft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.8_Nylon_Draft_Print.inst.cfg | 5 +++-- .../um3_aa0.8_Nylon_Superdraft_Print.inst.cfg | 5 +++-- .../um3_aa0.8_Nylon_Verydraft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg | 5 +++-- .../um3_aa0.8_PLA_Superdraft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg | 5 +++-- .../ultimaker3/um3_aa0.8_PP_Draft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_PP_Superdraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_PP_Verydraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg | 7 ++++--- .../um3_aa0.8_TPU_Superdraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_bb0.4_PVA_Draft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_bb0.4_PVA_Fast_Print.inst.cfg | 9 +++++---- .../ultimaker3/um3_bb0.4_PVA_High_Quality.inst.cfg | 9 +++++---- .../ultimaker3/um3_bb0.4_PVA_Normal_Quality.inst.cfg | 9 +++++---- .../ultimaker3/um3_bb0.8_PVA_Draft_Print.inst.cfg | 7 ++++--- .../um3_bb0.8_PVA_Superdraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_bb0.8_PVA_Verydraft_Print.inst.cfg | 7 ++++--- .../ultimaker3/um3_global_Draft_Quality.inst.cfg | 4 ++-- .../ultimaker3/um3_global_Fast_Quality.inst.cfg | 4 ++-- .../ultimaker3/um3_global_High_Quality.inst.cfg | 4 ++-- .../ultimaker3/um3_global_Normal_Quality.inst.cfg | 4 ++-- .../ultimaker3/um3_global_Superdraft_Quality.inst.cfg | 4 ++-- .../ultimaker3/um3_global_Verydraft_Quality.inst.cfg | 4 ++-- .../k8800_ABS_Extreme_Quality.inst.cfg | 6 +++--- .../k8800_ABS_High_Quality.inst.cfg | 6 +++--- .../k8800_ABS_Normal_Quality.inst.cfg | 6 +++--- .../k8800_PET_Extreme_Quality.inst.cfg | 6 +++--- .../k8800_PET_High_Quality.inst.cfg | 6 +++--- .../k8800_PET_Normal_Quality.inst.cfg | 6 +++--- .../k8800_PLA_Extreme_Quality.inst.cfg | 6 +++--- .../k8800_PLA_High_Quality.inst.cfg | 6 +++--- .../k8800_PLA_Normal_Quality.inst.cfg | 6 +++--- .../k8800_TPU_Extreme_Quality.inst.cfg | 6 +++--- .../k8800_TPU_High_Quality.inst.cfg | 6 +++--- .../k8800_TPU_Normal_Quality.inst.cfg | 4 ++-- 386 files changed, 1234 insertions(+), 1134 deletions(-) diff --git a/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg b/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg index 32550d86a5..7d1c1bf588 100644 --- a/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = abax_pri3 [metadata] -type = quality -material = generic_pla -weight = -1 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = -1 +material = generic_pla [values] layer_height = 0.2 @@ -19,4 +19,4 @@ speed_print = 80 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/abax_pri3/apri3_pla_high.inst.cfg b/resources/quality/abax_pri3/apri3_pla_high.inst.cfg index 2007785719..46a4178dd9 100644 --- a/resources/quality/abax_pri3/apri3_pla_high.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_high.inst.cfg @@ -4,11 +4,11 @@ name = Extra Fine definition = abax_pri3 [metadata] -type = quality -material = generic_pla -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla [values] layer_height = 0.1 @@ -19,4 +19,4 @@ speed_print = 50 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg b/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg index dba0a0460f..3f6f36cfe6 100644 --- a/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = abax_pri3 [metadata] -type = quality -material = generic_pla -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pla [values] layer_height = 0.2 @@ -19,4 +19,4 @@ speed_print = 50 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg b/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg index 11892a6223..517c767ac5 100644 --- a/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg +++ b/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = abax_pri5 [metadata] -type = quality -material = generic_pla -weight = -1 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = -1 +material = generic_pla [values] layer_height = 0.2 @@ -19,4 +19,4 @@ speed_print = 80 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/abax_pri5/apri5_pla_high.inst.cfg b/resources/quality/abax_pri5/apri5_pla_high.inst.cfg index 852efe699e..01699e39f6 100644 --- a/resources/quality/abax_pri5/apri5_pla_high.inst.cfg +++ b/resources/quality/abax_pri5/apri5_pla_high.inst.cfg @@ -4,11 +4,11 @@ name = Extra Fine definition = abax_pri5 [metadata] -type = quality -material = generic_pla -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla [values] layer_height = 0.1 @@ -19,4 +19,4 @@ speed_print = 50 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg b/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg index 244d544c80..ea1023dc43 100644 --- a/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg +++ b/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = abax_pri5 [metadata] -type = quality -material = generic_pla -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pla [values] layer_height = 0.2 @@ -19,4 +19,4 @@ speed_print = 50 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/abax_titan/atitan_pla_fast.inst.cfg b/resources/quality/abax_titan/atitan_pla_fast.inst.cfg index a2d802a3ba..ae489c3792 100644 --- a/resources/quality/abax_titan/atitan_pla_fast.inst.cfg +++ b/resources/quality/abax_titan/atitan_pla_fast.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = abax_titan [metadata] -type = quality -material = generic_pla -weight = -1 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = -1 +material = generic_pla [values] layer_height = 0.2 @@ -19,4 +19,4 @@ speed_print = 80 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/abax_titan/atitan_pla_high.inst.cfg b/resources/quality/abax_titan/atitan_pla_high.inst.cfg index 7ee8c35133..f9bf350814 100644 --- a/resources/quality/abax_titan/atitan_pla_high.inst.cfg +++ b/resources/quality/abax_titan/atitan_pla_high.inst.cfg @@ -2,12 +2,13 @@ version = 2 name = Extra Fine definition = abax_titan + [metadata] -type = quality -material = generic_pla -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla [values] layer_height = 0.1 @@ -18,4 +19,4 @@ speed_print = 50 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/abax_titan/atitan_pla_normal.inst.cfg b/resources/quality/abax_titan/atitan_pla_normal.inst.cfg index 6c40914566..c73d6901fb 100644 --- a/resources/quality/abax_titan/atitan_pla_normal.inst.cfg +++ b/resources/quality/abax_titan/atitan_pla_normal.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = abax_titan [metadata] -type = quality -material = generic_pla -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pla [values] layer_height = 0.2 @@ -19,4 +19,4 @@ speed_print = 50 speed_layer_0 = =round(speed_print * 30 / 50) speed_topbottom = 20 cool_min_layer_time = 5 -cool_min_speed = 10 \ No newline at end of file +cool_min_speed = 10 diff --git a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg index c6281767f9..caa6d8edb6 100644 --- a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg +++ b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_draft.inst.cfg @@ -4,10 +4,10 @@ name = Draft definition = anycubic_i3_mega [metadata] +setting_version = 4 type = quality quality_type = draft weight = 0 -setting_version = 4 [values] acceleration_enabled = True @@ -57,4 +57,4 @@ support_type = everywhere support_use_towers = False support_xy_distance = 0.7 top_bottom_thickness = 1.2 -wall_thickness = 1.2 \ No newline at end of file +wall_thickness = 1.2 diff --git a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg index 839054a4df..5d6f8d9013 100644 --- a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg +++ b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_high.inst.cfg @@ -4,10 +4,10 @@ name = High definition = anycubic_i3_mega [metadata] +setting_version = 4 type = quality quality_type = high weight = 2 -setting_version = 4 [values] acceleration_enabled = True @@ -57,4 +57,4 @@ support_type = everywhere support_use_towers = False support_xy_distance = 0.7 top_bottom_thickness = 1.2 -wall_thickness = 1.2 \ No newline at end of file +wall_thickness = 1.2 diff --git a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg index 241a8b2e2c..ca25afa424 100644 --- a/resources/quality/anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg +++ b/resources/quality/anycubic_i3_mega/anycubic_i3_mega_normal.inst.cfg @@ -4,10 +4,10 @@ name = Normal definition = anycubic_i3_mega [metadata] +setting_version = 4 type = quality quality_type = normal weight = 1 -setting_version = 4 [values] acceleration_enabled = True @@ -57,4 +57,4 @@ support_type = everywhere support_use_towers = False support_xy_distance = 0.7 top_bottom_thickness = 1.2 -wall_thickness = 1.2 \ No newline at end of file +wall_thickness = 1.2 diff --git a/resources/quality/builder_premium/bp_BVOH_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_BVOH_Coarse_Quality.inst.cfg index 92f899bdeb..d83f2a1ccd 100644 --- a/resources/quality/builder_premium/bp_BVOH_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_BVOH_Coarse_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Coarse definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = coarse -material = verbatim_bvoh_175 -setting_version = 4 weight = -1 +material = verbatim_bvoh_175 [values] material_print_temperature = =default_material_print_temperature + 5 @@ -21,4 +21,3 @@ layer_height = 0.3 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 speed_print = 40 - diff --git a/resources/quality/builder_premium/bp_BVOH_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_BVOH_High_Quality.inst.cfg index cd8947aa80..f029a0206f 100644 --- a/resources/quality/builder_premium/bp_BVOH_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_BVOH_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High Quality definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = high -material = verbatim_bvoh_175 -setting_version = 4 weight = 1 +material = verbatim_bvoh_175 [values] acceleration_print = 2000 @@ -22,4 +22,4 @@ layer_height = 0.1 top_thickness = =layer_height * 7 bottom_thickness = =layer_height * 5 speed_print = 40 -layer_height_0 = 0.2 \ No newline at end of file +layer_height_0 = 0.2 diff --git a/resources/quality/builder_premium/bp_BVOH_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_BVOH_Normal_Quality.inst.cfg index d59f768470..640812b37d 100644 --- a/resources/quality/builder_premium/bp_BVOH_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_BVOH_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = normal -material = verbatim_bvoh_175 -setting_version = 4 weight = 0 +material = verbatim_bvoh_175 [values] material_print_temperature = =default_material_print_temperature + 5 @@ -20,4 +20,4 @@ material_bed_temperature_layer_0= =material_bed_temperature layer_height = 0.2 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 -speed_print = 40 \ No newline at end of file +speed_print = 40 diff --git a/resources/quality/builder_premium/bp_Innoflex60_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_Innoflex60_Coarse_Quality.inst.cfg index 41d882ee1d..905cf50518 100644 --- a/resources/quality/builder_premium/bp_Innoflex60_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_Innoflex60_Coarse_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Coarse definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = coarse -material = innofill_innoflex60_175 -setting_version = 4 weight = -1 +material = innofill_innoflex60_175 [values] material_print_temperature = =default_material_print_temperature @@ -21,4 +21,3 @@ layer_height = 0.3 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 speed_print = 30 - diff --git a/resources/quality/builder_premium/bp_Innoflex60_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_Innoflex60_High_Quality.inst.cfg index 147e1f4db8..835ce04d61 100644 --- a/resources/quality/builder_premium/bp_Innoflex60_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_Innoflex60_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High Quality definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = high -material = innofill_innoflex60_175 -setting_version = 4 weight = 1 +material = innofill_innoflex60_175 [values] acceleration_print = 2000 @@ -22,4 +22,4 @@ layer_height = 0.1 top_thickness = =layer_height * 7 bottom_thickness = =layer_height * 5 speed_print = 30 -layer_height_0 = 0.2 \ No newline at end of file +layer_height_0 = 0.2 diff --git a/resources/quality/builder_premium/bp_Innoflex60_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_Innoflex60_Normal_Quality.inst.cfg index fb43c8de19..ba176dbc5c 100644 --- a/resources/quality/builder_premium/bp_Innoflex60_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_Innoflex60_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = normal -material = innofill_innoflex60_175 -setting_version = 4 weight = 0 +material = innofill_innoflex60_175 [values] material_print_temperature = =default_material_print_temperature @@ -20,4 +20,4 @@ material_bed_temperature_layer_0= =material_bed_temperature layer_height = 0.2 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 -speed_print = 30 \ No newline at end of file +speed_print = 30 diff --git a/resources/quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg index f887600585..ce9e58ea04 100644 --- a/resources/quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Coarse definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_petg_175 -setting_version = 4 weight = -1 +material = generic_petg_175 [values] material_print_temperature = =default_material_print_temperature - 5 @@ -21,4 +21,3 @@ layer_height = 0.3 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 speed_print = 60 - diff --git a/resources/quality/builder_premium/bp_PET_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_PET_High_Quality.inst.cfg index 4258f2f708..cbde2790df 100644 --- a/resources/quality/builder_premium/bp_PET_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PET_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High Quality definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_petg_175 -setting_version = 4 weight = 1 +material = generic_petg_175 [values] acceleration_print = 2000 @@ -22,4 +22,4 @@ layer_height = 0.1 top_thickness = =layer_height * 7 bottom_thickness = =layer_height * 5 speed_print = 40 -layer_height_0 = 0.2 \ No newline at end of file +layer_height_0 = 0.2 diff --git a/resources/quality/builder_premium/bp_PET_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_PET_Normal_Quality.inst.cfg index b732073795..af122db9cc 100644 --- a/resources/quality/builder_premium/bp_PET_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PET_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_petg_175 -setting_version = 4 weight = 0 +material = generic_petg_175 [values] material_print_temperature = =default_material_print_temperature - 5 @@ -20,4 +20,4 @@ material_bed_temperature_layer_0= =material_bed_temperature layer_height = 0.2 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 -speed_print = 50 \ No newline at end of file +speed_print = 50 diff --git a/resources/quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg index 4f0c26dd7d..d8baf277a9 100644 --- a/resources/quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Coarse definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_pla_175 -setting_version = 4 weight = -1 +material = generic_pla_175 [values] material_print_temperature = =default_material_print_temperature + 15 @@ -21,4 +21,3 @@ layer_height = 0.3 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 speed_print = 60 - diff --git a/resources/quality/builder_premium/bp_PLA_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_PLA_High_Quality.inst.cfg index 4a9bcb90bf..49675e25d9 100644 --- a/resources/quality/builder_premium/bp_PLA_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PLA_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High Quality definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pla_175 -setting_version = 4 weight = 1 +material = generic_pla_175 [values] acceleration_print = 2000 @@ -22,4 +22,4 @@ layer_height = 0.1 top_thickness = =layer_height * 7 bottom_thickness = =layer_height * 5 speed_print = 40 -layer_height_0 = 0.2 \ No newline at end of file +layer_height_0 = 0.2 diff --git a/resources/quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg index 6af5601fd6..113bdba605 100644 --- a/resources/quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pla_175 -setting_version = 4 weight = 0 +material = generic_pla_175 [values] material_print_temperature = =default_material_print_temperature + 15 @@ -20,4 +20,4 @@ material_bed_temperature_layer_0= =material_bed_temperature layer_height = 0.2 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 -speed_print = 50 \ No newline at end of file +speed_print = 50 diff --git a/resources/quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg index 12a4c9d883..059f25a70f 100644 --- a/resources/quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Coarse definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_pva_175 -setting_version = 4 weight = -1 +material = generic_pva_175 [values] material_print_temperature = =default_material_print_temperature + 10 @@ -21,4 +21,3 @@ layer_height = 0.3 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 speed_print = 40 - diff --git a/resources/quality/builder_premium/bp_PVA_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_PVA_High_Quality.inst.cfg index d32017c5f2..5da254aa9b 100644 --- a/resources/quality/builder_premium/bp_PVA_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PVA_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High Quality definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pva_175 -setting_version = 4 weight = 1 +material = generic_pva_175 [values] acceleration_print = 2000 @@ -22,4 +22,4 @@ layer_height = 0.1 top_thickness = =layer_height * 7 bottom_thickness = =layer_height * 5 speed_print = 40 -layer_height_0 = 0.2 \ No newline at end of file +layer_height_0 = 0.2 diff --git a/resources/quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg index 2acc354822..562b2257f5 100644 --- a/resources/quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pva_175 -setting_version = 4 weight = 0 +material = generic_pva_175 [values] material_print_temperature = =default_material_print_temperature + 10 @@ -20,4 +20,4 @@ material_bed_temperature_layer_0= =material_bed_temperature layer_height = 0.2 top_thickness = =layer_height * 5 bottom_thickness = =layer_height * 3 -speed_print = 40 \ No newline at end of file +speed_print = 40 diff --git a/resources/quality/builder_premium/bp_global_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_global_Coarse_Quality.inst.cfg index 4b66293d04..c9b2b3a654 100644 --- a/resources/quality/builder_premium/bp_global_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_global_Coarse_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Coarse definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = coarse -setting_version = 4 weight = -1 global_quality = True [values] -layer_height = 0.3 \ No newline at end of file +layer_height = 0.3 diff --git a/resources/quality/builder_premium/bp_global_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_global_High_Quality.inst.cfg index 4a97dda084..efad0f96e5 100644 --- a/resources/quality/builder_premium/bp_global_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_global_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High Quality definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = high -setting_version = 4 weight = 1 global_quality = True [values] -layer_height = 0.1 \ No newline at end of file +layer_height = 0.1 diff --git a/resources/quality/builder_premium/bp_global_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_global_Normal_Quality.inst.cfg index 15ea66879f..69c6214aa8 100644 --- a/resources/quality/builder_premium/bp_global_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_global_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = builder_premium_small [metadata] +setting_version = 4 type = quality quality_type = normal -setting_version = 4 weight = 0 global_quality = True [values] -layer_height = 0.2 \ No newline at end of file +layer_height = 0.2 diff --git a/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg index 418855a9ba..89ab9a09d4 100644 --- a/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_abs_175_cartesio_0.25_mm weight = 1 -setting_version = 4 +material = generic_abs_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg index e95ef08e22..a83a6d1e31 100644 --- a/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_abs_175_cartesio_0.25_mm weight = 2 -setting_version = 4 +material = generic_abs_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg index 524f5ba12a..b5281407dd 100644 --- a/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_abs_175_cartesio_0.4_mm weight = 1 -setting_version = 4 +material = generic_abs_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg index 24ffb19d6f..b366026793 100644 --- a/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_abs_175_cartesio_0.4_mm weight = 2 -setting_version = 4 +material = generic_abs_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg index 1281a3afdd..0f4896ea74 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_abs_175_cartesio_0.8_mm weight = 3 -setting_version = 4 +material = generic_abs_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg index a8d19deef7..5f3f20c9ee 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Extra Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = extra coarse -material = generic_abs_175_cartesio_0.8_mm weight = 4 -setting_version = 4 +material = generic_abs_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg index 87cc855f44..2a5b873dd4 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_abs_175_cartesio_0.8_mm weight = 1 -setting_version = 4 +material = generic_abs_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg index 4ca2598051..887a252e06 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_abs_175_cartesio_0.8_mm weight = 2 -setting_version = 4 +material = generic_abs_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_high.inst.cfg b/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_high.inst.cfg index 42eb705f11..6b186f427c 100644 --- a/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_high.inst.cfg +++ b/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = dsm_arnitel2045_175_cartesio_0.4_mm weight = 1 -setting_version = 4 +material = dsm_arnitel2045_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg b/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg index 538fe91b76..11bf7cf2e6 100644 --- a/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg +++ b/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = dsm_arnitel2045_175_cartesio_0.4_mm weight = 2 -setting_version = 4 +material = dsm_arnitel2045_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/cartesio_global_Coarse_Quality.inst.cfg b/resources/quality/cartesio/cartesio_global_Coarse_Quality.inst.cfg index 11760b139f..53cbb6bf06 100644 --- a/resources/quality/cartesio/cartesio_global_Coarse_Quality.inst.cfg +++ b/resources/quality/cartesio/cartesio_global_Coarse_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = coarse -global_quality = True weight = -3 -setting_version = 4 +global_quality = True [values] layer_height = 0.4 diff --git a/resources/quality/cartesio/cartesio_global_Extra_Coarse_Quality.inst.cfg b/resources/quality/cartesio/cartesio_global_Extra_Coarse_Quality.inst.cfg index c654dba598..4d612db89f 100644 --- a/resources/quality/cartesio/cartesio_global_Extra_Coarse_Quality.inst.cfg +++ b/resources/quality/cartesio/cartesio_global_Extra_Coarse_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Extra Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = extra coarse -global_quality = True weight = -4 -setting_version = 4 +global_quality = True [values] layer_height = 0.6 diff --git a/resources/quality/cartesio/cartesio_global_High_Quality.inst.cfg b/resources/quality/cartesio/cartesio_global_High_Quality.inst.cfg index 393a5f3b39..b9e4f287a1 100644 --- a/resources/quality/cartesio/cartesio_global_High_Quality.inst.cfg +++ b/resources/quality/cartesio/cartesio_global_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -global_quality = True weight = 1 -setting_version = 4 +global_quality = True [values] layer_height = 0.1 diff --git a/resources/quality/cartesio/cartesio_global_Normal_Quality.inst.cfg b/resources/quality/cartesio/cartesio_global_Normal_Quality.inst.cfg index c09493ba10..1b3af7c9ce 100644 --- a/resources/quality/cartesio/cartesio_global_Normal_Quality.inst.cfg +++ b/resources/quality/cartesio/cartesio_global_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -global_quality = True weight = 0 -setting_version = 4 +global_quality = True [values] layer_height = 0.2 diff --git a/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg index eae4e82cd3..b4417d4bcf 100644 --- a/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_hips_175_cartesio_0.25_mm weight = 1 -setting_version = 4 +material = generic_hips_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg index 0c47b18196..b669f21a2b 100644 --- a/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_hips_175_cartesio_0.25_mm weight = 2 -setting_version = 4 +material = generic_hips_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg index 14f1ea4662..c88f8be029 100644 --- a/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_hips_175_cartesio_0.4_mm weight = 1 -setting_version = 4 +material = generic_hips_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg index bd13b358ff..4790926e3b 100644 --- a/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_hips_175_cartesio_0.4_mm weight = 2 -setting_version = 4 +material = generic_hips_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg index ca864692c3..e096fbb3a4 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_hips_175_cartesio_0.8_mm weight = 3 -setting_version = 4 +material = generic_hips_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg index 3cadef4fdd..80a44678ca 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Extra Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = extra coarse -material = generic_hips_175_cartesio_0.8_mm weight = 4 -setting_version = 4 +material = generic_hips_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg index 07839c8a9a..e1754d5ba0 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_hips_175_cartesio_0.8_mm weight = 1 -setting_version = 4 +material = generic_hips_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg index acc9db0891..b728e01c99 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_hips_175_cartesio_0.8_mm weight = 2 -setting_version = 4 +material = generic_hips_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg index b1f2f17d41..b81a053cd3 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_nylon_175_cartesio_0.25_mm weight = 1 -setting_version = 4 +material = generic_nylon_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg index bcfa1c2e30..b09e2ac794 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_nylon_175_cartesio_0.25_mm weight = 2 -setting_version = 4 +material = generic_nylon_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg index 2cd50efeb2..b43839439f 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_nylon_175_cartesio_0.4_mm weight = 1 -setting_version = 4 +material = generic_nylon_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg index 7a7d767ea3..36cfe49afb 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_nylon_175_cartesio_0.4_mm weight = 2 -setting_version = 4 +material = generic_nylon_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg index 5684c89e23..ef3185814b 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_nylon_175_cartesio_0.8_mm weight = 3 -setting_version = 4 +material = generic_nylon_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg index 8d97e9ac5f..af57d6f3ab 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Extra Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = extra coarse -material = generic_nylon_175_cartesio_0.8_mm weight = 4 -setting_version = 4 +material = generic_nylon_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg index 946f8de34d..99e932c954 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_nylon_175_cartesio_0.8_mm weight = 1 -setting_version = 4 +material = generic_nylon_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg index 80f390c254..a0fef367a6 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_nylon_175_cartesio_0.8_mm weight = 2 -setting_version = 4 +material = generic_nylon_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg index ff6547dd91..ac0f7a35fa 100644 --- a/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pc_175_cartesio_0.25_mm weight = 1 -setting_version = 4 +material = generic_pc_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg index f3faa9c129..5f77a2a91e 100644 --- a/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pc_175_cartesio_0.25_mm weight = 2 -setting_version = 4 +material = generic_pc_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg index 3aa808fab5..835c94e5fd 100644 --- a/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pc_175_cartesio_0.4_mm weight = 1 -setting_version = 4 +material = generic_pc_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg index f9be12da3a..7e48b4a94c 100644 --- a/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pc_175_cartesio_0.4_mm weight = 2 -setting_version = 4 +material = generic_pc_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg index 597187437b..e857476b8b 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_pc_175_cartesio_0.8_mm weight = 3 -setting_version = 4 +material = generic_pc_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg index 6d1fa196ec..0fc24de569 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Extra Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = extra coarse -material = generic_pc_175_cartesio_0.8_mm weight = 4 -setting_version = 4 +material = generic_pc_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg index c570b65350..3c58129546 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pc_175_cartesio_0.8_mm weight = 1 -setting_version = 4 +material = generic_pc_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg index 0d73b24197..3b8765b21a 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pc_175_cartesio_0.8_mm weight = 2 -setting_version = 4 +material = generic_pc_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg index c5c4be6f4a..94bf52b2a4 100644 --- a/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_petg_175_cartesio_0.25_mm weight = 1 -setting_version = 4 +material = generic_petg_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg index 6d12bdc402..d5517b57b5 100644 --- a/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_petg_175_cartesio_0.25_mm weight = 2 -setting_version = 4 +material = generic_petg_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg index 43dda5007c..33b3bfa99d 100644 --- a/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_petg_175_cartesio_0.4_mm weight = 1 -setting_version = 4 +material = generic_petg_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg index 094dc33263..1bdbe32229 100644 --- a/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_petg_175_cartesio_0.4_mm weight = 2 -setting_version = 4 +material = generic_petg_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg index da9e4ad3dd..20b2d38856 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_petg_175_cartesio_0.8_mm weight = 3 -setting_version = 4 +material = generic_petg_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg index 607ba778a1..cdb4d08dd0 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Extra Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = extra coarse -material = generic_petg_175_cartesio_0.8_mm weight = 4 -setting_version = 4 +material = generic_petg_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg index 3010d95dab..e125e9dd63 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_petg_175_cartesio_0.8_mm weight = 1 -setting_version = 4 +material = generic_petg_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg index fbf8fac67f..91a513d171 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_petg_175_cartesio_0.8_mm weight = 2 -setting_version = 4 +material = generic_petg_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg index 9d8130602e..cbd40f3f8f 100644 --- a/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pla_175_cartesio_0.25_mm weight = 1 -setting_version = 4 +material = generic_pla_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg index 98401dbf42..3eed8df302 100644 --- a/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pla_175_cartesio_0.25_mm weight = 0 -setting_version = 4 +material = generic_pla_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg index 2eda5103d7..0822ab8c07 100644 --- a/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pla_175_cartesio_0.4_mm weight = 1 -setting_version = 4 +material = generic_pla_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg index f3d3820ff7..80fb24553f 100644 --- a/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pla_175_cartesio_0.4_mm weight = 0 -setting_version = 4 +material = generic_pla_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg index d2cf708336..c6b92d50a7 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_pla_175_cartesio_0.8_mm weight = -3 -setting_version = 4 +material = generic_pla_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg index 888d8f91a7..cb2633313a 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Extra Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = extra coarse -material = generic_pla_175_cartesio_0.8_mm weight = -4 -setting_version = 4 +material = generic_pla_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg index 558514db98..de0298f57e 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pla_175_cartesio_0.8_mm weight = 1 -setting_version = 4 +material = generic_pla_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg index 9c508e4a1f..c6f4e012b6 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pla_175_cartesio_0.8_mm weight = 0 -setting_version = 4 +material = generic_pla_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg index fcbf4913de..22fdd98317 100644 --- a/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pva_175_cartesio_0.25_mm weight = 1 -setting_version = 4 +material = generic_pva_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg index 3893421df0..8288294d0c 100644 --- a/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pva_175_cartesio_0.25_mm weight = 2 -setting_version = 4 +material = generic_pva_175 +variant = 0.25 mm [values] infill_line_width = 0.3 diff --git a/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg index 5876db1e2e..2719eb458e 100644 --- a/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pva_175_cartesio_0.4_mm weight = 1 -setting_version = 4 +material = generic_pva_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg index c977e79a5c..6a97ec860f 100644 --- a/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pva_175_cartesio_0.4_mm weight = 2 -setting_version = 4 +material = generic_pva_175 +variant = 0.4 mm [values] infill_line_width = 0.5 diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg index 8c36d8e7ed..12ca609a7b 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = coarse -material = generic_pva_175_cartesio_0.8_mm weight = 3 -setting_version = 4 +material = generic_pva_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg index c2b19868f6..d793282c41 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Extra Coarse definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = extra coarse -material = generic_pva_175_cartesio_0.8_mm weight = 4 -setting_version = 4 +material = generic_pva_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg index 5bd285285a..a43689e7c9 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg @@ -4,11 +4,12 @@ name = High definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pva_175_cartesio_0.8_mm weight = 1 -setting_version = 4 +material = generic_pva_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg index a11bff95e1..f9ead11d79 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = cartesio [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pva_175_cartesio_0.8_mm weight = 2 -setting_version = 4 +material = generic_pva_175 +variant = 0.8 mm [values] infill_line_width = 0.9 diff --git a/resources/quality/coarse.inst.cfg b/resources/quality/coarse.inst.cfg index 133ffc8951..1accd77807 100644 --- a/resources/quality/coarse.inst.cfg +++ b/resources/quality/coarse.inst.cfg @@ -4,11 +4,11 @@ name = Coarse Quality definition = fdmprinter [metadata] +setting_version = 4 type = quality quality_type = coarse -global_quality = True weight = -3 -setting_version = 4 +global_quality = True [values] layer_height = 0.4 diff --git a/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg index 43643b6b92..aebb72d610 100644 --- a/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg @@ -4,11 +4,11 @@ definition = deltacomb name = Fast Quality (beta) [metadata] -type = quality setting_version = 4 -material = generic_abs_175 +type = quality quality_type = fast weight = -1 +material = generic_abs_175 [values] adhesion_type = raft @@ -22,4 +22,3 @@ cool_fan_speed_min = 50 cool_min_layer_time = 3 cool_min_speed = 20 material_bed_temperature = 80 - diff --git a/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg index 99e47bc9cb..05b54eb81e 100644 --- a/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg @@ -4,11 +4,11 @@ definition = deltacomb name = High Quality (beta) [metadata] -type = quality setting_version = 4 -material = generic_abs_175 +type = quality quality_type = high weight = 1 +material = generic_abs_175 [values] adhesion_type = raft @@ -22,4 +22,3 @@ cool_fan_speed_min = 50 cool_min_layer_time = 3 cool_min_speed = 20 material_bed_temperature = 80 - diff --git a/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg index a2aa2be769..67c8525b4f 100644 --- a/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg @@ -4,11 +4,11 @@ definition = deltacomb name = Normal Quality (beta) [metadata] -type = quality setting_version = 4 -material = generic_abs_175 +type = quality quality_type = normal weight = 0 +material = generic_abs_175 [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg index fac23939cf..511ee2712f 100644 --- a/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg @@ -4,11 +4,11 @@ name = Fast Quality (beta) definition = deltacomb [metadata] +setting_version = 4 type = quality -material = generic_nylon_175 quality_type = fast weight = -1 -setting_version = 4 +material = generic_nylon_175 [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg index d594126474..47c3e26782 100644 --- a/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg @@ -4,11 +4,11 @@ name = High Quality (beta) definition = deltacomb [metadata] +setting_version = 4 type = quality -material = generic_nylon_175 quality_type = high weight = 1 -setting_version = 4 +material = generic_nylon_175 [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg index 76716fc16d..49ffada336 100644 --- a/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg @@ -4,11 +4,11 @@ name = Normal Quality (beta) definition = deltacomb [metadata] +setting_version = 4 type = quality -material = generic_nylon_175 quality_type = normal weight = 0 -setting_version = 4 +material = generic_nylon_175 [values] adhesion_type = raft @@ -55,4 +55,3 @@ support_z_distance = 0.15 top_bottom_thickness = 0.8 wall_thickness = 0.8 z_seam_type = random - diff --git a/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg index 9783cb11cc..684b72587c 100644 --- a/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg @@ -4,11 +4,11 @@ definition = deltacomb name = Fast Quality [metadata] -type = quality setting_version = 4 -material = generic_pla_175 +type = quality quality_type = fast weight = -1 +material = generic_pla_175 [values] adhesion_type = skirt @@ -21,4 +21,3 @@ cool_fan_speed_max = 100 cool_fan_speed_min = 100 cool_min_layer_time = 5 cool_min_speed = 20 - diff --git a/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg index 9513e98b6a..a80f23fa9b 100644 --- a/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg @@ -4,11 +4,11 @@ definition = deltacomb name = High Quality [metadata] -type = quality setting_version = 4 -material = generic_pla_175 +type = quality quality_type = high weight = 1 +material = generic_pla_175 [values] adhesion_type = skirt @@ -22,4 +22,3 @@ cool_fan_speed_min = 100 cool_min_layer_time = 5 cool_min_speed = 20 material_print_temperature_layer_0 = =default_material_print_temperature + 5 - diff --git a/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg index d88f5909f0..8a02873fa2 100644 --- a/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg @@ -4,11 +4,11 @@ definition = deltacomb name = Normal Quality [metadata] -type = quality setting_version = 4 -material = generic_pla_175 +type = quality quality_type = normal weight = 0 +material = generic_pla_175 [values] adhesion_type = skirt diff --git a/resources/quality/draft.inst.cfg b/resources/quality/draft.inst.cfg index a155c8f2e1..2b375878b6 100644 --- a/resources/quality/draft.inst.cfg +++ b/resources/quality/draft.inst.cfg @@ -1,15 +1,14 @@ - [general] version = 2 name = Draft Quality definition = fdmprinter [metadata] +setting_version = 4 type = quality quality_type = draft -global_quality = True weight = -2 -setting_version = 4 +global_quality = True [values] layer_height = 0.2 diff --git a/resources/quality/extra_coarse.inst.cfg b/resources/quality/extra_coarse.inst.cfg index ce28e54721..6c11c9e61b 100644 --- a/resources/quality/extra_coarse.inst.cfg +++ b/resources/quality/extra_coarse.inst.cfg @@ -4,11 +4,11 @@ name = Extra Coarse Quality definition = fdmprinter [metadata] +setting_version = 4 type = quality quality_type = Extra coarse -global_quality = True weight = -4 -setting_version = 4 +global_quality = True [values] layer_height = 0.6 diff --git a/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg index 245997a27e..8a48962553 100644 --- a/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_fast.inst.cfg @@ -4,11 +4,11 @@ definition = fabtotum name = Fast Quality [metadata] -type = quality setting_version = 4 -material = fabtotum_abs +type = quality quality_type = fast weight = -1 +material = fabtotum_abs [values] adhesion_type = raft @@ -21,4 +21,3 @@ cool_fan_speed_max = 50 cool_fan_speed_min = 50 cool_min_layer_time = 3 cool_min_speed = 20 - diff --git a/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg index 26300eec7d..c8a970e180 100644 --- a/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_high.inst.cfg @@ -4,11 +4,11 @@ definition = fabtotum name = High Quality [metadata] -type = quality setting_version = 4 -material = fabtotum_abs +type = quality quality_type = high weight = 1 +material = fabtotum_abs [values] adhesion_type = raft @@ -21,4 +21,3 @@ cool_fan_speed_max = 50 cool_fan_speed_min = 50 cool_min_layer_time = 3 cool_min_speed = 20 - diff --git a/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg index 53d20c8cbc..03b580a9c3 100644 --- a/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_abs_normal.inst.cfg @@ -4,11 +4,11 @@ definition = fabtotum name = Normal Quality [metadata] -type = quality setting_version = 4 -material = fabtotum_abs +type = quality quality_type = normal weight = 0 +material = fabtotum_abs [values] adhesion_type = raft @@ -21,4 +21,3 @@ cool_fan_speed_max = 50 cool_fan_speed_min = 50 cool_min_layer_time = 3 cool_min_speed = 20 - diff --git a/resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg index 22bbcbeaeb..7c5769c489 100644 --- a/resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_nylon_fast.inst.cfg @@ -4,11 +4,11 @@ name = Fast Quality definition = fabtotum [metadata] +setting_version = 4 type = quality -material = fabtotum_nylon quality_type = fast weight = -1 -setting_version = 4 +material = fabtotum_nylon [values] adhesion_type = raft @@ -54,4 +54,4 @@ support_type = buildplate support_z_distance = 0.15 top_bottom_thickness = 0.8 wall_thickness = 0.8 -z_seam_type = random \ No newline at end of file +z_seam_type = random diff --git a/resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg b/resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg index a625bd715f..a74a6d5138 100644 --- a/resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_nylon_high.inst.cfg @@ -4,11 +4,11 @@ name = High Quality definition = fabtotum [metadata] +setting_version = 4 type = quality -material = fabtotum_nylon quality_type = high weight = 1 -setting_version = 4 +material = fabtotum_nylon [values] adhesion_type = raft @@ -54,4 +54,4 @@ support_type = buildplate support_z_distance = 0.15 top_bottom_thickness = 0.8 wall_thickness = 0.8 -z_seam_type = random \ No newline at end of file +z_seam_type = random diff --git a/resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg index b05d30c5c6..c3de34beb3 100644 --- a/resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_nylon_normal.inst.cfg @@ -4,11 +4,11 @@ name = Normal Quality definition = fabtotum [metadata] +setting_version = 4 type = quality -material = fabtotum_nylon quality_type = normal weight = 0 -setting_version = 4 +material = fabtotum_nylon [values] adhesion_type = raft @@ -55,4 +55,3 @@ support_z_distance = 0.15 top_bottom_thickness = 0.8 wall_thickness = 0.8 z_seam_type = random - diff --git a/resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg b/resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg index 1f1c93961b..3c71af3727 100644 --- a/resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_pla_fast.inst.cfg @@ -4,11 +4,11 @@ definition = fabtotum name = Fast Quality [metadata] -type = quality setting_version = 4 -material = fabtotum_pla +type = quality quality_type = fast weight = -1 +material = fabtotum_pla [values] adhesion_type = skirt @@ -21,4 +21,3 @@ cool_fan_speed_max = 100 cool_fan_speed_min = 100 cool_min_layer_time = 5 cool_min_speed = 20 - diff --git a/resources/quality/fabtotum/fabtotum_pla_high.inst.cfg b/resources/quality/fabtotum/fabtotum_pla_high.inst.cfg index 9cd067703c..0832f84d0c 100644 --- a/resources/quality/fabtotum/fabtotum_pla_high.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_pla_high.inst.cfg @@ -4,11 +4,11 @@ definition = fabtotum name = High Quality [metadata] -type = quality setting_version = 4 -material = fabtotum_pla +type = quality quality_type = high weight = 1 +material = fabtotum_pla [values] adhesion_type = skirt @@ -21,4 +21,3 @@ cool_fan_speed_max = 100 cool_fan_speed_min = 100 cool_min_layer_time = 5 cool_min_speed = 20 - diff --git a/resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg b/resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg index 5b5125c4e5..16afc56cf1 100644 --- a/resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg +++ b/resources/quality/fabtotum/fabtotum_pla_normal.inst.cfg @@ -4,11 +4,11 @@ definition = fabtotum name = Normal Quality [metadata] -type = quality setting_version = 4 -material = fabtotum_pla +type = quality quality_type = normal weight = 0 +material = fabtotum_pla [values] adhesion_type = skirt @@ -21,4 +21,3 @@ cool_fan_speed_max = 100 cool_fan_speed_min = 100 cool_min_layer_time = 5 cool_min_speed = 20 - diff --git a/resources/quality/gmax15plus/gmax15plus_pla_dual_normal.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_dual_normal.inst.cfg index 74d3d1c134..67b5cb49b8 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_dual_normal.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_dual_normal.inst.cfg @@ -4,10 +4,10 @@ name = gMax 1.5+ Dual Normal Layers definition = gmax15plus_dual [metadata] +setting_version = 4 type = quality quality_type = normal weight = -1 -setting_version = 4 global_quality = True [values] diff --git a/resources/quality/gmax15plus/gmax15plus_pla_dual_thick.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_dual_thick.inst.cfg index 32191f36d8..376e3241ff 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_dual_thick.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_dual_thick.inst.cfg @@ -4,10 +4,10 @@ name = gMax 1.5+ Dual Thick Layers definition = gmax15plus_dual [metadata] +setting_version = 4 type = quality quality_type = course weight = -2 -setting_version = 4 global_quality = True [values] diff --git a/resources/quality/gmax15plus/gmax15plus_pla_dual_thin.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_dual_thin.inst.cfg index 5906875a3a..1c0cabd84f 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_dual_thin.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_dual_thin.inst.cfg @@ -4,10 +4,10 @@ name = gMax 1.5+ Dual Thin Layers definition = gmax15plus_dual [metadata] +setting_version = 4 type = quality quality_type = high weight = 0 -setting_version = 4 global_quality = True [values] diff --git a/resources/quality/gmax15plus/gmax15plus_pla_dual_very_thick.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_dual_very_thick.inst.cfg index a94a621a88..d292284531 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_dual_very_thick.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_dual_very_thick.inst.cfg @@ -4,10 +4,10 @@ name = gMax 1.5+ Dual Very Thick Layers definition = gmax15plus_dual [metadata] +setting_version = 4 type = quality quality_type = extra_course weight = -3 -setting_version = 4 global_quality = True [values] diff --git a/resources/quality/gmax15plus/gmax15plus_pla_normal.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_normal.inst.cfg index a6513cba80..3baad3a928 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_normal.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_normal.inst.cfg @@ -4,10 +4,10 @@ name = gMax 1.5+ Normal Layers definition = gmax15plus [metadata] +setting_version = 4 type = quality quality_type = normal weight = -1 -setting_version = 4 global_quality = True [values] @@ -58,5 +58,3 @@ top_thickness = 1 bottom_layers = 2 wall_line_count = 2 z_seam_corner = z_seam_corner_none - - diff --git a/resources/quality/gmax15plus/gmax15plus_pla_thick.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_thick.inst.cfg index be0d99a413..856ab7d3db 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_thick.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_thick.inst.cfg @@ -4,10 +4,10 @@ name = gMax 1.5+ Thick Layers definition = gmax15plus [metadata] +setting_version = 4 type = quality quality_type = course weight = -2 -setting_version = 4 global_quality = True [values] @@ -57,4 +57,4 @@ top_layers = 3 top_thickness = 1 bottom_layers = 2 wall_line_count = 2 -z_seam_corner = z_seam_corner_none \ No newline at end of file +z_seam_corner = z_seam_corner_none diff --git a/resources/quality/gmax15plus/gmax15plus_pla_thin.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_thin.inst.cfg index 7069db6dd6..46f41e195f 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_thin.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_thin.inst.cfg @@ -4,10 +4,10 @@ name = gMax 1.5+ Thin Layers definition = gmax15plus [metadata] +setting_version = 4 type = quality quality_type = high weight = 0 -setting_version = 4 global_quality = True [values] @@ -57,4 +57,4 @@ top_layers = 5 top_thickness = 1 bottom_layers = 3 wall_line_count = 2 -z_seam_corner = z_seam_corner_none \ No newline at end of file +z_seam_corner = z_seam_corner_none diff --git a/resources/quality/gmax15plus/gmax15plus_pla_very_thick.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_very_thick.inst.cfg index 88d03ee77f..938f21a13d 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_very_thick.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_very_thick.inst.cfg @@ -4,10 +4,10 @@ name = gMax 1.5+ Very Thick Layers definition = gmax15plus [metadata] +setting_version = 4 type = quality quality_type = extra_course weight = -3 -setting_version = 4 global_quality = True [values] @@ -56,4 +56,4 @@ top_layers = 3 top_thickness = 1 bottom_layers = 2 wall_line_count = 2 -z_seam_corner = z_seam_corner_none \ No newline at end of file +z_seam_corner = z_seam_corner_none diff --git a/resources/quality/high.inst.cfg b/resources/quality/high.inst.cfg index d4333c90da..9ef90181a3 100644 --- a/resources/quality/high.inst.cfg +++ b/resources/quality/high.inst.cfg @@ -4,11 +4,11 @@ name = Extra Fine definition = fdmprinter [metadata] +setting_version = 4 type = quality quality_type = high -global_quality = True weight = 1 -setting_version = 4 +global_quality = True [values] layer_height = 0.06 diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg index e36286c6ae..e5b3aed52b 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = imade3d_jellybox [metadata] -type = quality -material = generic_petg_imade3d_jellybox_0.4_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_petg +variant = 0.4 mm [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg index 3240bad98b..e7f2d5d60a 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = imade3d_jellybox [metadata] -type = quality -material = generic_petg_imade3d_jellybox_0.4_mm_2-fans -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_petg +variant = 0.4 mm 2-fans [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg index 2790a5a742..4d122f1ac2 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg @@ -4,11 +4,12 @@ name = Medium definition = imade3d_jellybox [metadata] -type = quality -material = generic_petg_imade3d_jellybox_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_petg +variant = 0.4 mm [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg index 14f141f0bf..9646b0bb5f 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg @@ -4,11 +4,12 @@ name = Medium definition = imade3d_jellybox [metadata] -type = quality -material = generic_petg_imade3d_jellybox_0.4_mm_2-fans -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_petg +variant = 0.4 mm 2-fans [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg index 842ec618e0..8ecfa927a7 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = imade3d_jellybox [metadata] -type = quality -material = generic_pla_imade3d_jellybox_0.4_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_pla +variant = 0.4 mm [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg index 17e085d84d..52c7df70f3 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg @@ -4,11 +4,12 @@ name = Coarse definition = imade3d_jellybox [metadata] -type = quality -material = generic_pla_imade3d_jellybox_0.4_mm_2-fans -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_pla +variant = 0.4 mm 2-fans [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg index a4b44f47f6..a48dbe2f81 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = imade3d_jellybox [metadata] -type = quality -material = generic_pla_imade3d_jellybox_0.4_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla +variant = 0.4 mm [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg index 962b3c9ad4..4707337611 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = imade3d_jellybox [metadata] -type = quality -material = generic_pla_imade3d_jellybox_0.4_mm_2-fans -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla +variant = 0.4 mm 2-fans [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg index 952b16ecf8..2f5a0f33a8 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg @@ -4,11 +4,12 @@ name = Medium definition = imade3d_jellybox [metadata] -type = quality -material = generic_pla_imade3d_jellybox_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pla +variant = 0.4 mm [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg index bd70d105a4..f0451fc9be 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg @@ -4,11 +4,12 @@ name = Medium definition = imade3d_jellybox [metadata] -type = quality -material = generic_pla_imade3d_jellybox_0.4_mm_2-fans -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pla +variant = 0.4 mm 2-fans [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg index a9d0679612..179623153a 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg @@ -4,11 +4,12 @@ name = UltraFine definition = imade3d_jellybox [metadata] -type = quality -material = generic_pla_imade3d_jellybox_0.4_mm -weight = 2 -quality_type = ultrahigh setting_version = 4 +type = quality +quality_type = ultrahigh +weight = 2 +material = generic_pla +variant = 0.4 mm [values] adhesion_type = skirt diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine_2-fans.inst.cfg index 097e1fc76a..b35db0fde6 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine_2-fans.inst.cfg @@ -4,11 +4,12 @@ name = UltraFine definition = imade3d_jellybox [metadata] -type = quality -material = generic_pla_imade3d_jellybox_0.4_mm_2-fans -weight = 2 -quality_type = ultrahigh setting_version = 4 +type = quality +quality_type = ultrahigh +weight = 2 +material = generic_pla +variant = 0.4 mm 2-fans [values] adhesion_type = skirt diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_draft.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_draft.inst.cfg index 5401ec7bd6..add07c797a 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_draft.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_draft.inst.cfg @@ -4,11 +4,11 @@ name = Draft definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = coarse weight = -3 material = generic_abs -quality_type = coarse -setting_version = 4 [values] layer_height = 0.35 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_extra_fine.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_extra_fine.inst.cfg index aea8fc9535..8d31e439e1 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_extra_fine.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_extra_fine.inst.cfg @@ -4,11 +4,11 @@ name = Extra Fine definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = high weight = 1 material = generic_abs -quality_type = high -setting_version = 4 [values] layer_height = 0.06 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_fine.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_fine.inst.cfg index 24adbd9f6c..936e9f8cd8 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_fine.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_fine.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = normal weight = 0 material = generic_abs -quality_type = normal -setting_version = 4 [values] layer_height = 0.1 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_low.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_low.inst.cfg index 98d2475633..8f48616dbf 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_low.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_low.inst.cfg @@ -4,11 +4,11 @@ name = Low definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = draft weight = -2 material = generic_abs -quality_type = draft -setting_version = 4 [values] layer_height = 0.2 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg index ab2e9dabbc..440575a066 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = low weight = -1 material = generic_abs -quality_type = low -setting_version = 4 [values] layer_height = 0.15 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_draft.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_draft.inst.cfg index f868ab40fc..d9ea0e6850 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_draft.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_draft.inst.cfg @@ -4,11 +4,11 @@ name = Draft definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = coarse weight = -3 material = generic_pla -quality_type = coarse -setting_version = 4 [values] layer_height = 0.35 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_extra_fine.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_extra_fine.inst.cfg index e907f7ccaf..b1775b994f 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_extra_fine.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_extra_fine.inst.cfg @@ -4,11 +4,11 @@ name = Extra Fine definition = kemiq_q2_beta [metadata] -type = quality -material = generic_pla -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla [values] layer_height = 0.06 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_fine.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_fine.inst.cfg index 841023d532..cf7e070cb8 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_fine.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_fine.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = normal weight = 0 material = generic_pla -quality_type = normal -setting_version = 4 [values] layer_height = 0.1 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_low.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_low.inst.cfg index ca874c6bce..8b40fabb7b 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_low.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_low.inst.cfg @@ -4,11 +4,11 @@ name = Low definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = draft weight = -2 material = generic_pla -quality_type = draft -setting_version = 4 [values] layer_height = 0.2 diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg index fcfbe72b24..12ca8ed571 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = kemiq_q2_beta [metadata] +setting_version = 4 type = quality +quality_type = low weight = -1 material = generic_pla -quality_type = low -setting_version = 4 [values] layer_height = 0.15 diff --git a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_draft.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_draft.inst.cfg index 009af9b87b..fcda1b081e 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_draft.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_draft.inst.cfg @@ -4,11 +4,11 @@ name = Draft definition = kemiq_q2_gama [metadata] +setting_version = 4 type = quality +quality_type = coarse weight = -3 material = generic_pla -quality_type = coarse -setting_version = 4 [values] layer_height = 0.35 diff --git a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_extra_fine.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_extra_fine.inst.cfg index 447e3b012d..52e5e8df98 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_extra_fine.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_extra_fine.inst.cfg @@ -4,11 +4,11 @@ name = Extra Fine definition = kemiq_q2_gama [metadata] -type = quality -material = generic_pla -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla [values] layer_height = 0.06 diff --git a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_fine.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_fine.inst.cfg index 80b2375108..b3ea5b8967 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_fine.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_fine.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = kemiq_q2_gama [metadata] +setting_version = 4 type = quality +quality_type = normal weight = 0 material = generic_pla -quality_type = normal -setting_version = 4 [values] layer_height = 0.1 diff --git a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_low.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_low.inst.cfg index e30c52f4e6..08a3db0b1f 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_low.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_low.inst.cfg @@ -4,11 +4,11 @@ name = Low definition = kemiq_q2_gama [metadata] +setting_version = 4 type = quality +quality_type = draft weight = -2 material = generic_pla -quality_type = draft -setting_version = 4 [values] layer_height = 0.2 diff --git a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg index 31bdaa51bc..51368f1b1b 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = kemiq_q2_gama [metadata] +setting_version = 4 type = quality +quality_type = low weight = -1 material = generic_pla -quality_type = low -setting_version = 4 [values] layer_height = 0.15 diff --git a/resources/quality/low.inst.cfg b/resources/quality/low.inst.cfg index e92490722d..25cb71e2bc 100644 --- a/resources/quality/low.inst.cfg +++ b/resources/quality/low.inst.cfg @@ -4,11 +4,11 @@ name = Low Quality definition = fdmprinter [metadata] +setting_version = 4 type = quality quality_type = low -global_quality = True weight = -1 -setting_version = 4 +global_quality = True [values] infill_sparse_density = 10 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg index 19cc9fd00d..084094f5e7 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg @@ -4,12 +4,12 @@ name = Fast definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_abs_175 weight = -2 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg index 5677a0d58d..1e3419dc7e 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg @@ -4,12 +4,12 @@ name = Normal definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_abs_175 weight = -1 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg index 7798b3f545..0758cd6630 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg @@ -4,12 +4,12 @@ name = Finer definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_abs_175 weight = 1 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg index c87c66c813..da347ac13c 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg @@ -4,12 +4,12 @@ name = Fine definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_abs_175 weight = 0 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg index e6e3cfcd6c..cc25431062 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg @@ -4,12 +4,12 @@ name = Lowest Quality Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_abs_175 weight = -5 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg index fb08013809..2b7f830b3f 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg @@ -4,12 +4,12 @@ name = Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_abs_175 weight = -3 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg index 385d852688..73abddc696 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg @@ -4,12 +4,12 @@ name = Ultra Fine definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = ultra -material = generic_abs_175 weight = 2 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg index 7026391fb6..22adb14e71 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg @@ -4,12 +4,12 @@ name = Low Detail Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_abs_175 weight = -4 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg index 54be6ecbcc..89d7f2f2ec 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg @@ -4,10 +4,10 @@ name = M1 Quality definition = malyan_m200 [metadata] -type = quality -weight = 2 -quality_type = fine setting_version = 4 +type = quality +quality_type = fine +weight = 2 [values] layer_height = 0.04375 diff --git a/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg index 568dd796f3..555b280c1c 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg @@ -4,10 +4,10 @@ name = M2 Quality definition = malyan_m200 [metadata] -type = quality -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 [values] layer_height = 0.0875 diff --git a/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg index 1dc436502b..7829f33086 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg @@ -4,10 +4,10 @@ name = M3 Quality definition = malyan_m200 [metadata] -type = quality -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 [values] layer_height = 0.13125 diff --git a/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg index 314a8acd83..e6fd4c9368 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg @@ -4,11 +4,11 @@ name = M4 Quality definition = malyan_m200 [metadata] -type = quality -weight = -1 -quality_type = fast -global_quality = true setting_version = 4 +type = quality +quality_type = fast +weight = -1 +global_quality = true [values] layer_height = 0.175 diff --git a/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg index a7fedb7e04..143693dbc4 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg @@ -4,10 +4,10 @@ name = M5 Quality definition = malyan_m200 [metadata] -type = quality -weight = -2 -quality_type = faster setting_version = 4 +type = quality +quality_type = faster +weight = -2 [values] layer_height = 0.21875 diff --git a/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg index 441abc3070..3dc33a81a0 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg @@ -4,10 +4,10 @@ name = M6 Quality definition = malyan_m200 [metadata] -type = quality -weight = -3 -quality_type = draft setting_version = 4 +type = quality +quality_type = draft +weight = -3 [values] layer_height = 0.2625 diff --git a/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg index 2588838174..c7d6911a67 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg @@ -4,10 +4,10 @@ name = M7 Quality definition = malyan_m200 [metadata] -type = quality -weight = -4 -quality_type = turbo setting_version = 4 +type = quality +quality_type = turbo +weight = -4 [values] layer_height = 0.30625 diff --git a/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg index 800b6104d9..5d14204a1e 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg @@ -4,11 +4,11 @@ name = M8 Quality definition = malyan_m200 [metadata] -type = quality -weight = -5 -quality_type = hyper -global_quality = true setting_version = 4 +type = quality +quality_type = hyper +weight = -5 +global_quality = true [values] layer_height = 0.35 diff --git a/resources/quality/malyan_m200/malyan_m200_global_Draft_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_Draft_Quality.inst.cfg index d3104caa87..fd999cc6c7 100644 --- a/resources/quality/malyan_m200/malyan_m200_global_Draft_Quality.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_global_Draft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Fast definition = malyan_m200 [metadata] -type = quality -weight = -2 -quality_type = draft -global_quality = True setting_version = 4 +type = quality +quality_type = draft +weight = -2 +global_quality = True [values] layer_height = 0.21875 diff --git a/resources/quality/malyan_m200/malyan_m200_global_Fast_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_Fast_Quality.inst.cfg index aec535bd71..8027a7b01a 100644 --- a/resources/quality/malyan_m200/malyan_m200_global_Fast_Quality.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_global_Fast_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = malyan_m200 [metadata] -type = quality -weight = -1 -quality_type = fast -global_quality = True setting_version = 4 +type = quality +quality_type = fast +weight = -1 +global_quality = True [values] layer_height = 0.175 diff --git a/resources/quality/malyan_m200/malyan_m200_global_High_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_High_Quality.inst.cfg index ca202862a2..01fea67382 100644 --- a/resources/quality/malyan_m200/malyan_m200_global_High_Quality.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_global_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Finer definition = malyan_m200 [metadata] -type = quality -weight = 1 -quality_type = high -global_quality = True setting_version = 4 +type = quality +quality_type = high +weight = 1 +global_quality = True [values] layer_height = 0.0875 diff --git a/resources/quality/malyan_m200/malyan_m200_global_Normal_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_Normal_Quality.inst.cfg index 7076718903..a705d187f1 100644 --- a/resources/quality/malyan_m200/malyan_m200_global_Normal_Quality.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_global_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = malyan_m200 [metadata] -type = quality -weight = 0 -quality_type = normal -global_quality = True setting_version = 4 +type = quality +quality_type = normal +weight = 0 +global_quality = True [values] layer_height = 0.13125 diff --git a/resources/quality/malyan_m200/malyan_m200_global_SuperDraft_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_SuperDraft_Quality.inst.cfg index 7dfbdb5886..92f1eb2286 100644 --- a/resources/quality/malyan_m200/malyan_m200_global_SuperDraft_Quality.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_global_SuperDraft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Lowest Quality Draft definition = malyan_m200 [metadata] -type = quality -weight = -5 -quality_type = superdraft -global_quality = True setting_version = 4 +type = quality +quality_type = superdraft +weight = -5 +global_quality = True [values] layer_height = 0.35 diff --git a/resources/quality/malyan_m200/malyan_m200_global_ThickerDraft_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_ThickerDraft_Quality.inst.cfg index 2fbf82b128..246443503e 100644 --- a/resources/quality/malyan_m200/malyan_m200_global_ThickerDraft_Quality.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_global_ThickerDraft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Draft definition = malyan_m200 [metadata] -type = quality -weight = -3 -quality_type = thickerdraft -global_quality = True setting_version = 4 +type = quality +quality_type = thickerdraft +weight = -3 +global_quality = True [values] layer_height = 0.2625 diff --git a/resources/quality/malyan_m200/malyan_m200_global_Ultra_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_Ultra_Quality.inst.cfg index 90e589cca5..0bbe46be4e 100644 --- a/resources/quality/malyan_m200/malyan_m200_global_Ultra_Quality.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_global_Ultra_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Ultra Fine definition = malyan_m200 [metadata] -type = quality -weight = 2 -quality_type = ultra -global_quality = True setting_version = 4 +type = quality +quality_type = ultra +weight = 2 +global_quality = True [values] layer_height = 0.04375 diff --git a/resources/quality/malyan_m200/malyan_m200_global_VeryDraft_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_VeryDraft_Quality.inst.cfg index 1210ee214b..5cc85b9bc8 100644 --- a/resources/quality/malyan_m200/malyan_m200_global_VeryDraft_Quality.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_global_VeryDraft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Low Detail Draft definition = malyan_m200 [metadata] -type = quality -weight = -4 -quality_type = verydraft -global_quality = True setting_version = 4 +type = quality +quality_type = verydraft +weight = -4 +global_quality = True [values] layer_height = 0.30625 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg index aef83471ba..9d3e31cb16 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg @@ -4,8 +4,8 @@ name = Fast definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_petg_175 weight = -2 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg index 3c7fc2c239..9d68dee0bf 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg @@ -4,8 +4,8 @@ name = Normal definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_petg_175 weight = -1 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg index eb1654eae3..63aefb027b 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg @@ -4,8 +4,8 @@ name = Finer definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_petg_175 weight = 1 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg index 53e60d2d62..402c87886c 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg @@ -4,8 +4,8 @@ name = Fine definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_petg_175 weight = 0 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg index d2a96386ae..9029b4508a 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg @@ -4,8 +4,8 @@ name = Lowest Quality Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_petg_175 weight = -5 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg index e2f37ae43b..e9b440e1f6 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg @@ -4,8 +4,8 @@ name = Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_petg_175 weight = -3 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg index 0fa89f2569..1517f7d340 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg @@ -4,8 +4,8 @@ name = Ultra Fine definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = ultra -material = generic_petg_175 weight = 2 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg index 84bedf5c14..3d3346eac5 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg @@ -4,8 +4,8 @@ name = Low Detail Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_petg_175 weight = -4 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg index 4f221eceb7..b05a336aee 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg @@ -4,12 +4,12 @@ name = Fast definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pla_175 weight = -2 -setting_version = 4 +material = generic_pla_175 [values] material_bed_temperature = 60 -material_bed_temperature_layer_0 = 60 \ No newline at end of file +material_bed_temperature_layer_0 = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg index 3097fe055a..e45fe903e2 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg @@ -4,12 +4,12 @@ name = Normal definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_pla_175 weight = -1 -setting_version = 4 +material = generic_pla_175 [values] material_bed_temperature = 60 -material_bed_temperature_layer_0 = 60 \ No newline at end of file +material_bed_temperature_layer_0 = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg index 062c120ad0..adeae8ae33 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg @@ -4,12 +4,12 @@ name = Finer definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pla_175 weight = 1 -setting_version = 4 +material = generic_pla_175 [values] material_bed_temperature = 60 -material_bed_temperature_layer_0 = 60 \ No newline at end of file +material_bed_temperature_layer_0 = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg index e01141ed9e..0c0f9fcb5a 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg @@ -4,12 +4,12 @@ name = Fine definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pla_175 weight = 0 -setting_version = 4 +material = generic_pla_175 [values] material_bed_temperature = 60 -material_bed_temperature_layer_0 = 60 \ No newline at end of file +material_bed_temperature_layer_0 = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg index 53eb4380eb..e5e5d6d40d 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg @@ -4,12 +4,12 @@ name = Lowest Quality Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_pla_175 weight = -5 -setting_version = 4 +material = generic_pla_175 [values] material_bed_temperature = 60 -material_bed_temperature_layer_0 = 60 \ No newline at end of file +material_bed_temperature_layer_0 = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg index 32d2b419bc..95323181d7 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg @@ -4,12 +4,12 @@ name = Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_pla_175 weight = -3 -setting_version = 4 +material = generic_pla_175 [values] material_bed_temperature = 60 -material_bed_temperature_layer_0 = 60 \ No newline at end of file +material_bed_temperature_layer_0 = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg index 3865059254..8b0005e60d 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg @@ -4,12 +4,12 @@ name = Ultra Fine definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = ultra -material = generic_pla_175 weight = 2 -setting_version = 4 +material = generic_pla_175 [values] material_bed_temperature = 60 -material_bed_temperature_layer_0 = 60 \ No newline at end of file +material_bed_temperature_layer_0 = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg index a624c056be..cc8ef3c9cd 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg @@ -4,12 +4,12 @@ name = Low Detail Draft definition = malyan_m200 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_pla_175 weight = -4 -setting_version = 4 +material = generic_pla_175 [values] material_bed_temperature = 60 -material_bed_temperature_layer_0 = 60 \ No newline at end of file +material_bed_temperature_layer_0 = 60 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg index a63256573a..b75f20a1a6 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg @@ -4,12 +4,12 @@ name = Fast definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_abs_175 weight = -2 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg index 49f4486596..e06394dea5 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg @@ -4,12 +4,12 @@ name = Normal definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_abs_175 weight = -1 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg index eab16a8e2b..7249fb039c 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg @@ -4,12 +4,12 @@ name = Finer definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_abs_175 weight = 1 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg index 03aeb4067b..a0237b3af2 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg @@ -4,12 +4,12 @@ name = Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_abs_175 weight = 0 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg index 148f53ba73..c858d341d2 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg @@ -4,12 +4,12 @@ name = Lowest Quality Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_abs_175 weight = -5 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg index e2ad71a360..9996338c79 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg @@ -4,12 +4,12 @@ name = Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_abs_175 weight = -3 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg index 7ebdf80baf..5d94f941c8 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg @@ -4,12 +4,12 @@ name = Ultra Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_abs_175 weight = 2 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg index 9965ae8bcf..0635565027 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg @@ -4,12 +4,12 @@ name = Low Detail Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_abs_175 weight = -4 -setting_version = 4 +material = generic_abs_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Draft_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Draft_Quality.inst.cfg index b7d0faa2c7..d8aa07b779 100644 --- a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Draft_Quality.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Draft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Fast definition = monoprice_select_mini_v2 [metadata] -type = quality -weight = -2 -quality_type = draft -global_quality = True setting_version = 4 +type = quality +quality_type = draft +weight = -2 +global_quality = True [values] layer_height = 0.21875 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Fast_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Fast_Quality.inst.cfg index f7f338e4c9..a0620d532a 100644 --- a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Fast_Quality.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Fast_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = monoprice_select_mini_v2 [metadata] -type = quality -weight = -1 -quality_type = fast -global_quality = True setting_version = 4 +type = quality +quality_type = fast +weight = -1 +global_quality = True [values] layer_height = 0.175 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_High_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_High_Quality.inst.cfg index 4a37a1afd8..7237dbc42a 100644 --- a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_High_Quality.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Finer definition = monoprice_select_mini_v2 [metadata] -type = quality -weight = 1 -quality_type = high -global_quality = True setting_version = 4 +type = quality +quality_type = high +weight = 1 +global_quality = True [values] layer_height = 0.0875 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Normal_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Normal_Quality.inst.cfg index b8e545adcf..bcb360d310 100644 --- a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Normal_Quality.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = monoprice_select_mini_v2 [metadata] -type = quality -weight = 0 -quality_type = normal -global_quality = True setting_version = 4 +type = quality +quality_type = normal +weight = 0 +global_quality = True [values] layer_height = 0.13125 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_SuperDraft_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_SuperDraft_Quality.inst.cfg index 0ef9db5875..81954f86e7 100644 --- a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_SuperDraft_Quality.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_SuperDraft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Lowest Quality Draft definition = monoprice_select_mini_v2 [metadata] -type = quality -weight = -5 -quality_type = superdraft -global_quality = True setting_version = 4 +type = quality +quality_type = superdraft +weight = -5 +global_quality = True [values] layer_height = 0.35 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_ThickerDraft_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_ThickerDraft_Quality.inst.cfg index 4dd3a7aafe..1fe7ee22ab 100644 --- a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_ThickerDraft_Quality.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_ThickerDraft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Draft definition = monoprice_select_mini_v2 [metadata] -type = quality -weight = -3 -quality_type = thickerdraft -global_quality = True setting_version = 4 +type = quality +quality_type = thickerdraft +weight = -3 +global_quality = True [values] layer_height = 0.2625 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Ultra_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Ultra_Quality.inst.cfg index 337f0d06bc..89e2f43dad 100644 --- a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Ultra_Quality.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Ultra_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Ultra Fine definition = monoprice_select_mini_v2 [metadata] -type = quality -weight = 2 -quality_type = ultra -global_quality = True setting_version = 4 +type = quality +quality_type = ultra +weight = 2 +global_quality = True [values] layer_height = 0.04375 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_VeryDraft_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_VeryDraft_Quality.inst.cfg index e884077069..c7fc09d9e8 100644 --- a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_VeryDraft_Quality.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_VeryDraft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Low Detail Draft definition = monoprice_select_mini_v2 [metadata] -type = quality -weight = -4 -quality_type = verydraft -global_quality = True setting_version = 4 +type = quality +quality_type = verydraft +weight = -4 +global_quality = True [values] layer_height = 0.30625 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg index 4a03c17a63..42e0d69476 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg @@ -4,8 +4,8 @@ name = Fast definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_nylon_175 weight = -2 -setting_version = 4 \ No newline at end of file +material = generic_nylon_175 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg index 1c04f77b8b..e62e654fc3 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg @@ -4,8 +4,8 @@ name = Normal definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_nylon_175 weight = -1 -setting_version = 4 \ No newline at end of file +material = generic_nylon_175 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg index d57516598a..cca4b98678 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg @@ -4,8 +4,8 @@ name = Finer definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_nylon_175 weight = 1 -setting_version = 4 \ No newline at end of file +material = generic_nylon_175 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg index 308ea86311..56c28e372f 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg @@ -4,8 +4,8 @@ name = Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_nylon_175 weight = 0 -setting_version = 4 \ No newline at end of file +material = generic_nylon_175 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg index db4f3ca907..14375b3c41 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg @@ -4,8 +4,8 @@ name = Lowest Quality Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_nylon_175 weight = -5 -setting_version = 4 \ No newline at end of file +material = generic_nylon_175 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg index 9a1afc0e48..01c45f2401 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg @@ -4,8 +4,8 @@ name = Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_nylon_175 weight = -3 -setting_version = 4 \ No newline at end of file +material = generic_nylon_175 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg index 3453671a72..205915cd7c 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg @@ -4,8 +4,8 @@ name = Ultra Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = ultra -material = generic_nylon_175 weight = 2 -setting_version = 4 \ No newline at end of file +material = generic_nylon_175 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg index ee2531fc4e..124121c35c 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg @@ -4,8 +4,8 @@ name = Low Detail Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_nylon_175 weight = -4 -setting_version = 4 \ No newline at end of file +material = generic_nylon_175 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg index aa5fc7844d..ae69e5fe46 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg @@ -4,12 +4,12 @@ name = Fast definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pc_175 weight = -2 -setting_version = 4 +material = generic_pc_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg index 232c4ab6f3..8e78ee7827 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg @@ -4,12 +4,12 @@ name = Normal definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_pc_175 weight = -1 -setting_version = 4 +material = generic_pc_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg index aa9da322fb..761859e1a5 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg @@ -4,12 +4,12 @@ name = Finer definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pc_175 weight = 1 -setting_version = 4 +material = generic_pc_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg index 145b21221b..91575da188 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg @@ -4,12 +4,12 @@ name = Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pc_175 weight = 0 -setting_version = 4 +material = generic_pc_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg index b6e53bda62..9295b6b6d1 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg @@ -4,12 +4,12 @@ name = Lowest Quality Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_pc_175 weight = -5 -setting_version = 4 +material = generic_pc_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg index 055228ab13..02ba4841e8 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg @@ -4,12 +4,12 @@ name = Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_pc_175 weight = -3 -setting_version = 4 +material = generic_pc_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg index a3e99b998e..8b3833371b 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg @@ -4,12 +4,12 @@ name = Ultra Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = ultra -material = generic_pc_175 weight = 2 -setting_version = 4 +material = generic_pc_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg index 73f5a2f2c9..f0ada1c6a8 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg @@ -4,12 +4,12 @@ name = Low Detail Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_pc_175 weight = -4 -setting_version = 4 +material = generic_pc_175 [values] material_bed_temperature = 70 -material_bed_temperature_layer_0 = 70 \ No newline at end of file +material_bed_temperature_layer_0 = 70 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg index 8a33e03310..9278a6920a 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg @@ -4,8 +4,8 @@ name = Fast definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_petg_175 weight = -2 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg index fb084fa08e..503362f755 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg @@ -4,8 +4,8 @@ name = Normal definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_petg_175 weight = -1 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg index 16891f6f43..3d8ae1d5d0 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg @@ -4,8 +4,8 @@ name = Finer definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_petg_175 weight = 1 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg index bb2f0b47a8..66c69b237e 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg @@ -4,8 +4,8 @@ name = Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_petg_175 weight = 0 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg index 78ca1b6b7a..2b517e1521 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg @@ -4,8 +4,8 @@ name = Lowest Quality Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_petg_175 weight = -5 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg index 69606ff913..969bd71f1a 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg @@ -4,8 +4,8 @@ name = Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_petg_175 weight = -3 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg index 7c5ac599c8..ef97518e2a 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg @@ -4,8 +4,8 @@ name = Ultra Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = ultra -material = generic_petg_175 weight = 2 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg index ed0c2510f5..7d338616dd 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg @@ -4,8 +4,8 @@ name = Low Detail Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_petg_175 weight = -4 -setting_version = 4 \ No newline at end of file +material = generic_petg_175 diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg index 04a955cf6c..b3ccc9f82b 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg @@ -4,8 +4,8 @@ name = Fast definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pla_175 weight = -2 -setting_version = 4 \ No newline at end of file +material = generic_pla_175 diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg index 6efc0935e2..67ed46db58 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg @@ -4,8 +4,8 @@ name = Normal definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_pla_175 weight = 0 -setting_version = 4 \ No newline at end of file +material = generic_pla_175 diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg index 8fe2371e5d..17b8f7a8b7 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg @@ -4,8 +4,8 @@ name = Finer definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pla_175 weight = 0 -setting_version = 4 \ No newline at end of file +material = generic_pla_175 diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg index 01351154c4..7852138707 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg @@ -4,8 +4,8 @@ name = Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pla_175 weight = 0 -setting_version = 4 \ No newline at end of file +material = generic_pla_175 diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg index adfced9787..aa46df06b6 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg @@ -4,8 +4,8 @@ name = Lowest Quality Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_pla_175 weight = -5 -setting_version = 4 \ No newline at end of file +material = generic_pla_175 diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg index f4522c9778..39cf607b25 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg @@ -4,8 +4,8 @@ name = Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = thickerdraft -material = generic_pla_175 weight = -3 -setting_version = 4 \ No newline at end of file +material = generic_pla_175 diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg index 2fa8eb7f81..18d93dac2d 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg @@ -4,8 +4,8 @@ name = Ultra Fine definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality quality_type = ultra -material = generic_pla_175 weight = 2 -setting_version = 4 \ No newline at end of file +material = generic_pla_175 diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg index e59cf4a490..e8fff16371 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg @@ -4,8 +4,8 @@ name = Low Detail Draft definition = monoprice_select_mini_v2 [metadata] +setting_version = 4 type = quality -quality_type = verydraft material = generic_pla_175 weight = 0 -setting_version = 4 \ No newline at end of file +quality_type = verydraft diff --git a/resources/quality/normal.inst.cfg b/resources/quality/normal.inst.cfg index 9fb7b238cd..2eeb91324f 100644 --- a/resources/quality/normal.inst.cfg +++ b/resources/quality/normal.inst.cfg @@ -4,10 +4,10 @@ name = Fine definition = fdmprinter [metadata] +setting_version = 4 type = quality quality_type = normal -global_quality = True weight = 0 -setting_version = 4 +global_quality = True [values] diff --git a/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg index ae8a377116..208fa453fe 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_high.inst.cfg @@ -4,10 +4,10 @@ name = Extra Fine definition = peopoly_moai [metadata] -type = quality -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 [values] infill_sparse_density = 70 diff --git a/resources/quality/peopoly_moai/peopoly_moai_max.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_max.inst.cfg index 07ab7e364b..cc764009a9 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_max.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_max.inst.cfg @@ -4,10 +4,10 @@ name = Maximum Quality definition = peopoly_moai [metadata] -type = quality -weight = 2 -quality_type = extra_high setting_version = 4 +type = quality +quality_type = extra_high +weight = 2 [values] infill_sparse_density = 70 diff --git a/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg b/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg index e0d2f7d818..2baa70be1e 100644 --- a/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg +++ b/resources/quality/peopoly_moai/peopoly_moai_normal.inst.cfg @@ -4,10 +4,10 @@ name = Fine definition = peopoly_moai [metadata] -type = quality -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 [values] infill_sparse_density = 70 diff --git a/resources/quality/tevo_blackwidow/tevo_blackwidow_draft.inst.cfg b/resources/quality/tevo_blackwidow/tevo_blackwidow_draft.inst.cfg index 082b7dded7..2536cbba12 100644 --- a/resources/quality/tevo_blackwidow/tevo_blackwidow_draft.inst.cfg +++ b/resources/quality/tevo_blackwidow/tevo_blackwidow_draft.inst.cfg @@ -4,10 +4,10 @@ name = Draft definition = tevo_blackwidow [metadata] +setting_version = 4 type = quality quality_type = draft weight = -2 -setting_version = 4 [values] brim_width = 4.0 @@ -30,4 +30,4 @@ support_type = everywhere support_use_towers = False support_xy_distance = 0.7 top_bottom_thickness = 1.2 -wall_thickness = 1.2 \ No newline at end of file +wall_thickness = 1.2 diff --git a/resources/quality/tevo_blackwidow/tevo_blackwidow_high.inst.cfg b/resources/quality/tevo_blackwidow/tevo_blackwidow_high.inst.cfg index 79d020463f..29599eaebc 100644 --- a/resources/quality/tevo_blackwidow/tevo_blackwidow_high.inst.cfg +++ b/resources/quality/tevo_blackwidow/tevo_blackwidow_high.inst.cfg @@ -4,10 +4,10 @@ name = High definition = tevo_blackwidow [metadata] +setting_version = 4 type = quality quality_type = high weight = 1 -setting_version = 4 [values] brim_width = 4.0 @@ -30,4 +30,4 @@ support_type = everywhere support_use_towers = False support_xy_distance = 0.7 top_bottom_thickness = 1.2 -wall_thickness = 1.2 \ No newline at end of file +wall_thickness = 1.2 diff --git a/resources/quality/tevo_blackwidow/tevo_blackwidow_normal.inst.cfg b/resources/quality/tevo_blackwidow/tevo_blackwidow_normal.inst.cfg index 2982c44d3d..98dbf5a79a 100644 --- a/resources/quality/tevo_blackwidow/tevo_blackwidow_normal.inst.cfg +++ b/resources/quality/tevo_blackwidow/tevo_blackwidow_normal.inst.cfg @@ -4,10 +4,10 @@ name = Normal definition = tevo_blackwidow [metadata] +setting_version = 4 type = quality quality_type = normal weight = 0 -setting_version = 4 [values] brim_width = 4.0 @@ -30,4 +30,4 @@ support_type = everywhere support_use_towers = False support_xy_distance = 0.7 top_bottom_thickness = 1.2 -wall_thickness = 1.2 \ No newline at end of file +wall_thickness = 1.2 diff --git a/resources/quality/ultimaker2/um2_draft.inst.cfg b/resources/quality/ultimaker2/um2_draft.inst.cfg index 4fe3f51e20..821c864bb8 100644 --- a/resources/quality/ultimaker2/um2_draft.inst.cfg +++ b/resources/quality/ultimaker2/um2_draft.inst.cfg @@ -4,10 +4,10 @@ name = Draft Quality definition = ultimaker2 [metadata] +setting_version = 4 type = quality quality_type = draft weight = -2 -setting_version = 4 [values] layer_height = 0.2 diff --git a/resources/quality/ultimaker2/um2_high.inst.cfg b/resources/quality/ultimaker2/um2_high.inst.cfg index 96941beed2..54119933b5 100644 --- a/resources/quality/ultimaker2/um2_high.inst.cfg +++ b/resources/quality/ultimaker2/um2_high.inst.cfg @@ -4,10 +4,10 @@ name = Extra Fine definition = ultimaker2 [metadata] +setting_version = 4 type = quality quality_type = high weight = 1 -setting_version = 4 [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2/um2_low.inst.cfg b/resources/quality/ultimaker2/um2_low.inst.cfg index 832962984c..acd6c849d1 100644 --- a/resources/quality/ultimaker2/um2_low.inst.cfg +++ b/resources/quality/ultimaker2/um2_low.inst.cfg @@ -4,10 +4,10 @@ name = Low Quality definition = ultimaker2 [metadata] +setting_version = 4 type = quality quality_type = low weight = -1 -setting_version = 4 [values] infill_sparse_density = 10 diff --git a/resources/quality/ultimaker2/um2_normal.inst.cfg b/resources/quality/ultimaker2/um2_normal.inst.cfg index ea804feb80..ea7efc64ac 100644 --- a/resources/quality/ultimaker2/um2_normal.inst.cfg +++ b/resources/quality/ultimaker2/um2_normal.inst.cfg @@ -4,9 +4,9 @@ name = Fine definition = ultimaker2 [metadata] +setting_version = 4 type = quality quality_type = normal weight = 0 -setting_version = 4 [values] diff --git a/resources/quality/ultimaker2_plus/pla_0.25_normal.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.25_normal.inst.cfg index 638a1a9384..07e3dcd7db 100644 --- a/resources/quality/ultimaker2_plus/pla_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.25_normal.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pla_ultimaker2_plus_0.25_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla +variant = 0.25 mm [values] cool_min_layer_time = 5 @@ -19,4 +20,3 @@ speed_layer_0 = =round(speed_print * 30 / 30) speed_print = 30 top_bottom_thickness = 0.72 wall_thickness = 0.88 - diff --git a/resources/quality/ultimaker2_plus/pla_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.4_fast.inst.cfg index 9f4dfc0b5d..2a72e40d80 100644 --- a/resources/quality/ultimaker2_plus/pla_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.4_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_pla_ultimaker2_plus_0.4_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_pla +variant = 0.4 mm [values] cool_min_layer_time = 5 @@ -22,4 +23,3 @@ speed_travel = 150 speed_wall = 50 top_bottom_thickness = 0.75 wall_thickness = 0.7 - diff --git a/resources/quality/ultimaker2_plus/pla_0.4_high.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.4_high.inst.cfg index 7bf51b0211..ce41158378 100644 --- a/resources/quality/ultimaker2_plus/pla_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.4_high.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pla_ultimaker2_plus_0.4_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla +variant = 0.4 mm [values] cool_min_layer_time = 5 @@ -20,4 +21,3 @@ speed_print = 50 speed_topbottom = 20 top_bottom_thickness = 0.72 wall_thickness = 1.05 - diff --git a/resources/quality/ultimaker2_plus/pla_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.4_normal.inst.cfg index 3c6f40e0bc..edfe131ddf 100644 --- a/resources/quality/ultimaker2_plus/pla_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.4_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pla_ultimaker2_plus_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pla +variant = 0.4 mm [values] cool_min_layer_time = 5 @@ -20,4 +21,3 @@ speed_print = 50 speed_topbottom = 20 top_bottom_thickness = 0.8 wall_thickness = 1.05 - diff --git a/resources/quality/ultimaker2_plus/pla_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.6_normal.inst.cfg index ef79e30b74..548c7478ba 100644 --- a/resources/quality/ultimaker2_plus/pla_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.6_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -material = generic_pla_ultimaker2_plus_0.6_mm -type = quality -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pla +variant = 0.6 mm [values] cool_min_layer_time = 5 @@ -22,4 +23,3 @@ speed_wall = 40 speed_wall_0 = 25 top_bottom_thickness = 1.2 wall_thickness = 1.59 - diff --git a/resources/quality/ultimaker2_plus/pla_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.8_normal.inst.cfg index 42418ea392..a257d3d6f8 100644 --- a/resources/quality/ultimaker2_plus/pla_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.8_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -material = generic_pla_ultimaker2_plus_0.8_mm -type = quality -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_pla +variant = 0.8 mm [values] cool_min_layer_time = 5 @@ -20,4 +21,3 @@ speed_print = 40 speed_wall_0 = 25 top_bottom_thickness = 1.2 wall_thickness = 2.1 - diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg index 50a4076de2..e448b9d180 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_abs_ultimaker2_plus_0.25_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_abs +variant = 0.25 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.2 @@ -21,4 +22,3 @@ speed_layer_0 = =round(speed_print * 30 / 30) speed_print = 30 top_bottom_thickness = 0.72 wall_thickness = 0.88 - diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg index 9d1bcf6ff5..3fd2de3a36 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_abs_ultimaker2_plus_0.4_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_abs +variant = 0.4 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.2 @@ -24,4 +25,3 @@ speed_travel = 150 speed_wall = 40 top_bottom_thickness = 0.75 wall_thickness = 0.7 - diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.4_high.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.4_high.inst.cfg index 84a5557434..2f119ae86b 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.4_high.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_abs_ultimaker2_plus_0.4_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_abs +variant = 0.4 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.2 @@ -22,4 +23,3 @@ speed_print = 45 speed_wall = 30 top_bottom_thickness = 0.72 wall_thickness = 1.05 - diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg index efc749ad8c..8416e69dba 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_abs_ultimaker2_plus_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_abs +variant = 0.4 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.2 @@ -22,4 +23,3 @@ speed_print = 45 speed_wall = 30 top_bottom_thickness = 0.8 wall_thickness = 1.05 - diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg index eb706c5762..393e630299 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_abs_ultimaker2_plus_0.6_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_abs +variant = 0.6 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.5 @@ -22,4 +23,3 @@ speed_layer_0 = =round(speed_print * 30 / 40) speed_print = 40 top_bottom_thickness = 1.2 wall_thickness = 1.59 - diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg index 2dba5a9304..d0dcbb0908 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_abs_ultimaker2_plus_0.8_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_abs +variant = 0.8 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.5 @@ -21,4 +22,3 @@ speed_layer_0 = =round(speed_print * 30 / 40) speed_print = 40 top_bottom_thickness = 1.2 wall_thickness = 2.1 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg index 8e87e0e7b6..1047b0ca39 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_ultimaker2_plus_0.25_mm -weight = -1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = -1 +material = generic_cpe +variant = 0.25 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.2 @@ -21,4 +22,3 @@ speed_layer_0 = =round(speed_print * 30 / 30) speed_print = 30 top_bottom_thickness = 0.72 wall_thickness = 0.88 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg index e311df00a8..7beaf2f229 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_ultimaker2_plus_0.4_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_cpe +variant = 0.4 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.8 @@ -23,4 +24,3 @@ speed_travel = 150 speed_wall = 40 top_bottom_thickness = 0.75 wall_thickness = 0.7 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg index 685b7798fc..efd73655b1 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_ultimaker2_plus_0.4_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_cpe +variant = 0.4 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.8 @@ -22,4 +23,3 @@ speed_print = 45 speed_wall = 30 top_bottom_thickness = 0.72 wall_thickness = 1.05 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg index aadb4195f3..3badb3f191 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_ultimaker2_plus_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_cpe +variant = 0.4 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.8 @@ -22,4 +23,3 @@ speed_print = 45 speed_wall = 30 top_bottom_thickness = 0.8 wall_thickness = 1.05 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg index 332033368f..727d68eede 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_ultimaker2_plus_0.6_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_cpe +variant = 0.6 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.8 @@ -21,4 +22,3 @@ speed_layer_0 = =round(speed_print * 30 / 40) speed_print = 40 top_bottom_thickness = 1.2 wall_thickness = 1.59 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg index e4fcae8aa1..1460d69b7a 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_ultimaker2_plus_0.8_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_cpe +variant = 0.8 mm [values] cool_fan_speed_min = =cool_fan_speed * 0.8 @@ -21,4 +22,3 @@ speed_layer_0 = =round(speed_print * 30 / 40) speed_print = 40 top_bottom_thickness = 1.2 wall_thickness = 2.1 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpep_0.4_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpep_0.4_draft.inst.cfg index 55af936a89..be33739e72 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpep_0.4_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpep_0.4_draft.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_plus_ultimaker2_plus_0.4_mm -weight = -2 -quality_type = draft setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_cpe_plus +variant = 0.4 mm [values] adhesion_type = raft @@ -40,4 +41,3 @@ support_pattern = lines support_z_distance = 0.26 top_bottom_thickness = 1.5 wall_thickness = 1.14 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpep_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpep_0.4_normal.inst.cfg index eb0ca5e81f..58cf4bd0e3 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpep_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpep_0.4_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_plus_ultimaker2_plus_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_cpe_plus +variant = 0.4 mm [values] adhesion_type = raft @@ -40,4 +41,3 @@ support_pattern = lines support_z_distance = 0.26 top_bottom_thickness = 1.5 wall_thickness = 1.14 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpep_0.6_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpep_0.6_draft.inst.cfg index b324d867bc..fe4f895611 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpep_0.6_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpep_0.6_draft.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_plus_ultimaker2_plus_0.6_mm -weight = -2 -quality_type = draft setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_cpe_plus +variant = 0.6 mm [values] adhesion_type = raft @@ -44,4 +45,3 @@ support_xy_distance = 0.6 support_z_distance = 0.22 top_bottom_thickness = 0.75 wall_thickness = 1.14 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpep_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpep_0.6_normal.inst.cfg index c8c7576d30..bcc507a3d9 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpep_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpep_0.6_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_plus_ultimaker2_plus_0.6_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_cpe_plus +variant = 0.6 mm [values] adhesion_type = raft @@ -44,4 +45,3 @@ support_xy_distance = 0.6 support_z_distance = 0.22 top_bottom_thickness = 0.75 wall_thickness = 1.14 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpep_0.8_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpep_0.8_draft.inst.cfg index 28353f729d..c27d90ead8 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpep_0.8_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpep_0.8_draft.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_plus_ultimaker2_plus_0.8_mm -weight = -2 -quality_type = draft setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_cpe_plus +variant = 0.8 mm [values] adhesion_type = raft @@ -39,4 +40,3 @@ support_pattern = lines support_z_distance = 0.26 top_bottom_thickness = 1.2 wall_thickness = 2.1 - diff --git a/resources/quality/ultimaker2_plus/um2p_cpep_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpep_0.8_normal.inst.cfg index f74db21b91..7eb8b1fd72 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpep_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpep_0.8_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_cpe_plus_ultimaker2_plus_0.8_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_cpe_plus +variant = 0.8 mm [values] adhesion_type = raft @@ -39,4 +40,3 @@ support_pattern = lines support_z_distance = 0.26 top_bottom_thickness = 1.2 wall_thickness = 2.1 - diff --git a/resources/quality/ultimaker2_plus/um2p_nylon_0.25_high.inst.cfg b/resources/quality/ultimaker2_plus/um2p_nylon_0.25_high.inst.cfg index b8924423e2..33041f89ae 100644 --- a/resources/quality/ultimaker2_plus/um2p_nylon_0.25_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_nylon_0.25_high.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_nylon_ultimaker2_plus_0.25_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_nylon +variant = 0.25 mm [values] adhesion_type = raft @@ -41,4 +42,3 @@ support_xy_distance = 0.6 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 1 - diff --git a/resources/quality/ultimaker2_plus/um2p_nylon_0.25_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_nylon_0.25_normal.inst.cfg index 323fa51a8d..88974491cb 100644 --- a/resources/quality/ultimaker2_plus/um2p_nylon_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_nylon_0.25_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_nylon_ultimaker2_plus_0.25_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_nylon +variant = 0.25 mm [values] adhesion_type = raft @@ -41,4 +42,3 @@ support_xy_distance = 0.6 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 1 - diff --git a/resources/quality/ultimaker2_plus/um2p_nylon_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_nylon_0.4_fast.inst.cfg index 7628cd0be1..832fa12bc9 100644 --- a/resources/quality/ultimaker2_plus/um2p_nylon_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_nylon_0.4_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_nylon_ultimaker2_plus_0.4_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_nylon +variant = 0.4 mm [values] adhesion_type = raft @@ -40,4 +41,3 @@ support_xy_distance = 0.6 support_z_distance = =layer_height * 2 top_bottom_thickness = 0.75 wall_thickness = 1.06 - diff --git a/resources/quality/ultimaker2_plus/um2p_nylon_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_nylon_0.4_normal.inst.cfg index a97a4c4e8f..c12573691e 100644 --- a/resources/quality/ultimaker2_plus/um2p_nylon_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_nylon_0.4_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_nylon_ultimaker2_plus_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_nylon +variant = 0.4 mm [values] adhesion_type = raft @@ -39,4 +40,3 @@ support_xy_distance = 0.6 support_z_distance = =layer_height * 2 top_bottom_thickness = 0.75 wall_thickness = 1.06 - diff --git a/resources/quality/ultimaker2_plus/um2p_nylon_0.6_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_nylon_0.6_fast.inst.cfg index 0cd7bbdbfd..eaa4f86e23 100644 --- a/resources/quality/ultimaker2_plus/um2p_nylon_0.6_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_nylon_0.6_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_nylon_ultimaker2_plus_0.6_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_nylon +variant = 0.6 mm [values] adhesion_type = raft @@ -45,4 +46,3 @@ support_xy_distance = 0.7 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 1.2 - diff --git a/resources/quality/ultimaker2_plus/um2p_nylon_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_nylon_0.6_normal.inst.cfg index d5e0025913..5e3db4db22 100644 --- a/resources/quality/ultimaker2_plus/um2p_nylon_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_nylon_0.6_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_nylon_ultimaker2_plus_0.6_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_nylon +variant = 0.6 mm [values] adhesion_type = raft @@ -43,4 +44,3 @@ support_xy_distance = 0.7 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 1.2 - diff --git a/resources/quality/ultimaker2_plus/um2p_nylon_0.8_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_nylon_0.8_draft.inst.cfg index f653a90f95..38a71c9109 100644 --- a/resources/quality/ultimaker2_plus/um2p_nylon_0.8_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_nylon_0.8_draft.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker2_plus [metadata] -type = quality -material = generic_nylon_ultimaker2_plus_0.8_mm -weight = -2 -quality_type = draft setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_nylon +variant = 0.8 mm [values] adhesion_type = raft @@ -44,4 +45,3 @@ support_xy_distance = 0.75 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 2.4 - diff --git a/resources/quality/ultimaker2_plus/um2p_nylon_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_nylon_0.8_normal.inst.cfg index 144c8e74ac..9d20a6d91f 100644 --- a/resources/quality/ultimaker2_plus/um2p_nylon_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_nylon_0.8_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_nylon_ultimaker2_plus_0.8_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_nylon +variant = 0.8 mm [values] adhesion_type = raft @@ -44,4 +45,3 @@ support_xy_distance = 0.75 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 2.4 - diff --git a/resources/quality/ultimaker2_plus/um2p_pc_0.25_high.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pc_0.25_high.inst.cfg index d38f2af4d3..7829d7b7b9 100644 --- a/resources/quality/ultimaker2_plus/um2p_pc_0.25_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pc_0.25_high.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pc_ultimaker2_plus_0.25_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pc +variant = 0.25 mm [values] adhesion_type = raft @@ -35,4 +36,3 @@ support_infill_rate = 20 support_pattern = lines support_z_distance = 0.19 wall_thickness = 0.88 - diff --git a/resources/quality/ultimaker2_plus/um2p_pc_0.25_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pc_0.25_normal.inst.cfg index aa176f67a2..168a308916 100644 --- a/resources/quality/ultimaker2_plus/um2p_pc_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pc_0.25_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pc_ultimaker2_plus_0.25_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pc +variant = 0.25 mm [values] adhesion_type = raft @@ -35,4 +36,3 @@ support_infill_rate = 20 support_pattern = lines support_z_distance = 0.19 wall_thickness = 0.88 - diff --git a/resources/quality/ultimaker2_plus/um2p_pc_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pc_0.4_fast.inst.cfg index 0408ead05e..46a349d81f 100644 --- a/resources/quality/ultimaker2_plus/um2p_pc_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pc_0.4_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_pc_ultimaker2_plus_0.4_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_pc +variant = 0.4 mm [values] adhesion_type = raft @@ -36,4 +37,3 @@ support_infill_rate = 20 support_pattern = lines support_z_distance = 0.19 wall_thickness = 1.2 - diff --git a/resources/quality/ultimaker2_plus/um2p_pc_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pc_0.4_normal.inst.cfg index ed430f10c0..0c2450f512 100644 --- a/resources/quality/ultimaker2_plus/um2p_pc_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pc_0.4_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pc_ultimaker2_plus_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pc +variant = 0.4 mm [values] adhesion_type = raft @@ -36,4 +37,3 @@ support_infill_rate = 20 support_pattern = lines support_z_distance = 0.19 wall_thickness = 1.2 - diff --git a/resources/quality/ultimaker2_plus/um2p_pc_0.6_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pc_0.6_fast.inst.cfg index b6c3a66c0b..68528a0209 100644 --- a/resources/quality/ultimaker2_plus/um2p_pc_0.6_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pc_0.6_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_pc_ultimaker2_plus_0.6_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_pc +variant = 0.6 mm [values] adhesion_type = raft @@ -42,4 +43,3 @@ support_pattern = lines support_z_distance = 0.21 top_bottom_thickness = 0.75 wall_thickness = 1.06 - diff --git a/resources/quality/ultimaker2_plus/um2p_pc_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pc_0.6_normal.inst.cfg index 0dfb533f56..a92110a149 100644 --- a/resources/quality/ultimaker2_plus/um2p_pc_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pc_0.6_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pc_ultimaker2_plus_0.6_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pc +variant = 0.6 mm [values] adhesion_type = raft @@ -42,4 +43,3 @@ support_pattern = lines support_z_distance = 0.21 top_bottom_thickness = 0.75 wall_thickness = 1.06 - diff --git a/resources/quality/ultimaker2_plus/um2p_pc_0.8_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pc_0.8_draft.inst.cfg index 3eee23006f..8c8bff3846 100644 --- a/resources/quality/ultimaker2_plus/um2p_pc_0.8_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pc_0.8_draft.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker2_plus [metadata] -type = quality -material = generic_pc_ultimaker2_plus_0.8_mm -weight = -2 -quality_type = draft setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_pc +variant = 0.8 mm [values] adhesion_type = raft @@ -36,4 +37,3 @@ support_pattern = lines support_z_distance = 0.26 top_bottom_thickness = 2.0 wall_thickness = 2.1 - diff --git a/resources/quality/ultimaker2_plus/um2p_pc_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pc_0.8_normal.inst.cfg index 40da82e6bf..db83d5181f 100644 --- a/resources/quality/ultimaker2_plus/um2p_pc_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pc_0.8_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pc_ultimaker2_plus_0.8_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pc +variant = 0.8 mm [values] adhesion_type = raft @@ -36,4 +37,3 @@ support_pattern = lines support_z_distance = 0.26 top_bottom_thickness = 1.2 wall_thickness = 2.1 - diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.4_fast.inst.cfg index 6f4e366209..b7474044f3 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.4_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_pp_ultimaker2_plus_0.4_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_pp +variant = 0.4 mm [values] acceleration_enabled = True @@ -68,4 +69,3 @@ travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =round(line_width * 0.38 / 0.38, 2) wall_thickness = 0.76 - diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.4_normal.inst.cfg index c7224f475f..f6d2c38161 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.4_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_pp_ultimaker2_plus_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pp +variant = 0.4 mm [values] acceleration_enabled = True @@ -67,4 +68,3 @@ travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =round(line_width * 0.38 / 0.38, 2) wall_thickness = 0.76 - diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg index 203db9883e..e2fa538445 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker2_plus [metadata] -type = quality -material = generic_pp_ultimaker2_plus_0.6_mm -weight = -2 -quality_type = draft setting_version = 4 +type = quality +quality_type = draft +weight = -2 +material = generic_pp +variant = 0.6 mm [values] acceleration_enabled = True @@ -70,4 +71,3 @@ travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =round(line_width * 0.57 / 0.57, 2) wall_thickness = 1.14 - diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg index 64dfbc9281..3cda5e7e63 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_pp_ultimaker2_plus_0.6_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_pp +variant = 0.6 mm [values] acceleration_enabled = True @@ -70,4 +71,3 @@ travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =round(line_width * 0.57 / 0.57, 2) wall_thickness = 1.14 - diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg index f6d56242dd..402d63f027 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker2_plus [metadata] -type = quality -material = generic_pp_ultimaker2_plus_0.8_mm -weight = -2 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -2 +material = generic_pp +variant = 0.8 mm [values] acceleration_enabled = True @@ -70,4 +71,3 @@ travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =round(line_width * 0.76 / 0.76, 2) wall_thickness = 1.52 - diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg index ecb3e3da4a..2275bd49a7 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast definition = ultimaker2_plus [metadata] -type = quality -material = generic_pp_ultimaker2_plus_0.8_mm -weight = -3 -quality_type = draft setting_version = 4 +type = quality +quality_type = draft +weight = -3 +material = generic_pp +variant = 0.8 mm [values] acceleration_enabled = True @@ -70,4 +71,3 @@ travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =round(line_width * 0.76 / 0.76, 2) wall_thickness = 1.52 - diff --git a/resources/quality/ultimaker2_plus/um2p_tpu_0.25_high.inst.cfg b/resources/quality/ultimaker2_plus/um2p_tpu_0.25_high.inst.cfg index b1cb56a543..2ad062bd31 100644 --- a/resources/quality/ultimaker2_plus/um2p_tpu_0.25_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_tpu_0.25_high.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_tpu_ultimaker2_plus_0.25_mm -weight = 1 -quality_type = high setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_tpu +variant = 0.25 mm [values] adhesion_type = brim @@ -40,4 +41,3 @@ support_xy_distance = 0.6 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 0.88 - diff --git a/resources/quality/ultimaker2_plus/um2p_tpu_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_tpu_0.4_normal.inst.cfg index 80cc92fe64..56ce55ee96 100644 --- a/resources/quality/ultimaker2_plus/um2p_tpu_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_tpu_0.4_normal.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker2_plus [metadata] -type = quality -material = generic_tpu_ultimaker2_plus_0.4_mm -weight = 0 -quality_type = normal setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_tpu +variant = 0.4 mm [values] adhesion_type = brim @@ -37,4 +38,3 @@ support_xy_distance = 0.65 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 1.05 - diff --git a/resources/quality/ultimaker2_plus/um2p_tpu_0.6_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_tpu_0.6_fast.inst.cfg index 9796adada9..6bcc5fa31f 100644 --- a/resources/quality/ultimaker2_plus/um2p_tpu_0.6_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_tpu_0.6_fast.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker2_plus [metadata] -type = quality -material = generic_tpu_ultimaker2_plus_0.6_mm -weight = -1 -quality_type = fast setting_version = 4 +type = quality +quality_type = fast +weight = -1 +material = generic_tpu +variant = 0.6 mm [values] adhesion_type = brim @@ -42,4 +43,3 @@ support_xy_distance = 0.7 support_z_distance = =layer_height * 2 top_bottom_thickness = 1.2 wall_thickness = 1.14 - diff --git a/resources/quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg index fc7d4d12d2..0b100d8717 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_ABS_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_abs_ultimaker3_AA_0.25 weight = 0 -setting_version = 4 +material = generic_abs +variant = AA 0.25 [values] cool_fan_speed = 40 @@ -20,4 +21,3 @@ prime_tower_wall_thickness = 0.9 retraction_prime_speed = 25 speed_topbottom = =math.ceil(speed_print * 30 / 55) wall_thickness = 0.92 - diff --git a/resources/quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg index 83e0c549c4..77494d6339 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_CPE_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_cpe_ultimaker3_AA_0.25 weight = 0 -setting_version = 4 +material = generic_cpe +variant = AA 0.25 [values] prime_tower_size = 12 @@ -18,4 +19,3 @@ speed_infill = 40 speed_topbottom = =math.ceil(speed_print * 30 / 55) top_bottom_thickness = 0.8 wall_thickness = 0.92 - diff --git a/resources/quality/ultimaker3/um3_aa0.25_Nylon_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_Nylon_Normal_Quality.inst.cfg index 58ddc32101..0187084ff8 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_Nylon_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_Nylon_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_nylon_ultimaker3_AA_0.25 weight = 0 -setting_version = 4 +material = generic_nylon +variant = AA 0.25 [values] cool_min_layer_time_fan_speed_max = 20 @@ -32,4 +33,3 @@ switch_extruder_prime_speed = 30 switch_extruder_retraction_amount = 30 switch_extruder_retraction_speeds = 40 wall_line_width_x = =wall_line_width - diff --git a/resources/quality/ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg index 7c9fa32949..0070419a4e 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_PC_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine - Experimental definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pc_ultimaker3_AA_0.25 weight = 0 -setting_version = 4 +material = generic_pc +variant = AA 0.25 [values] acceleration_enabled = True @@ -53,4 +54,3 @@ switch_extruder_retraction_speeds = 35 wall_0_inset = 0 wall_line_width_x = =line_width wall_thickness = 1.2 - diff --git a/resources/quality/ultimaker3/um3_aa0.25_PLA_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_PLA_Normal_Quality.inst.cfg index 1bee4b8f18..b2347f1902 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_PLA_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_PLA_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pla_ultimaker3_AA_0.25 weight = 0 -setting_version = 4 +material = generic_pla +variant = AA 0.25 [values] brim_width = 8 @@ -33,4 +34,3 @@ travel_avoid_distance = 0.4 wall_0_inset = 0.015 wall_0_wipe_dist = 0.25 wall_thickness = 0.7 - diff --git a/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg index ccc558530e..732289dedf 100644 --- a/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.25_PP_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine - Experimental definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pp_ultimaker3_AA_0.25 weight = 0 -setting_version = 4 +material = generic_pp +variant = AA 0.25 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_ABS_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_ABS_Draft_Print.inst.cfg index 13dca72c27..a5cc4aaa0c 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_ABS_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_ABS_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_abs_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_abs +variant = AA 0.4 [values] machine_nozzle_cool_down_speed = 0.85 @@ -24,4 +25,3 @@ speed_topbottom = =math.ceil(speed_print * 35 / 60) speed_wall = =math.ceil(speed_print * 45 / 60) speed_wall_0 = =math.ceil(speed_wall * 35 / 45) wall_thickness = 1 - diff --git a/resources/quality/ultimaker3/um3_aa0.4_ABS_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_ABS_Fast_Print.inst.cfg index 10fa10c726..ba80ad588e 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_ABS_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_ABS_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_abs_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_abs +variant = AA 0.4 [values] cool_min_speed = 7 @@ -24,4 +25,3 @@ speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 60) speed_wall = =math.ceil(speed_print * 40 / 60) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) - diff --git a/resources/quality/ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg index 02f2327468..c84ef6dabe 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_ABS_High_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_abs_ultimaker3_AA_0.4 weight = 1 -setting_version = 4 +material = generic_abs +variant = AA 0.4 [values] cool_min_speed = 12 @@ -23,4 +24,3 @@ speed_print = 50 speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 30 / 50) - diff --git a/resources/quality/ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg index fccb6a35f5..f3c9f6a892 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_ABS_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_abs_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_abs +variant = AA 0.4 [values] machine_nozzle_cool_down_speed = 0.85 @@ -21,4 +22,3 @@ speed_print = 55 speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 55) speed_wall = =math.ceil(speed_print * 30 / 55) - diff --git a/resources/quality/ultimaker3/um3_aa0.4_BAM_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_BAM_Draft_Print.inst.cfg index f3c6ae8387..fbc0c599ef 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_BAM_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_BAM_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_bam_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_bam +variant = AA 0.4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height diff --git a/resources/quality/ultimaker3/um3_aa0.4_BAM_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_BAM_Fast_Print.inst.cfg index e027477595..d6f64cb056 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_BAM_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_BAM_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_bam_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_bam +variant = AA 0.4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height diff --git a/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg index 3ced3a0417..53fb52bff6 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_bam_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_bam +variant = AA 0.4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height diff --git a/resources/quality/ultimaker3/um3_aa0.4_CPEP_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_CPEP_Draft_Print.inst.cfg index dfdb1ca8a7..dd089294de 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_CPEP_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_CPEP_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_cpe_plus_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_cpe_plus +variant = AA 0.4 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_CPEP_Fast_Print.inst.cfg index 93b371a627..373107d767 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_CPEP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_CPEP_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_cpe_plus_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_cpe_plus +variant = AA 0.4 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_CPEP_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_CPEP_High_Quality.inst.cfg index 93647f9f44..67544db97b 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_CPEP_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_CPEP_High_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_cpe_plus_ultimaker3_AA_0.4 weight = 1 -setting_version = 4 +material = generic_cpe_plus +variant = AA 0.4 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_CPEP_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_CPEP_Normal_Quality.inst.cfg index 2886ef2229..183d05ce60 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_CPEP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_CPEP_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_cpe_plus_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_cpe_plus +variant = AA 0.4 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_CPE_Draft_Print.inst.cfg index 5e3daf5a9e..74395628af 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_CPE_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_CPE_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_cpe_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_cpe +variant = AA 0.4 [values] material_print_temperature = =default_material_print_temperature + 10 @@ -22,4 +23,3 @@ speed_topbottom = =math.ceil(speed_print * 35 / 60) speed_wall = =math.ceil(speed_print * 45 / 60) speed_wall_0 = =math.ceil(speed_wall * 35 / 45) wall_thickness = 1 - diff --git a/resources/quality/ultimaker3/um3_aa0.4_CPE_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_CPE_Fast_Print.inst.cfg index e48f83994d..dbcf7f3e42 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_CPE_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_CPE_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_cpe_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_cpe +variant = AA 0.4 [values] cool_min_speed = 7 @@ -21,4 +22,3 @@ speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 60) speed_wall = =math.ceil(speed_print * 40 / 60) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) - diff --git a/resources/quality/ultimaker3/um3_aa0.4_CPE_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_CPE_High_Quality.inst.cfg index fd0a8cd18d..89b5210631 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_CPE_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_CPE_High_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_cpe_ultimaker3_AA_0.4 weight = 1 -setting_version = 4 +material = generic_cpe +variant = AA 0.4 [values] cool_min_speed = 12 @@ -22,4 +23,3 @@ speed_print = 50 speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 30 / 50) - diff --git a/resources/quality/ultimaker3/um3_aa0.4_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_CPE_Normal_Quality.inst.cfg index 56c997eb15..12927714ec 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_CPE_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_CPE_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_cpe_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_cpe +variant = AA 0.4 [values] machine_nozzle_cool_down_speed = 0.85 @@ -20,4 +21,3 @@ speed_print = 55 speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 55) speed_wall = =math.ceil(speed_print * 30 / 55) - diff --git a/resources/quality/ultimaker3/um3_aa0.4_Nylon_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_Nylon_Draft_Print.inst.cfg index 15283a3242..ff938df8f8 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_Nylon_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_Nylon_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_nylon_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_nylon +variant = AA 0.4 [values] adhesion_type = brim @@ -33,4 +34,3 @@ switch_extruder_prime_speed = 30 switch_extruder_retraction_amount = 30 switch_extruder_retraction_speeds = 40 wall_line_width_x = =wall_line_width - diff --git a/resources/quality/ultimaker3/um3_aa0.4_Nylon_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_Nylon_Fast_Print.inst.cfg index c063725e82..e9fd6df1e2 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_Nylon_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_Nylon_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_nylon_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_nylon +variant = AA 0.4 [values] adhesion_type = brim @@ -33,4 +34,3 @@ switch_extruder_prime_speed = 30 switch_extruder_retraction_amount = 30 switch_extruder_retraction_speeds = 40 wall_line_width_x = =wall_line_width - diff --git a/resources/quality/ultimaker3/um3_aa0.4_Nylon_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_Nylon_High_Quality.inst.cfg index 218e1e50e1..635cc573ea 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_Nylon_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_Nylon_High_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_nylon_ultimaker3_AA_0.4 weight = 1 -setting_version = 4 +material = generic_nylon +variant = AA 0.4 [values] adhesion_type = brim @@ -32,4 +33,3 @@ switch_extruder_prime_speed = 30 switch_extruder_retraction_amount = 30 switch_extruder_retraction_speeds = 40 wall_line_width_x = =wall_line_width - diff --git a/resources/quality/ultimaker3/um3_aa0.4_Nylon_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_Nylon_Normal_Quality.inst.cfg index 3b96939ac9..778ace19e4 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_Nylon_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_Nylon_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_nylon_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_nylon +variant = AA 0.4 [values] adhesion_type = brim @@ -32,4 +33,3 @@ switch_extruder_prime_speed = 30 switch_extruder_retraction_amount = 30 switch_extruder_retraction_speeds = 40 wall_line_width_x = =wall_line_width - diff --git a/resources/quality/ultimaker3/um3_aa0.4_PC_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PC_Draft_Print.inst.cfg index f8b4dd067c..437e4676b3 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PC_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PC_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pc_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_pc +variant = AA 0.4 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_PC_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PC_Fast_Print.inst.cfg index 1db3935180..320cf0a96f 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PC_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PC_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_pc_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_pc +variant = AA 0.4 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_PC_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PC_High_Quality.inst.cfg index 0f9e9b15b0..6d7e8f7976 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PC_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PC_High_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pc_ultimaker3_AA_0.4 weight = 1 -setting_version = 4 +material = generic_pc +variant = AA 0.4 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_PC_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PC_Normal_Quality.inst.cfg index 26a3136069..c18e9dbbd5 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PC_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PC_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pc_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_pc +variant = AA 0.4 [values] acceleration_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg index a32d9268d3..24b7c51fbc 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PLA_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pla_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_pla +variant = AA 0.4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height @@ -26,4 +27,3 @@ speed_wall = =math.ceil(speed_print * 55 / 70) speed_wall_0 = =math.ceil(speed_wall * 45 / 50) top_bottom_thickness = 1 wall_thickness = 1 - diff --git a/resources/quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg index 30b7d44d4e..6b3d8642e0 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PLA_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_pla_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_pla +variant = AA 0.4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height @@ -25,4 +26,3 @@ speed_wall = =math.ceil(speed_print * 40 / 80) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) top_bottom_thickness = 1 wall_thickness = 1 - diff --git a/resources/quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg index da62ce2e3f..6009031e0c 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PLA_High_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = high -material = generic_pla_ultimaker3_AA_0.4 weight = 1 -setting_version = 4 +material = generic_pla +variant = AA 0.4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height @@ -27,4 +28,3 @@ speed_topbottom = =math.ceil(speed_print * 30 / 60) speed_wall = =math.ceil(speed_print * 30 / 60) top_bottom_thickness = 1 wall_thickness = 1 - diff --git a/resources/quality/ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg index 04707735f5..3722134df6 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PLA_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pla_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_pla +variant = AA 0.4 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height @@ -23,4 +24,3 @@ skin_overlap = 10 speed_layer_0 = 20 top_bottom_thickness = 1 wall_thickness = 1 - diff --git a/resources/quality/ultimaker3/um3_aa0.4_PP_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PP_Draft_Print.inst.cfg index 3fe25e563a..265e068598 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PP_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PP_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pp_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_pp +variant = AA 0.4 [values] acceleration_enabled = True @@ -63,4 +64,4 @@ switch_extruder_retraction_speeds = 35 travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =line_width -wall_thickness = =line_width * 3 \ No newline at end of file +wall_thickness = =line_width * 3 diff --git a/resources/quality/ultimaker3/um3_aa0.4_PP_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PP_Fast_Print.inst.cfg index 4c92c7a14b..7698c0a273 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PP_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_pp_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_pp +variant = AA 0.4 [values] acceleration_enabled = True @@ -63,4 +64,4 @@ top_bottom_thickness = 1.1 travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =line_width -wall_thickness = =line_width * 3 \ No newline at end of file +wall_thickness = =line_width * 3 diff --git a/resources/quality/ultimaker3/um3_aa0.4_PP_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_PP_Normal_Quality.inst.cfg index db55956497..897ec993e7 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_PP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_PP_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_pp_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_pp +variant = AA 0.4 [values] acceleration_enabled = True @@ -62,4 +63,4 @@ top_bottom_thickness = 1 travel_avoid_distance = 3 wall_0_inset = 0 wall_line_width_x = =line_width -wall_thickness = =line_width * 3 \ No newline at end of file +wall_thickness = =line_width * 3 diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg index f6828f88fb..c34415462c 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_tpu_ultimaker3_AA_0.4 weight = -2 -setting_version = 4 +material = generic_tpu +variant = AA 0.4 [values] acceleration_enabled = True @@ -62,4 +63,4 @@ top_bottom_thickness = 0.7 travel_avoid_distance = 1.5 wall_0_inset = 0 wall_line_width_x = =line_width -wall_thickness = 0.76 \ No newline at end of file +wall_thickness = 0.76 diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg index 80be26d24c..70a638ee17 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -material = generic_tpu_ultimaker3_AA_0.4 weight = -1 -setting_version = 4 +material = generic_tpu +variant = AA 0.4 [values] acceleration_enabled = True @@ -63,4 +64,4 @@ top_bottom_thickness = 0.7 travel_avoid_distance = 1.5 wall_0_inset = 0 wall_line_width_x = =line_width -wall_thickness = 0.76 \ No newline at end of file +wall_thickness = 0.76 diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg index 53044e1805..a92c9c7391 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg @@ -4,11 +4,12 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -material = generic_tpu_ultimaker3_AA_0.4 weight = 0 -setting_version = 4 +material = generic_tpu +variant = AA 0.4 [values] acceleration_enabled = True @@ -60,4 +61,4 @@ top_bottom_thickness = 0.7 travel_avoid_distance = 1.5 wall_0_inset = 0 wall_line_width_x = =line_width -wall_thickness = 0.76 \ No newline at end of file +wall_thickness = 0.76 diff --git a/resources/quality/ultimaker3/um3_aa0.8_ABS_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_ABS_Draft_Print.inst.cfg index 7c16e6e8ee..78930b84e2 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_ABS_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_ABS_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_abs_ultimaker3_AA_0.8 weight = -2 -setting_version = 4 +material = generic_abs +variant = AA 0.8 [values] line_width = =machine_nozzle_size * 0.875 diff --git a/resources/quality/ultimaker3/um3_aa0.8_ABS_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_ABS_Superdraft_Print.inst.cfg index 728b4c868f..9470779bd4 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_ABS_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_ABS_Superdraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Sprint definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_abs_ultimaker3_AA_0.8 weight = -4 -setting_version = 4 +material = generic_abs +variant = AA 0.8 [values] layer_height = 0.4 diff --git a/resources/quality/ultimaker3/um3_aa0.8_ABS_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_ABS_Verydraft_Print.inst.cfg index 98ae70c568..d28e9b75b6 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_ABS_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_ABS_Verydraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_abs_ultimaker3_AA_0.8 weight = -3 -setting_version = 4 +material = generic_abs +variant = AA 0.8 [values] layer_height = 0.3 diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg index 0a05e9aafd..6f84174c5a 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast - Experimental definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_cpe_plus_ultimaker3_AA_0.8 weight = -2 -setting_version = 4 +material = generic_cpe_plus +variant = AA 0.8 [values] brim_width = 14 @@ -35,4 +36,4 @@ support_bottom_distance = =support_z_distance support_line_width = =round(line_width * 0.6 / 0.7, 2) support_z_distance = =layer_height top_bottom_thickness = 1.2 -travel_avoid_distance = 1.5 \ No newline at end of file +travel_avoid_distance = 1.5 diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Superdraft_Print.inst.cfg index 82efb6a57b..09e59ee8ca 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Superdraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Sprint - Experimental definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_cpe_plus_ultimaker3_AA_0.8 weight = -4 -setting_version = 4 +material = generic_cpe_plus +variant = AA 0.8 [values] brim_width = 14 @@ -36,4 +37,4 @@ support_bottom_distance = =support_z_distance support_line_width = =round(line_width * 0.6 / 0.7, 2) support_z_distance = =layer_height top_bottom_thickness = 1.2 -travel_avoid_distance = 1.5 \ No newline at end of file +travel_avoid_distance = 1.5 diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Verydraft_Print.inst.cfg index ff375b6e49..7b7d211c21 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPEP_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPEP_Verydraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast - Experimental definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_cpe_plus_ultimaker3_AA_0.8 weight = -3 -setting_version = 4 +material = generic_cpe_plus +variant = AA 0.8 [values] brim_width = 14 @@ -36,4 +37,4 @@ support_bottom_distance = =support_z_distance support_line_width = =round(line_width * 0.6 / 0.7, 2) support_z_distance = =layer_height top_bottom_thickness = 1.2 -travel_avoid_distance = 1.5 \ No newline at end of file +travel_avoid_distance = 1.5 diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPE_Draft_Print.inst.cfg index b4d7035b8d..ecce20d9a2 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPE_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPE_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_cpe_ultimaker3_AA_0.8 weight = -2 -setting_version = 4 +material = generic_cpe +variant = AA 0.8 [values] brim_width = 15 diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPE_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPE_Superdraft_Print.inst.cfg index b5ccc38534..a14d4601ee 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPE_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPE_Superdraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Sprint definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_cpe_ultimaker3_AA_0.8 weight = -4 -setting_version = 4 +material = generic_cpe +variant = AA 0.8 [values] brim_width = 15 diff --git a/resources/quality/ultimaker3/um3_aa0.8_CPE_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_CPE_Verydraft_Print.inst.cfg index 33ae223526..7a6cbc7251 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_CPE_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_CPE_Verydraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_cpe_ultimaker3_AA_0.8 weight = -3 -setting_version = 4 +material = generic_cpe +variant = AA 0.8 [values] brim_width = 15 diff --git a/resources/quality/ultimaker3/um3_aa0.8_Nylon_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_Nylon_Draft_Print.inst.cfg index 43ec77453c..9254894df3 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_Nylon_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_Nylon_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_nylon_ultimaker3_AA_0.8 weight = -2 -setting_version = 4 +material = generic_nylon +variant = AA 0.8 [values] brim_width = 5.6 diff --git a/resources/quality/ultimaker3/um3_aa0.8_Nylon_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_Nylon_Superdraft_Print.inst.cfg index 5b8626e8c2..f6e2787e65 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_Nylon_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_Nylon_Superdraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Sprint definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_nylon_ultimaker3_AA_0.8 weight = -4 -setting_version = 4 +material = generic_nylon +variant = AA 0.8 [values] brim_width = 5.6 diff --git a/resources/quality/ultimaker3/um3_aa0.8_Nylon_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_Nylon_Verydraft_Print.inst.cfg index 0b115ada4b..794ccd006d 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_Nylon_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_Nylon_Verydraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_nylon_ultimaker3_AA_0.8 weight = -3 -setting_version = 4 +material = generic_nylon +variant = AA 0.8 [values] brim_width = 5.6 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg index 0b666d2e0b..c0ae3852dc 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PC_Fast_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast - Experimental definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pc_ultimaker3_AA_0.8 weight = 0 -setting_version = 4 +material = generic_pc +variant = AA 0.8 [values] brim_width = 14 @@ -28,4 +29,4 @@ speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) support_line_width = =round(line_width * 0.6 / 0.7, 2) -travel_avoid_distance = 3 \ No newline at end of file +travel_avoid_distance = 3 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg index de212df4af..ca58342847 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PC_Superdraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Sprint - Experimental definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_pc_ultimaker3_AA_0.8 weight = -2 -setting_version = 4 +material = generic_pc +variant = AA 0.8 [values] brim_width = 14 @@ -28,4 +29,4 @@ speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) support_line_width = =round(line_width * 0.6 / 0.7, 2) -travel_avoid_distance = 3 \ No newline at end of file +travel_avoid_distance = 3 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg index 3e0c669eeb..6c69aa8ff5 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PC_Verydraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast - Experimental definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_pc_ultimaker3_AA_0.8 weight = -1 -setting_version = 4 +material = generic_pc +variant = AA 0.8 [values] brim_width = 14 @@ -29,4 +30,4 @@ speed_topbottom = =math.ceil(speed_print * 25 / 50) speed_wall = =math.ceil(speed_print * 40 / 50) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) support_line_width = =round(line_width * 0.6 / 0.7, 2) -travel_avoid_distance = 3 \ No newline at end of file +travel_avoid_distance = 3 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg index 8b3c3e56c6..c03cc1ad5f 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pla_ultimaker3_AA_0.8 weight = -2 -setting_version = 4 +material = generic_pla +variant = AA 0.8 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg index 2fe8f7c6f9..b1252a3662 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Superdraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Sprint definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_pla_ultimaker3_AA_0.8 weight = -4 -setting_version = 4 +material = generic_pla +variant = AA 0.8 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height diff --git a/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg index 9072e0c60f..191a7a4b1d 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PLA_Verydraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_pla_ultimaker3_AA_0.8 weight = -3 -setting_version = 4 +material = generic_pla +variant = AA 0.8 [values] cool_fan_full_at_height = =layer_height_0 + 2 * layer_height diff --git a/resources/quality/ultimaker3/um3_aa0.8_PP_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PP_Draft_Print.inst.cfg index f46c3cfb8f..fb67666dc7 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PP_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PP_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_pp_ultimaker3_AA_0.8 weight = -2 -setting_version = 4 +material = generic_pp +variant = AA 0.8 [values] brim_width = 25 @@ -48,4 +49,4 @@ top_bottom_thickness = 1.6 travel_compensate_overlapping_walls_0_enabled = False wall_0_wipe_dist = =line_width * 2 wall_line_width_x = =round(line_width * 0.8 / 0.8, 2) -wall_thickness = 1.6 \ No newline at end of file +wall_thickness = 1.6 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PP_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PP_Superdraft_Print.inst.cfg index ac8087d0c4..0fe9eb2bf9 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PP_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PP_Superdraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Sprint definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_pp_ultimaker3_AA_0.8 weight = -4 -setting_version = 4 +material = generic_pp +variant = AA 0.8 [values] brim_width = 25 @@ -48,4 +49,4 @@ top_bottom_thickness = 1.6 travel_compensate_overlapping_walls_0_enabled = False wall_0_wipe_dist = =line_width * 2 wall_line_width_x = =round(line_width * 0.8 / 0.8, 2) -wall_thickness = 1.6 \ No newline at end of file +wall_thickness = 1.6 diff --git a/resources/quality/ultimaker3/um3_aa0.8_PP_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_PP_Verydraft_Print.inst.cfg index daf60f24e6..5ec1311987 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_PP_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_PP_Verydraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_pp_ultimaker3_AA_0.8 weight = -3 -setting_version = 4 +material = generic_pp +variant = AA 0.8 [values] brim_width = 25 @@ -48,4 +49,4 @@ top_bottom_thickness = 1.6 travel_compensate_overlapping_walls_0_enabled = False wall_0_wipe_dist = =line_width * 2 wall_line_width_x = =round(line_width * 0.8 / 0.8, 2) -wall_thickness = 1.6 \ No newline at end of file +wall_thickness = 1.6 diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg index d5d7479a0e..c2dd5f696d 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -material = generic_tpu_ultimaker3_AA_0.8 weight = -2 -setting_version = 4 +material = generic_tpu +variant = AA 0.8 [values] brim_width = 8.75 @@ -60,4 +61,4 @@ travel_avoid_distance = 1.5 travel_compensate_overlapping_walls_0_enabled = False wall_0_wipe_dist = =line_width * 2 wall_line_width_x = =round(line_width * 0.6 / 0.8, 2) -wall_thickness = 1.3 \ No newline at end of file +wall_thickness = 1.3 diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg index 86c6a3df77..b4efb6158d 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Sprint definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -material = generic_tpu_ultimaker3_AA_0.8 weight = -4 -setting_version = 4 +material = generic_tpu +variant = AA 0.8 [values] brim_width = 8.75 @@ -61,4 +62,4 @@ travel_avoid_distance = 1.5 travel_compensate_overlapping_walls_0_enabled = False wall_0_wipe_dist = =line_width * 2 wall_line_width_x = =round(line_width * 0.6 / 0.8, 2) -wall_thickness = 1.3 \ No newline at end of file +wall_thickness = 1.3 diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg index 8af3edcddd..4d2a18cd71 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg @@ -4,11 +4,12 @@ name = Extra Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -material = generic_tpu_ultimaker3_AA_0.8 weight = -3 -setting_version = 4 +material = generic_tpu +variant = AA 0.8 [values] brim_width = 8.75 @@ -60,4 +61,4 @@ travel_avoid_distance = 1.5 travel_compensate_overlapping_walls_0_enabled = False wall_0_wipe_dist = =line_width * 2 wall_line_width_x = =round(line_width * 0.6 / 0.8, 2) -wall_thickness = 1.3 \ No newline at end of file +wall_thickness = 1.3 diff --git a/resources/quality/ultimaker3/um3_bb0.4_PVA_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_bb0.4_PVA_Draft_Print.inst.cfg index c87f744932..eacdaccffe 100644 --- a/resources/quality/ultimaker3/um3_bb0.4_PVA_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_bb0.4_PVA_Draft_Print.inst.cfg @@ -4,14 +4,15 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_pva_ultimaker3_BB_0.4 -setting_version = 4 +material = generic_pva +variant = BB 0.4 [values] material_print_temperature = =default_material_print_temperature + 10 material_standby_temperature = 100 prime_tower_enable = False -skin_overlap = 20 \ No newline at end of file +skin_overlap = 20 diff --git a/resources/quality/ultimaker3/um3_bb0.4_PVA_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_bb0.4_PVA_Fast_Print.inst.cfg index 23fa6d61d8..c6ddd85181 100644 --- a/resources/quality/ultimaker3/um3_bb0.4_PVA_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_bb0.4_PVA_Fast_Print.inst.cfg @@ -4,15 +4,16 @@ name = Normal definition = ultimaker3 [metadata] -weight = -1 +setting_version = 4 type = quality quality_type = fast -material = generic_pva_ultimaker3_BB_0.4 -setting_version = 4 +weight = -1 +material = generic_pva +variant = BB 0.4 [values] material_print_temperature = =default_material_print_temperature + 5 material_standby_temperature = 100 prime_tower_enable = False skin_overlap = 15 -support_infill_sparse_thickness = 0.3 \ No newline at end of file +support_infill_sparse_thickness = 0.3 diff --git a/resources/quality/ultimaker3/um3_bb0.4_PVA_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_bb0.4_PVA_High_Quality.inst.cfg index 3ba82d65c6..0b1d0f9f8d 100644 --- a/resources/quality/ultimaker3/um3_bb0.4_PVA_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_bb0.4_PVA_High_Quality.inst.cfg @@ -4,13 +4,14 @@ name = Extra Fine definition = ultimaker3 [metadata] -weight = 1 +setting_version = 4 type = quality quality_type = high -material = generic_pva_ultimaker3_BB_0.4 -setting_version = 4 +weight = 1 +material = generic_pva +variant = BB 0.4 [values] material_standby_temperature = 100 prime_tower_enable = False -support_infill_sparse_thickness = 0.18 \ No newline at end of file +support_infill_sparse_thickness = 0.18 diff --git a/resources/quality/ultimaker3/um3_bb0.4_PVA_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_bb0.4_PVA_Normal_Quality.inst.cfg index a709d5613b..9980e2b31c 100644 --- a/resources/quality/ultimaker3/um3_bb0.4_PVA_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_bb0.4_PVA_Normal_Quality.inst.cfg @@ -4,12 +4,13 @@ name = Fine definition = ultimaker3 [metadata] -weight = 0 +setting_version = 4 type = quality quality_type = normal -material = generic_pva_ultimaker3_BB_0.4 -setting_version = 4 +weight = 0 +material = generic_pva +variant = BB 0.4 [values] material_standby_temperature = 100 -prime_tower_enable = False \ No newline at end of file +prime_tower_enable = False diff --git a/resources/quality/ultimaker3/um3_bb0.8_PVA_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_bb0.8_PVA_Draft_Print.inst.cfg index 4cb296b4c7..edc960cc8c 100644 --- a/resources/quality/ultimaker3/um3_bb0.8_PVA_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_bb0.8_PVA_Draft_Print.inst.cfg @@ -4,12 +4,13 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_pva_ultimaker3_BB_0.8 -setting_version = 4 +material = generic_pva +variant = BB 0.8 [values] material_print_temperature = =default_material_print_temperature + 5 -material_standby_temperature = 100 \ No newline at end of file +material_standby_temperature = 100 diff --git a/resources/quality/ultimaker3/um3_bb0.8_PVA_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_bb0.8_PVA_Superdraft_Print.inst.cfg index 5249517844..6fb66dab14 100644 --- a/resources/quality/ultimaker3/um3_bb0.8_PVA_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_bb0.8_PVA_Superdraft_Print.inst.cfg @@ -4,13 +4,14 @@ name = Sprint definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft weight = -4 -material = generic_pva_ultimaker3_BB_0.8 -setting_version = 4 +material = generic_pva +variant = BB 0.8 [values] layer_height = 0.4 material_standby_temperature = 100 -support_interface_height = 0.9 \ No newline at end of file +support_interface_height = 0.9 diff --git a/resources/quality/ultimaker3/um3_bb0.8_PVA_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_bb0.8_PVA_Verydraft_Print.inst.cfg index c34e19b134..12288919fe 100644 --- a/resources/quality/ultimaker3/um3_bb0.8_PVA_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_bb0.8_PVA_Verydraft_Print.inst.cfg @@ -4,14 +4,15 @@ name = Extra Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft weight = -3 -material = generic_pva_ultimaker3_BB_0.8 -setting_version = 4 +material = generic_pva +variant = BB 0.8 [values] layer_height = 0.3 material_standby_temperature = 100 support_infill_sparse_thickness = 0.3 -support_interface_height = 1.2 \ No newline at end of file +support_interface_height = 1.2 diff --git a/resources/quality/ultimaker3/um3_global_Draft_Quality.inst.cfg b/resources/quality/ultimaker3/um3_global_Draft_Quality.inst.cfg index b56775a987..9f13bbd3c2 100644 --- a/resources/quality/ultimaker3/um3_global_Draft_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_global_Draft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = draft -global_quality = True weight = -2 -setting_version = 4 +global_quality = True [values] layer_height = 0.2 diff --git a/resources/quality/ultimaker3/um3_global_Fast_Quality.inst.cfg b/resources/quality/ultimaker3/um3_global_Fast_Quality.inst.cfg index 12f1183364..073ae82a07 100644 --- a/resources/quality/ultimaker3/um3_global_Fast_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_global_Fast_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = fast -global_quality = True weight = -1 -setting_version = 4 +global_quality = True [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker3/um3_global_High_Quality.inst.cfg b/resources/quality/ultimaker3/um3_global_High_Quality.inst.cfg index cf6e6c45e0..1daff86c49 100644 --- a/resources/quality/ultimaker3/um3_global_High_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_global_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Extra Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = high -global_quality = True weight = 0 -setting_version = 4 +global_quality = True [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker3/um3_global_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_global_Normal_Quality.inst.cfg index fef2328923..91c5bab8b7 100644 --- a/resources/quality/ultimaker3/um3_global_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_global_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Fine definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = normal -global_quality = True weight = 0 -setting_version = 4 +global_quality = True [values] layer_height = 0.1 diff --git a/resources/quality/ultimaker3/um3_global_Superdraft_Quality.inst.cfg b/resources/quality/ultimaker3/um3_global_Superdraft_Quality.inst.cfg index be9acd4394..da39b065d5 100644 --- a/resources/quality/ultimaker3/um3_global_Superdraft_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_global_Superdraft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Sprint definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = superdraft -global_quality = True weight = -4 -setting_version = 4 +global_quality = True [values] layer_height = 0.4 diff --git a/resources/quality/ultimaker3/um3_global_Verydraft_Quality.inst.cfg b/resources/quality/ultimaker3/um3_global_Verydraft_Quality.inst.cfg index e2c828fc2d..11e8315a7b 100644 --- a/resources/quality/ultimaker3/um3_global_Verydraft_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_global_Verydraft_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Extra Fast definition = ultimaker3 [metadata] +setting_version = 4 type = quality quality_type = verydraft -global_quality = True weight = -3 -setting_version = 4 +global_quality = True [values] layer_height = 0.3 diff --git a/resources/quality/vertex_delta_k8800/k8800_ABS_Extreme_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_ABS_Extreme_Quality.inst.cfg index 2c42bd82b6..50a1ef3415 100644 --- a/resources/quality/vertex_delta_k8800/k8800_ABS_Extreme_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_ABS_Extreme_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Extreme definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = extreme -material = Vertex_Delta_ABS weight = 2 -setting_version = 4 +material = Vertex_Delta_ABS [values] layer_height = 0.05 @@ -19,4 +19,4 @@ material_initial_print_temperature = 250 material_print_temperature = 250 retraction_amount = 3 material_standby_temperature = 225 -cool_fan_speed = 0 \ No newline at end of file +cool_fan_speed = 0 diff --git a/resources/quality/vertex_delta_k8800/k8800_ABS_High_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_ABS_High_Quality.inst.cfg index a770131adb..e650f11afd 100644 --- a/resources/quality/vertex_delta_k8800/k8800_ABS_High_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_ABS_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = high -material = Vertex_Delta_ABS weight = 1 -setting_version = 4 +material = Vertex_Delta_ABS [values] layer_height = 0.1 @@ -19,4 +19,4 @@ material_initial_print_temperature = 250 material_print_temperature = 250 retraction_amount = 3 material_standby_temperature = 225 -cool_fan_speed = 0 \ No newline at end of file +cool_fan_speed = 0 diff --git a/resources/quality/vertex_delta_k8800/k8800_ABS_Normal_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_ABS_Normal_Quality.inst.cfg index 7c7e635149..aa962190ce 100644 --- a/resources/quality/vertex_delta_k8800/k8800_ABS_Normal_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_ABS_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = normal -material = Vertex_Delta_ABS weight = 0 -setting_version = 4 +material = Vertex_Delta_ABS [values] layer_height = 0.2 @@ -19,4 +19,4 @@ material_initial_print_temperature = 250 material_print_temperature = 250 retraction_amount = 3 material_standby_temperature = 225 -cool_fan_speed = 00 \ No newline at end of file +cool_fan_speed = 00 diff --git a/resources/quality/vertex_delta_k8800/k8800_PET_Extreme_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_PET_Extreme_Quality.inst.cfg index 836d900247..29a4170adf 100644 --- a/resources/quality/vertex_delta_k8800/k8800_PET_Extreme_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_PET_Extreme_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Extreme definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = extreme -material = Vertex_Delta_PET weight = 2 -setting_version = 4 +material = Vertex_Delta_PET [values] layer_height = 0.05 @@ -19,4 +19,4 @@ material_initial_print_temperature = 240 material_print_temperature = 240 retraction_amount = 3 material_standby_temperature = 215 -cool_fan_speed = 10 \ No newline at end of file +cool_fan_speed = 10 diff --git a/resources/quality/vertex_delta_k8800/k8800_PET_High_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_PET_High_Quality.inst.cfg index b0cae312b2..fc92590da1 100644 --- a/resources/quality/vertex_delta_k8800/k8800_PET_High_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_PET_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = high -material = Vertex_Delta_PET weight = 1 -setting_version = 4 +material = Vertex_Delta_PET [values] layer_height = 0.1 @@ -19,4 +19,4 @@ material_initial_print_temperature = 240 material_print_temperature = 240 retraction_amount = 3 material_standby_temperature = 215 -cool_fan_speed = 10 \ No newline at end of file +cool_fan_speed = 10 diff --git a/resources/quality/vertex_delta_k8800/k8800_PET_Normal_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_PET_Normal_Quality.inst.cfg index ebec26d04a..b02bfa5178 100644 --- a/resources/quality/vertex_delta_k8800/k8800_PET_Normal_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_PET_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = normal -material = Vertex_Delta_PET weight = 0 -setting_version = 4 +material = Vertex_Delta_PET [values] layer_height = 0.2 @@ -19,4 +19,4 @@ material_initial_print_temperature = 240 material_print_temperature = 240 retraction_amount = 3 material_standby_temperature = 215 -cool_fan_speed = 10 \ No newline at end of file +cool_fan_speed = 10 diff --git a/resources/quality/vertex_delta_k8800/k8800_PLA_Extreme_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_PLA_Extreme_Quality.inst.cfg index 13ad6455c9..3cdad7a06f 100644 --- a/resources/quality/vertex_delta_k8800/k8800_PLA_Extreme_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_PLA_Extreme_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Extreme definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = extreme -material = Vertex_Delta_PLA weight = 2 -setting_version = 4 +material = Vertex_Delta_PLA [values] layer_height = 0.05 @@ -19,4 +19,4 @@ material_initial_print_temperature = 200 material_print_temperature = 200 retraction_amount = 3 material_standby_temperature = 175 -cool_fan_speed = 40 \ No newline at end of file +cool_fan_speed = 40 diff --git a/resources/quality/vertex_delta_k8800/k8800_PLA_High_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_PLA_High_Quality.inst.cfg index e8c7e893cb..192750ef71 100644 --- a/resources/quality/vertex_delta_k8800/k8800_PLA_High_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_PLA_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = high -material = Vertex_Delta_PLA weight = 1 -setting_version = 4 +material = Vertex_Delta_PLA [values] layer_height = 0.1 @@ -19,4 +19,4 @@ material_initial_print_temperature = 200 material_print_temperature = 200 retraction_amount = 3 material_standby_temperature = 175 -cool_fan_speed = 40 \ No newline at end of file +cool_fan_speed = 40 diff --git a/resources/quality/vertex_delta_k8800/k8800_PLA_Normal_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_PLA_Normal_Quality.inst.cfg index 27002caea2..1e519734bb 100644 --- a/resources/quality/vertex_delta_k8800/k8800_PLA_Normal_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_PLA_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = normal -material = Vertex_Delta_PLA weight = 0 -setting_version = 4 +material = Vertex_Delta_PLA [values] layer_height = 0.2 @@ -19,4 +19,4 @@ material_initial_print_temperature = 200 material_print_temperature = 200 retraction_amount = 3 material_standby_temperature = 175 -cool_fan_speed = 40 \ No newline at end of file +cool_fan_speed = 40 diff --git a/resources/quality/vertex_delta_k8800/k8800_TPU_Extreme_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_TPU_Extreme_Quality.inst.cfg index 8a0a01fb0b..9da37f2148 100644 --- a/resources/quality/vertex_delta_k8800/k8800_TPU_Extreme_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_TPU_Extreme_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Extreme definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = extreme -material = Vertex_Delta_TPU weight = 2 -setting_version = 4 +material = Vertex_Delta_TPU [values] layer_height = 0.05 @@ -19,4 +19,4 @@ material_initial_print_temperature = 220 material_print_temperature = 220 retraction_amount = 3 material_standby_temperature = 195 -cool_fan_speed = 20 \ No newline at end of file +cool_fan_speed = 20 diff --git a/resources/quality/vertex_delta_k8800/k8800_TPU_High_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_TPU_High_Quality.inst.cfg index 7e23947f39..f5583d32b9 100644 --- a/resources/quality/vertex_delta_k8800/k8800_TPU_High_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_TPU_High_Quality.inst.cfg @@ -4,11 +4,11 @@ name = High definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = high -material = Vertex_Delta_TPU weight = 1 -setting_version = 4 +material = Vertex_Delta_TPU [values] layer_height = 0.1 @@ -19,4 +19,4 @@ material_initial_print_temperature = 220 material_print_temperature = 220 retraction_amount = 3 material_standby_temperature = 195 -cool_fan_speed = 20 \ No newline at end of file +cool_fan_speed = 20 diff --git a/resources/quality/vertex_delta_k8800/k8800_TPU_Normal_Quality.inst.cfg b/resources/quality/vertex_delta_k8800/k8800_TPU_Normal_Quality.inst.cfg index 5fb46e1ea6..a520eb2473 100644 --- a/resources/quality/vertex_delta_k8800/k8800_TPU_Normal_Quality.inst.cfg +++ b/resources/quality/vertex_delta_k8800/k8800_TPU_Normal_Quality.inst.cfg @@ -4,11 +4,11 @@ name = Normal definition = vertex_delta_k8800 [metadata] +setting_version = 4 type = quality quality_type = normal -material = Vertex_Delta_TPU weight = 0 -setting_version = 4 +material = Vertex_Delta_TPU [values] layer_height = 0.2 From 8ac9811b41301ccec1eb0678e6530439a027bd6a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 13 Feb 2018 09:29:30 +0100 Subject: [PATCH 040/371] WIP: Create QualityManager --- cura/CuraApplication.py | 11 +- cura/Machines/ContainerGroup.py | 10 + cura/Machines/QualityManager.py | 358 ++++++++++++++++++++++ cura/Settings/MachineManager.py | 8 +- cura/Settings/ProfilesModel.py | 56 ++++ resources/definitions/ultimaker3.def.json | 1 + resources/qml/Menus/ProfileMenu.qml | 13 +- 7 files changed, 450 insertions(+), 7 deletions(-) create mode 100644 cura/Machines/ContainerGroup.py create mode 100644 cura/Machines/QualityManager.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 7812024422..82a112f56f 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -52,7 +52,8 @@ from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyT from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator -from cura.Settings.ProfilesModel import ProfilesModel +from cura.Settings.NozzleModel import NozzleModel +from cura.Settings.ProfilesModel import ProfilesModel, NewQualityProfilesModel from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager @@ -60,6 +61,7 @@ from cura.Settings.UserProfilesModel import UserProfilesModel from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager from cura.Machines.VariantManager import VariantManager +from cura.Machines.QualityManager import QualityGroup from . import PlatformPhysics @@ -738,6 +740,10 @@ class CuraApplication(QtApplication): self._material_manager = MaterialManager(container_registry) self._material_manager.initialize() + from cura.Machines.QualityManager import QualityManager + self._quality_manager = QualityManager(container_registry) + self._quality_manager.initialize() + # Check if we should run as single instance or not self._setUpSingleInstanceServer() @@ -922,6 +928,9 @@ class CuraApplication(QtApplication): qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") + qmlRegisterType(NewQualityProfilesModel, "Cura", 1, 0, "NewQualityProfilesModel") + qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") + qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") qmlRegisterType(QualityAndUserProfilesModel, "Cura", 1, 0, "QualityAndUserProfilesModel") qmlRegisterType(UserProfilesModel, "Cura", 1, 0, "UserProfilesModel") diff --git a/cura/Machines/ContainerGroup.py b/cura/Machines/ContainerGroup.py new file mode 100644 index 0000000000..5c34f0f123 --- /dev/null +++ b/cura/Machines/ContainerGroup.py @@ -0,0 +1,10 @@ +from PyQt5.Qt import QObject + +from cura.Machines.ContainerNode import ContainerNode + + +class ContainerGroup(QObject): + def __init__(self, parent = None): + super().__init__(parent) + self.node_for_global = None # type: ContainerNode + self.nodes_for_extruders = dict() diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py new file mode 100644 index 0000000000..43556dbb4a --- /dev/null +++ b/cura/Machines/QualityManager.py @@ -0,0 +1,358 @@ +from typing import Optional + +from PyQt5.Qt import pyqtSignal, QObject + +from UM.Application import Application +from UM.Logger import Logger +from UM.Settings.InstanceContainer import InstanceContainer +from UM.Util import parseBool + +from cura.Machines.ContainerGroup import ContainerGroup +from cura.Machines.ContainerNode import ContainerNode + + +# +# Quality lookup tree structure: +# +# ------| +# | | +# +# | +# +# | +# +# | +# +# + +# + + +class QualityChangesGroup: + __slots__ = ("name", "qc_for_global", "qc_for_extruders_dict") + + def __init__(self, name: str): + self.name = name # type: str + self.qc_for_global = None # type: Optional["QualityNode"] + self.qc_for_extruders_dict = dict() # -> QualityNode + + def addMetadata(self, metadata: dict): + extruder_id = metadata.get("extruder") + if extruder_id is not None: + self.qc_for_extruders_dict[extruder_id] = QualityNode(metadata) + else: + self.qc_for_global = QualityNode(metadata) + + def getContainerForGlobalStack(self) -> "InstanceContainer": + return self.qc_for_global.getContainer() + + def getContainerForExtruderStack(self, extruder_definition_id: str) -> Optional["InstanceContainer"]: + qc_node = self.qc_for_extruders_dict.get(extruder_definition_id) + container = None + if qc_node is not None: + container = qc_node.getContainer() + return container + + +class QualityGroup(ContainerGroup): + + def __init__(self, name, quality_type, parent = None): + super().__init__(parent) + self.name = name + self.quality_type = quality_type + self.is_available = False + + +class QualityNode(ContainerNode): + __slots__ = ("metadata", "container", "quality_type_map", "children_map") + + def __init__(self, metadata = None): + super().__init__(metadata = metadata) + self.quality_type_map = {} + + + def addQualityMetadata(self, quality_type: str, metadata: dict): + if quality_type not in self.quality_type_map: + self.quality_type_map[quality_type] = QualityNode(metadata) + + def getQualityNode(self, quality_type: str): + return self.quality_type_map.get(quality_type) + + def addQualityChangesMetadata(self, quality_type: str, metadata: dict): + if quality_type not in self.quality_type_map: + self.quality_type_map[quality_type] = QualityNode() + quality_type_node = self.quality_type_map[quality_type] + + name = metadata["name"] + if name not in quality_type_node.children_map: + quality_type_node.children_map[name] = QualityChangesGroup(name) + qc_group = quality_type_node.children_map[name] + qc_group.addMetadata(metadata) + + +class QualityManager(QObject): + + def __init__(self, container_registry, parent = None): + super().__init__(parent) + + self._material_manager = Application.getInstance()._material_manager + + self._container_registry = container_registry + self._empty_quality_container = self._container_registry.findInstanceContainers(id = "empty_quality")[0] + #self._empty_quality_changes_container = self._container_registry.findInstanceContainers(id = "empty_quality_changes")[0] + + self._machine_variant_material_quality_type_to_quality_dict = {} # for quality lookup + self._machine_quality_type_to_quality_changes_dict = {} # for quality_changes lookup + + self._default_machine_definition_id = "fdmprinter" + + def initialize(self): + # Initialize the lookup tree for quality profiles with following structure: + # -> -> + # -> + quality_metadata_list = self._container_registry.findContainersMetadata(type = "quality") + for metadata in quality_metadata_list: + if metadata["id"] == "empty_quality": + continue + + definition_id = metadata["definition"] + quality_type = metadata["quality_type"] + + root_material_id = metadata.get("material") + variant_name = metadata.get("variant") + is_global_quality = metadata.get("global_quality", False) + is_global_quality = is_global_quality or (root_material_id is None and variant_name is None) + + # Sanity check: material+variant and is_global_quality cannot be present at the same time + if is_global_quality and (root_material_id or variant_name): + raise RuntimeError("Quality profile [%s] contains invalid data: it is a global quality but contains 'material' and 'nozzle' info." % metadata["id"]) + + if definition_id not in self._machine_variant_material_quality_type_to_quality_dict: + self._machine_variant_material_quality_type_to_quality_dict[definition_id] = QualityNode() + machine_node = self._machine_variant_material_quality_type_to_quality_dict[definition_id] + + if is_global_quality: + # For global qualities, save data in the machine node + machine_node.addQualityMetadata(quality_type, metadata) + continue + + if variant_name is not None: + # If variant_name is specified in the quality/quality_changes profile, check if material is specified, + # too. + if variant_name not in machine_node.children_map: + machine_node.children_map[variant_name] = QualityNode() + variant_node = machine_node.children_map[variant_name] + + if root_material_id is None: + # If only variant_name is specified but material is not, add the quality/quality_changes metadata + # into the current variant node. + variant_node.addQualityMetadata(quality_type, metadata) + else: + # If only variant_name and material are both specified, go one level deeper: create a material node + # under the current variant node, and then add the quality/quality_changes metadata into the + # material node. + if root_material_id not in variant_node.children_map: + variant_node.children_map[root_material_id] = QualityNode() + material_node = variant_node.children_map[root_material_id] + + material_node.addQualityMetadata(quality_type, metadata) + + else: + # If variant_name is not specified, check if material is specified. + if root_material_id is not None: + if root_material_id not in machine_node.children_map: + machine_node.children_map[root_material_id] = QualityNode() + material_node = machine_node.children_map[root_material_id] + + material_node.addQualityMetadata(quality_type, metadata) + + # Initialize the lookup tree for quality_changes profiles with following structure: + # -> -> + quality_changes_metadata_list = self._container_registry.findContainersMetadata(type = "quality_changes") + for metadata in quality_changes_metadata_list: + if metadata["id"] == "empty_quality_changes": + continue + + machine_definition_id = metadata["definition"] + quality_type = metadata["quality_type"] + + if machine_definition_id not in self._machine_quality_type_to_quality_changes_dict: + self._machine_quality_type_to_quality_changes_dict[machine_definition_id] = QualityNode() + machine_node = self._machine_quality_type_to_quality_changes_dict[machine_definition_id] + + machine_node.addQualityChangesMetadata(quality_type, metadata) + + def getQualityGroups(self, machine: "GlobalStack") -> dict: + # TODO: How to make this simpler, including the fallbacks. + # Get machine definition ID + machine_definition_id = self._default_machine_definition_id + if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): + machine_definition_id = machine.getMetaDataEntry("quality_definition") + if machine_definition_id is None: + machine_definition_id = machine.definition.getId() + + machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) + if not machine_node: + Logger.log("e", "Cannot find node for machine def [%s] in quality lookup table", machine_definition_id) + + # iterate over all quality_types in the machine node + quality_group_dict = {} + for quality_type, quality_node in machine_node.quality_type_map.items(): + quality_group = QualityGroup(quality_node.metadata["name"], quality_type) + quality_group.node_for_global = quality_node + + quality_group_dict[quality_type] = quality_group + + # Iterate over all extruders + for position, extruder in machine.extruders.items(): + variant_name = None + if extruder.variant.getId() != "empty_variant": + variant_name = extruder.variant.getName() + + # This is a list of root material IDs to use for searching for suitable quality profiles. + # The root material IDs in this list are in prioritized order. + root_material_id_list = [] + has_material = False # flag indicating whether this extruder has a material assigned + if extruder.material.getId() != "empty_material": + has_material = True + root_material_id = extruder.material.getMetaDataEntry("base_file") + root_material_id_list.append(root_material_id) + + # Also try to get the fallback material + material_type = extruder.material.getMetaDataEntry("material") + fallback_root_material_metadata = self._material_manager.getFallbackMaterialForType(material_type) + if fallback_root_material_metadata: + root_material_id_list.append(fallback_root_material_metadata["id"]) + + variant_node = None + material_node = None + + if variant_name: + # In this case, we have both a specific variant and a specific material + variant_node = machine_node.getChildNode(variant_name) + if not variant_node: + continue + if has_material: + for root_material_id in root_material_id_list: + material_node = variant_node.getChildNode(root_material_id) + if material_node: + break + if not material_node: + # No suitable quality found: not supported + Logger.log("d", "Cannot find quality with machine [%s], variant name [%s], and materials [%s].", + machine_definition_id, variant_name, ", ".join(root_material_id_list)) + continue + else: + # In this case, we only have a specific material but NOT a variant + if has_material: + for root_material_id in root_material_id_list: + material_node = machine_node.getChildNode(root_material_id) + if material_node: + break + if not material_node: + # No suitable quality found: not supported + Logger.log("d", "Cannot find quality with machine [%s], variant name [%s], and materials [%s].", + machine_definition_id, variant_name, ", ".join(root_material_id_list)) + continue + + node_to_check = material_node + if not node_to_check: + node_to_check = variant_node + if not node_to_check: + node_to_check = machine_node + + for quality_type, quality_node in node_to_check.quality_type_map.items(): + if quality_type not in quality_group_dict: + quality_group = QualityGroup(quality_node.metadata["name"], quality_type) + quality_group_dict[quality_type] = quality_group + + quality_group = quality_group_dict[quality_type] + + quality_group.nodes_for_extruders[position] = quality_node + + used_extruders = set() + # TODO: This will change after the Machine refactoring + for i in range(machine.getProperty("machine_extruder_count", "value")): + used_extruders.add(str(i)) + + # Update the "is_available" flag for each quality group. + for quality_group in quality_group_dict.values(): + is_available = True + if quality_group.node_for_global is None: + is_available = False + if is_available: + for position in used_extruders: + if position not in quality_group.nodes_for_extruders: + is_available = False + break + + quality_group.is_available = is_available + + return quality_group_dict + + + def getQuality(self, quality_type: str, machine: "GlobalStack"): + # Get machine definition ID + machine_definition_id = self._default_machine_definition_id + if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): + machine_definition_id = machine.getMetaDataEntry("quality_definition") + if machine_definition_id is None: + machine_definition_id = machine.definition.getId() + + machine_quality = self.getQualityContainer(quality_type, machine_definition_id) + extruder_quality_dict = {} + for position, extruder in machine.extruders.items(): + variant = extruder.variant + material = extruder.material + + variant_name = variant.getName() + if variant.getId() == "empty_variant": + variant_name = None + root_material_id = material.getMetaDataEntry("base_file") + if material.getId() == "empty_material": + root_material_id = None + + extruder_quality = self.getQualityContainer(quality_type, machine_definition_id, + variant_name, root_material_id) + extruder_quality_dict[position] = extruder_quality + + # TODO: return as a group + return machine_quality, extruder_quality_dict + + def getQualityContainer(self, quality_type: str, machine_definition_id: dict, + variant_name: Optional[str] = None, + root_material_id: Optional[str] = None) -> "InstanceContainer": + assert machine_definition_id is not None + assert quality_type is not None + + # If the specified quality cannot be found, empty_quality will be returned. + container = self._empty_quality_container + + machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) + variant_node = None + material_node = None + if machine_node is not None: + if variant_name is not None: + variant_node = machine_node.getChildNode(variant_name) + if variant_node is not None: + if root_material_id is not None: + material_node = variant_node.getChildNode(root_material_id) + elif root_material_id is not None: + material_node = machine_node.getChildNode(root_material_id) + + nodes_to_try = [material_node, variant_node, machine_node] + if machine_definition_id != self._default_machine_definition_id: + default_machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(self._default_machine_definition_id) + nodes_to_try.append(default_machine_node) + + for node in nodes_to_try: + if node is None: + continue + quality_node = node.getQualityNode(quality_type) + if quality_node is None: + continue + + container = quality_node.getContainer() + break + + return container + diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 1fa4a602bc..f0305751d4 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1509,12 +1509,12 @@ class MachineManager(QObject): self._global_container_stack.extruders[position].variant = container_node.getContainer() @pyqtSlot("QVariant") - def handleQualityGroup(self, quality_group): - Logger.log("d", "---------------- qg = [%s]", quality_group.name) + def handleQualityGroup(self, qg): + Logger.log("d", "---------------- qg = [%s]", qg.name) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): - self._global_container_stack.quality = quality_group.node_for_global.getContainer() + self._global_container_stack.quality = qg.node_for_global.getContainer() self._global_container_stack.qualityChanges = self._empty_quality_changes_container - for position, node in quality_group.nodes_for_extruders.items(): + for position, node in qg.nodes_for_extruders.items(): self._global_container_stack.extruders[position].quality = node.getContainer() self._global_container_stack.extruders[position].qualityChanges = self._empty_quality_changes_container diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index 77cd407457..719a406406 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -18,6 +18,62 @@ if TYPE_CHECKING: from cura.Settings.ExtruderStack import ExtruderStack +from UM.Qt.ListModel import ListModel + + +class NewQualityProfilesModel(ListModel): + IdRole = Qt.UserRole + 1 + NameRole = Qt.UserRole + 2 + QualityTypeRole = Qt.UserRole + 3 + LayerHeightRole = Qt.UserRole + 4 + AvailableRole = Qt.UserRole + 5 + QualityGroupRole = Qt.UserRole + 6 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.IdRole, "id") + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.QualityTypeRole, "quality_type") + self.addRoleName(self.LayerHeightRole, "layer_height") + self.addRoleName(self.AvailableRole, "available") + self.addRoleName(self.QualityGroupRole, "quality_group") + + # TODO: connect signals + Application.getInstance().globalContainerStackChanged.connect(self._update) + Application.getInstance().getMachineManager().activeVariantChanged.connect(self._update) + Application.getInstance().getMachineManager().activeStackChanged.connect(self._update) + Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update) + + def _update(self): + # TODO: get all available qualities + self.items.clear() + + quality_manager = Application.getInstance()._quality_manager + active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + if active_global_stack is None: + self.setItems([]) + return + + quality_group_dict = quality_manager.getQualityGroups(active_global_stack) + + item_list = [] + + for key in sorted(quality_group_dict): + quality_group = quality_group_dict[key] + + item = {"id": "TODO", + "name": quality_group.name, + "layer_height": "TODO", + "available": quality_group.is_available, + "quality_group": quality_group} + + item_list.append(item) + + self.setItems(item_list) + + + ## QML Model for listing the current list of valid quality profiles. # class ProfilesModel(InstanceContainersModel): diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 826960a621..74e4a9551e 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -17,6 +17,7 @@ "has_variants": true, "preferred_variant": "*aa04*", "preferred_quality": "*Normal*", + "preferred_quality_type": "fine", "variants_name": "Print core", "machine_extruder_trains": { diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index f543bb36eb..bde60a3dde 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -11,9 +11,15 @@ Menu { id: menu + // TODO: single instance + Cura.NewQualityProfilesModel + { + id: qualityProfilesModel + } + Instantiator { - model: Cura.ProfilesModel + model: qualityProfilesModel MenuItem { @@ -21,7 +27,10 @@ Menu checkable: true checked: Cura.MachineManager.activeQualityId == model.id exclusiveGroup: group - onTriggered: Cura.MachineManager.setActiveQuality(model.id) + onTriggered: { + Cura.MachineManager.handleQualityGroup(model.quality_group) + //Cura.MachineManager.setActiveQuality(model.id) + } visible: model.available } From 0f045ce1213859bd50861aed6cfd733c614f68dd Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 8 Feb 2018 16:28:26 +0100 Subject: [PATCH 041/371] WIP: TO BE REMOVED: TestTools plugin --- plugins/TestTools/TestTool.py | 27 +++++++++++++++++++++++++++ plugins/TestTools/__init__.py | 13 +++++++++++++ plugins/TestTools/plugin.json | 7 +++++++ 3 files changed, 47 insertions(+) create mode 100644 plugins/TestTools/TestTool.py create mode 100644 plugins/TestTools/__init__.py create mode 100644 plugins/TestTools/plugin.json diff --git a/plugins/TestTools/TestTool.py b/plugins/TestTools/TestTool.py new file mode 100644 index 0000000000..3c852e5997 --- /dev/null +++ b/plugins/TestTools/TestTool.py @@ -0,0 +1,27 @@ +# Copyright (c) 2016 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. +from UM.Extension import Extension + +from PyQt5.QtCore import QObject + + +class TestTool(Extension, QObject): + def __init__(self, parent = None): + QObject.__init__(self, parent) + Extension.__init__(self) + + self.addMenuItem("Test material manager", self._testMaterialManager) + self.addMenuItem("Test get quality", self._testGetQuality) + + def _testMaterialManager(self): + print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + from cura.CuraApplication import CuraApplication + CuraApplication.getInstance()._material_manager._test_metadata() + + def _testGetQuality(self): + print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + from cura.CuraApplication import CuraApplication + result_dict = {} + global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack + result = CuraApplication.getInstance()._quality_manager.getQualityGroups(global_stack) + diff --git a/plugins/TestTools/__init__.py b/plugins/TestTools/__init__.py new file mode 100644 index 0000000000..7d41651404 --- /dev/null +++ b/plugins/TestTools/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2016 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from . import TestTool + +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + +def getMetaData(): + return {} + +def register(app): + return {"extension": TestTool.TestTool()} diff --git a/plugins/TestTools/plugin.json b/plugins/TestTools/plugin.json new file mode 100644 index 0000000000..846e39bf09 --- /dev/null +++ b/plugins/TestTools/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "Test Tools", + "author": "Ultimaker", + "version": "1.0", + "description": "Dump the contents of all settings to a HTML file.", + "api": 4 +} \ No newline at end of file From e65adc72580472ad3b8ec18403654ca7934e4bc2 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 13 Feb 2018 16:46:47 +0100 Subject: [PATCH 042/371] WIP: New setMaterial/Variant/Quality in MachineManager --- cura/Settings/MachineManager.py | 103 +++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 8 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f0305751d4..000fb93e0e 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -132,6 +132,9 @@ class MachineManager(QObject): if containers: containers[0].nameChanged.connect(self._onMaterialNameChanged) + ### new + self._current_quality_group = None + globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value) activeMaterialChanged = pyqtSignal() activeVariantChanged = pyqtSignal() @@ -1500,21 +1503,105 @@ class MachineManager(QObject): return [ s.containersChanged for s in stacks ] # New + def _setEmptyQuality(self): + self._current_quality_group = None + self._global_container_stack.quality = self._empty_quality_container + self._global_container_stack.qualityChanges = self._empty_quality_changes_container + for extruder in self._global_container_stack.extruders.values(): + extruder.quality = self._empty_quality_container + extruder.qualityChanges = self._empty_quality_changes_container + + def _setQualityGroup(self, quality_group, empty_quality_changes = True): + self._current_quality_group = quality_group + self._global_container_stack.quality = quality_group.node_for_global.getContainer() + if empty_quality_changes: + self._global_container_stack.qualityChanges = self._empty_quality_changes_container + for position, node in quality_group.nodes_for_extruders.items(): + self._global_container_stack.extruders[position].quality = node.getContainer() + if empty_quality_changes: + self._global_container_stack.extruders[position].qualityChanges = self._empty_quality_changes_container + + def _setVariantGroup(self, position, container_node): + self._global_container_stack.extruders[position].variant = container_node.getContainer() + + def _setMaterial(self, position, container_node = None): + if container_node: + self._global_container_stack.extruders[position].material = container_node.getContainer() + else: + self._global_container_stack.extruders[position].material = self._empty_material_container + + ## Update current quality type and machine after setting material + def _updateQualityWithMaterial(self): + current_quality = None + if self._current_quality_group: + current_quality = self._current_quality_group.quality_type + quality_manager = Application.getInstance()._quality_manager + candidate_quality_groups = quality_manager.getQualityGroups(self._global_container_stack) + available_quality_types = {qt for qt, g in candidate_quality_groups.items() if g.is_available} + + if not available_quality_types: + self._setEmptyQuality() + return + + if current_quality in available_quality_types: + self._setQualityGroup(candidate_quality_groups[current_quality], empty_quality_changes = False) + return + + quality_type = sorted(list(available_quality_types))[0] + preferred_quality_type = self._global_container_stack.getMetaDataEntry("preferred_quality_type") + if preferred_quality_type in available_quality_types: + quality_type = preferred_quality_type + + self._setQualityGroup(candidate_quality_groups[quality_type], empty_quality_changes = False) + + def _updateMaterialWithVariant(self, position, current_material_base_name, current_variant_name): + material_manager = Application.getInstance()._material_manager + material_diameter = self._global_container_stack.getProperty("material_diameter", "value") + candidate_materials = material_manager.getAvailableMaterials( + self._global_container_stack.getId(), + current_variant_name, + material_diameter) + + if not candidate_materials: + self._setMaterial(position, container_node = None) + return + + if current_material_base_name in candidate_materials: + new_material = candidate_materials[current_material_base_name] + self._setMaterial(position, new_material) + return + + # # Find a fallback material + # preferred_material_query = self._global_container_stack.getMetaDataEntry("preferred_material") + # preferred_material_key = preferred_material_query.replace("*", "") + # if preferred_material_key in candidate_materials: + # self._setMaterial(position, candidate_materials[preferred_material_key]) + # return + + @pyqtSlot(str, "QVariant") + def setMaterial(self, position, container_node): + Logger.log("d", "---------------- container = [%s]", container_node) + position = str(position) + self.blurSettings.emit() + with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): + self._setMaterial(position, container_node) + self._updateQualityWithMaterial() + @pyqtSlot(str, "QVariant") def setVariantGroup(self, position, container_node): Logger.log("d", "---------------- container = [%s]", container_node) position = str(position) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): - self._global_container_stack.extruders[position].variant = container_node.getContainer() + self._setVariantGroup(position, container_node) + current_variant_name = container_node.metadata["name"] + current_material_base_name = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") + self._updateMaterialWithVariant(position, current_material_base_name, current_variant_name) + self._updateQualityWithMaterial() @pyqtSlot("QVariant") - def handleQualityGroup(self, qg): - Logger.log("d", "---------------- qg = [%s]", qg.name) + def handleQualityGroup(self, quality_group): + Logger.log("d", "---------------- qg = [%s]", quality_group.name) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): - self._global_container_stack.quality = qg.node_for_global.getContainer() - self._global_container_stack.qualityChanges = self._empty_quality_changes_container - for position, node in qg.nodes_for_extruders.items(): - self._global_container_stack.extruders[position].quality = node.getContainer() - self._global_container_stack.extruders[position].qualityChanges = self._empty_quality_changes_container + self._setQualityGroup(quality_group) From d99bacb2d2ebe586ed1e7a2f6c68d22b4b5656cd Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 13 Feb 2018 21:13:44 +0100 Subject: [PATCH 043/371] WIP: Create ContainerNode and ContainerGroup --- cura/Machines/ContainerGroup.py | 5 ++++- cura/Machines/ContainerNode.py | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/cura/Machines/ContainerGroup.py b/cura/Machines/ContainerGroup.py index 5c34f0f123..1061abadda 100644 --- a/cura/Machines/ContainerGroup.py +++ b/cura/Machines/ContainerGroup.py @@ -1,10 +1,13 @@ +from typing import Optional + from PyQt5.Qt import QObject from cura.Machines.ContainerNode import ContainerNode class ContainerGroup(QObject): + def __init__(self, parent = None): super().__init__(parent) - self.node_for_global = None # type: ContainerNode + self.node_for_global = None # type: Optional[ContainerNode] self.nodes_for_extruders = dict() diff --git a/cura/Machines/ContainerNode.py b/cura/Machines/ContainerNode.py index b9ebaa698a..059bccba0d 100644 --- a/cura/Machines/ContainerNode.py +++ b/cura/Machines/ContainerNode.py @@ -3,25 +3,37 @@ from typing import Optional from collections import OrderedDict from UM.Logger import Logger +from UM.Settings.InstanceContainer import InstanceContainer -## A metadata / container combination. Use getContainer to get the container corresponding to the metadata +## +# A metadata / container combination. Use getContainer() to get the container corresponding to the metadata. +# +# ContainerNode is a multi-purpose class. It has two main purposes: +# 1. It encapsulates an InstanceContainer. It contains that InstanceContainer's +# - metadata (Always) +# - container (lazy-loaded when needed) +# 2. It also serves as a node in a hierarchical InstanceContainer lookup table/tree. +# This is used in Variant, Material, and Quality Managers. +# class ContainerNode: - def __init__(self, metadata = None): + __slots__ = ("metadata", "container", "children_map") + + def __init__(self, metadata: Optional[dict] = None): self.metadata = metadata self.container = None self.children_map = OrderedDict() - def getChildNode(self, child_key: str) -> Optional["QualityNode"]: + def getChildNode(self, child_key: str) -> Optional["ContainerNode"]: return self.children_map.get(child_key) def getContainer(self) -> "InstanceContainer": if self.metadata is None: - raise RuntimeError("Cannot get container for a QualityNode without metadata") + raise RuntimeError("Cannot get container for a ContainerNode without metadata") if self.container is None: container_id = self.metadata["id"] - Logger.log("d", "Lazy-loading container [%s]", container_id) + Logger.log("i", "Lazy-loading container [%s]", container_id) from UM.Settings.ContainerRegistry import ContainerRegistry container_list = ContainerRegistry.getInstance().findInstanceContainers(id = container_id) if not container_list: @@ -30,5 +42,5 @@ class ContainerNode: return self.container - def __str__(self): + def __str__(self) -> str: return "ContainerNode[%s]" % self.metadata.get("id") From 8f8de0454f2e5cf6d6697e045f7d5ad5da8ceab9 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 13 Feb 2018 21:34:23 +0100 Subject: [PATCH 044/371] WIP: Cleanup the current MachineManager --- cura/Settings/MachineManager.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 000fb93e0e..a2be0e0e27 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -652,25 +652,6 @@ class MachineManager(QObject): return 0 # No quality profile. - ## Get the Material ID associated with the currently active material - # \returns MaterialID (string) if found, empty string otherwise - @pyqtProperty(str, notify=activeQualityChanged) - def activeQualityMaterialId(self) -> str: - if self._active_container_stack: - quality = self._active_container_stack.quality - if quality: - material_id = quality.getMetaDataEntry("material") - if material_id: - # if the currently active machine inherits its qualities from a different machine - # definition, make sure to return a material that is relevant to that machine definition - definition_id = self.activeDefinitionId - quality_definition_id = self.activeQualityDefinitionId - if definition_id != quality_definition_id: - material_id = material_id.replace(definition_id, quality_definition_id, 1) - - return material_id - return "" - @pyqtProperty(str, notify=activeQualityChanged) def activeQualityName(self) -> str: if self._active_container_stack and self._global_container_stack: From cd53ae06390db7e7da853c77bcedecd0dbadb1cd Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 13 Feb 2018 21:33:43 +0100 Subject: [PATCH 045/371] WIP: Refactor ProfileMenu.qml --- cura/CuraApplication.py | 9 ++++- cura/Machines/ContainerGroup.py | 9 ++++- cura/Machines/QualityManager.py | 5 +-- cura/Settings/MachineManager.py | 20 +++++++++- cura/Settings/ProfilesModel.py | 59 +++++++++++++++++++++-------- resources/qml/Menus/ProfileMenu.qml | 36 +++--------------- 6 files changed, 83 insertions(+), 55 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 82a112f56f..9a74cde13f 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -388,6 +388,8 @@ class CuraApplication(QtApplication): self.getCuraSceneController().setActiveBuildPlate(0) # Initialize + self._new_quality_profile_model = None + CuraApplication.Created = True @pyqtSlot(str, result = str) @@ -896,6 +898,11 @@ class CuraApplication(QtApplication): def getPrintInformation(self): return self._print_information + def getNewQualityProfileModel(self, *args, **kwargs): + if self._new_quality_profile_model is None: + self._new_quality_profile_model = NewQualityProfilesModel(self) + return self._new_quality_profile_model + ## Registers objects for the QML engine to use. # # \param engine The QML engine. @@ -928,7 +935,7 @@ class CuraApplication(QtApplication): qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") - qmlRegisterType(NewQualityProfilesModel, "Cura", 1, 0, "NewQualityProfilesModel") + qmlRegisterSingletonType(NewQualityProfilesModel, "Cura", 1, 0, "NewQualityProfilesModel", self.getNewQualityProfileModel) qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") diff --git a/cura/Machines/ContainerGroup.py b/cura/Machines/ContainerGroup.py index 1061abadda..3b17a0ae60 100644 --- a/cura/Machines/ContainerGroup.py +++ b/cura/Machines/ContainerGroup.py @@ -1,13 +1,18 @@ from typing import Optional -from PyQt5.Qt import QObject +from PyQt5.Qt import QObject, pyqtSlot from cura.Machines.ContainerNode import ContainerNode class ContainerGroup(QObject): - def __init__(self, parent = None): + def __init__(self, name: str, parent = None): super().__init__(parent) + self.name = name self.node_for_global = None # type: Optional[ContainerNode] self.nodes_for_extruders = dict() + + @pyqtSlot(result = str) + def getName(self) -> str: + return self.name diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 43556dbb4a..7d998361b1 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -55,9 +55,8 @@ class QualityChangesGroup: class QualityGroup(ContainerGroup): - def __init__(self, name, quality_type, parent = None): - super().__init__(parent) - self.name = name + def __init__(self, name: str, quality_type: str, parent = None): + super().__init__(name, parent) self.quality_type = quality_type self.is_available = False diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index a2be0e0e27..aeec747fa5 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -46,6 +46,7 @@ if TYPE_CHECKING: class MachineManager(QObject): + def __init__(self, parent = None): super().__init__(parent) @@ -132,9 +133,13 @@ class MachineManager(QObject): if containers: containers[0].nameChanged.connect(self._onMaterialNameChanged) - ### new + ### NEW self._current_quality_group = None + ### NEW + activeQualityGroupChanged = pyqtSignal() + + globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value) activeMaterialChanged = pyqtSignal() activeVariantChanged = pyqtSignal() @@ -1494,14 +1499,20 @@ class MachineManager(QObject): def _setQualityGroup(self, quality_group, empty_quality_changes = True): self._current_quality_group = quality_group + + # Set quality and quality_changes for the GlobalStack self._global_container_stack.quality = quality_group.node_for_global.getContainer() if empty_quality_changes: self._global_container_stack.qualityChanges = self._empty_quality_changes_container + + # Set quality and quality_changes for each ExtruderStack for position, node in quality_group.nodes_for_extruders.items(): self._global_container_stack.extruders[position].quality = node.getContainer() if empty_quality_changes: self._global_container_stack.extruders[position].qualityChanges = self._empty_quality_changes_container + self.activeQualityGroupChanged.emit() + def _setVariantGroup(self, position, container_node): self._global_container_stack.extruders[position].variant = container_node.getContainer() @@ -1581,8 +1592,13 @@ class MachineManager(QObject): self._updateQualityWithMaterial() @pyqtSlot("QVariant") - def handleQualityGroup(self, quality_group): + def setQualityGroup(self, quality_group): Logger.log("d", "---------------- qg = [%s]", quality_group.name) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setQualityGroup(quality_group) + + @pyqtProperty("QVariant", fset = setQualityGroup, notify = activeQualityGroupChanged) + def activeQualityGroup(self): + return self._current_quality_group + diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index 719a406406..fd508f247a 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -2,25 +2,24 @@ # Cura is released under the terms of the LGPLv3 or higher. from collections import OrderedDict +from typing import List, TYPE_CHECKING from PyQt5.QtCore import Qt from UM.Application import Application +from UM.Logger import Logger +from UM.Qt.ListModel import ListModel from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel from cura.QualityManager import QualityManager from cura.Settings.ExtruderManager import ExtruderManager - -from typing import List, TYPE_CHECKING +from cura.Machines.QualityManager import QualityGroup if TYPE_CHECKING: from cura.Settings.ExtruderStack import ExtruderStack -from UM.Qt.ListModel import ListModel - - class NewQualityProfilesModel(ListModel): IdRole = Qt.UserRole + 1 NameRole = Qt.UserRole + 2 @@ -39,32 +38,35 @@ class NewQualityProfilesModel(ListModel): self.addRoleName(self.AvailableRole, "available") self.addRoleName(self.QualityGroupRole, "quality_group") - # TODO: connect signals + # connect signals Application.getInstance().globalContainerStackChanged.connect(self._update) - Application.getInstance().getMachineManager().activeVariantChanged.connect(self._update) - Application.getInstance().getMachineManager().activeStackChanged.connect(self._update) - Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update) + Application.getInstance().getMachineManager().activeQualityGroupChanged.connect(self._update) + + self._quality_manager = Application.getInstance()._quality_manager + + self._layer_height_unit = "" # This is cached def _update(self): - # TODO: get all available qualities - self.items.clear() + Logger.log("d", "Updating quality profile model ...") - quality_manager = Application.getInstance()._quality_manager active_global_stack = Application.getInstance().getMachineManager()._global_container_stack if active_global_stack is None: self.setItems([]) + Logger.log("d", "No active GlobalStack, set quality profile model as empty.") return - quality_group_dict = quality_manager.getQualityGroups(active_global_stack) + quality_group_dict = self._quality_manager.getQualityGroups(active_global_stack) item_list = [] - for key in sorted(quality_group_dict): quality_group = quality_group_dict[key] - item = {"id": "TODO", + layer_height = self._fetchLayerHeight(quality_group) + + item = {"id": "TODO", # TODO: probably will be removed "name": quality_group.name, - "layer_height": "TODO", + "layer_height": layer_height + self._layer_height_unit, + "layer_height_without_unit": layer_height, "available": quality_group.is_available, "quality_group": quality_group} @@ -72,6 +74,31 @@ class NewQualityProfilesModel(ListModel): self.setItems(item_list) + def _fetchLayerHeight(self, quality_group: "QualityGroup"): + active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + if not self._layer_height_unit: + unit = active_global_stack.definition.getProperty("layer_height", "unit") + if not unit: + unit = "" + self._layer_height_unit = unit + + if not quality_group.is_available: + return "" + + # Get layer_height from the quality profile for the GlobalStack + container = quality_group.node_for_global.getContainer() + + layer_height = "" + if container.hasProperty("layer_height", "value"): + layer_height = str(container.getProperty("layer_height", "value")) + else: + # Look for layer_height in the GlobalStack from material -> definition + for idx in range(4): + container = active_global_stack.getContainer(idx) + if container.hasProperty("layer_height", "value"): + layer_height = container.getProperty("layer_height", "value") + break + return str(layer_height) ## QML Model for listing the current list of valid quality profiles. diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index bde60a3dde..9013216e32 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -1,8 +1,8 @@ // Copyright (c) 2016 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick 2.8 +import QtQuick.Controls 1.4 import UM 1.2 as UM import Cura 1.0 as Cura @@ -11,25 +11,18 @@ Menu { id: menu - // TODO: single instance - Cura.NewQualityProfilesModel - { - id: qualityProfilesModel - } - Instantiator { - model: qualityProfilesModel + model: Cura.NewQualityProfilesModel MenuItem { text: (model.layer_height != "") ? model.name + " - " + model.layer_height : model.name checkable: true - checked: Cura.MachineManager.activeQualityId == model.id + checked: Cura.MachineManager.activeQualityGroup.getName() == model.name exclusiveGroup: group onTriggered: { - Cura.MachineManager.handleQualityGroup(model.quality_group) - //Cura.MachineManager.setActiveQuality(model.id) + Cura.MachineManager.setQualityGroup(model.quality_group) } visible: model.available } @@ -82,23 +75,4 @@ Menu MenuItem { action: Cura.Actions.resetProfile } MenuSeparator { } MenuItem { action: Cura.Actions.manageProfiles } - - function getFilter(initial_conditions) - { - var result = initial_conditions; - - if(Cura.MachineManager.filterQualityByMachine) - { - result.definition = Cura.MachineManager.activeQualityDefinitionId; - if(Cura.MachineManager.hasMaterials) - { - result.material = Cura.MachineManager.activeQualityMaterialId; - } - } - else - { - result.definition = "fdmprinter" - } - return result - } } From 54363bad025072822488ae6bfb708a8b91e8112e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 13 Feb 2018 22:37:43 +0100 Subject: [PATCH 046/371] WIP: Refactor NozzleMenu.qml --- cura/Settings/MachineManager.py | 6 ++-- resources/qml/Menus/NozzleMenu.qml | 45 ++---------------------------- 2 files changed, 7 insertions(+), 44 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index aeec747fa5..d4ca2e7d47 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1168,11 +1168,11 @@ class MachineManager(QObject): return "" @pyqtProperty(str, notify = activeVariantChanged) - def activeVariantId(self) -> str: + def activeVariantName(self) -> str: if self._active_container_stack: variant = self._active_container_stack.variant if variant: - return variant.getId() + return variant.getName() return "" @@ -1488,7 +1488,9 @@ class MachineManager(QObject): stacks.append(self._global_container_stack) return [ s.containersChanged for s in stacks ] + # # New + # def _setEmptyQuality(self): self._current_quality_group = None self._global_container_stack.quality = self._empty_quality_container diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index 6d554218a1..27082cfb4b 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -16,20 +16,19 @@ Menu property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 property bool isClusterPrinter: { - if(Cura.MachineManager.printerOutputDevices.length == 0) + if (Cura.MachineManager.printerOutputDevices.length == 0) { return false; } var clusterSize = Cura.MachineManager.printerOutputDevices[0].clusterSize; // This is not a cluster printer or the cluster it is just one printer - if(clusterSize == undefined || clusterSize == 1) + if (clusterSize == undefined || clusterSize == 1) { return false; } return true; } - // TODO: single instance?? Cura.NozzleModel { id: nozzleModel @@ -43,55 +42,17 @@ Menu { text: model.hotend_name checkable: true - checked: Cura.MachineManager.activeVariantId == model.hotend_name + checked: Cura.MachineManager.activeVariantName == model.hotend_name exclusiveGroup: group onTriggered: { var position = Cura.ExtruderManager.activeExtruderIndex; Cura.MachineManager.setVariantGroup(position, model.container_node); } - visible: true } onObjectAdded: menu.insertItem(index, object); onObjectRemoved: menu.removeItem(object); } - /* - Instantiator - { - id: nozzleInstantiator - model: UM.InstanceContainersModel - { - filter: - { - var filter_dict = - { - "type": "variant", - "definition": Cura.MachineManager.activeQualityDefinitionId //Only show variants of this machine - } - if (Cura.MachineManager.hasVariantBuildplates) - { - filter_dict["hardware_type"] = "nozzle" - } - - return filter_dict - } - } - MenuItem { - text: model.name - checkable: true - checked: model.id == Cura.MachineManager.allActiveVariantIds[Cura.ExtruderManager.extruderIds[extruderIndex]] - exclusiveGroup: group - onTriggered: - { - var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; - Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); - Cura.MachineManager.setActiveVariant(model.id); - Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); - } - } - onObjectAdded: menu.insertItem(index, object) - onObjectRemoved: menu.removeItem(object) - } */ ExclusiveGroup { id: group } } From 27169e883cdc557f3c6ca1876fd546af4144db66 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 14 Feb 2018 10:34:56 +0100 Subject: [PATCH 047/371] CURA-4606 Ensure the correct material is highlighted in the material menu --- cura/Machines/MaterialManager.py | 3 +- cura/Settings/MachineManager.py | 18 ++++++++- resources/qml/Menus/MaterialMenu.qml | 59 +--------------------------- 3 files changed, 20 insertions(+), 60 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 596da50fb2..b65e01487c 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -4,7 +4,6 @@ from PyQt5.Qt import QTimer, QObject, pyqtSignal from UM.Logger import Logger from UM.Settings import ContainerRegistry -from UM.Settings import InstanceContainer from cura.Machines.ContainerNode import ContainerNode @@ -227,7 +226,7 @@ class MaterialManager(QObject): # 1. the given machine doesn't have materials; # 2. cannot find any material InstanceContainers with the given settings. # - def getMaterial(self, machine_definition_id: str, variant_name: Optional[str], diameter: float, root_material_id: str) -> Optional["InstanceContainer"]: + def getMaterialNode(self, machine_definition_id: str, variant_name: Optional[str], diameter: float, root_material_id: str) -> Optional["InstanceContainer"]: # round the diameter to get the approximate diameter rounded_diameter = str(round(diameter)) if rounded_diameter not in self._diameter_machine_variant_material_map: diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index d4ca2e7d47..bb2f8cbd79 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -135,11 +135,11 @@ class MachineManager(QObject): ### NEW self._current_quality_group = None + self._current_root_material_id = {} ### NEW activeQualityGroupChanged = pyqtSignal() - globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value) activeMaterialChanged = pyqtSignal() activeVariantChanged = pyqtSignal() @@ -155,6 +155,8 @@ class MachineManager(QObject): outputDevicesChanged = pyqtSignal() + rootMaterialChanged = pyqtSignal() + def _onOutputDevicesChanged(self) -> None: for printer_output_device in self._printer_output_devices: printer_output_device.hotendIdChanged.disconnect(self._onHotendIdChanged) @@ -1491,6 +1493,15 @@ class MachineManager(QObject): # # New # + + @pyqtProperty("QVariant", notify = rootMaterialChanged) + def currentRootMaterialId(self): + # initial filling the current_root_material_id + for position in self._global_container_stack.extruders: + if position not in self._current_root_material_id: + self._current_root_material_id[position] = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") + return self._current_root_material_id + def _setEmptyQuality(self): self._current_quality_group = None self._global_container_stack.quality = self._empty_quality_container @@ -1523,6 +1534,11 @@ class MachineManager(QObject): self._global_container_stack.extruders[position].material = container_node.getContainer() else: self._global_container_stack.extruders[position].material = self._empty_material_container + # The _current_root_material_id is used in the MaterialMenu to see which material is selected + root_material_id = container_node.metadata["base_file"] + if root_material_id != self._current_root_material_id[position]: + self._current_root_material_id[position] = root_material_id + self.rootMaterialChanged.emit() ## Update current quality type and machine after setting material def _updateQualityWithMaterial(self): diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 111e5ab6af..cb4ee5eefb 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -14,48 +14,6 @@ Menu property int extruderIndex: 0 property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 - property bool isClusterPrinter: - { - if(Cura.MachineManager.printerOutputDevices.length == 0) - { - return false; - } - var clusterSize = Cura.MachineManager.printerOutputDevices[0].clusterSize; - // This is not a cluster printer or the cluster it is just one printer - if(clusterSize == undefined || clusterSize == 1) - { - return false; - } - return true; - } - - MenuItem - { - id: automaticMaterial - text: - { - if(visible) - { - var materialName = Cura.MachineManager.printerOutputDevices[0].materialNames[extruderIndex]; - return catalog.i18nc("@title:menuitem %1 is the automatically selected material", "Automatic: %1").arg(materialName); - } - return ""; - } - visible: printerConnected && Cura.MachineManager.printerOutputDevices[0].materialNames != undefined && Cura.MachineManager.printerOutputDevices[0].materialNames.length > extruderIndex && !isClusterPrinter - onTriggered: - { - var materialId = Cura.MachineManager.printerOutputDevices[0].materialIds[extruderIndex]; - var items = materialsModel.items; - for(var i in items) - { - if (items[i]["metadata"]["GUID"] == materialId) - { - Cura.MachineManager.setActiveMaterial(items[i].id); - break; - } - } - } - } MenuSeparator { @@ -69,19 +27,11 @@ Menu { text: model.name checkable: true - checked: model.id == Cura.MachineManager.allActiveMaterialIds[Cura.ExtruderManager.extruderIds[extruderIndex]] + checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[Cura.ExtruderManager.activeExtruderIndex] exclusiveGroup: group onTriggered: { - - const container_id = model.id; - // This workaround is done because of the application menus for materials and variants for multiextrusion printers. - // The extruder menu would always act on the correspoding extruder only, instead of acting on the extruder selected in the UI. - var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; - //Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); - //Cura.MachineManager.setActiveMaterial(container_id); - //Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); Cura.MachineManager.setMaterial(activeExtruderIndex, model.container_node); } } @@ -120,13 +70,8 @@ Menu exclusiveGroup: group onTriggered: { - const container_id = model.id; - // This workaround is done because of the application menus for materials and variants for multiextrusion printers. - // The extruder menu would always act on the correspoding extruder only, instead of acting on the extruder selected in the UI. var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; - Cura.ExtruderManager.setActiveExtruderIndex(extruderIndex); - Cura.MachineManager.setActiveMaterial(container_id); - Cura.ExtruderManager.setActiveExtruderIndex(activeExtruderIndex); + Cura.MachineManager.setMaterial(activeExtruderIndex, model.container_node); } } onObjectAdded: brandMaterialsMenu.insertItem(index, object) From d84ea07e9efe54ce90be2524803fa5a2d753f81d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 09:31:42 +0100 Subject: [PATCH 048/371] WIP: add getQaulityChangesGroup() --- cura/Machines/ContainerNode.py | 2 +- cura/Machines/QualityManager.py | 147 ++++++++++++++++++++++---------- plugins/TestTools/TestTool.py | 14 ++- 3 files changed, 113 insertions(+), 50 deletions(-) diff --git a/cura/Machines/ContainerNode.py b/cura/Machines/ContainerNode.py index 059bccba0d..4d8d663284 100644 --- a/cura/Machines/ContainerNode.py +++ b/cura/Machines/ContainerNode.py @@ -43,4 +43,4 @@ class ContainerNode: return self.container def __str__(self) -> str: - return "ContainerNode[%s]" % self.metadata.get("id") + return "%s[%s]" % (self.__class__.__name__, self.metadata.get("id")) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 7d998361b1..0e9bf99bd4 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -27,30 +27,48 @@ from cura.Machines.ContainerNode import ContainerNode # -class QualityChangesGroup: - __slots__ = ("name", "qc_for_global", "qc_for_extruders_dict") +class QualityChangesGroup(ContainerGroup): - def __init__(self, name: str): - self.name = name # type: str - self.qc_for_global = None # type: Optional["QualityNode"] - self.qc_for_extruders_dict = dict() # -> QualityNode + def __init__(self, name: str, parent = None): + super().__init__(name, parent) + + def addNode(self, node: "QualityNode"): + # TODO: in 3.2 and earlier, a quality_changes container may have a field called "extruder" which contains the + # extruder definition ID it belongs to. But, in fact, we only need to know the following things: + # 1. which machine a custom profile is suitable for, + # 2. if this profile is for the GlobalStack, + # 3. if this profile is for an ExtruderStack and which one (the position). + # + # So, it is preferred to have a field like this: + # extruder_position = 1 + # instead of this: + # extruder = custom_extruder_1 + # + # An upgrade needs to be done if we want to do it this way. Before that, we use the extruder's definition + # to figure out its position. + # + extruder_definition_id = node.metadata.get("extruder") + if extruder_definition_id: + container_registry = Application.getInstance().getContainerRegistry() + metadata_list = container_registry.findDefinitionContainersMetadata(id = extruder_definition_id) + if not metadata_list: + raise RuntimeError("%s cannot get metadata for extruder definition [%s]" % + (self, extruder_definition_id)) + extruder_definition_metadata = metadata_list[0] + extruder_position = str(extruder_definition_metadata["position"]) + + if extruder_position in self.nodes_for_extruders: + raise RuntimeError("%s tries to overwrite the existing nodes_for_extruders position [%s] %s with %s" % + (self, extruder_position, self.node_for_global, node)) + + self.nodes_for_extruders[extruder_position] = node - def addMetadata(self, metadata: dict): - extruder_id = metadata.get("extruder") - if extruder_id is not None: - self.qc_for_extruders_dict[extruder_id] = QualityNode(metadata) else: - self.qc_for_global = QualityNode(metadata) - - def getContainerForGlobalStack(self) -> "InstanceContainer": - return self.qc_for_global.getContainer() - - def getContainerForExtruderStack(self, extruder_definition_id: str) -> Optional["InstanceContainer"]: - qc_node = self.qc_for_extruders_dict.get(extruder_definition_id) - container = None - if qc_node is not None: - container = qc_node.getContainer() - return container + # This is a quality_changes for the GlobalStack + if self.node_for_global is not None: + raise RuntimeError("%s tries to overwrite the existing node_for_global %s with %s" % + (self, self.node_for_global, node)) + self.node_for_global = node class QualityGroup(ContainerGroup): @@ -60,20 +78,20 @@ class QualityGroup(ContainerGroup): self.quality_type = quality_type self.is_available = False - +# +# QualityNode is used for BOTH quality and quality_changes containers. +# class QualityNode(ContainerNode): - __slots__ = ("metadata", "container", "quality_type_map", "children_map") - def __init__(self, metadata = None): + def __init__(self, metadata: Optional[dict] = None): super().__init__(metadata = metadata) - self.quality_type_map = {} - + self.quality_type_map = {} # quality_type -> QualityNode for InstanceContainer def addQualityMetadata(self, quality_type: str, metadata: dict): if quality_type not in self.quality_type_map: self.quality_type_map[quality_type] = QualityNode(metadata) - def getQualityNode(self, quality_type: str): + def getQualityNode(self, quality_type: str) -> Optional["QualityNode"]: return self.quality_type_map.get(quality_type) def addQualityChangesMetadata(self, quality_type: str, metadata: dict): @@ -84,8 +102,8 @@ class QualityNode(ContainerNode): name = metadata["name"] if name not in quality_type_node.children_map: quality_type_node.children_map[name] = QualityChangesGroup(name) - qc_group = quality_type_node.children_map[name] - qc_group.addMetadata(metadata) + quality_changes_group = quality_type_node.children_map[name] + quality_changes_group.addNode(QualityNode(metadata)) class QualityManager(QObject): @@ -164,6 +182,11 @@ class QualityManager(QObject): material_node.addQualityMetadata(quality_type, metadata) + # Initialize quality + self._initializeQualityChangesTables() + + + def _initializeQualityChangesTables(self): # Initialize the lookup tree for quality_changes profiles with following structure: # -> -> quality_changes_metadata_list = self._container_registry.findContainersMetadata(type = "quality_changes") @@ -180,6 +203,51 @@ class QualityManager(QObject): machine_node.addQualityChangesMetadata(quality_type, metadata) + # Updates the given quality groups' availabilities according to which extruders are being used/ enabled. + def _updateQualityGroupsAvailability(self, machine: "GlobalStack", quality_group_list): + used_extruders = set() + # TODO: This will change after the Machine refactoring + for i in range(machine.getProperty("machine_extruder_count", "value")): + used_extruders.add(str(i)) + + # Update the "is_available" flag for each quality group. + for quality_group in quality_group_list: + is_available = True + if quality_group.node_for_global is None: + is_available = False + if is_available: + for position in used_extruders: + if position not in quality_group.nodes_for_extruders: + is_available = False + break + + quality_group.is_available = is_available + + # Returns a dict of "custom profile name" -> QualityChangesGroup + def getQualityChangesGroup(self, machine: "GlobalStack") -> dict: + # TODO: How to make this simpler? + # Get machine definition ID + machine_definition_id = self._default_machine_definition_id + if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): + machine_definition_id = machine.getMetaDataEntry("quality_definition") + if machine_definition_id is None: + machine_definition_id = machine.definition.getId() + + machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id) + if not machine_node: + raise RuntimeError("Cannot find node for machine def [%s] in QualityChanges lookup table" % machine_definition_id) + + # iterate over all quality_types in the machine node + quality_changes_group_dict = dict() + for quality_type, quality_changes_node in machine_node.quality_type_map.items(): + for quality_changes_name, quality_changes_group in quality_changes_node.children_map.items(): + quality_changes_group_dict[quality_changes_name] = quality_changes_group + + # Update availabilities for each quality group + self._updateQualityGroupsAvailability(machine, quality_changes_group_dict.values()) + + return quality_changes_group_dict + def getQualityGroups(self, machine: "GlobalStack") -> dict: # TODO: How to make this simpler, including the fallbacks. # Get machine definition ID @@ -191,7 +259,7 @@ class QualityManager(QObject): machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) if not machine_node: - Logger.log("e", "Cannot find node for machine def [%s] in quality lookup table", machine_definition_id) + raise RuntimeError("Cannot find node for machine def [%s] in Quality lookup table" % machine_definition_id) # iterate over all quality_types in the machine node quality_group_dict = {} @@ -268,23 +336,8 @@ class QualityManager(QObject): quality_group.nodes_for_extruders[position] = quality_node - used_extruders = set() - # TODO: This will change after the Machine refactoring - for i in range(machine.getProperty("machine_extruder_count", "value")): - used_extruders.add(str(i)) - - # Update the "is_available" flag for each quality group. - for quality_group in quality_group_dict.values(): - is_available = True - if quality_group.node_for_global is None: - is_available = False - if is_available: - for position in used_extruders: - if position not in quality_group.nodes_for_extruders: - is_available = False - break - - quality_group.is_available = is_available + # Update availabilities for each quality group + self._updateQualityGroupsAvailability(machine, quality_group_dict.values()) return quality_group_dict diff --git a/plugins/TestTools/TestTool.py b/plugins/TestTools/TestTool.py index 3c852e5997..e2312e578f 100644 --- a/plugins/TestTools/TestTool.py +++ b/plugins/TestTools/TestTool.py @@ -1,5 +1,5 @@ -# Copyright (c) 2016 Ultimaker B.V. -# Cura is released under the terms of the AGPLv3 or higher. +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv2 or higher. from UM.Extension import Extension from PyQt5.QtCore import QObject @@ -12,6 +12,7 @@ class TestTool(Extension, QObject): self.addMenuItem("Test material manager", self._testMaterialManager) self.addMenuItem("Test get quality", self._testGetQuality) + self.addMenuItem("Test get quality changes", self.testGetQualityChanges) def _testMaterialManager(self): print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") @@ -24,4 +25,13 @@ class TestTool(Extension, QObject): result_dict = {} global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack result = CuraApplication.getInstance()._quality_manager.getQualityGroups(global_stack) + print("!!!!!!!!!!!!!!!!!!!") + def testGetQualityChanges(self): + print("!!!!!!!!!!!!!!!!!!!") + + from cura.CuraApplication import CuraApplication + result_dict = {} + global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack + result = CuraApplication.getInstance()._quality_manager.getQualityChangesGroup(global_stack) + print("!!!!!!!!!!!!!!!!!!!") From bf2317a74d09707e24f88d74864ecdde9dfb96c8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 10:47:30 +0100 Subject: [PATCH 049/371] WIP: use new QualityChangesGroups --- cura/CuraApplication.py | 9 +++++++- cura/Machines/QualityManager.py | 35 +++++++++++++++++------------ cura/Settings/MachineManager.py | 29 +++++++++++++++++++++++- cura/Settings/ProfilesModel.py | 29 ++++++++++++++++++++++++ plugins/TestTools/TestTool.py | 5 +++-- resources/qml/Menus/ProfileMenu.qml | 13 ++++++----- 6 files changed, 97 insertions(+), 23 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 9a74cde13f..44d4761321 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -53,7 +53,7 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator from cura.Settings.NozzleModel import NozzleModel -from cura.Settings.ProfilesModel import ProfilesModel, NewQualityProfilesModel +from cura.Settings.ProfilesModel import ProfilesModel, NewQualityProfilesModel, NewCustomQualityProfilesModel from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager @@ -389,6 +389,7 @@ class CuraApplication(QtApplication): self.getCuraSceneController().setActiveBuildPlate(0) # Initialize self._new_quality_profile_model = None + self._new_custom_quality_profile_model = None CuraApplication.Created = True @@ -903,6 +904,11 @@ class CuraApplication(QtApplication): self._new_quality_profile_model = NewQualityProfilesModel(self) return self._new_quality_profile_model + def getNewCustomQualityProfilesModel(self, *args, **kwargs): + if self._new_custom_quality_profile_model is None: + self._new_custom_quality_profile_model = NewCustomQualityProfilesModel(self) + return self._new_custom_quality_profile_model + ## Registers objects for the QML engine to use. # # \param engine The QML engine. @@ -936,6 +942,7 @@ class CuraApplication(QtApplication): qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") qmlRegisterSingletonType(NewQualityProfilesModel, "Cura", 1, 0, "NewQualityProfilesModel", self.getNewQualityProfileModel) + qmlRegisterSingletonType(NewCustomQualityProfilesModel, "Cura", 1, 0, "NewCustomQualityProfilesModel", self.getNewCustomQualityProfilesModel) qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 0e9bf99bd4..1c7f82550a 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -27,10 +27,18 @@ from cura.Machines.ContainerNode import ContainerNode # -class QualityChangesGroup(ContainerGroup): +class QualityGroup(ContainerGroup): - def __init__(self, name: str, parent = None): + def __init__(self, name: str, quality_type: str, parent = None): super().__init__(name, parent) + self.quality_type = quality_type + self.is_available = False + + +class QualityChangesGroup(QualityGroup): + + def __init__(self, name: str, quality_type: str, parent = None): + super().__init__(name, quality_type, parent) def addNode(self, node: "QualityNode"): # TODO: in 3.2 and earlier, a quality_changes container may have a field called "extruder" which contains the @@ -70,13 +78,9 @@ class QualityChangesGroup(ContainerGroup): (self, self.node_for_global, node)) self.node_for_global = node + def __str__(self) -> str: + return "%s[<%s>, available = %s]" % (self.__class__.__name__, self.name, self.is_available) -class QualityGroup(ContainerGroup): - - def __init__(self, name: str, quality_type: str, parent = None): - super().__init__(name, parent) - self.quality_type = quality_type - self.is_available = False # # QualityNode is used for BOTH quality and quality_changes containers. @@ -101,7 +105,7 @@ class QualityNode(ContainerNode): name = metadata["name"] if name not in quality_type_node.children_map: - quality_type_node.children_map[name] = QualityChangesGroup(name) + quality_type_node.children_map[name] = QualityChangesGroup(name, quality_type) quality_changes_group = quality_type_node.children_map[name] quality_changes_group.addNode(QualityNode(metadata)) @@ -224,7 +228,7 @@ class QualityManager(QObject): quality_group.is_available = is_available # Returns a dict of "custom profile name" -> QualityChangesGroup - def getQualityChangesGroup(self, machine: "GlobalStack") -> dict: + def getQualityChangesGroups(self, machine: "GlobalStack") -> dict: # TODO: How to make this simpler? # Get machine definition ID machine_definition_id = self._default_machine_definition_id @@ -237,14 +241,17 @@ class QualityManager(QObject): if not machine_node: raise RuntimeError("Cannot find node for machine def [%s] in QualityChanges lookup table" % machine_definition_id) - # iterate over all quality_types in the machine node + # Update availability for each QualityChangesGroup: + # A custom profile is always available as long as the quality_type it's based on is available + quality_group_dict = self.getQualityGroups(machine) + available_quality_type_list = [qt for qt, qg in quality_group_dict.items() if qg.is_available] + + # Iterate over all quality_types in the machine node quality_changes_group_dict = dict() for quality_type, quality_changes_node in machine_node.quality_type_map.items(): for quality_changes_name, quality_changes_group in quality_changes_node.children_map.items(): quality_changes_group_dict[quality_changes_name] = quality_changes_group - - # Update availabilities for each quality group - self._updateQualityGroupsAvailability(machine, quality_changes_group_dict.values()) + quality_changes_group.is_available = quality_type in available_quality_type_list return quality_changes_group_dict diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index bb2f8cbd79..3b37afd328 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -134,11 +134,13 @@ class MachineManager(QObject): containers[0].nameChanged.connect(self._onMaterialNameChanged) ### NEW - self._current_quality_group = None self._current_root_material_id = {} + self._current_quality_group = None + self._current_quality_changes_group = None ### NEW activeQualityGroupChanged = pyqtSignal() + activeQualityChangesGroupChanged = pyqtSignal() globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value) activeMaterialChanged = pyqtSignal() @@ -1502,6 +1504,27 @@ class MachineManager(QObject): self._current_root_material_id[position] = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") return self._current_root_material_id + def _setQualityChangesGroup(self, quality_changes_group): + self._current_quality_changes_group = quality_changes_group + + # TODO: quality_changes groups depend on a quality_type. Here it's fetching the quality_types every time. + # Can we do this better, like caching the quality group a quality_changes group depends on? + quality_manager = Application.getInstance()._quality_manager + quality_group_dict = quality_manager.getQualityGroups(self._global_container_stack) + + quality_type = quality_changes_group.quality_type + + container = self._empty_quality_changes_container + if quality_changes_group.node_for_global is not None: + container = quality_changes_group.node_for_global.getContainer() + self._global_container_stack.qualityChanges = container + self._global_container_stack.quality = quality_group_dict[quality_type] + + for position, extruder in self._global_container_stack.extruders.items(): + container = quality_changes_group.nodes_for_extruders.get(position, + self._empty_quality_changes_container) + extruder.qualityChanges = container + def _setEmptyQuality(self): self._current_quality_group = None self._global_container_stack.quality = self._empty_quality_container @@ -1510,9 +1533,13 @@ class MachineManager(QObject): extruder.quality = self._empty_quality_container extruder.qualityChanges = self._empty_quality_changes_container + self.activeQualityGroupChanged.emit() + def _setQualityGroup(self, quality_group, empty_quality_changes = True): self._current_quality_group = quality_group + #TODO: check quality_changes + # Set quality and quality_changes for the GlobalStack self._global_container_stack.quality = quality_group.node_for_global.getContainer() if empty_quality_changes: diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index fd508f247a..b05bc46dd5 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -101,6 +101,35 @@ class NewQualityProfilesModel(ListModel): return str(layer_height) +class NewCustomQualityProfilesModel(NewQualityProfilesModel): + + def _update(self): + Logger.log("d", "Updating %s ...", self.__class__.__name__) + + active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + if active_global_stack is None: + self.setItems([]) + Logger.log("d", "No active GlobalStack, set %s as empty.", self.__class__.__name__) + return + + quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(active_global_stack) + + item_list = [] + for key in sorted(quality_changes_group_dict): + quality_changes_group = quality_changes_group_dict[key] + + item = {"id": "TODO", # TODO: probably will be removed + "name": quality_changes_group.name, + "layer_height": "", + "layer_height_without_unit": "", + "available": quality_changes_group.is_available, + "quality_changes_group": quality_changes_group} + + item_list.append(item) + + self.setItems(item_list) + + ## QML Model for listing the current list of valid quality profiles. # class ProfilesModel(InstanceContainersModel): diff --git a/plugins/TestTools/TestTool.py b/plugins/TestTools/TestTool.py index e2312e578f..a8812c21ba 100644 --- a/plugins/TestTools/TestTool.py +++ b/plugins/TestTools/TestTool.py @@ -33,5 +33,6 @@ class TestTool(Extension, QObject): from cura.CuraApplication import CuraApplication result_dict = {} global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack - result = CuraApplication.getInstance()._quality_manager.getQualityChangesGroup(global_stack) - print("!!!!!!!!!!!!!!!!!!!") + result = CuraApplication.getInstance()._quality_manager.getQualityChangesGroups(global_stack) + for name, r in result.items(): + print("!!!!!!!!!! [%s] - %s" % (name, r)) diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index 9013216e32..f212d82b6e 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -40,18 +40,21 @@ Menu Instantiator { id: customProfileInstantiator - model: Cura.UserProfilesModel + model: Cura.NewCustomQualityProfilesModel + + Connections { - onModelReset: customSeparator.visible = rowCount() > 0 + target: Cura.NewCustomQualityProfilesModel + onModelReset: customSeparator.visible = Cura.NewCustomQualityProfilesModel.rowCount() > 0 } MenuItem { text: model.name - checkable: true - checked: Cura.MachineManager.activeQualityChangesId == model.id + checkable: model.available + checked: Cura.MachineManager.activeQualityChangesId == model.id // TODO: fix for new exclusiveGroup: group - onTriggered: Cura.MachineManager.setActiveQuality(model.id) + onTriggered: Cura.MachineManager.setActiveQuality(model.id) // TODO: fix for new } onObjectAdded: From 8aab8f4394368d851fb1f6412a51666dd2f4cf9a Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 14 Feb 2018 11:12:21 +0100 Subject: [PATCH 050/371] CURA-4606 cleanup and optimization for replaceContainer --- cura/Machines/QualityManager.py | 3 ++- cura/Settings/CuraContainerStack.py | 4 ++++ cura/Settings/MachineManager.py | 1 + resources/qml/Menus/MaterialMenu.qml | 6 ------ resources/qml/Menus/NozzleMenu.qml | 15 --------------- resources/qml/Menus/ProfileMenu.qml | 2 +- 6 files changed, 8 insertions(+), 23 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 1c7f82550a..a719a7df8c 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -239,7 +239,8 @@ class QualityManager(QObject): machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id) if not machine_node: - raise RuntimeError("Cannot find node for machine def [%s] in QualityChanges lookup table" % machine_definition_id) + Logger.log("e", "Cannot find node for machine def [%s] in QualityChanges lookup table", machine_definition_id) + return {} # Update availability for each QualityChangesGroup: # A custom profile is always available as long as the quality_type it's based on is available diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index b97bb3314e..93e4b55bba 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -348,6 +348,10 @@ class CuraContainerStack(ContainerStack): elif container != self._empty_instance_container and container.getMetaDataEntry("type") != expected_type: raise Exceptions.InvalidContainerError("Cannot replace container at index {index} with a container that is not of {type} type, but {actual_type} type.".format(index = index, type = expected_type, actual_type = container.getMetaDataEntry("type"))) + current_container = self._containers[index] + if current_container.getId() == container.getId(): + return + super().replaceContainer(index, container, postpone_emit) ## Overridden from ContainerStack diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 3b37afd328..15bb388f26 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1642,6 +1642,7 @@ class MachineManager(QObject): self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setQualityGroup(quality_group) + Logger.log("d", "Quality set!") @pyqtProperty("QVariant", fset = setQualityGroup, notify = activeQualityGroupChanged) def activeQualityGroup(self): diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index cb4ee5eefb..e77ab2861a 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -13,12 +13,6 @@ Menu title: "Material" property int extruderIndex: 0 - property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 - - MenuSeparator - { - visible: automaticMaterial.visible - } Instantiator { diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index 27082cfb4b..8cb01fcde6 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -13,21 +13,6 @@ Menu title: "Nozzle" property int extruderIndex: 0 - property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 - property bool isClusterPrinter: - { - if (Cura.MachineManager.printerOutputDevices.length == 0) - { - return false; - } - var clusterSize = Cura.MachineManager.printerOutputDevices[0].clusterSize; - // This is not a cluster printer or the cluster it is just one printer - if (clusterSize == undefined || clusterSize == 1) - { - return false; - } - return true; - } Cura.NozzleModel { diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index f212d82b6e..6005ce9805 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -19,7 +19,7 @@ Menu { text: (model.layer_height != "") ? model.name + " - " + model.layer_height : model.name checkable: true - checked: Cura.MachineManager.activeQualityGroup.getName() == model.name + checked: Cura.MachineManager.activeQualityGroup && (Cura.MachineManager.activeQualityGroup.getName() == model.name) exclusiveGroup: group onTriggered: { Cura.MachineManager.setQualityGroup(model.quality_group) From b1e4cb91de02ade0bd567389419f7c73c8082b9b Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 14 Feb 2018 11:19:33 +0100 Subject: [PATCH 051/371] CURA-4606 cleanup auto sync in machinemanager --- cura/Settings/MachineManager.py | 114 -------------------------------- 1 file changed, 114 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 15bb388f26..752353fe79 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -160,16 +160,10 @@ class MachineManager(QObject): rootMaterialChanged = pyqtSignal() def _onOutputDevicesChanged(self) -> None: - for printer_output_device in self._printer_output_devices: - printer_output_device.hotendIdChanged.disconnect(self._onHotendIdChanged) - printer_output_device.materialIdChanged.disconnect(self._onMaterialIdChanged) - self._printer_output_devices = [] for printer_output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices(): if isinstance(printer_output_device, PrinterOutputDevice): self._printer_output_devices.append(printer_output_device) - printer_output_device.hotendIdChanged.connect(self._onHotendIdChanged) - printer_output_device.materialIdChanged.connect(self._onMaterialIdChanged) self.outputDevicesChanged.emit() @@ -193,114 +187,6 @@ class MachineManager(QObject): def totalNumberOfSettings(self) -> int: return len(ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0].getAllKeys()) - def _onHotendIdChanged(self) -> None: - if not self._global_container_stack or not self._printer_output_devices: - return - - active_printer_model = self._printer_output_devices[0].activePrinter - if not active_printer_model: - return - - change_found = False - machine_id = self.activeMachineId - extruders = sorted(ExtruderManager.getInstance().getMachineExtruders(machine_id), - key=lambda k: k.getMetaDataEntry("position")) - - for extruder_model, extruder in zip(active_printer_model.extruders, extruders): - containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(type="variant", - definition=self._global_container_stack.definition.getId(), - name=extruder_model.hotendID) - if containers: - # The hotend ID is known. - machine_id = self.activeMachineId - if extruder.variant.getName() != extruder_model.hotendID: - change_found = True - self._auto_hotends_changed[extruder.getMetaDataEntry("position")] = containers[0]["id"] - - if change_found: - # A change was found, let the output device handle this. - self._printer_output_devices[0].materialHotendChangedMessage(self._materialHotendChangedCallback) - - def _onMaterialIdChanged(self) -> None: - if not self._global_container_stack or not self._printer_output_devices: - return - - active_printer_model = self._printer_output_devices[0].activePrinter - if not active_printer_model: - return - - change_found = False - machine_id = self.activeMachineId - extruders = sorted(ExtruderManager.getInstance().getMachineExtruders(machine_id), - key=lambda k: k.getMetaDataEntry("position")) - - for extruder_model, extruder in zip(active_printer_model.extruders, extruders): - if extruder_model.activeMaterial is None: - continue - containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(type="material", - definition=self._global_container_stack.definition.getId(), - GUID=extruder_model.activeMaterial.guid) - if containers: - # The material is known. - if extruder.material.getMetaDataEntry("GUID") != extruder_model.activeMaterial.guid: - change_found = True - if self._global_container_stack.definition.getMetaDataEntry("has_variants") and extruder.variant: - variant_id = self.getQualityVariantId(self._global_container_stack.definition, - extruder.variant) - for container in containers: - if container.get("variant") == variant_id: - self._auto_materials_changed[extruder.getMetaDataEntry("position")] = container["id"] - break - else: - # Just use the first result we found. - self._auto_materials_changed[extruder.getMetaDataEntry("position")] = containers[0]["id"] - if change_found: - # A change was found, let the output device handle this. - self._printer_output_devices[0].materialHotendChangedMessage(self._materialHotendChangedCallback) - - def _materialHotendChangedCallback(self, button) -> None: - if button == QMessageBox.No: - self._auto_materials_changed = {} - self._auto_hotends_changed = {} - return - self._autoUpdateMaterials() - self._autoUpdateHotends() - - def _autoUpdateMaterials(self) -> None: - extruder_manager = ExtruderManager.getInstance() - for position in self._auto_materials_changed: - material_id = self._auto_materials_changed[position] - old_index = extruder_manager.activeExtruderIndex - - if old_index != int(position): - extruder_manager.setActiveExtruderIndex(int(position)) - else: - old_index = None - - Logger.log("d", "Setting material of hotend %s to %s" % (position, material_id)) - self.setActiveMaterial(material_id) - - if old_index is not None: - extruder_manager.setActiveExtruderIndex(old_index) - self._auto_materials_changed = {} # Processed all of them now. - - def _autoUpdateHotends(self) -> None: - extruder_manager = ExtruderManager.getInstance() - for position in self._auto_hotends_changed: - hotend_id = self._auto_hotends_changed[position] - old_index = extruder_manager.activeExtruderIndex - - if old_index != int(position): - extruder_manager.setActiveExtruderIndex(int(position)) - else: - old_index = None - Logger.log("d", "Setting hotend variant of hotend %s to %s" % (position, hotend_id)) - self.setActiveVariant(hotend_id) - - if old_index is not None: - extruder_manager.setActiveExtruderIndex(old_index) - self._auto_hotends_changed = {} # Processed all of them now. - def _onGlobalContainerChanged(self) -> None: if self._global_container_stack: try: From 730cbb25bf317802bebb2eadf0153ac20c0a90bf Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 14:13:21 +0100 Subject: [PATCH 052/371] WIP: Simplify machine creation --- cura/CuraApplication.py | 6 + cura/Machines/QualityManager.py | 9 +- cura/Settings/CuraStackBuilder.py | 204 ++++++++++-------- resources/definitions/fdmprinter.def.json | 3 +- .../definitions/ultimaker2_plus.def.json | 1 + resources/definitions/ultimaker3.def.json | 3 +- 6 files changed, 129 insertions(+), 97 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 44d4761321..dc0a65be1d 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -294,21 +294,25 @@ class CuraApplication(QtApplication): # Since they are empty, they should never be serialized and instead just programmatically created. # We need them to simplify the switching between materials. empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() + self.empty_container = empty_container empty_definition_changes_container = copy.deepcopy(empty_container) empty_definition_changes_container.setMetaDataEntry("id", "empty_definition_changes") empty_definition_changes_container.addMetaDataEntry("type", "definition_changes") ContainerRegistry.getInstance().addContainer(empty_definition_changes_container) + self.empty_definition_changes_container = empty_definition_changes_container empty_variant_container = copy.deepcopy(empty_container) empty_variant_container.setMetaDataEntry("id", "empty_variant") empty_variant_container.addMetaDataEntry("type", "variant") ContainerRegistry.getInstance().addContainer(empty_variant_container) + self.empty_variant_container = empty_variant_container empty_material_container = copy.deepcopy(empty_container) empty_material_container.setMetaDataEntry("id", "empty_material") empty_material_container.addMetaDataEntry("type", "material") ContainerRegistry.getInstance().addContainer(empty_material_container) + self.empty_material_container = empty_material_container empty_quality_container = copy.deepcopy(empty_container) empty_quality_container.setMetaDataEntry("id", "empty_quality") @@ -317,12 +321,14 @@ class CuraApplication(QtApplication): empty_quality_container.addMetaDataEntry("type", "quality") empty_quality_container.addMetaDataEntry("supported", False) ContainerRegistry.getInstance().addContainer(empty_quality_container) + self.empty_quality_container = empty_quality_container empty_quality_changes_container = copy.deepcopy(empty_container) empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") empty_quality_changes_container.addMetaDataEntry("type", "quality_changes") empty_quality_changes_container.addMetaDataEntry("quality_type", "not_supported") ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) + self.empty_quality_changes_container = empty_quality_changes_container with ContainerRegistry.getInstance().lockFile(): ContainerRegistry.getInstance().loadAllMetadata() diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index a719a7df8c..ee8b9c8922 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -257,7 +257,7 @@ class QualityManager(QObject): return quality_changes_group_dict def getQualityGroups(self, machine: "GlobalStack") -> dict: - # TODO: How to make this simpler, including the fallbacks. + # TODO: How to make this simpler, including the fall backs. # Get machine definition ID machine_definition_id = self._default_machine_definition_id if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): @@ -270,8 +270,13 @@ class QualityManager(QObject): raise RuntimeError("Cannot find node for machine def [%s] in Quality lookup table" % machine_definition_id) # iterate over all quality_types in the machine node + node_to_fetch_global = machine_node quality_group_dict = {} - for quality_type, quality_node in machine_node.quality_type_map.items(): + if not node_to_fetch_global.quality_type_map: + # Fallback mechanism: + # If there is no machine-specific quality, fallback to use the default fdmprinter's. + node_to_fetch_global = self._machine_variant_material_quality_type_to_quality_dict.get(self._default_machine_definition_id) + for quality_type, quality_node in node_to_fetch_global.quality_type_map.items(): quality_group = QualityGroup(quality_node.metadata["name"], quality_type) quality_group.node_for_global = quality_node diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 608a13c600..365658ee48 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -6,6 +6,7 @@ from UM.Logger import Logger from UM.Settings.Interfaces import DefinitionContainerInterface from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Util import parseBool from .GlobalStack import GlobalStack from .ExtruderStack import ExtruderStack @@ -22,7 +23,13 @@ class CuraStackBuilder: # \return The new global stack or None if an error occurred. @classmethod def createMachine(cls, name: str, definition_id: str) -> Optional[GlobalStack]: + from cura.CuraApplication import CuraApplication + application = CuraApplication.getInstance() + variant_manager = CuraApplication.getInstance()._variant_manager + material_manager = CuraApplication.getInstance()._material_manager + quality_manager = CuraApplication.getInstance()._quality_manager registry = ContainerRegistry.getInstance() + definitions = registry.findDefinitionContainers(id = definition_id) if not definitions: Logger.log("w", "Definition {definition} was not found!", definition = definition_id) @@ -30,7 +37,33 @@ class CuraStackBuilder: machine_definition = definitions[0] - generated_name = registry.createUniqueName("machine", "", name, machine_definition.name) + # get variant container for extruders + variant_container = application.empty_variant_container + # Only look for the preferred variant if this machine has variants + variant_name = None + if parseBool(machine_definition.getMetaDataEntry("has_variants", False)): + variant_name = machine_definition.getMetaDataEntry("preferred_variant_name") + if variant_name: + variant_node = variant_manager.getVariant(definition_id, variant_name) + # Sanity check. If you see this error, the related definition files should be fixed. + if variant_node is None: + raise RuntimeError("Cannot find variant with definition [%s] and variant name [%s]" % (definition_id, variant_name)) + variant_container = variant_node.getContainer() + + # get material container for extruders + material_container = application.empty_material_container + # Only look for the preferred material if this machine has materials + if parseBool(machine_definition.getMetaDataEntry("has_materials", False)): + material_diameter = machine_definition.getProperty("material_diameter", "value") + root_material_id = machine_definition.getMetaDataEntry("preferred_material") + material_node = material_manager.getMaterialNode(definition_id, variant_name, material_diameter, root_material_id) + # Sanity check. If you see this error, the related definition files should be fixed. + if not material_node: + raise RuntimeError("Cannot find material with definition [%s], variant_name [%s], and root_material_id [%s]" % + (definition_id, variant_name, root_material_id)) + material_container = material_node.getContainer() + + generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName()) # Make sure the new name does not collide with any definition or (quality) profile # createUniqueName() only looks at other stacks, but not at definitions or quality profiles # Note that we don't go for uniqueName() immediately because that function matches with ignore_case set to true @@ -40,49 +73,45 @@ class CuraStackBuilder: new_global_stack = cls.createGlobalStack( new_stack_id = generated_name, definition = machine_definition, - quality = "default", - material = "default", - variant = "default", + variant_container = application.empty_variant_container, # TODO: fix for build plate + material_container = application.empty_material_container, + quality_container = application.empty_quality_container, ) - new_global_stack.setName(generated_name) - extruder_definition = registry.findDefinitionContainers(machine = machine_definition.getId()) + # Create ExtruderStacks + extruder_dict = machine_definition.getMetaDataEntry("machine_extruder_trains") - if not extruder_definition: - # create extruder stack for single extrusion machines that have no separate extruder definition files - extruder_definition = registry.findDefinitionContainers(id = "fdmextruder")[0] - new_extruder_id = registry.uniqueName(machine_definition.getName() + " " + extruder_definition.id) + for position, extruder_definition_id in extruder_dict.items(): + # Sanity check: make sure that the positions in the extruder definitions are same as in the machine + # definition + extruder_definition = registry.findDefinitionContainers(id = extruder_definition_id)[0] + position_in_extruder_def = extruder_definition.getMetaDataEntry("position") + if position_in_extruder_def != position: + raise RuntimeError("Extruder position [%s] defined in extruder definition [%s] is not the same as in machine definition [%s] position [%s]" % + (position_in_extruder_def, extruder_definition_id, definition_id, position)) + + new_extruder_id = registry.uniqueName(extruder_definition_id) new_extruder = cls.createExtruderStack( new_extruder_id, - definition = extruder_definition, - machine_definition_id = machine_definition.getId(), - quality = "default", - material = "default", - variant = "default", - next_stack = new_global_stack + extruder_definition = extruder_definition, + machine_definition_id = definition_id, + position = position, + variant_container = variant_container, + material_container = material_container, + quality_container = application.empty_quality_container, ) + new_extruder.setNextStack(new_global_stack) new_global_stack.addExtruder(new_extruder) registry.addContainer(new_extruder) - else: - # create extruder stack for each found extruder definition - for extruder_definition in registry.findDefinitionContainers(machine = machine_definition.id): - position = extruder_definition.getMetaDataEntry("position", None) - if not position: - Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.id) - new_extruder_id = registry.uniqueName(extruder_definition.id) - new_extruder = cls.createExtruderStack( - new_extruder_id, - definition = extruder_definition, - machine_definition_id = machine_definition.getId(), - quality = "default", - material = "default", - variant = "default", - next_stack = new_global_stack - ) - new_global_stack.addExtruder(new_extruder) - registry.addContainer(new_extruder) + preferred_quality_type = machine_definition.getMetaDataEntry("preferred_quality_type") + quality_group_dict = quality_manager.getQualityGroups(new_global_stack) + quality_group = quality_group_dict.get(preferred_quality_type) + + new_global_stack.quality = quality_group.node_for_global.getContainer() + for position, extruder_stack in new_global_stack.extruders.items(): + extruder_stack.quality = quality_group.nodes_for_extruders[position].getContainer() # Register the global stack after the extruder stacks are created. This prevents the registry from adding another # extruder stack because the global stack didn't have one yet (which is enforced since Cura 3.1). @@ -100,43 +129,27 @@ class CuraStackBuilder: # # \return A new Global stack instance with the specified parameters. @classmethod - def createExtruderStack(cls, new_stack_id: str, definition: DefinitionContainerInterface, machine_definition_id: str, **kwargs) -> ExtruderStack: - stack = ExtruderStack(new_stack_id) - stack.setName(definition.getName()) - stack.setDefinition(definition) - stack.addMetaDataEntry("position", definition.getMetaDataEntry("position")) - - if "next_stack" in kwargs: - # Add stacks before containers are added, since they may trigger a setting update. - stack.setNextStack(kwargs["next_stack"]) - - user_container = InstanceContainer(new_stack_id + "_user") - user_container.addMetaDataEntry("type", "user") - user_container.addMetaDataEntry("extruder", new_stack_id) + def createExtruderStack(cls, new_stack_id: str, extruder_definition: DefinitionContainerInterface, machine_definition_id: str, + position: int, + variant_container, material_container, quality_container) -> ExtruderStack: from cura.CuraApplication import CuraApplication - user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - user_container.setDefinition(machine_definition_id) + application = CuraApplication.getInstance() - stack.setUserChanges(user_container) + stack = ExtruderStack(new_stack_id) + stack.setName(extruder_definition.getName()) + stack.setDefinition(extruder_definition) - # Important! The order here matters, because that allows the stack to - # assume the material and variant have already been set. - if "definition_changes" in kwargs: - stack.setDefinitionChangesById(kwargs["definition_changes"]) - else: - stack.setDefinitionChanges(cls.createDefinitionChangesContainer(stack, new_stack_id + "_settings")) + stack.addMetaDataEntry("position", position) - if "variant" in kwargs: - stack.setVariantById(kwargs["variant"]) + user_container = cls.createUserChangesContainer(new_stack_id + "_user", machine_definition_id, new_stack_id, + is_global_stack = False) - if "material" in kwargs: - stack.setMaterialById(kwargs["material"]) - - if "quality" in kwargs: - stack.setQualityById(kwargs["quality"]) - - if "quality_changes" in kwargs: - stack.setQualityChangesById(kwargs["quality_changes"]) + stack.definitionChanges = cls.createDefinitionChangesContainer(stack, new_stack_id + "_settings") + stack.variant = variant_container + stack.material = material_container + stack.quality = quality_container + stack.qualityChanges = application.empty_quality_changes_container + stack.userChanges = user_container # Only add the created containers to the registry after we have set all the other # properties. This makes the create operation more transactional, since any problems @@ -153,42 +166,47 @@ class CuraStackBuilder: # # \return A new Global stack instance with the specified parameters. @classmethod - def createGlobalStack(cls, new_stack_id: str, definition: DefinitionContainerInterface, **kwargs) -> GlobalStack: + def createGlobalStack(cls, new_stack_id: str, definition: DefinitionContainerInterface, + variant_container, material_container, quality_container) -> GlobalStack: + from cura.CuraApplication import CuraApplication + application = CuraApplication.getInstance() + stack = GlobalStack(new_stack_id) stack.setDefinition(definition) - user_container = InstanceContainer(new_stack_id + "_user") - user_container.addMetaDataEntry("type", "user") - user_container.addMetaDataEntry("machine", new_stack_id) - from cura.CuraApplication import CuraApplication - user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - user_container.setDefinition(definition.getId()) + # Create user container + user_container = cls.createUserChangesContainer(new_stack_id + "_user", definition.getId(), new_stack_id, + is_global_stack = True) - stack.setUserChanges(user_container) - - # Important! The order here matters, because that allows the stack to - # assume the material and variant have already been set. - if "definition_changes" in kwargs: - stack.setDefinitionChangesById(kwargs["definition_changes"]) - else: - stack.setDefinitionChanges(cls.createDefinitionChangesContainer(stack, new_stack_id + "_settings")) - - if "variant" in kwargs: - stack.setVariantById(kwargs["variant"]) - - if "material" in kwargs: - stack.setMaterialById(kwargs["material"]) - - if "quality" in kwargs: - stack.setQualityById(kwargs["quality"]) - - if "quality_changes" in kwargs: - stack.setQualityChangesById(kwargs["quality_changes"]) + stack.definitionChanges = cls.createDefinitionChangesContainer(stack, new_stack_id + "_settings") + stack.variant = variant_container + stack.material = material_container + stack.quality = quality_container + stack.qualityChanges = application.empty_quality_changes_container + stack.userChanges = user_container ContainerRegistry.getInstance().addContainer(user_container) return stack + @classmethod + def createUserChangesContainer(cls, container_name: str, definition_id: str, stack_id: str, + is_global_stack: bool) -> "InstanceContainer": + from cura.CuraApplication import CuraApplication + + unique_container_name = ContainerRegistry.getInstance().uniqueName(container_name) + + container = InstanceContainer(unique_container_name) + container.setDefinition(definition_id) + container.addMetaDataEntry("type", "user") + container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) + + metadata_key_to_add = "machine" if is_global_stack else "extruder" + container.addMetaDataEntry(metadata_key_to_add, stack_id) + + return container + + @classmethod def createDefinitionChangesContainer(cls, container_stack, container_name, container_index = None): from cura.CuraApplication import CuraApplication diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 80bb9b19b9..366158d042 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -11,8 +11,9 @@ "file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj;application/x3g", "visible": false, "has_materials": true, - "preferred_material": "*generic_pla*", + "preferred_material": "generic_pla", "preferred_quality": "*normal*", + "preferred_quality_type": "normal", "machine_extruder_trains": { "0": "fdmextruder" diff --git a/resources/definitions/ultimaker2_plus.def.json b/resources/definitions/ultimaker2_plus.def.json index 58833904d2..bc90776289 100644 --- a/resources/definitions/ultimaker2_plus.def.json +++ b/resources/definitions/ultimaker2_plus.def.json @@ -10,6 +10,7 @@ "platform": "ultimaker2_platform.obj", "platform_texture": "Ultimaker2Plusbackplate.png", "preferred_variant": "*0.4*", + "preferred_variant_name": "0.4 mm", "has_variants": true, "has_materials": true, "has_machine_materials": true, diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 74e4a9551e..9a98b83efb 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -16,8 +16,9 @@ "has_variant_materials": true, "has_variants": true, "preferred_variant": "*aa04*", + "preferred_variant_name": "AA 0.4", "preferred_quality": "*Normal*", - "preferred_quality_type": "fine", + "preferred_quality_type": "normal", "variants_name": "Print core", "machine_extruder_trains": { From c469ebbf9fac22448828945f69e361bfd6834e2e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 16:08:21 +0100 Subject: [PATCH 053/371] WIP: Fix material lookup problems and update definition files --- cura/Machines/MaterialManager.py | 16 +++++++-------- cura/Machines/QualityManager.py | 3 +-- .../definitions/anycubic_i3_mega.def.json | 2 +- .../builder_premium_large.def.json | 20 +++++++++---------- .../builder_premium_medium.def.json | 20 +++++++++---------- .../builder_premium_small.def.json | 20 +++++++++---------- resources/definitions/cartesio.def.json | 5 ++--- resources/definitions/creality_cr10.def.json | 2 +- resources/definitions/fabtotum.def.json | 4 ++-- resources/definitions/fdmprinter.def.json | 1 - resources/definitions/gmax15plus.def.json | 4 +--- .../definitions/gmax15plus_dual.def.json | 4 ++-- .../definitions/imade3d_jellybox.def.json | 5 ++--- resources/definitions/malyan_m200.def.json | 2 +- .../monoprice_select_mini_v2.def.json | 2 +- .../definitions/tevo_blackwidow.def.json | 2 +- .../definitions/ultimaker2_plus.def.json | 1 - resources/definitions/ultimaker3.def.json | 2 -- .../definitions/ultimaker3_extended.def.json | 2 +- 19 files changed, 51 insertions(+), 66 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index b65e01487c..880ef399bf 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -249,15 +249,15 @@ class MaterialManager(QObject): # 1. variant-specific material # 2. machine-specific material # 3. generic material (for fdmprinter) - material_node = None - if variant_node is not None: - if root_material_id in variant_node.material_map: - material_node = variant_node.material_map.get(root_material_id) + nodes_to_check = [variant_node, machine_node, + machine_variant_material_map.get(self._default_machine_definition_id)] - # Fallback: machine-specific materials, including "fdmprinter" - if material_node is None: - if machine_node is not None: - material_node = machine_node.material_map.get(root_material_id) + material_node = None + for node in nodes_to_check: + if node is not None: + material_node = node.material_map.get(root_material_id) + if material_node: + break return material_node diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index ee8b9c8922..132c2e3dfa 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -320,7 +320,7 @@ class QualityManager(QObject): # No suitable quality found: not supported Logger.log("d", "Cannot find quality with machine [%s], variant name [%s], and materials [%s].", machine_definition_id, variant_name, ", ".join(root_material_id_list)) - continue + else: # In this case, we only have a specific material but NOT a variant if has_material: @@ -332,7 +332,6 @@ class QualityManager(QObject): # No suitable quality found: not supported Logger.log("d", "Cannot find quality with machine [%s], variant name [%s], and materials [%s].", machine_definition_id, variant_name, ", ".join(root_material_id_list)) - continue node_to_check = material_node if not node_to_check: diff --git a/resources/definitions/anycubic_i3_mega.def.json b/resources/definitions/anycubic_i3_mega.def.json index cba868900c..7106038193 100644 --- a/resources/definitions/anycubic_i3_mega.def.json +++ b/resources/definitions/anycubic_i3_mega.def.json @@ -12,7 +12,7 @@ "platform": "anycubic_i3_mega_platform.stl", "has_materials": false, "has_machine_quality": true, - "preferred_quality": "*normal*" + "preferred_quality_type": "normal" }, "overrides": diff --git a/resources/definitions/builder_premium_large.def.json b/resources/definitions/builder_premium_large.def.json index b496dc524e..deb1539a9a 100644 --- a/resources/definitions/builder_premium_large.def.json +++ b/resources/definitions/builder_premium_large.def.json @@ -12,16 +12,14 @@ "platform": "builder_premium_platform.stl", "platform_offset": [-126, -36, 117], "has_machine_quality": true, - "preferred_quality": "*Normal*", + "preferred_quality_type": "normal", "machine_extruder_trains": { "0": "builder_premium_large_rear", "1": "builder_premium_large_front" } }, - - - + "overrides": { "machine_name": { "default_value": "Builder Premium Large" }, "machine_heated_bed": { "default_value": true }, @@ -36,7 +34,7 @@ "default_material_print_temperature": { "value": "215" }, "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, "material_standby_temperature": { "value": "material_print_temperature" }, - + "switch_extruder_retraction_speeds": {"default_value": 15 }, "switch_extruder_retraction_speed": {"default_value": 15 }, "switch_extruder_prime_speed": {"default_value": 15 }, @@ -58,9 +56,9 @@ "prime_tower_wipe_enabled": { "default_value": false }, "prime_tower_min_volume": { "default_value": 50 }, "dual_pre_wipe": { "default_value": false }, - + "prime_blob_enable": { "enabled": true }, - + "acceleration_enabled": { "value": "True" }, "acceleration_layer_0": { "value": "acceleration_topbottom" }, "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, @@ -71,7 +69,7 @@ "acceleration_travel": { "value": "acceleration_print" }, "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 3000)" }, "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 1000 / 1000)" }, - + "cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" }, "cool_min_layer_time": { "default_value": 10 }, @@ -84,9 +82,9 @@ "jerk_topbottom": { "value": "math.ceil(jerk_print * 5 / 25)" }, "jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" }, "jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" }, - + "wall_thickness": { "value": "1.2" }, - + "retraction_amount": { "default_value": 3 }, "retraction_speed": { "default_value": 15 }, "retraction_retract_speed": { "default_value": 15 }, @@ -113,4 +111,4 @@ }, "machine_extruder_count": { "default_value": 2 } } -} \ No newline at end of file +} diff --git a/resources/definitions/builder_premium_medium.def.json b/resources/definitions/builder_premium_medium.def.json index fe8a039fc4..c28c7c5de6 100644 --- a/resources/definitions/builder_premium_medium.def.json +++ b/resources/definitions/builder_premium_medium.def.json @@ -12,16 +12,14 @@ "platform": "builder_premium_platform.stl", "platform_offset": [-126, -36, 117], "has_machine_quality": true, - "preferred_quality": "*Normal*", + "preferred_quality_type": "normal", "machine_extruder_trains": { "0": "builder_premium_medium_rear", "1": "builder_premium_medium_front" } }, - - - + "overrides": { "machine_name": { "default_value": "Builder Premium Medium" }, "machine_heated_bed": { "default_value": true }, @@ -36,7 +34,7 @@ "default_material_print_temperature": { "value": "215" }, "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, "material_standby_temperature": { "value": "material_print_temperature" }, - + "switch_extruder_retraction_speeds": {"default_value": 15 }, "switch_extruder_retraction_speed": {"default_value": 15 }, "switch_extruder_prime_speed": {"default_value": 15 }, @@ -58,9 +56,9 @@ "prime_tower_wipe_enabled": { "default_value": false }, "prime_tower_min_volume": { "default_value": 50 }, "dual_pre_wipe": { "default_value": false }, - + "prime_blob_enable": { "enabled": true }, - + "acceleration_enabled": { "value": "True" }, "acceleration_layer_0": { "value": "acceleration_topbottom" }, "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, @@ -71,7 +69,7 @@ "acceleration_travel": { "value": "acceleration_print" }, "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 3000)" }, "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 1000 / 1000)" }, - + "cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" }, "cool_min_layer_time": { "default_value": 10 }, @@ -84,9 +82,9 @@ "jerk_topbottom": { "value": "math.ceil(jerk_print * 5 / 25)" }, "jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" }, "jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" }, - + "wall_thickness": { "value": "1.2" }, - + "retraction_amount": { "default_value": 3 }, "retraction_speed": { "default_value": 15 }, "retraction_retract_speed": { "default_value": 15 }, @@ -113,4 +111,4 @@ }, "machine_extruder_count": { "default_value": 2 } } -} \ No newline at end of file +} diff --git a/resources/definitions/builder_premium_small.def.json b/resources/definitions/builder_premium_small.def.json index a1660b63cf..8e2fe44631 100644 --- a/resources/definitions/builder_premium_small.def.json +++ b/resources/definitions/builder_premium_small.def.json @@ -11,16 +11,14 @@ "platform": "builder_premium_platform.stl", "platform_offset": [-126, -36, 117], "has_machine_quality": true, - "preferred_quality": "*Normal*", + "preferred_quality_type": "normal", "machine_extruder_trains": { "0": "builder_premium_small_rear", "1": "builder_premium_small_front" } }, - - - + "overrides": { "machine_name": { "default_value": "Builder Premium Small" }, "machine_heated_bed": { "default_value": true }, @@ -35,7 +33,7 @@ "default_material_print_temperature": { "value": "215" }, "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, "material_standby_temperature": { "value": "material_print_temperature" }, - + "switch_extruder_retraction_speeds": {"default_value": 15 }, "switch_extruder_retraction_speed": {"default_value": 15 }, "switch_extruder_prime_speed": {"default_value": 15 }, @@ -57,9 +55,9 @@ "prime_tower_wipe_enabled": { "default_value": false }, "prime_tower_min_volume": { "default_value": 50 }, "dual_pre_wipe": { "default_value": false }, - + "prime_blob_enable": { "enabled": true }, - + "acceleration_enabled": { "value": "True" }, "acceleration_layer_0": { "value": "acceleration_topbottom" }, "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" }, @@ -70,7 +68,7 @@ "acceleration_travel": { "value": "acceleration_print" }, "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 3000)" }, "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 1000 / 1000)" }, - + "cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" }, "cool_min_layer_time": { "default_value": 10 }, @@ -83,9 +81,9 @@ "jerk_topbottom": { "value": "math.ceil(jerk_print * 5 / 25)" }, "jerk_wall": { "value": "math.ceil(jerk_print * 10 / 25)" }, "jerk_wall_0": { "value": "math.ceil(jerk_wall * 5 / 10)" }, - + "wall_thickness": { "value": "1.2" }, - + "retraction_amount": { "default_value": 3 }, "retraction_speed": { "default_value": 15 }, "retraction_retract_speed": { "default_value": 15 }, @@ -112,4 +110,4 @@ }, "machine_extruder_count": { "default_value": 2 } } -} \ No newline at end of file +} diff --git a/resources/definitions/cartesio.def.json b/resources/definitions/cartesio.def.json index 44f3153015..9deb257ac3 100644 --- a/resources/definitions/cartesio.def.json +++ b/resources/definitions/cartesio.def.json @@ -15,9 +15,8 @@ "has_variants": true, "variants_name": "Nozzle size", - "preferred_variant": "*0.8*", - "preferred_material": "*pla*", - "preferred_quality": "*normal*", + "preferred_variant_name": "0.8 mm", + "preferred_quality_type": "normal", "machine_extruder_trains": { diff --git a/resources/definitions/creality_cr10.def.json b/resources/definitions/creality_cr10.def.json index 7a58adcd4d..eb0b8c7306 100644 --- a/resources/definitions/creality_cr10.def.json +++ b/resources/definitions/creality_cr10.def.json @@ -7,7 +7,7 @@ "author": "Michael Wildermuth", "manufacturer": "Creality3D", "file_formats": "text/x-gcode", - "preferred_quality": "*Draft*" + "preferred_quality_type": "draft" }, "overrides": { "machine_width": { diff --git a/resources/definitions/fabtotum.def.json b/resources/definitions/fabtotum.def.json index 87ce11a35c..a53e9d9efb 100644 --- a/resources/definitions/fabtotum.def.json +++ b/resources/definitions/fabtotum.def.json @@ -13,8 +13,8 @@ "has_machine_quality": true, "has_variants": true, "variants_name": "Head", - "preferred_variant": "*lite04*", - "preferred_material": "*fabtotum_pla*", + "preferred_variant_name": "Lite 0.4 mm", + "preferred_material": "fabtotum_pla", "supports_usb_connection": false }, diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 366158d042..274c13d0f3 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -12,7 +12,6 @@ "visible": false, "has_materials": true, "preferred_material": "generic_pla", - "preferred_quality": "*normal*", "preferred_quality_type": "normal", "machine_extruder_trains": { diff --git a/resources/definitions/gmax15plus.def.json b/resources/definitions/gmax15plus.def.json index d651a86bb3..3a207cd054 100644 --- a/resources/definitions/gmax15plus.def.json +++ b/resources/definitions/gmax15plus.def.json @@ -12,9 +12,7 @@ "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl", "has_variants": true, "variants_name": "Hotend", - "preferred_variant": "*0.5mm E3D (Default)*" - - + "preferred_variant_name": "0.5mm E3D (Default)" }, "overrides": { diff --git a/resources/definitions/gmax15plus_dual.def.json b/resources/definitions/gmax15plus_dual.def.json index 4e9a91e88d..af26a2e30a 100644 --- a/resources/definitions/gmax15plus_dual.def.json +++ b/resources/definitions/gmax15plus_dual.def.json @@ -12,11 +12,11 @@ "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl", "has_variants": true, "variants_name": "Hotend", - "preferred_variant": "*0.5mm E3D (Default)*", + "preferred_variant_name": "0.5mm E3D (Default)", "machine_extruder_trains": { "0": "gmax15plus_dual_extruder_0", "1": "gmax15plus_dual_extruder_1" - } + } }, "overrides": { diff --git a/resources/definitions/imade3d_jellybox.def.json b/resources/definitions/imade3d_jellybox.def.json index 11df730408..b234e4b2cd 100644 --- a/resources/definitions/imade3d_jellybox.def.json +++ b/resources/definitions/imade3d_jellybox.def.json @@ -9,9 +9,8 @@ "platform": "imade3d_jellybox_platform.stl", "platform_offset": [ 0, -0.3, 0], "file_formats": "text/x-gcode", - "preferred_variant": "*0.4*", - "preferred_material": "*generic_pla*", - "preferred_quality": "*fast*", + "preferred_variant_name": "0.4 mm", + "preferred_quality_type": "fast", "has_materials": true, "has_variants": true, "has_machine_materials": true, diff --git a/resources/definitions/malyan_m200.def.json b/resources/definitions/malyan_m200.def.json index 365b031c43..a3f4f81ecf 100644 --- a/resources/definitions/malyan_m200.def.json +++ b/resources/definitions/malyan_m200.def.json @@ -11,7 +11,7 @@ "platform": "malyan_m200_platform.stl", "has_machine_quality": true, "has_materials": true, - "preferred_quality": "*normal*", + "preferred_quality_type": "normal", "supports_usb_connection": true, "visible": true, "first_start_actions": ["MachineSettingsAction"], diff --git a/resources/definitions/monoprice_select_mini_v2.def.json b/resources/definitions/monoprice_select_mini_v2.def.json index 87014c136b..99bb7ef50a 100644 --- a/resources/definitions/monoprice_select_mini_v2.def.json +++ b/resources/definitions/monoprice_select_mini_v2.def.json @@ -10,7 +10,7 @@ "file_formats": "text/x-gcode", "has_machine_quality": true, "has_materials": true, - "preferred_quality": "*normal*", + "preferred_quality_type": "normal", "visible": true }, diff --git a/resources/definitions/tevo_blackwidow.def.json b/resources/definitions/tevo_blackwidow.def.json index 04cadfb160..22f7095e17 100644 --- a/resources/definitions/tevo_blackwidow.def.json +++ b/resources/definitions/tevo_blackwidow.def.json @@ -11,7 +11,7 @@ "has_materials": false, "has_machine_quality": true, "platform": "tevo_blackwidow.stl", - "preferred_quality": "*normal*" + "preferred_quality_type": "normal" }, "overrides": { diff --git a/resources/definitions/ultimaker2_plus.def.json b/resources/definitions/ultimaker2_plus.def.json index bc90776289..935bf5b6c0 100644 --- a/resources/definitions/ultimaker2_plus.def.json +++ b/resources/definitions/ultimaker2_plus.def.json @@ -9,7 +9,6 @@ "file_formats": "text/x-gcode", "platform": "ultimaker2_platform.obj", "platform_texture": "Ultimaker2Plusbackplate.png", - "preferred_variant": "*0.4*", "preferred_variant_name": "0.4 mm", "has_variants": true, "has_materials": true, diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 9a98b83efb..8fda63f970 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -15,9 +15,7 @@ "has_machine_materials": true, "has_variant_materials": true, "has_variants": true, - "preferred_variant": "*aa04*", "preferred_variant_name": "AA 0.4", - "preferred_quality": "*Normal*", "preferred_quality_type": "normal", "variants_name": "Print core", "machine_extruder_trains": diff --git a/resources/definitions/ultimaker3_extended.def.json b/resources/definitions/ultimaker3_extended.def.json index 385199f4f1..3a1be3a303 100644 --- a/resources/definitions/ultimaker3_extended.def.json +++ b/resources/definitions/ultimaker3_extended.def.json @@ -16,7 +16,7 @@ "has_variant_materials": true, "has_materials": true, "has_variants": true, - "preferred_variant": "*aa04*", + "preferred_variant_name": "AA 0.4", "variants_name": "Print core", "machine_extruder_trains": { From 5ad4447e379cc4b40b2aade200a57d92d719c64d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 17:02:04 +0100 Subject: [PATCH 054/371] WIP: Update and fix definition files --- resources/definitions/101Hero.def.json | 1 + resources/definitions/3dator.def.json | 1 + resources/definitions/bq_hephestos_2.def.json | 1 + resources/definitions/builder_premium_large.def.json | 1 + resources/definitions/builder_premium_medium.def.json | 1 + resources/definitions/builder_premium_small.def.json | 1 + resources/definitions/cartesio.def.json | 1 + resources/definitions/delta_go.def.json | 3 ++- resources/definitions/deltacomb.def.json | 3 ++- resources/definitions/folgertech_FT-5.def.json | 3 ++- resources/definitions/gmax15plus.def.json | 1 + resources/definitions/gmax15plus_dual.def.json | 1 + resources/definitions/helloBEEprusa.def.json | 3 ++- resources/definitions/imade3d_jellybox.def.json | 1 + resources/definitions/julia.def.json | 3 ++- resources/definitions/makerbotreplicator.def.json | 3 ++- resources/definitions/malyan_m200.def.json | 1 + resources/definitions/mankati_fullscale_xt_plus.def.json | 3 ++- resources/definitions/ord.def.json | 1 + resources/definitions/printrbot_play.def.json | 3 ++- resources/definitions/printrbot_simple.def.json | 3 ++- resources/definitions/printrbot_simple_extended.def.json | 3 ++- resources/definitions/prusa_i3_mk2.def.json | 3 ++- resources/definitions/punchtec_connect_xl.def.json | 3 ++- resources/definitions/rigid3d.def.json | 3 ++- resources/definitions/rigid3d_3rdgen.def.json | 3 ++- resources/definitions/rigid3d_hobby.def.json | 3 ++- resources/definitions/rigid3d_zero.def.json | 3 ++- resources/definitions/robo_3d_r1.def.json | 3 ++- resources/definitions/tam.def.json | 1 + resources/definitions/zone3d_printer.def.json | 3 ++- 31 files changed, 49 insertions(+), 18 deletions(-) diff --git a/resources/definitions/101Hero.def.json b/resources/definitions/101Hero.def.json index 620fcfb519..ead1bd4cd2 100644 --- a/resources/definitions/101Hero.def.json +++ b/resources/definitions/101Hero.def.json @@ -8,6 +8,7 @@ "manufacturer": "101Hero", "file_formats": "text/x-gcode", "platform": "101hero-platform.stl", + "preferred_material": "generic_pla_175", "supports_usb_connection": true }, diff --git a/resources/definitions/3dator.def.json b/resources/definitions/3dator.def.json index 19307bfddd..3d9b2bd7e5 100644 --- a/resources/definitions/3dator.def.json +++ b/resources/definitions/3dator.def.json @@ -9,6 +9,7 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "supports_usb_connection": true, + "preferred_material": "generic_pla_175", "platform": "3dator_platform.stl" }, diff --git a/resources/definitions/bq_hephestos_2.def.json b/resources/definitions/bq_hephestos_2.def.json index a3493334b6..4c36384d63 100644 --- a/resources/definitions/bq_hephestos_2.def.json +++ b/resources/definitions/bq_hephestos_2.def.json @@ -8,6 +8,7 @@ "manufacturer": "BQ", "platform": "bq_hephestos_2_platform.stl", "platform_offset": [6, 1320, 0 ], + "preferred_material": "generic_pla_175", "file_formats": "text/x-gcode" }, diff --git a/resources/definitions/builder_premium_large.def.json b/resources/definitions/builder_premium_large.def.json index deb1539a9a..15e85d7910 100644 --- a/resources/definitions/builder_premium_large.def.json +++ b/resources/definitions/builder_premium_large.def.json @@ -13,6 +13,7 @@ "platform_offset": [-126, -36, 117], "has_machine_quality": true, "preferred_quality_type": "normal", + "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "builder_premium_large_rear", diff --git a/resources/definitions/builder_premium_medium.def.json b/resources/definitions/builder_premium_medium.def.json index c28c7c5de6..500bfca75f 100644 --- a/resources/definitions/builder_premium_medium.def.json +++ b/resources/definitions/builder_premium_medium.def.json @@ -13,6 +13,7 @@ "platform_offset": [-126, -36, 117], "has_machine_quality": true, "preferred_quality_type": "normal", + "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "builder_premium_medium_rear", diff --git a/resources/definitions/builder_premium_small.def.json b/resources/definitions/builder_premium_small.def.json index 8e2fe44631..1d6451430c 100644 --- a/resources/definitions/builder_premium_small.def.json +++ b/resources/definitions/builder_premium_small.def.json @@ -12,6 +12,7 @@ "platform_offset": [-126, -36, 117], "has_machine_quality": true, "preferred_quality_type": "normal", + "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "builder_premium_small_rear", diff --git a/resources/definitions/cartesio.def.json b/resources/definitions/cartesio.def.json index 9deb257ac3..49eecd2c24 100644 --- a/resources/definitions/cartesio.def.json +++ b/resources/definitions/cartesio.def.json @@ -17,6 +17,7 @@ "variants_name": "Nozzle size", "preferred_variant_name": "0.8 mm", "preferred_quality_type": "normal", + "preferred_material": "generic_pla_175", "machine_extruder_trains": { diff --git a/resources/definitions/delta_go.def.json b/resources/definitions/delta_go.def.json index a6d75b2983..6e9fa4aa09 100644 --- a/resources/definitions/delta_go.def.json +++ b/resources/definitions/delta_go.def.json @@ -8,7 +8,8 @@ "manufacturer": "Deltaprintr", "file_formats": "text/x-gcode", "platform_offset": [0, 0, 0], - "platform": "" + "platform": "", + "preferred_material": "generic_pla_175" }, "overrides": { "machine_name": { "default_value": "Delta Go" }, diff --git a/resources/definitions/deltacomb.def.json b/resources/definitions/deltacomb.def.json index 7e6e956dbc..26004e835e 100644 --- a/resources/definitions/deltacomb.def.json +++ b/resources/definitions/deltacomb.def.json @@ -10,7 +10,8 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "platform": "deltacomb.stl", - "has_machine_quality": true + "has_machine_quality": true, + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/folgertech_FT-5.def.json b/resources/definitions/folgertech_FT-5.def.json index 71c6987a1a..7c3489951f 100644 --- a/resources/definitions/folgertech_FT-5.def.json +++ b/resources/definitions/folgertech_FT-5.def.json @@ -7,7 +7,8 @@ "author": "Jaime van Kessel & Paul Bussiere", "manufacturer": "Folger Tech", "file_formats": "text/x-gcode", - "platform": "FT-5_build_plate.stl" + "platform": "FT-5_build_plate.stl", + "preferred_material": "generic_pla_175" }, "overrides": { "machine_heated_bed": { "default_value": true }, diff --git a/resources/definitions/gmax15plus.def.json b/resources/definitions/gmax15plus.def.json index 3a207cd054..8bd765d156 100644 --- a/resources/definitions/gmax15plus.def.json +++ b/resources/definitions/gmax15plus.def.json @@ -12,6 +12,7 @@ "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl", "has_variants": true, "variants_name": "Hotend", + "preferred_material": "generic_pla_175", "preferred_variant_name": "0.5mm E3D (Default)" }, diff --git a/resources/definitions/gmax15plus_dual.def.json b/resources/definitions/gmax15plus_dual.def.json index af26a2e30a..e93fc7c6a0 100644 --- a/resources/definitions/gmax15plus_dual.def.json +++ b/resources/definitions/gmax15plus_dual.def.json @@ -12,6 +12,7 @@ "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl", "has_variants": true, "variants_name": "Hotend", + "preferred_material": "generic_pla_175", "preferred_variant_name": "0.5mm E3D (Default)", "machine_extruder_trains": { "0": "gmax15plus_dual_extruder_0", diff --git a/resources/definitions/helloBEEprusa.def.json b/resources/definitions/helloBEEprusa.def.json index 2699a6c7d7..26692f8486 100644 --- a/resources/definitions/helloBEEprusa.def.json +++ b/resources/definitions/helloBEEprusa.def.json @@ -9,6 +9,7 @@ "platform": "BEEVERYCREATIVE-helloBEEprusa.stl", "platform_offset": [-226, -75, -196], "file_formats": "text/x-gcode", + "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "hBp_extruder_left", @@ -52,4 +53,4 @@ "retraction_speed": { "default_value": 15.0}, "retraction_amount": { "default_value": 1.5} } -} \ No newline at end of file +} diff --git a/resources/definitions/imade3d_jellybox.def.json b/resources/definitions/imade3d_jellybox.def.json index b234e4b2cd..42bf61f388 100644 --- a/resources/definitions/imade3d_jellybox.def.json +++ b/resources/definitions/imade3d_jellybox.def.json @@ -9,6 +9,7 @@ "platform": "imade3d_jellybox_platform.stl", "platform_offset": [ 0, -0.3, 0], "file_formats": "text/x-gcode", + "preferred_material": "generic_pla_175", "preferred_variant_name": "0.4 mm", "preferred_quality_type": "fast", "has_materials": true, diff --git a/resources/definitions/julia.def.json b/resources/definitions/julia.def.json index 7fdee30272..8a9402b332 100644 --- a/resources/definitions/julia.def.json +++ b/resources/definitions/julia.def.json @@ -7,7 +7,8 @@ "author": "Ultimaker", "manufacturer": "Fracktal", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/makerbotreplicator.def.json b/resources/definitions/makerbotreplicator.def.json index 3d690990ce..77aa5ab667 100644 --- a/resources/definitions/makerbotreplicator.def.json +++ b/resources/definitions/makerbotreplicator.def.json @@ -7,7 +7,8 @@ "author": "Ultimaker", "manufacturer": "MakerBot", "file_formats": "application/x3g", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/malyan_m200.def.json b/resources/definitions/malyan_m200.def.json index a3f4f81ecf..855fe58cd2 100644 --- a/resources/definitions/malyan_m200.def.json +++ b/resources/definitions/malyan_m200.def.json @@ -11,6 +11,7 @@ "platform": "malyan_m200_platform.stl", "has_machine_quality": true, "has_materials": true, + "preferred_material": "generic_pla_175", "preferred_quality_type": "normal", "supports_usb_connection": true, "visible": true, diff --git a/resources/definitions/mankati_fullscale_xt_plus.def.json b/resources/definitions/mankati_fullscale_xt_plus.def.json index 15ba889efc..39b3d018bf 100644 --- a/resources/definitions/mankati_fullscale_xt_plus.def.json +++ b/resources/definitions/mankati_fullscale_xt_plus.def.json @@ -7,7 +7,8 @@ "author": "RBC", "manufacturer": "Mankati", "file_formats": "text/x-gcode", - "platform": "mankati_fullscale_xt_plus_platform.stl" + "platform": "mankati_fullscale_xt_plus_platform.stl", + "preferred_material": "generic_pla_175" }, "overrides": { "machine_name": { "default_value": "Mankati Fullscale XT Plus" }, diff --git a/resources/definitions/ord.def.json b/resources/definitions/ord.def.json index 3238583ceb..471385cc7c 100644 --- a/resources/definitions/ord.def.json +++ b/resources/definitions/ord.def.json @@ -7,6 +7,7 @@ "author": "Ultimaker", "manufacturer": "ORD Solutions", "file_formats": "text/x-gcode", + "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "ord_extruder_0", diff --git a/resources/definitions/printrbot_play.def.json b/resources/definitions/printrbot_play.def.json index 36ef93e60c..3f98aff798 100644 --- a/resources/definitions/printrbot_play.def.json +++ b/resources/definitions/printrbot_play.def.json @@ -7,7 +7,8 @@ "author": "Chris Pearson", "manufacturer": "Printrbot", "file_formats": "text/x-gcode", - "platform": "printrbot_play.stl" + "platform": "printrbot_play.stl", + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/printrbot_simple.def.json b/resources/definitions/printrbot_simple.def.json index 7c86617ce5..52472fd743 100644 --- a/resources/definitions/printrbot_simple.def.json +++ b/resources/definitions/printrbot_simple.def.json @@ -8,7 +8,8 @@ "manufacturer": "PrintrBot", "platform": "printrbot_simple_metal_platform.stl", "platform_offset": [0, -3.45, 0], - "file_formats": "text/x-gcode" + "file_formats": "text/x-gcode", + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/printrbot_simple_extended.def.json b/resources/definitions/printrbot_simple_extended.def.json index 95395efb23..9463af5554 100644 --- a/resources/definitions/printrbot_simple_extended.def.json +++ b/resources/definitions/printrbot_simple_extended.def.json @@ -8,7 +8,8 @@ "manufacturer": "PrintrBot", "platform": "printrbot_simple_metal_upgrade.stl", "platform_offset": [0, -0.3, 0], - "file_formats": "text/x-gcode" + "file_formats": "text/x-gcode", + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/prusa_i3_mk2.def.json b/resources/definitions/prusa_i3_mk2.def.json index e58eb4d903..b70e2ab1dc 100644 --- a/resources/definitions/prusa_i3_mk2.def.json +++ b/resources/definitions/prusa_i3_mk2.def.json @@ -9,7 +9,8 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "platform": "prusai3_platform.stl", - "has_materials": true + "has_materials": true, + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/punchtec_connect_xl.def.json b/resources/definitions/punchtec_connect_xl.def.json index 02d3562b41..c1f5780270 100644 --- a/resources/definitions/punchtec_connect_xl.def.json +++ b/resources/definitions/punchtec_connect_xl.def.json @@ -12,7 +12,8 @@ "0": "punchtec_connect_xl_extruder_0", "1": "punchtec_connect_xl_extruder_1" }, - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/rigid3d.def.json b/resources/definitions/rigid3d.def.json index 97b0ebd276..21673e0010 100644 --- a/resources/definitions/rigid3d.def.json +++ b/resources/definitions/rigid3d.def.json @@ -7,7 +7,8 @@ "author": "Ultimaker", "manufacturer": "Rigid3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/rigid3d_3rdgen.def.json b/resources/definitions/rigid3d_3rdgen.def.json index 46c22bfa57..b5c2ae87ce 100644 --- a/resources/definitions/rigid3d_3rdgen.def.json +++ b/resources/definitions/rigid3d_3rdgen.def.json @@ -7,7 +7,8 @@ "author": "Ultimaker", "manufacturer": "Rigid3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/rigid3d_hobby.def.json b/resources/definitions/rigid3d_hobby.def.json index 872cc3e6f4..4b18521319 100644 --- a/resources/definitions/rigid3d_hobby.def.json +++ b/resources/definitions/rigid3d_hobby.def.json @@ -7,7 +7,8 @@ "author": "Ultimaker", "manufacturer": "Rigid3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/rigid3d_zero.def.json b/resources/definitions/rigid3d_zero.def.json index 56fb8284c0..44e5e7e96a 100644 --- a/resources/definitions/rigid3d_zero.def.json +++ b/resources/definitions/rigid3d_zero.def.json @@ -7,7 +7,8 @@ "author": "Ultimaker", "manufacturer": "Rigid3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/robo_3d_r1.def.json b/resources/definitions/robo_3d_r1.def.json index b179779c59..1c87e4575f 100644 --- a/resources/definitions/robo_3d_r1.def.json +++ b/resources/definitions/robo_3d_r1.def.json @@ -7,7 +7,8 @@ "author": "Ultimaker", "manufacturer": "Robo 3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { diff --git a/resources/definitions/tam.def.json b/resources/definitions/tam.def.json index 20bc96358d..11833b7841 100644 --- a/resources/definitions/tam.def.json +++ b/resources/definitions/tam.def.json @@ -10,6 +10,7 @@ "platform": "tam_series1.stl", "platform_offset": [-580.0, -6.23, 253.5], "has_materials": false, + "preferred_material": "generic_pla_175", "supported_actions":["UpgradeFirmware"] }, "overrides": { diff --git a/resources/definitions/zone3d_printer.def.json b/resources/definitions/zone3d_printer.def.json index bac8968951..b7f852054a 100644 --- a/resources/definitions/zone3d_printer.def.json +++ b/resources/definitions/zone3d_printer.def.json @@ -7,7 +7,8 @@ "author": "Ultimaker", "manufacturer": "Unknown", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0] + "platform_offset": [ 0, 0, 0], + "preferred_material": "generic_pla_175" }, "overrides": { From 194988dc9a0c0235e2f0ad2eefc6d182db6dcb1b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 20:44:44 +0100 Subject: [PATCH 055/371] WIP: Improve quality search fall back --- cura/Machines/QualityManager.py | 151 ++++++++------------------------ 1 file changed, 35 insertions(+), 116 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 132c2e3dfa..ad4fa6fc8f 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -189,7 +189,6 @@ class QualityManager(QObject): # Initialize quality self._initializeQualityChangesTables() - def _initializeQualityChangesTables(self): # Initialize the lookup tree for quality_changes profiles with following structure: # -> -> @@ -265,24 +264,24 @@ class QualityManager(QObject): if machine_definition_id is None: machine_definition_id = machine.definition.getId() + # To find the quality container for the GlobalStack, check in the following fall-back manner: + # (1) the machine-specific node + # (2) the generic node machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) - if not machine_node: - raise RuntimeError("Cannot find node for machine def [%s] in Quality lookup table" % machine_definition_id) + default_machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(self._default_machine_definition_id) + nodes_to_check = [machine_node, default_machine_node] - # iterate over all quality_types in the machine node - node_to_fetch_global = machine_node + # Iterate over all quality_types in the machine node quality_group_dict = {} - if not node_to_fetch_global.quality_type_map: - # Fallback mechanism: - # If there is no machine-specific quality, fallback to use the default fdmprinter's. - node_to_fetch_global = self._machine_variant_material_quality_type_to_quality_dict.get(self._default_machine_definition_id) - for quality_type, quality_node in node_to_fetch_global.quality_type_map.items(): - quality_group = QualityGroup(quality_node.metadata["name"], quality_type) - quality_group.node_for_global = quality_node + for node in nodes_to_check: + if node and node.quality_type_map: + for quality_type, quality_node in node.quality_type_map.items(): + quality_group = QualityGroup(quality_node.metadata["name"], quality_type) + quality_group.node_for_global = quality_node + quality_group_dict[quality_type] = quality_group + break - quality_group_dict[quality_type] = quality_group - - # Iterate over all extruders + # Iterate over all extruders to find quality containers for each extruder for position, extruder in machine.extruders.items(): variant_name = None if extruder.variant.getId() != "empty_variant": @@ -303,120 +302,40 @@ class QualityManager(QObject): if fallback_root_material_metadata: root_material_id_list.append(fallback_root_material_metadata["id"]) - variant_node = None - material_node = None + nodes_to_check = [] if variant_name: # In this case, we have both a specific variant and a specific material variant_node = machine_node.getChildNode(variant_name) - if not variant_node: - continue - if has_material: + if variant_node and has_material: for root_material_id in root_material_id_list: material_node = variant_node.getChildNode(root_material_id) if material_node: + nodes_to_check.append(material_node) break - if not material_node: - # No suitable quality found: not supported - Logger.log("d", "Cannot find quality with machine [%s], variant name [%s], and materials [%s].", - machine_definition_id, variant_name, ", ".join(root_material_id_list)) + nodes_to_check.append(variant_node) - else: - # In this case, we only have a specific material but NOT a variant - if has_material: - for root_material_id in root_material_id_list: - material_node = machine_node.getChildNode(root_material_id) - if material_node: - break - if not material_node: - # No suitable quality found: not supported - Logger.log("d", "Cannot find quality with machine [%s], variant name [%s], and materials [%s].", - machine_definition_id, variant_name, ", ".join(root_material_id_list)) + # In this case, we only have a specific material but NOT a variant + if has_material: + for root_material_id in root_material_id_list: + material_node = machine_node.getChildNode(root_material_id) + if material_node: + nodes_to_check.append(material_node) + break - node_to_check = material_node - if not node_to_check: - node_to_check = variant_node - if not node_to_check: - node_to_check = machine_node + nodes_to_check += [machine_node, default_machine_node] + for node in nodes_to_check: + if node and node.quality_type_map: + for quality_type, quality_node in node.quality_type_map.items(): + if quality_type not in quality_group_dict: + quality_group = QualityGroup(quality_node.metadata["name"], quality_type) + quality_group_dict[quality_type] = quality_group - for quality_type, quality_node in node_to_check.quality_type_map.items(): - if quality_type not in quality_group_dict: - quality_group = QualityGroup(quality_node.metadata["name"], quality_type) - quality_group_dict[quality_type] = quality_group - - quality_group = quality_group_dict[quality_type] - - quality_group.nodes_for_extruders[position] = quality_node + quality_group = quality_group_dict[quality_type] + quality_group.nodes_for_extruders[position] = quality_node + break # Update availabilities for each quality group self._updateQualityGroupsAvailability(machine, quality_group_dict.values()) return quality_group_dict - - - def getQuality(self, quality_type: str, machine: "GlobalStack"): - # Get machine definition ID - machine_definition_id = self._default_machine_definition_id - if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): - machine_definition_id = machine.getMetaDataEntry("quality_definition") - if machine_definition_id is None: - machine_definition_id = machine.definition.getId() - - machine_quality = self.getQualityContainer(quality_type, machine_definition_id) - extruder_quality_dict = {} - for position, extruder in machine.extruders.items(): - variant = extruder.variant - material = extruder.material - - variant_name = variant.getName() - if variant.getId() == "empty_variant": - variant_name = None - root_material_id = material.getMetaDataEntry("base_file") - if material.getId() == "empty_material": - root_material_id = None - - extruder_quality = self.getQualityContainer(quality_type, machine_definition_id, - variant_name, root_material_id) - extruder_quality_dict[position] = extruder_quality - - # TODO: return as a group - return machine_quality, extruder_quality_dict - - def getQualityContainer(self, quality_type: str, machine_definition_id: dict, - variant_name: Optional[str] = None, - root_material_id: Optional[str] = None) -> "InstanceContainer": - assert machine_definition_id is not None - assert quality_type is not None - - # If the specified quality cannot be found, empty_quality will be returned. - container = self._empty_quality_container - - machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) - variant_node = None - material_node = None - if machine_node is not None: - if variant_name is not None: - variant_node = machine_node.getChildNode(variant_name) - if variant_node is not None: - if root_material_id is not None: - material_node = variant_node.getChildNode(root_material_id) - elif root_material_id is not None: - material_node = machine_node.getChildNode(root_material_id) - - nodes_to_try = [material_node, variant_node, machine_node] - if machine_definition_id != self._default_machine_definition_id: - default_machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(self._default_machine_definition_id) - nodes_to_try.append(default_machine_node) - - for node in nodes_to_try: - if node is None: - continue - quality_node = node.getQualityNode(quality_type) - if quality_node is None: - continue - - container = quality_node.getContainer() - break - - return container - From c79dd313ac9942b72a6ea5a7f51dae50b6ae1139 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 20:45:34 +0100 Subject: [PATCH 056/371] WIP: Refactor duplicated code and clean up --- cura/Machines/MachineTools.py | 25 +++++++++++++++++++++++++ cura/Machines/QualityManager.py | 30 +++++++++++------------------- cura/Settings/CuraStackBuilder.py | 5 ++--- 3 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 cura/Machines/MachineTools.py diff --git a/cura/Machines/MachineTools.py b/cura/Machines/MachineTools.py new file mode 100644 index 0000000000..91daa2490b --- /dev/null +++ b/cura/Machines/MachineTools.py @@ -0,0 +1,25 @@ +from UM.Util import parseBool + + +# +# Gets the machine definition ID that can be used to search for Quality containers that are suitable for the given +# machine. The rule is as follows: +# 1. By default, the machine definition ID for quality container search will be "fdmprinter", which is the generic +# machine. +# 2. If a machine has its own machine quality (with "has_machine_quality = True"), we should use the given machine's +# own machine definition ID for quality search. +# Example: for an Ultimaker 3, the definition ID should be "ultimaker3". +# 3. When condition (2) is met, AND the machine has "quality_definition" defined in its definition file, then the +# definition ID specified in "quality_definition" should be used. +# Example: for an Ultimaker 3 Extended, it has "quality_definition = ultimaker3". This means Ultimaker 3 Extended +# shares the same set of qualities profiles as Ultimaker 3. +# +def getMachineDefinitionIDForQualitySearch(machine: "GlobalStack", default_definition_id: str = "fdmprinter") -> str: + machine_definition_id = default_definition_id + if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): + # Only use the machine's own quality definition ID if this machine has machine quality. + machine_definition_id = machine.getMetaDataEntry("quality_definition") + if machine_definition_id is None: + machine_definition_id = machine.definition.getId() + + return machine_definition_id diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index ad4fa6fc8f..cb723f41d0 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -1,14 +1,14 @@ from typing import Optional -from PyQt5.Qt import pyqtSignal, QObject +from PyQt5.Qt import QObject from UM.Application import Application from UM.Logger import Logger -from UM.Settings.InstanceContainer import InstanceContainer from UM.Util import parseBool from cura.Machines.ContainerGroup import ContainerGroup from cura.Machines.ContainerNode import ContainerNode +from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch # @@ -114,12 +114,12 @@ class QualityManager(QObject): def __init__(self, container_registry, parent = None): super().__init__(parent) - - self._material_manager = Application.getInstance()._material_manager - + self._application = Application.getInstance() + self._material_manager = self._application._material_manager self._container_registry = container_registry - self._empty_quality_container = self._container_registry.findInstanceContainers(id = "empty_quality")[0] - #self._empty_quality_changes_container = self._container_registry.findInstanceContainers(id = "empty_quality_changes")[0] + + self._empty_quality_container = self._application.empty_quality_container + self._empty_quality_changes_container = self._application.empty_quality_changes_container self._machine_variant_material_quality_type_to_quality_dict = {} # for quality lookup self._machine_quality_type_to_quality_changes_dict = {} # for quality_changes lookup @@ -229,12 +229,8 @@ class QualityManager(QObject): # Returns a dict of "custom profile name" -> QualityChangesGroup def getQualityChangesGroups(self, machine: "GlobalStack") -> dict: # TODO: How to make this simpler? - # Get machine definition ID - machine_definition_id = self._default_machine_definition_id - if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): - machine_definition_id = machine.getMetaDataEntry("quality_definition") - if machine_definition_id is None: - machine_definition_id = machine.definition.getId() + # Get machine definition ID for quality search + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id) if not machine_node: @@ -257,12 +253,8 @@ class QualityManager(QObject): def getQualityGroups(self, machine: "GlobalStack") -> dict: # TODO: How to make this simpler, including the fall backs. - # Get machine definition ID - machine_definition_id = self._default_machine_definition_id - if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): - machine_definition_id = machine.getMetaDataEntry("quality_definition") - if machine_definition_id is None: - machine_definition_id = machine.definition.getId() + # Get machine definition ID for quality search + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) # To find the quality container for the GlobalStack, check in the following fall-back manner: # (1) the machine-specific node diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 365658ee48..19a5caacb8 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from UM.Logger import Logger @@ -206,9 +206,8 @@ class CuraStackBuilder: return container - @classmethod - def createDefinitionChangesContainer(cls, container_stack, container_name, container_index = None): + def createDefinitionChangesContainer(cls, container_stack, container_name): from cura.CuraApplication import CuraApplication unique_container_name = ContainerRegistry.getInstance().uniqueName(container_name) From 73968e5c4894c2b196c3f1825cfc931cd4ce765a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 20:46:29 +0100 Subject: [PATCH 057/371] Revert "WIP: Update and fix definition files" This reverts commit 27a346a58beaea9de249ebf229f0979d51ad21ff. --- resources/definitions/101Hero.def.json | 1 - resources/definitions/3dator.def.json | 1 - resources/definitions/bq_hephestos_2.def.json | 1 - resources/definitions/builder_premium_large.def.json | 1 - resources/definitions/builder_premium_medium.def.json | 1 - resources/definitions/builder_premium_small.def.json | 1 - resources/definitions/cartesio.def.json | 1 - resources/definitions/delta_go.def.json | 3 +-- resources/definitions/deltacomb.def.json | 3 +-- resources/definitions/folgertech_FT-5.def.json | 3 +-- resources/definitions/gmax15plus.def.json | 1 - resources/definitions/gmax15plus_dual.def.json | 1 - resources/definitions/helloBEEprusa.def.json | 3 +-- resources/definitions/imade3d_jellybox.def.json | 1 - resources/definitions/julia.def.json | 3 +-- resources/definitions/makerbotreplicator.def.json | 3 +-- resources/definitions/malyan_m200.def.json | 1 - resources/definitions/mankati_fullscale_xt_plus.def.json | 3 +-- resources/definitions/ord.def.json | 1 - resources/definitions/printrbot_play.def.json | 3 +-- resources/definitions/printrbot_simple.def.json | 3 +-- resources/definitions/printrbot_simple_extended.def.json | 3 +-- resources/definitions/prusa_i3_mk2.def.json | 3 +-- resources/definitions/punchtec_connect_xl.def.json | 3 +-- resources/definitions/rigid3d.def.json | 3 +-- resources/definitions/rigid3d_3rdgen.def.json | 3 +-- resources/definitions/rigid3d_hobby.def.json | 3 +-- resources/definitions/rigid3d_zero.def.json | 3 +-- resources/definitions/robo_3d_r1.def.json | 3 +-- resources/definitions/tam.def.json | 1 - resources/definitions/zone3d_printer.def.json | 3 +-- ...r_0.def.json => punchtec_connect_xl_extruder_left.def.json} | 0 ..._1.def.json => punchtec_connect_xl_extruder_right.def.json} | 0 33 files changed, 18 insertions(+), 49 deletions(-) rename resources/extruders/{punchtec_connect_xl_extruder_0.def.json => punchtec_connect_xl_extruder_left.def.json} (100%) rename resources/extruders/{punchtec_connect_xl_extruder_1.def.json => punchtec_connect_xl_extruder_right.def.json} (100%) diff --git a/resources/definitions/101Hero.def.json b/resources/definitions/101Hero.def.json index ead1bd4cd2..620fcfb519 100644 --- a/resources/definitions/101Hero.def.json +++ b/resources/definitions/101Hero.def.json @@ -8,7 +8,6 @@ "manufacturer": "101Hero", "file_formats": "text/x-gcode", "platform": "101hero-platform.stl", - "preferred_material": "generic_pla_175", "supports_usb_connection": true }, diff --git a/resources/definitions/3dator.def.json b/resources/definitions/3dator.def.json index 3d9b2bd7e5..19307bfddd 100644 --- a/resources/definitions/3dator.def.json +++ b/resources/definitions/3dator.def.json @@ -9,7 +9,6 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "supports_usb_connection": true, - "preferred_material": "generic_pla_175", "platform": "3dator_platform.stl" }, diff --git a/resources/definitions/bq_hephestos_2.def.json b/resources/definitions/bq_hephestos_2.def.json index 4c36384d63..a3493334b6 100644 --- a/resources/definitions/bq_hephestos_2.def.json +++ b/resources/definitions/bq_hephestos_2.def.json @@ -8,7 +8,6 @@ "manufacturer": "BQ", "platform": "bq_hephestos_2_platform.stl", "platform_offset": [6, 1320, 0 ], - "preferred_material": "generic_pla_175", "file_formats": "text/x-gcode" }, diff --git a/resources/definitions/builder_premium_large.def.json b/resources/definitions/builder_premium_large.def.json index 15e85d7910..deb1539a9a 100644 --- a/resources/definitions/builder_premium_large.def.json +++ b/resources/definitions/builder_premium_large.def.json @@ -13,7 +13,6 @@ "platform_offset": [-126, -36, 117], "has_machine_quality": true, "preferred_quality_type": "normal", - "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "builder_premium_large_rear", diff --git a/resources/definitions/builder_premium_medium.def.json b/resources/definitions/builder_premium_medium.def.json index 500bfca75f..c28c7c5de6 100644 --- a/resources/definitions/builder_premium_medium.def.json +++ b/resources/definitions/builder_premium_medium.def.json @@ -13,7 +13,6 @@ "platform_offset": [-126, -36, 117], "has_machine_quality": true, "preferred_quality_type": "normal", - "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "builder_premium_medium_rear", diff --git a/resources/definitions/builder_premium_small.def.json b/resources/definitions/builder_premium_small.def.json index 1d6451430c..8e2fe44631 100644 --- a/resources/definitions/builder_premium_small.def.json +++ b/resources/definitions/builder_premium_small.def.json @@ -12,7 +12,6 @@ "platform_offset": [-126, -36, 117], "has_machine_quality": true, "preferred_quality_type": "normal", - "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "builder_premium_small_rear", diff --git a/resources/definitions/cartesio.def.json b/resources/definitions/cartesio.def.json index 49eecd2c24..9deb257ac3 100644 --- a/resources/definitions/cartesio.def.json +++ b/resources/definitions/cartesio.def.json @@ -17,7 +17,6 @@ "variants_name": "Nozzle size", "preferred_variant_name": "0.8 mm", "preferred_quality_type": "normal", - "preferred_material": "generic_pla_175", "machine_extruder_trains": { diff --git a/resources/definitions/delta_go.def.json b/resources/definitions/delta_go.def.json index 6e9fa4aa09..a6d75b2983 100644 --- a/resources/definitions/delta_go.def.json +++ b/resources/definitions/delta_go.def.json @@ -8,8 +8,7 @@ "manufacturer": "Deltaprintr", "file_formats": "text/x-gcode", "platform_offset": [0, 0, 0], - "platform": "", - "preferred_material": "generic_pla_175" + "platform": "" }, "overrides": { "machine_name": { "default_value": "Delta Go" }, diff --git a/resources/definitions/deltacomb.def.json b/resources/definitions/deltacomb.def.json index 26004e835e..7e6e956dbc 100644 --- a/resources/definitions/deltacomb.def.json +++ b/resources/definitions/deltacomb.def.json @@ -10,8 +10,7 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "platform": "deltacomb.stl", - "has_machine_quality": true, - "preferred_material": "generic_pla_175" + "has_machine_quality": true }, "overrides": { diff --git a/resources/definitions/folgertech_FT-5.def.json b/resources/definitions/folgertech_FT-5.def.json index 7c3489951f..71c6987a1a 100644 --- a/resources/definitions/folgertech_FT-5.def.json +++ b/resources/definitions/folgertech_FT-5.def.json @@ -7,8 +7,7 @@ "author": "Jaime van Kessel & Paul Bussiere", "manufacturer": "Folger Tech", "file_formats": "text/x-gcode", - "platform": "FT-5_build_plate.stl", - "preferred_material": "generic_pla_175" + "platform": "FT-5_build_plate.stl" }, "overrides": { "machine_heated_bed": { "default_value": true }, diff --git a/resources/definitions/gmax15plus.def.json b/resources/definitions/gmax15plus.def.json index 8bd765d156..3a207cd054 100644 --- a/resources/definitions/gmax15plus.def.json +++ b/resources/definitions/gmax15plus.def.json @@ -12,7 +12,6 @@ "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl", "has_variants": true, "variants_name": "Hotend", - "preferred_material": "generic_pla_175", "preferred_variant_name": "0.5mm E3D (Default)" }, diff --git a/resources/definitions/gmax15plus_dual.def.json b/resources/definitions/gmax15plus_dual.def.json index e93fc7c6a0..af26a2e30a 100644 --- a/resources/definitions/gmax15plus_dual.def.json +++ b/resources/definitions/gmax15plus_dual.def.json @@ -12,7 +12,6 @@ "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl", "has_variants": true, "variants_name": "Hotend", - "preferred_material": "generic_pla_175", "preferred_variant_name": "0.5mm E3D (Default)", "machine_extruder_trains": { "0": "gmax15plus_dual_extruder_0", diff --git a/resources/definitions/helloBEEprusa.def.json b/resources/definitions/helloBEEprusa.def.json index 26692f8486..2699a6c7d7 100644 --- a/resources/definitions/helloBEEprusa.def.json +++ b/resources/definitions/helloBEEprusa.def.json @@ -9,7 +9,6 @@ "platform": "BEEVERYCREATIVE-helloBEEprusa.stl", "platform_offset": [-226, -75, -196], "file_formats": "text/x-gcode", - "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "hBp_extruder_left", @@ -53,4 +52,4 @@ "retraction_speed": { "default_value": 15.0}, "retraction_amount": { "default_value": 1.5} } -} +} \ No newline at end of file diff --git a/resources/definitions/imade3d_jellybox.def.json b/resources/definitions/imade3d_jellybox.def.json index 42bf61f388..b234e4b2cd 100644 --- a/resources/definitions/imade3d_jellybox.def.json +++ b/resources/definitions/imade3d_jellybox.def.json @@ -9,7 +9,6 @@ "platform": "imade3d_jellybox_platform.stl", "platform_offset": [ 0, -0.3, 0], "file_formats": "text/x-gcode", - "preferred_material": "generic_pla_175", "preferred_variant_name": "0.4 mm", "preferred_quality_type": "fast", "has_materials": true, diff --git a/resources/definitions/julia.def.json b/resources/definitions/julia.def.json index 8a9402b332..7fdee30272 100644 --- a/resources/definitions/julia.def.json +++ b/resources/definitions/julia.def.json @@ -7,8 +7,7 @@ "author": "Ultimaker", "manufacturer": "Fracktal", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/definitions/makerbotreplicator.def.json b/resources/definitions/makerbotreplicator.def.json index 77aa5ab667..3d690990ce 100644 --- a/resources/definitions/makerbotreplicator.def.json +++ b/resources/definitions/makerbotreplicator.def.json @@ -7,8 +7,7 @@ "author": "Ultimaker", "manufacturer": "MakerBot", "file_formats": "application/x3g", - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/definitions/malyan_m200.def.json b/resources/definitions/malyan_m200.def.json index 855fe58cd2..a3f4f81ecf 100644 --- a/resources/definitions/malyan_m200.def.json +++ b/resources/definitions/malyan_m200.def.json @@ -11,7 +11,6 @@ "platform": "malyan_m200_platform.stl", "has_machine_quality": true, "has_materials": true, - "preferred_material": "generic_pla_175", "preferred_quality_type": "normal", "supports_usb_connection": true, "visible": true, diff --git a/resources/definitions/mankati_fullscale_xt_plus.def.json b/resources/definitions/mankati_fullscale_xt_plus.def.json index 39b3d018bf..15ba889efc 100644 --- a/resources/definitions/mankati_fullscale_xt_plus.def.json +++ b/resources/definitions/mankati_fullscale_xt_plus.def.json @@ -7,8 +7,7 @@ "author": "RBC", "manufacturer": "Mankati", "file_formats": "text/x-gcode", - "platform": "mankati_fullscale_xt_plus_platform.stl", - "preferred_material": "generic_pla_175" + "platform": "mankati_fullscale_xt_plus_platform.stl" }, "overrides": { "machine_name": { "default_value": "Mankati Fullscale XT Plus" }, diff --git a/resources/definitions/ord.def.json b/resources/definitions/ord.def.json index 471385cc7c..3238583ceb 100644 --- a/resources/definitions/ord.def.json +++ b/resources/definitions/ord.def.json @@ -7,7 +7,6 @@ "author": "Ultimaker", "manufacturer": "ORD Solutions", "file_formats": "text/x-gcode", - "preferred_material": "generic_pla_175", "machine_extruder_trains": { "0": "ord_extruder_0", diff --git a/resources/definitions/printrbot_play.def.json b/resources/definitions/printrbot_play.def.json index 3f98aff798..36ef93e60c 100644 --- a/resources/definitions/printrbot_play.def.json +++ b/resources/definitions/printrbot_play.def.json @@ -7,8 +7,7 @@ "author": "Chris Pearson", "manufacturer": "Printrbot", "file_formats": "text/x-gcode", - "platform": "printrbot_play.stl", - "preferred_material": "generic_pla_175" + "platform": "printrbot_play.stl" }, "overrides": { diff --git a/resources/definitions/printrbot_simple.def.json b/resources/definitions/printrbot_simple.def.json index 52472fd743..7c86617ce5 100644 --- a/resources/definitions/printrbot_simple.def.json +++ b/resources/definitions/printrbot_simple.def.json @@ -8,8 +8,7 @@ "manufacturer": "PrintrBot", "platform": "printrbot_simple_metal_platform.stl", "platform_offset": [0, -3.45, 0], - "file_formats": "text/x-gcode", - "preferred_material": "generic_pla_175" + "file_formats": "text/x-gcode" }, "overrides": { diff --git a/resources/definitions/printrbot_simple_extended.def.json b/resources/definitions/printrbot_simple_extended.def.json index 9463af5554..95395efb23 100644 --- a/resources/definitions/printrbot_simple_extended.def.json +++ b/resources/definitions/printrbot_simple_extended.def.json @@ -8,8 +8,7 @@ "manufacturer": "PrintrBot", "platform": "printrbot_simple_metal_upgrade.stl", "platform_offset": [0, -0.3, 0], - "file_formats": "text/x-gcode", - "preferred_material": "generic_pla_175" + "file_formats": "text/x-gcode" }, "overrides": { diff --git a/resources/definitions/prusa_i3_mk2.def.json b/resources/definitions/prusa_i3_mk2.def.json index b70e2ab1dc..e58eb4d903 100644 --- a/resources/definitions/prusa_i3_mk2.def.json +++ b/resources/definitions/prusa_i3_mk2.def.json @@ -9,8 +9,7 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "platform": "prusai3_platform.stl", - "has_materials": true, - "preferred_material": "generic_pla_175" + "has_materials": true }, "overrides": { diff --git a/resources/definitions/punchtec_connect_xl.def.json b/resources/definitions/punchtec_connect_xl.def.json index c1f5780270..02d3562b41 100644 --- a/resources/definitions/punchtec_connect_xl.def.json +++ b/resources/definitions/punchtec_connect_xl.def.json @@ -12,8 +12,7 @@ "0": "punchtec_connect_xl_extruder_0", "1": "punchtec_connect_xl_extruder_1" }, - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/definitions/rigid3d.def.json b/resources/definitions/rigid3d.def.json index 21673e0010..97b0ebd276 100644 --- a/resources/definitions/rigid3d.def.json +++ b/resources/definitions/rigid3d.def.json @@ -7,8 +7,7 @@ "author": "Ultimaker", "manufacturer": "Rigid3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/definitions/rigid3d_3rdgen.def.json b/resources/definitions/rigid3d_3rdgen.def.json index b5c2ae87ce..46c22bfa57 100644 --- a/resources/definitions/rigid3d_3rdgen.def.json +++ b/resources/definitions/rigid3d_3rdgen.def.json @@ -7,8 +7,7 @@ "author": "Ultimaker", "manufacturer": "Rigid3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/definitions/rigid3d_hobby.def.json b/resources/definitions/rigid3d_hobby.def.json index 4b18521319..872cc3e6f4 100644 --- a/resources/definitions/rigid3d_hobby.def.json +++ b/resources/definitions/rigid3d_hobby.def.json @@ -7,8 +7,7 @@ "author": "Ultimaker", "manufacturer": "Rigid3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/definitions/rigid3d_zero.def.json b/resources/definitions/rigid3d_zero.def.json index 44e5e7e96a..56fb8284c0 100644 --- a/resources/definitions/rigid3d_zero.def.json +++ b/resources/definitions/rigid3d_zero.def.json @@ -7,8 +7,7 @@ "author": "Ultimaker", "manufacturer": "Rigid3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/definitions/robo_3d_r1.def.json b/resources/definitions/robo_3d_r1.def.json index 1c87e4575f..b179779c59 100644 --- a/resources/definitions/robo_3d_r1.def.json +++ b/resources/definitions/robo_3d_r1.def.json @@ -7,8 +7,7 @@ "author": "Ultimaker", "manufacturer": "Robo 3D", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/definitions/tam.def.json b/resources/definitions/tam.def.json index 11833b7841..20bc96358d 100644 --- a/resources/definitions/tam.def.json +++ b/resources/definitions/tam.def.json @@ -10,7 +10,6 @@ "platform": "tam_series1.stl", "platform_offset": [-580.0, -6.23, 253.5], "has_materials": false, - "preferred_material": "generic_pla_175", "supported_actions":["UpgradeFirmware"] }, "overrides": { diff --git a/resources/definitions/zone3d_printer.def.json b/resources/definitions/zone3d_printer.def.json index b7f852054a..bac8968951 100644 --- a/resources/definitions/zone3d_printer.def.json +++ b/resources/definitions/zone3d_printer.def.json @@ -7,8 +7,7 @@ "author": "Ultimaker", "manufacturer": "Unknown", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0], - "preferred_material": "generic_pla_175" + "platform_offset": [ 0, 0, 0] }, "overrides": { diff --git a/resources/extruders/punchtec_connect_xl_extruder_0.def.json b/resources/extruders/punchtec_connect_xl_extruder_left.def.json similarity index 100% rename from resources/extruders/punchtec_connect_xl_extruder_0.def.json rename to resources/extruders/punchtec_connect_xl_extruder_left.def.json diff --git a/resources/extruders/punchtec_connect_xl_extruder_1.def.json b/resources/extruders/punchtec_connect_xl_extruder_right.def.json similarity index 100% rename from resources/extruders/punchtec_connect_xl_extruder_1.def.json rename to resources/extruders/punchtec_connect_xl_extruder_right.def.json From 1538486e852e9208a1a447c87a23f9a88e33ff52 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 21:35:50 +0100 Subject: [PATCH 058/371] WIP: Change low quality_type to fast "low" is "fast", and the majority is using "fast". --- resources/quality/{low.inst.cfg => fast.inst.cfg} | 2 +- resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg | 2 +- resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg | 2 +- resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg | 2 +- .../quality/ultimaker2/{um2_low.inst.cfg => um2_fast.inst.cfg} | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename resources/quality/{low.inst.cfg => fast.inst.cfg} (94%) rename resources/quality/ultimaker2/{um2_low.inst.cfg => um2_fast.inst.cfg} (93%) diff --git a/resources/quality/low.inst.cfg b/resources/quality/fast.inst.cfg similarity index 94% rename from resources/quality/low.inst.cfg rename to resources/quality/fast.inst.cfg index 25cb71e2bc..4b78cfcd75 100644 --- a/resources/quality/low.inst.cfg +++ b/resources/quality/fast.inst.cfg @@ -6,7 +6,7 @@ definition = fdmprinter [metadata] setting_version = 4 type = quality -quality_type = low +quality_type = fast weight = -1 global_quality = True diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg index 440575a066..947fd0774d 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_abs_normal.inst.cfg @@ -6,7 +6,7 @@ definition = kemiq_q2_beta [metadata] setting_version = 4 type = quality -quality_type = low +quality_type = fast weight = -1 material = generic_abs diff --git a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg index 12ca8ed571..cc7d877c70 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_beta_pla_normal.inst.cfg @@ -6,7 +6,7 @@ definition = kemiq_q2_beta [metadata] setting_version = 4 type = quality -quality_type = low +quality_type = fast weight = -1 material = generic_pla diff --git a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg index 51368f1b1b..a71c3c731b 100644 --- a/resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg +++ b/resources/quality/kemiq_q2/kemiq_q2_gama_pla_normal.inst.cfg @@ -6,7 +6,7 @@ definition = kemiq_q2_gama [metadata] setting_version = 4 type = quality -quality_type = low +quality_type = fast weight = -1 material = generic_pla diff --git a/resources/quality/ultimaker2/um2_low.inst.cfg b/resources/quality/ultimaker2/um2_fast.inst.cfg similarity index 93% rename from resources/quality/ultimaker2/um2_low.inst.cfg rename to resources/quality/ultimaker2/um2_fast.inst.cfg index acd6c849d1..1292613642 100644 --- a/resources/quality/ultimaker2/um2_low.inst.cfg +++ b/resources/quality/ultimaker2/um2_fast.inst.cfg @@ -6,7 +6,7 @@ definition = ultimaker2 [metadata] setting_version = 4 type = quality -quality_type = low +quality_type = fast weight = -1 [values] From 0349c1c5d73d03accbcfe6033879c287d3d7d444 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 21:38:17 +0100 Subject: [PATCH 059/371] WIP: Fix Cartesio quality_type "Extra coarse" -> "extra coarse" --- resources/quality/extra_coarse.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/extra_coarse.inst.cfg b/resources/quality/extra_coarse.inst.cfg index 6c11c9e61b..bc8257a97f 100644 --- a/resources/quality/extra_coarse.inst.cfg +++ b/resources/quality/extra_coarse.inst.cfg @@ -6,7 +6,7 @@ definition = fdmprinter [metadata] setting_version = 4 type = quality -quality_type = Extra coarse +quality_type = extra coarse weight = -4 global_quality = True From df1d2f137b5a2772a30587ee1e9b5ab621213b6a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 21:40:40 +0100 Subject: [PATCH 060/371] WIP: Add material-diameter mapping to fix preferred material lookup --- cura/Machines/MaterialManager.py | 75 +++++++++++++++---------------- cura/Settings/CuraStackBuilder.py | 2 + 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 880ef399bf..bd827fe5ba 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -1,3 +1,4 @@ +from collections import defaultdict from typing import Optional from PyQt5.Qt import QTimer, QObject, pyqtSignal @@ -37,6 +38,7 @@ class MaterialManager(QObject): self._fallback_materials_map = dict() # material_type -> generic material metadata self._material_group_map = dict() # root_material_id -> MaterialGroup self._diameter_machine_variant_material_map = dict() # diameter -> dict(machine_definition_id -> MaterialNode) + self._material_diameter_map = defaultdict() # root_material_id -> diameter -> root_material_id for that diameter # The machine definition ID for the non-machine-specific materials. # This is used as the last fallback option if the given machine-specific material(s) cannot be found. @@ -58,7 +60,7 @@ class MaterialManager(QObject): self._material_group_map = {} self._diameter_machine_variant_material_map = {} - # Table #1 + # Map #1 # root_material_id -> MaterialGroup for material_metadata in material_metadata_list: material_id = material_metadata["id"] @@ -78,7 +80,7 @@ class MaterialManager(QObject): new_node = MaterialNode(material_metadata) group.derived_material_node_list.append(new_node) - # Table #2 + # Map #2 # Lookup table for material type -> fallback material metadata grouped_by_type_dict = dict() for root_material_id, material_node in self._material_group_map.items(): @@ -91,7 +93,35 @@ class MaterialManager(QObject): grouped_by_type_dict[material_type] = material_node.root_material_node.metadata self._fallback_materials_map = grouped_by_type_dict - # Table #3 + # Map #3 + # There can be multiple material profiles for the same material with different diameters, such as "generic_pla" + # and "generic_pla_175". This is inconvenient when we do material-specific quality lookup because a quality can + # be for either "generic_pla" or "generic_pla_175", but not both. This map helps to get the correct material ID + # for quality search. + self._material_diameter_map = defaultdict(defaultdict) + + # Group the material IDs by the same name, material, brand, and color but with different diameters. + material_group_dict = dict() + keys_to_fetch = ("name", "material", "brand", "color") + for root_material_id, machine_node in self._material_group_map.items(): + root_material_metadata = machine_node.root_material_node.metadata + + key_data = [] + for key in keys_to_fetch: + key_data.append(root_material_metadata.get(key)) + key_data = tuple(key_data) + + if key_data not in material_group_dict: + material_group_dict[key_data] = dict() + approximate_diameter = root_material_metadata.get("approximate_diameter") + material_group_dict[key_data][approximate_diameter] = root_material_metadata["id"] + + for data_dict in material_group_dict.values(): + for rmid1 in data_dict.values(): + for ad2, rmid2 in data_dict.items(): + self._material_diameter_map[rmid1][ad2] = rmid2 + + # Map #4 # "machine" -> "variant_name" -> "root material ID" -> specific material InstanceContainer # Construct the "machine" -> "variant" -> "root material ID" -> specific material InstanceContainer for material_metadata in material_metadata_list: @@ -148,43 +178,8 @@ class MaterialManager(QObject): def getMaterialGroup(self, root_material_id: str) -> Optional[MaterialGroup]: return self._material_group_map.get(root_material_id) - def _test_metadata(self): - # print all metadata - import os - with open("c:/workspace/guid_map.txt", "w", encoding = "utf-8") as f: - for machine_id, node in self._guid_to_root_materials_map.items(): - f.write((" - %s -> %s" % (machine_id, node.metadata["id"])) + os.linesep) - - if False: - with open("c:/workspace/material_map.txt", "w", encoding = "utf-8") as f: - for machine_id in self._machine_variant_material_map: - f.write((" -> %s" % machine_id) + os.linesep) - - test_cases = [{"machine": "ultimaker3", "variant": "AA 0.4", "material": "generic_pla", "diameter": 2.85}, - {"machine": "ultimaker2_plus", "variant": None, "material": "generic_abs", "diameter": 2.85}, - {"machine": "fdmprinter", "variant": None, "material": "generic_cpe", "diameter": 2.85}, - {"machine": "fdmprinter", "variant": None, "material": "generic_abs_175", "diameter": 2.85}, - {"machine": "fdmprinter", "variant": None, "material": "generic_nylon", "diameter": 1.75}, - {"machine": "fdmprinter", "variant": None, "material": "generic_nylon_175", "diameter": 1.75}, - ] - for tc in test_cases: - result = self.getMaterialNode( - tc['machine'], - tc['variant'], - tc['diameter'], - tc['material']) - tc['result_id'] = result.getContainer().getId() if result else "None" - Logger.log("d", "!!!!!!!! MaterialManager test: %s", tc) - - # test available materials - with open("c:/workspace/test.txt", "w", encoding="utf-8") as f: - for tc in test_cases: - result = self.getAvailableMaterials(tc['machine'], - tc['variant'], - tc['diameter']) - f.write("--- [%s] [%s] [%s]:" % (tc['machine'], tc['variant'], tc['diameter']) + "\n") - for r, md in result.items(): - f.write(" - %s -> %s" % (r, md["id"]) + "\n") + def getRootMaterialIDForDiameter(self, root_material_id: str, approximate_diameter: str) -> str: + return self._material_diameter_map.get(root_material_id).get(approximate_diameter, root_material_id) # # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup. diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 19a5caacb8..c50b034471 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -55,7 +55,9 @@ class CuraStackBuilder: # Only look for the preferred material if this machine has materials if parseBool(machine_definition.getMetaDataEntry("has_materials", False)): material_diameter = machine_definition.getProperty("material_diameter", "value") + approximate_material_diameter = str(round(material_diameter)) root_material_id = machine_definition.getMetaDataEntry("preferred_material") + root_material_id = material_manager.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter) material_node = material_manager.getMaterialNode(definition_id, variant_name, material_diameter, root_material_id) # Sanity check. If you see this error, the related definition files should be fixed. if not material_node: From 4af176dbf39a58fd59b8a613ba64407df3313204 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 21:48:04 +0100 Subject: [PATCH 061/371] WIP: Rename function to getVariantNode() --- cura/Machines/VariantManager.py | 4 ++-- cura/Settings/CuraStackBuilder.py | 2 +- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py index 1f9f0288ac..555dfec4a3 100644 --- a/cura/Machines/VariantManager.py +++ b/cura/Machines/VariantManager.py @@ -72,8 +72,8 @@ class VariantManager: # Gets the variant InstanceContainer with the given information. # Almost the same as getVariantMetadata() except that this returns an InstanceContainer if present. # - def getVariant(self, machine_type_name: str, variant_name: str, - variant_type: Optional[str] = None) -> Optional["InstanceContainer"]: + def getVariantNode(self, machine_type_name: str, variant_name: str, + variant_type: Optional[str] = None) -> Optional["InstanceContainer"]: return self._machine_to_variant_dict_map[machine_type_name].get(variant_name) def getVariantNodes(self, machine: "GlobalStack"): diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index c50b034471..c396a4a2be 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -44,7 +44,7 @@ class CuraStackBuilder: if parseBool(machine_definition.getMetaDataEntry("has_variants", False)): variant_name = machine_definition.getMetaDataEntry("preferred_variant_name") if variant_name: - variant_node = variant_manager.getVariant(definition_id, variant_name) + variant_node = variant_manager.getVariantNode(definition_id, variant_name) # Sanity check. If you see this error, the related definition files should be fixed. if variant_node is None: raise RuntimeError("Cannot find variant with definition [%s] and variant name [%s]" % (definition_id, variant_name)) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 54aaedb8f9..36a7733568 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -592,10 +592,9 @@ class XmlMaterialProfile(InstanceContainer): from cura.Machines.VariantManager import VariantType variant_manager = CuraApplication.getInstance().getVariantManager() - variant_node = variant_manager.getVariant(machine_id, VariantType.BUILD_PLATE, buildplate_id) + variant_node = variant_manager.getVariantNode(machine_id, buildplate_id) if not variant_node: continue - variant_metadata = variant_node.metadata # TODO: check if build plate variant exists @@ -623,7 +622,7 @@ class XmlMaterialProfile(InstanceContainer): continue variant_manager = CuraApplication.getInstance().getVariantManager() - variant_node = variant_manager.getVariant(machine_id, hotend_name) + variant_node = variant_manager.getVariantNode(machine_id, hotend_name) if not variant_node: continue From 12164a0c888e251911ed81e9595d56215dd09d80 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 22:00:00 +0100 Subject: [PATCH 062/371] WIP: Remove set..ById()s in CuraContainerStack --- cura/Settings/CuraContainerRegistry.py | 12 +-- cura/Settings/CuraContainerStack.py | 113 ------------------------- tests/Settings/TestExtruderStack.py | 59 ------------- tests/Settings/TestGlobalStack.py | 72 ---------------- 4 files changed, 6 insertions(+), 250 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index be5a10e293..e18710e46d 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -579,21 +579,21 @@ class CuraContainerRegistry(ContainerRegistry): variant_id = machine.variant.getId() else: variant_id = "empty_variant" - extruder_stack.setVariantById(variant_id) + extruder_stack.variant = self.findInstanceContainers(id = variant_id)[0] material_id = "default" if machine.material.getId() not in ("empty", "empty_material"): material_id = machine.material.getId() else: material_id = "empty_material" - extruder_stack.setMaterialById(material_id) + extruder_stack.material = self.findInstanceContainers(id = material_id)[0] quality_id = "default" if machine.quality.getId() not in ("empty", "empty_quality"): quality_id = machine.quality.getId() else: quality_id = "empty_quality" - extruder_stack.setQualityById(quality_id) + extruder_stack.quality = self.findInstanceContainers(id = quality_id)[0] machine_quality_changes = machine.qualityChanges if new_global_quality_changes is not None: @@ -605,7 +605,7 @@ class CuraContainerRegistry(ContainerRegistry): extruder_quality_changes_container = extruder_quality_changes_container[0] quality_changes_id = extruder_quality_changes_container.getId() - extruder_stack.setQualityChangesById(quality_changes_id) + extruder_stack.qualityChanges = self.findInstanceContainers(id = quality_changes_id)[0] else: # Some extruder quality_changes containers can be created at runtime as files in the qualities # folder. Those files won't be loaded in the registry immediately. So we also need to search @@ -614,7 +614,7 @@ class CuraContainerRegistry(ContainerRegistry): if extruder_quality_changes_container: quality_changes_id = extruder_quality_changes_container.getId() extruder_quality_changes_container.addMetaDataEntry("extruder", extruder_stack.definition.getId()) - extruder_stack.setQualityChangesById(quality_changes_id) + extruder_stack.qualityChanges = self.findInstanceContainers(id = quality_changes_id)[0] else: # if we still cannot find a quality changes container for the extruder, create a new one container_name = machine_quality_changes.getName() @@ -649,7 +649,7 @@ class CuraContainerRegistry(ContainerRegistry): machine_quality_changes.removeInstance(qc_setting_key, postpone_emit=True) else: - extruder_stack.setQualityChangesById("empty_quality_changes") + extruder_stack.qualityChanges = self.findInstanceContainers(id = "empty_quality_changes")[0] self.addContainer(extruder_stack) diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index 93e4b55bba..c2fd4ba2f4 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -83,20 +83,6 @@ class CuraContainerStack(ContainerStack): def setQualityChanges(self, new_quality_changes: InstanceContainer, postpone_emit = False) -> None: self.replaceContainer(_ContainerIndexes.QualityChanges, new_quality_changes, postpone_emit = postpone_emit) - ## Set the quality changes container by an ID. - # - # This will search for the specified container and set it. If no container was found, an error will be raised. - # - # \param new_quality_changes_id The ID of the new quality changes container. - # - # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. - def setQualityChangesById(self, new_quality_changes_id: str) -> None: - quality_changes = ContainerRegistry.getInstance().findInstanceContainers(id = new_quality_changes_id) - if quality_changes: - self.setQualityChanges(quality_changes[0]) - else: - raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_quality_changes_id)) - ## Get the quality changes container. # # \return The quality changes container. Should always be a valid container, but can be equal to the empty InstanceContainer. @@ -110,31 +96,6 @@ class CuraContainerStack(ContainerStack): def setQuality(self, new_quality: InstanceContainer, postpone_emit = False) -> None: self.replaceContainer(_ContainerIndexes.Quality, new_quality, postpone_emit = postpone_emit) - ## Set the quality container by an ID. - # - # This will search for the specified container and set it. If no container was found, an error will be raised. - # There is a special value for ID, which is "default". The "default" value indicates the quality should be set - # to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultQuality - # for details. - # - # \param new_quality_id The ID of the new quality container. - # - # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. - def setQualityById(self, new_quality_id: str) -> None: - quality = self._empty_quality - if new_quality_id == "default": - new_quality = self.findDefaultQuality() - if new_quality: - quality = new_quality - else: - qualities = ContainerRegistry.getInstance().findInstanceContainers(id = new_quality_id) - if qualities: - quality = qualities[0] - else: - raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_quality_id)) - - self.setQuality(quality) - ## Get the quality container. # # \return The quality container. Should always be a valid container, but can be equal to the empty InstanceContainer. @@ -148,31 +109,6 @@ class CuraContainerStack(ContainerStack): def setMaterial(self, new_material: InstanceContainer, postpone_emit = False) -> None: self.replaceContainer(_ContainerIndexes.Material, new_material, postpone_emit = postpone_emit) - ## Set the material container by an ID. - # - # This will search for the specified container and set it. If no container was found, an error will be raised. - # There is a special value for ID, which is "default". The "default" value indicates the quality should be set - # to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultMaterial - # for details. - # - # \param new_material_id The ID of the new material container. - # - # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. - def setMaterialById(self, new_material_id: str) -> None: - material = self._empty_material - if new_material_id == "default": - new_material = self.findDefaultMaterial() - if new_material: - material = new_material - else: - materials = ContainerRegistry.getInstance().findInstanceContainers(id = new_material_id) - if materials: - material = materials[0] - else: - raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_material_id)) - - self.setMaterial(material) - ## Get the material container. # # \return The material container. Should always be a valid container, but can be equal to the empty InstanceContainer. @@ -186,31 +122,6 @@ class CuraContainerStack(ContainerStack): def setVariant(self, new_variant: InstanceContainer) -> None: self.replaceContainer(_ContainerIndexes.Variant, new_variant) - ## Set the variant container by an ID. - # - # This will search for the specified container and set it. If no container was found, an error will be raised. - # There is a special value for ID, which is "default". The "default" value indicates the quality should be set - # to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultVariant - # for details. - # - # \param new_variant_id The ID of the new variant container. - # - # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. - def setVariantById(self, new_variant_id: str) -> None: - variant = self._empty_variant - if new_variant_id == "default": - new_variant = self.findDefaultVariantBuildplate() if self.getMetaDataEntry("type") == "machine" else self.findDefaultVariant() - if new_variant: - variant = new_variant - else: - variants = ContainerRegistry.getInstance().findInstanceContainers(id = new_variant_id) - if variants: - variant = variants[0] - else: - raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_variant_id)) - - self.setVariant(variant) - ## Get the variant container. # # \return The variant container. Should always be a valid container, but can be equal to the empty InstanceContainer. @@ -224,18 +135,6 @@ class CuraContainerStack(ContainerStack): def setDefinitionChanges(self, new_definition_changes: InstanceContainer) -> None: self.replaceContainer(_ContainerIndexes.DefinitionChanges, new_definition_changes) - ## Set the definition changes container by an ID. - # - # \param new_definition_changes_id The ID of the new definition changes container. - # - # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. - def setDefinitionChangesById(self, new_definition_changes_id: str) -> None: - new_definition_changes = ContainerRegistry.getInstance().findInstanceContainers(id = new_definition_changes_id) - if new_definition_changes: - self.setDefinitionChanges(new_definition_changes[0]) - else: - raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_definition_changes_id)) - ## Get the definition changes container. # # \return The definition changes container. Should always be a valid container, but can be equal to the empty InstanceContainer. @@ -249,18 +148,6 @@ class CuraContainerStack(ContainerStack): def setDefinition(self, new_definition: DefinitionContainerInterface) -> None: self.replaceContainer(_ContainerIndexes.Definition, new_definition) - ## Set the definition container by an ID. - # - # \param new_definition_id The ID of the new definition container. - # - # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. - def setDefinitionById(self, new_definition_id: str) -> None: - new_definition = ContainerRegistry.getInstance().findDefinitionContainers(id = new_definition_id) - if new_definition: - self.setDefinition(new_definition[0]) - else: - raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_definition_id)) - ## Get the definition container. # # \return The definition container. Should always be a valid container, but can be equal to the empty InstanceContainer. diff --git a/tests/Settings/TestExtruderStack.py b/tests/Settings/TestExtruderStack.py index e1538cd3fc..ce829da4b3 100644 --- a/tests/Settings/TestExtruderStack.py +++ b/tests/Settings/TestExtruderStack.py @@ -325,30 +325,6 @@ def test_removeContainer(extruder_stack): with pytest.raises(InvalidOperationError): extruder_stack.removeContainer(unittest.mock.MagicMock()) -## Tests setting definitions by specifying an ID of a definition that exists. -def test_setDefinitionByIdExists(extruder_stack, container_registry): - container_registry.return_value = DefinitionContainer(container_id = "some_definition") - extruder_stack.setDefinitionById("some_definition") - assert extruder_stack.definition.getId() == "some_definition" - -## Tests setting definitions by specifying an ID of a definition that doesn't -# exist. -def test_setDefinitionByIdDoesntExist(extruder_stack): - with pytest.raises(InvalidContainerError): - extruder_stack.setDefinitionById("some_definition") #Container registry is empty now. - -## Tests setting materials by specifying an ID of a material that exists. -def test_setMaterialByIdExists(extruder_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "material") - extruder_stack.setMaterialById("InstanceContainer") - assert extruder_stack.material.getId() == "InstanceContainer" - -## Tests setting materials by specifying an ID of a material that doesn't -# exist. -def test_setMaterialByIdDoesntExist(extruder_stack): - with pytest.raises(InvalidContainerError): - extruder_stack.setMaterialById("some_material") #Container registry is empty now. - ## Tests setting properties directly on the extruder stack. @pytest.mark.parametrize("key, property, value", [ ("layer_height", "value", 0.1337), @@ -387,38 +363,3 @@ def test_setPropertyOtherContainers(target_container, stack_variable, extruder_s extruder_stack.setProperty(key, property, value, target_container = target_container) #The actual test. getattr(extruder_stack, stack_variable).setProperty.assert_called_once_with(key, property, value) #Make sure that the proper container gets a setProperty call. - -## Tests setting qualities by specifying an ID of a quality that exists. -def test_setQualityByIdExists(extruder_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "quality") - extruder_stack.setQualityById("InstanceContainer") - assert extruder_stack.quality.getId() == "InstanceContainer" - -## Tests setting qualities by specifying an ID of a quality that doesn't exist. -def test_setQualityByIdDoesntExist(extruder_stack): - with pytest.raises(InvalidContainerError): - extruder_stack.setQualityById("some_quality") #Container registry is empty now. - -## Tests setting quality changes by specifying an ID of a quality change that -# exists. -def test_setQualityChangesByIdExists(extruder_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "quality_changes") - extruder_stack.setQualityChangesById("InstanceContainer") - assert extruder_stack.qualityChanges.getId() == "InstanceContainer" - -## Tests setting quality changes by specifying an ID of a quality change that -# doesn't exist. -def test_setQualityChangesByIdDoesntExist(extruder_stack): - with pytest.raises(InvalidContainerError): - extruder_stack.setQualityChangesById("some_quality_changes") #Container registry is empty now. - -## Tests setting variants by specifying an ID of a variant that exists. -def test_setVariantByIdExists(extruder_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "variant") - extruder_stack.setVariantById("InstanceContainer") - assert extruder_stack.variant.getId() == "InstanceContainer" - -## Tests setting variants by specifying an ID of a variant that doesn't exist. -def test_setVariantByIdDoesntExist(extruder_stack): - with pytest.raises(InvalidContainerError): - extruder_stack.setVariantById("some_variant") #Container registry is empty now. diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index 9b0735c8f2..dc786b2df4 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -486,43 +486,6 @@ def test_removeContainer(global_stack): with pytest.raises(InvalidOperationError): global_stack.removeContainer(unittest.mock.MagicMock()) -## Tests setting definitions by specifying an ID of a definition that exists. -def test_setDefinitionByIdExists(global_stack, container_registry): - container_registry.return_value = DefinitionContainer(container_id = "some_definition") - global_stack.setDefinitionById("some_definition") - assert global_stack.definition.getId() == "some_definition" - -## Tests setting definitions by specifying an ID of a definition that doesn't -# exist. -def test_setDefinitionByIdDoesntExist(global_stack): - with pytest.raises(InvalidContainerError): - global_stack.setDefinitionById("some_definition") #Container registry is empty now. - -## Tests setting definition changes by specifying an ID of a container that -# exists. -def test_setDefinitionChangesByIdExists(global_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "definition_changes") - global_stack.setDefinitionChangesById("InstanceContainer") - assert global_stack.definitionChanges.getId() == "InstanceContainer" - -## Tests setting definition changes by specifying an ID of a container that -# doesn't exist. -def test_setDefinitionChangesByIdDoesntExist(global_stack): - with pytest.raises(InvalidContainerError): - global_stack.setDefinitionChangesById("some_definition_changes") #Container registry is empty now. - -## Tests setting materials by specifying an ID of a material that exists. -def test_setMaterialByIdExists(global_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "material") - global_stack.setMaterialById("InstanceContainer") - assert global_stack.material.getId() == "InstanceContainer" - -## Tests setting materials by specifying an ID of a material that doesn't -# exist. -def test_setMaterialByIdDoesntExist(global_stack): - with pytest.raises(InvalidContainerError): - global_stack.setMaterialById("some_material") #Container registry is empty now. - ## Tests whether changing the next stack is properly forbidden. def test_setNextStack(global_stack): with pytest.raises(InvalidOperationError): @@ -568,41 +531,6 @@ def test_setPropertyOtherContainers(target_container, stack_variable, global_sta getattr(global_stack, stack_variable).setProperty.assert_called_once_with(key, property, value) #Make sure that the proper container gets a setProperty call. -## Tests setting qualities by specifying an ID of a quality that exists. -def test_setQualityByIdExists(global_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "quality") - global_stack.setQualityById("InstanceContainer") - assert global_stack.quality.getId() == "InstanceContainer" - -## Tests setting qualities by specifying an ID of a quality that doesn't exist. -def test_setQualityByIdDoesntExist(global_stack): - with pytest.raises(InvalidContainerError): - global_stack.setQualityById("some_quality") #Container registry is empty now. - -## Tests setting quality changes by specifying an ID of a quality change that -# exists. -def test_setQualityChangesByIdExists(global_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "quality_changes") - global_stack.setQualityChangesById("InstanceContainer") - assert global_stack.qualityChanges.getId() == "InstanceContainer" - -## Tests setting quality changes by specifying an ID of a quality change that -# doesn't exist. -def test_setQualityChangesByIdDoesntExist(global_stack): - with pytest.raises(InvalidContainerError): - global_stack.setQualityChangesById("some_quality_changes") #Container registry is empty now. - -## Tests setting variants by specifying an ID of a variant that exists. -def test_setVariantByIdExists(global_stack, container_registry): - container_registry.return_value = getInstanceContainer(container_type = "variant") - global_stack.setVariantById("InstanceContainer") - assert global_stack.variant.getId() == "InstanceContainer" - -## Tests setting variants by specifying an ID of a variant that doesn't exist. -def test_setVariantByIdDoesntExist(global_stack): - with pytest.raises(InvalidContainerError): - global_stack.setVariantById("some_variant") #Container registry is empty now. - ## Smoke test for findDefaultVariant def test_smoke_findDefaultVariant(global_stack): global_stack.findDefaultVariant() From f4d69918fb8bb49ea03a9a0df84868cf4b4ca9e4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 22:05:11 +0100 Subject: [PATCH 063/371] WIP: Remove findDefault..()s --- cura/Settings/CuraContainerStack.py | 237 ---------------------------- cura/Settings/ExtruderStack.py | 5 - tests/Settings/TestGlobalStack.py | 12 -- 3 files changed, 254 deletions(-) diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index c2fd4ba2f4..00db4f57c7 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -282,243 +282,6 @@ class CuraContainerStack(ContainerStack): self._containers = new_containers - ## Find the variant that should be used as "default" variant. - # - # This will search for variants that match the current definition and pick the preferred one, - # if specified by the machine definition. - # - # The following criteria are used to find the default variant: - # - If the machine definition does not have a metadata entry "has_variants" set to True, return None - # - The definition of the variant should be the same as the machine definition for this stack. - # - The container should have a metadata entry "type" with value "variant". - # - If the machine definition has a metadata entry "preferred_variant", filter the variant IDs based on that. - # - # \return The container that should be used as default, or None if nothing was found or the machine does not use variants. - # - # \note This method assumes the stack has a valid machine definition. - def findDefaultVariant(self) -> Optional[ContainerInterface]: - definition = self._getMachineDefinition() - # has_variants can be overridden in other containers and stacks. - # In the case of UM2, it is overridden in the GlobalStack - if not self.getMetaDataEntry("has_variants"): - # If the machine does not use variants, we should never set a variant. - return None - - # First add any variant. Later, overwrite with preference if the preference is valid. - variant = None - definition_id = self._findInstanceContainerDefinitionId(definition) - variants = ContainerRegistry.getInstance().findInstanceContainers(definition = definition_id, type = "variant") - if variants: - variant = variants[0] - - preferred_variant_id = definition.getMetaDataEntry("preferred_variant") - if preferred_variant_id: - preferred_variants = ContainerRegistry.getInstance().findInstanceContainers(id = preferred_variant_id, definition = definition_id, type = "variant") - if preferred_variants: - variant = preferred_variants[0] - else: - Logger.log("w", "The preferred variant \"{variant}\" of stack {stack} does not exist or is not a variant.", variant = preferred_variant_id, stack = self.id) - # And leave it at the default variant. - - if variant: - return variant - - Logger.log("w", "Could not find a valid default variant for stack {stack}", stack = self.id) - return None - - ## Find the global variant that should be used as "default". This is used for the buildplates. - # - # This will search for variants that match the current definition and pick the preferred one, - # if specified by the machine definition. - # - # The following criteria are used to find the default global variant: - # - If the machine definition does not have a metadata entry "has_variant_buildplates" set to True, return None - # - The definition of the variant should be the same as the machine definition for this stack. - # - The container should have a metadata entry "type" with value "variant" and "hardware_type" with value "buildplate". - # - If the machine definition has a metadata entry "preferred_variant_buildplate", filter the variant IDs based on that. - # - # \return The container that should be used as default, or None if nothing was found or the machine does not use variants. - # - # \note This method assumes the stack has a valid machine definition. - def findDefaultVariantBuildplate(self) -> Optional[ContainerInterface]: - definition = self._getMachineDefinition() - # has_variant_buildplates can be overridden in other containers and stacks. - # In the case of UM2, it is overridden in the GlobalStack - if not self.getMetaDataEntry("has_variant_buildplates"): - # If the machine does not use variants, we should never set a variant. - return None - - # First add any variant. Later, overwrite with preference if the preference is valid. - variant = None - definition_id = self._findInstanceContainerDefinitionId(definition) - variants = ContainerRegistry.getInstance().findInstanceContainers(definition = definition_id, type = "variant", hardware_type = "buildplate") - if variants: - variant = variants[0] - - preferred_variant_buildplate_id = definition.getMetaDataEntry("preferred_variant_buildplate") - if preferred_variant_buildplate_id: - preferred_variant_buildplates = ContainerRegistry.getInstance().findInstanceContainers(id = preferred_variant_buildplate_id, definition = definition_id, type = "variant") - if preferred_variant_buildplates: - variant = preferred_variant_buildplates[0] - else: - Logger.log("w", "The preferred variant buildplate \"{variant}\" of stack {stack} does not exist or is not a variant.", - variant = preferred_variant_buildplate_id, stack = self.id) - # And leave it at the default variant. - - if variant: - return variant - - Logger.log("w", "Could not find a valid default buildplate variant for stack {stack}", stack = self.id) - return None - - ## Find the material that should be used as "default" material. - # - # This will search for materials that match the current definition and pick the preferred one, - # if specified by the machine definition. - # - # The following criteria are used to find the default material: - # - If the machine definition does not have a metadata entry "has_materials" set to True, return None - # - If the machine definition has a metadata entry "has_machine_materials", the definition of the material should - # be the same as the machine definition for this stack. Otherwise, the definition should be "fdmprinter". - # - The container should have a metadata entry "type" with value "material". - # - The material should have an approximate diameter that matches the machine - # - If the machine definition has a metadata entry "has_variants" and set to True, the "variant" metadata entry of - # the material should be the same as the ID of the variant in the stack. Only applies if "has_machine_materials" is also True. - # - If the stack currently has a material set, try to find a material that matches the current material by name. - # - Otherwise, if the machine definition has a metadata entry "preferred_material", try to find a material that matches the specified ID. - # - # \return The container that should be used as default, or None if nothing was found or the machine does not use materials. - def findDefaultMaterial(self) -> Optional[ContainerInterface]: - definition = self._getMachineDefinition() - if not definition.getMetaDataEntry("has_materials"): - # Machine does not use materials, never try to set it. - return None - - search_criteria = {"type": "material"} - if definition.getMetaDataEntry("has_machine_materials"): - search_criteria["definition"] = self._findInstanceContainerDefinitionId(definition) - - if definition.getMetaDataEntry("has_variants"): - search_criteria["variant"] = self.variant.id - else: - search_criteria["definition"] = "fdmprinter" - - if self.material != self._empty_material: - search_criteria["name"] = self.material.name - else: - preferred_material = definition.getMetaDataEntry("preferred_material") - if preferred_material: - search_criteria["id"] = preferred_material - - approximate_material_diameter = str(round(self.getProperty("material_diameter", "value"))) - search_criteria["approximate_diameter"] = approximate_material_diameter - - materials = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) - if not materials: - Logger.log("w", "The preferred material \"{material}\" could not be found for stack {stack}", material = preferred_material, stack = self.id) - # We failed to find any materials matching the specified criteria, drop some specific criteria and try to find - # a material that sort-of matches what we want. - search_criteria.pop("variant", None) - search_criteria.pop("id", None) - search_criteria.pop("name", None) - materials = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) - - if not materials: - Logger.log("w", "Could not find a valid material for stack {stack}", stack = self.id) - return None - - for material in materials: - # Prefer a read-only material - if ContainerRegistry.getInstance().isReadOnly(material.getId()): - return material - - return materials[0] - - - ## Find the quality that should be used as "default" quality. - # - # This will search for qualities that match the current definition and pick the preferred one, - # if specified by the machine definition. - # - # \return The container that should be used as default, or None if nothing was found. - def findDefaultQuality(self) -> Optional[ContainerInterface]: - definition = self._getMachineDefinition() - registry = ContainerRegistry.getInstance() - material_container = self.material if self.material.getId() not in (self._empty_material.getId(), self._empty_instance_container.getId()) else None - - search_criteria = {"type": "quality"} - - if definition.getMetaDataEntry("has_machine_quality"): - search_criteria["definition"] = self._findInstanceContainerDefinitionId(definition) - - if definition.getMetaDataEntry("has_materials") and material_container: - search_criteria["material"] = material_container.id - else: - search_criteria["definition"] = "fdmprinter" - - if self.quality != self._empty_quality: - search_criteria["name"] = self.quality.name - else: - preferred_quality = definition.getMetaDataEntry("preferred_quality") - if preferred_quality: - search_criteria["id"] = preferred_quality - - containers = registry.findInstanceContainers(**search_criteria) - if containers: - return containers[0] - - if "material" in search_criteria: - # First check if we can solve our material not found problem by checking if we can find quality containers - # that are assigned to the parents of this material profile. - try: - inherited_files = material_container.getInheritedFiles() - except AttributeError: # Material_container does not support inheritance. - inherited_files = [] - - if inherited_files: - for inherited_file in inherited_files: - # Extract the ID from the path we used to load the file. - search_criteria["material"] = os.path.basename(inherited_file).split(".")[0] - containers = registry.findInstanceContainers(**search_criteria) - if containers: - return containers[0] - - # We still weren't able to find a quality for this specific material. - # Try to find qualities for a generic version of the material. - material_search_criteria = {"type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic"} - if definition.getMetaDataEntry("has_machine_quality"): - if self.material != self._empty_instance_container: - material_search_criteria["definition"] = material_container.getMetaDataEntry("definition") - - if definition.getMetaDataEntry("has_variants"): - material_search_criteria["variant"] = material_container.getMetaDataEntry("variant") - else: - material_search_criteria["definition"] = self._findInstanceContainerDefinitionId(definition) - - if definition.getMetaDataEntry("has_variants") and self.variant != self._empty_instance_container: - material_search_criteria["variant"] = self.variant.id - else: - material_search_criteria["definition"] = "fdmprinter" - material_containers = registry.findInstanceContainersMetadata(**material_search_criteria) - # Try all materials to see if there is a quality profile available. - for material_container in material_containers: - search_criteria["material"] = material_container["id"] - - containers = registry.findInstanceContainers(**search_criteria) - if containers: - return containers[0] - - if "name" in search_criteria or "id" in search_criteria: - # If a quality by this name can not be found, try a wider set of search criteria - search_criteria.pop("name", None) - search_criteria.pop("id", None) - - containers = registry.findInstanceContainers(**search_criteria) - if containers: - return containers[0] - - return None - ## protected: # Helper to make sure we emit a PyQt signal on container changes. diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index 6f89d33393..a2ff092143 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -187,11 +187,6 @@ class ExtruderStack(CuraContainerStack): if has_global_dependencies: self.getNextStack().propertiesChanged.emit(key, properties) - def findDefaultVariant(self): - # The default variant is defined in the machine stack and/or definition, so use the machine stack to find - # the default variant. - return self.getNextStack().findDefaultVariant() - extruder_stack_mime = MimeType( name = "application/x-cura-extruderstack", diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index dc786b2df4..45ff13aaf3 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -530,15 +530,3 @@ def test_setPropertyOtherContainers(target_container, stack_variable, global_sta global_stack.setProperty(key, property, value, target_container = target_container) #The actual test. getattr(global_stack, stack_variable).setProperty.assert_called_once_with(key, property, value) #Make sure that the proper container gets a setProperty call. - -## Smoke test for findDefaultVariant -def test_smoke_findDefaultVariant(global_stack): - global_stack.findDefaultVariant() - -## Smoke test for findDefaultMaterial -def test_smoke_findDefaultMaterial(global_stack): - global_stack.findDefaultMaterial() - -## Smoke test for findDefaultQuality -def test_smoke_findDefaultQuality(global_stack): - global_stack.findDefaultQuality() From 13d745f07d2abcae26028b65ce1e431abca9af80 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 22:27:07 +0100 Subject: [PATCH 064/371] WIP: Move NozzleModel.py --- cura/CuraApplication.py | 4 +--- cura/{Settings => Machines/Models}/NozzleModel.py | 0 cura/Machines/Models/__init__.py | 0 cura/Settings/MachineManager.py | 3 --- 4 files changed, 1 insertion(+), 6 deletions(-) rename cura/{Settings => Machines/Models}/NozzleModel.py (100%) create mode 100644 cura/Machines/Models/__init__.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index dc0a65be1d..b1ec388f48 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -52,7 +52,7 @@ from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyT from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator -from cura.Settings.NozzleModel import NozzleModel +from cura.Machines.Models.NozzleModel import NozzleModel from cura.Settings.ProfilesModel import ProfilesModel, NewQualityProfilesModel, NewCustomQualityProfilesModel from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesModel @@ -61,8 +61,6 @@ from cura.Settings.UserProfilesModel import UserProfilesModel from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager from cura.Machines.VariantManager import VariantManager -from cura.Machines.QualityManager import QualityGroup - from . import PlatformPhysics from . import BuildVolume diff --git a/cura/Settings/NozzleModel.py b/cura/Machines/Models/NozzleModel.py similarity index 100% rename from cura/Settings/NozzleModel.py rename to cura/Machines/Models/NozzleModel.py diff --git a/cura/Machines/Models/__init__.py b/cura/Machines/Models/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 752353fe79..f5996bcf0f 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -122,9 +122,6 @@ class MachineManager(QObject): # Make sure _active_container_stack is properly initiated ExtruderManager.getInstance().setActiveExtruderIndex(0) - self._auto_materials_changed = {} - self._auto_hotends_changed = {} - self._material_incompatible_message = Message(catalog.i18nc("@info:status", "The selected material is incompatible with the selected machine or configuration."), title = catalog.i18nc("@info:title", "Incompatible Material")) From 9ffe89b49c351e65b8fee9313cfc40340882054b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 22:27:35 +0100 Subject: [PATCH 065/371] WIP: Remove setActiveVariant() --- cura/Settings/MachineManager.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f5996bcf0f..4871886542 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -749,27 +749,6 @@ class MachineManager(QObject): self.setActiveQuality(new_quality_id, always_discard_changes = always_discard_changes) - @pyqtSlot(str) - def setActiveVariant(self, variant_id: str, always_discard_changes = False): - with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): - containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_id) - if not containers or not self._active_container_stack: - return - Logger.log("d", "Attempting to change the active variant to %s", variant_id) - old_variant = self._active_container_stack.variant - old_material = self._active_container_stack.material - if old_variant: - self.blurSettings.emit() - self._new_variant_container = containers[0] # self._active_container_stack will be updated with a delay - Logger.log("d", "Active variant changed to {active_variant_id}".format(active_variant_id = containers[0].getId())) - preferred_material_name = None - if old_material: - preferred_material_name = old_material.getName() - preferred_material_id = self._updateMaterialContainer(self._global_container_stack.definition, self._global_container_stack, containers[0], preferred_material_name).id - self.setActiveMaterial(preferred_material_id, always_discard_changes = always_discard_changes) - else: - Logger.log("w", "While trying to set the active variant, no variant was found to replace.") - @pyqtSlot(str) def setActiveVariantBuildplate(self, variant_buildplate_id: str): with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): From 6dc53eb741d2c3aa97d1dd4a32d99b4a184b877b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 22:27:54 +0100 Subject: [PATCH 066/371] WIP: Fix NozzleMenu extruder binding --- resources/qml/Menus/BuildplateMenu.qml | 4 ++-- resources/qml/Menus/NozzleMenu.qml | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/resources/qml/Menus/BuildplateMenu.qml b/resources/qml/Menus/BuildplateMenu.qml index 4b85aa9e93..2679eec1d1 100644 --- a/resources/qml/Menus/BuildplateMenu.qml +++ b/resources/qml/Menus/BuildplateMenu.qml @@ -1,8 +1,8 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick 2.8 +import QtQuick.Controls 1.4 import UM 1.2 as UM import Cura 1.0 as Cura diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index 8cb01fcde6..d3ddbb8473 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -1,8 +1,8 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick 2.8 +import QtQuick.Controls 1.4 import UM 1.2 as UM import Cura 1.0 as Cura @@ -27,11 +27,10 @@ Menu { text: model.hotend_name checkable: true - checked: Cura.MachineManager.activeVariantName == model.hotend_name + checked: Cura.MachineManager.activeMachine.extruders[extruderIndex].variant.name == model.hotend_name exclusiveGroup: group onTriggered: { - var position = Cura.ExtruderManager.activeExtruderIndex; - Cura.MachineManager.setVariantGroup(position, model.container_node); + Cura.MachineManager.setVariantGroup(extruderIndex, model.container_node); } } From 8275e506ce6b3e995a2a03e485eb822f525119f8 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 15 Feb 2018 11:17:25 +0100 Subject: [PATCH 067/371] CURA-4606 fix material names for 1.75mm materials --- cura/Machines/MaterialManager.py | 31 ++++++++++++++++--- cura/Machines/QualityManager.py | 8 +++-- resources/definitions/gmax15plus.def.json | 1 + .../definitions/gmax15plus_dual.def.json | 1 + .../gmax15plus_pla_dual_normal.inst.cfg | 1 - .../gmax15plus_pla_dual_thick.inst.cfg | 1 - .../gmax15plus_pla_dual_thin.inst.cfg | 1 - .../gmax15plus_pla_dual_very_thick.inst.cfg | 1 - .../gmax15plus/gmax15plus_pla_normal.inst.cfg | 1 - .../gmax15plus/gmax15plus_pla_thick.inst.cfg | 1 - .../gmax15plus/gmax15plus_pla_thin.inst.cfg | 1 - .../gmax15plus_pla_very_thick.inst.cfg | 1 - 12 files changed, 33 insertions(+), 16 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index bd827fe5ba..f5a8995af1 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -38,11 +38,17 @@ class MaterialManager(QObject): self._fallback_materials_map = dict() # material_type -> generic material metadata self._material_group_map = dict() # root_material_id -> MaterialGroup self._diameter_machine_variant_material_map = dict() # diameter -> dict(machine_definition_id -> MaterialNode) + + # We're using these two maps to convert between the specific diameter material id and the generic material id + # because the generic material ids are used in qualities and definitions, while the specific diameter material is meant + # i.e. generic_pla -> generic_pla_175 self._material_diameter_map = defaultdict() # root_material_id -> diameter -> root_material_id for that diameter + self._diameter_material_map = dict() # material id including diameter (generic_pla_175) -> material root id (generic_pla) # The machine definition ID for the non-machine-specific materials. # This is used as the last fallback option if the given machine-specific material(s) cannot be found. self._default_machine_definition_id = "fdmprinter" + self._default_approximate_diameter_for_quality_search = "3" self._update_timer = QTimer(self) self._update_timer.setInterval(300) @@ -99,6 +105,7 @@ class MaterialManager(QObject): # be for either "generic_pla" or "generic_pla_175", but not both. This map helps to get the correct material ID # for quality search. self._material_diameter_map = defaultdict(defaultdict) + self._diameter_material_map = dict() # Group the material IDs by the same name, material, brand, and color but with different diameters. material_group_dict = dict() @@ -116,10 +123,17 @@ class MaterialManager(QObject): approximate_diameter = root_material_metadata.get("approximate_diameter") material_group_dict[key_data][approximate_diameter] = root_material_metadata["id"] + # Map [root_material_id][diameter] -> root_material_id for this diameter for data_dict in material_group_dict.values(): - for rmid1 in data_dict.values(): - for ad2, rmid2 in data_dict.items(): - self._material_diameter_map[rmid1][ad2] = rmid2 + for root_material_id1 in data_dict.values(): + for approximate_diameter2, root_material_id2 in data_dict.items(): + self._material_diameter_map[root_material_id1][approximate_diameter2] = root_material_id2 + + default_root_material_id = data_dict.get(self._default_approximate_diameter_for_quality_search) + if default_root_material_id is None: + default_root_material_id = list(data_dict.values())[0] # no default diameter present, just take "the" only one + for root_material_id in data_dict.values(): + self._diameter_material_map[root_material_id] = default_root_material_id # Map #4 # "machine" -> "variant_name" -> "root material ID" -> specific material InstanceContainer @@ -181,6 +195,9 @@ class MaterialManager(QObject): def getRootMaterialIDForDiameter(self, root_material_id: str, approximate_diameter: str) -> str: return self._material_diameter_map.get(root_material_id).get(approximate_diameter, root_material_id) + def getRootMaterialIDWithoutDiameter(self, root_material_id: str) -> str: + return self._diameter_material_map.get(root_material_id) + # # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup. # @@ -264,8 +281,12 @@ class MaterialManager(QObject): # This function returns the generic root material ID for the given material type, where material types are "PLA", # "ABS", etc. # - def getFallbackMaterialForType(self, material_type: str) -> dict: + def getFallbackMaterialId(self, material_type: str) -> str: # For safety if material_type not in self._fallback_materials_map: raise RuntimeError("Material type [%s] is not in the fallback materials table." % material_type) - return self._fallback_materials_map[material_type] + fallback_material = self._fallback_materials_map[material_type] + if fallback_material: + return self.getRootMaterialIDWithoutDiameter(fallback_material["id"]) + else: + return None diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index cb723f41d0..f0fd0168a6 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -286,13 +286,15 @@ class QualityManager(QObject): if extruder.material.getId() != "empty_material": has_material = True root_material_id = extruder.material.getMetaDataEntry("base_file") + # Convert possible generic_pla_175 -> generic_pla + root_material_id = self._material_manager.getRootMaterialIDWithoutDiameter(root_material_id) root_material_id_list.append(root_material_id) # Also try to get the fallback material material_type = extruder.material.getMetaDataEntry("material") - fallback_root_material_metadata = self._material_manager.getFallbackMaterialForType(material_type) - if fallback_root_material_metadata: - root_material_id_list.append(fallback_root_material_metadata["id"]) + fallback_root_material_id = self._material_manager.getFallbackMaterialId(material_type) + if fallback_root_material_id: + root_material_id_list.append(fallback_root_material_id) nodes_to_check = [] diff --git a/resources/definitions/gmax15plus.def.json b/resources/definitions/gmax15plus.def.json index 3a207cd054..897d492bb2 100644 --- a/resources/definitions/gmax15plus.def.json +++ b/resources/definitions/gmax15plus.def.json @@ -10,6 +10,7 @@ "category": "Other", "file_formats": "text/x-gcode", "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl", + "has_machine_quality": true, "has_variants": true, "variants_name": "Hotend", "preferred_variant_name": "0.5mm E3D (Default)" diff --git a/resources/definitions/gmax15plus_dual.def.json b/resources/definitions/gmax15plus_dual.def.json index af26a2e30a..8c57c8af63 100644 --- a/resources/definitions/gmax15plus_dual.def.json +++ b/resources/definitions/gmax15plus_dual.def.json @@ -11,6 +11,7 @@ "file_formats": "text/x-gcode", "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl", "has_variants": true, + "has_machine_quality": true, "variants_name": "Hotend", "preferred_variant_name": "0.5mm E3D (Default)", "machine_extruder_trains": { diff --git a/resources/quality/gmax15plus/gmax15plus_pla_dual_normal.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_dual_normal.inst.cfg index 67b5cb49b8..e08a6ff421 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_dual_normal.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_dual_normal.inst.cfg @@ -8,7 +8,6 @@ setting_version = 4 type = quality quality_type = normal weight = -1 -global_quality = True [values] layer_height = 0.2 diff --git a/resources/quality/gmax15plus/gmax15plus_pla_dual_thick.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_dual_thick.inst.cfg index 376e3241ff..86bfe2af6c 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_dual_thick.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_dual_thick.inst.cfg @@ -8,7 +8,6 @@ setting_version = 4 type = quality quality_type = course weight = -2 -global_quality = True [values] layer_height = 0.28 diff --git a/resources/quality/gmax15plus/gmax15plus_pla_dual_thin.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_dual_thin.inst.cfg index 1c0cabd84f..0d19c6c9f0 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_dual_thin.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_dual_thin.inst.cfg @@ -8,7 +8,6 @@ setting_version = 4 type = quality quality_type = high weight = 0 -global_quality = True [values] layer_height = 0.16 diff --git a/resources/quality/gmax15plus/gmax15plus_pla_dual_very_thick.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_dual_very_thick.inst.cfg index d292284531..2b58120762 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_dual_very_thick.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_dual_very_thick.inst.cfg @@ -8,7 +8,6 @@ setting_version = 4 type = quality quality_type = extra_course weight = -3 -global_quality = True [values] layer_height = 0.32 diff --git a/resources/quality/gmax15plus/gmax15plus_pla_normal.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_normal.inst.cfg index 3baad3a928..70920b6f6a 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_normal.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_normal.inst.cfg @@ -8,7 +8,6 @@ setting_version = 4 type = quality quality_type = normal weight = -1 -global_quality = True [values] layer_height = 0.2 diff --git a/resources/quality/gmax15plus/gmax15plus_pla_thick.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_thick.inst.cfg index 856ab7d3db..0f1e8a3802 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_thick.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_thick.inst.cfg @@ -8,7 +8,6 @@ setting_version = 4 type = quality quality_type = course weight = -2 -global_quality = True [values] layer_height = 0.28 diff --git a/resources/quality/gmax15plus/gmax15plus_pla_thin.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_thin.inst.cfg index 46f41e195f..f548affc2c 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_thin.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_thin.inst.cfg @@ -8,7 +8,6 @@ setting_version = 4 type = quality quality_type = high weight = 0 -global_quality = True [values] layer_height = 0.16 diff --git a/resources/quality/gmax15plus/gmax15plus_pla_very_thick.inst.cfg b/resources/quality/gmax15plus/gmax15plus_pla_very_thick.inst.cfg index 938f21a13d..5db77a70ea 100644 --- a/resources/quality/gmax15plus/gmax15plus_pla_very_thick.inst.cfg +++ b/resources/quality/gmax15plus/gmax15plus_pla_very_thick.inst.cfg @@ -8,7 +8,6 @@ setting_version = 4 type = quality quality_type = extra_course weight = -3 -global_quality = True [values] layer_height = 0.32 From aed0c124e942c450e1d1795613aaff50b6fc29a5 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 15 Feb 2018 11:47:14 +0100 Subject: [PATCH 068/371] CURA-4606 improved addExtruderStackForSingleExtrusionMachine by using containers directly --- cura/Settings/CuraContainerRegistry.py | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index e18710e46d..393e36db30 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -25,7 +25,6 @@ from UM.Resources import Resources from . import ExtruderStack from . import GlobalStack -from .ContainerManager import ContainerManager from .ExtruderManager import ExtruderManager from cura.CuraApplication import CuraApplication @@ -33,6 +32,7 @@ from cura.CuraApplication import CuraApplication from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") + class CuraContainerRegistry(ContainerRegistry): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -514,8 +514,6 @@ class CuraContainerRegistry(ContainerRegistry): extruder_stack.setDefinition(extruder_definition) extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position")) - from cura.CuraApplication import CuraApplication - # create a new definition_changes container for the extruder stack definition_changes_id = self.uniqueName(extruder_stack.getId() + "_settings") if create_new_ids else extruder_stack.getId() + "_settings" definition_changes_name = definition_changes_id @@ -574,26 +572,28 @@ class CuraContainerRegistry(ContainerRegistry): self.addContainer(user_container) extruder_stack.setUserChanges(user_container) - variant_id = "default" + application = CuraApplication.getInstance() + empty_variant = application.empty_variant_container + empty_material = application.empty_material_container + empty_quality = application.empty_quality_container + if machine.variant.getId() not in ("empty", "empty_variant"): - variant_id = machine.variant.getId() + variant = machine.variant else: - variant_id = "empty_variant" - extruder_stack.variant = self.findInstanceContainers(id = variant_id)[0] + variant = empty_variant + extruder_stack.variant = variant - material_id = "default" if machine.material.getId() not in ("empty", "empty_material"): - material_id = machine.material.getId() + material = machine.material else: - material_id = "empty_material" - extruder_stack.material = self.findInstanceContainers(id = material_id)[0] + material = empty_material + extruder_stack.material = material - quality_id = "default" if machine.quality.getId() not in ("empty", "empty_quality"): - quality_id = machine.quality.getId() + quality = machine.quality else: - quality_id = "empty_quality" - extruder_stack.quality = self.findInstanceContainers(id = quality_id)[0] + quality = empty_quality + extruder_stack.quality = quality machine_quality_changes = machine.qualityChanges if new_global_quality_changes is not None: From 1e0a078af8b06611c2ff9f0dbe0fb76de742d303 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 15 Feb 2018 15:05:37 +0100 Subject: [PATCH 069/371] WIP: Refactor Materials management page to use new Managers --- cura/CuraApplication.py | 3 +- cura/Settings/MaterialsModel.py | 112 +++- resources/qml/Preferences/MaterialView.qml | 18 +- resources/qml/Preferences/MaterialsPage.qml | 584 ++++++++---------- resources/qml/Preferences/OldMaterialView.qml | 467 ++++++++++++++ .../qml/Preferences/OldMaterialsPage.qml | 412 ++++++++++++ 6 files changed, 1264 insertions(+), 332 deletions(-) create mode 100644 resources/qml/Preferences/OldMaterialView.qml create mode 100644 resources/qml/Preferences/OldMaterialsPage.qml diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index b1ec388f48..eee0ecabe0 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -54,7 +54,7 @@ from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator from cura.Machines.Models.NozzleModel import NozzleModel from cura.Settings.ProfilesModel import ProfilesModel, NewQualityProfilesModel, NewCustomQualityProfilesModel -from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel +from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel, NewMaterialsModel from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.UserProfilesModel import UserProfilesModel @@ -944,6 +944,7 @@ class CuraApplication(QtApplication): qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") + qmlRegisterType(NewMaterialsModel, "Cura", 1, 0, "NewMaterialsModel") qmlRegisterSingletonType(NewQualityProfilesModel, "Cura", 1, 0, "NewQualityProfilesModel", self.getNewQualityProfileModel) qmlRegisterSingletonType(NewCustomQualityProfilesModel, "Cura", 1, 0, "NewCustomQualityProfilesModel", self.getNewCustomQualityProfilesModel) diff --git a/cura/Settings/MaterialsModel.py b/cura/Settings/MaterialsModel.py index ad3256ba32..f133684032 100644 --- a/cura/Settings/MaterialsModel.py +++ b/cura/Settings/MaterialsModel.py @@ -1,17 +1,16 @@ # Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Any, List -from PyQt5.QtCore import Qt - +from typing import Any, List, Optional +from PyQt5.QtCore import Qt, QObject from UM.Logger import Logger from UM.Qt.ListModel import ListModel -from UM.Settings.ContainerRegistry import ContainerRegistry #To listen for changes to the materials. -from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel #We're extending this class. +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel -def getAvailableMaterials(): +def getAvailableMaterials(extruder_position: Optional[int] = None): from cura.CuraApplication import CuraApplication machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() @@ -19,18 +18,21 @@ def getAvailableMaterials(): material_manager = CuraApplication.getInstance()._material_manager active_global_stack = machine_manager._global_container_stack - active_extruder_stack = extruder_manager.getActiveExtruderStack() + extruder_stack = extruder_manager.getActiveExtruderStack() + if extruder_position is not None: + if active_global_stack is not None: + extruder_stack = active_global_stack.extruders.get(str(extruder_position)) - if active_global_stack is None or active_extruder_stack is None: + if active_global_stack is None or extruder_stack is None: Logger.log("d", "Active global stack [%s] or extruder stack [%s] is None, setting material list to empty.", - active_global_stack, active_extruder_stack) + active_global_stack, extruder_stack) return machine_definition_id = active_global_stack.definition.getId() variant_name = None - if active_extruder_stack.variant.getId() != "empty_variant": - variant_name = active_extruder_stack.variant.getName() - diameter = active_extruder_stack.getProperty("material_diameter", "value") + if extruder_stack.variant.getId() != "empty_variant": + variant_name = extruder_stack.variant.getName() + diameter = extruder_stack.getProperty("material_diameter", "value") # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. result_dict = material_manager.getAvailableMaterials(machine_definition_id, variant_name, diameter) @@ -44,7 +46,7 @@ class BaseMaterialsModel(ListModel): BrandRole = Qt.UserRole + 4 MaterialRole = Qt.UserRole + 5 ColorRole = Qt.UserRole + 6 - ContainerNodeRole = Qt.UserRole + 6 + ContainerNodeRole = Qt.UserRole + 7 def __init__(self, parent = None): super().__init__(parent) @@ -184,6 +186,90 @@ class BrandMaterialsModel(ListModel): self.setItems(brand_item_list) +# +# This model is for the Material management page. +# +class NewMaterialsModel(ListModel): + RootMaterialIdRole = Qt.UserRole + 1 + DisplayNameRole = Qt.UserRole + 2 + BrandRole = Qt.UserRole + 3 + MaterialTypeRole = Qt.UserRole + 4 + ColorNameRole = Qt.UserRole + 5 + ColorCodeRole = Qt.UserRole + 6 + ContainerNodeRole = Qt.UserRole + 7 + ContainerIdRole = Qt.UserRole + 8 + + DescriptionRole = Qt.UserRole + 9 + AdhesionInfoRole = Qt.UserRole + 10 + ApproximateDiameterRole = Qt.UserRole + 11 + GuidRole = Qt.UserRole + 12 + DensityRole = Qt.UserRole + 13 + DiameterRole = Qt.UserRole + 14 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.RootMaterialIdRole, "root_material_id") + self.addRoleName(self.DisplayNameRole, "name") + self.addRoleName(self.BrandRole, "brand") + self.addRoleName(self.MaterialTypeRole, "material") + self.addRoleName(self.ColorNameRole, "color_name") + self.addRoleName(self.ColorCodeRole, "color_code") + self.addRoleName(self.ContainerNodeRole, "container_node") + self.addRoleName(self.ContainerIdRole, "container_id") + + self.addRoleName(self.DescriptionRole, "description") + self.addRoleName(self.AdhesionInfoRole, "adhesion_info") + self.addRoleName(self.ApproximateDiameterRole, "approximate_diameter") + self.addRoleName(self.GuidRole, "guid") + self.addRoleName(self.DensityRole, "density") + self.addRoleName(self.DiameterRole, "diameter") + + from cura.CuraApplication import CuraApplication + machine_manager = CuraApplication.getInstance().getMachineManager() + extruder_manager = CuraApplication.getInstance().getExtruderManager() + material_manager = CuraApplication.getInstance()._material_manager + + machine_manager.globalContainerChanged.connect(self._update) + extruder_manager.activeExtruderChanged.connect(self._update) + material_manager.materialsUpdated.connect(self._update) + + self._update() + + def _update(self): + result_dict = getAvailableMaterials() + if result_dict is None: + self.setItems([]) + return + + material_list = [] + for root_material_id, container_node in result_dict.items(): + keys_to_fetch = ("name", + "brand", + "material", + "color_name", + "color_code", + "description", + "adhesion_info", + "approximate_diameter",) + + item = {"root_material_id": container_node.metadata["base_file"], + "container_node": container_node, + "guid": container_node.metadata["GUID"], + "container_id": container_node.metadata["id"], + "density": container_node.metadata.get("properties", {}).get("density", ""), + "diameter": container_node.metadata.get("properties", {}).get("diameter", ""), + } + + for key in keys_to_fetch: + item[key] = container_node.metadata.get(key, "") + + material_list.append(item) + + material_list = sorted(material_list, key = lambda k: (k["brand"], k["name"])) + self.setItems(material_list) + + ## A model that shows a list of currently valid materials. Used by management page. class MaterialsModel(InstanceContainersModel): def __init__(self, parent = None): diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 5fdc8a24eb..50eb3d3e99 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -1,8 +1,8 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.1 -import QtQuick.Controls 1.3 +import QtQuick 2.8 +import QtQuick.Controls 1.4 import QtQuick.Dialogs 1.2 import UM 1.2 as UM @@ -357,8 +357,18 @@ TabView onEditingFinished: materialPropertyProvider.setPropertyValue("value", value) } - UM.ContainerPropertyProvider { id: materialPropertyProvider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key } - UM.ContainerPropertyProvider { id: machinePropertyProvider; containerId: Cura.MachineManager.activeDefinitionId; watchedProperties: [ "value" ]; key: model.key } + UM.ContainerPropertyProvider { + id: materialPropertyProvider + containerId: base.containerId + watchedProperties: [ "value" ] + key: model.key + } + UM.ContainerPropertyProvider { + id: machinePropertyProvider + containerId: Cura.MachineManager.activeDefinitionId + watchedProperties: [ "value" ] + key: model.key + } } } } diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 3a72f66cfc..cf8cd959bf 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -1,147 +1,61 @@ -//Copyright (c) 2017 Ultimaker B.V. -//Cura is released under the terms of the LGPLv3 or higher. +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. -import QtQuick 2.1 -import QtQuick.Controls 1.1 -import QtQuick.Dialogs 1.2 +import QtQuick 2.8 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 import UM 1.2 as UM import Cura 1.0 as Cura -UM.ManagementPage + +Item { - id: base; + id: base + property var resetEnabled: false // Keep PreferencesDialog happy - title: catalog.i18nc("@title:tab", "Materials"); + UM.I18nCatalog { id: catalog; name: "cura"; } - Component.onCompleted: - { - // Workaround to make sure all of the items are visible - objectList.positionViewAtBeginning(); + Cura.NewMaterialsModel { + id: materialsModel } - model: Cura.MaterialsModel - { - filter: - { - var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() } - if(Cura.MachineManager.filterMaterialsByMachine) - { - result.definition = Cura.MachineManager.activeQualityDefinitionId; - if(Cura.MachineManager.hasVariants) - { - result.variant_name = Cura.MachineManager.activeQualityVariantName; - } - } - else - { - result.definition = "fdmprinter"; - result.compatible = true; //NB: Only checks for compatibility in global version of material, but we don't have machine-specific materials anyway. - } - return result + Label { + id: titleLabel + + anchors { + top: parent.top + left: parent.left + right: parent.right + margins: 5 * screenScaleFactor } - sectionProperty: "brand" + font.pointSize: 18 + text: catalog.i18nc("@title:tab", "Materials") } - delegate: Rectangle + Row // Button Row { - width: objectList.width; - height: childrenRect.height; - color: isCurrentItem ? palette.highlight : index % 2 ? palette.base : palette.alternateBase - property bool isCurrentItem: ListView.isCurrentItem - - Row - { - spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - Rectangle - { - width: Math.round(parent.height * 0.8) - height: Math.round(parent.height * 0.8) - color: model.metadata.color_code - border.color: isCurrentItem ? palette.highlightedText : palette.text; - anchors.verticalCenter: parent.verticalCenter - } - Label - { - width: Math.round((parent.width * 0.3)) - text: model.metadata.material - elide: Text.ElideRight - font.italic: model.id == activeId - color: isCurrentItem ? palette.highlightedText : palette.text; - } - Label - { - text: (model.name != model.metadata.material) ? model.name : "" - elide: Text.ElideRight - font.italic: model.id == activeId - color: isCurrentItem ? palette.highlightedText : palette.text; - } + id: buttonRow + anchors { + left: parent.left + right: parent.right + top: titleLabel.bottom } - - MouseArea - { - anchors.fill: parent; - onClicked: - { - forceActiveFocus(); - if(!parent.ListView.isCurrentItem) - { - parent.ListView.view.currentIndex = index; - base.itemActivated(); - } - } - } - } - - activeId: Cura.MachineManager.activeMaterialId - activeIndex: getIndexById(activeId) - function getIndexById(material_id) - { - for(var i = 0; i < model.rowCount(); i++) { - if (model.getItem(i).id == material_id) { - return i; - } - } - return -1; - } - - scrollviewCaption: - { - var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; - if (Cura.MachineManager.hasVariants) - { - caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; - } - return caption; - } - detailsVisible: true - - section.property: "section" - section.delegate: Label - { - text: section - font.bold: true - anchors.left: parent.left; - anchors.leftMargin: UM.Theme.getSize("default_lining").width; - } - - buttons: [ + height: childrenRect.height // Activate button Button { text: catalog.i18nc("@action:button", "Activate") - iconName: "list-activate"; - enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials + iconName: "list-activate" + //enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials + enabled: true // TODO onClicked: { forceActiveFocus() Cura.MachineManager.setActiveMaterial(base.currentItem.id) currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. } - }, + } // Create button Button { @@ -149,31 +63,32 @@ UM.ManagementPage iconName: "list-add" onClicked: { forceActiveFocus() - Cura.ContainerManager.createMaterial() + // TODO } - }, + } // Duplicate button Button { text: catalog.i18nc("@action:button", "Duplicate"); - iconName: "list-add"; - enabled: base.currentItem != null + iconName: "list-add" + enabled: true //TODO onClicked: { forceActiveFocus() - Cura.ContainerManager.duplicateOriginalMaterial(base.currentItem.id) + // TODO } - }, + } // Remove button Button { text: catalog.i18nc("@action:button", "Remove") iconName: "list-remove" - enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) + //enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) + enabled: true // TODO onClicked: { forceActiveFocus() - confirmDialog.open() + // TODO } - }, + } // Import button Button { @@ -181,10 +96,10 @@ UM.ManagementPage iconName: "document-import" onClicked: { forceActiveFocus() - importDialog.open() + // TODO } visible: true - }, + } // Export button Button { @@ -192,221 +107,262 @@ UM.ManagementPage iconName: "document-export" onClicked: { forceActiveFocus() - exportDialog.open() + // TODO } enabled: currentItem != null } - - ] + } Item { - visible: base.currentItem != null - anchors.fill: parent + id: contentsItem + + anchors { + top: titleLabel.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + margins: 5 * screenScaleFactor + bottomMargin: 0 + } + + clip: true + } + + Item + { + anchors { + top: buttonRow.bottom + topMargin: UM.Theme.getSize("default_margin").height + left: parent.left + right: parent.right + bottom: parent.bottom + } + + SystemPalette { id: palette } + + Label + { + id: captionLabel + anchors { + top: parent.top + left: parent.left + } + text: "TODO" + width: materialScrollView.width + elide: Text.ElideRight + } + + ScrollView + { + id: materialScrollView + anchors { + top: captionLabel.visible ? captionLabel.bottom : parent.top + topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0 + bottom: parent.bottom + left: parent.left + } + + Rectangle { + parent: viewport + anchors.fill: parent + color: palette.light + } + + width: true ? (parent.width * 0.4) | 0 : parent.width + + ListView + { + id: materialListView + + model: materialsModel + + section.property: "brand" + section.criteria: ViewSection.FullString + section.delegate: Rectangle + { + width: materialScrollView.width + height: childrenRect.height + color: palette.light + + Label + { + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_lining").width + text: section + font.bold: true + color: palette.text + } + } + + delegate: Rectangle + { + width: materialScrollView.width + height: childrenRect.height + color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase + + Row + { + spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + Rectangle + { + width: Math.floor(parent.height * 0.8) + height: Math.floor(parent.height * 0.8) + color: model.color_code + border.color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; + anchors.verticalCenter: parent.verticalCenter + } + Label + { + width: Math.floor((parent.width * 0.3)) + text: model.material + elide: Text.ElideRight + font.italic: { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return model.root_material_id == root_material_id; // TODO + } + color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; + } + Label + { + text: (model.name != model.material) ? model.name : "" + elide: Text.ElideRight + font.italic: { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return model.root_material_id == root_material_id; // TODO + } + color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; + } + } + + MouseArea + { + anchors.fill: parent + onClicked: { + parent.ListView.view.currentIndex = model.index; + } + } + } + + onCurrentIndexChanged: + { + var model = materialsModel.getItem(currentIndex); + materialDetailsView.containerId = model.container_id; + + detailsPanel.updateMaterialPropertiesObject(); + } + } + } + Item { - id: profileName + id: detailsPanel - width: parent.width; - height: childrenRect.height - - Label { text: materialProperties.name; font: UM.Theme.getFont("large"); } - } - - MaterialView - { - anchors - { - left: parent.left - right: parent.right - top: profileName.bottom - topMargin: UM.Theme.getSize("default_margin").height + anchors { + left: materialScrollView.right + leftMargin: UM.Theme.getSize("default_margin").width + top: parent.top bottom: parent.bottom + right: parent.right } - editingEnabled: base.currentItem != null && !base.currentItem.readOnly - - properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.id : "" - - property alias pane: base - } - - QtObject - { - id: materialProperties - - property string guid: "00000000-0000-0000-0000-000000000000" - property string name: "Unknown"; - property string profile_type: "Unknown"; - property string supplier: "Unknown"; - property string material_type: "Unknown"; - - property string color_name: "Yellow"; - property color color_code: "yellow"; - - property real density: 0.0; - property real diameter: 0.0; - property string approximate_diameter: "0"; - - property real spool_cost: 0.0; - property real spool_weight: 0.0; - property real spool_length: 0.0; - property real cost_per_meter: 0.0; - - property string description: ""; - property string adhesion_info: ""; - } - - UM.ConfirmRemoveDialog - { - id: confirmDialog - object: base.currentItem != null ? base.currentItem.name : "" - onYes: + function updateMaterialPropertiesObject() { - // A material container can actually be multiple items, so we need to find (and remove) all of them. - var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file") - if(base_file == "") - { - base_file = base.currentItem.id - } - var guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID") - // remove base container first, it otherwise triggers loading the base file while removing other containers - var base_containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "id": base_file, "base_file": base_file, "type": "material"}) - for(var i in base_containers) - { - Cura.ContainerManager.removeContainer(base_containers[i]); - } - var containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "base_file": base_file, "type": "material"}) - for(var i in containers) - { - Cura.ContainerManager.removeContainer(containers[i]); - } - if(base.objectList.currentIndex > 0) - { - base.objectList.currentIndex--; - } - currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. - } - } + var currentItem = materialsModel.getItem(materialListView.currentIndex); - FileDialog - { - id: importDialog; - title: catalog.i18nc("@title:window", "Import Material"); - selectExisting: true; - nameFilters: Cura.ContainerManager.getContainerNameFilters("material") - folder: CuraApplication.getDefaultPath("dialog_material_path") - onAccepted: - { - var result = Cura.ContainerManager.importMaterialContainer(fileUrl) + materialProperties.name = currentItem.name; + materialProperties.guid = currentItem.guid; - messageDialog.title = catalog.i18nc("@title:window", "Import Material") - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags or !", "Could not import material %1: %2").arg(fileUrl).arg(result.message) - if(result.status == "success") + materialProperties.supplier = currentItem.brand ? currentItem.brand : "Unknown"; + materialProperties.material_type = currentItem.material ? currentItem.material : "Unknown"; + materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; + materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; + + materialProperties.description = currentItem.description ? currentItem.description : ""; + materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; + + if(currentItem.properties != undefined && currentItem.properties != null) { - messageDialog.icon = StandardIcon.Information - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl) - } - else if(result.status == "duplicate") - { - messageDialog.icon = StandardIcon.Warning + materialProperties.density = currentItem.density ? currentItem.density : 0.0; + materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; + materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; } else { - messageDialog.icon = StandardIcon.Critical + materialProperties.density = 0.0; + materialProperties.diameter = 0.0; + materialProperties.approximate_diameter = "0"; } - messageDialog.open() - CuraApplication.setDefaultPath("dialog_material_path", folder) } - } - FileDialog - { - id: exportDialog; - title: catalog.i18nc("@title:window", "Export Material"); - selectExisting: false; - nameFilters: Cura.ContainerManager.getContainerNameFilters("material") - folder: CuraApplication.getDefaultPath("dialog_material_path") - onAccepted: + Item { - if(base.currentItem.metadata.base_file) + anchors.fill: parent + + Item // Material title Label { - var result = Cura.ContainerManager.exportContainer(base.currentItem.metadata.base_file, selectedNameFilter, fileUrl) - } - else - { - var result = Cura.ContainerManager.exportContainer(base.currentItem.id, selectedNameFilter, fileUrl) + id: profileName + + width: parent.width + height: childrenRect.height + + Label { + text: materialProperties.name + font: UM.Theme.getFont("large") + } } - messageDialog.title = catalog.i18nc("@title:window", "Export Material") - if(result.status == "error") + MaterialView // Material detailed information view below the title Label { - messageDialog.icon = StandardIcon.Critical - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags and !", "Failed to export material to %1: %2").arg(fileUrl).arg(result.message) - messageDialog.open() + id: materialDetailsView + anchors + { + left: parent.left + right: parent.right + top: profileName.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: parent.bottom + } + + editingEnabled: base.currentItem != null && !base.currentItem.readOnly + + properties: materialProperties + containerId: base.currentItem != null ? base.currentItem.id : "" + + property alias pane: base } - else if(result.status == "success") + + QtObject { - messageDialog.icon = StandardIcon.Information - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully exported material to %1").arg(result.path) - messageDialog.open() + id: materialProperties + + property string guid: "00000000-0000-0000-0000-000000000000" + property string name: "Unknown"; + property string profile_type: "Unknown"; + property string supplier: "Unknown"; + property string material_type: "Unknown"; + + property string color_name: "Yellow"; + property color color_code: "yellow"; + + property real density: 0.0; + property real diameter: 0.0; + property string approximate_diameter: "0"; + + property real spool_cost: 0.0; + property real spool_weight: 0.0; + property real spool_length: 0.0; + property real cost_per_meter: 0.0; + + property string description: ""; + property string adhesion_info: ""; } - CuraApplication.setDefaultPath("dialog_material_path", folder) } } - - MessageDialog - { - id: messageDialog - } - - UM.SettingPropertyProvider - { - id: materialDiameterProvider - - containerStackId: Cura.ExtruderManager.activeExtruderStackId - key: "material_diameter" - watchedProperties: [ "value" ] - storeIndex: 5 - } - - UM.I18nCatalog { id: catalog; name: "cura"; } - SystemPalette { id: palette } - } - - onCurrentItemChanged: - { - if(currentItem == null) - { - return - } - materialProperties.name = currentItem.name; - materialProperties.guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID"); - - if(currentItem.metadata != undefined && currentItem.metadata != null) - { - materialProperties.supplier = currentItem.metadata.brand ? currentItem.metadata.brand : "Unknown"; - materialProperties.material_type = currentItem.metadata.material ? currentItem.metadata.material : "Unknown"; - materialProperties.color_name = currentItem.metadata.color_name ? currentItem.metadata.color_name : "Yellow"; - materialProperties.color_code = currentItem.metadata.color_code ? currentItem.metadata.color_code : "yellow"; - - materialProperties.description = currentItem.metadata.description ? currentItem.metadata.description : ""; - materialProperties.adhesion_info = currentItem.metadata.adhesion_info ? currentItem.metadata.adhesion_info : ""; - - if(currentItem.metadata.properties != undefined && currentItem.metadata.properties != null) - { - materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0; - materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0; - materialProperties.approximate_diameter = currentItem.metadata.approximate_diameter ? currentItem.metadata.approximate_diameter : "0"; - } - else - { - materialProperties.density = 0.0; - materialProperties.diameter = 0.0; - materialProperties.approximate_diameter = "0"; - } - - } } } diff --git a/resources/qml/Preferences/OldMaterialView.qml b/resources/qml/Preferences/OldMaterialView.qml new file mode 100644 index 0000000000..1b3a3b93a8 --- /dev/null +++ b/resources/qml/Preferences/OldMaterialView.qml @@ -0,0 +1,467 @@ +// Copyright (c) 2017 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.8 +import QtQuick.Controls 1.4 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +TabView +{ + id: base + + property QtObject properties; + + property bool editingEnabled: false; + property string currency: UM.Preferences.getValue("cura/currency") ? UM.Preferences.getValue("cura/currency") : "€" + property real firstColumnWidth: (width * 0.50) | 0 + property real secondColumnWidth: (width * 0.40) | 0 + property string containerId: "" + property var materialPreferenceValues: UM.Preferences.getValue("cura/material_settings") ? JSON.parse(UM.Preferences.getValue("cura/material_settings")) : {} + + property double spoolLength: calculateSpoolLength() + property real costPerMeter: calculateCostPerMeter() + + property bool reevaluateLinkedMaterials: false + property string linkedMaterialNames: + { + if (reevaluateLinkedMaterials) + { + reevaluateLinkedMaterials = false; + } + if(!base.containerId || !base.editingEnabled) + { + return "" + } + var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.containerId); + return linkedMaterials.join(", "); + } + + Tab + { + title: catalog.i18nc("@title", "Information") + + anchors.margins: UM.Theme.getSize("default_margin").width + + ScrollView + { + id: scrollView + anchors.fill: parent + horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff + flickableItem.flickableDirection: Flickable.VerticalFlick + frameVisible: true + + property real columnWidth: (viewport.width * 0.5 - UM.Theme.getSize("default_margin").width) | 0 + + Flow + { + id: containerGrid + + x: UM.Theme.getSize("default_margin").width + y: UM.Theme.getSize("default_lining").height + + width: base.width + property real rowHeight: textField.height + UM.Theme.getSize("default_lining").height + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Display Name") } + ReadOnlyTextField + { + id: displayNameTextField; + width: scrollView.columnWidth; + text: properties.name; + readOnly: !base.editingEnabled; + onEditingFinished: base.updateMaterialDisplayName(properties.name, text) + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") } + ReadOnlyTextField + { + id: textField; + width: scrollView.columnWidth; + text: properties.supplier; + readOnly: !base.editingEnabled; + onEditingFinished: base.updateMaterialSupplier(properties.supplier, text) + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") } + ReadOnlyTextField + { + width: scrollView.columnWidth; + text: properties.material_type; + readOnly: !base.editingEnabled; + onEditingFinished: base.updateMaterialType(properties.material_type, text) + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } + Row { + width: scrollView.columnWidth + height: parent.rowHeight + spacing: Math.floor(UM.Theme.getSize("default_margin").width / 2) + + // color indicator square + Rectangle { + id: colorSelector + color: properties.color_code + + width: Math.floor(colorLabel.height * 0.75) + height: Math.floor(colorLabel.height * 0.75) + border.width: UM.Theme.getSize("default_lining").height + + anchors.verticalCenter: parent.verticalCenter + + // open the color selection dialog on click + MouseArea { + anchors.fill: parent + onClicked: colorDialog.open() + enabled: base.editingEnabled + } + } + + // pretty color name text field + ReadOnlyTextField { + id: colorLabel; + text: properties.color_name; + readOnly: !base.editingEnabled + onEditingFinished: base.setMetaDataEntry("color_name", properties.color_name, text) + } + + // popup dialog to select a new color + // if successful it sets the properties.color_code value to the new color + ColorDialog { + id: colorDialog + color: properties.color_code + onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color) + } + } + + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } + + Label { width: parent.width; height: parent.rowHeight; font.bold: true; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Properties") } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") } + ReadOnlySpinBox + { + id: densitySpinBox + width: scrollView.columnWidth + value: properties.density + decimals: 2 + suffix: " g/cm³" + stepSize: 0.01 + readOnly: !base.editingEnabled + + onEditingFinished: base.setMetaDataEntry("properties/density", properties.density, value) + onValueChanged: updateCostPerMeter() + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") } + ReadOnlySpinBox + { + id: diameterSpinBox + width: scrollView.columnWidth + value: properties.diameter + decimals: 2 + suffix: " mm" + stepSize: 0.01 + readOnly: !base.editingEnabled + + onEditingFinished: + { + // This does not use a SettingPropertyProvider, because we need to make the change to all containers + // which derive from the same base_file + var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString(); + var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); + base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, Math.round(value).toString()); + base.setMetaDataEntry("properties/diameter", properties.diameter, value); + var new_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); + if (Cura.MachineManager.filterMaterialsByMachine && new_approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) + { + Cura.MaterialManager.showMaterialWarningMessage(base.containerId, old_diameter); + } + Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value); + } + onValueChanged: updateCostPerMeter() + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") } + SpinBox + { + id: spoolCostSpinBox + width: scrollView.columnWidth + value: base.getMaterialPreferenceValue(properties.guid, "spool_cost") + prefix: base.currency + " " + decimals: 2 + maximumValue: 100000000 + + onValueChanged: { + base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value)) + updateCostPerMeter() + } + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") } + SpinBox + { + id: spoolWeightSpinBox + width: scrollView.columnWidth + value: base.getMaterialPreferenceValue(properties.guid, "spool_weight") + suffix: " g" + stepSize: 100 + decimals: 0 + maximumValue: 10000 + + onValueChanged: { + base.setMaterialPreferenceValue(properties.guid, "spool_weight", parseFloat(value)) + updateCostPerMeter() + } + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") } + Label + { + width: scrollView.columnWidth + text: "~ %1 m".arg(Math.round(base.spoolLength)) + verticalAlignment: Qt.AlignVCenter + height: parent.rowHeight + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter") } + Label + { + width: scrollView.columnWidth + text: "~ %1 %2/m".arg(base.costPerMeter.toFixed(2)).arg(base.currency) + verticalAlignment: Qt.AlignVCenter + height: parent.rowHeight + } + + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height; visible: unlinkMaterialButton.visible } + Label + { + width: 2 * scrollView.columnWidth + verticalAlignment: Qt.AlignVCenter + text: catalog.i18nc("@label", "This material is linked to %1 and shares some of its properties.").arg(base.linkedMaterialNames) + wrapMode: Text.WordWrap + visible: unlinkMaterialButton.visible + } + Button + { + id: unlinkMaterialButton + text: catalog.i18nc("@label", "Unlink Material") + visible: base.linkedMaterialNames != "" + onClicked: + { + Cura.ContainerManager.unlinkMaterial(base.containerId) + base.reevaluateLinkedMaterials = true + } + } + + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } + + Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Description") } + + ReadOnlyTextArea + { + text: properties.description; + width: 2 * scrollView.columnWidth + wrapMode: Text.WordWrap + + readOnly: !base.editingEnabled; + + onEditingFinished: base.setMetaDataEntry("description", properties.description, text) + } + + Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Adhesion Information") } + + ReadOnlyTextArea + { + text: properties.adhesion_info; + width: 2 * scrollView.columnWidth + wrapMode: Text.WordWrap + + readOnly: !base.editingEnabled; + + onEditingFinished: base.setMetaDataEntry("adhesion_info", properties.adhesion_info, text) + } + + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } + } + + function updateCostPerMeter() + { + base.spoolLength = calculateSpoolLength(diameterSpinBox.value, densitySpinBox.value, spoolWeightSpinBox.value); + base.costPerMeter = calculateCostPerMeter(spoolCostSpinBox.value); + } + } + } + + Tab + { + title: catalog.i18nc("@label", "Print settings") + anchors + { + leftMargin: UM.Theme.getSize("default_margin").width + topMargin: UM.Theme.getSize("default_margin").height + bottomMargin: UM.Theme.getSize("default_margin").height + rightMargin: 0 + } + + ScrollView + { + anchors.fill: parent; + + ListView + { + model: UM.SettingDefinitionsModel + { + containerId: Cura.MachineManager.activeDefinitionId + visibilityHandler: Cura.MaterialSettingsVisibilityHandler { } + expanded: ["*"] + } + + delegate: UM.TooltipArea + { + width: childrenRect.width + height: childrenRect.height + text: model.description + Label + { + id: label + width: base.firstColumnWidth; + height: spinBox.height + UM.Theme.getSize("default_lining").height + text: model.label + elide: Text.ElideRight + verticalAlignment: Qt.AlignVCenter + } + ReadOnlySpinBox + { + id: spinBox + anchors.left: label.right + value: { + if (!isNaN(parseFloat(materialPropertyProvider.properties.value))) + { + return parseFloat(materialPropertyProvider.properties.value); + } + if (!isNaN(parseFloat(machinePropertyProvider.properties.value))) + { + return parseFloat(machinePropertyProvider.properties.value); + } + return 0; + } + width: base.secondColumnWidth + readOnly: !base.editingEnabled + suffix: " " + model.unit + maximumValue: 99999 + decimals: model.unit == "mm" ? 2 : 0 + + onEditingFinished: materialPropertyProvider.setPropertyValue("value", value) + } + + UM.ContainerPropertyProvider { id: materialPropertyProvider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key } + UM.ContainerPropertyProvider { id: machinePropertyProvider; containerId: Cura.MachineManager.activeDefinitionId; watchedProperties: [ "value" ]; key: model.key } + } + } + } + } + + function calculateSpoolLength(diameter, density, spoolWeight) + { + if(!diameter) + { + diameter = properties.diameter; + } + if(!density) + { + density = properties.density; + } + if(!spoolWeight) + { + spoolWeight = base.getMaterialPreferenceValue(properties.guid, "spool_weight"); + } + + if (diameter == 0 || density == 0 || spoolWeight == 0) + { + return 0; + } + var area = Math.PI * Math.pow(diameter / 2, 2); // in mm2 + var volume = (spoolWeight / density); // in cm3 + return volume / area; // in m + } + + function calculateCostPerMeter(spoolCost) + { + if(!spoolCost) + { + spoolCost = base.getMaterialPreferenceValue(properties.guid, "spool_cost"); + } + + if (spoolLength == 0) + { + return 0; + } + return spoolCost / spoolLength; + } + + // Tiny convenience function to check if a value really changed before trying to set it. + function setMetaDataEntry(entry_name, old_value, new_value) { + if (old_value != new_value) { + Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, entry_name, new_value) + // make sure the UI properties are updated as well since we don't re-fetch the entire model here + // When the entry_name is something like properties/diameter, we take the last part of the entry_name + var list = entry_name.split("/") + var key = list[list.length - 1] + properties[key] = new_value + } + } + + function setMaterialPreferenceValue(material_guid, entry_name, new_value) + { + if(!(material_guid in materialPreferenceValues)) + { + materialPreferenceValues[material_guid] = {}; + } + if(entry_name in materialPreferenceValues[material_guid] && materialPreferenceValues[material_guid][entry_name] == new_value) + { + // value has not changed + return + } + materialPreferenceValues[material_guid][entry_name] = new_value; + + // store preference + UM.Preferences.setValue("cura/material_settings", JSON.stringify(materialPreferenceValues)); + } + + function getMaterialPreferenceValue(material_guid, entry_name) + { + if(material_guid in materialPreferenceValues && entry_name in materialPreferenceValues[material_guid]) + { + return materialPreferenceValues[material_guid][entry_name]; + } + return 0; + } + + // update the display name of the material + function updateMaterialDisplayName (old_name, new_name) { + + // don't change when new name is the same + if (old_name == new_name) { + return + } + + // update the values + Cura.ContainerManager.setContainerName(base.containerId, new_name) + materialProperties.name = new_name + } + + // update the type of the material + function updateMaterialType (old_type, new_type) { + base.setMetaDataEntry("material", old_type, new_type) + materialProperties.material_type = new_type + } + + // update the supplier of the material + function updateMaterialSupplier (old_supplier, new_supplier) { + base.setMetaDataEntry("brand", old_supplier, new_supplier) + materialProperties.supplier = new_supplier + } +} diff --git a/resources/qml/Preferences/OldMaterialsPage.qml b/resources/qml/Preferences/OldMaterialsPage.qml new file mode 100644 index 0000000000..0a24b9c663 --- /dev/null +++ b/resources/qml/Preferences/OldMaterialsPage.qml @@ -0,0 +1,412 @@ +//Copyright (c) 2017 Ultimaker B.V. +//Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.8 +import QtQuick.Controls 1.4 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +UM.ManagementPage +{ + id: base + title: catalog.i18nc("@title:tab", "Materials") + + Component.onCompleted: + { + // Workaround to make sure all of the items are visible + objectList.positionViewAtBeginning(); + } + + model: Cura.MaterialsModel + { + filter: + { + var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() } + if(Cura.MachineManager.filterMaterialsByMachine) + { + result.definition = Cura.MachineManager.activeQualityDefinitionId; + if(Cura.MachineManager.hasVariants) + { + result.variant_name = Cura.MachineManager.activeQualityVariantName; + } + } + else + { + result.definition = "fdmprinter"; + result.compatible = true; //NB: Only checks for compatibility in global version of material, but we don't have machine-specific materials anyway. + } + return result + } + + sectionProperty: "brand" + } + + delegate: Rectangle + { + width: objectList.width; + height: childrenRect.height; + color: isCurrentItem ? palette.highlight : index % 2 ? palette.base : palette.alternateBase + property bool isCurrentItem: ListView.isCurrentItem + + Row + { + spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + Rectangle + { + width: Math.floor(parent.height * 0.8) + height: Math.floor(parent.height * 0.8) + color: model.metadata.color_code + border.color: isCurrentItem ? palette.highlightedText : palette.text; + anchors.verticalCenter: parent.verticalCenter + } + Label + { + width: Math.floor((parent.width * 0.3)) + text: model.metadata.material + elide: Text.ElideRight + font.italic: model.id == activeId + color: isCurrentItem ? palette.highlightedText : palette.text; + } + Label + { + text: (model.name != model.metadata.material) ? model.name : "" + elide: Text.ElideRight + font.italic: model.id == activeId + color: isCurrentItem ? palette.highlightedText : palette.text; + } + } + + MouseArea + { + anchors.fill: parent; + onClicked: + { + forceActiveFocus(); + if(!parent.ListView.isCurrentItem) + { + parent.ListView.view.currentIndex = index; + base.itemActivated(); + } + } + } + } + + activeId: Cura.MachineManager.activeMaterialId + activeIndex: getIndexById(activeId) + function getIndexById(material_id) + { + for(var i = 0; i < model.rowCount(); i++) { + if (model.getItem(i).id == material_id) { + return i; + } + } + return -1; + } + + scrollviewCaption: + { + var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; + if (Cura.MachineManager.hasVariants) + { + caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; + } + return caption; + } + detailsVisible: true + + section.property: "section" + section.delegate: Label + { + text: section + font.bold: true + anchors.left: parent.left; + anchors.leftMargin: UM.Theme.getSize("default_lining").width; + } + + buttons: [ + + // Activate button + Button { + text: catalog.i18nc("@action:button", "Activate") + iconName: "list-activate"; + enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials + onClicked: { + forceActiveFocus() + Cura.MachineManager.setActiveMaterial(base.currentItem.id) + currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. + } + }, + + // Create button + Button { + text: catalog.i18nc("@action:button", "Create") + iconName: "list-add" + onClicked: { + forceActiveFocus() + Cura.ContainerManager.createMaterial() + } + }, + + // Duplicate button + Button { + text: catalog.i18nc("@action:button", "Duplicate"); + iconName: "list-add"; + enabled: base.currentItem != null + onClicked: { + forceActiveFocus() + Cura.ContainerManager.duplicateOriginalMaterial(base.currentItem.id) + } + }, + + // Remove button + Button { + text: catalog.i18nc("@action:button", "Remove") + iconName: "list-remove" + enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) + onClicked: { + forceActiveFocus() + confirmDialog.open() + } + }, + + // Import button + Button { + text: catalog.i18nc("@action:button", "Import") + iconName: "document-import" + onClicked: { + forceActiveFocus() + importDialog.open() + } + visible: true + }, + + // Export button + Button { + text: catalog.i18nc("@action:button", "Export") + iconName: "document-export" + onClicked: { + forceActiveFocus() + exportDialog.open() + } + enabled: currentItem != null + } + + ] + + Item { + visible: base.currentItem != null + anchors.fill: parent + + Item // Material title Label + { + id: profileName + + width: parent.width; + height: childrenRect.height + + Label { text: materialProperties.name; font: UM.Theme.getFont("large"); } + } + + MaterialView // Material detailed information view below the title Label + { + anchors + { + left: parent.left + right: parent.right + top: profileName.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: parent.bottom + } + + editingEnabled: base.currentItem != null && !base.currentItem.readOnly + + properties: materialProperties + containerId: base.currentItem != null ? base.currentItem.id : "" + + property alias pane: base + } + + QtObject + { + id: materialProperties + + property string guid: "00000000-0000-0000-0000-000000000000" + property string name: "Unknown"; + property string profile_type: "Unknown"; + property string supplier: "Unknown"; + property string material_type: "Unknown"; + + property string color_name: "Yellow"; + property color color_code: "yellow"; + + property real density: 0.0; + property real diameter: 0.0; + property string approximate_diameter: "0"; + + property real spool_cost: 0.0; + property real spool_weight: 0.0; + property real spool_length: 0.0; + property real cost_per_meter: 0.0; + + property string description: ""; + property string adhesion_info: ""; + } + + UM.ConfirmRemoveDialog + { + id: confirmDialog + object: base.currentItem != null ? base.currentItem.name : "" + onYes: + { + // A material container can actually be multiple items, so we need to find (and remove) all of them. + var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file") + if(base_file == "") + { + base_file = base.currentItem.id + } + var guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID") + // remove base container first, it otherwise triggers loading the base file while removing other containers + var base_containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "id": base_file, "base_file": base_file, "type": "material"}) + for(var i in base_containers) + { + Cura.ContainerManager.removeContainer(base_containers[i]); + } + var containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "base_file": base_file, "type": "material"}) + for(var i in containers) + { + Cura.ContainerManager.removeContainer(containers[i]); + } + if(base.objectList.currentIndex > 0) + { + base.objectList.currentIndex--; + } + currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. + } + } + + FileDialog + { + id: importDialog; + title: catalog.i18nc("@title:window", "Import Material"); + selectExisting: true; + nameFilters: Cura.ContainerManager.getContainerNameFilters("material") + folder: CuraApplication.getDefaultPath("dialog_material_path") + onAccepted: + { + var result = Cura.ContainerManager.importMaterialContainer(fileUrl) + + messageDialog.title = catalog.i18nc("@title:window", "Import Material") + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags or !", "Could not import material %1: %2").arg(fileUrl).arg(result.message) + if(result.status == "success") + { + messageDialog.icon = StandardIcon.Information + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl) + } + else if(result.status == "duplicate") + { + messageDialog.icon = StandardIcon.Warning + } + else + { + messageDialog.icon = StandardIcon.Critical + } + messageDialog.open() + CuraApplication.setDefaultPath("dialog_material_path", folder) + } + } + + FileDialog + { + id: exportDialog; + title: catalog.i18nc("@title:window", "Export Material"); + selectExisting: false; + nameFilters: Cura.ContainerManager.getContainerNameFilters("material") + folder: CuraApplication.getDefaultPath("dialog_material_path") + onAccepted: + { + if(base.currentItem.metadata.base_file) + { + var result = Cura.ContainerManager.exportContainer(base.currentItem.metadata.base_file, selectedNameFilter, fileUrl) + } + else + { + var result = Cura.ContainerManager.exportContainer(base.currentItem.id, selectedNameFilter, fileUrl) + } + + messageDialog.title = catalog.i18nc("@title:window", "Export Material") + if(result.status == "error") + { + messageDialog.icon = StandardIcon.Critical + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags and !", "Failed to export material to %1: %2").arg(fileUrl).arg(result.message) + messageDialog.open() + } + else if(result.status == "success") + { + messageDialog.icon = StandardIcon.Information + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully exported material to %1").arg(result.path) + messageDialog.open() + } + CuraApplication.setDefaultPath("dialog_material_path", folder) + } + } + + MessageDialog + { + id: messageDialog + } + + UM.SettingPropertyProvider + { + id: materialDiameterProvider + + containerStackId: Cura.ExtruderManager.activeExtruderStackId + key: "material_diameter" + watchedProperties: [ "value" ] + storeIndex: 5 + } + + UM.I18nCatalog { id: catalog; name: "cura"; } + SystemPalette { id: palette } + } + + onCurrentItemChanged: + { + if(currentItem == null) + { + return + } + materialProperties.name = currentItem.name; + materialProperties.guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID"); + + if(currentItem.metadata != undefined && currentItem.metadata != null) + { + materialProperties.supplier = currentItem.metadata.brand ? currentItem.metadata.brand : "Unknown"; + materialProperties.material_type = currentItem.metadata.material ? currentItem.metadata.material : "Unknown"; + materialProperties.color_name = currentItem.metadata.color_name ? currentItem.metadata.color_name : "Yellow"; + materialProperties.color_code = currentItem.metadata.color_code ? currentItem.metadata.color_code : "yellow"; + + materialProperties.description = currentItem.metadata.description ? currentItem.metadata.description : ""; + materialProperties.adhesion_info = currentItem.metadata.adhesion_info ? currentItem.metadata.adhesion_info : ""; + + if(currentItem.metadata.properties != undefined && currentItem.metadata.properties != null) + { + materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0; + materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0; + materialProperties.approximate_diameter = currentItem.metadata.approximate_diameter ? currentItem.metadata.approximate_diameter : "0"; + } + else + { + materialProperties.density = 0.0; + materialProperties.diameter = 0.0; + materialProperties.approximate_diameter = "0"; + } + + } + } +} From 4468f4d620ad7babdb1c26f27fa00c8bed573bf6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 15 Feb 2018 15:06:15 +0100 Subject: [PATCH 070/371] WIP: Fix NozzleMenu warning on non-notifiable bindings --- cura/Settings/MachineManager.py | 7 ++++++- resources/qml/Menus/NozzleMenu.qml | 12 +++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 4871886542..89106f9bda 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1302,6 +1302,12 @@ class MachineManager(QObject): def createMachineManager(): return MachineManager() + @pyqtSlot(int, result = "QVariant") + def getExtruder(self, position: int): + if self._global_container_stack: + return self._global_container_stack.extruders.get(str(position)) + return None + @deprecated("Use ExtruderStack.material = ... and it won't be necessary", "2.7") def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None) -> InstanceContainer: if not definition.getMetaDataEntry("has_materials"): @@ -1357,7 +1363,6 @@ class MachineManager(QObject): # # New # - @pyqtProperty("QVariant", notify = rootMaterialChanged) def currentRootMaterialId(self): # initial filling the current_root_material_id diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index d3ddbb8473..96b21f285c 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -19,6 +19,16 @@ Menu id: nozzleModel } + property var extruderStack: Cura.MachineManager.getExtruder(extruderIndex) + + Connections + { + target: Cura.MachineManager + onGlobalContainerChanged: { + menu.extruderStack = Cura.MachineManager.getExtruder(extruderIndex) + } + } + Instantiator { model: nozzleModel @@ -27,7 +37,7 @@ Menu { text: model.hotend_name checkable: true - checked: Cura.MachineManager.activeMachine.extruders[extruderIndex].variant.name == model.hotend_name + checked: extruderStack.variant.name == model.hotend_name exclusiveGroup: group onTriggered: { Cura.MachineManager.setVariantGroup(extruderIndex, model.container_node); From a0b53dc1c9befb7e36c9dfc264caa4fdaf50929a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 15 Feb 2018 15:47:00 +0100 Subject: [PATCH 071/371] WIP: Materials management page, make Activate work --- .../MaterialSettingsVisibilityHandler.py | 1 + cura/Settings/MaterialsModel.py | 4 ++ resources/qml/Preferences/MaterialsPage.qml | 45 ++++++++++++++----- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/cura/Settings/MaterialSettingsVisibilityHandler.py b/cura/Settings/MaterialSettingsVisibilityHandler.py index 5b6050d2c0..bafe566293 100644 --- a/cura/Settings/MaterialSettingsVisibilityHandler.py +++ b/cura/Settings/MaterialSettingsVisibilityHandler.py @@ -3,6 +3,7 @@ import UM.Settings.Models.SettingVisibilityHandler + class MaterialSettingsVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler.SettingVisibilityHandler): def __init__(self, parent = None, *args, **kwargs): super().__init__(parent = parent, *args, **kwargs) diff --git a/cura/Settings/MaterialsModel.py b/cura/Settings/MaterialsModel.py index f133684032..51f9e09be6 100644 --- a/cura/Settings/MaterialsModel.py +++ b/cura/Settings/MaterialsModel.py @@ -205,6 +205,7 @@ class NewMaterialsModel(ListModel): GuidRole = Qt.UserRole + 12 DensityRole = Qt.UserRole + 13 DiameterRole = Qt.UserRole + 14 + IsReadOnlyRole = Qt.UserRole + 15 def __init__(self, parent = None): super().__init__(parent) @@ -224,8 +225,10 @@ class NewMaterialsModel(ListModel): self.addRoleName(self.GuidRole, "guid") self.addRoleName(self.DensityRole, "density") self.addRoleName(self.DiameterRole, "diameter") + self.addRoleName(self.IsReadOnlyRole, "is_read_only") from cura.CuraApplication import CuraApplication + self._container_registry = CuraApplication.getInstance().getContainerRegistry() machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() material_manager = CuraApplication.getInstance()._material_manager @@ -259,6 +262,7 @@ class NewMaterialsModel(ListModel): "container_id": container_node.metadata["id"], "density": container_node.metadata.get("properties", {}).get("density", ""), "diameter": container_node.metadata.get("properties", {}).get("diameter", ""), + "is_read_only": self._container_registry.isReadOnly(container_node.metadata["id"]), } for key in keys_to_fetch: diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index cf8cd959bf..ae90c13e8c 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -34,6 +34,19 @@ Item text: catalog.i18nc("@title:tab", "Materials") } + property var currentItem: + { + var current_index = materialListView.currentIndex; + return materialsModel.getItem(current_index); + } + + property var isCurrentItemActivated: + { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return base.currentItem.root_material_id == root_material_id; + } + Row // Button Row { id: buttonRow @@ -48,12 +61,15 @@ Item Button { text: catalog.i18nc("@action:button", "Activate") iconName: "list-activate" - //enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials - enabled: true // TODO + enabled: !isCurrentItemActivated onClicked: { forceActiveFocus() - Cura.MachineManager.setActiveMaterial(base.currentItem.id) - currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. + + var current_index = materialListView.currentIndex; + var item = materialsModel.getItem(current_index); + + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node); } } @@ -147,7 +163,16 @@ Item top: parent.top left: parent.left } - text: "TODO" + visible: text != "" + text: { + // OLD STUFF + var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; + if (Cura.MachineManager.hasVariants) + { + caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; + } + return caption; + } width: materialScrollView.width elide: Text.ElideRight } @@ -219,10 +244,10 @@ Item width: Math.floor((parent.width * 0.3)) text: model.material elide: Text.ElideRight - font.italic: { + font.italic: { // TODO: make it easier const extruder_position = Cura.ExtruderManager.activeExtruderIndex; const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return model.root_material_id == root_material_id; // TODO + return model.root_material_id == root_material_id } color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; } @@ -230,10 +255,10 @@ Item { text: (model.name != model.material) ? model.name : "" elide: Text.ElideRight - font.italic: { + font.italic: { // TODO: make it easier const extruder_position = Cura.ExtruderManager.activeExtruderIndex; const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return model.root_material_id == root_material_id; // TODO + return model.root_material_id == root_material_id; } color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; } @@ -329,7 +354,7 @@ Item bottom: parent.bottom } - editingEnabled: base.currentItem != null && !base.currentItem.readOnly + editingEnabled: base.currentItem != null && !base.currentItem.is_read_only properties: materialProperties containerId: base.currentItem != null ? base.currentItem.id : "" From 20e0f8a82af24f32ba34888980f4178d0381bf5a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 11:00:48 +0100 Subject: [PATCH 072/371] WIP: Fix material serialization --- .../XmlMaterialProfile/XmlMaterialProfile.py | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 36a7733568..f35f15b737 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -190,6 +190,8 @@ class XmlMaterialProfile(InstanceContainer): machine_container_map = {} machine_nozzle_map = {} + variant_manager = CuraApplication.getInstance()._variant_manager + all_containers = registry.findInstanceContainers(GUID = self.getMetaDataEntry("GUID"), base_file = self.getId()) for container in all_containers: definition_id = container.getDefinition().getId() @@ -202,9 +204,10 @@ class XmlMaterialProfile(InstanceContainer): if definition_id not in machine_nozzle_map: machine_nozzle_map[definition_id] = {} - variant = container.getMetaDataEntry("variant") - if variant: - machine_nozzle_map[definition_id][variant] = container + variant_name = container.getMetaDataEntry("variant_name") + if variant_name: + machine_nozzle_map[definition_id][variant_name] = variant_manager.getVariantNode(definition_id, + variant_name) continue machine_container_map[definition_id] = container @@ -236,16 +239,12 @@ class XmlMaterialProfile(InstanceContainer): self._addSettingElement(builder, instance) # Find all hotend sub-profiles corresponding to this material and machine and add them to this profile. - for hotend_id, hotend in machine_nozzle_map[definition_id].items(): - variant_containers = registry.findInstanceContainersMetadata(id = hotend.getMetaDataEntry("variant")) - if not variant_containers: - continue - + for hotend_name, variant_node in machine_nozzle_map[definition_id].items(): # The hotend identifier is not the containers name, but its "name". - builder.start("hotend", {"id": variant_containers[0]["name"]}) + builder.start("hotend", {"id": hotend_name}) # Compatible is a special case, as it's added as a meta data entry (instead of an instance). - compatible = hotend.getMetaDataEntry("compatible") + compatible = variant_node.metadata.get("compatible") if compatible is not None: builder.start("setting", {"key": "hardware compatible"}) if compatible: @@ -254,7 +253,7 @@ class XmlMaterialProfile(InstanceContainer): builder.data("no") builder.end("setting") - for instance in hotend.findInstances(): + for instance in variant_node.getContainer().findInstances(): if container.getInstance(instance.definition.key) and container.getProperty(instance.definition.key, "value") == instance.value: # If the settings match that of the machine profile, just skip since we inherit the machine profile. continue From 7fa218e9cdde2fd8ba0ad57e2e27a4fddbaa0715 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 11:16:49 +0100 Subject: [PATCH 073/371] WIP: Remove old Settings/MaterialManager --- cura/CuraApplication.py | 7 ---- cura/Settings/MaterialManager.py | 57 -------------------------------- 2 files changed, 64 deletions(-) delete mode 100644 cura/Settings/MaterialManager.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index eee0ecabe0..e9be1f96c9 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -73,7 +73,6 @@ from . import CameraImageProvider from . import MachineActionManager from cura.Settings.MachineManager import MachineManager -from cura.Settings.MaterialManager import MaterialManager from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.UserChangesModel import UserChangesModel from cura.Settings.ExtrudersModel import ExtrudersModel @@ -852,11 +851,6 @@ class CuraApplication(QtApplication): self._extruder_manager = ExtruderManager.createExtruderManager() return self._extruder_manager - def getMaterialManager(self, *args): - if self._material_manager is None: - self._material_manager = MaterialManager.createMaterialManager() - return self._material_manager - def getObjectsModel(self, *args): if self._object_manager is None: self._object_manager = ObjectsModel.createObjectsModel() @@ -930,7 +924,6 @@ class CuraApplication(QtApplication): qmlRegisterSingletonType(CuraSceneController, "Cura", 1, 2, "SceneController", self.getCuraSceneController) qmlRegisterSingletonType(ExtruderManager, "Cura", 1, 0, "ExtruderManager", self.getExtruderManager) qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, "MachineManager", self.getMachineManager) - qmlRegisterSingletonType(MaterialManager, "Cura", 1, 0, "MaterialManager", self.getMaterialManager) qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, "SettingInheritanceManager", self.getSettingInheritanceManager) qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 2, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager) qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) diff --git a/cura/Settings/MaterialManager.py b/cura/Settings/MaterialManager.py deleted file mode 100644 index 80d2723438..0000000000 --- a/cura/Settings/MaterialManager.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2017 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from PyQt5.QtCore import QObject, pyqtSlot #To expose data to QML. - -from cura.Settings.ContainerManager import ContainerManager -from UM.Logger import Logger -from UM.Message import Message #To create a warning message about material diameter. -from UM.i18n import i18nCatalog #Translated strings. - -catalog = i18nCatalog("cura") - -## Handles material-related data, processing requests to change them and -# providing data for the GUI. -# -# TODO: Move material-related managing over from the machine manager to here. -class MaterialManager(QObject): - ## Creates the global values for the material manager to use. - def __init__(self, parent = None): - super().__init__(parent) - - #Material diameter changed warning message. - self._material_diameter_warning_message = Message(catalog.i18nc("@info:status Has a cancel button next to it.", - "The selected material diameter causes the material to become incompatible with the current printer."), title = catalog.i18nc("@info:title", "Incompatible Material")) - self._material_diameter_warning_message.addAction("Undo", catalog.i18nc("@action:button", "Undo"), None, catalog.i18nc("@action", "Undo changing the material diameter.")) - self._material_diameter_warning_message.actionTriggered.connect(self._materialWarningMessageAction) - - ## Creates an instance of the MaterialManager. - # - # This should only be called by PyQt to create the singleton instance of - # this class. - @staticmethod - def createMaterialManager(engine = None, script_engine = None): - return MaterialManager() - - @pyqtSlot(str, str) - def showMaterialWarningMessage(self, material_id, previous_diameter): - self._material_diameter_warning_message.previous_diameter = previous_diameter #Make sure that the undo button can properly undo the action. - self._material_diameter_warning_message.material_id = material_id - self._material_diameter_warning_message.show() - - ## Called when clicking "undo" on the warning dialogue for disappeared - # materials. - # - # This executes the undo action, restoring the material diameter. - # - # \param button The identifier of the button that was pressed. - def _materialWarningMessageAction(self, message, button): - if button == "Undo": - container_manager = ContainerManager.getInstance() - container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "properties/diameter", self._material_diameter_warning_message.previous_diameter) - approximate_previous_diameter = str(round(float(self._material_diameter_warning_message.previous_diameter))) - container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "approximate_diameter", approximate_previous_diameter) - container_manager.setContainerProperty(self._material_diameter_warning_message.material_id, "material_diameter", "value", self._material_diameter_warning_message.previous_diameter); - message.hide() - else: - Logger.log("w", "Unknown button action for material diameter warning message: {action}".format(action = button)) \ No newline at end of file From f024f45cfe02da487ac41231692793fb65b5cf18 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 11:18:19 +0100 Subject: [PATCH 074/371] WIP: Rework Material management page --- cura/Machines/MaterialManager.py | 41 +++++--- cura/Settings/ContainerManager.py | 98 ++++++------------- .../XmlMaterialProfile/XmlMaterialProfile.py | 24 +++-- resources/qml/Preferences/MaterialView.qml | 34 ++++--- resources/qml/Preferences/MaterialsPage.qml | 21 ++-- 5 files changed, 104 insertions(+), 114 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index f5a8995af1..25130fe255 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -1,4 +1,4 @@ -from collections import defaultdict +from collections import defaultdict, OrderedDict from typing import Optional from PyQt5.Qt import QTimer, QObject, pyqtSignal @@ -17,6 +17,9 @@ class MaterialGroup: self.root_material_node = None self.derived_material_node_list = [] + def __str__(self) -> str: + return "%s[%s]" % (self.__class__.__name__, self.name) + class MaterialNode(ContainerNode): __slots__ = ("material_map", "children_map") @@ -45,6 +48,9 @@ class MaterialManager(QObject): self._material_diameter_map = defaultdict() # root_material_id -> diameter -> root_material_id for that diameter self._diameter_material_map = dict() # material id including diameter (generic_pla_175) -> material root id (generic_pla) + # This is used in Legacy UM3 send material function and the material management page. + self._guid_material_groups_map = defaultdict(list) # GUID -> a list of material_groups + # The machine definition ID for the non-machine-specific materials. # This is used as the last fallback option if the given machine-specific material(s) cannot be found. self._default_machine_definition_id = "fdmprinter" @@ -63,7 +69,7 @@ class MaterialManager(QObject): # Find all materials and put them in a matrix for quick search. material_metadata_list = self._container_registry.findContainersMetadata(type = "material") - self._material_group_map = {} + self._material_group_map = OrderedDict() self._diameter_machine_variant_material_map = {} # Map #1 @@ -85,6 +91,14 @@ class MaterialManager(QObject): else: new_node = MaterialNode(material_metadata) group.derived_material_node_list.append(new_node) + self._material_group_map = OrderedDict(sorted(self._material_group_map.items(), key = lambda x: x[0])) + + # Map #1.5 + # GUID -> material group list + self._guid_material_groups_map = defaultdict(list) + for root_material_id, material_group in self._material_group_map.items(): + guid = material_group.root_material_node.metadata["GUID"] + self._guid_material_groups_map[guid].append(material_group) # Map #2 # Lookup table for material type -> fallback material metadata @@ -198,6 +212,9 @@ class MaterialManager(QObject): def getRootMaterialIDWithoutDiameter(self, root_material_id: str) -> str: return self._diameter_material_map.get(root_material_id) + def getMaterialGroupListByGUID(self, guid: str) -> Optional[list]: + return self._guid_material_groups_map.get(guid) + # # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup. # @@ -206,29 +223,27 @@ class MaterialManager(QObject): rounded_diameter = str(round(diameter)) if rounded_diameter not in self._diameter_machine_variant_material_map: Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s])", diameter, rounded_diameter) - return {} + return dict() # If there are variant materials, get the variant material machine_variant_material_map = self._diameter_machine_variant_material_map[rounded_diameter] machine_node = machine_variant_material_map.get(machine_definition_id) + default_machine_node = machine_variant_material_map.get(self._default_machine_definition_id) variant_node = None - if machine_node is None: - machine_node = machine_variant_material_map.get(self._default_machine_definition_id) if variant_name is not None and machine_node is not None: variant_node = machine_node.getChildNode(variant_name) + nodes_to_check = [variant_node, machine_node, default_machine_node] + # Fallback mechanism of finding materials: # 1. variant-specific material # 2. machine-specific material # 3. generic material (for fdmprinter) - material_id_metadata_dict = {} - if variant_node is not None: - material_id_metadata_dict = {mid: node for mid, node in variant_node.material_map.items()} - - # Fallback: machine-specific materials, including "fdmprinter" - if not material_id_metadata_dict: - if machine_node is not None: - material_id_metadata_dict = {mid: node for mid, node in machine_node.material_map.items()} + material_id_metadata_dict = dict() + for node in nodes_to_check: + if node is not None: + material_id_metadata_dict = {mid: node for mid, node in variant_node.material_map.items()} + break return material_id_metadata_dict diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 4c92eed845..7d4c702cf4 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -764,16 +764,16 @@ class ContainerManager(QObject): ## Create a duplicate of a material, which has the same GUID and base_file metadata # # \return \type{str} the id of the newly created container. - @pyqtSlot(str, result = str) - def duplicateMaterial(self, material_id: str) -> str: - assert material_id + @pyqtSlot("QVariant") + def duplicateMaterial(self, material_node): + root_material_id = material_node.metadata["base_file"] from cura.CuraApplication import CuraApplication material_manager = CuraApplication.getInstance()._material_manager - material_group = material_manager.getMaterialGroup(material_id) + material_group = material_manager.getMaterialGroup(root_material_id) if not material_group: - Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id) + Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", root_material_id) return "" base_container = material_group.root_material_node.getContainer() @@ -803,7 +803,7 @@ class ContainerManager(QObject): if container_to_copy.getMetaDataEntry("variant_name"): variant_name = container_to_copy.getMetaDataEntry("variant_name") new_id += "_" + variant_name.replace(" ", "_") - if current_id == material_id: + if current_id == root_material_id: clone_of_original = new_id new_container = copy.deepcopy(container_to_copy) @@ -814,17 +814,6 @@ class ContainerManager(QObject): for container_to_add in new_containers: container_to_add.setDirty(True) ContainerRegistry.getInstance().addContainer(container_to_add) - return self._getMaterialContainerIdForActiveMachine(clone_of_original) - - ## Create a duplicate of a material or it's original entry - # - # \return \type{str} the id of the newly created container. - @pyqtSlot(str, result = str) - def duplicateOriginalMaterial(self, material_id): - - # check if the given material has a base file (i.e. was shipped by default) - base_file = self.getContainerMetaDataEntry(material_id, "base_file") - return self.duplicateMaterial(base_file) ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # @@ -869,72 +858,43 @@ class ContainerManager(QObject): duplicated_container.setName(catalog.i18nc("@label", "Custom Material")) self._container_registry.addContainer(duplicated_container) - return self._getMaterialContainerIdForActiveMachine(new_id) - - ## Find the id of a material container based on the new material - # Utilty function that is shared between duplicateMaterial and createMaterial - # - # \param base_file \type{str} the id of the created container. - def _getMaterialContainerIdForActiveMachine(self, base_file): - global_stack = Application.getInstance().getGlobalContainerStack() - if not global_stack: - return base_file - - has_machine_materials = parseBool(global_stack.getMetaDataEntry("has_machine_materials", default = False)) - has_variant_materials = parseBool(global_stack.getMetaDataEntry("has_variant_materials", default = False)) - has_variants = parseBool(global_stack.getMetaDataEntry("has_variants", default = False)) - if has_machine_materials or has_variant_materials: - if has_variants: - materials = self._container_registry.findInstanceContainersMetadata(type = "material", base_file = base_file, definition = global_stack.getBottom().getId(), variant = self._machine_manager.activeVariantId) - else: - materials = self._container_registry.findInstanceContainersMetadata(type = "material", base_file = base_file, definition = global_stack.getBottom().getId()) - - if materials: - return materials[0]["id"] - - Logger.log("w", "Unable to find a suitable container based on %s for the current machine.", base_file) - return "" # do not activate a new material if a container can not be found - - return base_file ## Get a list of materials that have the same GUID as the reference material # # \param material_id \type{str} the id of the material for which to get the linked materials. # \return \type{list} a list of names of materials with the same GUID - @pyqtSlot(str, result = "QStringList") - def getLinkedMaterials(self, material_id: str): - containers = self._container_registry.findInstanceContainersMetadata(id = material_id) - if not containers: - Logger.log("d", "Unable to find materials linked to material with id %s, because it doesn't exist.", material_id) - return [] + @pyqtSlot("QVariant", result = "QStringList") + def getLinkedMaterials(self, material_node): + guid = material_node.metadata["GUID"] - material_container = containers[0] - material_base_file = material_container.get("base_file", "") - material_guid = material_container.get("GUID", "") - if not material_guid: - Logger.log("d", "Unable to find materials linked to material with id %s, because it doesn't have a GUID.", material_id) - return [] + from cura.CuraApplication import CuraApplication + material_manager = CuraApplication.getInstance()._material_manager + + material_group_list = material_manager.getMaterialGroupListByGUID(guid) - containers = self._container_registry.findInstanceContainersMetadata(type = "material", GUID = material_guid) linked_material_names = [] - for container in containers: - if container["id"] in [material_id, material_base_file] or container.get("base_file") != container["id"]: - continue - - linked_material_names.append(container["name"]) + if material_group_list: + for material_group in material_group_list: + linked_material_names.append(material_group.root_material_node.metadata["name"]) return linked_material_names ## Unlink a material from all other materials by creating a new GUID # \param material_id \type{str} the id of the material to create a new GUID for. - @pyqtSlot(str) - def unlinkMaterial(self, material_id: str): - containers = self._container_registry.findInstanceContainers(id=material_id) - if not containers: - Logger.log("d", "Unable to make the material with id %s unique, because it doesn't exist.", material_id) - return "" + @pyqtSlot("QVariant") + def unlinkMaterial(self, material_node): + # Get the material group + from cura.CuraApplication import CuraApplication + material_manager = CuraApplication.getInstance()._material_manager + material_group = material_manager.getMaterialGroup(material_node.metadata["base_file"]) - containers[0].setMetaDataEntry("GUID", str(uuid.uuid4())) + # Generate a new GUID + new_guid = str(uuid.uuid4()) + # Update the GUID + # NOTE: We only need to set the root material container because XmlMaterialProfile.setMetaDataEntry() will + # take care of the derived containers too + container = material_group.root_material_node.getContainer() + container.setMetaDataEntry("GUID", new_guid) ## Get the singleton instance for this class. @classmethod diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index f35f15b737..338a72434f 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -48,18 +48,28 @@ class XmlMaterialProfile(InstanceContainer): ## Overridden from InstanceContainer # set the meta data for all machine / variant combinations - def setMetaDataEntry(self, key, value): + def setMetaDataEntry(self, key, value, is_first_call = True): registry = ContainerRegistry.getInstance() if registry.isReadOnly(self.getId()): return - super().setMetaDataEntry(key, value) + # Prevent recursion + if is_first_call: + super().setMetaDataEntry(key, value) - basefile = self.getMetaDataEntry("base_file", self.getId()) #if basefile is self.getId, this is a basefile. - # Update all containers that share basefile - for container in registry.findInstanceContainers(base_file = basefile): - if container.getMetaDataEntry(key, None) != value: # Prevent recursion - container.setMetaDataEntry(key, value) + # Get the MaterialGroup + material_manager = CuraApplication.getInstance()._material_manager + root_material_id = self.getMetaDataEntry("base_file") #if basefile is self.getId, this is a basefile. + material_group = material_manager.getMaterialGroup(root_material_id) + + # Update the root material container + root_material_container = material_group.root_material_node.getContainer() + root_material_container.setMetaDataEntry(key, value, is_first_call = False) + + # Update all containers derived from it + for node in material_group.derived_material_node_list: + container = node.getContainer() + container.setMetaDataEntry(key, value, is_first_call = False) ## Overridden from InstanceContainer, similar to setMetaDataEntry. # without this function the setName would only set the name of the specific nozzle / material / machine combination container diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 50eb3d3e99..f07564f7a5 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -12,7 +12,8 @@ TabView { id: base - property QtObject properties; + property QtObject properties + property var currentMaterialNode: null property bool editingEnabled: false; property string currency: UM.Preferences.getValue("cura/currency") ? UM.Preferences.getValue("cura/currency") : "€" @@ -27,15 +28,16 @@ TabView property bool reevaluateLinkedMaterials: false property string linkedMaterialNames: { - if (reevaluateLinkedMaterials) - { + if (reevaluateLinkedMaterials) { reevaluateLinkedMaterials = false; } - if(!base.containerId || !base.editingEnabled) - { + if (!base.containerId || !base.editingEnabled) { + return "" + } + var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentMaterialNode); + if (linkedMaterials.length <= 1) { return "" } - var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.containerId); return linkedMaterials.join(", "); } @@ -80,18 +82,18 @@ TabView { id: textField; width: scrollView.columnWidth; - text: properties.supplier; + text: properties.brand; readOnly: !base.editingEnabled; - onEditingFinished: base.updateMaterialSupplier(properties.supplier, text) + onEditingFinished: base.updateMaterialBrand(properties.brand, text) } Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") } ReadOnlyTextField { width: scrollView.columnWidth; - text: properties.material_type; + text: properties.material; readOnly: !base.editingEnabled; - onEditingFinished: base.updateMaterialType(properties.material_type, text) + onEditingFinished: base.updateMaterialType(properties.material, text) } Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } @@ -251,7 +253,7 @@ TabView visible: base.linkedMaterialNames != "" onClicked: { - Cura.ContainerManager.unlinkMaterial(base.containerId) + Cura.ContainerManager.unlinkMaterial(base.currentMaterialNode) base.reevaluateLinkedMaterials = true } } @@ -466,12 +468,12 @@ TabView // update the type of the material function updateMaterialType (old_type, new_type) { base.setMetaDataEntry("material", old_type, new_type) - materialProperties.material_type = new_type + materialProperties.material= new_type } - // update the supplier of the material - function updateMaterialSupplier (old_supplier, new_supplier) { - base.setMetaDataEntry("brand", old_supplier, new_supplier) - materialProperties.supplier = new_supplier + // update the brand of the material + function updateMaterialBrand (old_brand, new_brand) { + base.setMetaDataEntry("brand", old_brand, new_brand) + materialProperties.brand = new_brand } } diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index ae90c13e8c..9fbd8a5042 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -34,6 +34,8 @@ Item text: catalog.i18nc("@title:tab", "Materials") } + property var hasCurrentItem: materialListView.currentItem != null; + property var currentItem: { var current_index = materialListView.currentIndex; @@ -65,9 +67,6 @@ Item onClicked: { forceActiveFocus() - var current_index = materialListView.currentIndex; - var item = materialsModel.getItem(current_index); - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node); } @@ -87,10 +86,11 @@ Item Button { text: catalog.i18nc("@action:button", "Duplicate"); iconName: "list-add" - enabled: true //TODO + enabled: base.hasCurrentItem onClicked: { forceActiveFocus() - // TODO + + Cura.ContainerManager.duplicateMaterial(base.currentItem.container_node); } } @@ -277,6 +277,7 @@ Item { var model = materialsModel.getItem(currentIndex); materialDetailsView.containerId = model.container_id; + materialDetailsView.currentMaterialNode = model.container_node; detailsPanel.updateMaterialPropertiesObject(); } @@ -303,8 +304,8 @@ Item materialProperties.name = currentItem.name; materialProperties.guid = currentItem.guid; - materialProperties.supplier = currentItem.brand ? currentItem.brand : "Unknown"; - materialProperties.material_type = currentItem.material ? currentItem.material : "Unknown"; + materialProperties.brand = currentItem.brand ? currentItem.brand : "Unknown"; + materialProperties.material = currentItem.material ? currentItem.material : "Unknown"; materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; @@ -358,6 +359,7 @@ Item properties: materialProperties containerId: base.currentItem != null ? base.currentItem.id : "" + currentMaterialNode: base.currentItem property alias pane: base } @@ -369,8 +371,9 @@ Item property string guid: "00000000-0000-0000-0000-000000000000" property string name: "Unknown"; property string profile_type: "Unknown"; - property string supplier: "Unknown"; - property string material_type: "Unknown"; + property string brand: "Unknown"; + property string material: "Unknown"; // This needs to be named as "material" to be consistent with + // the material container's metadata entry property string color_name: "Yellow"; property color color_code: "yellow"; From 188c0343cff3feaa42552804396ab054daf233c4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 11:54:11 +0100 Subject: [PATCH 075/371] WIP: Improve map creation in MaterialManager --- cura/Machines/MaterialManager.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 25130fe255..a97b588e68 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -45,7 +45,7 @@ class MaterialManager(QObject): # We're using these two maps to convert between the specific diameter material id and the generic material id # because the generic material ids are used in qualities and definitions, while the specific diameter material is meant # i.e. generic_pla -> generic_pla_175 - self._material_diameter_map = defaultdict() # root_material_id -> diameter -> root_material_id for that diameter + self._material_diameter_map = defaultdict(dict) # root_material_id -> diameter -> root_material_id for that diameter self._diameter_material_map = dict() # material id including diameter (generic_pla_175) -> material root id (generic_pla) # This is used in Legacy UM3 send material function and the material management page. @@ -118,7 +118,7 @@ class MaterialManager(QObject): # and "generic_pla_175". This is inconvenient when we do material-specific quality lookup because a quality can # be for either "generic_pla" or "generic_pla_175", but not both. This map helps to get the correct material ID # for quality search. - self._material_diameter_map = defaultdict(defaultdict) + self._material_diameter_map = defaultdict(dict) self._diameter_material_map = dict() # Group the material IDs by the same name, material, brand, and color but with different diameters. @@ -140,8 +140,11 @@ class MaterialManager(QObject): # Map [root_material_id][diameter] -> root_material_id for this diameter for data_dict in material_group_dict.values(): for root_material_id1 in data_dict.values(): - for approximate_diameter2, root_material_id2 in data_dict.items(): - self._material_diameter_map[root_material_id1][approximate_diameter2] = root_material_id2 + if root_material_id1 in self._material_diameter_map: + continue + diameter_map = data_dict + for root_material_id2 in data_dict.values(): + self._material_diameter_map[root_material_id2] = diameter_map default_root_material_id = data_dict.get(self._default_approximate_diameter_for_quality_search) if default_root_material_id is None: From a5afaab467a52e19107ba8d25758010027729652 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 12:12:43 +0100 Subject: [PATCH 076/371] WIP: Fix material duplication and metadata update --- cura/Machines/MaterialManager.py | 4 +- cura/Settings/ContainerManager.py | 40 +++++++------------ .../XmlMaterialProfile/XmlMaterialProfile.py | 9 +++-- resources/qml/Preferences/MaterialView.qml | 2 +- 4 files changed, 23 insertions(+), 32 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index a97b588e68..550308f1dc 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -69,8 +69,7 @@ class MaterialManager(QObject): # Find all materials and put them in a matrix for quick search. material_metadata_list = self._container_registry.findContainersMetadata(type = "material") - self._material_group_map = OrderedDict() - self._diameter_machine_variant_material_map = {} + self._material_group_map = dict() # Map #1 # root_material_id -> MaterialGroup @@ -155,6 +154,7 @@ class MaterialManager(QObject): # Map #4 # "machine" -> "variant_name" -> "root material ID" -> specific material InstanceContainer # Construct the "machine" -> "variant" -> "root material ID" -> specific material InstanceContainer + self._diameter_machine_variant_material_map = dict() for material_metadata in material_metadata_list: # We don't store empty material in the lookup tables if material_metadata["id"] == "empty_material": diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 7d4c702cf4..737810ee9d 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -42,8 +42,10 @@ class ContainerManager(QObject): def __init__(self, parent = None): super().__init__(parent) + self._application = Application.getInstance() self._container_registry = ContainerRegistry.getInstance() - self._machine_manager = Application.getInstance().getMachineManager() + self._machine_manager = self._application.getMachineManager() + self._material_manager = self._application._material_manager self._container_name_filters = {} ## Create a duplicate of the specified container @@ -211,18 +213,15 @@ class ContainerManager(QObject): # \param entry_value The new value of the entry. # # \return True if successful, False if not. - @pyqtSlot(str, str, str, result = bool) - def setContainerMetaDataEntry(self, container_id, entry_name, entry_value): - if self._container_registry.isReadOnly(container_id): - Logger.log("w", "Cannot set metadata of read-only container %s.", container_id) + # TODO: This is ONLY used by MaterialView for material containers. Maybe refactor this. + @pyqtSlot("QVariant", str, str) + def setContainerMetaDataEntry(self, container_node, entry_name, entry_value): + root_material_id = container_node.metadata["base_file"] + if self._container_registry.isReadOnly(root_material_id): + Logger.log("w", "Cannot set metadata of read-only container %s.", root_material_id) return False - containers = self._container_registry.findContainers(id = container_id) #We need the complete container, since we need to know whether the container is read-only or not. - if not containers: - Logger.log("w", "Could not set metadata of container %s because it was not found.", container_id) - return False - - container = containers[0] + material_group = self._material_manager.getMaterialGroup(root_material_id) entries = entry_name.split("/") entry_name = entries.pop() @@ -230,7 +229,7 @@ class ContainerManager(QObject): sub_item_changed = False if entries: root_name = entries.pop(0) - root = container.getMetaDataEntry(root_name) + root = material_group.root_material_node.metadata.get(root_name) item = root for _ in range(len(entries)): @@ -243,12 +242,11 @@ class ContainerManager(QObject): entry_name = root_name entry_value = root + container = material_group.root_material_node.getContainer() container.setMetaDataEntry(entry_name, entry_value) if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed. container.metaDataChanged.emit(container) - return True - ## Set a setting property of the specified container. # # This will set the specified property of the specified setting of the container @@ -768,10 +766,7 @@ class ContainerManager(QObject): def duplicateMaterial(self, material_node): root_material_id = material_node.metadata["base_file"] - from cura.CuraApplication import CuraApplication - material_manager = CuraApplication.getInstance()._material_manager - - material_group = material_manager.getMaterialGroup(root_material_id) + material_group = self._material_manager.getMaterialGroup(root_material_id) if not material_group: Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", root_material_id) return "" @@ -867,10 +862,7 @@ class ContainerManager(QObject): def getLinkedMaterials(self, material_node): guid = material_node.metadata["GUID"] - from cura.CuraApplication import CuraApplication - material_manager = CuraApplication.getInstance()._material_manager - - material_group_list = material_manager.getMaterialGroupListByGUID(guid) + material_group_list = self._material_manager.getMaterialGroupListByGUID(guid) linked_material_names = [] if material_group_list: @@ -883,9 +875,7 @@ class ContainerManager(QObject): @pyqtSlot("QVariant") def unlinkMaterial(self, material_node): # Get the material group - from cura.CuraApplication import CuraApplication - material_manager = CuraApplication.getInstance()._material_manager - material_group = material_manager.getMaterialGroup(material_node.metadata["base_file"]) + material_group = self._material_manager.getMaterialGroup(material_node.metadata["base_file"]) # Generate a new GUID new_guid = str(uuid.uuid4()) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 338a72434f..80e3e3b721 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -48,14 +48,15 @@ class XmlMaterialProfile(InstanceContainer): ## Overridden from InstanceContainer # set the meta data for all machine / variant combinations - def setMetaDataEntry(self, key, value, is_first_call = True): + def setMetaDataEntry(self, key, value, apply_to_all = True): registry = ContainerRegistry.getInstance() if registry.isReadOnly(self.getId()): return # Prevent recursion - if is_first_call: + if not apply_to_all: super().setMetaDataEntry(key, value) + return # Get the MaterialGroup material_manager = CuraApplication.getInstance()._material_manager @@ -64,12 +65,12 @@ class XmlMaterialProfile(InstanceContainer): # Update the root material container root_material_container = material_group.root_material_node.getContainer() - root_material_container.setMetaDataEntry(key, value, is_first_call = False) + root_material_container.setMetaDataEntry(key, value, apply_to_all = False) # Update all containers derived from it for node in material_group.derived_material_node_list: container = node.getContainer() - container.setMetaDataEntry(key, value, is_first_call = False) + container.setMetaDataEntry(key, value, apply_to_all = False) ## Overridden from InstanceContainer, similar to setMetaDataEntry. # without this function the setName would only set the name of the specific nozzle / material / machine combination container diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index f07564f7a5..0c3063ff41 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -417,7 +417,7 @@ TabView // Tiny convenience function to check if a value really changed before trying to set it. function setMetaDataEntry(entry_name, old_value, new_value) { if (old_value != new_value) { - Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, entry_name, new_value) + Cura.ContainerManager.setContainerMetaDataEntry(base.currentMaterialNode, entry_name, new_value) // make sure the UI properties are updated as well since we don't re-fetch the entire model here // When the entry_name is something like properties/diameter, we take the last part of the entry_name var list = entry_name.split("/") From 779f49f5454f163037cbda62b800c31179318a92 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 12:35:51 +0100 Subject: [PATCH 077/371] WIP: Make material removal work in material management dialog --- cura/Settings/ContainerManager.py | 22 ++++++++---- resources/qml/Preferences/MaterialsPage.qml | 38 +++++++++++++++------ 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 737810ee9d..3775655671 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -759,6 +759,19 @@ class ContainerManager(QObject): return new_change_instances + @pyqtSlot("QVariant") + def removeMaterial(self, material_node): + root_material_id = material_node.metadata["base_file"] + material_group = self._material_manager.getMaterialGroup(root_material_id) + if not material_group: + Logger.log("d", "Unable to remove the material with id %s, because it doesn't exist.", root_material_id) + return + + nodes_to_remove = [material_group.root_material_node] + material_group.derived_material_node_list + for node in nodes_to_remove: + self._container_registry.removeContainer(node.metadata["id"]) + + ## Create a duplicate of a material, which has the same GUID and base_file metadata # # \return \type{str} the id of the newly created container. @@ -769,7 +782,7 @@ class ContainerManager(QObject): material_group = self._material_manager.getMaterialGroup(root_material_id) if not material_group: Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", root_material_id) - return "" + return base_container = material_group.root_material_node.getContainer() containers_to_copy = [] @@ -787,10 +800,9 @@ class ContainerManager(QObject): new_base_container.getMetaData()["base_file"] = new_base_id new_containers.append(new_base_container) - #Clone all of them. - clone_of_original = None #Keeping track of which one is the clone of the original material, since we need to return that. + # Clone all of them. for container_to_copy in containers_to_copy: - #Create unique IDs for every clone. + # Create unique IDs for every clone. current_id = container_to_copy.getId() new_id = new_base_id if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": @@ -798,8 +810,6 @@ class ContainerManager(QObject): if container_to_copy.getMetaDataEntry("variant_name"): variant_name = container_to_copy.getMetaDataEntry("variant_name") new_id += "_" + variant_name.replace(" ", "_") - if current_id == root_material_id: - clone_of_original = new_id new_container = copy.deepcopy(container_to_copy) new_container.getMetaData()["id"] = new_id diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 9fbd8a5042..782637a6be 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -4,6 +4,7 @@ import QtQuick 2.8 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.3 import UM 1.2 as UM import Cura 1.0 as Cura @@ -34,16 +35,14 @@ Item text: catalog.i18nc("@title:tab", "Materials") } - property var hasCurrentItem: materialListView.currentItem != null; + property var hasCurrentItem: materialListView.currentItem != null - property var currentItem: - { + property var currentItem: { var current_index = materialListView.currentIndex; return materialsModel.getItem(current_index); } - property var isCurrentItemActivated: - { + property var isCurrentItemActivated: { const extruder_position = Cura.ExtruderManager.activeExtruderIndex; const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; return base.currentItem.root_material_id == root_material_id; @@ -88,8 +87,7 @@ Item iconName: "list-add" enabled: base.hasCurrentItem onClicked: { - forceActiveFocus() - + forceActiveFocus(); Cura.ContainerManager.duplicateMaterial(base.currentItem.container_node); } } @@ -98,11 +96,10 @@ Item Button { text: catalog.i18nc("@action:button", "Remove") iconName: "list-remove" - //enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) - enabled: true // TODO + enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated onClicked: { - forceActiveFocus() - // TODO + forceActiveFocus(); + confirmRemoveMaterialDialog.open(); } } @@ -129,6 +126,25 @@ Item } } + MessageDialog + { + id: confirmRemoveMaterialDialog + + icon: StandardIcon.Question; + title: catalog.i18nc("@title:window", "Confirm Remove") + text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(base.currentItem.name) + standardButtons: StandardButton.Yes | StandardButton.No + modality: Qt.ApplicationModal + + onYes: + { + Cura.ContainerManager.removeMaterial(base.currentItem.container_node); + // reset current item to the first if available + materialListView.currentIndex = 0; + } + } + + Item { id: contentsItem From 4f29fc9ab270fd99184a7714fe4987cef19291b5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 13:54:15 +0100 Subject: [PATCH 078/371] WIP: make material creation work --- cura/Settings/ContainerManager.py | 56 ++++++++------------- resources/qml/Preferences/MaterialsPage.qml | 4 +- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 3775655671..f31c4fda04 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -776,7 +776,7 @@ class ContainerManager(QObject): # # \return \type{str} the id of the newly created container. @pyqtSlot("QVariant") - def duplicateMaterial(self, material_node): + def duplicateMaterial(self, material_node, new_base_id = None, new_metadata = None): root_material_id = material_node.metadata["base_file"] material_group = self._material_manager.getMaterialGroup(root_material_id) @@ -794,16 +794,19 @@ class ContainerManager(QObject): # Create a new ID & container to hold the data. new_containers = [] - new_base_id = self._container_registry.uniqueName(base_container.getId()) + if new_base_id is None: + new_base_id = self._container_registry.uniqueName(base_container.getId()) new_base_container = copy.deepcopy(base_container) new_base_container.getMetaData()["id"] = new_base_id new_base_container.getMetaData()["base_file"] = new_base_id + if new_metadata is not None: + for key, value in new_metadata.items(): + new_base_container.getMetaData()[key] = value new_containers.append(new_base_container) # Clone all of them. for container_to_copy in containers_to_copy: # Create unique IDs for every clone. - current_id = container_to_copy.getId() new_id = new_base_id if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": new_id += "_" + container_to_copy.getMetaDataEntry("definition") @@ -814,6 +817,10 @@ class ContainerManager(QObject): new_container = copy.deepcopy(container_to_copy) new_container.getMetaData()["id"] = new_id new_container.getMetaData()["base_file"] = new_base_id + if new_metadata is not None: + for key, value in new_metadata.items(): + new_container.getMetaData()[key] = value + new_containers.append(new_container) for container_to_add in new_containers: @@ -823,46 +830,27 @@ class ContainerManager(QObject): ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # # \return \type{str} the id of the newly created container. - @pyqtSlot(result = str) - def createMaterial(self) -> str: + @pyqtSlot() + def createMaterial(self): # Ensure all settings are saved. Application.getInstance().saveSettings() global_stack = Application.getInstance().getGlobalContainerStack() - if not global_stack: - return "" - approximate_diameter = str(round(global_stack.getProperty("material_diameter", "value"))) - containers = self._container_registry.findInstanceContainersMetadata(id = "generic_pla*", approximate_diameter = approximate_diameter) - if not containers: - Logger.log("d", "Unable to create a new material by cloning Generic PLA, because it cannot be found for the material diameter for this machine.") - return "" - - base_file = containers[0].get("base_file") - containers = self._container_registry.findInstanceContainers(id = base_file) - if not containers: - Logger.log("d", "Unable to create a new material by cloning Generic PLA, because the base file for Generic PLA for this machine can not be found.") - return "" + root_material_id = "generic_pla" + root_material_id = self._material_manager.getRootMaterialIDForDiameter(root_material_id, approximate_diameter) + material_group = self._material_manager.getMaterialGroup(root_material_id) # Create a new ID & container to hold the data. new_id = self._container_registry.uniqueName("custom_material") - container_type = type(containers[0]) # Always XMLMaterialProfile, since we specifically clone the base_file - duplicated_container = container_type(new_id) + new_metadata = {"name": catalog.i18nc("@label", "Custom Material"), + "brand": catalog.i18nc("@label", "Custom"), + "GUID": str(uuid.uuid4()), + } - # Instead of duplicating we load the data from the basefile again. - # This ensures that the inheritance goes well and all "cut up" subclasses of the xmlMaterial profile - # are also correctly created. - with open(containers[0].getPath(), encoding="utf-8") as f: - duplicated_container.deserialize(f.read()) - - duplicated_container.setMetaDataEntry("GUID", str(uuid.uuid4())) - duplicated_container.setMetaDataEntry("brand", catalog.i18nc("@label", "Custom")) - # We're defaulting to PLA, as machines with material profiles don't like material types they don't know. - # TODO: This is a hack, the only reason this is in now is to bandaid the problem as we're close to a release! - duplicated_container.setMetaDataEntry("material", "PLA") - duplicated_container.setName(catalog.i18nc("@label", "Custom Material")) - - self._container_registry.addContainer(duplicated_container) + self.duplicateMaterial(material_group.root_material_node, + new_base_id = new_id, + new_metadata = new_metadata) ## Get a list of materials that have the same GUID as the reference material # diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 782637a6be..4a8bc9e3c9 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -76,8 +76,8 @@ Item text: catalog.i18nc("@action:button", "Create") iconName: "list-add" onClicked: { - forceActiveFocus() - // TODO + forceActiveFocus(); + Cura.ContainerManager.createMaterial(); } } From 0b859bb308e35093b32ad1111ffa8a1e6baabf74 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 14:04:49 +0100 Subject: [PATCH 079/371] WIP: Make material export work --- cura/Settings/ContainerManager.py | 16 +++++----- resources/qml/Preferences/MaterialsPage.qml | 35 +++++++++++++++++++-- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index f31c4fda04..3738825d26 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -397,7 +397,7 @@ class ContainerManager(QObject): @pyqtSlot(str, str, QUrl, result = "QVariantMap") def exportContainer(self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]: if not container_id or not file_type or not file_url_or_string: - return { "status": "error", "message": "Invalid arguments"} + return {"status": "error", "message": "Invalid arguments"} if isinstance(file_url_or_string, QUrl): file_url = file_url_or_string.toLocalFile() @@ -405,20 +405,20 @@ class ContainerManager(QObject): file_url = file_url_or_string if not file_url: - return { "status": "error", "message": "Invalid path"} + return {"status": "error", "message": "Invalid path"} mime_type = None - if not file_type in self._container_name_filters: + if file_type not in self._container_name_filters: try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url) except MimeTypeNotFoundError: - return { "status": "error", "message": "Unknown File Type" } + return {"status": "error", "message": "Unknown File Type"} else: mime_type = self._container_name_filters[file_type]["mime"] containers = self._container_registry.findContainers(id = container_id) if not containers: - return { "status": "error", "message": "Container not found"} + return {"status": "error", "message": "Container not found"} container = containers[0] if Platform.isOSX() and "." in file_url: @@ -435,12 +435,12 @@ class ContainerManager(QObject): result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"), catalog.i18nc("@label Don't translate the XML tag !", "The file {0} already exists. Are you sure you want to overwrite it?").format(file_url)) if result == QMessageBox.No: - return { "status": "cancelled", "message": "User cancelled"} + return {"status": "cancelled", "message": "User cancelled"} try: contents = container.serialize() except NotImplementedError: - return { "status": "error", "message": "Unable to serialize container"} + return {"status": "error", "message": "Unable to serialize container"} if contents is None: return {"status": "error", "message": "Serialization returned None. Unable to write to file"} @@ -448,7 +448,7 @@ class ContainerManager(QObject): with SaveFile(file_url, "w") as f: f.write(contents) - return { "status": "success", "message": "Succesfully exported container", "path": file_url} + return {"status": "success", "message": "Successfully exported container", "path": file_url} ## Imports a profile from a file # diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 4a8bc9e3c9..5592e97150 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -119,8 +119,8 @@ Item text: catalog.i18nc("@action:button", "Export") iconName: "document-export" onClicked: { - forceActiveFocus() - // TODO + forceActiveFocus(); + exportMaterialDialog.open(); } enabled: currentItem != null } @@ -144,6 +144,37 @@ Item } } + FileDialog + { + id: exportMaterialDialog + title: catalog.i18nc("@title:window", "Export Material") + selectExisting: false + nameFilters: Cura.ContainerManager.getContainerNameFilters("material") + folder: CuraApplication.getDefaultPath("dialog_material_path") + onAccepted: + { + var result = Cura.ContainerManager.exportContainer(base.currentItem.root_material_id, selectedNameFilter, fileUrl); + + messageDialog.title = catalog.i18nc("@title:window", "Export Material"); + if (result.status == "error") { + messageDialog.icon = StandardIcon.Critical; + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags and !", "Failed to export material to %1: %2").arg(fileUrl).arg(result.message); + messageDialog.open(); + } + else if (result.status == "success") { + messageDialog.icon = StandardIcon.Information; + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully exported material to %1").arg(result.path); + messageDialog.open(); + } + CuraApplication.setDefaultPath("dialog_material_path", folder); + } + } + + MessageDialog + { + id: messageDialog + } + Item { id: contentsItem From 581699cd8d1a5c0f993bfcce75413eae436097fb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 14:08:45 +0100 Subject: [PATCH 080/371] WIP: Make material import work --- cura/Settings/ContainerManager.py | 12 ++++---- resources/qml/Preferences/MaterialsPage.qml | 32 +++++++++++++++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 3738825d26..240b7dfa4d 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -459,7 +459,7 @@ class ContainerManager(QObject): @pyqtSlot(QUrl, result = "QVariantMap") def importMaterialContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]: if not file_url_or_string: - return { "status": "error", "message": "Invalid path"} + return {"status": "error", "message": "Invalid path"} if isinstance(file_url_or_string, QUrl): file_url = file_url_or_string.toLocalFile() @@ -467,16 +467,16 @@ class ContainerManager(QObject): file_url = file_url_or_string if not file_url or not os.path.exists(file_url): - return { "status": "error", "message": "Invalid path" } + return {"status": "error", "message": "Invalid path"} try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url) except MimeTypeNotFoundError: - return { "status": "error", "message": "Could not determine mime type of file" } + return {"status": "error", "message": "Could not determine mime type of file"} container_type = self._container_registry.getContainerForMimeType(mime_type) if not container_type: - return { "status": "error", "message": "Could not find a container to handle the specified file."} + return {"status": "error", "message": "Could not find a container to handle the specified file."} container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url))) container_id = self._container_registry.uniqueName(container_id) @@ -487,7 +487,7 @@ class ContainerManager(QObject): with open(file_url, "rt", encoding = "utf-8") as f: container.deserialize(f.read()) except PermissionError: - return { "status": "error", "message": "Permission denied when trying to read the file"} + return {"status": "error", "message": "Permission denied when trying to read the file"} except Exception as ex: return {"status": "error", "message": str(ex)} @@ -495,7 +495,7 @@ class ContainerManager(QObject): self._container_registry.addContainer(container) - return { "status": "success", "message": "Successfully imported container {0}".format(container.getName()) } + return {"status": "success", "message": "Successfully imported container {0}".format(container.getName())} ## Update the current active quality changes container with the settings from the user container. # diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 5592e97150..92d596485c 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -108,8 +108,8 @@ Item text: catalog.i18nc("@action:button", "Import") iconName: "document-import" onClicked: { - forceActiveFocus() - // TODO + forceActiveFocus(); + importMaterialDialog.open(); } visible: true } @@ -144,6 +144,34 @@ Item } } + FileDialog + { + id: importMaterialDialog + title: catalog.i18nc("@title:window", "Import Material") + selectExisting: true + nameFilters: Cura.ContainerManager.getContainerNameFilters("material") + folder: CuraApplication.getDefaultPath("dialog_material_path") + onAccepted: + { + var result = Cura.ContainerManager.importMaterialContainer(fileUrl); + + messageDialog.title = catalog.i18nc("@title:window", "Import Material"); + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags or !", "Could not import material %1: %2").arg(fileUrl).arg(result.message); + if (result.status == "success") { + messageDialog.icon = StandardIcon.Information; + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl); + } + else if (result.status == "duplicate") { + messageDialog.icon = StandardIcon.Warning; + } + else { + messageDialog.icon = StandardIcon.Critical; + } + messageDialog.open(); + CuraApplication.setDefaultPath("dialog_material_path", folder); + } + } + FileDialog { id: exportMaterialDialog From 850661fbdc0bb6bb893bb2fef2050c903a2ae292 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 14:09:38 +0100 Subject: [PATCH 081/371] WIP: Remove old material management QMLs --- resources/qml/Preferences/OldMaterialView.qml | 467 ------------------ .../qml/Preferences/OldMaterialsPage.qml | 412 --------------- 2 files changed, 879 deletions(-) delete mode 100644 resources/qml/Preferences/OldMaterialView.qml delete mode 100644 resources/qml/Preferences/OldMaterialsPage.qml diff --git a/resources/qml/Preferences/OldMaterialView.qml b/resources/qml/Preferences/OldMaterialView.qml deleted file mode 100644 index 1b3a3b93a8..0000000000 --- a/resources/qml/Preferences/OldMaterialView.qml +++ /dev/null @@ -1,467 +0,0 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.8 -import QtQuick.Controls 1.4 -import QtQuick.Dialogs 1.2 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -TabView -{ - id: base - - property QtObject properties; - - property bool editingEnabled: false; - property string currency: UM.Preferences.getValue("cura/currency") ? UM.Preferences.getValue("cura/currency") : "€" - property real firstColumnWidth: (width * 0.50) | 0 - property real secondColumnWidth: (width * 0.40) | 0 - property string containerId: "" - property var materialPreferenceValues: UM.Preferences.getValue("cura/material_settings") ? JSON.parse(UM.Preferences.getValue("cura/material_settings")) : {} - - property double spoolLength: calculateSpoolLength() - property real costPerMeter: calculateCostPerMeter() - - property bool reevaluateLinkedMaterials: false - property string linkedMaterialNames: - { - if (reevaluateLinkedMaterials) - { - reevaluateLinkedMaterials = false; - } - if(!base.containerId || !base.editingEnabled) - { - return "" - } - var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.containerId); - return linkedMaterials.join(", "); - } - - Tab - { - title: catalog.i18nc("@title", "Information") - - anchors.margins: UM.Theme.getSize("default_margin").width - - ScrollView - { - id: scrollView - anchors.fill: parent - horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff - flickableItem.flickableDirection: Flickable.VerticalFlick - frameVisible: true - - property real columnWidth: (viewport.width * 0.5 - UM.Theme.getSize("default_margin").width) | 0 - - Flow - { - id: containerGrid - - x: UM.Theme.getSize("default_margin").width - y: UM.Theme.getSize("default_lining").height - - width: base.width - property real rowHeight: textField.height + UM.Theme.getSize("default_lining").height - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Display Name") } - ReadOnlyTextField - { - id: displayNameTextField; - width: scrollView.columnWidth; - text: properties.name; - readOnly: !base.editingEnabled; - onEditingFinished: base.updateMaterialDisplayName(properties.name, text) - } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") } - ReadOnlyTextField - { - id: textField; - width: scrollView.columnWidth; - text: properties.supplier; - readOnly: !base.editingEnabled; - onEditingFinished: base.updateMaterialSupplier(properties.supplier, text) - } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") } - ReadOnlyTextField - { - width: scrollView.columnWidth; - text: properties.material_type; - readOnly: !base.editingEnabled; - onEditingFinished: base.updateMaterialType(properties.material_type, text) - } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } - Row { - width: scrollView.columnWidth - height: parent.rowHeight - spacing: Math.floor(UM.Theme.getSize("default_margin").width / 2) - - // color indicator square - Rectangle { - id: colorSelector - color: properties.color_code - - width: Math.floor(colorLabel.height * 0.75) - height: Math.floor(colorLabel.height * 0.75) - border.width: UM.Theme.getSize("default_lining").height - - anchors.verticalCenter: parent.verticalCenter - - // open the color selection dialog on click - MouseArea { - anchors.fill: parent - onClicked: colorDialog.open() - enabled: base.editingEnabled - } - } - - // pretty color name text field - ReadOnlyTextField { - id: colorLabel; - text: properties.color_name; - readOnly: !base.editingEnabled - onEditingFinished: base.setMetaDataEntry("color_name", properties.color_name, text) - } - - // popup dialog to select a new color - // if successful it sets the properties.color_code value to the new color - ColorDialog { - id: colorDialog - color: properties.color_code - onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color) - } - } - - Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } - - Label { width: parent.width; height: parent.rowHeight; font.bold: true; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Properties") } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") } - ReadOnlySpinBox - { - id: densitySpinBox - width: scrollView.columnWidth - value: properties.density - decimals: 2 - suffix: " g/cm³" - stepSize: 0.01 - readOnly: !base.editingEnabled - - onEditingFinished: base.setMetaDataEntry("properties/density", properties.density, value) - onValueChanged: updateCostPerMeter() - } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") } - ReadOnlySpinBox - { - id: diameterSpinBox - width: scrollView.columnWidth - value: properties.diameter - decimals: 2 - suffix: " mm" - stepSize: 0.01 - readOnly: !base.editingEnabled - - onEditingFinished: - { - // This does not use a SettingPropertyProvider, because we need to make the change to all containers - // which derive from the same base_file - var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString(); - var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); - base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, Math.round(value).toString()); - base.setMetaDataEntry("properties/diameter", properties.diameter, value); - var new_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); - if (Cura.MachineManager.filterMaterialsByMachine && new_approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) - { - Cura.MaterialManager.showMaterialWarningMessage(base.containerId, old_diameter); - } - Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value); - } - onValueChanged: updateCostPerMeter() - } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") } - SpinBox - { - id: spoolCostSpinBox - width: scrollView.columnWidth - value: base.getMaterialPreferenceValue(properties.guid, "spool_cost") - prefix: base.currency + " " - decimals: 2 - maximumValue: 100000000 - - onValueChanged: { - base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value)) - updateCostPerMeter() - } - } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") } - SpinBox - { - id: spoolWeightSpinBox - width: scrollView.columnWidth - value: base.getMaterialPreferenceValue(properties.guid, "spool_weight") - suffix: " g" - stepSize: 100 - decimals: 0 - maximumValue: 10000 - - onValueChanged: { - base.setMaterialPreferenceValue(properties.guid, "spool_weight", parseFloat(value)) - updateCostPerMeter() - } - } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") } - Label - { - width: scrollView.columnWidth - text: "~ %1 m".arg(Math.round(base.spoolLength)) - verticalAlignment: Qt.AlignVCenter - height: parent.rowHeight - } - - Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter") } - Label - { - width: scrollView.columnWidth - text: "~ %1 %2/m".arg(base.costPerMeter.toFixed(2)).arg(base.currency) - verticalAlignment: Qt.AlignVCenter - height: parent.rowHeight - } - - Item { width: parent.width; height: UM.Theme.getSize("default_margin").height; visible: unlinkMaterialButton.visible } - Label - { - width: 2 * scrollView.columnWidth - verticalAlignment: Qt.AlignVCenter - text: catalog.i18nc("@label", "This material is linked to %1 and shares some of its properties.").arg(base.linkedMaterialNames) - wrapMode: Text.WordWrap - visible: unlinkMaterialButton.visible - } - Button - { - id: unlinkMaterialButton - text: catalog.i18nc("@label", "Unlink Material") - visible: base.linkedMaterialNames != "" - onClicked: - { - Cura.ContainerManager.unlinkMaterial(base.containerId) - base.reevaluateLinkedMaterials = true - } - } - - Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } - - Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Description") } - - ReadOnlyTextArea - { - text: properties.description; - width: 2 * scrollView.columnWidth - wrapMode: Text.WordWrap - - readOnly: !base.editingEnabled; - - onEditingFinished: base.setMetaDataEntry("description", properties.description, text) - } - - Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Adhesion Information") } - - ReadOnlyTextArea - { - text: properties.adhesion_info; - width: 2 * scrollView.columnWidth - wrapMode: Text.WordWrap - - readOnly: !base.editingEnabled; - - onEditingFinished: base.setMetaDataEntry("adhesion_info", properties.adhesion_info, text) - } - - Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } - } - - function updateCostPerMeter() - { - base.spoolLength = calculateSpoolLength(diameterSpinBox.value, densitySpinBox.value, spoolWeightSpinBox.value); - base.costPerMeter = calculateCostPerMeter(spoolCostSpinBox.value); - } - } - } - - Tab - { - title: catalog.i18nc("@label", "Print settings") - anchors - { - leftMargin: UM.Theme.getSize("default_margin").width - topMargin: UM.Theme.getSize("default_margin").height - bottomMargin: UM.Theme.getSize("default_margin").height - rightMargin: 0 - } - - ScrollView - { - anchors.fill: parent; - - ListView - { - model: UM.SettingDefinitionsModel - { - containerId: Cura.MachineManager.activeDefinitionId - visibilityHandler: Cura.MaterialSettingsVisibilityHandler { } - expanded: ["*"] - } - - delegate: UM.TooltipArea - { - width: childrenRect.width - height: childrenRect.height - text: model.description - Label - { - id: label - width: base.firstColumnWidth; - height: spinBox.height + UM.Theme.getSize("default_lining").height - text: model.label - elide: Text.ElideRight - verticalAlignment: Qt.AlignVCenter - } - ReadOnlySpinBox - { - id: spinBox - anchors.left: label.right - value: { - if (!isNaN(parseFloat(materialPropertyProvider.properties.value))) - { - return parseFloat(materialPropertyProvider.properties.value); - } - if (!isNaN(parseFloat(machinePropertyProvider.properties.value))) - { - return parseFloat(machinePropertyProvider.properties.value); - } - return 0; - } - width: base.secondColumnWidth - readOnly: !base.editingEnabled - suffix: " " + model.unit - maximumValue: 99999 - decimals: model.unit == "mm" ? 2 : 0 - - onEditingFinished: materialPropertyProvider.setPropertyValue("value", value) - } - - UM.ContainerPropertyProvider { id: materialPropertyProvider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key } - UM.ContainerPropertyProvider { id: machinePropertyProvider; containerId: Cura.MachineManager.activeDefinitionId; watchedProperties: [ "value" ]; key: model.key } - } - } - } - } - - function calculateSpoolLength(diameter, density, spoolWeight) - { - if(!diameter) - { - diameter = properties.diameter; - } - if(!density) - { - density = properties.density; - } - if(!spoolWeight) - { - spoolWeight = base.getMaterialPreferenceValue(properties.guid, "spool_weight"); - } - - if (diameter == 0 || density == 0 || spoolWeight == 0) - { - return 0; - } - var area = Math.PI * Math.pow(diameter / 2, 2); // in mm2 - var volume = (spoolWeight / density); // in cm3 - return volume / area; // in m - } - - function calculateCostPerMeter(spoolCost) - { - if(!spoolCost) - { - spoolCost = base.getMaterialPreferenceValue(properties.guid, "spool_cost"); - } - - if (spoolLength == 0) - { - return 0; - } - return spoolCost / spoolLength; - } - - // Tiny convenience function to check if a value really changed before trying to set it. - function setMetaDataEntry(entry_name, old_value, new_value) { - if (old_value != new_value) { - Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, entry_name, new_value) - // make sure the UI properties are updated as well since we don't re-fetch the entire model here - // When the entry_name is something like properties/diameter, we take the last part of the entry_name - var list = entry_name.split("/") - var key = list[list.length - 1] - properties[key] = new_value - } - } - - function setMaterialPreferenceValue(material_guid, entry_name, new_value) - { - if(!(material_guid in materialPreferenceValues)) - { - materialPreferenceValues[material_guid] = {}; - } - if(entry_name in materialPreferenceValues[material_guid] && materialPreferenceValues[material_guid][entry_name] == new_value) - { - // value has not changed - return - } - materialPreferenceValues[material_guid][entry_name] = new_value; - - // store preference - UM.Preferences.setValue("cura/material_settings", JSON.stringify(materialPreferenceValues)); - } - - function getMaterialPreferenceValue(material_guid, entry_name) - { - if(material_guid in materialPreferenceValues && entry_name in materialPreferenceValues[material_guid]) - { - return materialPreferenceValues[material_guid][entry_name]; - } - return 0; - } - - // update the display name of the material - function updateMaterialDisplayName (old_name, new_name) { - - // don't change when new name is the same - if (old_name == new_name) { - return - } - - // update the values - Cura.ContainerManager.setContainerName(base.containerId, new_name) - materialProperties.name = new_name - } - - // update the type of the material - function updateMaterialType (old_type, new_type) { - base.setMetaDataEntry("material", old_type, new_type) - materialProperties.material_type = new_type - } - - // update the supplier of the material - function updateMaterialSupplier (old_supplier, new_supplier) { - base.setMetaDataEntry("brand", old_supplier, new_supplier) - materialProperties.supplier = new_supplier - } -} diff --git a/resources/qml/Preferences/OldMaterialsPage.qml b/resources/qml/Preferences/OldMaterialsPage.qml deleted file mode 100644 index 0a24b9c663..0000000000 --- a/resources/qml/Preferences/OldMaterialsPage.qml +++ /dev/null @@ -1,412 +0,0 @@ -//Copyright (c) 2017 Ultimaker B.V. -//Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.8 -import QtQuick.Controls 1.4 -import QtQuick.Dialogs 1.2 - -import UM 1.2 as UM -import Cura 1.0 as Cura - - -UM.ManagementPage -{ - id: base - title: catalog.i18nc("@title:tab", "Materials") - - Component.onCompleted: - { - // Workaround to make sure all of the items are visible - objectList.positionViewAtBeginning(); - } - - model: Cura.MaterialsModel - { - filter: - { - var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() } - if(Cura.MachineManager.filterMaterialsByMachine) - { - result.definition = Cura.MachineManager.activeQualityDefinitionId; - if(Cura.MachineManager.hasVariants) - { - result.variant_name = Cura.MachineManager.activeQualityVariantName; - } - } - else - { - result.definition = "fdmprinter"; - result.compatible = true; //NB: Only checks for compatibility in global version of material, but we don't have machine-specific materials anyway. - } - return result - } - - sectionProperty: "brand" - } - - delegate: Rectangle - { - width: objectList.width; - height: childrenRect.height; - color: isCurrentItem ? palette.highlight : index % 2 ? palette.base : palette.alternateBase - property bool isCurrentItem: ListView.isCurrentItem - - Row - { - spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - Rectangle - { - width: Math.floor(parent.height * 0.8) - height: Math.floor(parent.height * 0.8) - color: model.metadata.color_code - border.color: isCurrentItem ? palette.highlightedText : palette.text; - anchors.verticalCenter: parent.verticalCenter - } - Label - { - width: Math.floor((parent.width * 0.3)) - text: model.metadata.material - elide: Text.ElideRight - font.italic: model.id == activeId - color: isCurrentItem ? palette.highlightedText : palette.text; - } - Label - { - text: (model.name != model.metadata.material) ? model.name : "" - elide: Text.ElideRight - font.italic: model.id == activeId - color: isCurrentItem ? palette.highlightedText : palette.text; - } - } - - MouseArea - { - anchors.fill: parent; - onClicked: - { - forceActiveFocus(); - if(!parent.ListView.isCurrentItem) - { - parent.ListView.view.currentIndex = index; - base.itemActivated(); - } - } - } - } - - activeId: Cura.MachineManager.activeMaterialId - activeIndex: getIndexById(activeId) - function getIndexById(material_id) - { - for(var i = 0; i < model.rowCount(); i++) { - if (model.getItem(i).id == material_id) { - return i; - } - } - return -1; - } - - scrollviewCaption: - { - var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; - if (Cura.MachineManager.hasVariants) - { - caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; - } - return caption; - } - detailsVisible: true - - section.property: "section" - section.delegate: Label - { - text: section - font.bold: true - anchors.left: parent.left; - anchors.leftMargin: UM.Theme.getSize("default_lining").width; - } - - buttons: [ - - // Activate button - Button { - text: catalog.i18nc("@action:button", "Activate") - iconName: "list-activate"; - enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials - onClicked: { - forceActiveFocus() - Cura.MachineManager.setActiveMaterial(base.currentItem.id) - currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. - } - }, - - // Create button - Button { - text: catalog.i18nc("@action:button", "Create") - iconName: "list-add" - onClicked: { - forceActiveFocus() - Cura.ContainerManager.createMaterial() - } - }, - - // Duplicate button - Button { - text: catalog.i18nc("@action:button", "Duplicate"); - iconName: "list-add"; - enabled: base.currentItem != null - onClicked: { - forceActiveFocus() - Cura.ContainerManager.duplicateOriginalMaterial(base.currentItem.id) - } - }, - - // Remove button - Button { - text: catalog.i18nc("@action:button", "Remove") - iconName: "list-remove" - enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) - onClicked: { - forceActiveFocus() - confirmDialog.open() - } - }, - - // Import button - Button { - text: catalog.i18nc("@action:button", "Import") - iconName: "document-import" - onClicked: { - forceActiveFocus() - importDialog.open() - } - visible: true - }, - - // Export button - Button { - text: catalog.i18nc("@action:button", "Export") - iconName: "document-export" - onClicked: { - forceActiveFocus() - exportDialog.open() - } - enabled: currentItem != null - } - - ] - - Item { - visible: base.currentItem != null - anchors.fill: parent - - Item // Material title Label - { - id: profileName - - width: parent.width; - height: childrenRect.height - - Label { text: materialProperties.name; font: UM.Theme.getFont("large"); } - } - - MaterialView // Material detailed information view below the title Label - { - anchors - { - left: parent.left - right: parent.right - top: profileName.bottom - topMargin: UM.Theme.getSize("default_margin").height - bottom: parent.bottom - } - - editingEnabled: base.currentItem != null && !base.currentItem.readOnly - - properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.id : "" - - property alias pane: base - } - - QtObject - { - id: materialProperties - - property string guid: "00000000-0000-0000-0000-000000000000" - property string name: "Unknown"; - property string profile_type: "Unknown"; - property string supplier: "Unknown"; - property string material_type: "Unknown"; - - property string color_name: "Yellow"; - property color color_code: "yellow"; - - property real density: 0.0; - property real diameter: 0.0; - property string approximate_diameter: "0"; - - property real spool_cost: 0.0; - property real spool_weight: 0.0; - property real spool_length: 0.0; - property real cost_per_meter: 0.0; - - property string description: ""; - property string adhesion_info: ""; - } - - UM.ConfirmRemoveDialog - { - id: confirmDialog - object: base.currentItem != null ? base.currentItem.name : "" - onYes: - { - // A material container can actually be multiple items, so we need to find (and remove) all of them. - var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file") - if(base_file == "") - { - base_file = base.currentItem.id - } - var guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID") - // remove base container first, it otherwise triggers loading the base file while removing other containers - var base_containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "id": base_file, "base_file": base_file, "type": "material"}) - for(var i in base_containers) - { - Cura.ContainerManager.removeContainer(base_containers[i]); - } - var containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "base_file": base_file, "type": "material"}) - for(var i in containers) - { - Cura.ContainerManager.removeContainer(containers[i]); - } - if(base.objectList.currentIndex > 0) - { - base.objectList.currentIndex--; - } - currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. - } - } - - FileDialog - { - id: importDialog; - title: catalog.i18nc("@title:window", "Import Material"); - selectExisting: true; - nameFilters: Cura.ContainerManager.getContainerNameFilters("material") - folder: CuraApplication.getDefaultPath("dialog_material_path") - onAccepted: - { - var result = Cura.ContainerManager.importMaterialContainer(fileUrl) - - messageDialog.title = catalog.i18nc("@title:window", "Import Material") - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags or !", "Could not import material %1: %2").arg(fileUrl).arg(result.message) - if(result.status == "success") - { - messageDialog.icon = StandardIcon.Information - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl) - } - else if(result.status == "duplicate") - { - messageDialog.icon = StandardIcon.Warning - } - else - { - messageDialog.icon = StandardIcon.Critical - } - messageDialog.open() - CuraApplication.setDefaultPath("dialog_material_path", folder) - } - } - - FileDialog - { - id: exportDialog; - title: catalog.i18nc("@title:window", "Export Material"); - selectExisting: false; - nameFilters: Cura.ContainerManager.getContainerNameFilters("material") - folder: CuraApplication.getDefaultPath("dialog_material_path") - onAccepted: - { - if(base.currentItem.metadata.base_file) - { - var result = Cura.ContainerManager.exportContainer(base.currentItem.metadata.base_file, selectedNameFilter, fileUrl) - } - else - { - var result = Cura.ContainerManager.exportContainer(base.currentItem.id, selectedNameFilter, fileUrl) - } - - messageDialog.title = catalog.i18nc("@title:window", "Export Material") - if(result.status == "error") - { - messageDialog.icon = StandardIcon.Critical - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags and !", "Failed to export material to %1: %2").arg(fileUrl).arg(result.message) - messageDialog.open() - } - else if(result.status == "success") - { - messageDialog.icon = StandardIcon.Information - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully exported material to %1").arg(result.path) - messageDialog.open() - } - CuraApplication.setDefaultPath("dialog_material_path", folder) - } - } - - MessageDialog - { - id: messageDialog - } - - UM.SettingPropertyProvider - { - id: materialDiameterProvider - - containerStackId: Cura.ExtruderManager.activeExtruderStackId - key: "material_diameter" - watchedProperties: [ "value" ] - storeIndex: 5 - } - - UM.I18nCatalog { id: catalog; name: "cura"; } - SystemPalette { id: palette } - } - - onCurrentItemChanged: - { - if(currentItem == null) - { - return - } - materialProperties.name = currentItem.name; - materialProperties.guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID"); - - if(currentItem.metadata != undefined && currentItem.metadata != null) - { - materialProperties.supplier = currentItem.metadata.brand ? currentItem.metadata.brand : "Unknown"; - materialProperties.material_type = currentItem.metadata.material ? currentItem.metadata.material : "Unknown"; - materialProperties.color_name = currentItem.metadata.color_name ? currentItem.metadata.color_name : "Yellow"; - materialProperties.color_code = currentItem.metadata.color_code ? currentItem.metadata.color_code : "yellow"; - - materialProperties.description = currentItem.metadata.description ? currentItem.metadata.description : ""; - materialProperties.adhesion_info = currentItem.metadata.adhesion_info ? currentItem.metadata.adhesion_info : ""; - - if(currentItem.metadata.properties != undefined && currentItem.metadata.properties != null) - { - materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0; - materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0; - materialProperties.approximate_diameter = currentItem.metadata.approximate_diameter ? currentItem.metadata.approximate_diameter : "0"; - } - else - { - materialProperties.density = 0.0; - materialProperties.diameter = 0.0; - materialProperties.approximate_diameter = "0"; - } - - } - } -} From e5cc7efdf2562e0bf9830e00d517694af237b213 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 14:17:10 +0100 Subject: [PATCH 082/371] WIP: Cleanup ContainerManager --- cura/Settings/ContainerManager.py | 144 ------------------------------ 1 file changed, 144 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 240b7dfa4d..0df7f4ba05 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -48,150 +48,6 @@ class ContainerManager(QObject): self._material_manager = self._application._material_manager self._container_name_filters = {} - ## Create a duplicate of the specified container - # - # This will create and add a duplicate of the container corresponding - # to the container ID. - # - # \param container_id \type{str} The ID of the container to duplicate. - # - # \return The ID of the new container, or an empty string if duplication failed. - @pyqtSlot(str, result = str) - def duplicateContainer(self, container_id): - #TODO: It should be able to duplicate a container of which only the metadata is known. - containers = self._container_registry.findContainers(id = container_id) - if not containers: - Logger.log("w", "Could duplicate container %s because it was not found.", container_id) - return "" - - container = containers[0] - new_container = self.duplicateContainerInstance(container) - return new_container.getId() - - ## Create a duplicate of the given container instance - # - # This will create and add a duplicate of the container that was passed. - # - # \param container \type{ContainerInterface} The container to duplicate. - # - # \return The duplicated container, or None if duplication failed. - def duplicateContainerInstance(self, container): - new_container = None - new_name = self._container_registry.uniqueName(container.getName()) - # Only InstanceContainer has a duplicate method at the moment. - # So fall back to serialize/deserialize when no duplicate method exists. - if hasattr(container, "duplicate"): - new_container = container.duplicate(new_name) - else: - new_container = container.__class__(new_name) - new_container.deserialize(container.serialize()) - new_container.setName(new_name) - - # TODO: we probably don't want to add it to the registry here! - if new_container: - self._container_registry.addContainer(new_container) - - return new_container - - ## Change the name of a specified container to a new name. - # - # \param container_id \type{str} The ID of the container to change the name of. - # \param new_id \type{str} The new ID of the container. - # \param new_name \type{str} The new name of the specified container. - # - # \return True if successful, False if not. - @pyqtSlot(str, str, str, result = bool) - def renameContainer(self, container_id, new_id, new_name): - containers = self._container_registry.findContainers(id = container_id) - if not containers: - Logger.log("w", "Could rename container %s because it was not found.", container_id) - return False - - container = containers[0] - # First, remove the container from the registry. This will clean up any files related to the container. - self._container_registry.removeContainer(container_id) - - # Ensure we have a unique name for the container - new_name = self._container_registry.uniqueName(new_name) - - # Then, update the name and ID of the container - container.setName(new_name) - container._id = new_id # TODO: Find a nicer way to set a new, unique ID - - # Finally, re-add the container so it will be properly serialized again. - self._container_registry.addContainer(container) - - return True - - ## Remove the specified container. - # - # \param container_id \type{str} The ID of the container to remove. - # - # \return True if the container was successfully removed, False if not. - @pyqtSlot(str, result = bool) - def removeContainer(self, container_id): - containers = self._container_registry.findContainers(id = container_id) - if not containers: - Logger.log("w", "Could not remove container %s because it was not found.", container_id) - return False - - self._container_registry.removeContainer(containers[0].getId()) - - return True - - ## Merge a container with another. - # - # This will try to merge one container into the other, by going through the container - # and setting the right properties on the other container. - # - # \param merge_into_id \type{str} The ID of the container to merge into. - # \param merge_id \type{str} The ID of the container to merge. - # - # \return True if successfully merged, False if not. - @pyqtSlot(str, result = bool) - def mergeContainers(self, merge_into_id, merge_id): - containers = self._container_registry.findContainers(id = merge_into_id) - if not containers: - Logger.log("w", "Could merge into container %s because it was not found.", merge_into_id) - return False - - merge_into = containers[0] - - containers = self._container_registry.findContainers(id = merge_id) - if not containers: - Logger.log("w", "Could not merge container %s because it was not found", merge_id) - return False - - merge = containers[0] - - if not isinstance(merge, type(merge_into)): - Logger.log("w", "Cannot merge two containers of different types") - return False - - self._performMerge(merge_into, merge) - - return True - - ## Clear the contents of a container. - # - # \param container_id \type{str} The ID of the container to clear. - # - # \return True if successful, False if not. - @pyqtSlot(str, result = bool) - def clearContainer(self, container_id): - if self._container_registry.isReadOnly(container_id): - Logger.log("w", "Cannot clear read-only container %s", container_id) - return False - - containers = self._container_registry.findContainers(id = container_id) - if not containers: - Logger.log("w", "Could clear container %s because it was not found.", container_id) - return False - - containers[0].clear() - - return True - @pyqtSlot(str, str, result=str) def getContainerMetaDataEntry(self, container_id, entry_name): metadatas = self._container_registry.findContainersMetadata(id = container_id) From f7f9c68fcc8ae8d14d4fb3e8c635bce6147eaf6b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 14:17:35 +0100 Subject: [PATCH 083/371] WIP: Refactor setMaterialName() --- cura/Settings/ContainerManager.py | 23 +++++++++------------- resources/qml/Preferences/MaterialView.qml | 3 +-- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 0df7f4ba05..c420f5b49e 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -160,21 +160,16 @@ class ContainerManager(QObject): return container.getProperty(setting_key, property_name) - ## Set the name of the specified container. - @pyqtSlot(str, str, result = bool) - def setContainerName(self, container_id, new_name): - if self._container_registry.isReadOnly(container_id): - Logger.log("w", "Cannot set name of read-only container %s.", container_id) - return False + ## Set the name of the specified material. + @pyqtSlot("QVariant", str) + def setMaterialName(self, material_node, new_name): + root_material_id = material_node.metadata["base_file"] + if self._container_registry.isReadOnly(root_material_id): + Logger.log("w", "Cannot set name of read-only container %s.", root_material_id) + return - containers = self._container_registry.findContainers(id = container_id) #We need to get the full container, not just metadata, since we need to know whether it's read-only. - if not containers: - Logger.log("w", "Could not set name of container %s because it was not found.", container_id) - return False - - containers[0].setName(new_name) - - return True + material_group = self._material_manager.getMaterialGroup(root_material_id) + material_group.root_material_node.getContainer().setName(new_name) ## Find instance containers matching certain criteria. # diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 0c3063ff41..6e3d04fa2c 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -454,14 +454,13 @@ TabView // update the display name of the material function updateMaterialDisplayName (old_name, new_name) { - // don't change when new name is the same if (old_name == new_name) { return } // update the values - Cura.ContainerManager.setContainerName(base.containerId, new_name) + Cura.ContainerManager.setMaterialName(base.currentMaterialNode, new_name) materialProperties.name = new_name } From bed2106fc6b4d5bec2691cb8e8411b59c5a861ce Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 14:26:04 +0100 Subject: [PATCH 084/371] WIP: Backup old profile management QMLs --- resources/qml/Preferences/{ProfileTab.qml => OldProfileTab.qml} | 0 .../qml/Preferences/{ProfilesPage.qml => OldProfilesPage.qml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename resources/qml/Preferences/{ProfileTab.qml => OldProfileTab.qml} (100%) rename resources/qml/Preferences/{ProfilesPage.qml => OldProfilesPage.qml} (100%) diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/OldProfileTab.qml similarity index 100% rename from resources/qml/Preferences/ProfileTab.qml rename to resources/qml/Preferences/OldProfileTab.qml diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/OldProfilesPage.qml similarity index 100% rename from resources/qml/Preferences/ProfilesPage.qml rename to resources/qml/Preferences/OldProfilesPage.qml From 96f126436465c69368733914f58dddab5205f497 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 16:40:09 +0100 Subject: [PATCH 085/371] WIP: Rework profile management page --- cura/CuraApplication.py | 4 + cura/Machines/MaterialManager.py | 6 +- .../Machines/Models/QualityManagementModel.py | 75 +++++ cura/Machines/QualityManager.py | 34 +- cura/Settings/MachineManager.py | 82 +++-- cura/Settings/MaterialsModel.py | 2 +- cura/Settings/ProfilesModel.py | 2 + resources/qml/Preferences/ProfileTab.qml | 98 ++++++ resources/qml/Preferences/ProfilesPage.qml | 294 ++++++++++++++++++ 9 files changed, 561 insertions(+), 36 deletions(-) create mode 100644 cura/Machines/Models/QualityManagementModel.py create mode 100644 resources/qml/Preferences/ProfileTab.qml create mode 100644 resources/qml/Preferences/ProfilesPage.qml diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e9be1f96c9..3b15069598 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -61,6 +61,7 @@ from cura.Settings.UserProfilesModel import UserProfilesModel from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager from cura.Machines.VariantManager import VariantManager +from cura.Machines.Models.QualityManagementModel import QualityManagementModel from . import PlatformPhysics from . import BuildVolume @@ -939,6 +940,9 @@ class CuraApplication(QtApplication): qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") qmlRegisterType(NewMaterialsModel, "Cura", 1, 0, "NewMaterialsModel") + # TODO: make this singleton? + qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") + qmlRegisterSingletonType(NewQualityProfilesModel, "Cura", 1, 0, "NewQualityProfilesModel", self.getNewQualityProfileModel) qmlRegisterSingletonType(NewCustomQualityProfilesModel, "Cura", 1, 0, "NewCustomQualityProfilesModel", self.getNewCustomQualityProfilesModel) qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 550308f1dc..84f08a3b27 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -59,7 +59,7 @@ class MaterialManager(QObject): self._update_timer = QTimer(self) self._update_timer.setInterval(300) self._update_timer.setSingleShot(True) - self._update_timer.timeout.connect(self._updateTables) + self._update_timer.timeout.connect(self._updateMaps) self._container_registry.containerMetaDataChanged.connect(self._onContainerMetadataChanged) self._container_registry.containerAdded.connect(self._onContainerMetadataChanged) @@ -192,7 +192,7 @@ class MaterialManager(QObject): self.materialsUpdated.emit() - def _updateTables(self): + def _updateMaps(self): self.initialize() def _onContainerMetadataChanged(self, container): @@ -203,7 +203,7 @@ class MaterialManager(QObject): if container_type != "material": return - # TODO: update the cache table + # update the maps self._update_timer.start() def getMaterialGroup(self, root_material_id: str) -> Optional[MaterialGroup]: diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py new file mode 100644 index 0000000000..fab6a36410 --- /dev/null +++ b/cura/Machines/Models/QualityManagementModel.py @@ -0,0 +1,75 @@ + + +from PyQt5.QtCore import Qt + +from UM.Qt.ListModel import ListModel + + +class QualityManagementModel(ListModel): + NameRole = Qt.UserRole + 1 + IsReadOnlyRole = Qt.UserRole + 2 + QualityGroupRole = Qt.UserRole + 3 + QualityChangesGroupRole = Qt.UserRole + 4 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.IsReadOnlyRole, "is_read_only") + self.addRoleName(self.QualityGroupRole, "quality_group") + self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") + + from cura.CuraApplication import CuraApplication + self._container_registry = CuraApplication.getInstance().getContainerRegistry() + self._machine_manager = CuraApplication.getInstance().getMachineManager() + self._extruder_manager = CuraApplication.getInstance().getExtruderManager() + self._quality_manager = CuraApplication.getInstance()._quality_manager + + self._machine_manager.globalContainerChanged.connect(self._update) + #self._quality_manager.materialsUpdated.connect(self._update) # TODO + + self._update() + + def _update(self): + global_stack = self._machine_manager._global_container_stack + + quality_group_dict = self._quality_manager.getQualityGroups(global_stack) + quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(global_stack) + + available_quality_types = set(qt for qt, qg in quality_group_dict.items() if qg.is_available) + if not available_quality_types and not quality_changes_group_dict: + # Nothing to show + self.setItems([]) + return + + item_list = [] + # Create quality group items + for quality_group in quality_group_dict.values(): + if not quality_group.is_available: + continue + + item = {"name": quality_group.name, + "is_read_only": True, + "quality_group": quality_group, + "quality_changes_group": None} + item_list.append(item) + # Sort by quality names + item_list = sorted(item_list, key = lambda x: x["name"]) + + # Create quality_changes group items + quality_changes_item_list = [] + for quality_changes_group in quality_changes_group_dict.values(): + if quality_changes_group.quality_type not in available_quality_types: + continue + quality_group = quality_group_dict[quality_changes_group.quality_type] + item = {"name": quality_changes_group.name, + "is_read_only": False, + "quality_group": quality_group, + "quality_changes_group": quality_changes_group} + quality_changes_item_list.append(item) + + # Sort quality_changes items by names and append to the item list + quality_changes_item_list = sorted(quality_changes_item_list, key = lambda x: x["name"]) + item_list += quality_changes_item_list + + self.setItems(item_list) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index f0fd0168a6..53b85a1dca 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -1,10 +1,9 @@ from typing import Optional -from PyQt5.Qt import QObject +from PyQt5.QtCore import QObject, QTimer from UM.Application import Application from UM.Logger import Logger -from UM.Util import parseBool from cura.Machines.ContainerGroup import ContainerGroup from cura.Machines.ContainerNode import ContainerNode @@ -126,6 +125,15 @@ class QualityManager(QObject): self._default_machine_definition_id = "fdmprinter" + self._container_registry.containerMetaDataChanged.connect(self._onContainerMetadataChanged) + self._container_registry.containerAdded.connect(self._onContainerMetadataChanged) + self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged) + + self._update_timer = QTimer(self) + self._update_timer.setInterval(300) + self._update_timer.setSingleShot(True) + self._update_timer.timeout.connect(self._updateMaps) + def initialize(self): # Initialize the lookup tree for quality profiles with following structure: # -> -> @@ -186,10 +194,6 @@ class QualityManager(QObject): material_node.addQualityMetadata(quality_type, metadata) - # Initialize quality - self._initializeQualityChangesTables() - - def _initializeQualityChangesTables(self): # Initialize the lookup tree for quality_changes profiles with following structure: # -> -> quality_changes_metadata_list = self._container_registry.findContainersMetadata(type = "quality_changes") @@ -206,6 +210,20 @@ class QualityManager(QObject): machine_node.addQualityChangesMetadata(quality_type, metadata) + def _updateMaps(self): + self.initialize() + + def _onContainerMetadataChanged(self, container): + self._onContainerChanged(container) + + def _onContainerChanged(self, container): + container_type = container.getMetaDataEntry("type") + if container_type not in ("quality", "quality_changes"): + return + + # update the cache table + self._update_timer.start() + # Updates the given quality groups' availabilities according to which extruders are being used/ enabled. def _updateQualityGroupsAvailability(self, machine: "GlobalStack", quality_group_list): used_extruders = set() @@ -234,8 +252,8 @@ class QualityManager(QObject): machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id) if not machine_node: - Logger.log("e", "Cannot find node for machine def [%s] in QualityChanges lookup table", machine_definition_id) - return {} + Logger.log("i", "Cannot find node for machine def [%s] in QualityChanges lookup table", machine_definition_id) + return dict() # Update availability for each QualityChangesGroup: # A custom profile is always available as long as the quality_type it's based on is available diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 89106f9bda..8f66f92f1c 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -12,7 +12,6 @@ from UM.Signal import Signal from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer import UM.FlameProfiler from UM.FlameProfiler import pyqtSlot -from PyQt5.QtWidgets import QMessageBox from UM import Util from UM.Application import Application @@ -1371,27 +1370,6 @@ class MachineManager(QObject): self._current_root_material_id[position] = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") return self._current_root_material_id - def _setQualityChangesGroup(self, quality_changes_group): - self._current_quality_changes_group = quality_changes_group - - # TODO: quality_changes groups depend on a quality_type. Here it's fetching the quality_types every time. - # Can we do this better, like caching the quality group a quality_changes group depends on? - quality_manager = Application.getInstance()._quality_manager - quality_group_dict = quality_manager.getQualityGroups(self._global_container_stack) - - quality_type = quality_changes_group.quality_type - - container = self._empty_quality_changes_container - if quality_changes_group.node_for_global is not None: - container = quality_changes_group.node_for_global.getContainer() - self._global_container_stack.qualityChanges = container - self._global_container_stack.quality = quality_group_dict[quality_type] - - for position, extruder in self._global_container_stack.extruders.items(): - container = quality_changes_group.nodes_for_extruders.get(position, - self._empty_quality_changes_container) - extruder.qualityChanges = container - def _setEmptyQuality(self): self._current_quality_group = None self._global_container_stack.quality = self._empty_quality_container @@ -1405,8 +1383,6 @@ class MachineManager(QObject): def _setQualityGroup(self, quality_group, empty_quality_changes = True): self._current_quality_group = quality_group - #TODO: check quality_changes - # Set quality and quality_changes for the GlobalStack self._global_container_stack.quality = quality_group.node_for_global.getContainer() if empty_quality_changes: @@ -1419,6 +1395,44 @@ class MachineManager(QObject): self._global_container_stack.extruders[position].qualityChanges = self._empty_quality_changes_container self.activeQualityGroupChanged.emit() + self.activeQualityChangesGroupChanged.emit() + + def _setQualityChangesGroup(self, quality_changes_group): + # TODO: quality_changes groups depend on a quality_type. Here it's fetching the quality_types every time. + # Can we do this better, like caching the quality group a quality_changes group depends on? + quality_type = quality_changes_group.quality_type + quality_manager = Application.getInstance()._quality_manager + quality_group_dict = quality_manager.getQualityGroups(self._global_container_stack) + quality_group = quality_group_dict[quality_type] + + quality_changes_container = self._empty_quality_changes_container + quality_container = self._empty_quality_changes_container + if quality_changes_group.node_for_global: + quality_changes_container = quality_changes_group.node_for_global.getContainer() + if quality_group.node_for_global: + quality_container = quality_group.node_for_global.getContainer() + + self._global_container_stack.quality = quality_container + self._global_container_stack.qualityChanges = quality_changes_container + + for position, extruder in self._global_container_stack.extruders.items(): + quality_changes_node = quality_changes_group.nodes_for_extruders.get(position) + quality_node = quality_group.nodes_for_extruders.get(position) + + quality_changes_container = self._empty_quality_changes_container + quality_container = self._empty_quality_changes_container + if quality_changes_node: + quality_changes_container = quality_changes_node.getContainer() + if quality_node: + quality_container = quality_node.getContainer() + + extruder.quality = quality_container + extruder.qualityChanges = quality_changes_container + + self._current_quality_group = quality_group + self._current_quality_changes_group = quality_changes_group + self.activeQualityGroupChanged.emit() + self.activeQualityChangesGroupChanged.emit() def _setVariantGroup(self, position, container_node): self._global_container_stack.extruders[position].variant = container_node.getContainer() @@ -1515,3 +1529,23 @@ class MachineManager(QObject): def activeQualityGroup(self): return self._current_quality_group + @pyqtSlot("QVariant") + def setQualityChangesGroup(self, quality_changes_group): + Logger.log("d", "---------------- qcg = [%s]", quality_changes_group.name) + self.blurSettings.emit() + with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): + self._setQualityChangesGroup(quality_changes_group) + Logger.log("d", "Quality changes set!") + + @pyqtProperty("QVariant", fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged) + def activeQualityChangesGroup(self): + return self._current_quality_changes_group + + @pyqtProperty(str, notify = activeQualityGroupChanged) + def activeQualityOrQualityChangesName(self): + name = "" + if self._current_quality_changes_group: + name = self._current_quality_changes_group.name + elif self._current_quality_group: + name = self._current_quality_group.name + return name diff --git a/cura/Settings/MaterialsModel.py b/cura/Settings/MaterialsModel.py index 51f9e09be6..72b39a90aa 100644 --- a/cura/Settings/MaterialsModel.py +++ b/cura/Settings/MaterialsModel.py @@ -2,7 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from typing import Any, List, Optional -from PyQt5.QtCore import Qt, QObject +from PyQt5.QtCore import Qt from UM.Logger import Logger from UM.Qt.ListModel import ListModel diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index b05bc46dd5..eaef48e168 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -27,6 +27,7 @@ class NewQualityProfilesModel(ListModel): LayerHeightRole = Qt.UserRole + 4 AvailableRole = Qt.UserRole + 5 QualityGroupRole = Qt.UserRole + 6 + QualityChangesGroupRole = Qt.UserRole + 7 def __init__(self, parent = None): super().__init__(parent) @@ -37,6 +38,7 @@ class NewQualityProfilesModel(ListModel): self.addRoleName(self.LayerHeightRole, "layer_height") self.addRoleName(self.AvailableRole, "available") self.addRoleName(self.QualityGroupRole, "quality_group") + self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") # connect signals Application.getInstance().globalContainerStackChanged.connect(self._update) diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml new file mode 100644 index 0000000000..47446c82c2 --- /dev/null +++ b/resources/qml/Preferences/ProfileTab.qml @@ -0,0 +1,98 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.8 +import QtQuick.Controls 1.4 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Tab +{ + id: base + + property string extruderId: ""; + property string extruderDefinition: ""; + property string quality: ""; + property string material: ""; + + TableView + { + anchors.fill: parent + anchors.margins: UM.Theme.getSize("default_margin").width + + Component + { + id: itemDelegate + + UM.TooltipArea + { + property var setting: qualitySettings.getItem(styleData.row) + height: childrenRect.height + width: (parent != null) ? parent.width : 0 + text: (styleData.value.substr(0,1) == "=") ? styleData.value : "" + + Label + { + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + text: (styleData.value.substr(0,1) == "=") ? catalog.i18nc("@info:status", "Calculated") : styleData.value + font.strikeout: styleData.column == 1 && quality == Cura.MachineManager.globalQualityId && setting.user_value != "" + font.italic: setting.profile_value_source == "quality_changes" || (quality == Cura.MachineManager.globalQualityId && setting.user_value != "") + opacity: font.strikeout ? 0.5 : 1 + color: styleData.textColor + elide: Text.ElideRight + } + } + } + + TableViewColumn + { + role: "label" + title: catalog.i18nc("@title:column", "Setting") + width: (parent.width * 0.4) | 0 + delegate: itemDelegate + } + TableViewColumn + { + role: "profile_value" + title: catalog.i18nc("@title:column", "Profile") + width: (parent.width * 0.18) | 0 + delegate: itemDelegate + } + TableViewColumn + { + role: "user_value" + title: catalog.i18nc("@title:column", "Current"); + visible: quality == Cura.MachineManager.globalQualityId + width: (parent.width * 0.18) | 0 + delegate: itemDelegate + } + TableViewColumn + { + role: "unit" + title: catalog.i18nc("@title:column", "Unit") + width: (parent.width * 0.14) | 0 + delegate: itemDelegate + } + + section.property: "category" + section.delegate: Label + { + text: section + font.bold: true + } + + model: Cura.QualitySettingsModel + { + id: qualitySettings + extruderId: base.extruderId + extruderDefinition: base.extruderDefinition + quality: base.quality != null ? base.quality : "" + material: base.material != null ? base.material : "" + } + + SystemPalette { id: palette } + } +} diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml new file mode 100644 index 0000000000..633e965bd9 --- /dev/null +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -0,0 +1,294 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.8 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +Item +{ + id: base + property var resetEnabled: false // Keep PreferencesDialog happy + + UM.I18nCatalog { id: catalog; name: "cura"; } + + Cura.QualityManagementModel { + id: qualitiesModel + } + + Label { + id: titleLabel + + anchors { + top: parent.top + left: parent.left + right: parent.right + margins: 5 * screenScaleFactor + } + + font.pointSize: 18 + text: catalog.i18nc("@title:tab", "Profiles") + } + + Row // Button Row + { + id: buttonRow + anchors { + left: parent.left + right: parent.right + top: titleLabel.bottom + } + height: childrenRect.height + + // Activate button + Button + { + text: catalog.i18nc("@action:button", "Activate") + iconName: "list-activate" + //enabled: base.currentItem != null ? base.currentItem.id != Cura.MachineManager.activeQualityId : false; + enabled: true // TODO + onClicked: { + // TODO + } + } + + // Create button + Button + { + text: catalog.i18nc("@label", "Create") + iconName: "list-add" + //enabled: base.canCreateProfile() && !Cura.MachineManager.stacksHaveErrors + enabled: true // TODO + //visible: base.canCreateProfile() + visible: true // TODO + + onClicked: { + // TODO + } + } + + // Duplicate button + Button + { + text: catalog.i18nc("@label", "Duplicate") + iconName: "list-add" + //enabled: ! base.canCreateProfile() + enabled: true // TODO + //visible: ! base.canCreateProfile() + visible: true // TODO + + onClicked: { + // TODO + } + } + + // Remove button + Button + { + text: catalog.i18nc("@action:button", "Remove") + iconName: "list-remove" + //enabled: base.currentItem != null ? !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) : false; + enabled: true // TODO + onClicked: { + // TODO + } + } + + // Rename button + Button + { + text: catalog.i18nc("@action:button", "Rename") + iconName: "edit-rename" + //enabled: base.currentItem != null ? !base.currentItem.readOnly : false; + enabled: true // TODO + onClicked: { + // TODO + } + } + + // Import button + Button + { + text: catalog.i18nc("@action:button", "Import") + iconName: "document-import" + onClicked: { + // TODO + } + } + + // Export button + Button + { + text: catalog.i18nc("@action:button", "Export") + iconName: "document-export" + //enabled: currentItem != null && !base.currentItem.readOnly + enabled: true // TODO + onClicked: { + // TODO + } + } + } + + + + Item { + id: contentsItem + + anchors { + top: titleLabel.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + margins: 5 * screenScaleFactor + bottomMargin: 0 + } + + clip: true + } + + Item + { + anchors { + top: buttonRow.bottom + topMargin: UM.Theme.getSize("default_margin").height + left: parent.left + right: parent.right + bottom: parent.bottom + } + + SystemPalette { id: palette } + + Label + { + id: captionLabel + anchors { + top: parent.top + left: parent.left + } + visible: text != "" + text: { + // OLD STUFF + return catalog.i18nc("@label %1 is printer name", "Printer: %1").arg(Cura.MachineManager.activeMachineName); + } + width: profileScrollView.width + elide: Text.ElideRight + } + + ScrollView + { + id: profileScrollView + anchors { + top: captionLabel.visible ? captionLabel.bottom : parent.top + topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0 + bottom: parent.bottom + left: parent.left + } + + Rectangle { + parent: viewport + anchors.fill: parent + color: palette.light + } + + width: true ? (parent.width * 0.4) | 0 : parent.width + + ListView + { + id: qualityListView + + model: qualitiesModel + + section.property: "is_read_only" + section.delegate: Rectangle + { + height: childrenRect.height + + Label + { + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_lining").width + text: section == "true" ? catalog.i18nc("@label", "Protected profiles") : catalog.i18nc("@label", "Custom profiles") + font.bold: true + } + } + + delegate: Rectangle + { + width: profileScrollView.width + height: childrenRect.height + color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase + + Row + { + spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + Label + { + width: Math.floor((parent.width * 0.3)) + text: model.name + elide: Text.ElideRight + font.italic: { // TODO: make it easier + return model.name == Cura.MachineManager.activeQualityOrQualityChangesName; + } + color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; + } + } + + MouseArea + { + anchors.fill: parent + onClicked: { + parent.ListView.view.currentIndex = model.index; + } + } + } + + onCurrentIndexChanged: + { + var model = qualitiesModel.getItem(currentIndex); + // TODO + } + } + } + + + Item + { + id: detailsPanel + + anchors { + left: profileScrollView.right + leftMargin: UM.Theme.getSize("default_margin").width + top: parent.top + bottom: parent.bottom + right: parent.right + } + + Item + { + anchors.fill: parent + + Item // Profile title Label + { + id: profileName + + width: parent.width + height: childrenRect.height + + Label { + text: "TODO" // TODO + font: UM.Theme.getFont("large") + } + } + + } + } + } +} From 720dd70935e7c1079566d3a386f04501e551d95a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 17:01:57 +0100 Subject: [PATCH 086/371] WIP: Cleanup MachineManager --- cura/Settings/MachineManager.py | 112 +------------------------------- 1 file changed, 3 insertions(+), 109 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 8f66f92f1c..d3480b503b 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -333,16 +333,6 @@ class MachineManager(QObject): Logger.log("d", "Checking %s stacks for errors took %.2f s" % (count, time.time() - time_start)) return False - ## Remove all instances from the top instanceContainer (effectively removing all user-changed settings) - @pyqtSlot() - def clearUserSettings(self) -> None: - if not self._active_container_stack: - return - - self.blurSettings.emit() - user_settings = self._active_container_stack.getTop() - user_settings.clear() - ## Check if the global_container has instances in the user container @pyqtProperty(bool, notify = activeStackValueChanged) def hasUserSettings(self) -> bool: @@ -484,21 +474,6 @@ class MachineManager(QObject): return "" - @pyqtProperty("QVariantMap", notify = activeVariantChanged) - def allActiveVariantIds(self) -> Dict[str, str]: - result = {} - - active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - if active_stacks is not None: #If we have a global stack. - for stack in active_stacks: - variant_container = stack.variant - if not variant_container: - continue - - result[stack.getId()] = variant_container.getId() - - return result - ## Gets a dict with the active materials ids set in all extruder stacks and the global stack # (when there is one extruder, the material is set in the global stack) # @@ -622,21 +597,6 @@ class MachineManager(QObject): return False return True - ## Get the Quality ID associated with the currently active extruder - # Note that this only returns the "quality", not the "quality_changes" - # \returns QualityID (string) if found, empty string otherwise - # \sa activeQualityId() - # \todo Ideally, this method would be named activeQualityId(), and the other one - # would be named something like activeQualityOrQualityChanges() for consistency - @pyqtProperty(str, notify = activeQualityChanged) - def activeQualityContainerId(self) -> str: - # We're using the active stack instead of the global stack in case the list of qualities differs per extruder - if self._global_container_stack: - quality = self._active_container_stack.quality - if quality: - return quality.getId() - return "" - @pyqtProperty(str, notify = activeQualityChanged) def activeQualityChangesId(self) -> str: if self._active_container_stack: @@ -748,6 +708,7 @@ class MachineManager(QObject): self.setActiveQuality(new_quality_id, always_discard_changes = always_discard_changes) + # TODO: refactor this @pyqtSlot(str) def setActiveVariantBuildplate(self, variant_buildplate_id: str): with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): @@ -843,7 +804,6 @@ class MachineManager(QObject): # before the user decided to keep or discard any of their changes using the dialog. # The Application.onDiscardOrKeepProfileChangesClosed signal triggers this method. def _executeDelayedActiveContainerStackChanges(self): - Logger.log("d", "Applying configuration changes...") if self._new_variant_container is not None: @@ -1032,15 +992,6 @@ class MachineManager(QObject): return "" - @pyqtProperty(str, notify = activeVariantChanged) - def activeVariantName(self) -> str: - if self._active_container_stack: - variant = self._active_container_stack.variant - if variant: - return variant.getName() - - return "" - @pyqtProperty(str, notify = activeVariantChanged) def activeVariantBuildplateName(self) -> str: if self._global_container_stack: @@ -1080,25 +1031,6 @@ class MachineManager(QObject): def getQualityDefinitionId(self, definition: "DefinitionContainer") -> str: return QualityManager.getInstance().getParentMachineDefinition(definition).getId() - ## Get the Variant ID to use to select quality profiles for the currently active variant - # \returns VariantID (string) if found, empty string otherwise - # \sa getQualityVariantId - @pyqtProperty(str, notify = activeVariantChanged) - def activeQualityVariantId(self) -> str: - if self._active_container_stack: - variant = self._active_container_stack.variant - if variant: - return self.getQualityVariantId(self._global_container_stack.definition, variant) - return "" - - @pyqtProperty(str, notify = activeVariantChanged) - def activeQualityVariantName(self) -> str: - if self._active_container_stack: - variant = self._active_container_stack.variant - if variant.getId() != "empty_variant": - return variant.getName() - return "" - ## Get the Variant ID to use to select quality profiles for variants of the specified definitions # This is normally the id of the variant itself, but machines can specify a different definition # to inherit qualities from, which has consequences for the variant to use as well @@ -1307,44 +1239,6 @@ class MachineManager(QObject): return self._global_container_stack.extruders.get(str(position)) return None - @deprecated("Use ExtruderStack.material = ... and it won't be necessary", "2.7") - def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None) -> InstanceContainer: - if not definition.getMetaDataEntry("has_materials"): - return self._empty_material_container - - approximate_material_diameter = str(round(stack.getProperty("material_diameter", "value"))) - search_criteria = { "type": "material", "approximate_diameter": approximate_material_diameter } - - if definition.getMetaDataEntry("has_machine_materials"): - search_criteria["definition"] = self.getQualityDefinitionId(definition) - - if definition.getMetaDataEntry("has_variants") and variant_container: - search_criteria["variant"] = self.getQualityVariantId(definition, variant_container) - else: - search_criteria["definition"] = "fdmprinter" - - if preferred_material_name: - search_criteria["name"] = preferred_material_name - else: - preferred_material = definition.getMetaDataEntry("preferred_material") - if preferred_material: - search_criteria["id"] = preferred_material - - containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) - if containers: - return containers[0] - - if "variant" in search_criteria or "id" in search_criteria: - # If a material by this name can not be found, try a wider set of search criteria - search_criteria.pop("variant", None) - search_criteria.pop("id", None) - - containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) - if containers: - return containers[0] - Logger.log("w", "Unable to find a material container with provided criteria, returning an empty one instead.") - return self._empty_material_container - def _onMachineNameChanged(self): self.globalContainerChanged.emit() @@ -1434,7 +1328,7 @@ class MachineManager(QObject): self.activeQualityGroupChanged.emit() self.activeQualityChangesGroupChanged.emit() - def _setVariantGroup(self, position, container_node): + def _setVariantNode(self, position, container_node): self._global_container_stack.extruders[position].variant = container_node.getContainer() def _setMaterial(self, position, container_node = None): @@ -1511,7 +1405,7 @@ class MachineManager(QObject): position = str(position) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): - self._setVariantGroup(position, container_node) + self._setVariantNode(position, container_node) current_variant_name = container_node.metadata["name"] current_material_base_name = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") self._updateMaterialWithVariant(position, current_material_base_name, current_variant_name) From e0f82fb5c6ecea6f71cd2fad885292077d661fe5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 16 Feb 2018 17:02:24 +0100 Subject: [PATCH 087/371] WIP: Fix MaterialsManager getAvailableMaterials() --- cura/Machines/MaterialManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 84f08a3b27..b52bd7dca2 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -245,7 +245,7 @@ class MaterialManager(QObject): material_id_metadata_dict = dict() for node in nodes_to_check: if node is not None: - material_id_metadata_dict = {mid: node for mid, node in variant_node.material_map.items()} + material_id_metadata_dict = {mid: node for mid, node in node.material_map.items()} break return material_id_metadata_dict From 1a19175b35a59fbe86c9238bc06409700ebdd97d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 13:36:25 +0100 Subject: [PATCH 088/371] WIP: Fix quality sliderbar --- cura/Settings/ProfilesModel.py | 7 ++++--- resources/qml/Menus/ProfileMenu.qml | 2 +- resources/qml/SidebarSimple.qml | 24 ++++++++++++++---------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index eaef48e168..719eaf0869 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -67,6 +67,7 @@ class NewQualityProfilesModel(ListModel): item = {"id": "TODO", # TODO: probably will be removed "name": quality_group.name, + "quality_type": quality_group.quality_type, "layer_height": layer_height + self._layer_height_unit, "layer_height_without_unit": layer_height, "available": quality_group.is_available, @@ -74,6 +75,9 @@ class NewQualityProfilesModel(ListModel): item_list.append(item) + # Sort items based on layer_height + item_list = sorted(item_list, key = lambda x: float(x["layer_height_without_unit"])) + self.setItems(item_list) def _fetchLayerHeight(self, quality_group: "QualityGroup"): @@ -84,9 +88,6 @@ class NewQualityProfilesModel(ListModel): unit = "" self._layer_height_unit = unit - if not quality_group.is_available: - return "" - # Get layer_height from the quality profile for the GlobalStack container = quality_group.node_for_global.getContainer() diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index 6005ce9805..713b4b856e 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -34,7 +34,7 @@ Menu MenuSeparator { id: customSeparator - visible: Cura.UserProfilesModel.rowCount > 0 + visible: Cura.NewCustomQualityProfilesModel.rowCount > 0 } Instantiator diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index ae9fe57b64..33aa98ba9f 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -57,7 +57,10 @@ Item interval: 50 running: false repeat: false - onTriggered: Cura.MachineManager.setActiveQuality(Cura.ProfilesModel.getItem(qualitySlider.value).id) + onTriggered: { + var item = Cura.NewQualityProfilesModel.getItem(qualitySlider.value); + Cura.MachineManager.activeQualityGroup = item.quality_group; + } } Component.onCompleted: qualityModel.update() @@ -102,14 +105,14 @@ Item var availableMin = -1 var availableMax = -1 - for (var i = 0; i < Cura.ProfilesModel.rowCount(); i++) { - var qualityItem = Cura.ProfilesModel.getItem(i) + for (var i = 0; i < Cura.NewQualityProfilesModel.rowCount(); i++) { + var qualityItem = Cura.NewQualityProfilesModel.getItem(i) // Add each quality item to the UI quality model qualityModel.append(qualityItem) // Set selected value - if (Cura.MachineManager.activeQualityType == qualityItem.metadata.quality_type) { + if (Cura.MachineManager.activeQualityType == qualityItem.quality_type) { // set to -1 when switching to user created profile so all ticks are clickable if (Cura.SimpleModeSettingsManager.isProfileUserCreated) { @@ -165,7 +168,7 @@ Item qualityModel.existingQualityProfile = 0 // check, the ticks count cannot be less than zero - qualityModel.totalTicks = Math.max(0, Cura.ProfilesModel.rowCount() - 1) + qualityModel.totalTicks = Math.max(0, Cura.NewQualityProfilesModel.rowCount() - 1) } } @@ -191,13 +194,13 @@ Item anchors.verticalCenter: parent.verticalCenter anchors.top: parent.top anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) - color: (Cura.MachineManager.activeMachine != null && Cura.ProfilesModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + color: (Cura.MachineManager.activeMachine != null && Cura.NewQualityProfilesModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") text: { var result = "" if(Cura.MachineManager.activeMachine != null) { - result = Cura.ProfilesModel.getItem(index).layer_height_without_unit + result = Cura.NewQualityProfilesModel.getItem(index).layer_height_without_unit if(result == undefined) { @@ -262,7 +265,7 @@ Item Rectangle { anchors.verticalCenter: parent.verticalCenter - color: Cura.ProfilesModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + color: Cura.NewQualityProfilesModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") width: 1 * screenScaleFactor height: 6 * screenScaleFactor y: 0 @@ -408,9 +411,10 @@ Item // if the current profile is user-created, switch to a built-in quality if (Cura.SimpleModeSettingsManager.isProfileUserCreated) { - if (Cura.ProfilesModel.rowCount() > 0) + if (Cura.NewQualityProfilesModel.rowCount() > 0) { - Cura.MachineManager.setActiveQuality(Cura.ProfilesModel.getItem(0).id) + var item = Cura.NewQualityProfilesModel.getItem(0); + Cura.MachineManager.activeQualityGroup = item.quality_group; } } if (Cura.SimpleModeSettingsManager.isProfileCustomized) From 2cfdbc1b164eafc410f260ca39b945dfe587c8a8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 14:10:01 +0100 Subject: [PATCH 089/371] WIP: Remove old quality models --- cura/CuraApplication.py | 7 +- cura/Settings/MachineManager.py | 12 -- cura/Settings/ProfilesModel.py | 204 ------------------- cura/Settings/QualityAndUserProfilesModel.py | 54 ----- cura/Settings/UserProfilesModel.py | 85 -------- 5 files changed, 1 insertion(+), 361 deletions(-) delete mode 100644 cura/Settings/QualityAndUserProfilesModel.py delete mode 100644 cura/Settings/UserProfilesModel.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 3b15069598..ee94050515 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -53,11 +53,9 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator from cura.Machines.Models.NozzleModel import NozzleModel -from cura.Settings.ProfilesModel import ProfilesModel, NewQualityProfilesModel, NewCustomQualityProfilesModel +from cura.Settings.ProfilesModel import NewQualityProfilesModel, NewCustomQualityProfilesModel from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel, NewMaterialsModel -from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager -from cura.Settings.UserProfilesModel import UserProfilesModel from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager from cura.Machines.VariantManager import VariantManager @@ -934,7 +932,6 @@ class CuraApplication(QtApplication): qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer") qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") - qmlRegisterSingletonType(ProfilesModel, "Cura", 1, 0, "ProfilesModel", ProfilesModel.createProfilesModel) qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") @@ -948,8 +945,6 @@ class CuraApplication(QtApplication): qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") - qmlRegisterType(QualityAndUserProfilesModel, "Cura", 1, 0, "QualityAndUserProfilesModel") - qmlRegisterType(UserProfilesModel, "Cura", 1, 0, "UserProfilesModel") qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index d3480b503b..e53145ee87 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -18,10 +18,8 @@ from UM.Application import Application from UM.Preferences import Preferences from UM.Logger import Logger from UM.Message import Message -from UM.Decorators import deprecated from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.ContainerStack import ContainerStack from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.SettingFunction import SettingFunction from UM.Signal import postponeSignals, CompressTechnique @@ -36,8 +34,6 @@ from .CuraStackBuilder import CuraStackBuilder from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") -from cura.Settings.ProfilesModel import ProfilesModel - if TYPE_CHECKING: from UM.Settings.DefinitionContainer import DefinitionContainer from cura.Settings.CuraContainerStack import CuraContainerStack @@ -72,7 +68,6 @@ class MachineManager(QObject): Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) Application.getInstance().getContainerRegistry().containerLoadComplete.connect(self._onInstanceContainersChanged) - self._connected_to_profiles_model = False ## When the global container is changed, active material probably needs to be updated. self.globalContainerChanged.connect(self.activeMaterialChanged) @@ -269,13 +264,6 @@ class MachineManager(QObject): self.__emitChangedSignals() def _onInstanceContainersChanged(self, container) -> None: - # This should not trigger the ProfilesModel to be created, or there will be an infinite recursion - if not self._connected_to_profiles_model and ProfilesModel.hasInstance(): - # This triggers updating the qualityModel in SidebarSimple whenever ProfilesModel is updated - Logger.log("d", "Connecting profiles model...") - ProfilesModel.getInstance().itemsChanged.connect(self._onProfilesModelChanged) - self._connected_to_profiles_model = True - self._instance_container_timer.start() def _onPropertyChanged(self, key: str, property_name: str) -> None: diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index 719eaf0869..a6276cdbed 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -131,207 +131,3 @@ class NewCustomQualityProfilesModel(NewQualityProfilesModel): item_list.append(item) self.setItems(item_list) - - -## QML Model for listing the current list of valid quality profiles. -# -class ProfilesModel(InstanceContainersModel): - LayerHeightRole = Qt.UserRole + 1001 - LayerHeightWithoutUnitRole = Qt.UserRole + 1002 - AvailableRole = Qt.UserRole + 1003 - - def __init__(self, parent = None): - super().__init__(parent) - self.addRoleName(self.LayerHeightRole, "layer_height") - self.addRoleName(self.LayerHeightWithoutUnitRole, "layer_height_without_unit") - self.addRoleName(self.AvailableRole, "available") - - Application.getInstance().globalContainerStackChanged.connect(self._update) - Application.getInstance().getMachineManager().activeVariantChanged.connect(self._update) - Application.getInstance().getMachineManager().activeStackChanged.connect(self._update) - Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update) - - self._empty_quality = ContainerRegistry.getInstance().findContainers(id = "empty_quality")[0] - - # Factory function, used by QML - @staticmethod - def createProfilesModel(engine, js_engine): - return ProfilesModel.getInstance() - - ## Get the singleton instance for this class. - @classmethod - def getInstance(cls) -> "ProfilesModel": - # Note: Explicit use of class name to prevent issues with inheritance. - if not ProfilesModel.__instance: - ProfilesModel.__instance = cls() - return ProfilesModel.__instance - - @classmethod - def hasInstance(cls) -> bool: - return ProfilesModel.__instance is not None - - __instance = None # type: "ProfilesModel" - - ## Fetch the list of containers to display. - # - # See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers(). - def _fetchInstanceContainers(self): - global_container_stack = Application.getInstance().getGlobalContainerStack() - if global_container_stack is None: - return {}, {} - global_stack_definition = global_container_stack.definition - - # Get the list of extruders and place the selected extruder at the front of the list. - extruder_stacks = self._getOrderedExtruderStacksList() - materials = [extruder.material for extruder in extruder_stacks] - - # Fetch the list of usable qualities across all extruders. - # The actual list of quality profiles come from the first extruder in the extruder list. - result = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) - - # The usable quality types are set - quality_type_set = set([x.getMetaDataEntry("quality_type") for x in result]) - - # Fetch all qualities available for this machine and the materials selected in extruders - all_qualities = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition, materials) - - # If in the all qualities there is some of them that are not available due to incompatibility with materials - # we also add it so that they will appear in the slide quality bar. However in recomputeItems will be marked as - # not available so they will be shown in gray - for quality in all_qualities: - if quality.getMetaDataEntry("quality_type") not in quality_type_set: - result.append(quality) - - if len(result) > 1 and self._empty_quality in result: - result.remove(self._empty_quality) - - return {item.getId(): item for item in result}, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet. - - ## Re-computes the items in this model, and adds the layer height role. - def _recomputeItems(self): - # Some globals that we can re-use. - global_container_stack = Application.getInstance().getGlobalContainerStack() - if global_container_stack is None: - return - - extruder_stacks = self._getOrderedExtruderStacksList() - container_registry = ContainerRegistry.getInstance() - - # Get a list of usable/available qualities for this machine and material - qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) - - unit = global_container_stack.getBottom().getProperty("layer_height", "unit") - if not unit: - unit = "" - - # group all quality items according to quality_types, so we know which profile suits the currently - # active machine and material, and later yield the right ones. - tmp_all_quality_items = OrderedDict() - for item in super()._recomputeItems(): - profiles = container_registry.findContainersMetadata(id = item["id"]) - if not profiles or "quality_type" not in profiles[0]: - quality_type = "" - else: - quality_type = profiles[0]["quality_type"] - - if quality_type not in tmp_all_quality_items: - tmp_all_quality_items[quality_type] = {"suitable_container": None, "all_containers": []} - - tmp_all_quality_items[quality_type]["all_containers"].append(item) - if tmp_all_quality_items[quality_type]["suitable_container"] is None: - tmp_all_quality_items[quality_type]["suitable_container"] = item - - # reverse the ordering (finest first, coarsest last) - all_quality_items = OrderedDict() - for key in reversed(tmp_all_quality_items.keys()): - all_quality_items[key] = tmp_all_quality_items[key] - - # First the suitable containers are set in the model - containers = [] - for data_item in all_quality_items.values(): - suitable_item = data_item["suitable_container"] - if suitable_item is not None: - containers.append(suitable_item) - - # Once the suitable containers are collected, the rest of the containers are appended - for data_item in all_quality_items.values(): - for item in data_item["all_containers"]: - if item not in containers: - containers.append(item) - - # Now all the containers are set - for item in containers: - profile = container_registry.findContainers(id = item["id"]) - - # When for some reason there is no profile container in the registry - if not profile: - self._setItemLayerHeight(item, "", "") - item["available"] = False - yield item - continue - - profile = profile[0] - - # When there is a profile but it's an empty quality should. It's shown in the list (they are "Not Supported" profiles) - if profile.getId() == "empty_quality": - self._setItemLayerHeight(item, "", "") - item["available"] = True - yield item - continue - - item["available"] = profile in qualities - - # Easy case: This profile defines its own layer height. - if profile.hasProperty("layer_height", "value"): - self._setItemLayerHeight(item, profile.getProperty("layer_height", "value"), unit) - yield item - continue - - machine_manager = Application.getInstance().getMachineManager() - - # Quality-changes profile that has no value for layer height. Get the corresponding quality profile and ask that profile. - quality_type = profile.getMetaDataEntry("quality_type", None) - if quality_type: - quality_results = machine_manager.determineQualityAndQualityChangesForQualityType(quality_type) - for quality_result in quality_results: - if quality_result["stack"] is global_container_stack: - quality = quality_result["quality"] - break - else: - # No global container stack in the results: - if quality_results: - # Take any of the extruders. - quality = quality_results[0]["quality"] - else: - quality = None - if quality and quality.hasProperty("layer_height", "value"): - self._setItemLayerHeight(item, quality.getProperty("layer_height", "value"), unit) - yield item - continue - - # Quality has no value for layer height either. Get the layer height from somewhere lower in the stack. - skip_until_container = global_container_stack.material - if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): # No material in stack. - skip_until_container = global_container_stack.variant - if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): # No variant in stack. - skip_until_container = global_container_stack.getBottom() - self._setItemLayerHeight(item, global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId()), unit) # Fall through to the currently loaded material. - yield item - - ## Get a list of extruder stacks with the active extruder at the front of the list. - @staticmethod - def _getOrderedExtruderStacksList() -> List["ExtruderStack"]: - extruder_manager = ExtruderManager.getInstance() - extruder_stacks = extruder_manager.getActiveExtruderStacks() - active_extruder = extruder_manager.getActiveExtruderStack() - - if active_extruder in extruder_stacks: - extruder_stacks.remove(active_extruder) - extruder_stacks = [active_extruder] + extruder_stacks - - return extruder_stacks - - @staticmethod - def _setItemLayerHeight(item, value, unit): - item["layer_height"] = str(value) + unit - item["layer_height_without_unit"] = str(value) diff --git a/cura/Settings/QualityAndUserProfilesModel.py b/cura/Settings/QualityAndUserProfilesModel.py deleted file mode 100644 index 645e63acdb..0000000000 --- a/cura/Settings/QualityAndUserProfilesModel.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2016 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. -from UM.Application import Application -from UM.Settings.ContainerRegistry import ContainerRegistry - -from cura.QualityManager import QualityManager -from cura.Settings.ProfilesModel import ProfilesModel -from cura.Settings.ExtruderManager import ExtruderManager - - -## QML Model for listing the current list of valid quality and quality changes profiles. -# -class QualityAndUserProfilesModel(ProfilesModel): - def __init__(self, parent = None): - super().__init__(parent) - - self._empty_quality = ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0] - - ## Fetch the list of containers to display. - # - # See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers(). - def _fetchInstanceContainers(self): - global_container_stack = Application.getInstance().getGlobalContainerStack() - if not global_container_stack: - return {}, {} - - # Fetch the list of quality changes. - quality_manager = QualityManager.getInstance() - machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition) - quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) - - extruder_manager = ExtruderManager.getInstance() - active_extruder = extruder_manager.getActiveExtruderStack() - extruder_stacks = self._getOrderedExtruderStacksList() - - # Fetch the list of usable qualities across all extruders. - # The actual list of quality profiles come from the first extruder in the extruder list. - quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) - - # Filter the quality_change by the list of available quality_types - quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) - # Also show custom profiles based on "Not Supported" quality profile - quality_type_set.add(self._empty_quality.getMetaDataEntry("quality_type")) - filtered_quality_changes = {qc.getId(): qc for qc in quality_changes_list if - qc.getMetaDataEntry("quality_type") in quality_type_set and - qc.getMetaDataEntry("extruder") is not None and - (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or - qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())} - - result = filtered_quality_changes - for q in quality_list: - if q.getId() != "empty_quality": - result[q.getId()] = q - return result, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet. diff --git a/cura/Settings/UserProfilesModel.py b/cura/Settings/UserProfilesModel.py deleted file mode 100644 index 6605f52f8a..0000000000 --- a/cura/Settings/UserProfilesModel.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2017 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from UM.Application import Application -from UM.Settings.ContainerRegistry import ContainerRegistry - -from cura.QualityManager import QualityManager -from cura.Settings.ProfilesModel import ProfilesModel -from cura.Settings.ExtruderManager import ExtruderManager - -## QML Model for listing the current list of valid quality changes profiles. -# -class UserProfilesModel(ProfilesModel): - def __init__(self, parent = None): - super().__init__(parent) - - #Need to connect to the metaDataChanged signal of the active materials. - self.__current_extruders = [] - self.__current_materials = [] - - Application.getInstance().getExtruderManager().extrudersChanged.connect(self.__onExtrudersChanged) - self.__onExtrudersChanged() - self.__current_materials = [extruder.material for extruder in self.__current_extruders] - for material in self.__current_materials: - material.metaDataChanged.connect(self._onContainerChanged) - - self._empty_quality = ContainerRegistry.getInstance().findContainers(id = "empty_quality")[0] - - ## Fetch the list of containers to display. - # - # See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers(). - def _fetchInstanceContainers(self): - global_container_stack = Application.getInstance().getGlobalContainerStack() - if not global_container_stack: - return {}, {} - - # Fetch the list of quality changes. - quality_manager = QualityManager.getInstance() - machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition) - quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) - - extruder_manager = ExtruderManager.getInstance() - active_extruder = extruder_manager.getActiveExtruderStack() - extruder_stacks = self._getOrderedExtruderStacksList() - - # Fetch the list of usable qualities across all extruders. - # The actual list of quality profiles come from the first extruder in the extruder list. - quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) - - # Filter the quality_change by the list of available quality_types - quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) - quality_type_set.add(self._empty_quality.getMetaDataEntry("quality_type")) - - filtered_quality_changes = {qc.getId():qc for qc in quality_changes_list if - qc.getMetaDataEntry("quality_type") in quality_type_set and - qc.getMetaDataEntry("extruder") is not None and - (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or - qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())} - - return filtered_quality_changes, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet. - - ## Called when a container changed on an extruder stack. - # - # If it's the material we need to connect to the metaDataChanged signal of - # that. - def __onContainerChanged(self, new_container): - #Careful not to update when a quality or quality changes profile changed! - #If you then update you're going to have an infinite recursion because the update may change the container. - if new_container.getMetaDataEntry("type") == "material": - for material in self.__current_materials: - material.metaDataChanged.disconnect(self._onContainerChanged) - self.__current_materials = [extruder.material for extruder in self.__current_extruders] - for material in self.__current_materials: - material.metaDataChanged.connect(self._onContainerChanged) - - ## Called when the current set of extruders change. - # - # This makes sure that we are listening to the signal for when the - # materials change. - def __onExtrudersChanged(self): - for extruder in self.__current_extruders: - extruder.containersChanged.disconnect(self.__onContainerChanged) - self.__current_extruders = Application.getInstance().getExtruderManager().getExtruderStacks() - for extruder in self.__current_extruders: - extruder.containersChanged.connect(self.__onContainerChanged) \ No newline at end of file From b449f39cc74e722e1d6db17ebf3721cd8ce49c5a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 14:39:47 +0100 Subject: [PATCH 090/371] WIP: Do not profiles submenu for each Extruder You cannot change quality for an individual Extruder, so it doesn't make sense to show that for each Extruder. --- resources/qml/Cura.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index f474d93900..4a75f76e8b 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -194,7 +194,6 @@ UM.MainWindow NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index } MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials; extruderIndex: index } - ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); } MenuSeparator { } @@ -207,7 +206,7 @@ UM.MainWindow BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: Cura.MachineManager.hasVariantBuildplates } NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasVariants } MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasMaterials } - ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); visible: machineExtruderCount.properties.value <= 1 } + ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); } MenuSeparator { } From 9dce0afaea3b4a8b53b7657b3578890af2c604d4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 14:44:39 +0100 Subject: [PATCH 091/371] WIP: Fix extruder submenu --- resources/qml/Cura.qml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 4a75f76e8b..9dbbb80904 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -190,22 +190,24 @@ UM.MainWindow model: Cura.ExtrudersModel { simpleNames: true } Menu { title: model.name - visible: machineExtruderCount.properties.value > 1 NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index } MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials; extruderIndex: index } - MenuSeparator { } + MenuSeparator { + visible: Cura.MachineManager.hasVariants || Cura.MachineManager.hasMaterials + } - MenuItem { text: catalog.i18nc("@action:inmenu", "Set as Active Extruder"); onTriggered: Cura.ExtruderManager.setActiveExtruderIndex(model.index) } + MenuItem { + text: catalog.i18nc("@action:inmenu", "Set as Active Extruder") + onTriggered: Cura.ExtruderManager.setActiveExtruderIndex(model.index) + } } onObjectAdded: settingsMenu.insertItem(index, object) onObjectRemoved: settingsMenu.removeItem(object) } BuildplateMenu { title: catalog.i18nc("@title:menu", "&Build plate"); visible: Cura.MachineManager.hasVariantBuildplates } - NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasVariants } - MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: machineExtruderCount.properties.value <= 1 && Cura.MachineManager.hasMaterials } ProfileMenu { title: catalog.i18nc("@title:menu", "&Profile"); } MenuSeparator { } From 171a05ae6add981719911f86b789e335c256f91b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 14:48:09 +0100 Subject: [PATCH 092/371] WIP: Fix layer_height fetching that inherits the default Fix layer height fetching for those quality profiles that inherits the layer height from the definition. --- cura/Settings/ProfilesModel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index a6276cdbed..06b5679d9e 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -88,10 +88,12 @@ class NewQualityProfilesModel(ListModel): unit = "" self._layer_height_unit = unit + default_layer_height = active_global_stack.definition.getProperty("layer_height", "value") + # Get layer_height from the quality profile for the GlobalStack container = quality_group.node_for_global.getContainer() - layer_height = "" + layer_height = default_layer_height if container.hasProperty("layer_height", "value"): layer_height = str(container.getProperty("layer_height", "value")) else: From 19eb37e6123016a563c835694158e5ca1b2865b4 Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 17 Feb 2018 14:53:07 +0100 Subject: [PATCH 093/371] Update AboutDialog.qml --- resources/qml/AboutDialog.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/AboutDialog.qml b/resources/qml/AboutDialog.qml index 30e540e80a..771b55f13f 100644 --- a/resources/qml/AboutDialog.qml +++ b/resources/qml/AboutDialog.qml @@ -136,6 +136,7 @@ UM.Dialog projectsModel.append({ name:"Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" }); projectsModel.append({ name:"Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" }); + projectsModel.append({ name:"AppImageKit", description: catalog.i18nc("@label", "AppImageKit"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" }); } } } From c84ba800d30a0c2e6d6afb404877d8d87689f12f Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 17 Feb 2018 14:58:25 +0100 Subject: [PATCH 094/371] Update AboutDialog.qml --- resources/qml/AboutDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/AboutDialog.qml b/resources/qml/AboutDialog.qml index 771b55f13f..5d3b1d1544 100644 --- a/resources/qml/AboutDialog.qml +++ b/resources/qml/AboutDialog.qml @@ -136,7 +136,7 @@ UM.Dialog projectsModel.append({ name:"Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" }); projectsModel.append({ name:"Font-Awesome-SVG-PNG", description: catalog.i18nc("@label", "SVG icons"), license: "SIL OFL 1.1", url: "https://github.com/encharm/Font-Awesome-SVG-PNG" }); - projectsModel.append({ name:"AppImageKit", description: catalog.i18nc("@label", "AppImageKit"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" }); + projectsModel.append({ name:"AppImageKit", description: catalog.i18nc("@label", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" }); } } } From 236bd09d083c7b0fa4400fb26905c9c802913cff Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 14:58:56 +0100 Subject: [PATCH 095/371] WIP: Refactor quality model files --- cura/CuraApplication.py | 29 ++- .../Models/CustomQualityProfilesModel.py | 36 +++ cura/Machines/Models/NozzleModel.py | 3 + .../Machines/Models/QualityManagementModel.py | 3 +- .../Models/QualityProfilesModel.py} | 233 ++++++++---------- resources/qml/Menus/ProfileMenu.qml | 12 +- resources/qml/SidebarSimple.qml | 22 +- 7 files changed, 172 insertions(+), 166 deletions(-) create mode 100644 cura/Machines/Models/CustomQualityProfilesModel.py rename cura/{Settings/ProfilesModel.py => Machines/Models/QualityProfilesModel.py} (68%) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index ee94050515..395d6655cb 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -52,8 +52,11 @@ from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyT from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator + from cura.Machines.Models.NozzleModel import NozzleModel -from cura.Settings.ProfilesModel import NewQualityProfilesModel, NewCustomQualityProfilesModel +from cura.Machines.Models.QualityProfilesModel import QualityProfilesModel +from cura.Machines.Models.CustomQualityProfilesModel import CustomQualityProfilesModel + from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel, NewMaterialsModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager @@ -390,8 +393,8 @@ class CuraApplication(QtApplication): self.getCuraSceneController().setActiveBuildPlate(0) # Initialize - self._new_quality_profile_model = None - self._new_custom_quality_profile_model = None + self._quality_profile_model = None + self._custom_quality_profile_model = None CuraApplication.Created = True @@ -896,15 +899,15 @@ class CuraApplication(QtApplication): def getPrintInformation(self): return self._print_information - def getNewQualityProfileModel(self, *args, **kwargs): - if self._new_quality_profile_model is None: - self._new_quality_profile_model = NewQualityProfilesModel(self) - return self._new_quality_profile_model + def getQualityProfileModel(self, *args, **kwargs): + if self._quality_profile_model is None: + self._quality_profile_model = QualityProfilesModel(self) + return self._quality_profile_model - def getNewCustomQualityProfilesModel(self, *args, **kwargs): - if self._new_custom_quality_profile_model is None: - self._new_custom_quality_profile_model = NewCustomQualityProfilesModel(self) - return self._new_custom_quality_profile_model + def getCustomQualityProfilesModel(self, *args, **kwargs): + if self._custom_quality_profile_model is None: + self._custom_quality_profile_model = CustomQualityProfilesModel(self) + return self._custom_quality_profile_model ## Registers objects for the QML engine to use. # @@ -940,8 +943,8 @@ class CuraApplication(QtApplication): # TODO: make this singleton? qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") - qmlRegisterSingletonType(NewQualityProfilesModel, "Cura", 1, 0, "NewQualityProfilesModel", self.getNewQualityProfileModel) - qmlRegisterSingletonType(NewCustomQualityProfilesModel, "Cura", 1, 0, "NewCustomQualityProfilesModel", self.getNewCustomQualityProfilesModel) + qmlRegisterSingletonType(QualityProfilesModel, "Cura", 1, 0, "QualityProfilesModel", self.getQualityProfileModel) + qmlRegisterSingletonType(CustomQualityProfilesModel, "Cura", 1, 0, "CustomQualityProfilesModel", self.getCustomQualityProfilesModel) qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") diff --git a/cura/Machines/Models/CustomQualityProfilesModel.py b/cura/Machines/Models/CustomQualityProfilesModel.py new file mode 100644 index 0000000000..8b6fc2deb6 --- /dev/null +++ b/cura/Machines/Models/CustomQualityProfilesModel.py @@ -0,0 +1,36 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.Application import Application +from UM.Logger import Logger + +from cura.Machines.Models.QualityProfilesModel import QualityProfilesModel + + +class CustomQualityProfilesModel(QualityProfilesModel): + + def _update(self): + Logger.log("d", "Updating %s ...", self.__class__.__name__) + + active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + if active_global_stack is None: + self.setItems([]) + Logger.log("d", "No active GlobalStack, set %s as empty.", self.__class__.__name__) + return + + quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(active_global_stack) + + item_list = [] + for key in sorted(quality_changes_group_dict): + quality_changes_group = quality_changes_group_dict[key] + + item = {"id": "TODO", # TODO: probably will be removed + "name": quality_changes_group.name, + "layer_height": "", + "layer_height_without_unit": "", + "available": quality_changes_group.is_available, + "quality_changes_group": quality_changes_group} + + item_list.append(item) + + self.setItems(item_list) diff --git a/cura/Machines/Models/NozzleModel.py b/cura/Machines/Models/NozzleModel.py index 3ad28f3287..271580962a 100644 --- a/cura/Machines/Models/NozzleModel.py +++ b/cura/Machines/Models/NozzleModel.py @@ -1,3 +1,6 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + from PyQt5.QtCore import Qt from UM.Application import Application diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py index fab6a36410..589fec3440 100644 --- a/cura/Machines/Models/QualityManagementModel.py +++ b/cura/Machines/Models/QualityManagementModel.py @@ -1,4 +1,5 @@ - +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. from PyQt5.QtCore import Qt diff --git a/cura/Settings/ProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py similarity index 68% rename from cura/Settings/ProfilesModel.py rename to cura/Machines/Models/QualityProfilesModel.py index 06b5679d9e..19262bf75a 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -1,135 +1,98 @@ -# Copyright (c) 2017 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from collections import OrderedDict -from typing import List, TYPE_CHECKING - -from PyQt5.QtCore import Qt - -from UM.Application import Application -from UM.Logger import Logger -from UM.Qt.ListModel import ListModel -from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel - -from cura.QualityManager import QualityManager -from cura.Settings.ExtruderManager import ExtruderManager -from cura.Machines.QualityManager import QualityGroup - -if TYPE_CHECKING: - from cura.Settings.ExtruderStack import ExtruderStack - - -class NewQualityProfilesModel(ListModel): - IdRole = Qt.UserRole + 1 - NameRole = Qt.UserRole + 2 - QualityTypeRole = Qt.UserRole + 3 - LayerHeightRole = Qt.UserRole + 4 - AvailableRole = Qt.UserRole + 5 - QualityGroupRole = Qt.UserRole + 6 - QualityChangesGroupRole = Qt.UserRole + 7 - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.IdRole, "id") - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.QualityTypeRole, "quality_type") - self.addRoleName(self.LayerHeightRole, "layer_height") - self.addRoleName(self.AvailableRole, "available") - self.addRoleName(self.QualityGroupRole, "quality_group") - self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") - - # connect signals - Application.getInstance().globalContainerStackChanged.connect(self._update) - Application.getInstance().getMachineManager().activeQualityGroupChanged.connect(self._update) - - self._quality_manager = Application.getInstance()._quality_manager - - self._layer_height_unit = "" # This is cached - - def _update(self): - Logger.log("d", "Updating quality profile model ...") - - active_global_stack = Application.getInstance().getMachineManager()._global_container_stack - if active_global_stack is None: - self.setItems([]) - Logger.log("d", "No active GlobalStack, set quality profile model as empty.") - return - - quality_group_dict = self._quality_manager.getQualityGroups(active_global_stack) - - item_list = [] - for key in sorted(quality_group_dict): - quality_group = quality_group_dict[key] - - layer_height = self._fetchLayerHeight(quality_group) - - item = {"id": "TODO", # TODO: probably will be removed - "name": quality_group.name, - "quality_type": quality_group.quality_type, - "layer_height": layer_height + self._layer_height_unit, - "layer_height_without_unit": layer_height, - "available": quality_group.is_available, - "quality_group": quality_group} - - item_list.append(item) - - # Sort items based on layer_height - item_list = sorted(item_list, key = lambda x: float(x["layer_height_without_unit"])) - - self.setItems(item_list) - - def _fetchLayerHeight(self, quality_group: "QualityGroup"): - active_global_stack = Application.getInstance().getMachineManager()._global_container_stack - if not self._layer_height_unit: - unit = active_global_stack.definition.getProperty("layer_height", "unit") - if not unit: - unit = "" - self._layer_height_unit = unit - - default_layer_height = active_global_stack.definition.getProperty("layer_height", "value") - - # Get layer_height from the quality profile for the GlobalStack - container = quality_group.node_for_global.getContainer() - - layer_height = default_layer_height - if container.hasProperty("layer_height", "value"): - layer_height = str(container.getProperty("layer_height", "value")) - else: - # Look for layer_height in the GlobalStack from material -> definition - for idx in range(4): - container = active_global_stack.getContainer(idx) - if container.hasProperty("layer_height", "value"): - layer_height = container.getProperty("layer_height", "value") - break - return str(layer_height) - - -class NewCustomQualityProfilesModel(NewQualityProfilesModel): - - def _update(self): - Logger.log("d", "Updating %s ...", self.__class__.__name__) - - active_global_stack = Application.getInstance().getMachineManager()._global_container_stack - if active_global_stack is None: - self.setItems([]) - Logger.log("d", "No active GlobalStack, set %s as empty.", self.__class__.__name__) - return - - quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(active_global_stack) - - item_list = [] - for key in sorted(quality_changes_group_dict): - quality_changes_group = quality_changes_group_dict[key] - - item = {"id": "TODO", # TODO: probably will be removed - "name": quality_changes_group.name, - "layer_height": "", - "layer_height_without_unit": "", - "available": quality_changes_group.is_available, - "quality_changes_group": quality_changes_group} - - item_list.append(item) - - self.setItems(item_list) +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from PyQt5.QtCore import Qt + +from UM.Application import Application +from UM.Logger import Logger +from UM.Qt.ListModel import ListModel +from cura.Machines.QualityManager import QualityGroup + + +# +# QML Model for all built-in quality profiles. +# +class QualityProfilesModel(ListModel): + IdRole = Qt.UserRole + 1 + NameRole = Qt.UserRole + 2 + QualityTypeRole = Qt.UserRole + 3 + LayerHeightRole = Qt.UserRole + 4 + AvailableRole = Qt.UserRole + 5 + QualityGroupRole = Qt.UserRole + 6 + QualityChangesGroupRole = Qt.UserRole + 7 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.IdRole, "id") + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.QualityTypeRole, "quality_type") + self.addRoleName(self.LayerHeightRole, "layer_height") + self.addRoleName(self.AvailableRole, "available") + self.addRoleName(self.QualityGroupRole, "quality_group") + self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") + + # connect signals + Application.getInstance().globalContainerStackChanged.connect(self._update) + Application.getInstance().getMachineManager().activeQualityGroupChanged.connect(self._update) + + self._quality_manager = Application.getInstance()._quality_manager + + self._layer_height_unit = "" # This is cached + + def _update(self): + Logger.log("d", "Updating quality profile model ...") + + active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + if active_global_stack is None: + self.setItems([]) + Logger.log("d", "No active GlobalStack, set quality profile model as empty.") + return + + quality_group_dict = self._quality_manager.getQualityGroups(active_global_stack) + + item_list = [] + for key in sorted(quality_group_dict): + quality_group = quality_group_dict[key] + + layer_height = self._fetchLayerHeight(quality_group) + + item = {"id": "TODO", # TODO: probably will be removed + "name": quality_group.name, + "quality_type": quality_group.quality_type, + "layer_height": layer_height + self._layer_height_unit, + "layer_height_without_unit": layer_height, + "available": quality_group.is_available, + "quality_group": quality_group} + + item_list.append(item) + + # Sort items based on layer_height + item_list = sorted(item_list, key = lambda x: float(x["layer_height_without_unit"])) + + self.setItems(item_list) + + def _fetchLayerHeight(self, quality_group: "QualityGroup"): + active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + if not self._layer_height_unit: + unit = active_global_stack.definition.getProperty("layer_height", "unit") + if not unit: + unit = "" + self._layer_height_unit = unit + + default_layer_height = active_global_stack.definition.getProperty("layer_height", "value") + + # Get layer_height from the quality profile for the GlobalStack + container = quality_group.node_for_global.getContainer() + + layer_height = default_layer_height + if container.hasProperty("layer_height", "value"): + layer_height = str(container.getProperty("layer_height", "value")) + else: + # Look for layer_height in the GlobalStack from material -> definition + for idx in range(4): + container = active_global_stack.getContainer(idx) + if container.hasProperty("layer_height", "value"): + layer_height = container.getProperty("layer_height", "value") + break + return str(layer_height) diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index 713b4b856e..8d26bfc982 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.8 @@ -13,7 +13,7 @@ Menu Instantiator { - model: Cura.NewQualityProfilesModel + model: Cura.QualityProfilesModel MenuItem { @@ -34,18 +34,18 @@ Menu MenuSeparator { id: customSeparator - visible: Cura.NewCustomQualityProfilesModel.rowCount > 0 + visible: Cura.CustomQualityProfilesModel.rowCount > 0 } Instantiator { id: customProfileInstantiator - model: Cura.NewCustomQualityProfilesModel + model: Cura.CustomQualityProfilesModel Connections { - target: Cura.NewCustomQualityProfilesModel - onModelReset: customSeparator.visible = Cura.NewCustomQualityProfilesModel.rowCount() > 0 + target: Cura.CustomQualityProfilesModel + onModelReset: customSeparator.visible = Cura.CustomQualityProfilesModel.rowCount() > 0 } MenuItem diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 33aa98ba9f..c296a72281 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -1,7 +1,7 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.8 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.3 @@ -58,7 +58,7 @@ Item running: false repeat: false onTriggered: { - var item = Cura.NewQualityProfilesModel.getItem(qualitySlider.value); + var item = Cura.QualityProfilesModel.getItem(qualitySlider.value); Cura.MachineManager.activeQualityGroup = item.quality_group; } } @@ -105,8 +105,8 @@ Item var availableMin = -1 var availableMax = -1 - for (var i = 0; i < Cura.NewQualityProfilesModel.rowCount(); i++) { - var qualityItem = Cura.NewQualityProfilesModel.getItem(i) + for (var i = 0; i < Cura.QualityProfilesModel.rowCount(); i++) { + var qualityItem = Cura.QualityProfilesModel.getItem(i) // Add each quality item to the UI quality model qualityModel.append(qualityItem) @@ -168,7 +168,7 @@ Item qualityModel.existingQualityProfile = 0 // check, the ticks count cannot be less than zero - qualityModel.totalTicks = Math.max(0, Cura.NewQualityProfilesModel.rowCount() - 1) + qualityModel.totalTicks = Math.max(0, Cura.QualityProfilesModel.rowCount() - 1) } } @@ -194,13 +194,13 @@ Item anchors.verticalCenter: parent.verticalCenter anchors.top: parent.top anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) - color: (Cura.MachineManager.activeMachine != null && Cura.NewQualityProfilesModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") text: { var result = "" if(Cura.MachineManager.activeMachine != null) { - result = Cura.NewQualityProfilesModel.getItem(index).layer_height_without_unit + result = Cura.QualityProfilesModel.getItem(index).layer_height_without_unit if(result == undefined) { @@ -265,7 +265,7 @@ Item Rectangle { anchors.verticalCenter: parent.verticalCenter - color: Cura.NewQualityProfilesModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + color: Cura.QualityProfilesModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") width: 1 * screenScaleFactor height: 6 * screenScaleFactor y: 0 @@ -411,9 +411,9 @@ Item // if the current profile is user-created, switch to a built-in quality if (Cura.SimpleModeSettingsManager.isProfileUserCreated) { - if (Cura.NewQualityProfilesModel.rowCount() > 0) + if (Cura.QualityProfilesModel.rowCount() > 0) { - var item = Cura.NewQualityProfilesModel.getItem(0); + var item = Cura.QualityProfilesModel.getItem(0); Cura.MachineManager.activeQualityGroup = item.quality_group; } } From 38502e682964c3831e1da2753acdb69ce50cbbd0 Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 17 Feb 2018 14:59:58 +0100 Subject: [PATCH 096/371] Update cura.pot --- resources/i18n/cura.pot | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/resources/i18n/cura.pot b/resources/i18n/cura.pot index e8148997ce..1620e11d81 100644 --- a/resources/i18n/cura.pot +++ b/resources/i18n/cura.pot @@ -3598,6 +3598,11 @@ msgctxt "@label" msgid "SVG icons" msgstr "" +#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:139 +msgctxt "@label" +msgid "Linux cross-distribution application deployment" +msgstr "" + #: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:41 msgctxt "@label" msgid "Profile:" From e55f2d0355db124256a0e6986ddaeb347e28fad1 Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 17 Feb 2018 15:02:37 +0100 Subject: [PATCH 097/371] Update cura.po --- resources/i18n/de_DE/cura.po | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/resources/i18n/de_DE/cura.po b/resources/i18n/de_DE/cura.po index 9af48a4d06..250e3e5e1b 100644 --- a/resources/i18n/de_DE/cura.po +++ b/resources/i18n/de_DE/cura.po @@ -3485,6 +3485,11 @@ msgctxt "@label" msgid "SVG icons" msgstr "SVG-Symbole" +#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:139 +msgctxt "@label" +msgid "Linux cross-distribution application deployment" +msgstr "Distributionsunabhängiges Format für Linux-Anwendungen" + #: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:41 msgctxt "@label" msgid "Profile:" From 1c8f63e47fe7840905d5c844aba0ce475b011e5d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 15:08:47 +0100 Subject: [PATCH 098/371] WIP: Fix for buildplate --- cura/Machines/Models/NozzleModel.py | 6 +++--- cura/Machines/VariantManager.py | 31 +++++++++++++++++------------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/cura/Machines/Models/NozzleModel.py b/cura/Machines/Models/NozzleModel.py index 271580962a..9d1be393cf 100644 --- a/cura/Machines/Models/NozzleModel.py +++ b/cura/Machines/Models/NozzleModel.py @@ -33,13 +33,13 @@ class NozzleModel(ListModel): self.setItems([]) return - variant_group_dict = variant_manager.getVariantNodes(active_global_stack) - if not variant_group_dict: + variant_node_dict = variant_manager.getVariantNodes(active_global_stack) + if not variant_node_dict: self.setItems([]) return item_list = [] - for hotend_name, container_node in sorted(variant_group_dict.items(), key = lambda i: i[0]): + for hotend_name, container_node in sorted(variant_node_dict.items(), key = lambda i: i[0]): item = {"id": hotend_name, "hotend_name": hotend_name, "container_node": container_node diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py index 555dfec4a3..05ddfe869c 100644 --- a/cura/Machines/VariantManager.py +++ b/cura/Machines/VariantManager.py @@ -1,8 +1,11 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from collections import OrderedDict from typing import Optional from UM.Logger import Logger from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.InstanceContainer import InstanceContainer from cura.Machines.ContainerNode import ContainerNode from cura.Settings.GlobalStack import GlobalStack @@ -35,7 +38,7 @@ class VariantManager: def __init__(self, container_registry): self._container_registry = container_registry # type: ContainerRegistry - self._machine_to_variant_dict_map = {} # -> + self._machine_to_variant_dict_map = dict() # -> self._exclude_variant_id_list = ["empty_variant"] @@ -44,6 +47,8 @@ class VariantManager: # - initializing the variant lookup table based on the metadata in ContainerRegistry. # def initialize(self): + self._machine_to_variant_dict_map = OrderedDict() + # Cache all variants from the container registry to a variant map for better searching and organization. variant_metadata_list = self._container_registry.findContainersMetadata(type = "variant") for variant_metadata in variant_metadata_list: @@ -54,13 +59,12 @@ class VariantManager: variant_name = variant_metadata["name"] variant_definition = variant_metadata["definition"] if variant_definition not in self._machine_to_variant_dict_map: - self._machine_to_variant_dict_map[variant_definition] = {} - #for variant_type in ALL_VARIANT_TYPES: - # self._machine_to_variant_dict_map[variant_definition][variant_type] = {} + self._machine_to_variant_dict_map[variant_definition] = OrderedDict() + for variant_type in ALL_VARIANT_TYPES: + self._machine_to_variant_dict_map[variant_definition][variant_type] = dict() variant_type = variant_metadata["hardware_type"] - #variant_dict = self._machine_to_variant_dict_map[variant_definition][variant_type] - variant_dict = self._machine_to_variant_dict_map[variant_definition] + variant_dict = self._machine_to_variant_dict_map[variant_definition][variant_type] if variant_name in variant_dict: # ERROR: duplicated variant name. raise RuntimeError("Found duplicated variant name [%s], type [%s] for machine [%s]" % @@ -72,10 +76,11 @@ class VariantManager: # Gets the variant InstanceContainer with the given information. # Almost the same as getVariantMetadata() except that this returns an InstanceContainer if present. # - def getVariantNode(self, machine_type_name: str, variant_name: str, - variant_type: Optional[str] = None) -> Optional["InstanceContainer"]: - return self._machine_to_variant_dict_map[machine_type_name].get(variant_name) + def getVariantNode(self, machine_definition_id: str, variant_name: str, + variant_type: Optional[str] = VariantType.NOZZLE) -> Optional["ContainerNode"]: + return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}).get(variant_name) - def getVariantNodes(self, machine: "GlobalStack"): - machine_type_name = machine.definition.getId() - return self._machine_to_variant_dict_map.get(machine_type_name) + def getVariantNodes(self, machine: "GlobalStack", + variant_type: Optional[str] = VariantType.NOZZLE) -> dict: + machine_definition_id = machine.definition.getId() + return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}) From 495fc8bbd705f5145fe8312207b3f048a7dcc106 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 22:23:49 +0100 Subject: [PATCH 099/371] WIP: Refactor BuildPlateModel and split MultiBuildPlateModel --- cura/CuraApplication.py | 32 ++++++---- cura/Machines/Models/BuildPlateModel.py | 40 +++++++++++++ .../Models/Other/MultiBuildPlateModel.py} | 23 ++++---- cura/Machines/Models/Other/__init__.py | 0 cura/PrintInformation.py | 19 +++--- cura/Scene/ConvexHullNode.py | 2 +- cura/Scene/CuraSceneController.py | 16 ++--- cura/Scene/CuraSceneNode.py | 4 +- cura/Settings/MachineManager.py | 59 +++++++++++++------ plugins/3MFReader/ThreeMFReader.py | 2 +- plugins/3MFWriter/ThreeMFWriter.py | 2 +- .../CuraEngineBackend/CuraEngineBackend.py | 10 ++-- plugins/CuraEngineBackend/ProcessGCodeJob.py | 2 +- plugins/GCodeReader/FlavorParser.py | 2 +- plugins/GCodeWriter/GCodeWriter.py | 2 +- .../PostProcessingPlugin.py | 2 +- plugins/SimulationView/SimulationPass.py | 2 +- plugins/SupportEraser/SupportEraser.py | 2 +- .../ClusterUM3OutputDevice.py | 2 +- .../LegacyUM3OutputDevice.py | 2 +- plugins/USBPrinting/USBPrinterOutputDevice.py | 2 +- .../qml/DiscardOrKeepProfileChangesDialog.qml | 2 +- resources/qml/Menus/BuildplateMenu.qml | 20 ++----- resources/qml/Menus/ContextMenu.qml | 12 ++-- resources/qml/Menus/ViewMenu.qml | 10 ++-- resources/qml/ObjectsList.qml | 10 ++-- resources/qml/SidebarSimple.qml | 2 +- 27 files changed, 172 insertions(+), 111 deletions(-) create mode 100644 cura/Machines/Models/BuildPlateModel.py rename cura/{BuildPlateModel.py => Machines/Models/Other/MultiBuildPlateModel.py} (76%) create mode 100644 cura/Machines/Models/Other/__init__.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 395d6655cb..b369ebcfed 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -53,10 +53,13 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator +from cura.Machines.Models.BuildPlateModel import BuildPlateModel from cura.Machines.Models.NozzleModel import NozzleModel from cura.Machines.Models.QualityProfilesModel import QualityProfilesModel from cura.Machines.Models.CustomQualityProfilesModel import CustomQualityProfilesModel +from cura.Machines.Models.Other.MultiBuildPlateModel import MultiBuildPlateModel + from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel, NewMaterialsModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager @@ -84,7 +87,6 @@ from cura.Settings.QualitySettingsModel import QualitySettingsModel from cura.Settings.ContainerManager import ContainerManager from cura.ObjectsModel import ObjectsModel -from cura.BuildPlateModel import BuildPlateModel from PyQt5.QtCore import QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS from UM.FlameProfiler import pyqtSlot @@ -219,6 +221,7 @@ class CuraApplication(QtApplication): self._material_manager = None self._object_manager = None self._build_plate_model = None + self._multi_build_plate_model = None self._setting_inheritance_manager = None self._simple_mode_settings_manager = None self._cura_scene_controller = None @@ -858,10 +861,14 @@ class CuraApplication(QtApplication): self._object_manager = ObjectsModel.createObjectsModel() return self._object_manager + def getMultiBuildPlateModel(self, *args): + if self._multi_build_plate_model is None: + self._multi_build_plate_model = MultiBuildPlateModel(self) + return self._multi_build_plate_model + def getBuildPlateModel(self, *args): if self._build_plate_model is None: - self._build_plate_model = BuildPlateModel.createBuildPlateModel() - + self._build_plate_model = BuildPlateModel(self) return self._build_plate_model def getCuraSceneController(self, *args): @@ -923,15 +930,16 @@ class CuraApplication(QtApplication): qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") - qmlRegisterSingletonType(CuraSceneController, "Cura", 1, 2, "SceneController", self.getCuraSceneController) + qmlRegisterSingletonType(CuraSceneController, "Cura", 1, 0, "SceneController", self.getCuraSceneController) qmlRegisterSingletonType(ExtruderManager, "Cura", 1, 0, "ExtruderManager", self.getExtruderManager) qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, "MachineManager", self.getMachineManager) qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, "SettingInheritanceManager", self.getSettingInheritanceManager) - qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 2, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager) + qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager) qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) - qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 2, "ObjectsModel", self.getObjectsModel) - qmlRegisterSingletonType(BuildPlateModel, "Cura", 1, 2, "BuildPlateModel", self.getBuildPlateModel) + qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 0, "ObjectsModel", self.getObjectsModel) + qmlRegisterSingletonType(BuildPlateModel, "Cura", 1, 0, "BuildPlateModel", self.getBuildPlateModel) + qmlRegisterSingletonType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel", self.getMultiBuildPlateModel) qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer") qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") @@ -951,7 +959,7 @@ class CuraApplication(QtApplication): qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") - qmlRegisterType(UserChangesModel, "Cura", 1, 1, "UserChangesModel") + qmlRegisterType(UserChangesModel, "Cura", 1, 0, "UserChangesModel") qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager) # As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work. @@ -1033,7 +1041,7 @@ class CuraApplication(QtApplication): count = 0 scene_bounding_box = None is_block_slicing_node = False - active_build_plate = self.getBuildPlateModel().activeBuildPlate + active_build_plate = self._multi_build_plate_model.activeBuildPlate for node in DepthFirstIterator(self.getController().getScene().getRoot()): if ( not issubclass(type(node), CuraSceneNode) or @@ -1282,7 +1290,7 @@ class CuraApplication(QtApplication): @pyqtSlot() def arrangeAll(self): nodes = [] - active_build_plate = self.getBuildPlateModel().activeBuildPlate + active_build_plate = self._multi_build_plate_model.activeBuildPlate for node in DepthFirstIterator(self.getController().getScene().getRoot()): if not isinstance(node, SceneNode): continue @@ -1431,7 +1439,7 @@ class CuraApplication(QtApplication): group_decorator = GroupDecorator() group_node.addDecorator(group_decorator) group_node.addDecorator(ConvexHullDecorator()) - group_node.addDecorator(BuildPlateDecorator(self.getBuildPlateModel().activeBuildPlate)) + group_node.addDecorator(BuildPlateDecorator(self._multi_build_plate_model.activeBuildPlate)) group_node.setParent(self.getController().getScene().getRoot()) group_node.setSelectable(True) center = Selection.getSelectionCenter() @@ -1576,7 +1584,7 @@ class CuraApplication(QtApplication): arrange_objects_on_load = ( not Preferences.getInstance().getValue("cura/use_multi_build_plate") or not Preferences.getInstance().getValue("cura/not_arrange_objects_on_load")) - target_build_plate = self.getBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1 + target_build_plate = self._multi_build_plate_model.activeBuildPlate if arrange_objects_on_load else -1 root = self.getController().getScene().getRoot() fixed_nodes = [] diff --git a/cura/Machines/Models/BuildPlateModel.py b/cura/Machines/Models/BuildPlateModel.py new file mode 100644 index 0000000000..ff623eeca7 --- /dev/null +++ b/cura/Machines/Models/BuildPlateModel.py @@ -0,0 +1,40 @@ +from PyQt5.QtCore import Qt + +from UM.Application import Application +from UM.Qt.ListModel import ListModel + +from cura.Machines.VariantManager import VariantType + + +class BuildPlateModel(ListModel): + NameRole = Qt.UserRole + 1 + ContainerNodeRole = Qt.UserRole + 2 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.ContainerNodeRole, "container_node") + + self._application = Application.getInstance() + self._variant_manager = self._application._variant_manager + self._machine_manager = self._application.getMachineManager() + + self._machine_manager.globalContainerChanged.connect(self._update) + + self._update() + + def _update(self): + global_stack = self._machine_manager._global_container_stack + if not global_stack: + self.setItems([]) + return + + variant_dict = self._variant_manager.getVariantNodes(global_stack, variant_type = VariantType.BUILD_PLATE) + + item_list = [] + for name, variant_node in variant_dict.items(): + item = {"name": name, + "container_node": variant_node} + item_list.append(item) + self.setItems(item_list) diff --git a/cura/BuildPlateModel.py b/cura/Machines/Models/Other/MultiBuildPlateModel.py similarity index 76% rename from cura/BuildPlateModel.py rename to cura/Machines/Models/Other/MultiBuildPlateModel.py index 73f61202c6..78ad458a99 100644 --- a/cura/BuildPlateModel.py +++ b/cura/Machines/Models/Other/MultiBuildPlateModel.py @@ -1,24 +1,25 @@ -from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot +from PyQt5.QtCore import pyqtSignal, pyqtProperty -from UM.Qt.ListModel import ListModel -from UM.Scene.Selection import Selection -from UM.Logger import Logger from UM.Application import Application +from UM.Scene.Selection import Selection +from UM.Qt.ListModel import ListModel -class BuildPlateModel(ListModel): +class MultiBuildPlateModel(ListModel): + maxBuildPlateChanged = pyqtSignal() activeBuildPlateChanged = pyqtSignal() selectionChanged = pyqtSignal() - def __init__(self): - super().__init__() - Application.getInstance().getController().getScene().sceneChanged.connect(self._updateSelectedObjectBuildPlateNumbers) + def __init__(self, parent = None): + super().__init__(parent) + + self._application = Application.getInstance() + self._application.getController().getScene().sceneChanged.connect(self._updateSelectedObjectBuildPlateNumbers) Selection.selectionChanged.connect(self._updateSelectedObjectBuildPlateNumbers) self._max_build_plate = 1 # default self._active_build_plate = -1 - self._selection_build_plates = [] def setMaxBuildPlate(self, max_build_plate): self._max_build_plate = max_build_plate @@ -37,10 +38,6 @@ class BuildPlateModel(ListModel): def activeBuildPlate(self): return self._active_build_plate - @staticmethod - def createBuildPlateModel(): - return BuildPlateModel() - def _updateSelectedObjectBuildPlateNumbers(self, *args): result = set() for node in Selection.getAllSelectedObjects(): diff --git a/cura/Machines/Models/Other/__init__.py b/cura/Machines/Models/Other/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 8b6fbb1f28..9cbd7aec7e 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -76,15 +76,18 @@ class PrintInformation(QObject): self._active_build_plate = 0 self._initVariablesWithBuildPlate(self._active_build_plate) - Application.getInstance().globalContainerStackChanged.connect(self._updateJobName) - Application.getInstance().fileLoaded.connect(self.setBaseName) - Application.getInstance().getBuildPlateModel().activeBuildPlateChanged.connect(self._onActiveBuildPlateChanged) - Application.getInstance().workspaceLoaded.connect(self.setProjectName) + self._application = Application.getInstance() + self._multi_build_plate_model = self._application.getMultiBuildPlateModel() + + self._application.globalContainerStackChanged.connect(self._updateJobName) + self._application.fileLoaded.connect(self.setBaseName) + self._application.workspaceLoaded.connect(self.setProjectName) + self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveBuildPlateChanged) Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) self._active_material_container = None - Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._onActiveMaterialChanged) + self._application.getMachineManager().activeMaterialChanged.connect(self._onActiveMaterialChanged) self._onActiveMaterialChanged() self._material_amounts = [] @@ -260,7 +263,7 @@ class PrintInformation(QObject): if preference != "cura/material_settings": return - for build_plate_number in range(Application.getInstance().getBuildPlateModel().maxBuildPlate + 1): + for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1): self._calculateInformation(build_plate_number) def _onActiveMaterialChanged(self): @@ -278,7 +281,7 @@ class PrintInformation(QObject): self._active_material_container.metaDataChanged.connect(self._onMaterialMetaDataChanged) def _onActiveBuildPlateChanged(self): - new_active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate + new_active_build_plate = self._multi_build_plate_model.activeBuildPlate if new_active_build_plate != self._active_build_plate: self._active_build_plate = new_active_build_plate @@ -291,7 +294,7 @@ class PrintInformation(QObject): self.currentPrintTimeChanged.emit() def _onMaterialMetaDataChanged(self, *args, **kwargs): - for build_plate_number in range(Application.getInstance().getBuildPlateModel().maxBuildPlate + 1): + for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1): self._calculateInformation(build_plate_number) @pyqtSlot(str) diff --git a/cura/Scene/ConvexHullNode.py b/cura/Scene/ConvexHullNode.py index 6c8c201498..1131958627 100644 --- a/cura/Scene/ConvexHullNode.py +++ b/cura/Scene/ConvexHullNode.py @@ -68,7 +68,7 @@ class ConvexHullNode(SceneNode): ConvexHullNode.shader.setUniformValue("u_opacity", 0.6) if self.getParent(): - if self.getMeshData() and isinstance(self._node, SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate: + if self.getMeshData() and isinstance(self._node, SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate: renderer.queueNode(self, transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8) if self._convex_hull_head_mesh: renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8) diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py index 1c008d1893..d60179ae08 100644 --- a/cura/Scene/CuraSceneController.py +++ b/cura/Scene/CuraSceneController.py @@ -4,7 +4,7 @@ from PyQt5.QtCore import Qt, pyqtSlot, QObject from PyQt5.QtWidgets import QApplication from cura.ObjectsModel import ObjectsModel -from cura.BuildPlateModel import BuildPlateModel +from cura.Machines.Models.Other.MultiBuildPlateModel import MultiBuildPlateModel from UM.Application import Application from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator @@ -16,11 +16,11 @@ from UM.Signal import Signal class CuraSceneController(QObject): activeBuildPlateChanged = Signal() - def __init__(self, objects_model: ObjectsModel, build_plate_model: BuildPlateModel): + def __init__(self, objects_model: ObjectsModel, multi_build_plate_model: MultiBuildPlateModel): super().__init__() self._objects_model = objects_model - self._build_plate_model = build_plate_model + self._multi_build_plate_model = multi_build_plate_model self._active_build_plate = -1 self._last_selected_index = 0 @@ -41,9 +41,9 @@ class CuraSceneController(QObject): self._max_build_plate = max_build_plate changed = True if changed: - self._build_plate_model.setMaxBuildPlate(self._max_build_plate) + self._multi_build_plate_model.setMaxBuildPlate(self._max_build_plate) build_plates = [{"name": "Build Plate %d" % (i + 1), "buildPlateNumber": i} for i in range(self._max_build_plate + 1)] - self._build_plate_model.setItems(build_plates) + self._multi_build_plate_model.setItems(build_plates) if self._active_build_plate > self._max_build_plate: build_plate_number = 0 if self._last_selected_index >= 0: # go to the buildplate of the item you last selected @@ -104,12 +104,12 @@ class CuraSceneController(QObject): self._active_build_plate = nr Selection.clear() - self._build_plate_model.setActiveBuildPlate(nr) + self._multi_build_plate_model.setActiveBuildPlate(nr) self._objects_model.setActiveBuildPlate(nr) self.activeBuildPlateChanged.emit() @staticmethod def createCuraSceneController(): objects_model = Application.getInstance().getObjectsModel() - build_plate_model = Application.getInstance().getBuildPlateModel() - return CuraSceneController(objects_model = objects_model, build_plate_model = build_plate_model) + multi_build_plate_model = Application.getInstance().getMultiBuildPlateModel() + return CuraSceneController(objects_model = objects_model, multi_build_plate_model = multi_build_plate_model) diff --git a/cura/Scene/CuraSceneNode.py b/cura/Scene/CuraSceneNode.py index 969d491f49..df346baaad 100644 --- a/cura/Scene/CuraSceneNode.py +++ b/cura/Scene/CuraSceneNode.py @@ -20,10 +20,10 @@ class CuraSceneNode(SceneNode): return self._outside_buildarea or self.callDecoration("getBuildPlateNumber") < 0 def isVisible(self): - return super().isVisible() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate + return super().isVisible() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate def isSelectable(self) -> bool: - return super().isSelectable() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate + return super().isSelectable() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate ## Get the extruder used to print this node. If there is no active node, then the extruder in position zero is returned # TODO The best way to do it is by adding the setActiveExtruder decorator to every node when is loaded diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index e53145ee87..9f25e27a5c 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -545,11 +545,11 @@ class MachineManager(QObject): return "" @pyqtProperty(str, notify=activeVariantChanged) - def globalVariantId(self) -> str: + def globalVariantName(self) -> str: if self._global_container_stack: variant = self._global_container_stack.variant if variant and not isinstance(variant, type(self._empty_variant_container)): - return variant.getId() + return variant.getName() return "" @pyqtProperty(str, notify = activeQualityChanged) @@ -1319,6 +1319,9 @@ class MachineManager(QObject): def _setVariantNode(self, position, container_node): self._global_container_stack.extruders[position].variant = container_node.getContainer() + def _setGlobalVariant(self, container_node): + self._global_container_stack.variant = container_node.getContainer() + def _setMaterial(self, position, container_node = None): if container_node: self._global_container_stack.extruders[position].material = container_node.getContainer() @@ -1354,22 +1357,33 @@ class MachineManager(QObject): self._setQualityGroup(candidate_quality_groups[quality_type], empty_quality_changes = False) - def _updateMaterialWithVariant(self, position, current_material_base_name, current_variant_name): - material_manager = Application.getInstance()._material_manager - material_diameter = self._global_container_stack.getProperty("material_diameter", "value") - candidate_materials = material_manager.getAvailableMaterials( - self._global_container_stack.getId(), - current_variant_name, - material_diameter) + def _updateMaterialWithVariant(self, position: Optional[str]): + if position is None: + position_list = list(self._global_container_stack.extruders.keys()) + else: + position_list = [position] - if not candidate_materials: - self._setMaterial(position, container_node = None) - return + for position in position_list: + extruder = self._global_container_stack.extruders[position] - if current_material_base_name in candidate_materials: - new_material = candidate_materials[current_material_base_name] - self._setMaterial(position, new_material) - return + current_material_base_name = extruder.material.getMetaDataEntry("base_file") + current_variant_name = extruder.variant.getMetaDataEntry("name") + + material_manager = Application.getInstance()._material_manager + material_diameter = self._global_container_stack.getProperty("material_diameter", "value") + candidate_materials = material_manager.getAvailableMaterials( + self._global_container_stack.getId(), + current_variant_name, + material_diameter) + + if not candidate_materials: + self._setMaterial(position, container_node = None) + continue + + if current_material_base_name in candidate_materials: + new_material = candidate_materials[current_material_base_name] + self._setMaterial(position, new_material) + continue # # Find a fallback material # preferred_material_query = self._global_container_stack.getMetaDataEntry("preferred_material") @@ -1378,6 +1392,15 @@ class MachineManager(QObject): # self._setMaterial(position, candidate_materials[preferred_material_key]) # return + @pyqtSlot("QVariant") + def setGlobalVariant(self, container_node): + Logger.log("d", "---------------- container = [%s]", container_node) + self.blurSettings.emit() + with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): + self._setGlobalVariant(container_node) + self._updateMaterialWithVariant(None) # Update all materials + self._updateQualityWithMaterial() + @pyqtSlot(str, "QVariant") def setMaterial(self, position, container_node): Logger.log("d", "---------------- container = [%s]", container_node) @@ -1394,9 +1417,7 @@ class MachineManager(QObject): self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setVariantNode(position, container_node) - current_variant_name = container_node.metadata["name"] - current_material_base_name = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") - self._updateMaterialWithVariant(position, current_material_base_name, current_variant_name) + self._updateMaterialWithVariant(position) self._updateQualityWithMaterial() @pyqtSlot("QVariant") diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 1726818100..907c1c44b7 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -77,7 +77,7 @@ class ThreeMFReader(MeshReader): self._object_count += 1 node_name = "Object %s" % self._object_count - active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate um_node = CuraSceneNode() um_node.addDecorator(BuildPlateDecorator(active_build_plate)) diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index c4b7035cf1..ff6333763a 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -68,7 +68,7 @@ class ThreeMFWriter(MeshWriter): if not isinstance(um_node, SceneNode): return None - active_build_plate_nr = CuraApplication.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate_nr = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate if um_node.callDecoration("getBuildPlateNumber") != active_build_plate_nr: return diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 1c275d6d5b..cd4f74141b 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -70,7 +70,7 @@ class CuraEngineBackend(QObject, Backend): # Workaround to disable layer view processing if layer view is not active. self._layer_view_active = False Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) - Application.getInstance().getBuildPlateModel().activeBuildPlateChanged.connect(self._onActiveViewChanged) + Application.getInstance().getMultiBuildPlateModel().activeBuildPlateChanged.connect(self._onActiveViewChanged) self._onActiveViewChanged() self._stored_layer_data = [] self._stored_optimized_layer_data = {} # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob @@ -207,7 +207,7 @@ class CuraEngineBackend(QObject, Backend): self._scene.gcode_dict = {} # see if we really have to slice - active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate build_plate_to_be_sliced = self._build_plates_to_be_sliced.pop(0) Logger.log("d", "Going to slice build plate [%s]!" % build_plate_to_be_sliced) num_objects = self._numObjects() @@ -497,7 +497,7 @@ class CuraEngineBackend(QObject, Backend): node.getParent().removeChild(node) def markSliceAll(self): - for build_plate_number in range(Application.getInstance().getBuildPlateModel().maxBuildPlate + 1): + for build_plate_number in range(Application.getInstance().getMultiBuildPlateModel().maxBuildPlate + 1): if build_plate_number not in self._build_plates_to_be_sliced: self._build_plates_to_be_sliced.append(build_plate_number) @@ -582,7 +582,7 @@ class CuraEngineBackend(QObject, Backend): Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time ) # See if we need to process the sliced layers job. - active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate if self._layer_view_active and (self._process_layers_job is None or not self._process_layers_job.isRunning()) and active_build_plate == self._start_slice_job_build_plate: self._startProcessSlicedLayersJob(active_build_plate) # self._onActiveViewChanged() @@ -702,7 +702,7 @@ class CuraEngineBackend(QObject, Backend): application = Application.getInstance() view = application.getController().getActiveView() if view: - active_build_plate = application.getBuildPlateModel().activeBuildPlate + active_build_plate = application.getMultiBuildPlateModel().activeBuildPlate if view.getPluginId() == "SimulationView": # If switching to layer view, we should process the layers if that hasn't been done yet. self._layer_view_active = True # There is data and we're not slicing at the moment diff --git a/plugins/CuraEngineBackend/ProcessGCodeJob.py b/plugins/CuraEngineBackend/ProcessGCodeJob.py index ed430f8fa9..817daa9f85 100644 --- a/plugins/CuraEngineBackend/ProcessGCodeJob.py +++ b/plugins/CuraEngineBackend/ProcessGCodeJob.py @@ -12,6 +12,6 @@ class ProcessGCodeLayerJob(Job): self._message = message def run(self): - active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate gcode_list = self._scene.gcode_dict[active_build_plate_id] gcode_list.append(self._message.data.decode("utf-8", "replace")) diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index f63ba3ca69..c064ffbf10 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -437,7 +437,7 @@ class FlavorParser: scene_node.addDecorator(gcode_list_decorator) # gcode_dict stores gcode_lists for a number of build plates. - active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate gcode_dict = {active_build_plate_id: gcode_list} Application.getInstance().getController().getScene().gcode_dict = gcode_dict diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index 368942fd08..ede0e2c251 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -60,7 +60,7 @@ class GCodeWriter(MeshWriter): Logger.log("e", "GCodeWriter does not support non-text mode.") return False - active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate scene = Application.getInstance().getController().getScene() gcode_dict = getattr(scene, "gcode_dict") if not gcode_dict: diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.py b/plugins/PostProcessingPlugin/PostProcessingPlugin.py index f491afbec0..566b05abf3 100644 --- a/plugins/PostProcessingPlugin/PostProcessingPlugin.py +++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.py @@ -62,7 +62,7 @@ class PostProcessingPlugin(QObject, Extension): return # get gcode list for the active build plate - active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate gcode_list = gcode_dict[active_build_plate_id] if not gcode_list: return diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index 76d7127534..cd0eda2929 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -93,7 +93,7 @@ class SimulationPass(RenderPass): self.bind() tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay, backface_cull = True) - active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate head_position = None # Indicates the current position of the print head nozzle_node = None diff --git a/plugins/SupportEraser/SupportEraser.py b/plugins/SupportEraser/SupportEraser.py index 9e2d41014d..ddc6b96c3a 100644 --- a/plugins/SupportEraser/SupportEraser.py +++ b/plugins/SupportEraser/SupportEraser.py @@ -42,7 +42,7 @@ class SupportEraser(Tool): mesh.addCube(10,10,10) node.setMeshData(mesh.build()) - active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate node.addDecorator(SettingOverrideDecorator()) node.addDecorator(BuildPlateDecorator(active_build_plate)) diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py index 26b445ef90..0b5a0696c6 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py @@ -81,7 +81,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): self.writeStarted.emit(self) gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict", []) - active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate gcode_list = gcode_dict[active_build_plate_id] if not gcode_list: diff --git a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py index 647a7f822c..512671b3b3 100644 --- a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py @@ -184,7 +184,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): self.writeStarted.emit(self) gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict", []) - active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate gcode_list = gcode_dict[active_build_plate_id] if not gcode_list: diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index b53f502d81..6e2b5153db 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -99,7 +99,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice): Application.getInstance().getController().setActiveStage("MonitorStage") # find the G-code for the active build plate to print - active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict") gcode_list = gcode_dict[active_build_plate_id] diff --git a/resources/qml/DiscardOrKeepProfileChangesDialog.qml b/resources/qml/DiscardOrKeepProfileChangesDialog.qml index 915a11fde2..afa9fda0bd 100644 --- a/resources/qml/DiscardOrKeepProfileChangesDialog.qml +++ b/resources/qml/DiscardOrKeepProfileChangesDialog.qml @@ -7,7 +7,7 @@ import QtQuick.Dialogs 1.2 import QtQuick.Window 2.1 import UM 1.2 as UM -import Cura 1.1 as Cura +import Cura 1.0 as Cura UM.Dialog { diff --git a/resources/qml/Menus/BuildplateMenu.qml b/resources/qml/Menus/BuildplateMenu.qml index 2679eec1d1..8dfc3ced6c 100644 --- a/resources/qml/Menus/BuildplateMenu.qml +++ b/resources/qml/Menus/BuildplateMenu.qml @@ -14,26 +14,18 @@ Menu Instantiator { - id: buildplateInstantiator - model: UM.InstanceContainersModel - { - filter: - { - "type": "variant", - "hardware_type": "buildplate", - "definition": Cura.MachineManager.activeDefinitionId //Only show variants of this machine - } - } + model: Cura.BuildPlateModel + MenuItem { text: model.name checkable: true - checked: model.id == Cura.MachineManager.globalVariantId + checked: model.name == Cura.MachineManager.globalVariantName // TODO exclusiveGroup: group - onTriggered: - { - Cura.MachineManager.setActiveVariantBuildplate(model.id); + onTriggered: { + Cura.MachineManager.setGlobalVariant(model.container_node); // TODO } } + onObjectAdded: menu.insertItem(index, object) onObjectRemoved: menu.removeItem(object) } diff --git a/resources/qml/Menus/ContextMenu.qml b/resources/qml/Menus/ContextMenu.qml index b5f51f4d63..a37204d255 100644 --- a/resources/qml/Menus/ContextMenu.qml +++ b/resources/qml/Menus/ContextMenu.qml @@ -7,7 +7,7 @@ import QtQuick.Dialogs 1.2 import QtQuick.Window 2.1 import UM 1.2 as UM -import Cura 1.2 as Cura +import Cura 1.0 as Cura Menu { @@ -45,13 +45,13 @@ Menu Instantiator { - model: Cura.BuildPlateModel + model: Cura.MultiBuildPlateModel MenuItem { enabled: UM.Selection.hasSelection - text: Cura.BuildPlateModel.getItem(index).name; - onTriggered: CuraActions.setBuildPlateForSelection(Cura.BuildPlateModel.getItem(index).buildPlateNumber); + text: Cura.MultiBuildPlateModel.getItem(index).name; + onTriggered: CuraActions.setBuildPlateForSelection(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber); checkable: true - checked: Cura.BuildPlateModel.selectionBuildPlates.indexOf(Cura.BuildPlateModel.getItem(index).buildPlateNumber) != -1; + checked: Cura.MultiBuildPlateModel.selectionBuildPlates.indexOf(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber) != -1; visible: UM.Preferences.getValue("cura/use_multi_build_plate") } onObjectAdded: base.insertItem(index, object); @@ -62,7 +62,7 @@ Menu enabled: UM.Selection.hasSelection text: "New build plate"; onTriggered: { - CuraActions.setBuildPlateForSelection(Cura.BuildPlateModel.maxBuildPlate + 1); + CuraActions.setBuildPlateForSelection(Cura.MultiBuildPlateModel.maxBuildPlate + 1); checked = false; } checkable: true diff --git a/resources/qml/Menus/ViewMenu.qml b/resources/qml/Menus/ViewMenu.qml index afc80dd314..ff749bec90 100644 --- a/resources/qml/Menus/ViewMenu.qml +++ b/resources/qml/Menus/ViewMenu.qml @@ -5,7 +5,7 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 import UM 1.2 as UM -import Cura 1.2 as Cura +import Cura 1.0 as Cura Menu { @@ -53,12 +53,12 @@ Menu visible: UM.Preferences.getValue("cura/use_multi_build_plate") Instantiator { - model: Cura.BuildPlateModel + model: Cura.MultiBuildPlateModel MenuItem { - text: Cura.BuildPlateModel.getItem(index).name; - onTriggered: Cura.SceneController.setActiveBuildPlate(Cura.BuildPlateModel.getItem(index).buildPlateNumber); + text: Cura.MultiBuildPlateModel.getItem(index).name; + onTriggered: Cura.SceneController.setActiveBuildPlate(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber); checkable: true; - checked: Cura.BuildPlateModel.getItem(index).buildPlateNumber == Cura.BuildPlateModel.activeBuildPlate; + checked: Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber == Cura.MultiBuildPlateModel.activeBuildPlate; exclusiveGroup: buildPlateGroup; visible: UM.Preferences.getValue("cura/use_multi_build_plate") } diff --git a/resources/qml/ObjectsList.qml b/resources/qml/ObjectsList.qml index b64f08d003..f51e1081e6 100644 --- a/resources/qml/ObjectsList.qml +++ b/resources/qml/ObjectsList.qml @@ -8,7 +8,7 @@ import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.1 import UM 1.3 as UM -import Cura 1.2 as Cura +import Cura 1.0 as Cura import "Menus" @@ -67,7 +67,7 @@ Rectangle Rectangle { height: childrenRect.height - color: Cura.BuildPlateModel.getItem(index).buildPlateNumber == Cura.BuildPlateModel.activeBuildPlate ? palette.highlight : index % 2 ? palette.base : palette.alternateBase + color: Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber == Cura.MultiBuildPlateModel.activeBuildPlate ? palette.highlight : index % 2 ? palette.base : palette.alternateBase width: parent.width Label { @@ -75,8 +75,8 @@ Rectangle anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width width: parent.width - 2 * UM.Theme.getSize("default_margin").width - 30 - text: Cura.BuildPlateModel.getItem(index) ? Cura.BuildPlateModel.getItem(index).name : ""; - color: Cura.BuildPlateModel.activeBuildPlate == index ? palette.highlightedText : palette.text + text: Cura.MultiBuildPlateModel.getItem(index) ? Cura.MultiBuildPlateModel.getItem(index).name : ""; + color: Cura.MultiBuildPlateModel.activeBuildPlate == index ? palette.highlightedText : palette.text elide: Text.ElideRight } @@ -118,7 +118,7 @@ Rectangle ListView { id: buildPlateListView - model: Cura.BuildPlateModel + model: Cura.MultiBuildPlateModel width: parent.width delegate: buildPlateDelegate } diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index c296a72281..0f9c8b0e55 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -7,7 +7,7 @@ import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.3 import UM 1.2 as UM -import Cura 1.2 as Cura +import Cura 1.0 as Cura Item { From 6124729f01001aa7f09118e8c29228e37446363e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 17 Feb 2018 22:27:56 +0100 Subject: [PATCH 100/371] WIP: Cleanup MachineManager --- cura/Settings/MachineManager.py | 106 -------------------------------- 1 file changed, 106 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 9f25e27a5c..28a36b7e87 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -609,112 +609,6 @@ class MachineManager(QObject): if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved - ## Set the active material by switching out a container - # Depending on from/to material+current variant, a quality profile is chosen and set. - @pyqtSlot(str) - def setActiveMaterial(self, material_id: str, always_discard_changes = False): - with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): - containers = ContainerRegistry.getInstance().findInstanceContainers(id = material_id) - if not containers or not self._active_container_stack: - return - material_container = containers[0] - - Logger.log("d", "Attempting to change the active material to %s", material_id) - - old_material = self._active_container_stack.material - old_quality = self._active_container_stack.quality - old_quality_type = None - if old_quality and old_quality.getId() != self._empty_quality_container.getId(): - old_quality_type = old_quality.getMetaDataEntry("quality_type") - old_quality_changes = self._active_container_stack.qualityChanges - if not old_material: - Logger.log("w", "While trying to set the active material, no material was found to replace it.") - return - - if old_quality_changes and isinstance(old_quality_changes, type(self._empty_quality_changes_container)): - old_quality_changes = None - - self.blurSettings.emit() - old_material.nameChanged.disconnect(self._onMaterialNameChanged) - - self._new_material_container = material_container # self._active_container_stack will be updated with a delay - Logger.log("d", "Active material changed") - - material_container.nameChanged.connect(self._onMaterialNameChanged) - - if material_container.getMetaDataEntry("compatible") == False: - self._material_incompatible_message.show() - else: - self._material_incompatible_message.hide() - - quality_type = None - new_quality_id = None - if old_quality: - new_quality_id = old_quality.getId() - quality_type = old_quality.getMetaDataEntry("quality_type") - if old_quality_changes: - quality_type = old_quality_changes.getMetaDataEntry("quality_type") - new_quality_id = old_quality_changes.getId() - - global_stack = Application.getInstance().getGlobalContainerStack() - if global_stack: - quality_manager = QualityManager.getInstance() - - candidate_quality = None - if quality_type: - candidate_quality = quality_manager.findQualityByQualityType(quality_type, - quality_manager.getWholeMachineDefinition(global_stack.definition), - [material_container.getMetaData()]) - - if not candidate_quality or candidate_quality.getId() == self._empty_quality_changes_container: - Logger.log("d", "Attempting to find fallback quality") - # Fall back to a quality (which must be compatible with all other extruders) - new_qualities = quality_manager.findAllUsableQualitiesForMachineAndExtruders( - self._global_container_stack, ExtruderManager.getInstance().getExtruderStacks()) - - quality_types = sorted([q.getMetaDataEntry("quality_type") for q in new_qualities], reverse = True) - quality_type_to_use = None - if quality_types: - # try to use the same quality as before, otherwise the first one in the quality_types - quality_type_to_use = quality_types[0] - if old_quality_type is not None and old_quality_type in quality_type_to_use: - quality_type_to_use = old_quality_type - - new_quality = None - for q in new_qualities: - if quality_type_to_use is not None and q.getMetaDataEntry("quality_type") == quality_type_to_use: - new_quality = q - break - - if new_quality is not None: - new_quality_id = new_quality.getId() # Just pick the first available one - else: - Logger.log("w", "No quality profile found that matches the current machine and extruders.") - else: - if not old_quality_changes: - new_quality_id = candidate_quality.getId() - - self.setActiveQuality(new_quality_id, always_discard_changes = always_discard_changes) - - # TODO: refactor this - @pyqtSlot(str) - def setActiveVariantBuildplate(self, variant_buildplate_id: str): - with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): - containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_buildplate_id) - if not containers or not self._global_container_stack: - return - Logger.log("d", "Attempting to change the active buildplate to %s", variant_buildplate_id) - old_buildplate = self._global_container_stack.variant - if old_buildplate: - self.blurSettings.emit() - self._new_buildplate_container = containers[0] # self._active_container_stack will be updated with a delay - Logger.log("d", "Active buildplate changed to {active_variant_buildplate_id}".format(active_variant_buildplate_id = containers[0].getId())) - - # Force set the active quality as it is so the values are updated - self.setActiveMaterial(self._active_container_stack.material.getId()) - else: - Logger.log("w", "While trying to set the active buildplate, no buildplate was found to replace.") - ## set the active quality # \param quality_id The quality_id of either a quality or a quality_changes @pyqtSlot(str) From 2c689ef03f981ad3d8a6bd381360e225d131ed0e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 19 Feb 2018 09:14:04 +0100 Subject: [PATCH 101/371] Log markup --- plugins/CuraEngineBackend/CuraEngineBackend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 1c275d6d5b..79fa12114f 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -192,7 +192,7 @@ class CuraEngineBackend(QObject, Backend): ## Perform a slice of the scene. def slice(self): - Logger.log("d", "starting to slice!") + Logger.log("d", "Starting to slice...") self._slice_start_time = time() if not self._build_plates_to_be_sliced: self.processingProgress.emit(1.0) @@ -200,7 +200,7 @@ class CuraEngineBackend(QObject, Backend): return if self._process_layers_job: - Logger.log("d", " ## Process layers job still busy, trying later") + Logger.log("d", "Process layers job still busy, trying later.") return if not hasattr(self._scene, "gcode_dict"): From 1891294079320f8fee3e39c58a549ff25fd29cf3 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 19 Feb 2018 11:02:08 +0100 Subject: [PATCH 102/371] CURA-4606 fix material manager to exclude custom materials from some lookup tables --- cura/Machines/MaterialManager.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index b52bd7dca2..664d55a4c1 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -100,16 +100,24 @@ class MaterialManager(QObject): self._guid_material_groups_map[guid].append(material_group) # Map #2 - # Lookup table for material type -> fallback material metadata + # Lookup table for material type -> fallback material metadata, only for read-only materials grouped_by_type_dict = dict() for root_material_id, material_node in self._material_group_map.items(): + if not self._container_registry.isReadOnly(root_material_id): + continue material_type = material_node.root_material_node.metadata["material"] if material_type not in grouped_by_type_dict: grouped_by_type_dict[material_type] = {"generic": None, "others": []} brand = material_node.root_material_node.metadata["brand"] if brand.lower() == "generic": - grouped_by_type_dict[material_type] = material_node.root_material_node.metadata + to_add = True + if material_type in grouped_by_type_dict: + diameter = material_node.root_material_node.metadata.get("approximate_diameter") + if diameter != self._default_approximate_diameter_for_quality_search: + to_add = False # don't add if it's not the default diameter + if to_add: + grouped_by_type_dict[material_type] = material_node.root_material_node.metadata self._fallback_materials_map = grouped_by_type_dict # Map #3 @@ -124,6 +132,9 @@ class MaterialManager(QObject): material_group_dict = dict() keys_to_fetch = ("name", "material", "brand", "color") for root_material_id, machine_node in self._material_group_map.items(): + if not self._container_registry.isReadOnly(root_material_id): + continue + root_material_metadata = machine_node.root_material_node.metadata key_data = [] From 5d4a2a7e4930431b5ad4a0a54983a9526c3c3afb Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 19 Feb 2018 11:02:42 +0100 Subject: [PATCH 103/371] CURA-4606 qtquick dialogs 1.2 to be compatible with older pyqt --- resources/qml/Preferences/MaterialsPage.qml | 2 +- resources/qml/Preferences/ProfilesPage.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 92d596485c..4eddc45d76 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -4,7 +4,7 @@ import QtQuick 2.8 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 -import QtQuick.Dialogs 1.3 +import QtQuick.Dialogs 1.2 import UM 1.2 as UM import Cura 1.0 as Cura diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 633e965bd9..df5f4faa33 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -4,7 +4,7 @@ import QtQuick 2.8 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 -import QtQuick.Dialogs 1.3 +import QtQuick.Dialogs 1.2 import UM 1.2 as UM import Cura 1.0 as Cura From 438f11b2e6eb63c5b76a009ac86f49cfad1a0cbc Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 19 Feb 2018 14:09:02 +0100 Subject: [PATCH 104/371] CURA-4965 Custom / Duplicated Material's Build Plate Temperature returns to default Holy hell that took a long time to figure out. Thanks @diegopradogesto! --- cura/Settings/MaterialSettingsVisibilityHandler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MaterialSettingsVisibilityHandler.py b/cura/Settings/MaterialSettingsVisibilityHandler.py index 5b6050d2c0..530284991d 100644 --- a/cura/Settings/MaterialSettingsVisibilityHandler.py +++ b/cura/Settings/MaterialSettingsVisibilityHandler.py @@ -9,7 +9,7 @@ class MaterialSettingsVisibilityHandler(UM.Settings.Models.SettingVisibilityHand material_settings = { "default_material_print_temperature", - "material_bed_temperature", + "default_material_bed_temperature", "material_standby_temperature", #"material_flow_temp_graph", "cool_fan_speed", From 2d5f65a954fd44fc2d4e63e3ab114a20fa5d34b3 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 14:23:05 +0100 Subject: [PATCH 105/371] WIP: Fix NozzleMenu QObject result type --- cura/Settings/MachineManager.py | 2 +- resources/qml/Menus/NozzleMenu.qml | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 28a36b7e87..3c35aaad64 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1115,7 +1115,7 @@ class MachineManager(QObject): def createMachineManager(): return MachineManager() - @pyqtSlot(int, result = "QVariant") + @pyqtSlot(int, result = QObject) def getExtruder(self, position: int): if self._global_container_stack: return self._global_container_stack.extruders.get(str(position)) diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index 96b21f285c..ea1c0000f4 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -13,19 +13,18 @@ Menu title: "Nozzle" property int extruderIndex: 0 + property var extruderStack: Cura.MachineManager.getExtruder(menu.extruderIndex) Cura.NozzleModel { id: nozzleModel } - property var extruderStack: Cura.MachineManager.getExtruder(extruderIndex) - Connections { target: Cura.MachineManager onGlobalContainerChanged: { - menu.extruderStack = Cura.MachineManager.getExtruder(extruderIndex) + menu.extruderStack = Cura.MachineManager.getExtruder(extruderIndex); } } From 1afe2668f77c6ee20d2877ba70f17a07a001b6a1 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 19 Feb 2018 15:04:08 +0100 Subject: [PATCH 106/371] Fix: Extreme small model was not automatically scaled. --- cura/CuraApplication.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 07b3aab60c..90c7dbb75e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1547,8 +1547,16 @@ class CuraApplication(QtApplication): for original_node in nodes: # Create a CuraSceneNode just if the original node is not that type - node = original_node if isinstance(original_node, CuraSceneNode) else CuraSceneNode() - node.setMeshData(original_node.getMeshData()) + if isinstance(original_node, CuraSceneNode): + node = original_node + else: + node = CuraSceneNode() + node.setMeshData(original_node.getMeshData()) + + #Setting meshdata does not apply scaling. + if(original_node.getScale() != Vector(1.0, 1.0, 1.0)): + node.scale(original_node.getScale()) + node.setSelectable(True) node.setName(os.path.basename(filename)) From 3ff9cb6b1e3bb917cee1e5041eae03c2a9cab6d2 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 19 Feb 2018 15:03:04 +0100 Subject: [PATCH 107/371] CURA-4606 added first Profile management page --- cura/CuraApplication.py | 2 +- cura/Machines/ContainerGroup.py | 9 + cura/Machines/Models/QualitySettingsModel.py | 147 ++++++++ cura/Machines/QualityManager.py | 5 +- cura/Settings/QualitySettingsModel.py | 249 ------------ resources/qml/Preferences/OldProfileTab.qml | 98 ----- resources/qml/Preferences/OldProfilesPage.qml | 356 ------------------ resources/qml/Preferences/ProfileTab.qml | 16 +- resources/qml/Preferences/ProfilesPage.qml | 96 ++++- 9 files changed, 260 insertions(+), 718 deletions(-) create mode 100644 cura/Machines/Models/QualitySettingsModel.py delete mode 100644 cura/Settings/QualitySettingsModel.py delete mode 100644 resources/qml/Preferences/OldProfileTab.qml delete mode 100644 resources/qml/Preferences/OldProfilesPage.qml diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index b369ebcfed..57054c5d3b 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -83,7 +83,7 @@ from cura.Settings.UserChangesModel import UserChangesModel from cura.Settings.ExtrudersModel import ExtrudersModel from cura.Settings.ContainerSettingsModel import ContainerSettingsModel from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler -from cura.Settings.QualitySettingsModel import QualitySettingsModel +from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel from cura.Settings.ContainerManager import ContainerManager from cura.ObjectsModel import ObjectsModel diff --git a/cura/Machines/ContainerGroup.py b/cura/Machines/ContainerGroup.py index 3b17a0ae60..d1ceb81dec 100644 --- a/cura/Machines/ContainerGroup.py +++ b/cura/Machines/ContainerGroup.py @@ -16,3 +16,12 @@ class ContainerGroup(QObject): @pyqtSlot(result = str) def getName(self) -> str: return self.name + + def getAllKeys(self) -> set: + result = set() + for node in [self.node_for_global] + list(self.nodes_for_extruders.values()): + if node is None: + continue + for key in node.getContainer().getAllKeys(): + result.add(key) + return result diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py new file mode 100644 index 0000000000..d3a177c3eb --- /dev/null +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -0,0 +1,147 @@ +# Copyright (c) 2017 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt + +from UM.Logger import Logger +import UM.Qt +from UM.Application import Application +from UM.Settings.ContainerRegistry import ContainerRegistry +import os + +from UM.i18n import i18nCatalog + + +class QualitySettingsModel(UM.Qt.ListModel.ListModel): + KeyRole = Qt.UserRole + 1 + LabelRole = Qt.UserRole + 2 + UnitRole = Qt.UserRole + 3 + ProfileValueRole = Qt.UserRole + 4 + ProfileValueSourceRole = Qt.UserRole + 5 + UserValueRole = Qt.UserRole + 6 + CategoryRole = Qt.UserRole + 7 + + def __init__(self, parent = None): + super().__init__(parent = parent) + + self._container_registry = ContainerRegistry.getInstance() + self._application = Application.getInstance() + + self._extruder_position = "" + self._quality = None + self._i18n_catalog = None + + self.addRoleName(self.KeyRole, "key") + self.addRoleName(self.LabelRole, "label") + self.addRoleName(self.UnitRole, "unit") + self.addRoleName(self.ProfileValueRole, "profile_value") + self.addRoleName(self.ProfileValueSourceRole, "profile_value_source") + self.addRoleName(self.UserValueRole, "user_value") + self.addRoleName(self.CategoryRole, "category") + + self._empty_quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0] + + self._update() + + def setExtruderPosition(self, extruder_position): + if extruder_position != self._extruder_position: + self._extruder_position = extruder_position + self._update() + self.extruderPositionChanged.emit() + + extruderPositionChanged = pyqtSignal() + @pyqtProperty(str, fset = setExtruderPosition, notify = extruderPositionChanged) + def extruderPosition(self): + return self._extruder_position + + def setQuality(self, quality): + if quality != self._quality: + self._quality = quality + self._update() + self.qualityChanged.emit() + + qualityChanged = pyqtSignal() + @pyqtProperty(dict, fset = setQuality, notify = qualityChanged) + def quality(self): + return self._quality + + def _update(self): + if self._quality is None: + self.setItems([]) + return + + items = [] + + global_container_stack = Application.getInstance().getGlobalContainerStack() + definition_container = global_container_stack.definition + + quality_group = self._quality["quality_group"] + quality_changes_group = self._quality["quality_changes_group"] + + if self._extruder_position == "": + quality_node = quality_group.node_for_global + else: + quality_node = quality_group.nodes_for_extruders.get(self._extruder_position) + settings_keys = quality_group.getAllKeys() + quality_containers = [quality_node.getContainer()] + + if quality_changes_group is not None: + if self._extruder_position == "": + quality_changes_node = quality_changes_group.node_for_global + else: + quality_changes_node = quality_changes_group.nodes_for_extruders.get(self._extruder_position) + if quality_changes_node is not None: # it can be None if number of extruders are changed during runtime + quality_containers.insert(0, quality_changes_node.getContainer()) + settings_keys.update(quality_changes_group.getAllKeys()) + + current_category = "" + for definition in definition_container.findDefinitions(): + if definition.type == "category": + current_category = definition.label + if self._i18n_catalog: + current_category = self._i18n_catalog.i18nc(definition.key + " label", definition.label) + continue + + profile_value = None + profile_value_source = "" + for quality_container in quality_containers: + new_value = quality_container.getProperty(definition.key, "value") + + if new_value is not None: + profile_value_source = quality_container.getMetaDataEntry("type") + profile_value = new_value + + # Global tab should use resolve (if there is one) + if self._extruder_position == "": + resolve_value = global_container_stack.getProperty(definition.key, "resolve") + if resolve_value is not None and definition.key in settings_keys: + profile_value = resolve_value + + if profile_value is not None: + break + + user_value = None + if not self._extruder_position: + user_value = global_container_stack.userChanges.getProperty(definition.key, "value") + else: + extruder_stack = global_container_stack.extruders[self._extruder_position] + user_value = extruder_stack.userChanges.getProperty(definition.key, "value") + + if profile_value is None and user_value is None: + continue + + label = definition.label + if self._i18n_catalog: + label = self._i18n_catalog.i18nc(definition.key + " label", label) + + items.append({ + "key": definition.key, + "label": label, + "unit": definition.unit, + "profile_value": "" if profile_value is None else str(profile_value), # it is for display only + "profile_value_source": profile_value_source, + "user_value": "" if user_value is None else str(user_value), + "category": current_category + }) + + self.setItems(items) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 53b85a1dca..c2481af85e 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -138,6 +138,10 @@ class QualityManager(QObject): # Initialize the lookup tree for quality profiles with following structure: # -> -> # -> + + self._machine_variant_material_quality_type_to_quality_dict = {} # for quality lookup + self._machine_quality_type_to_quality_changes_dict = {} # for quality_changes lookup + quality_metadata_list = self._container_registry.findContainersMetadata(type = "quality") for metadata in quality_metadata_list: if metadata["id"] == "empty_quality": @@ -207,7 +211,6 @@ class QualityManager(QObject): if machine_definition_id not in self._machine_quality_type_to_quality_changes_dict: self._machine_quality_type_to_quality_changes_dict[machine_definition_id] = QualityNode() machine_node = self._machine_quality_type_to_quality_changes_dict[machine_definition_id] - machine_node.addQualityChangesMetadata(quality_type, metadata) def _updateMaps(self): diff --git a/cura/Settings/QualitySettingsModel.py b/cura/Settings/QualitySettingsModel.py deleted file mode 100644 index fb1aa9a6b2..0000000000 --- a/cura/Settings/QualitySettingsModel.py +++ /dev/null @@ -1,249 +0,0 @@ -# Copyright (c) 2017 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt - -from UM.Logger import Logger -import UM.Qt -from UM.Application import Application -from UM.Settings.ContainerRegistry import ContainerRegistry -import os - -from UM.i18n import i18nCatalog - - -class QualitySettingsModel(UM.Qt.ListModel.ListModel): - KeyRole = Qt.UserRole + 1 - LabelRole = Qt.UserRole + 2 - UnitRole = Qt.UserRole + 3 - ProfileValueRole = Qt.UserRole + 4 - ProfileValueSourceRole = Qt.UserRole + 5 - UserValueRole = Qt.UserRole + 6 - CategoryRole = Qt.UserRole + 7 - - def __init__(self, parent = None): - super().__init__(parent = parent) - - self._container_registry = ContainerRegistry.getInstance() - - self._extruder_id = None - self._extruder_definition_id = None - self._quality_id = None - self._material_id = None - self._i18n_catalog = None - - self.addRoleName(self.KeyRole, "key") - self.addRoleName(self.LabelRole, "label") - self.addRoleName(self.UnitRole, "unit") - self.addRoleName(self.ProfileValueRole, "profile_value") - self.addRoleName(self.ProfileValueSourceRole, "profile_value_source") - self.addRoleName(self.UserValueRole, "user_value") - self.addRoleName(self.CategoryRole, "category") - - self._empty_quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0] - - def setExtruderId(self, extruder_id): - if extruder_id != self._extruder_id: - self._extruder_id = extruder_id - self._update() - self.extruderIdChanged.emit() - - extruderIdChanged = pyqtSignal() - @pyqtProperty(str, fset = setExtruderId, notify = extruderIdChanged) - def extruderId(self): - return self._extruder_id - - def setExtruderDefinition(self, extruder_definition): - if extruder_definition != self._extruder_definition_id: - self._extruder_definition_id = extruder_definition - self._update() - self.extruderDefinitionChanged.emit() - - extruderDefinitionChanged = pyqtSignal() - @pyqtProperty(str, fset = setExtruderDefinition, notify = extruderDefinitionChanged) - def extruderDefinition(self): - return self._extruder_definition_id - - def setQuality(self, quality): - if quality != self._quality_id: - self._quality_id = quality - self._update() - self.qualityChanged.emit() - - qualityChanged = pyqtSignal() - @pyqtProperty(str, fset = setQuality, notify = qualityChanged) - def quality(self): - return self._quality_id - - def setMaterial(self, material): - if material != self._material_id: - self._material_id = material - self._update() - self.materialChanged.emit() - - materialChanged = pyqtSignal() - @pyqtProperty(str, fset = setMaterial, notify = materialChanged) - def material(self): - return self._material_id - - def _update(self): - if not self._quality_id: - return - - items = [] - - definition_container = Application.getInstance().getGlobalContainerStack().getBottom() - - containers = self._container_registry.findInstanceContainers(id = self._quality_id) - if not containers: - Logger.log("w", "Could not find a quality container with id %s", self._quality_id) - return - - quality_container = None - quality_changes_container = None - - if containers[0].getMetaDataEntry("type") == "quality": - quality_container = containers[0] - else: - quality_changes_container = containers[0] - - if quality_changes_container.getMetaDataEntry("quality_type") == self._empty_quality.getMetaDataEntry("quality_type"): - quality_container = self._empty_quality - else: - criteria = { - "type": "quality", - "quality_type": quality_changes_container.getMetaDataEntry("quality_type"), - "definition": quality_changes_container.getDefinition().getId() - } - - quality_container = self._container_registry.findInstanceContainers(**criteria) - if not quality_container: - Logger.log("w", "Could not find a quality container matching quality changes %s", quality_changes_container.getId()) - return - - quality_container = quality_container[0] - - quality_type = quality_container.getMetaDataEntry("quality_type") - - if quality_type == "not_supported": - containers = [] - else: - definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(quality_container.getDefinition()) - definition = quality_container.getDefinition() - - # Check if the definition container has a translation file. - definition_suffix = ContainerRegistry.getMimeTypeForContainer(type(definition)).preferredSuffix - catalog = i18nCatalog(os.path.basename(definition_id + "." + definition_suffix)) - if catalog.hasTranslationLoaded(): - self._i18n_catalog = catalog - - for file_name in quality_container.getDefinition().getInheritedFiles(): - catalog = i18nCatalog(os.path.basename(file_name)) - if catalog.hasTranslationLoaded(): - self._i18n_catalog = catalog - - criteria = {"type": "quality", "quality_type": quality_type, "definition": definition_id} - - if self._material_id and self._material_id != "empty_material": - criteria["material"] = self._material_id - - criteria["extruder"] = self._extruder_id - - containers = self._container_registry.findInstanceContainers(**criteria) - if not containers: - # Try again, this time without extruder - new_criteria = criteria.copy() - new_criteria.pop("extruder") - containers = self._container_registry.findInstanceContainers(**new_criteria) - - if not containers and "material" in criteria: - # Try again, this time without material - criteria.pop("material", None) - containers = self._container_registry.findInstanceContainers(**criteria) - - if not containers: - # Try again, this time without material or extruder - criteria.pop("extruder") # "material" has already been popped - containers = self._container_registry.findInstanceContainers(**criteria) - - if not containers: - Logger.log("w", "Could not find any quality containers matching the search criteria %s" % str(criteria)) - return - - if quality_changes_container: - if quality_type == "not_supported": - criteria = {"type": "quality_changes", "quality_type": quality_type, "name": quality_changes_container.getName()} - else: - criteria = {"type": "quality_changes", "quality_type": quality_type, "definition": definition_id, "name": quality_changes_container.getName()} - if self._extruder_definition_id != "": - extruder_definitions = self._container_registry.findDefinitionContainers(id = self._extruder_definition_id) - if extruder_definitions: - criteria["extruder"] = Application.getInstance().getMachineManager().getQualityDefinitionId(extruder_definitions[0]) - criteria["name"] = quality_changes_container.getName() - else: - criteria["extruder"] = None - - changes = self._container_registry.findInstanceContainers(**criteria) - if changes: - containers.extend(changes) - - global_container_stack = Application.getInstance().getGlobalContainerStack() - - current_category = "" - for definition in definition_container.findDefinitions(): - if definition.type == "category": - current_category = definition.label - if self._i18n_catalog: - current_category = self._i18n_catalog.i18nc(definition.key + " label", definition.label) - continue - - profile_value = None - profile_value_source = "" - for container in containers: - new_value = container.getProperty(definition.key, "value") - - if new_value is not None: - profile_value_source = container.getMetaDataEntry("type") - profile_value = new_value - - # Global tab should use resolve (if there is one) - if not self._extruder_id: - resolve_value = global_container_stack.getProperty(definition.key, "resolve") - if resolve_value is not None and profile_value is not None and profile_value_source != "quality_changes": - profile_value = resolve_value - - user_value = None - if not self._extruder_id: - user_value = global_container_stack.getTop().getProperty(definition.key, "value") - else: - extruder_stack = self._container_registry.findContainerStacks(id = self._extruder_id) - if extruder_stack: - user_value = extruder_stack[0].getTop().getProperty(definition.key, "value") - - if profile_value is None and user_value is None: - continue - - settable_per_extruder = global_container_stack.getProperty(definition.key, "settable_per_extruder") - # If a setting is not settable per extruder (global) and we're looking at an extruder tab, don't show this value. - if self._extruder_id != "" and not settable_per_extruder: - continue - - # If a setting is settable per extruder (not global) and we're looking at global tab, don't show this value. - if self._extruder_id == "" and settable_per_extruder: - continue - - label = definition.label - if self._i18n_catalog: - label = self._i18n_catalog.i18nc(definition.key + " label", label) - - items.append({ - "key": definition.key, - "label": label, - "unit": definition.unit, - "profile_value": "" if profile_value is None else str(profile_value), # it is for display only - "profile_value_source": profile_value_source, - "user_value": "" if user_value is None else str(user_value), - "category": current_category - }) - - self.setItems(items) diff --git a/resources/qml/Preferences/OldProfileTab.qml b/resources/qml/Preferences/OldProfileTab.qml deleted file mode 100644 index acebea3500..0000000000 --- a/resources/qml/Preferences/OldProfileTab.qml +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2016 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.1 -import QtQuick.Controls 1.1 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -Tab -{ - id: base - - property string extruderId: ""; - property string extruderDefinition: ""; - property string quality: ""; - property string material: ""; - - TableView - { - anchors.fill: parent - anchors.margins: UM.Theme.getSize("default_margin").width - - Component - { - id: itemDelegate - - UM.TooltipArea - { - property var setting: qualitySettings.getItem(styleData.row) - height: childrenRect.height - width: (parent != null) ? parent.width : 0 - text: (styleData.value.substr(0,1) == "=") ? styleData.value : "" - - Label - { - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - text: (styleData.value.substr(0,1) == "=") ? catalog.i18nc("@info:status", "Calculated") : styleData.value - font.strikeout: styleData.column == 1 && quality == Cura.MachineManager.globalQualityId && setting.user_value != "" - font.italic: setting.profile_value_source == "quality_changes" || (quality == Cura.MachineManager.globalQualityId && setting.user_value != "") - opacity: font.strikeout ? 0.5 : 1 - color: styleData.textColor - elide: Text.ElideRight - } - } - } - - TableViewColumn - { - role: "label" - title: catalog.i18nc("@title:column", "Setting") - width: (parent.width * 0.4) | 0 - delegate: itemDelegate - } - TableViewColumn - { - role: "profile_value" - title: catalog.i18nc("@title:column", "Profile") - width: (parent.width * 0.18) | 0 - delegate: itemDelegate - } - TableViewColumn - { - role: "user_value" - title: catalog.i18nc("@title:column", "Current"); - visible: quality == Cura.MachineManager.globalQualityId - width: (parent.width * 0.18) | 0 - delegate: itemDelegate - } - TableViewColumn - { - role: "unit" - title: catalog.i18nc("@title:column", "Unit") - width: (parent.width * 0.14) | 0 - delegate: itemDelegate - } - - section.property: "category" - section.delegate: Label - { - text: section - font.bold: true - } - - model: Cura.QualitySettingsModel - { - id: qualitySettings - extruderId: base.extruderId - extruderDefinition: base.extruderDefinition - quality: base.quality != null ? base.quality : "" - material: base.material != null ? base.material : "" - } - - SystemPalette { id: palette } - } -} diff --git a/resources/qml/Preferences/OldProfilesPage.qml b/resources/qml/Preferences/OldProfilesPage.qml deleted file mode 100644 index e3ba9b23a4..0000000000 --- a/resources/qml/Preferences/OldProfilesPage.qml +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright (c) 2016 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.1 -import QtQuick.Controls 1.1 -import QtQuick.Dialogs 1.2 - -import UM 1.2 as UM -import Cura 1.0 as Cura - -UM.ManagementPage -{ - id: base; - - title: catalog.i18nc("@title:tab", "Profiles"); - property var extrudersModel: Cura.ExtrudersModel{} - - model: Cura.QualityAndUserProfilesModel { } - - section.property: "readOnly" - section.delegate: Rectangle - { - height: childrenRect.height; - - Label - { - anchors.left: parent.left; - anchors.leftMargin: UM.Theme.getSize("default_lining").width; - text: section == "true" ? catalog.i18nc("@label", "Protected profiles") : catalog.i18nc("@label", "Custom profiles") - font.bold: true - } - } - - activeId: Cura.MachineManager.activeQualityId - activeIndex: { - for(var i = 0; i < model.rowCount(); i++) { - if (model.getItem(i).id == Cura.MachineManager.activeQualityId) { - return i; - } - } - return -1; - } - - function canCreateProfile() { - return base.currentItem && (base.currentItem.id == Cura.MachineManager.activeQualityId) && Cura.MachineManager.hasUserSettings; - } - - buttons: [ - Button - { - text: catalog.i18nc("@action:button", "Activate"); - iconName: "list-activate"; - enabled: base.currentItem != null ? base.currentItem.id != Cura.MachineManager.activeQualityId : false; - onClicked: - { - Cura.MachineManager.setActiveQuality(base.currentItem.id) - currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. - } - }, - - // Create button - Button - { - text: catalog.i18nc("@label", "Create") - enabled: base.canCreateProfile() && !Cura.MachineManager.stacksHaveErrors - visible: base.canCreateProfile() - iconName: "list-add"; - - onClicked: - { - newNameDialog.object = base.currentItem != null ? Cura.ContainerManager.makeUniqueName(base.currentItem.name) : ""; - newNameDialog.open(); - newNameDialog.selectText(); - } - }, - - // Duplicate button - Button - { - text: catalog.i18nc("@label", "Duplicate") - enabled: ! base.canCreateProfile() - visible: ! base.canCreateProfile() - iconName: "list-add"; - - onClicked: - { - newDuplicateNameDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name); - newDuplicateNameDialog.open(); - newDuplicateNameDialog.selectText(); - } - }, - - Button - { - text: catalog.i18nc("@action:button", "Remove"); - iconName: "list-remove"; - enabled: base.currentItem != null ? !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) : false; - onClicked: confirmDialog.open(); - }, - Button - { - text: catalog.i18nc("@action:button", "Rename"); - iconName: "edit-rename"; - enabled: base.currentItem != null ? !base.currentItem.readOnly : false; - onClicked: - { - renameDialog.open(); - renameDialog.selectText(); - } - }, - Button - { - text: catalog.i18nc("@action:button", "Import"); - iconName: "document-import"; - onClicked: importDialog.open(); - }, - Button - { - text: catalog.i18nc("@action:button", "Export") - iconName: "document-export" - onClicked: exportDialog.open() - enabled: currentItem != null && !base.currentItem.readOnly - } - ] - - scrollviewCaption: catalog.i18nc("@label %1 is printer name","Printer: %1").arg(Cura.MachineManager.activeMachineName) - - signal createProfile() - onCreateProfile: - { - newNameDialog.object = base.currentItem != null ? Cura.ContainerManager.makeUniqueName(base.currentItem.name) : ""; - newNameDialog.open(); - newNameDialog.selectText(); - } - - signal selectContainer(string name) - onSelectContainer: - { - objectList.currentIndex = objectList.model.find("name", name); - } - - Item { - visible: base.currentItem != null - anchors.fill: parent - - Label { - id: profileName - text: base.currentItem ? base.currentItem.name: "" - font: UM.Theme.getFont("large") - width: parent.width - elide: Text.ElideRight - } - - Flow { - id: currentSettingsActions - visible: currentItem && currentItem.id == Cura.MachineManager.activeQualityId - anchors.left: parent.left - anchors.right: parent.right - anchors.top: profileName.bottom - anchors.topMargin: UM.Theme.getSize("default_margin").height - - Button - { - text: { - return catalog.i18nc("@action:button", "Update profile with current settings/overrides"); - } - enabled: Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) - onClicked: Cura.ContainerManager.updateQualityChanges() - } - - Button - { - text: catalog.i18nc("@action:button", "Discard current changes"); - enabled: Cura.MachineManager.hasUserSettings - onClicked: Cura.ContainerManager.clearUserContainers(); - } - } - - Column { - id: profileNotices - anchors.top: currentSettingsActions.visible ? currentSettingsActions.bottom : currentSettingsActions.anchors.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - anchors.left: parent.left - anchors.right: parent.right - spacing: UM.Theme.getSize("default_margin").height - - Label { - id: defaultsMessage - visible: false - text: catalog.i18nc("@action:label", "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below.") - wrapMode: Text.WordWrap - width: parent.width - } - Label { - id: noCurrentSettingsMessage - visible: currentItem && currentItem.id == Cura.MachineManager.activeQualityId && !Cura.MachineManager.hasUserSettings - text: catalog.i18nc("@action:label", "Your current settings match the selected profile.") - wrapMode: Text.WordWrap - width: parent.width - } - } - - TabView - { - anchors.left: parent.left - anchors.top: profileNotices.visible ? profileNotices.bottom : profileNotices.anchors.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - anchors.right: parent.right - anchors.bottom: parent.bottom - - currentIndex: Cura.ExtruderManager.extruderCount > 0 ? Cura.ExtruderManager.activeExtruderIndex + 1 : 0 - - ProfileTab - { - title: catalog.i18nc("@title:tab", "Global Settings"); - quality: base.currentItem != null ? base.currentItem.id : ""; - material: Cura.MachineManager.allActiveMaterialIds[Cura.MachineManager.activeMachineId] - } - - Repeater - { - model: base.extrudersModel - - ProfileTab - { - title: model.name; - extruderId: model.id; - extruderDefinition: model.definition; - quality: base.currentItem != null ? base.currentItem.id : ""; - material: Cura.MachineManager.allActiveMaterialIds[model.id] - } - } - } - } - - Item - { - UM.I18nCatalog { id: catalog; name: "cura"; } - - UM.ConfirmRemoveDialog - { - id: confirmDialog - object: base.currentItem != null ? base.currentItem.name : "" - onYes: - { - var name = base.currentItem.name; - Cura.ContainerManager.removeQualityChanges(name) - if(Cura.MachineManager.activeQualityName == name) - { - Cura.MachineManager.setActiveQuality(base.model.getItem(0).name) - } - objectList.currentIndex = -1 //Reset selection. - } - } - - UM.RenameDialog - { - title: catalog.i18nc("@title:window", "Rename Profile") - id: renameDialog; - object: base.currentItem != null ? base.currentItem.name : "" - onAccepted: - { - Cura.ContainerManager.renameQualityChanges(base.currentItem.name, newName) - objectList.currentIndex = -1 //Reset selection. - } - } - - // Dialog to request a name when creating a new profile - UM.RenameDialog - { - title: catalog.i18nc("@title:window", "Create Profile") - id: newNameDialog; - object: ""; - onAccepted: - { - var selectedContainer = Cura.ContainerManager.createQualityChanges(newName); - base.selectContainer(selectedContainer); - objectList.currentIndex = -1 //Reset selection. - } - } - - // Dialog to request a name when duplicating a new profile - UM.RenameDialog - { - title: catalog.i18nc("@title:window", "Duplicate Profile") - id: newDuplicateNameDialog; - object: ""; - onAccepted: - { - var selectedContainer = Cura.ContainerManager.duplicateQualityOrQualityChanges(base.currentItem.name, newName); - base.selectContainer(selectedContainer); - objectList.currentIndex = -1 //Reset selection. - } - } - - MessageDialog - { - id: messageDialog - title: catalog.i18nc("@window:title", "Import Profile"); - standardButtons: StandardButton.Ok - modality: Qt.ApplicationModal - } - - FileDialog - { - id: importDialog; - title: catalog.i18nc("@title:window", "Import Profile"); - selectExisting: true; - nameFilters: base.model.getFileNameFilters("profile_reader") - folder: CuraApplication.getDefaultPath("dialog_profile_path") - onAccepted: - { - var result = Cura.ContainerManager.importProfile(fileUrl); - messageDialog.text = result.message - if(result.status == "ok") - { - messageDialog.icon = StandardIcon.Information - } - else if(result.status == "duplicate") - { - messageDialog.icon = StandardIcon.Warning - } - else - { - messageDialog.icon = StandardIcon.Critical - } - messageDialog.open() - CuraApplication.setDefaultPath("dialog_profile_path", folder) - } - } - - FileDialog - { - id: exportDialog; - title: catalog.i18nc("@title:window", "Export Profile"); - selectExisting: false; - nameFilters: base.model.getFileNameFilters("profile_writer") - folder: CuraApplication.getDefaultPath("dialog_profile_path") - onAccepted: - { - var containers = Cura.ContainerManager.findInstanceContainers({"type": "quality_changes", "name": base.currentItem.name}) - var result = Cura.ContainerManager.exportProfile(containers, fileUrl, selectedNameFilter) - - if(result && result.status == "error") - { - messageDialog.icon = StandardIcon.Critical - messageDialog.text = result.message - messageDialog.open() - } - - // else pop-up Message thing from python code - CuraApplication.setDefaultPath("dialog_profile_path", folder) - } - } - } -} diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml index 47446c82c2..0ea84dbc83 100644 --- a/resources/qml/Preferences/ProfileTab.qml +++ b/resources/qml/Preferences/ProfileTab.qml @@ -11,10 +11,8 @@ Tab { id: base - property string extruderId: ""; - property string extruderDefinition: ""; - property string quality: ""; - property string material: ""; + property string extruderPosition: ""; + property var quality: null; TableView { @@ -38,8 +36,8 @@ Tab anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.right: parent.right text: (styleData.value.substr(0,1) == "=") ? catalog.i18nc("@info:status", "Calculated") : styleData.value - font.strikeout: styleData.column == 1 && quality == Cura.MachineManager.globalQualityId && setting.user_value != "" - font.italic: setting.profile_value_source == "quality_changes" || (quality == Cura.MachineManager.globalQualityId && setting.user_value != "") + font.strikeout: styleData.column == 1 && setting.user_value != "" // TODO && quality == Cura.MachineManager.globalQualityId + font.italic: setting.profile_value_source == "quality_changes" || (setting.user_value != "") // TODO: (setting.user_value != "" && quality == Cura.MachineManager.globalQualityId) opacity: font.strikeout ? 0.5 : 1 color: styleData.textColor elide: Text.ElideRight @@ -65,7 +63,7 @@ Tab { role: "user_value" title: catalog.i18nc("@title:column", "Current"); - visible: quality == Cura.MachineManager.globalQualityId + visible: true // TODO quality == Cura.MachineManager.globalQualityId width: (parent.width * 0.18) | 0 delegate: itemDelegate } @@ -87,10 +85,8 @@ Tab model: Cura.QualitySettingsModel { id: qualitySettings - extruderId: base.extruderId - extruderDefinition: base.extruderDefinition + extruderPosition: base.extruderPosition quality: base.quality != null ? base.quality : "" - material: base.material != null ? base.material : "" } SystemPalette { id: palette } diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index df5f4faa33..f2a442debe 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -14,6 +14,7 @@ Item { id: base property var resetEnabled: false // Keep PreferencesDialog happy + property var extrudersModel: Cura.ExtrudersModel{} UM.I18nCatalog { id: catalog; name: "cura"; } @@ -35,6 +36,17 @@ Item text: catalog.i18nc("@title:tab", "Profiles") } + property var hasCurrentItem: qualityListView.currentItem != null + + property var currentItem: { + var current_index = qualityListView.currentIndex; + return qualitiesModel.getItem(current_index); + } + + property var isCurrentItemActivated: { + // TODO + } + Row // Button Row { id: buttonRow @@ -50,8 +62,7 @@ Item { text: catalog.i18nc("@action:button", "Activate") iconName: "list-activate" - //enabled: base.currentItem != null ? base.currentItem.id != Cura.MachineManager.activeQualityId : false; - enabled: true // TODO + enabled: base.currentItem != null ? base.currentItem.name != Cura.MachineManager.activeQualityOrQualityChangesName : false; onClicked: { // TODO } @@ -259,6 +270,7 @@ Item } + // details panel on the right Item { id: detailsPanel @@ -283,11 +295,89 @@ Item height: childrenRect.height Label { - text: "TODO" // TODO + text: base.currentItem.name // TODO font: UM.Theme.getFont("large") } } + Flow { + id: currentSettingsActions + visible: true // TODO //currentItem && currentItem.id == Cura.MachineManager.activeQualityId + anchors.left: parent.left + anchors.right: parent.right + anchors.top: profileName.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + + Button + { + text: { + return catalog.i18nc("@action:button", "Update profile with current settings/overrides"); + } + enabled: Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) + onClicked: Cura.ContainerManager.updateQualityChanges() + } + + Button + { + text: catalog.i18nc("@action:button", "Discard current changes"); + enabled: Cura.MachineManager.hasUserSettings + onClicked: Cura.ContainerManager.clearUserContainers(); + } + } + + Column { + id: profileNotices + anchors.top: currentSettingsActions.visible ? currentSettingsActions.bottom : currentSettingsActions.anchors.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.left: parent.left + anchors.right: parent.right + spacing: UM.Theme.getSize("default_margin").height + + Label { + id: defaultsMessage + visible: false + text: catalog.i18nc("@action:label", "This profile uses the defaults specified by the printer, so it has no settings/overrides in the list below.") + wrapMode: Text.WordWrap + width: parent.width + } + Label { + id: noCurrentSettingsMessage + visible: currentItem && currentItem.id == Cura.MachineManager.activeQualityId && !Cura.MachineManager.hasUserSettings + text: catalog.i18nc("@action:label", "Your current settings match the selected profile.") + wrapMode: Text.WordWrap + width: parent.width + } + } + + + TabView + { + anchors.left: parent.left + anchors.top: profileNotices.visible ? profileNotices.bottom : profileNotices.anchors.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.right: parent.right + anchors.bottom: parent.bottom + + currentIndex: 0 + + ProfileTab + { + title: catalog.i18nc("@title:tab", "Global Settings"); + quality: base.currentItem; + } + + Repeater + { + model: base.extrudersModel + + ProfileTab + { + title: model.name; + extruderPosition: model.index; + quality: base.currentItem; + } + } + } } } } From 8efe13a55ab1e13ed6c2b57170ab4d455c545e2d Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 19 Feb 2018 15:24:58 +0100 Subject: [PATCH 108/371] CURA-4606 fix profiles page Active button --- cura/Settings/MachineManager.py | 2 ++ resources/qml/Menus/ProfileMenu.qml | 6 +++--- resources/qml/Preferences/ProfilesPage.qml | 13 ++++++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 3c35aaad64..68fbf19c13 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1148,6 +1148,7 @@ class MachineManager(QObject): def _setEmptyQuality(self): self._current_quality_group = None + self._current_quality_changes_group = None self._global_container_stack.quality = self._empty_quality_container self._global_container_stack.qualityChanges = self._empty_quality_changes_container for extruder in self._global_container_stack.extruders.values(): @@ -1158,6 +1159,7 @@ class MachineManager(QObject): def _setQualityGroup(self, quality_group, empty_quality_changes = True): self._current_quality_group = quality_group + self._current_quality_changes_group = None # Set quality and quality_changes for the GlobalStack self._global_container_stack.quality = quality_group.node_for_global.getContainer() diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index 8d26bfc982..5924ad5322 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -19,7 +19,7 @@ Menu { text: (model.layer_height != "") ? model.name + " - " + model.layer_height : model.name checkable: true - checked: Cura.MachineManager.activeQualityGroup && (Cura.MachineManager.activeQualityGroup.getName() == model.name) + checked: Cura.MachineManager.activeQualityOrQualityChangesName == model.name exclusiveGroup: group onTriggered: { Cura.MachineManager.setQualityGroup(model.quality_group) @@ -52,9 +52,9 @@ Menu { text: model.name checkable: model.available - checked: Cura.MachineManager.activeQualityChangesId == model.id // TODO: fix for new + checked: Cura.MachineManager.activeQualityOrQualityChangesName == model.name exclusiveGroup: group - onTriggered: Cura.MachineManager.setActiveQuality(model.id) // TODO: fix for new + onTriggered: Cura.MachineManager.setQualityChangesGroup(model.quality_changes_group) } onObjectAdded: diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index f2a442debe..0424dd823f 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -44,7 +44,10 @@ Item } property var isCurrentItemActivated: { - // TODO + if (!base.currentItem) { + return false; + } + return base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName; } Row // Button Row @@ -62,9 +65,13 @@ Item { text: catalog.i18nc("@action:button", "Activate") iconName: "list-activate" - enabled: base.currentItem != null ? base.currentItem.name != Cura.MachineManager.activeQualityOrQualityChangesName : false; + enabled: !isCurrentItemActivated onClicked: { - // TODO + if (base.currentItem.is_read_only) { + Cura.MachineManager.setQualityGroup(base.currentItem.quality_group); + } else { + Cura.MachineManager.setQualityChangesGroup(base.currentItem.quality_changes_group); + } } } From 51062a4784ee9901941f95c22d42f6a7ee7bbfdb Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 15 Feb 2018 16:39:37 +0100 Subject: [PATCH 109/371] Add a button to open the configuration folder. --- cura/CrashHandler.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index 24df54b74e..d74b48a53a 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -14,8 +14,9 @@ import urllib.request import urllib.error import shutil -from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QFile +from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QUrl from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox, QCheckBox, QPushButton +from PyQt5.QtGui import QDesktopServices from UM.Application import Application from UM.Logger import Logger @@ -91,7 +92,7 @@ class CrashHandler: label = QLabel() label.setText(catalog.i18nc("@label crash message", """

    A fatal error has occurred.

    Unfortunately, Cura encountered an unrecoverable error during start up. It was possibly caused by some incorrect configuration files. We suggest to backup and reset your configuration.

    -

    Your backup can be found in your Configuration folder.

    +

    Backups can be found in the configuration folder.

    Please send us this Crash Report to fix the problem.

    """)) label.setWordWrap(True) @@ -105,8 +106,13 @@ class CrashHandler: show_details_button.setMaximumWidth(200) show_details_button.clicked.connect(self._showDetailedReport) + show_configuration_folder_button = QPushButton(catalog.i18nc("@action:button", "Show configuration folder"), dialog) + show_configuration_folder_button.setMaximumWidth(200) + show_configuration_folder_button.clicked.connect(self._showConfigurationFolder) + layout.addWidget(self._send_report_checkbox) layout.addWidget(show_details_button) + layout.addWidget(show_configuration_folder_button) # "backup and start clean" and "close" buttons buttons = QDialogButtonBox() @@ -182,6 +188,10 @@ class CrashHandler: self.early_crash_dialog.close() + def _showConfigurationFolder(self): + path = Resources.getConfigStoragePath(); + QDesktopServices.openUrl(QUrl.fromLocalFile( path )) + def _showDetailedReport(self): self.dialog.exec_() From 3cf16fd34b3b26b442f5aa8142660460787855ef Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 19 Feb 2018 15:37:08 +0100 Subject: [PATCH 110/371] Removed sending of material profiles. It takes a godawfull long time and the machine ignores most of them anyway. --- plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py index 647a7f822c..87d4b9ec0a 100644 --- a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py @@ -419,8 +419,6 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): self._authentication_failed_message.show() elif status_code == 200: self.setAuthenticationState(AuthState.Authenticated) - # Now we know for sure that we are authenticated, send the material profiles to the machine. - self._sendMaterialProfiles() def _checkAuthentication(self): Logger.log("d", "Checking if authentication is correct for id %s and key %s", self._authentication_id, self._getSafeAuthKey()) From 7a78f9821f6fa04a963f4ff730dc135be72f7e6e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 19 Feb 2018 16:15:35 +0100 Subject: [PATCH 111/371] CURA-4606 fixed Create profile --- .../Machines/Models/QualityManagementModel.py | 2 +- cura/Machines/Models/QualityProfilesModel.py | 1 + cura/Machines/Models/QualitySettingsModel.py | 2 ++ cura/Machines/QualityManager.py | 6 ++++ cura/Settings/ContainerManager.py | 16 ++++++---- resources/qml/Preferences/ProfilesPage.qml | 32 +++++++++++++------ 6 files changed, 42 insertions(+), 17 deletions(-) diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py index 589fec3440..cf7a163d9c 100644 --- a/cura/Machines/Models/QualityManagementModel.py +++ b/cura/Machines/Models/QualityManagementModel.py @@ -27,7 +27,7 @@ class QualityManagementModel(ListModel): self._quality_manager = CuraApplication.getInstance()._quality_manager self._machine_manager.globalContainerChanged.connect(self._update) - #self._quality_manager.materialsUpdated.connect(self._update) # TODO + self._quality_manager.qualitiesUpdated.connect(self._update) self._update() diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index 19262bf75a..11127190e1 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -37,6 +37,7 @@ class QualityProfilesModel(ListModel): Application.getInstance().getMachineManager().activeQualityGroupChanged.connect(self._update) self._quality_manager = Application.getInstance()._quality_manager + self._quality_manager.qualitiesUpdated.connect(self._update) self._layer_height_unit = "" # This is cached diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index d3a177c3eb..6353ec841e 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -26,6 +26,7 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): self._container_registry = ContainerRegistry.getInstance() self._application = Application.getInstance() + self._quality_manager = self._application._quality_manager self._extruder_position = "" self._quality = None @@ -42,6 +43,7 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): self._empty_quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0] self._update() + self._quality_manager.qualitiesUpdated.connect(self._update) def setExtruderPosition(self, extruder_position): if extruder_position != self._extruder_position: diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index c2481af85e..a5457344f1 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -1,5 +1,6 @@ from typing import Optional +from PyQt5.Qt import pyqtSignal from PyQt5.QtCore import QObject, QTimer from UM.Application import Application @@ -111,6 +112,8 @@ class QualityNode(ContainerNode): class QualityManager(QObject): + qualitiesUpdated = pyqtSignal() + def __init__(self, container_registry, parent = None): super().__init__(parent) self._application = Application.getInstance() @@ -213,6 +216,9 @@ class QualityManager(QObject): machine_node = self._machine_quality_type_to_quality_changes_dict[machine_definition_id] machine_node.addQualityChangesMetadata(quality_type, metadata) + Logger.log("d", "Lookup tables updated.") + self.qualitiesUpdated.emit() + def _updateMaps(self): self.initialize() diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index c420f5b49e..f6ce1bfaf7 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -398,16 +398,16 @@ class ContainerManager(QObject): # stack and clear the user settings. # # \return \type{bool} True if the operation was successfully, False if not. - @pyqtSlot(str, result = bool) + @pyqtSlot(str) def createQualityChanges(self, base_name): global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: - return False + return active_quality_name = self._machine_manager.activeQualityName if active_quality_name == "": Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) - return False + return self._machine_manager.blurSettings.emit() if base_name is None or base_name == "": @@ -416,7 +416,7 @@ class ContainerManager(QObject): # Go through the active stacks and create quality_changes containers from the user containers. for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): - user_container = stack.getTop() + user_container = stack.userChanges quality_container = stack.quality quality_changes_container = stack.qualityChanges if not quality_container or not quality_changes_container: @@ -431,10 +431,12 @@ class ContainerManager(QObject): self._performMerge(new_changes, user_container) self._container_registry.addContainer(new_changes) - stack.replaceContainer(stack.getContainerIndex(quality_changes_container), new_changes) + #stack.replaceContainer(stack.getContainerIndex(quality_changes_container), new_changes) - self._machine_manager.activeQualityChanged.emit() - return True + #self._machine_manager.activeQualityChanged.emit() + + #self._machine_manager.activeQualityGroupChanged.emit() + #self._machine_manager.activeQualityChangesGroupChanged.emit() ## Remove all quality changes containers matching a specified name. # diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 0424dd823f..5452648187 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -50,6 +50,10 @@ Item return base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName; } + property var canCreateProfile: { + return isCurrentItemActivated && Cura.MachineManager.hasUserSettings; + } + Row // Button Row { id: buttonRow @@ -80,13 +84,13 @@ Item { text: catalog.i18nc("@label", "Create") iconName: "list-add" - //enabled: base.canCreateProfile() && !Cura.MachineManager.stacksHaveErrors - enabled: true // TODO - //visible: base.canCreateProfile() - visible: true // TODO + enabled: base.canCreateProfile && !Cura.MachineManager.stacksHaveErrors + visible: base.canCreateProfile onClicked: { - // TODO + newNameDialog.object = base.currentItem != null ? Cura.ContainerManager.makeUniqueName(Cura.MachineManager.activeQualityOrQualityChangesName) : ""; + newNameDialog.open(); + newNameDialog.selectText(); } } @@ -95,10 +99,8 @@ Item { text: catalog.i18nc("@label", "Duplicate") iconName: "list-add" - //enabled: ! base.canCreateProfile() - enabled: true // TODO - //visible: ! base.canCreateProfile() - visible: true // TODO + enabled: !base.canCreateProfile + visible: !base.canCreateProfile onClicked: { // TODO @@ -153,6 +155,18 @@ Item } + // Dialog to request a name when creating a new profile + UM.RenameDialog + { + title: catalog.i18nc("@title:window", "Create Profile") + id: newNameDialog; + object: ""; + onAccepted: + { + var selectedContainer = Cura.ContainerManager.createQualityChanges(newName); + objectList.currentIndex = -1 //Reset selection. + } + } Item { id: contentsItem From bd10f23311d1738c7d5487117f414289fe941820 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 19 Feb 2018 16:47:04 +0100 Subject: [PATCH 112/371] CURA-4606 reimplemented duplicate profile --- cura/Machines/ContainerGroup.py | 10 +- cura/Settings/ContainerManager.py | 108 ++++----------------- resources/qml/Preferences/ProfilesPage.qml | 20 +++- 3 files changed, 46 insertions(+), 92 deletions(-) diff --git a/cura/Machines/ContainerGroup.py b/cura/Machines/ContainerGroup.py index d1ceb81dec..b7ad634f3c 100644 --- a/cura/Machines/ContainerGroup.py +++ b/cura/Machines/ContainerGroup.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import List, Optional from PyQt5.Qt import QObject, pyqtSlot @@ -25,3 +25,11 @@ class ContainerGroup(QObject): for key in node.getContainer().getAllKeys(): result.add(key) return result + + def getAllNodes(self) -> List[ContainerNode]: + result = [] + if self.node_for_global is not None: + result.append(self.node_for_global) + for extruder_node in self.nodes_for_extruders.values(): + result.append(extruder_node) + return result diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index f6ce1bfaf7..f58dcab640 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -424,7 +424,8 @@ class ContainerManager(QObject): continue extruder_id = None if stack is global_stack else QualityManager.getInstance().getParentMachineDefinition(stack.getBottom()).getId() - new_changes = self._createQualityChanges(quality_container, unique_name, + quality_type = quality_container.getMetaDataEntry("quality_type") + new_changes = self._createQualityChanges(quality_type, unique_name, Application.getInstance().getGlobalContainerStack().getBottom(), extruder_id) self._performMerge(new_changes, quality_changes_container, clear_settings = False) @@ -526,91 +527,22 @@ class ContainerManager(QObject): self._machine_manager.activeQualityChanged.emit() return True - ## Duplicate a specified set of quality or quality_changes containers. - # - # This will search for containers matching the specified name. If the container is a "quality" type container, a new - # quality_changes container will be created with the specified quality as base. If the container is a "quality_changes" - # container, it is simply duplicated and renamed. - # - # \param quality_name The name of the quality to duplicate. - # - # \return A string containing the name of the duplicated containers, or an empty string if it failed. - @pyqtSlot(str, str, result = str) - def duplicateQualityOrQualityChanges(self, quality_name, base_name): - global_stack = Application.getInstance().getGlobalContainerStack() - if not global_stack or not quality_name: - return "" - machine_definition = global_stack.definition - - active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() - if active_stacks is None: - return "" - material_metadatas = [stack.material.getMetaData() for stack in active_stacks] - - result = self._duplicateQualityOrQualityChangesForMachineType(quality_name, base_name, - QualityManager.getInstance().getParentMachineDefinition(machine_definition), - material_metadatas) - return result[0].getName() if result else "" - - ## Duplicate a quality or quality changes profile specific to a machine type - # - # \param quality_name The name of the quality or quality changes container to duplicate. - # \param base_name The desired name for the new container. - # \param machine_definition The machine with the specific machine type. - # \param material_metadatas Metadata of materials - # \return List of duplicated quality profiles. - def _duplicateQualityOrQualityChangesForMachineType(self, quality_name: str, base_name: str, machine_definition: DefinitionContainer, material_metadatas: List[Dict[str, Any]]) -> List[InstanceContainer]: - Logger.log("d", "Attempting to duplicate the quality %s", quality_name) - - if base_name is None: - base_name = quality_name - # Try to find a Quality with the name. - container = QualityManager.getInstance().findQualityByName(quality_name, machine_definition, material_metadatas) - if container: - Logger.log("d", "We found a quality to duplicate.") - return self._duplicateQualityForMachineType(container, base_name, machine_definition) - Logger.log("d", "We found a quality_changes to duplicate.") - # Assume it is a quality changes. - return self._duplicateQualityChangesForMachineType(quality_name, base_name, machine_definition) - - # Duplicate a quality profile - def _duplicateQualityForMachineType(self, quality_container, base_name, machine_definition) -> List[InstanceContainer]: - if base_name is None: - base_name = quality_container.getName() - new_name = self._container_registry.uniqueName(base_name) - - new_change_instances = [] - - # Handle the global stack first. - global_changes = self._createQualityChanges(quality_container, new_name, machine_definition, None) - new_change_instances.append(global_changes) - self._container_registry.addContainer(global_changes) - - # Handle the extruders if present. - extruders = machine_definition.getMetaDataEntry("machine_extruder_trains") - if extruders: - for extruder_id in extruders: - extruder = extruders[extruder_id] - new_changes = self._createQualityChanges(quality_container, new_name, machine_definition, extruder) - new_change_instances.append(new_changes) - self._container_registry.addContainer(new_changes) - - return new_change_instances - - # Duplicate a quality changes container - def _duplicateQualityChangesForMachineType(self, quality_changes_name, base_name, machine_definition) -> List[InstanceContainer]: - new_change_instances = [] - for container in QualityManager.getInstance().findQualityChangesByName(quality_changes_name, - machine_definition): - base_id = container.getMetaDataEntry("extruder") - if not base_id: - base_id = container.getDefinition().getId() - new_unique_id = self._createUniqueId(base_id, base_name) - new_container = container.duplicate(new_unique_id, base_name) - new_change_instances.append(new_container) - self._container_registry.addContainer(new_container) - - return new_change_instances + @pyqtSlot(str, dict) + def duplicateQualityChanges(self, quality_changes_name, quality_model_item): + quality_group = quality_model_item["quality_group"] + quality_changes_group = quality_model_item["quality_changes_group"] + if quality_changes_group is None: + # create global quality changes only + new_quality_changes = self._createQualityChanges( + quality_group.quality_type, quality_changes_name, + Application.getInstance().getGlobalContainerStack().definition, + extruder_id = None) + self._container_registry.addContainer(new_quality_changes) + else: + for node in quality_changes_group.getAllNodes(): + container = node.getContainer() + new_id = self._container_registry.uniqueName(container.getId()) + self._container_registry.addContainer(container.duplicate(new_id, quality_changes_name)) @pyqtSlot("QVariant") def removeMaterial(self, material_node): @@ -832,14 +764,14 @@ class ContainerManager(QObject): # \param extruder_id # # \return A new quality_changes container with the specified container as base. - def _createQualityChanges(self, quality_container, new_name, machine_definition, extruder_id): + def _createQualityChanges(self, quality_type, new_name, machine_definition, extruder_id): base_id = machine_definition.getId() if extruder_id is None else extruder_id # Create a new quality_changes container for the quality. quality_changes = InstanceContainer(self._createUniqueId(base_id, new_name)) quality_changes.setName(new_name) quality_changes.addMetaDataEntry("type", "quality_changes") - quality_changes.addMetaDataEntry("quality_type", quality_container.getMetaDataEntry("quality_type")) + quality_changes.addMetaDataEntry("quality_type", quality_type) # If we are creating a container for an extruder, ensure we add that to the container if extruder_id is not None: diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 5452648187..096d37e50b 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -103,7 +103,9 @@ Item visible: !base.canCreateProfile onClicked: { - // TODO + newDuplicateNameDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name); + newDuplicateNameDialog.open(); + newDuplicateNameDialog.selectText(); } } @@ -154,8 +156,7 @@ Item } } - - // Dialog to request a name when creating a new profile + // Dialog to request a name when creating a new profile UM.RenameDialog { title: catalog.i18nc("@title:window", "Create Profile") @@ -168,6 +169,19 @@ Item } } + // Dialog to request a name when duplicating a new profile + UM.RenameDialog + { + title: catalog.i18nc("@title:window", "Duplicate Profile") + id: newDuplicateNameDialog; + object: ""; + onAccepted: + { + Cura.ContainerManager.duplicateQualityChanges(newName, base.currentItem); + objectList.currentIndex = -1 //Reset selection. + } + } + Item { id: contentsItem From faf02424a7add957291fa54b5c96e9e8e28fe7ba Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 16:50:18 +0100 Subject: [PATCH 113/371] WIP: Cleanup MachineManager --- cura/Settings/MachineManager.py | 201 -------------------------------- 1 file changed, 201 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 68fbf19c13..de8f6328f7 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -609,78 +609,6 @@ class MachineManager(QObject): if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved - ## set the active quality - # \param quality_id The quality_id of either a quality or a quality_changes - @pyqtSlot(str) - def setActiveQuality(self, quality_id: str, always_discard_changes = False): - with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): - self.blurSettings.emit() - - Logger.log("d", "Attempting to change the active quality to %s", quality_id) - - containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = quality_id) - if not containers or not self._global_container_stack: - return - - # Quality profile come in two flavours: type=quality and type=quality_changes - # If we found a quality_changes profile then look up its parent quality profile. - container_type = containers[0].get("type") - quality_name = containers[0]["name"] - quality_type = containers[0].get("quality_type") - - # Get quality container and optionally the quality_changes container. - if container_type == "quality": - new_quality_settings_list = self.determineQualityAndQualityChangesForQualityType(quality_type) - elif container_type == "quality_changes": - new_quality_settings_list = self._determineQualityAndQualityChangesForQualityChanges(quality_name) - else: - Logger.log("e", "Tried to set quality to a container that is not of the right type: {container_id}".format(container_id = containers[0]["id"])) - return - - # Check if it was at all possible to find new settings - if new_quality_settings_list is None: - return - - # check if any of the stacks have a not supported profile - # if that is the case, all stacks should have a not supported state (otherwise it will show quality_type normal) - has_not_supported_quality = False - - # check all stacks for not supported - for setting_info in new_quality_settings_list: - if setting_info["quality"].getMetaDataEntry("quality_type") == "not_supported": - has_not_supported_quality = True - break - - # set all stacks to not supported if that's the case - if has_not_supported_quality: - for setting_info in new_quality_settings_list: - setting_info["quality"] = self._empty_quality_container - - self._new_quality_containers.clear() - - # store the upcoming quality profile changes per stack for later execution - # this prevents re-slicing before the user has made a choice in the discard or keep dialog - # (see _executeDelayedActiveContainerStackChanges) - for setting_info in new_quality_settings_list: - stack = setting_info["stack"] - stack_quality = setting_info["quality"] - stack_quality_changes = setting_info["quality_changes"] - - self._new_quality_containers.append({ - "stack": stack, - "quality": stack_quality, - "quality_changes": stack_quality_changes - }) - - Logger.log("d", "Active quality changed") - - # show the keep/discard dialog after the containers have been switched. Otherwise, the default values on - # the dialog will be the those before the switching. - self._executeDelayedActiveContainerStackChanges() - - if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1 and not always_discard_changes: - Application.getInstance().discardOrKeepProfileChanges() - ## Used to update material and variant in the active container stack with a delay. # This delay prevents the stack from triggering a lot of signals (eventually resulting in slicing) # before the user decided to keep or discard any of their changes using the dialog. @@ -721,135 +649,6 @@ class MachineManager(QObject): self._new_buildplate_container = None self._new_variant_container = None - ## Determine the quality and quality changes settings for the current machine for a quality name. - # - # \param quality_name \type{str} the name of the quality. - # \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes". - @UM.FlameProfiler.profile - def determineQualityAndQualityChangesForQualityType(self, quality_type: str) -> List[Dict[str, Union["CuraContainerStack", InstanceContainer]]]: - quality_manager = QualityManager.getInstance() - result = [] - empty_quality_changes = self._empty_quality_changes_container - global_container_stack = self._global_container_stack - if not global_container_stack: - return [] - - global_machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition) - extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - - # find qualities for extruders - for extruder_stack in extruder_stacks: - material_metadata = extruder_stack.material.getMetaData() - - # TODO: fix this - if self._new_material_container and extruder_stack.getId() == self._active_container_stack.getId(): - material_metadata = self._new_material_container.getMetaData() - - quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material_metadata]) - - if not quality: - # No quality profile is found for this quality type. - quality = self._empty_quality_container - - result.append({ - "stack": extruder_stack, - "quality": quality, - "quality_changes": empty_quality_changes - }) - - # also find a global quality for the machine - global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [], global_quality = "True") - - # if there is not global quality but we're using a single extrusion machine, copy the quality of the first extruder - CURA-4482 - if not global_quality and len(extruder_stacks) == 1: - global_quality = result[0]["quality"] - - # if there is still no global quality, set it to empty (not supported) - if not global_quality: - global_quality = self._empty_quality_container - - result.append({ - "stack": global_container_stack, - "quality": global_quality, - "quality_changes": empty_quality_changes - }) - - return result - - ## Determine the quality and quality changes settings for the current machine for a quality changes name. - # - # \param quality_changes_name \type{str} the name of the quality changes. - # \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes". - def _determineQualityAndQualityChangesForQualityChanges(self, quality_changes_name: str) -> Optional[List[Dict[str, Union["CuraContainerStack", InstanceContainer]]]]: - result = [] - quality_manager = QualityManager.getInstance() - - global_container_stack = self._global_container_stack - global_machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition) - quality_changes_profiles = quality_manager.findQualityChangesByName(quality_changes_name, global_machine_definition) - - global_quality_changes = [qcp for qcp in quality_changes_profiles if qcp.getMetaDataEntry("extruder") is None] - if global_quality_changes: - global_quality_changes = global_quality_changes[0] - else: - Logger.log("e", "Could not find the global quality changes container with name %s", quality_changes_name) - return None - - # For the global stack, find a quality which matches the quality_type in - # the quality changes profile and also satisfies any material constraints. - quality_type = global_quality_changes.getMetaDataEntry("quality_type") - - extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - - # append the extruder quality changes - for extruder_stack in extruder_stacks: - extruder_definition = quality_manager.getParentMachineDefinition(extruder_stack.definition) - - quality_changes_list = [qcp for qcp in quality_changes_profiles if qcp.getMetaDataEntry("extruder") == extruder_definition.getId()] - - if quality_changes_list: - quality_changes = quality_changes_list[0] - else: - quality_changes = global_quality_changes - if not quality_changes: - quality_changes = self._empty_quality_changes_container - - material_metadata = extruder_stack.material.getMetaData() - - if self._new_material_container and self._active_container_stack.getId() == extruder_stack.getId(): - material_metadata = self._new_material_container.getMetaData() - - quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material_metadata]) - - if not quality: - # No quality profile found for this quality type. - quality = self._empty_quality_container - - result.append({ - "stack": extruder_stack, - "quality": quality, - "quality_changes": quality_changes - }) - - # append the global quality changes - global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, global_quality = "True") - - # if there is not global quality but we're using a single extrusion machine, copy the quality of the first extruder - CURA-4482 - if not global_quality and len(extruder_stacks) == 1: - global_quality = result[0]["quality"] - - # if still no global quality changes are found we set it to empty (not supported) - if not global_quality: - global_quality = self._empty_quality_container - - result.append({ - "stack": global_container_stack, - "quality": global_quality, - "quality_changes": global_quality_changes - }) - - return result - def _replaceQualityOrQualityChangesInStack(self, stack: "CuraContainerStack", container: "InstanceContainer", postpone_emit = False): # Disconnect the signal handling from the old container. container_type = container.getMetaDataEntry("type") From 1d4d592d454d202512441ea8b6bb07b55dab3bfa Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 19 Feb 2018 16:52:32 +0100 Subject: [PATCH 114/371] CURA-4790 Added weight properties to theme --- resources/themes/cura-light/theme.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index b7ab0000de..8eb874334a 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -6,47 +6,57 @@ "fonts": { "large": { "size": 1.35, + "weight": 63, "bold": true, "family": "Noto Sans" }, "large_nonbold": { "size": 1.35, + "weight": 25, "family": "Noto Sans" }, "default": { "size": 1.0, + "weight": 25, "family": "Noto Sans" }, "default_bold": { "size": 1.0, + "weight": 63, "bold": true, "family": "Noto Sans" }, "default_italic": { "size": 1.15, + "weight": 25, "italic": true, "family": "Noto Sans" }, "small": { "size": 1.0, + "weight": 63, "bold": true, "family": "Noto Sans" }, "very_small": { "size": 1.0, + "weight": 25, "family": "Noto Sans" }, "button_tooltip": { "size": 1.0, + "weight": 25, "family": "Noto Sans" }, "setting_category": { "size": 1.15, + "weight": 63, "bold": true, "family": "Noto Sans" }, "action_button": { "size": 1.15, + "weight": 25, "bold": true, "family": "Noto Sans" } From 3546e54c95215be59e96c6a64be1b00753104f42 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 17:01:26 +0100 Subject: [PATCH 115/371] WIP: Cleanup --- .../Models/CustomQualityProfilesModel.py | 3 +-- cura/Machines/Models/QualityProfilesModel.py | 3 +-- cura/Machines/Models/QualitySettingsModel.py | 16 ++++++---------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/cura/Machines/Models/CustomQualityProfilesModel.py b/cura/Machines/Models/CustomQualityProfilesModel.py index 8b6fc2deb6..71a6b6c0f7 100644 --- a/cura/Machines/Models/CustomQualityProfilesModel.py +++ b/cura/Machines/Models/CustomQualityProfilesModel.py @@ -24,8 +24,7 @@ class CustomQualityProfilesModel(QualityProfilesModel): for key in sorted(quality_changes_group_dict): quality_changes_group = quality_changes_group_dict[key] - item = {"id": "TODO", # TODO: probably will be removed - "name": quality_changes_group.name, + item = {"name": quality_changes_group.name, "layer_height": "", "layer_height_without_unit": "", "available": quality_changes_group.is_available, diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index 11127190e1..b30daa85f6 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -58,8 +58,7 @@ class QualityProfilesModel(ListModel): layer_height = self._fetchLayerHeight(quality_group) - item = {"id": "TODO", # TODO: probably will be removed - "name": quality_group.name, + item = {"name": quality_group.name, "quality_type": quality_group.quality_type, "layer_height": layer_height + self._layer_height_unit, "layer_height_without_unit": layer_height, diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index 6353ec841e..6336549270 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -1,18 +1,14 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt -from UM.Logger import Logger -import UM.Qt from UM.Application import Application +from UM.Qt.ListModel import ListModel from UM.Settings.ContainerRegistry import ContainerRegistry -import os - -from UM.i18n import i18nCatalog -class QualitySettingsModel(UM.Qt.ListModel.ListModel): +class QualitySettingsModel(ListModel): KeyRole = Qt.UserRole + 1 LabelRole = Qt.UserRole + 2 UnitRole = Qt.UserRole + 3 @@ -45,13 +41,15 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): self._update() self._quality_manager.qualitiesUpdated.connect(self._update) + extruderPositionChanged = pyqtSignal() + qualityChanged = pyqtSignal() + def setExtruderPosition(self, extruder_position): if extruder_position != self._extruder_position: self._extruder_position = extruder_position self._update() self.extruderPositionChanged.emit() - extruderPositionChanged = pyqtSignal() @pyqtProperty(str, fset = setExtruderPosition, notify = extruderPositionChanged) def extruderPosition(self): return self._extruder_position @@ -62,7 +60,6 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): self._update() self.qualityChanged.emit() - qualityChanged = pyqtSignal() @pyqtProperty(dict, fset = setQuality, notify = qualityChanged) def quality(self): return self._quality @@ -122,7 +119,6 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): if profile_value is not None: break - user_value = None if not self._extruder_position: user_value = global_container_stack.userChanges.getProperty(definition.key, "value") else: From 251fe8a3a6975c83258237f7f58515601644ce9a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 17:03:30 +0100 Subject: [PATCH 116/371] WIP: Remove ContainerSettingModel --- cura/CuraApplication.py | 2 - cura/Settings/ContainerSettingsModel.py | 97 ------------------------- 2 files changed, 99 deletions(-) delete mode 100644 cura/Settings/ContainerSettingsModel.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 57054c5d3b..795c254d8c 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -81,7 +81,6 @@ from cura.Settings.MachineManager import MachineManager from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.UserChangesModel import UserChangesModel from cura.Settings.ExtrudersModel import ExtrudersModel -from cura.Settings.ContainerSettingsModel import ContainerSettingsModel from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel from cura.Settings.ContainerManager import ContainerManager @@ -942,7 +941,6 @@ class CuraApplication(QtApplication): qmlRegisterSingletonType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel", self.getMultiBuildPlateModel) qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer") qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") - qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") diff --git a/cura/Settings/ContainerSettingsModel.py b/cura/Settings/ContainerSettingsModel.py deleted file mode 100644 index 2c4bef6464..0000000000 --- a/cura/Settings/ContainerSettingsModel.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2016 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from UM.Application import Application -from UM.Qt.ListModel import ListModel - -from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot, QUrl - -from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.InstanceContainer import InstanceContainer -from UM.Settings.SettingFunction import SettingFunction - -class ContainerSettingsModel(ListModel): - LabelRole = Qt.UserRole + 1 - CategoryRole = Qt.UserRole + 2 - UnitRole = Qt.UserRole + 3 - ValuesRole = Qt.UserRole + 4 - - def __init__(self, parent = None): - super().__init__(parent) - self.addRoleName(self.LabelRole, "label") - self.addRoleName(self.CategoryRole, "category") - self.addRoleName(self.UnitRole, "unit") - self.addRoleName(self.ValuesRole, "values") - - self._container_ids = [] - self._containers = [] - - def _onPropertyChanged(self, key, property_name): - if property_name == "value": - self._update() - - def _update(self): - items = [] - - if len(self._container_ids) == 0: - return - - keys = [] - for container in self._containers: - keys = keys + list(container.getAllKeys()) - - keys = list(set(keys)) # remove duplicate keys - - for key in keys: - definition = None - category = None - values = [] - for container in self._containers: - instance = container.getInstance(key) - if instance: - definition = instance.definition - - # Traverse up to find the category - category = definition - while category.type != "category": - category = category.parent - - value = container.getProperty(key, "value") - if type(value) == SettingFunction: - values.append("=\u0192") - else: - values.append(container.getProperty(key, "value")) - else: - values.append("") - - items.append({ - "key": key, - "values": values, - "label": definition.label, - "unit": definition.unit, - "category": category.label - }) - items.sort(key = lambda k: (k["category"], k["key"])) - self.setItems(items) - - ## Set the ids of the containers which have the settings this model should list. - # Also makes sure the model updates when the containers have property changes - def setContainers(self, container_ids): - for container in self._containers: - container.propertyChanged.disconnect(self._onPropertyChanged) - - self._container_ids = container_ids - self._containers = [] - - for container_id in self._container_ids: - containers = ContainerRegistry.getInstance().findContainers(id = container_id) - if containers: - containers[0].propertyChanged.connect(self._onPropertyChanged) - self._containers.append(containers[0]) - - self._update() - - containersChanged = pyqtSignal() - @pyqtProperty("QVariantList", fset = setContainers, notify = containersChanged) - def containers(self): - return self.container_ids From c29f3130a7f8891e0e73932d2b99f9ee127c8cfd Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 19:55:09 +0100 Subject: [PATCH 117/371] WIP: Fix QualitySettingsModel --- cura/Machines/Models/QualitySettingsModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index 6336549270..a39396c324 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -60,7 +60,7 @@ class QualitySettingsModel(ListModel): self._update() self.qualityChanged.emit() - @pyqtProperty(dict, fset = setQuality, notify = qualityChanged) + @pyqtProperty("QVariantMap", fset = setQuality, notify = qualityChanged) def quality(self): return self._quality From 65e01d62033a99830861cc480aaa74e7c983a03a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 19:58:02 +0100 Subject: [PATCH 118/371] WIP: Refactor Profile management code --- cura/Machines/Models/QualitySettingsModel.py | 43 ++++++++++---------- resources/qml/Preferences/ProfileTab.qml | 6 +-- resources/qml/Preferences/ProfilesPage.qml | 41 ++++++++----------- 3 files changed, 40 insertions(+), 50 deletions(-) diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index a39396c324..e91897b632 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -20,14 +20,6 @@ class QualitySettingsModel(ListModel): def __init__(self, parent = None): super().__init__(parent = parent) - self._container_registry = ContainerRegistry.getInstance() - self._application = Application.getInstance() - self._quality_manager = self._application._quality_manager - - self._extruder_position = "" - self._quality = None - self._i18n_catalog = None - self.addRoleName(self.KeyRole, "key") self.addRoleName(self.LabelRole, "label") self.addRoleName(self.UnitRole, "unit") @@ -36,36 +28,43 @@ class QualitySettingsModel(ListModel): self.addRoleName(self.UserValueRole, "user_value") self.addRoleName(self.CategoryRole, "category") - self._empty_quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0] + self._container_registry = ContainerRegistry.getInstance() + self._application = Application.getInstance() + self._quality_manager = self._application._quality_manager + + self._extruder_position = "" + self._quality_item = None + self._i18n_catalog = None - self._update() self._quality_manager.qualitiesUpdated.connect(self._update) + self._update() + extruderPositionChanged = pyqtSignal() - qualityChanged = pyqtSignal() + qualityItemChanged = pyqtSignal() def setExtruderPosition(self, extruder_position): if extruder_position != self._extruder_position: self._extruder_position = extruder_position - self._update() self.extruderPositionChanged.emit() + self._update() @pyqtProperty(str, fset = setExtruderPosition, notify = extruderPositionChanged) def extruderPosition(self): return self._extruder_position - def setQuality(self, quality): - if quality != self._quality: - self._quality = quality + def setQualityItem(self, quality_item): + if quality_item != self._quality_item: + self._quality_item = quality_item + self.qualityItemChanged.emit() self._update() - self.qualityChanged.emit() - @pyqtProperty("QVariantMap", fset = setQuality, notify = qualityChanged) - def quality(self): - return self._quality + @pyqtProperty("QVariantMap", fset = setQualityItem, notify = qualityItemChanged) + def qualityItem(self): + return self._quality_item def _update(self): - if self._quality is None: + if self._quality_item is None: self.setItems([]) return @@ -74,8 +73,8 @@ class QualitySettingsModel(ListModel): global_container_stack = Application.getInstance().getGlobalContainerStack() definition_container = global_container_stack.definition - quality_group = self._quality["quality_group"] - quality_changes_group = self._quality["quality_changes_group"] + quality_group = self._quality_item["quality_group"] + quality_changes_group = self._quality_item["quality_changes_group"] if self._extruder_position == "": quality_node = quality_group.node_for_global diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml index 0ea84dbc83..5acbeecda9 100644 --- a/resources/qml/Preferences/ProfileTab.qml +++ b/resources/qml/Preferences/ProfileTab.qml @@ -11,8 +11,8 @@ Tab { id: base - property string extruderPosition: ""; - property var quality: null; + property string extruderPosition: "" + property var qualityItem: null TableView { @@ -86,7 +86,7 @@ Tab { id: qualitySettings extruderPosition: base.extruderPosition - quality: base.quality != null ? base.quality : "" + qualityItem: base.qualityItem } SystemPalette { id: palette } diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 096d37e50b..f675453d67 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -14,7 +14,7 @@ Item { id: base property var resetEnabled: false // Keep PreferencesDialog happy - property var extrudersModel: Cura.ExtrudersModel{} + property var extrudersModel: Cura.ExtrudersModel {} UM.I18nCatalog { id: catalog; name: "cura"; } @@ -24,14 +24,12 @@ Item Label { id: titleLabel - anchors { top: parent.top left: parent.left right: parent.right margins: 5 * screenScaleFactor } - font.pointSize: 18 text: catalog.i18nc("@title:tab", "Profiles") } @@ -160,12 +158,12 @@ Item UM.RenameDialog { title: catalog.i18nc("@title:window", "Create Profile") - id: newNameDialog; - object: ""; + id: newNameDialog + object: "" onAccepted: { var selectedContainer = Cura.ContainerManager.createQualityChanges(newName); - objectList.currentIndex = -1 //Reset selection. + qualityListView.currentIndex = -1 // TODO: Reset selection. } } @@ -173,12 +171,12 @@ Item UM.RenameDialog { title: catalog.i18nc("@title:window", "Duplicate Profile") - id: newDuplicateNameDialog; - object: ""; + id: newDuplicateNameDialog + object: "" onAccepted: { Cura.ContainerManager.duplicateQualityChanges(newName, base.currentItem); - objectList.currentIndex = -1 //Reset selection. + qualityListView.currentIndex = -1; // TODO: Reset selection. } } @@ -217,10 +215,7 @@ Item left: parent.left } visible: text != "" - text: { - // OLD STUFF - return catalog.i18nc("@label %1 is printer name", "Printer: %1").arg(Cura.MachineManager.activeMachineName); - } + text: catalog.i18nc("@label %1 is printer name", "Printer: %1").arg(Cura.MachineManager.activeMachineName) width: profileScrollView.width elide: Text.ElideRight } @@ -280,10 +275,8 @@ Item width: Math.floor((parent.width * 0.3)) text: model.name elide: Text.ElideRight - font.italic: { // TODO: make it easier - return model.name == Cura.MachineManager.activeQualityOrQualityChangesName; - } - color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; + font.italic: model.name == Cura.MachineManager.activeQualityOrQualityChangesName // TODO: make it easier + color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text } } @@ -345,9 +338,7 @@ Item Button { - text: { - return catalog.i18nc("@action:button", "Update profile with current settings/overrides"); - } + text: catalog.i18nc("@action:button", "Update profile with current settings/overrides") enabled: Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) onClicked: Cura.ContainerManager.updateQualityChanges() } @@ -397,8 +388,8 @@ Item ProfileTab { - title: catalog.i18nc("@title:tab", "Global Settings"); - quality: base.currentItem; + title: catalog.i18nc("@title:tab", "Global Settings") + qualityItem: base.currentItem } Repeater @@ -407,9 +398,9 @@ Item ProfileTab { - title: model.name; - extruderPosition: model.index; - quality: base.currentItem; + title: model.name + extruderPosition: model.index + qualityItem: base.currentItem } } } From 486bcae677763584019e92b05fec216d9c20bc2a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 20:21:02 +0100 Subject: [PATCH 119/371] WIP: Fix remove quality --- cura/Settings/ContainerManager.py | 49 ++++------------------ resources/qml/Preferences/ProfilesPage.qml | 27 ++++++++++-- 2 files changed, 30 insertions(+), 46 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index f58dcab640..c21e7899ed 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -439,49 +439,14 @@ class ContainerManager(QObject): #self._machine_manager.activeQualityGroupChanged.emit() #self._machine_manager.activeQualityChangesGroupChanged.emit() - ## Remove all quality changes containers matching a specified name. # - # This will search for quality_changes containers matching the supplied name and remove them. - # Note that if the machine specifies that qualities should be filtered by machine and/or material - # only the containers related to the active machine/material are removed. + # Remove the given quality changes group # - # \param quality_name The name of the quality changes to remove. - # - # \return \type{bool} True if successful, False if not. - @pyqtSlot(str, result = bool) - def removeQualityChanges(self, quality_name): - Logger.log("d", "Attempting to remove the quality change containers with name %s", quality_name) - containers_found = False - - if not quality_name: - return containers_found # Without a name we will never find a container to remove. - - # If the container that is being removed is the currently active quality, set another quality as the active quality - activate_quality = quality_name == self._machine_manager.activeQualityName - activate_quality_type = None - - global_stack = Application.getInstance().getGlobalContainerStack() - if not global_stack or not quality_name: - return "" - machine_definition = QualityManager.getInstance().getParentMachineDefinition(global_stack.getBottom()) - - for container in QualityManager.getInstance().findQualityChangesByName(quality_name, machine_definition): - containers_found = True - if activate_quality and not activate_quality_type: - activate_quality_type = container.getMetaDataEntry("quality") - self._container_registry.removeContainer(container.getId()) - - if not containers_found: - Logger.log("d", "Unable to remove quality containers, as we did not find any by the name of %s", quality_name) - - elif activate_quality: - definition_id = "fdmprinter" if not self._machine_manager.filterQualityByMachine else self._machine_manager.activeDefinitionId - containers = self._container_registry.findInstanceContainersMetadata(type = "quality", definition = definition_id, quality_type = activate_quality_type) - if containers: - self._machine_manager.setActiveQuality(containers[0]["id"]) - self._machine_manager.activeQualityChanged.emit() - - return containers_found + @pyqtSlot(QObject) + def removeQualityChangesGroup(self, quality_changes_group): + Logger.log("i", "Removing quality changes group [%s]", quality_changes_group.name) + for node in quality_changes_group.getAllNodes(): + self._container_registry.removeContainer(node.metadata["id"]) ## Rename a set of quality changes containers. # @@ -527,7 +492,7 @@ class ContainerManager(QObject): self._machine_manager.activeQualityChanged.emit() return True - @pyqtSlot(str, dict) + @pyqtSlot(str, "QVariantMap") def duplicateQualityChanges(self, quality_changes_name, quality_model_item): quality_group = quality_model_item["quality_group"] quality_changes_group = quality_model_item["quality_changes_group"] diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index f675453d67..a469426519 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -112,10 +112,10 @@ Item { text: catalog.i18nc("@action:button", "Remove") iconName: "list-remove" - //enabled: base.currentItem != null ? !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) : false; - enabled: true // TODO + enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated onClicked: { - // TODO + forceActiveFocus(); + confirmRemoveQualityDialog.open(); } } @@ -162,7 +162,7 @@ Item object: "" onAccepted: { - var selectedContainer = Cura.ContainerManager.createQualityChanges(newName); + Cura.ContainerManager.createQualityChanges(newName); qualityListView.currentIndex = -1 // TODO: Reset selection. } } @@ -180,6 +180,25 @@ Item } } + // Confirmation dialog for removing a profile + MessageDialog + { + id: confirmRemoveQualityDialog + + icon: StandardIcon.Question; + title: catalog.i18nc("@title:window", "Confirm Remove") + text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(base.currentItem.name) + standardButtons: StandardButton.Yes | StandardButton.No + modality: Qt.ApplicationModal + + onYes: + { + Cura.ContainerManager.removeQualityChangesGroup(base.currentItem.quality_changes_group); + // reset current item to the first if available + qualityListView.currentIndex = -1; + } + } + Item { id: contentsItem From 5b37de8adbc689093ae1330818a55038164b5ef8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 20:33:36 +0100 Subject: [PATCH 120/371] WIP: Fix quality renaming --- cura/Settings/ContainerManager.py | 38 ++++++-------------- resources/qml/Preferences/ProfilesPage.qml | 42 ++++++++++++++-------- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index c21e7899ed..9486fbbdee 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -458,39 +458,21 @@ class ContainerManager(QObject): # \param new_name The new name of the quality changes. # # \return True if successful, False if not. - @pyqtSlot(str, str, result = bool) - def renameQualityChanges(self, quality_name, new_name): - Logger.log("d", "User requested QualityChanges container rename of %s to %s", quality_name, new_name) - if not quality_name or not new_name: - return False - - if quality_name == new_name: - Logger.log("w", "Unable to rename %s to %s, because they are the same.", quality_name, new_name) - return True - - global_stack = Application.getInstance().getGlobalContainerStack() - if not global_stack: - return False - + @pyqtSlot(QObject, str) + def renameQualityChangesGroup(self, quality_changes_group, new_name): + Logger.log("i", "Renaming QualityChangesGroup[%s] to [%s]", quality_changes_group.name, new_name) self._machine_manager.blurSettings.emit() + if new_name == quality_changes_group.name: + Logger.log("i", "QualityChangesGroup name [%s] unchanged.", quality_changes_group.name) + return + new_name = self._container_registry.uniqueName(new_name) - - container_registry = self._container_registry - - containers_to_rename = self._container_registry.findInstanceContainersMetadata(type = "quality_changes", name = quality_name) - - for container in containers_to_rename: - stack_id = global_stack.getId() - if "extruder" in container: - stack_id = container["extruder"] - container_registry.renameContainer(container["id"], new_name, self._createUniqueId(stack_id, new_name)) - - if not containers_to_rename: - Logger.log("e", "Unable to rename %s, because we could not find the profile", quality_name) + for node in quality_changes_group.getAllNodes(): + node.getContainer().setName(new_name) self._machine_manager.activeQualityChanged.emit() - return True + self._machine_manager.activeQualityGroupChanged.emit() @pyqtSlot(str, "QVariantMap") def duplicateQualityChanges(self, quality_changes_name, quality_model_item): diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index a469426519..6c58a1e69d 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -86,9 +86,9 @@ Item visible: base.canCreateProfile onClicked: { - newNameDialog.object = base.currentItem != null ? Cura.ContainerManager.makeUniqueName(Cura.MachineManager.activeQualityOrQualityChangesName) : ""; - newNameDialog.open(); - newNameDialog.selectText(); + createQualityDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name); + createQualityDialog.open(); + createQualityDialog.selectText(); } } @@ -101,9 +101,9 @@ Item visible: !base.canCreateProfile onClicked: { - newDuplicateNameDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name); - newDuplicateNameDialog.open(); - newDuplicateNameDialog.selectText(); + duplicateQualityDialog.object = Cura.ContainerManager.makeUniqueName(base.currentItem.name); + duplicateQualityDialog.open(); + duplicateQualityDialog.selectText(); } } @@ -124,10 +124,11 @@ Item { text: catalog.i18nc("@action:button", "Rename") iconName: "edit-rename" - //enabled: base.currentItem != null ? !base.currentItem.readOnly : false; - enabled: true // TODO + enabled: base.hasCurrentItem && !base.currentItem.is_read_only onClicked: { - // TODO + renameQualityDialog.object = base.currentItem.name; + renameQualityDialog.open(); + renameQualityDialog.selectText(); } } @@ -157,26 +158,26 @@ Item // Dialog to request a name when creating a new profile UM.RenameDialog { + id: createQualityDialog title: catalog.i18nc("@title:window", "Create Profile") - id: newNameDialog object: "" onAccepted: { Cura.ContainerManager.createQualityChanges(newName); - qualityListView.currentIndex = -1 // TODO: Reset selection. + qualityListView.currentIndex = -1; // TODO: Reset selection. } } // Dialog to request a name when duplicating a new profile UM.RenameDialog { + id: duplicateQualityDialog title: catalog.i18nc("@title:window", "Duplicate Profile") - id: newDuplicateNameDialog object: "" onAccepted: { Cura.ContainerManager.duplicateQualityChanges(newName, base.currentItem); - qualityListView.currentIndex = -1; // TODO: Reset selection. + qualityListView.currentIndex = -1; // TODO: Reset selection. } } @@ -195,7 +196,20 @@ Item { Cura.ContainerManager.removeQualityChangesGroup(base.currentItem.quality_changes_group); // reset current item to the first if available - qualityListView.currentIndex = -1; + qualityListView.currentIndex = -1; // TODO: Reset selection. + } + } + + // Dialog to rename a quality profile + UM.RenameDialog + { + id: renameQualityDialog + title: catalog.i18nc("@title:window", "Rename Profile") + object: "" + onAccepted: + { + Cura.ContainerManager.renameQualityChangesGroup(base.currentItem.quality_changes_group, newName); + qualityListView.currentIndex = -1; // TODO: Reset selection. } } From d4db41503f991a1ee7d0ec5977a2bb843b2efff9 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 20:43:05 +0100 Subject: [PATCH 121/371] WIP: Cleanup ContainerManager --- cura/Settings/ContainerManager.py | 58 ++++++++----------------------- 1 file changed, 15 insertions(+), 43 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 9486fbbdee..d16bdca8a7 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -5,12 +5,11 @@ import copy import os.path import urllib.parse import uuid -from typing import Any, Dict, List, Union +from typing import Dict, Union from PyQt5.QtCore import QObject, QUrl, QVariant from UM.FlameProfiler import pyqtSlot from PyQt5.QtWidgets import QMessageBox -from UM.Util import parseBool from UM.PluginRegistry import PluginRegistry from UM.SaveFile import SaveFile @@ -22,7 +21,6 @@ from UM.Application import Application from UM.Settings.ContainerStack import ContainerStack from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.InstanceContainer import InstanceContainer -from cura.QualityManager import QualityManager from UM.MimeTypeDatabase import MimeTypeNotFoundError from UM.Settings.ContainerRegistry import ContainerRegistry @@ -30,6 +28,8 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.i18n import i18nCatalog from cura.Settings.ExtruderManager import ExtruderManager +from cura.Settings.ExtruderStack import ExtruderStack +from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch catalog = i18nCatalog("cura") @@ -183,32 +183,6 @@ class ContainerManager(QObject): def findInstanceContainers(self, criteria): return [entry["id"] for entry in self._container_registry.findInstanceContainersMetadata(**criteria)] - @pyqtSlot(str, result = bool) - def isContainerUsed(self, container_id): - Logger.log("d", "Checking if container %s is currently used", container_id) - # check if this is a material container. If so, check if any material with the same base is being used by any - # stacks. - container_ids_to_check = [container_id] - container_results = self._container_registry.findInstanceContainersMetadata(id = container_id, type = "material") - if container_results: - this_container = container_results[0] - material_base_file = this_container["id"] - if "base_file" in this_container: - material_base_file = this_container["base_file"] - # check all material container IDs with the same base - material_containers = self._container_registry.findInstanceContainersMetadata(base_file = material_base_file, - type = "material") - if material_containers: - container_ids_to_check = [container["id"] for container in material_containers] - - all_stacks = self._container_registry.findContainerStacks() - for stack in all_stacks: - for used_container_id in container_ids_to_check: - if used_container_id in [child.getId() for child in stack.getContainers()]: - Logger.log("d", "The container is in use by %s", stack.getId()) - return True - return False - @pyqtSlot(str, result = str) def makeUniqueName(self, original_name): return self._container_registry.uniqueName(original_name) @@ -423,11 +397,11 @@ class ContainerManager(QObject): Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) continue - extruder_id = None if stack is global_stack else QualityManager.getInstance().getParentMachineDefinition(stack.getBottom()).getId() + extruder_definition_id = None + if isinstance(stack, ExtruderStack): + extruder_definition_id = stack.definition.getId() quality_type = quality_container.getMetaDataEntry("quality_type") - new_changes = self._createQualityChanges(quality_type, unique_name, - Application.getInstance().getGlobalContainerStack().getBottom(), - extruder_id) + new_changes = self._createQualityChanges(quality_type, unique_name, global_stack, extruder_definition_id) self._performMerge(new_changes, quality_changes_container, clear_settings = False) self._performMerge(new_changes, user_container) @@ -476,14 +450,14 @@ class ContainerManager(QObject): @pyqtSlot(str, "QVariantMap") def duplicateQualityChanges(self, quality_changes_name, quality_model_item): + global_stack = Application.getInstance().getGlobalContainerStack() + quality_group = quality_model_item["quality_group"] quality_changes_group = quality_model_item["quality_changes_group"] if quality_changes_group is None: # create global quality changes only - new_quality_changes = self._createQualityChanges( - quality_group.quality_type, quality_changes_name, - Application.getInstance().getGlobalContainerStack().definition, - extruder_id = None) + new_quality_changes = self._createQualityChanges(quality_group.quality_type, quality_changes_name, + global_stack, extruder_id = None) self._container_registry.addContainer(new_quality_changes) else: for node in quality_changes_group.getAllNodes(): @@ -711,8 +685,8 @@ class ContainerManager(QObject): # \param extruder_id # # \return A new quality_changes container with the specified container as base. - def _createQualityChanges(self, quality_type, new_name, machine_definition, extruder_id): - base_id = machine_definition.getId() if extruder_id is None else extruder_id + def _createQualityChanges(self, quality_type, new_name, machine, extruder_id): + base_id = machine.definition.getId() if extruder_id is None else extruder_id # Create a new quality_changes container for the quality. quality_changes = InstanceContainer(self._createUniqueId(base_id, new_name)) @@ -725,10 +699,8 @@ class ContainerManager(QObject): quality_changes.addMetaDataEntry("extruder", extruder_id) # If the machine specifies qualities should be filtered, ensure we match the current criteria. - if not machine_definition.getMetaDataEntry("has_machine_quality"): - quality_changes.setDefinition("fdmprinter") - else: - quality_changes.setDefinition(QualityManager.getInstance().getParentMachineDefinition(machine_definition).getId()) + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + quality_changes.setDefinition(machine_definition_id) from cura.CuraApplication import CuraApplication quality_changes.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) From 3fffc2c6213af5769a2cfd7a261086c16cfef768 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 20:50:14 +0100 Subject: [PATCH 122/371] WIP: Cleanup old QualityManager --- cura/QualityManager.py | 36 ------------------------------ cura/Settings/ContainerManager.py | 2 +- plugins/3MFReader/ThreeMFReader.py | 16 +++++++------ 3 files changed, 10 insertions(+), 44 deletions(-) diff --git a/cura/QualityManager.py b/cura/QualityManager.py index 76a0c86a5f..358bf4e422 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -27,42 +27,6 @@ class QualityManager: __instance = None # type: "QualityManager" - ## Find a quality by name for a specific machine definition and materials. - # - # \param quality_name - # \param machine_definition (Optional) \type{DefinitionContainerInterface} If nothing is - # specified then the currently selected machine definition is used. - # \param material_containers_metadata If nothing is specified then the - # current set of selected materials is used. - # \return the matching quality container \type{InstanceContainer} - def findQualityByName(self, quality_name: str, machine_definition: Optional["DefinitionContainerInterface"] = None, material_containers_metadata: Optional[List[Dict[str, Any]]] = None) -> Optional[InstanceContainer]: - criteria = {"type": "quality", "name": quality_name} - result = self._getFilteredContainersForStack(machine_definition, material_containers_metadata, **criteria) - - # Fall back to using generic materials and qualities if nothing could be found. - if not result and material_containers_metadata and len(material_containers_metadata) == 1: - basic_materials = self._getBasicMaterialMetadatas(material_containers_metadata[0]) - result = self._getFilteredContainersForStack(machine_definition, basic_materials, **criteria) - - return result[0] if result else None - - ## Find a quality changes container by name. - # - # \param quality_changes_name \type{str} the name of the quality changes container. - # \param machine_definition (Optional) \type{DefinitionContainer} If nothing is - # specified then the currently selected machine definition is used.. - # \return the matching quality changes containers \type{List[InstanceContainer]} - def findQualityChangesByName(self, quality_changes_name: str, machine_definition: Optional["DefinitionContainerInterface"] = None): - if not machine_definition: - global_stack = Application.getGlobalContainerStack() - if not global_stack: - return [] #No stack, so no current definition could be found, so there are no quality changes either. - machine_definition = global_stack.definition - - result = self.findAllQualityChangesForMachine(machine_definition) - result = [quality_change for quality_change in result if quality_change.getName() == quality_changes_name] - return result - ## Fetch the list of available quality types for this combination of machine definition and materials. # # \param machine_definition \type{DefinitionContainer} diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index d16bdca8a7..759c5d5be7 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -161,7 +161,7 @@ class ContainerManager(QObject): return container.getProperty(setting_key, property_name) ## Set the name of the specified material. - @pyqtSlot("QVariant", str) + @pyqtSlot(QObject, str) def setMaterialName(self, material_node, new_name): root_material_id = material_node.metadata["base_file"] if self._container_registry.isReadOnly(root_material_id): diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 907c1c44b7..b81fd435b9 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -4,26 +4,28 @@ import os.path import zipfile +import numpy + +import Savitar + +from UM.Application import Application from UM.Logger import Logger from UM.Math.Matrix import Matrix from UM.Math.Vector import Vector from UM.Mesh.MeshBuilder import MeshBuilder from UM.Mesh.MeshReader import MeshReader from UM.Scene.GroupDecorator import GroupDecorator + from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator -from UM.Application import Application from cura.Settings.ExtruderManager import ExtruderManager -from cura.QualityManager import QualityManager from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Scene.BuildPlateDecorator import BuildPlateDecorator from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator from cura.Scene.ZOffsetDecorator import ZOffsetDecorator +from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch MYPY = False -import Savitar -import numpy - try: if not MYPY: import xml.etree.cElementTree as ET @@ -120,8 +122,8 @@ class ThreeMFReader(MeshReader): um_node.callDecoration("setActiveExtruder", default_stack.getId()) # Get the definition & set it - definition = QualityManager.getInstance().getParentMachineDefinition(global_container_stack.getBottom()) - um_node.callDecoration("getStack").getTop().setDefinition(definition.getId()) + definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack.definition) + um_node.callDecoration("getStack").getTop().setDefinition(definition_id) setting_container = um_node.callDecoration("getStack").getTop() From 2cd98910005ab0d696e42f93485f6e204fded452 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 21:00:49 +0100 Subject: [PATCH 123/371] WIP: Fix material QVariant type --- cura/Settings/ContainerManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 759c5d5be7..d16bdca8a7 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -161,7 +161,7 @@ class ContainerManager(QObject): return container.getProperty(setting_key, property_name) ## Set the name of the specified material. - @pyqtSlot(QObject, str) + @pyqtSlot("QVariant", str) def setMaterialName(self, material_node, new_name): root_material_id = material_node.metadata["base_file"] if self._container_registry.isReadOnly(root_material_id): From 7e84e7570fb5087d495760ddf4b1950921e17fb8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 21:02:33 +0100 Subject: [PATCH 124/371] WIP: Cleanup ContainerManager --- cura/Settings/ContainerManager.py | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index d16bdca8a7..af4924b8b3 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -706,34 +706,6 @@ class ContainerManager(QObject): quality_changes.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) return quality_changes - - ## Import profiles from a list of file_urls. - # Each QUrl item must end with .curaprofile, or it will not be imported. - # - # \param QVariant, essentially a list with QUrl objects. - # \return Dict with keys status, text - @pyqtSlot("QVariantList", result="QVariantMap") - def importProfiles(self, file_urls): - status = "ok" - results = {"ok": [], "error": []} - for file_url in file_urls: - if not file_url.isValid(): - continue - path = file_url.toLocalFile() - if not path: - continue - if not path.endswith(".curaprofile"): - continue - - single_result = self._container_registry.importProfile(path) - if single_result["status"] == "error": - status = "error" - results[single_result["status"]].append(single_result["message"]) - - return { - "status": status, - "message": "\n".join(results["ok"] + results["error"])} - ## Import single profile, file_url does not have to end with curaprofile @pyqtSlot(QUrl, result="QVariantMap") def importProfile(self, file_url): From 0c3ac090c9001b05f4b6834f6f5b8d20f9cd83ee Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 21:11:01 +0100 Subject: [PATCH 125/371] WIP: Cleanup --- cura/Settings/CuraContainerRegistry.py | 19 +++++----------- cura/Settings/MachineManager.py | 26 ++-------------------- resources/qml/Preferences/ProfilesPage.qml | 3 +-- 3 files changed, 8 insertions(+), 40 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 393e36db30..29ee5c4b95 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -28,6 +28,7 @@ from . import GlobalStack from .ExtruderManager import ExtruderManager from cura.CuraApplication import CuraApplication +from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -296,7 +297,7 @@ class CuraContainerRegistry(ContainerRegistry): elif profile_index < len(machine_extruders) + 1: # This is assumed to be an extruder profile - extruder_id = Application.getInstance().getMachineManager().getQualityDefinitionId(machine_extruders[profile_index - 1].getBottom()) + extruder_id = machine_extruders[profile_index - 1].definition.getId() if not profile.getMetaDataEntry("extruder"): profile.addMetaDataEntry("extruder", extruder_id) else: @@ -356,7 +357,9 @@ class CuraContainerRegistry(ContainerRegistry): quality_type_criteria = {"quality_type": quality_type} if self._machineHasOwnQualities(): - profile.setDefinition(self._activeQualityDefinition().getId()) + global_container_stack = Application.getInstance().getGlobalContainerStack() + definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack) + profile.setDefinition(definition_id) if self._machineHasOwnMaterials(): active_material_id = self._activeMaterialId() if active_material_id and active_material_id != "empty": # only update if there is an active material @@ -407,18 +410,6 @@ class CuraContainerRegistry(ContainerRegistry): result.append( (plugin_id, meta_data) ) return result - ## Get the definition to use to select quality profiles for the active machine - # \return the active quality definition object or None if there is no quality definition - def _activeQualityDefinition(self): - global_container_stack = Application.getInstance().getGlobalContainerStack() - if global_container_stack: - definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(global_container_stack.getBottom()) - definition = self.findDefinitionContainers(id = definition_id)[0] - - if definition: - return definition - return None - ## Returns true if the current machine requires its own materials # \return True if the current machine requires its own materials def _machineHasOwnMaterials(self): diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index de8f6328f7..31deb91c34 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -24,6 +24,7 @@ from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.SettingFunction import SettingFunction from UM.Signal import postponeSignals, CompressTechnique +from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch from cura.QualityManager import QualityManager from cura.PrinterOutputDevice import PrinterOutputDevice @@ -698,35 +699,12 @@ class MachineManager(QObject): ## Get the Definition ID to use to select quality profiles for the currently active machine # \returns DefinitionID (string) if found, empty string otherwise - # \sa getQualityDefinitionId @pyqtProperty(str, notify = globalContainerChanged) def activeQualityDefinitionId(self) -> str: if self._global_container_stack: - return self.getQualityDefinitionId(self._global_container_stack.definition) + return getMachineDefinitionIDForQualitySearch(self._global_container_stack) return "" - ## Get the Definition ID to use to select quality profiles for machines of the specified definition - # This is normally the id of the definition itself, but machines can specify a different definition to inherit qualities from - # \param definition (DefinitionContainer) machine definition - # \returns DefinitionID (string) if found, empty string otherwise - def getQualityDefinitionId(self, definition: "DefinitionContainer") -> str: - return QualityManager.getInstance().getParentMachineDefinition(definition).getId() - - ## Get the Variant ID to use to select quality profiles for variants of the specified definitions - # This is normally the id of the variant itself, but machines can specify a different definition - # to inherit qualities from, which has consequences for the variant to use as well - # \param definition (DefinitionContainer) machine definition - # \param variant (InstanceContainer) variant definition - # \returns VariantID (string) if found, empty string otherwise - def getQualityVariantId(self, definition: "DefinitionContainer", variant: "InstanceContainer") -> str: - variant_id = variant.getId() - definition_id = definition.getId() - quality_definition_id = self.getQualityDefinitionId(definition) - - if definition_id != quality_definition_id: - variant_id = variant_id.replace(definition_id, quality_definition_id, 1) - return variant_id - ## Gets how the active definition calls variants # Caveat: per-definition-variant-title is currently not translated (though the fallback is) @pyqtProperty(str, notify = globalContainerChanged) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 6c58a1e69d..57ec7a1222 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -147,8 +147,7 @@ Item { text: catalog.i18nc("@action:button", "Export") iconName: "document-export" - //enabled: currentItem != null && !base.currentItem.readOnly - enabled: true // TODO + enabled: base.hasCurrentItem && !base.currentItem.is_read_only onClicked: { // TODO } From 5bb6efcb3e26aecef839311ad16a97d10201f120 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 21:20:10 +0100 Subject: [PATCH 126/371] WIP: Cleanup MachineManager --- cura/Settings/MachineManager.py | 15 --------------- resources/qml/WorkspaceSummaryDialog.qml | 2 +- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 31deb91c34..3ff5cb1011 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -586,14 +586,6 @@ class MachineManager(QObject): return False return True - @pyqtProperty(str, notify = activeQualityChanged) - def activeQualityChangesId(self) -> str: - if self._active_container_stack: - quality_changes = self._active_container_stack.qualityChanges - if quality_changes and not isinstance(quality_changes, type(self._empty_quality_changes_container)): - return quality_changes.getId() - return "" - ## Check if a container is read_only @pyqtSlot(str, result = bool) def isReadOnly(self, container_id: str) -> bool: @@ -690,13 +682,6 @@ class MachineManager(QObject): return "" - @pyqtProperty(str, notify=globalContainerChanged) - def activeDefinitionName(self) -> str: - if self._global_container_stack: - return self._global_container_stack.definition.getName() - - return "" - ## Get the Definition ID to use to select quality profiles for the currently active machine # \returns DefinitionID (string) if found, empty string otherwise @pyqtProperty(str, notify = globalContainerChanged) diff --git a/resources/qml/WorkspaceSummaryDialog.qml b/resources/qml/WorkspaceSummaryDialog.qml index a05dee5a9a..8f00377d58 100644 --- a/resources/qml/WorkspaceSummaryDialog.qml +++ b/resources/qml/WorkspaceSummaryDialog.qml @@ -101,7 +101,7 @@ UM.Dialog } Label { - text: Cura.MachineManager.activeDefinitionName + text: Cura.MachineManager.activeMachine.definition.name width: (parent.width / 3) | 0 } } From 27f7d16a57b86cb7b1eeabd16d7090a27b26f61f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 21:47:12 +0100 Subject: [PATCH 127/371] WIP: Make import/export profile work --- .../Machines/Models/QualityManagementModel.py | 44 ++++++++++++++- cura/Settings/ContainerManager.py | 20 ++----- cura/Settings/CuraContainerRegistry.py | 25 +-------- resources/qml/Preferences/ProfilesPage.qml | 55 ++++++++++++++++++- 4 files changed, 103 insertions(+), 41 deletions(-) diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py index cf7a163d9c..6e5b37bbfa 100644 --- a/cura/Machines/Models/QualityManagementModel.py +++ b/cura/Machines/Models/QualityManagementModel.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, pyqtSlot from UM.Qt.ListModel import ListModel @@ -74,3 +74,45 @@ class QualityManagementModel(ListModel): item_list += quality_changes_item_list self.setItems(item_list) + + # TODO: Duplicated code here from InstanceContainersModel. Refactor and remove this later. + # + ## Gets a list of the possible file filters that the plugins have + # registered they can read or write. The convenience meta-filters + # "All Supported Types" and "All Files" are added when listing + # readers, but not when listing writers. + # + # \param io_type \type{str} name of the needed IO type + # \return A list of strings indicating file name filters for a file + # dialog. + @pyqtSlot(str, result = "QVariantList") + def getFileNameFilters(self, io_type): + from UM.i18n import i18nCatalog + catalog = i18nCatalog("uranium") + #TODO: This function should be in UM.Resources! + filters = [] + all_types = [] + for plugin_id, meta_data in self._getIOPlugins(io_type): + for io_plugin in meta_data[io_type]: + filters.append(io_plugin["description"] + " (*." + io_plugin["extension"] + ")") + all_types.append("*.{0}".format(io_plugin["extension"])) + + if "_reader" in io_type: + # if we're listing readers, add the option to show all supported files as the default option + filters.insert(0, catalog.i18nc("@item:inlistbox", "All Supported Types ({0})", " ".join(all_types))) + filters.append(catalog.i18nc("@item:inlistbox", "All Files (*)")) # Also allow arbitrary files, if the user so prefers. + return filters + + ## Gets a list of profile reader or writer plugins + # \return List of tuples of (plugin_id, meta_data). + def _getIOPlugins(self, io_type): + from UM.PluginRegistry import PluginRegistry + pr = PluginRegistry.getInstance() + active_plugin_ids = pr.getActivePlugins() + + result = [] + for plugin_id in active_plugin_ids: + meta_data = pr.getMetaData(plugin_id) + if io_type in meta_data: + result.append( (plugin_id, meta_data) ) + return result diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index af4924b8b3..6eb9aa0311 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -171,18 +171,6 @@ class ContainerManager(QObject): material_group = self._material_manager.getMaterialGroup(root_material_id) material_group.root_material_node.getContainer().setName(new_name) - ## Find instance containers matching certain criteria. - # - # This effectively forwards to - # ContainerRegistry::findInstanceContainersMetadata. - # - # \param criteria A dict of key - value pairs to search for. - # - # \return A list of container IDs that match the given criteria. - @pyqtSlot("QVariantMap", result = "QVariantList") - def findInstanceContainers(self, criteria): - return [entry["id"] for entry in self._container_registry.findInstanceContainersMetadata(**criteria)] - @pyqtSlot(str, result = str) def makeUniqueName(self, original_name): return self._container_registry.uniqueName(original_name) @@ -716,11 +704,13 @@ class ContainerManager(QObject): return return self._container_registry.importProfile(path) - @pyqtSlot("QVariantList", QUrl, str) - def exportProfile(self, instance_id: str, file_url: QUrl, file_type: str) -> None: + @pyqtSlot(QObject, QUrl, str) + def exportQualityChangesGroup(self, quality_changes_group, file_url: QUrl, file_type: str): if not file_url.isValid(): return path = file_url.toLocalFile() if not path: return - self._container_registry.exportProfile(instance_id, path, file_type) + + container_list = [n.getContainer() for n in quality_changes_group.getAllNodes()] + self._container_registry.exportQualityProfile(container_list, path, file_type) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 29ee5c4b95..7103167b9c 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -103,7 +103,7 @@ class CuraContainerRegistry(ContainerRegistry): # \param instance_ids \type{list} the IDs of the profiles to export. # \param file_name \type{str} the full path and filename to export to. # \param file_type \type{str} the file type with the format " (*.)" - def exportProfile(self, instance_ids, file_name, file_type): + def exportQualityProfile(self, container_list, file_name, file_type): # Parse the fileType to deduce what plugin can save the file format. # fileType has the format " (*.)" split = file_type.rfind(" (*.") # Find where the description ends and the extension starts. @@ -122,31 +122,10 @@ class CuraContainerRegistry(ContainerRegistry): catalog.i18nc("@label Don't translate the XML tag !", "The file {0} already exists. Are you sure you want to overwrite it?").format(file_name)) if result == QMessageBox.No: return - found_containers = [] - extruder_positions = [] - for instance_id in instance_ids: - containers = ContainerRegistry.getInstance().findInstanceContainers(id = instance_id) - if containers: - found_containers.append(containers[0]) - - # Determine the position of the extruder of this container - extruder_id = containers[0].getMetaDataEntry("extruder", "") - if extruder_id == "": - # Global stack - extruder_positions.append(-1) - else: - extruder_containers = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = extruder_id) - if extruder_containers: - extruder_positions.append(int(extruder_containers[0].get("position", 0))) - else: - extruder_positions.append(0) - # Ensure the profiles are always exported in order (global, extruder 0, extruder 1, ...) - found_containers = [containers for (positions, containers) in sorted(zip(extruder_positions, found_containers))] profile_writer = self._findProfileWriter(extension, description) - try: - success = profile_writer.write(file_name, found_containers) + success = profile_writer.write(file_name, container_list) except Exception as e: Logger.log("e", "Failed to export profile to %s: %s", file_name, str(e)) m = Message(catalog.i18nc("@info:status Don't translate the XML tags or !", "Failed to export profile to {0}: {1}", file_name, str(e)), diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 57ec7a1222..ce8bd7dd3c 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -138,7 +138,7 @@ Item text: catalog.i18nc("@action:button", "Import") iconName: "document-import" onClicked: { - // TODO + importDialog.open(); } } @@ -149,7 +149,7 @@ Item iconName: "document-export" enabled: base.hasCurrentItem && !base.currentItem.is_read_only onClicked: { - // TODO + exportDialog.open(); } } } @@ -212,6 +212,57 @@ Item } } + // Dialog for importing a quality profile + FileDialog + { + id: importDialog + title: catalog.i18nc("@title:window", "Import Profile") + selectExisting: true + nameFilters: qualitiesModel.getFileNameFilters("profile_reader") // TODO: make this easier + folder: CuraApplication.getDefaultPath("dialog_profile_path") + onAccepted: + { + var result = Cura.ContainerManager.importProfile(fileUrl); + messageDialog.text = result.message; + if (result.status == "ok") { + messageDialog.icon = StandardIcon.Information; + } + else if (result.status == "duplicate") { + messageDialog.icon = StandardIcon.Warning; + } + else { + messageDialog.icon = StandardIcon.Critical; + } + messageDialog.open(); + CuraApplication.setDefaultPath("dialog_profile_path", folder); + } + } + + // Dialog for exporting a quality profile + FileDialog + { + id: exportDialog + title: catalog.i18nc("@title:window", "Export Profile") + selectExisting: false + nameFilters: qualitiesModel.getFileNameFilters("profile_writer") // TODO: make this easier + folder: CuraApplication.getDefaultPath("dialog_profile_path") + onAccepted: + { + // TODO: make this easier + var result = Cura.ContainerManager.exportQualityChangesGroup(base.currentItem.quality_changes_group, + fileUrl, selectedNameFilter); + + if (result && result.status == "error") { + messageDialog.icon = StandardIcon.Critical; + messageDialog.text = result.message; + messageDialog.open(); + } + + // else pop-up Message thing from python code + CuraApplication.setDefaultPath("dialog_profile_path", folder); + } + } + Item { id: contentsItem From 62c31c2f6ce84edcf7565d20e1aca8add9295e03 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 19 Feb 2018 22:11:47 +0100 Subject: [PATCH 128/371] WIP: Remove old QualityManager --- cura/Machines/QualityManager.py | 24 ++ cura/QualityManager.py | 296 -------------------- cura/Settings/CuraContainerRegistry.py | 37 +-- cura/Settings/MachineManager.py | 2 - plugins/3MFReader/ThreeMFWorkspaceReader.py | 10 +- 5 files changed, 34 insertions(+), 335 deletions(-) delete mode 100644 cura/QualityManager.py diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index a5457344f1..f7ca84e83d 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -360,3 +360,27 @@ class QualityManager(QObject): self._updateQualityGroupsAvailability(machine, quality_group_dict.values()) return quality_group_dict + + def getQualityGroupsForMachineDefinition(self, machine: str) -> dict: + # Get machine definition ID for quality search + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + + # To find the quality container for the GlobalStack, check in the following fall-back manner: + # (1) the machine-specific node + # (2) the generic node + machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) + default_machine_node = self._machine_variant_material_quality_type_to_quality_dict.get( + self._default_machine_definition_id) + nodes_to_check = [machine_node, default_machine_node] + + # Iterate over all quality_types in the machine node + quality_group_dict = dict() + for node in nodes_to_check: + if node and node.quality_type_map: + for quality_type, quality_node in node.quality_type_map.items(): + quality_group = QualityGroup(quality_node.metadata["name"], quality_type) + quality_group.node_for_global = quality_node + quality_group_dict[quality_type] = quality_group + break + + return quality_group_dict diff --git a/cura/QualityManager.py b/cura/QualityManager.py deleted file mode 100644 index 358bf4e422..0000000000 --- a/cura/QualityManager.py +++ /dev/null @@ -1,296 +0,0 @@ -# Copyright (c) 2017 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -# This collects a lot of quality and quality changes related code which was split between ContainerManager -# and the MachineManager and really needs to usable from both. -from typing import Any, Dict, List, Optional, TYPE_CHECKING - -from UM.Application import Application -from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.InstanceContainer import InstanceContainer -from cura.Settings.ExtruderManager import ExtruderManager - -if TYPE_CHECKING: - from cura.Settings.GlobalStack import GlobalStack - from cura.Settings.ExtruderStack import ExtruderStack - from UM.Settings.DefinitionContainer import DefinitionContainerInterface - -class QualityManager: - - ## Get the singleton instance for this class. - @classmethod - def getInstance(cls) -> "QualityManager": - # Note: Explicit use of class name to prevent issues with inheritance. - if not QualityManager.__instance: - QualityManager.__instance = cls() - return QualityManager.__instance - - __instance = None # type: "QualityManager" - - ## Fetch the list of available quality types for this combination of machine definition and materials. - # - # \param machine_definition \type{DefinitionContainer} - # \param material_containers \type{List[InstanceContainer]} - # \return \type{List[str]} - def findAllQualityTypesForMachineAndMaterials(self, machine_definition: "DefinitionContainerInterface", material_containers: List[InstanceContainer]) -> List[str]: - # Determine the common set of quality types which can be - # applied to all of the materials for this machine. - quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_containers[0]) - common_quality_types = set(quality_type_dict.keys()) - for material_container in material_containers[1:]: - next_quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_container) - common_quality_types.intersection_update(set(next_quality_type_dict.keys())) - - return list(common_quality_types) - - def findAllQualitiesForMachineAndMaterials(self, machine_definition: "DefinitionContainerInterface", material_containers: List[InstanceContainer]) -> List[InstanceContainer]: - # Determine the common set of quality types which can be - # applied to all of the materials for this machine. - quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_containers[0]) - qualities = set(quality_type_dict.values()) - for material_container in material_containers[1:]: - next_quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_container) - qualities.intersection_update(set(next_quality_type_dict.values())) - - return list(qualities) - - ## Fetches a dict of quality types names to quality profiles for a combination of machine and material. - # - # \param machine_definition \type{DefinitionContainer} the machine definition. - # \param material \type{InstanceContainer} the material. - # \return \type{Dict[str, InstanceContainer]} the dict of suitable quality type names mapping to qualities. - def __fetchQualityTypeDictForMaterial(self, machine_definition: "DefinitionContainerInterface", material: InstanceContainer) -> Dict[str, InstanceContainer]: - qualities = self.findAllQualitiesForMachineMaterial(machine_definition, material) - quality_type_dict = {} - for quality in qualities: - quality_type_dict[quality.getMetaDataEntry("quality_type")] = quality - return quality_type_dict - - ## Find a quality container by quality type. - # - # \param quality_type \type{str} the name of the quality type to search for. - # \param machine_definition (Optional) \type{InstanceContainer} If nothing is - # specified then the currently selected machine definition is used. - # \param material_containers_metadata If nothing is specified then the - # current set of selected materials is used. - # \return the matching quality container \type{InstanceContainer} - def findQualityByQualityType(self, quality_type: str, machine_definition: Optional["DefinitionContainerInterface"] = None, material_containers_metadata: Optional[List[Dict[str, Any]]] = None, **kwargs) -> InstanceContainer: - criteria = kwargs - criteria["type"] = "quality" - if quality_type: - criteria["quality_type"] = quality_type - result = self._getFilteredContainersForStack(machine_definition, material_containers_metadata, **criteria) - # Fall back to using generic materials and qualities if nothing could be found. - if not result and material_containers_metadata and len(material_containers_metadata) == 1: - basic_materials = self._getBasicMaterialMetadatas(material_containers_metadata[0]) - if basic_materials: - result = self._getFilteredContainersForStack(machine_definition, basic_materials, **criteria) - return result[0] if result else None - - ## Find all suitable qualities for a combination of machine and material. - # - # \param machine_definition \type{DefinitionContainer} the machine definition. - # \param material_container \type{InstanceContainer} the material. - # \return \type{List[InstanceContainer]} the list of suitable qualities. - def findAllQualitiesForMachineMaterial(self, machine_definition: "DefinitionContainerInterface", material_container: InstanceContainer) -> List[InstanceContainer]: - criteria = {"type": "quality"} - result = self._getFilteredContainersForStack(machine_definition, [material_container.getMetaData()], **criteria) - if not result: - basic_materials = self._getBasicMaterialMetadatas(material_container.getMetaData()) - if basic_materials: - result = self._getFilteredContainersForStack(machine_definition, basic_materials, **criteria) - - return result - - ## Find all quality changes for a machine. - # - # \param machine_definition \type{DefinitionContainer} the machine definition. - # \return \type{List[InstanceContainer]} the list of quality changes - def findAllQualityChangesForMachine(self, machine_definition: "DefinitionContainerInterface") -> List[InstanceContainer]: - if machine_definition.getMetaDataEntry("has_machine_quality"): - definition_id = machine_definition.getId() - else: - definition_id = "fdmprinter" - - filter_dict = { "type": "quality_changes", "definition": definition_id } - quality_changes_list = ContainerRegistry.getInstance().findInstanceContainers(**filter_dict) - return quality_changes_list - - def findAllExtruderDefinitionsForMachine(self, machine_definition: "DefinitionContainerInterface") -> List["DefinitionContainerInterface"]: - filter_dict = { "machine": machine_definition.getId() } - return ContainerRegistry.getInstance().findDefinitionContainers(**filter_dict) - - ## Find all quality changes for a given extruder. - # - # \param extruder_definition The extruder to find the quality changes for. - # \return The list of quality changes for the given extruder. - def findAllQualityChangesForExtruder(self, extruder_definition: "DefinitionContainerInterface") -> List[InstanceContainer]: - filter_dict = {"type": "quality_changes", "extruder": extruder_definition.getId()} - return ContainerRegistry.getInstance().findInstanceContainers(**filter_dict) - - ## Find all usable qualities for a machine and extruders. - # - # Finds all of the qualities for this combination of machine and extruders. - # Only one quality per quality type is returned. i.e. if there are 2 qualities with quality_type=normal - # then only one of then is returned (at random). - # - # \param global_container_stack \type{GlobalStack} the global machine definition - # \param extruder_stacks \type{List[ExtruderStack]} the list of extruder stacks - # \return \type{List[InstanceContainer]} the list of the matching qualities. The quality profiles - # return come from the first extruder in the given list of extruders. - def findAllUsableQualitiesForMachineAndExtruders(self, global_container_stack: "GlobalStack", extruder_stacks: List["ExtruderStack"]) -> List[InstanceContainer]: - global_machine_definition = global_container_stack.getBottom() - - machine_manager = Application.getInstance().getMachineManager() - active_stack_id = machine_manager.activeStackId - - materials = [] - - for stack in extruder_stacks: - if stack.getId() == active_stack_id and machine_manager.newMaterial: - materials.append(machine_manager.newMaterial) - else: - materials.append(stack.material) - - quality_types = self.findAllQualityTypesForMachineAndMaterials(global_machine_definition, materials) - - # Map the list of quality_types to InstanceContainers - qualities = self.findAllQualitiesForMachineMaterial(global_machine_definition, materials[0]) - quality_type_dict = {} - for quality in qualities: - quality_type_dict[quality.getMetaDataEntry("quality_type")] = quality - - return [quality_type_dict[quality_type] for quality_type in quality_types] - - ## Fetch more basic versions of a material. - # - # This tries to find a generic or basic version of the given material. - # \param material_container \type{Dict[str, Any]} The metadata of a - # material to find the basic versions of. - # \return \type{List[Dict[str, Any]]} A list of the metadata of basic - # materials, or an empty list if none could be found. - def _getBasicMaterialMetadatas(self, material_container: Dict[str, Any]) -> List[Dict[str, Any]]: - if "definition" not in material_container: - definition_id = "fdmprinter" - else: - material_container_definition = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = material_container["definition"]) - if not material_container_definition: - definition_id = "fdmprinter" - else: - material_container_definition = material_container_definition[0] - if "has_machine_quality" not in material_container_definition: - definition_id = "fdmprinter" - else: - definition_id = material_container_definition.get("quality_definition", material_container_definition["id"]) - - base_material = material_container.get("material") - if base_material: - # There is a basic material specified - criteria = { - "type": "material", - "name": base_material, - "definition": definition_id, - "variant": material_container.get("variant") - } - containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(**criteria) - return containers - - return [] - - def _getFilteredContainers(self, **kwargs): - return self._getFilteredContainersForStack(None, None, **kwargs) - - def _getFilteredContainersForStack(self, machine_definition: "DefinitionContainerInterface" = None, material_metadata: Optional[List[Dict[str, Any]]] = None, **kwargs): - # Fill in any default values. - if machine_definition is None: - machine_definition = Application.getInstance().getGlobalContainerStack().getBottom() - quality_definition_id = machine_definition.getMetaDataEntry("quality_definition") - if quality_definition_id is not None: - machine_definition = ContainerRegistry.getInstance().findDefinitionContainers(id = quality_definition_id)[0] - - if not material_metadata: - active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() - if active_stacks: - material_metadata = [stack.material.getMetaData() for stack in active_stacks] - - criteria = kwargs - filter_by_material = False - - machine_definition = self.getParentMachineDefinition(machine_definition) - criteria["definition"] = machine_definition.getId() - found_containers_with_machine_definition = ContainerRegistry.getInstance().findInstanceContainersMetadata(**criteria) - whole_machine_definition = self.getWholeMachineDefinition(machine_definition) - if whole_machine_definition.getMetaDataEntry("has_machine_quality"): - definition_id = machine_definition.getMetaDataEntry("quality_definition", whole_machine_definition.getId()) - criteria["definition"] = definition_id - - filter_by_material = whole_machine_definition.getMetaDataEntry("has_materials") - # only fall back to "fdmprinter" when there is no container for this machine - elif not found_containers_with_machine_definition: - criteria["definition"] = "fdmprinter" - - # Stick the material IDs in a set - material_ids = set() - - for material_instance in material_metadata: - if material_instance is not None: - # Add the parent material too. - for basic_material in self._getBasicMaterialMetadatas(material_instance): - material_ids.add(basic_material["id"]) - material_ids.add(material_instance["id"]) - containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria) - - result = [] - for container in containers: - # If the machine specifies we should filter by material, exclude containers that do not match any active material. - if filter_by_material and container.getMetaDataEntry("material") not in material_ids and "global_quality" not in kwargs: - continue - result.append(container) - - return result - - ## Get the parent machine definition of a machine definition. - # - # \param machine_definition \type{DefinitionContainer} This may be a normal machine definition or - # an extruder definition. - # \return \type{DefinitionContainer} the parent machine definition. If the given machine - # definition doesn't have a parent then it is simply returned. - def getParentMachineDefinition(self, machine_definition: "DefinitionContainerInterface") -> "DefinitionContainerInterface": - container_registry = ContainerRegistry.getInstance() - - machine_entry = machine_definition.getMetaDataEntry("machine") - if machine_entry is None: - # We have a normal (whole) machine defintion - quality_definition = machine_definition.getMetaDataEntry("quality_definition") - if quality_definition is not None: - parent_machine_definition = container_registry.findDefinitionContainers(id = quality_definition)[0] - return self.getParentMachineDefinition(parent_machine_definition) - else: - return machine_definition - else: - # This looks like an extruder. Find the rest of the machine. - whole_machine = container_registry.findDefinitionContainers(id = machine_entry)[0] - parent_machine = self.getParentMachineDefinition(whole_machine) - if whole_machine is parent_machine: - # This extruder already belongs to a 'parent' machine def. - return machine_definition - else: - # Look up the corresponding extruder definition in the parent machine definition. - extruder_position = machine_definition.getMetaDataEntry("position") - parent_extruder_id = parent_machine.getMetaDataEntry("machine_extruder_trains")[extruder_position] - return container_registry.findDefinitionContainers(id = parent_extruder_id)[0] - - ## Get the whole/global machine definition from an extruder definition. - # - # \param machine_definition \type{DefinitionContainer} This may be a normal machine definition or - # an extruder definition. - # \return \type{DefinitionContainerInterface} - def getWholeMachineDefinition(self, machine_definition: "DefinitionContainerInterface") -> "DefinitionContainerInterface": - machine_entry = machine_definition.getMetaDataEntry("machine") - if machine_entry is None: - # This already is a 'global' machine definition. - return machine_definition - else: - container_registry = ContainerRegistry.getInstance() - whole_machine = container_registry.findDefinitionContainers(id = machine_entry)[0] - return whole_machine diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 7103167b9c..329fbe77b7 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -335,41 +335,16 @@ class CuraContainerRegistry(ContainerRegistry): return catalog.i18nc("@info:status", "Profile is missing a quality type.") quality_type_criteria = {"quality_type": quality_type} - if self._machineHasOwnQualities(): - global_container_stack = Application.getInstance().getGlobalContainerStack() - definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack) - profile.setDefinition(definition_id) - if self._machineHasOwnMaterials(): - active_material_id = self._activeMaterialId() - if active_material_id and active_material_id != "empty": # only update if there is an active material - profile.addMetaDataEntry("material", active_material_id) - quality_type_criteria["material"] = active_material_id - - quality_type_criteria["definition"] = profile.getDefinition().getId() - - else: - profile.setDefinition("fdmprinter") - quality_type_criteria["definition"] = "fdmprinter" - - machine_definition = Application.getInstance().getGlobalContainerStack().getBottom() - del quality_type_criteria["definition"] - - # materials = None - - if "material" in quality_type_criteria: - # materials = ContainerRegistry.getInstance().findInstanceContainers(id = quality_type_criteria["material"]) - del quality_type_criteria["material"] - - # Do not filter quality containers here with materials because we are trying to import a profile, so it should - # NOT be restricted by the active materials on the current machine. - materials = None + global_stack = Application.getInstance().getGlobalContainerStack() + definition_id = getMachineDefinitionIDForQualitySearch(global_stack) + profile.setDefinition(definition_id) # Check to make sure the imported profile actually makes sense in context of the current configuration. # This prevents issues where importing a "draft" profile for a machine without "draft" qualities would report as # successfully imported but then fail to show up. - from cura.QualityManager import QualityManager - qualities = QualityManager.getInstance()._getFilteredContainersForStack(machine_definition, materials, **quality_type_criteria) - if not qualities: + quality_manager = CuraApplication.getInstance()._quality_manager + quality_group_dict = quality_manager.getQualityGroupsForMachineDefinition(global_stack) + if quality_type not in quality_group_dict: return catalog.i18nc("@info:status", "Could not find a quality type {0} for the current configuration.", quality_type) ContainerRegistry.getInstance().addContainer(profile) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 3ff5cb1011..7be3f0798e 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -26,7 +26,6 @@ from UM.Signal import postponeSignals, CompressTechnique from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch -from cura.QualityManager import QualityManager from cura.PrinterOutputDevice import PrinterOutputDevice from cura.Settings.ExtruderManager import ExtruderManager @@ -36,7 +35,6 @@ from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") if TYPE_CHECKING: - from UM.Settings.DefinitionContainer import DefinitionContainer from cura.Settings.CuraContainerStack import CuraContainerStack from cura.Settings.GlobalStack import GlobalStack diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 8291ca3b52..d584a0efd6 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -23,7 +23,6 @@ from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderStack import ExtruderStack from cura.Settings.GlobalStack import GlobalStack from cura.Settings.CuraContainerStack import _ContainerIndexes -from cura.QualityManager import QualityManager from cura.CuraApplication import CuraApplication from configparser import ConfigParser @@ -858,10 +857,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if machine_extruder_count is not None: extruder_stacks_in_use = extruder_stacks[:machine_extruder_count] - available_quality = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_stack, - extruder_stacks_in_use) + quality_manager = CuraApplication.getInstance()._quality_manager + all_quality_groups = quality_manager.getQualityGroups(global_stack) + available_quality_types = [qt for qt, qg in all_quality_groups.items() if qg.is_available] if not has_not_supported: - has_not_supported = not available_quality + has_not_supported = not available_quality_types quality_has_been_changed = False @@ -875,8 +875,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # The machine in the project has non-empty quality and there are usable qualities for this machine. # We need to check if the current quality_type is still usable for this machine, if not, then the quality # will be reset to the "preferred quality" if present, otherwise "normal". - available_quality_types = [q.getMetaDataEntry("quality_type") for q in available_quality] - if global_stack.quality.getMetaDataEntry("quality_type") not in available_quality_types: # We are here because the quality_type specified in the project is not supported any more, # so we need to switch it to the "preferred quality" if present, otherwise "normal". From 6cc65e97f202c1b982b0836ef9ba7eda32be90dd Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 20 Feb 2018 09:13:11 +0100 Subject: [PATCH 129/371] WIP: Cleanup MaterialsModel --- cura/CuraApplication.py | 5 ++- .../Models}/MaterialsModel.py | 34 +------------------ resources/qml/Preferences/MaterialsPage.qml | 2 +- 3 files changed, 4 insertions(+), 37 deletions(-) rename cura/{Settings => Machines/Models}/MaterialsModel.py (88%) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 795c254d8c..41f5fbc4b2 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -60,7 +60,7 @@ from cura.Machines.Models.CustomQualityProfilesModel import CustomQualityProfile from cura.Machines.Models.Other.MultiBuildPlateModel import MultiBuildPlateModel -from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel, NewMaterialsModel +from cura.Machines.Models.MaterialsModel import BrandMaterialsModel, GenericMaterialsModel, MaterialsModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager @@ -944,7 +944,7 @@ class CuraApplication(QtApplication): qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") - qmlRegisterType(NewMaterialsModel, "Cura", 1, 0, "NewMaterialsModel") + qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") # TODO: make this singleton? qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") @@ -953,7 +953,6 @@ class CuraApplication(QtApplication): qmlRegisterSingletonType(CustomQualityProfilesModel, "Cura", 1, 0, "CustomQualityProfilesModel", self.getCustomQualityProfilesModel) qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") - qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") diff --git a/cura/Settings/MaterialsModel.py b/cura/Machines/Models/MaterialsModel.py similarity index 88% rename from cura/Settings/MaterialsModel.py rename to cura/Machines/Models/MaterialsModel.py index 72b39a90aa..7d390277d6 100644 --- a/cura/Settings/MaterialsModel.py +++ b/cura/Machines/Models/MaterialsModel.py @@ -189,7 +189,7 @@ class BrandMaterialsModel(ListModel): # # This model is for the Material management page. # -class NewMaterialsModel(ListModel): +class MaterialsModel(ListModel): RootMaterialIdRole = Qt.UserRole + 1 DisplayNameRole = Qt.UserRole + 2 BrandRole = Qt.UserRole + 3 @@ -272,35 +272,3 @@ class NewMaterialsModel(ListModel): material_list = sorted(material_list, key = lambda k: (k["brand"], k["name"])) self.setItems(material_list) - - -## A model that shows a list of currently valid materials. Used by management page. -class MaterialsModel(InstanceContainersModel): - def __init__(self, parent = None): - super().__init__(parent) - - ContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerMetaDataChanged) - - ## Called when the metadata of the container was changed. - # - # This makes sure that we only update when it was a material that changed. - # - # \param container The container whose metadata was changed. - def _onContainerMetaDataChanged(self, container): - if container.getMetaDataEntry("type") == "material": #Only need to update if a material was changed. - self._container_change_timer.start() - - def _onContainerChanged(self, container): - if container.getMetaDataEntry("type", "") == "material": - super()._onContainerChanged(container) - - ## Group brand together - def _sortKey(self, item) -> List[Any]: - result = [] - result.append(item["metadata"]["brand"]) - result.append(item["metadata"]["material"]) - result.append(item["metadata"]["name"]) - result.append(item["metadata"]["color_name"]) - result.append(item["metadata"]["id"]) - result.extend(super()._sortKey(item)) - return result diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 4eddc45d76..8d14ada759 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -17,7 +17,7 @@ Item UM.I18nCatalog { id: catalog; name: "cura"; } - Cura.NewMaterialsModel { + Cura.MaterialsModel { id: materialsModel } From 6a4f5192386f3064a0915eeaa2bfc1b3150f0ae9 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 20 Feb 2018 09:30:05 +0100 Subject: [PATCH 130/371] Revert "CURA-4946 Add the quality_definition metadata entry to the gcode so when" This reverts commit 744313af273ed34a5796d3970c3915f68abaedc7. --- cura/Settings/CuraContainerRegistry.py | 17 +++++------------ plugins/GCodeWriter/GCodeWriter.py | 5 ----- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index be5a10e293..e26dab7399 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -228,23 +228,16 @@ class CuraContainerRegistry(ContainerRegistry): Logger.log("e", "Incorrect profile [%s]. Could not find global profile", file_name) return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "This profile {0} contains incorrect data, could not import it.", file_name)} - - # In a profile we can have the quality_definition metadata, but if not, we get the definition - profile_definition = global_profile.getMetaDataEntry("quality_definition") - if not profile_definition: - profile_definition = global_profile.getMetaDataEntry("definition") - - # The expected machine definition may be the quality_definition if defined or the current definition id - expected_machine_definition = None + profile_definition = global_profile.getMetaDataEntry("definition") + expected_machine_definition = "fdmprinter" if parseBool(global_container_stack.getMetaDataEntry("has_machine_quality", "False")): expected_machine_definition = global_container_stack.getMetaDataEntry("quality_definition") - if not expected_machine_definition: - expected_machine_definition = global_container_stack.definition.getId() - + if not expected_machine_definition: + expected_machine_definition = global_container_stack.definition.getId() if expected_machine_definition is not None and profile_definition is not None and profile_definition != expected_machine_definition: Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition) return { "status": "error", - "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it.", file_name, profile_definition, expected_machine_definition)} + "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} doesn't match with your current machine, could not import it.", file_name)} name_seed = os.path.splitext(os.path.basename(file_name))[0] new_name = self.uniqueName(name_seed) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index 368942fd08..d06332bec1 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -5,7 +5,6 @@ from UM.Mesh.MeshWriter import MeshWriter from UM.Logger import Logger from UM.Application import Application from UM.Settings.InstanceContainer import InstanceContainer -from UM.Util import parseBool from cura.Settings.ExtruderManager import ExtruderManager @@ -121,10 +120,6 @@ class GCodeWriter(MeshWriter): if flat_global_container.getMetaDataEntry("quality_type", None) is None: flat_global_container.addMetaDataEntry("quality_type", stack.quality.getMetaDataEntry("quality_type", "normal")) - # Ensure that quality_definition is set. (Can happen if we have empty quality changes). - if parseBool(stack.getMetaDataEntry("has_machine_quality", "False")): - flat_global_container.addMetaDataEntry("quality_definition", stack.getMetaDataEntry("quality_definition")) - serialized = flat_global_container.serialize() data = {"global_quality": serialized} From 21c475344306726cc365022f9f3bf355578226e0 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 09:54:22 +0100 Subject: [PATCH 131/371] CURA-4606 fallback value for layer height must come from definition --- cura/Machines/Models/QualityProfilesModel.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index b30daa85f6..88a999b6ad 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -90,9 +90,7 @@ class QualityProfilesModel(ListModel): layer_height = str(container.getProperty("layer_height", "value")) else: # Look for layer_height in the GlobalStack from material -> definition - for idx in range(4): - container = active_global_stack.getContainer(idx) - if container.hasProperty("layer_height", "value"): - layer_height = container.getProperty("layer_height", "value") - break + container = active_global_stack.definition + if container.hasProperty("layer_height", "value"): + layer_height = container.getProperty("layer_height", "value") return str(layer_height) From c7f8044a3289175e0003d602680080f0275e3d25 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 20 Feb 2018 10:46:01 +0100 Subject: [PATCH 132/371] CURA-4790 Changed light weights back to normal --- resources/themes/cura-light/theme.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 8eb874334a..1b5ddfe141 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -12,12 +12,12 @@ }, "large_nonbold": { "size": 1.35, - "weight": 25, + "weight": 50, "family": "Noto Sans" }, "default": { "size": 1.0, - "weight": 25, + "weight": 50, "family": "Noto Sans" }, "default_bold": { @@ -28,7 +28,7 @@ }, "default_italic": { "size": 1.15, - "weight": 25, + "weight": 50, "italic": true, "family": "Noto Sans" }, @@ -40,12 +40,12 @@ }, "very_small": { "size": 1.0, - "weight": 25, + "weight": 50, "family": "Noto Sans" }, "button_tooltip": { "size": 1.0, - "weight": 25, + "weight": 50, "family": "Noto Sans" }, "setting_category": { @@ -56,7 +56,7 @@ }, "action_button": { "size": 1.15, - "weight": 25, + "weight": 50, "bold": true, "family": "Noto Sans" } From 1bdd50e17f0c76beb10fcaa2f3efbcbb1e61f846 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 20 Feb 2018 11:04:23 +0100 Subject: [PATCH 133/371] CURA-4790 Removed "bold" property --- resources/themes/cura-light/theme.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 1b5ddfe141..8c8e6d1c47 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -7,7 +7,6 @@ "large": { "size": 1.35, "weight": 63, - "bold": true, "family": "Noto Sans" }, "large_nonbold": { @@ -23,7 +22,6 @@ "default_bold": { "size": 1.0, "weight": 63, - "bold": true, "family": "Noto Sans" }, "default_italic": { @@ -35,7 +33,6 @@ "small": { "size": 1.0, "weight": 63, - "bold": true, "family": "Noto Sans" }, "very_small": { @@ -51,13 +48,11 @@ "setting_category": { "size": 1.15, "weight": 63, - "bold": true, "family": "Noto Sans" }, "action_button": { "size": 1.15, "weight": 50, - "bold": true, "family": "Noto Sans" } }, From 6af5a5d4bc9a419e99437d793e2f496b8b74c67a Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 20 Feb 2018 11:11:21 +0100 Subject: [PATCH 134/371] CURA-4946 When storing the gcode profile, the definition must be the quality definition if the printer has_machine_quality. Otherwise the fdmprinter definition must be used as a fallback. If there is no quality_definition then the printer definition is use. --- cura/Settings/CuraContainerRegistry.py | 2 +- plugins/GCodeWriter/GCodeWriter.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index e26dab7399..540f0b3475 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -237,7 +237,7 @@ class CuraContainerRegistry(ContainerRegistry): if expected_machine_definition is not None and profile_definition is not None and profile_definition != expected_machine_definition: Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition) return { "status": "error", - "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} doesn't match with your current machine, could not import it.", file_name)} + "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it.", file_name, profile_definition, expected_machine_definition)} name_seed = os.path.splitext(os.path.basename(file_name))[0] new_name = self.uniqueName(name_seed) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index d06332bec1..7ef8c494ba 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -5,6 +5,7 @@ from UM.Mesh.MeshWriter import MeshWriter from UM.Logger import Logger from UM.Application import Application from UM.Settings.InstanceContainer import InstanceContainer +from UM.Util import parseBool from cura.Settings.ExtruderManager import ExtruderManager @@ -120,6 +121,14 @@ class GCodeWriter(MeshWriter): if flat_global_container.getMetaDataEntry("quality_type", None) is None: flat_global_container.addMetaDataEntry("quality_type", stack.quality.getMetaDataEntry("quality_type", "normal")) + # Change the default defintion + default_machine_definition = "fdmprinter" + if parseBool(stack.getMetaDataEntry("has_machine_quality", "False")): + default_machine_definition = stack.getMetaDataEntry("quality_definition") + if not default_machine_definition: + default_machine_definition = stack.definition.getId() + flat_global_container.setMetaDataEntry("definition", default_machine_definition) + serialized = flat_global_container.serialize() data = {"global_quality": serialized} @@ -140,6 +149,15 @@ class GCodeWriter(MeshWriter): # Ensure that quality_type is set. (Can happen if we have empty quality changes). if flat_extruder_quality.getMetaDataEntry("quality_type", None) is None: flat_extruder_quality.addMetaDataEntry("quality_type", extruder.quality.getMetaDataEntry("quality_type", "normal")) + + # Change the default defintion + default_extruder_definition = "fdmextruder" + if parseBool(stack.getMetaDataEntry("has_machine_quality", "False")): + default_extruder_definition = extruder.getMetaDataEntry("quality_definition") + if not default_extruder_definition: + default_extruder_definition = extruder.definition.getId() + flat_extruder_quality.setMetaDataEntry("definition", default_extruder_definition) + extruder_serialized = flat_extruder_quality.serialize() data.setdefault("extruder_quality", []).append(extruder_serialized) From c432d4ffbbb8cbcbf38e040a3161e6c21106ae8d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 20 Feb 2018 11:16:32 +0100 Subject: [PATCH 135/371] WIP: Simplify global stack and extruder stack activation and fixes --- cura/Settings/CuraStackBuilder.py | 5 +++-- cura/Settings/ExtruderManager.py | 13 ++----------- cura/Settings/ExtruderStack.py | 3 +-- cura/Settings/MachineManager.py | 6 ++++-- plugins/CuraEngineBackend/CuraEngineBackend.py | 1 - resources/qml/Menus/NozzleMenu.qml | 7 ++++--- 6 files changed, 14 insertions(+), 21 deletions(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index c396a4a2be..f5e08b766a 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -102,6 +102,7 @@ class CuraStackBuilder: variant_container = variant_container, material_container = material_container, quality_container = application.empty_quality_container, + global_stack = new_global_stack, ) new_extruder.setNextStack(new_global_stack) new_global_stack.addExtruder(new_extruder) @@ -133,11 +134,11 @@ class CuraStackBuilder: @classmethod def createExtruderStack(cls, new_stack_id: str, extruder_definition: DefinitionContainerInterface, machine_definition_id: str, position: int, - variant_container, material_container, quality_container) -> ExtruderStack: + variant_container, material_container, quality_container, global_stack) -> ExtruderStack: from cura.CuraApplication import CuraApplication application = CuraApplication.getInstance() - stack = ExtruderStack(new_stack_id) + stack = ExtruderStack(new_stack_id, parent = global_stack) stack.setName(extruder_definition.getName()) stack.setDefinition(extruder_definition) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 35b5b1320b..56834ca32a 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -36,22 +36,15 @@ class ExtruderManager(QObject): self._global_container_stack_definition_id = None self._addCurrentMachineExtruders() - Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged) + #Application.getInstance().globalContainerStackChanged.connect(self._globalContainerStackChanged) Selection.selectionChanged.connect(self.resetSelectedObjectExtruders) ## Signal to notify other components when the list of extruders for a machine definition changes. extrudersChanged = pyqtSignal(QVariant) - ## Signal to notify other components when the global container stack is switched to a definition - # that has different extruders than the previous global container stack - globalContainerStackDefinitionChanged = pyqtSignal() - ## Notify when the user switches the currently active extruder. activeExtruderChanged = pyqtSignal() - ## The signal notifies subscribers if extruders are added - extrudersAdded = pyqtSignal() - ## Gets the unique identifier of the currently active extruder stack. # # The currently active extruder stack is the stack that is currently being @@ -371,11 +364,10 @@ class ExtruderManager(QObject): return result[:machine_extruder_count] - def __globalContainerStackChanged(self) -> None: + def _globalContainerStackChanged(self) -> None: global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack and global_container_stack.getBottom() and global_container_stack.getBottom().getId() != self._global_container_stack_definition_id: self._global_container_stack_definition_id = global_container_stack.getBottom().getId() - self.globalContainerStackDefinitionChanged.emit() # If the global container changed, the machine changed and might have extruders that were not registered yet self._addCurrentMachineExtruders() @@ -415,7 +407,6 @@ class ExtruderManager(QObject): if extruders_changed: self.extrudersChanged.emit(global_stack_id) - self.extrudersAdded.emit() self.setActiveExtruderIndex(0) ## Get all extruder values for a certain setting. diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index a2ff092143..5a3ac85d75 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -3,7 +3,6 @@ from typing import Any, TYPE_CHECKING, Optional -from UM.Application import Application from UM.Decorators import override from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase from UM.Settings.ContainerStack import ContainerStack @@ -34,7 +33,7 @@ class ExtruderStack(CuraContainerStack): # # This will set the next stack and ensure that we register this stack as an extruder. @override(ContainerStack) - def setNextStack(self, stack: ContainerStack) -> None: + def setNextStack(self, stack: CuraContainerStack) -> None: super().setNextStack(stack) stack.addExtruder(self) self.addMetaDataEntry("machine", stack.id) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7be3f0798e..45c7648916 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -283,6 +283,7 @@ class MachineManager(QObject): containers = container_registry.findContainerStacks(id = stack_id) if containers: Application.getInstance().setGlobalContainerStack(containers[0]) + ExtruderManager.getInstance()._globalContainerStackChanged() self.__emitChangedSignals() @@ -877,9 +878,10 @@ class MachineManager(QObject): @pyqtSlot(int, result = QObject) def getExtruder(self, position: int): + extruder = None if self._global_container_stack: - return self._global_container_stack.extruders.get(str(position)) - return None + extruder = self._global_container_stack.extruders.get(str(position)) + return extruder def _onMachineNameChanged(self): self.globalContainerChanged.emit() diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index cd4f74141b..ea3ac3c0f8 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -88,7 +88,6 @@ class CuraEngineBackend(QObject, Backend): # self._global_container_stack = None Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged) - Application.getInstance().getExtruderManager().extrudersAdded.connect(self._onGlobalStackChanged) self._onGlobalStackChanged() Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished) diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index ea1c0000f4..153bd88220 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -13,7 +13,8 @@ Menu title: "Nozzle" property int extruderIndex: 0 - property var extruderStack: Cura.MachineManager.getExtruder(menu.extruderIndex) + property QtObject extruderStack: Cura.MachineManager.getExtruder(menu.extruderIndex) + property bool hasExtruderStack: extruderStack != null Cura.NozzleModel { @@ -24,7 +25,7 @@ Menu { target: Cura.MachineManager onGlobalContainerChanged: { - menu.extruderStack = Cura.MachineManager.getExtruder(extruderIndex); + menu.extruderStack = Cura.MachineManager.getExtruder(menu.extruderIndex); } } @@ -36,7 +37,7 @@ Menu { text: model.hotend_name checkable: true - checked: extruderStack.variant.name == model.hotend_name + checked: menu.hasExtruderStack && extruderStack.variant.name == model.hotend_name exclusiveGroup: group onTriggered: { Cura.MachineManager.setVariantGroup(extruderIndex, model.container_node); From fa37a48caae47ff0777fbcf747f153ce8d19ec52 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 20 Feb 2018 11:25:42 +0100 Subject: [PATCH 136/371] WIP: Fix default buildplate lookup --- cura/Settings/CuraStackBuilder.py | 43 +++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index f5e08b766a..0348d6855f 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -1,16 +1,17 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from UM.Logger import Logger +from typing import Optional +from UM.Logger import Logger from UM.Settings.Interfaces import DefinitionContainerInterface from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Util import parseBool +from cura.Machines.VariantManager import VariantType from .GlobalStack import GlobalStack from .ExtruderStack import ExtruderStack -from typing import Optional ## Contains helper functions to create new machines. @@ -37,18 +38,32 @@ class CuraStackBuilder: machine_definition = definitions[0] + # get variant container for the global stack + global_variant_container = application.empty_variant_container + if parseBool(machine_definition.getMetaDataEntry("has_variant_buildplates", False)): + global_variant_name = machine_definition.getMetaDataEntry("preferred_variant_buildplate_name") + if global_variant_name: + variant_node = variant_manager.getVariantNode(definition_id, global_variant_name, + variant_type = VariantType.BUILD_PLATE) + if variant_node is None: + raise RuntimeError("Cannot find buildplate variant with definition [%s] and variant name [%s]" % + (definition_id, global_variant_name)) + global_variant_container = variant_node.getContainer() + + # get variant container for extruders - variant_container = application.empty_variant_container + extruder_variant_container = application.empty_variant_container # Only look for the preferred variant if this machine has variants - variant_name = None + extruder_variant_name = None if parseBool(machine_definition.getMetaDataEntry("has_variants", False)): - variant_name = machine_definition.getMetaDataEntry("preferred_variant_name") - if variant_name: - variant_node = variant_manager.getVariantNode(definition_id, variant_name) + extruder_variant_name = machine_definition.getMetaDataEntry("preferred_variant_name") + if extruder_variant_name: + variant_node = variant_manager.getVariantNode(definition_id, extruder_variant_name) # Sanity check. If you see this error, the related definition files should be fixed. if variant_node is None: - raise RuntimeError("Cannot find variant with definition [%s] and variant name [%s]" % (definition_id, variant_name)) - variant_container = variant_node.getContainer() + raise RuntimeError("Cannot find extruder variant with definition [%s] and variant name [%s]" % + (definition_id, extruder_variant_name)) + extruder_variant_container = variant_node.getContainer() # get material container for extruders material_container = application.empty_material_container @@ -58,11 +73,11 @@ class CuraStackBuilder: approximate_material_diameter = str(round(material_diameter)) root_material_id = machine_definition.getMetaDataEntry("preferred_material") root_material_id = material_manager.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter) - material_node = material_manager.getMaterialNode(definition_id, variant_name, material_diameter, root_material_id) + material_node = material_manager.getMaterialNode(definition_id, extruder_variant_name, material_diameter, root_material_id) # Sanity check. If you see this error, the related definition files should be fixed. if not material_node: - raise RuntimeError("Cannot find material with definition [%s], variant_name [%s], and root_material_id [%s]" % - (definition_id, variant_name, root_material_id)) + raise RuntimeError("Cannot find material with definition [%s], extruder_variant_name [%s], and root_material_id [%s]" % + (definition_id, extruder_variant_name, root_material_id)) material_container = material_node.getContainer() generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName()) @@ -75,7 +90,7 @@ class CuraStackBuilder: new_global_stack = cls.createGlobalStack( new_stack_id = generated_name, definition = machine_definition, - variant_container = application.empty_variant_container, # TODO: fix for build plate + variant_container = global_variant_container, material_container = application.empty_material_container, quality_container = application.empty_quality_container, ) @@ -99,7 +114,7 @@ class CuraStackBuilder: extruder_definition = extruder_definition, machine_definition_id = definition_id, position = position, - variant_container = variant_container, + variant_container = extruder_variant_container, material_container = material_container, quality_container = application.empty_quality_container, global_stack = new_global_stack, From 605043235a620b6d3530eded0320e6223e78015b Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 11:36:51 +0100 Subject: [PATCH 137/371] CURA-4606 fixed create profile from profile context menu --- resources/qml/Preferences/ProfilesPage.qml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index ce8bd7dd3c..2a6bd9c6f2 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -154,6 +154,15 @@ Item } } + // Click create profile from ... in Profile context menu + signal createProfile() + onCreateProfile: + { + createQualityDialog.object = Cura.ContainerManager.makeUniqueName(Cura.MachineManager.activeQualityOrQualityChangesName); + createQualityDialog.open(); + createQualityDialog.selectText(); + } + // Dialog to request a name when creating a new profile UM.RenameDialog { From c76995c926352e93637cec963ea4d59a45da551e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 11:39:59 +0100 Subject: [PATCH 138/371] CURA-4606 update quality profiles model with field LayerHeightWithoutUnitRole --- cura/Machines/Models/QualityProfilesModel.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index 88a999b6ad..28edf9c888 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -17,9 +17,10 @@ class QualityProfilesModel(ListModel): NameRole = Qt.UserRole + 2 QualityTypeRole = Qt.UserRole + 3 LayerHeightRole = Qt.UserRole + 4 - AvailableRole = Qt.UserRole + 5 - QualityGroupRole = Qt.UserRole + 6 - QualityChangesGroupRole = Qt.UserRole + 7 + LayerHeightWithoutUnitRole = Qt.UserRole + 5 + AvailableRole = Qt.UserRole + 6 + QualityGroupRole = Qt.UserRole + 7 + QualityChangesGroupRole = Qt.UserRole + 8 def __init__(self, parent = None): super().__init__(parent) @@ -28,6 +29,7 @@ class QualityProfilesModel(ListModel): self.addRoleName(self.NameRole, "name") self.addRoleName(self.QualityTypeRole, "quality_type") self.addRoleName(self.LayerHeightRole, "layer_height") + self.addRoleName(self.LayerHeightWithoutUnitRole, "layer_height_without_unit") self.addRoleName(self.AvailableRole, "available") self.addRoleName(self.QualityGroupRole, "quality_group") self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") From 3619f5aef32199269b956d2e2086601f9c3ee9a9 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 11:57:05 +0100 Subject: [PATCH 139/371] CURA-4606 update initial materials menu --- cura/Machines/Models/MaterialsModel.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/Machines/Models/MaterialsModel.py b/cura/Machines/Models/MaterialsModel.py index 7d390277d6..e79ebe36bc 100644 --- a/cura/Machines/Models/MaterialsModel.py +++ b/cura/Machines/Models/MaterialsModel.py @@ -74,6 +74,8 @@ class GenericMaterialsModel(BaseMaterialsModel): extruder_manager.activeExtruderChanged.connect(self._update) material_manager.materialsUpdated.connect(self._update) + self._update() + def _update(self): item_list = [] result_dict = getAvailableMaterials() From b2ca8565c985e7d4634aaa0d3ac6fc8a1ff0b34d Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 13:02:39 +0100 Subject: [PATCH 140/371] CURA-4606 fix startup crash --- cura/BuildVolume.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 60e7a32857..6401ad77af 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -936,8 +936,8 @@ class BuildVolume(SceneNode): # stack. # # \return A sequence of setting values, one for each extruder. - def _getSettingFromAllExtruders(self, setting_key, property = "value"): - all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, property) + def _getSettingFromAllExtruders(self, setting_key): + all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "value") all_types = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "type") for i in range(len(all_values)): if not all_values[i] and (all_types[i] == "int" or all_types[i] == "float"): @@ -950,7 +950,7 @@ class BuildVolume(SceneNode): # not part of the collision radius, such as bed adhesion (skirt/brim/raft) # and travel avoid distance. def _getEdgeDisallowedSize(self): - if not self._global_container_stack: + if not self._global_container_stack or not self._global_container_stack.extruders: return 0 container_stack = self._global_container_stack From b9e7ee18a6cc2b12388925f79d2f6db6a2a64774 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 13:06:54 +0100 Subject: [PATCH 141/371] CURA-4606 fixed menu setting nozzle --- resources/qml/Menus/MaterialMenu.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index e77ab2861a..ac398356fd 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -21,12 +21,11 @@ Menu { text: model.name checkable: true - checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[Cura.ExtruderManager.activeExtruderIndex] + checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[extruderIndex] exclusiveGroup: group onTriggered: { - var activeExtruderIndex = Cura.ExtruderManager.activeExtruderIndex; - Cura.MachineManager.setMaterial(activeExtruderIndex, model.container_node); + Cura.MachineManager.setMaterial(extruderIndex, model.container_node); } } onObjectAdded: menu.insertItem(index, object) From f27685e6ac4ca5c4536bae656e8cb98e51cff1cc Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 20 Feb 2018 13:56:30 +0100 Subject: [PATCH 142/371] CURA-4017 Enable the setting zig_zagiffy_infill for the grid and triangular patterns --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 80bb9b19b9..b1f79dcbb6 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1528,7 +1528,7 @@ "description": "Connect the ends where the infill pattern meets the inner wall using a line which follows the shape of the inner wall. Enabling this setting can make the infill adhere to the walls better and reduce the effects of infill on the quality of vertical surfaces. Disabling this setting reduces the amount of material used.", "type": "bool", "default_value": true, - "enabled": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'", + "enabled": "infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_pattern == 'grid' or infill_pattern == 'triangles'", "settable_per_mesh": true }, "infill_angles": From 9e9d981acd6d444f5bd906c7cfedc839100c60a7 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 15:17:19 +0100 Subject: [PATCH 143/371] CURA-4606 ensure that setting a new machine ends with correct quality (changes) group --- cura/Settings/MachineManager.py | 38 +++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 45c7648916..37fc3add7a 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -47,6 +47,10 @@ class MachineManager(QObject): self._active_container_stack = None # type: CuraContainerStack self._global_container_stack = None # type: GlobalStack + self._current_root_material_id = {} + self._current_quality_group = None + self._current_quality_changes_group = None + self.machine_extruder_material_update_dict = collections.defaultdict(list) # Used to store the new containers until after confirming the dialog @@ -65,8 +69,9 @@ class MachineManager(QObject): self._instance_container_timer.setSingleShot(True) self._instance_container_timer.timeout.connect(self.__emitChangedSignals) - Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) - Application.getInstance().getContainerRegistry().containerLoadComplete.connect(self._onInstanceContainersChanged) + self._application = Application.getInstance() + self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged) + self._application.getContainerRegistry().containerLoadComplete.connect(self._onInstanceContainersChanged) ## When the global container is changed, active material probably needs to be updated. self.globalContainerChanged.connect(self.activeMaterialChanged) @@ -123,10 +128,6 @@ class MachineManager(QObject): if containers: containers[0].nameChanged.connect(self._onMaterialNameChanged) - ### NEW - self._current_root_material_id = {} - self._current_quality_group = None - self._current_quality_changes_group = None ### NEW activeQualityGroupChanged = pyqtSignal() @@ -273,6 +274,30 @@ class MachineManager(QObject): elif property_name == "validationState": self._error_check_timer.start() + ## Given a global_stack, make sure that it's all valid by searching for this quality group and applying it again + def _initMachineState(self, global_stack): + material_dict = {} + for position, extruder in global_stack.extruders.items(): + material_dict[position] = extruder.material.getMetaDataEntry("base_file") + self._current_root_material_id = material_dict + global_quality = global_stack.quality + global_quality_changes = global_stack.qualityChanges + + quality_groups = self._application._quality_manager.getQualityGroups(global_stack) + quality_type = global_quality.getMetaDataEntry("quality_type") + if quality_type in quality_groups: + new_quality_group = quality_groups[quality_type] + else: + new_quality_group = quality_groups.values()[0] + Logger.log("e", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values())) + self._setQualityGroup(new_quality_group) + + if global_quality_changes.getId() != "empty_quality_changes": + quality_changes_groups = self._application._quality_manager.getQualityChangesGroups(global_stack) + if quality_type in quality_changes_groups: + new_quality_changes_group = quality_changes_groups[quality_type] + self._setQualityChangesGroup(new_quality_changes_group) + @pyqtSlot(str) def setActiveMachine(self, stack_id: str) -> None: self.blurSettings.emit() # Ensure no-one has focus. @@ -284,6 +309,7 @@ class MachineManager(QObject): if containers: Application.getInstance().setGlobalContainerStack(containers[0]) ExtruderManager.getInstance()._globalContainerStackChanged() + self._initMachineState(containers[0]) self.__emitChangedSignals() From 4ba7ce0890b43b31c711689b9665bbe70968786a Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 15:26:20 +0100 Subject: [PATCH 144/371] CURA-4606 fix pyqt cleaning up by setting extruder stack parent --- cura/Settings/ExtruderManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 56834ca32a..3bf248970e 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -396,6 +396,7 @@ class ExtruderManager(QObject): self._extruder_trains[global_stack_id][extruder_train.getMetaDataEntry("position")] = extruder_train # regardless of what the next stack is, we have to set it again, because of signal routing. ??? + extruder_train.setParent(global_stack) extruder_train.setNextStack(global_stack) extruders_changed = True From c56b3bc7bd1312507b7725286aff3f3b1c7acca1 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 15:35:17 +0100 Subject: [PATCH 145/371] CURA-4606 add the discard or keep changes screen --- cura/Settings/MachineManager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 37fc3add7a..c35c8dc004 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1110,8 +1110,13 @@ class MachineManager(QObject): self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setQualityGroup(quality_group) + Logger.log("d", "Quality set!") + # See if we need to show the Discard or Keep changes screen + if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: + Application.getInstance().discardOrKeepProfileChanges() + @pyqtProperty("QVariant", fset = setQualityGroup, notify = activeQualityGroupChanged) def activeQualityGroup(self): return self._current_quality_group From b96d49c0103fa728daeda89108e15174f4c5c9f7 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Feb 2018 16:04:41 +0100 Subject: [PATCH 146/371] CURA-4606 ensure startup order for machine manager before build volume to prevent errors there --- cura/CuraApplication.py | 2 ++ cura/Machines/Models/QualityProfilesModel.py | 2 ++ cura/Settings/MachineManager.py | 25 ++++++++++---------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 41f5fbc4b2..b66bdcb6a8 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -754,6 +754,8 @@ class CuraApplication(QtApplication): self._quality_manager = QualityManager(container_registry) self._quality_manager.initialize() + self.getMachineManager() # ensure creation of machine manager + # Check if we should run as single instance or not self._setUpSingleInstanceServer() diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index 28edf9c888..034852a101 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -43,6 +43,8 @@ class QualityProfilesModel(ListModel): self._layer_height_unit = "" # This is cached + self._update() + def _update(self): Logger.log("d", "Updating quality profile model ...") diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index c35c8dc004..3844879081 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -107,18 +107,12 @@ class MachineManager(QObject): self._global_event_keys = set() - active_machine_id = Preferences.getInstance().getValue("cura/active_machine") - self._printer_output_devices = [] Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged) # There might already be some output devices by the time the signal is connected self._onOutputDevicesChanged() - if active_machine_id != "" and ContainerRegistry.getInstance().findContainerStacksMetadata(id = active_machine_id): - # An active machine was saved, so restore it. - self.setActiveMachine(active_machine_id) - # Make sure _active_container_stack is properly initiated - ExtruderManager.getInstance().setActiveExtruderIndex(0) + self._application.callLater(self.setInitialActiveMachine) self._material_incompatible_message = Message(catalog.i18nc("@info:status", "The selected material is incompatible with the selected machine or configuration."), @@ -150,6 +144,14 @@ class MachineManager(QObject): rootMaterialChanged = pyqtSignal() + def setInitialActiveMachine(self): + active_machine_id = Preferences.getInstance().getValue("cura/active_machine") + if active_machine_id != "" and ContainerRegistry.getInstance().findContainerStacksMetadata(id = active_machine_id): + # An active machine was saved, so restore it. + self.setActiveMachine(active_machine_id) + # Make sure _active_container_stack is properly initiated + ExtruderManager.getInstance().setActiveExtruderIndex(0) + def _onOutputDevicesChanged(self) -> None: self._printer_output_devices = [] for printer_output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices(): @@ -285,11 +287,10 @@ class MachineManager(QObject): quality_groups = self._application._quality_manager.getQualityGroups(global_stack) quality_type = global_quality.getMetaDataEntry("quality_type") - if quality_type in quality_groups: - new_quality_group = quality_groups[quality_type] - else: - new_quality_group = quality_groups.values()[0] - Logger.log("e", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values())) + if not quality_type in quality_groups: + Logger.log("w", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values())) + return + new_quality_group = quality_groups[quality_type] self._setQualityGroup(new_quality_group) if global_quality_changes.getId() != "empty_quality_changes": From c323bac306217be924548284106351160429bdb1 Mon Sep 17 00:00:00 2001 From: maukcc Date: Tue, 20 Feb 2018 17:15:21 +0100 Subject: [PATCH 147/371] extruder change update extruder change update: - wiping nozzles - temperature updates --- resources/definitions/cartesio.def.json | 11 ++++++----- .../extruders/cartesio_extruder_0.def.json | 13 +++---------- .../extruders/cartesio_extruder_1.def.json | 13 +++---------- .../extruders/cartesio_extruder_2.def.json | 17 +++++------------ .../extruders/cartesio_extruder_3.def.json | 15 ++++----------- .../abs/cartesio_0.25_abs_high.inst.cfg | 2 +- .../abs/cartesio_0.25_abs_normal.inst.cfg | 2 +- .../cartesio/abs/cartesio_0.4_abs_high.inst.cfg | 2 +- .../abs/cartesio_0.4_abs_normal.inst.cfg | 2 +- .../abs/cartesio_0.8_abs_coarse.inst.cfg | 2 +- .../abs/cartesio_0.8_abs_extra_coarse.inst.cfg | 2 +- .../cartesio/abs/cartesio_0.8_abs_high.inst.cfg | 2 +- .../abs/cartesio_0.8_abs_normal.inst.cfg | 2 +- .../cartesio_0.4_arnitel2045_high.inst.cfg | 2 +- .../cartesio_0.4_arnitel2045_normal.inst.cfg | 2 +- .../hips/cartesio_0.25_hips_high.inst.cfg | 2 +- .../hips/cartesio_0.25_hips_normal.inst.cfg | 2 +- .../hips/cartesio_0.4_hips_high.inst.cfg | 2 +- .../hips/cartesio_0.4_hips_normal.inst.cfg | 2 +- .../hips/cartesio_0.8_hips_coarse.inst.cfg | 2 +- .../cartesio_0.8_hips_extra_coarse.inst.cfg | 2 +- .../hips/cartesio_0.8_hips_high.inst.cfg | 2 +- .../hips/cartesio_0.8_hips_normal.inst.cfg | 2 +- .../nylon/cartesio_0.25_nylon_high.inst.cfg | 2 +- .../nylon/cartesio_0.25_nylon_normal.inst.cfg | 2 +- .../nylon/cartesio_0.4_nylon_high.inst.cfg | 2 +- .../nylon/cartesio_0.4_nylon_normal.inst.cfg | 2 +- .../nylon/cartesio_0.8_nylon_coarse.inst.cfg | 2 +- .../cartesio_0.8_nylon_extra_coarse.inst.cfg | 2 +- .../nylon/cartesio_0.8_nylon_high.inst.cfg | 2 +- .../nylon/cartesio_0.8_nylon_normal.inst.cfg | 2 +- .../cartesio/pc/cartesio_0.25_pc_high.inst.cfg | 2 +- .../pc/cartesio_0.25_pc_normal.inst.cfg | 2 +- .../cartesio/pc/cartesio_0.4_pc_high.inst.cfg | 2 +- .../cartesio/pc/cartesio_0.4_pc_normal.inst.cfg | 2 +- .../cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg | 2 +- .../pc/cartesio_0.8_pc_extra_coarse.inst.cfg | 2 +- .../cartesio/pc/cartesio_0.8_pc_high.inst.cfg | 2 +- .../cartesio/pc/cartesio_0.8_pc_normal.inst.cfg | 2 +- .../petg/cartesio_0.25_petg_high.inst.cfg | 2 +- .../petg/cartesio_0.25_petg_normal.inst.cfg | 2 +- .../petg/cartesio_0.4_petg_high.inst.cfg | 2 +- .../petg/cartesio_0.4_petg_normal.inst.cfg | 2 +- .../petg/cartesio_0.8_petg_coarse.inst.cfg | 2 +- .../cartesio_0.8_petg_extra_coarse.inst.cfg | 2 +- .../petg/cartesio_0.8_petg_high.inst.cfg | 2 +- .../petg/cartesio_0.8_petg_normal.inst.cfg | 2 +- .../pla/cartesio_0.25_pla_high.inst.cfg | 2 +- .../pla/cartesio_0.25_pla_normal.inst.cfg | 2 +- .../cartesio/pla/cartesio_0.4_pla_high.inst.cfg | 2 +- .../pla/cartesio_0.4_pla_normal.inst.cfg | 2 +- .../pla/cartesio_0.8_pla_coarse.inst.cfg | 2 +- .../pla/cartesio_0.8_pla_extra_coarse.inst.cfg | 2 +- .../cartesio/pla/cartesio_0.8_pla_high.inst.cfg | 2 +- .../pla/cartesio_0.8_pla_normal.inst.cfg | 2 +- .../pva/cartesio_0.25_pva_high.inst.cfg | 2 +- .../pva/cartesio_0.25_pva_normal.inst.cfg | 2 +- .../cartesio/pva/cartesio_0.4_pva_high.inst.cfg | 2 +- .../pva/cartesio_0.4_pva_normal.inst.cfg | 2 +- .../pva/cartesio_0.8_pva_coarse.inst.cfg | 2 +- .../pva/cartesio_0.8_pva_extra_coarse.inst.cfg | 2 +- .../cartesio/pva/cartesio_0.8_pva_high.inst.cfg | 2 +- .../pva/cartesio_0.8_pva_normal.inst.cfg | 2 +- 63 files changed, 79 insertions(+), 106 deletions(-) diff --git a/resources/definitions/cartesio.def.json b/resources/definitions/cartesio.def.json index 44f3153015..a4bab6432d 100644 --- a/resources/definitions/cartesio.def.json +++ b/resources/definitions/cartesio.def.json @@ -5,7 +5,7 @@ "metadata": { "visible": true, "author": "Scheepers", - "manufacturer": "Cartesio bv", + "manufacturer": "MaukCC", "file_formats": "text/x-gcode", "has_machine_quality": true, @@ -14,7 +14,7 @@ "has_variant_materials": true, "has_variants": true, - "variants_name": "Nozzle size", + "variants_name": "Tool", "preferred_variant": "*0.8*", "preferred_material": "*pla*", "preferred_quality": "*normal*", @@ -44,7 +44,7 @@ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "material_print_temp_wait": { "default_value": false }, "material_bed_temp_wait": { "default_value": false }, - "prime_tower_enable": { "default_value": true }, + "prime_tower_enable": { "default_value": false }, "prime_tower_wall_thickness": { "resolve": 0.7 }, "prime_tower_size": { "value": 24.0 }, "prime_tower_position_x": { "value": 125 }, @@ -55,15 +55,16 @@ [[215, 135], [-215, 135], [-215, 75], [215, 75]] ]}, "machine_start_gcode": { - "default_value": "\nM92 E159 ;2288 for V5 extruder\n\nM140 S{material_bed_temperature_layer_0}\nM104 S120 T1\nM104 S120 T2\nM104 S120 T3\n\nG21\nG90\nM42 S255 P13 ;chamber lights\nM42 S255 P12 ;fume extraction\nM204 S300 ;default acceleration\nM205 X10 ;default jerk\n\nM117 Homing Y ......\nG28 Y\nM117 Homing X ......\nG28 X\nM117 Homing Z ......\nG28 Z F100\nG1 Z10 F600\nG1 X70 Y20 F9000;go to wipe point\n\nM190 S{material_bed_temperature_layer_0}\n\nM117 Heating for 50 sec.\nG4 S20\nM117 Heating for 30 sec.\nG4 S20\nM117 Heating for 10 sec.\nM300 S1200 P1000\nG4 S9\n\nM117 purging nozzle....\nT0\nG92 E0;set E\nG1 E10 F100\nG92 E0\nG1 E-1 F600\n\nM117 wiping nozzle....\nG1 X1 Y24 F3000\nG1 X70 F9000\nG1 Z10 F900\n\nM104 S21 T1\nM104 S21 T2\nM104 S21 T3\n\nM117 Printing .....\n" + "default_value": "\nM92 E159 ;2288 for V5 extruder\n\nM140 S{material_bed_temperature_layer_0}\nM104 T1 S120\nM104 T2 S120\nM104 T3 S120\n\nG21\nG90\nM42 S255 P13 ;chamber lights\nM42 S255 P12 ;fume extraction\nM204 S300 ;default acceleration\nM205 X10 ;default jerk\n\nM117 Homing Y ......\nG28 Y\nM117 Homing X ......\nG28 X\nM117 Homing Z ......\nG28 Z F100\nG1 Z10 F600\nG1 X70 Y20 F9000;go to wipe point\n\nM190 S{material_bed_temperature_layer_0}\n\nM117 Heating for 50 sec.\nG4 S20\nM117 Heating for 30 sec.\nG4 S20\nM117 Heating for 10 sec.\nM300 S1200 P1000\nG4 S9\n\nM117 purging nozzle....\nT0\nG92 E0;set E\nG1 E10 F100\nG92 E0\nG1 E-1 F600\n\nM117 wiping nozzle....\nG1 X1 Y24 F3000\nG1 X70 F9000\nG1 Z10 F900\n\nM104 T1 S21\nM104 T2 S21\nM104 T3 S21\n\nM117 Printing .....\n" }, "machine_end_gcode": { - "default_value": "; -- END GCODE --\nM117 cooling down....\nM106 S255\nM140 S5\nM104 S5 T0\nM104 S5 T1\nM104 S5 T2\nM104 S5 T3\n\nG91\nG1 Z1 F900\nG90\n\nG1 X20.0 Y260.0 F6000\nG4 S7\nM84\nG4 S90\nM107\nM42 P12 S0\nM42 P13 S0\nM84\nT0\nM117 Finished.\n; -- end of GCODE --" + "default_value": "; -- END GCODE --\nM117 cooling down....\nM106 S255\nM140 S5\nM104 T0 S5\nM104 T1 S5\nM104 T2 S5\nM104 T3 S5\n\nG91\nG1 Z1 F900\nG90\n\nG1 X20.0 Y260.0 F6000\nG4 S7\nM84\nG4 S90\nM107\nM42 P12 S0\nM42 P13 S0\nM84\nT0\nM117 Finished.\n; -- end of GCODE --" }, "layer_height": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" }, "layer_height_0": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" }, "retraction_extra_prime_amount": { "minimum_value_warning": "-2.0" }, "optimize_wall_printing_order": { "default_value": true }, + "material_initial_print_temperature": {"maximum_value_warning": "material_print_temperature + 15" }, "machine_nozzle_heat_up_speed": {"default_value": 20}, "machine_nozzle_cool_down_speed": {"default_value": 20}, "machine_min_cool_heat_time_window": {"default_value": 5} diff --git a/resources/extruders/cartesio_extruder_0.def.json b/resources/extruders/cartesio_extruder_0.def.json index 5558d9325e..47b5b5abf5 100644 --- a/resources/extruders/cartesio_extruder_0.def.json +++ b/resources/extruders/cartesio_extruder_0.def.json @@ -16,17 +16,10 @@ "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 }, "machine_extruder_start_code": { - "default_value": "\n;start extruder_0\n\nM117 printing...\n" + "default_value": "\n;start T0\n\nM104 T0 S{material_print_temperature_layer_0}\nG1 X65 Y35 F9000 ; go to wipe position\nM109 T0 S{material_print_temperature_layer_0}; wait for temp\nG1 E10 F300; prime\nG92 E0\nG1 X45 Y15 F3000; wipe\nG1 X55 F9000\nG1 Y35 F6000; wipe again\n\nM117 printing...\n" }, "machine_extruder_end_code": { - "default_value": "\nM104 T0 S120\n;end extruder_0\nM117 temp is {material_print_temp}\n" - }, - - "machine_extruder_start_pos_abs": { "default_value": true }, - "machine_extruder_start_pos_x": { "default_value": 24 }, - "machine_extruder_start_pos_y": { "default_value": 16 }, - "machine_extruder_end_pos_abs": { "default_value": true }, - "machine_extruder_end_pos_x": { "default_value": 48 }, - "machine_extruder_end_pos_y": { "default_value": 16 } + "default_value": "\nM104 T0 S{material_standby_temperature}\nG1 X65 Y35 F9000 ; go to wipe position\nM109 T0 R{material_standby_temperature}; wait for temp\nG1 X45 Y15 F3000; wipe\nG1 X55 F9000\nG1 Y35 F6000; wipe again\n\n;end T0\n\n" + } } } diff --git a/resources/extruders/cartesio_extruder_1.def.json b/resources/extruders/cartesio_extruder_1.def.json index f8350f8091..78bcccd12a 100644 --- a/resources/extruders/cartesio_extruder_1.def.json +++ b/resources/extruders/cartesio_extruder_1.def.json @@ -16,17 +16,10 @@ "machine_nozzle_offset_x": { "default_value": 24.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 }, "machine_extruder_start_code": { - "default_value": "\n;start extruder_1\n\nM117 printing...\n" + "default_value": "\n;start T1\n\nM104 T1 S{material_print_temperature_layer_0}\nG1 X41 Y35 F9000 ; go to wipe position\nM109 T1 S{material_print_temperature_layer_0}; wait for temp\nG1 E10 F300; prime\nG92 E0\nG1 X21 Y15 F3000; wipe\nG1 X34 F9000\nG1 Y35 F6000; wipe again\n\nM117 printing...\n" }, "machine_extruder_end_code": { - "default_value": "\nM104 T1 S120\n;end extruder_1\n" - }, - - "machine_extruder_start_pos_abs": { "default_value": true }, - "machine_extruder_start_pos_x": { "default_value": 48 }, - "machine_extruder_start_pos_y": { "default_value": 16 }, - "machine_extruder_end_pos_abs": { "default_value": true }, - "machine_extruder_end_pos_x": { "default_value": 24 }, - "machine_extruder_end_pos_y": { "default_value": 16 } + "default_value": "\nM104 T1 S{material_standby_temperature}\nG1 X41 Y35 F9000 ; go to wipe position\nM109 T1 R{material_standby_temperature}; wait for temp\nG1 X21 Y15 F3000; wipe\nG1 X31 F9000\nG1 Y35 F6000; wipe again\n\n;end T1\n\n" + } } } diff --git a/resources/extruders/cartesio_extruder_2.def.json b/resources/extruders/cartesio_extruder_2.def.json index bfc10e75c3..dbd6643bfe 100644 --- a/resources/extruders/cartesio_extruder_2.def.json +++ b/resources/extruders/cartesio_extruder_2.def.json @@ -13,20 +13,13 @@ "default_value": 2, "maximum_value": "3" }, - "machine_nozzle_offset_x": { "default_value": 0.0 }, - "machine_nozzle_offset_y": { "default_value": 0.0 }, + "machine_nozzle_offset_x": { "default_value": 24.0 }, + "machine_nozzle_offset_y": { "default_value": -100.0 }, "machine_extruder_start_code": { - "default_value": "\n;start extruder_2\n\nM117 printing...\n" + "default_value": "\n;start T2\n\nM104 T2 S{material_print_temperature_layer_0}\nG1 X41 Y215 F9000 ; go to wipe position\nM109 T2 S{material_print_temperature_layer_0}; wait for temp\nG1 E10 F300; prime\nG92 E0\nG1 X21 Y235 F3000; wipe\nG1 X31 F9000\nG1 Y215 F6000; wipe again\n\nM117 printing...\n" }, "machine_extruder_end_code": { - "default_value": "\nM104 T2 S120\n;end extruder_2\n" - }, - - "machine_extruder_start_pos_abs": { "default_value": true }, - "machine_extruder_start_pos_x": { "default_value": 24 }, - "machine_extruder_start_pos_y": { "default_value": 309 }, - "machine_extruder_end_pos_abs": { "default_value": true }, - "machine_extruder_end_pos_x": { "default_value": 48 }, - "machine_extruder_end_pos_y": { "default_value": 309 } + "default_value": "\nM104 T2 S{material_standby_temperature}\nG1 X41 Y215 F9000 ; go to wipe position\nM109 T2 R{material_standby_temperature}; wait for temp\nG1 X21 Y235 F3000; wipe\nG1 X31 F9000\nG1 Y215 F6000; wipe again\n\n;end T2\n\n" + } } } diff --git a/resources/extruders/cartesio_extruder_3.def.json b/resources/extruders/cartesio_extruder_3.def.json index f0be53e564..beed117abe 100644 --- a/resources/extruders/cartesio_extruder_3.def.json +++ b/resources/extruders/cartesio_extruder_3.def.json @@ -14,19 +14,12 @@ "maximum_value": "3" }, "machine_nozzle_offset_x": { "default_value": 0.0 }, - "machine_nozzle_offset_y": { "default_value": 0.0 }, + "machine_nozzle_offset_y": { "default_value": -100.0 }, "machine_extruder_start_code": { - "default_value": "\n;start extruder_3\n\nM117 printing...\n" + "default_value": "\n;start T3\n\nM104 T3 S{material_print_temperature_layer_0}\nG1 X65 Y215 F9000 ; go to wipe position\nM109 T3 S{material_print_temperature_layer_0}; wait for temp\nG1 E10 F300; prime\nG92 E0\nG1 X45 Y235 F3000; wipe\nG1 X55 F9000\nG1 Y215 F6000; wipe again\n\nM117 printing...\n" }, "machine_extruder_end_code": { - "default_value": "\nM104 T3 S120\n;end extruder_3\n" - }, - - "machine_extruder_start_pos_abs": { "default_value": true }, - "machine_extruder_start_pos_x": { "default_value": 48 }, - "machine_extruder_start_pos_y": { "default_value": 309 }, - "machine_extruder_end_pos_abs": { "default_value": true }, - "machine_extruder_end_pos_x": { "default_value": 24 }, - "machine_extruder_end_pos_y": { "default_value": 309} + "default_value": "\nM104 T3 S{material_standby_temperature}\nG1 X65 Y215 F9000 ; go to wipe position\nM109 T3 R{material_standby_temperature}; wait for temp\nG1 X45 Y235 F3000; wipe\nG1 X55 F9000\nG1 Y215 F6000; wipe again\n\n;end T3\n\n" + } } } diff --git a/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg index 418855a9ba..f541fd9654 100644 --- a/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg index e95ef08e22..a3c1d1ac14 100644 --- a/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg index 524f5ba12a..e299ccd2b2 100644 --- a/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg index 24ffb19d6f..ea92f0bd34 100644 --- a/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg index 1281a3afdd..3887e9dfe2 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg index a8d19deef7..c9f430ac9a 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg index 87cc855f44..983d199533 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg index 4ca2598051..06570a7153 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_high.inst.cfg b/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_high.inst.cfg index 42eb705f11..8afe86164e 100644 --- a/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_high.inst.cfg +++ b/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 2 diff --git a/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg b/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg index 538fe91b76..27c659ea0a 100644 --- a/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg +++ b/resources/quality/cartesio/arnitel/cartesio_0.4_arnitel2045_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 2 diff --git a/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg index eae4e82cd3..670b9012c7 100644 --- a/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg index 0c47b18196..c2a5bbff08 100644 --- a/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg index 14f1ea4662..fd3efddd07 100644 --- a/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg index bd13b358ff..1b0acd573e 100644 --- a/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg index ca864692c3..ca9907923f 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg index 3cadef4fdd..8f79fa6d37 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg index 07839c8a9a..1b7dac5eaf 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg index acc9db0891..843f14ea43 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg index b1f2f17d41..f8a1d2df33 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg index bcfa1c2e30..6c6f608390 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg index 2cd50efeb2..53abdcad1f 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg index 7a7d767ea3..9ff9dbf5e9 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg index 5684c89e23..4add038914 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg index 8d97e9ac5f..0020950cd5 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg index 946f8de34d..b74faaec40 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg index 80f390c254..cb59f1803c 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg index ff6547dd91..a1bee46782 100644 --- a/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg index f3faa9c129..dc5b88f84b 100644 --- a/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg index 3aa808fab5..49ddf1bc98 100644 --- a/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg index f9be12da3a..47fe5d9a40 100644 --- a/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg index 597187437b..c4313f2718 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg index 6d1fa196ec..5e093a8f32 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg index c570b65350..fa1bebc645 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg index 0d73b24197..12cb3a5abd 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg index c5c4be6f4a..f926688cc7 100644 --- a/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg index 6d12bdc402..fbea40e500 100644 --- a/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg index 43dda5007c..30f0d2d926 100644 --- a/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg index 094dc33263..688373bf94 100644 --- a/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg index da9e4ad3dd..2516cd17e8 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg index 607ba778a1..5c1995f5bc 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg index 3010d95dab..eb0afde18f 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 50 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg index fbf8fac67f..27c7b894b5 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg index 9d8130602e..90572b988f 100644 --- a/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg index 98401dbf42..51faec512e 100644 --- a/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg index 2eda5103d7..54e59d2e44 100644 --- a/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg index f3d3820ff7..a8526458b1 100644 --- a/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg index d2cf708336..02e86f00f5 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg index 888d8f91a7..aff51dc552 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg index 558514db98..2e000b9ce4 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg index 9c508e4a1f..240b0d497f 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 10 diff --git a/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg index fcbf4913de..9330a977b7 100644 --- a/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg index 3893421df0..204ca68174 100644 --- a/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg index 5876db1e2e..7a484180d4 100644 --- a/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg index c977e79a5c..6e12288510 100644 --- a/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg index 8c36d8e7ed..eefb7fe8a3 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg index c2b19868f6..cd7fe200bf 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg index 5bd285285a..602575b93c 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg index a11bff95e1..4201c8e37d 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg @@ -23,7 +23,7 @@ infill_sparse_density = 40 infill_pattern = grid material_print_temperature_layer_0 = =material_print_temperature + 5 -material_initial_print_temperature = =material_print_temperature +material_initial_print_temperature = =material_print_temperature_layer_0 + 5 material_final_print_temperature = =material_print_temperature retraction_min_travel = =round(line_width * 10) retraction_prime_speed = 8 From 767539b80b22207c4a9356b7bc430575a2c450f8 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 20 Feb 2018 10:46:01 +0100 Subject: [PATCH 148/371] CURA-4790 Changed light weights back to normal --- resources/themes/cura-light/theme.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 8eb874334a..1b5ddfe141 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -12,12 +12,12 @@ }, "large_nonbold": { "size": 1.35, - "weight": 25, + "weight": 50, "family": "Noto Sans" }, "default": { "size": 1.0, - "weight": 25, + "weight": 50, "family": "Noto Sans" }, "default_bold": { @@ -28,7 +28,7 @@ }, "default_italic": { "size": 1.15, - "weight": 25, + "weight": 50, "italic": true, "family": "Noto Sans" }, @@ -40,12 +40,12 @@ }, "very_small": { "size": 1.0, - "weight": 25, + "weight": 50, "family": "Noto Sans" }, "button_tooltip": { "size": 1.0, - "weight": 25, + "weight": 50, "family": "Noto Sans" }, "setting_category": { @@ -56,7 +56,7 @@ }, "action_button": { "size": 1.15, - "weight": 25, + "weight": 50, "bold": true, "family": "Noto Sans" } From 03265cb90a5eec0a0fb0fd827371e9d5d2b1993e Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 20 Feb 2018 11:04:23 +0100 Subject: [PATCH 149/371] CURA-4790 Removed "bold" property --- resources/themes/cura-light/theme.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 1b5ddfe141..8c8e6d1c47 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -7,7 +7,6 @@ "large": { "size": 1.35, "weight": 63, - "bold": true, "family": "Noto Sans" }, "large_nonbold": { @@ -23,7 +22,6 @@ "default_bold": { "size": 1.0, "weight": 63, - "bold": true, "family": "Noto Sans" }, "default_italic": { @@ -35,7 +33,6 @@ "small": { "size": 1.0, "weight": 63, - "bold": true, "family": "Noto Sans" }, "very_small": { @@ -51,13 +48,11 @@ "setting_category": { "size": 1.15, "weight": 63, - "bold": true, "family": "Noto Sans" }, "action_button": { "size": 1.15, "weight": 50, - "bold": true, "family": "Noto Sans" } }, From 31ad0dd56c0f55b7d5555085e6890e9972369e1c Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 21 Feb 2018 08:43:39 +0100 Subject: [PATCH 150/371] Allow zig-zaggifying infill for patterns other than Cross as well It is now supported for any linear-based infill except zigzag (which has its own algorithm; that's a TODO). Contributes to issue CURA-4017. --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b1f79dcbb6..6cfebf3dad 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1528,7 +1528,7 @@ "description": "Connect the ends where the infill pattern meets the inner wall using a line which follows the shape of the inner wall. Enabling this setting can make the infill adhere to the walls better and reduce the effects of infill on the quality of vertical surfaces. Disabling this setting reduces the amount of material used.", "type": "bool", "default_value": true, - "enabled": "infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_pattern == 'grid' or infill_pattern == 'triangles'", + "enabled": "infill_pattern == 'grid' || infill_pattern == 'triangles' || infill_pattern == 'trihexagon' || infill_pattern == 'cubic' || infill_pattern == 'tetrahedral' || infill_pattern == 'quarter_cubic' || infill_pattern == 'cross' || infill_pattern == 'cross_3d'", "settable_per_mesh": true }, "infill_angles": From f3aeb01af0adfedca30941b1c4fb10306c5aa466 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 21 Feb 2018 08:45:08 +0100 Subject: [PATCH 151/371] Only enable Connect Infill Lines by default for Cross We don't want to change the default behaviour yet. Contributes to issue CURA-4017. --- resources/definitions/fdmprinter.def.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6cfebf3dad..b5b7cd1c5d 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1527,7 +1527,8 @@ "label": "Connect Infill Lines", "description": "Connect the ends where the infill pattern meets the inner wall using a line which follows the shape of the inner wall. Enabling this setting can make the infill adhere to the walls better and reduce the effects of infill on the quality of vertical surfaces. Disabling this setting reduces the amount of material used.", "type": "bool", - "default_value": true, + "default_value": false, + "value": "infill_pattern == 'cross' || infill_pattern == 'cross_3d'", "enabled": "infill_pattern == 'grid' || infill_pattern == 'triangles' || infill_pattern == 'trihexagon' || infill_pattern == 'cubic' || infill_pattern == 'tetrahedral' || infill_pattern == 'quarter_cubic' || infill_pattern == 'cross' || infill_pattern == 'cross_3d'", "settable_per_mesh": true }, From 8401e1c7f76d3c7ecc72cd4bf55bf9205206b7ce Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 09:13:42 +0100 Subject: [PATCH 152/371] CURA-4606 incompatible material(s) now results in an empty quality list --- cura/Machines/Models/QualityProfilesModel.py | 8 +++++++- cura/Settings/MachineManager.py | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index 034852a101..2f1374cc8b 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -48,12 +48,18 @@ class QualityProfilesModel(ListModel): def _update(self): Logger.log("d", "Updating quality profile model ...") - active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + machine_manager = Application.getInstance().getMachineManager() + active_global_stack = machine_manager._global_container_stack if active_global_stack is None: self.setItems([]) Logger.log("d", "No active GlobalStack, set quality profile model as empty.") return + # Check for material compatibility + if not machine_manager.activeMaterialsCompatible(): + self.setItems([]) + return + quality_group_dict = self._quality_manager.getQualityGroups(active_global_stack) item_list = [] diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 3844879081..5673039497 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1018,6 +1018,13 @@ class MachineManager(QObject): self._current_root_material_id[position] = root_material_id self.rootMaterialChanged.emit() + def activeMaterialsCompatible(self): + # check material - variant compatibility + for position, extruder in self._global_container_stack.extruders.items(): + if not extruder.material.getMetaDataEntry("compatible"): + return False + return True + ## Update current quality type and machine after setting material def _updateQualityWithMaterial(self): current_quality = None @@ -1027,6 +1034,11 @@ class MachineManager(QObject): candidate_quality_groups = quality_manager.getQualityGroups(self._global_container_stack) available_quality_types = {qt for qt, g in candidate_quality_groups.items() if g.is_available} + if not self.activeMaterialsCompatible: + Logger.log("d", "Material [%s] is not compatible, setting empty material." % str(extruder.material)) + self._setEmptyQuality() + return + if not available_quality_types: self._setEmptyQuality() return From f9e2d7fe2cc5813f8b1c954cac6fc37c120849c4 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 09:17:31 +0100 Subject: [PATCH 153/371] CURA-4606 changing current print core now always updates the correct one --- cura/Settings/MachineManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 5673039497..c864eaaac5 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1003,6 +1003,7 @@ class MachineManager(QObject): def _setVariantNode(self, position, container_node): self._global_container_stack.extruders[position].variant = container_node.getContainer() + self.activeVariantChanged.emit() def _setGlobalVariant(self, container_node): self._global_container_stack.variant = container_node.getContainer() From 6110b83844af70ffc6fc67c852ca952baa7b692f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 21 Feb 2018 09:51:14 +0100 Subject: [PATCH 154/371] Use 'or' instead of '||' for Python code Oops. Contributes to issue CURA-4017. --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index b5b7cd1c5d..c8045ebce9 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1528,8 +1528,8 @@ "description": "Connect the ends where the infill pattern meets the inner wall using a line which follows the shape of the inner wall. Enabling this setting can make the infill adhere to the walls better and reduce the effects of infill on the quality of vertical surfaces. Disabling this setting reduces the amount of material used.", "type": "bool", "default_value": false, - "value": "infill_pattern == 'cross' || infill_pattern == 'cross_3d'", - "enabled": "infill_pattern == 'grid' || infill_pattern == 'triangles' || infill_pattern == 'trihexagon' || infill_pattern == 'cubic' || infill_pattern == 'tetrahedral' || infill_pattern == 'quarter_cubic' || infill_pattern == 'cross' || infill_pattern == 'cross_3d'", + "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'", + "enabled": "infill_pattern == 'grid' or infill_pattern == 'triangles' or infill_pattern == 'trihexagon' or infill_pattern == 'cubic' or infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' or infill_pattern == 'cross' or infill_pattern == 'cross_3d'", "settable_per_mesh": true }, "infill_angles": From ad6548a5dc98c0f203089dea8a526faefcafaa55 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 10:35:17 +0100 Subject: [PATCH 155/371] CURA-4606 factored activeMaterialName out --- cura/Settings/MachineManager.py | 32 ++++++++++---------------- resources/qml/Settings/SettingView.qml | 2 +- resources/qml/SidebarHeader.qml | 4 ++-- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index c864eaaac5..5a04d498af 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -48,6 +48,7 @@ class MachineManager(QObject): self._global_container_stack = None # type: GlobalStack self._current_root_material_id = {} + self._current_root_material_name = {} self._current_quality_group = None self._current_quality_changes_group = None @@ -445,15 +446,6 @@ class MachineManager(QObject): return "" - @pyqtProperty(str, notify = activeMaterialChanged) - def activeMaterialName(self) -> str: - if self._active_container_stack: - material = self._active_container_stack.material - if material: - return material.getName() - - return "" - @pyqtProperty("QVariantList", notify=activeVariantChanged) def activeVariantNames(self) -> List[str]: result = [] @@ -533,17 +525,6 @@ class MachineManager(QObject): return 0 # No quality profile. - @pyqtProperty(str, notify=activeQualityChanged) - def activeQualityName(self) -> str: - if self._active_container_stack and self._global_container_stack: - quality = self._global_container_stack.qualityChanges - if quality and not isinstance(quality, type(self._empty_quality_changes_container)): - return quality.getName() - quality = self._active_container_stack.quality - if quality: - return quality.getName() - return "" - @pyqtProperty(str, notify=activeQualityChanged) def activeQualityId(self) -> str: if self._active_container_stack: @@ -935,6 +916,15 @@ class MachineManager(QObject): self._current_root_material_id[position] = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") return self._current_root_material_id + @pyqtProperty("QVariant", notify = rootMaterialChanged) + def currentRootMaterialName(self): + # initial filling the current_root_material_name + for position in self._global_container_stack.extruders: + if position not in self._current_root_material_name: + material = self._global_container_stack.extruders[position].material + self._current_root_material_name[position] = material.getName() + return self._current_root_material_name + def _setEmptyQuality(self): self._current_quality_group = None self._current_quality_changes_group = None @@ -1015,8 +1005,10 @@ class MachineManager(QObject): self._global_container_stack.extruders[position].material = self._empty_material_container # The _current_root_material_id is used in the MaterialMenu to see which material is selected root_material_id = container_node.metadata["base_file"] + root_material_name = container_node.getContainer().getName() if root_material_id != self._current_root_material_id[position]: self._current_root_material_id[position] = root_material_id + self._current_root_material_name[position] = root_material_name self.rootMaterialChanged.emit() def activeMaterialsCompatible(self): diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 47c8b188ad..e03cb4977f 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -544,4 +544,4 @@ Item } } } -} \ No newline at end of file +} diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index d43b8d3752..2c99ce2dd3 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -252,8 +252,8 @@ Column { id: materialSelection - text: Cura.MachineManager.activeMaterialName - tooltip: Cura.MachineManager.activeMaterialName + text: Cura.MachineManager.currentRootMaterialName[base.currentExtruderIndex] + tooltip: Cura.MachineManager.currentRootMaterialName[base.currentExtruderIndex] visible: Cura.MachineManager.hasMaterials enabled: !extrudersList.visible || base.currentExtruderIndex > -1 height: UM.Theme.getSize("setting_control").height From 363db9e536d1bc93d2084ddc48b25e03ad972740 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 10:35:48 +0100 Subject: [PATCH 156/371] CURA-4606 no stack checking for errors on active extruder switch --- cura/Settings/MachineManager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 5a04d498af..20e453d431 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -250,8 +250,6 @@ class MachineManager(QObject): self._active_container_stack = ExtruderManager.getInstance().getActiveExtruderStack() - self._error_check_timer.start() - if old_active_container_stack != self._active_container_stack: # Many methods and properties related to the active quality actually depend # on _active_container_stack. If it changes, then the properties change. From c3349baf391a112ac5c86b36e75d3be6bf76c759 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 10:36:11 +0100 Subject: [PATCH 157/371] CURA-4606 fix bug concerning activeMaterialsCompatible; factor out activeQualityName --- cura/Settings/MachineManager.py | 5 ++--- resources/qml/Settings/SettingView.qml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 20e453d431..ec024f7b49 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1025,8 +1025,7 @@ class MachineManager(QObject): candidate_quality_groups = quality_manager.getQualityGroups(self._global_container_stack) available_quality_types = {qt for qt, g in candidate_quality_groups.items() if g.is_available} - if not self.activeMaterialsCompatible: - Logger.log("d", "Material [%s] is not compatible, setting empty material." % str(extruder.material)) + if not self.activeMaterialsCompatible(): self._setEmptyQuality() return @@ -1139,7 +1138,7 @@ class MachineManager(QObject): @pyqtProperty(str, notify = activeQualityGroupChanged) def activeQualityOrQualityChangesName(self): - name = "" + name = self._empty_quality_container.getName() if self._current_quality_changes_group: name = self._current_quality_changes_group.name elif self._current_quality_group: diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index e03cb4977f..8ff4c33244 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -63,7 +63,7 @@ Item menu: ProfileMenu { } function generateActiveQualityText () { - var result = Cura.MachineManager.activeQualityName; + var result = Cura.MachineManager.activeQualityOrQualityChangesName; if (Cura.MachineManager.isActiveQualitySupported) { if (Cura.MachineManager.activeQualityLayerHeight > 0) { From 471182333d218190c99c42427d29e82fd12b06c6 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 10:41:39 +0100 Subject: [PATCH 158/371] CURA-4606 refactored activeMaterialNames --- cura/Settings/MachineManager.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index ec024f7b49..e34b1a0763 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -460,15 +460,7 @@ class MachineManager(QObject): @pyqtProperty("QVariantList", notify = activeMaterialChanged) def activeMaterialNames(self) -> List[str]: - result = [] - - active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() - if active_stacks is not None: - for stack in active_stacks: - material_container = stack.material - if material_container and material_container != self._empty_material_container: - result.append(material_container.getName()) - return result + return list(self._current_root_material_name.values()) @pyqtProperty(str, notify=activeMaterialChanged) def activeMaterialId(self) -> str: From c338e1b7d69c252ae80d9590700823108a37f320 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 10:44:51 +0100 Subject: [PATCH 159/371] WIP: Fix quality profiles for abax_pri3 - Fixed duplicated quality_type and name for qualities "Fast" and "Fine" - Moved global settings to separate global quality files - Fix abax_pri3 definition file: has_machine_quality = true - MAYBE FIXME: Normal and Fast have the same layer height. Don't know if that's intended. They are kept as before. --- resources/definitions/abax_pri3.def.json | 3 ++- resources/quality/abax_pri3/apri3_fast.inst.cfg | 14 ++++++++++++++ resources/quality/abax_pri3/apri3_high.inst.cfg | 14 ++++++++++++++ resources/quality/abax_pri3/apri3_normal.inst.cfg | 14 ++++++++++++++ .../quality/abax_pri3/apri3_pla_fast.inst.cfg | 5 ++--- .../quality/abax_pri3/apri3_pla_high.inst.cfg | 1 - .../quality/abax_pri3/apri3_pla_normal.inst.cfg | 1 - 7 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 resources/quality/abax_pri3/apri3_fast.inst.cfg create mode 100644 resources/quality/abax_pri3/apri3_high.inst.cfg create mode 100644 resources/quality/abax_pri3/apri3_normal.inst.cfg diff --git a/resources/definitions/abax_pri3.def.json b/resources/definitions/abax_pri3.def.json index 2fa648096f..f91a501a6f 100644 --- a/resources/definitions/abax_pri3.def.json +++ b/resources/definitions/abax_pri3.def.json @@ -6,7 +6,8 @@ "visible": true, "author": "ABAX 3d Technologies", "manufacturer": "ABAX 3d Technologies", - "file_formats": "text/x-gcode" + "file_formats": "text/x-gcode", + "has_machine_quality": true }, "overrides": { "machine_start_gcode": { diff --git a/resources/quality/abax_pri3/apri3_fast.inst.cfg b/resources/quality/abax_pri3/apri3_fast.inst.cfg new file mode 100644 index 0000000000..7db569ec72 --- /dev/null +++ b/resources/quality/abax_pri3/apri3_fast.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 2 +name = Fast +definition = abax_pri3 + +[metadata] +setting_version = 4 +type = quality +quality_type = fast +weight = -1 +global_quality = True + +[values] +layer_height = 0.2 diff --git a/resources/quality/abax_pri3/apri3_high.inst.cfg b/resources/quality/abax_pri3/apri3_high.inst.cfg new file mode 100644 index 0000000000..8a95b71a88 --- /dev/null +++ b/resources/quality/abax_pri3/apri3_high.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 2 +name = Extra Fine +definition = abax_pri3 + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 1 +global_quality = True + +[values] +layer_height = 0.1 diff --git a/resources/quality/abax_pri3/apri3_normal.inst.cfg b/resources/quality/abax_pri3/apri3_normal.inst.cfg new file mode 100644 index 0000000000..29b25d889f --- /dev/null +++ b/resources/quality/abax_pri3/apri3_normal.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 2 +name = Fine +definition = abax_pri3 + +[metadata] +setting_version = 4 +type = quality +quality_type = normal +weight = 0 +global_quality = True + +[values] +layer_height = 0.2 diff --git a/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg b/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg index 7d1c1bf588..f24f198b2e 100644 --- a/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg @@ -1,17 +1,16 @@ [general] version = 2 -name = Fine +name = Fast definition = abax_pri3 [metadata] setting_version = 4 type = quality -quality_type = normal +quality_type = fast weight = -1 material = generic_pla [values] -layer_height = 0.2 wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 diff --git a/resources/quality/abax_pri3/apri3_pla_high.inst.cfg b/resources/quality/abax_pri3/apri3_pla_high.inst.cfg index 46a4178dd9..5b4c470842 100644 --- a/resources/quality/abax_pri3/apri3_pla_high.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_high.inst.cfg @@ -11,7 +11,6 @@ weight = 1 material = generic_pla [values] -layer_height = 0.1 wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 diff --git a/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg b/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg index 3f6f36cfe6..2df629af38 100644 --- a/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg @@ -11,7 +11,6 @@ weight = 0 material = generic_pla [values] -layer_height = 0.2 wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 From be211b73114cf3a8dbd0b2963b833a606779c280 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:04:29 +0100 Subject: [PATCH 160/371] WIP: Fix quality profiles for abax_pri5 - Removed redundant quality profiles for abax_pri5 and reuse the abax_pri3 ones - Fix abax_pri5 definition file: has_machine_quality = true --- resources/definitions/abax_pri5.def.json | 4 +++- .../quality/abax_pri5/apri5_pla_fast.inst.cfg | 22 ------------------- .../quality/abax_pri5/apri5_pla_high.inst.cfg | 22 ------------------- .../abax_pri5/apri5_pla_normal.inst.cfg | 22 ------------------- 4 files changed, 3 insertions(+), 67 deletions(-) delete mode 100644 resources/quality/abax_pri5/apri5_pla_fast.inst.cfg delete mode 100644 resources/quality/abax_pri5/apri5_pla_high.inst.cfg delete mode 100644 resources/quality/abax_pri5/apri5_pla_normal.inst.cfg diff --git a/resources/definitions/abax_pri5.def.json b/resources/definitions/abax_pri5.def.json index cbebb576b0..b8310221b1 100644 --- a/resources/definitions/abax_pri5.def.json +++ b/resources/definitions/abax_pri5.def.json @@ -6,7 +6,9 @@ "visible": true, "author": "ABAX 3d Technologies", "manufacturer": "ABAX 3d Technologies", - "file_formats": "text/x-gcode" + "file_formats": "text/x-gcode", + "quality_definition": "abax_pri3", + "has_machine_quality": true }, "overrides": { "machine_start_gcode": { diff --git a/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg b/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg deleted file mode 100644 index 517c767ac5..0000000000 --- a/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 2 -name = Fine -definition = abax_pri5 - -[metadata] -setting_version = 4 -type = quality -quality_type = normal -weight = -1 -material = generic_pla - -[values] -layer_height = 0.2 -wall_thickness = 1.05 -top_bottom_thickness = 0.8 -infill_sparse_density = 20 -speed_print = 80 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/abax_pri5/apri5_pla_high.inst.cfg b/resources/quality/abax_pri5/apri5_pla_high.inst.cfg deleted file mode 100644 index 01699e39f6..0000000000 --- a/resources/quality/abax_pri5/apri5_pla_high.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 2 -name = Extra Fine -definition = abax_pri5 - -[metadata] -setting_version = 4 -type = quality -quality_type = high -weight = 1 -material = generic_pla - -[values] -layer_height = 0.1 -wall_thickness = 1.05 -top_bottom_thickness = 0.8 -infill_sparse_density = 20 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg b/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg deleted file mode 100644 index ea1023dc43..0000000000 --- a/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 2 -name = Fine -definition = abax_pri5 - -[metadata] -setting_version = 4 -type = quality -quality_type = normal -weight = 0 -material = generic_pla - -[values] -layer_height = 0.2 -wall_thickness = 1.05 -top_bottom_thickness = 0.8 -infill_sparse_density = 20 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 From 76f431af76229fdb4fbe1eaaf07cce70a4a941eb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:06:08 +0100 Subject: [PATCH 161/371] WIP: Only fetch variants if the machine has any --- cura/Machines/Models/BuildPlateModel.py | 6 ++++++ cura/Machines/Models/NozzleModel.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/cura/Machines/Models/BuildPlateModel.py b/cura/Machines/Models/BuildPlateModel.py index ff623eeca7..fccf4fa44e 100644 --- a/cura/Machines/Models/BuildPlateModel.py +++ b/cura/Machines/Models/BuildPlateModel.py @@ -2,6 +2,7 @@ from PyQt5.QtCore import Qt from UM.Application import Application from UM.Qt.ListModel import ListModel +from UM.Util import parseBool from cura.Machines.VariantManager import VariantType @@ -30,6 +31,11 @@ class BuildPlateModel(ListModel): self.setItems([]) return + has_variants = parseBool(global_stack.getMetaDataEntry("has_variant_buildplates", False)) + if not has_variants: + self.setItems([]) + return + variant_dict = self._variant_manager.getVariantNodes(global_stack, variant_type = VariantType.BUILD_PLATE) item_list = [] diff --git a/cura/Machines/Models/NozzleModel.py b/cura/Machines/Models/NozzleModel.py index 9d1be393cf..19d4a800c8 100644 --- a/cura/Machines/Models/NozzleModel.py +++ b/cura/Machines/Models/NozzleModel.py @@ -5,6 +5,7 @@ from PyQt5.QtCore import Qt from UM.Application import Application from UM.Qt.ListModel import ListModel +from UM.Util import parseBool class NozzleModel(ListModel): @@ -33,6 +34,11 @@ class NozzleModel(ListModel): self.setItems([]) return + has_variants = parseBool(active_global_stack.getMetaDataEntry("has_variants", False)) + if not has_variants: + self.setItems([]) + return + variant_node_dict = variant_manager.getVariantNodes(active_global_stack) if not variant_node_dict: self.setItems([]) From 2e3e01ff95fc5a022c3ed7dab062ab81f950ae13 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 11:13:35 +0100 Subject: [PATCH 162/371] CURA-4606 Cleanup WorkspaceSummaryDialog and prepare for single extrusion mode --- cura/Settings/MachineManager.py | 49 +++++++++++++----------- resources/qml/WorkspaceSummaryDialog.qml | 8 ++-- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index e34b1a0763..4fe47ba466 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -444,24 +444,6 @@ class MachineManager(QObject): return "" - @pyqtProperty("QVariantList", notify=activeVariantChanged) - def activeVariantNames(self) -> List[str]: - result = [] - - # Just return the variants in the extruder stack(s). For the variant in the global stack, use activeVariantBuildplateName - active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() - if active_stacks is not None: - for stack in active_stacks: - variant_container = stack.variant - if variant_container and variant_container != self._empty_variant_container: - result.append(variant_container.getName()) - - return result - - @pyqtProperty("QVariantList", notify = activeMaterialChanged) - def activeMaterialNames(self) -> List[str]: - return list(self._current_root_material_name.values()) - @pyqtProperty(str, notify=activeMaterialChanged) def activeMaterialId(self) -> str: if self._active_container_stack: @@ -898,6 +880,12 @@ class MachineManager(QObject): # # New # + + # We not fetch it from _current_root_material_id, but later we can get it from somewhere else + @pyqtProperty("QVariantList", notify = rootMaterialChanged) + def currentExtruderPositions(self): + return sorted(list(self._current_root_material_id.keys())) + @pyqtProperty("QVariant", notify = rootMaterialChanged) def currentRootMaterialId(self): # initial filling the current_root_material_id @@ -909,12 +897,29 @@ class MachineManager(QObject): @pyqtProperty("QVariant", notify = rootMaterialChanged) def currentRootMaterialName(self): # initial filling the current_root_material_name - for position in self._global_container_stack.extruders: - if position not in self._current_root_material_name: - material = self._global_container_stack.extruders[position].material - self._current_root_material_name[position] = material.getName() + if self._global_container_stack: + for position in self._global_container_stack.extruders: + if position not in self._current_root_material_name: + material = self._global_container_stack.extruders[position].material + self._current_root_material_name[position] = material.getName() return self._current_root_material_name + ## Return the variant names in the extruder stack(s). + ## For the variant in the global stack, use activeVariantBuildplateName + @pyqtProperty("QVariant", notify = activeVariantChanged) + def activeVariantNames(self): + result = {} + + active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() + if active_stacks is not None: + for stack in active_stacks: + variant_container = stack.variant + position = stack.getMetaDataEntry("position") + if variant_container and variant_container != self._empty_variant_container: + result[position] = variant_container.getName() + + return result + def _setEmptyQuality(self): self._current_quality_group = None self._current_quality_changes_group = None diff --git a/resources/qml/WorkspaceSummaryDialog.qml b/resources/qml/WorkspaceSummaryDialog.qml index 8f00377d58..b9ea77fa70 100644 --- a/resources/qml/WorkspaceSummaryDialog.qml +++ b/resources/qml/WorkspaceSummaryDialog.qml @@ -148,7 +148,7 @@ UM.Dialog Repeater { - model: Cura.MachineManager.activeMaterialNames + model: Cura.MachineManager.currentExtruderPositions delegate: Column { Item // Spacer @@ -158,7 +158,7 @@ UM.Dialog } Label { - text: catalog.i18nc("@action:label", "Extruder %1").arg(index+1) + text: catalog.i18nc("@action:label", "Extruder %1").arg(modelData) } height: childrenRect.height width: parent.width @@ -173,7 +173,7 @@ UM.Dialog } Label { - text: Cura.MachineManager.activeVariantNames[index] + ", " + modelData + text: Cura.MachineManager.activeVariantNames[modelData] + ", " + Cura.MachineManager.currentRootMaterialName[modelData] width: (parent.width / 3) | 0 } } @@ -294,4 +294,4 @@ UM.Dialog } } } -} \ No newline at end of file +} From 628d0315421111f47b56d2bcb581af9cc464b9d1 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:14:07 +0100 Subject: [PATCH 163/371] WIP: Fix models to check if global stack exists --- cura/Machines/Models/MaterialsModel.py | 39 ++++++++++++++++++-------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/cura/Machines/Models/MaterialsModel.py b/cura/Machines/Models/MaterialsModel.py index e79ebe36bc..97a1d27a31 100644 --- a/cura/Machines/Models/MaterialsModel.py +++ b/cura/Machines/Models/MaterialsModel.py @@ -66,23 +66,28 @@ class GenericMaterialsModel(BaseMaterialsModel): super().__init__(parent) from cura.CuraApplication import CuraApplication - machine_manager = CuraApplication.getInstance().getMachineManager() - extruder_manager = CuraApplication.getInstance().getExtruderManager() - material_manager = CuraApplication.getInstance()._material_manager + self._machine_manager = CuraApplication.getInstance().getMachineManager() + self._extruder_manager = CuraApplication.getInstance().getExtruderManager() + self._material_manager = CuraApplication.getInstance()._material_manager - machine_manager.globalContainerChanged.connect(self._update) - extruder_manager.activeExtruderChanged.connect(self._update) - material_manager.materialsUpdated.connect(self._update) + self._machine_manager.globalContainerChanged.connect(self._update) + self._extruder_manager.activeExtruderChanged.connect(self._update) + self._material_manager.materialsUpdated.connect(self._update) self._update() def _update(self): - item_list = [] + global_stack = self._machine_manager.activeMachine + if global_stack is None: + self.setItems([]) + return + result_dict = getAvailableMaterials() if result_dict is None: self.setItems([]) return + item_list = [] for root_material_id, container_node in result_dict.items(): metadata = container_node.metadata # Only add results for generic materials @@ -128,21 +133,26 @@ class BrandMaterialsModel(ListModel): self.addRoleName(self.MaterialsRole, "materials") from cura.CuraApplication import CuraApplication - machine_manager = CuraApplication.getInstance().getMachineManager() + self._machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() material_manager = CuraApplication.getInstance()._material_manager - machine_manager.globalContainerChanged.connect(self._update) + self._machine_manager.globalContainerChanged.connect(self._update) extruder_manager.activeExtruderChanged.connect(self._update) material_manager.materialsUpdated.connect(self._update) def _update(self): - brand_item_list = [] + global_stack = self._machine_manager.activeMachine + if global_stack is None: + self.setItems([]) + return + result_dict = getAvailableMaterials() if result_dict is None: self.setItems([]) return + brand_item_list = [] brand_group_dict = {} for root_material_id, container_node in result_dict.items(): metadata = container_node.metadata @@ -231,17 +241,22 @@ class MaterialsModel(ListModel): from cura.CuraApplication import CuraApplication self._container_registry = CuraApplication.getInstance().getContainerRegistry() - machine_manager = CuraApplication.getInstance().getMachineManager() + self._machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() material_manager = CuraApplication.getInstance()._material_manager - machine_manager.globalContainerChanged.connect(self._update) + self._machine_manager.globalContainerChanged.connect(self._update) extruder_manager.activeExtruderChanged.connect(self._update) material_manager.materialsUpdated.connect(self._update) self._update() def _update(self): + global_stack = self._machine_manager.activeMachine + if global_stack is None: + self.setItems([]) + return + result_dict = getAvailableMaterials() if result_dict is None: self.setItems([]) From c65192000e08ace9005018fe50b2f038f9c16749 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:19:18 +0100 Subject: [PATCH 164/371] WIP: Fix material name fetching in QML --- resources/qml/SidebarHeader.qml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index 2c99ce2dd3..b78cade1de 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -252,8 +252,18 @@ Column { id: materialSelection - text: Cura.MachineManager.currentRootMaterialName[base.currentExtruderIndex] - tooltip: Cura.MachineManager.currentRootMaterialName[base.currentExtruderIndex] + property var currentRootMaterialName: + { + var materials = Cura.MachineManager.currentRootMaterialName; + var materialName = ""; + if (base.currentExtruderIndex in materials) { + materialName = materials[base.currentExtruderIndex]; + } + return materialName; + } + + text: currentRootMaterialName + tooltip: currentRootMaterialName visible: Cura.MachineManager.hasMaterials enabled: !extrudersList.visible || base.currentExtruderIndex > -1 height: UM.Theme.getSize("setting_control").height From 6e5fed6b5ec3cb689e84157ee08ea74dc2b56ba9 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:21:16 +0100 Subject: [PATCH 165/371] WIP: Fix quality name in SettingView --- resources/qml/Settings/SettingView.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 8ff4c33244..cef7ce9077 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -57,7 +57,7 @@ Item height: UM.Theme.getSize("setting_control").height anchors.left: globalProfileLabel.right anchors.right: parent.right - tooltip: Cura.MachineManager.activeQualityName + tooltip: Cura.MachineManager.activeQualityOrQualityChangesName style: UM.Theme.styles.sidebar_header_button activeFocusOnPress: true menu: ProfileMenu { } From ec8ee6e31a8a7ee5a9d83d239e7d13e2c9728718 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:22:10 +0100 Subject: [PATCH 166/371] WIP: Fix quality name in workspace summary dialog --- resources/qml/WorkspaceSummaryDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/WorkspaceSummaryDialog.qml b/resources/qml/WorkspaceSummaryDialog.qml index b9ea77fa70..1cfe36d14b 100644 --- a/resources/qml/WorkspaceSummaryDialog.qml +++ b/resources/qml/WorkspaceSummaryDialog.qml @@ -217,7 +217,7 @@ UM.Dialog } Label { - text: Cura.MachineManager.activeQualityName + text: Cura.MachineManager.activeQualityOrQualityChangesName width: (parent.width / 3) | 0 } From 6cd47453bb4ac0be7182010d946e2619c7013e79 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:36:46 +0100 Subject: [PATCH 167/371] WIP: Fix activeMaterialsCompatible() --- cura/Settings/MachineManager.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 4fe47ba466..c570f0649a 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1008,9 +1008,10 @@ class MachineManager(QObject): def activeMaterialsCompatible(self): # check material - variant compatibility - for position, extruder in self._global_container_stack.extruders.items(): - if not extruder.material.getMetaDataEntry("compatible"): - return False + if Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False)): + for position, extruder in self._global_container_stack.extruders.items(): + if not extruder.material.getMetaDataEntry("compatible"): + return False return True ## Update current quality type and machine after setting material From a4a1babc5949d8e47783069981363736d02987aa Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:37:14 +0100 Subject: [PATCH 168/371] WIP: Fix UM2 quality profiles - Remove layer_height from the profiles because they are not global qualities - The layer_heights are the same as the default ones so no need to make specific global qualities for UM2 --- resources/quality/ultimaker2/um2_draft.inst.cfg | 1 - resources/quality/ultimaker2/um2_fast.inst.cfg | 1 - resources/quality/ultimaker2/um2_high.inst.cfg | 1 - 3 files changed, 3 deletions(-) diff --git a/resources/quality/ultimaker2/um2_draft.inst.cfg b/resources/quality/ultimaker2/um2_draft.inst.cfg index 821c864bb8..1115deacd9 100644 --- a/resources/quality/ultimaker2/um2_draft.inst.cfg +++ b/resources/quality/ultimaker2/um2_draft.inst.cfg @@ -10,4 +10,3 @@ quality_type = draft weight = -2 [values] -layer_height = 0.2 diff --git a/resources/quality/ultimaker2/um2_fast.inst.cfg b/resources/quality/ultimaker2/um2_fast.inst.cfg index 1292613642..8bc5b7dee3 100644 --- a/resources/quality/ultimaker2/um2_fast.inst.cfg +++ b/resources/quality/ultimaker2/um2_fast.inst.cfg @@ -11,7 +11,6 @@ weight = -1 [values] infill_sparse_density = 10 -layer_height = 0.15 cool_min_layer_time = 3 speed_wall_0 = 40 speed_wall_x = 80 diff --git a/resources/quality/ultimaker2/um2_high.inst.cfg b/resources/quality/ultimaker2/um2_high.inst.cfg index 54119933b5..8d6573b2be 100644 --- a/resources/quality/ultimaker2/um2_high.inst.cfg +++ b/resources/quality/ultimaker2/um2_high.inst.cfg @@ -10,6 +10,5 @@ quality_type = high weight = 1 [values] -layer_height = 0.06 speed_topbottom = 15 speed_infill = 80 From c411091fde958dd02298b17a3efe8f7a486fae17 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 11:47:08 +0100 Subject: [PATCH 169/371] WIP: Only add global_quality containers for global stack qualities --- cura/Machines/QualityManager.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index f7ca84e83d..a98a698cb6 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -5,6 +5,7 @@ from PyQt5.QtCore import QObject, QTimer from UM.Application import Application from UM.Logger import Logger +from UM.Util import parseBool from cura.Machines.ContainerGroup import ContainerGroup from cura.Machines.ContainerNode import ContainerNode @@ -294,6 +295,12 @@ class QualityManager(QObject): quality_group_dict = {} for node in nodes_to_check: if node and node.quality_type_map: + # Only include global qualities + quality_node = list(node.quality_type_map.values())[0] + is_global_quality = parseBool(quality_node.metadata.get("global_quality", False)) + if not is_global_quality: + continue + for quality_type, quality_node in node.quality_type_map.items(): quality_group = QualityGroup(quality_node.metadata["name"], quality_type) quality_group.node_for_global = quality_node From 02472f6ad2c84c43717a3a6896ebbec78d243345 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 12:39:04 +0100 Subject: [PATCH 170/371] WIP: Fix material name update upon machine switching --- cura/Settings/MachineManager.py | 13 +++++++++---- resources/qml/SidebarHeader.qml | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index c570f0649a..6cb6724a5a 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -259,10 +259,10 @@ class MachineManager(QObject): self.activeQualityChanged.emit() self.activeVariantChanged.emit() self.activeMaterialChanged.emit() - self._error_check_timer.start() - def _onProfilesModelChanged(self, *args) -> None: - self.__emitChangedSignals() + self.rootMaterialChanged.emit() + + self._error_check_timer.start() def _onInstanceContainersChanged(self, container) -> None: self._instance_container_timer.start() @@ -307,7 +307,11 @@ class MachineManager(QObject): containers = container_registry.findContainerStacks(id = stack_id) if containers: - Application.getInstance().setGlobalContainerStack(containers[0]) + global_stack = containers[0] + Application.getInstance().setGlobalContainerStack(global_stack) + self._global_container_stack = global_stack + self.globalContainerChanged.emit() + self._onGlobalContainerChanged() ExtruderManager.getInstance()._globalContainerStackChanged() self._initMachineState(containers[0]) @@ -898,6 +902,7 @@ class MachineManager(QObject): def currentRootMaterialName(self): # initial filling the current_root_material_name if self._global_container_stack: + self._current_root_material_name = {} for position in self._global_container_stack.extruders: if position not in self._current_root_material_name: material = self._global_container_stack.extruders[position].material diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index b78cade1de..5d9cbe2ad1 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -265,7 +265,7 @@ Column text: currentRootMaterialName tooltip: currentRootMaterialName visible: Cura.MachineManager.hasMaterials - enabled: !extrudersList.visible || base.currentExtruderIndex > -1 + enabled: !extrudersList.visible || base.currentExtruderIndex > -1 height: UM.Theme.getSize("setting_control").height width: Math.round(parent.width * 0.7) + UM.Theme.getSize("sidebar_margin").width anchors.right: parent.right From 3364e24988baa009f33bdc9bb1f51492aeb9cea1 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 12:39:54 +0100 Subject: [PATCH 171/371] WIP: Be less wordy --- cura/Machines/Models/QualityProfilesModel.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index 2f1374cc8b..4b5e3bdf86 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -49,8 +49,8 @@ class QualityProfilesModel(ListModel): Logger.log("d", "Updating quality profile model ...") machine_manager = Application.getInstance().getMachineManager() - active_global_stack = machine_manager._global_container_stack - if active_global_stack is None: + global_stack = machine_manager._global_container_stack + if global_stack is None: self.setItems([]) Logger.log("d", "No active GlobalStack, set quality profile model as empty.") return @@ -60,7 +60,7 @@ class QualityProfilesModel(ListModel): self.setItems([]) return - quality_group_dict = self._quality_manager.getQualityGroups(active_global_stack) + quality_group_dict = self._quality_manager.getQualityGroups(global_stack) item_list = [] for key in sorted(quality_group_dict): @@ -83,14 +83,14 @@ class QualityProfilesModel(ListModel): self.setItems(item_list) def _fetchLayerHeight(self, quality_group: "QualityGroup"): - active_global_stack = Application.getInstance().getMachineManager()._global_container_stack + global_stack = Application.getInstance().getMachineManager()._global_container_stack if not self._layer_height_unit: - unit = active_global_stack.definition.getProperty("layer_height", "unit") + unit = global_stack.definition.getProperty("layer_height", "unit") if not unit: unit = "" self._layer_height_unit = unit - default_layer_height = active_global_stack.definition.getProperty("layer_height", "value") + default_layer_height = global_stack.definition.getProperty("layer_height", "value") # Get layer_height from the quality profile for the GlobalStack container = quality_group.node_for_global.getContainer() @@ -100,7 +100,7 @@ class QualityProfilesModel(ListModel): layer_height = str(container.getProperty("layer_height", "value")) else: # Look for layer_height in the GlobalStack from material -> definition - container = active_global_stack.definition + container = global_stack.definition if container.hasProperty("layer_height", "value"): layer_height = container.getProperty("layer_height", "value") return str(layer_height) From b7659edd3bd15930b6c4c6832cf1036c8058bf9d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 12:40:56 +0100 Subject: [PATCH 172/371] WIP: Remove unused ID role in QualityProfilesModel --- cura/Machines/Models/QualityProfilesModel.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index 4b5e3bdf86..3bfccd409d 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -13,19 +13,17 @@ from cura.Machines.QualityManager import QualityGroup # QML Model for all built-in quality profiles. # class QualityProfilesModel(ListModel): - IdRole = Qt.UserRole + 1 - NameRole = Qt.UserRole + 2 - QualityTypeRole = Qt.UserRole + 3 - LayerHeightRole = Qt.UserRole + 4 - LayerHeightWithoutUnitRole = Qt.UserRole + 5 - AvailableRole = Qt.UserRole + 6 - QualityGroupRole = Qt.UserRole + 7 - QualityChangesGroupRole = Qt.UserRole + 8 + NameRole = Qt.UserRole + 1 + QualityTypeRole = Qt.UserRole + 2 + LayerHeightRole = Qt.UserRole + 3 + LayerHeightWithoutUnitRole = Qt.UserRole + 4 + AvailableRole = Qt.UserRole + 5 + QualityGroupRole = Qt.UserRole + 6 + QualityChangesGroupRole = Qt.UserRole + 7 def __init__(self, parent = None): super().__init__(parent) - self.addRoleName(self.IdRole, "id") self.addRoleName(self.NameRole, "name") self.addRoleName(self.QualityTypeRole, "quality_type") self.addRoleName(self.LayerHeightRole, "layer_height") From b3ef4a05d54b267d67d5c56a973e123cdae3c6b1 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 13:18:59 +0100 Subject: [PATCH 173/371] CURA-4606 skip non global qualities when looking for extruder qualities --- cura/Machines/QualityManager.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index a98a698cb6..078de762d4 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -354,6 +354,12 @@ class QualityManager(QObject): nodes_to_check += [machine_node, default_machine_node] for node in nodes_to_check: if node and node.quality_type_map: + # Only include variant qualities; skip non global qualities + quality_node = list(node.quality_type_map.values())[0] + is_global_quality = parseBool(quality_node.metadata.get("global_quality", False)) + if is_global_quality: + continue + for quality_type, quality_node in node.quality_type_map.items(): if quality_type not in quality_group_dict: quality_group = QualityGroup(quality_node.metadata["name"], quality_type) From 631b72c007c04a542b9f8d1cb2ec1a866f3caf24 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 14:16:26 +0100 Subject: [PATCH 174/371] CURA-4606 in all quality profiles, rename all the specific 1.75mm materials back to the generic material --- cura/Settings/CuraStackBuilder.py | 5 ++++- .../quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg | 2 +- .../quality/builder_premium/bp_PET_High_Quality.inst.cfg | 2 +- .../quality/builder_premium/bp_PET_Normal_Quality.inst.cfg | 2 +- .../quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg | 2 +- .../quality/builder_premium/bp_PLA_High_Quality.inst.cfg | 2 +- .../quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg | 2 +- .../quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg | 2 +- .../quality/builder_premium/bp_PVA_High_Quality.inst.cfg | 2 +- .../quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg | 2 +- .../quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg | 2 +- .../quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg | 2 +- .../quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg | 2 +- .../quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg | 2 +- .../quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg | 2 +- .../cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg | 2 +- .../quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg | 2 +- .../quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg | 2 +- .../quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg | 2 +- .../quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg | 2 +- .../quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg | 2 +- .../quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg | 2 +- .../quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg | 2 +- .../cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg | 2 +- .../quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg | 2 +- .../quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg | 2 +- .../quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg | 2 +- .../cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg | 2 +- .../quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg | 2 +- .../cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg | 2 +- .../cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg | 2 +- .../cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg | 2 +- .../quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg | 2 +- .../cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg | 2 +- resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg | 2 +- .../quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg | 2 +- resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg | 2 +- .../quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg | 2 +- .../quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg | 2 +- .../cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg | 2 +- resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg | 2 +- .../quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg | 2 +- .../quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg | 2 +- .../quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg | 2 +- .../quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg | 2 +- .../quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg | 2 +- .../quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg | 2 +- .../cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg | 2 +- .../quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg | 2 +- .../quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg | 2 +- .../quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg | 2 +- .../quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg | 2 +- .../quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg | 2 +- .../quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg | 2 +- .../quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg | 2 +- .../cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg | 2 +- .../quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg | 2 +- .../quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg | 2 +- .../quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg | 2 +- .../quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg | 2 +- .../quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg | 2 +- .../quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg | 2 +- .../quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg | 2 +- .../cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg | 2 +- .../quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg | 2 +- .../quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_abs_high.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_pla_high.inst.cfg | 2 +- resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg | 2 +- .../quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg | 2 +- .../quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg | 2 +- .../quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg | 2 +- .../quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg | 2 +- .../malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg | 2 +- .../malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg | 2 +- .../quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg | 2 +- .../malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg | 2 +- .../quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg | 2 +- .../quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg | 2 +- .../quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg | 2 +- .../malyan_m200/petg/malyan_m200_petg_normal.inst.cfg | 2 +- .../malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg | 2 +- .../malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg | 2 +- .../quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg | 2 +- .../malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg | 2 +- .../quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg | 2 +- .../quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg | 2 +- .../quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg | 2 +- .../quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg | 2 +- .../malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg | 2 +- .../malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg | 2 +- .../quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg | 2 +- .../malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg | 2 +- .../abs/monoprice_select_mini_v2_abs_draft.inst.cfg | 2 +- .../abs/monoprice_select_mini_v2_abs_fast.inst.cfg | 2 +- .../abs/monoprice_select_mini_v2_abs_high.inst.cfg | 2 +- .../abs/monoprice_select_mini_v2_abs_normal.inst.cfg | 2 +- .../abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg | 2 +- .../abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg | 2 +- .../abs/monoprice_select_mini_v2_abs_ultra.inst.cfg | 2 +- .../abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg | 2 +- .../nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg | 2 +- .../nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg | 2 +- .../nylon/monoprice_select_mini_v2_nylon_high.inst.cfg | 2 +- .../nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg | 2 +- .../nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg | 2 +- .../monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg | 2 +- .../nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg | 2 +- .../nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg | 2 +- .../pc/monoprice_select_mini_v2_pc_draft.inst.cfg | 2 +- .../pc/monoprice_select_mini_v2_pc_fast.inst.cfg | 2 +- .../pc/monoprice_select_mini_v2_pc_high.inst.cfg | 2 +- .../pc/monoprice_select_mini_v2_pc_normal.inst.cfg | 2 +- .../pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg | 2 +- .../pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg | 2 +- .../pc/monoprice_select_mini_v2_pc_ultra.inst.cfg | 2 +- .../pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg | 2 +- .../petg/monoprice_select_mini_v2_petg_draft.inst.cfg | 2 +- .../petg/monoprice_select_mini_v2_petg_fast.inst.cfg | 2 +- .../petg/monoprice_select_mini_v2_petg_high.inst.cfg | 2 +- .../petg/monoprice_select_mini_v2_petg_normal.inst.cfg | 2 +- .../petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg | 2 +- .../petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg | 2 +- .../petg/monoprice_select_mini_v2_petg_ultra.inst.cfg | 2 +- .../petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg | 2 +- .../pla/monoprice_select_mini_v2_pla_draft.inst.cfg | 2 +- .../pla/monoprice_select_mini_v2_pla_fast.inst.cfg | 2 +- .../pla/monoprice_select_mini_v2_pla_high.inst.cfg | 2 +- .../pla/monoprice_select_mini_v2_pla_normal.inst.cfg | 2 +- .../pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg | 2 +- .../pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg | 2 +- .../pla/monoprice_select_mini_v2_pla_ultra.inst.cfg | 2 +- .../pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg | 2 +- 139 files changed, 142 insertions(+), 139 deletions(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 0348d6855f..fc0d4f6f8e 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -129,7 +129,10 @@ class CuraStackBuilder: new_global_stack.quality = quality_group.node_for_global.getContainer() for position, extruder_stack in new_global_stack.extruders.items(): - extruder_stack.quality = quality_group.nodes_for_extruders[position].getContainer() + if position in quality_group.nodes_for_extruders: + extruder_stack.quality = quality_group.nodes_for_extruders[position].getContainer() + else: + extruder_stack.quality = application.empty_quality_container # Register the global stack after the extruder stacks are created. This prevents the registry from adding another # extruder stack because the global stack didn't have one yet (which is enforced since Cura 3.1). diff --git a/resources/quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg index ce9e58ea04..736defd5c6 100644 --- a/resources/quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PET_Coarse_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = -1 -material = generic_petg_175 +material = generic_petg [values] material_print_temperature = =default_material_print_temperature - 5 diff --git a/resources/quality/builder_premium/bp_PET_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_PET_High_Quality.inst.cfg index cbde2790df..82c7fa7baf 100644 --- a/resources/quality/builder_premium/bp_PET_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PET_High_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_petg_175 +material = generic_petg [values] acceleration_print = 2000 diff --git a/resources/quality/builder_premium/bp_PET_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_PET_Normal_Quality.inst.cfg index af122db9cc..b1e9ff91df 100644 --- a/resources/quality/builder_premium/bp_PET_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PET_Normal_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_petg_175 +material = generic_petg [values] material_print_temperature = =default_material_print_temperature - 5 diff --git a/resources/quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg index d8baf277a9..9b8078e266 100644 --- a/resources/quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PLA_Coarse_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = -1 -material = generic_pla_175 +material = generic_pla [values] material_print_temperature = =default_material_print_temperature + 15 diff --git a/resources/quality/builder_premium/bp_PLA_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_PLA_High_Quality.inst.cfg index 49675e25d9..2bbfb02e0d 100644 --- a/resources/quality/builder_premium/bp_PLA_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PLA_High_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pla_175 +material = generic_pla [values] acceleration_print = 2000 diff --git a/resources/quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg index 113bdba605..b77ac747a8 100644 --- a/resources/quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PLA_Normal_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pla_175 +material = generic_pla [values] material_print_temperature = =default_material_print_temperature + 15 diff --git a/resources/quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg b/resources/quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg index 059f25a70f..f626604f70 100644 --- a/resources/quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PVA_Coarse_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = -1 -material = generic_pva_175 +material = generic_pva [values] material_print_temperature = =default_material_print_temperature + 10 diff --git a/resources/quality/builder_premium/bp_PVA_High_Quality.inst.cfg b/resources/quality/builder_premium/bp_PVA_High_Quality.inst.cfg index 5da254aa9b..caf0bd4bd7 100644 --- a/resources/quality/builder_premium/bp_PVA_High_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PVA_High_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pva_175 +material = generic_pva [values] acceleration_print = 2000 diff --git a/resources/quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg b/resources/quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg index 562b2257f5..4f08010a6f 100644 --- a/resources/quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg +++ b/resources/quality/builder_premium/bp_PVA_Normal_Quality.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pva_175 +material = generic_pva [values] material_print_temperature = =default_material_print_temperature + 10 diff --git a/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg index 89ab9a09d4..996c8e400b 100644 --- a/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.25_abs_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_abs_175 +material = generic_abs variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg index a83a6d1e31..5fdbaab51a 100644 --- a/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.25_abs_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_abs_175 +material = generic_abs variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg index b5281407dd..66fa5e4c30 100644 --- a/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.4_abs_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_abs_175 +material = generic_abs variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg index b366026793..31cb6adc72 100644 --- a/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.4_abs_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_abs_175 +material = generic_abs variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg index 0f4896ea74..7bc7791bfa 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = 3 -material = generic_abs_175 +material = generic_abs variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg index 5f3f20c9ee..137bd8cd7b 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_extra_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = extra coarse weight = 4 -material = generic_abs_175 +material = generic_abs variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg index 2a5b873dd4..96c0009578 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_abs_175 +material = generic_abs variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg b/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg index 887a252e06..10389823eb 100644 --- a/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg +++ b/resources/quality/cartesio/abs/cartesio_0.8_abs_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_abs_175 +material = generic_abs variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg index b4417d4bcf..fb76afc867 100644 --- a/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.25_hips_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_hips_175 +material = generic_hips variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg index b669f21a2b..8fb06f3bbc 100644 --- a/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.25_hips_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_hips_175 +material = generic_hips variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg index c88f8be029..ec29af6c6e 100644 --- a/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.4_hips_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_hips_175 +material = generic_hips variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg index 4790926e3b..61a48e0c61 100644 --- a/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.4_hips_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_hips_175 +material = generic_hips variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg index e096fbb3a4..1bafda10fa 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = 3 -material = generic_hips_175 +material = generic_hips variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg index 80a44678ca..0f77442040 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_extra_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = extra coarse weight = 4 -material = generic_hips_175 +material = generic_hips variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg index e1754d5ba0..0edcffa05c 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_hips_175 +material = generic_hips variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg b/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg index b728e01c99..a50a7015d5 100644 --- a/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg +++ b/resources/quality/cartesio/hips/cartesio_0.8_hips_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_hips_175 +material = generic_hips variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg index b81a053cd3..50bb6532bd 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_nylon_175 +material = generic_nylon variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg index b09e2ac794..649018bd89 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.25_nylon_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_nylon_175 +material = generic_nylon variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg index b43839439f..17b274c05d 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_nylon_175 +material = generic_nylon variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg index 36cfe49afb..0d7d1963cc 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.4_nylon_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_nylon_175 +material = generic_nylon variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg index ef3185814b..bbab5caee1 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = 3 -material = generic_nylon_175 +material = generic_nylon variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg index af57d6f3ab..568eb59e32 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_extra_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = extra coarse weight = 4 -material = generic_nylon_175 +material = generic_nylon variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg index 99e932c954..b6ef10e5df 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_nylon_175 +material = generic_nylon variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg index a0fef367a6..d05407393a 100644 --- a/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg +++ b/resources/quality/cartesio/nylon/cartesio_0.8_nylon_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_nylon_175 +material = generic_nylon variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg index ac0f7a35fa..adb88df236 100644 --- a/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.25_pc_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pc_175 +material = generic_pc variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg index 5f77a2a91e..92b5fc08a7 100644 --- a/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.25_pc_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_pc_175 +material = generic_pc variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg index 835c94e5fd..c00437edd9 100644 --- a/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.4_pc_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pc_175 +material = generic_pc variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg index 7e48b4a94c..c0257a19e1 100644 --- a/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.4_pc_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_pc_175 +material = generic_pc variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg index e857476b8b..8b89c00c72 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = 3 -material = generic_pc_175 +material = generic_pc variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg index 0fc24de569..1f5491f65f 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_extra_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = extra coarse weight = 4 -material = generic_pc_175 +material = generic_pc variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg index 3c58129546..3d0d49617e 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pc_175 +material = generic_pc variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg b/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg index 3b8765b21a..7a8d77df37 100644 --- a/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg +++ b/resources/quality/cartesio/pc/cartesio_0.8_pc_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_pc_175 +material = generic_pc variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg index 94bf52b2a4..4e0d95ec9b 100644 --- a/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.25_petg_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_petg_175 +material = generic_petg variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg index d5517b57b5..2903b8d658 100644 --- a/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.25_petg_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_petg_175 +material = generic_petg variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg index 33b3bfa99d..bd0e7af5c7 100644 --- a/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.4_petg_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_petg_175 +material = generic_petg variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg index 1bdbe32229..a97e82542f 100644 --- a/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.4_petg_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_petg_175 +material = generic_petg variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg index 20b2d38856..41392abb37 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = 3 -material = generic_petg_175 +material = generic_petg variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg index cdb4d08dd0..fc425bfeaa 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_extra_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = extra coarse weight = 4 -material = generic_petg_175 +material = generic_petg variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg index e125e9dd63..0925e920a6 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_petg_175 +material = generic_petg variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg b/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg index 91a513d171..a70eb22797 100644 --- a/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg +++ b/resources/quality/cartesio/petg/cartesio_0.8_petg_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_petg_175 +material = generic_petg variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg index cbd40f3f8f..a2e3492051 100644 --- a/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.25_pla_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pla_175 +material = generic_pla variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg index 3eed8df302..3f5d23f800 100644 --- a/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.25_pla_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pla_175 +material = generic_pla variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg index 0822ab8c07..5e747adb32 100644 --- a/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.4_pla_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pla_175 +material = generic_pla variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg index 80fb24553f..7318dd3bf6 100644 --- a/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.4_pla_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pla_175 +material = generic_pla variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg index c6b92d50a7..cbdf5887b4 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = -3 -material = generic_pla_175 +material = generic_pla variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg index cb2633313a..622c6f0d51 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_extra_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = extra coarse weight = -4 -material = generic_pla_175 +material = generic_pla variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg index de0298f57e..8fbd09497d 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pla_175 +material = generic_pla variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg b/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg index c6f4e012b6..247d2ed5f7 100644 --- a/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg +++ b/resources/quality/cartesio/pla/cartesio_0.8_pla_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pla_175 +material = generic_pla variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg index 22fdd98317..28a5694246 100644 --- a/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.25_pva_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pva_175 +material = generic_pva variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg index 8288294d0c..cfc2d92399 100644 --- a/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.25_pva_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_pva_175 +material = generic_pva variant = 0.25 mm [values] diff --git a/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg index 2719eb458e..aec07d46dc 100644 --- a/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.4_pva_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pva_175 +material = generic_pva variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg index 6a97ec860f..85c5f20fa9 100644 --- a/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.4_pva_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_pva_175 +material = generic_pva variant = 0.4 mm [values] diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg index 12ca609a7b..f1d05741a6 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = coarse weight = 3 -material = generic_pva_175 +material = generic_pva variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg index d793282c41..1e261c93cc 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_extra_coarse.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = extra coarse weight = 4 -material = generic_pva_175 +material = generic_pva variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg index a43689e7c9..d7697c643f 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pva_175 +material = generic_pva variant = 0.8 mm [values] diff --git a/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg b/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg index f9ead11d79..8a2705fdfa 100644 --- a/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg +++ b/resources/quality/cartesio/pva/cartesio_0.8_pva_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 2 -material = generic_pva_175 +material = generic_pva variant = 0.8 mm [values] diff --git a/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg index aebb72d610..75774fc000 100644 --- a/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_fast.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_abs_175 +material = generic_abs [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg index 05b54eb81e..65542f114a 100644 --- a/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_abs_175 +material = generic_abs [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg index 67c8525b4f..55248345fa 100644 --- a/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_abs_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_abs_175 +material = generic_abs [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg index 511ee2712f..5986c65872 100644 --- a/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_nylon_fast.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_nylon_175 +material = generic_nylon [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg index 47c3e26782..158f903bab 100644 --- a/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_nylon_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_nylon_175 +material = generic_nylon [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg index 49ffada336..89024f30b7 100644 --- a/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_nylon_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_nylon_175 +material = generic_nylon [values] adhesion_type = raft diff --git a/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg index 684b72587c..98a5578d89 100644 --- a/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_fast.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_pla_175 +material = generic_pla [values] adhesion_type = skirt diff --git a/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg index a80f23fa9b..554312ce7b 100644 --- a/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pla_175 +material = generic_pla [values] adhesion_type = skirt diff --git a/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg b/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg index 8a02873fa2..3f22aa1200 100644 --- a/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg +++ b/resources/quality/deltacomb/deltacomb_pla_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pla_175 +material = generic_pla [values] adhesion_type = skirt diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg index 084094f5e7..c02e789dfe 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg index 1e3419dc7e..7f4f368e06 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg index 0758cd6630..37335b61ee 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg index da347ac13c..138c31ab14 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg index cc25431062..2d748bd698 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = superdraft weight = -5 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg index 2b7f830b3f..ebf7798733 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = -3 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg index 73abddc696..5be92914be 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = ultra weight = 2 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg index 22adb14e71..bfe92a98e1 100644 --- a/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = verydraft weight = -4 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg index 9d3e31cb16..038af5eec0 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg index 9d68dee0bf..df341d195c 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg index 63aefb027b..ff9dbc8227 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg index 402c87886c..8531bbf98b 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg index 9029b4508a..8b065ecea8 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = superdraft weight = -5 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg index e9b440e1f6..97672ee1c7 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = -3 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg index 1517f7d340..7b92f9d454 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = ultra weight = 2 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg index 3d3346eac5..1a1b59d90f 100644 --- a/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = verydraft weight = -4 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg index b05a336aee..f3ef39f009 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_pla_175 +material = generic_pla [values] material_bed_temperature = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg index e45fe903e2..0e047b140e 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_pla_175 +material = generic_pla [values] material_bed_temperature = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg index adeae8ae33..e68ad90c6c 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pla_175 +material = generic_pla [values] material_bed_temperature = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg index 0c0f9fcb5a..78bdc826ba 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pla_175 +material = generic_pla [values] material_bed_temperature = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg index e5e5d6d40d..cc24c4a0b2 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = superdraft weight = -5 -material = generic_pla_175 +material = generic_pla [values] material_bed_temperature = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg index 95323181d7..5bfb82ee90 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = -3 -material = generic_pla_175 +material = generic_pla [values] material_bed_temperature = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg index 8b0005e60d..d042fc7978 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = ultra weight = 2 -material = generic_pla_175 +material = generic_pla [values] material_bed_temperature = 60 diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg index cc8ef3c9cd..8e79071db4 100644 --- a/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = verydraft weight = -4 -material = generic_pla_175 +material = generic_pla [values] material_bed_temperature = 60 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg index b75f20a1a6..3387b51d7d 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg index e06394dea5..da187c85ea 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg index 7249fb039c..a2efa54353 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg index a0237b3af2..a331a63aaf 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg index c858d341d2..d328e353ac 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = superdraft weight = -5 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg index 9996338c79..8e64dae5aa 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = -3 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg index 5d94f941c8..5757e57a3b 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = 2 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg index 0635565027..77810c8809 100644 --- a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = verydraft weight = -4 -material = generic_abs_175 +material = generic_abs [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg index 42e0d69476..80905c64f7 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_nylon_175 +material = generic_nylon diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg index e62e654fc3..eab42b728e 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_nylon_175 +material = generic_nylon diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg index cca4b98678..1261eff697 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_nylon_175 +material = generic_nylon diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg index 56c28e372f..6cf8709bf6 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_nylon_175 +material = generic_nylon diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg index 14375b3c41..3cf4efb73b 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = superdraft weight = -5 -material = generic_nylon_175 +material = generic_nylon diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg index 01c45f2401..22f27ab084 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = -3 -material = generic_nylon_175 +material = generic_nylon diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg index 205915cd7c..b3b80d651f 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = ultra weight = 2 -material = generic_nylon_175 +material = generic_nylon diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg index 124121c35c..efd93a5381 100644 --- a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = verydraft weight = -4 -material = generic_nylon_175 +material = generic_nylon diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg index ae69e5fe46..05283042c2 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_pc_175 +material = generic_pc [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg index 8e78ee7827..07319fe4db 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_pc_175 +material = generic_pc [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg index 761859e1a5..668040c851 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_pc_175 +material = generic_pc [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg index 91575da188..e9d907fabd 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pc_175 +material = generic_pc [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg index 9295b6b6d1..5d1af5a430 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = superdraft weight = -5 -material = generic_pc_175 +material = generic_pc [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg index 02ba4841e8..06c4b4f405 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = -3 -material = generic_pc_175 +material = generic_pc [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg index 8b3833371b..821658554d 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = ultra weight = 2 -material = generic_pc_175 +material = generic_pc [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg index f0ada1c6a8..93dc04e13c 100644 --- a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg @@ -8,7 +8,7 @@ setting_version = 4 type = quality quality_type = verydraft weight = -4 -material = generic_pc_175 +material = generic_pc [values] material_bed_temperature = 70 diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg index 9278a6920a..917e8b98a3 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg index 503362f755..aa98ea4de0 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = fast weight = -1 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg index 3d8ae1d5d0..3db3af0db2 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = high weight = 1 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg index 66c69b237e..e39fd54550 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg index 2b517e1521..6d9e99d365 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = superdraft weight = -5 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg index 969bd71f1a..5227aac686 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = -3 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg index ef97518e2a..a58c05b004 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = ultra weight = 2 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg index 7d338616dd..0fe38fb5df 100644 --- a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = verydraft weight = -4 -material = generic_petg_175 +material = generic_petg diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg index b3ccc9f82b..0b9f10a790 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = draft weight = -2 -material = generic_pla_175 +material = generic_pla diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg index 67ed46db58..d831890413 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = fast weight = 0 -material = generic_pla_175 +material = generic_pla diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg index 17b8f7a8b7..f5049308f3 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = high weight = 0 -material = generic_pla_175 +material = generic_pla diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg index 7852138707..f63c87a52c 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = normal weight = 0 -material = generic_pla_175 +material = generic_pla diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg index aa46df06b6..a8bd9a5179 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = superdraft weight = -5 -material = generic_pla_175 +material = generic_pla diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg index 39cf607b25..df1ae97a16 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = thickerdraft weight = -3 -material = generic_pla_175 +material = generic_pla diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg index 18d93dac2d..3b3ec79692 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg @@ -8,4 +8,4 @@ setting_version = 4 type = quality quality_type = ultra weight = 2 -material = generic_pla_175 +material = generic_pla diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg index e8fff16371..5e63de3952 100644 --- a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg @@ -6,6 +6,6 @@ definition = monoprice_select_mini_v2 [metadata] setting_version = 4 type = quality -material = generic_pla_175 +material = generic_pla weight = 0 quality_type = verydraft From 70d5cd246234518209fcd70e180e41200451c81e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 14:30:29 +0100 Subject: [PATCH 175/371] Fix: Replace all activeQualityName with activeQualityOrQualityChangesName --- cura/Settings/ContainerManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 6eb9aa0311..ea82af8d7f 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -366,7 +366,7 @@ class ContainerManager(QObject): if not global_stack: return - active_quality_name = self._machine_manager.activeQualityName + active_quality_name = self._machine_manager.activeQualityOrQualityChangesName if active_quality_name == "": Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) return From d72f8e87505d150c7f8c9009263f263988c7db06 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 14:41:45 +0100 Subject: [PATCH 176/371] CURA-4606 fix warning materials on machines that do not have has_variant_materials --- cura/Machines/QualityManager.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 078de762d4..a9aa6e9dcf 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -283,6 +283,8 @@ class QualityManager(QObject): # TODO: How to make this simpler, including the fall backs. # Get machine definition ID for quality search machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + # This determines if we should only get the global qualities for the global stack and skip the global qualities for the extruder stacks + has_variant_materials = parseBool(machine.getMetaDataEntry("has_variant_materials", False)) # To find the quality container for the GlobalStack, check in the following fall-back manner: # (1) the machine-specific node @@ -296,10 +298,11 @@ class QualityManager(QObject): for node in nodes_to_check: if node and node.quality_type_map: # Only include global qualities - quality_node = list(node.quality_type_map.values())[0] - is_global_quality = parseBool(quality_node.metadata.get("global_quality", False)) - if not is_global_quality: - continue + if has_variant_materials: + quality_node = list(node.quality_type_map.values())[0] + is_global_quality = parseBool(quality_node.metadata.get("global_quality", False)) + if not is_global_quality: + continue for quality_type, quality_node in node.quality_type_map.items(): quality_group = QualityGroup(quality_node.metadata["name"], quality_type) @@ -354,11 +357,12 @@ class QualityManager(QObject): nodes_to_check += [machine_node, default_machine_node] for node in nodes_to_check: if node and node.quality_type_map: - # Only include variant qualities; skip non global qualities - quality_node = list(node.quality_type_map.values())[0] - is_global_quality = parseBool(quality_node.metadata.get("global_quality", False)) - if is_global_quality: - continue + if has_variant_materials: + # Only include variant qualities; skip non global qualities + quality_node = list(node.quality_type_map.values())[0] + is_global_quality = parseBool(quality_node.metadata.get("global_quality", False)) + if is_global_quality: + continue for quality_type, quality_node in node.quality_type_map.items(): if quality_type not in quality_group_dict: From fcff00e9daa3d056a65a261b01ace85e760e6271 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 21 Feb 2018 14:42:28 +0100 Subject: [PATCH 177/371] Remove plugins from preferences since they're now managed via the plugin browser --- resources/qml/Cura.qml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index f474d93900..799797f9f9 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -518,6 +518,9 @@ UM.MainWindow insertPage(4, catalog.i18nc("@title:tab", "Profiles"), Qt.resolvedUrl("Preferences/ProfilesPage.qml")); + // Remove plug-ins page because we will use the shiny new plugin browser: + removePage(5); + //Force refresh setPage(0); } @@ -629,17 +632,6 @@ UM.MainWindow } } - // show the installed plugins page in the preferences dialog - Connections - { - target: Cura.Actions.configurePlugins - onTriggered: - { - preferences.visible = true - preferences.setPage(5) - } - } - UM.ExtensionModel { id: curaExtensions } From 98a05ae483b3f54817cc34432b8e6ebde3c382bb Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 21 Feb 2018 14:44:27 +0100 Subject: [PATCH 178/371] Fixed typo ("coping" -> "copying") --- setup.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index a91ba535d5..0d78f44ddc 100644 --- a/setup.py +++ b/setup.py @@ -51,24 +51,24 @@ setup(name="Cura", #console=[{"script": "cura_app.py"}], options={"py2exe": {"skip_archive": False, "includes": includes}}) -print("Coping Cura plugins.") +print("Copying Cura plugins.") shutil.copytree(os.path.dirname(UM.__file__) + "/../plugins", "dist/plugins", ignore = shutil.ignore_patterns("ConsoleLogger", "OBJWriter", "MLPWriter", "MLPReader")) for path in os.listdir("plugins"): copytree("plugins/" + path, "dist/plugins/" + path) -print("Coping resources.") +print("Copying resources.") copytree(os.path.dirname(UM.__file__) + "/../resources", "dist/resources") copytree("resources", "dist/resources") -print("Coping Uranium QML.") +print("Copying Uranium QML.") shutil.copytree(os.path.dirname(UM.__file__) + "/Qt/qml/UM", "dist/qml/UM") for site_package in site.getsitepackages(): qt_origin_path = os.path.join(site_package, "PyQt5") if os.path.isdir(qt_origin_path): - print("Coping PyQt5 plugins from: %s" % qt_origin_path) + print("Copying PyQt5 plugins from: %s" % qt_origin_path) shutil.copytree(os.path.join(qt_origin_path, "plugins"), "dist/PyQt5/plugins") - print("Coping PyQt5 QtQuick from: %s" % qt_origin_path) + print("Copying PyQt5 QtQuick from: %s" % qt_origin_path) shutil.copytree(os.path.join(qt_origin_path, "qml/QtQuick"), "dist/qml/QtQuick") shutil.copytree(os.path.join(qt_origin_path, "qml/QtQuick.2"), "dist/qml/QtQuick.2") - print("Coping PyQt5 svg library from: %s" % qt_origin_path) + print("Copying PyQt5 svg library from: %s" % qt_origin_path) shutil.copy(os.path.join(qt_origin_path, "Qt5Svg.dll"), "dist/Qt5Svg.dll") print("Copying Angle libraries from %s" % qt_origin_path) shutil.copy(os.path.join(qt_origin_path, "libEGL.dll"), "dist/libEGL.dll") From 3ed9ac1e83d2cad797a779c8b3d971902f1d40ae Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Wed, 21 Feb 2018 14:54:05 +0100 Subject: [PATCH 179/371] Fix: Monitor icon state was not updated properly CURA-4977 --- plugins/MonitorStage/MonitorStage.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/MonitorStage/MonitorStage.py b/plugins/MonitorStage/MonitorStage.py index 1a999ca896..1a1d37cbdf 100644 --- a/plugins/MonitorStage/MonitorStage.py +++ b/plugins/MonitorStage/MonitorStage.py @@ -69,9 +69,11 @@ class MonitorStage(CuraStage): self._printer_output_device.connectionStateChanged.connect(self._updateIconSource) self._setActivePrinter(self._printer_output_device.activePrinter) - # Force an update of the icon source - self._updateIconSource() + # Force an update of the icon source + self._updateIconSource() except IndexError: + #If index error occurs, then the icon on monitor button also should be updated + self._updateIconSource() pass def _onEngineCreated(self): From 5ba0ac8a43a10dd5191c13d3d23da19517951aa9 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 15:59:49 +0100 Subject: [PATCH 180/371] CURA-4606 switch to first extruder when switching machines; this prevents crashing when switching to single extruder machine --- cura/Settings/MachineManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 6cb6724a5a..85a02a8a30 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -308,6 +308,7 @@ class MachineManager(QObject): containers = container_registry.findContainerStacks(id = stack_id) if containers: global_stack = containers[0] + ExtruderManager.getInstance().setActiveExtruderIndex(0) # Switch to first extruder Application.getInstance().setGlobalContainerStack(global_stack) self._global_container_stack = global_stack self.globalContainerChanged.emit() From 244b10940333c763315818770bd746252aa08dcc Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Feb 2018 16:30:45 +0100 Subject: [PATCH 181/371] CURA-4606 CURA-4995 switching print core now correctly updates the material --- cura/Settings/MachineManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 85a02a8a30..cbb201610b 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1063,7 +1063,7 @@ class MachineManager(QObject): material_manager = Application.getInstance()._material_manager material_diameter = self._global_container_stack.getProperty("material_diameter", "value") candidate_materials = material_manager.getAvailableMaterials( - self._global_container_stack.getId(), + self._global_container_stack.definition.getId(), current_variant_name, material_diameter) From 7a3ebe1a42ed992bf0fda1f56a9d9d8b168a5ffb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 16:28:11 +0100 Subject: [PATCH 182/371] Fix NozzleMenu active nozzle bullet --- cura/Settings/ExtruderManager.py | 9 +++------ cura/Settings/MachineManager.py | 5 +++-- resources/qml/Menus/NozzleMenu.qml | 16 ++++------------ 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 3bf248970e..fa045e9496 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -30,10 +30,11 @@ class ExtruderManager(QObject): def __init__(self, parent = None): super().__init__(parent) + self._application = Application.getInstance() + self._extruder_trains = {} # Per machine, a dictionary of extruder container stack IDs. Only for separately defined extruders. self._active_extruder_index = -1 # Indicates the index of the active extruder stack. -1 means no active extruder stack self._selected_object_extruders = [] - self._global_container_stack_definition_id = None self._addCurrentMachineExtruders() #Application.getInstance().globalContainerStackChanged.connect(self._globalContainerStackChanged) @@ -365,10 +366,6 @@ class ExtruderManager(QObject): return result[:machine_extruder_count] def _globalContainerStackChanged(self) -> None: - global_container_stack = Application.getInstance().getGlobalContainerStack() - if global_container_stack and global_container_stack.getBottom() and global_container_stack.getBottom().getId() != self._global_container_stack_definition_id: - self._global_container_stack_definition_id = global_container_stack.getBottom().getId() - # If the global container changed, the machine changed and might have extruders that were not registered yet self._addCurrentMachineExtruders() @@ -376,7 +373,7 @@ class ExtruderManager(QObject): ## Adds the extruders of the currently active machine. def _addCurrentMachineExtruders(self) -> None: - global_stack = Application.getInstance().getGlobalContainerStack() + global_stack = self._application.getGlobalContainerStack() extruders_changed = False if global_stack: diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index cbb201610b..6fc9245ffc 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -311,10 +311,11 @@ class MachineManager(QObject): ExtruderManager.getInstance().setActiveExtruderIndex(0) # Switch to first extruder Application.getInstance().setGlobalContainerStack(global_stack) self._global_container_stack = global_stack - self.globalContainerChanged.emit() - self._onGlobalContainerChanged() + Application.getInstance().setGlobalContainerStack(global_stack) ExtruderManager.getInstance()._globalContainerStackChanged() self._initMachineState(containers[0]) + self.globalContainerChanged.emit() + self._onGlobalContainerChanged() self.__emitChangedSignals() diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index 153bd88220..0b961a5a11 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -13,22 +13,12 @@ Menu title: "Nozzle" property int extruderIndex: 0 - property QtObject extruderStack: Cura.MachineManager.getExtruder(menu.extruderIndex) - property bool hasExtruderStack: extruderStack != null Cura.NozzleModel { id: nozzleModel } - Connections - { - target: Cura.MachineManager - onGlobalContainerChanged: { - menu.extruderStack = Cura.MachineManager.getExtruder(menu.extruderIndex); - } - } - Instantiator { model: nozzleModel @@ -37,10 +27,12 @@ Menu { text: model.hotend_name checkable: true - checked: menu.hasExtruderStack && extruderStack.variant.name == model.hotend_name + checked: { + return Cura.MachineManager.activeVariantNames[extruderIndex] == model.hotend_name + } exclusiveGroup: group onTriggered: { - Cura.MachineManager.setVariantGroup(extruderIndex, model.container_node); + Cura.MachineManager.setVariantGroup(menu.extruderIndex, model.container_node); } } From 4b1ec905c1a887f73ebe3c2a32ac50ba7b010005 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 16:39:34 +0100 Subject: [PATCH 183/371] Fix UM2 qualities --- resources/quality/ultimaker2/um2_draft.inst.cfg | 2 ++ resources/quality/ultimaker2/um2_fast.inst.cfg | 2 ++ resources/quality/ultimaker2/um2_high.inst.cfg | 2 ++ resources/quality/ultimaker2/um2_normal.inst.cfg | 1 + 4 files changed, 7 insertions(+) diff --git a/resources/quality/ultimaker2/um2_draft.inst.cfg b/resources/quality/ultimaker2/um2_draft.inst.cfg index 1115deacd9..88d3ed3520 100644 --- a/resources/quality/ultimaker2/um2_draft.inst.cfg +++ b/resources/quality/ultimaker2/um2_draft.inst.cfg @@ -8,5 +8,7 @@ setting_version = 4 type = quality quality_type = draft weight = -2 +global_quality = True [values] +layer_height = 0.2 diff --git a/resources/quality/ultimaker2/um2_fast.inst.cfg b/resources/quality/ultimaker2/um2_fast.inst.cfg index 8bc5b7dee3..36e4fe03c2 100644 --- a/resources/quality/ultimaker2/um2_fast.inst.cfg +++ b/resources/quality/ultimaker2/um2_fast.inst.cfg @@ -8,9 +8,11 @@ setting_version = 4 type = quality quality_type = fast weight = -1 +global_quality = True [values] infill_sparse_density = 10 +layer_height = 0.15 cool_min_layer_time = 3 speed_wall_0 = 40 speed_wall_x = 80 diff --git a/resources/quality/ultimaker2/um2_high.inst.cfg b/resources/quality/ultimaker2/um2_high.inst.cfg index 8d6573b2be..2fb7ead455 100644 --- a/resources/quality/ultimaker2/um2_high.inst.cfg +++ b/resources/quality/ultimaker2/um2_high.inst.cfg @@ -8,7 +8,9 @@ setting_version = 4 type = quality quality_type = high weight = 1 +global_quality = True [values] +layer_height = 0.06 speed_topbottom = 15 speed_infill = 80 diff --git a/resources/quality/ultimaker2/um2_normal.inst.cfg b/resources/quality/ultimaker2/um2_normal.inst.cfg index ea7efc64ac..51fe1f317c 100644 --- a/resources/quality/ultimaker2/um2_normal.inst.cfg +++ b/resources/quality/ultimaker2/um2_normal.inst.cfg @@ -8,5 +8,6 @@ setting_version = 4 type = quality quality_type = normal weight = 0 +global_quality = True [values] From d83b803fe0d5096f4ce7ed9d8a6820989e8b0bd6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 16:47:12 +0100 Subject: [PATCH 184/371] Fix: Update active material names if materials lookup table gets updated --- cura/Settings/MachineManager.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 6fc9245ffc..7ca9040d2a 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -123,6 +123,14 @@ class MachineManager(QObject): if containers: containers[0].nameChanged.connect(self._onMaterialNameChanged) + # NEW + self._material_manager = self._application._material_manager + self._material_manager.materialsUpdated.connect(self._onMaterialsUpdated) + + def _onMaterialsUpdated(self): + # When the materials lookup table gets updated, it can mean that a material has its name changed, which should + # be reflected on the GUI. This signal emission makes sure that it happens. + self.rootMaterialChanged.emit() ### NEW activeQualityGroupChanged = pyqtSignal() From 7ea245a57dd8672b84fdaae5aac52586e3164b9d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 17:28:28 +0100 Subject: [PATCH 185/371] Fix: Show longer names on profile management page --- resources/qml/Preferences/ProfilesPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 2a6bd9c6f2..bcf624eb87 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -364,7 +364,7 @@ Item anchors.right: parent.right Label { - width: Math.floor((parent.width * 0.3)) + width: Math.floor((parent.width * 0.8)) text: model.name elide: Text.ElideRight font.italic: model.name == Cura.MachineManager.activeQualityOrQualityChangesName // TODO: make it easier From 47e4b35e700a52fc6e9289edd348a72974ee8bfa Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 19:44:42 +0100 Subject: [PATCH 186/371] WIP: Cleanup --- resources/qml/Preferences/ProfilesPage.qml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index bcf624eb87..1d29b26e50 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -367,7 +367,7 @@ Item width: Math.floor((parent.width * 0.8)) text: model.name elide: Text.ElideRight - font.italic: model.name == Cura.MachineManager.activeQualityOrQualityChangesName // TODO: make it easier + font.italic: model.name == Cura.MachineManager.activeQualityOrQualityChangesName color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text } } @@ -380,16 +380,9 @@ Item } } } - - onCurrentIndexChanged: - { - var model = qualitiesModel.getItem(currentIndex); - // TODO - } } } - // details panel on the right Item { From f946f62db187030b50d6afacafce276e6a4838e9 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 21 Feb 2018 20:27:33 +0100 Subject: [PATCH 187/371] WIP: Cleanup Upgrade 30 to 31 --- .../VersionUpgrade30to31.py | 74 ------------------- 1 file changed, 74 deletions(-) diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py b/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py index d7b2c1a001..a88ff5ac1c 100644 --- a/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py +++ b/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py @@ -3,14 +3,9 @@ import configparser #To parse preference files. import io #To serialise the preference files afterwards. -import os -from urllib.parse import quote_plus -from UM.Resources import Resources from UM.VersionUpgrade import VersionUpgrade #We're inheriting from this. -from cura.CuraApplication import CuraApplication - # a list of all legacy "Not Supported" quality profiles _OLD_NOT_SUPPORTED_PROFILES = [ @@ -130,7 +125,6 @@ class VersionUpgrade30to31(VersionUpgrade): parser.write(output) return [filename], [output.getvalue()] - ## Upgrades a container stack from version 3.0 to 3.1. # # \param serialised The serialised form of a container stack. @@ -172,71 +166,3 @@ class VersionUpgrade30to31(VersionUpgrade): output = io.StringIO() parser.write(output) return [filename], [output.getvalue()] - - def _getSingleExtrusionMachineQualityChanges(self, quality_changes_container): - quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer) - quality_changes_containers = [] - - for item in os.listdir(quality_changes_dir): - file_path = os.path.join(quality_changes_dir, item) - if not os.path.isfile(file_path): - continue - - parser = configparser.ConfigParser(interpolation = None) - try: - parser.read([file_path]) - except: - # skip, it is not a valid stack file - continue - - if not parser.has_option("metadata", "type"): - continue - if "quality_changes" != parser["metadata"]["type"]: - continue - - if not parser.has_option("general", "name"): - continue - if quality_changes_container["general"]["name"] != parser["general"]["name"]: - continue - - quality_changes_containers.append(parser) - - return quality_changes_containers - - def _createExtruderQualityChangesForSingleExtrusionMachine(self, filename, global_quality_changes): - suffix = "_" + quote_plus(global_quality_changes["general"]["name"].lower()) - machine_name = os.path.os.path.basename(filename).replace(".inst.cfg", "").replace(suffix, "") - - # Why is this here?! - # When we load a .curaprofile file the deserialize will trigger a version upgrade, creating a dangling file. - # This file can be recognized by it's lack of a machine name in the target filename. - # So when we detect that situation here, we don't create the file and return. - if machine_name == "": - return - - new_filename = machine_name + "_" + "fdmextruder" + suffix - - extruder_quality_changes_parser = configparser.ConfigParser(interpolation = None) - extruder_quality_changes_parser.add_section("general") - extruder_quality_changes_parser["general"]["version"] = str(2) - extruder_quality_changes_parser["general"]["name"] = global_quality_changes["general"]["name"] - extruder_quality_changes_parser["general"]["definition"] = global_quality_changes["general"]["definition"] - - # check renamed definition - if extruder_quality_changes_parser["general"]["definition"] in _RENAMED_DEFINITION_DICT: - extruder_quality_changes_parser["general"]["definition"] = _RENAMED_DEFINITION_DICT[extruder_quality_changes_parser["general"]["definition"]] - - extruder_quality_changes_parser.add_section("metadata") - extruder_quality_changes_parser["metadata"]["quality_type"] = global_quality_changes["metadata"]["quality_type"] - extruder_quality_changes_parser["metadata"]["type"] = global_quality_changes["metadata"]["type"] - extruder_quality_changes_parser["metadata"]["setting_version"] = str(4) - extruder_quality_changes_parser["metadata"]["extruder"] = "fdmextruder" - - extruder_quality_changes_output = io.StringIO() - extruder_quality_changes_parser.write(extruder_quality_changes_output) - extruder_quality_changes_filename = quote_plus(new_filename) + ".inst.cfg" - - quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer) - - with open(os.path.join(quality_changes_dir, extruder_quality_changes_filename), "w", encoding = "utf-8") as f: - f.write(extruder_quality_changes_output.getvalue()) From 3591e01b251afd3e93cc5994380106c5547a2324 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Feb 2018 09:20:33 +0100 Subject: [PATCH 188/371] CURA-4606 CURA-5002 fix crash with machine with variants, but no variants defined --- cura/Machines/MaterialManager.py | 5 +++-- cura/Machines/VariantManager.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 664d55a4c1..54216972a4 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -256,8 +256,9 @@ class MaterialManager(QObject): material_id_metadata_dict = dict() for node in nodes_to_check: if node is not None: - material_id_metadata_dict = {mid: node for mid, node in node.material_map.items()} - break + for material_id, node in node.material_map.items(): + if material_id not in material_id_metadata_dict: + material_id_metadata_dict[material_id] = node return material_id_metadata_dict diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py index 05ddfe869c..834b47dd0f 100644 --- a/cura/Machines/VariantManager.py +++ b/cura/Machines/VariantManager.py @@ -83,4 +83,4 @@ class VariantManager: def getVariantNodes(self, machine: "GlobalStack", variant_type: Optional[str] = VariantType.NOZZLE) -> dict: machine_definition_id = machine.definition.getId() - return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}) + return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {}) From 3095140bc338f7c4f6b8138a30562fc64510680f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 10:22:13 +0100 Subject: [PATCH 189/371] Fix quality/qualityChanges group initialization --- cura/Settings/MachineManager.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7ca9040d2a..4204beb6a4 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -290,21 +290,21 @@ class MachineManager(QObject): material_dict[position] = extruder.material.getMetaDataEntry("base_file") self._current_root_material_id = material_dict global_quality = global_stack.quality - global_quality_changes = global_stack.qualityChanges - - quality_groups = self._application._quality_manager.getQualityGroups(global_stack) quality_type = global_quality.getMetaDataEntry("quality_type") - if not quality_type in quality_groups: - Logger.log("w", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values())) - return - new_quality_group = quality_groups[quality_type] - self._setQualityGroup(new_quality_group) + global_quality_changes = global_stack.qualityChanges if global_quality_changes.getId() != "empty_quality_changes": quality_changes_groups = self._application._quality_manager.getQualityChangesGroups(global_stack) if quality_type in quality_changes_groups: new_quality_changes_group = quality_changes_groups[quality_type] self._setQualityChangesGroup(new_quality_changes_group) + else: + quality_groups = self._application._quality_manager.getQualityGroups(global_stack) + if quality_type not in quality_groups: + Logger.log("w", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values())) + return + new_quality_group = quality_groups[quality_type] + self._setQualityGroup(new_quality_group) @pyqtSlot(str) def setActiveMachine(self, stack_id: str) -> None: From b014800eac3bacea790693ee04cb4984e761698e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 11:00:32 +0100 Subject: [PATCH 190/371] Fix various quality related issues --- cura/Settings/MachineManager.py | 35 ++++++++-------------- resources/qml/Preferences/ProfileTab.qml | 6 ++-- resources/qml/Preferences/ProfilesPage.qml | 8 ++--- resources/qml/SidebarAdvanced.qml | 2 +- 4 files changed, 20 insertions(+), 31 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 4204beb6a4..7f74df60eb 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -527,18 +527,7 @@ class MachineManager(QObject): return quality_changes.getId() return "" - @pyqtProperty(str, notify=activeQualityChanged) - def globalQualityId(self) -> str: - if self._global_container_stack: - quality = self._global_container_stack.qualityChanges - if quality and not isinstance(quality, type(self._empty_quality_changes_container)): - return quality.getId() - quality = self._global_container_stack.quality - if quality: - return quality.getId() - return "" - - @pyqtProperty(str, notify=activeVariantChanged) + @pyqtProperty(str, notify = activeVariantChanged) def globalVariantName(self) -> str: if self._global_container_stack: variant = self._global_container_stack.variant @@ -546,21 +535,21 @@ class MachineManager(QObject): return variant.getName() return "" - @pyqtProperty(str, notify = activeQualityChanged) + @pyqtProperty(str, notify = activeQualityGroupChanged) def activeQualityType(self) -> str: + quality_type = "" if self._active_container_stack: - quality = self._active_container_stack.quality - if quality: - return quality.getMetaDataEntry("quality_type") - return "" + if self._current_quality_group: + quality_type = self._current_quality_group.quality_type + return quality_type - @pyqtProperty(bool, notify = activeQualityChanged) + @pyqtProperty(bool, notify = activeQualityGroupChanged) def isActiveQualitySupported(self) -> bool: - if self._active_container_stack: - quality = self._active_container_stack.quality - if quality: - return Util.parseBool(quality.getMetaDataEntry("supported", True)) - return False + is_supported = False + if self._global_container_stack: + if self._current_quality_group: + is_supported = self._current_quality_group.is_available + return is_supported ## Returns whether there is anything unsupported in the current set-up. # diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml index 5acbeecda9..b4b2299c15 100644 --- a/resources/qml/Preferences/ProfileTab.qml +++ b/resources/qml/Preferences/ProfileTab.qml @@ -36,8 +36,8 @@ Tab anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.right: parent.right text: (styleData.value.substr(0,1) == "=") ? catalog.i18nc("@info:status", "Calculated") : styleData.value - font.strikeout: styleData.column == 1 && setting.user_value != "" // TODO && quality == Cura.MachineManager.globalQualityId - font.italic: setting.profile_value_source == "quality_changes" || (setting.user_value != "") // TODO: (setting.user_value != "" && quality == Cura.MachineManager.globalQualityId) + font.strikeout: styleData.column == 1 && setting.user_value != "" && qualityItem.name == Cura.MachineManager.activeQualityOrQualityChangesName + font.italic: setting.profile_value_source == "quality_changes" || (setting.user_value != "" && qualityItem.name == Cura.MachineManager.activeQualityOrQualityChangesName) opacity: font.strikeout ? 0.5 : 1 color: styleData.textColor elide: Text.ElideRight @@ -63,7 +63,7 @@ Tab { role: "user_value" title: catalog.i18nc("@title:column", "Current"); - visible: true // TODO quality == Cura.MachineManager.globalQualityId + visible: qualityItem.name == Cura.MachineManager.activeQualityOrQualityChangesName width: (parent.width * 0.18) | 0 delegate: itemDelegate } diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 1d29b26e50..6a42034846 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -408,14 +408,14 @@ Item height: childrenRect.height Label { - text: base.currentItem.name // TODO + text: base.currentItem.name font: UM.Theme.getFont("large") } } Flow { id: currentSettingsActions - visible: true // TODO //currentItem && currentItem.id == Cura.MachineManager.activeQualityId + visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName anchors.left: parent.left anchors.right: parent.right anchors.top: profileName.bottom @@ -424,7 +424,7 @@ Item Button { text: catalog.i18nc("@action:button", "Update profile with current settings/overrides") - enabled: Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) + enabled: Cura.MachineManager.hasUserSettings && !base.currentItem.is_read_only onClicked: Cura.ContainerManager.updateQualityChanges() } @@ -453,7 +453,7 @@ Item } Label { id: noCurrentSettingsMessage - visible: currentItem && currentItem.id == Cura.MachineManager.activeQualityId && !Cura.MachineManager.hasUserSettings + visible: base.isCurrentItemActivated && !Cura.MachineManager.hasUserSettings text: catalog.i18nc("@action:label", "Your current settings match the selected profile.") wrapMode: Text.WordWrap width: parent.width diff --git a/resources/qml/SidebarAdvanced.qml b/resources/qml/SidebarAdvanced.qml index ff5f545c80..ae77bc8d1b 100644 --- a/resources/qml/SidebarAdvanced.qml +++ b/resources/qml/SidebarAdvanced.qml @@ -1,7 +1,7 @@ // Copyright (c) 2015 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.8 import QtQuick.Controls 2.0 import "Settings" From 7a2c25226a1ebc150ceb7b4200ebe7ed3e621f32 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 12:59:26 +0100 Subject: [PATCH 191/371] Fix initial quality_changes group setup --- cura/Settings/MachineManager.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7f74df60eb..47877c8a7f 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -79,6 +79,9 @@ class MachineManager(QObject): self.globalContainerChanged.connect(self.activeVariantChanged) self.globalContainerChanged.connect(self.activeQualityChanged) + self.globalContainerChanged.connect(self.activeQualityChangesGroupChanged) + self.globalContainerChanged.connect(self.activeQualityGroupChanged) + self._stacks_have_errors = None # type:Optional[bool] self._empty_definition_changes_container = ContainerRegistry.getInstance().findContainers(id = "empty_definition_changes")[0] @@ -242,6 +245,7 @@ class MachineManager(QObject): Application.getInstance().callLater(func) del self.machine_extruder_material_update_dict[self._global_container_stack.getId()] + self.activeQualityGroupChanged.emit() self._error_check_timer.start() ## Update self._stacks_valid according to _checkStacksForErrors and emit if change. @@ -292,11 +296,12 @@ class MachineManager(QObject): global_quality = global_stack.quality quality_type = global_quality.getMetaDataEntry("quality_type") global_quality_changes = global_stack.qualityChanges + global_quality_changes_name = global_quality_changes.getName() if global_quality_changes.getId() != "empty_quality_changes": quality_changes_groups = self._application._quality_manager.getQualityChangesGroups(global_stack) - if quality_type in quality_changes_groups: - new_quality_changes_group = quality_changes_groups[quality_type] + if global_quality_changes_name in quality_changes_groups: + new_quality_changes_group = quality_changes_groups[global_quality_changes_name] self._setQualityChangesGroup(new_quality_changes_group) else: quality_groups = self._application._quality_manager.getQualityGroups(global_stack) From 25dd63dc215247e50518488090c25c2c5aad60ee Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 13:45:46 +0100 Subject: [PATCH 192/371] WIP: Cleanup MachineManager --- cura/Settings/MachineManager.py | 19 ++----------------- resources/qml/Actions.qml | 2 +- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 47877c8a7f..76aefb3c0b 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -496,7 +496,7 @@ class MachineManager(QObject): # # \return The layer height of the currently active quality profile. If # there is no quality profile, this returns 0. - @pyqtProperty(float, notify=activeQualityChanged) + @pyqtProperty(float, notify = activeQualityGroupChanged) def activeQualityLayerHeight(self) -> float: if not self._global_container_stack: return 0 @@ -516,22 +516,6 @@ class MachineManager(QObject): return 0 # No quality profile. - @pyqtProperty(str, notify=activeQualityChanged) - def activeQualityId(self) -> str: - if self._active_container_stack: - quality = self._active_container_stack.quality - if isinstance(quality, type(self._empty_quality_container)): - return "" - quality_changes = self._active_container_stack.qualityChanges - if quality and quality_changes: - if isinstance(quality_changes, type(self._empty_quality_changes_container)): - # It's a built-in profile - return quality.getId() - else: - # Custom profile - return quality_changes.getId() - return "" - @pyqtProperty(str, notify = activeVariantChanged) def globalVariantName(self) -> str: if self._global_container_stack: @@ -939,6 +923,7 @@ class MachineManager(QObject): extruder.qualityChanges = self._empty_quality_changes_container self.activeQualityGroupChanged.emit() + self.activeQualityChangesGroupChanged.emit() def _setQualityGroup(self, quality_group, empty_quality_changes = True): self._current_quality_group = quality_group diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 05ff5050e9..23c19bece8 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -173,7 +173,7 @@ Item Action { id: updateProfileAction; - enabled: !Cura.MachineManager.stacksHaveErrors && Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) + enabled: !Cura.MachineManager.stacksHaveErrors && Cura.MachineManager.hasUserSettings && Cura.MachineManager.activeQualityChangesGroup != null text: catalog.i18nc("@action:inmenu menubar:profile","&Update profile with current settings/overrides"); onTriggered: Cura.ContainerManager.updateQualityChanges(); } From b415a361101cffec1eaafcb4a3fd179d3aa9f212 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 13:58:35 +0100 Subject: [PATCH 193/371] WIP: Remove delayed update in MachineManager --- cura/CuraApplication.py | 3 -- cura/Settings/MachineManager.py | 77 --------------------------------- 2 files changed, 80 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 464694dbcd..a1a2f52305 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -540,8 +540,6 @@ class CuraApplication(QtApplication): has_user_interaction = True return has_user_interaction - onDiscardOrKeepProfileChangesClosed = pyqtSignal() # Used to notify other managers that the dialog was closed - @pyqtSlot(str) def discardOrKeepProfileChangesClosed(self, option): if option == "discard": @@ -564,7 +562,6 @@ class CuraApplication(QtApplication): user_global_container.update() # notify listeners that quality has changed (after user selected discard or keep) - self.onDiscardOrKeepProfileChangesClosed.emit() self.getMachineManager().activeQualityChanged.emit() @pyqtSlot(int) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 76aefb3c0b..f2446b8017 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -54,12 +54,6 @@ class MachineManager(QObject): self.machine_extruder_material_update_dict = collections.defaultdict(list) - # Used to store the new containers until after confirming the dialog - self._new_variant_container = None # type: Optional[InstanceContainer] - self._new_buildplate_container = None # type: Optional[InstanceContainer] - self._new_material_container = None # type: Optional[InstanceContainer] - self._new_quality_containers = [] # type: List[Dict] - self._error_check_timer = QTimer() self._error_check_timer.setInterval(250) self._error_check_timer.setSingleShot(True) @@ -104,9 +98,6 @@ class MachineManager(QObject): ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged) self.activeStackChanged.connect(self.activeStackValueChanged) - # when a user closed dialog check if any delayed material or variant changes need to be applied - Application.getInstance().onDiscardOrKeepProfileChangesClosed.connect(self._executeDelayedActiveContainerStackChanges) - Preferences.getInstance().addPreference("cura/active_machine", "") self._global_event_keys = set() @@ -172,18 +163,6 @@ class MachineManager(QObject): self.outputDevicesChanged.emit() - @property - def newVariant(self): - return self._new_variant_container - - @property - def newBuildplate(self): - return self._new_buildplate_container - - @property - def newMaterial(self): - return self._new_material_container - @pyqtProperty("QVariantList", notify = outputDevicesChanged) def printerOutputDevices(self): return self._printer_output_devices @@ -314,7 +293,6 @@ class MachineManager(QObject): @pyqtSlot(str) def setActiveMachine(self, stack_id: str) -> None: self.blurSettings.emit() # Ensure no-one has focus. - self._cancelDelayedActiveContainerStackChanges() container_registry = ContainerRegistry.getInstance() @@ -573,61 +551,6 @@ class MachineManager(QObject): if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved - ## Used to update material and variant in the active container stack with a delay. - # This delay prevents the stack from triggering a lot of signals (eventually resulting in slicing) - # before the user decided to keep or discard any of their changes using the dialog. - # The Application.onDiscardOrKeepProfileChangesClosed signal triggers this method. - def _executeDelayedActiveContainerStackChanges(self): - Logger.log("d", "Applying configuration changes...") - - if self._new_variant_container is not None: - self._active_container_stack.variant = self._new_variant_container - self._new_variant_container = None - - if self._new_buildplate_container is not None: - self._global_container_stack.variant = self._new_buildplate_container - self._new_buildplate_container = None - - if self._new_material_container is not None: - self._active_container_stack.material = self._new_material_container - self._new_material_container = None - - # apply the new quality to all stacks - if self._new_quality_containers: - for new_quality in self._new_quality_containers: - self._replaceQualityOrQualityChangesInStack(new_quality["stack"], new_quality["quality"], postpone_emit = True) - self._replaceQualityOrQualityChangesInStack(new_quality["stack"], new_quality["quality_changes"], postpone_emit = True) - - for new_quality in self._new_quality_containers: - new_quality["stack"].nameChanged.connect(self._onQualityNameChanged) - new_quality["stack"].sendPostponedEmits() # Send the signals that were postponed in _replaceQualityOrQualityChangesInStack - - self._new_quality_containers.clear() - - Logger.log("d", "New configuration applied") - - ## Cancel set changes for material and variant in the active container stack. - # Used for ignoring any changes when switching between printers (setActiveMachine) - def _cancelDelayedActiveContainerStackChanges(self): - self._new_material_container = None - self._new_buildplate_container = None - self._new_variant_container = None - - def _replaceQualityOrQualityChangesInStack(self, stack: "CuraContainerStack", container: "InstanceContainer", postpone_emit = False): - # Disconnect the signal handling from the old container. - container_type = container.getMetaDataEntry("type") - if container_type == "quality": - stack.quality.nameChanged.disconnect(self._onQualityNameChanged) - stack.setQuality(container, postpone_emit = postpone_emit) - stack.quality.nameChanged.connect(self._onQualityNameChanged) - elif container_type == "quality_changes" or container_type is None: - # If the container is an empty container, we need to change the quality_changes. - # Quality can never be set to empty. - stack.qualityChanges.nameChanged.disconnect(self._onQualityNameChanged) - stack.setQualityChanges(container, postpone_emit = postpone_emit) - stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged) - self._onQualityNameChanged() - @pyqtProperty(str, notify = activeVariantChanged) def activeVariantName(self) -> str: if self._active_container_stack: From 392f7297318b62ded0f02c3fcc3b6a4aaa7e8814 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 14:21:10 +0100 Subject: [PATCH 194/371] Reduce number of QML singletons --- cura/CuraApplication.py | 8 ++++++-- resources/qml/Menus/BuildplateMenu.qml | 8 +++++--- resources/qml/Menus/ContextMenu.qml | 12 +++++++----- resources/qml/Menus/ViewMenu.qml | 10 ++++++---- resources/qml/ObjectsList.qml | 14 ++++++-------- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a1a2f52305..a2dc27f483 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -2,6 +2,8 @@ # Cura is released under the terms of the LGPLv3 or higher. #Type hinting. from typing import Dict + +from PyQt5.QtCore import QObject from PyQt5.QtNetwork import QLocalServer from PyQt5.QtNetwork import QLocalSocket @@ -859,11 +861,13 @@ class CuraApplication(QtApplication): self._object_manager = ObjectsModel.createObjectsModel() return self._object_manager + @pyqtSlot(result = QObject) def getMultiBuildPlateModel(self, *args): if self._multi_build_plate_model is None: self._multi_build_plate_model = MultiBuildPlateModel(self) return self._multi_build_plate_model + @pyqtSlot(result = QObject) def getBuildPlateModel(self, *args): if self._build_plate_model is None: self._build_plate_model = BuildPlateModel(self) @@ -936,8 +940,8 @@ class CuraApplication(QtApplication): qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 0, "ObjectsModel", self.getObjectsModel) - qmlRegisterSingletonType(BuildPlateModel, "Cura", 1, 0, "BuildPlateModel", self.getBuildPlateModel) - qmlRegisterSingletonType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel", self.getMultiBuildPlateModel) + qmlRegisterType(BuildPlateModel, "Cura", 1, 0, "BuildPlateModel") + qmlRegisterType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel") qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer") qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") diff --git a/resources/qml/Menus/BuildplateMenu.qml b/resources/qml/Menus/BuildplateMenu.qml index 8dfc3ced6c..0b67b37cc1 100644 --- a/resources/qml/Menus/BuildplateMenu.qml +++ b/resources/qml/Menus/BuildplateMenu.qml @@ -12,17 +12,19 @@ Menu id: menu title: "Build plate" + property Cura.BuildPlateModel buildPlateModel: CuraApplication.getBuildPlateModel() + Instantiator { - model: Cura.BuildPlateModel + model: menu.buildPlateModel MenuItem { text: model.name checkable: true - checked: model.name == Cura.MachineManager.globalVariantName // TODO + checked: model.name == Cura.MachineManager.globalVariantName exclusiveGroup: group onTriggered: { - Cura.MachineManager.setGlobalVariant(model.container_node); // TODO + Cura.MachineManager.setGlobalVariant(model.container_node); } } diff --git a/resources/qml/Menus/ContextMenu.qml b/resources/qml/Menus/ContextMenu.qml index a37204d255..656e94b336 100644 --- a/resources/qml/Menus/ContextMenu.qml +++ b/resources/qml/Menus/ContextMenu.qml @@ -15,6 +15,8 @@ Menu property bool shouldShowExtruders: machineExtruderCount.properties.value > 1; + property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() + // Selection-related actions. MenuItem { action: Cura.Actions.centerSelection; } MenuItem { action: Cura.Actions.deleteSelection; } @@ -45,13 +47,13 @@ Menu Instantiator { - model: Cura.MultiBuildPlateModel + model: base.multiBuildPlateModel MenuItem { enabled: UM.Selection.hasSelection - text: Cura.MultiBuildPlateModel.getItem(index).name; - onTriggered: CuraActions.setBuildPlateForSelection(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber); + text: base.multiBuildPlateModel.getItem(index).name; + onTriggered: CuraActions.setBuildPlateForSelection(base.multiBuildPlateModel.getItem(index).buildPlateNumber); checkable: true - checked: Cura.MultiBuildPlateModel.selectionBuildPlates.indexOf(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber) != -1; + checked: base.multiBuildPlateModel.selectionBuildPlates.indexOf(base.multiBuildPlateModel.getItem(index).buildPlateNumber) != -1; visible: UM.Preferences.getValue("cura/use_multi_build_plate") } onObjectAdded: base.insertItem(index, object); @@ -62,7 +64,7 @@ Menu enabled: UM.Selection.hasSelection text: "New build plate"; onTriggered: { - CuraActions.setBuildPlateForSelection(Cura.MultiBuildPlateModel.maxBuildPlate + 1); + CuraActions.setBuildPlateForSelection(base.multiBuildPlateModel.maxBuildPlate + 1); checked = false; } checkable: true diff --git a/resources/qml/Menus/ViewMenu.qml b/resources/qml/Menus/ViewMenu.qml index ff749bec90..fc0339e0c6 100644 --- a/resources/qml/Menus/ViewMenu.qml +++ b/resources/qml/Menus/ViewMenu.qml @@ -13,6 +13,8 @@ Menu id: base enabled: !PrintInformation.preSliced + property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() + // main views Instantiator { @@ -53,12 +55,12 @@ Menu visible: UM.Preferences.getValue("cura/use_multi_build_plate") Instantiator { - model: Cura.MultiBuildPlateModel + model: base.multiBuildPlateModel MenuItem { - text: Cura.MultiBuildPlateModel.getItem(index).name; - onTriggered: Cura.SceneController.setActiveBuildPlate(Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber); + text: base.multiBuildPlateModel.getItem(index).name; + onTriggered: Cura.SceneController.setActiveBuildPlate(base.multiBuildPlateModel.getItem(index).buildPlateNumber); checkable: true; - checked: Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber == Cura.MultiBuildPlateModel.activeBuildPlate; + checked: base.multiBuildPlateModel.getItem(index).buildPlateNumber == base.multiBuildPlateModel.activeBuildPlate; exclusiveGroup: buildPlateGroup; visible: UM.Preferences.getValue("cura/use_multi_build_plate") } diff --git a/resources/qml/ObjectsList.qml b/resources/qml/ObjectsList.qml index f51e1081e6..e7dd63ea05 100644 --- a/resources/qml/ObjectsList.qml +++ b/resources/qml/ObjectsList.qml @@ -33,6 +33,8 @@ Rectangle property bool collapsed: true; + property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() + SystemPalette { id: palette } Button { @@ -67,7 +69,7 @@ Rectangle Rectangle { height: childrenRect.height - color: Cura.MultiBuildPlateModel.getItem(index).buildPlateNumber == Cura.MultiBuildPlateModel.activeBuildPlate ? palette.highlight : index % 2 ? palette.base : palette.alternateBase + color: multiBuildPlateModel.getItem(index).buildPlateNumber == multiBuildPlateModel.activeBuildPlate ? palette.highlight : index % 2 ? palette.base : palette.alternateBase width: parent.width Label { @@ -75,8 +77,8 @@ Rectangle anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width width: parent.width - 2 * UM.Theme.getSize("default_margin").width - 30 - text: Cura.MultiBuildPlateModel.getItem(index) ? Cura.MultiBuildPlateModel.getItem(index).name : ""; - color: Cura.MultiBuildPlateModel.activeBuildPlate == index ? palette.highlightedText : palette.text + text: multiBuildPlateModel.getItem(index) ? multiBuildPlateModel.getItem(index).name : ""; + color: multiBuildPlateModel.activeBuildPlate == index ? palette.highlightedText : palette.text elide: Text.ElideRight } @@ -118,13 +120,12 @@ Rectangle ListView { id: buildPlateListView - model: Cura.MultiBuildPlateModel + model: multiBuildPlateModel width: parent.width delegate: buildPlateDelegate } } - Component { id: objectDelegate Rectangle @@ -200,7 +201,6 @@ Rectangle } } - CheckBox { id: filterBuildPlateCheckbox @@ -260,6 +260,4 @@ Rectangle } action: Cura.Actions.arrangeAll; } - - } From 32afa9bfd4e544402a207e95ef78da9dba6c4d63 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Feb 2018 14:27:58 +0100 Subject: [PATCH 195/371] CURA-4606 CURA-5003 fixed sometimes crash material management page upon opening, provide correct containerId to MaterialView --- resources/qml/Preferences/MaterialsPage.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 8d14ada759..22d906ac62 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -433,8 +433,8 @@ Item editingEnabled: base.currentItem != null && !base.currentItem.is_read_only properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.id : "" - currentMaterialNode: base.currentItem + containerId: base.currentItem != null ? base.currentItem.container_id : "" + currentMaterialNode: base.currentItem.container_node property alias pane: base } From a88e69d109fcf643980a50d8b9823695be348ef8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 15:00:12 +0100 Subject: [PATCH 196/371] Revert "WIP: Fix quality profiles for abax_pri5" Keep the old quality profiles for now to make it safe. --- resources/definitions/abax_pri5.def.json | 4 +--- .../quality/abax_pri5/apri5_pla_fast.inst.cfg | 22 +++++++++++++++++++ .../quality/abax_pri5/apri5_pla_high.inst.cfg | 22 +++++++++++++++++++ .../abax_pri5/apri5_pla_normal.inst.cfg | 22 +++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 resources/quality/abax_pri5/apri5_pla_fast.inst.cfg create mode 100644 resources/quality/abax_pri5/apri5_pla_high.inst.cfg create mode 100644 resources/quality/abax_pri5/apri5_pla_normal.inst.cfg diff --git a/resources/definitions/abax_pri5.def.json b/resources/definitions/abax_pri5.def.json index b8310221b1..cbebb576b0 100644 --- a/resources/definitions/abax_pri5.def.json +++ b/resources/definitions/abax_pri5.def.json @@ -6,9 +6,7 @@ "visible": true, "author": "ABAX 3d Technologies", "manufacturer": "ABAX 3d Technologies", - "file_formats": "text/x-gcode", - "quality_definition": "abax_pri3", - "has_machine_quality": true + "file_formats": "text/x-gcode" }, "overrides": { "machine_start_gcode": { diff --git a/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg b/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg new file mode 100644 index 0000000000..517c767ac5 --- /dev/null +++ b/resources/quality/abax_pri5/apri5_pla_fast.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = Fine +definition = abax_pri5 + +[metadata] +setting_version = 4 +type = quality +quality_type = normal +weight = -1 +material = generic_pla + +[values] +layer_height = 0.2 +wall_thickness = 1.05 +top_bottom_thickness = 0.8 +infill_sparse_density = 20 +speed_print = 80 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/abax_pri5/apri5_pla_high.inst.cfg b/resources/quality/abax_pri5/apri5_pla_high.inst.cfg new file mode 100644 index 0000000000..01699e39f6 --- /dev/null +++ b/resources/quality/abax_pri5/apri5_pla_high.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = Extra Fine +definition = abax_pri5 + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 1 +material = generic_pla + +[values] +layer_height = 0.1 +wall_thickness = 1.05 +top_bottom_thickness = 0.8 +infill_sparse_density = 20 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg b/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg new file mode 100644 index 0000000000..ea1023dc43 --- /dev/null +++ b/resources/quality/abax_pri5/apri5_pla_normal.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = Fine +definition = abax_pri5 + +[metadata] +setting_version = 4 +type = quality +quality_type = normal +weight = 0 +material = generic_pla + +[values] +layer_height = 0.2 +wall_thickness = 1.05 +top_bottom_thickness = 0.8 +infill_sparse_density = 20 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 From 0846021b674fa672a5842559479c708ce8d0b5a1 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 15:12:15 +0100 Subject: [PATCH 197/371] Fix imade3d jellybox quality profiles --- .../generic_petg_0.4_coarse.inst.cfg | 3 --- .../generic_petg_0.4_coarse_2-fans.inst.cfg | 3 --- .../generic_petg_0.4_medium.inst.cfg | 3 --- .../generic_petg_0.4_medium_2-fans.inst.cfg | 3 --- .../generic_pla_0.4_coarse.inst.cfg | 3 --- .../generic_pla_0.4_coarse_2-fans.inst.cfg | 3 --- .../generic_pla_0.4_fine.inst.cfg | 3 --- .../generic_pla_0.4_fine_2-fans.inst.cfg | 3 --- .../generic_pla_0.4_medium.inst.cfg | 3 --- .../generic_pla_0.4_medium_2-fans.inst.cfg | 3 --- .../generic_pla_0.4_ultrafine.inst.cfg | 3 --- .../generic_pla_0.4_ultrafine_2-fans.inst.cfg | 2 -- .../imade3d_jellybox_coarse.inst.cfg | 16 ++++++++++++++++ .../imade3d_jellybox_fine.inst.cfg | 16 ++++++++++++++++ .../imade3d_jellybox_normal.inst.cfg | 16 ++++++++++++++++ .../imade3d_jellybox_ultrafine.inst.cfg | 16 ++++++++++++++++ 16 files changed, 64 insertions(+), 35 deletions(-) create mode 100644 resources/quality/imade3d_jellybox/imade3d_jellybox_coarse.inst.cfg create mode 100644 resources/quality/imade3d_jellybox/imade3d_jellybox_fine.inst.cfg create mode 100644 resources/quality/imade3d_jellybox/imade3d_jellybox_normal.inst.cfg create mode 100644 resources/quality/imade3d_jellybox/imade3d_jellybox_ultrafine.inst.cfg diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg index e5b3aed52b..f300f5d95b 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg @@ -12,7 +12,6 @@ material = generic_petg variant = 0.4 mm [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.3 -layer_height_0 = 0.3 line_width = 0.4 material_bed_temperature = 50 material_bed_temperature_layer_0 = 55 diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg index e7f2d5d60a..804807184b 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg @@ -12,7 +12,6 @@ material = generic_petg variant = 0.4 mm 2-fans [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.3 -layer_height_0 = 0.3 line_width = 0.4 material_bed_temperature = 50 material_bed_temperature_layer_0 = 55 diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg index 4d122f1ac2..c39c8a7a98 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg @@ -12,7 +12,6 @@ material = generic_petg variant = 0.4 mm [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.2 -layer_height_0 = 0.3 line_width = 0.4 material_bed_temperature = 50 material_bed_temperature_layer_0 = 55 diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg index 9646b0bb5f..17cc1493e1 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg @@ -12,7 +12,6 @@ material = generic_petg variant = 0.4 mm 2-fans [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.2 -layer_height_0 = 0.3 line_width = 0.4 material_bed_temperature = 50 material_bed_temperature_layer_0 = 55 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg index 8ecfa927a7..738eb627fe 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg @@ -12,7 +12,6 @@ material = generic_pla variant = 0.4 mm [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.3 -layer_height_0 = 0.3 line_width = 0.4 material_flow = 90 meshfix_union_all = False diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg index 52c7df70f3..4f44559fbc 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg @@ -12,7 +12,6 @@ material = generic_pla variant = 0.4 mm 2-fans [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.3 -layer_height_0 = 0.3 line_width = 0.4 material_flow = 90 meshfix_union_all = False diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg index a48dbe2f81..f9f32237b0 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg @@ -12,7 +12,6 @@ material = generic_pla variant = 0.4 mm [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.1 -layer_height_0 = 0.3 line_width = 0.4 material_flow = 90 material_print_temperature = 205 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg index 4707337611..82f5a4fa32 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg @@ -12,7 +12,6 @@ material = generic_pla variant = 0.4 mm 2-fans [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.1 -layer_height_0 = 0.3 line_width = 0.4 material_flow = 90 material_print_temperature = 205 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg index 2f5a0f33a8..5ee2111c3a 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg @@ -12,7 +12,6 @@ material = generic_pla variant = 0.4 mm [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.2 -layer_height_0 = 0.3 line_width = 0.4 material_flow = 90 meshfix_union_all = False diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg index f0451fc9be..5d34259ccd 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg @@ -12,7 +12,6 @@ material = generic_pla variant = 0.4 mm 2-fans [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.2 -layer_height_0 = 0.3 line_width = 0.4 material_flow = 90 meshfix_union_all = False diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg index 179623153a..1826e69513 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg @@ -12,7 +12,6 @@ material = generic_pla variant = 0.4 mm [values] -adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 @@ -27,8 +26,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.05 -layer_height_0 = 0.3 line_width = 0.4 material_flow = 90 material_print_temperature = 202 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine_2-fans.inst.cfg index b35db0fde6..5b05c10604 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine_2-fans.inst.cfg @@ -27,8 +27,6 @@ infill_line_width = 0.6 infill_overlap = 15 infill_pattern = zigzag infill_sparse_density = 20 -layer_height = 0.05 -layer_height_0 = 0.3 line_width = 0.4 material_flow = 90 material_print_temperature = 202 diff --git a/resources/quality/imade3d_jellybox/imade3d_jellybox_coarse.inst.cfg b/resources/quality/imade3d_jellybox/imade3d_jellybox_coarse.inst.cfg new file mode 100644 index 0000000000..2e940ea646 --- /dev/null +++ b/resources/quality/imade3d_jellybox/imade3d_jellybox_coarse.inst.cfg @@ -0,0 +1,16 @@ +[general] +version = 2 +name = Coarse +definition = imade3d_jellybox + +[metadata] +setting_version = 4 +type = quality +quality_type = fast +weight = -1 +global_quality = True + +[values] +adhesion_type = skirt +layer_height = 0.3 +layer_height_0 = 0.3 diff --git a/resources/quality/imade3d_jellybox/imade3d_jellybox_fine.inst.cfg b/resources/quality/imade3d_jellybox/imade3d_jellybox_fine.inst.cfg new file mode 100644 index 0000000000..9979558963 --- /dev/null +++ b/resources/quality/imade3d_jellybox/imade3d_jellybox_fine.inst.cfg @@ -0,0 +1,16 @@ +[general] +version = 2 +name = Fine +definition = imade3d_jellybox + +[metadata] +setting_version = 4 +type = quality +quality_type = high +weight = 1 +global_quality = True + +[values] +adhesion_type = skirt +layer_height = 0.1 +layer_height_0 = 0.3 diff --git a/resources/quality/imade3d_jellybox/imade3d_jellybox_normal.inst.cfg b/resources/quality/imade3d_jellybox/imade3d_jellybox_normal.inst.cfg new file mode 100644 index 0000000000..0574099b63 --- /dev/null +++ b/resources/quality/imade3d_jellybox/imade3d_jellybox_normal.inst.cfg @@ -0,0 +1,16 @@ +[general] +version = 2 +name = Medium +definition = imade3d_jellybox + +[metadata] +setting_version = 4 +type = quality +quality_type = normal +weight = 0 +global_quality = True + +[values] +adhesion_type = skirt +layer_height = 0.2 +layer_height_0 = 0.3 diff --git a/resources/quality/imade3d_jellybox/imade3d_jellybox_ultrafine.inst.cfg b/resources/quality/imade3d_jellybox/imade3d_jellybox_ultrafine.inst.cfg new file mode 100644 index 0000000000..39344ce7f4 --- /dev/null +++ b/resources/quality/imade3d_jellybox/imade3d_jellybox_ultrafine.inst.cfg @@ -0,0 +1,16 @@ +[general] +version = 2 +name = UltraFine +definition = imade3d_jellybox + +[metadata] +setting_version = 4 +type = quality +quality_type = ultrahigh +weight = 2 +global_quality = True + +[values] +adhesion_type = skirt +layer_height = 0.05 +layer_height_0 = 0.3 From 21e4ed1ae9bed29307c336139c74f19def3fc52a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Feb 2018 20:48:21 +0100 Subject: [PATCH 198/371] Fix punchtec extruder IDs --- ...uder_left.def.json => punchtec_connect_xl_extruder_0.def.json} | 0 ...der_right.def.json => punchtec_connect_xl_extruder_1.def.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename resources/extruders/{punchtec_connect_xl_extruder_left.def.json => punchtec_connect_xl_extruder_0.def.json} (100%) rename resources/extruders/{punchtec_connect_xl_extruder_right.def.json => punchtec_connect_xl_extruder_1.def.json} (100%) diff --git a/resources/extruders/punchtec_connect_xl_extruder_left.def.json b/resources/extruders/punchtec_connect_xl_extruder_0.def.json similarity index 100% rename from resources/extruders/punchtec_connect_xl_extruder_left.def.json rename to resources/extruders/punchtec_connect_xl_extruder_0.def.json diff --git a/resources/extruders/punchtec_connect_xl_extruder_right.def.json b/resources/extruders/punchtec_connect_xl_extruder_1.def.json similarity index 100% rename from resources/extruders/punchtec_connect_xl_extruder_right.def.json rename to resources/extruders/punchtec_connect_xl_extruder_1.def.json From ab8fda8812684bad30d84128d9dfad041afb448d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 15:21:48 +0100 Subject: [PATCH 199/371] Fix createMachine: evaluate material diameter if it is a function --- cura/Settings/CuraStackBuilder.py | 34 ++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index fc0d4f6f8e..9273b272c1 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -7,6 +7,7 @@ from UM.Logger import Logger from UM.Settings.Interfaces import DefinitionContainerInterface from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.SettingFunction import SettingFunction from UM.Util import parseBool from cura.Machines.VariantManager import VariantType @@ -50,7 +51,6 @@ class CuraStackBuilder: (definition_id, global_variant_name)) global_variant_container = variant_node.getContainer() - # get variant container for extruders extruder_variant_container = application.empty_variant_container # Only look for the preferred variant if this machine has variants @@ -65,21 +65,6 @@ class CuraStackBuilder: (definition_id, extruder_variant_name)) extruder_variant_container = variant_node.getContainer() - # get material container for extruders - material_container = application.empty_material_container - # Only look for the preferred material if this machine has materials - if parseBool(machine_definition.getMetaDataEntry("has_materials", False)): - material_diameter = machine_definition.getProperty("material_diameter", "value") - approximate_material_diameter = str(round(material_diameter)) - root_material_id = machine_definition.getMetaDataEntry("preferred_material") - root_material_id = material_manager.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter) - material_node = material_manager.getMaterialNode(definition_id, extruder_variant_name, material_diameter, root_material_id) - # Sanity check. If you see this error, the related definition files should be fixed. - if not material_node: - raise RuntimeError("Cannot find material with definition [%s], extruder_variant_name [%s], and root_material_id [%s]" % - (definition_id, extruder_variant_name, root_material_id)) - material_container = material_node.getContainer() - generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName()) # Make sure the new name does not collide with any definition or (quality) profile # createUniqueName() only looks at other stacks, but not at definitions or quality profiles @@ -96,6 +81,23 @@ class CuraStackBuilder: ) new_global_stack.setName(generated_name) + # get material container for extruders + material_container = application.empty_material_container + # Only look for the preferred material if this machine has materials + if parseBool(machine_definition.getMetaDataEntry("has_materials", False)): + material_diameter = machine_definition.getProperty("material_diameter", "value") + if isinstance(material_diameter, SettingFunction): + material_diameter = material_diameter(new_global_stack) + approximate_material_diameter = str(round(material_diameter)) + root_material_id = machine_definition.getMetaDataEntry("preferred_material") + root_material_id = material_manager.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter) + material_node = material_manager.getMaterialNode(definition_id, extruder_variant_name, material_diameter, root_material_id) + # Sanity check. If you see this error, the related definition files should be fixed. + if not material_node: + raise RuntimeError("Cannot find material with definition [%s], extruder_variant_name [%s], and root_material_id [%s]" % + (definition_id, extruder_variant_name, root_material_id)) + material_container = material_node.getContainer() + # Create ExtruderStacks extruder_dict = machine_definition.getMetaDataEntry("machine_extruder_trains") From c7499d6e1714a983c1a2072981af6176c76e40f5 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Feb 2018 15:52:02 +0100 Subject: [PATCH 200/371] CURA-4606 CURA-5003 fix saving material metadata when switching material; fix crashing on fallback material on materials without fallback --- cura/Machines/MaterialManager.py | 3 ++- resources/qml/Preferences/MaterialsPage.qml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 54216972a4..ae679a5ee6 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -314,7 +314,8 @@ class MaterialManager(QObject): def getFallbackMaterialId(self, material_type: str) -> str: # For safety if material_type not in self._fallback_materials_map: - raise RuntimeError("Material type [%s] is not in the fallback materials table." % material_type) + Logger.log("w", "The material type [%s] does not have a fallback material" % material_type) + return None fallback_material = self._fallback_materials_map[material_type] if fallback_material: return self.getRootMaterialIDWithoutDiameter(fallback_material["id"]) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 22d906ac62..de7b629f48 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -350,6 +350,7 @@ Item onCurrentIndexChanged: { + forceActiveFocus(); // causes the changed fields to be saved var model = materialsModel.getItem(currentIndex); materialDetailsView.containerId = model.container_id; materialDetailsView.currentMaterialNode = model.container_node; From 32e1015f25cc3f0ae76db086066c937e09cc50d7 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 16:02:41 +0100 Subject: [PATCH 201/371] WIP: Cleanup PrintInformation --- cura/PrintInformation.py | 60 +++++++--------------- cura/Settings/MachineManager.py | 19 +++---- resources/qml/Preferences/MachinesPage.qml | 5 +- 3 files changed, 27 insertions(+), 57 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 9cbd7aec7e..d1ab8506ab 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -1,27 +1,22 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty -from UM.FlameProfiler import pyqtSlot +from typing import Dict +import math +import os.path +import unicodedata +import json +import re # To create abbreviations for printer names. + +from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot from UM.Application import Application from UM.Logger import Logger from UM.Qt.Duration import Duration from UM.Preferences import Preferences from UM.Scene.SceneNode import SceneNode -from UM.Settings.ContainerRegistry import ContainerRegistry -from cura.Scene.CuraSceneNode import CuraSceneNode - -from cura.Settings.ExtruderManager import ExtruderManager -from typing import Dict - -import math -import os.path -import unicodedata -import json -import re #To create abbreviations for printer names. - from UM.i18n import i18nCatalog + catalog = i18nCatalog("cura") ## A class for processing and calculating minimum, current and maximum print time as well as managing the job name @@ -86,9 +81,8 @@ class PrintInformation(QObject): Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) - self._active_material_container = None - self._application.getMachineManager().activeMaterialChanged.connect(self._onActiveMaterialChanged) - self._onActiveMaterialChanged() + self._application.getMachineManager().rootMaterialChanged.connect(self._onActiveMaterialsChanged) + self._onActiveMaterialsChanged() self._material_amounts = [] @@ -203,7 +197,8 @@ class PrintInformation(QObject): self._current_print_time[build_plate_number].setDuration(total_estimated_time) def _calculateInformation(self, build_plate_number): - if Application.getInstance().getGlobalContainerStack() is None: + global_stack = Application.getInstance().getGlobalContainerStack() + if global_stack is None: return # Material amount is sent as an amount of mm^3, so calculate length from that @@ -215,18 +210,13 @@ class PrintInformation(QObject): material_preference_values = json.loads(Preferences.getInstance().getValue("cura/material_settings")) - extruder_stacks = list(ExtruderManager.getInstance().getMachineExtruders(Application.getInstance().getGlobalContainerStack().getId())) + extruder_stacks = global_stack.extruders for index, amount in enumerate(self._material_amounts): ## Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some # list comprehension filtering to solve this for us. - material = None - if extruder_stacks: # Multi extrusion machine - extruder_stack = [extruder for extruder in extruder_stacks if extruder.getMetaDataEntry("position") == str(index)][0] - density = extruder_stack.getMetaDataEntry("properties", {}).get("density", 0) - material = extruder_stack.findContainer({"type": "material"}) - else: # Machine with no extruder stacks - density = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("properties", {}).get("density", 0) - material = Application.getInstance().getGlobalContainerStack().findContainer({"type": "material"}) + extruder_stack = extruder_stacks[str(index)] + density = extruder_stack.getMetaDataEntry("properties", {}).get("density", 0) + material = extruder_stack.findContainer({"type": "material"}) weight = float(amount) * float(density) / 1000 cost = 0 @@ -266,20 +256,6 @@ class PrintInformation(QObject): for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1): self._calculateInformation(build_plate_number) - def _onActiveMaterialChanged(self): - if self._active_material_container: - try: - self._active_material_container.metaDataChanged.disconnect(self._onMaterialMetaDataChanged) - except TypeError: #pyQtSignal gives a TypeError when disconnecting from something that is already disconnected. - pass - - active_material_id = Application.getInstance().getMachineManager().activeMaterialId - active_material_containers = ContainerRegistry.getInstance().findInstanceContainers(id = active_material_id) - - if active_material_containers: - self._active_material_container = active_material_containers[0] - self._active_material_container.metaDataChanged.connect(self._onMaterialMetaDataChanged) - def _onActiveBuildPlateChanged(self): new_active_build_plate = self._multi_build_plate_model.activeBuildPlate if new_active_build_plate != self._active_build_plate: @@ -293,7 +269,7 @@ class PrintInformation(QObject): self.materialNamesChanged.emit() self.currentPrintTimeChanged.emit() - def _onMaterialMetaDataChanged(self, *args, **kwargs): + def _onActiveMaterialsChanged(self, *args, **kwargs): for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1): self._calculateInformation(build_plate_number) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f2446b8017..4013b1e1cd 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -409,25 +409,16 @@ class MachineManager(QObject): def stacksHaveErrors(self) -> bool: return bool(self._stacks_have_errors) - @pyqtProperty(str, notify = activeStackChanged) - def activeUserProfileId(self) -> str: - if self._active_container_stack: - return self._active_container_stack.getTop().getId() - - return "" - @pyqtProperty(str, notify = globalContainerChanged) def activeMachineName(self) -> str: if self._global_container_stack: return self._global_container_stack.getName() - return "" @pyqtProperty(str, notify = globalContainerChanged) def activeMachineId(self) -> str: if self._global_container_stack: return self._global_container_stack.getId() - return "" @pyqtProperty(QObject, notify = globalContainerChanged) @@ -438,16 +429,18 @@ class MachineManager(QObject): def activeStackId(self) -> str: if self._active_container_stack: return self._active_container_stack.getId() - return "" + @pyqtProperty(QObject, notify = activeStackChanged) + def activeStack(self) -> Optional["ExtruderStack"]: + return self._active_container_stack + @pyqtProperty(str, notify=activeMaterialChanged) def activeMaterialId(self) -> str: if self._active_container_stack: material = self._active_container_stack.material if material: return material.getId() - return "" ## Gets a dict with the active materials ids set in all extruder stacks and the global stack @@ -804,9 +797,9 @@ class MachineManager(QObject): @pyqtProperty("QVariant", notify = rootMaterialChanged) def currentRootMaterialId(self): # initial filling the current_root_material_id + self._current_root_material_id = {} for position in self._global_container_stack.extruders: - if position not in self._current_root_material_id: - self._current_root_material_id[position] = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") + self._current_root_material_id[position] = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file") return self._current_root_material_id @pyqtProperty("QVariant", notify = rootMaterialChanged) diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index 889dfa8d5b..49a8d286a8 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -1,13 +1,14 @@ // Copyright (c) 2016 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.1 -import QtQuick.Controls 1.1 +import QtQuick 2.8 +import QtQuick.Controls 1.4 import QtQuick.Window 2.1 import UM 1.2 as UM import Cura 1.0 as Cura + UM.ManagementPage { id: base; From b209badf6868e915a689cd6def63ad3b200eb537 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Feb 2018 16:14:01 +0100 Subject: [PATCH 202/371] CURA-4606 CURA-5003 fix density and diameter in material manager --- resources/qml/Preferences/MaterialsPage.qml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index de7b629f48..e4856a2d4b 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -388,18 +388,9 @@ Item materialProperties.description = currentItem.description ? currentItem.description : ""; materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; - if(currentItem.properties != undefined && currentItem.properties != null) - { - materialProperties.density = currentItem.density ? currentItem.density : 0.0; - materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; - materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; - } - else - { - materialProperties.density = 0.0; - materialProperties.diameter = 0.0; - materialProperties.approximate_diameter = "0"; - } + materialProperties.density = currentItem.density ? currentItem.density : 0.0; + materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; + materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; } Item From a8bd57a9ebc1737869b2957fc21bb0888908f11c Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Feb 2018 16:17:32 +0100 Subject: [PATCH 203/371] CURA-4606 CURA-5003 brands sections in materials management page are now case insensitive --- cura/Machines/Models/MaterialsModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/Models/MaterialsModel.py b/cura/Machines/Models/MaterialsModel.py index 97a1d27a31..6b253790f1 100644 --- a/cura/Machines/Models/MaterialsModel.py +++ b/cura/Machines/Models/MaterialsModel.py @@ -287,5 +287,5 @@ class MaterialsModel(ListModel): material_list.append(item) - material_list = sorted(material_list, key = lambda k: (k["brand"], k["name"])) + material_list = sorted(material_list, key = lambda k: (k["brand"].lower(), k["name"])) self.setItems(material_list) From dba748bd8a4aced9428d870b0684b686c435bd86 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 22 Feb 2018 16:43:50 +0100 Subject: [PATCH 204/371] Add new setting for zig-zaggifying support You can now also use the zigzag type patterns for support. Contributes to issue CURA-4017. --- resources/definitions/fdmprinter.def.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index c8045ebce9..7eba95f2fc 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3572,6 +3572,18 @@ "settable_per_mesh": false, "settable_per_extruder": true }, + "zig_zaggify_support": + { + "label": "Connect Support Lines", + "description": "Connect the ends of the support lines together. Enabling this setting can make your support more sturdy and reduce underextrusion, but it will cost more material.", + "type": "bool", + "default_value": false, + "value": "support_pattern == 'cross'", + "enabled": "support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'cross'", + "limit_to_extruder": "support_infill_extruder_nr", + "settable_per_mesh": false, + "settable_per_extruder": true + }, "support_connect_zigzags": { "label": "Connect Support ZigZags", From fc9b2c35297fa8615bf338ebe16db9dea398d22a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 22 Feb 2018 16:44:39 +0100 Subject: [PATCH 205/371] Limit infill zigzaggify setting to infill extruder Let's give it the same properties as the infill pattern setting. Contributes to issue CURA-4017. --- resources/definitions/fdmprinter.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 7eba95f2fc..4b14500360 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1530,6 +1530,7 @@ "default_value": false, "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'", "enabled": "infill_pattern == 'grid' or infill_pattern == 'triangles' or infill_pattern == 'trihexagon' or infill_pattern == 'cubic' or infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' or infill_pattern == 'cross' or infill_pattern == 'cross_3d'", + "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, "infill_angles": From 94ca4fffe3c89684a1ebe6b54c8354a04903e738 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 22 Feb 2018 16:46:48 +0100 Subject: [PATCH 206/371] CURA-4946 In the gcode just store the default machine definition --- plugins/GCodeWriter/GCodeWriter.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index 7ef8c494ba..225800454f 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -151,12 +151,7 @@ class GCodeWriter(MeshWriter): flat_extruder_quality.addMetaDataEntry("quality_type", extruder.quality.getMetaDataEntry("quality_type", "normal")) # Change the default defintion - default_extruder_definition = "fdmextruder" - if parseBool(stack.getMetaDataEntry("has_machine_quality", "False")): - default_extruder_definition = extruder.getMetaDataEntry("quality_definition") - if not default_extruder_definition: - default_extruder_definition = extruder.definition.getId() - flat_extruder_quality.setMetaDataEntry("definition", default_extruder_definition) + flat_extruder_quality.setMetaDataEntry("definition", default_machine_definition) extruder_serialized = flat_extruder_quality.serialize() data.setdefault("extruder_quality", []).append(extruder_serialized) From d2ffd59431fc8f94cc6bcb7decd17cf85c02f8f8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 16:52:54 +0100 Subject: [PATCH 207/371] Switch to the new quality profile when it is created --- cura/CuraApplication.py | 21 ++++++++++----- cura/Settings/ContainerManager.py | 8 +----- resources/qml/Preferences/ProfilesPage.qml | 30 +++++++++++++++++++++- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a2dc27f483..152ad05f9a 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -240,8 +240,7 @@ class CuraApplication(QtApplication): if kwargs["parsed_command_line"].get("trigger_early_crash", False): assert not "This crash is triggered by the trigger_early_crash command line argument." - # new stuff - self._variant_manager = VariantManager(ContainerRegistry.getInstance()) + self._variant_manager = None self.default_theme = "cura-light" @@ -723,9 +722,6 @@ class CuraApplication(QtApplication): return False return True - def getVariantManager(self): - return self._variant_manager - def preRun(self): # Last check for unknown commandline arguments parser = self.getCommandlineParser() @@ -743,14 +739,15 @@ class CuraApplication(QtApplication): self.preRun() container_registry = ContainerRegistry.getInstance() + self._variant_manager = VariantManager(container_registry) self._variant_manager.initialize() from cura.Machines.MaterialManager import MaterialManager - self._material_manager = MaterialManager(container_registry) + self._material_manager = MaterialManager(container_registry, parent = self) self._material_manager.initialize() from cura.Machines.QualityManager import QualityManager - self._quality_manager = QualityManager(container_registry) + self._quality_manager = QualityManager(container_registry, parent = self) self._quality_manager.initialize() self.getMachineManager() # ensure creation of machine manager @@ -856,6 +853,16 @@ class CuraApplication(QtApplication): self._extruder_manager = ExtruderManager.createExtruderManager() return self._extruder_manager + def getVariantManager(self, *args): + return self._variant_manager + + def getMaterialManager(self, *args): + return self._material_manager + + @pyqtSlot(result = QObject) + def getQualityManager(self, *args): + return self._quality_manager + def getObjectsModel(self, *args): if self._object_manager is None: self._object_manager = ObjectsModel.createObjectsModel() diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index ea82af8d7f..10934e7275 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -333,7 +333,7 @@ class ContainerManager(QObject): self._performMerge(quality_changes, stack.getTop()) - self._machine_manager.activeQualityChanged.emit() + self._machine_manager.activeQualityChangesGroupChanged.emit() return True @@ -394,12 +394,6 @@ class ContainerManager(QObject): self._performMerge(new_changes, user_container) self._container_registry.addContainer(new_changes) - #stack.replaceContainer(stack.getContainerIndex(quality_changes_container), new_changes) - - #self._machine_manager.activeQualityChanged.emit() - - #self._machine_manager.activeQualityGroupChanged.emit() - #self._machine_manager.activeQualityChangesGroupChanged.emit() # # Remove the given quality changes group diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 6a42034846..cdd87058f0 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -171,8 +171,36 @@ Item object: "" onAccepted: { + base.newQualityChangesNameToSwitchTo = newName; // We want to switch to the new profile once it's created Cura.ContainerManager.createQualityChanges(newName); - qualityListView.currentIndex = -1; // TODO: Reset selection. + } + } + + property string newQualityChangesNameToSwitchTo: "" + + // This connection makes sure that we will switch to the new + Connections + { + target: qualitiesModel + onItemsChanged: { + var currentItemName = base.currentItem == null ? "" : base.currentItem.name; + + for (var idx = 0; idx < qualitiesModel.rowCount(); ++idx) { + var item = qualitiesModel.getItem(idx); + if (base.newQualityChangesNameToSwitchTo != "") { + if (item.name == base.newQualityChangesNameToSwitchTo) { + // Switch to the newly created profile if needed + qualityListView.currentIndex = idx; + if (item.is_read_only) { + Cura.MachineManager.setQualityGroup(item.quality_group); + } else { + Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group); + } + base.newQualityChangesNameToSwitchTo = ""; + } + break; + } + } } } From cad6a3bb3dcd0d3b11b359bf586f2e56e983367e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Feb 2018 17:14:23 +0100 Subject: [PATCH 208/371] CURA-4606 CURA-5003 select and activate material after create, duplicate --- cura/Settings/ContainerManager.py | 3 ++- resources/qml/Preferences/MaterialsPage.qml | 28 ++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 10934e7275..fc9253ef1e 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -518,7 +518,7 @@ class ContainerManager(QObject): ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # # \return \type{str} the id of the newly created container. - @pyqtSlot() + @pyqtSlot(result = str) def createMaterial(self): # Ensure all settings are saved. Application.getInstance().saveSettings() @@ -539,6 +539,7 @@ class ContainerManager(QObject): self.duplicateMaterial(material_group.root_material_node, new_base_id = new_id, new_metadata = new_metadata) + return new_id ## Get a list of materials that have the same GUID as the reference material # diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index e4856a2d4b..0e40785ca3 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -77,7 +77,7 @@ Item iconName: "list-add" onClicked: { forceActiveFocus(); - Cura.ContainerManager.createMaterial(); + base.newRootMaterialIdToSwitchTo = Cura.ContainerManager.createMaterial(); } } @@ -88,6 +88,7 @@ Item enabled: base.hasCurrentItem onClicked: { forceActiveFocus(); + base.newRootMaterialIdToSwitchTo = base.currentItem.root_material_id; Cura.ContainerManager.duplicateMaterial(base.currentItem.container_node); } } @@ -126,6 +127,31 @@ Item } } + property string newRootMaterialIdToSwitchTo: "" + + // This connection makes sure that we will switch to the new + Connections + { + target: materialsModel + onItemsChanged: { + var currentItemName = base.currentItem == null ? "" : base.currentItem.name; + var position = Cura.ExtruderManager.activeExtruderIndex; + + if (base.newRootMaterialIdToSwitchTo != "") { + for (var idx = 0; idx < materialsModel.rowCount(); ++idx) { + var item = materialsModel.getItem(idx); + if (item.root_material_id == base.newRootMaterialIdToSwitchTo) { + // Switch to the newly created profile if needed + materialListView.currentIndex = idx; + Cura.MachineManager.setMaterial(position, item.container_node); + base.newRootMaterialIdToSwitchTo = ""; + break; + } + } + } + } + } + MessageDialog { id: confirmRemoveMaterialDialog From 8dfa52f15c1b9119c0f298c93882657c6bdd4a00 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 20:58:41 +0100 Subject: [PATCH 209/371] Fix material menu model extruder binding and initial update --- cura/CuraApplication.py | 2 -- cura/Machines/Models/MaterialsModel.py | 42 +++++++++++++++++++++----- resources/qml/Menus/MaterialMenu.qml | 3 +- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 152ad05f9a..3cb78c01b2 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -955,8 +955,6 @@ class CuraApplication(QtApplication): qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel") - - # TODO: make this singleton? qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") qmlRegisterSingletonType(QualityProfilesModel, "Cura", 1, 0, "QualityProfilesModel", self.getQualityProfileModel) diff --git a/cura/Machines/Models/MaterialsModel.py b/cura/Machines/Models/MaterialsModel.py index 6b253790f1..616903062e 100644 --- a/cura/Machines/Models/MaterialsModel.py +++ b/cura/Machines/Models/MaterialsModel.py @@ -1,13 +1,11 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Any, List, Optional -from PyQt5.QtCore import Qt +from typing import Optional +from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty from UM.Logger import Logger from UM.Qt.ListModel import ListModel -from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel def getAvailableMaterials(extruder_position: Optional[int] = None): @@ -48,6 +46,8 @@ class BaseMaterialsModel(ListModel): ColorRole = Qt.UserRole + 6 ContainerNodeRole = Qt.UserRole + 7 + extruderPositionChanged = pyqtSignal() + def __init__(self, parent = None): super().__init__(parent) @@ -59,6 +59,17 @@ class BaseMaterialsModel(ListModel): self.addRoleName(self.ColorRole, "color_name") self.addRoleName(self.ContainerNodeRole, "container_node") + self._extruder_position = 0 + + def setExtruderPosition(self, position: int): + if self._extruder_position != position: + self._extruder_position = position + self.extruderPositionChanged.emit() + + @pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged) + def extruderPosition(self) -> int: + return self._extruder_positoin + class GenericMaterialsModel(BaseMaterialsModel): @@ -82,7 +93,7 @@ class GenericMaterialsModel(BaseMaterialsModel): self.setItems([]) return - result_dict = getAvailableMaterials() + result_dict = getAvailableMaterials(self._extruder_position) if result_dict is None: self.setItems([]) return @@ -126,12 +137,16 @@ class BrandMaterialsModel(ListModel): NameRole = Qt.UserRole + 1 MaterialsRole = Qt.UserRole + 2 + extruderPositionChanged = pyqtSignal() + def __init__(self, parent = None): super().__init__(parent) self.addRoleName(self.NameRole, "name") self.addRoleName(self.MaterialsRole, "materials") + self._extruder_position = 0 + from cura.CuraApplication import CuraApplication self._machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() @@ -141,13 +156,24 @@ class BrandMaterialsModel(ListModel): extruder_manager.activeExtruderChanged.connect(self._update) material_manager.materialsUpdated.connect(self._update) + self._update() + + def setExtruderPosition(self, position: int): + if self._extruder_position != position: + self._extruder_position = position + self.extruderPositionChanged.emit() + + @pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged) + def extruderPosition(self) -> int: + return self._extruder_position + def _update(self): global_stack = self._machine_manager.activeMachine if global_stack is None: self.setItems([]) return - result_dict = getAvailableMaterials() + result_dict = getAvailableMaterials(self._extruder_position) if result_dict is None: self.setItems([]) return @@ -180,7 +206,7 @@ class BrandMaterialsModel(ListModel): for brand, material_dict in brand_group_dict.items(): brand_item = {"name": brand, - "materials": MaterialsModelGroupedByType(self)} # TODO + "materials": MaterialsModelGroupedByType(self)} material_type_item_list = [] for material_type, material_list in material_dict.items(): diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index ac398356fd..25fa221e9a 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -82,12 +82,13 @@ Menu Cura.GenericMaterialsModel { id: genericMaterialsModel - //Component.onCompleted: populateMenuModels() + extruderPosition: menu.extruderIndex } Cura.BrandMaterialsModel { id: brandModel + extruderPosition: menu.extruderIndex } ExclusiveGroup { id: group } From f51129b1036bbfc460e32b3ade95009c16046892 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 21:47:06 +0100 Subject: [PATCH 210/371] Remove TestTools plugin --- plugins/TestTools/TestTool.py | 38 ----------------------------------- plugins/TestTools/__init__.py | 13 ------------ plugins/TestTools/plugin.json | 7 ------- 3 files changed, 58 deletions(-) delete mode 100644 plugins/TestTools/TestTool.py delete mode 100644 plugins/TestTools/__init__.py delete mode 100644 plugins/TestTools/plugin.json diff --git a/plugins/TestTools/TestTool.py b/plugins/TestTools/TestTool.py deleted file mode 100644 index a8812c21ba..0000000000 --- a/plugins/TestTools/TestTool.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv2 or higher. -from UM.Extension import Extension - -from PyQt5.QtCore import QObject - - -class TestTool(Extension, QObject): - def __init__(self, parent = None): - QObject.__init__(self, parent) - Extension.__init__(self) - - self.addMenuItem("Test material manager", self._testMaterialManager) - self.addMenuItem("Test get quality", self._testGetQuality) - self.addMenuItem("Test get quality changes", self.testGetQualityChanges) - - def _testMaterialManager(self): - print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - from cura.CuraApplication import CuraApplication - CuraApplication.getInstance()._material_manager._test_metadata() - - def _testGetQuality(self): - print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - from cura.CuraApplication import CuraApplication - result_dict = {} - global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack - result = CuraApplication.getInstance()._quality_manager.getQualityGroups(global_stack) - print("!!!!!!!!!!!!!!!!!!!") - - def testGetQualityChanges(self): - print("!!!!!!!!!!!!!!!!!!!") - - from cura.CuraApplication import CuraApplication - result_dict = {} - global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack - result = CuraApplication.getInstance()._quality_manager.getQualityChangesGroups(global_stack) - for name, r in result.items(): - print("!!!!!!!!!! [%s] - %s" % (name, r)) diff --git a/plugins/TestTools/__init__.py b/plugins/TestTools/__init__.py deleted file mode 100644 index 7d41651404..0000000000 --- a/plugins/TestTools/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2016 Ultimaker B.V. -# Cura is released under the terms of the AGPLv3 or higher. - -from . import TestTool - -from UM.i18n import i18nCatalog -catalog = i18nCatalog("cura") - -def getMetaData(): - return {} - -def register(app): - return {"extension": TestTool.TestTool()} diff --git a/plugins/TestTools/plugin.json b/plugins/TestTools/plugin.json deleted file mode 100644 index 846e39bf09..0000000000 --- a/plugins/TestTools/plugin.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "Test Tools", - "author": "Ultimaker", - "version": "1.0", - "description": "Dump the contents of all settings to a HTML file.", - "api": 4 -} \ No newline at end of file From e53048079d362d19efcc4388f262b7844e10d621 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 23:04:59 +0100 Subject: [PATCH 211/371] Remove debugging logs --- cura/Settings/MachineManager.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 4013b1e1cd..6aa137016e 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -989,7 +989,6 @@ class MachineManager(QObject): @pyqtSlot("QVariant") def setGlobalVariant(self, container_node): - Logger.log("d", "---------------- container = [%s]", container_node) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setGlobalVariant(container_node) @@ -998,7 +997,6 @@ class MachineManager(QObject): @pyqtSlot(str, "QVariant") def setMaterial(self, position, container_node): - Logger.log("d", "---------------- container = [%s]", container_node) position = str(position) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): @@ -1007,7 +1005,6 @@ class MachineManager(QObject): @pyqtSlot(str, "QVariant") def setVariantGroup(self, position, container_node): - Logger.log("d", "---------------- container = [%s]", container_node) position = str(position) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): @@ -1017,13 +1014,10 @@ class MachineManager(QObject): @pyqtSlot("QVariant") def setQualityGroup(self, quality_group): - Logger.log("d", "---------------- qg = [%s]", quality_group.name) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setQualityGroup(quality_group) - Logger.log("d", "Quality set!") - # See if we need to show the Discard or Keep changes screen if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: Application.getInstance().discardOrKeepProfileChanges() @@ -1034,11 +1028,9 @@ class MachineManager(QObject): @pyqtSlot("QVariant") def setQualityChangesGroup(self, quality_changes_group): - Logger.log("d", "---------------- qcg = [%s]", quality_changes_group.name) self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setQualityChangesGroup(quality_changes_group) - Logger.log("d", "Quality changes set!") @pyqtProperty("QVariant", fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged) def activeQualityChangesGroup(self): From a3a206c6dd58edd6177b7a171a2674d545278f12 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 23:07:49 +0100 Subject: [PATCH 212/371] Quality groups are QObjects --- cura/Settings/MachineManager.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 6aa137016e..6569fa5cb2 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1012,7 +1012,7 @@ class MachineManager(QObject): self._updateMaterialWithVariant(position) self._updateQualityWithMaterial() - @pyqtSlot("QVariant") + @pyqtSlot(QObject) def setQualityGroup(self, quality_group): self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): @@ -1022,17 +1022,17 @@ class MachineManager(QObject): if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: Application.getInstance().discardOrKeepProfileChanges() - @pyqtProperty("QVariant", fset = setQualityGroup, notify = activeQualityGroupChanged) + @pyqtProperty(QObject, fset = setQualityGroup, notify = activeQualityGroupChanged) def activeQualityGroup(self): return self._current_quality_group - @pyqtSlot("QVariant") + @pyqtSlot(QObject) def setQualityChangesGroup(self, quality_changes_group): self.blurSettings.emit() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setQualityChangesGroup(quality_changes_group) - @pyqtProperty("QVariant", fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged) + @pyqtProperty(QObject, fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged) def activeQualityChangesGroup(self): return self._current_quality_changes_group From dec7ad25e2d0e9decfcd65e0766ea78582ef7436 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 23:08:26 +0100 Subject: [PATCH 213/371] Fix activate newly created custom quality profile --- resources/qml/Preferences/ProfilesPage.qml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index cdd87058f0..224c8f1b3d 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -185,20 +185,16 @@ Item onItemsChanged: { var currentItemName = base.currentItem == null ? "" : base.currentItem.name; - for (var idx = 0; idx < qualitiesModel.rowCount(); ++idx) { - var item = qualitiesModel.getItem(idx); - if (base.newQualityChangesNameToSwitchTo != "") { + if (base.newQualityChangesNameToSwitchTo != "") { + for (var idx = 0; idx < qualitiesModel.rowCount(); ++idx) { + var item = qualitiesModel.getItem(idx); if (item.name == base.newQualityChangesNameToSwitchTo) { // Switch to the newly created profile if needed qualityListView.currentIndex = idx; - if (item.is_read_only) { - Cura.MachineManager.setQualityGroup(item.quality_group); - } else { - Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group); - } + Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group); base.newQualityChangesNameToSwitchTo = ""; + break; } - break; } } } From f487c5b084eb9a857cb3636d8cd2dcfff5d947fb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 22 Feb 2018 23:31:41 +0100 Subject: [PATCH 214/371] Fix profile management page --- cura/Machines/Models/QualitySettingsModel.py | 6 +++- cura/Settings/ContainerManager.py | 17 ++++----- resources/qml/Preferences/ProfilesPage.qml | 37 +++++++++++++------- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index e91897b632..304e2f36f0 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -89,7 +89,11 @@ class QualitySettingsModel(ListModel): else: quality_changes_node = quality_changes_group.nodes_for_extruders.get(self._extruder_position) if quality_changes_node is not None: # it can be None if number of extruders are changed during runtime - quality_containers.insert(0, quality_changes_node.getContainer()) + try: + quality_containers.insert(0, quality_changes_node.getContainer()) + except: + # FIXME: This is to prevent incomplete update of QualityManager + return settings_keys.update(quality_changes_group.getAllKeys()) current_category = "" diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 10934e7275..730800af77 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -404,24 +404,17 @@ class ContainerManager(QObject): for node in quality_changes_group.getAllNodes(): self._container_registry.removeContainer(node.metadata["id"]) - ## Rename a set of quality changes containers. # - # This will search for quality_changes containers matching the supplied name and rename them. - # Note that if the machine specifies that qualities should be filtered by machine and/or material - # only the containers related to the active machine/material are renamed. + # Rename a set of quality changes containers. Returns the new name. # - # \param quality_name The name of the quality changes containers to rename. - # \param new_name The new name of the quality changes. - # - # \return True if successful, False if not. - @pyqtSlot(QObject, str) - def renameQualityChangesGroup(self, quality_changes_group, new_name): + @pyqtSlot(QObject, str, result = str) + def renameQualityChangesGroup(self, quality_changes_group, new_name) -> str: Logger.log("i", "Renaming QualityChangesGroup[%s] to [%s]", quality_changes_group.name, new_name) self._machine_manager.blurSettings.emit() if new_name == quality_changes_group.name: Logger.log("i", "QualityChangesGroup name [%s] unchanged.", quality_changes_group.name) - return + return new_name new_name = self._container_registry.uniqueName(new_name) for node in quality_changes_group.getAllNodes(): @@ -430,6 +423,8 @@ class ContainerManager(QObject): self._machine_manager.activeQualityChanged.emit() self._machine_manager.activeQualityGroupChanged.emit() + return new_name + @pyqtSlot(str, "QVariantMap") def duplicateQualityChanges(self, quality_changes_name, quality_model_item): global_stack = Application.getInstance().getGlobalContainerStack() diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 224c8f1b3d..e5c7e3662a 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -171,32 +171,46 @@ Item object: "" onAccepted: { - base.newQualityChangesNameToSwitchTo = newName; // We want to switch to the new profile once it's created + base.newQualityNameToSelect = newName; // We want to switch to the new profile once it's created + base.toActivateNewQuality = true; Cura.ContainerManager.createQualityChanges(newName); } } - property string newQualityChangesNameToSwitchTo: "" + property string newQualityNameToSelect: "" + property bool toActivateNewQuality: false - // This connection makes sure that we will switch to the new + // This connection makes sure that we will switch to the correct quality after the model gets updated Connections { target: qualitiesModel onItemsChanged: { - var currentItemName = base.currentItem == null ? "" : base.currentItem.name; + var toSelectItemName = base.currentItem == null ? "" : base.currentItem.name; + if (newQualityNameToSelect != "") { + toSelectItemName = newQualityNameToSelect; + } - if (base.newQualityChangesNameToSwitchTo != "") { + var newIdx = -1; // Default to nothing if nothing can be found + if (toSelectItemName != "") { + // Select the required quality name if given for (var idx = 0; idx < qualitiesModel.rowCount(); ++idx) { var item = qualitiesModel.getItem(idx); - if (item.name == base.newQualityChangesNameToSwitchTo) { + if (item.name == toSelectItemName) { // Switch to the newly created profile if needed - qualityListView.currentIndex = idx; - Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group); - base.newQualityChangesNameToSwitchTo = ""; + newIdx = idx; + if (base.toActivateNewQuality) { + // Activate this custom quality if required + Cura.MachineManager.setQualityChangesGroup(item.quality_changes_group); + } break; } } } + qualityListView.currentIndex = newIdx; + + // Reset states + base.newQualityNameToSelect = ""; + base.toActivateNewQuality = false; } } @@ -209,7 +223,6 @@ Item onAccepted: { Cura.ContainerManager.duplicateQualityChanges(newName, base.currentItem); - qualityListView.currentIndex = -1; // TODO: Reset selection. } } @@ -240,8 +253,8 @@ Item object: "" onAccepted: { - Cura.ContainerManager.renameQualityChangesGroup(base.currentItem.quality_changes_group, newName); - qualityListView.currentIndex = -1; // TODO: Reset selection. + var actualNewName = Cura.ContainerManager.renameQualityChangesGroup(base.currentItem.quality_changes_group, newName); + base.newQualityNameToSelect = actualNewName; // Select the new name after the model gets updated } } From ed7dec0caef9d0bdb9d1f4f55a9ee76691314bd6 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 23 Feb 2018 13:05:29 +0100 Subject: [PATCH 215/371] Fix: per model settings validation CURA-4972 --- cura/ObjectsModel.py | 10 +++ plugins/CuraEngineBackend/StartSliceJob.py | 5 ++ .../PerObjectSettingsTool/PerObjectItem.qml | 15 +++- .../PerObjectSettingsPanel.qml | 11 ++- .../PerObjectSettingsTool.py | 69 +++++++++++++++++++ 5 files changed, 108 insertions(+), 2 deletions(-) diff --git a/cura/ObjectsModel.py b/cura/ObjectsModel.py index f02e8b4db5..d7077d3d85 100644 --- a/cura/ObjectsModel.py +++ b/cura/ObjectsModel.py @@ -19,6 +19,8 @@ class ObjectsModel(ListModel): self._build_plate_number = -1 + self._stacks_have_errors = None # type:Optional[bool] + def setActiveBuildPlate(self, nr): self._build_plate_number = nr self._update() @@ -67,3 +69,11 @@ class ObjectsModel(ListModel): @staticmethod def createObjectsModel(): return ObjectsModel() + + ## Check if none of the model's stacks contain error states + # The setting applied for the settings per model + def stacksHaveErrors(self) -> bool: + return bool(self._stacks_have_errors) + + def setStacksHaveErrors(self, value): + self._stacks_have_errors = value \ No newline at end of file diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index b19c387a14..8b7205f8b2 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -136,6 +136,11 @@ class StartSliceJob(Job): self.setResult(StartJobResult.MaterialIncompatible) return + # Validate settings per selectable model + if Application.getInstance().getObjectsModel().stacksHaveErrors(): + self.setResult(StartJobResult.ObjectSettingError) + return + # Don't slice if there is a per object setting with an error value. for node in DepthFirstIterator(self._scene.getRoot()): if node.isSelectable(): diff --git a/plugins/PerObjectSettingsTool/PerObjectItem.qml b/plugins/PerObjectSettingsTool/PerObjectItem.qml index 559ad2bf81..89679b57a2 100644 --- a/plugins/PerObjectSettingsTool/PerObjectItem.qml +++ b/plugins/PerObjectSettingsTool/PerObjectItem.qml @@ -25,7 +25,20 @@ UM.TooltipArea onClicked: { - addedSettingsModel.setVisible(model.key, checked); + // Important first set visible and then subscribe + // otherwise the setting is not yet in list + // For unsubscribe is important first remove the subscription and then + // set as invisible + if(checked) + { + addedSettingsModel.setVisible(model.key, checked); + UM.ActiveTool.triggerAction("subscribeForSettingValidation", model.key) + } + else + { + UM.ActiveTool.triggerAction("unsubscribeForSettingValidation", model.key) + addedSettingsModel.setVisible(model.key, checked); + } UM.ActiveTool.forceUpdate(); } } diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 03a2ce1bf4..c591bc9ae3 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -54,6 +54,12 @@ Item { id: meshTypeSelection style: UM.Theme.styles.combobox onActivated: { + + console.log("!!!!!!!!!!!!!!!!!!!") + + if(model.get(index).type == "anti_overhang_mesh") + console.log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + UM.ActiveTool.setProperty("MeshType", model.get(index).type) } model: ListModel @@ -240,7 +246,10 @@ Item { width: Math.round(UM.Theme.getSize("setting").height / 2) height: UM.Theme.getSize("setting").height - onClicked: addedSettingsModel.setVisible(model.key, false) + onClicked: { + UM.ActiveTool.triggerAction("unsubscribeForSettingValidation", model.key) + addedSettingsModel.setVisible(model.key, false) + } style: ButtonStyle { diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py index d2db5ff420..aa8bb92045 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py @@ -10,7 +10,10 @@ from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator from cura.Settings.ExtruderManager import ExtruderManager from UM.Settings.SettingInstance import SettingInstance from UM.Event import Event +from UM.Settings.Validator import ValidatorState +from UM.Logger import Logger +from PyQt5.QtCore import QTimer ## This tool allows the user to add & change settings per node in the scene. # The settings per object are kept in a ContainerStack, which is linked to a node by decorator. @@ -34,6 +37,13 @@ class PerObjectSettingsTool(Tool): self._onGlobalContainerChanged() Selection.selectionChanged.connect(self._updateEnabled) + self._scene = Application.getInstance().getController().getScene() + + self._error_check_timer = QTimer() + self._error_check_timer.setInterval(250) + self._error_check_timer.setSingleShot(True) + self._error_check_timer.timeout.connect(self._updateStacksHaveErrors) + def event(self, event): super().event(event) @@ -142,3 +152,62 @@ class PerObjectSettingsTool(Tool): else: self._single_model_selected = True Application.getInstance().getController().toolEnabledChanged.emit(self._plugin_id, self._advanced_mode and self._single_model_selected) + + + def _onPropertyChanged(self, key: str, property_name: str) -> None: + if property_name == "validationState": + self._error_check_timer.start() + + def _updateStacksHaveErrors(self) -> None: + self._checkStacksHaveErrors() + + + def _checkStacksHaveErrors(self): + + for node in DepthFirstIterator(self._scene.getRoot()): + + # valdiate only objects which can be selected because the settings per object + # can be applied only for them + if not node.isSelectable(): + continue + + hasErrors = self._checkStackForErrors(node.callDecoration("getStack")) + Application.getInstance().getObjectsModel().setStacksHaveErrors(hasErrors) + + #If any of models has an error then no reason check next objects on the build plate + if hasErrors: + break + + + def _checkStackForErrors(self, stack): + if stack is None: + return False + + for key in stack.getAllKeys(): + validation_state = stack.getProperty(key, "validationState") + if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError): + Logger.log("w", "Setting Per Object %s is not valid.", key) + return True + return False + + def subscribeForSettingValidation(self, setting_name): + selected_object = Selection.getSelectedObject(0) + stack = selected_object.callDecoration("getStack") # Don't try to get the active extruder since it may be None anyway. + if not stack: + return "" + + settings = stack.getTop() + setting_instance = settings.getInstance(setting_name) + if setting_instance: + setting_instance.propertyChanged.connect(self._onPropertyChanged) + + def unsubscribeForSettingValidation(self, setting_name): + selected_object = Selection.getSelectedObject(0) + stack = selected_object.callDecoration("getStack") # Don't try to get the active extruder since it may be None anyway. + if not stack: + return "" + + settings = stack.getTop() + setting_instance = settings.getInstance(setting_name) + if setting_instance: + setting_instance.propertyChanged.disconnect(self._onPropertyChanged) From 3c6e94ea81c1b56ee6efdf0bd28f5df809beede8 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 23 Feb 2018 13:08:15 +0100 Subject: [PATCH 216/371] CURA-4968 Add the support eraser cube to the bottom of the buildplate when the automatic drop models preference is OFF --- plugins/SupportEraser/SupportEraser.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/SupportEraser/SupportEraser.py b/plugins/SupportEraser/SupportEraser.py index 9e2d41014d..4e55702687 100644 --- a/plugins/SupportEraser/SupportEraser.py +++ b/plugins/SupportEraser/SupportEraser.py @@ -1,6 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. - +from UM.Math.Vector import Vector from UM.Tool import Tool from PyQt5.QtCore import Qt, QUrl from UM.Application import Application @@ -41,6 +41,9 @@ class SupportEraser(Tool): mesh = MeshBuilder() mesh.addCube(10,10,10) node.setMeshData(mesh.build()) + # Place the cube in the platform. Do it manually so it works if the "automatic drop models" is OFF + move_vector = Vector(0, 5, 0) + node.setPosition(move_vector) active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate From e3411e9edbeb09ce2d738f7f453d46af839fab38 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 23 Feb 2018 14:52:35 +0100 Subject: [PATCH 217/371] CURA-4972 More zen. --- plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index c591bc9ae3..11e4a9cd0e 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -54,12 +54,6 @@ Item { id: meshTypeSelection style: UM.Theme.styles.combobox onActivated: { - - console.log("!!!!!!!!!!!!!!!!!!!") - - if(model.get(index).type == "anti_overhang_mesh") - console.log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") - UM.ActiveTool.setProperty("MeshType", model.get(index).type) } model: ListModel From d0cc9ba8a6494618e6b1d4ec6e03f059fd4a0995 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 09:42:29 +0100 Subject: [PATCH 218/371] Remove debugging prints --- plugins/PostProcessingPlugin/scripts/PauseAtHeight.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py index 1414593040..3367f85a77 100644 --- a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py +++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py @@ -174,15 +174,12 @@ class PauseAtHeight(Script): if not line.startswith(";LAYER:"): continue current_layer = line[len(";LAYER:"):] - print("----------current_layer:", current_layer) try: current_layer = int(current_layer) except ValueError: #Couldn't cast to int. Something is wrong with this g-code data. - print("----------couldn't cast to int") continue if current_layer < pause_layer: break #Try the next layer. - print("------------hit! Got it!") prevLayer = data[index - 1] prevLines = prevLayer.split("\n") From 5160373580aeb3c236873308e82cc23d6431a2ec Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 09:43:10 +0100 Subject: [PATCH 219/371] Add helper function to write g-code lines Requested during the post-processing script workshop that I was giving. --- plugins/PostProcessingPlugin/Script.py | 52 ++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/plugins/PostProcessingPlugin/Script.py b/plugins/PostProcessingPlugin/Script.py index 7d603ba11f..5d9362c851 100644 --- a/plugins/PostProcessingPlugin/Script.py +++ b/plugins/PostProcessingPlugin/Script.py @@ -105,6 +105,58 @@ class Script: except: return default + ## Convenience function to produce a line of g-code. + # + # You can put in an original g-code line and it'll re-use all the values + # in that line. + # All other keyword parameters are put in the result in g-code's format. + # For instance, if you put ``G=1`` in the parameters, it will output + # ``G1``. If you put ``G=1, X=100`` in the parameters, it will output + # ``G1 X100``. The parameters G and M will always be put first. The + # parameters T and S will be put second (or first if there is no G or M). + # The rest of the parameters will be put in arbitrary order. + # \param line The original g-code line that must be modified. If not + # provided, an entirely new g-code line will be produced. + # \return A line of g-code with the desired parameters filled in. + def putValue(self, line = "", **kwargs): + #Strip the comment. + comment = "" + if ";" in line: + comment = line[line.find(";"):] + line = line[:line.find(";")] #Strip the comment. + + #Parse the original g-code line. + for part in line.split(" "): + if part == "": + continue + parameter = part[0] + if parameter in kwargs: + continue #Skip this one. The user-provided parameter overwrites the one in the line. + value = part[1:] + kwargs[parameter] = value + + #Write the new g-code line. + result = "" + priority_parameters = ["G", "M", "T", "S", "F", "X", "Y", "Z"] #First some parameters that get priority. In order of priority! + for priority_key in priority_parameters: + if priority_key in kwargs: + if result != "": + result += " " + result += priority_key + str(kwargs[priority_key]) + del kwargs[priority_key] + for key, value in kwargs.items(): + if result != "": + result += " " + result += key + str(value) + + #Put the comment back in. + if comment != "": + if result != "": + result += " " + result += ";" + comment + + return result + ## This is called when the script is executed. # It gets a list of g-code strings and needs to return a (modified) list. def execute(self, data): From a7e191071128a0d447fffc7e0532133f7fd4dc83 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 09:54:07 +0100 Subject: [PATCH 220/371] Add E in the priority list This way we're assured of the order in which these parameters occur, even though the firmware doesn't care about it. It's easier to read though. --- plugins/PostProcessingPlugin/Script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/Script.py b/plugins/PostProcessingPlugin/Script.py index 5d9362c851..7f419cd422 100644 --- a/plugins/PostProcessingPlugin/Script.py +++ b/plugins/PostProcessingPlugin/Script.py @@ -137,7 +137,7 @@ class Script: #Write the new g-code line. result = "" - priority_parameters = ["G", "M", "T", "S", "F", "X", "Y", "Z"] #First some parameters that get priority. In order of priority! + priority_parameters = ["G", "M", "T", "S", "F", "X", "Y", "Z", "E"] #First some parameters that get priority. In order of priority! for priority_key in priority_parameters: if priority_key in kwargs: if result != "": From 6934c3f88101da6c5e13603d3bd40c652c198564 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 09:54:42 +0100 Subject: [PATCH 221/371] Use self.putValue to write g-code Mostly as a test of this function. Seems to work. --- .../scripts/PauseAtHeight.py | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py index 3367f85a77..a1159f8051 100644 --- a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py +++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py @@ -204,51 +204,51 @@ class PauseAtHeight(Script): prepend_gcode += ";current layer: {layer}\n".format(layer = current_layer) # Retraction - prepend_gcode += "M83\n" + prepend_gcode += self.putValue(M = 83) + "\n" if retraction_amount != 0: - prepend_gcode += "G1 E-%f F%f\n" % (retraction_amount, retraction_speed * 60) + prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n" # Move the head away - prepend_gcode += "G1 Z%f F300\n" % (current_z + 1) - prepend_gcode += "G1 X%f Y%f F9000\n" % (park_x, park_y) + prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n" + prepend_gcode += self.putValue(G = 1, X = park_x, Y = park_y, F = 9000) + "\n" if current_z < 15: - prepend_gcode += "G1 Z15 F300\n" + prepend_gcode += self.putValue(G = 1, Z = 15, F = 300) + "\n" # Disable the E steppers - prepend_gcode += "M84 E0\n" + prepend_gcode += self.putValue(M = 84, E = 0) + "\n" # Set extruder standby temperature - prepend_gcode += "M104 S%i; standby temperature\n" % (standby_temperature) + prepend_gcode += self.putValue(M = 104, S = standby_temperature) + "; standby temperature\n" # Wait till the user continues printing - prepend_gcode += "M0 ;Do the actual pause\n" + prepend_gcode += self.putValue(M = 0) + ";Do the actual pause\n" # Set extruder resume temperature - prepend_gcode += "M109 S%i; resume temperature\n" % (resume_temperature) + prepend_gcode += self.putValue(M = 109, S = resume_temperature) + "; resume temperature\n" # Push the filament back, if retraction_amount != 0: - prepend_gcode += "G1 E%f F%f\n" % (retraction_amount, retraction_speed * 60) + prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n" # Optionally extrude material if extrude_amount != 0: - prepend_gcode += "G1 E%f F%f\n" % (extrude_amount, extrude_speed * 60) + prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = extrude_speed * 60) + "\n" # and retract again, the properly primes the nozzle # when changing filament. if retraction_amount != 0: - prepend_gcode += "G1 E-%f F%f\n" % (retraction_amount, retraction_speed * 60) + prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n" # Move the head back - prepend_gcode += "G1 Z%f F300\n" % (current_z + 1) - prepend_gcode += "G1 X%f Y%f F9000\n" % (x, y) + prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n" + prepend_gcode += self.putValue(G = 1, X = x, Y = y, F = 9000) + "\n" if retraction_amount != 0: - prepend_gcode += "G1 E%f F%f\n" % (retraction_amount, retraction_speed * 60) - prepend_gcode += "G1 F9000\n" - prepend_gcode += "M82\n" + prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n" + prepend_gcode += self.putValue(G = 1, F = 9000) + "\n" + prepend_gcode += self.putValue(M = 82) + "\n" # reset extrude value to pre pause value - prepend_gcode += "G92 E%f\n" % (current_e) + prepend_gcode += self.putValue(G = 92, E = current_e) + "\n" layer = prepend_gcode + layer From 2df9802ba5c49f7666fcfcb64b9c1ba0760d4f88 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 26 Feb 2018 09:57:16 +0100 Subject: [PATCH 222/371] CURA-4606 CURA-5010 fix print information crashing on printer switch --- cura/PrintInformation.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index d1ab8506ab..e7db889b8f 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -75,6 +75,7 @@ class PrintInformation(QObject): self._multi_build_plate_model = self._application.getMultiBuildPlateModel() self._application.globalContainerStackChanged.connect(self._updateJobName) + self._application.globalContainerStackChanged.connect(self.setToZeroPrintInformation) self._application.fileLoaded.connect(self.setBaseName) self._application.workspaceLoaded.connect(self.setProjectName) self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveBuildPlateChanged) @@ -211,7 +212,12 @@ class PrintInformation(QObject): material_preference_values = json.loads(Preferences.getInstance().getValue("cura/material_settings")) extruder_stacks = global_stack.extruders - for index, amount in enumerate(self._material_amounts): + #for index, amount in enumerate(self._material_amounts): + for extruder_key in global_stack.extruders.keys(): + index = int(extruder_key) + if index >= len(self._material_amounts): # Right now the _material_amounts is a list, where the index is the extruder number + continue + amount = self._material_amounts[index] ## Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some # list comprehension filtering to solve this for us. extruder_stack = extruder_stacks[str(index)] @@ -375,7 +381,9 @@ class PrintInformation(QObject): return result # Simulate message with zero time duration - def setToZeroPrintInformation(self, build_plate): + def setToZeroPrintInformation(self, build_plate = None): + if build_plate is None: + build_plate = self._active_build_plate # Construct the 0-time message temp_message = {} From 9ddc6a52b716b5dc5e373d11d1a44a17bfaea500 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 26 Feb 2018 11:40:21 +0100 Subject: [PATCH 223/371] Refactor fix for extruder stack material diameters and nozzle sizes --- cura/Settings/ExtruderManager.py | 71 ++++++++++++++++++++++++++++---- cura/Settings/ExtruderStack.py | 69 ------------------------------- 2 files changed, 62 insertions(+), 78 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index fa045e9496..178cf31e3f 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -12,6 +12,7 @@ from UM.Scene.Selection import Selection from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator from UM.Settings.ContainerRegistry import ContainerRegistry # Finding containers by ID. from UM.Settings.SettingFunction import SettingFunction +from UM.Settings.SettingInstance import SettingInstance from UM.Settings.ContainerStack import ContainerStack from UM.Settings.PropertyEvaluationContext import PropertyEvaluationContext from typing import Optional, List, TYPE_CHECKING, Union @@ -397,16 +398,67 @@ class ExtruderManager(QObject): extruder_train.setNextStack(global_stack) extruders_changed = True - # FIX: We have to remove those settings here because we know that those values have been copied to all - # the extruders at this point. - for key in ("material_diameter", "machine_nozzle_size"): - if global_stack.definitionChanges.hasProperty(key, "value"): - global_stack.definitionChanges.removeInstance(key, postpone_emit = True) - + self._fixMaterialDiameterAndNozzleSize(global_stack, extruder_trains) if extruders_changed: self.extrudersChanged.emit(global_stack_id) self.setActiveExtruderIndex(0) + def _fixMaterialDiameterAndNozzleSize(self, global_stack, extruder_stack_list): + keys_to_copy = ["material_diameter", "machine_nozzle_size"] # these will be copied over to all extruders + + extruder_positions_to_update = set() + for extruder_stack in extruder_stack_list: + for key in keys_to_copy: + # Only copy the value when this extruder doesn't have the value. + if extruder_stack.definitionChanges.hasProperty(key, "value"): + continue + + # + # We cannot add a setting definition of "material_diameter" into the extruder's definition at runtime + # because all other machines which uses "fdmextruder" as the extruder definition will be affected. + # + # The problem is that single extrusion machines have their default material diameter defined in the global + # definitions. Now we automatically create an extruder stack for those machines using "fdmextruder" + # definition, which doesn't have the specific "material_diameter" and "machine_nozzle_size" defined for + # each machine. This results in wrong values which can be found in the MachineSettings dialog. + # + # To solve this, we put "material_diameter" back into the "fdmextruder" definition because modifying it in + # the extruder definition will affect all machines which uses the "fdmextruder" definition. Moreover, now + # we also check the value defined in the machine definition. If present, the value defined in the global + # stack's definition changes container will be copied. Otherwise, we will check if the default values in the + # machine definition and the extruder definition are the same, and if not, the default value in the machine + # definition will be copied to the extruder stack's definition changes. + # + setting_value_in_global_def_changes = global_stack.definitionChanges.getProperty(key, "value") + setting_value_in_global_def = global_stack.definition.getProperty(key, "value") + setting_value = setting_value_in_global_def + if setting_value_in_global_def_changes is not None: + setting_value = setting_value_in_global_def_changes + if setting_value == extruder_stack.definition.getProperty(key, "value"): + continue + + setting_definition = global_stack.getSettingDefinition(key) + new_instance = SettingInstance(setting_definition, extruder_stack.definitionChanges) + new_instance.setProperty("value", setting_value) + new_instance.resetState() # Ensure that the state is not seen as a user state. + extruder_stack.definitionChanges.addInstance(new_instance) + extruder_stack.definitionChanges.setDirty(True) + + # Make sure the material diameter is up to date for the extruder stack. + if key == "material_diameter": + position = int(extruder_stack.getMetaDataEntry("position")) + extruder_positions_to_update.add(position) + + # We have to remove those settings here because we know that those values have been copied to all + # the extruders at this point. + for key in keys_to_copy: + if global_stack.definitionChanges.hasProperty(key, "value"): + global_stack.definitionChanges.removeInstance(key, postpone_emit = True) + + # Update material diameter for extruders + for position in extruder_positions_to_update: + self.updateMaterialForDiameter(position, global_stack = global_stack) + ## Get all extruder values for a certain setting. # # This is exposed to SettingFunction so it can be used in value functions. @@ -492,10 +544,11 @@ class ExtruderManager(QObject): return ExtruderManager.getExtruderValues(key) ## Updates the material container to a material that matches the material diameter set for the printer - def updateMaterialForDiameter(self, extruder_position: int): - global_stack = Application.getInstance().getGlobalContainerStack() + def updateMaterialForDiameter(self, extruder_position: int, global_stack = None): if not global_stack: - return + global_stack = Application.getInstance().getGlobalContainerStack() + if not global_stack: + return if not global_stack.getMetaDataEntry("has_materials", False): return diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index 5a3ac85d75..870de62c98 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -41,75 +41,6 @@ class ExtruderStack(CuraContainerStack): # For backward compatibility: Register the extruder with the Extruder Manager ExtruderManager.getInstance().registerExtruder(self, stack.id) - # Now each machine will have at least one extruder stack. If this is the first extruder, the extruder-specific - # settings such as nozzle size and material diameter should be moved from the machine's definition_changes to - # the this extruder's definition_changes. - # - # We do this here because it is tooooo expansive to do it in the version upgrade: During the version upgrade, - # when we are upgrading a definition_changes container file, there is NO guarantee that other files such as - # machine an extruder stack files are upgraded before this, so we cannot read those files assuming they are in - # the latest format. - # - # MORE: - # For single-extrusion machines, nozzle size is saved in the global stack, so the nozzle size value should be - # carried to the first extruder. - # For material diameter, it was supposed to be applied to all extruders, so its value should be copied to all - # extruders. - - keys_to_copy = ["material_diameter", "machine_nozzle_size"] # these will be copied over to all extruders - - for key in keys_to_copy: - # Only copy the value when this extruder doesn't have the value. - if self.definitionChanges.hasProperty(key, "value"): - continue - - # WARNING: this might be very dangerous and should be refactored ASAP! - # - # We cannot add a setting definition of "material_diameter" into the extruder's definition at runtime - # because all other machines which uses "fdmextruder" as the extruder definition will be affected. - # - # The problem is that single extrusion machines have their default material diameter defined in the global - # definitions. Now we automatically create an extruder stack for those machines using "fdmextruder" - # definition, which doesn't have the specific "material_diameter" and "machine_nozzle_size" defined for - # each machine. This results in wrong values which can be found in the MachineSettings dialog. - # - # To solve this, we put "material_diameter" back into the "fdmextruder" definition because modifying it in - # the extruder definition will affect all machines which uses the "fdmextruder" definition. Moreover, now - # we also check the value defined in the machine definition. If present, the value defined in the global - # stack's definition changes container will be copied. Otherwise, we will check if the default values in the - # machine definition and the extruder definition are the same, and if not, the default value in the machine - # definition will be copied to the extruder stack's definition changes. - # - setting_value_in_global_def_changes = stack.definitionChanges.getProperty(key, "value") - setting_value_in_global_def = stack.definition.getProperty(key, "value") - setting_value = setting_value_in_global_def - if setting_value_in_global_def_changes is not None: - setting_value = setting_value_in_global_def_changes - if setting_value == self.definition.getProperty(key, "value"): - continue - - setting_definition = stack.getSettingDefinition(key) - new_instance = SettingInstance(setting_definition, self.definitionChanges) - new_instance.setProperty("value", setting_value) - new_instance.resetState() # Ensure that the state is not seen as a user state. - self.definitionChanges.addInstance(new_instance) - self.definitionChanges.setDirty(True) - - # Make sure the material diameter is up to date for the extruder stack. - if key == "material_diameter": - from cura.CuraApplication import CuraApplication - machine_manager = CuraApplication.getInstance().getMachineManager() - position = self.getMetaDataEntry("position", "0") - func = lambda p = position: CuraApplication.getInstance().getExtruderManager().updateMaterialForDiameter(p) - machine_manager.machine_extruder_material_update_dict[stack.getId()].append(func) - - # NOTE: We cannot remove the setting from the global stack's definition changes container because for - # material diameter, it needs to be applied to all extruders, but here we don't know how many extruders - # a machine actually has and how many extruders has already been loaded for that machine, so we have to - # keep this setting for any remaining extruders that haven't been loaded yet. - # - # Those settings will be removed in ExtruderManager which knows all those info. - @override(ContainerStack) def getNextStack(self) -> Optional["GlobalStack"]: return super().getNextStack() From cd0846fad25be6af91736c1e3032365f44c4f60c Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 26 Feb 2018 11:49:51 +0100 Subject: [PATCH 224/371] PostProcessing plugi, script Pause at Height redo layers gives incorrect E-values CURA-4670 --- .../PostProcessingPlugin/scripts/PauseAtHeight.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py index 1414593040..10de2fa318 100644 --- a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py +++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py @@ -187,6 +187,9 @@ class PauseAtHeight(Script): prevLayer = data[index - 1] prevLines = prevLayer.split("\n") current_e = 0. + + # Access last layer, browse it backwards to find + # last extruder absolute position for prevLine in reversed(prevLines): current_e = self.getValue(prevLine, "E", -1) if current_e >= 0: @@ -197,6 +200,18 @@ class PauseAtHeight(Script): prevLayer = data[index - i] layer = prevLayer + layer + # Get extruder's absolute position at the + # begining of the first layer redone + # see https://github.com/nallath/PostProcessingPlugin/issues/55 + if i == redo_layers: + prevLines = prevLayer.split("\n") + for line in prevLines: + new_e = self.getValue(line, 'E', current_e) + + if new_e != current_e: + current_e = new_e + break + prepend_gcode = ";TYPE:CUSTOM\n" prepend_gcode += ";added code by post processing\n" prepend_gcode += ";script: PauseAtHeight.py\n" From f5b3775b7c4c7afabc90d0b8bdecfec22ebf908d Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 26 Feb 2018 14:01:43 +0100 Subject: [PATCH 225/371] CURA-4966 When loading a project, check the quality in all the extruder stacks and replace with the global quality if they don't match. --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 33 ++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 8291ca3b52..35c56a2a14 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -775,9 +775,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Ensure a unique ID and name stack.setMetaDataEntry("id", new_id) - # Keep same quality between extruders and global stack - stack.quality = global_stack.quality - self._container_registry.addContainer(stack) extruder_stacks_added.append(stack) containers_added.append(stack) @@ -830,7 +827,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): return ## In case there is a new machine and once the extruders are created, the global stack is added to the registry, - # otherwise the accContainers function in CuraContainerRegistry will create an extruder stack and then creating + # otherwise the addContainers function in CuraContainerRegistry will create an extruder stack and then creating # useless files if self._resolve_strategies["machine"] == "new": self._container_registry.addContainer(global_stack) @@ -940,6 +937,34 @@ class ThreeMFWorkspaceReader(WorkspaceReader): extruder_stack.quality = new_quality_container global_stack.quality = new_quality_container + # Now we are checking if the quality in the extruder stacks is the same as in the global. In other case, + # the quality is set to be the same. + definition_id = global_stack.definition.getId() + definition_id = global_stack.definition.getMetaDataEntry("quality_definition", definition_id) + if not parseBool(global_stack.getMetaDataEntry("has_machine_quality", "False")): + definition_id = "fdmprinter" + + for extruder_stack in extruder_stacks_in_use: + + # If the quality is different in the stacks, then the quality in the global stack is trusted + if extruder_stack.quality.getMetaDataEntry("quality_type", None) != global_stack.quality.getMetaDataEntry("quality_type", None): + search_criteria = {"id": global_stack.quality.getId(), + "type": "quality", + "definition": definition_id} + if global_stack.getMetaDataEntry("has_machine_materials") and extruder_stack.material.getId() not in ("empty", "empty_material"): + search_criteria["material"] = extruder_stack.material.getId() + containers = self._container_registry.findInstanceContainers(**search_criteria) + if containers: + extruder_stack.quality = containers[0] + extruder_stack.qualityChanges = empty_quality_changes_container + else: + Logger.log("e", "Cannot find a suitable quality for extruder [%s].", extruder_stack.getId()) + + quality_has_been_changed = True + + else: + Logger.log("i", "The quality is the same for the global and the extruder stack [%s]", global_stack.quality.getId()) + # Replacing the old containers if resolve is "new". # When resolve is "new", some containers will get renamed, so all the other containers that reference to those # MUST get updated too. From 91d271b9931c5a927c64a1f9f5e8e7fc83b0c6d6 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 14:47:19 +0100 Subject: [PATCH 226/371] Reset UM2+ PP profiles retraction minimum travel These settings were set to be lower than the line width. I'm resetting them so that they will again be 2 times the line width. Otherwise we'll get retractions between every skin line which is really bad for PP. Fixes #3171. --- resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg | 1 - resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg | 1 - resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg | 1 - resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg | 1 - 4 files changed, 4 deletions(-) diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg index 203db9883e..ef808a81d0 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.6_draft.inst.cfg @@ -46,7 +46,6 @@ retraction_extrusion_window = 1 retraction_hop = 0.15 retraction_hop_enabled = True retraction_hop_only_when_collides = True -retraction_min_travel = 0.5 retraction_prime_speed = 15 skin_overlap = 10 skirt_brim_line_width = 0.6 diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg index 64dfbc9281..c3da178405 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.6_fast.inst.cfg @@ -46,7 +46,6 @@ retraction_extrusion_window = 1 retraction_hop = 0.15 retraction_hop_enabled = True retraction_hop_only_when_collides = True -retraction_min_travel = 0.5 retraction_prime_speed = 15 skin_overlap = 10 skirt_brim_line_width = 0.6 diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg index f6d56242dd..063097845e 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.8_draft.inst.cfg @@ -46,7 +46,6 @@ retraction_extrusion_window = 1 retraction_hop = 0.15 retraction_hop_enabled = True retraction_hop_only_when_collides = True -retraction_min_travel = 0.5 retraction_prime_speed = 15 skin_overlap = 10 skirt_brim_line_width = 0.8 diff --git a/resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg b/resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg index ecb3e3da4a..5014f9d66d 100644 --- a/resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_pp_0.8_verydraft.inst.cfg @@ -46,7 +46,6 @@ retraction_extrusion_window = 1 retraction_hop = 0.15 retraction_hop_enabled = True retraction_hop_only_when_collides = True -retraction_min_travel = 0.5 retraction_prime_speed = 15 skin_overlap = 10 skirt_brim_line_width = 0.8 From cde67ab84c932b537b5839677d632077409e288a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 14:48:06 +0100 Subject: [PATCH 227/371] Add warning for low Retraction Min Travel Because if you set it to be too close to the line width, you'll get retractions between every skin line. --- resources/definitions/fdmprinter.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 4b14500360..d282eeae0a 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2137,6 +2137,7 @@ "default_value": 1.5, "value": "line_width * 2", "minimum_value": "0", + "minimum_value_warning": "line_width * 1.5", "maximum_value_warning": "10", "enabled": "retraction_enable", "settable_per_mesh": false, From 94bce5369116d9d261d2e79690348e63e677d0d8 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 15:47:07 +0100 Subject: [PATCH 228/371] Update headers --- resources/i18n/zh_TW/cura.po | 10 +++++----- resources/i18n/zh_TW/fdmprinter.def.json.po | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/i18n/zh_TW/cura.po b/resources/i18n/zh_TW/cura.po index 7d4cca2681..0a1c5e9294 100644 --- a/resources/i18n/zh_TW/cura.po +++ b/resources/i18n/zh_TW/cura.po @@ -1,16 +1,16 @@ # Cura -# Copyright (C) 2017 Ultimaker +# Copyright (C) 2018 Ultimaker # This file is distributed under the same license as the Cura package. -# Ruben Dulek , 2017. +# Ruben Dulek , 2018. # msgid "" msgstr "" -"Project-Id-Version: Cura 3.1\n" +"Project-Id-Version: Cura 3.2\n" "Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n" -"POT-Creation-Date: 2017-08-02 16:53+0000\n" +"POT-Creation-Date: 2018-01-29 16:53+0000\n" "PO-Revision-Date: 2018-02-04 11:18+0800\n" "Last-Translator: Zhang Heh Ji \n" -"Language-Team: TEAM\n" +"Language-Team: Zhang Heh Ji \n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" diff --git a/resources/i18n/zh_TW/fdmprinter.def.json.po b/resources/i18n/zh_TW/fdmprinter.def.json.po index d12b05d56a..a20c882f5d 100644 --- a/resources/i18n/zh_TW/fdmprinter.def.json.po +++ b/resources/i18n/zh_TW/fdmprinter.def.json.po @@ -1,16 +1,16 @@ # Cura JSON setting files -# Copyright (C) 2017 Ultimaker +# Copyright (C) 2018 Ultimaker # This file is distributed under the same license as the Cura package. -# Ruben Dulek , 2017. +# Ruben Dulek , 2018. # msgid "" msgstr "" -"Project-Id-Version: Cura 3.1\n" +"Project-Id-Version: Cura 3.2\n" "Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n" -"POT-Creation-Date: 2017-08-02 16:53+0000\n" +"POT-Creation-Date: 2018-01-29 16:53+0000\n" "PO-Revision-Date: 2018-02-01 20:58+0800\n" "Last-Translator: Zhang Heh Ji \n" -"Language-Team: TEAM\n" +"Language-Team: Zhang Heh Ji \n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" From c16214e0f36c9bb80811c1ed19d458a0bef5b14c Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 15:48:04 +0100 Subject: [PATCH 229/371] Traditional Chinese is complete again At least, complete for 3.2. --- resources/qml/Preferences/GeneralPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 4c964540f0..1c7b2bcf7c 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -163,7 +163,7 @@ UM.PreferencesPage append({ text: "Русский", code: "ru_RU" }) append({ text: "Türkçe", code: "tr_TR" }) append({ text: "简体中文", code: "zh_CN" }) - //Traditional Chinese is disabled for being incomplete: append({ text: "正體字", code: "zh_TW" }) + append({ text: "正體字", code: "zh_TW" }) var date_object = new Date(); if (date_object.getUTCMonth() == 8 && date_object.getUTCDate() == 19) //Only add Pirate on the 19th of September. From b5d1e5be36e208dceece86fe94725bf9588049e8 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Feb 2018 16:20:49 +0100 Subject: [PATCH 230/371] Remove 'None' default for quality_type It has no semantic meaning to specify that here. The behaviour of this commit should be the same since 'None' is the default value for that parameter. Contributes to issue CURA-4966. --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 35c56a2a14..08234aa8be 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -947,7 +947,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): for extruder_stack in extruder_stacks_in_use: # If the quality is different in the stacks, then the quality in the global stack is trusted - if extruder_stack.quality.getMetaDataEntry("quality_type", None) != global_stack.quality.getMetaDataEntry("quality_type", None): + if extruder_stack.quality.getMetaDataEntry("quality_type") != global_stack.quality.getMetaDataEntry("quality_type"): search_criteria = {"id": global_stack.quality.getId(), "type": "quality", "definition": definition_id} From c23827cfa17c08f1e674c4ec49f36aa451cb3bbd Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 26 Feb 2018 16:33:25 +0100 Subject: [PATCH 231/371] CURA-4606 CURA-5003 activate duplicated material and always switch to correct material after some material change --- cura/Settings/ContainerManager.py | 3 +- resources/qml/Preferences/MaterialsPage.qml | 56 ++++++++++++++------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 3a352d370c..e1364581f6 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -458,7 +458,7 @@ class ContainerManager(QObject): ## Create a duplicate of a material, which has the same GUID and base_file metadata # # \return \type{str} the id of the newly created container. - @pyqtSlot("QVariant") + @pyqtSlot("QVariant", result = str) def duplicateMaterial(self, material_node, new_base_id = None, new_metadata = None): root_material_id = material_node.metadata["base_file"] @@ -509,6 +509,7 @@ class ContainerManager(QObject): for container_to_add in new_containers: container_to_add.setDirty(True) ContainerRegistry.getInstance().addContainer(container_to_add) + return new_base_id ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 0e40785ca3..671b5c6b9b 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -37,7 +37,7 @@ Item property var hasCurrentItem: materialListView.currentItem != null - property var currentItem: { + property var currentItem: { // is soon to be overwritten var current_index = materialListView.currentIndex; return materialsModel.getItem(current_index); } @@ -78,6 +78,7 @@ Item onClicked: { forceActiveFocus(); base.newRootMaterialIdToSwitchTo = Cura.ContainerManager.createMaterial(); + base.toActivateNewMaterial = true; } } @@ -88,8 +89,8 @@ Item enabled: base.hasCurrentItem onClicked: { forceActiveFocus(); - base.newRootMaterialIdToSwitchTo = base.currentItem.root_material_id; - Cura.ContainerManager.duplicateMaterial(base.currentItem.container_node); + base.newRootMaterialIdToSwitchTo = Cura.ContainerManager.duplicateMaterial(base.currentItem.container_node); + base.toActivateNewMaterial = true; } } @@ -128,27 +129,43 @@ Item } property string newRootMaterialIdToSwitchTo: "" + property bool toActivateNewMaterial: false // This connection makes sure that we will switch to the new Connections { target: materialsModel onItemsChanged: { - var currentItemName = base.currentItem == null ? "" : base.currentItem.name; + var currentItemId = base.currentItem == null ? "" : base.currentItem.root_material_id; var position = Cura.ExtruderManager.activeExtruderIndex; - if (base.newRootMaterialIdToSwitchTo != "") { - for (var idx = 0; idx < materialsModel.rowCount(); ++idx) { - var item = materialsModel.getItem(idx); - if (item.root_material_id == base.newRootMaterialIdToSwitchTo) { - // Switch to the newly created profile if needed - materialListView.currentIndex = idx; + // try to pick the currently selected item; it may have been moved + if (base.newRootMaterialIdToSwitchTo == "") { + base.newRootMaterialIdToSwitchTo = currentItemId; + } + + for (var idx = 0; idx < materialsModel.rowCount(); ++idx) { + var item = materialsModel.getItem(idx); + if (item.root_material_id == base.newRootMaterialIdToSwitchTo) { + // Switch to the newly created profile if needed + materialListView.currentIndex = idx; + materialListView.activateDetailsWithIndex(materialListView.currentIndex); + if (base.toActivateNewMaterial) { Cura.MachineManager.setMaterial(position, item.container_node); - base.newRootMaterialIdToSwitchTo = ""; - break; } + base.newRootMaterialIdToSwitchTo = ""; + base.toActivateNewMaterial = false; + return } } + + materialListView.currentIndex = 0; + materialListView.activateDetailsWithIndex(materialListView.currentIndex); + if (base.toActivateNewMaterial) { + Cura.MachineManager.setMaterial(position, materialsModel.getItem(0).container_node); + } + base.newRootMaterialIdToSwitchTo = ""; + base.toActivateNewMaterial = false; } } @@ -165,8 +182,6 @@ Item onYes: { Cura.ContainerManager.removeMaterial(base.currentItem.container_node); - // reset current item to the first if available - materialListView.currentIndex = 0; } } @@ -374,15 +389,20 @@ Item } } - onCurrentIndexChanged: - { - forceActiveFocus(); // causes the changed fields to be saved - var model = materialsModel.getItem(currentIndex); + function activateDetailsWithIndex(index) { + var model = materialsModel.getItem(index); + base.currentItem = model; materialDetailsView.containerId = model.container_id; materialDetailsView.currentMaterialNode = model.container_node; detailsPanel.updateMaterialPropertiesObject(); } + + onCurrentIndexChanged: + { + forceActiveFocus(); // causes the changed fields to be saved + activateDetailsWithIndex(currentIndex); + } } } From 12c51f40668f818dbd070c35286ba4f4d2db7129 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 26 Feb 2018 17:05:55 +0100 Subject: [PATCH 232/371] Use setActiveMachine() in project loading --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index d584a0efd6..1c1d2f30a4 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -1057,7 +1057,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader): CuraApplication.getInstance().getMachineManager().activeQualityChanged.emit() # Actually change the active machine. - Application.getInstance().setGlobalContainerStack(global_stack) + machine_manager = Application.getInstance().getMachineManager() + machine_manager.setActiveMachine(global_stack.getId()) # Notify everything/one that is to notify about changes. global_stack.containersChanged.emit(global_stack.getTop()) From 0b8678d2ae29cb58b3f16a6df7efd4fe2cf28138 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 26 Feb 2018 19:33:16 +0100 Subject: [PATCH 233/371] Explicitly create MachineManager --- cura/CuraApplication.py | 4 ++-- cura/Settings/MachineManager.py | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 3cb78c01b2..eb09f1ed82 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -750,7 +750,7 @@ class CuraApplication(QtApplication): self._quality_manager = QualityManager(container_registry, parent = self) self._quality_manager.initialize() - self.getMachineManager() # ensure creation of machine manager + self._machine_manager = MachineManager(self) # Check if we should run as single instance or not self._setUpSingleInstanceServer() @@ -845,7 +845,7 @@ class CuraApplication(QtApplication): def getMachineManager(self, *args) -> MachineManager: if self._machine_manager is None: - self._machine_manager = MachineManager.createMachineManager() + self._machine_manager = MachineManager(self) return self._machine_manager def getExtruderManager(self, *args): diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 6569fa5cb2..b75f805d73 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -760,10 +760,6 @@ class MachineManager(QObject): # Signal that the global stack has changed Application.getInstance().globalContainerStackChanged.emit() - @staticmethod - def createMachineManager(): - return MachineManager() - @pyqtSlot(int, result = QObject) def getExtruder(self, position: int): extruder = None From a74f84fce7fbbbbde957fb7716ecc2e57ca28bfa Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 26 Feb 2018 19:35:56 +0100 Subject: [PATCH 234/371] Add comment why sorting the material group map --- cura/Machines/MaterialManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index ae679a5ee6..cbfc822303 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -90,6 +90,7 @@ class MaterialManager(QObject): else: new_node = MaterialNode(material_metadata) group.derived_material_node_list.append(new_node) + # Order this map alphabetically so it's easier to navigate in a debugger self._material_group_map = OrderedDict(sorted(self._material_group_map.items(), key = lambda x: x[0])) # Map #1.5 From d9d2cc90693ce2cfc232f2906ce0a9c7578fd9a2 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 26 Feb 2018 19:37:29 +0100 Subject: [PATCH 235/371] Remove unused code in PrintInformation --- cura/PrintInformation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index e7db889b8f..279e7e0c03 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -212,7 +212,6 @@ class PrintInformation(QObject): material_preference_values = json.loads(Preferences.getInstance().getValue("cura/material_settings")) extruder_stacks = global_stack.extruders - #for index, amount in enumerate(self._material_amounts): for extruder_key in global_stack.extruders.keys(): index = int(extruder_key) if index >= len(self._material_amounts): # Right now the _material_amounts is a list, where the index is the extruder number From 17d3be03b4bc8d0ea6558c0127180a96fc17de81 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 26 Feb 2018 19:38:44 +0100 Subject: [PATCH 236/371] Use getMaterialManager() in ContainerManager --- cura/Settings/ContainerManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index e1364581f6..9701a7b406 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -45,7 +45,7 @@ class ContainerManager(QObject): self._application = Application.getInstance() self._container_registry = ContainerRegistry.getInstance() self._machine_manager = self._application.getMachineManager() - self._material_manager = self._application._material_manager + self._material_manager = self._application.getMaterialManager() self._container_name_filters = {} @pyqtSlot(str, str, result=str) From ccd4bb285beb44d792e6ee56a8aaf0e71d66ffa7 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 26 Feb 2018 19:40:31 +0100 Subject: [PATCH 237/371] Use userChanges instead of getTop() --- plugins/3MFReader/ThreeMFReader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index b81fd435b9..80ef913b54 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -123,9 +123,9 @@ class ThreeMFReader(MeshReader): # Get the definition & set it definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack.definition) - um_node.callDecoration("getStack").getTop().setDefinition(definition_id) + um_node.callDecoration("getStack").userChanges.setDefinition(definition_id) - setting_container = um_node.callDecoration("getStack").getTop() + setting_container = um_node.callDecoration("getStack").userChanges for key in settings: setting_value = settings[key] From d79206301d847de4ff94739e6a9f20253fa187e7 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 27 Feb 2018 11:43:54 +0100 Subject: [PATCH 238/371] CURA-4606 CURA-5012 fix incompatible diameter update message in materialview --- resources/qml/Preferences/MaterialView.qml | 47 +++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 6e3d04fa2c..3dc16c5a86 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -41,6 +41,10 @@ TabView return linkedMaterials.join(", "); } + function getApproximateDiameter(diameter) { + return Math.round(diameter); + } + Tab { title: catalog.i18nc("@title", "Information") @@ -67,6 +71,34 @@ TabView width: base.width property real rowHeight: textField.height + UM.Theme.getSize("default_lining").height + MessageDialog + { + id: confirmDiameterChangeDialog + + icon: StandardIcon.Question; + title: catalog.i18nc("@title:window", "Confirm Diameter Change") + text: catalog.i18nc("@label (%1 is object name)", "The new material diameter is set to %1 mm, which is not compatible to the current machine. Do you wish to continue?".arg(new_diameter_value)) + standardButtons: StandardButton.Yes | StandardButton.No + modality: Qt.ApplicationModal + + property var new_diameter_value: null; + property var old_diameter_value: null; + property var old_approximate_diameter_value: null; + + onYes: + { + Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", new_diameter_value); + base.setMetaDataEntry("approximate_diameter", old_approximate_diameter_value, getApproximateDiameter(new_diameter_value).toString()); + base.setMetaDataEntry("properties/diameter", properties.diameter, new_diameter_value); + } + + onNo: + { + properties.diameter = old_diameter_value; + diameterSpinBox.value = properties.diameter; + } + } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Display Name") } ReadOnlyTextField { @@ -174,14 +206,19 @@ TabView // which derive from the same base_file var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString(); var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); - base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, Math.round(value).toString()); - base.setMetaDataEntry("properties/diameter", properties.diameter, value); - var new_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); + var new_approximate_diameter = getApproximateDiameter(value); if (Cura.MachineManager.filterMaterialsByMachine && new_approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) { - Cura.MaterialManager.showMaterialWarningMessage(base.containerId, old_diameter); + confirmDiameterChangeDialog.old_diameter_value = old_diameter; + confirmDiameterChangeDialog.new_diameter_value = value; + confirmDiameterChangeDialog.old_approximate_diameter_value = old_approximate_diameter; + + confirmDiameterChangeDialog.open() + } else { + Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value); + base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, getApproximateDiameter(value).toString()); + base.setMetaDataEntry("properties/diameter", properties.diameter, value); } - Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value); } onValueChanged: updateCostPerMeter() } From c47045a42e39ef42828cb87383f9f052fe5d979a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 27 Feb 2018 11:47:17 +0100 Subject: [PATCH 239/371] Revert "CuraApplication/UM.MeshBuilder: Removing _reloadMeshFinished" This reverts commit 269b52487ed28e42daf7e2716117c4d3d27bc2fa. It was crashing Cura when pressing F5. The completion of this job should not be moved to Uranium because the job exists only in Cura. Contributes to issue CURA-4912. --- cura/CuraApplication.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 720fcab86b..90c7dbb75e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1307,7 +1307,7 @@ class CuraApplication(QtApplication): if file_name: job = ReadMeshJob(file_name) job._node = node - job.finished.connect(node._reloadJobFinished) + job.finished.connect(self._reloadMeshFinished) job.start() else: Logger.log("w", "Unable to reload data because we don't have a filename.") @@ -1436,6 +1436,14 @@ class CuraApplication(QtApplication): fileLoaded = pyqtSignal(str) fileCompleted = pyqtSignal(str) + def _reloadMeshFinished(self, job): + # TODO; This needs to be fixed properly. We now make the assumption that we only load a single mesh! + mesh_data = job.getResult()[0].getMeshData() + if mesh_data: + job._node.setMeshData(mesh_data) + else: + Logger.log("w", "Could not find a mesh in reloaded node.") + def _openFile(self, filename): self.readLocalFile(QUrl.fromLocalFile(filename)) From df462412254d804aeb2ff7b376326e2a500983d0 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 27 Feb 2018 13:03:08 +0100 Subject: [PATCH 240/371] CURA-4606 CURA-5012 corrected and moved approximateMaterialDiameter to ExtruderStack --- cura/Machines/Models/MaterialsModel.py | 2 +- cura/Settings/ExtruderManager.py | 1 + cura/Settings/ExtruderStack.py | 29 ++++++++++++++++++++++ cura/Settings/GlobalStack.py | 15 ----------- resources/qml/Preferences/MaterialView.qml | 2 +- 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/cura/Machines/Models/MaterialsModel.py b/cura/Machines/Models/MaterialsModel.py index 616903062e..5ef5845371 100644 --- a/cura/Machines/Models/MaterialsModel.py +++ b/cura/Machines/Models/MaterialsModel.py @@ -30,7 +30,7 @@ def getAvailableMaterials(extruder_position: Optional[int] = None): variant_name = None if extruder_stack.variant.getId() != "empty_variant": variant_name = extruder_stack.variant.getName() - diameter = extruder_stack.getProperty("material_diameter", "value") + diameter = extruder_stack.approximateMaterialDiameter # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. result_dict = material_manager.getAvailableMaterials(machine_definition_id, variant_name, diameter) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 178cf31e3f..fe1bb6a990 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -179,6 +179,7 @@ class ExtruderManager(QObject): self._selected_object_extruders = [] self.selectedObjectExtrudersChanged.emit() + @pyqtSlot(result = QObject) def getActiveExtruderStack(self) -> Optional["ExtruderStack"]: global_container_stack = Application.getInstance().getGlobalContainerStack() diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index 870de62c98..2995aae795 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -3,6 +3,8 @@ from typing import Any, TYPE_CHECKING, Optional +from PyQt5.QtCore import pyqtProperty + from UM.Decorators import override from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase from UM.Settings.ContainerStack import ContainerStack @@ -49,6 +51,33 @@ class ExtruderStack(CuraContainerStack): def getLoadingPriority(cls) -> int: return 3 + ## Return the filament diameter that the machine requires. + # + # If the machine has no requirement for the diameter, -1 is returned. + # \return The filament diameter for the printer + @property + def materialDiameter(self) -> float: + containers_to_check = [self.variant, self.definitionChanges, self.definition] + + for container in containers_to_check: + if container is not None: + material_diameter = container.getProperty("material_diameter", "value") + if material_diameter is not None: + return material_diameter + return -1 + + ## Return the approximate filament diameter that the machine requires. + # + # The approximate material diameter is the material diameter rounded to + # the nearest millimetre. + # + # If the machine has no requirement for the diameter, -1 is returned. + # + # \return The approximate filament diameter for the printer + @pyqtProperty(float) + def approximateMaterialDiameter(self) -> float: + return round(float(self.materialDiameter)) + ## Overridden from ContainerStack # # It will perform a few extra checks when trying to get properties. diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 6d18bf615b..ae1f1370ed 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -125,21 +125,6 @@ class GlobalStack(CuraContainerStack): def setNextStack(self, next_stack: ContainerStack) -> None: raise Exceptions.InvalidOperationError("Global stack cannot have a next stack!") - ## Gets the approximate filament diameter that the machine requires. - # - # The approximate material diameter is the material diameter rounded to - # the nearest millimetre. - # - # If the machine has no requirement for the diameter, -1 is returned. - # - # \return The approximate filament diameter for the printer, as a string. - @pyqtProperty(str) - def approximateMaterialDiameter(self) -> str: - material_diameter = self.definition.getProperty("material_diameter", "value") - if material_diameter is None: - return "-1" - return str(round(float(material_diameter))) #Round, then convert back to string. - # protected: # Determine whether or not we should try to get the "resolve" property instead of the diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 3dc16c5a86..021fcc02e1 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -207,7 +207,7 @@ TabView var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString(); var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); var new_approximate_diameter = getApproximateDiameter(value); - if (Cura.MachineManager.filterMaterialsByMachine && new_approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) + if (Cura.MachineManager.filterMaterialsByMachine && new_approximate_diameter != Cura.ExtruderManager.getActiveExtruderStack().approximateMaterialDiameter) { confirmDiameterChangeDialog.old_diameter_value = old_diameter; confirmDiameterChangeDialog.new_diameter_value = value; From 5412a29ef9962c33145edf3f59341abd9f221c2f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 13:04:18 +0100 Subject: [PATCH 241/371] Fix update quality upon material change --- cura/Settings/MachineManager.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index b75f805d73..fd4b5b455c 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -839,7 +839,8 @@ class MachineManager(QObject): def _setQualityGroup(self, quality_group, empty_quality_changes = True): self._current_quality_group = quality_group - self._current_quality_changes_group = None + if empty_quality_changes: + self._current_quality_changes_group = None # Set quality and quality_changes for the GlobalStack self._global_container_stack.quality = quality_group.node_for_global.getContainer() @@ -946,7 +947,7 @@ class MachineManager(QObject): if preferred_quality_type in available_quality_types: quality_type = preferred_quality_type - self._setQualityGroup(candidate_quality_groups[quality_type], empty_quality_changes = False) + self._setQualityGroup(candidate_quality_groups[quality_type], empty_quality_changes = True) def _updateMaterialWithVariant(self, position: Optional[str]): if position is None: From dfa870b6a9521d4eac7084d089ffdffce7998b75 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 13:15:03 +0100 Subject: [PATCH 242/371] Remove approximate diameter unit tests because the function/property is gone --- tests/Settings/TestGlobalStack.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index 45ff13aaf3..6bf10dd8c1 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -116,31 +116,6 @@ def test_addExtruder(global_stack): # global_stack.addExtruder(unittest.mock.MagicMock()) assert len(global_stack.extruders) == 2 #Didn't add the faulty extruder. -## Tests getting the approximate material diameter. -@pytest.mark.parametrize("diameter, approximate_diameter", [ - #Some real-life cases that are common in printers. - (2.85, 3), - (1.75, 2), - (3.0, 3), - (2.0, 2), - #Exceptional cases. - (0, 0), - (-10.1, -10), - (-1, -1), - (9000.1, 9000) -]) -def test_approximateMaterialDiameter(diameter, approximate_diameter, global_stack): - global_stack.definition = DefinitionContainer(container_id = "TestDefinition") - material_diameter = UM.Settings.SettingDefinition.SettingDefinition(key = "material_diameter", container = global_stack.definition) - material_diameter.addSupportedProperty("value", UM.Settings.SettingDefinition.DefinitionPropertyType.Any, default = diameter) - global_stack.definition.definitions.append(material_diameter) - assert float(global_stack.approximateMaterialDiameter) == approximate_diameter - -## Tests getting the material diameter when there is no material diameter. -def test_approximateMaterialDiameterNoDiameter(global_stack): - global_stack.definition = DefinitionContainer(container_id = "TestDefinition") - assert global_stack.approximateMaterialDiameter == "-1" - #Tests setting user changes profiles to invalid containers. @pytest.mark.parametrize("container", [ getInstanceContainer(container_type = "wrong container type"), From a2e84bbe9734ccbe28902dd543533c6d3876cb04 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 13:49:20 +0100 Subject: [PATCH 243/371] Fix set quality group in init machine --- cura/Settings/MachineManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index fd4b5b455c..6a39ce127b 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -288,7 +288,7 @@ class MachineManager(QObject): Logger.log("w", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values())) return new_quality_group = quality_groups[quality_type] - self._setQualityGroup(new_quality_group) + self._setQualityGroup(new_quality_group, empty_quality_changes = True) @pyqtSlot(str) def setActiveMachine(self, stack_id: str) -> None: From 2f866873209accda80921308e9cb07db9d46aecc Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 13:49:45 +0100 Subject: [PATCH 244/371] Fix init machine for machines loaded from project files --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 5d34e4b059..6dd20b66e0 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -1082,11 +1082,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): CuraApplication.getInstance().getMachineManager().activeQualityChanged.emit() # Actually change the active machine. - machine_manager = Application.getInstance().getMachineManager() - machine_manager.setActiveMachine(global_stack.getId()) - - # Notify everything/one that is to notify about changes. - global_stack.containersChanged.emit(global_stack.getTop()) + CuraApplication.getInstance().callLater(self._updateActiveMachine, global_stack) # Load all the nodes / meshdata of the workspace nodes = self._3mf_mesh_reader.read(file_name) @@ -1099,6 +1095,14 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self.setWorkspaceName(base_file_name) return nodes + def _updateActiveMachine(self, global_stack): + # Actually change the active machine. + machine_manager = Application.getInstance().getMachineManager() + machine_manager.setActiveMachine(global_stack.getId()) + + # Notify everything/one that is to notify about changes. + global_stack.containersChanged.emit(global_stack.getTop()) + ## HACK: Replaces the material container in the given stack with a newly created material container. # This function is used when the user chooses to resolve material conflicts by creating new ones. def _replaceStackMaterialWithNew(self, stack, old_new_material_dict): From 08bfe933856ef14eaed42198029a13ef6cb8c76e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 27 Feb 2018 13:57:30 +0100 Subject: [PATCH 245/371] CURA-4606 CURA-5020 switching to quality changes now also checks and shows keep or discard user settings --- cura/Settings/MachineManager.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index fd4b5b455c..4e1d88a3b1 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1029,6 +1029,10 @@ class MachineManager(QObject): with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self._setQualityChangesGroup(quality_changes_group) + # See if we need to show the Discard or Keep changes screen + if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: + Application.getInstance().discardOrKeepProfileChanges() + @pyqtProperty(QObject, fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged) def activeQualityChangesGroup(self): return self._current_quality_changes_group From 950f6708c4a108c3ea4bf2e2340ea5e8bf0c0e5b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 14:20:17 +0100 Subject: [PATCH 246/371] Make sure to generate unique name for duplicated quality changes --- cura/Settings/ContainerManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 9701a7b406..d49ec79037 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -437,10 +437,11 @@ class ContainerManager(QObject): global_stack, extruder_id = None) self._container_registry.addContainer(new_quality_changes) else: + new_name = self._container_registry.uniqueName(quality_changes_name) for node in quality_changes_group.getAllNodes(): container = node.getContainer() new_id = self._container_registry.uniqueName(container.getId()) - self._container_registry.addContainer(container.duplicate(new_id, quality_changes_name)) + self._container_registry.addContainer(container.duplicate(new_id, new_name)) @pyqtSlot("QVariant") def removeMaterial(self, material_node): From cbeaf3b2872abd40e97ef6b9ef6b0dddb2139903 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 27 Feb 2018 15:14:34 +0100 Subject: [PATCH 247/371] CURA-4606 set empty quality when setting active machine when the current quality type is not in the available qualities --- cura/Settings/MachineManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index a710d74238..627e7661ba 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -286,6 +286,7 @@ class MachineManager(QObject): quality_groups = self._application._quality_manager.getQualityGroups(global_stack) if quality_type not in quality_groups: Logger.log("w", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values())) + self._setEmptyQuality() return new_quality_group = quality_groups[quality_type] self._setQualityGroup(new_quality_group, empty_quality_changes = True) From ae00fc2a7eca8c7754dc29031937890590ba81fe Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 27 Feb 2018 15:15:04 +0100 Subject: [PATCH 248/371] CURA-4606 change activeQualityLayerHeight to use self._current_quality(_changes)_group --- cura/Settings/MachineManager.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 627e7661ba..5abd5d4649 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -472,21 +472,17 @@ class MachineManager(QObject): def activeQualityLayerHeight(self) -> float: if not self._global_container_stack: return 0 - - quality_changes = self._global_container_stack.qualityChanges - if quality_changes: - value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = quality_changes.getId()) + if self._current_quality_changes_group: + value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = self._global_container_stack.qualityChanges.getId()) if isinstance(value, SettingFunction): value = value(self._global_container_stack) return value - quality = self._global_container_stack.quality - if quality: - value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = quality.getId()) + elif self._current_quality_group: + value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = self._global_container_stack.quality.getId()) if isinstance(value, SettingFunction): value = value(self._global_container_stack) return value - - return 0 # No quality profile. + return 0 @pyqtProperty(str, notify = activeVariantChanged) def globalVariantName(self) -> str: From f304e7f2e73828c4d2f1c5ceeb15c3f6196bbc66 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 15:58:34 +0100 Subject: [PATCH 249/371] Revert "Use userChanges instead of getTop()" PerObjectContainerStacks are not CuraContainerStacks, so we cannot use "userChanges" with it. --- plugins/3MFReader/ThreeMFReader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 80ef913b54..b81fd435b9 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -123,9 +123,9 @@ class ThreeMFReader(MeshReader): # Get the definition & set it definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack.definition) - um_node.callDecoration("getStack").userChanges.setDefinition(definition_id) + um_node.callDecoration("getStack").getTop().setDefinition(definition_id) - setting_container = um_node.callDecoration("getStack").userChanges + setting_container = um_node.callDecoration("getStack").getTop() for key in settings: setting_value = settings[key] From 632e0469fb5d818431a78d5b065adc3f9fdf724e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 15:59:39 +0100 Subject: [PATCH 250/371] Fix 3MF Reader --- plugins/3MFReader/ThreeMFReader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index b81fd435b9..95d8146d32 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -122,7 +122,7 @@ class ThreeMFReader(MeshReader): um_node.callDecoration("setActiveExtruder", default_stack.getId()) # Get the definition & set it - definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack.definition) + definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack) um_node.callDecoration("getStack").getTop().setDefinition(definition_id) setting_container = um_node.callDecoration("getStack").getTop() From 62e7cb9a2dfc469e9fd095e47ce0554a689031f5 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 27 Feb 2018 16:05:07 +0100 Subject: [PATCH 251/371] CURA-4972 Allow reslice after setting is removed The issue Andreea found was caused by the fact that the object was unsubscribed from setting validation while still having the illegal value, because the setting (and its illegal value) was removed AFTER unsubscribing. Thus the illegal value got "saved" until the next time you added that setting and set the correct value. --- plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 11e4a9cd0e..4b5d2a5708 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -241,8 +241,8 @@ Item { height: UM.Theme.getSize("setting").height onClicked: { - UM.ActiveTool.triggerAction("unsubscribeForSettingValidation", model.key) addedSettingsModel.setVisible(model.key, false) + UM.ActiveTool.triggerAction("unsubscribeForSettingValidation", model.key) } style: ButtonStyle From 9dcd72fb36b4ee6f95eeb1d06cf1fb10b7f239ad Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 16:06:09 +0100 Subject: [PATCH 252/371] Remove outdated TODOs --- cura/Machines/QualityManager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index a9aa6e9dcf..eb8a3611c1 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -256,7 +256,6 @@ class QualityManager(QObject): # Returns a dict of "custom profile name" -> QualityChangesGroup def getQualityChangesGroups(self, machine: "GlobalStack") -> dict: - # TODO: How to make this simpler? # Get machine definition ID for quality search machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) @@ -280,7 +279,6 @@ class QualityManager(QObject): return quality_changes_group_dict def getQualityGroups(self, machine: "GlobalStack") -> dict: - # TODO: How to make this simpler, including the fall backs. # Get machine definition ID for quality search machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) # This determines if we should only get the global qualities for the global stack and skip the global qualities for the extruder stacks From 85e3857785168648449dd45d0aa37af10f4ce8fd Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Feb 2018 16:12:28 +0100 Subject: [PATCH 253/371] Use getters to get managers for CuraStackBuilder --- cura/Settings/CuraStackBuilder.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 9273b272c1..4d103d2537 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -27,9 +27,9 @@ class CuraStackBuilder: def createMachine(cls, name: str, definition_id: str) -> Optional[GlobalStack]: from cura.CuraApplication import CuraApplication application = CuraApplication.getInstance() - variant_manager = CuraApplication.getInstance()._variant_manager - material_manager = CuraApplication.getInstance()._material_manager - quality_manager = CuraApplication.getInstance()._quality_manager + variant_manager = application.getVariantManager() + material_manager = application.getMaterialManager() + quality_manager = application.getQualityManager() registry = ContainerRegistry.getInstance() definitions = registry.findDefinitionContainers(id = definition_id) From 01071da4c17f7517eda0fd68fe523eaf3444287e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 27 Feb 2018 16:33:37 +0100 Subject: [PATCH 254/371] CURA-4606 corrected slider bar, it now updates correctly from 0 available qualities to 1 available quality --- resources/qml/SidebarSimple.qml | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 0f9c8b0e55..877e3a1557 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -137,7 +137,7 @@ Item // Set total available ticks for active slider part if (availableMin != -1) { - qualityModel.availableTotalTicks = availableMax - availableMin + qualityModel.availableTotalTicks = availableMax - availableMin + 1 } // Calculate slider values @@ -164,7 +164,7 @@ Item function reset () { qualityModel.clear() - qualityModel.availableTotalTicks = -1 + qualityModel.availableTotalTicks = 0 qualityModel.existingQualityProfile = 0 // check, the ticks count cannot be less than zero @@ -273,32 +273,24 @@ Item } } - Rectangle { - id: disabledHandleButton - visible: !qualitySlider.visible - anchors.centerIn: parent - color: UM.Theme.getColor("quality_slider_unavailable") - implicitWidth: 10 * screenScaleFactor - implicitHeight: implicitWidth - radius: Math.round(width / 2) - } - Slider { id: qualitySlider height: UM.Theme.getSize("sidebar_margin").height anchors.bottom: speedSlider.bottom - enabled: qualityModel.availableTotalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized - visible: qualityModel.totalTicks > 0 + enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized + visible: qualityModel.availableTotalTicks > 0 updateValueWhileDragging : false minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0 - maximumValue: qualityModel.qualitySliderAvailableMax >= 0 ? qualityModel.qualitySliderAvailableMax : 0 + // maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly + // speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available) + maximumValue: qualityModel.qualitySliderAvailableMax >= 1 ? qualityModel.qualitySliderAvailableMax : 1 stepSize: 1 value: qualityModel.qualitySliderActiveIndex - width: qualityModel.qualitySliderStepWidth * qualityModel.availableTotalTicks + width: qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks - 1) anchors.right: parent.right anchors.rightMargin: qualityModel.qualitySliderMarginRight @@ -376,7 +368,7 @@ Item text: catalog.i18nc("@label", "Slower") font: UM.Theme.getFont("default") - color: (qualityModel.availableTotalTicks > 0) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + color: (qualityModel.availableTotalTicks > 1) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") horizontalAlignment: Text.AlignLeft } @@ -387,7 +379,7 @@ Item text: catalog.i18nc("@label", "Faster") font: UM.Theme.getFont("default") - color: (qualityModel.availableTotalTicks > 0) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + color: (qualityModel.availableTotalTicks > 1) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") horizontalAlignment: Text.AlignRight } From a74282a66435fb433a9b0fc2f543ebef51ac38ae Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 28 Feb 2018 09:15:53 +0100 Subject: [PATCH 255/371] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index b78b9b91a2..d8e36d9729 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,9 +1,12 @@ From 1eaec2ecbc0c22a20879cc8c5fb36cf8b60e4932 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 28 Feb 2018 09:17:11 +0100 Subject: [PATCH 256/371] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index d8e36d9729..97c849144d 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,9 +1,9 @@ Material Type -> list of materials +class BrandMaterialsModel(ListModel): + NameRole = Qt.UserRole + 1 + MaterialsRole = Qt.UserRole + 2 + + extruderPositionChanged = pyqtSignal() + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.MaterialsRole, "materials") + + self._extruder_position = 0 + + from cura.CuraApplication import CuraApplication + self._machine_manager = CuraApplication.getInstance().getMachineManager() + extruder_manager = CuraApplication.getInstance().getExtruderManager() + material_manager = CuraApplication.getInstance()._material_manager + + self._machine_manager.globalContainerChanged.connect(self._update) + extruder_manager.activeExtruderChanged.connect(self._update) + material_manager.materialsUpdated.connect(self._update) + + self._update() + + def setExtruderPosition(self, position: int): + if self._extruder_position != position: + self._extruder_position = position + self.extruderPositionChanged.emit() + + @pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged) + def extruderPosition(self) -> int: + return self._extruder_position + + def _update(self): + global_stack = self._machine_manager.activeMachine + if global_stack is None: + self.setItems([]) + return + + result_dict = getAvailableMaterials(self._extruder_position) + if result_dict is None: + self.setItems([]) + return + + brand_item_list = [] + brand_group_dict = {} + for root_material_id, container_node in result_dict.items(): + metadata = container_node.metadata + brand = metadata["brand"] + # Only add results for generic materials + if brand.lower() == "generic": + continue + + if brand not in brand_group_dict: + brand_group_dict[brand] = {} + + material_type = metadata["material"] + if material_type not in brand_group_dict[brand]: + brand_group_dict[brand][material_type] = [] + + item = {"root_material_id": root_material_id, + "id": metadata["id"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "container_node": container_node + } + brand_group_dict[brand][material_type].append(item) + + for brand, material_dict in brand_group_dict.items(): + brand_item = {"name": brand, + "materials": MaterialsModelGroupedByType(self)} + + material_type_item_list = [] + for material_type, material_list in material_dict.items(): + material_type_item = {"name": material_type, + "colors": BaseMaterialsModel(self)} + material_type_item["colors"].clear() + material_type_item["colors"].setItems(material_list) + + material_type_item_list.append(material_type_item) + + brand_item["materials"].setItems(material_type_item_list) + + brand_item_list.append(brand_item) + + self.setItems(brand_item_list) + diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py new file mode 100644 index 0000000000..dd18abe7c3 --- /dev/null +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -0,0 +1,54 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from .BaseMaterialsModel import BaseMaterialsModel, getAvailableMaterials + + +class GenericMaterialsModel(BaseMaterialsModel): + + def __init__(self, parent = None): + super().__init__(parent) + + from cura.CuraApplication import CuraApplication + self._machine_manager = CuraApplication.getInstance().getMachineManager() + self._extruder_manager = CuraApplication.getInstance().getExtruderManager() + self._material_manager = CuraApplication.getInstance()._material_manager + + self._machine_manager.globalContainerChanged.connect(self._update) + self._extruder_manager.activeExtruderChanged.connect(self._update) + self._material_manager.materialsUpdated.connect(self._update) + + self._update() + + def _update(self): + global_stack = self._machine_manager.activeMachine + if global_stack is None: + self.setItems([]) + return + + result_dict = getAvailableMaterials(self._extruder_position) + if result_dict is None: + self.setItems([]) + return + + item_list = [] + for root_material_id, container_node in result_dict.items(): + metadata = container_node.metadata + # Only add results for generic materials + if metadata["brand"].lower() != "generic": + continue + + item = {"root_material_id": root_material_id, + "id": metadata["id"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "container_node": container_node + } + item_list.append(item) + + # Sort the item list by material name alphabetically + item_list = sorted(item_list, key = lambda d: d["name"]) + + self.setItems(item_list) diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py new file mode 100644 index 0000000000..35173129e0 --- /dev/null +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -0,0 +1,101 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from PyQt5.QtCore import Qt, pyqtProperty + +from UM.Qt.ListModel import ListModel + +from .BaseMaterialsModel import getAvailableMaterials + + +# +# This model is for the Material management page. +# +class MaterialManagementModel(ListModel): + RootMaterialIdRole = Qt.UserRole + 1 + DisplayNameRole = Qt.UserRole + 2 + BrandRole = Qt.UserRole + 3 + MaterialTypeRole = Qt.UserRole + 4 + ColorNameRole = Qt.UserRole + 5 + ColorCodeRole = Qt.UserRole + 6 + ContainerNodeRole = Qt.UserRole + 7 + ContainerIdRole = Qt.UserRole + 8 + + DescriptionRole = Qt.UserRole + 9 + AdhesionInfoRole = Qt.UserRole + 10 + ApproximateDiameterRole = Qt.UserRole + 11 + GuidRole = Qt.UserRole + 12 + DensityRole = Qt.UserRole + 13 + DiameterRole = Qt.UserRole + 14 + IsReadOnlyRole = Qt.UserRole + 15 + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(self.RootMaterialIdRole, "root_material_id") + self.addRoleName(self.DisplayNameRole, "name") + self.addRoleName(self.BrandRole, "brand") + self.addRoleName(self.MaterialTypeRole, "material") + self.addRoleName(self.ColorNameRole, "color_name") + self.addRoleName(self.ColorCodeRole, "color_code") + self.addRoleName(self.ContainerNodeRole, "container_node") + self.addRoleName(self.ContainerIdRole, "container_id") + + self.addRoleName(self.DescriptionRole, "description") + self.addRoleName(self.AdhesionInfoRole, "adhesion_info") + self.addRoleName(self.ApproximateDiameterRole, "approximate_diameter") + self.addRoleName(self.GuidRole, "guid") + self.addRoleName(self.DensityRole, "density") + self.addRoleName(self.DiameterRole, "diameter") + self.addRoleName(self.IsReadOnlyRole, "is_read_only") + + from cura.CuraApplication import CuraApplication + self._container_registry = CuraApplication.getInstance().getContainerRegistry() + self._machine_manager = CuraApplication.getInstance().getMachineManager() + extruder_manager = CuraApplication.getInstance().getExtruderManager() + material_manager = CuraApplication.getInstance()._material_manager + + self._machine_manager.globalContainerChanged.connect(self._update) + extruder_manager.activeExtruderChanged.connect(self._update) + material_manager.materialsUpdated.connect(self._update) + + self._update() + + def _update(self): + global_stack = self._machine_manager.activeMachine + if global_stack is None: + self.setItems([]) + return + + result_dict = getAvailableMaterials() + if result_dict is None: + self.setItems([]) + return + + material_list = [] + for root_material_id, container_node in result_dict.items(): + keys_to_fetch = ("name", + "brand", + "material", + "color_name", + "color_code", + "description", + "adhesion_info", + "approximate_diameter",) + + item = {"root_material_id": container_node.metadata["base_file"], + "container_node": container_node, + "guid": container_node.metadata["GUID"], + "container_id": container_node.metadata["id"], + "density": container_node.metadata.get("properties", {}).get("density", ""), + "diameter": container_node.metadata.get("properties", {}).get("diameter", ""), + "is_read_only": self._container_registry.isReadOnly(container_node.metadata["id"]), + } + + for key in keys_to_fetch: + item[key] = container_node.metadata.get(key, "") + + material_list.append(item) + + material_list = sorted(material_list, key = lambda k: (k["brand"].lower(), k["name"])) + self.setItems(material_list) diff --git a/cura/Machines/Models/MaterialsModel.py b/cura/Machines/Models/MaterialsModel.py deleted file mode 100644 index 5ef5845371..0000000000 --- a/cura/Machines/Models/MaterialsModel.py +++ /dev/null @@ -1,317 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from typing import Optional -from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty - -from UM.Logger import Logger -from UM.Qt.ListModel import ListModel - - -def getAvailableMaterials(extruder_position: Optional[int] = None): - from cura.CuraApplication import CuraApplication - machine_manager = CuraApplication.getInstance().getMachineManager() - extruder_manager = CuraApplication.getInstance().getExtruderManager() - - material_manager = CuraApplication.getInstance()._material_manager - - active_global_stack = machine_manager._global_container_stack - extruder_stack = extruder_manager.getActiveExtruderStack() - if extruder_position is not None: - if active_global_stack is not None: - extruder_stack = active_global_stack.extruders.get(str(extruder_position)) - - if active_global_stack is None or extruder_stack is None: - Logger.log("d", "Active global stack [%s] or extruder stack [%s] is None, setting material list to empty.", - active_global_stack, extruder_stack) - return - - machine_definition_id = active_global_stack.definition.getId() - variant_name = None - if extruder_stack.variant.getId() != "empty_variant": - variant_name = extruder_stack.variant.getName() - diameter = extruder_stack.approximateMaterialDiameter - - # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. - result_dict = material_manager.getAvailableMaterials(machine_definition_id, variant_name, diameter) - return result_dict - - -class BaseMaterialsModel(ListModel): - RootMaterialIdRole = Qt.UserRole + 1 - IdRole = Qt.UserRole + 2 - NameRole = Qt.UserRole + 3 - BrandRole = Qt.UserRole + 4 - MaterialRole = Qt.UserRole + 5 - ColorRole = Qt.UserRole + 6 - ContainerNodeRole = Qt.UserRole + 7 - - extruderPositionChanged = pyqtSignal() - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.RootMaterialIdRole, "root_material_id") - self.addRoleName(self.IdRole, "id") - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.BrandRole, "brand") - self.addRoleName(self.MaterialRole, "material") - self.addRoleName(self.ColorRole, "color_name") - self.addRoleName(self.ContainerNodeRole, "container_node") - - self._extruder_position = 0 - - def setExtruderPosition(self, position: int): - if self._extruder_position != position: - self._extruder_position = position - self.extruderPositionChanged.emit() - - @pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged) - def extruderPosition(self) -> int: - return self._extruder_positoin - - -class GenericMaterialsModel(BaseMaterialsModel): - - def __init__(self, parent = None): - super().__init__(parent) - - from cura.CuraApplication import CuraApplication - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance()._material_manager - - self._machine_manager.globalContainerChanged.connect(self._update) - self._extruder_manager.activeExtruderChanged.connect(self._update) - self._material_manager.materialsUpdated.connect(self._update) - - self._update() - - def _update(self): - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - - result_dict = getAvailableMaterials(self._extruder_position) - if result_dict is None: - self.setItems([]) - return - - item_list = [] - for root_material_id, container_node in result_dict.items(): - metadata = container_node.metadata - # Only add results for generic materials - if metadata["brand"].lower() != "generic": - continue - - item = {"root_material_id": root_material_id, - "id": metadata["id"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "container_node": container_node - } - item_list.append(item) - - # Sort the item list by material name alphabetically - item_list = sorted(item_list, key = lambda d: d["name"]) - - self.setItems(item_list) - - -class MaterialsModelGroupedByType(ListModel): - NameRole = Qt.UserRole + 1 - ColorsRole = Qt.UserRole + 2 - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.ColorsRole, "colors") - - -## Brand --> Material Type -> list of materials -class BrandMaterialsModel(ListModel): - NameRole = Qt.UserRole + 1 - MaterialsRole = Qt.UserRole + 2 - - extruderPositionChanged = pyqtSignal() - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.MaterialsRole, "materials") - - self._extruder_position = 0 - - from cura.CuraApplication import CuraApplication - self._machine_manager = CuraApplication.getInstance().getMachineManager() - extruder_manager = CuraApplication.getInstance().getExtruderManager() - material_manager = CuraApplication.getInstance()._material_manager - - self._machine_manager.globalContainerChanged.connect(self._update) - extruder_manager.activeExtruderChanged.connect(self._update) - material_manager.materialsUpdated.connect(self._update) - - self._update() - - def setExtruderPosition(self, position: int): - if self._extruder_position != position: - self._extruder_position = position - self.extruderPositionChanged.emit() - - @pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged) - def extruderPosition(self) -> int: - return self._extruder_position - - def _update(self): - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - - result_dict = getAvailableMaterials(self._extruder_position) - if result_dict is None: - self.setItems([]) - return - - brand_item_list = [] - brand_group_dict = {} - for root_material_id, container_node in result_dict.items(): - metadata = container_node.metadata - brand = metadata["brand"] - # Only add results for generic materials - if brand.lower() == "generic": - continue - - if brand not in brand_group_dict: - brand_group_dict[brand] = {} - - material_type = metadata["material"] - if material_type not in brand_group_dict[brand]: - brand_group_dict[brand][material_type] = [] - - item = {"root_material_id": root_material_id, - "id": metadata["id"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "container_node": container_node - } - brand_group_dict[brand][material_type].append(item) - - for brand, material_dict in brand_group_dict.items(): - brand_item = {"name": brand, - "materials": MaterialsModelGroupedByType(self)} - - material_type_item_list = [] - for material_type, material_list in material_dict.items(): - material_type_item = {"name": material_type, - "colors": BaseMaterialsModel(self)} - material_type_item["colors"].clear() - material_type_item["colors"].setItems(material_list) - - material_type_item_list.append(material_type_item) - - brand_item["materials"].setItems(material_type_item_list) - - brand_item_list.append(brand_item) - - self.setItems(brand_item_list) - - -# -# This model is for the Material management page. -# -class MaterialsModel(ListModel): - RootMaterialIdRole = Qt.UserRole + 1 - DisplayNameRole = Qt.UserRole + 2 - BrandRole = Qt.UserRole + 3 - MaterialTypeRole = Qt.UserRole + 4 - ColorNameRole = Qt.UserRole + 5 - ColorCodeRole = Qt.UserRole + 6 - ContainerNodeRole = Qt.UserRole + 7 - ContainerIdRole = Qt.UserRole + 8 - - DescriptionRole = Qt.UserRole + 9 - AdhesionInfoRole = Qt.UserRole + 10 - ApproximateDiameterRole = Qt.UserRole + 11 - GuidRole = Qt.UserRole + 12 - DensityRole = Qt.UserRole + 13 - DiameterRole = Qt.UserRole + 14 - IsReadOnlyRole = Qt.UserRole + 15 - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.RootMaterialIdRole, "root_material_id") - self.addRoleName(self.DisplayNameRole, "name") - self.addRoleName(self.BrandRole, "brand") - self.addRoleName(self.MaterialTypeRole, "material") - self.addRoleName(self.ColorNameRole, "color_name") - self.addRoleName(self.ColorCodeRole, "color_code") - self.addRoleName(self.ContainerNodeRole, "container_node") - self.addRoleName(self.ContainerIdRole, "container_id") - - self.addRoleName(self.DescriptionRole, "description") - self.addRoleName(self.AdhesionInfoRole, "adhesion_info") - self.addRoleName(self.ApproximateDiameterRole, "approximate_diameter") - self.addRoleName(self.GuidRole, "guid") - self.addRoleName(self.DensityRole, "density") - self.addRoleName(self.DiameterRole, "diameter") - self.addRoleName(self.IsReadOnlyRole, "is_read_only") - - from cura.CuraApplication import CuraApplication - self._container_registry = CuraApplication.getInstance().getContainerRegistry() - self._machine_manager = CuraApplication.getInstance().getMachineManager() - extruder_manager = CuraApplication.getInstance().getExtruderManager() - material_manager = CuraApplication.getInstance()._material_manager - - self._machine_manager.globalContainerChanged.connect(self._update) - extruder_manager.activeExtruderChanged.connect(self._update) - material_manager.materialsUpdated.connect(self._update) - - self._update() - - def _update(self): - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - - result_dict = getAvailableMaterials() - if result_dict is None: - self.setItems([]) - return - - material_list = [] - for root_material_id, container_node in result_dict.items(): - keys_to_fetch = ("name", - "brand", - "material", - "color_name", - "color_code", - "description", - "adhesion_info", - "approximate_diameter",) - - item = {"root_material_id": container_node.metadata["base_file"], - "container_node": container_node, - "guid": container_node.metadata["GUID"], - "container_id": container_node.metadata["id"], - "density": container_node.metadata.get("properties", {}).get("density", ""), - "diameter": container_node.metadata.get("properties", {}).get("diameter", ""), - "is_read_only": self._container_registry.isReadOnly(container_node.metadata["id"]), - } - - for key in keys_to_fetch: - item[key] = container_node.metadata.get(key, "") - - material_list.append(item) - - material_list = sorted(material_list, key = lambda k: (k["brand"].lower(), k["name"])) - self.setItems(material_list) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 671b5c6b9b..1177f20334 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -17,7 +17,7 @@ Item UM.I18nCatalog { id: catalog; name: "cura"; } - Cura.MaterialsModel { + Cura.MaterialManagementModel { id: materialsModel } From c21174eea8a2684b659de03cc4a0b45b372ed8eb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 11:55:29 +0100 Subject: [PATCH 282/371] Fix the usage of protected variables in material models --- cura/Machines/Models/BaseMaterialsModel.py | 5 ++--- cura/Machines/Models/BrandMaterialsModel.py | 2 +- cura/Machines/Models/GenericMaterialsModel.py | 2 +- cura/Machines/Models/MaterialManagementModel.py | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 1ad4da8513..1b06fa5d1a 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -12,10 +12,9 @@ def getAvailableMaterials(extruder_position: Optional[int] = None): from cura.CuraApplication import CuraApplication machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() + material_manager = CuraApplication.getInstance().getMaterialManager() - material_manager = CuraApplication.getInstance()._material_manager - - active_global_stack = machine_manager._global_container_stack + active_global_stack = machine_manager.activeMachine extruder_stack = extruder_manager.getActiveExtruderStack() if extruder_position is not None: if active_global_stack is not None: diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index 9e2aaa02e8..1edef672d4 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -37,7 +37,7 @@ class BrandMaterialsModel(ListModel): from cura.CuraApplication import CuraApplication self._machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() - material_manager = CuraApplication.getInstance()._material_manager + material_manager = CuraApplication.getInstance().getMaterialManager() self._machine_manager.globalContainerChanged.connect(self._update) extruder_manager.activeExtruderChanged.connect(self._update) diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index dd18abe7c3..c15f88d59a 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -12,7 +12,7 @@ class GenericMaterialsModel(BaseMaterialsModel): from cura.CuraApplication import CuraApplication self._machine_manager = CuraApplication.getInstance().getMachineManager() self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance()._material_manager + self._material_manager = CuraApplication.getInstance().getMaterialManager() self._machine_manager.globalContainerChanged.connect(self._update) self._extruder_manager.activeExtruderChanged.connect(self._update) diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index 35173129e0..cd1aa12427 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -53,7 +53,7 @@ class MaterialManagementModel(ListModel): self._container_registry = CuraApplication.getInstance().getContainerRegistry() self._machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() - material_manager = CuraApplication.getInstance()._material_manager + material_manager = CuraApplication.getInstance().getMaterialManager() self._machine_manager.globalContainerChanged.connect(self._update) extruder_manager.activeExtruderChanged.connect(self._update) From 7b794249f68326e8db1b05913b7a16f6971a00a9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 1 Mar 2018 13:33:14 +0100 Subject: [PATCH 283/371] Add 512 padding bytes to the end of the g-code Due to a bug in the firmware of the Ultimaker 2, the print was already ending before the last few commands were executed completely. It would then finish the last few commands in a different routine but the extrusion modifier wasn't applied there, resulting in a blob on your print. This is a workaround that puts always one file system page (512 bytes) of padding at the end of the g-code file. If these comments are not executed that is fine. If they are then it's also fine. Until the bug is fixed in firmware, this will at least prevent the issue from occurring for users. --- resources/definitions/ultimaker2.def.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/definitions/ultimaker2.def.json b/resources/definitions/ultimaker2.def.json index 038071574f..33b48116be 100644 --- a/resources/definitions/ultimaker2.def.json +++ b/resources/definitions/ultimaker2.def.json @@ -20,12 +20,10 @@ "overrides": { "machine_name": { "default_value": "Ultimaker 2" }, "machine_start_gcode" : { - "default_value": "", "value": "\"\" if machine_gcode_flavor == \"UltiGCode\" else \"G21 ;metric values\\nG90 ;absolute positioning\\nM82 ;set extruder to absolute mode\\nM107 ;start with the fan off\\nG28 Z0 ;move Z to bottom endstops\\nG28 X0 Y0 ;move X/Y to endstops\\nG1 X15 Y0 F4000 ;move X/Y to front of printer\\nG1 Z15.0 F9000 ;move the platform to 15mm\\nG92 E0 ;zero the extruded length\\nG1 F200 E10 ;extrude 10 mm of feed stock\\nG92 E0 ;zero the extruded length again\\nG1 F9000\\n;Put printing message on LCD screen\\nM117 Printing...\"" }, "machine_end_gcode" : { - "default_value": "", - "value": "\"\" if machine_gcode_flavor == \"UltiGCode\" else \"M104 S0 ;extruder heater off\\nM140 S0 ;heated bed heater off (if you have it)\\nG91 ;relative positioning\\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\\nM84 ;steppers off\\nG90 ;absolute positioning\"" + "value": "\";Version _2.6 of the firmware can abort the print too early if the file ends\\n;too soon. However if the file hasn't ended yet because there are comments at\\n;the end of the file, it won't abort yet. Therefore we have to put at least 512\\n;bytes at the end of the g-code so that the file is not yet finished by the\\n;time that the motion planner gets flushed. With firmware version _3.3 this\\n;should be fixed, so this comment wouldn't be necessary any more. Now we have\\n;to pad this text to make precisely 512 bytes.\" if machine_gcode_flavor == \"UltiGCode\" else \"M104 S0 ;extruder heater off\\nM140 S0 ;heated bed heater off (if you have it)\\nG91 ;relative positioning\\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\\nM84 ;steppers off\\nG90 ;absolute positioning\\n;Version _2.6 of the firmware can abort the print too early if the file ends\\n;too soon. However if the file hasn't ended yet because there are comments at\\n;the end of the file, it won't abort yet. Therefore we have to put at least 512\\n;bytes at the end of the g-code so that the file is not yet finished by the\\n;time that the motion planner gets flushed. With firmware version _3.3 this\\n;should be fixed, so this comment wouldn't be necessary any more. Now we have\\n;to pad this text to make precisely 512 bytes.\"" }, "machine_width": { "default_value": 223 From b4c353699960ae39d129159fefc7e587a5eee68b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:02:57 +0100 Subject: [PATCH 284/371] Move getAvailableMaterials() into MaterialManager --- cura/Machines/MaterialManager.py | 14 +++++++++ cura/Machines/Models/BaseMaterialsModel.py | 30 ------------------- cura/Machines/Models/BrandMaterialsModel.py | 13 ++++---- cura/Machines/Models/GenericMaterialsModel.py | 5 ++-- .../Models/MaterialManagementModel.py | 14 ++++----- 5 files changed, 31 insertions(+), 45 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index ffb796a705..2dd39d1fe1 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -260,6 +260,20 @@ class MaterialManager(QObject): return material_id_metadata_dict + # + # A convenience function to get available materials for the given machine with the extruder position. + # + def getAvailableMaterialsForMachineExtruder(self, machine: "GlobalStack", + extruder_stack: "ExtruderStack") -> Optional[dict]: + machine_definition_id = machine.definition.getId() + variant_name = None + if extruder_stack.variant.getId() != "empty_variant": + variant_name = extruder_stack.variant.getName() + diameter = extruder_stack.approximateMaterialDiameter + + # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. + return self.getAvailableMaterials(machine_definition_id, variant_name, diameter) + # # Gets MaterialNode for the given extruder and machine with the given material name. # Returns None if: diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 1b06fa5d1a..c93473031a 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -1,41 +1,11 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Optional from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty -from UM.Logger import Logger from UM.Qt.ListModel import ListModel -def getAvailableMaterials(extruder_position: Optional[int] = None): - from cura.CuraApplication import CuraApplication - machine_manager = CuraApplication.getInstance().getMachineManager() - extruder_manager = CuraApplication.getInstance().getExtruderManager() - material_manager = CuraApplication.getInstance().getMaterialManager() - - active_global_stack = machine_manager.activeMachine - extruder_stack = extruder_manager.getActiveExtruderStack() - if extruder_position is not None: - if active_global_stack is not None: - extruder_stack = active_global_stack.extruders.get(str(extruder_position)) - - if active_global_stack is None or extruder_stack is None: - Logger.log("d", "Active global stack [%s] or extruder stack [%s] is None, setting material list to empty.", - active_global_stack, extruder_stack) - return - - machine_definition_id = active_global_stack.definition.getId() - variant_name = None - if extruder_stack.variant.getId() != "empty_variant": - variant_name = extruder_stack.variant.getName() - diameter = extruder_stack.approximateMaterialDiameter - - # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. - result_dict = material_manager.getAvailableMaterials(machine_definition_id, variant_name, diameter) - return result_dict - - class BaseMaterialsModel(ListModel): RootMaterialIdRole = Qt.UserRole + 1 IdRole = Qt.UserRole + 2 diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index 1edef672d4..74518adcd6 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -5,7 +5,7 @@ from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty from UM.Qt.ListModel import ListModel -from .BaseMaterialsModel import BaseMaterialsModel, getAvailableMaterials +from .BaseMaterialsModel import BaseMaterialsModel class MaterialsModelGroupedByType(ListModel): @@ -36,12 +36,12 @@ class BrandMaterialsModel(ListModel): from cura.CuraApplication import CuraApplication self._machine_manager = CuraApplication.getInstance().getMachineManager() - extruder_manager = CuraApplication.getInstance().getExtruderManager() - material_manager = CuraApplication.getInstance().getMaterialManager() + self._extruder_manager = CuraApplication.getInstance().getExtruderManager() + self._material_manager = CuraApplication.getInstance().getMaterialManager() self._machine_manager.globalContainerChanged.connect(self._update) - extruder_manager.activeExtruderChanged.connect(self._update) - material_manager.materialsUpdated.connect(self._update) + self._extruder_manager.activeExtruderChanged.connect(self._update) + self._material_manager.materialsUpdated.connect(self._update) self._update() @@ -59,8 +59,9 @@ class BrandMaterialsModel(ListModel): if global_stack is None: self.setItems([]) return + extruder_stack = global_stack.extruders[str(self._extruder_position)] - result_dict = getAvailableMaterials(self._extruder_position) + result_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) if result_dict is None: self.setItems([]) return diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index c15f88d59a..da7ef686d3 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from .BaseMaterialsModel import BaseMaterialsModel, getAvailableMaterials +from .BaseMaterialsModel import BaseMaterialsModel class GenericMaterialsModel(BaseMaterialsModel): @@ -25,8 +25,9 @@ class GenericMaterialsModel(BaseMaterialsModel): if global_stack is None: self.setItems([]) return + extruder_stack = global_stack.extruders[str(self._extruder_position)] - result_dict = getAvailableMaterials(self._extruder_position) + result_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) if result_dict is None: self.setItems([]) return diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index cd1aa12427..abff1d6010 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -5,8 +5,6 @@ from PyQt5.QtCore import Qt, pyqtProperty from UM.Qt.ListModel import ListModel -from .BaseMaterialsModel import getAvailableMaterials - # # This model is for the Material management page. @@ -52,12 +50,12 @@ class MaterialManagementModel(ListModel): from cura.CuraApplication import CuraApplication self._container_registry = CuraApplication.getInstance().getContainerRegistry() self._machine_manager = CuraApplication.getInstance().getMachineManager() - extruder_manager = CuraApplication.getInstance().getExtruderManager() - material_manager = CuraApplication.getInstance().getMaterialManager() + self._extruder_manager = CuraApplication.getInstance().getExtruderManager() + self._material_manager = CuraApplication.getInstance().getMaterialManager() self._machine_manager.globalContainerChanged.connect(self._update) - extruder_manager.activeExtruderChanged.connect(self._update) - material_manager.materialsUpdated.connect(self._update) + self._extruder_manager.activeExtruderChanged.connect(self._update) + self._material_manager.materialsUpdated.connect(self._update) self._update() @@ -66,8 +64,10 @@ class MaterialManagementModel(ListModel): if global_stack is None: self.setItems([]) return + active_extruder_stack = self._machine_manager.activeStack - result_dict = getAvailableMaterials() + result_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, + active_extruder_stack) if result_dict is None: self.setItems([]) return From 4b7c8a8a80b27a00590a4c42beda39acd3031071 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:09:58 +0100 Subject: [PATCH 285/371] Add doc for BaseMaterialsModel --- cura/Machines/Models/BaseMaterialsModel.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index c93473031a..de0c68d60a 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -6,6 +6,12 @@ from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty from UM.Qt.ListModel import ListModel +# +# This is the base model class for GenericMaterialsModel and BrandMaterialsModel +# Those 2 models are used by the material drop down menu to show generic materials and branded materials separately. +# The extruder position defined here is being used to bound a menu to the correct extruder. This is used in the top +# bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu +# class BaseMaterialsModel(ListModel): RootMaterialIdRole = Qt.UserRole + 1 IdRole = Qt.UserRole + 2 From d6f6dbe45efd799b987928cbc679bd2850ae2c66 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:12:34 +0100 Subject: [PATCH 286/371] Rename to available_material_dict --- cura/Machines/Models/BrandMaterialsModel.py | 8 ++++---- cura/Machines/Models/GenericMaterialsModel.py | 7 ++++--- cura/Machines/Models/MaterialManagementModel.py | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index 74518adcd6..ec1e3c7ebe 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -61,14 +61,15 @@ class BrandMaterialsModel(ListModel): return extruder_stack = global_stack.extruders[str(self._extruder_position)] - result_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) - if result_dict is None: + available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, + extruder_stack) + if available_material_dict is None: self.setItems([]) return brand_item_list = [] brand_group_dict = {} - for root_material_id, container_node in result_dict.items(): + for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata brand = metadata["brand"] # Only add results for generic materials @@ -110,4 +111,3 @@ class BrandMaterialsModel(ListModel): brand_item_list.append(brand_item) self.setItems(brand_item_list) - diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index da7ef686d3..f5b18adde9 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -27,13 +27,14 @@ class GenericMaterialsModel(BaseMaterialsModel): return extruder_stack = global_stack.extruders[str(self._extruder_position)] - result_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) - if result_dict is None: + available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, + extruder_stack) + if available_material_dict is None: self.setItems([]) return item_list = [] - for root_material_id, container_node in result_dict.items(): + for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata # Only add results for generic materials if metadata["brand"].lower() != "generic": diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index abff1d6010..b250232282 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -66,14 +66,14 @@ class MaterialManagementModel(ListModel): return active_extruder_stack = self._machine_manager.activeStack - result_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, - active_extruder_stack) - if result_dict is None: + available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, + active_extruder_stack) + if available_material_dict is None: self.setItems([]) return material_list = [] - for root_material_id, container_node in result_dict.items(): + for root_material_id, container_node in available_material_dict.items(): keys_to_fetch = ("name", "brand", "material", From 72b42113b3ca16e801ae9aea866533912d4f00f0 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:19:01 +0100 Subject: [PATCH 287/371] Add doc for BrandMaterialsModel --- cura/Machines/Models/BrandMaterialsModel.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index ec1e3c7ebe..f6430b39da 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -8,6 +8,9 @@ from UM.Qt.ListModel import ListModel from .BaseMaterialsModel import BaseMaterialsModel +# +# This is an intermediate model to group materials with different colours for a same brand and type. +# class MaterialsModelGroupedByType(ListModel): NameRole = Qt.UserRole + 1 ColorsRole = Qt.UserRole + 2 @@ -19,7 +22,18 @@ class MaterialsModelGroupedByType(ListModel): self.addRoleName(self.ColorsRole, "colors") -## Brand --> Material Type -> list of materials +# +# This model is used to show branded materials in the material drop down menu. +# The structure of the menu looks like this: +# Brand -> Material Type -> list of materials +# +# To illustrate, a branded material menu may look like this: +# Ultimaker -> PLA -> Yellow PLA +# -> Black PLA +# -> ... +# -> ABS -> White ABS +# ... +# class BrandMaterialsModel(ListModel): NameRole = Qt.UserRole + 1 MaterialsRole = Qt.UserRole + 2 From c0604e5c759ab003a3d09728a7024a29ae9e0079 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:25:11 +0100 Subject: [PATCH 288/371] Move MultiBuildPlateModel into Models folder --- cura/CuraApplication.py | 2 +- cura/Machines/Models/{Other => }/MultiBuildPlateModel.py | 0 cura/Machines/Models/Other/__init__.py | 0 cura/Scene/CuraSceneController.py | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename cura/Machines/Models/{Other => }/MultiBuildPlateModel.py (100%) delete mode 100644 cura/Machines/Models/Other/__init__.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a4e86626dc..2aa1f8db3a 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -60,7 +60,7 @@ from cura.Machines.Models.NozzleModel import NozzleModel from cura.Machines.Models.QualityProfilesModel import QualityProfilesModel from cura.Machines.Models.CustomQualityProfilesModel import CustomQualityProfilesModel -from cura.Machines.Models.Other.MultiBuildPlateModel import MultiBuildPlateModel +from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel diff --git a/cura/Machines/Models/Other/MultiBuildPlateModel.py b/cura/Machines/Models/MultiBuildPlateModel.py similarity index 100% rename from cura/Machines/Models/Other/MultiBuildPlateModel.py rename to cura/Machines/Models/MultiBuildPlateModel.py diff --git a/cura/Machines/Models/Other/__init__.py b/cura/Machines/Models/Other/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py index d60179ae08..749c5257a2 100644 --- a/cura/Scene/CuraSceneController.py +++ b/cura/Scene/CuraSceneController.py @@ -4,7 +4,7 @@ from PyQt5.QtCore import Qt, pyqtSlot, QObject from PyQt5.QtWidgets import QApplication from cura.ObjectsModel import ObjectsModel -from cura.Machines.Models.Other.MultiBuildPlateModel import MultiBuildPlateModel +from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel from UM.Application import Application from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator From 52da140833dd84e5a28c502e2a30fcf9e30e5d2d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:27:13 +0100 Subject: [PATCH 289/371] Add doc and copyright headers for MultiBuildPlateModel --- cura/Machines/Models/MultiBuildPlateModel.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cura/Machines/Models/MultiBuildPlateModel.py b/cura/Machines/Models/MultiBuildPlateModel.py index 78ad458a99..f0f4997014 100644 --- a/cura/Machines/Models/MultiBuildPlateModel.py +++ b/cura/Machines/Models/MultiBuildPlateModel.py @@ -1,3 +1,6 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + from PyQt5.QtCore import pyqtSignal, pyqtProperty from UM.Application import Application @@ -5,6 +8,10 @@ from UM.Scene.Selection import Selection from UM.Qt.ListModel import ListModel +# +# This is the model for multi build plate feature. +# This has nothing to do with the build plate types you can choose on the sidebar for a machine. +# class MultiBuildPlateModel(ListModel): maxBuildPlateChanged = pyqtSignal() From a395f93706d5eea2b4279b7c06bad55d773d1c36 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:28:58 +0100 Subject: [PATCH 290/371] Add docs for quality models --- cura/Machines/Models/QualityManagementModel.py | 3 +++ cura/Machines/Models/QualityProfilesModel.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py index 6e5b37bbfa..ab0101cfc6 100644 --- a/cura/Machines/Models/QualityManagementModel.py +++ b/cura/Machines/Models/QualityManagementModel.py @@ -6,6 +6,9 @@ from PyQt5.QtCore import Qt, pyqtSlot from UM.Qt.ListModel import ListModel +# +# This the QML model for the quality management page. +# class QualityManagementModel(ListModel): NameRole = Qt.UserRole + 1 IsReadOnlyRole = Qt.UserRole + 2 diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesModel.py index 3bfccd409d..6452f848ed 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesModel.py @@ -6,11 +6,12 @@ from PyQt5.QtCore import Qt from UM.Application import Application from UM.Logger import Logger from UM.Qt.ListModel import ListModel + from cura.Machines.QualityManager import QualityGroup # -# QML Model for all built-in quality profiles. +# QML Model for all built-in quality profiles. This model is used for the drop-down quality menu. # class QualityProfilesModel(ListModel): NameRole = Qt.UserRole + 1 From 06ec16d6271aadb59d1de5a3dc7b9b6706bbe9db Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:37:48 +0100 Subject: [PATCH 291/371] Rename quality drop down menu models --- cura/CuraApplication.py | 30 ++++++++++--------- ...CustomQualityProfilesDropDownMenuModel.py} | 4 +-- ...py => QualityProfilesDropDownMenuModel.py} | 2 +- resources/qml/Menus/ProfileMenu.qml | 10 +++---- resources/qml/SidebarSimple.qml | 18 +++++------ 5 files changed, 33 insertions(+), 31 deletions(-) rename cura/Machines/Models/{CustomQualityProfilesModel.py => CustomQualityProfilesDropDownMenuModel.py} (87%) rename cura/Machines/Models/{QualityProfilesModel.py => QualityProfilesDropDownMenuModel.py} (98%) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 2aa1f8db3a..de5d46ba96 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -57,8 +57,8 @@ from cura.Settings.MachineNameValidator import MachineNameValidator from cura.Machines.Models.BuildPlateModel import BuildPlateModel from cura.Machines.Models.NozzleModel import NozzleModel -from cura.Machines.Models.QualityProfilesModel import QualityProfilesModel -from cura.Machines.Models.CustomQualityProfilesModel import CustomQualityProfilesModel +from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel +from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel @@ -399,8 +399,8 @@ class CuraApplication(QtApplication): self.getCuraSceneController().setActiveBuildPlate(0) # Initialize - self._quality_profile_model = None - self._custom_quality_profile_model = None + self._quality_profile_drop_down_menu_model = None + self._custom_quality_profile_drop_down_menu_model = None CuraApplication.Created = True @@ -918,15 +918,15 @@ class CuraApplication(QtApplication): def getPrintInformation(self): return self._print_information - def getQualityProfileModel(self, *args, **kwargs): - if self._quality_profile_model is None: - self._quality_profile_model = QualityProfilesModel(self) - return self._quality_profile_model + def getQualityProfilesDropDownMenuModel(self, *args, **kwargs): + if self._quality_profile_drop_down_menu_model is None: + self._quality_profile_drop_down_menu_model = QualityProfilesDropDownMenuModel(self) + return self._quality_profile_drop_down_menu_model - def getCustomQualityProfilesModel(self, *args, **kwargs): - if self._custom_quality_profile_model is None: - self._custom_quality_profile_model = CustomQualityProfilesModel(self) - return self._custom_quality_profile_model + def getCustomQualityProfilesDropDownMenuModel(self, *args, **kwargs): + if self._custom_quality_profile_drop_down_menu_model is None: + self._custom_quality_profile_drop_down_menu_model = CustomQualityProfilesDropDownMenuModel(self) + return self._custom_quality_profile_drop_down_menu_model ## Registers objects for the QML engine to use. # @@ -960,8 +960,10 @@ class CuraApplication(QtApplication): qmlRegisterType(MaterialManagementModel, "Cura", 1, 0, "MaterialManagementModel") qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") - qmlRegisterSingletonType(QualityProfilesModel, "Cura", 1, 0, "QualityProfilesModel", self.getQualityProfileModel) - qmlRegisterSingletonType(CustomQualityProfilesModel, "Cura", 1, 0, "CustomQualityProfilesModel", self.getCustomQualityProfilesModel) + qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0, + "QualityProfilesDropDownMenuModel", self.getQualityProfilesDropDownMenuModel) + qmlRegisterSingletonType(CustomQualityProfilesDropDownMenuModel, "Cura", 1, 0, + "CustomQualityProfilesDropDownMenuModel", self.getCustomQualityProfilesDropDownMenuModel) qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") diff --git a/cura/Machines/Models/CustomQualityProfilesModel.py b/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py similarity index 87% rename from cura/Machines/Models/CustomQualityProfilesModel.py rename to cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py index 4c88d83fdc..f2b164703f 100644 --- a/cura/Machines/Models/CustomQualityProfilesModel.py +++ b/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py @@ -4,13 +4,13 @@ from UM.Application import Application from UM.Logger import Logger -from cura.Machines.Models.QualityProfilesModel import QualityProfilesModel +from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel # # This model is used for the custom profile items in the profile drop down menu. # -class CustomQualityProfilesModel(QualityProfilesModel): +class CustomQualityProfilesDropDownMenuModel(QualityProfilesDropDownMenuModel): def _update(self): Logger.log("d", "Updating %s ...", self.__class__.__name__) diff --git a/cura/Machines/Models/QualityProfilesModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py similarity index 98% rename from cura/Machines/Models/QualityProfilesModel.py rename to cura/Machines/Models/QualityProfilesDropDownMenuModel.py index 6452f848ed..30b8634294 100644 --- a/cura/Machines/Models/QualityProfilesModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -13,7 +13,7 @@ from cura.Machines.QualityManager import QualityGroup # # QML Model for all built-in quality profiles. This model is used for the drop-down quality menu. # -class QualityProfilesModel(ListModel): +class QualityProfilesDropDownMenuModel(ListModel): NameRole = Qt.UserRole + 1 QualityTypeRole = Qt.UserRole + 2 LayerHeightRole = Qt.UserRole + 3 diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index 5924ad5322..7a78b7a911 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -13,7 +13,7 @@ Menu Instantiator { - model: Cura.QualityProfilesModel + model: Cura.QualityProfilesDropDownMenuModel MenuItem { @@ -34,18 +34,18 @@ Menu MenuSeparator { id: customSeparator - visible: Cura.CustomQualityProfilesModel.rowCount > 0 + visible: Cura.CustomQualityProfilesDropDownMenuModel.rowCount > 0 } Instantiator { id: customProfileInstantiator - model: Cura.CustomQualityProfilesModel + model: Cura.CustomQualityProfilesDropDownMenuModel Connections { - target: Cura.CustomQualityProfilesModel - onModelReset: customSeparator.visible = Cura.CustomQualityProfilesModel.rowCount() > 0 + target: Cura.CustomQualityProfilesDropDownMenuModel + onModelReset: customSeparator.visible = Cura.CustomQualityProfilesDropDownMenuModel.rowCount() > 0 } MenuItem diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 507091a721..fa8f253452 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -58,7 +58,7 @@ Item running: false repeat: false onTriggered: { - var item = Cura.QualityProfilesModel.getItem(qualitySlider.value); + var item = Cura.QualityProfilesDropDownMenuModel.getItem(qualitySlider.value); Cura.MachineManager.activeQualityGroup = item.quality_group; } } @@ -105,8 +105,8 @@ Item var availableMin = -1 var availableMax = -1 - for (var i = 0; i < Cura.QualityProfilesModel.rowCount(); i++) { - var qualityItem = Cura.QualityProfilesModel.getItem(i) + for (var i = 0; i < Cura.QualityProfilesDropDownMenuModel.rowCount(); i++) { + var qualityItem = Cura.QualityProfilesDropDownMenuModel.getItem(i) // Add each quality item to the UI quality model qualityModel.append(qualityItem) @@ -168,7 +168,7 @@ Item qualityModel.existingQualityProfile = 0 // check, the ticks count cannot be less than zero - qualityModel.totalTicks = Math.max(0, Cura.QualityProfilesModel.rowCount() - 1) + qualityModel.totalTicks = Math.max(0, Cura.QualityProfilesDropDownMenuModel.rowCount() - 1) } } @@ -194,13 +194,13 @@ Item anchors.verticalCenter: parent.verticalCenter anchors.top: parent.top anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) - color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesDropDownMenuModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") text: { var result = "" if(Cura.MachineManager.activeMachine != null) { - result = Cura.QualityProfilesModel.getItem(index).layer_height_without_unit + result = Cura.QualityProfilesDropDownMenuModel.getItem(index).layer_height_without_unit if(result == undefined) { @@ -265,7 +265,7 @@ Item Rectangle { anchors.verticalCenter: parent.verticalCenter - color: Cura.QualityProfilesModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") + color: Cura.QualityProfilesDropDownMenuModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") width: 1 * screenScaleFactor height: 6 * screenScaleFactor y: 0 @@ -403,9 +403,9 @@ Item // if the current profile is user-created, switch to a built-in quality if (Cura.SimpleModeSettingsManager.isProfileUserCreated) { - if (Cura.QualityProfilesModel.rowCount() > 0) + if (Cura.QualityProfilesDropDownMenuModel.rowCount() > 0) { - var item = Cura.QualityProfilesModel.getItem(0); + var item = Cura.QualityProfilesDropDownMenuModel.getItem(0); Cura.MachineManager.activeQualityGroup = item.quality_group; } } From d1c518f6d7882426a1306b4fe50a995b3acd6030 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:44:06 +0100 Subject: [PATCH 292/371] Fix the usage of protected variables in quality models --- .../CustomQualityProfilesDropDownMenuModel.py | 3 +-- cura/Machines/Models/QualityManagementModel.py | 4 ++-- .../Models/QualityProfilesDropDownMenuModel.py | 17 +++++++++-------- cura/Machines/Models/QualitySettingsModel.py | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py b/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py index f2b164703f..0d297379cd 100644 --- a/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py @@ -1,7 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from UM.Application import Application from UM.Logger import Logger from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel @@ -15,7 +14,7 @@ class CustomQualityProfilesDropDownMenuModel(QualityProfilesDropDownMenuModel): def _update(self): Logger.log("d", "Updating %s ...", self.__class__.__name__) - active_global_stack = Application.getInstance().getMachineManager().activeMachine + active_global_stack = self._machine_manager.activeMachine if active_global_stack is None: self.setItems([]) Logger.log("d", "No active GlobalStack, set %s as empty.", self.__class__.__name__) diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py index ab0101cfc6..a3c321815a 100644 --- a/cura/Machines/Models/QualityManagementModel.py +++ b/cura/Machines/Models/QualityManagementModel.py @@ -27,7 +27,7 @@ class QualityManagementModel(ListModel): self._container_registry = CuraApplication.getInstance().getContainerRegistry() self._machine_manager = CuraApplication.getInstance().getMachineManager() self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._quality_manager = CuraApplication.getInstance()._quality_manager + self._quality_manager = CuraApplication.getInstance().getQualityManager() self._machine_manager.globalContainerChanged.connect(self._update) self._quality_manager.qualitiesUpdated.connect(self._update) @@ -35,7 +35,7 @@ class QualityManagementModel(ListModel): self._update() def _update(self): - global_stack = self._machine_manager._global_container_stack + global_stack = self._machine_manager.activeMachine quality_group_dict = self._quality_manager.getQualityGroups(global_stack) quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(global_stack) diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py index 30b8634294..9e38184ce7 100644 --- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -33,11 +33,13 @@ class QualityProfilesDropDownMenuModel(ListModel): self.addRoleName(self.QualityGroupRole, "quality_group") self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") - # connect signals - Application.getInstance().globalContainerStackChanged.connect(self._update) - Application.getInstance().getMachineManager().activeQualityGroupChanged.connect(self._update) + self._application = Application.getInstance() + self._machine_manager = self._application.getMachineManager() + self._quality_manager = Application.getInstance().getQualityManager() - self._quality_manager = Application.getInstance()._quality_manager + # connect signals + self._application.globalContainerStackChanged.connect(self._update) + self._machine_manager.activeQualityGroupChanged.connect(self._update) self._quality_manager.qualitiesUpdated.connect(self._update) self._layer_height_unit = "" # This is cached @@ -47,15 +49,14 @@ class QualityProfilesDropDownMenuModel(ListModel): def _update(self): Logger.log("d", "Updating quality profile model ...") - machine_manager = Application.getInstance().getMachineManager() - global_stack = machine_manager._global_container_stack + global_stack = self._machine_manager.activeMachine if global_stack is None: self.setItems([]) Logger.log("d", "No active GlobalStack, set quality profile model as empty.") return # Check for material compatibility - if not machine_manager.activeMaterialsCompatible(): + if not self._machine_manager.activeMaterialsCompatible(): self.setItems([]) return @@ -82,7 +83,7 @@ class QualityProfilesDropDownMenuModel(ListModel): self.setItems(item_list) def _fetchLayerHeight(self, quality_group: "QualityGroup"): - global_stack = Application.getInstance().getMachineManager()._global_container_stack + global_stack = self._machine_manager.activeMachine if not self._layer_height_unit: unit = global_stack.definition.getProperty("layer_height", "unit") if not unit: diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index a62654ad2c..9e18261d32 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -33,7 +33,7 @@ class QualitySettingsModel(ListModel): self._container_registry = ContainerRegistry.getInstance() self._application = Application.getInstance() - self._quality_manager = self._application._quality_manager + self._quality_manager = self._application.getQualityManager() self._extruder_position = "" self._selected_quality_item = None # The selected quality in the quality management page @@ -73,7 +73,7 @@ class QualitySettingsModel(ListModel): items = [] - global_container_stack = Application.getInstance().getGlobalContainerStack() + global_container_stack = self._application.getGlobalContainerStack() definition_container = global_container_stack.definition quality_group = self._selected_quality_item["quality_group"] From b74e2553e79453caef751dcaa80827033b662b61 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:47:52 +0100 Subject: [PATCH 293/371] Use more descriptive variable names --- cura/Machines/Models/QualityManagementModel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py index a3c321815a..e089f92329 100644 --- a/cura/Machines/Models/QualityManagementModel.py +++ b/cura/Machines/Models/QualityManagementModel.py @@ -40,7 +40,8 @@ class QualityManagementModel(ListModel): quality_group_dict = self._quality_manager.getQualityGroups(global_stack) quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(global_stack) - available_quality_types = set(qt for qt, qg in quality_group_dict.items() if qg.is_available) + available_quality_types = set(quality_type for quality_type, quality_group in quality_group_dict.items() + if quality_group.is_available) if not available_quality_types and not quality_changes_group_dict: # Nothing to show self.setItems([]) From e87077802f941f0435b3730901fbbc7b75fa7e7e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 15:55:44 +0100 Subject: [PATCH 294/371] Change to layer_height and layer_height_unit --- .../Models/QualityProfilesDropDownMenuModel.py | 10 +++++----- resources/qml/Menus/ProfileMenu.qml | 2 +- resources/qml/SidebarSimple.qml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py index 9e38184ce7..8fd6f2afb7 100644 --- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -17,7 +17,7 @@ class QualityProfilesDropDownMenuModel(ListModel): NameRole = Qt.UserRole + 1 QualityTypeRole = Qt.UserRole + 2 LayerHeightRole = Qt.UserRole + 3 - LayerHeightWithoutUnitRole = Qt.UserRole + 4 + LayerHeightUnitRole = Qt.UserRole + 4 AvailableRole = Qt.UserRole + 5 QualityGroupRole = Qt.UserRole + 6 QualityChangesGroupRole = Qt.UserRole + 7 @@ -28,7 +28,7 @@ class QualityProfilesDropDownMenuModel(ListModel): self.addRoleName(self.NameRole, "name") self.addRoleName(self.QualityTypeRole, "quality_type") self.addRoleName(self.LayerHeightRole, "layer_height") - self.addRoleName(self.LayerHeightWithoutUnitRole, "layer_height_without_unit") + self.addRoleName(self.LayerHeightUnitRole, "layer_height_unit") self.addRoleName(self.AvailableRole, "available") self.addRoleName(self.QualityGroupRole, "quality_group") self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") @@ -70,15 +70,15 @@ class QualityProfilesDropDownMenuModel(ListModel): item = {"name": quality_group.name, "quality_type": quality_group.quality_type, - "layer_height": layer_height + self._layer_height_unit, - "layer_height_without_unit": layer_height, + "layer_height": layer_height, + "layer_height_unit": self._layer_height_unit, "available": quality_group.is_available, "quality_group": quality_group} item_list.append(item) # Sort items based on layer_height - item_list = sorted(item_list, key = lambda x: float(x["layer_height_without_unit"])) + item_list = sorted(item_list, key = lambda x: float(x["layer_height"])) self.setItems(item_list) diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index 7a78b7a911..19461f6005 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -17,7 +17,7 @@ Menu MenuItem { - text: (model.layer_height != "") ? model.name + " - " + model.layer_height : model.name + text: (model.layer_height != "") ? model.name + " - " + model.layer_height + model.layer_height_unit : model.name checkable: true checked: Cura.MachineManager.activeQualityOrQualityChangesName == model.name exclusiveGroup: group diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index fa8f253452..1991a9fa57 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -200,7 +200,7 @@ Item var result = "" if(Cura.MachineManager.activeMachine != null) { - result = Cura.QualityProfilesDropDownMenuModel.getItem(index).layer_height_without_unit + result = Cura.QualityProfilesDropDownMenuModel.getItem(index).layer_height if(result == undefined) { From afae550b5a48e16e3efeebb8fee7cd4e0ccc02db Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 16:00:46 +0100 Subject: [PATCH 295/371] Store layer_height as float --- cura/Machines/Models/QualityProfilesDropDownMenuModel.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py index 8fd6f2afb7..d3135b31c6 100644 --- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -78,7 +78,7 @@ class QualityProfilesDropDownMenuModel(ListModel): item_list.append(item) # Sort items based on layer_height - item_list = sorted(item_list, key = lambda x: float(x["layer_height"])) + item_list = sorted(item_list, key = lambda x: x["layer_height"]) self.setItems(item_list) @@ -97,10 +97,10 @@ class QualityProfilesDropDownMenuModel(ListModel): layer_height = default_layer_height if container.hasProperty("layer_height", "value"): - layer_height = str(container.getProperty("layer_height", "value")) + layer_height = container.getProperty("layer_height", "value") else: # Look for layer_height in the GlobalStack from material -> definition container = global_stack.definition if container.hasProperty("layer_height", "value"): layer_height = container.getProperty("layer_height", "value") - return str(layer_height) + return float(layer_height) From 71e84784191abe2d0b3cf51cb0017a2f498ef695 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 16:26:12 +0100 Subject: [PATCH 296/371] Rename to selected_position --- cura/Machines/Models/QualitySettingsModel.py | 33 ++++++++++---------- resources/qml/Preferences/ProfileTab.qml | 2 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index 9e18261d32..1221b1b14b 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -35,7 +35,8 @@ class QualitySettingsModel(ListModel): self._application = Application.getInstance() self._quality_manager = self._application.getQualityManager() - self._extruder_position = "" + self._selected_position = "" # empty string means GlobalStack + # strings such as "0", "1", etc. mean extruder positions self._selected_quality_item = None # The selected quality in the quality management page self._i18n_catalog = None @@ -43,18 +44,18 @@ class QualitySettingsModel(ListModel): self._update() - extruderPositionChanged = pyqtSignal() + selectedPositionChanged = pyqtSignal() selectedQualityItemChanged = pyqtSignal() - def setExtruderPosition(self, extruder_position): - if extruder_position != self._extruder_position: - self._extruder_position = extruder_position - self.extruderPositionChanged.emit() + def setSelectedPosition(self, selected_position): + if selected_position != self._selected_position: + self._selected_position = selected_position + self.selectedPositionChanged.emit() self._update() - @pyqtProperty(str, fset = setExtruderPosition, notify = extruderPositionChanged) - def extruderPosition(self): - return self._extruder_position + @pyqtProperty(str, fset = setSelectedPosition, notify = selectedPositionChanged) + def selectedPosition(self): + return self._selected_position def setSelectedQualityItem(self, selected_quality_item): if selected_quality_item != self._selected_quality_item: @@ -79,18 +80,18 @@ class QualitySettingsModel(ListModel): quality_group = self._selected_quality_item["quality_group"] quality_changes_group = self._selected_quality_item["quality_changes_group"] - if self._extruder_position == "": + if self._selected_position == "": quality_node = quality_group.node_for_global else: - quality_node = quality_group.nodes_for_extruders.get(self._extruder_position) + quality_node = quality_group.nodes_for_extruders.get(self._selected_position) settings_keys = quality_group.getAllKeys() quality_containers = [quality_node.getContainer()] if quality_changes_group is not None: - if self._extruder_position == "": + if self._selected_position == "": quality_changes_node = quality_changes_group.node_for_global else: - quality_changes_node = quality_changes_group.nodes_for_extruders.get(self._extruder_position) + quality_changes_node = quality_changes_group.nodes_for_extruders.get(self._selected_position) if quality_changes_node is not None: # it can be None if number of extruders are changed during runtime try: quality_containers.insert(0, quality_changes_node.getContainer()) @@ -117,7 +118,7 @@ class QualitySettingsModel(ListModel): profile_value = new_value # Global tab should use resolve (if there is one) - if self._extruder_position == "": + if self._selected_position == "": resolve_value = global_container_stack.getProperty(definition.key, "resolve") if resolve_value is not None and definition.key in settings_keys: profile_value = resolve_value @@ -125,10 +126,10 @@ class QualitySettingsModel(ListModel): if profile_value is not None: break - if not self._extruder_position: + if not self._selected_position: user_value = global_container_stack.userChanges.getProperty(definition.key, "value") else: - extruder_stack = global_container_stack.extruders[self._extruder_position] + extruder_stack = global_container_stack.extruders[self._selected_position] user_value = extruder_stack.userChanges.getProperty(definition.key, "value") if profile_value is None and user_value is None: diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml index 82671f306f..dcabf012b7 100644 --- a/resources/qml/Preferences/ProfileTab.qml +++ b/resources/qml/Preferences/ProfileTab.qml @@ -85,7 +85,7 @@ Tab model: Cura.QualitySettingsModel { id: qualitySettings - extruderPosition: base.extruderPosition + selectedPosition: base.extruderPosition selectedQualityItem: base.qualityItem } From 59f31c9fe06a80d9b637fd0ee4257fb85f8613bc Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 16:29:56 +0100 Subject: [PATCH 297/371] Add doc for quality settings model grouping --- cura/Machines/Models/QualitySettingsModel.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index 1221b1b14b..b1f30e84ee 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -100,6 +100,9 @@ class QualitySettingsModel(ListModel): return settings_keys.update(quality_changes_group.getAllKeys()) + # We iterate over all definitions instead of settings in a quality/qualtiy_changes group is because in the GUI, + # the settings are grouped together by categories, and we had to go over all the definitions to figure out + # which setting belongs in which category. current_category = "" for definition in definition_container.findDefinitions(): if definition.type == "category": From 31d1a3b5dbec39ea93cf78e0117dddfcce944d9b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 16:31:00 +0100 Subject: [PATCH 298/371] Code style fix --- cura/Machines/MaterialGroup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Machines/MaterialGroup.py b/cura/Machines/MaterialGroup.py index 9111cc3a80..009778943a 100644 --- a/cura/Machines/MaterialGroup.py +++ b/cura/Machines/MaterialGroup.py @@ -1,6 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. + # # A MaterialGroup represents a group of material InstanceContainers that are derived from a single material profile. # The main InstanceContainer which has the ID of the material profile file name is called the "root_material". For From 97059daf6ab0e7e1d209efaf770424375ef49153 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 1 Mar 2018 16:37:01 +0100 Subject: [PATCH 299/371] Separate quality manager related classes into separate files --- cura/Machines/QualityChangesGroup.py | 53 +++++++++++ cura/Machines/QualityGroup.py | 51 +++++++++++ cura/Machines/QualityManager.py | 129 +-------------------------- cura/Machines/QualityNode.py | 35 ++++++++ 4 files changed, 143 insertions(+), 125 deletions(-) create mode 100644 cura/Machines/QualityChangesGroup.py create mode 100644 cura/Machines/QualityGroup.py create mode 100644 cura/Machines/QualityNode.py diff --git a/cura/Machines/QualityChangesGroup.py b/cura/Machines/QualityChangesGroup.py new file mode 100644 index 0000000000..f8de3d2011 --- /dev/null +++ b/cura/Machines/QualityChangesGroup.py @@ -0,0 +1,53 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.Application import Application + +from .QualityGroup import QualityGroup + + +class QualityChangesGroup(QualityGroup): + + def __init__(self, name: str, quality_type: str, parent = None): + super().__init__(name, quality_type, parent) + self._container_registry = Application.getInstance().getContainerRegistry() + + def addNode(self, node: "QualityNode"): + # TODO: in 3.2 and earlier, a quality_changes container may have a field called "extruder" which contains the + # extruder definition ID it belongs to. But, in fact, we only need to know the following things: + # 1. which machine a custom profile is suitable for, + # 2. if this profile is for the GlobalStack, + # 3. if this profile is for an ExtruderStack and which one (the position). + # + # So, it is preferred to have a field like this: + # extruder_position = 1 + # instead of this: + # extruder = custom_extruder_1 + # + # An upgrade needs to be done if we want to do it this way. Before that, we use the extruder's definition + # to figure out its position. + # + extruder_definition_id = node.metadata.get("extruder") + if extruder_definition_id: + metadata_list = self._container_registry.findDefinitionContainersMetadata(id = extruder_definition_id) + if not metadata_list: + raise RuntimeError("%s cannot get metadata for extruder definition [%s]" % + (self, extruder_definition_id)) + extruder_definition_metadata = metadata_list[0] + extruder_position = str(extruder_definition_metadata["position"]) + + if extruder_position in self.nodes_for_extruders: + raise RuntimeError("%s tries to overwrite the existing nodes_for_extruders position [%s] %s with %s" % + (self, extruder_position, self.node_for_global, node)) + + self.nodes_for_extruders[extruder_position] = node + + else: + # This is a quality_changes for the GlobalStack + if self.node_for_global is not None: + raise RuntimeError("%s tries to overwrite the existing node_for_global %s with %s" % + (self, self.node_for_global, node)) + self.node_for_global = node + + def __str__(self) -> str: + return "%s[<%s>, available = %s]" % (self.__class__.__name__, self.name, self.is_available) diff --git a/cura/Machines/QualityGroup.py b/cura/Machines/QualityGroup.py new file mode 100644 index 0000000000..6067f04038 --- /dev/null +++ b/cura/Machines/QualityGroup.py @@ -0,0 +1,51 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from typing import Optional, List + +from PyQt5.QtCore import QObject, pyqtSlot + + +# +# A QualityGroup represents a group of containers that must be applied to each ContainerStack when it's used. +# Some concrete examples are Quality and QualityChanges: when we select quality type "normal", this quality type +# must be applied to all stacks in a machine, although each stack can have different containers. Use an Ultimaker 3 +# as an example, suppose we choose quality type "normal", the actual InstanceContainers on each stack may look +# as below: +# GlobalStack ExtruderStack 1 ExtruderStack 2 +# quality container: um3_global_normal um3_aa04_pla_normal um3_aa04_abs_normal +# +# This QualityGroup is mainly used in quality and quality_changes to group the containers that can be applied to +# a machine, so when a quality/custom quality is selected, the container can be directly applied to each stack instead +# of looking them up again. +# +class QualityGroup(QObject): + + def __init__(self, name: str, quality_type: str, parent = None): + super().__init__(parent) + self.name = name + self.node_for_global = None # type: Optional["QualityGroup"] + self.nodes_for_extruders = dict() # position str -> QualityGroup + self.quality_type = quality_type + self.is_available = False + + @pyqtSlot(result = str) + def getName(self) -> str: + return self.name + + def getAllKeys(self) -> set: + result = set() + for node in [self.node_for_global] + list(self.nodes_for_extruders.values()): + if node is None: + continue + for key in node.getContainer().getAllKeys(): + result.add(key) + return result + + def getAllNodes(self) -> List["QualityGroup"]: + result = [] + if self.node_for_global is not None: + result.append(self.node_for_global) + for extruder_node in self.nodes_for_extruders.values(): + result.append(extruder_node) + return result diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 90ba7d8da3..e587816dff 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -1,16 +1,14 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Optional, List - -from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot +from PyQt5.QtCore import QObject, QTimer, pyqtSignal from UM.Application import Application from UM.Logger import Logger from UM.Util import parseBool -from cura.Machines.ContainerNode import ContainerNode - +from .QualityGroup import QualityGroup +from .QualityNode import QualityNode # # Quality lookup tree structure: @@ -27,125 +25,6 @@ from cura.Machines.ContainerNode import ContainerNode # + # -# -# A QualityGroup represents a group of containers that must be applied to each ContainerStack when it's used. -# Some concrete examples are Quality and QualityChanges: when we select quality type "normal", this quality type -# must be applied to all stacks in a machine, although each stack can have different containers. Use an Ultimaker 3 -# as an example, suppose we choose quality type "normal", the actual InstanceContainers on each stack may look -# as below: -# GlobalStack ExtruderStack 1 ExtruderStack 2 -# quality container: um3_global_normal um3_aa04_pla_normal um3_aa04_abs_normal -# -# This QualityGroup is mainly used in quality and quality_changes to group the containers that can be applied to -# a machine, so when a quality/custom quality is selected, the container can be directly applied to each stack instead -# of looking them up again. -# -class QualityGroup(QObject): - - def __init__(self, name: str, quality_type: str, parent = None): - super().__init__(parent) - self.name = name - self.node_for_global = None # type: Optional["QualityGroup"] - self.nodes_for_extruders = dict() # position str -> QualityGroup - self.quality_type = quality_type - self.is_available = False - - @pyqtSlot(result = str) - def getName(self) -> str: - return self.name - - def getAllKeys(self) -> set: - result = set() - for node in [self.node_for_global] + list(self.nodes_for_extruders.values()): - if node is None: - continue - for key in node.getContainer().getAllKeys(): - result.add(key) - return result - - def getAllNodes(self) -> List["QualityGroup"]: - result = [] - if self.node_for_global is not None: - result.append(self.node_for_global) - for extruder_node in self.nodes_for_extruders.values(): - result.append(extruder_node) - return result - - -class QualityChangesGroup(QualityGroup): - - def __init__(self, name: str, quality_type: str, parent = None): - super().__init__(name, quality_type, parent) - - def addNode(self, node: "QualityNode"): - # TODO: in 3.2 and earlier, a quality_changes container may have a field called "extruder" which contains the - # extruder definition ID it belongs to. But, in fact, we only need to know the following things: - # 1. which machine a custom profile is suitable for, - # 2. if this profile is for the GlobalStack, - # 3. if this profile is for an ExtruderStack and which one (the position). - # - # So, it is preferred to have a field like this: - # extruder_position = 1 - # instead of this: - # extruder = custom_extruder_1 - # - # An upgrade needs to be done if we want to do it this way. Before that, we use the extruder's definition - # to figure out its position. - # - extruder_definition_id = node.metadata.get("extruder") - if extruder_definition_id: - container_registry = Application.getInstance().getContainerRegistry() - metadata_list = container_registry.findDefinitionContainersMetadata(id = extruder_definition_id) - if not metadata_list: - raise RuntimeError("%s cannot get metadata for extruder definition [%s]" % - (self, extruder_definition_id)) - extruder_definition_metadata = metadata_list[0] - extruder_position = str(extruder_definition_metadata["position"]) - - if extruder_position in self.nodes_for_extruders: - raise RuntimeError("%s tries to overwrite the existing nodes_for_extruders position [%s] %s with %s" % - (self, extruder_position, self.node_for_global, node)) - - self.nodes_for_extruders[extruder_position] = node - - else: - # This is a quality_changes for the GlobalStack - if self.node_for_global is not None: - raise RuntimeError("%s tries to overwrite the existing node_for_global %s with %s" % - (self, self.node_for_global, node)) - self.node_for_global = node - - def __str__(self) -> str: - return "%s[<%s>, available = %s]" % (self.__class__.__name__, self.name, self.is_available) - - -# -# QualityNode is used for BOTH quality and quality_changes containers. -# -class QualityNode(ContainerNode): - - def __init__(self, metadata: Optional[dict] = None): - super().__init__(metadata = metadata) - self.quality_type_map = {} # quality_type -> QualityNode for InstanceContainer - - def addQualityMetadata(self, quality_type: str, metadata: dict): - if quality_type not in self.quality_type_map: - self.quality_type_map[quality_type] = QualityNode(metadata) - - def getQualityNode(self, quality_type: str) -> Optional["QualityNode"]: - return self.quality_type_map.get(quality_type) - - def addQualityChangesMetadata(self, quality_type: str, metadata: dict): - if quality_type not in self.quality_type_map: - self.quality_type_map[quality_type] = QualityNode() - quality_type_node = self.quality_type_map[quality_type] - - name = metadata["name"] - if name not in quality_type_node.children_map: - quality_type_node.children_map[name] = QualityChangesGroup(name, quality_type) - quality_changes_group = quality_type_node.children_map[name] - quality_changes_group.addNode(QualityNode(metadata)) - # # Similar to MaterialManager, QualityManager maintains a number of maps and trees for material lookup. @@ -164,7 +43,7 @@ class QualityManager(QObject): def __init__(self, container_registry, parent = None): super().__init__(parent) self._application = Application.getInstance() - self._material_manager = self._application._material_manager + self._material_manager = self._application.getMaterialManager() self._container_registry = container_registry self._empty_quality_container = self._application.empty_quality_container diff --git a/cura/Machines/QualityNode.py b/cura/Machines/QualityNode.py new file mode 100644 index 0000000000..a30e219da3 --- /dev/null +++ b/cura/Machines/QualityNode.py @@ -0,0 +1,35 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from typing import Optional + +from .ContainerNode import ContainerNode +from .QualityChangesGroup import QualityChangesGroup + + +# +# QualityNode is used for BOTH quality and quality_changes containers. +# +class QualityNode(ContainerNode): + + def __init__(self, metadata: Optional[dict] = None): + super().__init__(metadata = metadata) + self.quality_type_map = {} # quality_type -> QualityNode for InstanceContainer + + def addQualityMetadata(self, quality_type: str, metadata: dict): + if quality_type not in self.quality_type_map: + self.quality_type_map[quality_type] = QualityNode(metadata) + + def getQualityNode(self, quality_type: str) -> Optional["QualityNode"]: + return self.quality_type_map.get(quality_type) + + def addQualityChangesMetadata(self, quality_type: str, metadata: dict): + if quality_type not in self.quality_type_map: + self.quality_type_map[quality_type] = QualityNode() + quality_type_node = self.quality_type_map[quality_type] + + name = metadata["name"] + if name not in quality_type_node.children_map: + quality_type_node.children_map[name] = QualityChangesGroup(name, quality_type) + quality_changes_group = quality_type_node.children_map[name] + quality_changes_group.addNode(QualityNode(metadata)) From feb314387438b93237f51ecc4ea8b7d824243551 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 1 Mar 2018 17:51:51 +0100 Subject: [PATCH 300/371] CURA-5032 Settings for settings visibility Settings groups now match specification. --- .../advanced.cfg | 182 ++++-------------- .../basic.cfg | 30 ++- .../expert.cfg | 153 +++++++++++++-- 3 files changed, 178 insertions(+), 187 deletions(-) diff --git a/resources/preset_setting_visibility_groups/advanced.cfg b/resources/preset_setting_visibility_groups/advanced.cfg index 3bbe0ce065..e68ee787f5 100644 --- a/resources/preset_setting_visibility_groups/advanced.cfg +++ b/resources/preset_setting_visibility_groups/advanced.cfg @@ -8,120 +8,71 @@ weight = 2 layer_height layer_height_0 line_width +wall_line_width +wall_line_width_0 +wall_line_width_x +skin_line_width +infill_line_width +initial_layer_line_width_factor [shell] wall_extruder_nr +wall_0_extruder_nr +wall_x_extruder_nr wall_thickness -wall_0_wipe_dist -roofing_extruder_nr -roofing_layer_count +wall_line_count top_bottom_extruder_nr top_bottom_thickness -top_bottom_pattern -top_bottom_pattern_0 -skin_angles -wall_0_inset +top_thickness +top_layers +bottom_thickness +bottom_layers 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_line_distance 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_infill +speed_wall +speed_wall_0 +speed_wall_x +speed_topbottom +speed_support +speed_prime_tower 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 @@ -130,9 +81,12 @@ retraction_hop_after_extruder_switch [cooling] cool_fan_enabled cool_fan_speed +cool_fan_speed_min +cool_fan_speed_max cool_min_layer_time_fan_speed_max cool_fan_speed_0 cool_fan_full_at_height +cool_fan_full_layer cool_min_layer_time cool_min_speed cool_lift_head @@ -140,115 +94,45 @@ cool_lift_head [support] support_enable support_extruder_nr +support_infill_extruder_nr +support_extruder_nr_layer_0 +support_interface_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 +support_roof_enable +support_bottom_enable [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_line_count 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 +conical_overhang_enabled +support_conical_enabled +adaptive_layer_height_enabled diff --git a/resources/preset_setting_visibility_groups/basic.cfg b/resources/preset_setting_visibility_groups/basic.cfg index 062feb9189..4196a3a9e7 100644 --- a/resources/preset_setting_visibility_groups/basic.cfg +++ b/resources/preset_setting_visibility_groups/basic.cfg @@ -9,30 +9,28 @@ layer_height [shell] wall_thickness +wall_line_count top_bottom_thickness -z_seam_x -z_seam_y +top_thickness +top_layers +bottom_thickness +bottom_layers +xy_offset [infill] infill_sparse_density -gradual_infill_steps +infill_pattern [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] +retraction_hop_enabled [cooling] cool_fan_enabled @@ -41,26 +39,20 @@ cool_fan_enabled support_enable support_extruder_nr support_type +support_angle [platform_adhesion] +prime_blob_enable 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] \ No newline at end of file +[experimental] diff --git a/resources/preset_setting_visibility_groups/expert.cfg b/resources/preset_setting_visibility_groups/expert.cfg index 1be5ca7804..0cd9adfd46 100644 --- a/resources/preset_setting_visibility_groups/expert.cfg +++ b/resources/preset_setting_visibility_groups/expert.cfg @@ -8,15 +8,33 @@ weight = 3 layer_height layer_height_0 line_width +wall_line_width +wall_line_width_0 +wall_line_width_x +skin_line_width +infill_line_width +skirt_brim_line_width +support_line_width +support_interface_line_width +support_roof_line_width +support_bottom_line_width +prime_tower_line_width +initial_layer_line_width_factor [shell] wall_extruder_nr +wall_0_extruder_nr +wall_x_extruder_nr wall_thickness +wall_line_count wall_0_wipe_dist -roofing_extruder_nr roofing_layer_count top_bottom_extruder_nr top_bottom_thickness +top_thickness +top_layers +bottom_thickness +bottom_layers top_bottom_pattern top_bottom_pattern_0 skin_angles @@ -25,6 +43,8 @@ optimize_wall_printing_order outer_inset_first alternate_extra_perimeter travel_compensate_overlapping_walls_enabled +travel_compensate_overlapping_walls_0_enabled +travel_compensate_overlapping_walls_x_enabled fill_perimeter_gaps filter_out_tiny_gaps fill_outline_gaps @@ -50,6 +70,7 @@ jerk_ironing [infill] infill_extruder_nr infill_sparse_density +infill_line_distance infill_pattern zig_zaggify_infill infill_angles @@ -57,7 +78,9 @@ infill_offset_x infill_offset_y sub_div_rad_add infill_overlap +infill_overlap_mm skin_overlap +skin_overlap_mm infill_wipe_dist infill_sparse_thickness gradual_infill_steps @@ -65,8 +88,13 @@ gradual_infill_step_height infill_before_walls min_infill_area skin_preshrink +top_skin_preshrink +bottom_skin_preshrink expand_skins_expand_distance +top_skin_expand_distance +bottom_skin_expand_distance max_skin_angle_for_expansion +min_skin_width_for_expansion [material] default_material_print_temperature @@ -75,7 +103,6 @@ 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 @@ -86,6 +113,8 @@ retraction_enable retract_at_layer_change retraction_amount retraction_speed +retraction_retract_speed +retraction_prime_speed retraction_extra_prime_amount retraction_min_travel retraction_count_max @@ -93,11 +122,25 @@ retraction_extrusion_window material_standby_temperature switch_extruder_retraction_amount switch_extruder_retraction_speeds +switch_extruder_retraction_speed +switch_extruder_prime_speed [speed] speed_print +speed_infill +speed_wall +speed_wall_0 +speed_wall_x +speed_roofing +speed_topbottom +speed_support +speed_support_infill +speed_support_interface +speed_prime_tower speed_travel speed_layer_0 +speed_print_layer_0 +speed_travel_layer_0 skirt_brim_speed max_feedrate_z_override speed_slowdown_layers @@ -105,13 +148,37 @@ speed_equalize_flow_enabled speed_equalize_flow_max acceleration_enabled acceleration_print +acceleration_infill +acceleration_wall +acceleration_wall_0 +acceleration_wall_x +acceleration_roofing +acceleration_topbottom +acceleration_support +acceleration_support_infill +acceleration_support_interface +acceleration_prime_tower acceleration_travel acceleration_layer_0 +acceleration_print_layer_0 +acceleration_travel_layer_0 acceleration_skirt_brim jerk_enabled jerk_print +jerk_infill +jerk_wall +jerk_wall_0 +jerk_wall_x +jerk_roofing +jerk_topbottom +jerk_support +jerk_support_infill +jerk_support_interface +jerk_prime_tower jerk_travel jerk_layer_0 +jerk_print_layer_0 +jerk_travel_layer_0 jerk_skirt_brim [travel] @@ -130,9 +197,12 @@ retraction_hop_after_extruder_switch [cooling] cool_fan_enabled cool_fan_speed +cool_fan_speed_min +cool_fan_speed_max cool_min_layer_time_fan_speed_max cool_fan_speed_0 cool_fan_full_at_height +cool_fan_full_layer cool_min_layer_time cool_min_speed cool_lift_head @@ -140,12 +210,20 @@ cool_lift_head [support] support_enable support_extruder_nr +support_infill_extruder_nr +support_extruder_nr_layer_0 +support_interface_extruder_nr +support_roof_extruder_nr +support_bottom_extruder_nr support_type support_angle support_pattern support_connect_zigzags support_infill_rate +support_line_distance support_z_distance +support_top_distance +support_bottom_distance support_xy_distance support_xy_overrides_z support_xy_distance_overhang @@ -157,9 +235,15 @@ support_infill_sparse_thickness gradual_support_infill_steps gradual_support_infill_step_height support_interface_enable +support_roof_enable +support_bottom_enable support_interface_height +support_roof_height +support_bottom_height support_interface_skip_height support_interface_density +support_roof_density +support_bottom_density support_interface_pattern support_use_towers support_tower_diameter @@ -169,19 +253,17 @@ 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_line_count brim_outside_only raft_margin raft_smoothing raft_airgap -layer_0_z_overlap raft_surface_layers raft_surface_thickness raft_surface_line_width @@ -201,6 +283,7 @@ raft_fan_speed prime_tower_enable prime_tower_size prime_tower_min_volume +prime_tower_wall_thickness prime_tower_position_x prime_tower_position_y prime_tower_flow @@ -238,8 +321,25 @@ smooth_spiralized_contours relative_extrusion [experimental] +support_tree_enable +support_tree_angle +support_tree_branch_distance +support_tree_branch_diameter +support_tree_branch_diameter_angle +support_tree_collision_resolution +support_tree_wall_thickness +support_tree_wall_count +slicing_tolerance +roofing_line_width +roofing_pattern +roofing_angles +infill_enable_travel_optimization +material_flow_dependent_temperature +material_flow_temp_graph +meshfix_maximum_resolution support_skip_some_zags support_skip_zag_per_mm +support_zag_skip_count draft_shield_enabled draft_shield_dist draft_shield_height_limitation @@ -267,19 +367,34 @@ infill_hollow magic_fuzzy_skin_enabled magic_fuzzy_skin_thickness magic_fuzzy_skin_point_density +magic_fuzzy_skin_point_dist 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 +wireframe_enabled +wireframe_height +wireframe_roof_inset +wireframe_printspeed +wireframe_printspeed_bottom +wireframe_printspeed_up +wireframe_printspeed_down +wireframe_printspeed_flat +wireframe_flow +wireframe_flow_connection +wireframe_flow_flat +wireframe_top_delay +wireframe_bottom_delay +wireframe_flat_delay +wireframe_up_half_speed +wireframe_top_jump +wireframe_fall_down +wireframe_drag_along +wireframe_strategy +wireframe_straight_before_down +wireframe_roof_fall_down +wireframe_roof_drag_along +wireframe_roof_outer_delay +wireframe_nozzle_clearance +adaptive_layer_height_enabled +adaptive_layer_height_variation +adaptive_layer_height_variation_step +adaptive_layer_height_threshold From ae57e23eecb21ac6256745a05567b6dda1abf5f3 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 1 Mar 2018 19:48:41 +0100 Subject: [PATCH 301/371] Create a mouse area around the sidebar to avoid propagating mouse wheel events. Contributes to CURA-4495 --- resources/qml/Cura.qml | 8 ++++++++ resources/qml/Settings/SettingView.qml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 191aa59690..0b4c8089c8 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -476,6 +476,14 @@ UM.MainWindow collapseSidebarAnimation.start(); } } + + MouseArea + { + visible: UM.Controller.activeStage.sidebarComponent != "" + anchors.fill: parent + acceptedButtons: Qt.AllButtons + onWheel: wheel.accepted = true + } } UM.MessageStack diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 47c8b188ad..46842baa98 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -142,7 +142,7 @@ Item TextField { id: filter; - + height: parent.height anchors.left: parent.left anchors.right: clearFilterButton.left anchors.rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width) From 844a597e082e00a98002984ba741493004560a69 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 09:28:25 +0100 Subject: [PATCH 302/371] Fix materials models --- cura/Machines/Models/BrandMaterialsModel.py | 4 ++++ cura/Machines/Models/GenericMaterialsModel.py | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index f6430b39da..6628d924f1 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -73,6 +73,10 @@ class BrandMaterialsModel(ListModel): if global_stack is None: self.setItems([]) return + extruder_position = str(self._extruder_position) + if extruder_position not in global_stack.extruders: + self.setItems([]) + return extruder_stack = global_stack.extruders[str(self._extruder_position)] available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index f5b18adde9..d20fc05b6e 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -25,7 +25,11 @@ class GenericMaterialsModel(BaseMaterialsModel): if global_stack is None: self.setItems([]) return - extruder_stack = global_stack.extruders[str(self._extruder_position)] + extruder_position = str(self._extruder_position) + if extruder_position not in global_stack.extruders: + self.setItems([]) + return + extruder_stack = global_stack.extruders[extruder_position] available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) From 5351ce7d237dd1be5a3b382ac2f7005e62260a5f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 09:29:00 +0100 Subject: [PATCH 303/371] Fix dagoma discoeasy200 travel speed 100 CURA-4988 --- resources/definitions/dagoma_discoeasy200.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json index 1674801b5e..4f0fddc41d 100644 --- a/resources/definitions/dagoma_discoeasy200.def.json +++ b/resources/definitions/dagoma_discoeasy200.def.json @@ -50,7 +50,7 @@ "default_value": 60 }, "speed_travel": { - "default_value": 100 + "value": "100" }, "retraction_amount": { "default_value": 3.5 From c82b2f2f6c041916c386ddbf46f0a46ffe0f7820 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 09:29:36 +0100 Subject: [PATCH 304/371] Fix gcode flave RepRap for dagoma neva CURA-4988 --- resources/definitions/dagoma_neva.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json index 430d2f6ab1..21a557ac22 100644 --- a/resources/definitions/dagoma_neva.def.json +++ b/resources/definitions/dagoma_neva.def.json @@ -42,7 +42,7 @@ "default_value": "elliptic" }, "machine_gcode_flavor": { - "default_value": "RepRap" + "default_value": "RepRap (RepRap)" }, "machine_start_gcode": { "default_value": ";Gcode by Cura\nG90\nG28\nM109 S100\nG29\nM104 S{material_print_temperature_layer_0}\nG0 X0 Y-85\nG0 Z0.26\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n" From 1743954ef73e3c4510c29f325b474f694ec61f26 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 09:33:13 +0100 Subject: [PATCH 305/371] chmod a+x check_preset_settings.py CURA-5032 --- tools/check_preset_settings.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tools/check_preset_settings.py diff --git a/tools/check_preset_settings.py b/tools/check_preset_settings.py old mode 100644 new mode 100755 From acbc6893f5cc6f449e3d7d7531472c03331bfcea Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 2 Mar 2018 14:51:13 +0100 Subject: [PATCH 306/371] Also allow backspace to delete models See the documentation in the code as to why. Macintosh keyboards... Fixes #3257. --- resources/qml/Actions.qml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index aade7c6053..819edb1fc4 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -236,6 +236,16 @@ Item onTriggered: CuraActions.deleteSelection(); } + Action //Also add backspace as the same function as delete because on Macintosh keyboards the button called "delete" is actually a backspace, and the user expects it to function as a delete. + { + id: backspaceSelectionAction + text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete &Selected Model", "Delete &Selected Models", UM.Selection.selectionCount) + enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection + iconName: "edit-delete" + shortcut: StandardKey.Backspace + onTriggered: CuraActions.deleteSelection() + } + Action { id: centerSelectionAction; From e080ff2db098ade6795db3fd91f49b807c9bdb71 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Fri, 2 Mar 2018 15:04:33 +0100 Subject: [PATCH 307/371] Revert "Combing to "No Skin"" This reverts commit ca83089eff9f9ed3b8a37b1d593993662cb27e0c. --- resources/definitions/ultimaker3.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 826960a621..27cbd15bf3 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -123,7 +123,6 @@ "raft_margin": { "value": "10" }, "raft_surface_layers": { "value": "1" }, "retraction_amount": { "value": "2" }, - "retraction_combing": { "default_value": "noskin" }, "retraction_count_max": { "value": "10" }, "retraction_extrusion_window": { "value": "1" }, "retraction_hop": { "value": "2" }, From 0305ad1ea2e15b92fe00da8182bbd2cb82ed29f5 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Fri, 2 Mar 2018 15:11:26 +0100 Subject: [PATCH 308/371] Zig_zaggifying the infills Connected infill lines in all our profiles, for increased strenght and print quality. --- resources/definitions/ultimaker3.def.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json index 27cbd15bf3..29395e8fd5 100644 --- a/resources/definitions/ultimaker3.def.json +++ b/resources/definitions/ultimaker3.def.json @@ -153,6 +153,7 @@ "travel_avoid_distance": { "value": "3" }, "wall_0_inset": { "value": "0" }, "wall_line_width_x": { "value": "round(wall_line_width * 0.3 / 0.35, 2)" }, - "wall_thickness": { "value": "1" } + "wall_thickness": { "value": "1" }, + "zig_zaggify_infill": { "value": "True" } } } From 75d106368eb481078eb1bf23dfb826b6e7eda445 Mon Sep 17 00:00:00 2001 From: THeijmans Date: Fri, 2 Mar 2018 15:15:23 +0100 Subject: [PATCH 309/371] Retraction minimum travel fix Retraction minimum travel distance set to two times the line width for all 0.4 and 0.8 mm TPU profiles. --- resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg | 2 +- resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg | 2 +- .../quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg | 2 +- resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg | 2 +- .../quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg | 2 +- .../quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg index f6828f88fb..e2751a13ac 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Draft_Print.inst.cfg @@ -44,7 +44,7 @@ retraction_extrusion_window = 1 retraction_hop = 1.5 retraction_hop_enabled = True retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 +retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 skin_overlap = 5 speed_equalize_flow_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg index 80be26d24c..13ff46cef4 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Fast_Print.inst.cfg @@ -45,7 +45,7 @@ retraction_extrusion_window = 1 retraction_hop = 1.5 retraction_hop_enabled = True retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 +retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 skin_overlap = 5 speed_equalize_flow_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg index 53044e1805..04454a9ff3 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_TPU_Normal_Quality.inst.cfg @@ -42,7 +42,7 @@ retraction_extrusion_window = 1 retraction_hop = 1.5 retraction_hop_enabled = True retraction_hop_only_when_collides = True -retraction_min_travel = 0.8 +retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 skin_overlap = 5 speed_equalize_flow_enabled = True diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg index d5d7479a0e..8c11e1247a 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Draft_Print.inst.cfg @@ -40,7 +40,7 @@ retraction_count_max = 12 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = 0.8 +retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 skin_line_width = =round(line_width * 0.78 / 0.8, 2) speed_print = 30 diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg index 86c6a3df77..6bd777f4b0 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Superdraft_Print.inst.cfg @@ -41,7 +41,7 @@ retraction_count_max = 12 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = 0.8 +retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 skin_line_width = =round(line_width * 0.78 / 0.8, 2) speed_print = 30 diff --git a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg index 8af3edcddd..f43818d7d4 100644 --- a/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.8_TPU_Verydraft_Print.inst.cfg @@ -40,7 +40,7 @@ retraction_count_max = 12 retraction_extra_prime_amount = 0.5 retraction_hop = 1.5 retraction_hop_only_when_collides = False -retraction_min_travel = 0.8 +retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 skin_line_width = =round(line_width * 0.78 / 0.8, 2) speed_print = 30 From 2135e30aadffd3832eea43dc16245490c331f436 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:10:06 +0100 Subject: [PATCH 310/371] Simplify for loop in _calculateInformation() --- cura/PrintInformation.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 279e7e0c03..50d80e11bb 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -212,14 +212,13 @@ class PrintInformation(QObject): material_preference_values = json.loads(Preferences.getInstance().getValue("cura/material_settings")) extruder_stacks = global_stack.extruders - for extruder_key in global_stack.extruders.keys(): - index = int(extruder_key) + for position, extruder_stack in extruder_stacks.keys(): + index = int(position) if index >= len(self._material_amounts): # Right now the _material_amounts is a list, where the index is the extruder number continue amount = self._material_amounts[index] ## Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some # list comprehension filtering to solve this for us. - extruder_stack = extruder_stacks[str(index)] density = extruder_stack.getMetaDataEntry("properties", {}).get("density", 0) material = extruder_stack.findContainer({"type": "material"}) From a6f22fd9cc058ebf4f7c99e715d2a182ddba2e0a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:10:59 +0100 Subject: [PATCH 311/371] Remove unnecessary comments --- cura/PrintInformation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 50d80e11bb..fe30db08b3 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -214,7 +214,7 @@ class PrintInformation(QObject): extruder_stacks = global_stack.extruders for position, extruder_stack in extruder_stacks.keys(): index = int(position) - if index >= len(self._material_amounts): # Right now the _material_amounts is a list, where the index is the extruder number + if index >= len(self._material_amounts): continue amount = self._material_amounts[index] ## Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some From d372fc75e723f364d8639d51a9b22afc81e47def Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:16:51 +0100 Subject: [PATCH 312/371] Fix type hinting for getFallbackMaterialIdByMaterialType() --- cura/Machines/MaterialManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 2dd39d1fe1..faaabb01e5 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -329,7 +329,7 @@ class MaterialManager(QObject): # This function returns the generic root material ID for the given material type, where material types are "PLA", # "ABS", etc. # - def getFallbackMaterialIdByMaterialType(self, material_type: str) -> str: + def getFallbackMaterialIdByMaterialType(self, material_type: str) -> Optional[str]: # For safety if material_type not in self._fallback_materials_map: Logger.log("w", "The material type [%s] does not have a fallback material" % material_type) From f7377e6321eea9970f47cb42c090b70c2d6c54f9 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:20:03 +0100 Subject: [PATCH 313/371] Fix extruder_stacks.items() --- cura/PrintInformation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index fe30db08b3..b52b61fcac 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -212,7 +212,7 @@ class PrintInformation(QObject): material_preference_values = json.loads(Preferences.getInstance().getValue("cura/material_settings")) extruder_stacks = global_stack.extruders - for position, extruder_stack in extruder_stacks.keys(): + for position, extruder_stack in extruder_stacks.items(): index = int(position) if index >= len(self._material_amounts): continue From c6128ef5ba48f6189d7054c56c9e8995e0c01952 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:22:22 +0100 Subject: [PATCH 314/371] Move setMaterialName() into MaterialManager --- cura/CuraApplication.py | 1 + cura/Machines/MaterialManager.py | 19 ++++++++++++++++++- cura/Settings/ContainerManager.py | 11 ----------- resources/qml/Preferences/MaterialView.qml | 4 +++- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index de5d46ba96..2ca321e4cc 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -859,6 +859,7 @@ class CuraApplication(QtApplication): def getVariantManager(self, *args): return self._variant_manager + @pyqtSlot(result = QObject) def getMaterialManager(self, *args): return self._material_manager diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index faaabb01e5..a318e67a0f 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -4,7 +4,7 @@ from collections import defaultdict, OrderedDict from typing import Optional -from PyQt5.Qt import QTimer, QObject, pyqtSignal +from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot from UM.Logger import Logger from UM.Settings import ContainerRegistry @@ -339,3 +339,20 @@ class MaterialManager(QObject): return self.getRootMaterialIDWithoutDiameter(fallback_material["id"]) else: return None + + # + # Methods for GUI + # + + # + # Sets the new name for the given material. + # + @pyqtSlot("QVariant", str) + def setMaterialName(self, material_node: "MaterialNode", name: str): + root_material_id = material_node.metadata["base_file"] + if self._container_registry.isReadOnly(root_material_id): + Logger.log("w", "Cannot set name of read-only container %s.", root_material_id) + return + + material_group = self.getMaterialGroup(root_material_id) + material_group.root_material_node.getContainer().setName(name) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 96fff61b0b..c0451b4b5e 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -160,17 +160,6 @@ class ContainerManager(QObject): return container.getProperty(setting_key, property_name) - ## Set the name of the specified material. - @pyqtSlot("QVariant", str) - def setMaterialName(self, material_node, new_name): - root_material_id = material_node.metadata["base_file"] - if self._container_registry.isReadOnly(root_material_id): - Logger.log("w", "Cannot set name of read-only container %s.", root_material_id) - return - - material_group = self._material_manager.getMaterialGroup(root_material_id) - material_group.root_material_node.getContainer().setName(new_name) - @pyqtSlot(str, result = str) def makeUniqueName(self, original_name): return self._container_registry.uniqueName(original_name) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 021fcc02e1..7e0efd56de 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -12,6 +12,8 @@ TabView { id: base + property QtObject materialManager: CuraApplication.getMaterialManager() + property QtObject properties property var currentMaterialNode: null @@ -497,7 +499,7 @@ TabView } // update the values - Cura.ContainerManager.setMaterialName(base.currentMaterialNode, new_name) + base.materialManager.setMaterialName(base.currentMaterialNode, new_name) materialProperties.name = new_name } From 29631fa8eb29a19a82f2bcc91af6ae4e5d7490ae Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:25:16 +0100 Subject: [PATCH 315/371] Fix QualityManager doc --- cura/Machines/QualityManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index e587816dff..00393d1e8f 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -27,7 +27,7 @@ from .QualityNode import QualityNode # -# Similar to MaterialManager, QualityManager maintains a number of maps and trees for material lookup. +# Similar to MaterialManager, QualityManager maintains a number of maps and trees for quality profile lookup. # The models GUI and QML use are now only dependent on the QualityManager. That means as long as the data in # QualityManager gets updated correctly, the GUI models should be updated correctly too, and the same goes for GUI. # From 27f45742237e3d6099c4daedfcd7f786408dda25 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:31:57 +0100 Subject: [PATCH 316/371] Remove some superfluous comments in QualityManager --- cura/Machines/QualityManager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 00393d1e8f..fe7b52d50b 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -184,7 +184,6 @@ class QualityManager(QObject): # Returns a dict of "custom profile name" -> QualityChangesGroup def getQualityChangesGroups(self, machine: "GlobalStack") -> dict: - # Get machine definition ID for quality search machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id) @@ -207,8 +206,8 @@ class QualityManager(QObject): return quality_changes_group_dict def getQualityGroups(self, machine: "GlobalStack") -> dict: - # Get machine definition ID for quality search machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + # This determines if we should only get the global qualities for the global stack and skip the global qualities for the extruder stacks has_variant_materials = parseBool(machine.getMetaDataEntry("has_variant_materials", False)) From e340f8e53460cebb80aa120f0b2aef81eff84521 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:34:42 +0100 Subject: [PATCH 317/371] Add documentation for getQualityGroups() --- cura/Machines/QualityManager.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index fe7b52d50b..924521a076 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -205,6 +205,12 @@ class QualityManager(QObject): return quality_changes_group_dict + # + # Gets all quality groups for the given machine. Both available and none available ones will be included. + # It returns a dictionary with "quality_type"s as keys and "QualityGroup"s as values. + # Whether a QualityGroup is available can be unknown via the field QualityGroup.is_available. + # For more details, see QualityGroup. + # def getQualityGroups(self, machine: "GlobalStack") -> dict: machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) From fc36df2bea6b700aebe4775126e0889252112c41 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:37:23 +0100 Subject: [PATCH 318/371] Remove unnecessary comments in getQualityGroupsForMachineDefinition() --- cura/Machines/QualityManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 924521a076..e7c4157868 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -310,7 +310,6 @@ class QualityManager(QObject): return quality_group_dict def getQualityGroupsForMachineDefinition(self, machine: "GlobalStack") -> dict: - # Get machine definition ID for quality search machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) # To find the quality container for the GlobalStack, check in the following fall-back manner: From 0944653412886111007f1c01bb8d7046bfc87fdd Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:41:19 +0100 Subject: [PATCH 319/371] Change VariantType to an Enum --- cura/Machines/VariantManager.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py index 834b47dd0f..f7d80100a8 100644 --- a/cura/Machines/VariantManager.py +++ b/cura/Machines/VariantManager.py @@ -1,6 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from enum import Enum from collections import OrderedDict from typing import Optional @@ -11,7 +12,7 @@ from cura.Machines.ContainerNode import ContainerNode from cura.Settings.GlobalStack import GlobalStack -class VariantType: +class VariantType(Enum): BUILD_PLATE = "buildplate" NOZZLE = "nozzle" @@ -64,6 +65,7 @@ class VariantManager: self._machine_to_variant_dict_map[variant_definition][variant_type] = dict() variant_type = variant_metadata["hardware_type"] + variant_type = VariantType(variant_type) variant_dict = self._machine_to_variant_dict_map[variant_definition][variant_type] if variant_name in variant_dict: # ERROR: duplicated variant name. @@ -77,10 +79,10 @@ class VariantManager: # Almost the same as getVariantMetadata() except that this returns an InstanceContainer if present. # def getVariantNode(self, machine_definition_id: str, variant_name: str, - variant_type: Optional[str] = VariantType.NOZZLE) -> Optional["ContainerNode"]: + variant_type: Optional["VariantType"] = VariantType.NOZZLE) -> Optional["ContainerNode"]: return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}).get(variant_name) def getVariantNodes(self, machine: "GlobalStack", - variant_type: Optional[str] = VariantType.NOZZLE) -> dict: + variant_type: Optional["VariantType"] = VariantType.NOZZLE) -> dict: machine_definition_id = machine.definition.getId() return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {}) From 6cae82a64ebba4999a699952ba5cd5c1af2bde4a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:42:07 +0100 Subject: [PATCH 320/371] Fix comments for createQualityChanges() --- cura/Settings/ContainerManager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index c0451b4b5e..22f890c6ac 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -347,8 +347,6 @@ class ContainerManager(QObject): # This will go through the global and extruder stacks and create quality_changes containers from # the user containers in each stack. These then replace the quality_changes containers in the # stack and clear the user settings. - # - # \return \type{bool} True if the operation was successfully, False if not. @pyqtSlot(str) def createQualityChanges(self, base_name): global_stack = Application.getInstance().getGlobalContainerStack() From 8324f4f44e247e96c87225ae028db1334abcb76e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:47:25 +0100 Subject: [PATCH 321/371] Move removeQualityChangesGroup() into QualityManager --- cura/Machines/QualityManager.py | 20 +++++++++++++++++++- cura/Settings/ContainerManager.py | 9 --------- resources/qml/Preferences/ProfilesPage.qml | 6 ++++-- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index e7c4157868..ed64fe92b6 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -1,7 +1,8 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from PyQt5.QtCore import QObject, QTimer, pyqtSignal +from typing import TYPE_CHECKING +from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot from UM.Application import Application from UM.Logger import Logger @@ -10,6 +11,10 @@ from UM.Util import parseBool from .QualityGroup import QualityGroup from .QualityNode import QualityNode +if TYPE_CHECKING: + from cura.Settings.GlobalStack import GlobalStack + from .QualityChangesGroup import QualityChangesGroup + # # Quality lookup tree structure: # @@ -332,6 +337,19 @@ class QualityManager(QObject): return quality_group_dict + # + # Methods for GUI + # + + # + # Remove the given quality changes group. + # + @pyqtSlot(QObject) + def removeQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup"): + Logger.log("i", "Removing quality changes group [%s]", quality_changes_group.name) + for node in quality_changes_group.getAllNodes(): + self._container_registry.removeContainer(node.metadata["id"]) + # # Gets the machine definition ID that can be used to search for Quality containers that are suitable for the given diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 22f890c6ac..d4f72139b1 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -382,15 +382,6 @@ class ContainerManager(QObject): self._container_registry.addContainer(new_changes) - # - # Remove the given quality changes group - # - @pyqtSlot(QObject) - def removeQualityChangesGroup(self, quality_changes_group): - Logger.log("i", "Removing quality changes group [%s]", quality_changes_group.name) - for node in quality_changes_group.getAllNodes(): - self._container_registry.removeContainer(node.metadata["id"]) - # # Rename a set of quality changes containers. Returns the new name. # diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index e5c7e3662a..7beb96a535 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -13,6 +13,8 @@ import Cura 1.0 as Cura Item { id: base + + property QtObject qualityManager: CuraApplication.getQualityManager() property var resetEnabled: false // Keep PreferencesDialog happy property var extrudersModel: Cura.ExtrudersModel {} @@ -239,9 +241,9 @@ Item onYes: { - Cura.ContainerManager.removeQualityChangesGroup(base.currentItem.quality_changes_group); + base.qualityManager.removeQualityChangesGroup(base.currentItem.quality_changes_group); // reset current item to the first if available - qualityListView.currentIndex = -1; // TODO: Reset selection. + qualityListView.currentIndex = -1; // Reset selection. } } From 355b8cbac3189354454ad1aa16b1d687dbf1b0c6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 16:58:50 +0100 Subject: [PATCH 322/371] Move renameQualityChangesGroup() into QualityManager --- cura/Machines/QualityManager.py | 22 ++++++++++++++++++++++ cura/Settings/ContainerManager.py | 21 --------------------- resources/qml/Preferences/ProfilesPage.qml | 2 +- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index ed64fe92b6..4b0d54671a 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from typing import TYPE_CHECKING + from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot from UM.Application import Application @@ -350,6 +351,27 @@ class QualityManager(QObject): for node in quality_changes_group.getAllNodes(): self._container_registry.removeContainer(node.metadata["id"]) + # + # Rename a set of quality changes containers. Returns the new name. + # + @pyqtSlot(QObject, str, result = str) + def renameQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", new_name: str) -> str: + Logger.log("i", "Renaming QualityChangesGroup[%s] to [%s]", quality_changes_group.name, new_name) + if new_name == quality_changes_group.name: + Logger.log("i", "QualityChangesGroup name [%s] unchanged.", quality_changes_group.name) + return new_name + + new_name = self._container_registry.uniqueName(new_name) + for node in quality_changes_group.getAllNodes(): + node.getContainer().setName(new_name) + + quality_changes_group.name = new_name + + self._application.getMachineManager().activeQualityChanged.emit() + self._application.getMachineManager().activeQualityGroupChanged.emit() + + return new_name + # # Gets the machine definition ID that can be used to search for Quality containers that are suitable for the given diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index d4f72139b1..1356df3dd1 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -382,27 +382,6 @@ class ContainerManager(QObject): self._container_registry.addContainer(new_changes) - # - # Rename a set of quality changes containers. Returns the new name. - # - @pyqtSlot(QObject, str, result = str) - def renameQualityChangesGroup(self, quality_changes_group, new_name) -> str: - Logger.log("i", "Renaming QualityChangesGroup[%s] to [%s]", quality_changes_group.name, new_name) - self._machine_manager.blurSettings.emit() - - if new_name == quality_changes_group.name: - Logger.log("i", "QualityChangesGroup name [%s] unchanged.", quality_changes_group.name) - return new_name - - new_name = self._container_registry.uniqueName(new_name) - for node in quality_changes_group.getAllNodes(): - node.getContainer().setName(new_name) - - self._machine_manager.activeQualityChanged.emit() - self._machine_manager.activeQualityGroupChanged.emit() - - return new_name - @pyqtSlot(str, "QVariantMap") def duplicateQualityChanges(self, quality_changes_name, quality_model_item): global_stack = Application.getInstance().getGlobalContainerStack() diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 7beb96a535..07b703dfcd 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -255,7 +255,7 @@ Item object: "" onAccepted: { - var actualNewName = Cura.ContainerManager.renameQualityChangesGroup(base.currentItem.quality_changes_group, newName); + var actualNewName = base.qualityManager.renameQualityChangesGroup(base.currentItem.quality_changes_group, newName); base.newQualityNameToSelect = actualNewName; // Select the new name after the model gets updated } } From 1f403f815d08aa49fbb1403c7bf72acd0ddde0f8 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 2 Mar 2018 17:05:58 +0100 Subject: [PATCH 323/371] CURA-4972 Moved validation to `SettingOverrideDecorator.py` **The diagnosis:** The issue arrises from the fact that while the original object is subscribed to be validated, that subscription is only created by setting it as a settings override object. A clone of that object, while still a settings-override object, never gets subscribed because it's not explicitly set with the tool. **The solution (?):** I moved all the validation stuff over to SettingOverrideDecorator.py, and use its onSettingChanged() function to trigger the validation. Unfortunately, I can't use the timer because of some limitation with QTTimer and threads. So it's _a bit laggy in some places, and I'd be open to tips about how to fix this. It does work reliably though. --- cura/Settings/SettingOverrideDecorator.py | 24 ++++++++++++++++--- .../PerObjectSettingsTool.py | 8 ++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py index b853c06c8e..6e98f014dc 100644 --- a/cura/Settings/SettingOverrideDecorator.py +++ b/cura/Settings/SettingOverrideDecorator.py @@ -3,12 +3,14 @@ import copy +from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNodeDecorator import SceneNodeDecorator from UM.Signal import Signal, signalemitter from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Logger import Logger - +from UM.Settings.Validator import ValidatorState +from PyQt5.QtCore import QTimer from UM.Application import Application from cura.Settings.PerObjectContainerStack import PerObjectContainerStack @@ -38,6 +40,10 @@ class SettingOverrideDecorator(SceneNodeDecorator): self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId() self._is_non_printing_mesh = False + self._error_check_timer = QTimer() + self._error_check_timer.setInterval(250) + self._error_check_timer.setSingleShot(True) + self._error_check_timer.timeout.connect(self._checkStackForErrors) self._stack.propertyChanged.connect(self._onSettingChanged) @@ -93,9 +99,21 @@ class SettingOverrideDecorator(SceneNodeDecorator): # Trigger slice/need slicing if the value has changed. if property_name == "value": self._is_non_printing_mesh = any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_printing_mesh_settings) + if not self._is_non_printing_mesh: + # self._error_check_timer.start() + self._checkStackForErrors() + Application.getInstance().getBackend().needsSlicing() + Application.getInstance().getBackend().tickle() - Application.getInstance().getBackend().needsSlicing() - Application.getInstance().getBackend().tickle() + def _checkStackForErrors(self): + hasErrors = False; + for key in self._stack.getAllKeys(): + validation_state = self._stack.getProperty(key, "validationState") + if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError): + Logger.log("w", "Setting Per Object %s is not valid.", key) + hasErrors = True + break + Application.getInstance().getObjectsModel().setStacksHaveErrors(hasErrors) ## Makes sure that the stack upon which the container stack is placed is # kept up to date. diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py index aa8bb92045..b671db48fb 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py @@ -44,7 +44,6 @@ class PerObjectSettingsTool(Tool): self._error_check_timer.setSingleShot(True) self._error_check_timer.timeout.connect(self._updateStacksHaveErrors) - def event(self, event): super().event(event) if event.type == Event.MousePressEvent and self._controller.getToolsEnabled(): @@ -156,10 +155,12 @@ class PerObjectSettingsTool(Tool): def _onPropertyChanged(self, key: str, property_name: str) -> None: if property_name == "validationState": - self._error_check_timer.start() + # self._error_check_timer.start() + return def _updateStacksHaveErrors(self) -> None: - self._checkStacksHaveErrors() + return + # self._checkStacksHaveErrors() def _checkStacksHaveErrors(self): @@ -180,6 +181,7 @@ class PerObjectSettingsTool(Tool): def _checkStackForErrors(self, stack): + print("checking for errors") if stack is None: return False From ca785c9df30a7b79a7a6b7d7f9a07774b53257c6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 17:08:58 +0100 Subject: [PATCH 324/371] Move duplicateQualityChanges() to QualityManager --- cura/Machines/QualityManager.py | 54 ++++++++++++++++++- cura/Settings/ContainerManager.py | 63 ---------------------- resources/qml/Preferences/ProfilesPage.qml | 2 +- 3 files changed, 54 insertions(+), 65 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 4b0d54671a..794ea19c14 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -1,13 +1,14 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot from UM.Application import Application from UM.Logger import Logger from UM.Util import parseBool +from UM.Settings.InstanceContainer import InstanceContainer from .QualityGroup import QualityGroup from .QualityNode import QualityNode @@ -372,6 +373,57 @@ class QualityManager(QObject): return new_name + # + # Duplicates the given quality. + # + @pyqtSlot(str, "QVariantMap") + def duplicateQualityChanges(self, quality_changes_name, quality_model_item): + global_stack = self._application.getGlobalContainerStack() + if not global_stack: + Logger.log("i", "No active global stack, cannot duplicate quality changes.") + return + + quality_group = quality_model_item["quality_group"] + quality_changes_group = quality_model_item["quality_changes_group"] + if quality_changes_group is None: + # create global quality changes only + new_quality_changes = self._createQualityChanges(quality_group.quality_type, quality_changes_name, + global_stack, extruder_id = None) + self._container_registry.addContainer(new_quality_changes) + else: + new_name = self._container_registry.uniqueName(quality_changes_name) + for node in quality_changes_group.getAllNodes(): + container = node.getContainer() + new_id = self._container_registry.uniqueName(container.getId()) + self._container_registry.addContainer(container.duplicate(new_id, new_name)) + + # + # Create a quality changes container with the given setup. + # + def _createQualityChanges(self, quality_type: str, new_name: str, machine: "GlobalStack", + extruder_id: Optional[str]) -> "InstanceContainer": + base_id = machine.definition.getId() if extruder_id is None else extruder_id + new_id = base_id + "_" + new_name + new_id = new_id.lower().replace(" ", "_") + new_id = self._container_registry.uniqueName(new_id) + + # Create a new quality_changes container for the quality. + quality_changes = InstanceContainer(new_id) + quality_changes.setName(new_name) + quality_changes.addMetaDataEntry("type", "quality_changes") + quality_changes.addMetaDataEntry("quality_type", quality_type) + + # If we are creating a container for an extruder, ensure we add that to the container + if extruder_id is not None: + quality_changes.addMetaDataEntry("extruder", extruder_id) + + # If the machine specifies qualities should be filtered, ensure we match the current criteria. + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + quality_changes.setDefinition(machine_definition_id) + + quality_changes.addMetaDataEntry("setting_version", self._application.SettingVersion) + return quality_changes + # # Gets the machine definition ID that can be used to search for Quality containers that are suitable for the given diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 1356df3dd1..c81292c46e 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -382,24 +382,6 @@ class ContainerManager(QObject): self._container_registry.addContainer(new_changes) - @pyqtSlot(str, "QVariantMap") - def duplicateQualityChanges(self, quality_changes_name, quality_model_item): - global_stack = Application.getInstance().getGlobalContainerStack() - - quality_group = quality_model_item["quality_group"] - quality_changes_group = quality_model_item["quality_changes_group"] - if quality_changes_group is None: - # create global quality changes only - new_quality_changes = self._createQualityChanges(quality_group.quality_type, quality_changes_name, - global_stack, extruder_id = None) - self._container_registry.addContainer(new_quality_changes) - else: - new_name = self._container_registry.uniqueName(quality_changes_name) - for node in quality_changes_group.getAllNodes(): - container = node.getContainer() - new_id = self._container_registry.uniqueName(container.getId()) - self._container_registry.addContainer(container.duplicate(new_id, new_name)) - @pyqtSlot("QVariant") def removeMaterial(self, material_node): root_material_id = material_node.metadata["base_file"] @@ -598,51 +580,6 @@ class ContainerManager(QObject): name_filter = "{0} ({1})".format(mime_type.comment, suffix_list) self._container_name_filters[name_filter] = entry - ## Creates a unique ID for a container by prefixing the name with the stack ID. - # - # This method creates a unique ID for a container by prefixing it with a specified stack ID. - # This is done to ensure we have an easily identified ID for quality changes, which have the - # same name across several stacks. - # - # \param stack_id The ID of the stack to prepend. - # \param container_name The name of the container that we are creating a unique ID for. - # - # \return Container name prefixed with stack ID, in lower case with spaces replaced by underscores. - def _createUniqueId(self, stack_id, container_name): - result = stack_id + "_" + container_name - result = result.lower() - result.replace(" ", "_") - return result - - ## Create a quality changes container for a specified quality container. - # - # \param quality_container The quality container to create a changes container for. - # \param new_name The name of the new quality_changes container. - # \param machine_definition The machine definition this quality changes container is specific to. - # \param extruder_id - # - # \return A new quality_changes container with the specified container as base. - def _createQualityChanges(self, quality_type, new_name, machine, extruder_id): - base_id = machine.definition.getId() if extruder_id is None else extruder_id - - # Create a new quality_changes container for the quality. - quality_changes = InstanceContainer(self._createUniqueId(base_id, new_name)) - quality_changes.setName(new_name) - quality_changes.addMetaDataEntry("type", "quality_changes") - quality_changes.addMetaDataEntry("quality_type", quality_type) - - # If we are creating a container for an extruder, ensure we add that to the container - if extruder_id is not None: - quality_changes.addMetaDataEntry("extruder", extruder_id) - - # If the machine specifies qualities should be filtered, ensure we match the current criteria. - machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) - quality_changes.setDefinition(machine_definition_id) - - from cura.CuraApplication import CuraApplication - quality_changes.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - return quality_changes - ## Import single profile, file_url does not have to end with curaprofile @pyqtSlot(QUrl, result="QVariantMap") def importProfile(self, file_url): diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 07b703dfcd..aaf9bdac0e 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -224,7 +224,7 @@ Item object: "" onAccepted: { - Cura.ContainerManager.duplicateQualityChanges(newName, base.currentItem); + base.qualityManager.duplicateQualityChanges(newName, base.currentItem); } } From 7642afb9feaa4ec212c0f6f66f9d234f20e713a8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 17:16:35 +0100 Subject: [PATCH 325/371] Move duplicateMaterial() to MaterialManager --- cura/Machines/MaterialManager.py | 60 +++++++++++++++++++++ cura/Settings/ContainerManager.py | 55 ------------------- resources/qml/Preferences/MaterialsPage.qml | 4 +- 3 files changed, 63 insertions(+), 56 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index a318e67a0f..95540a9a41 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -2,10 +2,12 @@ # Cura is released under the terms of the LGPLv3 or higher. from collections import defaultdict, OrderedDict +import copy from typing import Optional from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot +from UM.Application import Application from UM.Logger import Logger from UM.Settings import ContainerRegistry @@ -29,6 +31,7 @@ class MaterialManager(QObject): def __init__(self, container_registry, parent = None): super().__init__(parent) + self._application = Application.getInstance() self._container_registry = container_registry # type: ContainerRegistry self._fallback_materials_map = dict() # material_type -> generic material metadata @@ -356,3 +359,60 @@ class MaterialManager(QObject): material_group = self.getMaterialGroup(root_material_id) material_group.root_material_node.getContainer().setName(name) + + # + # Creates a duplicate of a material, which has the same GUID and base_file metadata. + # Returns the root material ID of the duplicated material if successful. + # + @pyqtSlot("QVariant", result = str) + def duplicateMaterial(self, material_node, new_base_id = None, new_metadata = None) -> Optional[str]: + root_material_id = material_node.metadata["base_file"] + + material_group = self.getMaterialGroup(root_material_id) + if not material_group: + Logger.log("i", "Unable to duplicate the material with id %s, because it doesn't exist.", root_material_id) + return None + + base_container = material_group.root_material_node.getContainer() + containers_to_copy = [] + for node in material_group.derived_material_node_list: + containers_to_copy.append(node.getContainer()) + + # Ensure all settings are saved. + self._application.saveSettings() + + # Create a new ID & container to hold the data. + new_containers = [] + if new_base_id is None: + new_base_id = self._container_registry.uniqueName(base_container.getId()) + new_base_container = copy.deepcopy(base_container) + new_base_container.getMetaData()["id"] = new_base_id + new_base_container.getMetaData()["base_file"] = new_base_id + if new_metadata is not None: + for key, value in new_metadata.items(): + new_base_container.getMetaData()[key] = value + new_containers.append(new_base_container) + + # Clone all of them. + for container_to_copy in containers_to_copy: + # Create unique IDs for every clone. + new_id = new_base_id + if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": + new_id += "_" + container_to_copy.getMetaDataEntry("definition") + if container_to_copy.getMetaDataEntry("variant_name"): + variant_name = container_to_copy.getMetaDataEntry("variant_name") + new_id += "_" + variant_name.replace(" ", "_") + + new_container = copy.deepcopy(container_to_copy) + new_container.getMetaData()["id"] = new_id + new_container.getMetaData()["base_file"] = new_base_id + if new_metadata is not None: + for key, value in new_metadata.items(): + new_container.getMetaData()[key] = value + + new_containers.append(new_container) + + for container_to_add in new_containers: + container_to_add.setDirty(True) + self._container_registry.addContainer(container_to_add) + return new_base_id diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index c81292c46e..b3bb9a594e 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -395,61 +395,6 @@ class ContainerManager(QObject): self._container_registry.removeContainer(node.metadata["id"]) - ## Create a duplicate of a material, which has the same GUID and base_file metadata - # - # \return \type{str} the id of the newly created container. - @pyqtSlot("QVariant", result = str) - def duplicateMaterial(self, material_node, new_base_id = None, new_metadata = None): - root_material_id = material_node.metadata["base_file"] - - material_group = self._material_manager.getMaterialGroup(root_material_id) - if not material_group: - Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", root_material_id) - return - - base_container = material_group.root_material_node.getContainer() - containers_to_copy = [] - for node in material_group.derived_material_node_list: - containers_to_copy.append(node.getContainer()) - - # Ensure all settings are saved. - Application.getInstance().saveSettings() - - # Create a new ID & container to hold the data. - new_containers = [] - if new_base_id is None: - new_base_id = self._container_registry.uniqueName(base_container.getId()) - new_base_container = copy.deepcopy(base_container) - new_base_container.getMetaData()["id"] = new_base_id - new_base_container.getMetaData()["base_file"] = new_base_id - if new_metadata is not None: - for key, value in new_metadata.items(): - new_base_container.getMetaData()[key] = value - new_containers.append(new_base_container) - - # Clone all of them. - for container_to_copy in containers_to_copy: - # Create unique IDs for every clone. - new_id = new_base_id - if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": - new_id += "_" + container_to_copy.getMetaDataEntry("definition") - if container_to_copy.getMetaDataEntry("variant_name"): - variant_name = container_to_copy.getMetaDataEntry("variant_name") - new_id += "_" + variant_name.replace(" ", "_") - - new_container = copy.deepcopy(container_to_copy) - new_container.getMetaData()["id"] = new_id - new_container.getMetaData()["base_file"] = new_base_id - if new_metadata is not None: - for key, value in new_metadata.items(): - new_container.getMetaData()[key] = value - - new_containers.append(new_container) - - for container_to_add in new_containers: - container_to_add.setDirty(True) - ContainerRegistry.getInstance().addContainer(container_to_add) - return new_base_id ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 1177f20334..224bc66f3c 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -13,6 +13,8 @@ import Cura 1.0 as Cura Item { id: base + + property QtObject materialManager: CuraApplication.getMaterialManager() property var resetEnabled: false // Keep PreferencesDialog happy UM.I18nCatalog { id: catalog; name: "cura"; } @@ -89,7 +91,7 @@ Item enabled: base.hasCurrentItem onClicked: { forceActiveFocus(); - base.newRootMaterialIdToSwitchTo = Cura.ContainerManager.duplicateMaterial(base.currentItem.container_node); + base.newRootMaterialIdToSwitchTo = base.materialManager.duplicateMaterial(base.currentItem.container_node); base.toActivateNewMaterial = true; } } From 5f0bb3a2837d9b7d3de7706882dcca4e9857c74e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 17:20:26 +0100 Subject: [PATCH 326/371] Move removeMaterial() to MaterialManager --- cura/Machines/MaterialManager.py | 15 +++++++++++++++ cura/Settings/ContainerManager.py | 14 -------------- resources/qml/Preferences/MaterialsPage.qml | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 95540a9a41..3665a9a423 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -360,6 +360,21 @@ class MaterialManager(QObject): material_group = self.getMaterialGroup(root_material_id) material_group.root_material_node.getContainer().setName(name) + # + # Removes the given material. + # + @pyqtSlot("QVariant") + def removeMaterial(self, material_node: "MaterialNode"): + root_material_id = material_node.metadata["base_file"] + material_group = self.getMaterialGroup(root_material_id) + if not material_group: + Logger.log("d", "Unable to remove the material with id %s, because it doesn't exist.", root_material_id) + return + + nodes_to_remove = [material_group.root_material_node] + material_group.derived_material_node_list + for node in nodes_to_remove: + self._container_registry.removeContainer(node.metadata["id"]) + # # Creates a duplicate of a material, which has the same GUID and base_file metadata. # Returns the root material ID of the duplicated material if successful. diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index b3bb9a594e..ce641eb2f0 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -382,20 +382,6 @@ class ContainerManager(QObject): self._container_registry.addContainer(new_changes) - @pyqtSlot("QVariant") - def removeMaterial(self, material_node): - root_material_id = material_node.metadata["base_file"] - material_group = self._material_manager.getMaterialGroup(root_material_id) - if not material_group: - Logger.log("d", "Unable to remove the material with id %s, because it doesn't exist.", root_material_id) - return - - nodes_to_remove = [material_group.root_material_node] + material_group.derived_material_node_list - for node in nodes_to_remove: - self._container_registry.removeContainer(node.metadata["id"]) - - - ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # # \return \type{str} the id of the newly created container. diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 224bc66f3c..71cf584997 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -183,7 +183,7 @@ Item onYes: { - Cura.ContainerManager.removeMaterial(base.currentItem.container_node); + base.materialManager.removeMaterial(base.currentItem.container_node); } } From cf2252f4f9255ced5f8f5a9c45493013526d35d5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 17:22:19 +0100 Subject: [PATCH 327/371] Simplify for loop in duplicateMaterial() --- cura/Machines/MaterialManager.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 3665a9a423..ac2d8ed895 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -389,9 +389,6 @@ class MaterialManager(QObject): return None base_container = material_group.root_material_node.getContainer() - containers_to_copy = [] - for node in material_group.derived_material_node_list: - containers_to_copy.append(node.getContainer()) # Ensure all settings are saved. self._application.saveSettings() @@ -409,7 +406,8 @@ class MaterialManager(QObject): new_containers.append(new_base_container) # Clone all of them. - for container_to_copy in containers_to_copy: + for node in material_group.derived_material_node_list: + container_to_copy = node.getContainer() # Create unique IDs for every clone. new_id = new_base_id if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": From c93643bc2f95b5292a2132a1bfdb8373e1539201 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 2 Mar 2018 17:30:19 +0100 Subject: [PATCH 328/371] Move createMaterial() to MaterialManager --- cura/Machines/MaterialManager.py | 29 +++++++++++++++++++++ cura/Settings/ContainerManager.py | 26 ------------------ resources/qml/Preferences/MaterialsPage.qml | 2 +- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index ac2d8ed895..5998e8b020 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -3,6 +3,7 @@ from collections import defaultdict, OrderedDict import copy +import uuid from typing import Optional from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot @@ -429,3 +430,31 @@ class MaterialManager(QObject): container_to_add.setDirty(True) self._container_registry.addContainer(container_to_add) return new_base_id + + # + # Create a new material by cloning Generic PLA for the current material diameter and generate a new GUID. + # + @pyqtSlot(result = str) + def createMaterial(self) -> str: + from UM.i18n import i18nCatalog + catalog = i18nCatalog("cura") + # Ensure all settings are saved. + self._application.saveSettings() + + global_stack = self._application.getGlobalContainerStack() + approximate_diameter = str(round(global_stack.getProperty("material_diameter", "value"))) + root_material_id = "generic_pla" + root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_diameter) + material_group = self.getMaterialGroup(root_material_id) + + # Create a new ID & container to hold the data. + new_id = self._container_registry.uniqueName("custom_material") + new_metadata = {"name": catalog.i18nc("@label", "Custom Material"), + "brand": catalog.i18nc("@label", "Custom"), + "GUID": str(uuid.uuid4()), + } + + self.duplicateMaterial(material_group.root_material_node, + new_base_id = new_id, + new_metadata = new_metadata) + return new_id diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index ce641eb2f0..19a010fe2a 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -382,32 +382,6 @@ class ContainerManager(QObject): self._container_registry.addContainer(new_changes) - ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue - # - # \return \type{str} the id of the newly created container. - @pyqtSlot(result = str) - def createMaterial(self): - # Ensure all settings are saved. - Application.getInstance().saveSettings() - - global_stack = Application.getInstance().getGlobalContainerStack() - approximate_diameter = str(round(global_stack.getProperty("material_diameter", "value"))) - root_material_id = "generic_pla" - root_material_id = self._material_manager.getRootMaterialIDForDiameter(root_material_id, approximate_diameter) - material_group = self._material_manager.getMaterialGroup(root_material_id) - - # Create a new ID & container to hold the data. - new_id = self._container_registry.uniqueName("custom_material") - new_metadata = {"name": catalog.i18nc("@label", "Custom Material"), - "brand": catalog.i18nc("@label", "Custom"), - "GUID": str(uuid.uuid4()), - } - - self.duplicateMaterial(material_group.root_material_node, - new_base_id = new_id, - new_metadata = new_metadata) - return new_id - ## Get a list of materials that have the same GUID as the reference material # # \param material_id \type{str} the id of the material for which to get the linked materials. diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 71cf584997..c833d8d1f5 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -79,7 +79,7 @@ Item iconName: "list-add" onClicked: { forceActiveFocus(); - base.newRootMaterialIdToSwitchTo = Cura.ContainerManager.createMaterial(); + base.newRootMaterialIdToSwitchTo = base.materialManager.createMaterial(); base.toActivateNewMaterial = true; } } From e3e470cb960db2318a27800cdcad2d9366645873 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 14:48:08 +0100 Subject: [PATCH 329/371] Simplify set update --- cura/Machines/QualityGroup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/Machines/QualityGroup.py b/cura/Machines/QualityGroup.py index 6067f04038..6945162401 100644 --- a/cura/Machines/QualityGroup.py +++ b/cura/Machines/QualityGroup.py @@ -38,8 +38,7 @@ class QualityGroup(QObject): for node in [self.node_for_global] + list(self.nodes_for_extruders.values()): if node is None: continue - for key in node.getContainer().getAllKeys(): - result.add(key) + result.update(node.getContainer().getAllKeys()) return result def getAllNodes(self) -> List["QualityGroup"]: From aa49b0131ee7c98b49f50d668546920b8a0cdde7 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 14:54:21 +0100 Subject: [PATCH 330/371] Remove outdated doc in QualityManager --- cura/Machines/QualityManager.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 794ea19c14..60ed15a9c3 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -17,21 +17,6 @@ if TYPE_CHECKING: from cura.Settings.GlobalStack import GlobalStack from .QualityChangesGroup import QualityChangesGroup -# -# Quality lookup tree structure: -# -# ------| -# | | -# -# | -# -# | -# -# | -# -# + -# - # # Similar to MaterialManager, QualityManager maintains a number of maps and trees for quality profile lookup. From 41b74684606a4dfdb3f77f0e419d28a7cccc156e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:03:54 +0100 Subject: [PATCH 331/371] Add comments for quality search priorities --- cura/Machines/QualityManager.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 60ed15a9c3..dc9dba8c4b 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -256,6 +256,17 @@ class QualityManager(QObject): if fallback_root_material_id: root_material_id_list.append(fallback_root_material_id) + # Here we construct a list of nodes we want to look for qualities with the highest priority first. + # The use case is that, when we look for qualities for a machine, we first want to search in the following + # order: + # 1. machine-variant-and-material-specific qualities if exist + # 2. machine-variant-specific qualities if exist + # 3. machine-material-specific qualities if exist + # 4. machine-specific qualities if exist + # 5. generic qualities if exist + # Each points above can be represented as a node in the lookup tree, so here we simply put those nodes into + # the list with priorities as the order. Later, we just need to loop over each node in this list and fetch + # qualities from there. nodes_to_check = [] if variant_name: From 5d5932547c672754bc45e2f151eb752cd4f8fd01 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:07:42 +0100 Subject: [PATCH 332/371] Cleanup imports for ContainerManager --- cura/Settings/ContainerManager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 19a010fe2a..b833e1f1e9 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -1,7 +1,6 @@ # Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -import copy import os.path import urllib.parse import uuid @@ -29,10 +28,10 @@ from UM.i18n import i18nCatalog from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderStack import ExtruderStack -from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch catalog = i18nCatalog("cura") + ## Manager class that contains common actions to deal with containers in Cura. # # This is primarily intended as a class to be able to perform certain actions From 86e12fc4378d583e144a69b34b569066286f50b6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:21:29 +0100 Subject: [PATCH 333/371] Add getDefaultVariantNode() in VariantManager --- cura/Machines/VariantManager.py | 25 ++++++++++++++++++++++++- cura/Settings/CuraStackBuilder.py | 26 +++++++------------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py index f7d80100a8..6cb0a3d7b2 100644 --- a/cura/Machines/VariantManager.py +++ b/cura/Machines/VariantManager.py @@ -3,14 +3,18 @@ from enum import Enum from collections import OrderedDict -from typing import Optional +from typing import Optional, TYPE_CHECKING from UM.Logger import Logger from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Util import parseBool from cura.Machines.ContainerNode import ContainerNode from cura.Settings.GlobalStack import GlobalStack +if TYPE_CHECKING: + from UM.Settings.DefinitionContainer import DefinitionContainer + class VariantType(Enum): BUILD_PLATE = "buildplate" @@ -86,3 +90,22 @@ class VariantManager: variant_type: Optional["VariantType"] = VariantType.NOZZLE) -> dict: machine_definition_id = machine.definition.getId() return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {}) + + # + # Gets the default variant for the given machine definition. + # + def getDefaultVariantNode(self, machine_definition: "DefinitionContainer", + variant_type: VariantType) -> Optional["ContainerNode"]: + machine_definition_id = machine_definition.getId() + preferred_variant_name = None + if variant_type == VariantType.BUILD_PLATE: + if parseBool(machine_definition.getMetaDataEntry("has_variant_buildplates", False)): + preferred_variant_name = machine_definition.getMetaDataEntry("preferred_variant_buildplate_name") + else: + if parseBool(machine_definition.getMetaDataEntry("has_variants", False)): + preferred_variant_name = machine_definition.getMetaDataEntry("preferred_variant_name") + + node = None + if preferred_variant_name: + node = self.getVariantNode(machine_definition_id, preferred_variant_name, variant_type) + return node diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 4d103d2537..efdfa677fc 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -41,29 +41,17 @@ class CuraStackBuilder: # get variant container for the global stack global_variant_container = application.empty_variant_container - if parseBool(machine_definition.getMetaDataEntry("has_variant_buildplates", False)): - global_variant_name = machine_definition.getMetaDataEntry("preferred_variant_buildplate_name") - if global_variant_name: - variant_node = variant_manager.getVariantNode(definition_id, global_variant_name, - variant_type = VariantType.BUILD_PLATE) - if variant_node is None: - raise RuntimeError("Cannot find buildplate variant with definition [%s] and variant name [%s]" % - (definition_id, global_variant_name)) - global_variant_container = variant_node.getContainer() + global_variant_node = variant_manager.getDefaultVariantNode(machine_definition, VariantType.BUILD_PLATE) + if global_variant_node: + global_variant_container = global_variant_node.getContainer() # get variant container for extruders extruder_variant_container = application.empty_variant_container - # Only look for the preferred variant if this machine has variants + extruder_variant_node = variant_manager.getDefaultVariantNode(machine_definition, VariantType.NOZZLE) extruder_variant_name = None - if parseBool(machine_definition.getMetaDataEntry("has_variants", False)): - extruder_variant_name = machine_definition.getMetaDataEntry("preferred_variant_name") - if extruder_variant_name: - variant_node = variant_manager.getVariantNode(definition_id, extruder_variant_name) - # Sanity check. If you see this error, the related definition files should be fixed. - if variant_node is None: - raise RuntimeError("Cannot find extruder variant with definition [%s] and variant name [%s]" % - (definition_id, extruder_variant_name)) - extruder_variant_container = variant_node.getContainer() + if extruder_variant_node: + extruder_variant_container = extruder_variant_node.getContainer() + extruder_variant_name = extruder_variant_container.getName() generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName()) # Make sure the new name does not collide with any definition or (quality) profile From 6db26eaca5053c5cabace4000a268fa0113b11a3 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:29:49 +0100 Subject: [PATCH 334/371] Add getDefaultMaterial() in MaterialManager --- cura/Machines/MaterialManager.py | 23 +++++++++++++++++++++-- cura/Settings/CuraStackBuilder.py | 15 ++------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 5998e8b020..98e4f67f82 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -4,17 +4,22 @@ from collections import defaultdict, OrderedDict import copy import uuid -from typing import Optional +from typing import Optional, TYPE_CHECKING from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot from UM.Application import Application from UM.Logger import Logger -from UM.Settings import ContainerRegistry +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.SettingFunction import SettingFunction +from UM.Util import parseBool from .MaterialNode import MaterialNode from .MaterialGroup import MaterialGroup +if TYPE_CHECKING: + from cura.Settings.GlobalStack import GlobalStack + # # MaterialManager maintains a number of maps and trees for material lookup. @@ -344,6 +349,20 @@ class MaterialManager(QObject): else: return None + def getDefaultMaterial(self, global_stack: "GlobalStack", extruder_variant_name: str) -> Optional["MaterialNode"]: + node = None + machine_definition = global_stack.definition + if parseBool(machine_definition.getMetaDataEntry("has_materials", False)): + material_diameter = machine_definition.getProperty("material_diameter", "value") + if isinstance(material_diameter, SettingFunction): + material_diameter = material_diameter(global_stack) + approximate_material_diameter = str(round(material_diameter)) + root_material_id = machine_definition.getMetaDataEntry("preferred_material") + root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter) + node = self.getMaterialNode(machine_definition.getId(), extruder_variant_name, + material_diameter, root_material_id) + return node + # # Methods for GUI # diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index efdfa677fc..a8234b9de9 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -71,19 +71,8 @@ class CuraStackBuilder: # get material container for extruders material_container = application.empty_material_container - # Only look for the preferred material if this machine has materials - if parseBool(machine_definition.getMetaDataEntry("has_materials", False)): - material_diameter = machine_definition.getProperty("material_diameter", "value") - if isinstance(material_diameter, SettingFunction): - material_diameter = material_diameter(new_global_stack) - approximate_material_diameter = str(round(material_diameter)) - root_material_id = machine_definition.getMetaDataEntry("preferred_material") - root_material_id = material_manager.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter) - material_node = material_manager.getMaterialNode(definition_id, extruder_variant_name, material_diameter, root_material_id) - # Sanity check. If you see this error, the related definition files should be fixed. - if not material_node: - raise RuntimeError("Cannot find material with definition [%s], extruder_variant_name [%s], and root_material_id [%s]" % - (definition_id, extruder_variant_name, root_material_id)) + material_node = material_manager.getDefaultMaterial(new_global_stack, extruder_variant_name) + if material_node: material_container = material_node.getContainer() # Create ExtruderStacks From a09bf7faa651bd09a4e0494a06660fba910ec18c Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:31:59 +0100 Subject: [PATCH 335/371] Move comments for _fixMaterialDiameterAndNozzleSize() --- cura/Settings/ExtruderManager.py | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index fe1bb6a990..a38e5cbfe1 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -404,6 +404,25 @@ class ExtruderManager(QObject): self.extrudersChanged.emit(global_stack_id) self.setActiveExtruderIndex(0) + # + # This function tries to fix the problem with per-extruder-settable nozzle size and material diameter problems + # in early versions (3.0 - 3.2.1). + # + # We cannot add a setting definition of "material_diameter" into the extruder's definition at runtime + # because all other machines which uses "fdmextruder" as the extruder definition will be affected. + # + # The problem is that single extrusion machines have their default material diameter defined in the global + # definitions. Now we automatically create an extruder stack for those machines using "fdmextruder" + # definition, which doesn't have the specific "material_diameter" and "machine_nozzle_size" defined for + # each machine. This results in wrong values which can be found in the MachineSettings dialog. + # + # To solve this, we put "material_diameter" back into the "fdmextruder" definition because modifying it in + # the extruder definition will affect all machines which uses the "fdmextruder" definition. Moreover, now + # we also check the value defined in the machine definition. If present, the value defined in the global + # stack's definition changes container will be copied. Otherwise, we will check if the default values in the + # machine definition and the extruder definition are the same, and if not, the default value in the machine + # definition will be copied to the extruder stack's definition changes. + # def _fixMaterialDiameterAndNozzleSize(self, global_stack, extruder_stack_list): keys_to_copy = ["material_diameter", "machine_nozzle_size"] # these will be copied over to all extruders @@ -414,22 +433,6 @@ class ExtruderManager(QObject): if extruder_stack.definitionChanges.hasProperty(key, "value"): continue - # - # We cannot add a setting definition of "material_diameter" into the extruder's definition at runtime - # because all other machines which uses "fdmextruder" as the extruder definition will be affected. - # - # The problem is that single extrusion machines have their default material diameter defined in the global - # definitions. Now we automatically create an extruder stack for those machines using "fdmextruder" - # definition, which doesn't have the specific "material_diameter" and "machine_nozzle_size" defined for - # each machine. This results in wrong values which can be found in the MachineSettings dialog. - # - # To solve this, we put "material_diameter" back into the "fdmextruder" definition because modifying it in - # the extruder definition will affect all machines which uses the "fdmextruder" definition. Moreover, now - # we also check the value defined in the machine definition. If present, the value defined in the global - # stack's definition changes container will be copied. Otherwise, we will check if the default values in the - # machine definition and the extruder definition are the same, and if not, the default value in the machine - # definition will be copied to the extruder stack's definition changes. - # setting_value_in_global_def_changes = global_stack.definitionChanges.getProperty(key, "value") setting_value_in_global_def = global_stack.definition.getProperty(key, "value") setting_value = setting_value_in_global_def From 7216641fad0c034a8db78070e9ec120460265d77 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:44:20 +0100 Subject: [PATCH 336/371] Update doc for _fixMaterialDiameterAndNozzleSize() --- cura/Settings/ExtruderManager.py | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index a38e5cbfe1..06342b68e5 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -408,20 +408,28 @@ class ExtruderManager(QObject): # This function tries to fix the problem with per-extruder-settable nozzle size and material diameter problems # in early versions (3.0 - 3.2.1). # - # We cannot add a setting definition of "material_diameter" into the extruder's definition at runtime - # because all other machines which uses "fdmextruder" as the extruder definition will be affected. + # In earlier versions, "nozzle size" and "material diameter" are only applicable to the complete machine, so all + # extruders share the same values. In this case, "nozzle size" and "material diameter" are saved in the + # GlobalStack's DefinitionChanges container. # - # The problem is that single extrusion machines have their default material diameter defined in the global - # definitions. Now we automatically create an extruder stack for those machines using "fdmextruder" - # definition, which doesn't have the specific "material_diameter" and "machine_nozzle_size" defined for - # each machine. This results in wrong values which can be found in the MachineSettings dialog. + # Later, we could have different "nozzle size" for each extruder, but "material diameter" could only be set for + # the entire machine. In this case, "nozzle size" should be saved in each ExtruderStack's DefinitionChanges, but + # "material diameter" still remains in the GlobalStack's DefinitionChanges. # - # To solve this, we put "material_diameter" back into the "fdmextruder" definition because modifying it in - # the extruder definition will affect all machines which uses the "fdmextruder" definition. Moreover, now - # we also check the value defined in the machine definition. If present, the value defined in the global - # stack's definition changes container will be copied. Otherwise, we will check if the default values in the - # machine definition and the extruder definition are the same, and if not, the default value in the machine - # definition will be copied to the extruder stack's definition changes. + # Lateer, both "nozzle size" and "material diameter" are settable per-extruder, and both settings should be saved + # in the ExtruderStack's DefinitionChanges. + # + # There were some bugs in upgrade so the data weren't saved correct as described above. This function tries fix + # this. + # + # One more thing is about material diameter and single-extrusion machines. Most single-extrusion machines don't + # specifically define their extruder definition, so they reuse "fdmextruder", but for those machines, they may + # define "material diameter = 1.75" in their machine definition, but in "fdmextruder", it's still "2.85". This + # causes a problem with incorrect default values. + # + # This is also fixed here in this way: If no "material diameter" is specified, it will look for the default value + # in both the Extruder's definition and the Global's definition. If 2 values don't match, we will use the value + # from the Global definition by setting it in the Extruder's DefinitionChanges container. # def _fixMaterialDiameterAndNozzleSize(self, global_stack, extruder_stack_list): keys_to_copy = ["material_diameter", "machine_nozzle_size"] # these will be copied over to all extruders From a2c2282b44dece50f9548a36fc4d747371ffd1a8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:50:33 +0100 Subject: [PATCH 337/371] Use context to evaluate materialDiameter --- cura/Settings/ExtruderStack.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index 2995aae795..4400f621c6 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -10,10 +10,9 @@ from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase from UM.Settings.ContainerStack import ContainerStack from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.Interfaces import ContainerInterface, PropertyEvaluationContext -from UM.Settings.SettingInstance import SettingInstance from . import Exceptions -from .CuraContainerStack import CuraContainerStack +from .CuraContainerStack import CuraContainerStack, _ContainerIndexes from .ExtruderManager import ExtruderManager if TYPE_CHECKING: @@ -57,14 +56,10 @@ class ExtruderStack(CuraContainerStack): # \return The filament diameter for the printer @property def materialDiameter(self) -> float: - containers_to_check = [self.variant, self.definitionChanges, self.definition] + context = PropertyEvaluationContext(self) + context.context["evaluate_from_container_index"] = _ContainerIndexes.Variant - for container in containers_to_check: - if container is not None: - material_diameter = container.getProperty("material_diameter", "value") - if material_diameter is not None: - return material_diameter - return -1 + return self.getProperty("material_diameter", "value", context = context) ## Return the approximate filament diameter that the machine requires. # From 632be11323815be21d6ce1257abddc24ba1aa6ed Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:51:51 +0100 Subject: [PATCH 338/371] Remove "#NEW"s --- cura/Settings/MachineManager.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index fe35673f16..0091de5e24 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -117,7 +117,6 @@ class MachineManager(QObject): if containers: containers[0].nameChanged.connect(self._onMaterialNameChanged) - # NEW self._material_manager = self._application._material_manager self._material_manager.materialsUpdated.connect(self._onMaterialsUpdated) @@ -126,7 +125,6 @@ class MachineManager(QObject): # be reflected on the GUI. This signal emission makes sure that it happens. self.rootMaterialChanged.emit() - ### NEW activeQualityGroupChanged = pyqtSignal() activeQualityChangesGroupChanged = pyqtSignal() @@ -784,10 +782,6 @@ class MachineManager(QObject): container = extruder.userChanges container.setProperty(setting_name, property_name, property_value) - # - # New - # - # We not fetch it from _current_root_material_id, but later we can get it from somewhere else @pyqtProperty("QVariantList", notify = rootMaterialChanged) def currentExtruderPositions(self): From 51fadc98687085496b718d2a398518fd995509c6 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:53:46 +0100 Subject: [PATCH 339/371] Remove unnecessary _onMaterialsUpdated() --- cura/Settings/MachineManager.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 0091de5e24..efcfaca4ea 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -118,12 +118,10 @@ class MachineManager(QObject): containers[0].nameChanged.connect(self._onMaterialNameChanged) self._material_manager = self._application._material_manager - self._material_manager.materialsUpdated.connect(self._onMaterialsUpdated) - def _onMaterialsUpdated(self): # When the materials lookup table gets updated, it can mean that a material has its name changed, which should # be reflected on the GUI. This signal emission makes sure that it happens. - self.rootMaterialChanged.emit() + self._material_manager.materialsUpdated.connect(self.rootMaterialChanged) activeQualityGroupChanged = pyqtSignal() activeQualityChangesGroupChanged = pyqtSignal() From 89716acc11d5b53683c347cf45a4bc05a9224d26 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:56:05 +0100 Subject: [PATCH 340/371] Remove redundant code in MachineManager --- cura/Settings/MachineManager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index efcfaca4ea..33a52528fd 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -297,12 +297,10 @@ class MachineManager(QObject): if containers: global_stack = containers[0] ExtruderManager.getInstance().setActiveExtruderIndex(0) # Switch to first extruder - Application.getInstance().setGlobalContainerStack(global_stack) self._global_container_stack = global_stack Application.getInstance().setGlobalContainerStack(global_stack) ExtruderManager.getInstance()._globalContainerStackChanged() self._initMachineState(containers[0]) - self.globalContainerChanged.emit() self._onGlobalContainerChanged() self.__emitChangedSignals() From bb04afa2ab3b6c8ab3c442d6fb9e1ca26c42ebb4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:57:28 +0100 Subject: [PATCH 341/371] Remove non-sense comments in MachineManager --- cura/Settings/MachineManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 33a52528fd..744d9c69c5 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -778,7 +778,6 @@ class MachineManager(QObject): container = extruder.userChanges container.setProperty(setting_name, property_name, property_value) - # We not fetch it from _current_root_material_id, but later we can get it from somewhere else @pyqtProperty("QVariantList", notify = rootMaterialChanged) def currentExtruderPositions(self): return sorted(list(self._current_root_material_id.keys())) From 413e4ca55dc6fe2ddf9802ac136213c370f9795c Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 15:59:59 +0100 Subject: [PATCH 342/371] Add doc for _setEmptyQuality() --- cura/Settings/MachineManager.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 744d9c69c5..ded507fc94 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -817,6 +817,10 @@ class MachineManager(QObject): return result + # + # Sets all quality and quality_changes containers to empty_quality and empty_quality_changes containers + # for all stacks in the currently active machine. + # def _setEmptyQuality(self): self._current_quality_group = None self._current_quality_changes_group = None From a220b55856dc27fa50d19e8b87e6fa2a0c4efd33 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:01:59 +0100 Subject: [PATCH 343/371] Simplify code in MachineManager --- cura/Settings/MachineManager.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index ded507fc94..0e21a7e4bd 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -118,6 +118,7 @@ class MachineManager(QObject): containers[0].nameChanged.connect(self._onMaterialNameChanged) self._material_manager = self._application._material_manager + self._quality_manager = self._application.getQualityManager() # When the materials lookup table gets updated, it can mean that a material has its name changed, which should # be reflected on the GUI. This signal emission makes sure that it happens. @@ -853,11 +854,8 @@ class MachineManager(QObject): self.activeQualityChangesGroupChanged.emit() def _setQualityChangesGroup(self, quality_changes_group): - # TODO: quality_changes groups depend on a quality_type. Here it's fetching the quality_types every time. - # Can we do this better, like caching the quality group a quality_changes group depends on? quality_type = quality_changes_group.quality_type - quality_manager = Application.getInstance()._quality_manager - quality_group_dict = quality_manager.getQualityGroups(self._global_container_stack) + quality_group_dict = self._quality_manager.getQualityGroups(self._global_container_stack) quality_group = quality_group_dict[quality_type] quality_changes_container = self._empty_quality_changes_container From 174bc7dbd7588e7bc31801cdd2bfeb61bfc75b63 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:04:30 +0100 Subject: [PATCH 344/371] Remove commented code in MachineManager --- cura/Settings/MachineManager.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 0e21a7e4bd..e357d778ca 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -971,13 +971,6 @@ class MachineManager(QObject): self._setMaterial(position, new_material) continue - # # Find a fallback material - # preferred_material_query = self._global_container_stack.getMetaDataEntry("preferred_material") - # preferred_material_key = preferred_material_query.replace("*", "") - # if preferred_material_key in candidate_materials: - # self._setMaterial(position, candidate_materials[preferred_material_key]) - # return - @pyqtSlot("QVariant") def setGlobalVariant(self, container_node): self.blurSettings.emit() From ca88e0df88df888329bb1c54b4b23a25587c8046 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:12:33 +0100 Subject: [PATCH 345/371] Add doc for calllater active machine in project loading --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 6dd20b66e0..cbe882f253 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -1082,6 +1082,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader): CuraApplication.getInstance().getMachineManager().activeQualityChanged.emit() # Actually change the active machine. + # + # This is scheduled for later is because it depends on the Variant/Material/Qualitiy Managers to have the latest + # data, but those managers will only update upon a container/container metadata changed signal. Because this + # function is running on the main thread (Qt thread), although those "changed" signals have been emitted, but + # they won't take effect until this function is done. + # To solve this, we schedule _updateActiveMachine() for later so it will have the latest data. CuraApplication.getInstance().callLater(self._updateActiveMachine, global_stack) # Load all the nodes / meshdata of the workspace From 25676426269ab2b688a42e9dffc249c002cda5c0 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:13:35 +0100 Subject: [PATCH 346/371] Remove outdated TODO --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 80e3e3b721..ff9df1a055 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -606,8 +606,6 @@ class XmlMaterialProfile(InstanceContainer): if not variant_node: continue - # TODO: check if build plate variant exists - buildplate_compatibility = machine_compatibility buildplate_recommended = machine_compatibility settings = buildplate.iterfind("./um:setting", self.__namespaces) From d24bc0b41b7a6c9f15e5e76d6db0c60c26c089bb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:23:54 +0100 Subject: [PATCH 347/371] Fix code style in MaterialView.qml --- resources/qml/Preferences/MaterialView.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 7e0efd56de..6cea001450 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -216,7 +216,8 @@ TabView confirmDiameterChangeDialog.old_approximate_diameter_value = old_approximate_diameter; confirmDiameterChangeDialog.open() - } else { + } + else { Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value); base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, getApproximateDiameter(value).toString()); base.setMetaDataEntry("properties/diameter", properties.diameter, value); From 575f38e63e55d195214bbddec9290c441b473f28 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:25:09 +0100 Subject: [PATCH 348/371] Fix code style in MaterialView.qml --- resources/qml/Preferences/MaterialView.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 6cea001450..0016f211e7 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -399,13 +399,15 @@ TabView onEditingFinished: materialPropertyProvider.setPropertyValue("value", value) } - UM.ContainerPropertyProvider { + UM.ContainerPropertyProvider + { id: materialPropertyProvider containerId: base.containerId watchedProperties: [ "value" ] key: model.key } - UM.ContainerPropertyProvider { + UM.ContainerPropertyProvider + { id: machinePropertyProvider containerId: Cura.MachineManager.activeDefinitionId watchedProperties: [ "value" ] From 0e5aff84e9b71df180df297169f751e5810c13d5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:26:00 +0100 Subject: [PATCH 349/371] Remove outdated comment in MaterialsPage.qml --- resources/qml/Preferences/MaterialsPage.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index c833d8d1f5..48259e51ca 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -283,7 +283,6 @@ Item } visible: text != "" text: { - // OLD STUFF var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; if (Cura.MachineManager.hasVariants) { From 86b75ae3b6807834c7940c6d7a0a169016d3b816 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:29:31 +0100 Subject: [PATCH 350/371] Remove outdated TODO --- resources/qml/Preferences/MaterialsPage.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 48259e51ca..cd72ef81b0 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -361,7 +361,7 @@ Item width: Math.floor((parent.width * 0.3)) text: model.material elide: Text.ElideRight - font.italic: { // TODO: make it easier + font.italic: { const extruder_position = Cura.ExtruderManager.activeExtruderIndex; const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; return model.root_material_id == root_material_id @@ -372,7 +372,7 @@ Item { text: (model.name != model.material) ? model.name : "" elide: Text.ElideRight - font.italic: { // TODO: make it easier + font.italic: { const extruder_position = Cura.ExtruderManager.activeExtruderIndex; const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; return model.root_material_id == root_material_id; From 730048d2b28aab42b6e05b3799422cc1b959dd46 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:32:29 +0100 Subject: [PATCH 351/371] Simplify code in MaterialsPage.qml --- resources/qml/Preferences/MaterialsPage.qml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index cd72ef81b0..b9b9207d1d 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -344,10 +344,19 @@ Item Row { + id: materialRow spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.right: parent.right + + property bool isItemActivated: + { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return model.root_material_id == root_material_id; + } + Rectangle { width: Math.floor(parent.height * 0.8) @@ -361,22 +370,14 @@ Item width: Math.floor((parent.width * 0.3)) text: model.material elide: Text.ElideRight - font.italic: { - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return model.root_material_id == root_material_id - } + font.italic: materialRow.isItemActivated color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; } Label { text: (model.name != model.material) ? model.name : "" elide: Text.ElideRight - font.italic: { - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return model.root_material_id == root_material_id; - } + font.italic: materialRow.isItemActivated color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; } } From 6a14e396105c96035e15235d880ac2ee9dfc982f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Sat, 3 Mar 2018 16:34:31 +0100 Subject: [PATCH 352/371] Remove outdated TODOs in ProfilesPage --- resources/qml/Preferences/ProfilesPage.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index aaf9bdac0e..e9bbb4bc66 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -266,7 +266,7 @@ Item id: importDialog title: catalog.i18nc("@title:window", "Import Profile") selectExisting: true - nameFilters: qualitiesModel.getFileNameFilters("profile_reader") // TODO: make this easier + nameFilters: qualitiesModel.getFileNameFilters("profile_reader") folder: CuraApplication.getDefaultPath("dialog_profile_path") onAccepted: { @@ -292,11 +292,10 @@ Item id: exportDialog title: catalog.i18nc("@title:window", "Export Profile") selectExisting: false - nameFilters: qualitiesModel.getFileNameFilters("profile_writer") // TODO: make this easier + nameFilters: qualitiesModel.getFileNameFilters("profile_writer") folder: CuraApplication.getDefaultPath("dialog_profile_path") onAccepted: { - // TODO: make this easier var result = Cura.ContainerManager.exportQualityChangesGroup(base.currentItem.quality_changes_group, fileUrl, selectedNameFilter); From 396ea274c457dc74005b40a2897d5d9c37539451 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 5 Mar 2018 09:23:21 +0100 Subject: [PATCH 353/371] Invert Y direction of nozzle offsets If there is a Y offset it should now move the disallowed areas in the correct direction The initial placement of the disallowed borders was already correct. Fixes #1977. --- cura/BuildVolume.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 60e7a32857..1cdcf9971a 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -826,6 +826,7 @@ class BuildVolume(SceneNode): offset_y = extruder.getProperty("machine_nozzle_offset_y", "value") if offset_y is None: offset_y = 0 + offset_y = -offset_y #Y direction of g-code is the inverse of Y direction of Cura's scene space. result[extruder_id] = [] for polygon in machine_disallowed_polygons: From 1e467b66c03414d1a1c35651dc06a03759228bc8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 10:22:11 +0100 Subject: [PATCH 354/371] Fix protected variable access --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index ff9df1a055..a23d5f590a 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -59,7 +59,7 @@ class XmlMaterialProfile(InstanceContainer): return # Get the MaterialGroup - material_manager = CuraApplication.getInstance()._material_manager + material_manager = CuraApplication.getInstance().getMaterialManager() root_material_id = self.getMetaDataEntry("base_file") #if basefile is self.getId, this is a basefile. material_group = material_manager.getMaterialGroup(root_material_id) From b4deb3e82823d8309f9ff834e48985a49546a0c3 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 10:23:36 +0100 Subject: [PATCH 355/371] Better logging in quality profile model --- cura/Machines/Models/QualityProfilesDropDownMenuModel.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py index d3135b31c6..081badc604 100644 --- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -57,6 +57,7 @@ class QualityProfilesDropDownMenuModel(ListModel): # Check for material compatibility if not self._machine_manager.activeMaterialsCompatible(): + Logger.log("d", "No active material compatibility, set quality profile model as empty.") self.setItems([]) return From 2255dc628be27e95a39a2dbf59af5ec3806a754b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 10:31:04 +0100 Subject: [PATCH 356/371] Remove unnecessary comments --- cura/Machines/Models/QualityProfilesDropDownMenuModel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py index 081badc604..fd919639c3 100644 --- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -37,7 +37,6 @@ class QualityProfilesDropDownMenuModel(ListModel): self._machine_manager = self._application.getMachineManager() self._quality_manager = Application.getInstance().getQualityManager() - # connect signals self._application.globalContainerStackChanged.connect(self._update) self._machine_manager.activeQualityGroupChanged.connect(self._update) self._quality_manager.qualitiesUpdated.connect(self._update) From f86c2a2f8aec4d152376c1b53730ee2a24edb1fa Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 10:32:59 +0100 Subject: [PATCH 357/371] Add comments for quality settings model --- cura/Machines/Models/QualitySettingsModel.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index b1f30e84ee..be00298c6f 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -87,6 +87,8 @@ class QualitySettingsModel(ListModel): settings_keys = quality_group.getAllKeys() quality_containers = [quality_node.getContainer()] + # Here, if the user has selected a quality changes, then "quality_changes_group" will not be None, and we fetch + # the settings in that quality_changes_group. if quality_changes_group is not None: if self._selected_position == "": quality_changes_node = quality_changes_group.node_for_global From d79a9f644972987f0e85f7933a9294b9597154ac Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 10:35:54 +0100 Subject: [PATCH 358/371] Add logging for quality settings model --- cura/Machines/Models/QualitySettingsModel.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index be00298c6f..38b7ec28e4 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -4,6 +4,7 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt from UM.Application import Application +from UM.Logger import Logger from UM.Qt.ListModel import ListModel from UM.Settings.ContainerRegistry import ContainerRegistry @@ -99,6 +100,7 @@ class QualitySettingsModel(ListModel): quality_containers.insert(0, quality_changes_node.getContainer()) except: # FIXME: This is to prevent incomplete update of QualityManager + Logger.logException("d", "Failed to get container for quality changes node %s", quality_changes_node) return settings_keys.update(quality_changes_group.getAllKeys()) From 6781627672465d7214e7287cc00fefbadc130295 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 5 Mar 2018 10:42:09 +0100 Subject: [PATCH 359/371] Fix: Flat model and reset all rotation did not work CURA-5039 --- plugins/PerObjectSettingsTool/PerObjectItem.qml | 4 ++-- plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectItem.qml b/plugins/PerObjectSettingsTool/PerObjectItem.qml index 89679b57a2..1317c00b19 100644 --- a/plugins/PerObjectSettingsTool/PerObjectItem.qml +++ b/plugins/PerObjectSettingsTool/PerObjectItem.qml @@ -32,11 +32,11 @@ UM.TooltipArea if(checked) { addedSettingsModel.setVisible(model.key, checked); - UM.ActiveTool.triggerAction("subscribeForSettingValidation", model.key) + UM.ActiveTool.triggerActionWithData("subscribeForSettingValidation", model.key) } else { - UM.ActiveTool.triggerAction("unsubscribeForSettingValidation", model.key) + UM.ActiveTool.triggerActionWithData("unsubscribeForSettingValidation", model.key) addedSettingsModel.setVisible(model.key, checked); } UM.ActiveTool.forceUpdate(); diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 4b5d2a5708..e72e1224df 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -242,7 +242,7 @@ Item { onClicked: { addedSettingsModel.setVisible(model.key, false) - UM.ActiveTool.triggerAction("unsubscribeForSettingValidation", model.key) + UM.ActiveTool.triggerActionWithData("unsubscribeForSettingValidation", model.key) } style: ButtonStyle From 6c42b662c85408c844792edeb60d084a21a8e8a5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 10:53:40 +0100 Subject: [PATCH 360/371] Add doc for apply_to_all in XMLMaterialProfile --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index a23d5f590a..edc782cc9e 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -48,6 +48,12 @@ class XmlMaterialProfile(InstanceContainer): ## Overridden from InstanceContainer # set the meta data for all machine / variant combinations + # + # The "apply_to_all" flag indicates whether this piece of metadata should be applied to all material containers + # or just this specific container. + # For example, when you change the material name, you want to apply it to all its derived containers, but for + # some specific settings, they should only be applied to a machine/variant-specific container. + # def setMetaDataEntry(self, key, value, apply_to_all = True): registry = ContainerRegistry.getInstance() if registry.isReadOnly(self.getId()): From caca5e502172e24c581c57de0af7fd4e9106e4fc Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 10:57:36 +0100 Subject: [PATCH 361/371] Fix code style in materialspage --- resources/qml/Preferences/MaterialsPage.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index b9b9207d1d..396cf58aa4 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -39,12 +39,14 @@ Item property var hasCurrentItem: materialListView.currentItem != null - property var currentItem: { // is soon to be overwritten + property var currentItem: + { // is soon to be overwritten var current_index = materialListView.currentIndex; return materialsModel.getItem(current_index); } - property var isCurrentItemActivated: { + property var isCurrentItemActivated: + { const extruder_position = Cura.ExtruderManager.activeExtruderIndex; const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; return base.currentItem.root_material_id == root_material_id; From eb5ce04229c6383dbac84dcf48c308eff69ebf50 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 10:59:10 +0100 Subject: [PATCH 362/371] Fix code style in materialspage --- resources/qml/Preferences/MaterialsPage.qml | 39 ++++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 396cf58aa4..a5bb2f9883 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -55,7 +55,8 @@ Item Row // Button Row { id: buttonRow - anchors { + anchors + { left: parent.left right: parent.right top: titleLabel.bottom @@ -63,11 +64,13 @@ Item height: childrenRect.height // Activate button - Button { + Button + { text: catalog.i18nc("@action:button", "Activate") iconName: "list-activate" enabled: !isCurrentItemActivated - onClicked: { + onClicked: + { forceActiveFocus() const extruder_position = Cura.ExtruderManager.activeExtruderIndex; @@ -76,10 +79,12 @@ Item } // Create button - Button { + Button + { text: catalog.i18nc("@action:button", "Create") iconName: "list-add" - onClicked: { + onClicked: + { forceActiveFocus(); base.newRootMaterialIdToSwitchTo = base.materialManager.createMaterial(); base.toActivateNewMaterial = true; @@ -87,11 +92,13 @@ Item } // Duplicate button - Button { + Button + { text: catalog.i18nc("@action:button", "Duplicate"); iconName: "list-add" enabled: base.hasCurrentItem - onClicked: { + onClicked: + { forceActiveFocus(); base.newRootMaterialIdToSwitchTo = base.materialManager.duplicateMaterial(base.currentItem.container_node); base.toActivateNewMaterial = true; @@ -99,21 +106,25 @@ Item } // Remove button - Button { + Button + { text: catalog.i18nc("@action:button", "Remove") iconName: "list-remove" enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated - onClicked: { + onClicked: + { forceActiveFocus(); confirmRemoveMaterialDialog.open(); } } // Import button - Button { + Button + { text: catalog.i18nc("@action:button", "Import") iconName: "document-import" - onClicked: { + onClicked: + { forceActiveFocus(); importMaterialDialog.open(); } @@ -121,10 +132,12 @@ Item } // Export button - Button { + Button + { text: catalog.i18nc("@action:button", "Export") iconName: "document-export" - onClicked: { + onClicked: + { forceActiveFocus(); exportMaterialDialog.open(); } From 6d97fd8dc20d25df6fd25d161d56847fe90242bd Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 11:01:52 +0100 Subject: [PATCH 363/371] Revert "WIP: Fix quality profiles for abax_pri3" This reverts commit c338e1b7d69c252ae80d9590700823108a37f320. --- resources/definitions/abax_pri3.def.json | 3 +-- resources/quality/abax_pri3/apri3_fast.inst.cfg | 14 -------------- resources/quality/abax_pri3/apri3_high.inst.cfg | 14 -------------- resources/quality/abax_pri3/apri3_normal.inst.cfg | 14 -------------- .../quality/abax_pri3/apri3_pla_fast.inst.cfg | 5 +++-- .../quality/abax_pri3/apri3_pla_high.inst.cfg | 1 + .../quality/abax_pri3/apri3_pla_normal.inst.cfg | 1 + 7 files changed, 6 insertions(+), 46 deletions(-) delete mode 100644 resources/quality/abax_pri3/apri3_fast.inst.cfg delete mode 100644 resources/quality/abax_pri3/apri3_high.inst.cfg delete mode 100644 resources/quality/abax_pri3/apri3_normal.inst.cfg diff --git a/resources/definitions/abax_pri3.def.json b/resources/definitions/abax_pri3.def.json index f91a501a6f..2fa648096f 100644 --- a/resources/definitions/abax_pri3.def.json +++ b/resources/definitions/abax_pri3.def.json @@ -6,8 +6,7 @@ "visible": true, "author": "ABAX 3d Technologies", "manufacturer": "ABAX 3d Technologies", - "file_formats": "text/x-gcode", - "has_machine_quality": true + "file_formats": "text/x-gcode" }, "overrides": { "machine_start_gcode": { diff --git a/resources/quality/abax_pri3/apri3_fast.inst.cfg b/resources/quality/abax_pri3/apri3_fast.inst.cfg deleted file mode 100644 index 7db569ec72..0000000000 --- a/resources/quality/abax_pri3/apri3_fast.inst.cfg +++ /dev/null @@ -1,14 +0,0 @@ -[general] -version = 2 -name = Fast -definition = abax_pri3 - -[metadata] -setting_version = 4 -type = quality -quality_type = fast -weight = -1 -global_quality = True - -[values] -layer_height = 0.2 diff --git a/resources/quality/abax_pri3/apri3_high.inst.cfg b/resources/quality/abax_pri3/apri3_high.inst.cfg deleted file mode 100644 index 8a95b71a88..0000000000 --- a/resources/quality/abax_pri3/apri3_high.inst.cfg +++ /dev/null @@ -1,14 +0,0 @@ -[general] -version = 2 -name = Extra Fine -definition = abax_pri3 - -[metadata] -setting_version = 4 -type = quality -quality_type = high -weight = 1 -global_quality = True - -[values] -layer_height = 0.1 diff --git a/resources/quality/abax_pri3/apri3_normal.inst.cfg b/resources/quality/abax_pri3/apri3_normal.inst.cfg deleted file mode 100644 index 29b25d889f..0000000000 --- a/resources/quality/abax_pri3/apri3_normal.inst.cfg +++ /dev/null @@ -1,14 +0,0 @@ -[general] -version = 2 -name = Fine -definition = abax_pri3 - -[metadata] -setting_version = 4 -type = quality -quality_type = normal -weight = 0 -global_quality = True - -[values] -layer_height = 0.2 diff --git a/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg b/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg index f24f198b2e..7d1c1bf588 100644 --- a/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_fast.inst.cfg @@ -1,16 +1,17 @@ [general] version = 2 -name = Fast +name = Fine definition = abax_pri3 [metadata] setting_version = 4 type = quality -quality_type = fast +quality_type = normal weight = -1 material = generic_pla [values] +layer_height = 0.2 wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 diff --git a/resources/quality/abax_pri3/apri3_pla_high.inst.cfg b/resources/quality/abax_pri3/apri3_pla_high.inst.cfg index 5b4c470842..46a4178dd9 100644 --- a/resources/quality/abax_pri3/apri3_pla_high.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_high.inst.cfg @@ -11,6 +11,7 @@ weight = 1 material = generic_pla [values] +layer_height = 0.1 wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 diff --git a/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg b/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg index 2df629af38..3f6f36cfe6 100644 --- a/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg +++ b/resources/quality/abax_pri3/apri3_pla_normal.inst.cfg @@ -11,6 +11,7 @@ weight = 0 material = generic_pla [values] +layer_height = 0.2 wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 From c99fca0890fd8c32b8146fce8c378add23faf974 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 11:09:54 +0100 Subject: [PATCH 364/371] Put adhesion_type back to imade3d profiles --- .../quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg | 1 + .../imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg | 1 + .../quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg | 1 + .../imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg | 1 + .../quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg | 1 + .../imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg | 1 + resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg | 1 + .../imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg | 1 + .../quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg | 1 + .../imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg | 1 + .../quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg | 1 + 11 files changed, 11 insertions(+) diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg index f300f5d95b..4d0493ae8b 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse.inst.cfg @@ -12,6 +12,7 @@ material = generic_petg variant = 0.4 mm [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg index 804807184b..9251ae43b4 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_coarse_2-fans.inst.cfg @@ -12,6 +12,7 @@ material = generic_petg variant = 0.4 mm 2-fans [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg index c39c8a7a98..a10a3bcf0a 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium.inst.cfg @@ -12,6 +12,7 @@ material = generic_petg variant = 0.4 mm [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg index 17cc1493e1..b851c2e17c 100644 --- a/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_petg_0.4_medium_2-fans.inst.cfg @@ -12,6 +12,7 @@ material = generic_petg variant = 0.4 mm 2-fans [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg index 738eb627fe..bc86119eb8 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse.inst.cfg @@ -12,6 +12,7 @@ material = generic_pla variant = 0.4 mm [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg index 4f44559fbc..c05927fad5 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_coarse_2-fans.inst.cfg @@ -12,6 +12,7 @@ material = generic_pla variant = 0.4 mm 2-fans [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg index f9f32237b0..1bec96f05c 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine.inst.cfg @@ -12,6 +12,7 @@ material = generic_pla variant = 0.4 mm [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg index 82f5a4fa32..609662a149 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_fine_2-fans.inst.cfg @@ -12,6 +12,7 @@ material = generic_pla variant = 0.4 mm 2-fans [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg index 5ee2111c3a..5249f2dc2b 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium.inst.cfg @@ -12,6 +12,7 @@ material = generic_pla variant = 0.4 mm [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg index 5d34259ccd..1534d3a6fb 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_medium_2-fans.inst.cfg @@ -12,6 +12,7 @@ material = generic_pla variant = 0.4 mm 2-fans [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 diff --git a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg index 1826e69513..1166bd70c9 100644 --- a/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg +++ b/resources/quality/imade3d_jellybox/generic_pla_0.4_ultrafine.inst.cfg @@ -12,6 +12,7 @@ material = generic_pla variant = 0.4 mm [values] +adhesion_type = skirt bottom_thickness = 0.6 coasting_enable = True coasting_speed = 95 From 1c7fdfd87104ec1ef0cd0782f74cdffb7009a552 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 5 Mar 2018 11:13:38 +0100 Subject: [PATCH 365/371] CURA-5032 Incorporated additional feedback --- resources/preset_setting_visibility_groups/expert.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resources/preset_setting_visibility_groups/expert.cfg b/resources/preset_setting_visibility_groups/expert.cfg index 0cd9adfd46..e180b831d8 100644 --- a/resources/preset_setting_visibility_groups/expert.cfg +++ b/resources/preset_setting_visibility_groups/expert.cfg @@ -109,6 +109,7 @@ material_diameter material_adhesion_tendency material_surface_energy material_flow +material_flow_layer_0 retraction_enable retract_at_layer_change retraction_amount @@ -218,6 +219,7 @@ support_bottom_extruder_nr support_type support_angle support_pattern +zig_zaggify_support support_connect_zigzags support_infill_rate support_line_distance @@ -281,6 +283,7 @@ raft_fan_speed [dual] prime_tower_enable +prime_tower_circular prime_tower_size prime_tower_min_volume prime_tower_wall_thickness From 072c85bacfb06cfaa13151809787ba86f040ac33 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 11:16:45 +0100 Subject: [PATCH 366/371] Put authors back for 3rd party variants --- resources/variants/cartesio_0.25.inst.cfg | 1 + resources/variants/cartesio_0.4.inst.cfg | 1 + resources/variants/cartesio_0.8.inst.cfg | 1 + resources/variants/fabtotum_hyb35.inst.cfg | 1 + resources/variants/fabtotum_lite04.inst.cfg | 1 + resources/variants/fabtotum_lite06.inst.cfg | 1 + resources/variants/fabtotum_pro02.inst.cfg | 1 + resources/variants/fabtotum_pro04.inst.cfg | 1 + resources/variants/fabtotum_pro06.inst.cfg | 1 + resources/variants/fabtotum_pro08.inst.cfg | 1 + resources/variants/gmax15plus_025_e3d.inst.cfg | 1 + resources/variants/gmax15plus_04_e3d.inst.cfg | 1 + resources/variants/gmax15plus_05_e3d.inst.cfg | 1 + resources/variants/gmax15plus_05_jhead.inst.cfg | 1 + resources/variants/gmax15plus_06_e3d.inst.cfg | 1 + resources/variants/gmax15plus_08_e3d.inst.cfg | 1 + resources/variants/gmax15plus_10_jhead.inst.cfg | 1 + resources/variants/gmax15plus_dual_025_e3d.inst.cfg | 1 + resources/variants/gmax15plus_dual_04_e3d.inst.cfg | 1 + resources/variants/gmax15plus_dual_05_e3d.inst.cfg | 1 + resources/variants/gmax15plus_dual_05_jhead.inst.cfg | 1 + resources/variants/gmax15plus_dual_06_e3d.inst.cfg | 1 + resources/variants/gmax15plus_dual_08_e3d.inst.cfg | 1 + resources/variants/gmax15plus_dual_10_jhead.inst.cfg | 1 + resources/variants/imade3d_jellybox_0.4.inst.cfg | 1 + resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg | 1 + 26 files changed, 26 insertions(+) diff --git a/resources/variants/cartesio_0.25.inst.cfg b/resources/variants/cartesio_0.25.inst.cfg index 2272aebde5..014069451c 100644 --- a/resources/variants/cartesio_0.25.inst.cfg +++ b/resources/variants/cartesio_0.25.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = cartesio [metadata] +author = Cartesio setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/cartesio_0.4.inst.cfg b/resources/variants/cartesio_0.4.inst.cfg index bd3302da03..7b5dccd980 100644 --- a/resources/variants/cartesio_0.4.inst.cfg +++ b/resources/variants/cartesio_0.4.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = cartesio [metadata] +author = Cartesio setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/cartesio_0.8.inst.cfg b/resources/variants/cartesio_0.8.inst.cfg index eda8248584..70271dbf75 100644 --- a/resources/variants/cartesio_0.8.inst.cfg +++ b/resources/variants/cartesio_0.8.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = cartesio [metadata] +author = Cartesio setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/fabtotum_hyb35.inst.cfg b/resources/variants/fabtotum_hyb35.inst.cfg index 6d699f6df8..e036b2e474 100644 --- a/resources/variants/fabtotum_hyb35.inst.cfg +++ b/resources/variants/fabtotum_hyb35.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = fabtotum [metadata] +author = FABtotum setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/fabtotum_lite04.inst.cfg b/resources/variants/fabtotum_lite04.inst.cfg index 5d376de4a1..defa6692a8 100644 --- a/resources/variants/fabtotum_lite04.inst.cfg +++ b/resources/variants/fabtotum_lite04.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = fabtotum [metadata] +author = FABtotum setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/fabtotum_lite06.inst.cfg b/resources/variants/fabtotum_lite06.inst.cfg index 0181461613..d269092b42 100644 --- a/resources/variants/fabtotum_lite06.inst.cfg +++ b/resources/variants/fabtotum_lite06.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = fabtotum [metadata] +author = FABtotum setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/fabtotum_pro02.inst.cfg b/resources/variants/fabtotum_pro02.inst.cfg index c63ed6d982..b705929c35 100644 --- a/resources/variants/fabtotum_pro02.inst.cfg +++ b/resources/variants/fabtotum_pro02.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = fabtotum [metadata] +author = FABtotum setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/fabtotum_pro04.inst.cfg b/resources/variants/fabtotum_pro04.inst.cfg index 6fc2d7c4f7..b835312324 100644 --- a/resources/variants/fabtotum_pro04.inst.cfg +++ b/resources/variants/fabtotum_pro04.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = fabtotum [metadata] +author = FABtotum setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/fabtotum_pro06.inst.cfg b/resources/variants/fabtotum_pro06.inst.cfg index bf48b91965..140b6618cf 100644 --- a/resources/variants/fabtotum_pro06.inst.cfg +++ b/resources/variants/fabtotum_pro06.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = fabtotum [metadata] +author = FABtotum setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/fabtotum_pro08.inst.cfg b/resources/variants/fabtotum_pro08.inst.cfg index 83f13ef8fc..421cd0b662 100644 --- a/resources/variants/fabtotum_pro08.inst.cfg +++ b/resources/variants/fabtotum_pro08.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = fabtotum [metadata] +author = FABtotum setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_025_e3d.inst.cfg b/resources/variants/gmax15plus_025_e3d.inst.cfg index 88730e6722..3c7b2e4949 100644 --- a/resources/variants/gmax15plus_025_e3d.inst.cfg +++ b/resources/variants/gmax15plus_025_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_04_e3d.inst.cfg b/resources/variants/gmax15plus_04_e3d.inst.cfg index f107d2ab16..e9c0cf1b18 100644 --- a/resources/variants/gmax15plus_04_e3d.inst.cfg +++ b/resources/variants/gmax15plus_04_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_05_e3d.inst.cfg b/resources/variants/gmax15plus_05_e3d.inst.cfg index 72081a4b3d..8575f3c539 100644 --- a/resources/variants/gmax15plus_05_e3d.inst.cfg +++ b/resources/variants/gmax15plus_05_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_05_jhead.inst.cfg b/resources/variants/gmax15plus_05_jhead.inst.cfg index ca086fca96..14d6ab5e9d 100644 --- a/resources/variants/gmax15plus_05_jhead.inst.cfg +++ b/resources/variants/gmax15plus_05_jhead.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_06_e3d.inst.cfg b/resources/variants/gmax15plus_06_e3d.inst.cfg index bbb5d18df1..5d3f5c63a9 100644 --- a/resources/variants/gmax15plus_06_e3d.inst.cfg +++ b/resources/variants/gmax15plus_06_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_08_e3d.inst.cfg b/resources/variants/gmax15plus_08_e3d.inst.cfg index 944420e064..af08cd2c7c 100644 --- a/resources/variants/gmax15plus_08_e3d.inst.cfg +++ b/resources/variants/gmax15plus_08_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_10_jhead.inst.cfg b/resources/variants/gmax15plus_10_jhead.inst.cfg index 832861a98a..df61d9729f 100644 --- a/resources/variants/gmax15plus_10_jhead.inst.cfg +++ b/resources/variants/gmax15plus_10_jhead.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_dual_025_e3d.inst.cfg b/resources/variants/gmax15plus_dual_025_e3d.inst.cfg index b80074479e..07bdfca9b7 100644 --- a/resources/variants/gmax15plus_dual_025_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_025_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus_dual [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_dual_04_e3d.inst.cfg b/resources/variants/gmax15plus_dual_04_e3d.inst.cfg index 3f25835e3a..966fe9f224 100644 --- a/resources/variants/gmax15plus_dual_04_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_04_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus_dual [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_dual_05_e3d.inst.cfg b/resources/variants/gmax15plus_dual_05_e3d.inst.cfg index c7dccfd7c7..85464bd733 100644 --- a/resources/variants/gmax15plus_dual_05_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_05_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus_dual [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_dual_05_jhead.inst.cfg b/resources/variants/gmax15plus_dual_05_jhead.inst.cfg index 0cffafee3b..689c76541a 100644 --- a/resources/variants/gmax15plus_dual_05_jhead.inst.cfg +++ b/resources/variants/gmax15plus_dual_05_jhead.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus_dual [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_dual_06_e3d.inst.cfg b/resources/variants/gmax15plus_dual_06_e3d.inst.cfg index a0dc450ec0..57641a4244 100644 --- a/resources/variants/gmax15plus_dual_06_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_06_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus_dual [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_dual_08_e3d.inst.cfg b/resources/variants/gmax15plus_dual_08_e3d.inst.cfg index 547cee823d..11523ccd67 100644 --- a/resources/variants/gmax15plus_dual_08_e3d.inst.cfg +++ b/resources/variants/gmax15plus_dual_08_e3d.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus_dual [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/gmax15plus_dual_10_jhead.inst.cfg b/resources/variants/gmax15plus_dual_10_jhead.inst.cfg index a565c073af..26721d0169 100644 --- a/resources/variants/gmax15plus_dual_10_jhead.inst.cfg +++ b/resources/variants/gmax15plus_dual_10_jhead.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = gmax15plus_dual [metadata] +author = gcreate setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/imade3d_jellybox_0.4.inst.cfg b/resources/variants/imade3d_jellybox_0.4.inst.cfg index cb20dadbf7..5baa8123f2 100644 --- a/resources/variants/imade3d_jellybox_0.4.inst.cfg +++ b/resources/variants/imade3d_jellybox_0.4.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = imade3d_jellybox [metadata] +author = IMADE3D setting_version = 4 type = variant hardware_type = nozzle diff --git a/resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg b/resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg index 95b696f432..5d1a01c366 100644 --- a/resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg +++ b/resources/variants/imade3d_jellybox_0.4_2-fans.inst.cfg @@ -4,6 +4,7 @@ version = 2 definition = imade3d_jellybox [metadata] +author = IMADE3D setting_version = 4 type = variant hardware_type = nozzle From 08f114ee6e13f02d2cf00cd17383343248fb5ae6 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 5 Mar 2018 12:49:23 +0100 Subject: [PATCH 367/371] Don't make print estimates translateable This was very very confusing for our translators. And all of the translators basically came down to the same translation: Leave it untranslated. So let's make it a bit easier on them and don't allow this to be translated. If we really want the currency to be translated to the correct position, Qt has currency printing in its locale as an option too. --- resources/qml/Sidebar.qml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 57a8e8beaa..e04d8607da 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -515,15 +515,12 @@ Rectangle weights = ["0"]; costs = ["0.00"]; } + var result = lengths.join(" + ") + "m / ~ " + weights.join(" + ") + "g"; if(someCostsKnown) { - return catalog.i18nc("@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost", "%1m / ~ %2g / ~ %4 %3").arg(lengths.join(" + ")) - .arg(weights.join(" + ")).arg(costs.join(" + ")).arg(UM.Preferences.getValue("cura/currency")); - } - else - { - return catalog.i18nc("@label Print estimates: m for meters, g for grams", "%1m / ~ %2g").arg(lengths.join(" + ")).arg(weights.join(" + ")); + result += " / ~ " + costs.join(" + ") + " " + UM.Preferences.getValue("cura/currency"); } + return result; } MouseArea { From 32fedf9559b8a9cf33e81dad8305e5c0dcf26d46 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 5 Mar 2018 13:01:32 +0100 Subject: [PATCH 368/371] Obtain filament diameter from stack for length calculation Otherwise we get it from the global stack which is always 2.85mm. Fixes #3284. --- cura/PrintInformation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 8b6fbb1f28..e71052023c 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -203,8 +203,6 @@ class PrintInformation(QObject): if Application.getInstance().getGlobalContainerStack() is None: return - # Material amount is sent as an amount of mm^3, so calculate length from that - radius = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") / 2 self._material_lengths[build_plate_number] = [] self._material_weights[build_plate_number] = [] self._material_costs[build_plate_number] = [] @@ -216,14 +214,15 @@ class PrintInformation(QObject): for index, amount in enumerate(self._material_amounts): ## Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some # list comprehension filtering to solve this for us. - material = None if extruder_stacks: # Multi extrusion machine extruder_stack = [extruder for extruder in extruder_stacks if extruder.getMetaDataEntry("position") == str(index)][0] density = extruder_stack.getMetaDataEntry("properties", {}).get("density", 0) material = extruder_stack.findContainer({"type": "material"}) + radius = extruder_stack.getProperty("material_diameter", "value") / 2 else: # Machine with no extruder stacks density = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("properties", {}).get("density", 0) material = Application.getInstance().getGlobalContainerStack().findContainer({"type": "material"}) + radius = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") / 2 weight = float(amount) * float(density) / 1000 cost = 0 @@ -242,6 +241,7 @@ class PrintInformation(QObject): else: cost = 0 + # Material amount is sent as an amount of mm^3, so calculate length from that if radius != 0: length = round((amount / (math.pi * radius ** 2)) / 1000, 2) else: From 3004b146ad06f3528be15330e9be31ecc9ad1068 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 5 Mar 2018 13:36:09 +0100 Subject: [PATCH 369/371] Fix: move createQualityChanges() to QualityManager CURA-4606 --- cura/Machines/QualityManager.py | 46 ++++++++++++++++++++++ cura/Settings/ContainerManager.py | 40 ------------------- resources/qml/Preferences/ProfilesPage.qml | 2 +- 3 files changed, 47 insertions(+), 41 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index dc9dba8c4b..a2871880f0 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -10,6 +10,8 @@ from UM.Logger import Logger from UM.Util import parseBool from UM.Settings.InstanceContainer import InstanceContainer +from cura.Settings.ExtruderStack import ExtruderStack + from .QualityGroup import QualityGroup from .QualityNode import QualityNode @@ -393,6 +395,50 @@ class QualityManager(QObject): new_id = self._container_registry.uniqueName(container.getId()) self._container_registry.addContainer(container.duplicate(new_id, new_name)) + ## Create quality changes containers from the user containers in the active stacks. + # + # This will go through the global and extruder stacks and create quality_changes containers from + # the user containers in each stack. These then replace the quality_changes containers in the + # stack and clear the user settings. + @pyqtSlot(str) + def createQualityChanges(self, base_name): + machine_manager = Application.getInstance().getMachineManager() + + global_stack = machine_manager.activeMachine + if not global_stack: + return + + active_quality_name = machine_manager.activeQualityOrQualityChangesName + if active_quality_name == "": + Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) + return + + machine_manager.blurSettings.emit() + if base_name is None or base_name == "": + base_name = active_quality_name + unique_name = self._container_registry.uniqueName(base_name) + + # Go through the active stacks and create quality_changes containers from the user containers. + stack_list = [global_stack] + list(global_stack.extruders.values()) + for stack in stack_list: + user_container = stack.userChanges + quality_container = stack.quality + quality_changes_container = stack.qualityChanges + if not quality_container or not quality_changes_container: + Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) + continue + + extruder_definition_id = None + if isinstance(stack, ExtruderStack): + extruder_definition_id = stack.definition.getId() + quality_type = quality_container.getMetaDataEntry("quality_type") + new_changes = self._createQualityChanges(quality_type, unique_name, global_stack, extruder_definition_id) + from cura.Settings.ContainerManager import ContainerManager + ContainerManager.getInstance()._performMerge(new_changes, quality_changes_container, clear_settings = False) + ContainerManager.getInstance()._performMerge(new_changes, user_container) + + self._container_registry.addContainer(new_changes) + # # Create a quality changes container with the given setup. # diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index b833e1f1e9..f910f0c0e2 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -341,46 +341,6 @@ class ContainerManager(QObject): for container in send_emits_containers: container.sendPostponedEmits() - ## Create quality changes containers from the user containers in the active stacks. - # - # This will go through the global and extruder stacks and create quality_changes containers from - # the user containers in each stack. These then replace the quality_changes containers in the - # stack and clear the user settings. - @pyqtSlot(str) - def createQualityChanges(self, base_name): - global_stack = Application.getInstance().getGlobalContainerStack() - if not global_stack: - return - - active_quality_name = self._machine_manager.activeQualityOrQualityChangesName - if active_quality_name == "": - Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) - return - - self._machine_manager.blurSettings.emit() - if base_name is None or base_name == "": - base_name = active_quality_name - unique_name = self._container_registry.uniqueName(base_name) - - # Go through the active stacks and create quality_changes containers from the user containers. - for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): - user_container = stack.userChanges - quality_container = stack.quality - quality_changes_container = stack.qualityChanges - if not quality_container or not quality_changes_container: - Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) - continue - - extruder_definition_id = None - if isinstance(stack, ExtruderStack): - extruder_definition_id = stack.definition.getId() - quality_type = quality_container.getMetaDataEntry("quality_type") - new_changes = self._createQualityChanges(quality_type, unique_name, global_stack, extruder_definition_id) - self._performMerge(new_changes, quality_changes_container, clear_settings = False) - self._performMerge(new_changes, user_container) - - self._container_registry.addContainer(new_changes) - ## Get a list of materials that have the same GUID as the reference material # # \param material_id \type{str} the id of the material for which to get the linked materials. diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index e9bbb4bc66..c604453190 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -175,7 +175,7 @@ Item { base.newQualityNameToSelect = newName; // We want to switch to the new profile once it's created base.toActivateNewQuality = true; - Cura.ContainerManager.createQualityChanges(newName); + base.qualityManager.createQualityChanges(newName); } } From 2de587a8c6361cfd61f6b99941823918dcf5531b Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 5 Mar 2018 15:32:46 +0100 Subject: [PATCH 370/371] Made some changes so the code also works with lower versions of Qt & pyQt --- resources/qml/Menus/BuildplateMenu.qml | 4 ++-- resources/qml/Menus/ContextMenu.qml | 2 +- resources/qml/Menus/MaterialMenu.qml | 2 +- resources/qml/Menus/NozzleMenu.qml | 2 +- resources/qml/Menus/ProfileMenu.qml | 2 +- resources/qml/Menus/ViewMenu.qml | 2 +- resources/qml/ObjectsList.qml | 4 ++-- resources/qml/Preferences/MachinesPage.qml | 2 +- resources/qml/Preferences/MaterialView.qml | 2 +- resources/qml/Preferences/MaterialsPage.qml | 2 +- resources/qml/Preferences/ProfileTab.qml | 2 +- resources/qml/Preferences/ProfilesPage.qml | 2 +- resources/qml/SidebarAdvanced.qml | 2 +- resources/qml/SidebarSimple.qml | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/resources/qml/Menus/BuildplateMenu.qml b/resources/qml/Menus/BuildplateMenu.qml index 0b67b37cc1..b924aa0879 100644 --- a/resources/qml/Menus/BuildplateMenu.qml +++ b/resources/qml/Menus/BuildplateMenu.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import UM 1.2 as UM @@ -12,7 +12,7 @@ Menu id: menu title: "Build plate" - property Cura.BuildPlateModel buildPlateModel: CuraApplication.getBuildPlateModel() + property var buildPlateModel: CuraApplication.getBuildPlateModel() Instantiator { diff --git a/resources/qml/Menus/ContextMenu.qml b/resources/qml/Menus/ContextMenu.qml index 656e94b336..83302f9463 100644 --- a/resources/qml/Menus/ContextMenu.qml +++ b/resources/qml/Menus/ContextMenu.qml @@ -15,7 +15,7 @@ Menu property bool shouldShowExtruders: machineExtruderCount.properties.value > 1; - property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() + property var multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() // Selection-related actions. MenuItem { action: Cura.Actions.centerSelection; } diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 25fa221e9a..d81e0c86c3 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import UM 1.2 as UM diff --git a/resources/qml/Menus/NozzleMenu.qml b/resources/qml/Menus/NozzleMenu.qml index 0b961a5a11..43f3b79dd4 100644 --- a/resources/qml/Menus/NozzleMenu.qml +++ b/resources/qml/Menus/NozzleMenu.qml @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import UM 1.2 as UM diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index 19461f6005..72cda13ca9 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import UM 1.2 as UM diff --git a/resources/qml/Menus/ViewMenu.qml b/resources/qml/Menus/ViewMenu.qml index fc0339e0c6..6bbb0b1e2e 100644 --- a/resources/qml/Menus/ViewMenu.qml +++ b/resources/qml/Menus/ViewMenu.qml @@ -13,7 +13,7 @@ Menu id: base enabled: !PrintInformation.preSliced - property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() + property var multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() // main views Instantiator diff --git a/resources/qml/ObjectsList.qml b/resources/qml/ObjectsList.qml index e7dd63ea05..8c8eaa16ae 100644 --- a/resources/qml/ObjectsList.qml +++ b/resources/qml/ObjectsList.qml @@ -31,9 +31,9 @@ Rectangle border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - property bool collapsed: true; + property bool collapsed: true - property Cura.MultiBuildPlateModel multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() + property var multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() SystemPalette { id: palette } diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index 49a8d286a8..62e5ef98b4 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2016 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Window 2.1 diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 0016f211e7..c987880305 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -1,7 +1,7 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Dialogs 1.2 diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index a5bb2f9883..4a6d07df81 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Uranium is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 import QtQuick.Dialogs 1.2 diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml index dcabf012b7..40f725e092 100644 --- a/resources/qml/Preferences/ProfileTab.qml +++ b/resources/qml/Preferences/ProfileTab.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import UM 1.2 as UM diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index c604453190..3e10aca000 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Uranium is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 import QtQuick.Dialogs 1.2 diff --git a/resources/qml/SidebarAdvanced.qml b/resources/qml/SidebarAdvanced.qml index ae77bc8d1b..ff5f545c80 100644 --- a/resources/qml/SidebarAdvanced.qml +++ b/resources/qml/SidebarAdvanced.qml @@ -1,7 +1,7 @@ // Copyright (c) 2015 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 2.0 import "Settings" diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 1991a9fa57..cef6f38b4b 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.8 +import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.3 From a35d4ae400855895a407038d2217e2a29a9b30b2 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 5 Mar 2018 16:43:58 +0100 Subject: [PATCH 371/371] Fix: After clicking "cancel" button while sending a print job the connection is disconnected CURA-4960 --- cura/PrinterOutput/NetworkedPrinterOutputDevice.py | 3 +++ plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py index a7b7edc636..315b195e2a 100644 --- a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py +++ b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py @@ -219,6 +219,9 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice): reply.uploadProgress.connect(onProgress) self._registerOnFinishedCallback(reply, onFinished) + + return reply + def postForm(self, target: str, header_data: str, body_data: bytes, onFinished: Optional[Callable[[Any, QNetworkReply], None]], onProgress: Callable = None) -> None: post_part = QHttpPart() post_part.setHeader(QNetworkRequest.ContentDispositionHeader, header_data) diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py index fa9abb8d4e..c0d538bb78 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py @@ -77,6 +77,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): self._cluster_size = int(properties.get(b"cluster_size", 0)) + self._latest_reply_handler = None + + def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs): self.writeStarted.emit(self) @@ -147,7 +150,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): parts.append(self._createFormPart("name=\"file\"; filename=\"%s\"" % file_name, compressed_gcode)) - self.postFormWithParts("print_jobs/", parts, onFinished=self._onPostPrintJobFinished, onProgress=self._onUploadPrintJobProgress) + self._latest_reply_handler = self.postFormWithParts("print_jobs/", parts, onFinished=self._onPostPrintJobFinished, onProgress=self._onUploadPrintJobProgress) @pyqtProperty(QObject, notify=activePrinterChanged) def activePrinter(self) -> Optional["PrinterOutputModel"]: @@ -187,6 +190,12 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): self._sending_gcode = False Application.getInstance().getController().setActiveStage("PrepareStage") + # After compressing the sliced model Cura sends data to printer, to stop receiving updates from the request + # the "reply" should be disconnected + if self._latest_reply_handler: + self._latest_reply_handler.disconnect() + + @pyqtSlot() def openPrintJobControlPanel(self): Logger.log("d", "Opening print job control panel...")