diff --git a/conandata.yml b/conandata.yml index a0a5a204ca..9b0e2e337b 100644 --- a/conandata.yml +++ b/conandata.yml @@ -6,7 +6,6 @@ requirements: - "fdm_materials/(latest)@ultimaker/testing" - "curaengine_plugin_gradual_flow/(latest)@ultimaker/stable" - "dulcificum/latest@ultimaker/testing" - - "pyarcus/5.3.0" - "pysavitar/5.3.0" - "pynest2d/5.3.0" - "curaengine_grpc_definitions/(latest)@ultimaker/testing" diff --git a/conanfile.py b/conanfile.py index ea1ac2e1f9..ca8427ad70 100644 --- a/conanfile.py +++ b/conanfile.py @@ -242,7 +242,7 @@ class CuraConan(ConanFile): self.output.warning(f"Source path for binary {binary['binary']} does not exist") continue - for bin in Path(src_path).glob(binary["binary"] + "*[.exe|.dll|.so|.dylib|.so.|.pdb]*"): + for bin in Path(src_path).glob(binary["binary"] + "*[.exe|.dll|.so|.dylib|.so.]*"): binaries.append((str(bin), binary["dst"])) for bin in Path(src_path).glob(binary["binary"]): binaries.append((str(bin), binary["dst"])) @@ -320,6 +320,8 @@ class CuraConan(ConanFile): self.options["openssl"].shared = True if self.conf.get("user.curaengine:sentry_url", "", check_type=str) != "": self.options["curaengine"].enable_sentry = True + self.options["arcus"].enable_sentry = True + self.options["clipper"].enable_sentry = True def validate(self): version = self.conf.get("user.cura:version", default = self.version, check_type = str) @@ -335,6 +337,7 @@ class CuraConan(ConanFile): for req in self.conan_data["requirements_internal"]: self.requires(req) self.requires("cpython/3.10.4@ultimaker/stable") + self.requires("clipper/6.4.2@ultimaker/stable") self.requires("openssl/3.2.0") self.requires("boost/1.82.0") self.requires("spdlog/1.12.0") diff --git a/plugins/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto index 9593b83528..238829ba64 100644 --- a/plugins/CuraEngineBackend/Cura.proto +++ b/plugins/CuraEngineBackend/Cura.proto @@ -35,6 +35,8 @@ message Slice repeated EnginePlugin engine_plugins = 5; string sentry_id = 6; // The anonymized Sentry user id that requested the slice string cura_version = 7; // The version of Cura that requested the slice + optional string project_name = 8; // The name of the project that requested the slice + optional string user_name = 9; // The Digital Factory account name of the user that requested the slice } message Extruder diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 818766d766..0c4003fadc 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -164,6 +164,7 @@ class CuraEngineBackend(QObject, Backend): application.getPreferences().addPreference("general/auto_slice", False) application.getPreferences().addPreference("info/send_engine_crash", True) + application.getPreferences().addPreference("info/anonymous_engine_crash_report", True) self._use_timer: bool = False @@ -1094,14 +1095,14 @@ class CuraEngineBackend(QObject, Backend): self._change_timer.timeout.disconnect(self.slice) def _onPreferencesChanged(self, preference: str) -> None: - if preference != "general/auto_slice" and preference != "info/send_engine_crash": + if preference != "general/auto_slice" and preference != "info/send_engine_crash" and preference != "info/anonymous_engine_crash_report": return if preference == "general/auto_slice": auto_slice = self.determineAutoSlicing() if auto_slice: self._change_timer.start() elif preference == "info/send_engine_crash": - os.environ["use_sentry"] = "1" if CuraApplication.getInstance().getPreferences().getValue("info/send_engine_crash") else "0" + os.environ["USE_SENTRY"] = "1" if CuraApplication.getInstance().getPreferences().getValue("info/send_engine_crash") else "0" def tickle(self) -> None: """Tickle the backend so in case of auto slicing, it starts the timer.""" diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 6ede9fa219..3a1d7ce431 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -352,6 +352,12 @@ class StartSliceJob(Job): self._slice_message.sentry_id = f"{user_id}" self._slice_message.cura_version = CuraVersion + # Add the project name to the message if the user allows for non-anonymous crash data collection. + account = CuraApplication.getInstance().getCuraAPI().account + if account and account.isLoggedIn and not CuraApplication.getInstance().getPreferences().getValue("info/anonymous_engine_crash_report"): + self._slice_message.project_name = CuraApplication.getInstance().getPrintInformation().baseName + self._slice_message.user_name = account.userName + # Build messages for extruder stacks for extruder_stack in global_stack.extruderList: self._buildExtruderMessage(extruder_stack) diff --git a/resources/extruders/ultimaker_methodx_extruder_left.def.json b/resources/extruders/ultimaker_methodx_extruder_left.def.json index 7051f056f3..648a1d6a5c 100644 --- a/resources/extruders/ultimaker_methodx_extruder_left.def.json +++ b/resources/extruders/ultimaker_methodx_extruder_left.def.json @@ -14,8 +14,8 @@ "default_value": 0, "maximum_value": "1" }, - "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S255\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM109 S{material_final_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed*255/100}" }, + "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S1.0\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM104 S{material_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed/100}" }, "machine_extruder_start_code_duration": { "default_value": 8 }, "machine_nozzle_offset_x": { "default_value": 0 }, "machine_nozzle_offset_y": { "default_value": 0 }, diff --git a/resources/extruders/ultimaker_methodx_extruder_right.def.json b/resources/extruders/ultimaker_methodx_extruder_right.def.json index 1fea854877..ea52c5dbd2 100644 --- a/resources/extruders/ultimaker_methodx_extruder_right.def.json +++ b/resources/extruders/ultimaker_methodx_extruder_right.def.json @@ -14,8 +14,8 @@ "default_value": 1, "maximum_value": "1" }, - "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S255\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM109 S{material_final_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed*255/100}" }, + "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S1.0\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM104 S{material_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed/100}" }, "machine_extruder_start_code_duration": { "default_value": 8 }, "machine_nozzle_offset_x": { "default_value": 0 }, "machine_nozzle_offset_y": { "default_value": 0 }, diff --git a/resources/extruders/ultimaker_methodxl_extruder_left.def.json b/resources/extruders/ultimaker_methodxl_extruder_left.def.json index 66670fe994..43de74b497 100644 --- a/resources/extruders/ultimaker_methodxl_extruder_left.def.json +++ b/resources/extruders/ultimaker_methodxl_extruder_left.def.json @@ -14,8 +14,8 @@ "default_value": 0, "maximum_value": "1" }, - "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S255\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM109 S{material_final_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed*255/100}" }, + "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S1.0\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM104 S{material_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed/100}" }, "machine_extruder_start_code_duration": { "default_value": 10 }, "machine_nozzle_offset_x": { "default_value": 0 }, "machine_nozzle_offset_y": { "default_value": 0 }, diff --git a/resources/extruders/ultimaker_methodxl_extruder_right.def.json b/resources/extruders/ultimaker_methodxl_extruder_right.def.json index 9f483e39bc..581811646f 100644 --- a/resources/extruders/ultimaker_methodxl_extruder_right.def.json +++ b/resources/extruders/ultimaker_methodxl_extruder_right.def.json @@ -14,8 +14,8 @@ "default_value": 1, "maximum_value": "1" }, - "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S255\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, - "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM109 S{material_final_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed*255/100}" }, + "machine_extruder_end_code": { "default_value": "M106 P{extruder_nr} S1.0\nG91\nG0 Z0.4 F600\nG90\nG0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000" }, + "machine_extruder_start_code": { "default_value": "G0 X{prime_tower_position_x - prime_tower_size/2} Y{prime_tower_position_y + prime_tower_size/2} F6000\nM104 S{material_print_temperature}\nG4 S5\nG91\nG0 Z-0.4 F600\nG90\nM107 P{(extruder_nr+1)%2}\nM106 P{extruder_nr} S{cool_fan_speed/100}" }, "machine_extruder_start_code_duration": { "default_value": 10 }, "machine_nozzle_offset_x": { "default_value": 0 }, "machine_nozzle_offset_y": { "default_value": 0 }, diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 587084444c..8871944523 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -124,6 +124,9 @@ UM.PreferencesPage UM.Preferences.resetPreference("info/send_engine_crash") sendEngineCrashCheckbox.checked = boolCheck(UM.Preferences.getValue("info/send_engine_crash")) + UM.Preferences.resetPreference("info/anonymous_engine_crash_report") + sendEngineCrashCheckboxAnonymous.checked = boolCheck(UM.Preferences.getValue("info/anonymous_engine_crash_report")) + UM.Preferences.resetPreference("info/automatic_update_check") checkUpdatesCheckbox.checked = boolCheck(UM.Preferences.getValue("info/automatic_update_check")) @@ -859,21 +862,63 @@ UM.PreferencesPage font: UM.Theme.getFont("medium_bold") text: catalog.i18nc("@label", "Privacy") } + UM.TooltipArea { width: childrenRect.width height: visible ? childrenRect.height : 0 - text: catalog.i18nc("@info:tooltip", "Should slicing crashes be automatically reported to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored.") + text: catalog.i18nc("@info:tooltip", "Should slicing crashes be automatically reported to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored, unless you give explicit permission.") UM.CheckBox { id: sendEngineCrashCheckbox - text: catalog.i18nc("@option:check","Send (anonymous) engine crash reports") + text: catalog.i18nc("@option:check","Send engine crash reports") checked: boolCheck(UM.Preferences.getValue("info/send_engine_crash")) onCheckedChanged: UM.Preferences.setValue("info/send_engine_crash", checked) } } + ButtonGroup + { + id: curaCrashGroup + buttons: [sendEngineCrashCheckboxAnonymous, sendEngineCrashCheckboxUser] + } + + UM.TooltipArea + { + width: childrenRect.width + height: visible ? childrenRect.height : 0 + text: catalog.i18nc("@info:tooltip", "Send crash reports without any personally identifiable information or models data to UltiMaker.") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + Cura.RadioButton + { + id: sendEngineCrashCheckboxAnonymous + text: catalog.i18nc("@option:radio", "Anonymous crash reports") + enabled: sendEngineCrashCheckbox.checked && Cura.API.account.isLoggedIn + checked: boolCheck(UM.Preferences.getValue("info/anonymous_engine_crash_report")) + onClicked: UM.Preferences.setValue("info/anonymous_engine_crash_report", true) + } + } + UM.TooltipArea + { + width: childrenRect.width + height: visible ? childrenRect.height : 0 + text: Cura.API.account.isLoggedIn ? + catalog.i18nc("@info:tooltip", "Send crash reports with your registered UltiMaker account name and the project name to UltiMaker Sentry. No actual model data is being send.") : + catalog.i18nc("@info:tooltip", "Please sign in to your UltiMaker account to allow sending non-anonymous data.") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + Cura.RadioButton + { + id: sendEngineCrashCheckboxUser + text: catalog.i18nc("@option:radio", "Include UltiMaker account name") + enabled: sendEngineCrashCheckbox.checked && Cura.API.account.isLoggedIn + checked: !boolCheck(UM.Preferences.getValue("info/anonymous_engine_crash_report")) && Cura.API.account.isLoggedIn + onClicked: UM.Preferences.setValue("info/anonymous_engine_crash_report", false) + } + } + UM.TooltipArea { width: childrenRect.width