From 6a93c2db43c4634e75b73577692e6b1a5f2f5e66 Mon Sep 17 00:00:00 2001 From: MariMakes <40423138+MariMakes@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:39:14 +0200 Subject: [PATCH 01/11] Update changelog for stable Contributes to CURA-12783 --- resources/texts/change_log.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/resources/texts/change_log.txt b/resources/texts/change_log.txt index d1f756f077..65e54d6c6b 100644 --- a/resources/texts/change_log.txt +++ b/resources/texts/change_log.txt @@ -24,6 +24,25 @@ - Updated Insert At Layerchange post processing plug-in to allow for lowercase commands, resolves https://github.com/Ultimaker/Cura/issues/20441 - Introduced a Post Processing Script that allows for defining Z-Hop on Travel, contributed by @GregValiant +* Bugs resolved since the Beta release: +- Improved slicing time on Windows machines making it significantly faster for a number of models +- Introduced Top Surface Extension setting to improve quality of details like text on the top of prints +- Updated traveling directions for monotonic top surface, to reduce traveling and improve part quality +- Fixed a bug where drawing closed shapes would not respect the drawn lines but would close filled shapes +- Introduced a workaround for deprecated face selection methods to remain backwards compatible for plugins +- Multi material settings are now settable per mesh +- Fixed a bug where you had to reslice to see your preview again after saving or sending the model +- Fixed group handling for painting features, and disabled painting for grouped objects because the painting is currently designed to allow painting a single object at once +- Fixed a bug where Cura would crash if you switched to another printer with a painted model +- Fixed a bug where the model and a prime tower could collide when a model was painted +- Fixed a bug where you could paint with an disabled extruder +- Improved handling of rotating your model when you are in paint on mode +- Updated settings to improve overhang, top/bottom settings on the UltiMaker S6 and S8 +- Updated settings to improve the Z seam settings for Factor 4 +- Fixed a bug with the translations where French translations had some Italian text in them on the recommended window +- Fixed a bug where the Makerbot Repicator+ could not start a print with a smart extruder+ +- Introduced messages when you cannot start a printjob over network because the printer Requires Authentication + * Bug fixes: - Fixed a bug where Cura would not start if you have an extremely strict AntiVirus program installed on the same PC - Fixed a bug on Mac where Pop Up Windows would hide behind the main window From 6f41127628c769d3acbfa708664fe7b6eee40357 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 22 Oct 2025 12:16:59 +0200 Subject: [PATCH 02/11] Make sure to require authentication again. ... even if it was previously obtained in the session, but something changed (on, say, the printers side). done as part of CURA-12717 --- plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py b/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py index a87f4d442b..199fd78f29 100644 --- a/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py @@ -302,6 +302,9 @@ class ClusterApiClient: if reply.error() != QNetworkReply.NetworkError.NoError: if reply.error() == QNetworkReply.NetworkError.AuthenticationRequiredError: + self._auth_id = None + self._auth_key = None + nonce_match = re.search(r'nonce="([^"]+)', str(reply.rawHeader(b"WWW-Authenticate"))) if nonce_match: self._nonce = nonce_match.group(1) From cd3aa024402f5afeceb4b5beff561436c15b6094 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 22 Oct 2025 12:19:26 +0200 Subject: [PATCH 03/11] Show the user a warning when the printer requires authentication. Also hide it when appropriate. part of CURA-12717 --- .../Messages/AuthorizationRequiredMessage.py | 34 +++++++++++++++++++ .../src/Network/ClusterApiClient.py | 11 ++++-- .../src/Network/LocalClusterOutputDevice.py | 13 ++++++- .../LocalClusterOutputDeviceManager.py | 11 +++++- 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 plugins/UM3NetworkPrinting/src/Messages/AuthorizationRequiredMessage.py diff --git a/plugins/UM3NetworkPrinting/src/Messages/AuthorizationRequiredMessage.py b/plugins/UM3NetworkPrinting/src/Messages/AuthorizationRequiredMessage.py new file mode 100644 index 0000000000..7dc95c554f --- /dev/null +++ b/plugins/UM3NetworkPrinting/src/Messages/AuthorizationRequiredMessage.py @@ -0,0 +1,34 @@ +# Copyright (c) 2025 UltiMaker +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.Message import Message + + +class AuthorizationRequiredMessage: + + _inner_message_instance = None + class InnerMessage(Message): + def __init__(self, printer_name: str, err_message: str) -> None: + super().__init__( + text = printer_name, + title = err_message, + message_type = Message.MessageType.WARNING, + lifetime = 0 + ) + + @classmethod + def _getInstance(cls) -> Message: + if cls._inner_message_instance is None: + cls._inner_message_instance = cls.InnerMessage("", "") + return cls._inner_message_instance + + @classmethod + def show(cls, printer_name: str, err_message: str) -> None: + msg = cls._getInstance() + msg.setText(printer_name) + msg.setTitle(err_message) + msg.show() + + @classmethod + def hide(cls) -> None: + cls._getInstance().hide() diff --git a/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py b/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py index 199fd78f29..d483e3d862 100644 --- a/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py @@ -16,6 +16,7 @@ from UM.Logger import Logger from cura.CuraApplication import CuraApplication +from ..Messages.AuthorizationRequiredMessage import AuthorizationRequiredMessage from ..Models.BaseModel import BaseModel from ..Models.Http.ClusterPrintJobStatus import ClusterPrintJobStatus from ..Models.Http.ClusterPrinterStatus import ClusterPrinterStatus @@ -56,7 +57,7 @@ class ClusterApiClient: # In order to avoid garbage collection we keep the callbacks in this list. _anti_gc_callbacks = [] # type: List[Callable[[], None]] - def __init__(self, address: str, on_error: Callable) -> None: + def __init__(self, address: str, on_error: Callable, on_auth_required: Callable) -> None: """Initializes a new cluster API client. :param address: The network address of the cluster to call. @@ -68,6 +69,7 @@ class ClusterApiClient: self._on_error = on_error self._auth_tries = 0 + self._on_auth_required = on_auth_required prefs = CuraApplication.getInstance().getPreferences() prefs.addPreference("cluster_api/auth_ids", "{}") @@ -305,6 +307,7 @@ class ClusterApiClient: self._auth_id = None self._auth_key = None + self._on_auth_required(reply.errorString()) nonce_match = re.search(r'nonce="([^"]+)', str(reply.rawHeader(b"WWW-Authenticate"))) if nonce_match: self._nonce = nonce_match.group(1) @@ -312,9 +315,13 @@ class ClusterApiClient: self._setLocalValueToPrefDict("cluster_api/nonce_counts", self._nonce_count) self._setLocalValueToPrefDict("cluster_api/nonces", self._nonce) CuraApplication.getInstance().savePreferences() - self._on_error(reply.errorString()) + else: + self._on_error(reply.errorString()) return + if self._auth_id and self._auth_key and self._nonce_count > 1: + AuthorizationRequiredMessage.hide() + # If no parse model is given, simply return the raw data in the callback. if not model: on_finished(reply.readAll()) diff --git a/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py b/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py index f51ff5a4e8..8ce237b22b 100644 --- a/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDevice.py @@ -21,6 +21,7 @@ from cura.PrinterOutput.PrinterOutputDevice import ConnectionType from .ClusterApiClient import ClusterApiClient from .SendMaterialJob import SendMaterialJob from ..ExportFileJob import ExportFileJob +from ..Messages.AuthorizationRequiredMessage import AuthorizationRequiredMessage from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice from ..Messages.PrintJobUploadBlockedMessage import PrintJobUploadBlockedMessage from ..Messages.PrintJobUploadErrorMessage import PrintJobUploadErrorMessage @@ -239,9 +240,19 @@ class LocalClusterOutputDevice(UltimakerNetworkedPrinterOutputDevice): if print_job.getPreviewImage() is None: self.getApiClient().getPrintJobPreviewImage(print_job.key, print_job.updatePreviewImageData) + def _onAuthRequired(self, error_msg: str) -> None: + active_name = CuraApplication.getInstance().getOutputDeviceManager().getActiveDevice().getName() + if self._name == active_name: + Logger.info(f"Authorization required for {self._name}: {error_msg}") + AuthorizationRequiredMessage.show(self._name, error_msg) + def getApiClient(self) -> ClusterApiClient: """Get the API client instance.""" if not self._cluster_api: - self._cluster_api = ClusterApiClient(self.address, on_error = lambda error: Logger.log("e", str(error))) + self._cluster_api = ClusterApiClient( + self._address, + on_error = lambda error: Logger.log("e", str(error)), + on_auth_required = self._onAuthRequired + ) return self._cluster_api diff --git a/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py index d35e409086..2b99a1410d 100644 --- a/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py @@ -15,6 +15,7 @@ from cura.Settings.GlobalStack import GlobalStack from .ZeroConfClient import ZeroConfClient from .ClusterApiClient import ClusterApiClient from .LocalClusterOutputDevice import LocalClusterOutputDevice +from ..Messages.AuthorizationRequiredMessage import AuthorizationRequiredMessage from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice from ..Messages.CloudFlowMessage import CloudFlowMessage from ..Messages.LegacyDeviceNoLongerSupportedMessage import LegacyDeviceNoLongerSupportedMessage @@ -44,6 +45,7 @@ class LocalClusterOutputDeviceManager: # Persistent dict containing the networked clusters. self._discovered_devices = {} # type: Dict[str, LocalClusterOutputDevice] self._output_device_manager = CuraApplication.getInstance().getOutputDeviceManager() + self._output_device_manager.activeDeviceChanged.connect(self._onActiveDeviceChanged) # Hook up ZeroConf client. self._zero_conf_client = ZeroConfClient() @@ -69,10 +71,17 @@ class LocalClusterOutputDeviceManager: self.stop() self.start() + def _onActiveDeviceChanged(self): + AuthorizationRequiredMessage.hide() + + def _onAuthRequired(self, error_msg: str) -> None: + Logger.info(f"Authorization required: {error_msg}") + AuthorizationRequiredMessage.show("", error_msg) + def addManualDevice(self, address: str, callback: Optional[Callable[[bool, str], None]] = None) -> None: """Add a networked printer manually by address.""" - api_client = ClusterApiClient(address, lambda error: Logger.log("e", str(error))) + api_client = ClusterApiClient(address, lambda error: Logger.log("e", str(error)), self._onAuthRequired) api_client.getSystem(lambda status: self._onCheckManualDeviceResponse(address, status, callback)) def removeManualDevice(self, device_id: str, address: Optional[str] = None) -> None: From b6f944a429290dfde3988480f7752ded56f6e99b Mon Sep 17 00:00:00 2001 From: Mariska <40423138+MariMakes@users.noreply.github.com> Date: Thu, 23 Oct 2025 10:53:05 +0200 Subject: [PATCH 04/11] Resolve comments Resolved comments --- resources/texts/change_log.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/texts/change_log.txt b/resources/texts/change_log.txt index 65e54d6c6b..b5ba0a535d 100644 --- a/resources/texts/change_log.txt +++ b/resources/texts/change_log.txt @@ -28,15 +28,15 @@ - Improved slicing time on Windows machines making it significantly faster for a number of models - Introduced Top Surface Extension setting to improve quality of details like text on the top of prints - Updated traveling directions for monotonic top surface, to reduce traveling and improve part quality -- Fixed a bug where drawing closed shapes would not respect the drawn lines but would close filled shapes +- Fixed a bug where painting closed shapes would not respect the drawn lines but would close filled shapes - Introduced a workaround for deprecated face selection methods to remain backwards compatible for plugins - Multi material settings are now settable per mesh - Fixed a bug where you had to reslice to see your preview again after saving or sending the model - Fixed group handling for painting features, and disabled painting for grouped objects because the painting is currently designed to allow painting a single object at once - Fixed a bug where Cura would crash if you switched to another printer with a painted model - Fixed a bug where the model and a prime tower could collide when a model was painted -- Fixed a bug where you could paint with an disabled extruder -- Improved handling of rotating your model when you are in paint on mode +- Fixed a bug where you could slice with a painted disabled extruder +- Improved handling of rotating your view when you are in paint on mode - Updated settings to improve overhang, top/bottom settings on the UltiMaker S6 and S8 - Updated settings to improve the Z seam settings for Factor 4 - Fixed a bug with the translations where French translations had some Italian text in them on the recommended window From 28178153cfe274bdbc6542beab14f9507988b9e4 Mon Sep 17 00:00:00 2001 From: Mariska <40423138+MariMakes@users.noreply.github.com> Date: Thu, 23 Oct 2025 10:56:17 +0200 Subject: [PATCH 05/11] Update known issues Removed the mention of Intent for stable, and added the one with the overlapping meshes. CURA-12783 --- resources/texts/change_log.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/resources/texts/change_log.txt b/resources/texts/change_log.txt index b5ba0a535d..6230a99672 100644 --- a/resources/texts/change_log.txt +++ b/resources/texts/change_log.txt @@ -91,11 +91,10 @@ - Introduced BIQU B2, contributed by @bjuraga - Introduced Geetech M1 and Geetech M1S Profiles, and updated the Geetech Thunder Profiles, contributed by @whoseyoung -* Known Issues, but we intend to resolve them for stable -- Painting can still be slow with very detailed models -- Prime tower area is not displayed nor considered when using multi-material via painting -- Painting does not work on models contained in a group -- Painting undo/redo/clear does not invalidate the slice result +* Known Issues +- When using a model with overlapping meshes, the paint on material may produce unexpected results +- Painting might still be slow with very detailed models + [5.10.2] From 0a07a6acd470f4cecf13129e6fbb52b25febc6b5 Mon Sep 17 00:00:00 2001 From: Mariska <40423138+MariMakes@users.noreply.github.com> Date: Thu, 23 Oct 2025 11:00:43 +0200 Subject: [PATCH 06/11] Update name of Replicator extruder For CURA-12783 Co-authored-by: Casper Lamboo --- resources/texts/change_log.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/texts/change_log.txt b/resources/texts/change_log.txt index 6230a99672..8041097e89 100644 --- a/resources/texts/change_log.txt +++ b/resources/texts/change_log.txt @@ -40,7 +40,7 @@ - Updated settings to improve overhang, top/bottom settings on the UltiMaker S6 and S8 - Updated settings to improve the Z seam settings for Factor 4 - Fixed a bug with the translations where French translations had some Italian text in them on the recommended window -- Fixed a bug where the Makerbot Repicator+ could not start a print with a smart extruder+ +- Fixed a bug where the Makerbot Repicator+ could not start a print with a Smart Extruder+ Tough - Introduced messages when you cannot start a printjob over network because the printer Requires Authentication * Bug fixes: From a32bf1c75305945d2a641af3976d14e2db096f2c Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 23 Oct 2025 11:25:13 +0200 Subject: [PATCH 07/11] Update resources/texts/change_log.txt --- resources/texts/change_log.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/texts/change_log.txt b/resources/texts/change_log.txt index 8041097e89..4cd8cde2c1 100644 --- a/resources/texts/change_log.txt +++ b/resources/texts/change_log.txt @@ -40,7 +40,7 @@ - Updated settings to improve overhang, top/bottom settings on the UltiMaker S6 and S8 - Updated settings to improve the Z seam settings for Factor 4 - Fixed a bug with the translations where French translations had some Italian text in them on the recommended window -- Fixed a bug where the Makerbot Repicator+ could not start a print with a Smart Extruder+ Tough +- Fixed a bug where the Makerbot Replicator+ could not start a print with a Smart Extruder+ Tough - Introduced messages when you cannot start a printjob over network because the printer Requires Authentication * Bug fixes: From 2e8bb25ccc3a87b6b37a479e146824376795ba83 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 23 Oct 2025 11:40:20 +0200 Subject: [PATCH 08/11] Lower the warning value for roofing_expansion --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 0dc68790e0..09cd190e56 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1551,7 +1551,7 @@ "default_value": "0", "value": "0", "minimum_value": "0", - "maximum_value_warning": "roofing_line_width * 10", + "maximum_value_warning": "roofing_line_width * 3", "enabled": "roofing_layer_count > 0 and top_layers > 0", "limit_to_extruder": "roofing_extruder_nr", "settable_per_mesh": true From 510100df1ae598155b1786007c9262d5d84a096e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 24 Oct 2025 14:22:42 +0200 Subject: [PATCH 09/11] Bump version to 5.12 --- conandata.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/conandata.yml b/conandata.yml index 5500df2f22..2aa9cb7781 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,17 +1,17 @@ -version: "5.11.0" +version: "5.12.0-alpha.0" commit: "unknown" requirements: - - "cura_resources/5.11.0" - - "uranium/5.11.0" - - "curaengine/5.11.0" - - "cura_binary_data/5.11.0" - - "fdm_materials/5.11.0" + - "cura_resources/5.12.0-alpha.0" + - "uranium/5.12.0-alpha.0" + - "curaengine/5.12.0-alpha.0" + - "cura_binary_data/5.12.0-alpha.0" + - "fdm_materials/5.12.0-alpha.0" - "dulcificum/5.10.0" - "pysavitar/5.11.0-alpha.0" - "pynest2d/5.10.0" requirements_internal: - - "fdm_materials/5.11.0" - - "cura_private_data/5.11.0-alpha.0@internal/testing" + - "fdm_materials/5.12.0-alpha.0" + - "cura_private_data/5.12.0-alpha.0@internal/testing" requirements_enterprise: - "native_cad_plugin/2.0.0" urls: From eeca0aa7b649d54d5cef5849f20db26fe0e691ec Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 28 Oct 2025 09:30:14 +0100 Subject: [PATCH 10/11] Accumulated errors weren't (cast to) strings. Fixes Sentry issue CURA-'9HY'. --- 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 503b39547a..916a0f80fd 100644 --- a/plugins/CuraDrive/src/RestoreBackupJob.py +++ b/plugins/CuraDrive/src/RestoreBackupJob.py @@ -157,7 +157,7 @@ class RestoreBackupJob(Job): Logger.info("All packages redownloaded!") self._job_done.set() else: - msgs = "\n - ".join(redownload_errors) + msgs = "\n".join([" - " + str(x) for x in redownload_errors]) Logger.error(f"Couldn't re-install at least one package(s) because: {msgs}") self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE self._job_done.set() From c86934bd6df663fad3054f1cf345311a3d905438 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 28 Oct 2025 09:32:42 +0100 Subject: [PATCH 11/11] Defensive programming: In case returns aren't boolean. Apparently this can occur -- has at least once according to Sentry issue CURA-'9K9', which this attempts to fix. --- cura/Settings/ExtruderManager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index a0ec63e1cf..a2554f2e34 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -248,11 +248,11 @@ class ExtruderManager(QObject): stack_to_use = container_registry.findContainerStacks(id = extruder_stack_id)[0] if not support_enabled: - support_enabled |= stack_to_use.getProperty("support_enable", "value") + support_enabled |= parseBool(stack_to_use.getProperty("support_enable", "value")) if not support_bottom_enabled: - support_bottom_enabled |= stack_to_use.getProperty("support_bottom_enable", "value") + support_bottom_enabled |= parseBool(stack_to_use.getProperty("support_bottom_enable", "value")) if not support_roof_enabled: - support_roof_enabled |= stack_to_use.getProperty("support_roof_enable", "value") + support_roof_enabled |= parseBool(stack_to_use.getProperty("support_roof_enable", "value")) painted_extruders = node.callDecoration("getPaintedExtruders") if painted_extruders is not None: