diff --git a/cura/Machines/Models/DiscoveredPrintersModel.py b/cura/Machines/Models/DiscoveredPrintersModel.py index 6d1bbdb698..37542f438c 100644 --- a/cura/Machines/Models/DiscoveredPrintersModel.py +++ b/cura/Machines/Models/DiscoveredPrintersModel.py @@ -129,6 +129,7 @@ class DiscoveredPrintersModel(QObject): self._discovered_printer_by_ip_dict = dict() # type: Dict[str, DiscoveredPrinter] self._plugin_for_manual_device = None # type: Optional[OutputDevicePlugin] + self._network_plugin_queue = [] # type: List[OutputDevicePlugin] self._manual_device_address = "" self._manual_device_request_timeout_in_seconds = 5 # timeout for adding a manual device in seconds @@ -153,20 +154,25 @@ class DiscoveredPrintersModel(QObject): all_plugins_dict = self._application.getOutputDeviceManager().getAllOutputDevicePlugins() - can_add_manual_plugins = [item for item in filter( + self._network_plugin_queue = [item for item in filter( lambda plugin_item: plugin_item.canAddManualDevice(address) in priority_order, all_plugins_dict.values())] - if not can_add_manual_plugins: + if not self._network_plugin_queue: Logger.log("d", "Could not find a plugin to accept adding %s manually via address.", address) return - plugin = max(can_add_manual_plugins, key = lambda p: priority_order.index(p.canAddManualDevice(address))) - self._plugin_for_manual_device = plugin - self._plugin_for_manual_device.addManualDevice(address, callback = self._onManualDeviceRequestFinished) - self._manual_device_address = address - self._manual_device_request_timer.start() - self.hasManualDeviceRequestInProgressChanged.emit() + self._attemptToAddManualDevice(address) + + def _attemptToAddManualDevice(self, address: str) -> None: + if self._network_plugin_queue: + self._plugin_for_manual_device = self._network_plugin_queue.pop() + Logger.log("d", "Network plugin %s: attempting to add manual device with address %s.", + self._plugin_for_manual_device.getId(), address) + self._plugin_for_manual_device.addManualDevice(address, callback=self._onManualDeviceRequestFinished) + self._manual_device_address = address + self._manual_device_request_timer.start() + self.hasManualDeviceRequestInProgressChanged.emit() @pyqtSlot() def cancelCurrentManualDeviceRequest(self) -> None: @@ -181,8 +187,11 @@ class DiscoveredPrintersModel(QObject): self.manualDeviceRequestFinished.emit(False) def _onManualRequestTimeout(self) -> None: - Logger.log("w", "Manual printer [%s] request timed out. Cancel the current request.", self._manual_device_address) + address = self._manual_device_address + Logger.log("w", "Manual printer [%s] request timed out. Cancel the current request.", address) self.cancelCurrentManualDeviceRequest() + if self._network_plugin_queue: + self._attemptToAddManualDevice(address) hasManualDeviceRequestInProgressChanged = pyqtSignal() @@ -198,6 +207,8 @@ class DiscoveredPrintersModel(QObject): self._manual_device_address = "" self.hasManualDeviceRequestInProgressChanged.emit() self.manualDeviceRequestFinished.emit(success) + if not success and self._network_plugin_queue: + self._attemptToAddManualDevice(address) @pyqtProperty("QVariantMap", notify = discoveredPrintersChanged) def discoveredPrintersByAddress(self) -> Dict[str, DiscoveredPrinter]: diff --git a/cura/Machines/Models/GlobalStacksModel.py b/cura/Machines/Models/GlobalStacksModel.py index 9db4ffe6db..201fbacd30 100644 --- a/cura/Machines/Models/GlobalStacksModel.py +++ b/cura/Machines/Models/GlobalStacksModel.py @@ -19,6 +19,7 @@ class GlobalStacksModel(ListModel): ConnectionTypeRole = Qt.UserRole + 4 MetaDataRole = Qt.UserRole + 5 DiscoverySourceRole = Qt.UserRole + 6 # For separating local and remote printers in the machine management page + RemovalWarningRole = Qt.UserRole + 7 def __init__(self, parent = None) -> None: super().__init__(parent) @@ -65,13 +66,21 @@ class GlobalStacksModel(ListModel): if parseBool(container_stack.getMetaDataEntry("hidden", False)): continue - section_name = "Network enabled printers" if has_remote_connection else "Local printers" + device_name = container_stack.getMetaDataEntry("group_name", container_stack.getName()) + section_name = "Connected printers" if has_remote_connection else "Preset printers" section_name = self._catalog.i18nc("@info:title", section_name) - items.append({"name": container_stack.getMetaDataEntry("group_name", container_stack.getName()), + default_removal_warning = self._catalog.i18nc( + "@label ({} is object name)", + "Are you sure you wish to remove {}? This cannot be undone!", device_name + ) + removal_warning = container_stack.getMetaDataEntry("removal_warning", default_removal_warning) + + items.append({"name": device_name, "id": container_stack.getId(), "hasRemoteConnection": has_remote_connection, "metadata": container_stack.getMetaData().copy(), - "discoverySource": section_name}) - items.sort(key = lambda i: (not i["hasRemoteConnection"], i["name"])) + "discoverySource": section_name, + "removalWarning": removal_warning}) + items.sort(key=lambda i: (not i["hasRemoteConnection"], i["name"])) self.setItems(items) diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py index b5f5fb4540..c1e6a352b9 100644 --- a/cura/Scene/ConvexHullDecorator.py +++ b/cura/Scene/ConvexHullDecorator.py @@ -224,7 +224,7 @@ class ConvexHullDecorator(SceneNodeDecorator): if self._node is None: return None if self._node.callDecoration("isGroup"): - points = numpy.zeros((0, 2), dtype=numpy.int32) + points = numpy.zeros((0, 2), dtype = numpy.int32) for child in self._node.getChildren(): child_hull = child.callDecoration("_compute2DConvexHull") if child_hull: @@ -268,7 +268,7 @@ class ConvexHullDecorator(SceneNodeDecorator): # Do not throw away vertices: the convex hull may be too small and objects can collide. # vertex_data = vertex_data[vertex_data[:,1] >= -0.01] - if len(vertex_data) >= 4: # type: ignore # mypy and numpy don't play along well just yet. + if vertex_data is not None and len(vertex_data) >= 4: # type: ignore # mypy and numpy don't play along well just yet. # Round the vertex data to 1/10th of a mm, then remove all duplicate vertices # This is done to greatly speed up further convex hull calculations as the convex hull # becomes much less complex when dealing with highly detailed models. diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 6ab72b029c..6c3c296d28 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -589,7 +589,15 @@ class ThreeMFWorkspaceReader(WorkspaceReader): def read(self, file_name): application = CuraApplication.getInstance() - archive = zipfile.ZipFile(file_name, "r") + try: + archive = zipfile.ZipFile(file_name, "r") + except EnvironmentError as e: + message = Message(i18n_catalog.i18nc("@info:error Don't translate the XML tags or !", + "Project file {0} is suddenly inaccessible: {1}.", file_name, str(e)), + title = i18n_catalog.i18nc("@info:title", "Can't Open Project File")) + message.show() + self.setWorkspaceName("") + return [], {} cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")] diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index f233e59fe5..3322bbd639 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -265,6 +265,13 @@ class CloudOutputDeviceManager: machine.setName(device.name) machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key) machine.setMetaDataEntry("group_name", device.name) + machine.setMetaDataEntry("removal_warning", self.I18N_CATALOG.i18nc( + "@label ({} is printer name)", + "{} will be removed until the next account sync.
To remove {} permanently, " + "visit Ultimaker Digital Factory. " + "

Are you sure you want to remove {} temporarily?", + device.name, device.name, device.name + )) machine.addConfiguredConnectionType(device.connectionType.value) def _connectToOutputDevice(self, device: CloudOutputDevice, machine: GlobalStack) -> None: diff --git a/plugins/VersionUpgrade/VersionUpgrade462to47/VersionUpgrade462to47.py b/plugins/VersionUpgrade/VersionUpgrade462to47/VersionUpgrade462to47.py index 7b328e10e6..70de42ab3b 100644 --- a/plugins/VersionUpgrade/VersionUpgrade462to47/VersionUpgrade462to47.py +++ b/plugins/VersionUpgrade/VersionUpgrade462to47/VersionUpgrade462to47.py @@ -64,7 +64,11 @@ class VersionUpgrade462to47(VersionUpgrade): ironing_inset = parser["values"]["ironing_inset"] if ironing_inset.startswith("="): ironing_inset = ironing_inset[1:] - ironing_inset = "=(" + ironing_inset + ") + skin_line_width * (1.0 - ironing_flow) / 2" + if "ironing_pattern" in parser["values"] and parser["values"]["ironing_pattern"] == "concentric": + correction = " + ironing_line_spacing - skin_line_width * (1.0 + ironing_flow / 100) / 2" + else: # If ironing_pattern doesn't exist, it means the default (zigzag) is selected + correction = " + skin_line_width * (1.0 - ironing_flow / 100) / 2" + ironing_inset = "=(" + ironing_inset + ")" + correction parser["values"]["ironing_inset"] = ironing_inset result = io.StringIO() diff --git a/resources/definitions/I3MetalMotion.def.json b/resources/definitions/I3MetalMotion.def.json new file mode 100644 index 0000000000..01dcc06ebe --- /dev/null +++ b/resources/definitions/I3MetalMotion.def.json @@ -0,0 +1,33 @@ +{ + "version": 2, + "name": "I3MetalMotion", + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "Peter Felecan", + "manufacturer": "eMotionTech", + "file_formats": "text/x-gcode", + "has_materials": true, + "preferred_material": "emotiontech_pla", + "machine_extruder_trains": + { + "0": "I3MetalMotion_extruder_0" + } + }, + + "overrides": { + "machine_name": { "default_value": "I3MetalMotion" }, + "machine_heated_bed": { "default_value": true }, + "machine_width": { "default_value": 200 }, + "machine_height": { "default_value": 200 }, + "machine_depth": { "default_value": 200 }, + "machine_center_is_zero": { "default_value": false }, + "machine_gcode_flavor": { "default_value": "RepRap (RepRap)" }, + "machine_start_gcode": { + "default_value": "G21 ; set units to millimeters\nG90 ; use absolute positioning\nM82 ; absolute extrusion mode\nM104 S{material_print_temperature_layer_0} ; set extruder temp\nM140 S{material_bed_temperature_layer_0} ; set bed temp\nM190 S{material_bed_temperature_layer_0} ; wait for bed temp\nM109 S{material_print_temperature_layer_0} ; wait for extruder temp\nG28 W ; home all\nG92 E0.0 ; reset extruder distance position\nG1 Y-3.0 F1000.0 ; go outside print area\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E21.5 F1000.0 ; intro line\nG92 E0.0 ; reset extruder distance position" + }, + "machine_end_gcode": { + "default_value": "G28 Z\nG28 X\nG28 Y\nM107 ; Turn off the fan\nG91; Relative positioning\nG1 E-1 ; reduce filament pressure\nM104 T0 S0\nG90 ; Absolute positioning\nG92 E0 ; Reset extruder position\nM140 S0 ; Disable heated bed\nM84 ; Turn the steppers off" + } + } +} diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 41031dbe2c..9ab33b3a6c 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1575,7 +1575,7 @@ "type": "float", "unit": "mm", "default_value": 0.35, - "value": "wall_line_width_0 / 2 + skin_line_width * (1.0 - ironing_flow) / 2", + "value": "wall_line_width_0 / 2 + (ironing_line_spacing - skin_line_width * (1.0 + ironing_flow / 100) / 2 if ironing_pattern == 'concentric' else skin_line_width * (1.0 - ironing_flow / 100) / 2)", "minimum_value_warning": "0", "maximum_value_warning": "wall_line_width_0", "enabled": "ironing_enabled", @@ -1761,7 +1761,7 @@ "description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees for the lines and zig zag patterns and 45 degrees for all other patterns).", "type": "[int]", "default_value": "[ ]", - "enabled": "infill_pattern != 'concentric' and infill_pattern != 'cubicsubdiv' and infill_sparse_density > 0", + "enabled": "infill_pattern != 'concentric' and infill_sparse_density > 0", "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, diff --git a/resources/definitions/hms434.def.json b/resources/definitions/hms434.def.json index 07ea24b2c2..cd20906ccc 100644 --- a/resources/definitions/hms434.def.json +++ b/resources/definitions/hms434.def.json @@ -104,7 +104,7 @@ "skin_outline_count": {"value": "0"}, "ironing_line_spacing": {"value": "line_width / 4 * 3"}, "ironing_flow": {"value": "0"}, - "ironing_inset": {"value": "ironing_line_spacing + skin_line_width * (1.0 - ironing_flow) / 2"}, + "ironing_inset": {"value": "ironing_line_spacing + (ironing_line_spacing - skin_line_width * (1.0 + ironing_flow / 100) / 2 if ironing_pattern == 'concentric' else skin_line_width * (1.0 - ironing_flow / 100) / 2)"}, "speed_ironing": {"value": "150"}, "infill_sparse_density": {"value": 30}, diff --git a/resources/definitions/skriware_2.def.json b/resources/definitions/skriware_2.def.json index 3b127b9a8f..ab5532db81 100644 --- a/resources/definitions/skriware_2.def.json +++ b/resources/definitions/skriware_2.def.json @@ -345,7 +345,7 @@ "value": "0.8" }, "ironing_inset": { - "value": "0.2 + skin_line_width * (1.0 - ironing_flow) / 2" + "value": "0.2 + (ironing_line_spacing - skin_line_width * (1.0 + ironing_flow / 100) / 2 if ironing_pattern == 'concentric' else skin_line_width * (1.0 - ironing_flow / 100) / 2)" }, "jerk_travel": { "value": "10" diff --git a/resources/definitions/tevo_tarantula.def.json b/resources/definitions/tevo_tarantula.def.json index a12bff24f8..eee773cd74 100644 --- a/resources/definitions/tevo_tarantula.def.json +++ b/resources/definitions/tevo_tarantula.def.json @@ -11,7 +11,8 @@ "platform": "prusai3_platform.3mf", "machine_extruder_trains": { - "0": "tevo_tarantula_extruder_0" + "0": "tevo_tarantula_extruder_0", + "1": "tevo_tarantula_extruder_1" } }, diff --git a/resources/definitions/tevo_tarantula_pro.def.json b/resources/definitions/tevo_tarantula_pro.def.json index b53c59062b..793942a50b 100644 --- a/resources/definitions/tevo_tarantula_pro.def.json +++ b/resources/definitions/tevo_tarantula_pro.def.json @@ -11,7 +11,8 @@ "has_materials": true, "machine_extruder_trains": { - "0": "tevo_tarantula_pro_extruder_0" + "0": "tevo_tarantula_pro_extruder_0", + "1": "tevo_tarantula_pro_extruder_1" } }, diff --git a/resources/extruders/I3MetalMotion_extruder_0.def.json b/resources/extruders/I3MetalMotion_extruder_0.def.json new file mode 100644 index 0000000000..064e1360b6 --- /dev/null +++ b/resources/extruders/I3MetalMotion_extruder_0.def.json @@ -0,0 +1,17 @@ +{ + + "version": 2, + "name": "I3MetalMotion extruder", + "inherits": "fdmextruder", + "metadata": { + "machine": "I3MetalMotion", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "material_diameter": { "default_value": 1.75 }, + "machine_nozzle_offset_x": { "default_value": 0 }, + "machine_nozzle_offset_y": { "default_value": 0 } + } +} diff --git a/resources/extruders/tevo_tarantula_extruder_1.def.json b/resources/extruders/tevo_tarantula_extruder_1.def.json new file mode 100644 index 0000000000..20d4c7004a --- /dev/null +++ b/resources/extruders/tevo_tarantula_extruder_1.def.json @@ -0,0 +1,15 @@ +{ + "version": 2, + "name": "Extruder 2", + "inherits": "fdmextruder", + "metadata": { + "machine": "tevo_tarantula", + "position": "1" + }, + + "overrides": { + "extruder_nr": { "default_value": 1 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/extruders/tevo_tarantula_pro_extruder_1.def.json b/resources/extruders/tevo_tarantula_pro_extruder_1.def.json new file mode 100644 index 0000000000..f02e74efff --- /dev/null +++ b/resources/extruders/tevo_tarantula_pro_extruder_1.def.json @@ -0,0 +1,15 @@ +{ + "version": 2, + "name": "Extruder 2", + "inherits": "fdmextruder", + "metadata": { + "machine": "tevo_tarantula_pro", + "position": "1" + }, + + "overrides": { + "extruder_nr": { "default_value": 1 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 404c961a90..caf01b518c 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -154,7 +154,7 @@ UM.PreferencesPage Component.onCompleted: { append({ text: "English", code: "en_US" }) - append({ text: "Czech", code: "cs_CZ" }) + append({ text: "Čeština", code: "cs_CZ" }) append({ text: "Deutsch", code: "de_DE" }) append({ text: "Español", code: "es_ES" }) //Finnish is disabled for being incomplete: append({ text: "Suomi", code: "fi_FI" }) diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index a3a8ec0e29..5341af65db 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -136,6 +136,7 @@ UM.ManagementPage { id: confirmDialog object: base.currentItem && base.currentItem.name ? base.currentItem.name : "" + text: base.currentItem ? base.currentItem.removalWarning : ""; onYes: { Cura.MachineManager.removeMachine(base.currentItem.id)