diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index 4595bf3996..f594ad3d0c 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Any, cast, List, Optional +from typing import Any, cast, List, Optional, Dict from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject from UM.Application import Application @@ -60,6 +60,8 @@ class CuraContainerStack(ContainerStack): import cura.CuraApplication #Here to prevent circular imports. self.setMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.SettingVersion) + self._settable_per_extruder_cache = {} # type: Dict[str, Any] + self.setDirty(False) # This is emitted whenever the containersChanged signal from the ContainerStack base class is emitted. @@ -387,6 +389,18 @@ class CuraContainerStack(ContainerStack): value = int(Application.getInstance().getMachineManager().defaultExtruderPosition) return value + def getProperty(self, key: str, property_name: str, context = None) -> Any: + if property_name == "settable_per_extruder": + # Setable per extruder isn't a value that can ever change. So once we requested it once, we can just keep + # that in memory. + try: + return self._settable_per_extruder_cache[key] + except KeyError: + self._settable_per_extruder_cache[key] = super().getProperty(key, property_name, context) + return self._settable_per_extruder_cache[key] + + return super().getProperty(key, property_name, context) + class _ContainerIndexes: """Private helper class to keep track of container positions and their types.""" diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index bb35b336c7..2a9838c671 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -131,13 +131,13 @@ class ExtruderStack(CuraContainerStack): if not self._next_stack: raise Exceptions.NoGlobalStackError("Extruder {id} is missing the next stack!".format(id = self.id)) - if context is None: - context = PropertyEvaluationContext() - context.pushContainer(self) + if context: + context.pushContainer(self) if not super().getProperty(key, "settable_per_extruder", context): result = self.getNextStack().getProperty(key, property_name, context) - context.popContainer() + if context: + context.popContainer() return result limit_to_extruder = super().getProperty(key, "limit_to_extruder", context) @@ -150,13 +150,15 @@ class ExtruderStack(CuraContainerStack): try: result = self.getNextStack().extruderList[int(limit_to_extruder)].getProperty(key, property_name, context) if result is not None: - context.popContainer() + if context: + context.popContainer() return result except IndexError: pass result = super().getProperty(key, property_name, context) - context.popContainer() + if context: + context.popContainer() return result @override(CuraContainerStack) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index a9164d0fb9..2c7cbf5e25 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -211,9 +211,8 @@ class GlobalStack(CuraContainerStack): if not self.definition.findDefinitions(key = key): return None - if context is None: - context = PropertyEvaluationContext() - context.pushContainer(self) + if context: + context.pushContainer(self) # Handle the "resolve" property. #TODO: Why the hell does this involve threading? @@ -238,13 +237,15 @@ class GlobalStack(CuraContainerStack): if super().getProperty(key, "settable_per_extruder", context): result = self._extruders[str(limit_to_extruder)].getProperty(key, property_name, context) if result is not None: - context.popContainer() + if context: + context.popContainer() return result else: Logger.log("e", "Setting {setting} has limit_to_extruder but is not settable per extruder!", setting = key) result = super().getProperty(key, property_name, context) - context.popContainer() + if context: + context.popContainer() return result @override(ContainerStack) @@ -256,8 +257,6 @@ class GlobalStack(CuraContainerStack): raise Exceptions.InvalidOperationError("Global stack cannot have a next stack!") - # protected: - # Determine whether or not we should try to get the "resolve" property instead of the # requested property. def _shouldResolve(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> bool: @@ -265,6 +264,10 @@ class GlobalStack(CuraContainerStack): # Do not try to resolve anything but the "value" property return False + if not self.definition.getProperty(key, "resolve"): + # If there isn't a resolve set for this setting, there isn't anything to do here. + return False + current_thread = threading.current_thread() if key in self._resolving_settings[current_thread.name]: # To prevent infinite recursion, if getProperty is called with the same key as @@ -273,10 +276,8 @@ class GlobalStack(CuraContainerStack): # track all settings that are being resolved. return False - setting_state = super().getProperty(key, "state", context = context) - if setting_state is not None and setting_state != InstanceState.Default: - # When the user has explicitly set a value, we should ignore any resolve and - # just return that value. + if self.hasUserValue(key): + # When the user has explicitly set a value, we should ignore any resolve and just return that value. return False return True