From 8e5cfd9566f89e85909158a003cf6b874384a688 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Mon, 22 May 2017 13:55:43 +0200 Subject: [PATCH 1/5] Add last missing settings that should still use extruderValue Contributes to CURA-3738 --- resources/definitions/fdmprinter.def.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 5f27f161c7..bea23144c1 100755 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -773,7 +773,7 @@ "type": "float", "enabled": "support_enable and support_roof_enable", "limit_to_extruder": "support_roof_extruder_nr", - "value": "support_interface_line_width", + "value": "extruderValue(support_roof_extruder_nr, 'support_interface_line_width')", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -789,7 +789,7 @@ "type": "float", "enabled": "support_enable and support_bottom_enable", "limit_to_extruder": "support_bottom_extruder_nr", - "value": "support_interface_line_width", + "value": "extruderValue(support_bottom_extruder_nr, 'support_interface_line_width')", "settable_per_mesh": false, "settable_per_extruder": true } @@ -1972,7 +1972,7 @@ "maximum_value_warning": "150", "enabled": "support_roof_enable and support_enable", "limit_to_extruder": "support_roof_extruder_nr", - "value": "speed_support_interface", + "value": "extruderValue(support_roof_extruder_nr, 'speed_support_interface')", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -1988,7 +1988,7 @@ "maximum_value_warning": "150", "enabled": "support_bottom_enable and support_enable", "limit_to_extruder": "support_bottom_extruder_nr", - "value": "speed_support_interface", + "value": "extruderValue(support_bottom_extruder_nr, 'speed_support_interface')", "settable_per_mesh": false, "settable_per_extruder": true } @@ -2288,11 +2288,11 @@ "unit": "mm/s²", "type": "float", "default_value": 3000, - "value": "acceleration_support_interface", + "value": "extruderValue(support_roof_extruder_nr, 'acceleration_support_interface')", "minimum_value": "0.1", "minimum_value_warning": "100", "maximum_value_warning": "10000", - "enabled": "resolveOrValue('acceleration_enabled') and support_roof_enable and support_enable", + "enabled": "acceleration_enabled and support_roof_enable and support_enable", "limit_to_extruder": "support_roof_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": true @@ -2304,11 +2304,11 @@ "unit": "mm/s²", "type": "float", "default_value": 3000, - "value": "acceleration_support_interface", + "value": "extruderValue(support_bottom_extruder_nr, 'acceleration_support_interface')", "minimum_value": "0.1", "minimum_value_warning": "100", "maximum_value_warning": "10000", - "enabled": "resolveOrValue('acceleration_enabled') and support_bottom_enable and support_enable", + "enabled": "acceleration_enabled and support_bottom_enable and support_enable", "limit_to_extruder": "support_bottom_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": true @@ -2553,7 +2553,7 @@ "unit": "mm/s", "type": "float", "default_value": 20, - "value": "jerk_support_interface", + "value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')", "minimum_value": "0.1", "maximum_value_warning": "50", "enabled": "resolveOrValue('jerk_enabled') and support_roof_enable and support_enable", @@ -2568,7 +2568,7 @@ "unit": "mm/s", "type": "float", "default_value": 20, - "value": "jerk_support_interface", + "value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')", "minimum_value": "0.1", "maximum_value_warning": "50", "enabled": "resolveOrValue('jerk_enabled') and support_bottom_enable and support_enable", From 6315947156c0abfc01e83abac318ba62c80e6e7b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 22 May 2017 12:48:40 +0200 Subject: [PATCH 2/5] Modify parameter types from DefinitionContainer to DefinitionContainerInterface It may also be any other class that implements the Definition Container Interface. Not really related to CURA-3803 but I'm putting it there anyway as I found it during that development. --- cura/Settings/ExtruderManager.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index bab4aa2d9e..ce6fd47de6 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -15,7 +15,7 @@ from UM.Settings.ContainerRegistry import ContainerRegistry #Finding containers from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.SettingFunction import SettingFunction from UM.Settings.ContainerStack import ContainerStack -from UM.Settings.DefinitionContainer import DefinitionContainer +from UM.Settings.Interfaces import DefinitionContainerInterface from typing import Optional, List, TYPE_CHECKING, Union if TYPE_CHECKING: @@ -74,7 +74,7 @@ class ExtruderManager(QObject): except KeyError: return 0 - @pyqtProperty("QVariantMap", notify=extrudersChanged) + @pyqtProperty("QVariantMap", notify = extrudersChanged) def extruderIds(self): map = {} global_stack_id = Application.getInstance().getGlobalContainerStack().getId() @@ -203,7 +203,7 @@ class ExtruderManager(QObject): # \param machine_definition The machine definition to add the extruders for. # \param machine_id The machine_id to add the extruders for. @deprecated("Use CuraStackBuilder", "2.6") - def addMachineExtruders(self, machine_definition: DefinitionContainer, machine_id: str) -> None: + def addMachineExtruders(self, machine_definition: DefinitionContainerInterface, machine_id: str) -> None: changed = False machine_definition_id = machine_definition.getId() if machine_id not in self._extruder_trains: @@ -263,7 +263,7 @@ class ExtruderManager(QObject): # \param position The position of this extruder train in the extruder slots of the machine. # \param machine_id The id of the "global" stack this extruder is linked to. @deprecated("Use CuraStackBuilder::createExtruderStack", "2.6") - def createExtruderTrain(self, extruder_definition: DefinitionContainer, machine_definition: DefinitionContainer, + def createExtruderTrain(self, extruder_definition: DefinitionContainerInterface, machine_definition: DefinitionContainerInterface, position, machine_id: str) -> None: # Cache some things. container_registry = ContainerRegistry.getInstance() @@ -525,7 +525,7 @@ class ExtruderManager(QObject): # # This is exposed to SettingFunction so it can be used in value functions. # - # \param key The key of the setting to retieve values for. + # \param key The key of the setting to retrieve values for. # # \return A list of values for all extruders. If an extruder does not have a value, it will not be in the list. # If no extruder has the value, the list will contain the global value. From 5ae02fb4c6a09145cca3fd3014399f8b486fb524 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 22 May 2017 12:50:53 +0200 Subject: [PATCH 3/5] Listen to changes on all extruders Not just the active extruder. The non-active extruder may change when loading a project file which happened to have the same printer (so no new printer is created) and the same material and variant in the active extruder but not the same material or variant in another extruder. Contributes to issue CURA-3803. --- cura/Settings/ExtrudersModel.py | 51 +++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index 7491f8aa93..918c674d3d 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -1,12 +1,15 @@ -# Copyright (c) 2016 Ultimaker B.V. +# Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer +from typing import Iterable import UM.Qt.ListModel from UM.Application import Application import UM.FlameProfiler from cura.Settings.ExtruderManager import ExtruderManager +from cura.Settings.ExtruderStack import ExtruderStack #To listen to changes on the extruders. +from cura.Settings.MachineManager import MachineManager #To listen to changes on the extruders of the currently active machine. ## Model that holds extruders. # @@ -66,16 +69,12 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): self._add_global = False self._simple_names = False - self._active_extruder_stack = None + self._active_machine_extruders = [] # type: Iterable[ExtruderStack] #Listen to changes. - Application.getInstance().globalContainerStackChanged.connect(self._updateExtruders) - manager = ExtruderManager.getInstance() - - self._updateExtruders() - - manager.activeExtruderChanged.connect(self._onActiveExtruderChanged) - self._onActiveExtruderChanged() + Application.getInstance().globalContainerStackChanged.connect(self._extrudersChanged) #When the machine is swapped we must update the active machine extruders. + ExtruderManager.getInstance().extrudersChanged.connect(self._extrudersChanged) #When the extruders change we must link to the stack-changed signal of the new extruder. + self._extrudersChanged() #Also calls _updateExtruders. def setAddGlobal(self, add): if add != self._add_global: @@ -104,17 +103,31 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): def simpleNames(self): return self._simple_names - def _onActiveExtruderChanged(self): - manager = ExtruderManager.getInstance() - active_extruder_stack = manager.getActiveExtruderStack() - if self._active_extruder_stack != active_extruder_stack: - if self._active_extruder_stack: - self._active_extruder_stack.containersChanged.disconnect(self._onExtruderStackContainersChanged) + ## Links to the stack-changed signal of the new extruders when an extruder + # is swapped out or added in the current machine. + # + # \param machine_id The machine for which the extruders changed. This is + # filled by the ExtruderManager.extrudersChanged signal when coming from + # that signal. Application.globalContainerStackChanged doesn't fill this + # signal; it's assumed to be the current printer in that case. + def _extrudersChanged(self, machine_id = None): + if machine_id is not None: + if Application.getInstance().getGlobalContainerStack() is None: + return #No machine, don't need to update the current machine's extruders. + if machine_id != Application.getInstance().getGlobalContainerStack().getId(): + return #Not the current machine. + #Unlink from old extruders. + for extruder in self._active_machine_extruders: + extruder.containersChanged.disconnect(self._onExtruderStackContainersChanged) - if active_extruder_stack: - # Update the model when the material container is changed - active_extruder_stack.containersChanged.connect(self._onExtruderStackContainersChanged) - self._active_extruder_stack = active_extruder_stack + #Link to new extruders. + self._active_machine_extruders = [] + extruder_manager = ExtruderManager.getInstance() + for extruder in extruder_manager.getExtruderStacks(): + extruder.containersChanged.connect(self._onExtruderStackContainersChanged) + self._active_machine_extruders.append(extruder) + + self._updateExtruders() #Since the new extruders may have different properties, update our own model. def _onExtruderStackContainersChanged(self, container): # Update when there is an empty container or material change From 8c166ea7708438bf8c55233eaa6bbb7bb502f64e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 22 May 2017 12:58:15 +0200 Subject: [PATCH 4/5] Use CuraContainerStack.definition instead of ContainerStack.getBottom() We know now that it must be a Cura Container Stack. This should be a bit faster, and makes the error message I was getting a bit more clear. Contributes to issue CURA-3803. --- cura/Settings/SettingInheritanceManager.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cura/Settings/SettingInheritanceManager.py b/cura/Settings/SettingInheritanceManager.py index 7e9bc2aa0e..d3a1655889 100644 --- a/cura/Settings/SettingInheritanceManager.py +++ b/cura/Settings/SettingInheritanceManager.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016 Ultimaker B.V. +# Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal @@ -35,7 +35,7 @@ class SettingInheritanceManager(QObject): ## Get the keys of all children settings with an override. @pyqtSlot(str, result = "QStringList") def getChildrenKeysWithOverride(self, key): - definitions = self._global_container_stack.getBottom().findDefinitions(key=key) + definitions = self._global_container_stack.definition.findDefinitions(key=key) if not definitions: Logger.log("w", "Could not find definition for key [%s]", key) return [] @@ -55,7 +55,7 @@ class SettingInheritanceManager(QObject): Logger.log("w", "Unable to find extruder for current machine with index %s", extruder_index) return [] - definitions = self._global_container_stack.getBottom().findDefinitions(key=key) + definitions = self._global_container_stack.definition.findDefinitions(key=key) if not definitions: Logger.log("w", "Could not find definition for key [%s] (2)", key) return [] @@ -93,7 +93,7 @@ class SettingInheritanceManager(QObject): def _onPropertyChanged(self, key, property_name): if (property_name == "value" or property_name == "enabled") and self._global_container_stack: - definitions = self._global_container_stack.getBottom().findDefinitions(key = key) + definitions = self._global_container_stack.definition.findDefinitions(key = key) if not definitions: return @@ -209,7 +209,7 @@ class SettingInheritanceManager(QObject): self._settings_with_inheritance_warning.append(setting_key) # Check all the categories if any of their children have their inheritance overwritten. - for category in self._global_container_stack.getBottom().findDefinitions(type = "category"): + for category in self._global_container_stack.definition.findDefinitions(type = "category"): if self._recursiveCheck(category): self._settings_with_inheritance_warning.append(category.key) From 5f0fb3f9bdf0d3e8cfdf8c36eac31c3c49d90872 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 22 May 2017 14:01:41 +0200 Subject: [PATCH 5/5] Don't squash signals updating materials and variants These may have different parameters, such as which machine and extruder they are updating the material and variant of. If we only pass the last signal on, then we're missing the update of other extruders. Contributes to issue CURA-3803. --- cura/Settings/MachineManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 9564b8a5b0..6f1b82a7b8 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -705,7 +705,7 @@ class MachineManager(QObject): # Depending on from/to material+current variant, a quality profile is chosen and set. @pyqtSlot(str) def setActiveMaterial(self, material_id: str): - with postponeSignals(*self._getContainerChangedSignals(), compress = True): + with postponeSignals(*self._getContainerChangedSignals()): containers = ContainerRegistry.getInstance().findInstanceContainers(id = material_id) if not containers or not self._active_container_stack: return @@ -770,7 +770,7 @@ class MachineManager(QObject): @pyqtSlot(str) def setActiveVariant(self, variant_id: str): - with postponeSignals(*self._getContainerChangedSignals(), compress = True): + with postponeSignals(*self._getContainerChangedSignals()): containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_id) if not containers or not self._active_container_stack: return