diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 13a97d5a89..9f4a4b197b 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -46,8 +46,15 @@ class ThreeMFReader(MeshReader): suffixes=["3mf"] ) ) + MimeTypeDatabase.addMimeType( + MimeType( + name="application/x-pcb", + comment="PCB", + suffixes=["pcb"] + ) + ) - self._supported_extensions = [".3mf"] + self._supported_extensions = [".3mf", ".pcb"] self._root = None self._base_name = "" self._unit = None diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index b97cb34b01..76cd1f386b 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -112,7 +112,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): def __init__(self) -> None: super().__init__() - self._supported_extensions = [".3mf"] + self._supported_extensions = [".3mf", ".pcb"] self._dialog = WorkspaceDialog() self._3mf_mesh_reader = None self._container_registry = ContainerRegistry.getInstance() @@ -228,11 +228,14 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._resolve_strategies = {k: None for k in resolve_strategy_keys} containers_found_dict = {k: False for k in resolve_strategy_keys} + # Check whether the file is a PCB + is_pcb = file_name.endswith('.pcb') + # # Read definition containers # machine_definition_id = None - updatable_machines = [] + updatable_machines = None if is_pcb else [] machine_definition_container_count = 0 extruder_definition_container_count = 0 definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)] @@ -250,7 +253,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if definition_container_type == "machine": machine_definition_id = container_id machine_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id) - if machine_definition_containers: + if machine_definition_containers and updatable_machines is not None: updatable_machines = [machine for machine in self._container_registry.findContainerStacks(type = "machine") if machine.definition == machine_definition_containers[0]] machine_type = definition_container["name"] variant_type_name = definition_container.get("variants_name", variant_type_name) @@ -617,6 +620,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._dialog.setVariantType(variant_type_name) self._dialog.setHasObjectsOnPlate(Application.getInstance().platformActivity) self._dialog.setMissingPackagesMetadata(missing_package_metadata) + self._dialog.setHasVisibleSelectSameProfileChanged(is_pcb) self._dialog.show() # Choosing the initially selected printer in MachineSelector diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 0203fc92b5..c5b624d35d 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -71,6 +71,8 @@ class WorkspaceDialog(QObject): self._install_missing_package_dialog: Optional[QObject] = None self._is_abstract_machine = False self._is_networked_machine = False + self._is_compatible_machine = False + self._has_visible_select_same_profile = False machineConflictChanged = pyqtSignal() qualityChangesConflictChanged = pyqtSignal() @@ -94,6 +96,8 @@ class WorkspaceDialog(QObject): extrudersChanged = pyqtSignal() isPrinterGroupChanged = pyqtSignal() missingPackagesChanged = pyqtSignal() + isCompatibleMachineChanged = pyqtSignal() + hasVisibleSelectSameProfileChanged = pyqtSignal() @pyqtProperty(bool, notify = isPrinterGroupChanged) def isPrinterGroup(self) -> bool: @@ -291,8 +295,30 @@ class WorkspaceDialog(QObject): @pyqtSlot(str) def setMachineToOverride(self, machine_name: str) -> None: + registry = ContainerRegistry.getInstance() + containers_expected = registry.findDefinitionContainers(name = self._machine_type) + containers_selected = registry.findContainerStacks(id = machine_name) + if len(containers_expected) == 1 and len(containers_selected) == 1: + new_compatible_machine = (containers_expected[0] == containers_selected[0].definition) + if new_compatible_machine != self._is_compatible_machine: + self._is_compatible_machine = new_compatible_machine + self.isCompatibleMachineChanged.emit() + self._override_machine = machine_name + @pyqtProperty(bool, notify = isCompatibleMachineChanged) + def isCompatibleMachine(self) -> bool: + return self._is_compatible_machine + + def setHasVisibleSelectSameProfileChanged(self, has_visible_select_same_profile): + if has_visible_select_same_profile != self._has_visible_select_same_profile: + self._has_visible_select_same_profile = has_visible_select_same_profile + self.hasVisibleSelectSameProfileChanged.emit() + + @pyqtProperty(bool, notify = hasVisibleSelectSameProfileChanged) + def hasVisibleSelectSameProfile(self): + return self._has_visible_select_same_profile + @pyqtSlot() def closeBackend(self) -> None: """Close the backend: otherwise one could end up with "Slicing...""" diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index d5f9b1817d..45fe7b6989 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -186,6 +186,15 @@ UM.Dialog rightLabelText: catalog.i18ncp("@action:label", "%1, %2 override", "%1, %2 overrides", manager.numSettingsOverridenByQualityChanges).arg(manager.qualityType).arg(manager.numSettingsOverridenByQualityChanges) visible: manager.numSettingsOverridenByQualityChanges != 0 } + + UM.CheckBox + { + text: catalog.i18nc("@action:checkbox", "Select the same profile") + enabled: manager.isCompatibleMachine + onEnabledChanged: checked = enabled + tooltip: enabled ? "" : catalog.i18nc("@tooltip", "You can use the same profile only if you have the same printer as the project was published with") + visible: manager.hasVisibleSelectSameProfile + } } comboboxVisible: manager.qualityChangesConflict diff --git a/plugins/3MFReader/__init__.py b/plugins/3MFReader/__init__.py index 5e2b68fce0..a07420d2c6 100644 --- a/plugins/3MFReader/__init__.py +++ b/plugins/3MFReader/__init__.py @@ -25,12 +25,20 @@ def getMetaData() -> Dict: { "extension": "3mf", "description": catalog.i18nc("@item:inlistbox", "3MF File") + }, + { + "extension": "pcb", + "description": catalog.i18nc("@item:inlistbox", "PCB File") } ] metaData["workspace_reader"] = [ { "extension": workspace_extension, "description": catalog.i18nc("@item:inlistbox", "3MF File") + }, + { + "extension": "pcb", + "description": catalog.i18nc("@item:inlistbox", "PCB File") } ] diff --git a/plugins/3MFReader/plugin.json b/plugins/3MFReader/plugin.json index bf0bc05364..1611c956d3 100644 --- a/plugins/3MFReader/plugin.json +++ b/plugins/3MFReader/plugin.json @@ -2,7 +2,7 @@ "name": "3MF Reader", "author": "Ultimaker B.V.", "version": "1.0.1", - "description": "Provides support for reading 3MF files.", + "description": "Provides support for reading 3MF and PCB files.", "api": 8, "i18n-catalog": "cura" } diff --git a/plugins/3MFWriter/plugin.json b/plugins/3MFWriter/plugin.json index b59d4ef8e1..be6d50267c 100644 --- a/plugins/3MFWriter/plugin.json +++ b/plugins/3MFWriter/plugin.json @@ -2,7 +2,7 @@ "name": "3MF Writer", "author": "Ultimaker B.V.", "version": "1.0.1", - "description": "Provides support for writing 3MF files.", + "description": "Provides support for writing 3MF and PCB files.", "api": 8, "i18n-catalog": "cura" } diff --git a/resources/qml/Menus/FileMenu.qml b/resources/qml/Menus/FileMenu.qml index 36a2820087..a6fb339faf 100644 --- a/resources/qml/Menus/FileMenu.qml +++ b/resources/qml/Menus/FileMenu.qml @@ -77,7 +77,10 @@ Cura.Menu enabled: UM.WorkspaceFileHandler.enabled onTriggered: { - var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/x-pcb" }; + var args = { "filter_by_machine": false, + "file_type": "workspace", + "preferred_mimetypes": "application/x-pcb", + "limit_mimetypes": "application/x-pcb"}; UM.OutputDeviceManager.requestWriteToDevice("local_file", PrintInformation.jobName, args) } }