From 38f74d502880dbdaec65075cc3bc86b669574db3 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 13:50:32 +0530 Subject: [PATCH 01/78] Add files via upload FabX Pro Definition File --- resources/definitions/fabxpro.def.json | 56 ++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 resources/definitions/fabxpro.def.json diff --git a/resources/definitions/fabxpro.def.json b/resources/definitions/fabxpro.def.json new file mode 100644 index 0000000000..94ed1d4d29 --- /dev/null +++ b/resources/definitions/fabxpro.def.json @@ -0,0 +1,56 @@ +{ + "version": 2, + "name": "FabX Pro", + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "FabX", + "manufacturer": "FabX", + "file_formats": "text/x-gcode", + "platform": "fabxpro_platform.stl", + "has_materials": true, + "has_machine_quality": true, + "machine_extruder_trains": + { + "0": "fabxpro_extruder_0" + } + }, + + "overrides": { + "machine_name": { "default_value": "FabX Pro" }, + "machine_width": { + "default_value": 170 + }, + "machine_height": { + "default_value": 170 + }, + "machine_depth": { + "default_value": 170 + }, + "machine_center_is_zero": { + "default_value": false + }, + "machine_heated_bed": { "default_value": true }, + "machine_head_with_fans_polygon": + { + "default_value": [ + [ -75, 35 ], + [ -75, -18 ], + [ 18, 35 ], + [ 18, -18 ] + ] + }, + "gantry_height": { + "value": "55" + }, + "machine_gcode_flavor": { + "default_value": "RepRap (Marlin/Sprinter)" + }, + "machine_start_gcode": { + "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E6 ;extrude 6 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": { + "value": "'M104 S0 ;extruder heater off' + ('\\nM140 S0 ;heated bed heater off' if machine_heated_bed else '') + '\\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'" + } + } +} From 4878052cc1b248b9b06d465c1280f6f361bb83ff Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 13:51:31 +0530 Subject: [PATCH 02/78] Add files via upload FabX pro extruder file --- resources/extruders/fabxpro_extruder_0.def.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 resources/extruders/fabxpro_extruder_0.def.json diff --git a/resources/extruders/fabxpro_extruder_0.def.json b/resources/extruders/fabxpro_extruder_0.def.json new file mode 100644 index 0000000000..1ce0059b9e --- /dev/null +++ b/resources/extruders/fabxpro_extruder_0.def.json @@ -0,0 +1,15 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "FabX Pro", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} From d2c3167450f50163e810eda1e5a715d3a2039e8d Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 13:54:23 +0530 Subject: [PATCH 03/78] Add files via upload Added STL of FabX Pro bed --- resources/meshes/fabxpro_github.STL | Bin 0 -> 263384 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/meshes/fabxpro_github.STL diff --git a/resources/meshes/fabxpro_github.STL b/resources/meshes/fabxpro_github.STL new file mode 100644 index 0000000000000000000000000000000000000000..f0fd3a2a80470129e41ddd6d23fbd97f8d2630e3 GIT binary patch literal 263384 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

4b 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 z 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 wqT}dxnE3P{eR~}WDW(xBOj>3$sG|!k4 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 Date: Wed, 19 Feb 2020 14:25:14 +0530 Subject: [PATCH 04/78] Add files via upload Quality files for FabX Pro --- .../fabxpro/fabxpro_abs_draft.inst.cfg | 24 +++++++++++++++++ .../quality/fabxpro/fabxpro_abs_fine.inst.cfg | 24 +++++++++++++++++ .../fabxpro/fabxpro_abs_normal.inst.cfg | 24 +++++++++++++++++ .../fabxpro/fabxpro_pla_draft.inst.cfg | 26 +++++++++++++++++++ .../quality/fabxpro/fabxpro_pla_fine.inst.cfg | 26 +++++++++++++++++++ .../fabxpro/fabxpro_pla_normal.inst.cfg | 26 +++++++++++++++++++ 6 files changed, 150 insertions(+) create mode 100644 resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg diff --git a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg new file mode 100644 index 0000000000..d6a6d22b08 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 4 +name = Draft ABS +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Draft ABS +weight = -2 +global_quality = True + +[values] +layer_height = 0.3 +layer_height_0 = 0.35 +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +support_enable = true +adhesion_type = raft +material_print_temperature = 240 +material_bed_temperature = 110 +cool_fan_enabled = false diff --git a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg new file mode 100644 index 0000000000..bfaccfadac --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 4 +name = Fine ABS +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Fine ABS +weight = -2 +global_quality = True + +[values] +layer_height = 0.1 +layer_height_0 = 0.15 +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +support_enable = true +adhesion_type = raft +material_print_temperature = 240 +material_bed_temperature = 110 +cool_fan_enabled = false diff --git a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg new file mode 100644 index 0000000000..c039ca61d7 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg @@ -0,0 +1,24 @@ +[general] +version = 4 +name = Normal ABS +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Normal ABS +weight = -2 +global_quality = True + +[values] +layer_height = 0.2 +layer_height_0 = 0.3 +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +support_enable = true +adhesion_type = raft +material_print_temperature = 240 +material_bed_temperature = 110 +cool_fan_enabled = false diff --git a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg new file mode 100644 index 0000000000..8bda2e29fe --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg @@ -0,0 +1,26 @@ +[general] +version = 4 +name = Draft PLA +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Draft PLA +weight = -2 +global_quality = True + +[values] +layer_height = 0.3 +layer_height_0 = 0.35 +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +support_enable = true +adhesion_type = skirt +material_print_temperature = 215 +material_bed_temperature = 60 +cool_fan_enabled = true +cool_fan_speed = 100 +cool_fan_full_at_height = 0.6 \ No newline at end of file diff --git a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg new file mode 100644 index 0000000000..c98d73e079 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg @@ -0,0 +1,26 @@ +[general] +version = 4 +name = Fine PLA +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Fine PLA +weight = -2 +global_quality = True + +[values] +layer_height = 0.1 +layer_height_0 = 0.15 +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +support_enable = true +adhesion_type = skirt +material_print_temperature = 215 +material_bed_temperature = 60 +cool_fan_enabled = true +cool_fan_speed = 100 +cool_fan_full_at_height = 0.6 \ No newline at end of file diff --git a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg new file mode 100644 index 0000000000..9727be8841 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg @@ -0,0 +1,26 @@ +[general] +version = 4 +name = Normal PLA +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Normal PLA +weight = -2 +global_quality = True + +[values] +layer_height = 0.2 +layer_height_0 = 0.3 +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +support_enable = true +adhesion_type = skirt +material_print_temperature = 215 +material_bed_temperature = 60 +cool_fan_enabled = true +cool_fan_speed = 100 +cool_fan_full_at_height = 0.6 \ No newline at end of file From 4993a26a9043ad898fed323cb5a1792942b94997 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 14:29:18 +0530 Subject: [PATCH 05/78] Update fabxpro.def.json --- resources/definitions/fabxpro.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fabxpro.def.json b/resources/definitions/fabxpro.def.json index 94ed1d4d29..012a9dec7a 100644 --- a/resources/definitions/fabxpro.def.json +++ b/resources/definitions/fabxpro.def.json @@ -47,7 +47,7 @@ "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E6 ;extrude 6 mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." + "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F840 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3 mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F840\n;Put printing message on LCD screen\nM117 Printing..." }, "machine_end_gcode": { "value": "'M104 S0 ;extruder heater off' + ('\\nM140 S0 ;heated bed heater off' if machine_heated_bed else '') + '\\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'" From d3742c2c957b20cf358b518862a1ea540f95cbd8 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 15:05:05 +0530 Subject: [PATCH 06/78] Update fabxpro.def.json --- resources/definitions/fabxpro.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fabxpro.def.json b/resources/definitions/fabxpro.def.json index 012a9dec7a..7db4814dcf 100644 --- a/resources/definitions/fabxpro.def.json +++ b/resources/definitions/fabxpro.def.json @@ -30,7 +30,7 @@ "machine_center_is_zero": { "default_value": false }, - "machine_heated_bed": { "default_value": true }, + "machine_heated_bed": { "default_value": true }, "machine_head_with_fans_polygon": { "default_value": [ From 5ae9f44aabdaa52accadb69d475df5ce34e9a419 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 18:15:33 +0530 Subject: [PATCH 07/78] Update fabxpro.def.json --- resources/definitions/fabxpro.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fabxpro.def.json b/resources/definitions/fabxpro.def.json index 7db4814dcf..048841d525 100644 --- a/resources/definitions/fabxpro.def.json +++ b/resources/definitions/fabxpro.def.json @@ -47,7 +47,7 @@ "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F840 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3 mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F840\n;Put printing message on LCD screen\nM117 Printing..." + "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3 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": { "value": "'M104 S0 ;extruder heater off' + ('\\nM140 S0 ;heated bed heater off' if machine_heated_bed else '') + '\\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'" From cef28f04a850312645e942eecf8aff3563880ef2 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 18:25:23 +0530 Subject: [PATCH 08/78] Delete fabxpro_github.STL --- resources/meshes/fabxpro_github.STL | Bin 263384 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 resources/meshes/fabxpro_github.STL diff --git a/resources/meshes/fabxpro_github.STL b/resources/meshes/fabxpro_github.STL deleted file mode 100644 index f0fd3a2a80470129e41ddd6d23fbd97f8d2630e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 263384 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

4b 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 z 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 wqT}dxnE3P{eR~}WDW(xBOj>3$sG|!k4 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 Date: Wed, 19 Feb 2020 18:26:02 +0530 Subject: [PATCH 09/78] Add files via upload --- resources/meshes/fabxpro_platform.STL | Bin 0 -> 263384 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/meshes/fabxpro_platform.STL diff --git a/resources/meshes/fabxpro_platform.STL b/resources/meshes/fabxpro_platform.STL new file mode 100644 index 0000000000000000000000000000000000000000..f0fd3a2a80470129e41ddd6d23fbd97f8d2630e3 GIT binary patch literal 263384 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

4b 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 z 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 wqT}dxnE3P{eR~}WDW(xBOj>3$sG|!k4 zu2$^994}j%Q?@d-$`WeU{MWy`Cfy|;wa9r zmg1#WKiqSa{q;S+{*kUKkBGuP{f@HZ9`=9F66|53-MUBFU&h4<)>!e=QMU8ye)a~_ zSq=6uv3Z}P?Z!LO+>fH?iUlS(s^a~@AcTxC-h&19 zFoAa$t-iaMPjJ-!rypZ)98FsuuwsGtJMV>sPxrIuo)|kG>|sJz{72Dc?Gh$9YUG%H zcB5Tm8k|+boaD53&+~G!Th1OPFz>|byk|!gJy$F+!BM(WKH|!@gFQ^3#fhs+zmNwm z)nJ07bjANl4bF1tnwb*CSrPpI^e3AmV?tNML}=M|a9JFsYg<+l?9tUJC5lT*s{|uk zD<*W^$x00_i=%WE$x1@kofFSlKaWoDAG+pUCBYsh+H5%{=WOT9jjq=x@gd8@dug~euP}ExS z+8ZBkR-3NS!`EhZJJ`bndS0|TP>IRr^f?Oe1;`sCkv0Q+n8?rKFu_sCqsTig5e@b* z5zQ@Of4P2bx&jHWOoAS3&U#DiVd9kDh02j1r@;hAaScoRR%*o_Caxc}Pj=)dU|E8r zICqxS;7r=cdwQi~cdVTy*uw-eUg^Bfe1fAm`F1*}-$Yz@|< zqPdkTlV@N8D_ddz<*ZZ)kAE|Sqp*5b&f89SZ#SKLiuZ)mS*)C~DBto@eVM>J%ISRA ze1fC+UDA{&%2~qim7sTTboCR?oumYe>`W&n(7QMBH!ZjhN~5O&_6f& zUOShR5*4*#0zG;Ye~+Ha;wZd@Z}h$WRKwMZJ$TdK=o$cAQc6_RiV3VHVB%{Ia9JEx zF~>`UigG;oJs-SvVRSt@E=hv*Cwl~$z*`t}-T zY%#5o{F_~yiiw#`>zmf^mCYloAUNvwS2i#$Y#C7$4Xndqbmb1L=wWn4kCm$x6Ik5? z*S}u_MCz|U+3nycUUkex7x5eaq18vLjy&;18~c|}7FhUXoihCESNFjGchR0;4--5i z%@N^OcHIw-!fIyHA9Q+If;~)BtQ(bTaNaPy0gQcwRfo#o;7JMgFcID|c67E@OmI~G zJ3pM$3oC5=fm$&UR`>WHwc@C-YDk1&PgsrQ57df@uo6l{gZC9jamG8lcR4SD){@oM z5@%kr1bdi3yUS|3E1%$~{5O$y7|}oNlYRYJ|Fo~h?=)pK*u%slM;({;`tk{m;+hk38$8E(g=Bl%oXz6KNRI*(6h5#$pb)xBYS&g=xv zC+OEBQ07YJGMLcsLI|DKswj6j&Sh{^{t9O7VIqHDF~LzhOEaw%jO@BXIL$NJyJ0(+P^`L)qG8DST&`Xu~cHJF^XDwuF#U3WmLzWrek^2=B9EIMt%sPMKz>3H}`p;qi+ z0wY`L$_pXb{o~$6mT_5E7T)@$6{cO^C!!JhOBDp(eNI=m&T25hQM|H1mf&6-R!mA) zzgW4x8WUK1DP2b+tHEV)6!#NTqA16lN7m6=GP?E(x6V@nMz*ET1X@lezSawu#ZkPn zK&s(t#jWjaKmC&#a>pNO=`(TW_Zymn&ns)UyY1liIY-U-c_Z^mum44K`nt7QGWsQp zq6!1v+SJV3)7#nYU=P~VMqA;moe~wbVgl`XlUYSDVA;L_M`86nqiYbR8bvvR?7@0{ zMpyM)xmq!S^#M(0-N9(BIEs5qE*LfP{SWSQV82=2qufsj#d|RG<_i-zHdc>KKEYA{ zTDFND{sJArA~^hqy-S`AR%~o{T-To&D_1Kfa9-K?dBtUM6wXSUId{`qp=WBf|B8OC z)t)eyge^#aaMjXRBA7s*+E%<#1ujc)6u-fh3OItt8hH#d_C0zbiv{*Dp4jAY|f|* z6CB0;gscY7z~;HtT-z+c9wug9c~y3VH(*%bhrYbVQ9NHftD#?g!e3?WB^(>yLej5K z$=|aCdzj!hYCgeH+z!qX>|x^jV@7A^GXyN#3g;+p&u2Aw?m2Hq#rR;V!5$_CZ!s!e zT`;S`1V{1Mq$7%+L;i|p!S@?U+|uW(XS`- zXiZjwJxt(T5L5ata)~JxnBXY9Z(>ScIc9=Ac&EkacZ#{BQoLN}>|p|{dzjJ}h)YbC z;3&Lllj@b?MFZ~@rTYhOAEl#Kteqv;!vx-A${8i&UJ|mG3gaA=KN80tCXgx0=|?faQ9KHm-46ar1b;n($MmuUdzio+4Rg}_b6vkA zpWrB-XPqT*tr;Di#5I_XTHNNu=iz?onyan|sJv z4fZgByIr<_9yE{mghzhyPTn4r53!sw#2^K$^~VIr)A;OMLd6CB0)hb$3B_*_}Yi>KeE3S)W^ z4fZe*#_=KqYlJb#3cYNtxLhW}_-9t5D9;ZjIEwd3R)alEgpt^+22hL@QMQJo_{e58 zLUzEF6|x3@V9S{ZS&B%lc*{8|WJUf55#ES!QQ;kmEaCPp=M&H$G}?n)x!!h$Shk7D z^isnP%jN*kV@;ztOW}f1Bj2y(z9sS{Rx>QzPYlI-Fw=u%0=XJnF)}JL8G@s@_nOt< ztSsh6rK>V=7B@?-4AU=(WHmSn^T=?Fecm{qU=I^K3oWZrMp)Ir zHyr7kCMCvw-7)oWxfNgM3Q(5dD13P}=gTMTVFK^2<$P_E36A3LZk4t|&Jy-8fw$}E zd!QvIOK?>F_q;F<*&Kanv%5MmU)W5()7!{c??696lI?ja=({#nWEWsWou!>90xEd22g_UB`alEVsMnKaq z6krrNePbDUEz={3T~WM+yyeJ#<*a+o9wzcNnBXX6)pAx!=O=x5*V5frxGj<0a`rG0 z-t%;HKEY98wXO&eW=%Oym`&yE?D$tnrC4AO6JhpNR--8Q5+*o`x38oi1bdhW^UJat zK(ho#aceNE!ELqh&ZsMwwX+0!m+46Jd7a|2Tpi z743Ny_p&bqpFQLG9(WV6^6L>mafc%h6Pz#2YB0f3cr!3N zlOtfo0zYf{sfKw=IbR0iCo*P*rE8Wjovjsnn81v*biI^(f}`@EwR|>Ut+4dHiIqF% zOkka|bj^uut+*_X;`1#_@Y#TM)y%bxP414vC1nZrFo8AQa@syja1{4svKrj-!fJo% z$~N3m%M$Ei0;>q-tfa#PM_~=ZbmbnWQS?g10-vvVhd1rlrKUdw;3zK zxNneuyWbsEm?vdruGD~;4OLiY#(g*Zr-S70uT89}@36R~BeI?nf%Sgfcf(KZBg7ro z*VLc<7q5Z$eB9T*4{m=)m43ng?oCoX+hwyyK-_+NP5s9+J)vLlSoGzTD*YD7zQ0b% z)G$d-np9K&&T?NXt~(R@ZTb_}6}|0ms;R$bC$E9Eqph@LI_`Q$6;^_F?}?tbcUmjA z7m}ns_SH7sJ;54GU{z?h=Gh)SgV zj^HRhvPm)?wd&K^*9u=xc5?(+R(U_AsH} zmD=eBA#MjzzoRGgZTs`S?op+0053YIN0q*v+v}{!*p5NB)YLCXQVsW|mU~~BT%~JH zoYn5CD*e`TcPqqj9FMN2q}$=XA0r+nbPn`pvxIo$)|&d$-t)(tqja6rJ=VXiO4nuW z)!{Y}U*Npzb&%KKa}+D3Tlpf_CT+{ll0i7zPxz(sY-a+irdwHC{rC<-Z-iP6KEZ47 zxyw;}6(q^Vch=M&@q#C?s<@T4$JaRYjw-Aj?lPNa9#&qfH?OX#KX_VYt(d^t;Vx&n zhok%7QB%L?+{#*URQ6tS6^`H&dwT-2Carw)`q$N_RAKFKJ7$AAv*e50t91U=J}0%o zmJgUvQ$K4hPq2pxd?VYg-lEQ&y5M#YlW<;b^;|1=htoCaw(m8qLG$8!o;a-mE3vtI z<;3A~%(nn>bYX2ru!jlFUpHMitszO;;h4XEdg}^;qcpQ!d!rCf<4m0Pj^Dews>Wx_ z_OC+w!OcV8Y0Cap`d-MemItF&a@8I;)^E9f^IXn${d)SbpJmVEBpGpAP5rsIR-U^| z=vusc{VZF40M5iomw637+c}EQ{3Pj)TD6H+qjY`hwaye`>NPd>#rdAlud1$kj67v#;W;?lTsv)Am3}+5 zMM3`F1J9_5lYFhRo)V$oG3whvh%<4P9JQ+__&I@Z1i1I}2Om&=MYWw=Q{UwhPw-XC z1ilgA-uhpyx6rF$JGP5lgB-kdz!wfg+P zxjSPIPhd2|$~WPED%@U$^VQ1N<*(kh{2JUD`|2Oz2=X<^1kQYS4IZ|ZT!TyS=&L6Z zJ@LUCLUh4B@rZh_q3@qxu-Ehk{cc~UEu<#?eS`ZuKMeZ^XmqUd+rgeJ;lC3&=Xbf6 zoCl)i?v(^qXu`f~FcO8U8TM>*&3!k3cp6u2-{;dSiaaGkze>{MW6?Ma_p7o0tt2=~ zziIO9GeQhUt&&hH{jSV{cGDVg)w*w&v{}2nRwHp|c&&}!4z4c~`rXED{v&OMmN<7; z-^>%pK)EO6q>+=Wbe`?ZllQGcUdy!xr=Bl&xC>CLRYGftJxu6)*g-7|AbNvX6rNE` za8$NkQUtMgxCYt7gs$~7;__-}^aXKFXe}|pQQRiNT@*y8ZTyyFJjzN==H0J{Rq1Tg zH)ag2(s`sC+&>f=13-)l$AjBAe4j_J&#jGp%vA-wy92=OxZ)fwSB*Hz1Ys**cd9q0yg+5uvho(xIyCTjKaPhKPI zDG|CV+ouDC?uJ^8AMdw=369cL;EpQ_aW*u5{?2Q#M^}`4@V4?=b-^9(>S>i4Oy~-B z3m+BwRP+be_@r_>I7(N{oARm^w~1 ztt2a7@olqAYIOe5zqwlkg%-;5CAT0CnP^zZ~fh0$7eE%Mn5 zZ!2qsKZfJ+X4^^)CUj=aRS(G(b-vuM!hM&wgQM_wJc$@tcj<=H7&gcKk3o4aBpWWd%eD_C1XI0-LSG&OrXc&-p-ueENzAnsMW8L zT5%MfS8g^{n{B1FBrW}W!tIxxn-+i~q6Z|Z~5p*k(e)4+xb8uDkCfYZq$2@(iF`-`~n)1C|gVIj?G~BOn zJW?VX#ZR?gabA79wDM`dgs$XyZ!5W%9E>e*TkW@l@6;TXeWKokTHP7$45QoZDR0=@ zFK*hW>VuYh$=3tyuA_QZac%%-`(5acJXcEB5G!$yt|8Y~Ye`ec&3raAQxfhY206>9hLv(AW=ohW>9> zZU;x{ESt;63b7UT)uSQf#U7o#Gi`%OWwjcOTJ_nqvQ|v!%%LN1odk`?<-WUTCBadA z{U^y~Ai9NCxQ=c1dT~&Lj*=d*-kA+Ln%S!5nb45u;F+P9s$XvH@IZZoe)o0O)AeQ9 zs4*Z0bgFztF`?g_-Tghe`J9MSRA zD!dosa-?gH6XGwZ)s>+?$Q~y2>oIL63*t8pKE4yoRnq+WpEV_&V<+G{YuQM%5^Q!_;4dEBq=de-kN{hIkd9%!h-tS6UA z-{M(mv6e=Gd?xkF?6`p&OJPF4p1$$hLO0@mwZ?T`gUjM59uZ2CP0=g*Z@50V?Tk12 zt$cO3$7^Y=Lc9GUoQWr-*^ko52oqTO&B_;#|2tpkYwOUk3~ z6XH>1oxck$GWK9iIQ!6$I;FH5&U;a;-Ru zGkQsKD~|bIp{1`YN*%Fxx2nt9?QSts(*E>Lx3VYavuI_kww2%VY#%^+sdZ-7(DMGr zB3w~#gtML7?Y<}M3ABA(Z{pnJr3KI*xxTjHX}|uG*FHo;d~ zWK2kMmiisuE#{WDGCoADdX~mHMZ;w_nb2;|3v`ODPV4LS?)xs!!hgq;34Kk5-IRI z5gO08_ZsZcZzR9oLZV6~CCMJx@*{fbc9c9!==YL8{$BR(fjCPZIjoZ4C|xsi^S6Z< zhgxlPx+m~7aL41BcJ&Q9n{HX_`Ud3vu-E69ZC*PD#6Vo86S|V`Ij752I|Lfb!#EBT z9L4$4B)Jmp_F>2Q))Lyd?(1dye|~utTFCBOWG9_|c@^g}F~W;l9Wc_@ianT-VyiJv zyLkNRRs0l9lAW-x+J}20dzjGmwmw|@bZp1dI1{hm&ucKjQQ4>S`WR!m`WjE*T{1hS zX1aOg_9<0(f6QWiQM0Vg^eX+X?WQZHL1SGIw@vkguH^UHEe%z8Gt6S08guxy4OO@X z-M3no&XOn2a@6XY(62Qcb(58n?U=Lnt-`m3WzA)~?|J)`JwJwG%hwI}MDCL@fo}`T zchKyEBlm~K8*+VwI~?E1kiT+o^W3l#|GTq`Cp#^&18eV!G1JTiAJLYsjJj>7ZY z^unH~|F;k_JK?vm+v}!n4N$v zzw)R|t(=F6w}0{9Cjahzp=+^sUwTlVAEmN5O22GA?;|1pg|_IIk9!UF=-1PK`lP&8 z|G_irmM}Mp>&t|Gq5Yaqg`R}7y(zT9ncyh>3jA27SHv|quBWdRd-O~5i$5%{)yLRZ zcOG21ub9xU*+1}}&^trp)iB1wwc@DksO1nG!D~V*oS$C&RKwVmdrRo9Zt_$+6h!wh zdxt$t;7)B;yK0)bZ#{Xc?GNIT?frHz!BH6Va&HOUedEy}Mt~T6v?tJ3b8Aw+v0Z%w z+HiQjVvXwE%KOe2fmpH36C8zhqFZ5lQlXp}2BPU&e_nClnF+K}-D+kn4wdbY8C%1~ zRQAs~il6O%JN|XJuN6P(AHTiUt!TaTnDSa(0gdO+uhd|oOJl8D(famVrB*Wf`cY`_ z@^)|(=O2>fMG(aue66^bs$bf;Xh^olnj{Z`cqNRnaL<$p{mRGKuTQJOHHb6ur|=wP zf}`~7AupUE#QV^=c{^V#_UKnh?)`XBrXP*bIS^fT@&s!zpx8ayT*3f;Qb?fD0P^!PDUT%{;*#CeWvH--`d+l|t8{?|k;J`s6H? z#Zmg@v=^U}mgOnfjxnKM%N{1UjhZAof*2m2A53tRevxgJ4@JX*_#m`o*uzA&y?X{) z0NXv~x194=c(>1D1$I+Cqdb>&9ro4O^*zBkD<<&Pp2h0#=J5Ik)M_N!K6~6zNpMuQ zO)c%+hr_wc9wzXfpZ#XoL+156MdJYEWG4U19}gxtire!^awoQ9{SAGs^c#mK9+Yj} z>(>k4?=Ko(V(;D)?mp~cJ^gy&`a^|y184g|7glQMmlto{E31c@fY|aK!^jVp%Y=UE z@$L?yaRxF)_cd2;IY%LzU|S4**j)K1AtV?6WoWnS8htwrZ(D^m;&D%W!QS1nW7$Zx zcAy3YZ5rU(*?~^32gBTrZ#U3VfCHO<{5sh=OukP>c_bwA0 z#Th-!NyYtYc<6s{e(&YCcbE0^Y}2^zWqq|jqgGwRRm&PoTzkh~WX)~6^?p52tG>|a z7Oq+*IBJKpI?Kx3c0!A45H~>MmawmQyzb7m_m-Zw-Qzq{R;z2Eq0cDRU}BARyUG{H zZS`5bq*mBhTSWF1M{(~JcOP6ITZZ#0tnzNJ89Ezfxx1akJiDrJSF-ON_AvgwDQb1( z=KgqKl*CG(?4r|dtHKzI%g}yth>V|dFSRH7gTwFFyJ*S71lm_FJG|>2LNCO<{lG8= z$z^dAT4yfnJa}s%K1YWB{xC|$9<=&gHv7(X%4@X_Mn+G1%Wns3Fo71Q%cOt#qhwfq zL}q)9e^hPv#pI|F-|Kzqf#sn_kT%Rn@PxG9Wa={ghd z9W|jr*O_>{_oxP4v0|^Gqd+_)|YUV7Av_f}?oEG)d0ImKPUz0;8esJLg+2t7|}%`(paT zKh>3u@XDN`sn2+V`)W);&wZ8sE6{#!)T=d>Ib@E~Z@M=@+xI!23;A~T=(plK{aRit znJIh9)s-4$g!@kU?yJa|D8!;xmAzDKQyPUiQ*LI&i)#sSHLlth!$<>ryK_RHlRZpeZA&XFVBYe>$yG`64bGB9kr7^w!aA2$R>0il03l??Z;x=c z|8naNVGeSF&369eBQ#+3o;$B=I&;IPUgFU+T>z_9s zURJ9KxCW2vR#_`1xKEuVhu|z}{7)spQM&f)>&HuPTjq;y^^qU{U=I`7{<*y2wji{x zxHqa_jOfyKL>2ejaqfaRFXS26!vxkgbYG}AYrzGm)utdezSQq4COAsJZ*j;aLR^e3 zKRonUI0u0Hu9a1p7Prgh1Cr!>obA6FufhF(Ca`jkl@+0?7t7ehji}X2VLO=MC|&9J zl1oQ|xC(@32id~}R->`90@aE2qEQW^M>wyT;3!=|xq8DQh@~LfZR@v#`{z84!+mPx zWUi{Izv7?%`d|+ec-qPQGV}g7qoDCR&fU`ncnu~vihKG=vJH;MfGs`2J$GG`y4^09 zmFECJT-3T!g9%;Tdg(u9%Rj}IpVXm};3(d2=$~Udt{v_P_AsGqZudAtH13ARBjGN} z1V?3$$FU%e4Y?)mlj%2+j{0?a+33gCB%i zVXlFDXYiGgw^ebk7(IPiRmBc2?AU6sIKdrzr?q@P|An%d>EaHv*cgUV67St57l|6~afWs_8*>UZ?!@!)af%^3!%^BXZQ(xD_%+^%Yn>4_@C=5X zfSK2Ww?xQ-|7e%?cI|q*W1Urv1Mp^OK0Y!$$H(IV&c+jk_tinWMn+dp=Ug38oO0tI zrk04}Kw~r9C3mH9qB9(&osK^^o{Zn(7ku@EsG%JxS9s^*cI|C>)e@JqW26>#9U3)- zv(yLizWU_cILgo&Rr?-wQM-2hzURh^x@Go%iBJB?xAAWGoPTF%@9@u`;k=f)gKcTX zqP@*l?t6N>_B^}rvD4d;MN%^R^DkR*9(5Uh!FN-y<{oEgkG0QE9s>re0q;q%K4&;e zd%8W&K`eaPBjOXKJ>s8T`0#d}2z|-1hqr5w_`9Dw9E>G#CqAF%oZ1n8;g%!Y zwYUCp|2(o?`{lea;xI6NjjQ@giuJk289IGzhl56eaS<3druUWhNLg&{6WX;C+o0hm zv||>AH_@!}qn8f`gYU$zQ-L0+s&obTD zgt;2N!87ryJZj(!R4bGZZ_-vy?!&u;pX2P6<5fAsQNFGo=e3uld9BZpak4|jvmo}o z;gD|g^KYSXXv#44`MEQYp0H^+!Xf%_#oZ8&Ttg&#GrTPR%9#Me(LK0# z!z})~Umw)%s+dWB`U>&8at&wTSqV{t(_cRj8eGBpSIU}nhNJLohA73PjmTi6XqDEe zfgRCNB_M_~`K>ax#gl&e3vFBtsI4^Ja~pIhQ>7fxYZX7HG9^V)~N z`0Eq#s(hB}44wb-)w8EVV*(gsH;bR#8II~&i@Z7*y)KUo_c#N!Qeh{Iolc_$b0Duu zBQj?=$|Dx&)$sPYY*zdn?s10Ba2&ZJHEsvvr`7xnM|tE0zZb6RqcpGe^(dVPuR%FO`-LxY!>YKdA8?m^nj%HcaFli%-@C0Z7`Nc6ew4-~K32o{ zvt)JEsGZhs_pu!+U(lsxrc4_>4AgVvC9pjQM>;*{({bM6h_P3SFf5m zW-Tzb!RI(}%gAsKM&#T-uR8C>f!(fZQ+$pM)11>aoPo6|?ps@Z@WcRUjKwoJGJU(w za1_?RxSMWuZ9&GP{C3l9!t>sAR{VLx8e_Py=L9mzvF^NBy4%x;EO?xu^9P6QNj6s$ zZBHlkMKN2wE2=Yxttb}y7S&EWFB)RuKI(IZ&O3a36g6Hx;;go5gO{C;;i#@->Ps*# zdF7<|dw8C<_WS+i^zJ#^OJjUB;Qjb~_^8hr+9CFq$EV?{?#GyVkBL#k8IIEavS++V z2HyF{Dtb^ITI2L^ySG9VY8~B)0=QO^J|n>nQF0dc)pibUrTENrQQD4Z0CB^a9q``+6f`;7D$gXd{i6f zwZH5ezbkLcQQAfD>(i;hte16DkK=1zzRu;VS=hA>jEO0R>>g+6yqVtTb2h=6pU+b~ z(HV~Fx=OYR826`rCVZBnQ*{2mLH8L8NBTRYY+RqqI78?0JiX^7xT@>GxP80$T{**1 zU9XDc_UF@m6H$*NDdYliZ#(9*_ynIg8b$xIn#sJ2~ zRRH%mL+2xHG2ud7)xLON&FdXCoZ%>6n?!5|8b_tfOrOPJjU}8o^{=9PrT1*iolp2? z{`sIYbS}VzjV{Jjor`hF6KTg2zjjA?l{uSDk)iY4CY|#uT-9d0uTs9KGaRM!<1Sk7OfX&rqi@O_aF5QSyYnAscDt$r zz<44(QLf<(oqc!q#b-g|Q83!mo#+flVWlyg8F%_7XM^!MzN?{W#^N5-bC$2KHKSbW z)w8=@Re|^JKB=zAHJpL^(Xc=DpUxc%4UQ8ZO=BNtI0{v*VSnl`2b=@O?qIx>R%P6S zJk+p1_14un-LC38e2(W*Z{QlvKt^lWpL(SO$3cUcne);}#u<)6)@<0HdV$Z$=r;v5 zCh7U`xxUVc`)JD}+C4Ua{v7!w>pl|WCGK&C&ZYZw@)6Kj4^Px#*TqqWGaRLJ@SdH- zsKH~1svS2ZYPiQ49!ArG?qqLjy%?FXe$o5z1Zr6_A zcb_!6UHgT<{o3em@sc@UY?*ok*KmgRj-I^7iO~2SjIn#f@5&jD($3S@JWa+ZFcgi_ z?&y~td2+k2c&a1`#CMm(q}zQa55l>_5<{Hc}a zXE>^Bo($Jm&Q0Hy=i*>b`s(6iI?8pQ-n-jXF}}N18n^p*<&42CqblxV|H`PnaaD{n zoVUaLSLG@J7@apxT?YUuHH!_ z8D}_Z_{OVM8=mo0HTC>;z}N{IYozg&dz^9hReh^9K7OjY|C6=BV9wp&({Jt`XXvE) z$EL3V#=pVXIE@pX;V7ME|IB^;z*q(Q!>#^Y9Jk|~!Rn*&&s2S{T(jx$mshH04SA;e zbJWL1mg~9yqNA?uZsO)yJpt0R9|1deYbVzS@=C(O*3I%MRvwn z2iK}gmYG)Vdg~6*s3UXWlXUMo!%?VktwyXlr95}_Tfn#$S2ZDBm3y3V_n58u7Onn% z|Bhf>4aOxIhNFCSIj&~>kaAd3?Lu|JlGB?~O+z*QN7I|SGFXY!d{exy+~bT?Ls2cY z;&fcqL@?HPE;3RTM1`nRQ>t&M5Kro+!96pFriid>I3r~aRR4Kr8Z?dvrw;tbD zgVWo`*ZWhYMTPwtx?L65)#`2Y{~pdrl^qo#g}5rl8Q%JR?4$gu9Ob_gzAN-mE$xw! zYJMuL%c`!uLNux=Wx!O3!$E^R=ML#kOe@C~_Hu5A9-^wKUcYCfcF$BOiv7TNB8|u# zg?pDfyj4H??S|bL+|P2<5AmwJEoYp0aE)hmR`bSh(2nRidgpbHjNg?r9EB&C=h9Ul zowz<2oYDU&)j|3Wh^wwQx#ErvZ`=@eT*PP6Zivip|3_Mn@_iDW;Suk+VzOKMuAJd0 zRFah3DQ3;#YvQVSCyq)C_c)_#^n5a+oJ*V-KRMpiCEwwM9OZHG zqF4>T;HxQm?oo2Q4a$zoA1v_>?sip+LF2Hre(oC1z&p5Py&B%yxT-nmaSlq)xicK) znIo9pVHEy{%i{0h9%ta)Ub5~E?{;YHiw%%8pA^$LsP1!&xv_6qYWafVKoY#VYp zuIdRe4ovS7XE@5gL%cQ3>KJHt_)YZO-+zDjW)kGG-TJ)8ix&DJg5VtxIg@o5@g z`TX1&sHqPpfUS5z3$E%JFxJh)MID8@{cz&kV~>&X3f_qipC3Pm=iK-{haL%w`@_vh zBYpQcqw8*n({WW7q+B&;I7(+?4f^mWe4gs+cYEVp?7Dt8$b_+v2LskThC)^4<~Q zOto9z-nD(PKW-aNNc-c5yR~EQrSkRT?kMLitem2uY3Ah~XB_|VcHy+NtLBZwRdJ_~ zndwdK3`ea$efw~3-=TAN2ZOuy?DJUs&7Cpy!(GC;xEl@Hr`>lADT*1;7@IPL+~W*X zb8+lbw!X6uG>!t}8pU31pAtuP-Hl``Fs7t6VV&dt>eQXuzqzUmX9&Of_|DzFE8gu3 zrcs7}4rh#;G(4OqyxdE>;HrK>M!G6zILd#gSm*U>`gT2LfrxOZ$9Vg`y}HFq7*%^M zjWRr5;tWKfL&eCPBll`T-8LA%>Ac%3tIyU+&!96L)wPz4*;I4W4AMQ$z$tUpDF@Fg$Gk8C8hr2GntB{( zILhnTieeA+AGhrgdrtHp)ydyKQvUwtotm)5QXTa2Bjri+cIfi^7saR0xaRcuUHR|q z46GYf>^P6nk1wFH#Y0iU8IHm_RrTWCF5vlY?`tYJX&+@173Uw@-82Y{b)hkE z;mGi))AL`gP@VeJGu2;P`!{)%3YEopCmwrDWVpu}u8j;KjL42j;}T~$3NxgNGq0t0 zW>jr3#_bd4#BbL<&gl9%Hbt-YRq8qY#3AgG7Us1_Zq5i)=N_$yWgyC_9D4US!=qG1 zF%WfL-=uM(GaQxn1F4V^5515no36?|&hUsuT)W$@PyBYB;i$B0NQI1eXzo^|$@Q6p(T?+1o#!_F$-@`r5NcBb)vXF39V<(-}w)FBbE6f>= zN_9*XGLpdf5E`RXHm-Y8eN=_aqi%aAtc-hiK>Fma;fz$9RUr!r8VexHqTi3^{~V6; znwFSZvtoL~VXp^{OR7O5e$tLTAUH0mmLAsBEsFC7?)JZ>ebqcB;|%OM!Es6T)2#-# z$2rdT1LAM)3`co3C8`IYF)h6l5d|(81^#=lMcc892X{uR2F>f&j(1GSi0~30E((q3 z*FiS!sXq$qQSNbu#~+X#jc@njG-hyyqwppw`R>~G(Z!&#DdG$(raS=mIHPMU;|9F1 zMy9GQ&lkgQQ0{W&)DnAVbc-4+gP6>EW8!z^F#uvKNVuw5_^yskV^L=~ z3X#c@d%bYy*jOQbPRi5wnY+$jerwu<_O7$kVbFL##lqd=44wNteE@etU?%w^DGSLN zj`AH6u#N+bf2ZHW=S$czEu7H3+QR2{o2&f?@5Je8T;g*zXJE(fa6R95eh$~n}H${efoT0OYm$`~F zFXqGDma=!8;V7Sx#Z#14OFfQ{=r6u&2j(G{hrhZB&8DRX2fgP@2~|!%-`rwNp6Xd+~er0)wNzbJ7UF*M4DRPBpFEX3X~OUZ)Y?K4psg zxW^e-Q4S}DO#Af?(D);s+S@0`H=HvZ4QHtXgg} zeba6X<`mtVM*7~CGcbDz`>LIH-zH7ip8t=u8R4I!_wXE8qUD?#&xywR~KyvjY(jPO1*(I9OYRAajoc+)EoHh2USAV zjXTUL|M1?P-DY0Q_tDCz&%B(0s-)`KTV|DuKFC?ojbNPG83Sm{yd34D^SA@ef8UGG zxsSq8QB^(p^&{n}8+09!7sX6yY?d^9yffwwIiaqkj8Hyec1`qn0e}WwFIW+jpBAyo7P$@N|ZokMx~^Y_aN^@sE@X z?z=rSmV(CcYodlT9OWmkB4-;r#NM?+T;WZ7&4o3nRO4JBzq#9bR6Eu`UY!^jJ_>V2 zs+O)$2Z^gXWj6Y#8{3bE@Mn{~8*z!FVI(ayr9NzD`vXJlknpifsG%3iFSWtM5mw zxJZ|=7G@Lp%?J05zqya8oPilq$vM?w{TIe}^$;{hrP+it9EBNKxz3Vvs)=hY1jZln zIX3uF)bOa9PGTRq(jo15221YT!b-%VI2MdcQ_h5YoS`$_r~Uj8Fs=e)hcsqzhNHX> zj=kEGDN^JfXJB?8PO$&rchp!J8gmYhpTilB^07qB_Avz+R%Bc-4p+@Rc)f0O zgB74LB{6)Y?+ol{&Ny84;K+4xRS)7WX-cbP&Ty2^OJeW*pQM3n=Pr9?+gn>T;gfU! zymHIFTXpNBnCYat3GZ>7fp48V7L*6>vSm{om#7lS8IHm@h`SV&_ny237+m4qB)u8j zgYi`r_C>j3^KMr~#%77(8qUDjF6^y;UF#5NG=b44t*bf1Q9k;>nUi3woJM5+tRWYt zd|^1=a07aEd(KNRCZq~Ce`=k9+@Esi)8$@O+!D|pTczn+MZw5#Cn=h{XT#>HI zJs;y>_Xb@8N3`LCYnZ3>MFjHVUiFX#+MrAo94 zyOWZEtNL$>A^Y{F%BKoD&vv`2N4S^8^wUR?-{89%v19z??n#*g6?V|=c2z&a`37qoI=_Z9Qf@!_4VQQ-^?Fn)zm#!`DkhJTAG`cYvwqi$EVE56;w(vGD5dpILSUMlQt1dWC8 z?es`IO`%MloT@Gkj$|9DmIN%eyjb~EaBRaah$_ioxB&NZBoY8NZ)Yy=HP zyfzv>|99mmjA~2la#UfLBQWm4x4Z46$Z$`pwXCq4QMaq=k9&8OG=}r5az?5jtgufJ zG!{fO>dlYl|IHoc?=I}1490S4XA1vqQ#MV7eTuqW)d1YP%VzFfXQaHG3i}k{sz&gW z-#q_!gMT{$|T&~T4z_DfxV^PU)vk{vZR`Qy0ei{2R%G~6Sb{h;4tII*w?hNEOhjVV{& z*!rT7PuVaF1+0gZ^xyf~No57&6E zxzF9l1P%Ad=G(yE5?E$>RlD^1;X%Va zve^%M|A@W965}Fh2*tJ>B|B>D_1XrtMHbsKXt+l1eOSX=E@-$%HpdA* ze!v(mG4PxZ5Q=R%N_N!vaPa8bxSOU04fn|ANXADvc<(001<(+RZ8=JI)OhuyQ))Y$ zcw^9Tk8F;LeYA{9?;aSAk{vZxcy~U+lp4fn|ASl!3)MbQ((QL>}P$RD3oyZ!C$ zgNA!#b2j0#4CJcyz;Kl8s4?p7v9({VvrN!%k8I9se7=MGst1OnWJitJE03!!_vT$Q z@mJv<*_>_pEDW*N9vF_29W@qye_U-u+xs)9;U3wX5BfZ@D0*UaMa7wAL!+KFS~%Z~ z|KoVKGeZP=)zrQZrc4fKh=C?L8IF=2HSo#n>APxik8Ea$;CthVF)5S782scxoozWv zcGSQxSWmxsi+f}xw*p{PYM-4nt_4Ew3xJNdtw(vYws3Zv0T;UlMqY#R1IZAfaz?-3--X$&Wk!v=c#XYiFafbe?LcK|cSWQQs9@*TV7&Cwh`9eznFpsWwnLRb-4jQ8nifuVccGTeekZ(C^xJNc~5;4=~9_Xo_Qw)Ar zLa{AJ$&MO`Omw7JMvHr7vrZIo4epel*3XSm2*tJ>B|B;$!qSmqGA-_r&2@RiXSh>( zTGcm3Ar#wklmc%H8Vq1=q9W@Z~>PRuN7Wc?z zJ_F)q)nC4v8uA=agVo6>gkoEck{vY=x$8)=z83e$W(_YQdesx(O%1iZA=Vcdi1n>0 z6x(u??5KeV)Pu&Tm+w?}6bc z*-_)TWw)vITWy`7;U3xCsm^z>Lsd!-3`fb18sCi_Qd{f%je~}JWOFY)-(wH^uq4KB zmOFodP;ARlvZKc2L)WW)@$;cU!#%RO!+6(fz@8Y6k{vas&0Mp#`OVt~4fn|Aj^0R4xe zJ+i;P{Nnbm``n2!6~Bj2Y|BxyqsB?!|Iobig9il-_sG8K(2LuBUp?%dkQjGELnyZ8 zDA`eC%KCGg|9k9_LBl<=xvQV=_J^2$4-7}ijv9yEIlK9+6ORoV?vc%X2Yo+6o&0f2{dG4O41`YSf=6?FV z+at1&664n8dQB3FZ8=JI)EIvBSEGjVLta8JX=33*+2r|gO0 zDB1CIoVnVa!`AONE@-$%Hc#a9-7t}J*8{^*vZKby556^Yjk!_7J+iqMr`K>}KeEKQ zdb#s&6N+s)N_NyZ<=(eu^h+AZ{zN`Qh5r>b*~6b6)$Ucz$jnTPd!Zo|8IF=2HNIN? z&Y4Z=yK;|go>1T?7ZgQL3`fb18u$e}^qad!HqTJ#y6<353`fb18k0wi==dVtyY7+A zGaG!L!=e!5Pq=r5Vq1=q9W|~#{;ZCF435vBdt`H$MdS{btPG6%K#FlEove~ZhJBd7i#K7m6Boy0nlLzH4^J>gnC?9@#uy!%y8P3NhOG-u>y%OV&HGEl0_Y8t8F4)JM5THc#{L z-8VxYm1Q_ecGN)6*`dDHJ+gUvi0{`K`r5!iUpq-Cw&f_aFpz*ff-9(a~$``W)8LIR);xGmf!k;Vqhv=7pQXA-Hg~|pd!?~6W_Xu0X2L?TEl0_Y8hFFi^iFh- zZ0@*;_oMC4&=bQ^vZDsx)HS`^-6Na(KHv>*`%H+z{zE9X@!Iyw&f_SqVAE+{VOoyZ0v*)#-f42F||-^%TcnU21dxu z8dJMRHh0*-$l2=d#K4$(fKY79QL>{3M*7W~8@NX{>-jJPuxdatIHnegZ8=JI)bLrV zdt|f95c8czy<*pyuuyEvQL>{3W?sWIS96bS)9E7pw6}&B|B;$;?F;+Rw%aRDA`d15y%e3EZrlU?IM2JIL$u9EVB$p$&MO6uXT^?t4E&Jgg9*I2S+}5 z8h($S7><%1HGE#{9@%Uck>b#w$CKs6;Jj8Sw&f_i>x${SM>bF1LwrAsui{C6Juw_5J8EF1p{}(F_sC|uSb+%RM4m+$)+Pc2 zYZI+Pu`Nf*jv78ob&qVei}jW;-raR9HF{z=N_N!1%1>QuMedQ!cCjK9$L+JJAqLip zCJDv193?wyU_ zhNEOh4Xi=dwFc=P*=!dpjbT1G=XPp{fi=hhLa{AJ$&MOW8LewA)jhJ=E>=v#Ty)bn zsUZf|QU?gdwj3opYT*CzUkhX5Eib-*CEA)+j_!Xk+6t?>CF*gS^zXogn0bRyboF#H z#Ga4Q;`@o@b|#sRQHViLH%7SH2BRf?4qjEs&k;TGBxTzA_X)qhx*dN5-klLWos3j( zRQ_R8p8A$5k-~S?)zitqDtS1q8La~+2G`G>;V9YheCJe&6g1o;o9$w?zeKJ<`h3PH zgkoEcl8r0^e2!F!6g1o;n;OVkD3LRfG{j&&gHUYCQL=fyUdXaw?NZQik8Eln`=Uhd zN76{OOJo#6u`Nf*j;HXYN~ECS9@*4D7DaK(Emk5|Eoq3sJTjr!mZN0HGbd9eQqXXZY-%9utwhdU(h!5+l~8QU zQL^JHm8lXbXt+l{q_b>)?IU5W|$wsy*zN=J;6g1o;n;OV&Es zXt+lcM zC7b6dG%AsThI?eQT~tSeGZdmms$B{iLa{AJ$&RNkq)Mcq;U3v+7gZkN427s+4Ay2e zPH=FP?0D)zszeGJ?vc%QQLR#ZU}^Ptq`ks+~$Q93>moJkUs$NJFXN9@*4D^$^;ZhA~v_RK~U(744r&gOy0sz<;3< zsXY9?_9of*M}7`g52eqMYM16?I7&9EtI$%aMB;a)N~Dq=p{RlHjnzY)-xaH!=3_WY zHmby+kt&hGo#-Cf)W9#x+NGq?6T?xmQSAneRJ#;3+#{PBxIaLkqq24>X^6q`u25t+N;ayDp^<8r zf`)r!Qv)Ld)-ENDo*0gjjcRFVq)Mcq;U3x4zzB!6OG%?AhNEPo>KhuY#o-7RZE>^| z+M-7`H84_R?NZVZgX3MH$Z(WwRIfvWHAQJGs!F7i9-*j#5hrVxl15JqN6AJNJ~Yri zYnQ_3aF1+iVC2l&rKHgl!%?!an*cOYB~s9Ek8EmS2Ef{-q#*{!yF#%oN6E&n2+&BC zNI}CrvZ;ZY3~QH?h8WzRK`6H6DB0NE0UD`xDQLJyHZ?FKW9?GX5QAelq1cwAWMh{K z{vNS*DQLJyHZ?G_WbKlEkHp}3S17jSDB0L;0~)CkDQLJyHZ?FqX6;ha=!xMd+1ND% z8h9VFb}4AMM>aJu(`W5c(h!5+l~8QUQL?f72{ckAQqXXZY-%84!P=#y(G$Z_vayQ` zG*Tr}&~T4zY9R8$+NGq?6T?xmu^SCEQteXEaF1+iAcDl&rKHgl!%?!as}3|$B~s9E zk8Eln5>|D_;d){?N;Y-}f<~%c3L5T_O$|i!Si6)yhZx+aNGP`DDB0NM2pXvpDQLJy zHZ>5LWbIPY=!xMd+1RZK8mV?EXt+lL7_v9FNEK7~`_ZZQ35uV?8Scq3 z&c9?LG;Tfgtmd0iO@lLJ6NPhz!&yR6!x`?$F?L&s8Ve$a<>-`8?F`vO;WXlKN>tQv zhI?|1(dS+TjpxTd(0o;@F>!`$qHun3IDIN=IKw?T#?A{+V7{^QoO7n<$;B7&V;Xo*W~d)wtSH+tlXui}}>fkWG|M zdW;&*a8HgA&z#&16`)TKjWwgrkWG|Mtc)7Ya8HiGQ!#Pw5^{w9_j=5yc7|-Cbf#w1 zaE5zw44w^&F~dsx*N#g0)XtDilur7L8qRP}j`7+))KDc7_>C1_o=V}Xy?!o4SB86X zjCfVs^tp597OAgwhHRqzB#EMMhI?|1sIl;!y*vJr`dVkmCaUWR70z%^juAClb|2Ak zNa|~yA)6>aUk@QcW4I^Bh#F@fc2>uP)Ym#gHc@^eA9heShI?|1sDYldLw&6?WE0i( zq(5i4C&!2yTaJIAo-%o*W};py#ZsuXToOqWm12 z&^tF6?#VHt271oA`dVkmCd&8nFA8V4C&!2y=sD}^Yn>sRDBtlv^v(^2dvc7Zart5E z)mKk-^v;k?l%ElRsDUxulVe1UKaCqwKQQ&R&X7%1*Ruzl;hr2LYM|$=tFLv2Y@+gDVZK_>zhHRp4{cJa$gI3-nf1`#o+>>KO4bRzD1{FQB7d&MBCiHOCJH0d? zbcTC!jDMc8K~v~Chgo0SXiIFO(8Gn(hvHSCuWc~glVim5iqLa5TVLB~OKhUh!-eya zqJ}fvlVi-riAtg8Y_`6((U#amp@$16HAM~dwGD=Qa*TMk6MD{O>uVcriA@xGxNv?{ z)NqD-a*TN5l+RL~A)6@laN&fjsNoFvm#E6^l;%!o2Y@lw!v^uj=@uK ziUK`n&HCC#TVfN19xj|?5;dIRo*W~deB!fIXUHZBJzT|8z@vsU+>>KGyVEdy4xgnu zLpD+9;VPWYl{B2;o*d(}PpE;Ovu1s5qb;$CLJwE5uZ^F>8Scq3&N#mr8a_*PhHRqH zqgL!|qlPowlVgnPU4sT9!i_yS5CukCF`rsC+ePFy^p6i-dr>!rdvc6;Rfq`Bv>0-u zEwPD0CmgoZQRlVd~;M1(smhTLdN zY@!gk4gKR9Uta(XXSgTFh#H6pcUTO$(U#amA#xk~+6zyjhBMrgV?+&~r8+}4QHb1z z{;@u9JT#o)o*W};AR^phG2}*DViSePZRl$^Ihq>Ia8HgAHGE#{4B12>avS>E?dF~j z4QIF~$A}s}uXToOq7bavS>E0cTLd8Scq3qK3~>ogtejL~cW0d)dO&aE5zwjHu!BT4%^63X$8;Kb~;i zxzKQidvc7ZfrxP3V#tlQ#3l-n+t5GuU!NMza8HgAH4qW5TMW6;me@ogavS>EFQ06I zhBMrgV?+&~r8+}4QHb1zzINDg)NqD-a*U|qvs7ouCJK?;&_6aWM-6AVC&!2yhzQp$ zhTLdNY@!gk4Sns{bH+i#8Scq3qK3~>ogtejM2bUS`~AD;K*JgC$uXivT79kKuL5V# zqtBjJU2xAv?Xrowd(74)=C#$2e!F2iKUP@b4Gj0>7*XSnmG2z3Rlj(akTYZxb>_jf z5~u1`^Tuxg4QIF~$A}tfmKv_g8M2A;Qy-E28E3+Q;hr2LYNXZI`50mo+vihXUHaM;U%}^dTq7zuqOQG&TvnT5j8HnV|MdhCmtIM(@qJURxbiTL&7>a8HgAHD>?tL-YF&927L1A)Bc2 zD-S7g@@6$^r?sKs4EN+1Q6tS#gN8F?6SdpAo0XW?R-Ya?2pZ0CPmU2a`eMCy`R#WL z8qSbS)E7JalxM70Gsmn24QIF~$A}u|V6T@)ZrnC#I72p3YmeTv#M!CUc{dJ(hBMrg zV?>QUn5AC)^Pxe*8M2AG;?_+{oYh)=@WcRUIKw?TM$}lpWk~JamW_jkGh`F>+$$TG zIG?k+7DZQhml(r6IY!hN(tDfQ7yZ`>8qSbSl%KF%6wYu@juAELSg+k`=xRa38M2A; zGfuHwVhs1>7*Qjwz6K3v$R^59cWtcj28MfbjHr=jsq-q z+>>KO4evR1f;By|&p-UjJN=YvxU8=giVR1|jv6T<96pD8Wb=$|KYP0ob)JvmDA`ft z!aI65KQS?$+vgtHJS*JK5a)Y0&v2CNsNsFBdt~!8^R8#)im~^gi35aUTaJ<)HN3BN zk8GZv?q~9L_O*vWLnyZ8DA`ft!56P@{y6ou?vc$Cf&HXl)P*F*h(XJ>3dOb@B|B;y zebEEWE2O^GJ+gVSv7dO1d$$LMqhv>o6cG-0iF;)8>}5Zbxe;})Z#!tYfkLq@N6C&F zDIy#++#{Rks{48Cji~c{3`fb18Yvd<;j)jvC%`x<@w8qd)xR zmC9K|o~i!cYf-#Q#K3(uP$;(LDA`dXMTEmuxkonJoiStOa+7ywS4(_Ijh+~ek{vZt zL^x=;M>gBN^x8h<`IpYFwtaLlXozt-esiJNmZM}xjg;vWG~6Sb?e_b{D&?0=v#Zyy zTO1laF&rg3YNSl3py3|bZ1>HkRm+zieY)EC&?TTD#wGY1La{AJ$&MN+A{;c_Bb)86 z|L&^gsRuk=O4Vu_06x(u??5N>Ar+Z|x-Gv`p4SnrXRsUs{ zf`%9e;rS4XZ8=JILxXF={2VRtV2=D0{uda*zP7A(| z27Yt?9zmULIZAfaND-Ex;U3v+7x!_+=VQB@20_CZg-~qEQL>{(iWCJ6_sC|uc+x69 z=kLC?7Bs}bGuSE=+j5lbsF5OGLBl<=*)HBI72j89^reO|3ZdARqhv>o6uAo;?vc%Q z@#d@e-u>+^1EC=X-ifV3u`Nf*jv6Tf88qA@o9*H~U$OuAY4lcLBkk@P;ARlvZF?d&<73o$Y#43;Z!dS zpHn?HeGO=cfw51kP;ARlvZDq@WF2V?*Ww=8Y!~CXYUk7DROd`z9U8_cgkoEck{vZL zvg}A>(H8f}X1f@1R!84Dr>ft#8Z^YfSahIJY|Bxyqefc!3E!1_WV2n2oU0|OIn~~6 zeW4)+?yE^cu`Nf*jv8qND`>b!HrvGvpjz>@In@$3tO^Y=FgKVa6x(u??5KemOGldH zw75q$+r@mR8uQtlYT8AsK*Jb?P;ARlvZF@IlntN5J+j#@=55t#-_5Cha%vxF7^4u1 zZ8=JI)W8gqYpFrQJ+j#@W|rs^pRKk&WMya=qY#R1IZAfaK<})+w!lmnZ9QBazRH$O zvWdd1n6dC`*+e0V z$F;lam{+Lb4EN+1Q3Dakx?+~jkWCb#kz9kUR(z1z3C?g&juAD~bKNlVd~;teA9Yjl~(ViNfj$b0(@0r)>)jXSgTFh#KlS@mJvt*+gL#i1`}T zz2mrFxHH_7V?+)0oYZiJY@)E5#k`a1>&v%?hBMrgV?+(_Ih`S!sIv~PF@L7o_0}Dr z;SBfW7*WG}PG`s_3ag9E1FHUh|BldbhI?|1sNp@QGh`EmRZ{ei)2cr|z7sT@;hr2L zYFz!++!-D3#r_;s++|U;{#pjGsD=&8M2A`?BprsKmR2SXSgTF7Xcuan*?*(@ z*)MD!G@K!usOyh!E6+Ge8qRP}j`75y)L3q>t?HMay?)SehHRqtYiTP->?sXrxF^RL za|$&+et$%LrQZ$+8qSbS)N2#l%5S!khBMrgW4u3}8k;_~Ykj2=D+di{$R?^!Yg>8G zKxsI`Jvqjr*HGi;Rrjg?;b*;rhBIUn_1yz)<;lIJ;SBfW7|%?i#wo~`_&pvI^nESP zkWJLDD%`tY+>!c0XSgTFSpPn1%)REw`mN*N@1TY=WD|A4oVN1Jm!;th_v9FTXHsMN zj$`Znw|hEhI72p3EBvFaoZBG{XSgTFnD96?PG9H5`bE3n7c`t9o2b>_Ybzg`Bn@Y{ zC&xJZS!x{q=&AKTe0@#OaE5H6Zv3RJ>~*m;oZ+4vUZcj^e>kiD*dAL24QI$EYR=bf{B>&FIQQ)O zsgJDQjB6~MA)BZJzicb_yC4pkWa~5Q&v)z_G@K!usBJ#SGkBpioZ+4v z^M9HYG@K!usGZ+z zD{tLR8qRP}j`3Zc8qZvMLj9q4I)a8XWD_;^Z+Jd7k%lwelVhCtAT^Gxj;b&5tCxd@ zGh`FB{*!IxxIWTwhI?|16Wge9>E?&kpF8S{py3SJL>=`o+n0tj+>>K0d;>LJ>9v1- zqYdKOfXeeR4+f`&6>6SdvpZRLTOcgEkt8Scq3&KpLJH(vTl z{i<2Rf`&6>6ZOM}wqO1KHrPIBI72p3wawbf2alG9Gu)G7 z{A*ciJihx1^}l>RGH5tMHc?YoNB^;}G@Rj{9AnF`IUn47+r{gDU17hV;SAYC)fQ1NE%au`LL2`g zXgEVQQSUuJr95RlX*k0@ImYncQ{#!!*^5&JL;SBfW7{`sF#(Mvo&@t-S(}IRGWE0iv+$rS+%Syu; z?#VHpI)EDM{%usp7h`@EG@K!usK<_+QZBTFG@Rj{9OJnfHID4NUdO|`pB*%uA)BZn zxNlcqSQ^f7PmXcT0BWqg-`trOA9zmCaE5H6j{nJ&^6v{s!x`?$G1gs_8ciP^HS_gr z<5}^}kWJJ%OHU~`4RKQTQOqOShyWc#k1;hr4hh5M+1Z+Dn}4`;|G>dEPo?KgLZdvc7{Yp8*{q*?cs zGh`FB<&Bf=-gSn1a*U2&Q3H2-vz`xU$R_H4=S;R|&>8N@F@_u*evki6Xx4M?4B12t zK4P-HOYodG81Bh21`VeM-agHZ_m#CJHc>BaKiS@i&TvnTaoal7z+1Fg?_FoeCTi97 zCfmE+8Scq3I+msedV^;5AI^|XRPP^8wm!-k?#VGG{-+HZy{CWO{Fk$1Kj;kEM9uoT z)%sdzxF^Th_%&*5zT@Jx9e*7Ab7#mVYUj6FZOq^d_v9G&KS~XZGHM!^I72p3k389G zV;^U@C&yUp9%^8;RMYs%8M2A`=>x4chI58{a*UgApaw>LHH{OUA)BZ_-P~$pQD?X( z$5`(IYGCwQ(|FezvWYtUl2#j2JHtIW#(O7G1EcVo#_i6KP1LZ{TWxOO4EN+1e?5d6 zm`&6)|8RzEq7FE+)#f&ob0N^rNPD zi8Evqb<&Eh7L##?dvc7Y7o`TGI5ow6oFSX2`qHfyTXKeba*T}^pa!B*HN~%-A)Bby z#ab;!<_!1b80&sF1saH|)f9(whHRn+E!1kUK4-Wm$LRQq8i)?o6i;-9Y@&8p0R2ZJ zX6X#~J0bf7*m4=qP4XY-z}UWo2b*F(HTQ_hI?|1 z)xvj$sB6wZ)M)Trg~3^vwSoZ+4v$uWL%H8tK{YoppWb3#5t;SAYC?R`h9mrjar^p%Z z$uU-5jB{sXAvLGGrNSAqiTd9flPx#O8Scq3X7{HCvZX9Z;hr4h@yDpKTV_dlhHLx<;thH2U$R-M_ zq*dp7tux${V|;oHHL${4)0(g|WD|we-l}um*%|K1F-|;}8XggLhHRp+YF%}%pF6`n zImZ94qlQO>ogtejtiD&Bc>vCEPmVGE_tfx+urp*6g)D-qGoQg3?#VI!^9VIOBJ2#= zL?IiZ>debTL?X;@|K+8o*d)$ z6{vwsr_o4!#z31dPAt;5n*S@ChCe0+p5mIK4-Wm$JnPv4UY&rLpD*!3amQw6P@9n z9OJWXso@b}XUHZB*^O0ao~1L~lVkjMCu(>^*cq~kLY8LLnJ?-L_v9Ey?nVud2s=YI zQOGu}@-bxh^LL%$o*d(Zpy3f=XUHZB*}qjjhU}gkW8snf z93ByNhHRpc#awmfQ#->wIYzHtsNoS|XUHZB+1OQQUbr*dlVcpUJvBTc>)*Cp(JvqkU z4XJ?&g<7gx!J= zo*d)ZdDQTTurp*6g{q{gvp&ih?#VHhe}x(z5q5@bqEKB`b=G+~!#z1h-^Zze%CK6h zB`cgEn5j$C!RIH9R8h4B14X zYOl)2klmAG9DfltJRvQC6MxoX&7h zjRSlC&yT#Mh%Y$J3}^6sA{b`>ua6io*ZNEwW#3{ zVQ0uD3e~w)XPvM!+>>K`wFEU#S=^jzkqc+YCJI%?RcF1kGu)G7EdCi|GN_PlPBqnq zGh`EmYU!%8Zrd5|$uVyED>YE*-JEK}3unkC3RT}#XZ^V|+>>L>d59Vw5q5@bqENkF zb=J{4!#z31y*E+ABf`#*O%$r|tIquZoZ+4v4 zPmb~45!Ap=2t(7}357FcM--!~jTo{qVuUt&a*SVWA2dFkJ0r!ZTbv=AC`6#`b0ALL zV087wD{;nuo2Y^4`OFk=Z*hifq7X^9-@_U1$uaI)ni}{88~ZajLpD)Z5wQEp8Scq3 zZu!?u(7>J8*q^}}vWddVhCLt7a8Hi$?u*pGs!T^($7ykfY@)D2W6!xW+>>Km^Ds5A zy3~=@qgtFHn<%U_+55^F?#VG8{~a~3O4gCq)moe(n<%W9*?ZR+?#VH(x{w-pQ#bZ! zaE5H6u<~d9hcn!hV=Q_CHPGWU_GfU0Y@)D&Y5kxx+>>K8?@bM?zSh%vZHqHx6NQyn z>(8Cxo*ZMBq13=Cay_j(w>U#KQCLy7afvhBlVc2Diy9coH1=n3hHRp+GH&B5XSgTF z*lZbU_-+f%kWCa;_-&l%4EN+1n}2g7G?1N8Px%Zj&X7$MG8JsR>kRkg7(aiX8pyJ! zr@V|7XUHZB85cHgcZPd%jJsZ-21fdg{TZAgnce7Im10U#wzzy12eD2{tV8LO%yVDY(D4=_v9FRO`-;7kd6HroFSViWF* z^U&f~&TvnTaq=>J*ek4DK@3!C!*+d~z+T!iba8Hi0(b3dEgubyqgEM3kg^X`o zH*kh~a*XRwpaxbN8v8RiLpD*!T(|WPXSgTFxaw4DV8x`dKZ7%56NLZ)ULhHRoxp9^ot@#H9OL_EsDYL0#{LY>kWCaSpKSfy8Scq3 z_J4~SSaEOc&)^K%M4^Jq@&KISo*ZM|zo~)DfyVv}&X7$MD$y*T!5Qw!F@Co=$L+{~ zXzb764B14XqR#R%oZ+4v9E?NNMcP;0)PB zp~BJfWSrri9OHvsse$Uuy6QQdA)6>vYFfUJGu)G7ocRlCpvtsEb*avfO%y6lEpN#g z?#VG;7)K3cIyLrZaE5H6P&sS)SI%%xj`79~)Ii2oV}Ax`$R-LEz?Mhm4EN+17e7c1 zWS%wlXK;pWqEN|f`Ebr~PmVEd4mEtY1!u@63KiLw*XIoP4+o Date: Wed, 19 Feb 2020 18:58:42 +0530 Subject: [PATCH 10/78] Update fabxpro_abs_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg index d6a6d22b08..a90ac86d10 100644 --- a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg @@ -8,7 +8,6 @@ setting_version = 11 type = quality quality_type = Draft ABS weight = -2 -global_quality = True [values] layer_height = 0.3 From 569a4583bdef500a51d7c586256c4c10dddccf61 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 18:58:56 +0530 Subject: [PATCH 11/78] Update fabxpro_abs_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg index bfaccfadac..54dc42febd 100644 --- a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg @@ -8,7 +8,6 @@ setting_version = 11 type = quality quality_type = Fine ABS weight = -2 -global_quality = True [values] layer_height = 0.1 From 62b14f33e0ec52a633b250a74b0ad1d18ed77900 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 18:59:12 +0530 Subject: [PATCH 12/78] Update fabxpro_abs_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg index c039ca61d7..6bb38c774a 100644 --- a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg @@ -8,7 +8,6 @@ setting_version = 11 type = quality quality_type = Normal ABS weight = -2 -global_quality = True [values] layer_height = 0.2 From 51442249e4235cc580f56709933e7ae59a4211a3 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 18:59:26 +0530 Subject: [PATCH 13/78] Update fabxpro_pla_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg index 8bda2e29fe..15de2b26c2 100644 --- a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg @@ -8,7 +8,6 @@ setting_version = 11 type = quality quality_type = Draft PLA weight = -2 -global_quality = True [values] layer_height = 0.3 @@ -23,4 +22,4 @@ material_print_temperature = 215 material_bed_temperature = 60 cool_fan_enabled = true cool_fan_speed = 100 -cool_fan_full_at_height = 0.6 \ No newline at end of file +cool_fan_full_at_height = 0.6 From dc2d88042d4554400f3c2d4b2ec375f33cb6a08f Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 18:59:40 +0530 Subject: [PATCH 14/78] Update fabxpro_pla_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg index c98d73e079..1b1a856766 100644 --- a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg @@ -8,7 +8,6 @@ setting_version = 11 type = quality quality_type = Fine PLA weight = -2 -global_quality = True [values] layer_height = 0.1 @@ -23,4 +22,4 @@ material_print_temperature = 215 material_bed_temperature = 60 cool_fan_enabled = true cool_fan_speed = 100 -cool_fan_full_at_height = 0.6 \ No newline at end of file +cool_fan_full_at_height = 0.6 From aad47cb919fced990eac8cf05fe1a3132da5cd40 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 19 Feb 2020 18:59:56 +0530 Subject: [PATCH 15/78] Update fabxpro_pla_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg index 9727be8841..680e2de716 100644 --- a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg @@ -8,7 +8,6 @@ setting_version = 11 type = quality quality_type = Normal PLA weight = -2 -global_quality = True [values] layer_height = 0.2 @@ -23,4 +22,4 @@ material_print_temperature = 215 material_bed_temperature = 60 cool_fan_enabled = true cool_fan_speed = 100 -cool_fan_full_at_height = 0.6 \ No newline at end of file +cool_fan_full_at_height = 0.6 From ba270fc0144c02fa836dca8dcc5d082051a410be Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 20 Feb 2020 17:31:06 +0530 Subject: [PATCH 16/78] Update fabxpro_abs_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg index a90ac86d10..d6a6d22b08 100644 --- a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Draft ABS weight = -2 +global_quality = True [values] layer_height = 0.3 From db6ce265c036417b54fe84176431063239f451a7 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 20 Feb 2020 17:31:44 +0530 Subject: [PATCH 17/78] Update fabxpro_abs_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg index 54dc42febd..bfaccfadac 100644 --- a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Fine ABS weight = -2 +global_quality = True [values] layer_height = 0.1 From 5c6270d6135fb9af74b460b854cebdf805a96bb1 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 20 Feb 2020 17:31:57 +0530 Subject: [PATCH 18/78] Update fabxpro_abs_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg index 6bb38c774a..c039ca61d7 100644 --- a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Normal ABS weight = -2 +global_quality = True [values] layer_height = 0.2 From e24479abd68e464382d77c3b0067120f6b05f193 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 20 Feb 2020 17:32:17 +0530 Subject: [PATCH 19/78] Update fabxpro_pla_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg index 15de2b26c2..a1f1343c96 100644 --- a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Draft PLA weight = -2 +global_quality = True [values] layer_height = 0.3 From 42a494bfd3523165c993407b185d895f067d2511 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 20 Feb 2020 17:32:38 +0530 Subject: [PATCH 20/78] Update fabxpro_pla_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg index 1b1a856766..9d825dfd39 100644 --- a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Fine PLA weight = -2 +global_quality = True [values] layer_height = 0.1 From 3cadf69514d70c2be3443389e4079383f6c8aafb Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 20 Feb 2020 17:32:51 +0530 Subject: [PATCH 21/78] Update fabxpro_pla_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg index 680e2de716..27f718a0fa 100644 --- a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Normal PLA weight = -2 +global_quality = True [values] layer_height = 0.2 From 055a224c7276fd7ba57b922355f2f26b71d67e2e Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Tue, 25 Feb 2020 07:34:34 +0530 Subject: [PATCH 22/78] Update fabxpro.def.json --- resources/definitions/fabxpro.def.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fabxpro.def.json b/resources/definitions/fabxpro.def.json index 048841d525..b70cc3b029 100644 --- a/resources/definitions/fabxpro.def.json +++ b/resources/definitions/fabxpro.def.json @@ -7,7 +7,7 @@ "author": "FabX", "manufacturer": "FabX", "file_formats": "text/x-gcode", - "platform": "fabxpro_platform.stl", + "platform": "fabxpro_platform.STL", "has_materials": true, "has_machine_quality": true, "machine_extruder_trains": @@ -30,7 +30,9 @@ "machine_center_is_zero": { "default_value": false }, - "machine_heated_bed": { "default_value": true }, + "machine_heated_bed": { + "default_value": true + }, "machine_head_with_fans_polygon": { "default_value": [ From 27902fe38fb6e3a32114f1ec705b4f92323c5c91 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 25 Feb 2020 14:41:02 +0100 Subject: [PATCH 23/78] Use JsonDecorator scope in the Toolbox and CloudSync Improves security by disallowing other content than json for requests CURA-7150 --- plugins/Toolbox/src/CloudSync/CloudApiClient.py | 3 ++- plugins/Toolbox/src/CloudSync/CloudPackageChecker.py | 6 ++++-- plugins/Toolbox/src/CloudSync/DownloadPresenter.py | 3 ++- plugins/Toolbox/src/Toolbox.py | 3 ++- plugins/Toolbox/src/UltimakerCloudScope.py | 9 ++++++--- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/plugins/Toolbox/src/CloudSync/CloudApiClient.py b/plugins/Toolbox/src/CloudSync/CloudApiClient.py index 6c14aea26c..ba1cbab624 100644 --- a/plugins/Toolbox/src/CloudSync/CloudApiClient.py +++ b/plugins/Toolbox/src/CloudSync/CloudApiClient.py @@ -1,5 +1,6 @@ from UM.Logger import Logger from UM.TaskManagement.HttpRequestManager import HttpRequestManager +from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication from ..CloudApiModel import CloudApiModel from ..UltimakerCloudScope import UltimakerCloudScope @@ -26,7 +27,7 @@ class CloudApiClient: if self.__instance is not None: raise RuntimeError("This is a Singleton. use getInstance()") - self._scope = UltimakerCloudScope(app) # type: UltimakerCloudScope + self._scope = JsonDecoratorScope(UltimakerCloudScope(app)) # type: JsonDecoratorScope app.getPackageManager().packageInstalled.connect(self._onPackageInstalled) diff --git a/plugins/Toolbox/src/CloudSync/CloudPackageChecker.py b/plugins/Toolbox/src/CloudSync/CloudPackageChecker.py index 7d223c87c6..7404489aee 100644 --- a/plugins/Toolbox/src/CloudSync/CloudPackageChecker.py +++ b/plugins/Toolbox/src/CloudSync/CloudPackageChecker.py @@ -11,6 +11,7 @@ from UM import i18nCatalog from UM.Logger import Logger from UM.Message import Message from UM.Signal import Signal +from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication, ApplicationMetadata from ..CloudApiModel import CloudApiModel from .SubscribedPackagesModel import SubscribedPackagesModel @@ -18,13 +19,14 @@ from ..UltimakerCloudScope import UltimakerCloudScope from typing import List, Dict, Any + class CloudPackageChecker(QObject): def __init__(self, application: CuraApplication) -> None: super().__init__() self.discrepancies = Signal() # Emits SubscribedPackagesModel self._application = application # type: CuraApplication - self._scope = UltimakerCloudScope(application) + self._scope = JsonDecoratorScope(UltimakerCloudScope(application)) self._model = SubscribedPackagesModel() self._application.initializationFinished.connect(self._onAppInitialized) @@ -106,4 +108,4 @@ class CloudPackageChecker(QObject): def _onSyncButtonClicked(self, sync_message: Message, sync_message_action: str) -> None: sync_message.hide() - self.discrepancies.emit(self._model) \ No newline at end of file + self.discrepancies.emit(self._model) diff --git a/plugins/Toolbox/src/CloudSync/DownloadPresenter.py b/plugins/Toolbox/src/CloudSync/DownloadPresenter.py index 743d96c574..06004df5da 100644 --- a/plugins/Toolbox/src/CloudSync/DownloadPresenter.py +++ b/plugins/Toolbox/src/CloudSync/DownloadPresenter.py @@ -11,6 +11,7 @@ from UM.Logger import Logger from UM.Message import Message from UM.Signal import Signal from UM.TaskManagement.HttpRequestManager import HttpRequestManager +from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication from .SubscribedPackagesModel import SubscribedPackagesModel from ..UltimakerCloudScope import UltimakerCloudScope @@ -29,7 +30,7 @@ class DownloadPresenter: self.done = Signal() self._app = app - self._scope = UltimakerCloudScope(app) + self._scope = JsonDecoratorScope(UltimakerCloudScope(app)) self._started = False self._progress_message = self._createProgressMessage() diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 55c6ba223b..9057538835 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -12,6 +12,7 @@ from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkRepl from UM.Logger import Logger from UM.PluginRegistry import PluginRegistry from UM.Extension import Extension +from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from UM.i18n import i18nCatalog from UM.Version import Version @@ -54,7 +55,7 @@ class Toolbox(QObject, Extension): self._download_request_data = None # type: Optional[HttpRequestData] self._download_progress = 0 # type: float self._is_downloading = False # type: bool - self._scope = UltimakerCloudScope(application) # type: UltimakerCloudScope + self._scope = JsonDecoratorScope(UltimakerCloudScope(application)) # type: JsonDecoratorScope self._request_urls = {} # type: Dict[str, str] self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated diff --git a/plugins/Toolbox/src/UltimakerCloudScope.py b/plugins/Toolbox/src/UltimakerCloudScope.py index 14583d7d59..257e97b1af 100644 --- a/plugins/Toolbox/src/UltimakerCloudScope.py +++ b/plugins/Toolbox/src/UltimakerCloudScope.py @@ -6,10 +6,13 @@ from cura.API import Account from cura.CuraApplication import CuraApplication -## Add a Authorization header to the request for Ultimaker Cloud Api requests. -# When the user is not logged in or a token is not available, a warning will be logged -# Also add the user agent headers (see DefaultUserAgentScope) class UltimakerCloudScope(DefaultUserAgentScope): + """Add an Authorization header to the request for Ultimaker Cloud Api requests. + + When the user is not logged in or a token is not available, a warning will be logged + Also add the user agent headers (see DefaultUserAgentScope) + """ + def __init__(self, application: CuraApplication): super().__init__(application) api = application.getCuraAPI() From 77590ad0e25b900756322a536420faf7f95741cf Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 25 Feb 2020 14:42:12 +0100 Subject: [PATCH 24/78] Disable SSL checking in debug mode Allows inspecting web traffic during development CURA-7150 --- cura_app.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cura_app.py b/cura_app.py index 38d1149080..1f0c4a0743 100755 --- a/cura_app.py +++ b/cura_app.py @@ -15,6 +15,8 @@ import sys import Arcus # @UnusedImport import Savitar # @UnusedImport +from PyQt5.QtNetwork import QSslConfiguration, QSslSocket + from UM.Platform import Platform from cura import ApplicationMetadata from cura.ApplicationMetadata import CuraAppName @@ -209,5 +211,10 @@ if Platform.isLinux() and getattr(sys, "frozen", False): import trimesh.exchange.load os.environ["LD_LIBRARY_PATH"] = old_env +if ApplicationMetadata.CuraDebugMode: + ssl_conf = QSslConfiguration.defaultConfiguration() + ssl_conf.setPeerVerifyMode(QSslSocket.VerifyNone) + QSslConfiguration.setDefaultConfiguration(ssl_conf) + app = CuraApplication() app.run() From 8f70bb934e30a1f9d7ebc89a9c18b7304ba0c5b8 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 26 Feb 2020 16:56:03 +0530 Subject: [PATCH 25/78] Update fabxpro_extruder_0.def.json --- resources/extruders/fabxpro_extruder_0.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/extruders/fabxpro_extruder_0.def.json b/resources/extruders/fabxpro_extruder_0.def.json index 1ce0059b9e..761aebe287 100644 --- a/resources/extruders/fabxpro_extruder_0.def.json +++ b/resources/extruders/fabxpro_extruder_0.def.json @@ -3,7 +3,7 @@ "name": "Extruder 1", "inherits": "fdmextruder", "metadata": { - "machine": "FabX Pro", + "machine": "fabxpro", "position": "0" }, From 86fb0383decb1469c44004d5e1a3c5c1ea2d55ef Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 28 Feb 2020 14:01:11 +0100 Subject: [PATCH 26/78] Refactor refresh backups call to use HttpRequestManager --- plugins/CuraDrive/src/DriveApiService.py | 44 +++++++++---------- plugins/CuraDrive/src/DrivePluginExtension.py | 5 ++- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index d8349ccc29..35f8d95ca6 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -5,14 +5,19 @@ import base64 import hashlib from datetime import datetime from tempfile import NamedTemporaryFile -from typing import Any, Optional, List, Dict +from typing import Any, Optional, List, Dict, Callable import requests from UM.Logger import Logger from UM.Message import Message from UM.Signal import Signal, signalemitter +from UM.TaskManagement.HttpRequestManager import HttpRequestManager +from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication +from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope + +from PyQt5.QtNetwork import QNetworkReply from .UploadBackupJob import UploadBackupJob from .Settings import Settings @@ -34,33 +39,24 @@ class DriveApiService: def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() + self._scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) - def getBackups(self) -> List[Dict[str, Any]]: - access_token = self._cura_api.account.accessToken - if not access_token: - Logger.log("w", "Could not get access token.") - return [] - try: - backup_list_request = requests.get(self.BACKUP_URL, headers = { - "Authorization": "Bearer {}".format(access_token) - }) - except requests.exceptions.ConnectionError: - Logger.logException("w", "Unable to connect with the server.") - return [] + def getBackups(self, changed: Callable): + def callback(reply: QNetworkReply): + backup_list_response = HttpRequestManager.readJSON(reply) + if "data" not in backup_list_response: + Logger.log("w", "Could not get backups from remote, actual response body was: %s", + str(backup_list_response)) + changed([]) # empty list of backups - # HTTP status 300s mean redirection. 400s and 500s are errors. - # Technically 300s are not errors, but the use case here relies on "requests" to handle redirects automatically. - if backup_list_request.status_code >= 300: - Logger.log("w", "Could not get backups list from remote: %s", backup_list_request.text) - Message(catalog.i18nc("@info:backup_status", "There was an error listing your backups."), title = catalog.i18nc("@info:title", "Backup")).show() - return [] + changed(backup_list_response["data"]) - backup_list_response = backup_list_request.json() - if "data" not in backup_list_response: - Logger.log("w", "Could not get backups from remote, actual response body was: %s", str(backup_list_response)) - return [] + HttpRequestManager.getInstance().get( + self.BACKUP_URL, + callback=callback, + scope=self._scope + ) - return backup_list_response["data"] def createBackup(self) -> None: self.creatingStateChanged.emit(is_creating = True) diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index bcc326a133..31bf0bc933 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -133,7 +133,10 @@ class DrivePluginExtension(QObject, Extension): @pyqtSlot(name = "refreshBackups") def refreshBackups(self) -> None: - self._backups = self._drive_api_service.getBackups() + self._drive_api_service.getBackups(self._backupsChangedCallback) + + def _backupsChangedCallback(self, backups): + self.backups = backups self.backupsChanged.emit() @pyqtProperty(bool, notify = restoringStateChanged) From 234acf0904f1a1a85cbc423c8c64b4b057fcadf3 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 28 Feb 2020 16:25:28 +0100 Subject: [PATCH 27/78] Fix bug: typo in variable name --- plugins/CuraDrive/src/DrivePluginExtension.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index 31bf0bc933..210d6ae8ea 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -136,7 +136,7 @@ class DrivePluginExtension(QObject, Extension): self._drive_api_service.getBackups(self._backupsChangedCallback) def _backupsChangedCallback(self, backups): - self.backups = backups + self._backups = backups self.backupsChanged.emit() @pyqtProperty(bool, notify = restoringStateChanged) From 4f2827e1bf903a73d9f25602a64a4c03ae87b7d5 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 28 Feb 2020 16:25:43 +0100 Subject: [PATCH 28/78] Refactor restore backups call to use HttpRequestManager --- plugins/CuraDrive/src/DriveApiService.py | 42 ++++++++++++++++-------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 35f8d95ca6..0a2d406d59 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -17,7 +17,7 @@ from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope -from PyQt5.QtNetwork import QNetworkReply +from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest from .UploadBackupJob import UploadBackupJob from .Settings import Settings @@ -30,6 +30,7 @@ catalog = i18nCatalog("cura") @signalemitter class DriveApiService: BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) + DISK_WRITE_BUFFER_SIZE = 512 * 1024 # Emit signal when restoring backup started or finished. restoringStateChanged = Signal() @@ -40,9 +41,14 @@ class DriveApiService: def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() self._scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) + self._in_progress_backup = None def getBackups(self, changed: Callable): - def callback(reply: QNetworkReply): + def callback(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): + if error is not None: + Logger.log("w", "Could not get backups: " + str(error)) + changed([]) + backup_list_response = HttpRequestManager.readJSON(reply) if "data" not in backup_list_response: Logger.log("w", "Could not get backups from remote, actual response body was: %s", @@ -94,22 +100,32 @@ class DriveApiService: # If there is no download URL, we can't restore the backup. return self._emitRestoreError() - try: - download_package = requests.get(download_url, stream = True) - except requests.exceptions.ConnectionError: - Logger.logException("e", "Unable to connect with the server") - return self._emitRestoreError() + def finishedCallback(reply: QNetworkReply, bu=backup) -> None: + self._onRestoreRequestCompleted(reply, None, bu) - if download_package.status_code >= 300: - # Something went wrong when attempting to download the backup. - Logger.log("w", "Could not download backup from url %s: %s", download_url, download_package.text) - return self._emitRestoreError() + HttpRequestManager.getInstance().get( + url = download_url, + callback = finishedCallback, + error_callback = self._onRestoreRequestCompleted + ) + + def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, backup = None): + if error is not None or reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200: + Logger.log("w", + "Requesting backup failed, response code %s while trying to connect to %s", + reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url()) + self._emitRestoreError() + return # We store the file in a temporary path fist to ensure integrity. temporary_backup_file = NamedTemporaryFile(delete = False) with open(temporary_backup_file.name, "wb") as write_backup: - for chunk in download_package: - write_backup.write(chunk) + app = CuraApplication.getInstance() + bytes_read = reply.read(DriveApiService.DISK_WRITE_BUFFER_SIZE) + while bytes_read: + write_backup.write(bytes_read) + bytes_read = reply.read(DriveApiService.DISK_WRITE_BUFFER_SIZE) + app.processEvents() if not self._verifyMd5Hash(temporary_backup_file.name, backup.get("md5_hash", "")): # Don't restore the backup if the MD5 hashes do not match. From 19c3f765f585908d1921d74fbc71c21c1e3d65cf Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 28 Feb 2020 17:08:31 +0100 Subject: [PATCH 29/78] Refactor delete backups call to use HttpRequestManager --- plugins/CuraDrive/src/DriveApiService.py | 48 ++++++++++--------- plugins/CuraDrive/src/DrivePluginExtension.py | 7 ++- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 0a2d406d59..0168d8de2b 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -10,7 +10,6 @@ from typing import Any, Optional, List, Dict, Callable import requests from UM.Logger import Logger -from UM.Message import Message from UM.Signal import Signal, signalemitter from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope @@ -40,10 +39,10 @@ class DriveApiService: def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() - self._scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) + self._jsonCloudScope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) self._in_progress_backup = None - def getBackups(self, changed: Callable): + def getBackups(self, changed: Callable[[List], None]): def callback(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): if error is not None: Logger.log("w", "Could not get backups: " + str(error)) @@ -59,8 +58,9 @@ class DriveApiService: HttpRequestManager.getInstance().get( self.BACKUP_URL, - callback=callback, - scope=self._scope + callback= callback, + error_callback = callback, + scope=self._jsonCloudScope ) @@ -110,7 +110,7 @@ class DriveApiService: ) def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, backup = None): - if error is not None or reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200: + if not DriveApiService._replyIndicatesSuccess(reply, error): Logger.log("w", "Requesting backup failed, response code %s while trying to connect to %s", reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url()) @@ -153,24 +153,28 @@ class DriveApiService: local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8") return known_hash == local_md5_hash - def deleteBackup(self, backup_id: str) -> bool: - access_token = self._cura_api.account.accessToken - if not access_token: - Logger.log("w", "Could not get access token.") - return False + @staticmethod + def _replyIndicatesSuccess(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): + """Returns whether reply status code indicates success and error is None""" + return error is None and 200 <= reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) < 300 - try: - delete_backup = requests.delete("{}/{}".format(self.BACKUP_URL, backup_id), headers = { - "Authorization": "Bearer {}".format(access_token) - }) - except requests.exceptions.ConnectionError: - Logger.logException("e", "Unable to connect with the server") - return False + def deleteBackup(self, backup_id: str, callable: Callable[[bool], None]): - if delete_backup.status_code >= 300: - Logger.log("w", "Could not delete backup: %s", delete_backup.text) - return False - return True + def finishedCallback(reply: QNetworkReply, ca=callable) -> None: + self._onDeleteRequestCompleted(reply, None, ca) + + def errorCallback(reply: QNetworkReply, error: QNetworkReply.NetworkError, ca=callable) -> None: + self._onDeleteRequestCompleted(reply, error, ca) + + HttpRequestManager.getInstance().delete( + url = "{}/{}".format(self.BACKUP_URL, backup_id), + callback = finishedCallback, + error_callback = errorCallback, + scope= self._jsonCloudScope + ) + + def _onDeleteRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, callable = None): + callable(DriveApiService._replyIndicatesSuccess(reply, error)) # Request a backup upload slot from the API. # \param backup_metadata: A dict containing some meta data about the backup. diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index 210d6ae8ea..34f30d8b3d 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -161,5 +161,8 @@ class DrivePluginExtension(QObject, Extension): @pyqtSlot(str, name = "deleteBackup") def deleteBackup(self, backup_id: str) -> None: - self._drive_api_service.deleteBackup(backup_id) - self.refreshBackups() + self._drive_api_service.deleteBackup(backup_id, self._backupDeletedCallback) + + def _backupDeletedCallback(self, success: bool): + if success: + self.refreshBackups() From 762f699f6462b861496462152035246aa14e3c19 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 28 Feb 2020 17:37:21 +0100 Subject: [PATCH 30/78] Refactor UploadBackupJob to use HttpRequestManager --- plugins/CuraDrive/src/DriveApiService.py | 14 +++------- plugins/CuraDrive/src/UploadBackupJob.py | 33 +++++++++++++++--------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 0168d8de2b..167eae4424 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -63,7 +63,6 @@ class DriveApiService: scope=self._jsonCloudScope ) - def createBackup(self) -> None: self.creatingStateChanged.emit(is_creating = True) @@ -87,9 +86,9 @@ class DriveApiService: upload_backup_job.start() def _onUploadFinished(self, job: "UploadBackupJob") -> None: - if job.backup_upload_error_message != "": + if job.backup_upload_error_text != "": # If the job contains an error message we pass it along so the UI can display it. - self.creatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_message) + self.creatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_text) else: self.creatingStateChanged.emit(is_creating = False) @@ -110,7 +109,7 @@ class DriveApiService: ) def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, backup = None): - if not DriveApiService._replyIndicatesSuccess(reply, error): + if not HttpRequestManager.replyIndicatesSuccess(reply, error): Logger.log("w", "Requesting backup failed, response code %s while trying to connect to %s", reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url()) @@ -153,11 +152,6 @@ class DriveApiService: local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8") return known_hash == local_md5_hash - @staticmethod - def _replyIndicatesSuccess(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): - """Returns whether reply status code indicates success and error is None""" - return error is None and 200 <= reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) < 300 - def deleteBackup(self, backup_id: str, callable: Callable[[bool], None]): def finishedCallback(reply: QNetworkReply, ca=callable) -> None: @@ -174,7 +168,7 @@ class DriveApiService: ) def _onDeleteRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, callable = None): - callable(DriveApiService._replyIndicatesSuccess(reply, error)) + callable(HttpRequestManager.replyIndicatesSuccess(reply, error)) # Request a backup upload slot from the API. # \param backup_metadata: A dict containing some meta data about the backup. diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py index 2e76ed9b4b..5ac48c7512 100644 --- a/plugins/CuraDrive/src/UploadBackupJob.py +++ b/plugins/CuraDrive/src/UploadBackupJob.py @@ -1,11 +1,11 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. - -import requests +from PyQt5.QtNetwork import QNetworkReply from UM.Job import Job from UM.Logger import Logger from UM.Message import Message +from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -21,21 +21,30 @@ class UploadBackupJob(Job): self._signed_upload_url = signed_upload_url self._backup_zip = backup_zip self._upload_success = False - self.backup_upload_error_message = "" + self.backup_upload_error_text = "" + self._message = None def run(self) -> None: - upload_message = Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE, progress = -1) - upload_message.show() + self._message = Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE, progress = -1) + self._message.show() - backup_upload = requests.put(self._signed_upload_url, data = self._backup_zip) - upload_message.hide() + HttpRequestManager.getInstance().put( + self._signed_upload_url, + data = self._backup_zip + ) - if backup_upload.status_code >= 300: - self.backup_upload_error_message = backup_upload.text - Logger.log("w", "Could not upload backup file: %s", backup_upload.text) - Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), title = self.MESSAGE_TITLE).show() - else: + def uploadFinishedCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError): + self._message.hide() + + self.backup_upload_error_text = HttpRequestManager.readText(reply) + + if HttpRequestManager.replyIndicatesSuccess(reply, error): self._upload_success = True Message(catalog.i18nc("@info:backup_status", "Your backup has finished uploading."), title = self.MESSAGE_TITLE).show() + else: + self.backup_upload_error_text = self.backup_upload_error_text + Logger.log("w", "Could not upload backup file: %s", self.backup_upload_error_text) + Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), + title=self.MESSAGE_TITLE).show() self.finished.emit(self) From 932b12e66c6be25f3467c505738b8c9a694a7043 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 2 Mar 2020 11:58:12 +0100 Subject: [PATCH 31/78] Convert doxygen to rst for DriveApiService --- plugins/CuraDrive/src/DriveApiService.py | 29 +++++++++++++++--------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 167eae4424..3a94cf7aa0 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -25,17 +25,18 @@ from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") -## The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling. @signalemitter class DriveApiService: + """The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling.""" + BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) DISK_WRITE_BUFFER_SIZE = 512 * 1024 - # Emit signal when restoring backup started or finished. restoringStateChanged = Signal() + """Emits signal when restoring backup started or finished.""" - # Emit signal when creating backup started or finished. creatingStateChanged = Signal() + """Emits signal when creating backup started or finished.""" def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() @@ -142,12 +143,15 @@ class DriveApiService: error_message = catalog.i18nc("@info:backup_status", "There was an error trying to restore your backup.")) - # Verify the MD5 hash of a file. - # \param file_path Full path to the file. - # \param known_hash The known MD5 hash of the file. - # \return: Success or not. @staticmethod def _verifyMd5Hash(file_path: str, known_hash: str) -> bool: + """Verify the MD5 hash of a file. + + :param file_path: Full path to the file. + :param known_hash: The known MD5 hash of the file. + :return: Success or not. + """ + with open(file_path, "rb") as read_backup: local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8") return known_hash == local_md5_hash @@ -170,11 +174,14 @@ class DriveApiService: def _onDeleteRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, callable = None): callable(HttpRequestManager.replyIndicatesSuccess(reply, error)) - # Request a backup upload slot from the API. - # \param backup_metadata: A dict containing some meta data about the backup. - # \param backup_size The size of the backup file in bytes. - # \return: The upload URL for the actual backup file if successful, otherwise None. def _requestBackupUpload(self, backup_metadata: Dict[str, Any], backup_size: int) -> Optional[str]: + """Request a backup upload slot from the API. + + :param backup_metadata: A dict containing some meta data about the backup. + :param backup_size: The size of the backup file in bytes. + :return: The upload URL for the actual backup file if successful, otherwise None. + """ + access_token = self._cura_api.account.accessToken if not access_token: Logger.log("w", "Could not get access token.") From 6c9b9909baa1cd8b379c6ea24c207a8ae8b7c4ac Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 2 Mar 2020 14:46:33 +0100 Subject: [PATCH 32/78] Fix UploadBackupJob --- plugins/CuraDrive/src/UploadBackupJob.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py index 5ac48c7512..598da495bd 100644 --- a/plugins/CuraDrive/src/UploadBackupJob.py +++ b/plugins/CuraDrive/src/UploadBackupJob.py @@ -29,11 +29,13 @@ class UploadBackupJob(Job): self._message.show() HttpRequestManager.getInstance().put( - self._signed_upload_url, - data = self._backup_zip + self._signed_upload_url, + data = self._backup_zip, + callback = self.uploadFinishedCallback, + error_callback = self.uploadFinishedCallback ) - def uploadFinishedCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError): + def uploadFinishedCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError = None): self._message.hide() self.backup_upload_error_text = HttpRequestManager.readText(reply) From 7243dc63a4f8815f80d244462e09734e485913f4 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 2 Mar 2020 15:12:42 +0100 Subject: [PATCH 33/78] Revert: Refactor UploadBackupJob to use HttpRequestManager It doesn't make sense to have a Job using HttpRequestManager because both are async and Note that the job itself should not emit finished, the JobQueue does that. --- plugins/CuraDrive/src/DriveApiService.py | 4 +-- plugins/CuraDrive/src/UploadBackupJob.py | 37 ++++++++---------------- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 3a94cf7aa0..ba43d01187 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -87,9 +87,9 @@ class DriveApiService: upload_backup_job.start() def _onUploadFinished(self, job: "UploadBackupJob") -> None: - if job.backup_upload_error_text != "": + if job.backup_upload_error_message != "": # If the job contains an error message we pass it along so the UI can display it. - self.creatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_text) + self.creatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_message) else: self.creatingStateChanged.emit(is_creating = False) diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py index 598da495bd..8ade697cb3 100644 --- a/plugins/CuraDrive/src/UploadBackupJob.py +++ b/plugins/CuraDrive/src/UploadBackupJob.py @@ -1,11 +1,11 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from PyQt5.QtNetwork import QNetworkReply + +import requests from UM.Job import Job from UM.Logger import Logger from UM.Message import Message -from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -21,32 +21,19 @@ class UploadBackupJob(Job): self._signed_upload_url = signed_upload_url self._backup_zip = backup_zip self._upload_success = False - self.backup_upload_error_text = "" - self._message = None + self.backup_upload_error_message = "" def run(self) -> None: - self._message = Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE, progress = -1) - self._message.show() + upload_message = Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE, progress = -1) + upload_message.show() - HttpRequestManager.getInstance().put( - self._signed_upload_url, - data = self._backup_zip, - callback = self.uploadFinishedCallback, - error_callback = self.uploadFinishedCallback - ) + backup_upload = requests.put(self._signed_upload_url, data = self._backup_zip) + upload_message.hide() - def uploadFinishedCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError = None): - self._message.hide() - - self.backup_upload_error_text = HttpRequestManager.readText(reply) - - if HttpRequestManager.replyIndicatesSuccess(reply, error): + if backup_upload.status_code >= 300: + self.backup_upload_error_message = backup_upload.text + Logger.log("w", "Could not upload backup file: %s", backup_upload.text) + Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), title = self.MESSAGE_TITLE).show() + else: self._upload_success = True Message(catalog.i18nc("@info:backup_status", "Your backup has finished uploading."), title = self.MESSAGE_TITLE).show() - else: - self.backup_upload_error_text = self.backup_upload_error_text - Logger.log("w", "Could not upload backup file: %s", self.backup_upload_error_text) - Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), - title=self.MESSAGE_TITLE).show() - - self.finished.emit(self) From 244d018a2eedb41d92339c6c3d46a60424fc30fe Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 2 Mar 2020 15:14:04 +0100 Subject: [PATCH 34/78] Refactor createBackup to use HttpRequestManager --- plugins/CuraDrive/src/DriveApiService.py | 82 +++++++++++++----------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index ba43d01187..922ca8afa7 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -3,12 +3,11 @@ import base64 import hashlib +import json from datetime import datetime from tempfile import NamedTemporaryFile from typing import Any, Optional, List, Dict, Callable -import requests - from UM.Logger import Logger from UM.Signal import Signal, signalemitter from UM.TaskManagement.HttpRequestManager import HttpRequestManager @@ -41,7 +40,9 @@ class DriveApiService: def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() self._jsonCloudScope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) - self._in_progress_backup = None + self._current_backup_zip_file = None + + self.creatingStateChanged.connect(self._creatingStateChanged) def getBackups(self, changed: Callable[[List], None]): def callback(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): @@ -76,15 +77,8 @@ class DriveApiService: # Create an upload entry for the backup. timestamp = datetime.now().isoformat() backup_meta_data["description"] = "{}.backup.{}.cura.zip".format(timestamp, backup_meta_data["cura_release"]) - backup_upload_url = self._requestBackupUpload(backup_meta_data, len(backup_zip_file)) - if not backup_upload_url: - self.creatingStateChanged.emit(is_creating = False, error_message ="Could not upload backup.") - return - - # Upload the backup to storage. - upload_backup_job = UploadBackupJob(backup_upload_url, backup_zip_file) - upload_backup_job.finished.connect(self._onUploadFinished) - upload_backup_job.start() + self._requestBackupUpload(backup_meta_data, len(backup_zip_file)) + self._current_backup_zip_file = backup_zip_file def _onUploadFinished(self, job: "UploadBackupJob") -> None: if job.backup_upload_error_message != "": @@ -156,12 +150,12 @@ class DriveApiService: local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8") return known_hash == local_md5_hash - def deleteBackup(self, backup_id: str, callable: Callable[[bool], None]): + def deleteBackup(self, backup_id: str, finishedCallable: Callable[[bool], None]): - def finishedCallback(reply: QNetworkReply, ca=callable) -> None: + def finishedCallback(reply: QNetworkReply, ca=finishedCallable) -> None: self._onDeleteRequestCompleted(reply, None, ca) - def errorCallback(reply: QNetworkReply, error: QNetworkReply.NetworkError, ca=callable) -> None: + def errorCallback(reply: QNetworkReply, error: QNetworkReply.NetworkError, ca=finishedCallable) -> None: self._onDeleteRequestCompleted(reply, error, ca) HttpRequestManager.getInstance().delete( @@ -174,7 +168,7 @@ class DriveApiService: def _onDeleteRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, callable = None): callable(HttpRequestManager.replyIndicatesSuccess(reply, error)) - def _requestBackupUpload(self, backup_metadata: Dict[str, Any], backup_size: int) -> Optional[str]: + def _requestBackupUpload(self, backup_metadata: Dict[str, Any], backup_size: int) -> None: """Request a backup upload slot from the API. :param backup_metadata: A dict containing some meta data about the backup. @@ -182,27 +176,37 @@ class DriveApiService: :return: The upload URL for the actual backup file if successful, otherwise None. """ - access_token = self._cura_api.account.accessToken - if not access_token: - Logger.log("w", "Could not get access token.") - return None - try: - backup_upload_request = requests.put( - self.BACKUP_URL, - json = {"data": {"backup_size": backup_size, - "metadata": backup_metadata - } - }, - headers = { - "Authorization": "Bearer {}".format(access_token) - }) - except requests.exceptions.ConnectionError: - Logger.logException("e", "Unable to connect with the server") - return None + payload = json.dumps({"data": {"backup_size": backup_size, + "metadata": backup_metadata + } + }).encode() - # Any status code of 300 or above indicates an error. - if backup_upload_request.status_code >= 300: - Logger.log("w", "Could not request backup upload: %s", backup_upload_request.text) - return None - - return backup_upload_request.json()["data"]["upload_url"] + HttpRequestManager.getInstance().put( + self.BACKUP_URL, + data = payload, + callback = self._onBackupUploadSlotCompleted, + error_callback = self._onBackupUploadSlotCompleted, + scope = self._jsonCloudScope) + + def _onBackupUploadSlotCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: + if error is not None: + Logger.warning(str(error)) + self.creatingStateChanged.emit(is_creating=False, error_message="Could not upload backup.") + return + if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) >= 300: + Logger.warning("Could not request backup upload: %s", HttpRequestManager.readText(reply)) + self.creatingStateChanged.emit(is_creating=False, error_message="Could not upload backup.") + return + + backup_upload_url = HttpRequestManager.readJSON(reply)["data"]["upload_url"] + + # Upload the backup to storage. + upload_backup_job = UploadBackupJob(backup_upload_url, self._current_backup_zip_file) + upload_backup_job.finished.connect(self._onUploadFinished) + upload_backup_job.start() + + def _creatingStateChanged(self, is_creating: bool = False, error_message: str = None) -> None: + """Cleanup after a backup is not needed anymore""" + + if not is_creating: + self._current_backup_zip_file = None From 59d66741a165de88fbebcee55eb33e82689e0284 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 4 Mar 2020 19:07:18 +0530 Subject: [PATCH 35/78] Update fabxpro_abs_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg index d6a6d22b08..4c9122cffd 100644 --- a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg @@ -17,8 +17,8 @@ speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = true +support_enable = True adhesion_type = raft material_print_temperature = 240 material_bed_temperature = 110 -cool_fan_enabled = false +cool_fan_enabled = False From 1b2e031c7cf2a03c4743581cd02bb5895748043f Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 4 Mar 2020 19:09:06 +0530 Subject: [PATCH 36/78] Update fabxpro_abs_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg index bfaccfadac..8b6a8c4dc2 100644 --- a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg @@ -17,8 +17,8 @@ speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = true +support_enable = True adhesion_type = raft material_print_temperature = 240 material_bed_temperature = 110 -cool_fan_enabled = false +cool_fan_enabled = False From dbe35a7825efcb89f1b0d54fe972227413e34508 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 4 Mar 2020 19:09:23 +0530 Subject: [PATCH 37/78] Update fabxpro_abs_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg index c039ca61d7..f478ddf8a7 100644 --- a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg @@ -17,8 +17,8 @@ speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = true +support_enable = True adhesion_type = raft material_print_temperature = 240 material_bed_temperature = 110 -cool_fan_enabled = false +cool_fan_enabled = False From 049db913e4f942d3f6682d4658492d6641703c9d Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 4 Mar 2020 19:09:46 +0530 Subject: [PATCH 38/78] Update fabxpro_pla_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg index a1f1343c96..fa6a79ed6b 100644 --- a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg @@ -17,10 +17,10 @@ speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = true +support_enable = True adhesion_type = skirt material_print_temperature = 215 material_bed_temperature = 60 -cool_fan_enabled = true +cool_fan_enabled = True cool_fan_speed = 100 cool_fan_full_at_height = 0.6 From 4546ad9c60f3b0c0e67f5f55b2735e78bb243a8e Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 4 Mar 2020 19:10:09 +0530 Subject: [PATCH 39/78] Update fabxpro_pla_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg index 9d825dfd39..fb01e0778d 100644 --- a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg @@ -17,10 +17,10 @@ speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = true +support_enable = True adhesion_type = skirt material_print_temperature = 215 material_bed_temperature = 60 -cool_fan_enabled = true +cool_fan_enabled = True cool_fan_speed = 100 cool_fan_full_at_height = 0.6 From 292873bea9e905c1f5cfe1272a71dea6c4a065b0 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 4 Mar 2020 19:10:30 +0530 Subject: [PATCH 40/78] Update fabxpro_pla_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg index 27f718a0fa..fd26ea4d2f 100644 --- a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg @@ -17,10 +17,10 @@ speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = true +support_enable = True adhesion_type = skirt material_print_temperature = 215 material_bed_temperature = 60 -cool_fan_enabled = true +cool_fan_enabled = True cool_fan_speed = 100 cool_fan_full_at_height = 0.6 From ed5c2b3f43c281ca10b9f6f57ae8120b9c57aada Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 10 Mar 2020 13:34:18 +0100 Subject: [PATCH 41/78] Refactor the create backup implementation to CreateBackupJob --- plugins/CuraDrive/src/CreateBackupJob.py | 122 +++++++++++++++++++++++ plugins/CuraDrive/src/DriveApiService.py | 69 ++----------- plugins/CuraDrive/src/UploadBackupJob.py | 39 -------- 3 files changed, 129 insertions(+), 101 deletions(-) create mode 100644 plugins/CuraDrive/src/CreateBackupJob.py delete mode 100644 plugins/CuraDrive/src/UploadBackupJob.py diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py new file mode 100644 index 0000000000..603733137b --- /dev/null +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -0,0 +1,122 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. +import json +import threading +from typing import Any, Dict, Optional + +from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest +from datetime import datetime + +from UM.Job import Job +from UM.Logger import Logger +from UM.Message import Message +from UM.TaskManagement.HttpRequestManager import HttpRequestManager +from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope + +from UM.i18n import i18nCatalog +from cura.CuraApplication import CuraApplication +from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope + +catalog = i18nCatalog("cura") + + +class CreateBackupJob(Job): + """Creates backup zip, requests upload url and uploads the backup file to cloud storage.""" + + MESSAGE_TITLE = catalog.i18nc("@info:title", "Backups") + + def __init__(self, api_backup_url: str) -> None: + """ Create a new backup Job. start the job by calling start() + + :param api_backup_url: The url of the 'backups' endpoint of the Cura Drive Api + """ + + super().__init__() + + self._api_backup_url = api_backup_url + self._jsonCloudScope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) + + + self._backup_zip = None + self._upload_success = False + self._upload_success_available = threading.Event() + self.backup_upload_error_message = "" + + def run(self) -> None: + upload_message = Message(catalog.i18nc("@info:backup_status", "Creating your backup..."), title = self.MESSAGE_TITLE, progress = -1) + upload_message.show() + CuraApplication.getInstance().processEvents() + cura_api = CuraApplication.getInstance().getCuraAPI() + self._backup_zip, backup_meta_data = cura_api.backups.createBackup() + + if not self._backup_zip or not backup_meta_data: + self.backup_upload_error_message = "Could not create backup." + upload_message.hide() + return + + upload_message.setText(catalog.i18nc("@info:backup_status", "Uploading your backup...")) + CuraApplication.getInstance().processEvents() + + # Create an upload entry for the backup. + timestamp = datetime.now().isoformat() + backup_meta_data["description"] = "{}.backup.{}.cura.zip".format(timestamp, backup_meta_data["cura_release"]) + self._requestUploadSlot(backup_meta_data, len(self._backup_zip)) + + self._upload_success_available.wait() + upload_message.hide() + + def _requestUploadSlot(self, backup_metadata: Dict[str, Any], backup_size: int) -> None: + """Request a backup upload slot from the API. + + :param backup_metadata: A dict containing some meta data about the backup. + :param backup_size: The size of the backup file in bytes. + :return: The upload URL for the actual backup file if successful, otherwise None. + """ + + payload = json.dumps({"data": {"backup_size": backup_size, + "metadata": backup_metadata + } + }).encode() + + HttpRequestManager.getInstance().put( + self._api_backup_url, + data = payload, + callback = self._onUploadSlotCompleted, + error_callback = self._onUploadSlotCompleted, + scope = self._jsonCloudScope) + + def _onUploadSlotCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: + if error is not None: + Logger.warning(str(error)) + self.backup_upload_error_message = "Could not upload backup." + self._upload_success_available.set() + return + if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) >= 300: + Logger.warning("Could not request backup upload: %s", HttpRequestManager.readText(reply)) + self.backup_upload_error_message = "Could not upload backup." + self._upload_success_available.set() + return + + backup_upload_url = HttpRequestManager.readJSON(reply)["data"]["upload_url"] + + # Upload the backup to storage. + HttpRequestManager.getInstance().put( + backup_upload_url, + data=self._backup_zip, + callback=self._uploadFinishedCallback, + error_callback=self._uploadFinishedCallback + ) + + def _uploadFinishedCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError = None): + self.backup_upload_error_text = HttpRequestManager.readText(reply) + + if HttpRequestManager.replyIndicatesSuccess(reply, error): + self._upload_success = True + Message(catalog.i18nc("@info:backup_status", "Your backup has finished uploading."), title = self.MESSAGE_TITLE).show() + else: + self.backup_upload_error_text = self.backup_upload_error_text + Logger.log("w", "Could not upload backup file: %s", self.backup_upload_error_text) + Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), + title=self.MESSAGE_TITLE).show() + + self._upload_success_available.set() diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 922ca8afa7..04f935268b 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -3,8 +3,6 @@ import base64 import hashlib -import json -from datetime import datetime from tempfile import NamedTemporaryFile from typing import Any, Optional, List, Dict, Callable @@ -17,7 +15,7 @@ from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest -from .UploadBackupJob import UploadBackupJob +from .CreateBackupJob import CreateBackupJob from .Settings import Settings from UM.i18n import i18nCatalog @@ -40,21 +38,20 @@ class DriveApiService: def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() self._jsonCloudScope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) - self._current_backup_zip_file = None - - self.creatingStateChanged.connect(self._creatingStateChanged) def getBackups(self, changed: Callable[[List], None]): def callback(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): if error is not None: Logger.log("w", "Could not get backups: " + str(error)) changed([]) + return backup_list_response = HttpRequestManager.readJSON(reply) if "data" not in backup_list_response: Logger.log("w", "Could not get backups from remote, actual response body was: %s", str(backup_list_response)) changed([]) # empty list of backups + return changed(backup_list_response["data"]) @@ -67,20 +64,11 @@ class DriveApiService: def createBackup(self) -> None: self.creatingStateChanged.emit(is_creating = True) + upload_backup_job = CreateBackupJob(self.BACKUP_URL) + upload_backup_job.finished.connect(self._onUploadFinished) + upload_backup_job.start() - # Create the backup. - backup_zip_file, backup_meta_data = self._cura_api.backups.createBackup() - if not backup_zip_file or not backup_meta_data: - self.creatingStateChanged.emit(is_creating = False, error_message ="Could not create backup.") - return - - # Create an upload entry for the backup. - timestamp = datetime.now().isoformat() - backup_meta_data["description"] = "{}.backup.{}.cura.zip".format(timestamp, backup_meta_data["cura_release"]) - self._requestBackupUpload(backup_meta_data, len(backup_zip_file)) - self._current_backup_zip_file = backup_zip_file - - def _onUploadFinished(self, job: "UploadBackupJob") -> None: + def _onUploadFinished(self, job: "CreateBackupJob") -> None: if job.backup_upload_error_message != "": # If the job contains an error message we pass it along so the UI can display it. self.creatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_message) @@ -167,46 +155,3 @@ class DriveApiService: def _onDeleteRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, callable = None): callable(HttpRequestManager.replyIndicatesSuccess(reply, error)) - - def _requestBackupUpload(self, backup_metadata: Dict[str, Any], backup_size: int) -> None: - """Request a backup upload slot from the API. - - :param backup_metadata: A dict containing some meta data about the backup. - :param backup_size: The size of the backup file in bytes. - :return: The upload URL for the actual backup file if successful, otherwise None. - """ - - payload = json.dumps({"data": {"backup_size": backup_size, - "metadata": backup_metadata - } - }).encode() - - HttpRequestManager.getInstance().put( - self.BACKUP_URL, - data = payload, - callback = self._onBackupUploadSlotCompleted, - error_callback = self._onBackupUploadSlotCompleted, - scope = self._jsonCloudScope) - - def _onBackupUploadSlotCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: - if error is not None: - Logger.warning(str(error)) - self.creatingStateChanged.emit(is_creating=False, error_message="Could not upload backup.") - return - if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) >= 300: - Logger.warning("Could not request backup upload: %s", HttpRequestManager.readText(reply)) - self.creatingStateChanged.emit(is_creating=False, error_message="Could not upload backup.") - return - - backup_upload_url = HttpRequestManager.readJSON(reply)["data"]["upload_url"] - - # Upload the backup to storage. - upload_backup_job = UploadBackupJob(backup_upload_url, self._current_backup_zip_file) - upload_backup_job.finished.connect(self._onUploadFinished) - upload_backup_job.start() - - def _creatingStateChanged(self, is_creating: bool = False, error_message: str = None) -> None: - """Cleanup after a backup is not needed anymore""" - - if not is_creating: - self._current_backup_zip_file = None diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py deleted file mode 100644 index 8ade697cb3..0000000000 --- a/plugins/CuraDrive/src/UploadBackupJob.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -import requests - -from UM.Job import Job -from UM.Logger import Logger -from UM.Message import Message - -from UM.i18n import i18nCatalog -catalog = i18nCatalog("cura") - - -class UploadBackupJob(Job): - MESSAGE_TITLE = catalog.i18nc("@info:title", "Backups") - - # This job is responsible for uploading the backup file to cloud storage. - # As it can take longer than some other tasks, we schedule this using a Cura Job. - def __init__(self, signed_upload_url: str, backup_zip: bytes) -> None: - super().__init__() - self._signed_upload_url = signed_upload_url - self._backup_zip = backup_zip - self._upload_success = False - self.backup_upload_error_message = "" - - def run(self) -> None: - upload_message = Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE, progress = -1) - upload_message.show() - - backup_upload = requests.put(self._signed_upload_url, data = self._backup_zip) - upload_message.hide() - - if backup_upload.status_code >= 300: - self.backup_upload_error_message = backup_upload.text - Logger.log("w", "Could not upload backup file: %s", backup_upload.text) - Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), title = self.MESSAGE_TITLE).show() - else: - self._upload_success = True - Message(catalog.i18nc("@info:backup_status", "Your backup has finished uploading."), title = self.MESSAGE_TITLE).show() From ebfad16508afd8452fb56e02df0c60bd909dbbb9 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 10 Mar 2020 14:21:52 +0100 Subject: [PATCH 42/78] Refactor the restore backup implementation to RestoreBackupJob --- plugins/CuraDrive/src/CreateBackupJob.py | 12 ++- plugins/CuraDrive/src/DriveApiService.py | 68 +++-------------- plugins/CuraDrive/src/RestoreBackupJob.py | 89 +++++++++++++++++++++++ 3 files changed, 106 insertions(+), 63 deletions(-) create mode 100644 plugins/CuraDrive/src/RestoreBackupJob.py diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index 603733137b..4a5764a3b6 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -36,10 +36,8 @@ class CreateBackupJob(Job): self._api_backup_url = api_backup_url self._jsonCloudScope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) - self._backup_zip = None - self._upload_success = False - self._upload_success_available = threading.Event() + self._job_done = threading.Event() self.backup_upload_error_message = "" def run(self) -> None: @@ -62,7 +60,7 @@ class CreateBackupJob(Job): backup_meta_data["description"] = "{}.backup.{}.cura.zip".format(timestamp, backup_meta_data["cura_release"]) self._requestUploadSlot(backup_meta_data, len(self._backup_zip)) - self._upload_success_available.wait() + self._job_done.wait() upload_message.hide() def _requestUploadSlot(self, backup_metadata: Dict[str, Any], backup_size: int) -> None: @@ -89,12 +87,12 @@ class CreateBackupJob(Job): if error is not None: Logger.warning(str(error)) self.backup_upload_error_message = "Could not upload backup." - self._upload_success_available.set() + self._job_done.set() return if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) >= 300: Logger.warning("Could not request backup upload: %s", HttpRequestManager.readText(reply)) self.backup_upload_error_message = "Could not upload backup." - self._upload_success_available.set() + self._job_done.set() return backup_upload_url = HttpRequestManager.readJSON(reply)["data"]["upload_url"] @@ -119,4 +117,4 @@ class CreateBackupJob(Job): Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), title=self.MESSAGE_TITLE).show() - self._upload_success_available.set() + self._job_done.set() diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 04f935268b..3af461126a 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -11,6 +11,7 @@ from UM.Signal import Signal, signalemitter from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication +from plugins.CuraDrive.src.RestoreBackupJob import RestoreBackupJob from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest @@ -27,7 +28,6 @@ class DriveApiService: """The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling.""" BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) - DISK_WRITE_BUFFER_SIZE = 512 * 1024 restoringStateChanged = Signal() """Emits signal when restoring backup started or finished.""" @@ -82,61 +82,16 @@ class DriveApiService: # If there is no download URL, we can't restore the backup. return self._emitRestoreError() - def finishedCallback(reply: QNetworkReply, bu=backup) -> None: - self._onRestoreRequestCompleted(reply, None, bu) + restore_backup_job = RestoreBackupJob(backup) + restore_backup_job.finished.connect(self._onRestoreFinished) + restore_backup_job.start() - HttpRequestManager.getInstance().get( - url = download_url, - callback = finishedCallback, - error_callback = self._onRestoreRequestCompleted - ) - - def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, backup = None): - if not HttpRequestManager.replyIndicatesSuccess(reply, error): - Logger.log("w", - "Requesting backup failed, response code %s while trying to connect to %s", - reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url()) - self._emitRestoreError() - return - - # We store the file in a temporary path fist to ensure integrity. - temporary_backup_file = NamedTemporaryFile(delete = False) - with open(temporary_backup_file.name, "wb") as write_backup: - app = CuraApplication.getInstance() - bytes_read = reply.read(DriveApiService.DISK_WRITE_BUFFER_SIZE) - while bytes_read: - write_backup.write(bytes_read) - bytes_read = reply.read(DriveApiService.DISK_WRITE_BUFFER_SIZE) - app.processEvents() - - if not self._verifyMd5Hash(temporary_backup_file.name, backup.get("md5_hash", "")): - # Don't restore the backup if the MD5 hashes do not match. - # This can happen if the download was interrupted. - Logger.log("w", "Remote and local MD5 hashes do not match, not restoring backup.") - return self._emitRestoreError() - - # Tell Cura to place the backup back in the user data folder. - with open(temporary_backup_file.name, "rb") as read_backup: - self._cura_api.backups.restoreBackup(read_backup.read(), backup.get("metadata", {})) - self.restoringStateChanged.emit(is_restoring = False) - - def _emitRestoreError(self) -> None: - self.restoringStateChanged.emit(is_restoring = False, - error_message = catalog.i18nc("@info:backup_status", - "There was an error trying to restore your backup.")) - - @staticmethod - def _verifyMd5Hash(file_path: str, known_hash: str) -> bool: - """Verify the MD5 hash of a file. - - :param file_path: Full path to the file. - :param known_hash: The known MD5 hash of the file. - :return: Success or not. - """ - - with open(file_path, "rb") as read_backup: - local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8") - return known_hash == local_md5_hash + def _onRestoreFinished(self, job: "RestoreBackupJob"): + if job.restore_backup_error_message != "": + # If the job contains an error message we pass it along so the UI can display it. + self.restoringStateChanged.emit(is_restoring=False) + else: + self.restoringStateChanged.emit(is_restoring = False, error_message = job.restore_backup_error_message) def deleteBackup(self, backup_id: str, finishedCallable: Callable[[bool], None]): @@ -153,5 +108,6 @@ class DriveApiService: scope= self._jsonCloudScope ) - def _onDeleteRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, callable = None): + @staticmethod + def _onDeleteRequestCompleted(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, callable = None): callable(HttpRequestManager.replyIndicatesSuccess(reply, error)) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py new file mode 100644 index 0000000000..86e32aca97 --- /dev/null +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -0,0 +1,89 @@ +import base64 +import hashlib +import threading +from tempfile import NamedTemporaryFile +from typing import Optional, Any, Dict + +from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest + +from UM.Job import Job +from UM.Logger import Logger +from UM.PackageManager import catalog +from UM.TaskManagement.HttpRequestManager import HttpRequestManager +from cura.CuraApplication import CuraApplication + + +class RestoreBackupJob(Job): + """Downloads a backup and overwrites local configuration with the backup. + + When `Job.finished` emits, `restore_backup_error_message` will either be `""` (no error) or an error message + """ + + DISK_WRITE_BUFFER_SIZE = 512 * 1024 + DEFAULT_ERROR_MESSAGE = catalog.i18nc("@info:backup_status", "There was an error trying to restore your backup.") + + def __init__(self, backup: Dict[str, Any]) -> None: + """ Create a new restore Job. start the job by calling start() + + :param backup: A dict containing a backup spec + """ + + super().__init__() + self._job_done = threading.Event() + + self._backup = backup + self.restore_backup_error_message = "" + + def run(self): + + HttpRequestManager.getInstance().get( + url = self._backup.get("download_url"), + callback = self._onRestoreRequestCompleted, + error_callback = self._onRestoreRequestCompleted + ) + + self._job_done.wait() + + def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): + if not HttpRequestManager.replyIndicatesSuccess(reply, error): + Logger.warning("Requesting backup failed, response code %s while trying to connect to %s", + reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url()) + self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE + self._job_done.set() + return + + # We store the file in a temporary path fist to ensure integrity. + temporary_backup_file = NamedTemporaryFile(delete = False) + with open(temporary_backup_file.name, "wb") as write_backup: + app = CuraApplication.getInstance() + bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) + while bytes_read: + write_backup.write(bytes_read) + bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE) + app.processEvents() + + if not self._verifyMd5Hash(temporary_backup_file.name, self._backup.get("md5_hash", "")): + # Don't restore the backup if the MD5 hashes do not match. + # This can happen if the download was interrupted. + Logger.log("w", "Remote and local MD5 hashes do not match, not restoring backup.") + self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE + + # Tell Cura to place the backup back in the user data folder. + with open(temporary_backup_file.name, "rb") as read_backup: + cura_api = CuraApplication.getInstance().getCuraAPI() + cura_api.backups.restoreBackup(read_backup.read(), self._backup.get("metadata", {})) + + self._job_done.set() + + @staticmethod + def _verifyMd5Hash(file_path: str, known_hash: str) -> bool: + """Verify the MD5 hash of a file. + + :param file_path: Full path to the file. + :param known_hash: The known MD5 hash of the file. + :return: Success or not. + """ + + with open(file_path, "rb") as read_backup: + local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8") + return known_hash == local_md5_hash From d11b3b0921edb708e7ce48d647dc8f35a1f385fc Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 10 Mar 2020 14:23:40 +0100 Subject: [PATCH 43/78] Extra comment for RestoreBackupJob --- plugins/CuraDrive/src/RestoreBackupJob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index 86e32aca97..08f9d73e1e 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -42,7 +42,7 @@ class RestoreBackupJob(Job): error_callback = self._onRestoreRequestCompleted ) - self._job_done.wait() + self._job_done.wait() # A job is considered finished when the run function completes def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): if not HttpRequestManager.replyIndicatesSuccess(reply, error): From e1cefc4edf19de3457fd1b938f083a4ed10dc923 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 12 Mar 2020 11:16:52 +0530 Subject: [PATCH 44/78] Update fabxpro_abs_draft.inst.cfg --- .../quality/fabxpro/fabxpro_abs_draft.inst.cfg | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg index 4c9122cffd..46b95f4e72 100644 --- a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg @@ -13,12 +13,24 @@ global_quality = True [values] layer_height = 0.3 layer_height_0 = 0.35 +initial_layer_line_width_factor = 150 +infill_before_walls = False speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = True adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 material_print_temperature = 240 material_bed_temperature = 110 cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 From e7fd4d031645509462c9bf919eaaa6c53679f46a Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 12 Mar 2020 11:17:21 +0530 Subject: [PATCH 45/78] Update fabxpro_abs_fine.inst.cfg --- .../quality/fabxpro/fabxpro_abs_fine.inst.cfg | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg index 8b6a8c4dc2..a3eabfb136 100644 --- a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg @@ -13,12 +13,24 @@ global_quality = True [values] layer_height = 0.1 layer_height_0 = 0.15 +initial_layer_line_width_factor = 150 +infill_before_walls = False speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = True adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 material_print_temperature = 240 material_bed_temperature = 110 cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 From d7fa66f1386c573f603ff75dff70bd168724cebf Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 12 Mar 2020 11:17:47 +0530 Subject: [PATCH 46/78] Update fabxpro_abs_normal.inst.cfg --- .../quality/fabxpro/fabxpro_abs_normal.inst.cfg | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg index f478ddf8a7..ac7a32a370 100644 --- a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg @@ -13,12 +13,24 @@ global_quality = True [values] layer_height = 0.2 layer_height_0 = 0.3 +initial_layer_line_width_factor = 150 +infill_before_walls = False speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = True adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 material_print_temperature = 240 material_bed_temperature = 110 cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 From d0d2fe166970e341ce31187754e4e097abd70d5e Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 12 Mar 2020 11:18:45 +0530 Subject: [PATCH 47/78] Update fabxpro_pla_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg index fa6a79ed6b..bf6feb92e0 100644 --- a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg @@ -13,14 +13,20 @@ global_quality = True [values] layer_height = 0.3 layer_height_0 = 0.35 +initial_layer_line_width_factor = 150 +infill_before_walls = False speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = True adhesion_type = skirt material_print_temperature = 215 material_bed_temperature = 60 -cool_fan_enabled = True +cool_fan_enabled = true cool_fan_speed = 100 cool_fan_full_at_height = 0.6 +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 From e4890e9dbf974f3fe378d1d93eda027b74119641 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 12 Mar 2020 11:19:12 +0530 Subject: [PATCH 48/78] Update fabxpro_pla_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg index fb01e0778d..898c1eee23 100644 --- a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg @@ -13,14 +13,20 @@ global_quality = True [values] layer_height = 0.1 layer_height_0 = 0.15 +initial_layer_line_width_factor = 150 +infill_before_walls = False speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = True adhesion_type = skirt material_print_temperature = 215 material_bed_temperature = 60 -cool_fan_enabled = True +cool_fan_enabled = true cool_fan_speed = 100 cool_fan_full_at_height = 0.6 +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 From c40048bb1d48edfeee232c5b8c2914c5da601b5f Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Thu, 12 Mar 2020 11:19:46 +0530 Subject: [PATCH 49/78] Update fabxpro_pla_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg index fd26ea4d2f..b3a6a49927 100644 --- a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg @@ -13,14 +13,20 @@ global_quality = True [values] layer_height = 0.2 layer_height_0 = 0.3 +initial_layer_line_width_factor = 150 +infill_before_walls = False speed_print = 55 speed_travel = 70 retraction_amount = 1 retraction_speed = 40 -support_enable = True adhesion_type = skirt material_print_temperature = 215 material_bed_temperature = 60 -cool_fan_enabled = True +cool_fan_enabled = true cool_fan_speed = 100 cool_fan_full_at_height = 0.6 +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 From 61af28c681982682ea3905be4798f38ca5c949ba Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Thu, 12 Mar 2020 13:57:09 +0100 Subject: [PATCH 50/78] Process review comments. CURA-7150 --- plugins/Toolbox/src/UltimakerCloudScope.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/Toolbox/src/UltimakerCloudScope.py b/plugins/Toolbox/src/UltimakerCloudScope.py index 257e97b1af..0e9adaf2e7 100644 --- a/plugins/Toolbox/src/UltimakerCloudScope.py +++ b/plugins/Toolbox/src/UltimakerCloudScope.py @@ -18,8 +18,8 @@ class UltimakerCloudScope(DefaultUserAgentScope): api = application.getCuraAPI() self._account = api.account # type: Account - def request_hook(self, request: QNetworkRequest): - super().request_hook(request) + def requestHook(self, request: QNetworkRequest): + super().requestHook(request) token = self._account.accessToken if not self._account.isLoggedIn or token is None: Logger.warning("Cannot add authorization to Cloud Api request") @@ -28,4 +28,4 @@ class UltimakerCloudScope(DefaultUserAgentScope): header_dict = { "Authorization": "Bearer {}".format(token) } - self.add_headers(request, header_dict) + self.addHeaders(request, header_dict) From 6dd8ebb06a41839793754acd438cbbdda1d3ef78 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Thu, 12 Mar 2020 17:06:33 +0100 Subject: [PATCH 51/78] Process review comments in Cura project CURA-7150 --- plugins/CuraDrive/src/CreateBackupJob.py | 40 +++++++++++------------ plugins/CuraDrive/src/DriveApiService.py | 20 ++++++------ plugins/CuraDrive/src/RestoreBackupJob.py | 4 +-- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index 4a5764a3b6..8e9bd9ad4c 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -1,18 +1,17 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2020 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import json import threading +from datetime import datetime from typing import Any, Dict, Optional from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest -from datetime import datetime from UM.Job import Job from UM.Logger import Logger from UM.Message import Message from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope - from UM.i18n import i18nCatalog from cura.CuraApplication import CuraApplication from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope @@ -24,6 +23,7 @@ class CreateBackupJob(Job): """Creates backup zip, requests upload url and uploads the backup file to cloud storage.""" MESSAGE_TITLE = catalog.i18nc("@info:title", "Backups") + DEFAULT_UPLOAD_ERROR_MESSAGE = catalog.i18nc("@info:backup_status", "There was an error while uploading your backup.") def __init__(self, api_backup_url: str) -> None: """ Create a new backup Job. start the job by calling start() @@ -34,11 +34,13 @@ class CreateBackupJob(Job): super().__init__() self._api_backup_url = api_backup_url - self._jsonCloudScope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) + self._json_cloud_scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) - self._backup_zip = None + self._backup_zip = None # type: Optional[bytes] self._job_done = threading.Event() + """Set when the job completes. Does not indicate success.""" self.backup_upload_error_message = "" + """After the job completes, an empty string indicates success. Othrerwise, the value is a translated message.""" def run(self) -> None: upload_message = Message(catalog.i18nc("@info:backup_status", "Creating your backup..."), title = self.MESSAGE_TITLE, progress = -1) @@ -48,7 +50,7 @@ class CreateBackupJob(Job): self._backup_zip, backup_meta_data = cura_api.backups.createBackup() if not self._backup_zip or not backup_meta_data: - self.backup_upload_error_message = "Could not create backup." + self.backup_upload_error_message = catalog.i18nc("@info:backup_status", "There was an error while creating your backup.") upload_message.hide() return @@ -61,14 +63,17 @@ class CreateBackupJob(Job): self._requestUploadSlot(backup_meta_data, len(self._backup_zip)) self._job_done.wait() - upload_message.hide() + if self.backup_upload_error_message == "": + upload_message.setText(catalog.i18nc("@info:backup_status", "Your backup has finished uploading.")) + else: + # some error occurred. This error is presented to the user by DrivePluginExtension + upload_message.hide() def _requestUploadSlot(self, backup_metadata: Dict[str, Any], backup_size: int) -> None: """Request a backup upload slot from the API. :param backup_metadata: A dict containing some meta data about the backup. :param backup_size: The size of the backup file in bytes. - :return: The upload URL for the actual backup file if successful, otherwise None. """ payload = json.dumps({"data": {"backup_size": backup_size, @@ -81,17 +86,17 @@ class CreateBackupJob(Job): data = payload, callback = self._onUploadSlotCompleted, error_callback = self._onUploadSlotCompleted, - scope = self._jsonCloudScope) + scope = self._json_cloud_scope) def _onUploadSlotCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: if error is not None: Logger.warning(str(error)) - self.backup_upload_error_message = "Could not upload backup." + self.backup_upload_error_message = self.DEFAULT_UPLOAD_ERROR_MESSAGE self._job_done.set() return if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) >= 300: Logger.warning("Could not request backup upload: %s", HttpRequestManager.readText(reply)) - self.backup_upload_error_message = "Could not upload backup." + self.backup_upload_error_message = self.DEFAULT_UPLOAD_ERROR_MESSAGE self._job_done.set() return @@ -106,15 +111,8 @@ class CreateBackupJob(Job): ) def _uploadFinishedCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError = None): - self.backup_upload_error_text = HttpRequestManager.readText(reply) - - if HttpRequestManager.replyIndicatesSuccess(reply, error): - self._upload_success = True - Message(catalog.i18nc("@info:backup_status", "Your backup has finished uploading."), title = self.MESSAGE_TITLE).show() - else: - self.backup_upload_error_text = self.backup_upload_error_text - Logger.log("w", "Could not upload backup file: %s", self.backup_upload_error_text) - Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), - title=self.MESSAGE_TITLE).show() + if not HttpRequestManager.replyIndicatesSuccess(reply, error): + Logger.log("w", "Could not upload backup file: %s", HttpRequestManager.readText(reply)) + self.backup_upload_error_message = self.DEFAULT_UPLOAD_ERROR_MESSAGE self._job_done.set() diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 3af461126a..0fe89447e6 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -1,25 +1,21 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -import base64 -import hashlib -from tempfile import NamedTemporaryFile from typing import Any, Optional, List, Dict, Callable +from PyQt5.QtNetwork import QNetworkReply + from UM.Logger import Logger from UM.Signal import Signal, signalemitter from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope +from UM.i18n import i18nCatalog from cura.CuraApplication import CuraApplication from plugins.CuraDrive.src.RestoreBackupJob import RestoreBackupJob from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope - -from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest - from .CreateBackupJob import CreateBackupJob from .Settings import Settings -from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -39,8 +35,8 @@ class DriveApiService: self._cura_api = CuraApplication.getInstance().getCuraAPI() self._jsonCloudScope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) - def getBackups(self, changed: Callable[[List], None]): - def callback(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): + def getBackups(self, changed: Callable[[List[Dict[str, Any]]], None]) -> None: + def callback(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: if error is not None: Logger.log("w", "Could not get backups: " + str(error)) changed([]) @@ -80,7 +76,11 @@ class DriveApiService: download_url = backup.get("download_url") if not download_url: # If there is no download URL, we can't restore the backup. - return self._emitRestoreError() + Logger.warning("backup download_url is missing. Aborting backup.") + self.restoringStateChanged.emit(is_restoring = False, + error_message = catalog.i18nc("@info:backup_status", + "There was an error trying to restore your backup.")) + return restore_backup_job = RestoreBackupJob(backup) restore_backup_job.finished.connect(self._onRestoreFinished) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index 08f9d73e1e..e26e55fd37 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -34,7 +34,7 @@ class RestoreBackupJob(Job): self._backup = backup self.restore_backup_error_message = "" - def run(self): + def run(self) -> None: HttpRequestManager.getInstance().get( url = self._backup.get("download_url"), @@ -44,7 +44,7 @@ class RestoreBackupJob(Job): self._job_done.wait() # A job is considered finished when the run function completes - def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None): + def _onRestoreRequestCompleted(self, reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: if not HttpRequestManager.replyIndicatesSuccess(reply, error): Logger.warning("Requesting backup failed, response code %s while trying to connect to %s", reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url()) From 2e7b47f1ea8f6a7efb46266722d9c50e1c47150a Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Thu, 12 Mar 2020 17:21:03 +0100 Subject: [PATCH 52/78] Add None-check for download url CURA-7150 --- plugins/CuraDrive/src/RestoreBackupJob.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index e26e55fd37..33ca115c06 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -36,8 +36,11 @@ class RestoreBackupJob(Job): def run(self) -> None: + url = self._backup.get("download_url") + assert url is not None + HttpRequestManager.getInstance().get( - url = self._backup.get("download_url"), + url =url, callback = self._onRestoreRequestCompleted, error_callback = self._onRestoreRequestCompleted ) From 96ed85f9c0c193deeb5637a4d9dd6d36053fa1f0 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Thu, 12 Mar 2020 17:48:54 +0100 Subject: [PATCH 53/78] Move UltimakerCloudAuthentication and UltimakerCloudScope ...to their own module Fixes an import error where UltimakerCloudScope was used my both the Toolbox and CuraDrive plugins CURA-7150 --- cura/API/Account.py | 5 +- cura/CuraApplication.py | 85 +++++++------------ .../UltimakerCloudAuthentication.py | 0 .../UltimakerCloud}/UltimakerCloudScope.py | 0 cura/UltimakerCloud/__init__.py | 0 plugins/CuraDrive/src/CreateBackupJob.py | 2 +- plugins/CuraDrive/src/DriveApiService.py | 4 +- plugins/CuraDrive/src/RestoreBackupJob.py | 2 +- plugins/CuraDrive/src/Settings.py | 2 +- plugins/Toolbox/src/CloudApiModel.py | 3 +- .../Toolbox/src/CloudSync/CloudApiClient.py | 2 +- .../src/CloudSync/CloudPackageChecker.py | 7 +- .../src/CloudSync/DownloadPresenter.py | 2 +- plugins/Toolbox/src/Toolbox.py | 11 +-- .../src/Cloud/CloudApiClient.py | 8 +- 15 files changed, 53 insertions(+), 80 deletions(-) rename cura/{ => UltimakerCloud}/UltimakerCloudAuthentication.py (100%) rename {plugins/Toolbox/src => cura/UltimakerCloud}/UltimakerCloudScope.py (100%) create mode 100644 cura/UltimakerCloud/__init__.py diff --git a/cura/API/Account.py b/cura/API/Account.py index 0e3af0e6c1..4391f730e5 100644 --- a/cura/API/Account.py +++ b/cura/API/Account.py @@ -4,12 +4,11 @@ from typing import Optional, Dict, TYPE_CHECKING from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty -from UM.i18n import i18nCatalog from UM.Message import Message -from cura import UltimakerCloudAuthentication - +from UM.i18n import i18nCatalog from cura.OAuth2.AuthorizationService import AuthorizationService from cura.OAuth2.Models import OAuth2Settings +from cura.UltimakerCloud import UltimakerCloudAuthentication if TYPE_CHECKING: from cura.CuraApplication import CuraApplication diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 7b17583f68..e58e03bf67 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -7,71 +7,52 @@ import time from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any import numpy - from PyQt5.QtCore import QObject, QTimer, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS from PyQt5.QtGui import QColor, QIcon -from PyQt5.QtWidgets import QMessageBox from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType +from PyQt5.QtWidgets import QMessageBox -from UM.i18n import i18nCatalog +import UM.Util +import cura.Settings.cura_empty_instance_containers from UM.Application import Application from UM.Decorators import override from UM.FlameProfiler import pyqtSlot from UM.Logger import Logger -from UM.Message import Message -from UM.Platform import Platform -from UM.PluginError import PluginNotFoundError -from UM.Resources import Resources -from UM.Preferences import Preferences -from UM.Qt.QtApplication import QtApplication # The class we're inheriting from. -import UM.Util -from UM.View.SelectionPass import SelectionPass # For typing. - from UM.Math.AxisAlignedBox import AxisAlignedBox from UM.Math.Matrix import Matrix from UM.Math.Quaternion import Quaternion from UM.Math.Vector import Vector - from UM.Mesh.ReadMeshJob import ReadMeshJob - +from UM.Message import Message from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation from UM.Operations.GroupedOperation import GroupedOperation from UM.Operations.SetTransformOperation import SetTransformOperation - +from UM.Platform import Platform +from UM.PluginError import PluginNotFoundError +from UM.Preferences import Preferences +from UM.Qt.QtApplication import QtApplication # The class we're inheriting from. +from UM.Resources import Resources from UM.Scene.Camera import Camera from UM.Scene.GroupDecorator import GroupDecorator from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection from UM.Scene.ToolHandle import ToolHandle - from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType from UM.Settings.SettingFunction import SettingFunction from UM.Settings.Validator import Validator - +from UM.View.SelectionPass import SelectionPass # For typing. from UM.Workspace.WorkspaceReader import WorkspaceReader - +from UM.i18n import i18nCatalog +from cura import ApplicationMetadata from cura.API import CuraAPI - from cura.Arranging.Arrange import Arrange -from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob +from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob from cura.Arranging.ShapeArray import ShapeArray - -from cura.Operations.SetParentOperation import SetParentOperation - -from cura.Scene.BlockSlicingDecorator import BlockSlicingDecorator -from cura.Scene.BuildPlateDecorator import BuildPlateDecorator -from cura.Scene.ConvexHullDecorator import ConvexHullDecorator -from cura.Scene.CuraSceneController import CuraSceneController -from cura.Scene.CuraSceneNode import CuraSceneNode - -from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator -from cura.Scene import ZOffsetDecorator from cura.Machines.MachineErrorChecker import MachineErrorChecker - from cura.Machines.Models.BuildPlateModel import BuildPlateModel from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel from cura.Machines.Models.DiscoveredPrintersModel import DiscoveredPrintersModel @@ -80,6 +61,8 @@ from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel from cura.Machines.Models.FirstStartMachineActionsModel import FirstStartMachineActionsModel from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel from cura.Machines.Models.GlobalStacksModel import GlobalStacksModel +from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel +from cura.Machines.Models.IntentModel import IntentModel from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel @@ -89,51 +72,47 @@ from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfile from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel from cura.Machines.Models.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel from cura.Machines.Models.UserChangesModel import UserChangesModel -from cura.Machines.Models.IntentModel import IntentModel -from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel - -from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice +from cura.Operations.SetParentOperation import SetParentOperation from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage - -import cura.Settings.cura_empty_instance_containers +from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice +from cura.Scene import ZOffsetDecorator +from cura.Scene.BlockSlicingDecorator import BlockSlicingDecorator +from cura.Scene.BuildPlateDecorator import BuildPlateDecorator +from cura.Scene.ConvexHullDecorator import ConvexHullDecorator +from cura.Scene.CuraSceneController import CuraSceneController +from cura.Scene.CuraSceneNode import CuraSceneNode +from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator from cura.Settings.ContainerManager import ContainerManager from cura.Settings.CuraContainerRegistry import CuraContainerRegistry from cura.Settings.CuraFormulaFunctions import CuraFormulaFunctions from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderStack import ExtruderStack +from cura.Settings.GlobalStack import GlobalStack +from cura.Settings.IntentManager import IntentManager from cura.Settings.MachineManager import MachineManager from cura.Settings.MachineNameValidator import MachineNameValidator -from cura.Settings.IntentManager import IntentManager from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager - from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager - from cura.UI import CuraSplashScreen, MachineActionManager, PrintInformation +from cura.UI.AddPrinterPagesModel import AddPrinterPagesModel from cura.UI.MachineSettingsManager import MachineSettingsManager from cura.UI.ObjectsModel import ObjectsModel -from cura.UI.TextManager import TextManager -from cura.UI.AddPrinterPagesModel import AddPrinterPagesModel from cura.UI.RecommendedMode import RecommendedMode +from cura.UI.TextManager import TextManager from cura.UI.WelcomePagesModel import WelcomePagesModel from cura.UI.WhatsNewPagesModel import WhatsNewPagesModel - +from cura.UltimakerCloud import UltimakerCloudAuthentication from cura.Utils.NetworkingUtil import NetworkingUtil - -from .SingleInstance import SingleInstance -from .AutoSave import AutoSave -from . import PlatformPhysics from . import BuildVolume from . import CameraAnimation from . import CuraActions +from . import PlatformPhysics from . import PrintJobPreviewImageProvider - -from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager - -from cura import ApplicationMetadata, UltimakerCloudAuthentication -from cura.Settings.GlobalStack import GlobalStack +from .AutoSave import AutoSave +from .SingleInstance import SingleInstance if TYPE_CHECKING: from UM.Settings.EmptyInstanceContainer import EmptyInstanceContainer diff --git a/cura/UltimakerCloudAuthentication.py b/cura/UltimakerCloud/UltimakerCloudAuthentication.py similarity index 100% rename from cura/UltimakerCloudAuthentication.py rename to cura/UltimakerCloud/UltimakerCloudAuthentication.py diff --git a/plugins/Toolbox/src/UltimakerCloudScope.py b/cura/UltimakerCloud/UltimakerCloudScope.py similarity index 100% rename from plugins/Toolbox/src/UltimakerCloudScope.py rename to cura/UltimakerCloud/UltimakerCloudScope.py diff --git a/cura/UltimakerCloud/__init__.py b/cura/UltimakerCloud/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index 8e9bd9ad4c..f5f557d003 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -14,7 +14,7 @@ from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from UM.i18n import i18nCatalog from cura.CuraApplication import CuraApplication -from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope +from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope catalog = i18nCatalog("cura") diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 0fe89447e6..fa010d915d 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -11,9 +11,9 @@ from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from UM.i18n import i18nCatalog from cura.CuraApplication import CuraApplication -from plugins.CuraDrive.src.RestoreBackupJob import RestoreBackupJob -from plugins.Toolbox.src.UltimakerCloudScope import UltimakerCloudScope +from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope from .CreateBackupJob import CreateBackupJob +from .RestoreBackupJob import RestoreBackupJob from .Settings import Settings catalog = i18nCatalog("cura") diff --git a/plugins/CuraDrive/src/RestoreBackupJob.py b/plugins/CuraDrive/src/RestoreBackupJob.py index 33ca115c06..c60de116e0 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -40,7 +40,7 @@ class RestoreBackupJob(Job): assert url is not None HttpRequestManager.getInstance().get( - url =url, + url = url, callback = self._onRestoreRequestCompleted, error_callback = self._onRestoreRequestCompleted ) diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py index abe64e0acd..639c63b45f 100644 --- a/plugins/CuraDrive/src/Settings.py +++ b/plugins/CuraDrive/src/Settings.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from cura import UltimakerCloudAuthentication +from cura.UltimakerCloud import UltimakerCloudAuthentication class Settings: diff --git a/plugins/Toolbox/src/CloudApiModel.py b/plugins/Toolbox/src/CloudApiModel.py index 556d54cf88..3386cffb51 100644 --- a/plugins/Toolbox/src/CloudApiModel.py +++ b/plugins/Toolbox/src/CloudApiModel.py @@ -1,6 +1,7 @@ from typing import Union -from cura import ApplicationMetadata, UltimakerCloudAuthentication +from cura import ApplicationMetadata +from cura.UltimakerCloud import UltimakerCloudAuthentication class CloudApiModel: diff --git a/plugins/Toolbox/src/CloudSync/CloudApiClient.py b/plugins/Toolbox/src/CloudSync/CloudApiClient.py index ba1cbab624..21eb1bdbd2 100644 --- a/plugins/Toolbox/src/CloudSync/CloudApiClient.py +++ b/plugins/Toolbox/src/CloudSync/CloudApiClient.py @@ -2,8 +2,8 @@ from UM.Logger import Logger from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication +from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope from ..CloudApiModel import CloudApiModel -from ..UltimakerCloudScope import UltimakerCloudScope class CloudApiClient: diff --git a/plugins/Toolbox/src/CloudSync/CloudPackageChecker.py b/plugins/Toolbox/src/CloudSync/CloudPackageChecker.py index 7404489aee..76c9c092c5 100644 --- a/plugins/Toolbox/src/CloudSync/CloudPackageChecker.py +++ b/plugins/Toolbox/src/CloudSync/CloudPackageChecker.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. import json +from typing import List, Dict, Any from typing import Optional from PyQt5.QtCore import QObject @@ -13,11 +14,9 @@ from UM.Message import Message from UM.Signal import Signal from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication, ApplicationMetadata -from ..CloudApiModel import CloudApiModel +from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope from .SubscribedPackagesModel import SubscribedPackagesModel -from ..UltimakerCloudScope import UltimakerCloudScope - -from typing import List, Dict, Any +from ..CloudApiModel import CloudApiModel class CloudPackageChecker(QObject): diff --git a/plugins/Toolbox/src/CloudSync/DownloadPresenter.py b/plugins/Toolbox/src/CloudSync/DownloadPresenter.py index 06004df5da..a16ed67218 100644 --- a/plugins/Toolbox/src/CloudSync/DownloadPresenter.py +++ b/plugins/Toolbox/src/CloudSync/DownloadPresenter.py @@ -13,8 +13,8 @@ from UM.Signal import Signal from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication +from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope from .SubscribedPackagesModel import SubscribedPackagesModel -from ..UltimakerCloudScope import UltimakerCloudScope ## Downloads a set of packages from the Ultimaker Cloud Marketplace diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 9057538835..ec1da6707a 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -9,23 +9,20 @@ from typing import cast, Any, Dict, List, Set, TYPE_CHECKING, Tuple, Optional, U from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply +from UM.Extension import Extension from UM.Logger import Logger from UM.PluginRegistry import PluginRegistry -from UM.Extension import Extension from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope -from UM.i18n import i18nCatalog from UM.Version import Version - +from UM.i18n import i18nCatalog from cura import ApplicationMetadata - from cura.CuraApplication import CuraApplication from cura.Machines.ContainerTree import ContainerTree - -from .CloudApiModel import CloudApiModel +from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope from .AuthorsModel import AuthorsModel +from .CloudApiModel import CloudApiModel from .CloudSync.LicenseModel import LicenseModel from .PackagesModel import PackagesModel -from .UltimakerCloudScope import UltimakerCloudScope if TYPE_CHECKING: from UM.TaskManagement.HttpRequestData import HttpRequestData diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py index ed8d22a478..6fec436843 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py @@ -9,18 +9,16 @@ from PyQt5.QtCore import QUrl from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager from UM.Logger import Logger -from cura import UltimakerCloudAuthentication from cura.API import Account - +from cura.UltimakerCloud import UltimakerCloudAuthentication from .ToolPathUploader import ToolPathUploader from ..Models.BaseModel import BaseModel from ..Models.Http.CloudClusterResponse import CloudClusterResponse -from ..Models.Http.CloudError import CloudError from ..Models.Http.CloudClusterStatus import CloudClusterStatus +from ..Models.Http.CloudError import CloudError +from ..Models.Http.CloudPrintJobResponse import CloudPrintJobResponse from ..Models.Http.CloudPrintJobUploadRequest import CloudPrintJobUploadRequest from ..Models.Http.CloudPrintResponse import CloudPrintResponse -from ..Models.Http.CloudPrintJobResponse import CloudPrintJobResponse - ## The generic type variable used to document the methods below. CloudApiClientModel = TypeVar("CloudApiClientModel", bound=BaseModel) From 4e8da5d7fd9585a5b7cd346206abd4a6749724cd Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 16 Mar 2020 17:20:59 +0100 Subject: [PATCH 54/78] Add missing typing CURA-7150 --- plugins/CuraDrive/src/DriveApiService.py | 14 +++++++------- plugins/CuraDrive/src/DrivePluginExtension.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index fa010d915d..367c6e61a5 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -86,20 +86,20 @@ class DriveApiService: restore_backup_job.finished.connect(self._onRestoreFinished) restore_backup_job.start() - def _onRestoreFinished(self, job: "RestoreBackupJob"): + def _onRestoreFinished(self, job: "RestoreBackupJob") -> None: if job.restore_backup_error_message != "": # If the job contains an error message we pass it along so the UI can display it. self.restoringStateChanged.emit(is_restoring=False) else: self.restoringStateChanged.emit(is_restoring = False, error_message = job.restore_backup_error_message) - def deleteBackup(self, backup_id: str, finishedCallable: Callable[[bool], None]): + def deleteBackup(self, backup_id: str, finished_callable: Callable[[bool], None]): - def finishedCallback(reply: QNetworkReply, ca=finishedCallable) -> None: - self._onDeleteRequestCompleted(reply, None, ca) + def finishedCallback(reply: QNetworkReply, ca: Callable[[bool], None] = finished_callable) -> None: + self._onDeleteRequestCompleted(reply, ca) - def errorCallback(reply: QNetworkReply, error: QNetworkReply.NetworkError, ca=finishedCallable) -> None: - self._onDeleteRequestCompleted(reply, error, ca) + def errorCallback(reply: QNetworkReply, error: QNetworkReply.NetworkError, ca: Callable[[bool], None] = finished_callable) -> None: + self._onDeleteRequestCompleted(reply, ca, error) HttpRequestManager.getInstance().delete( url = "{}/{}".format(self.BACKUP_URL, backup_id), @@ -109,5 +109,5 @@ class DriveApiService: ) @staticmethod - def _onDeleteRequestCompleted(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None, callable = None): + def _onDeleteRequestCompleted(reply: QNetworkReply, callable: Callable[[bool], None], error: Optional["QNetworkReply.NetworkError"] = None) -> None: callable(HttpRequestManager.replyIndicatesSuccess(reply, error)) diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index 34f30d8b3d..8de4876f52 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -135,7 +135,7 @@ class DrivePluginExtension(QObject, Extension): def refreshBackups(self) -> None: self._drive_api_service.getBackups(self._backupsChangedCallback) - def _backupsChangedCallback(self, backups): + def _backupsChangedCallback(self, backups: List[Dict[str, Any]]) -> None: self._backups = backups self.backupsChanged.emit() From 3bfc3dfbc9ed445409a605b59745bd5d1a1619ad Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 18 Mar 2020 12:29:39 +0530 Subject: [PATCH 55/78] Update fabxpro_abs_draft.inst.cfg Added filament brand --- resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg index 46b95f4e72..d42b536705 100644 --- a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg @@ -8,8 +8,10 @@ setting_version = 11 type = quality quality_type = Draft ABS weight = -2 +material = redd_abs global_quality = True + [values] layer_height = 0.3 layer_height_0 = 0.35 @@ -26,8 +28,6 @@ raft_surface_layers = 1 raft_surface_thickness = 0.1 raft_surface_line_spacing = 0.6 raft_base_thickness = 0.6 -material_print_temperature = 240 -material_bed_temperature = 110 cool_fan_enabled = False support_enable = True support_pattern = lines From ebc293707b5a589a7a9c42b12722174f7faf9191 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 18 Mar 2020 12:33:14 +0530 Subject: [PATCH 56/78] Update fabxpro_abs_fine.inst.cfg Added redd brand --- resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg index a3eabfb136..37a2c2b0b9 100644 --- a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Fine ABS weight = -2 +material = redd_abs global_quality = True [values] @@ -26,8 +27,6 @@ raft_surface_layers = 1 raft_surface_thickness = 0.1 raft_surface_line_spacing = 0.6 raft_base_thickness = 0.6 -material_print_temperature = 240 -material_bed_temperature = 110 cool_fan_enabled = False support_enable = True support_pattern = lines From ced64d6c3f0211b23ceedadaf03de11f5c58287e Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 18 Mar 2020 12:34:13 +0530 Subject: [PATCH 57/78] Update fabxpro_abs_normal.inst.cfg Added redd brand --- resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg index ac7a32a370..210bff9705 100644 --- a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Normal ABS weight = -2 +material = redd_abs global_quality = True [values] @@ -26,8 +27,6 @@ raft_surface_layers = 1 raft_surface_thickness = 0.1 raft_surface_line_spacing = 0.6 raft_base_thickness = 0.6 -material_print_temperature = 240 -material_bed_temperature = 110 cool_fan_enabled = False support_enable = True support_pattern = lines From b3ed7dd1f2b89b373888c0a4c9027150a0cd30f5 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 18 Mar 2020 12:35:47 +0530 Subject: [PATCH 58/78] Update fabxpro_pla_draft.inst.cfg Added redd brand --- resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg index bf6feb92e0..0244620e48 100644 --- a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Draft PLA weight = -2 +material = redd_pla global_quality = True [values] @@ -20,8 +21,6 @@ speed_travel = 70 retraction_amount = 1 retraction_speed = 40 adhesion_type = skirt -material_print_temperature = 215 -material_bed_temperature = 60 cool_fan_enabled = true cool_fan_speed = 100 cool_fan_full_at_height = 0.6 From f9bb949a8d7b4a11d8866897a0ca9b21242fc90f Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 18 Mar 2020 12:41:53 +0530 Subject: [PATCH 59/78] Update fabxpro_pla_fine.inst.cfg added redd brand --- resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg index 898c1eee23..fdf3ddf8fe 100644 --- a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Fine PLA weight = -2 +material = redd_pla global_quality = True [values] @@ -20,8 +21,6 @@ speed_travel = 70 retraction_amount = 1 retraction_speed = 40 adhesion_type = skirt -material_print_temperature = 215 -material_bed_temperature = 60 cool_fan_enabled = true cool_fan_speed = 100 cool_fan_full_at_height = 0.6 From a398c9c7009a885ccbe4c94a1c48114bdd935fed Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 18 Mar 2020 12:44:25 +0530 Subject: [PATCH 60/78] Update fabxpro_pla_normal.inst.cfg Added redd brand --- resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg index b3a6a49927..682b767ae6 100644 --- a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg @@ -8,6 +8,7 @@ setting_version = 11 type = quality quality_type = Normal PLA weight = -2 +material = redd_pla global_quality = True [values] @@ -20,8 +21,6 @@ speed_travel = 70 retraction_amount = 1 retraction_speed = 40 adhesion_type = skirt -material_print_temperature = 215 -material_bed_temperature = 60 cool_fan_enabled = true cool_fan_speed = 100 cool_fan_full_at_height = 0.6 From dc028c331740f1f2b7ce72b35afb9cbac5ba3295 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Wed, 18 Mar 2020 15:52:11 +0530 Subject: [PATCH 61/78] Add files via upload Adding quality files for additional materials --- .../fabxpro/fabxpro_asa_draft.inst.cfg | 36 +++++++++++++++++++ .../quality/fabxpro/fabxpro_asa_fine.inst.cfg | 36 +++++++++++++++++++ .../fabxpro/fabxpro_asa_normal.inst.cfg | 35 ++++++++++++++++++ .../fabxpro/fabxpro_hips_draft.inst.cfg | 36 +++++++++++++++++++ .../fabxpro/fabxpro_hips_fine.inst.cfg | 36 +++++++++++++++++++ .../fabxpro/fabxpro_hips_normal.inst.cfg | 35 ++++++++++++++++++ .../fabxpro/fabxpro_nylon_draft.inst.cfg | 36 +++++++++++++++++++ .../fabxpro/fabxpro_nylon_fine.inst.cfg | 36 +++++++++++++++++++ .../fabxpro/fabxpro_nylon_normal.inst.cfg | 35 ++++++++++++++++++ .../fabxpro/fabxpro_petg_draft.inst.cfg | 36 +++++++++++++++++++ .../fabxpro/fabxpro_petg_fine.inst.cfg | 36 +++++++++++++++++++ .../fabxpro/fabxpro_petg_normal.inst.cfg | 35 ++++++++++++++++++ .../fabxpro/fabxpro_tpe_draft.inst.cfg | 36 +++++++++++++++++++ .../quality/fabxpro/fabxpro_tpe_fine.inst.cfg | 36 +++++++++++++++++++ .../fabxpro/fabxpro_tpe_normal.inst.cfg | 35 ++++++++++++++++++ 15 files changed, 535 insertions(+) create mode 100644 resources/quality/fabxpro/fabxpro_asa_draft.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_asa_fine.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_asa_normal.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_hips_draft.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_hips_fine.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_hips_normal.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_nylon_draft.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_nylon_fine.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_nylon_normal.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_petg_draft.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_petg_fine.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_petg_normal.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_tpe_draft.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_tpe_fine.inst.cfg create mode 100644 resources/quality/fabxpro/fabxpro_tpe_normal.inst.cfg diff --git a/resources/quality/fabxpro/fabxpro_asa_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_asa_draft.inst.cfg new file mode 100644 index 0000000000..ef5bfe1ab8 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_asa_draft.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Draft +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Draft +weight = -2 +material = redd_asa +global_quality = True + + +[values] +layer_height = 0.3 +layer_height_0 = 0.35 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 diff --git a/resources/quality/fabxpro/fabxpro_asa_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_asa_fine.inst.cfg new file mode 100644 index 0000000000..9fb8243fba --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_asa_fine.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Fine +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Fine +weight = -2 +material = redd_asa +global_quality = True + +[values] +layer_height = 0.1 +layer_height_0 = 0.15 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 + diff --git a/resources/quality/fabxpro/fabxpro_asa_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_asa_normal.inst.cfg new file mode 100644 index 0000000000..3c4da49bc9 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_asa_normal.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Normal +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Normal +weight = -2 +material = redd_asa +global_quality = True + +[values] +layer_height = 0.2 +layer_height_0 = 0.3 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 \ No newline at end of file diff --git a/resources/quality/fabxpro/fabxpro_hips_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_hips_draft.inst.cfg new file mode 100644 index 0000000000..c2831c8bd4 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_hips_draft.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Draft +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Draft +weight = -2 +material = redd_hips +global_quality = True + + +[values] +layer_height = 0.3 +layer_height_0 = 0.35 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 diff --git a/resources/quality/fabxpro/fabxpro_hips_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_hips_fine.inst.cfg new file mode 100644 index 0000000000..fd06f2d051 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_hips_fine.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Fine +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Fine +weight = -2 +material = redd_hips +global_quality = True + +[values] +layer_height = 0.1 +layer_height_0 = 0.15 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 + diff --git a/resources/quality/fabxpro/fabxpro_hips_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_hips_normal.inst.cfg new file mode 100644 index 0000000000..b961438594 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_hips_normal.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Normal +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Normal +weight = -2 +material = redd_hips +global_quality = True + +[values] +layer_height = 0.2 +layer_height_0 = 0.3 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 \ No newline at end of file diff --git a/resources/quality/fabxpro/fabxpro_nylon_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_nylon_draft.inst.cfg new file mode 100644 index 0000000000..ccc8858ed6 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_nylon_draft.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Draft +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Draft +weight = -2 +material = redd_nylon +global_quality = True + + +[values] +layer_height = 0.3 +layer_height_0 = 0.35 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 diff --git a/resources/quality/fabxpro/fabxpro_nylon_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_nylon_fine.inst.cfg new file mode 100644 index 0000000000..34df2f3228 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_nylon_fine.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Fine +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Fine +weight = -2 +material = redd_nylon +global_quality = True + +[values] +layer_height = 0.1 +layer_height_0 = 0.15 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 + diff --git a/resources/quality/fabxpro/fabxpro_nylon_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_nylon_normal.inst.cfg new file mode 100644 index 0000000000..b34c6407ad --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_nylon_normal.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Normal +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Normal +weight = -2 +material = redd_nylon +global_quality = True + +[values] +layer_height = 0.2 +layer_height_0 = 0.3 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 \ No newline at end of file diff --git a/resources/quality/fabxpro/fabxpro_petg_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_petg_draft.inst.cfg new file mode 100644 index 0000000000..243a01924b --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_petg_draft.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Draft +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Draft +weight = -2 +material = redd_petg +global_quality = True + + +[values] +layer_height = 0.3 +layer_height_0 = 0.35 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 diff --git a/resources/quality/fabxpro/fabxpro_petg_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_petg_fine.inst.cfg new file mode 100644 index 0000000000..4c3329dfba --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_petg_fine.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Fine +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Fine +weight = -2 +material = redd_petg +global_quality = True + +[values] +layer_height = 0.1 +layer_height_0 = 0.15 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 + diff --git a/resources/quality/fabxpro/fabxpro_petg_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_petg_normal.inst.cfg new file mode 100644 index 0000000000..251dafc125 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_petg_normal.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Normal +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Normal +weight = -2 +material = redd_petg +global_quality = True + +[values] +layer_height = 0.2 +layer_height_0 = 0.3 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 55 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 \ No newline at end of file diff --git a/resources/quality/fabxpro/fabxpro_tpe_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_tpe_draft.inst.cfg new file mode 100644 index 0000000000..2e2a3b6830 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_tpe_draft.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Draft +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Draft +weight = -2 +material = redd_tpe +global_quality = True + + +[values] +layer_height = 0.3 +layer_height_0 = 0.35 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 35 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 diff --git a/resources/quality/fabxpro/fabxpro_tpe_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_tpe_fine.inst.cfg new file mode 100644 index 0000000000..bd4821762a --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_tpe_fine.inst.cfg @@ -0,0 +1,36 @@ +[general] +version = 4 +name = Fine +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Fine +weight = -2 +material = redd_tpe +global_quality = True + +[values] +layer_height = 0.1 +layer_height_0 = 0.15 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 35 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 + diff --git a/resources/quality/fabxpro/fabxpro_tpe_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_tpe_normal.inst.cfg new file mode 100644 index 0000000000..dcae187831 --- /dev/null +++ b/resources/quality/fabxpro/fabxpro_tpe_normal.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Normal +definition = fabxpro + +[metadata] +setting_version = 11 +type = quality +quality_type = Normal +weight = -2 +material = redd_tpe +global_quality = True + +[values] +layer_height = 0.2 +layer_height_0 = 0.3 +initial_layer_line_width_factor = 150 +infill_before_walls = False +speed_print = 35 +speed_travel = 70 +retraction_amount = 1 +retraction_speed = 40 +adhesion_type = raft +raft_margin = 5 +raft_airgap = 0.35 +raft_surface_layers = 1 +raft_surface_thickness = 0.1 +raft_surface_line_spacing = 0.6 +raft_base_thickness = 0.6 +cool_fan_enabled = False +support_enable = True +support_pattern = lines +support_infill_rate = 15 +support_z_distance = 0.15 +support_xy_distance = 0.85 \ No newline at end of file From 72a66f1358e99d634bb124d5162ea8499842437c Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 20 Mar 2020 17:31:21 +0100 Subject: [PATCH 62/78] Do not use the JsonDecorator scope for binary downloads CURA-7150 --- plugins/CuraDrive/src/DriveApiService.py | 6 +++--- plugins/Toolbox/src/CloudSync/DownloadPresenter.py | 3 +-- plugins/Toolbox/src/Toolbox.py | 9 +++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index fa010d915d..0c8d38ebd2 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -33,7 +33,7 @@ class DriveApiService: def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() - self._jsonCloudScope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) + self._json_cloud_scope = JsonDecoratorScope(UltimakerCloudScope(CuraApplication.getInstance())) def getBackups(self, changed: Callable[[List[Dict[str, Any]]], None]) -> None: def callback(reply: QNetworkReply, error: Optional["QNetworkReply.NetworkError"] = None) -> None: @@ -55,7 +55,7 @@ class DriveApiService: self.BACKUP_URL, callback= callback, error_callback = callback, - scope=self._jsonCloudScope + scope=self._json_cloud_scope ) def createBackup(self) -> None: @@ -105,7 +105,7 @@ class DriveApiService: url = "{}/{}".format(self.BACKUP_URL, backup_id), callback = finishedCallback, error_callback = errorCallback, - scope= self._jsonCloudScope + scope= self._json_cloud_scope ) @staticmethod diff --git a/plugins/Toolbox/src/CloudSync/DownloadPresenter.py b/plugins/Toolbox/src/CloudSync/DownloadPresenter.py index a16ed67218..a5d6eee0b6 100644 --- a/plugins/Toolbox/src/CloudSync/DownloadPresenter.py +++ b/plugins/Toolbox/src/CloudSync/DownloadPresenter.py @@ -11,7 +11,6 @@ from UM.Logger import Logger from UM.Message import Message from UM.Signal import Signal from UM.TaskManagement.HttpRequestManager import HttpRequestManager -from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from cura.CuraApplication import CuraApplication from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope from .SubscribedPackagesModel import SubscribedPackagesModel @@ -30,7 +29,7 @@ class DownloadPresenter: self.done = Signal() self._app = app - self._scope = JsonDecoratorScope(UltimakerCloudScope(app)) + self._scope = UltimakerCloudScope(app) self._started = False self._progress_message = self._createProgressMessage() diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index ec1da6707a..38666bb6e2 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -52,7 +52,8 @@ class Toolbox(QObject, Extension): self._download_request_data = None # type: Optional[HttpRequestData] self._download_progress = 0 # type: float self._is_downloading = False # type: bool - self._scope = JsonDecoratorScope(UltimakerCloudScope(application)) # type: JsonDecoratorScope + self._cloud_scope = UltimakerCloudScope(application) # type: UltimakerCloudScope + self._json_scope = JsonDecoratorScope(self._cloud_scope) # type: JsonDecoratorScope self._request_urls = {} # type: Dict[str, str] self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated @@ -149,7 +150,7 @@ class Toolbox(QObject, Extension): url = "{base_url}/packages/{package_id}/ratings".format(base_url = CloudApiModel.api_url, package_id = package_id) data = "{\"data\": {\"cura_version\": \"%s\", \"rating\": %i}}" % (Version(self._application.getVersion()), rating) - self._application.getHttpRequestManager().put(url, data = data.encode(), scope = self._scope) + self._application.getHttpRequestManager().put(url, data = data.encode(), scope = self._json_scope) def getLicenseDialogPluginFileLocation(self) -> str: return self._license_dialog_plugin_file_location @@ -539,7 +540,7 @@ class Toolbox(QObject, Extension): self._application.getHttpRequestManager().get(url, callback = callback, error_callback = error_callback, - scope=self._scope) + scope=self._json_scope) @pyqtSlot(str) def startDownload(self, url: str) -> None: @@ -552,7 +553,7 @@ class Toolbox(QObject, Extension): callback = callback, error_callback = error_callback, download_progress_callback = download_progress_callback, - scope=self._scope + scope=self._cloud_scope ) self._download_request_data = request_data From 6db8a9ec3e3734b553e60dfe382b78680a625753 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 20 Mar 2020 17:31:54 +0100 Subject: [PATCH 63/78] Set progress of backup message to 100% when done CURA-7150 --- plugins/CuraDrive/src/CreateBackupJob.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index f5f557d003..5c3ed529e0 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -65,6 +65,7 @@ class CreateBackupJob(Job): self._job_done.wait() if self.backup_upload_error_message == "": upload_message.setText(catalog.i18nc("@info:backup_status", "Your backup has finished uploading.")) + upload_message.setProgress(upload_message.getMaxProgress()) else: # some error occurred. This error is presented to the user by DrivePluginExtension upload_message.hide() From 1c374e7fc71c70bf5727aa443fd62133624b97ab Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 23 Mar 2020 09:37:34 +0100 Subject: [PATCH 64/78] Hide deltabot from Add Printer dialog We want users to use the "Custom FFF Printer" instead --- resources/definitions/deltabot.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/deltabot.def.json b/resources/definitions/deltabot.def.json index ad6a207bb2..6dbdfb418f 100644 --- a/resources/definitions/deltabot.def.json +++ b/resources/definitions/deltabot.def.json @@ -3,7 +3,7 @@ "version": 2, "inherits": "fdmprinter", "metadata": { - "visible": true, + "visible": false, "author": "Ultimaker", "manufacturer": "Custom", "file_formats": "text/x-gcode", From 1a4cb49ebad4593e1974af937ee80958265d8b24 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 23 Mar 2020 11:16:33 +0100 Subject: [PATCH 65/78] Hide upload message progress when upload is done CURA-7150 --- plugins/CuraDrive/src/CreateBackupJob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/CreateBackupJob.py b/plugins/CuraDrive/src/CreateBackupJob.py index 5c3ed529e0..25dc8a4949 100644 --- a/plugins/CuraDrive/src/CreateBackupJob.py +++ b/plugins/CuraDrive/src/CreateBackupJob.py @@ -65,7 +65,7 @@ class CreateBackupJob(Job): self._job_done.wait() if self.backup_upload_error_message == "": upload_message.setText(catalog.i18nc("@info:backup_status", "Your backup has finished uploading.")) - upload_message.setProgress(upload_message.getMaxProgress()) + upload_message.setProgress(None) # Hide progress bar else: # some error occurred. This error is presented to the user by DrivePluginExtension upload_message.hide() From e1c6f6ad552aa87d79cb1ce916d18c4b130471ba Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 23 Mar 2020 16:08:01 +0100 Subject: [PATCH 66/78] Add engineering profiles for engineering materials for UMS3 and UMS5 These are optimised for engineering applications, with greater dimensional accuracy and strength. Implements CURA-7313. --- ...s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg | 35 +++++++++++++++++++ ...a0.4_CPEP_Normal_Quality_Accurate.inst.cfg | 35 +++++++++++++++++++ ..._s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg | 35 +++++++++++++++++++ ...aa0.4_CPE_Normal_Quality_Accurate.inst.cfg | 35 +++++++++++++++++++ ...3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg | 35 +++++++++++++++++++ ...0.4_Nylon_Normal_Quality_Accurate.inst.cfg | 35 +++++++++++++++++++ ...m_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg | 35 +++++++++++++++++++ ..._aa0.4_PC_Normal_Quality_Accurate.inst.cfg | 35 +++++++++++++++++++ ...s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg | 35 +++++++++++++++++++ ...a0.4_CPEP_Normal_Quality_Accurate.inst.cfg | 35 +++++++++++++++++++ ..._s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg | 35 +++++++++++++++++++ ...aa0.4_CPE_Normal_Quality_Accurate.inst.cfg | 35 +++++++++++++++++++ ...5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg | 35 +++++++++++++++++++ ...0.4_Nylon_Normal_Quality_Accurate.inst.cfg | 35 +++++++++++++++++++ ...m_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg | 35 +++++++++++++++++++ ..._aa0.4_PC_Normal_Quality_Accurate.inst.cfg | 35 +++++++++++++++++++ 16 files changed, 560 insertions(+) create mode 100644 resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg create mode 100644 resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg new file mode 100644 index 0000000000..8b40a9869a --- /dev/null +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s3 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = fast +material = generic_cpe_plus +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg new file mode 100644 index 0000000000..64bd88d7d2 --- /dev/null +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s3 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = normal +material = generic_cpe_plus +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg new file mode 100644 index 0000000000..e8e179316e --- /dev/null +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s3 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = fast +material = generic_cpe +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg new file mode 100644 index 0000000000..e9da5cbc6b --- /dev/null +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s3 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = normal +material = generic_cpe +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg new file mode 100644 index 0000000000..112bd830d2 --- /dev/null +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s3 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = fast +material = generic_nylon +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg new file mode 100644 index 0000000000..e4a97cfa24 --- /dev/null +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s3 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = normal +material = generic_nylon +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg new file mode 100644 index 0000000000..2d0d26caac --- /dev/null +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s3 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = fast +material = generic_pc +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg new file mode 100644 index 0000000000..4211fa0bce --- /dev/null +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s3 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = normal +material = generic_pc +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg new file mode 100644 index 0000000000..0f67d272a7 --- /dev/null +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s5 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = fast +material = generic_cpe_plus +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg new file mode 100644 index 0000000000..6907b96e41 --- /dev/null +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s5 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = normal +material = generic_cpe_plus +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg new file mode 100644 index 0000000000..5b265ca1fc --- /dev/null +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s5 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = fast +material = generic_cpe +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg new file mode 100644 index 0000000000..dbc1d0cd64 --- /dev/null +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s5 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = normal +material = generic_cpe +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg new file mode 100644 index 0000000000..0587af0eb6 --- /dev/null +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s5 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = fast +material = generic_nylon +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg new file mode 100644 index 0000000000..ad7e0213e8 --- /dev/null +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s5 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = normal +material = generic_nylon +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg new file mode 100644 index 0000000000..6fa59487bd --- /dev/null +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s5 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = fast +material = generic_pc +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg new file mode 100644 index 0000000000..f18fea61ce --- /dev/null +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 4 +name = Accurate +definition = ultimaker_s5 + +[metadata] +setting_version = 11 +type = intent +intent_category = engineering +quality_type = normal +material = generic_pc +variant = AA 0.4 + +[values] +infill_line_width = =line_width +jerk_print = 30 +jerk_infill = =jerk_print +jerk_topbottom = =jerk_print +jerk_wall = =jerk_print +jerk_wall_0 = =jerk_wall +jerk_wall_x = =jerk_wall +jerk_layer_0 = 5 +line_width = =machine_nozzle_size +speed_print = 30 +speed_infill = =speed_print +speed_layer_0 = 20 +speed_topbottom = =speed_print +speed_wall = =speed_print +speed_wall_0 = =speed_wall +speed_wall_x = =speed_wall +top_bottom_thickness = =wall_thickness +wall_line_width_x = =line_width +wall_thickness = =line_width * 3 +xy_offset = =- layer_height * 0.2 + From 308096ec84df7e3363305ff0cc4a528e4b483de7 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 23 Mar 2020 16:10:56 +0100 Subject: [PATCH 67/78] Style consistency / readability Contributes to issue CURA-7313. --- .../ultimaker_s3/um_s3_aa0.4_ABS_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s3_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_PLA_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s3_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s3/um_s3_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s3_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s5_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_PLA_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s5_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg | 2 +- .../ultimaker_s5/um_s5_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg | 2 +- .../um_s5_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Fast_Print_Accurate.inst.cfg index a1d50aae0f..5ab984c5cb 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Fast_Print_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg index 26c5029924..3e749af40a 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg index 8b40a9869a..55e6b20baa 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg index 64bd88d7d2..0ed112b06e 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg index e8e179316e..636ddd0e49 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Fast_Print_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg index e9da5cbc6b..66d79d502a 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg index 112bd830d2..cb99ddc0ea 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg index e4a97cfa24..d207ace74b 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg index 2d0d26caac..44fedf583f 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Fast_Print_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg index 4211fa0bce..d926bb1fe4 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_PC_Normal_Quality_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Fast_Print_Accurate.inst.cfg index 63aa092cf1..4a5b4ebb95 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Fast_Print_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg index 82fe5e807b..dc5f97058c 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg index 865c53e4e8..ad66d8e286 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg index 36150f18a3..7b62ff3d06 100644 --- a/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s3/um_s3_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print_Accurate.inst.cfg index 6aed5bf11a..9ca5c61b21 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg index a141830f80..8e586aff25 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_ABS_Normal_Quality_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg index 0f67d272a7..e30d7af95c 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Fast_Print_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg index 6907b96e41..9df0cad0df 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPEP_Normal_Quality_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg index 5b265ca1fc..9f9e58068a 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg index dbc1d0cd64..02ffa379fb 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg index 0587af0eb6..9149be0de7 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Fast_Print_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg index ad7e0213e8..21bfa697f2 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_Nylon_Normal_Quality_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg index 6fa59487bd..6abfaddc7b 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Fast_Print_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg index f18fea61ce..9845dadf28 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_PC_Normal_Quality_Accurate.inst.cfg @@ -31,5 +31,5 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Fast_Print_Accurate.inst.cfg index d814866d39..8fcc2c128a 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Fast_Print_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg index b22b6ff4c2..f987eed58a 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_PLA_Normal_Quality_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg index 57ab6a727e..abe0e598f4 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Fast_Print_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 diff --git a/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg b/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg index a5f878bf4f..72ad6e61f7 100644 --- a/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg +++ b/resources/intent/ultimaker_s5/um_s5_aa0.4_TPLA_Normal_Quality_Accurate.inst.cfg @@ -31,4 +31,4 @@ speed_wall_x = =speed_wall top_bottom_thickness = =wall_thickness wall_line_width_x = =line_width wall_thickness = =line_width * 3 -xy_offset = =- layer_height * 0.2 +xy_offset = =-layer_height * 0.2 From f6f4486b517f37044d4d2ba59d530b3be8131068 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Tue, 24 Mar 2020 13:22:17 +0530 Subject: [PATCH 68/78] Update fabxpro_abs_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg index d42b536705..4505f89603 100644 --- a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg @@ -1,6 +1,6 @@ [general] version = 4 -name = Draft ABS +name = Draft definition = fabxpro [metadata] From 9a927ba36323da9c5dd78de4150ef5dde452aa2e Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Tue, 24 Mar 2020 13:22:36 +0530 Subject: [PATCH 69/78] Update fabxpro_abs_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg index 37a2c2b0b9..298a8f6eb7 100644 --- a/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_fine.inst.cfg @@ -1,12 +1,12 @@ [general] version = 4 -name = Fine ABS +name = Fine definition = fabxpro [metadata] setting_version = 11 type = quality -quality_type = Fine ABS +quality_type = Fine weight = -2 material = redd_abs global_quality = True From 348b54ff812c08ce6ed976ff494e78471cfcecd8 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Tue, 24 Mar 2020 13:22:53 +0530 Subject: [PATCH 70/78] Update fabxpro_abs_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg index 210bff9705..6ee74f26e4 100644 --- a/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_normal.inst.cfg @@ -1,12 +1,12 @@ [general] version = 4 -name = Normal ABS +name = Normal definition = fabxpro [metadata] setting_version = 11 type = quality -quality_type = Normal ABS +quality_type = Normal weight = -2 material = redd_abs global_quality = True From fda42406f30fb3f49adf2677b1e738d9737ac7aa Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Tue, 24 Mar 2020 13:23:08 +0530 Subject: [PATCH 71/78] Update fabxpro_abs_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg index 4505f89603..229e3ba587 100644 --- a/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_abs_draft.inst.cfg @@ -6,7 +6,7 @@ definition = fabxpro [metadata] setting_version = 11 type = quality -quality_type = Draft ABS +quality_type = Draft weight = -2 material = redd_abs global_quality = True From 95daab37e03c5657ef6b4eff64ad8405c422ff8f Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Tue, 24 Mar 2020 13:23:25 +0530 Subject: [PATCH 72/78] Update fabxpro_pla_draft.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg index 0244620e48..c8ef3215ba 100644 --- a/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_draft.inst.cfg @@ -1,12 +1,12 @@ [general] version = 4 -name = Draft PLA +name = Draft definition = fabxpro [metadata] setting_version = 11 type = quality -quality_type = Draft PLA +quality_type = Draft weight = -2 material = redd_pla global_quality = True From 94bebdae1747ce7b865cad50118501457615f8e2 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Tue, 24 Mar 2020 13:23:47 +0530 Subject: [PATCH 73/78] Update fabxpro_pla_fine.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg index fdf3ddf8fe..8e2a07bf4b 100644 --- a/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_fine.inst.cfg @@ -1,12 +1,12 @@ [general] version = 4 -name = Fine PLA +name = Fine definition = fabxpro [metadata] setting_version = 11 type = quality -quality_type = Fine PLA +quality_type = Fine weight = -2 material = redd_pla global_quality = True From 210841839795696d6b71d0b9449b0579c375a806 Mon Sep 17 00:00:00 2001 From: Hussain Bhavnagarwala Date: Tue, 24 Mar 2020 13:24:18 +0530 Subject: [PATCH 74/78] Update fabxpro_pla_normal.inst.cfg --- resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg index 682b767ae6..2f5228ddd1 100644 --- a/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg +++ b/resources/quality/fabxpro/fabxpro_pla_normal.inst.cfg @@ -1,12 +1,12 @@ [general] version = 4 -name = Normal PLA +name = Normal definition = fabxpro [metadata] setting_version = 11 type = quality -quality_type = Normal PLA +quality_type = Normal weight = -2 material = redd_pla global_quality = True From 0516756c3b53fd593e5ca2451bc6417c2be81c3d Mon Sep 17 00:00:00 2001 From: Matt Jani Date: Tue, 24 Mar 2020 12:54:38 +0100 Subject: [PATCH 75/78] Summary Updated Cloud sign in strings CURA-7314 --- resources/qml/Account/GeneralOperations.qml | 6 +++--- resources/qml/WelcomePages/CloudContent.qml | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/resources/qml/Account/GeneralOperations.qml b/resources/qml/Account/GeneralOperations.qml index f01b9538bd..bea90c1d67 100644 --- a/resources/qml/Account/GeneralOperations.qml +++ b/resources/qml/Account/GeneralOperations.qml @@ -26,7 +26,7 @@ Column anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter renderType: Text.NativeRendering - text: "Ultimaker Cloud" + text: "Ultimaker Account" font: UM.Theme.getFont("large_bold") color: UM.Theme.getColor("text") } @@ -37,7 +37,7 @@ Column anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter renderType: Text.NativeRendering - text: catalog.i18nc("@label", "The next generation 3D printing workflow") + text: catalog.i18nc("@label", "Your key to connected 3D printing") font: UM.Theme.getFont("default_bold") color: UM.Theme.getColor("text") } @@ -48,7 +48,7 @@ Column anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignLeft renderType: Text.NativeRendering - text: catalog.i18nc("@text", "- Send print jobs to Ultimaker printers outside your local network\n- Store your Ultimaker Cura settings in the cloud for use anywhere\n- Get exclusive access to print profiles from leading brands") + text: catalog.i18nc("@text", "- Customize your experience with more print profiles and plugins\n- Stay flexible by syncing your setup and loading it anywhere\n- Increase efficiency with a remote workflow on Ultimaker printers") lineHeight: 1.4 font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") diff --git a/resources/qml/WelcomePages/CloudContent.qml b/resources/qml/WelcomePages/CloudContent.qml index e9b6df94e0..b127dbfb3c 100644 --- a/resources/qml/WelcomePages/CloudContent.qml +++ b/resources/qml/WelcomePages/CloudContent.qml @@ -33,7 +33,7 @@ Item anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter - text: catalog.i18nc("@label", "Ultimaker Cloud") + text: catalog.i18nc("@label", "Ultimaker Account") color: UM.Theme.getColor("primary_button") font: UM.Theme.getFont("huge") renderType: Text.NativeRendering @@ -74,7 +74,7 @@ Item id: highlightTextLabel anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter - text: catalog.i18nc("@text", "The next generation 3D printing workflow") + text: catalog.i18nc("@text", "Your key to connected 3D printing") textFormat: Text.RichText color: UM.Theme.getColor("primary") font: UM.Theme.getFont("medium") @@ -91,13 +91,13 @@ Item var full_text = "" var t = "" - t = catalog.i18nc("@text", "- Send print jobs to Ultimaker printers outside your local network") + t = catalog.i18nc("@text", "- Customize your experience with more print profiles and plugins") full_text += "

" + t + "

" - t = catalog.i18nc("@text", "- Store your Ultimaker Cura settings in the cloud for use anywhere") + t = catalog.i18nc("@text", "- Stay flexible by syncing your setup and loading it anywhere") full_text += "

" + t + "

" - t = catalog.i18nc("@text", "- Get exclusive access to print profiles from leading brands") + t = catalog.i18nc("@text", "- Increase efficiency with a remote workflow on Ultimaker printers") full_text += "

" + t + "

" return full_text From a551492ebb8fd6ee3f6ffd65422c3ed5e1540cdd Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 24 Mar 2020 13:08:26 +0100 Subject: [PATCH 76/78] Adjust start g-code to not mix 50/50 by default This new start g-code has been tested on the A20 by @leshuguets in issue thread #7280. --- resources/definitions/geeetech_A10M.def.json | 2 +- resources/definitions/geeetech_A20M.def.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/geeetech_A10M.def.json b/resources/definitions/geeetech_A10M.def.json index d74a04f1ec..6a25e4c407 100644 --- a/resources/definitions/geeetech_A10M.def.json +++ b/resources/definitions/geeetech_A10M.def.json @@ -45,7 +45,7 @@ "machine_max_jerk_e": { "default_value": 2.5 }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": "G28 \nG1 Z15 F300\nM107\nG90\nM82\nM104 S215\nM140 S55\nG92 E0\nM109 S215\nM107\nM163 S0 P0.50\nM163 S1 P0.50\nM164 S4\nG0 X10 Y20 F6000\nG1 Z0.8\nG1 F300 X180 E40\nG1 F1200 Z2\nG92 E0\nG28" + "default_value": ";GeeeTech A10M start script\nG28 ;home\nG90 ;absolute positioning\nG1 X0 Y0 Z15 E0 F300 ;go to wait position\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_print_temperature_layer_0} ;set extruder temp and wait\nG1 Z0.8 F200 ;set extruder height\nG1 X220 Y0 E80 F1000 ;purge line\n;end of start script" }, "machine_end_gcode": { "default_value": "G91\nG1 E-1\nG0 X0 Y200\nM104 S0\nG90\nG92 E0\nM140 S0\nM84\nM104 S0\nM140 S0\nM84" diff --git a/resources/definitions/geeetech_A20M.def.json b/resources/definitions/geeetech_A20M.def.json index 5c38728ed1..476741c7fe 100644 --- a/resources/definitions/geeetech_A20M.def.json +++ b/resources/definitions/geeetech_A20M.def.json @@ -45,7 +45,7 @@ "machine_max_jerk_e": { "default_value": 2.5 }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": "G28 \nG1 Z15 F300\nM107\nG90\nM82\nM104 S215\nM140 S55\nG92 E0\nM109 S215\nM107\nM163 S0 P0.50\nM163 S1 P0.50\nM164 S4\nG0 X10 Y20 F6000\nG1 Z0.8\nG1 F300 X200 E40\nG1 F1200 Z2\nG92 E0\nG28" + "default_value": ";GeeeTech A20M start script\nG28 ;home\nG90 ;absolute positioning\nG1 X0 Y0 Z15 E0 F300 ;go to wait position\nM140 S{material_bed_temperature_layer_0} ;set bed temp\nM190 S{material_print_temperature_layer_0} ;set extruder temp and wait\nG1 Z0.8 F200 ;set extruder height\nG1 X220 Y0 E80 F1000 ;purge line\n;end of start script" }, "machine_end_gcode": { "default_value": "G91\nG1 E-1\nG0 X0 Y200\nM104 S0\nG90\nG92 E0\nM140 S0\nM84\nM104 S0\nM140 S0\nM84" From 5cdf1adccc62d23cbe20f235acbd6d1ee2e05f6a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 24 Mar 2020 13:18:50 +0100 Subject: [PATCH 77/78] Fix duplicate shortcut keys --- resources/i18n/hu_HU/cura.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/i18n/hu_HU/cura.po b/resources/i18n/hu_HU/cura.po index bedd8169f5..e93ca36d77 100644 --- a/resources/i18n/hu_HU/cura.po +++ b/resources/i18n/hu_HU/cura.po @@ -3599,7 +3599,7 @@ msgstr "&Fájl" #: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:31 msgctxt "@title:menu menubar:toplevel" msgid "&Edit" -msgstr "&Szerkesztés" +msgstr "S&zerkesztés" #: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:48 #: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12 @@ -4424,7 +4424,7 @@ msgstr "Anyagok kezelése..." #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:195 msgctxt "@action:inmenu menubar:profile" msgid "&Update profile with current settings/overrides" -msgstr "&Profil frissítése a jelenlegi beállításokkal/felülírásokkal" +msgstr "Profil &frissítése a jelenlegi beállításokkal/felülírásokkal" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203 msgctxt "@action:inmenu menubar:profile" @@ -4434,7 +4434,7 @@ msgstr "&Jelenlegi változtatások eldobása" #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:215 msgctxt "@action:inmenu menubar:profile" msgid "&Create profile from current settings/overrides..." -msgstr "&Profil létrehozása a jelenlegi beállításokkal/felülírásokkal..." +msgstr "Profil &létrehozása a jelenlegi beállításokkal/felülírásokkal..." #: /home/ruben/Projects/Cura/resources/qml/Actions.qml:221 msgctxt "@action:inmenu menubar:profile" From 8e324c594ea83baa860bfba07c39e6d05608a3c3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 24 Mar 2020 14:22:28 +0100 Subject: [PATCH 78/78] Adjust wall thickness to 1 line if using spiralise Except for printers that explicitly override it. Fixes #7317. --- resources/definitions/abax_pri3.def.json | 2 +- resources/definitions/abax_pri5.def.json | 2 +- resources/definitions/abax_titan.def.json | 2 +- resources/definitions/alfawise_u20.def.json | 2 +- resources/definitions/alfawise_u30.def.json | 2 +- resources/definitions/bq_hephestos.def.json | 2 +- resources/definitions/bq_hephestos_2.def.json | 2 +- resources/definitions/bq_hephestos_xl.def.json | 2 +- resources/definitions/bq_witbox.def.json | 2 +- resources/definitions/bq_witbox_2.def.json | 2 +- resources/definitions/cocoon_create_modelmaker.def.json | 2 +- resources/definitions/creality_cr-x.def.json | 2 +- resources/definitions/cubicon_common.def.json | 2 +- resources/definitions/easyarts_ares.def.json | 2 +- resources/definitions/fdmprinter.def.json | 1 + resources/definitions/felixpro2dual.def.json | 2 +- resources/definitions/felixtec4dual.def.json | 2 +- resources/definitions/gmax15plus.def.json | 2 +- resources/definitions/gmax15plus_dual.def.json | 2 +- resources/definitions/helloBEEprusa.def.json | 2 +- resources/definitions/innovo_inventor.def.json | 2 +- resources/definitions/jgaurora_a1.def.json | 2 +- resources/definitions/jgaurora_a3s.def.json | 2 +- resources/definitions/jgaurora_a5.def.json | 2 +- resources/definitions/jgaurora_jgmaker_magic.def.json | 2 +- resources/definitions/jgaurora_z_603s.def.json | 2 +- resources/definitions/makeit_pro_l.def.json | 2 +- resources/definitions/makeit_pro_m.def.json | 2 +- resources/definitions/makeit_pro_mx.def.json | 2 +- resources/definitions/mankati_fullscale_xt_plus.def.json | 2 +- resources/definitions/peopoly_moai.def.json | 2 +- resources/definitions/rigidbot.def.json | 2 +- resources/definitions/rigidbot_big.def.json | 2 +- resources/definitions/robo_3d_r1.def.json | 2 +- resources/definitions/skriware_2.def.json | 2 +- resources/definitions/tam.def.json | 2 +- resources/definitions/vertex_delta_k8800.def.json | 2 +- resources/definitions/vertex_nano_k8600.def.json | 2 +- 38 files changed, 38 insertions(+), 37 deletions(-) diff --git a/resources/definitions/abax_pri3.def.json b/resources/definitions/abax_pri3.def.json index 529636be90..8f0d1a97d8 100644 --- a/resources/definitions/abax_pri3.def.json +++ b/resources/definitions/abax_pri3.def.json @@ -44,7 +44,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1 + "value": "1" }, "top_bottom_thickness": { "default_value": 1 diff --git a/resources/definitions/abax_pri5.def.json b/resources/definitions/abax_pri5.def.json index 9e4e7e3b20..5730cc6e05 100644 --- a/resources/definitions/abax_pri5.def.json +++ b/resources/definitions/abax_pri5.def.json @@ -44,7 +44,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1 + "value": "1" }, "top_bottom_thickness": { "default_value": 1 diff --git a/resources/definitions/abax_titan.def.json b/resources/definitions/abax_titan.def.json index 98643df22b..dc5dd3b14f 100644 --- a/resources/definitions/abax_titan.def.json +++ b/resources/definitions/abax_titan.def.json @@ -44,7 +44,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1 + "value": "1" }, "top_bottom_thickness": { "default_value": 1 diff --git a/resources/definitions/alfawise_u20.def.json b/resources/definitions/alfawise_u20.def.json index 4da42fdb1d..5b9b8471c6 100644 --- a/resources/definitions/alfawise_u20.def.json +++ b/resources/definitions/alfawise_u20.def.json @@ -51,7 +51,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "speed_print": { "default_value": 40 diff --git a/resources/definitions/alfawise_u30.def.json b/resources/definitions/alfawise_u30.def.json index e05536f66c..3bfc1aaa4e 100644 --- a/resources/definitions/alfawise_u30.def.json +++ b/resources/definitions/alfawise_u30.def.json @@ -23,7 +23,7 @@ }, "material_diameter": { "default_value": 1.75 }, "layer_height_0": { "default_value": 0.2 }, - "wall_thickness": { "default_value": 1.2 }, + "wall_thickness": { "value": "1.2" }, "speed_print": { "default_value": 40 }, "support_enable": { "default_value": true }, "retraction_enable": { "default_value": true }, diff --git a/resources/definitions/bq_hephestos.def.json b/resources/definitions/bq_hephestos.def.json index d9e84dae87..6d81d2d0d5 100644 --- a/resources/definitions/bq_hephestos.def.json +++ b/resources/definitions/bq_hephestos.def.json @@ -49,7 +49,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1 + "value": "1" }, "top_bottom_thickness": { "default_value": 1 diff --git a/resources/definitions/bq_hephestos_2.def.json b/resources/definitions/bq_hephestos_2.def.json index 5c122eb9a4..ddc6197490 100644 --- a/resources/definitions/bq_hephestos_2.def.json +++ b/resources/definitions/bq_hephestos_2.def.json @@ -26,7 +26,7 @@ "machine_center_is_zero": { "default_value": false }, "layer_height": { "default_value": 0.2 }, "layer_height_0": { "default_value": 0.2 }, - "wall_thickness": { "default_value": 1.2 }, + "wall_thickness": { "value": "1.2" }, "top_bottom_thickness": { "default_value": 1.2 }, "infill_sparse_density": { "default_value": 20 }, "speed_print": { "default_value": 60 }, diff --git a/resources/definitions/bq_hephestos_xl.def.json b/resources/definitions/bq_hephestos_xl.def.json index 16d0953bf1..24344b6aba 100644 --- a/resources/definitions/bq_hephestos_xl.def.json +++ b/resources/definitions/bq_hephestos_xl.def.json @@ -48,7 +48,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1 + "value": "1" }, "top_bottom_thickness": { "default_value": 1 diff --git a/resources/definitions/bq_witbox.def.json b/resources/definitions/bq_witbox.def.json index fce2af9f97..085adf1afb 100644 --- a/resources/definitions/bq_witbox.def.json +++ b/resources/definitions/bq_witbox.def.json @@ -49,7 +49,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1 + "value": "1" }, "top_bottom_thickness": { "default_value": 1 diff --git a/resources/definitions/bq_witbox_2.def.json b/resources/definitions/bq_witbox_2.def.json index d1114aafd6..d0d1dddb53 100644 --- a/resources/definitions/bq_witbox_2.def.json +++ b/resources/definitions/bq_witbox_2.def.json @@ -48,7 +48,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "top_bottom_thickness": { "default_value": 1.2 diff --git a/resources/definitions/cocoon_create_modelmaker.def.json b/resources/definitions/cocoon_create_modelmaker.def.json index b738dc64ff..51c5b5e7cb 100644 --- a/resources/definitions/cocoon_create_modelmaker.def.json +++ b/resources/definitions/cocoon_create_modelmaker.def.json @@ -54,7 +54,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "top_bottom_thickness": { "default_value": 0.6 diff --git a/resources/definitions/creality_cr-x.def.json b/resources/definitions/creality_cr-x.def.json index 13409a7212..3d13c0f703 100644 --- a/resources/definitions/creality_cr-x.def.json +++ b/resources/definitions/creality_cr-x.def.json @@ -41,7 +41,7 @@ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { "default_value": "G21 ;metric values\nG28 ;home all\nG90 ;absolute positioning\nM107 ;start with the fan off\nG1 F2400 Z15.0 ;raise the nozzle 15mm\nM109 S{material_print_temperature} ;Set Extruder Temperature and Wait\nM190 S{material_bed_temperature}; Wait for bed temperature to reach target temp\nT0 ;Switch to Extruder 1\nG1 F3000 X5 Y10 Z0.2 ;move to prime start position\nG92 E0 ;reset extrusion distance\nG1 F600 X160 E15 ;prime nozzle in a line\nG1 F5000 X180 ;quick wipe\nG92 E0 ;reset extrusion distance" }, "machine_end_gcode": { "default_value": "M104 S0 ;hotend off\nM140 S0 ;bed off\nG92 E0\nG1 F2000 E-100 ;retract filament 100mm\nG92 E0\nG1 F3000 X0 Y270 ;move bed for easy part removal\nM84 ;disable steppers" }, - "wall_thickness": { "default_value": 1 }, + "wall_thickness": { "value": "1" }, "top_bottom_thickness": { "default_value": 1 } } } diff --git a/resources/definitions/cubicon_common.def.json b/resources/definitions/cubicon_common.def.json index 6b1e3d953e..61e684a283 100644 --- a/resources/definitions/cubicon_common.def.json +++ b/resources/definitions/cubicon_common.def.json @@ -46,7 +46,7 @@ "max_skin_angle_for_expansion": { "default_value": 90 }, "skin_angles": { "default_value": "[135,45]" }, "coasting_volume": { "default_value": 0.032 }, - "wall_thickness": { "default_value": 1.2 }, + "wall_thickness": { "value": "1.2" }, "cool_min_layer_time_fan_speed_max": { "default_value": 15 }, "cool_min_layer_time": { "default_value": 15 }, "support_interface_pattern": { "default_value": "zigzag" }, diff --git a/resources/definitions/easyarts_ares.def.json b/resources/definitions/easyarts_ares.def.json index 18d73a3531..8751f2c3e1 100644 --- a/resources/definitions/easyarts_ares.def.json +++ b/resources/definitions/easyarts_ares.def.json @@ -44,7 +44,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1 + "value": "1" }, "top_bottom_thickness": { "default_value": 1 diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 721876334a..8b19c5867f 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1032,6 +1032,7 @@ "description": "The thickness of the walls in the horizontal direction. This value divided by the wall line width defines the number of walls.", "unit": "mm", "default_value": 0.8, + "value": "wall_line_width_0 if magic_spiralize else 0.8", "minimum_value": "0", "minimum_value_warning": "line_width", "maximum_value_warning": "10 * line_width", diff --git a/resources/definitions/felixpro2dual.def.json b/resources/definitions/felixpro2dual.def.json index fdd8a1b694..7c883b2f76 100644 --- a/resources/definitions/felixpro2dual.def.json +++ b/resources/definitions/felixpro2dual.def.json @@ -26,7 +26,7 @@ "layer_height_0": { "default_value": 0.2 }, "infill_sparse_density": { "default_value": 20 }, - "wall_thickness": { "default_value": 1 }, + "wall_thickness": { "value": "1" }, "top_bottom_thickness": { "default_value": 1 }, "machine_width": { "default_value": 240 }, diff --git a/resources/definitions/felixtec4dual.def.json b/resources/definitions/felixtec4dual.def.json index efc13c1759..439e4473d0 100644 --- a/resources/definitions/felixtec4dual.def.json +++ b/resources/definitions/felixtec4dual.def.json @@ -25,7 +25,7 @@ "layer_height": { "default_value": 0.2 }, "layer_height_0": { "default_value": 0.3 }, "infill_sparse_density": { "default_value": 20 }, - "wall_thickness": { "default_value": 1 }, + "wall_thickness": { "value": "1" }, "top_bottom_thickness": { "default_value": 1 }, "infill_pattern": { "value": "'tetrahedral'" }, diff --git a/resources/definitions/gmax15plus.def.json b/resources/definitions/gmax15plus.def.json index e98d6c02fe..7cafa09727 100644 --- a/resources/definitions/gmax15plus.def.json +++ b/resources/definitions/gmax15plus.def.json @@ -48,7 +48,7 @@ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 ;Home X/Y/Z\nM104 S{material_print_temperature} ; Preheat\nM109 S{material_print_temperature} ; Preheat\nG91 ;relative positioning\nG90 ;absolute positioning\nG1 Z25.0 F9000 ;raise nozzle 25mm\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." }, "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-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" }, - "wall_thickness": { "default_value": 1 }, + "wall_thickness": { "value": "1" }, "top_bottom_thickness": { "default_value": 1 } } } diff --git a/resources/definitions/gmax15plus_dual.def.json b/resources/definitions/gmax15plus_dual.def.json index aaba2cc55b..8bfadfc4ba 100644 --- a/resources/definitions/gmax15plus_dual.def.json +++ b/resources/definitions/gmax15plus_dual.def.json @@ -46,7 +46,7 @@ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 ;Home X/Y/Z\nM104 S{material_print_temperature} T0 ; Preheat Left Extruder\nM104 S{material_print_temperature} T1 ; Preheat Right Extruder\nM109 S{material_print_temperature} T0 ; Preheat Left Extruder\nM109 S{material_print_temperature} T1 ; Preheat Right Extruder\nG91 ;relative positioning\nG90 ;absolute positioning\nM218 T1 X34.3 Y0; Set 2nd extruder offset. This can be changed later if needed\nG1 Z25.0 F9000 ;raise nozzle 25mm\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." }, "machine_end_gcode": { "default_value": "M104 S0 T0;Left extruder off\nM104 S0 T1; Right extruder 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" }, - "wall_thickness": { "default_value": 1 }, + "wall_thickness": { "value": "1" }, "top_bottom_thickness": { "default_value": 1 } } } diff --git a/resources/definitions/helloBEEprusa.def.json b/resources/definitions/helloBEEprusa.def.json index 2c8c4839d0..291253f09c 100644 --- a/resources/definitions/helloBEEprusa.def.json +++ b/resources/definitions/helloBEEprusa.def.json @@ -28,7 +28,7 @@ "machine_center_is_zero": { "default_value": false }, "layer_height": { "default_value": 0.2 }, "layer_height_0": { "default_value": 0.2 }, - "wall_thickness": { "default_value": 1.2 }, + "wall_thickness": { "value": "1.2" }, "top_bottom_thickness": { "default_value": 1.2 }, "infill_sparse_density": { "default_value": 20 }, "speed_print": { "default_value": 60 }, diff --git a/resources/definitions/innovo_inventor.def.json b/resources/definitions/innovo_inventor.def.json index df839b0fe4..9001aba923 100644 --- a/resources/definitions/innovo_inventor.def.json +++ b/resources/definitions/innovo_inventor.def.json @@ -56,7 +56,7 @@ "default_value": 0.15 }, "wall_thickness": { - "default_value": 0.8 + "value": "0.8" }, "top_bottom_thickness": { "default_value": 1.2 diff --git a/resources/definitions/jgaurora_a1.def.json b/resources/definitions/jgaurora_a1.def.json index 1c910f0d95..a952949b1f 100644 --- a/resources/definitions/jgaurora_a1.def.json +++ b/resources/definitions/jgaurora_a1.def.json @@ -51,7 +51,7 @@ "default_value": 0.12 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "speed_print": { "default_value": 40 diff --git a/resources/definitions/jgaurora_a3s.def.json b/resources/definitions/jgaurora_a3s.def.json index ead0a5f9e7..2427f961c1 100644 --- a/resources/definitions/jgaurora_a3s.def.json +++ b/resources/definitions/jgaurora_a3s.def.json @@ -51,7 +51,7 @@ "default_value": 0.12 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "speed_print": { "default_value": 35 diff --git a/resources/definitions/jgaurora_a5.def.json b/resources/definitions/jgaurora_a5.def.json index b9f179d38e..a31ad3ec56 100644 --- a/resources/definitions/jgaurora_a5.def.json +++ b/resources/definitions/jgaurora_a5.def.json @@ -53,7 +53,7 @@ "default_value": 0.12 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "speed_print": { "default_value": 40 diff --git a/resources/definitions/jgaurora_jgmaker_magic.def.json b/resources/definitions/jgaurora_jgmaker_magic.def.json index 8d0349a48c..58067b6dd3 100644 --- a/resources/definitions/jgaurora_jgmaker_magic.def.json +++ b/resources/definitions/jgaurora_jgmaker_magic.def.json @@ -51,7 +51,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "speed_print": { "default_value": 60 diff --git a/resources/definitions/jgaurora_z_603s.def.json b/resources/definitions/jgaurora_z_603s.def.json index 8dbf5a82bb..d122500dfb 100644 --- a/resources/definitions/jgaurora_z_603s.def.json +++ b/resources/definitions/jgaurora_z_603s.def.json @@ -51,7 +51,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "speed_print": { "default_value": 60 diff --git a/resources/definitions/makeit_pro_l.def.json b/resources/definitions/makeit_pro_l.def.json index d601a5c309..75479fd5cc 100644 --- a/resources/definitions/makeit_pro_l.def.json +++ b/resources/definitions/makeit_pro_l.def.json @@ -81,7 +81,7 @@ "default_value": 60 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "cool_min_layer_time_fan_speed_max": { "default_value": 5 diff --git a/resources/definitions/makeit_pro_m.def.json b/resources/definitions/makeit_pro_m.def.json index 267646b647..812a4fe901 100644 --- a/resources/definitions/makeit_pro_m.def.json +++ b/resources/definitions/makeit_pro_m.def.json @@ -81,7 +81,7 @@ "default_value": 60 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "cool_min_layer_time_fan_speed_max": { "default_value": 5 diff --git a/resources/definitions/makeit_pro_mx.def.json b/resources/definitions/makeit_pro_mx.def.json index 13770e8571..5f922dcd00 100644 --- a/resources/definitions/makeit_pro_mx.def.json +++ b/resources/definitions/makeit_pro_mx.def.json @@ -81,7 +81,7 @@ "default_value": 60 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "cool_min_layer_time_fan_speed_max": { "default_value": 5 diff --git a/resources/definitions/mankati_fullscale_xt_plus.def.json b/resources/definitions/mankati_fullscale_xt_plus.def.json index b6fa040750..fa5c8465c6 100644 --- a/resources/definitions/mankati_fullscale_xt_plus.def.json +++ b/resources/definitions/mankati_fullscale_xt_plus.def.json @@ -39,7 +39,7 @@ }, "layer_height": { "default_value": 0.2 }, - "wall_thickness": { "default_value": 0.8 }, + "wall_thickness": { "value": "0.8" }, "top_bottom_thickness": { "default_value": 0.3 }, "retraction_enable": { "default_value": true }, "retraction_speed": { "default_value": 50 }, diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index 8d7754a9ef..119d52c201 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -189,7 +189,7 @@ "value": "machine_nozzle_size / 3" }, "wall_thickness": { - "value": 0.5 + "value": "0.5" }, "infill_sparse_density": { "value": 70 diff --git a/resources/definitions/rigidbot.def.json b/resources/definitions/rigidbot.def.json index d6fb4f1651..f20ce1b7ec 100644 --- a/resources/definitions/rigidbot.def.json +++ b/resources/definitions/rigidbot.def.json @@ -44,7 +44,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 0.8 + "value": "0.8" }, "top_bottom_thickness": { "default_value": 0.3 diff --git a/resources/definitions/rigidbot_big.def.json b/resources/definitions/rigidbot_big.def.json index 9568417acc..fcd187706c 100644 --- a/resources/definitions/rigidbot_big.def.json +++ b/resources/definitions/rigidbot_big.def.json @@ -44,7 +44,7 @@ "default_value": 0.2 }, "wall_thickness": { - "default_value": 0.8 + "value": "0.8" }, "top_bottom_thickness": { "default_value": 0.3 diff --git a/resources/definitions/robo_3d_r1.def.json b/resources/definitions/robo_3d_r1.def.json index 36b8addd27..e72b0a2688 100644 --- a/resources/definitions/robo_3d_r1.def.json +++ b/resources/definitions/robo_3d_r1.def.json @@ -31,7 +31,7 @@ "layer_height_0": { "default_value": 0.15 }, "material_flow": { "default_value": 100 }, "infill_sparse_density": { "default_value": 10 }, - "wall_thickness": { "default_value": 1.2 }, + "wall_thickness": { "value": "1.2" }, "retraction_amount": { "default_value": 3 }, "layer_height": { "default_value": 0.2 }, "speed_print": { "default_value": 40 }, diff --git a/resources/definitions/skriware_2.def.json b/resources/definitions/skriware_2.def.json index ad717d774c..4534ea0350 100644 --- a/resources/definitions/skriware_2.def.json +++ b/resources/definitions/skriware_2.def.json @@ -322,7 +322,7 @@ "default_value": 2 }, "wall_thickness": { - "default_value": 1.2 + "value": "1.2" }, "support_infill_sparse_thickness": { "value": "resolveOrValue('layer_height')" diff --git a/resources/definitions/tam.def.json b/resources/definitions/tam.def.json index 0bc68f321a..940e8c6fa0 100644 --- a/resources/definitions/tam.def.json +++ b/resources/definitions/tam.def.json @@ -21,7 +21,7 @@ "layer_height": { "default_value": 0.2 }, "layer_height_0": { "default_value": 0.3 }, "infill_sparse_density": { "default_value": 5 }, - "wall_thickness": { "default_value": 1 }, + "wall_thickness": { "value": "1" }, "top_bottom_thickness": { "default_value": 1 }, "infill_pattern": { "value": "'tetrahedral'" }, diff --git a/resources/definitions/vertex_delta_k8800.def.json b/resources/definitions/vertex_delta_k8800.def.json index c92476da49..71646d76ee 100644 --- a/resources/definitions/vertex_delta_k8800.def.json +++ b/resources/definitions/vertex_delta_k8800.def.json @@ -49,7 +49,7 @@ "value": 0.35 }, "wall_thickness": { - "value": 0.7 + "value": "0.7" }, "top_bottom_thickness": { "value": 0.6 diff --git a/resources/definitions/vertex_nano_k8600.def.json b/resources/definitions/vertex_nano_k8600.def.json index ef9552caf3..9f7b9d2cb7 100644 --- a/resources/definitions/vertex_nano_k8600.def.json +++ b/resources/definitions/vertex_nano_k8600.def.json @@ -47,7 +47,7 @@ "value": 0.35 }, "wall_thickness": { - "value": 0.7 + "value": "0.7" }, "top_bottom_thickness": { "value": 0.6