From 98cc87d1cfd2838edfd2f58f50183ca6425dd293 Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Wed, 29 Jul 2020 13:02:34 +0200 Subject: [PATCH 01/12] Allow picking any printer of the same type when opening project file A ComboBox was added under the "Update existing" combobox which will display all the available printers that are of the same type with the printer in the project file. With this feature, the user will be able to select any same-type preexisting printer in Cura to be updated, instead of always create a new one when the project file's printer is not in Cura. CURA-7609 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 30 +++++++----- plugins/3MFReader/WorkspaceDialog.py | 23 +++++++++ plugins/3MFReader/WorkspaceDialog.qml | 53 ++++++++++++++++----- 3 files changed, 82 insertions(+), 24 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 664b14afa1..242e4a1223 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -133,12 +133,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # In Cura 2.5 and 2.6, the empty profiles used to have those long names self._old_empty_profile_id_dict = {"empty_%s" % k: "empty" for k in ["material", "variant"]} - self._is_same_machine_type = False + # self._is_same_machine_type = False self._old_new_materials = {} # type: Dict[str, str] self._machine_info = None def _clearState(self): - self._is_same_machine_type = False + # self._is_same_machine_type = False self._id_mapping = {} self._old_new_materials = {} self._machine_info = None @@ -229,6 +229,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Read definition containers # machine_definition_id = None + available_machines = [] 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)] @@ -244,7 +245,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader): definition_container_type = definition_container.get("type") if definition_container_type == "machine": - machine_definition_id = container_id + machine_definition_id = container_id # TODO + my_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id) + available_machines = [i.name for i in self._container_registry.findContainerStacks(type = "machine") if + i.definition == my_definition_containers[0]] machine_type = definition_container["name"] variant_type_name = definition_container.get("variants_name", variant_type_name) @@ -386,8 +390,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): machine_definition_id = id_list[7] stacks = self._container_registry.findContainerStacks(name = machine_name, type = "machine") - self._is_same_machine_type = True + # self._is_same_machine_type = True existing_global_stack = None + global_stack = None if stacks: global_stack = stacks[0] @@ -400,7 +405,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if global_stack.getContainer(index).getId() != container_id: machine_conflict = True break - self._is_same_machine_type = global_stack.definition.getId() == machine_definition_id + elif available_machines: + containers_found_dict["machine"] = True + # self._is_same_machine_type = global_stack.definition.getId() == machine_definition_id # Get quality type parser = ConfigParser(interpolation = None) @@ -482,7 +489,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if intent_id not in ("empty", "empty_intent"): extruder_info.intent_info = instance_container_info_dict[intent_id] - if not machine_conflict and containers_found_dict["machine"]: + if not machine_conflict and containers_found_dict["machine"] and global_stack: if int(position) >= len(global_stack.extruderList): continue @@ -548,8 +555,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._machine_info.custom_quality_name = quality_name self._machine_info.intent_category = intent_category - if machine_conflict and not self._is_same_machine_type: - machine_conflict = False + # if machine_conflict and not self._is_same_machine_type: + # machine_conflict = False is_printer_group = False if machine_conflict: @@ -571,6 +578,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes) self._dialog.setNumUserSettings(num_user_settings) self._dialog.setActiveMode(active_mode) + self._dialog.setAvailableMachines(available_machines) self._dialog.setMachineName(machine_name) self._dialog.setMaterialLabels(material_labels) self._dialog.setMachineType(machine_type) @@ -652,7 +660,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): application.expandedCategoriesChanged.emit() # Notify the GUI of the change # If a machine with the same name is of a different type, always create a new one. - if not self._is_same_machine_type or self._resolve_strategies["machine"] != "override": + if self._resolve_strategies["machine"] != "override" or not self._dialog.availableMachines: # We need to create a new machine machine_name = self._container_registry.uniqueName(self._machine_info.name) @@ -662,8 +670,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._container_registry.addContainer(global_stack) else: - # Find the machine - global_stacks = self._container_registry.findContainerStacks(name = self._machine_info.name, type = "machine") + # Find the machine which will be overridden + global_stacks = self._container_registry.findContainerStacks(name = self._dialog.getMachineToOverride(), type = "machine") if not global_stacks: message = Message(i18n_catalog.i18nc("@info:error Don't translate the XML tag !", "Project file {0} is made using profiles that are unknown to this version of Ultimaker Cura.", file_name)) message.show() diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 3c97146583..fba7c7ff9f 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -29,6 +29,7 @@ class WorkspaceDialog(QObject): "quality_changes": self._default_strategy, "definition_changes": self._default_strategy, "material": self._default_strategy} + self._override_machine = None self._visible = False self.showDialogSignal.connect(self.__show) @@ -45,6 +46,7 @@ class WorkspaceDialog(QObject): self._quality_type = "" self._intent_name = "" self._machine_name = "" + self._available_machines = [] self._machine_type = "" self._variant_type = "" self._material_labels = [] @@ -63,6 +65,7 @@ class WorkspaceDialog(QObject): qualityTypeChanged = pyqtSignal() intentNameChanged = pyqtSignal() machineNameChanged = pyqtSignal() + availableMachinesChanged = pyqtSignal() materialLabelsChanged = pyqtSignal() objectsOnPlateChanged = pyqtSignal() numUserSettingsChanged = pyqtSignal() @@ -142,6 +145,19 @@ class WorkspaceDialog(QObject): self._machine_name = machine_name self.machineNameChanged.emit() + @pyqtProperty("QVariantList", notify = availableMachinesChanged) + def availableMachines(self): + return self._available_machines + + def setAvailableMachines(self, available_machines): + if self._available_machines != available_machines: + self._available_machines = sorted(available_machines) + self.availableMachinesChanged.emit() + + @pyqtProperty(int, notify = availableMachinesChanged) + def availableMachinesCount(self): + return len(self._available_machines) + @pyqtProperty(str, notify=qualityTypeChanged) def qualityType(self): return self._quality_type @@ -229,6 +245,13 @@ class WorkspaceDialog(QObject): if key in self._result: self._result[key] = strategy + def getMachineToOverride(self): + return self._override_machine + + @pyqtSlot(str) + def setMachineToOverride(self, machine_name): + self._override_machine = machine_name + @pyqtSlot() def closeBackend(self): """Close the backend: otherwise one could end up with "Slicing...""" diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index d0fd3d0846..647dd0a378 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -20,6 +20,7 @@ UM.Dialog property int comboboxHeight: 15 * screenScaleFactor property int spacerHeight: 10 * screenScaleFactor + property string machineResolveStrategyCurrentKey: "override" onClosing: manager.notifyClosed() onVisibleChanged: @@ -101,34 +102,27 @@ UM.Dialog } UM.TooltipArea { - id: machineResolveTooltip + id: machineResolveStrategyTooltip width: (parent.width / 3) | 0 height: visible ? comboboxHeight : 0 - visible: manager.machineConflict + visible: manager.availableMachinesCount != 0 text: catalog.i18nc("@info:tooltip", "How should the conflict in the machine be resolved?") ComboBox { + id: machineResolveComboBox model: ListModel { Component.onCompleted: { - append({"key": "override", "label": catalog.i18nc("@action:ComboBox option", "Update") + " " + manager.machineName}); - append({"key": "new", "label": catalog.i18nc("@action:ComboBox option", "Create new")}); - } - } - Connections - { - target: manager - onMachineNameChanged: - { - machineResolveComboBox.model.get(0).label = catalog.i18nc("@action:ComboBox option", "Update") + " " + manager.machineName; + append({"key": "override", "label": catalog.i18nc("@action:ComboBox option", "Update existing printer")}); + append({"key": "new", "label": catalog.i18nc("@action:ComboBox option", "Create new printer")}); } } textRole: "label" - id: machineResolveComboBox width: parent.width onActivated: { + machineResolveStrategyCurrentKey = resolveStrategiesModel.get(index).key manager.setResolveStrategy("machine", resolveStrategiesModel.get(index).key) } } @@ -164,6 +158,39 @@ UM.Dialog text: manager.machineName width: (parent.width / 3) | 0 } + UM.TooltipArea + { + id: machineResolveTooltip + width: (parent.width / 3) | 0 + height: visible ? comboboxHeight : 0 + visible: base.visible && manager.availableMachinesCount != 0 && machineResolveStrategyCurrentKey == "override" + text: catalog.i18nc("@info:tooltip", "Which machine of the same type should be overriden?") + ComboBox + { + id: selectMachineComboBox + model: manager.availableMachines + width: parent.width + onCurrentIndexChanged: + { + manager.setMachineToOverride(model[currentIndex]) + } + onVisibleChanged: + { + if (visible) + { + currentIndex = 0 + for (var i = 0; i < count; i++) + { + if (model[i] == manager.machineName) + { + currentIndex = i + break + } + } + } + } + } + } } Item // Spacer From 52ea3e8fccf12a303ce88dcf8baaeb53f5551424 Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Wed, 29 Jul 2020 17:19:24 +0200 Subject: [PATCH 02/12] Change variable names (available -> updatable) CURA-7609 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 28 +++++++++------------ plugins/3MFReader/WorkspaceDialog.py | 24 +++++++++--------- plugins/3MFReader/WorkspaceDialog.qml | 6 ++--- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 242e4a1223..394670575b 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -133,12 +133,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # In Cura 2.5 and 2.6, the empty profiles used to have those long names self._old_empty_profile_id_dict = {"empty_%s" % k: "empty" for k in ["material", "variant"]} - # self._is_same_machine_type = False self._old_new_materials = {} # type: Dict[str, str] self._machine_info = None def _clearState(self): - # self._is_same_machine_type = False self._id_mapping = {} self._old_new_materials = {} self._machine_info = None @@ -229,7 +227,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Read definition containers # machine_definition_id = None - available_machines = [] + updatable_machines = [] 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)] @@ -246,9 +244,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): definition_container_type = definition_container.get("type") if definition_container_type == "machine": machine_definition_id = container_id # TODO - my_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id) - available_machines = [i.name for i in self._container_registry.findContainerStacks(type = "machine") if - i.definition == my_definition_containers[0]] + machine_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id) + if machine_definition_containers: + updatable_machines = [machine.name 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) @@ -390,7 +388,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): machine_definition_id = id_list[7] stacks = self._container_registry.findContainerStacks(name = machine_name, type = "machine") - # self._is_same_machine_type = True existing_global_stack = None global_stack = None @@ -405,9 +402,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if global_stack.getContainer(index).getId() != container_id: machine_conflict = True break - elif available_machines: + + if updatable_machines and not containers_found_dict["machine"]: containers_found_dict["machine"] = True - # self._is_same_machine_type = global_stack.definition.getId() == machine_definition_id # Get quality type parser = ConfigParser(interpolation = None) @@ -555,9 +552,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._machine_info.custom_quality_name = quality_name self._machine_info.intent_category = intent_category - # if machine_conflict and not self._is_same_machine_type: - # machine_conflict = False - is_printer_group = False if machine_conflict: group_name = existing_global_stack.getMetaDataEntry("group_name") @@ -578,7 +572,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes) self._dialog.setNumUserSettings(num_user_settings) self._dialog.setActiveMode(active_mode) - self._dialog.setAvailableMachines(available_machines) + self._dialog.setUpdatableMachines(updatable_machines) self._dialog.setMachineName(machine_name) self._dialog.setMaterialLabels(material_labels) self._dialog.setMachineType(machine_type) @@ -659,8 +653,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader): application.expandedCategoriesChanged.emit() # Notify the GUI of the change - # If a machine with the same name is of a different type, always create a new one. - if self._resolve_strategies["machine"] != "override" or not self._dialog.availableMachines: + # If there are no machines of the same type, create a new machine. + if self._resolve_strategies["machine"] != "override" or not self._dialog.updatableMachines: # We need to create a new machine machine_name = self._container_registry.uniqueName(self._machine_info.name) @@ -673,7 +667,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Find the machine which will be overridden global_stacks = self._container_registry.findContainerStacks(name = self._dialog.getMachineToOverride(), type = "machine") if not global_stacks: - message = Message(i18n_catalog.i18nc("@info:error Don't translate the XML tag !", "Project file {0} is made using profiles that are unknown to this version of Ultimaker Cura.", file_name)) + message = Message(i18n_catalog.i18nc("@info:error Don't translate the XML tag !", + "Project file {0} is made using profiles that" + " are unknown to this version of Ultimaker Cura.", file_name)) message.show() self.setWorkspaceName("") return [], {} diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index fba7c7ff9f..34da2729a9 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -46,7 +46,7 @@ class WorkspaceDialog(QObject): self._quality_type = "" self._intent_name = "" self._machine_name = "" - self._available_machines = [] + self._updatable_machines = [] self._machine_type = "" self._variant_type = "" self._material_labels = [] @@ -65,7 +65,7 @@ class WorkspaceDialog(QObject): qualityTypeChanged = pyqtSignal() intentNameChanged = pyqtSignal() machineNameChanged = pyqtSignal() - availableMachinesChanged = pyqtSignal() + updatableMachinesChanged = pyqtSignal() materialLabelsChanged = pyqtSignal() objectsOnPlateChanged = pyqtSignal() numUserSettingsChanged = pyqtSignal() @@ -145,18 +145,18 @@ class WorkspaceDialog(QObject): self._machine_name = machine_name self.machineNameChanged.emit() - @pyqtProperty("QVariantList", notify = availableMachinesChanged) - def availableMachines(self): - return self._available_machines + @pyqtProperty("QVariantList", notify = updatableMachinesChanged) + def updatableMachines(self): + return self._updatable_machines - def setAvailableMachines(self, available_machines): - if self._available_machines != available_machines: - self._available_machines = sorted(available_machines) - self.availableMachinesChanged.emit() + def setUpdatableMachines(self, updatable_machines): + if self._updatable_machines != updatable_machines: + self._updatable_machines = sorted(updatable_machines) + self.updatableMachinesChanged.emit() - @pyqtProperty(int, notify = availableMachinesChanged) - def availableMachinesCount(self): - return len(self._available_machines) + @pyqtProperty(int, notify = updatableMachinesChanged) + def updatableMachinesCount(self): + return len(self._updatable_machines) @pyqtProperty(str, notify=qualityTypeChanged) def qualityType(self): diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index 647dd0a378..e1b9e7a811 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -105,7 +105,7 @@ UM.Dialog id: machineResolveStrategyTooltip width: (parent.width / 3) | 0 height: visible ? comboboxHeight : 0 - visible: manager.availableMachinesCount != 0 + visible: manager.updatableMachinesCount != 0 text: catalog.i18nc("@info:tooltip", "How should the conflict in the machine be resolved?") ComboBox { @@ -163,12 +163,12 @@ UM.Dialog id: machineResolveTooltip width: (parent.width / 3) | 0 height: visible ? comboboxHeight : 0 - visible: base.visible && manager.availableMachinesCount != 0 && machineResolveStrategyCurrentKey == "override" + visible: base.visible && manager.updatableMachinesCount != 0 && machineResolveStrategyCurrentKey == "override" text: catalog.i18nc("@info:tooltip", "Which machine of the same type should be overriden?") ComboBox { id: selectMachineComboBox - model: manager.availableMachines + model: manager.updatableMachines width: parent.width onCurrentIndexChanged: { From ff4e4ccf55a130e7ae152d007804426eb0cdb78f Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 3 Aug 2020 09:07:20 +0200 Subject: [PATCH 03/12] Change text in the combobox Since it was anyway truncated CURA-7609 --- plugins/3MFReader/WorkspaceDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index e1b9e7a811..d206902ec3 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -114,7 +114,7 @@ UM.Dialog { Component.onCompleted: { - append({"key": "override", "label": catalog.i18nc("@action:ComboBox option", "Update existing printer")}); + append({"key": "override", "label": catalog.i18nc("@action:ComboBox option", "Update existing...")}); append({"key": "new", "label": catalog.i18nc("@action:ComboBox option", "Create new printer")}); } } From db857c8c20d02db7dad5e2386008692f4620c09f Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 3 Aug 2020 09:21:16 +0200 Subject: [PATCH 04/12] Add extra spacing between categories in the open project dialog CURA-7609 --- plugins/3MFReader/WorkspaceDialog.qml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index d206902ec3..48e93a3d3b 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -80,7 +80,7 @@ UM.Dialog } Item // Spacer { - height: spacerHeight + height: 2 * spacerHeight width: height } @@ -195,7 +195,7 @@ UM.Dialog Item // Spacer { - height: spacerHeight + height: 2 * spacerHeight width: height } Row @@ -298,7 +298,7 @@ UM.Dialog } Item // Spacer { - height: spacerHeight + height: 2 * spacerHeight width: height } Row @@ -360,7 +360,7 @@ UM.Dialog Item // Spacer { - height: spacerHeight + height: 2 * spacerHeight width: height } @@ -402,7 +402,7 @@ UM.Dialog } Item // Spacer { - height: spacerHeight + height: 2 * spacerHeight width: height } Row From 37febc9f600a48071c4d98b1d68a4108a364055b Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 3 Aug 2020 09:24:40 +0200 Subject: [PATCH 05/12] Remove comment CURA-7609 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 394670575b..5d4fa9256f 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -243,7 +243,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): definition_container_type = definition_container.get("type") if definition_container_type == "machine": - machine_definition_id = container_id # TODO + machine_definition_id = container_id machine_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id) if machine_definition_containers: updatable_machines = [machine.name for machine in self._container_registry.findContainerStacks(type = "machine") if machine.definition == machine_definition_containers[0]] From ce72bb1a0bda2891281e6c76e6e7f076a19f3251 Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 3 Aug 2020 15:47:01 +0200 Subject: [PATCH 06/12] Fix creating new machine being reverted to overridde in some cases CURA-7609 --- plugins/3MFReader/WorkspaceDialog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 34da2729a9..026daf0d7a 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -274,7 +274,7 @@ class WorkspaceDialog(QObject): self.qualityChangesConflictChanged.emit() def getResult(self): - if "machine" in self._result and not self._has_machine_conflict: + if "machine" in self._result and not self._updatable_machines: self._result["machine"] = None if "quality_changes" in self._result and not self._has_quality_changes_conflict: self._result["quality_changes"] = None From 60cfb6a8bea94fdb0f3a1d1df002282e0b4495cf Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 3 Aug 2020 17:28:44 +0200 Subject: [PATCH 07/12] Change name of updatable_machines to updatable_machine_names Since it is a list of name strings and not a list of machines. Response to feedback comment https://github.com/Ultimaker/Cura/pull/8142#discussion_r464307564 CURA-7609 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 5d4fa9256f..ee94d5b83d 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -227,7 +227,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Read definition containers # machine_definition_id = None - updatable_machines = [] + updatable_machine_names = [] 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)] @@ -246,7 +246,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): machine_definition_id = container_id machine_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id) if machine_definition_containers: - updatable_machines = [machine.name for machine in self._container_registry.findContainerStacks(type = "machine") if machine.definition == machine_definition_containers[0]] + updatable_machine_names = [machine.name 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) @@ -403,7 +403,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): machine_conflict = True break - if updatable_machines and not containers_found_dict["machine"]: + if updatable_machine_names and not containers_found_dict["machine"]: containers_found_dict["machine"] = True # Get quality type @@ -572,7 +572,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes) self._dialog.setNumUserSettings(num_user_settings) self._dialog.setActiveMode(active_mode) - self._dialog.setUpdatableMachines(updatable_machines) + self._dialog.setUpdatableMachineNames(updatable_machine_names) self._dialog.setMachineName(machine_name) self._dialog.setMaterialLabels(material_labels) self._dialog.setMachineType(machine_type) @@ -654,7 +654,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): application.expandedCategoriesChanged.emit() # Notify the GUI of the change # If there are no machines of the same type, create a new machine. - if self._resolve_strategies["machine"] != "override" or not self._dialog.updatableMachines: + if self._resolve_strategies["machine"] != "override" or not self._dialog.updatableMachineNames: # We need to create a new machine machine_name = self._container_registry.uniqueName(self._machine_info.name) From 6c59616e39408c8af60a184120055f4a0257dbd6 Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 3 Aug 2020 17:30:21 +0200 Subject: [PATCH 08/12] Process feedback comments Comments https://github.com/Ultimaker/Cura/pull/8142#discussion_r464309980 and https://github.com/Ultimaker/Cura/pull/8142#discussion_r464310281 CURA-7609 --- plugins/3MFReader/WorkspaceDialog.qml | 35 ++++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index 48e93a3d3b..e4e02818b2 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -20,6 +20,7 @@ UM.Dialog property int comboboxHeight: 15 * screenScaleFactor property int spacerHeight: 10 * screenScaleFactor + property int doubleSpacerHeight: 20 * screenScaleFactor property string machineResolveStrategyCurrentKey: "override" onClosing: manager.notifyClosed() @@ -36,7 +37,7 @@ UM.Dialog Item { anchors.fill: parent - anchors.margins: 20 * screenScaleFactor + anchors.margins: 10 * screenScaleFactor UM.I18nCatalog { @@ -80,7 +81,7 @@ UM.Dialog } Item // Spacer { - height: 2 * spacerHeight + height: doubleSpacerHeight width: height } @@ -105,7 +106,7 @@ UM.Dialog id: machineResolveStrategyTooltip width: (parent.width / 3) | 0 height: visible ? comboboxHeight : 0 - visible: manager.updatableMachinesCount != 0 + visible: manager.updatableMachineNamesCount != 0 text: catalog.i18nc("@info:tooltip", "How should the conflict in the machine be resolved?") ComboBox { @@ -163,12 +164,12 @@ UM.Dialog id: machineResolveTooltip width: (parent.width / 3) | 0 height: visible ? comboboxHeight : 0 - visible: base.visible && manager.updatableMachinesCount != 0 && machineResolveStrategyCurrentKey == "override" + visible: base.visible && manager.updatableMachineNamesCount != 0 && machineResolveStrategyCurrentKey == "override" text: catalog.i18nc("@info:tooltip", "Which machine of the same type should be overriden?") ComboBox { id: selectMachineComboBox - model: manager.updatableMachines + model: manager.updatableMachineNames width: parent.width onCurrentIndexChanged: { @@ -176,18 +177,18 @@ UM.Dialog } onVisibleChanged: { - if (visible) + if (!visible) {return} + + currentIndex = 0 + for (var i = 0; i < count; i++) { - currentIndex = 0 - for (var i = 0; i < count; i++) + if (model[i] == manager.machineName) { - if (model[i] == manager.machineName) - { - currentIndex = i - break - } + currentIndex = i + break } } + } } } @@ -195,7 +196,7 @@ UM.Dialog Item // Spacer { - height: 2 * spacerHeight + height: doubleSpacerHeight width: height } Row @@ -298,7 +299,7 @@ UM.Dialog } Item // Spacer { - height: 2 * spacerHeight + height: doubleSpacerHeight width: height } Row @@ -360,7 +361,7 @@ UM.Dialog Item // Spacer { - height: 2 * spacerHeight + height: doubleSpacerHeight width: height } @@ -402,7 +403,7 @@ UM.Dialog } Item // Spacer { - height: 2 * spacerHeight + height: spacerHeight width: height } Row From 9ad046654aaf0025ced710d1007271f0f1e406aa Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 3 Aug 2020 17:31:21 +0200 Subject: [PATCH 09/12] Add typing in WorkspaceDialog.py In response to feedback comment https://github.com/Ultimaker/Cura/pull/8142#discussion_r464309170 CURA-7609 --- plugins/3MFReader/WorkspaceDialog.py | 111 ++++++++++++++------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 026daf0d7a..4676a557e9 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -1,5 +1,6 @@ # Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from typing import List, Optional, Dict from PyQt5.QtCore import pyqtSignal, QObject, pyqtProperty, QCoreApplication from UM.FlameProfiler import pyqtSlot @@ -65,7 +66,7 @@ class WorkspaceDialog(QObject): qualityTypeChanged = pyqtSignal() intentNameChanged = pyqtSignal() machineNameChanged = pyqtSignal() - updatableMachinesChanged = pyqtSignal() + updatableMachineNamesChanged = pyqtSignal() materialLabelsChanged = pyqtSignal() objectsOnPlateChanged = pyqtSignal() numUserSettingsChanged = pyqtSignal() @@ -84,33 +85,33 @@ class WorkspaceDialog(QObject): self.isPrinterGroupChanged.emit() @pyqtProperty(str, notify=variantTypeChanged) - def variantType(self): + def variantType(self) -> str: return self._variant_type - def setVariantType(self, variant_type): + def setVariantType(self, variant_type: str) -> None: if self._variant_type != variant_type: self._variant_type = variant_type self.variantTypeChanged.emit() @pyqtProperty(str, notify=machineTypeChanged) - def machineType(self): + def machineType(self) -> str: return self._machine_type - def setMachineType(self, machine_type): + def setMachineType(self, machine_type: str) -> None: self._machine_type = machine_type self.machineTypeChanged.emit() - def setNumUserSettings(self, num_user_settings): + def setNumUserSettings(self, num_user_settings: int) -> None: if self._num_user_settings != num_user_settings: self._num_user_settings = num_user_settings self.numVisibleSettingsChanged.emit() @pyqtProperty(int, notify=numUserSettingsChanged) - def numUserSettings(self): + def numUserSettings(self) -> int: return self._num_user_settings @pyqtProperty(bool, notify=objectsOnPlateChanged) - def hasObjectsOnPlate(self): + def hasObjectsOnPlate(self) -> bool: return self._objects_on_plate def setHasObjectsOnPlate(self, objects_on_plate): @@ -119,10 +120,10 @@ class WorkspaceDialog(QObject): self.objectsOnPlateChanged.emit() @pyqtProperty("QVariantList", notify = materialLabelsChanged) - def materialLabels(self): + def materialLabels(self) -> List[str]: return self._material_labels - def setMaterialLabels(self, material_labels): + def setMaterialLabels(self, material_labels: List[str]) -> None: if self._material_labels != material_labels: self._material_labels = material_labels self.materialLabelsChanged.emit() @@ -137,49 +138,49 @@ class WorkspaceDialog(QObject): self.extrudersChanged.emit() @pyqtProperty(str, notify = machineNameChanged) - def machineName(self): + def machineName(self) -> str: return self._machine_name - def setMachineName(self, machine_name): + def setMachineName(self, machine_name: str) -> None: if self._machine_name != machine_name: self._machine_name = machine_name self.machineNameChanged.emit() - @pyqtProperty("QVariantList", notify = updatableMachinesChanged) - def updatableMachines(self): + @pyqtProperty("QVariantList", notify = updatableMachineNamesChanged) + def updatableMachineNames(self) -> List[str]: return self._updatable_machines - def setUpdatableMachines(self, updatable_machines): + def setUpdatableMachineNames(self, updatable_machines: List[str]) -> None: if self._updatable_machines != updatable_machines: self._updatable_machines = sorted(updatable_machines) - self.updatableMachinesChanged.emit() + self.updatableMachineNamesChanged.emit() - @pyqtProperty(int, notify = updatableMachinesChanged) - def updatableMachinesCount(self): + @pyqtProperty(int, notify = updatableMachineNamesChanged) + def updatableMachineNamesCount(self) -> int: return len(self._updatable_machines) @pyqtProperty(str, notify=qualityTypeChanged) - def qualityType(self): + def qualityType(self) -> str: return self._quality_type - def setQualityType(self, quality_type): + def setQualityType(self, quality_type: str) -> None: if self._quality_type != quality_type: self._quality_type = quality_type self.qualityTypeChanged.emit() @pyqtProperty(int, notify=numSettingsOverridenByQualityChangesChanged) - def numSettingsOverridenByQualityChanges(self): + def numSettingsOverridenByQualityChanges(self) -> int: return self._num_settings_overridden_by_quality_changes - def setNumSettingsOverriddenByQualityChanges(self, num_settings_overridden_by_quality_changes): + def setNumSettingsOverriddenByQualityChanges(self, num_settings_overridden_by_quality_changes: int) -> None: self._num_settings_overridden_by_quality_changes = num_settings_overridden_by_quality_changes self.numSettingsOverridenByQualityChangesChanged.emit() @pyqtProperty(str, notify=qualityNameChanged) - def qualityName(self): + def qualityName(self) -> str: return self._quality_name - def setQualityName(self, quality_name): + def setQualityName(self, quality_name: str) -> None: if self._quality_name != quality_name: self._quality_name = quality_name self.qualityNameChanged.emit() @@ -194,86 +195,86 @@ class WorkspaceDialog(QObject): self.intentNameChanged.emit() @pyqtProperty(str, notify=activeModeChanged) - def activeMode(self): + def activeMode(self) -> str: return self._active_mode - def setActiveMode(self, active_mode): + def setActiveMode(self, active_mode: int) -> None: if active_mode == 0: self._active_mode = i18n_catalog.i18nc("@title:tab", "Recommended") else: self._active_mode = i18n_catalog.i18nc("@title:tab", "Custom") self.activeModeChanged.emit() - @pyqtProperty(int, notify = hasVisibleSettingsFieldChanged) - def hasVisibleSettingsField(self): + @pyqtProperty(bool, notify = hasVisibleSettingsFieldChanged) + def hasVisibleSettingsField(self) -> bool: return self._has_visible_settings_field - def setHasVisibleSettingsField(self, has_visible_settings_field): + def setHasVisibleSettingsField(self, has_visible_settings_field: bool) -> None: self._has_visible_settings_field = has_visible_settings_field self.hasVisibleSettingsFieldChanged.emit() @pyqtProperty(int, constant = True) - def totalNumberOfSettings(self): + def totalNumberOfSettings(self) -> int: general_definition_containers = ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter") if not general_definition_containers: return 0 return len(general_definition_containers[0].getAllKeys()) @pyqtProperty(int, notify = numVisibleSettingsChanged) - def numVisibleSettings(self): + def numVisibleSettings(self) -> int: return self._num_visible_settings - def setNumVisibleSettings(self, num_visible_settings): + def setNumVisibleSettings(self, num_visible_settings: int) -> None: if self._num_visible_settings != num_visible_settings: self._num_visible_settings = num_visible_settings self.numVisibleSettingsChanged.emit() @pyqtProperty(bool, notify = machineConflictChanged) - def machineConflict(self): + def machineConflict(self) -> bool: return self._has_machine_conflict @pyqtProperty(bool, notify=qualityChangesConflictChanged) - def qualityChangesConflict(self): + def qualityChangesConflict(self) -> bool: return self._has_quality_changes_conflict @pyqtProperty(bool, notify=materialConflictChanged) - def materialConflict(self): + def materialConflict(self) -> bool: return self._has_material_conflict @pyqtSlot(str, str) - def setResolveStrategy(self, key, strategy): + def setResolveStrategy(self, key: str, strategy: str) -> None: if key in self._result: self._result[key] = strategy - def getMachineToOverride(self): + def getMachineToOverride(self) -> str: return self._override_machine @pyqtSlot(str) - def setMachineToOverride(self, machine_name): + def setMachineToOverride(self, machine_name: str) -> None: self._override_machine = machine_name @pyqtSlot() - def closeBackend(self): + def closeBackend(self) -> None: """Close the backend: otherwise one could end up with "Slicing...""" Application.getInstance().getBackend().close() - def setMaterialConflict(self, material_conflict): + def setMaterialConflict(self, material_conflict: bool) -> None: if self._has_material_conflict != material_conflict: self._has_material_conflict = material_conflict self.materialConflictChanged.emit() - def setMachineConflict(self, machine_conflict): + def setMachineConflict(self, machine_conflict: bool) -> None: if self._has_machine_conflict != machine_conflict: self._has_machine_conflict = machine_conflict self.machineConflictChanged.emit() - def setQualityChangesConflict(self, quality_changes_conflict): + def setQualityChangesConflict(self, quality_changes_conflict: bool) -> None: if self._has_quality_changes_conflict != quality_changes_conflict: self._has_quality_changes_conflict = quality_changes_conflict self.qualityChangesConflictChanged.emit() - def getResult(self): + def getResult(self) -> Dict[str, Optional[str]]: if "machine" in self._result and not self._updatable_machines: self._result["machine"] = None if "quality_changes" in self._result and not self._has_quality_changes_conflict: @@ -290,11 +291,13 @@ class WorkspaceDialog(QObject): return self._result - def _createViewFromQML(self): - path = os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url) - self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) + def _createViewFromQML(self) -> None: + three_mf_reader_path = PluginRegistry.getInstance().getPluginPath("3MFReader") + if three_mf_reader_path: + path = os.path.join(three_mf_reader_path, self._qml_url) + self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) - def show(self): + def show(self) -> None: # Emit signal so the right thread actually shows the view. if threading.current_thread() != threading.main_thread(): self._lock.acquire() @@ -307,7 +310,7 @@ class WorkspaceDialog(QObject): self.showDialogSignal.emit() @pyqtSlot() - def notifyClosed(self): + def notifyClosed(self) -> None: """Used to notify the dialog so the lock can be released.""" self._result = {} # The result should be cleared before hide, because after it is released the main thread lock @@ -317,7 +320,7 @@ class WorkspaceDialog(QObject): except: pass - def hide(self): + def hide(self) -> None: self._visible = False self._view.hide() try: @@ -326,7 +329,7 @@ class WorkspaceDialog(QObject): pass @pyqtSlot(bool) - def _onVisibilityChanged(self, visible): + def _onVisibilityChanged(self, visible: bool) -> None: if not visible: try: self._lock.release() @@ -334,17 +337,17 @@ class WorkspaceDialog(QObject): pass @pyqtSlot() - def onOkButtonClicked(self): + def onOkButtonClicked(self) -> None: self._view.hide() self.hide() @pyqtSlot() - def onCancelButtonClicked(self): + def onCancelButtonClicked(self) -> None: self._result = {} self._view.hide() self.hide() - def waitForClose(self): + def waitForClose(self) -> None: """Block thread until the dialog is closed.""" if self._visible: @@ -357,7 +360,7 @@ class WorkspaceDialog(QObject): time.sleep(1 / 50) QCoreApplication.processEvents() # Ensure that the GUI does not freeze. - def __show(self): + def __show(self) -> None: if self._view is None: self._createViewFromQML() if self._view: From e5d32716980c82d50bc3690963f303da3757eac5 Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 3 Aug 2020 17:43:14 +0200 Subject: [PATCH 10/12] Fix mypy complaining that Application has no createQmlComponent Using CuraApplication instead fixes the problem CURA-7609 --- plugins/3MFReader/WorkspaceDialog.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 4676a557e9..7291c81e9f 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -12,6 +12,9 @@ from UM.Settings.ContainerRegistry import ContainerRegistry import os import threading import time + +from cura.CuraApplication import CuraApplication + i18n_catalog = i18nCatalog("cura") @@ -295,7 +298,7 @@ class WorkspaceDialog(QObject): three_mf_reader_path = PluginRegistry.getInstance().getPluginPath("3MFReader") if three_mf_reader_path: path = os.path.join(three_mf_reader_path, self._qml_url) - self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) + self._view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self}) def show(self) -> None: # Emit signal so the right thread actually shows the view. From 4e20c7dddca698c970a6187d10d30b7cbdcedaf3 Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Tue, 4 Aug 2020 16:33:11 +0200 Subject: [PATCH 11/12] Rework the open project dialog to contain only 1 dropdown With the caveat that the qtQuickControls had to be updated to 2.3, due to a qt bug in 1.x that did not update the dropdown popup list according to the ListModel. This leads to a different look in the dropdowns and in the buttons of the open project dialog, compaired to the rest of the application. CURA-7609 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 10 +-- plugins/3MFReader/UpdatableMachinesModel.py | 43 +++++++++++ plugins/3MFReader/WorkspaceDialog.py | 31 ++++---- plugins/3MFReader/WorkspaceDialog.qml | 81 +++++++++------------ 4 files changed, 98 insertions(+), 67 deletions(-) create mode 100644 plugins/3MFReader/UpdatableMachinesModel.py diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index ee94d5b83d..9ae835aca5 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -227,7 +227,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Read definition containers # machine_definition_id = None - updatable_machine_names = [] + updatable_machines = [] 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)] @@ -246,7 +246,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): machine_definition_id = container_id machine_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id) if machine_definition_containers: - updatable_machine_names = [machine.name for machine in self._container_registry.findContainerStacks(type = "machine") if machine.definition == machine_definition_containers[0]] + 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) @@ -403,7 +403,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): machine_conflict = True break - if updatable_machine_names and not containers_found_dict["machine"]: + if updatable_machines and not containers_found_dict["machine"]: containers_found_dict["machine"] = True # Get quality type @@ -572,7 +572,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes) self._dialog.setNumUserSettings(num_user_settings) self._dialog.setActiveMode(active_mode) - self._dialog.setUpdatableMachineNames(updatable_machine_names) + self._dialog.setUpdatableMachinesModel(updatable_machines) self._dialog.setMachineName(machine_name) self._dialog.setMaterialLabels(material_labels) self._dialog.setMachineType(machine_type) @@ -654,7 +654,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): application.expandedCategoriesChanged.emit() # Notify the GUI of the change # If there are no machines of the same type, create a new machine. - if self._resolve_strategies["machine"] != "override" or not self._dialog.updatableMachineNames: + if self._resolve_strategies["machine"] != "override" or self._dialog.updatableMachinesModel.count <= 1: # We need to create a new machine machine_name = self._container_registry.uniqueName(self._machine_info.name) diff --git a/plugins/3MFReader/UpdatableMachinesModel.py b/plugins/3MFReader/UpdatableMachinesModel.py new file mode 100644 index 0000000000..a332c669e6 --- /dev/null +++ b/plugins/3MFReader/UpdatableMachinesModel.py @@ -0,0 +1,43 @@ +# Copyright (c) 2020 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from typing import Dict, List + +from PyQt5.QtCore import Qt + +from UM.Qt.ListModel import ListModel +from cura.Settings.GlobalStack import GlobalStack + +create_new_list_item = { + "id": "new", + "name": "Create new", + "displayName": "Create new", + "type": "default_option" # to make sure we are not mixing the "Create new" option with a printer with id "new" +} # type: Dict[str, str] + + +class UpdatableMachinesModel(ListModel): + """Model that holds cura packages. + + By setting the filter property the instances held by this model can be changed. + """ + + def __init__(self, parent = None) -> None: + super().__init__(parent) + + self.addRoleName(Qt.UserRole + 1, "id") + self.addRoleName(Qt.UserRole + 2, "name") + self.addRoleName(Qt.UserRole + 3, "displayName") + self.addRoleName(Qt.UserRole + 4, "type") # Either "default_option" or "machine" + + def update(self, machines: List[GlobalStack]) -> None: + items = [create_new_list_item] # type: List[Dict[str, str]] + + for machine in sorted(machines, key = lambda printer: printer.name): + items.append({ + "id": machine.id, + "name": machine.name, + "displayName": "Update " + machine.name, + "type": "machine" + }) + self.setItems(items) diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 7291c81e9f..ef053eb77c 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -1,6 +1,6 @@ -# Copyright (c) 2016 Ultimaker B.V. +# Copyright (c) 2020 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import List, Optional, Dict +from typing import List, Optional, Dict, cast from PyQt5.QtCore import pyqtSignal, QObject, pyqtProperty, QCoreApplication from UM.FlameProfiler import pyqtSlot @@ -8,6 +8,8 @@ from UM.PluginRegistry import PluginRegistry from UM.Application import Application from UM.i18n import i18nCatalog from UM.Settings.ContainerRegistry import ContainerRegistry +from cura.Settings.GlobalStack import GlobalStack +from .UpdatableMachinesModel import UpdatableMachinesModel import os import threading @@ -50,13 +52,13 @@ class WorkspaceDialog(QObject): self._quality_type = "" self._intent_name = "" self._machine_name = "" - self._updatable_machines = [] self._machine_type = "" self._variant_type = "" self._material_labels = [] self._extruders = [] self._objects_on_plate = False self._is_printer_group = False + self._updatable_machines_model = UpdatableMachinesModel(self) machineConflictChanged = pyqtSignal() qualityChangesConflictChanged = pyqtSignal() @@ -69,7 +71,7 @@ class WorkspaceDialog(QObject): qualityTypeChanged = pyqtSignal() intentNameChanged = pyqtSignal() machineNameChanged = pyqtSignal() - updatableMachineNamesChanged = pyqtSignal() + updatableMachinesChanged = pyqtSignal() materialLabelsChanged = pyqtSignal() objectsOnPlateChanged = pyqtSignal() numUserSettingsChanged = pyqtSignal() @@ -149,18 +151,13 @@ class WorkspaceDialog(QObject): self._machine_name = machine_name self.machineNameChanged.emit() - @pyqtProperty("QVariantList", notify = updatableMachineNamesChanged) - def updatableMachineNames(self) -> List[str]: - return self._updatable_machines + @pyqtProperty(QObject, notify = updatableMachinesChanged) + def updatableMachinesModel(self) -> UpdatableMachinesModel: + return cast(UpdatableMachinesModel, self._updatable_machines_model) - def setUpdatableMachineNames(self, updatable_machines: List[str]) -> None: - if self._updatable_machines != updatable_machines: - self._updatable_machines = sorted(updatable_machines) - self.updatableMachineNamesChanged.emit() - - @pyqtProperty(int, notify = updatableMachineNamesChanged) - def updatableMachineNamesCount(self) -> int: - return len(self._updatable_machines) + def setUpdatableMachinesModel(self, updatable_machines: List[GlobalStack]) -> None: + self._updatable_machines_model.update(updatable_machines) + self.updatableMachinesChanged.emit() @pyqtProperty(str, notify=qualityTypeChanged) def qualityType(self) -> str: @@ -245,7 +242,7 @@ class WorkspaceDialog(QObject): return self._has_material_conflict @pyqtSlot(str, str) - def setResolveStrategy(self, key: str, strategy: str) -> None: + def setResolveStrategy(self, key: str, strategy: Optional[str]) -> None: if key in self._result: self._result[key] = strategy @@ -278,7 +275,7 @@ class WorkspaceDialog(QObject): self.qualityChangesConflictChanged.emit() def getResult(self) -> Dict[str, Optional[str]]: - if "machine" in self._result and not self._updatable_machines: + if "machine" in self._result and self.updatableMachinesModel.count <= 1: self._result["machine"] = None if "quality_changes" in self._result and not self._has_quality_changes_conflict: self._result["quality_changes"] = None diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml index e4e02818b2..5f67f54c39 100644 --- a/plugins/3MFReader/WorkspaceDialog.qml +++ b/plugins/3MFReader/WorkspaceDialog.qml @@ -2,7 +2,7 @@ // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.10 -import QtQuick.Controls 1.4 +import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 import QtQuick.Window 2.2 @@ -21,7 +21,6 @@ UM.Dialog property int comboboxHeight: 15 * screenScaleFactor property int spacerHeight: 10 * screenScaleFactor property int doubleSpacerHeight: 20 * screenScaleFactor - property string machineResolveStrategyCurrentKey: "override" onClosing: manager.notifyClosed() onVisibleChanged: @@ -106,25 +105,50 @@ UM.Dialog id: machineResolveStrategyTooltip width: (parent.width / 3) | 0 height: visible ? comboboxHeight : 0 - visible: manager.updatableMachineNamesCount != 0 + visible: base.visible && machineResolveComboBox.model.count > 1 text: catalog.i18nc("@info:tooltip", "How should the conflict in the machine be resolved?") ComboBox { id: machineResolveComboBox - model: ListModel + model: manager.updatableMachinesModel + visible: machineResolveStrategyTooltip.visible + textRole: "displayName" + width: parent.width + onCurrentIndexChanged: { - Component.onCompleted: + if (model.getItem(currentIndex).id == "new" + && model.getItem(currentIndex).type == "default_option") { - append({"key": "override", "label": catalog.i18nc("@action:ComboBox option", "Update existing...")}); - append({"key": "new", "label": catalog.i18nc("@action:ComboBox option", "Create new printer")}); + manager.setResolveStrategy("machine", "new") + } + else + { + manager.setResolveStrategy("machine", "override") + manager.setMachineToOverride(model.getItem(currentIndex).id) } } - textRole: "label" - width: parent.width - onActivated: + + onVisibleChanged: { - machineResolveStrategyCurrentKey = resolveStrategiesModel.get(index).key - manager.setResolveStrategy("machine", resolveStrategiesModel.get(index).key) + if (!visible) {return} + + currentIndex = 0 + // If the project printer exists in Cura, set it as the default dropdown menu option. + // No need to check object 0, which is the "Create new" option + for (var i = 1; i < model.count; i++) + { + if (model.getItem(i).name == manager.machineName) + { + currentIndex = i + break + } + } + // The project printer does not exist in Cura. If there is at least one printer of the same + // type, select the first one, else set the index to "Create new" + if (currentIndex == 0 && model.count > 1) + { + currentIndex = 1 + } } } } @@ -159,39 +183,6 @@ UM.Dialog text: manager.machineName width: (parent.width / 3) | 0 } - UM.TooltipArea - { - id: machineResolveTooltip - width: (parent.width / 3) | 0 - height: visible ? comboboxHeight : 0 - visible: base.visible && manager.updatableMachineNamesCount != 0 && machineResolveStrategyCurrentKey == "override" - text: catalog.i18nc("@info:tooltip", "Which machine of the same type should be overriden?") - ComboBox - { - id: selectMachineComboBox - model: manager.updatableMachineNames - width: parent.width - onCurrentIndexChanged: - { - manager.setMachineToOverride(model[currentIndex]) - } - onVisibleChanged: - { - if (!visible) {return} - - currentIndex = 0 - for (var i = 0; i < count; i++) - { - if (model[i] == manager.machineName) - { - currentIndex = i - break - } - } - - } - } - } } Item // Spacer From c8771124ada36ef46ea34f50572c1161a46ba964 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 5 Aug 2020 14:56:39 +0200 Subject: [PATCH 12/12] Change function name to better reflect what it does CURA-7609 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 2 +- plugins/3MFReader/WorkspaceDialog.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 9ae835aca5..8f465aa8f9 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -572,7 +572,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes) self._dialog.setNumUserSettings(num_user_settings) self._dialog.setActiveMode(active_mode) - self._dialog.setUpdatableMachinesModel(updatable_machines) + self._dialog.setUpdatableMachines(updatable_machines) self._dialog.setMachineName(machine_name) self._dialog.setMaterialLabels(material_labels) self._dialog.setMachineType(machine_type) diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index ef053eb77c..8d59ec1339 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -155,7 +155,7 @@ class WorkspaceDialog(QObject): def updatableMachinesModel(self) -> UpdatableMachinesModel: return cast(UpdatableMachinesModel, self._updatable_machines_model) - def setUpdatableMachinesModel(self, updatable_machines: List[GlobalStack]) -> None: + def setUpdatableMachines(self, updatable_machines: List[GlobalStack]) -> None: self._updatable_machines_model.update(updatable_machines) self.updatableMachinesChanged.emit()