mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-06-30 06:55:12 +08:00
Merge pull request #4613 from Ultimaker/CURA-5812_fix_machine_actions
CURA-5808 Fix machine actions
This commit is contained in:
commit
41edfe85b5
@ -168,6 +168,8 @@ class CuraApplication(QtApplication):
|
||||
|
||||
self.default_theme = "cura-light"
|
||||
|
||||
self.change_log_url = "https://ultimaker.com/ultimaker-cura-latest-features"
|
||||
|
||||
self._boot_loading_time = time.time()
|
||||
|
||||
self._on_exit_callback_manager = OnExitCallbackManager(self)
|
||||
@ -304,8 +306,6 @@ class CuraApplication(QtApplication):
|
||||
self._machine_action_manager = MachineActionManager.MachineActionManager(self)
|
||||
self._machine_action_manager.initialize()
|
||||
|
||||
self.change_log_url = "https://ultimaker.com/ultimaker-cura-latest-features"
|
||||
|
||||
def __sendCommandToSingleInstance(self):
|
||||
self._single_instance = SingleInstance(self, self._files_to_open)
|
||||
|
||||
@ -701,7 +701,7 @@ class CuraApplication(QtApplication):
|
||||
self._quality_manager.initialize()
|
||||
|
||||
Logger.log("i", "Initializing machine manager")
|
||||
self._machine_manager = MachineManager(self)
|
||||
self._machine_manager = MachineManager(self, parent = self)
|
||||
|
||||
Logger.log("i", "Initializing container manager")
|
||||
self._container_manager = ContainerManager(self)
|
||||
|
@ -1,13 +1,13 @@
|
||||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import os
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.PluginObject import PluginObject
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Application import Application
|
||||
|
||||
import os
|
||||
|
||||
|
||||
## Machine actions are actions that are added to a specific machine type. Examples of such actions are
|
||||
@ -19,7 +19,7 @@ class MachineAction(QObject, PluginObject):
|
||||
## Create a new Machine action.
|
||||
# \param key unique key of the machine action
|
||||
# \param label Human readable label used to identify the machine action.
|
||||
def __init__(self, key, label = ""):
|
||||
def __init__(self, key: str, label: str = "") -> None:
|
||||
super().__init__()
|
||||
self._key = key
|
||||
self._label = label
|
||||
@ -30,14 +30,14 @@ class MachineAction(QObject, PluginObject):
|
||||
labelChanged = pyqtSignal()
|
||||
onFinished = pyqtSignal()
|
||||
|
||||
def getKey(self):
|
||||
def getKey(self) -> str:
|
||||
return self._key
|
||||
|
||||
@pyqtProperty(str, notify = labelChanged)
|
||||
def label(self):
|
||||
def label(self) -> str:
|
||||
return self._label
|
||||
|
||||
def setLabel(self, label):
|
||||
def setLabel(self, label: str) -> None:
|
||||
if self._label != label:
|
||||
self._label = label
|
||||
self.labelChanged.emit()
|
||||
@ -46,29 +46,35 @@ class MachineAction(QObject, PluginObject):
|
||||
# This should not be re-implemented by child classes, instead re-implement _reset.
|
||||
# /sa _reset
|
||||
@pyqtSlot()
|
||||
def reset(self):
|
||||
def reset(self) -> None:
|
||||
self._finished = False
|
||||
self._reset()
|
||||
|
||||
## Protected implementation of reset.
|
||||
# /sa reset()
|
||||
def _reset(self):
|
||||
def _reset(self) -> None:
|
||||
pass
|
||||
|
||||
@pyqtSlot()
|
||||
def setFinished(self):
|
||||
def setFinished(self) -> None:
|
||||
self._finished = True
|
||||
self._reset()
|
||||
self.onFinished.emit()
|
||||
|
||||
@pyqtProperty(bool, notify = onFinished)
|
||||
def finished(self):
|
||||
def finished(self) -> bool:
|
||||
return self._finished
|
||||
|
||||
## Protected helper to create a view object based on provided QML.
|
||||
def _createViewFromQML(self):
|
||||
path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), self._qml_url)
|
||||
self._view = Application.getInstance().createQmlComponent(path, {"manager": self})
|
||||
def _createViewFromQML(self) -> None:
|
||||
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
|
||||
if plugin_path is None:
|
||||
Logger.log("e", "Cannot create QML view: cannot find plugin path for plugin [%s]", self.getPluginId())
|
||||
return
|
||||
path = os.path.join(plugin_path, self._qml_url)
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
self._view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
|
||||
|
||||
@pyqtProperty(QObject, constant = True)
|
||||
def displayItem(self):
|
||||
|
@ -1,12 +1,18 @@
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from typing import TYPE_CHECKING, Optional, List, Set, Dict
|
||||
|
||||
from PyQt5.QtCore import QObject
|
||||
|
||||
from UM.FlameProfiler import pyqtSlot
|
||||
from UM.Logger import Logger
|
||||
from UM.PluginRegistry import PluginRegistry # So MachineAction can be added as plugin type
|
||||
from UM.Settings.DefinitionContainer import DefinitionContainer
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
from .MachineAction import MachineAction
|
||||
|
||||
|
||||
## Raised when trying to add an unknown machine action as a required action
|
||||
@ -20,46 +26,54 @@ class NotUniqueMachineActionError(Exception):
|
||||
|
||||
|
||||
class MachineActionManager(QObject):
|
||||
def __init__(self, application, parent = None):
|
||||
super().__init__(parent)
|
||||
def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
|
||||
super().__init__(parent = parent)
|
||||
self._application = application
|
||||
self._container_registry = self._application.getContainerRegistry()
|
||||
|
||||
self._machine_actions = {} # Dict of all known machine actions
|
||||
self._required_actions = {} # Dict of all required actions by definition ID
|
||||
self._supported_actions = {} # Dict of all supported actions by definition ID
|
||||
self._first_start_actions = {} # Dict of all actions that need to be done when first added by definition ID
|
||||
# Keeps track of which machines have already been processed so we don't do that again.
|
||||
self._definition_ids_with_default_actions_added = set() # type: Set[str]
|
||||
|
||||
# Dict of all known machine actions
|
||||
self._machine_actions = {} # type: Dict[str, MachineAction]
|
||||
# Dict of all required actions by definition ID
|
||||
self._required_actions = {} # type: Dict[str, List[MachineAction]]
|
||||
# Dict of all supported actions by definition ID
|
||||
self._supported_actions = {} # type: Dict[str, List[MachineAction]]
|
||||
# Dict of all actions that need to be done when first added by definition ID
|
||||
self._first_start_actions = {} # type: Dict[str, List[MachineAction]]
|
||||
|
||||
def initialize(self):
|
||||
container_registry = self._application.getContainerRegistry()
|
||||
|
||||
# Add machine_action as plugin type
|
||||
PluginRegistry.addType("machine_action", self.addMachineAction)
|
||||
|
||||
# Ensure that all containers that were registered before creation of this registry are also handled.
|
||||
# This should not have any effect, but it makes it safer if we ever refactor the order of things.
|
||||
for container in container_registry.findDefinitionContainers():
|
||||
self._onContainerAdded(container)
|
||||
# Adds all default machine actions that are defined in the machine definition for the given machine.
|
||||
def addDefaultMachineActions(self, global_stack: "GlobalStack") -> None:
|
||||
definition_id = global_stack.definition.getId()
|
||||
|
||||
container_registry.containerAdded.connect(self._onContainerAdded)
|
||||
if definition_id in self._definition_ids_with_default_actions_added:
|
||||
Logger.log("i", "Default machine actions have been added for machine definition [%s], do nothing.",
|
||||
definition_id)
|
||||
return
|
||||
|
||||
def _onContainerAdded(self, container):
|
||||
## Ensure that the actions are added to this manager
|
||||
if isinstance(container, DefinitionContainer):
|
||||
supported_actions = container.getMetaDataEntry("supported_actions", [])
|
||||
for action in supported_actions:
|
||||
self.addSupportedAction(container.getId(), action)
|
||||
supported_actions = global_stack.getMetaDataEntry("supported_actions", [])
|
||||
for action_key in supported_actions:
|
||||
self.addSupportedAction(definition_id, action_key)
|
||||
|
||||
required_actions = container.getMetaDataEntry("required_actions", [])
|
||||
for action in required_actions:
|
||||
self.addRequiredAction(container.getId(), action)
|
||||
required_actions = global_stack.getMetaDataEntry("required_actions", [])
|
||||
for action_key in required_actions:
|
||||
self.addRequiredAction(definition_id, action_key)
|
||||
|
||||
first_start_actions = container.getMetaDataEntry("first_start_actions", [])
|
||||
for action in first_start_actions:
|
||||
self.addFirstStartAction(container.getId(), action)
|
||||
first_start_actions = global_stack.getMetaDataEntry("first_start_actions", [])
|
||||
for action_key in first_start_actions:
|
||||
self.addFirstStartAction(definition_id, action_key)
|
||||
|
||||
self._definition_ids_with_default_actions_added.add(definition_id)
|
||||
Logger.log("i", "Default machine actions added for machine definition [%s]", definition_id)
|
||||
|
||||
## Add a required action to a machine
|
||||
# Raises an exception when the action is not recognised.
|
||||
def addRequiredAction(self, definition_id, action_key):
|
||||
def addRequiredAction(self, definition_id: str, action_key: str) -> None:
|
||||
if action_key in self._machine_actions:
|
||||
if definition_id in self._required_actions:
|
||||
if self._machine_actions[action_key] not in self._required_actions[definition_id]:
|
||||
@ -70,7 +84,7 @@ class MachineActionManager(QObject):
|
||||
raise UnknownMachineActionError("Action %s, which is required for %s is not known." % (action_key, definition_id))
|
||||
|
||||
## Add a supported action to a machine.
|
||||
def addSupportedAction(self, definition_id, action_key):
|
||||
def addSupportedAction(self, definition_id: str, action_key: str) -> None:
|
||||
if action_key in self._machine_actions:
|
||||
if definition_id in self._supported_actions:
|
||||
if self._machine_actions[action_key] not in self._supported_actions[definition_id]:
|
||||
@ -81,13 +95,10 @@ class MachineActionManager(QObject):
|
||||
Logger.log("w", "Unable to add %s to %s, as the action is not recognised", action_key, definition_id)
|
||||
|
||||
## Add an action to the first start list of a machine.
|
||||
def addFirstStartAction(self, definition_id, action_key, index = None):
|
||||
def addFirstStartAction(self, definition_id: str, action_key: str) -> None:
|
||||
if action_key in self._machine_actions:
|
||||
if definition_id in self._first_start_actions:
|
||||
if index is not None:
|
||||
self._first_start_actions[definition_id].insert(index, self._machine_actions[action_key])
|
||||
else:
|
||||
self._first_start_actions[definition_id].append(self._machine_actions[action_key])
|
||||
self._first_start_actions[definition_id].append(self._machine_actions[action_key])
|
||||
else:
|
||||
self._first_start_actions[definition_id] = [self._machine_actions[action_key]]
|
||||
else:
|
||||
@ -95,7 +106,7 @@ class MachineActionManager(QObject):
|
||||
|
||||
## Add a (unique) MachineAction
|
||||
# if the Key of the action is not unique, an exception is raised.
|
||||
def addMachineAction(self, action):
|
||||
def addMachineAction(self, action: "MachineAction") -> None:
|
||||
if action.getKey() not in self._machine_actions:
|
||||
self._machine_actions[action.getKey()] = action
|
||||
else:
|
||||
@ -105,7 +116,7 @@ class MachineActionManager(QObject):
|
||||
# \param definition_id The ID of the definition you want the supported actions of
|
||||
# \returns set of supported actions.
|
||||
@pyqtSlot(str, result = "QVariantList")
|
||||
def getSupportedActions(self, definition_id):
|
||||
def getSupportedActions(self, definition_id: str) -> List["MachineAction"]:
|
||||
if definition_id in self._supported_actions:
|
||||
return list(self._supported_actions[definition_id])
|
||||
else:
|
||||
@ -114,11 +125,11 @@ class MachineActionManager(QObject):
|
||||
## Get all actions required by given machine
|
||||
# \param definition_id The ID of the definition you want the required actions of
|
||||
# \returns set of required actions.
|
||||
def getRequiredActions(self, definition_id):
|
||||
def getRequiredActions(self, definition_id: str) -> List["MachineAction"]:
|
||||
if definition_id in self._required_actions:
|
||||
return self._required_actions[definition_id]
|
||||
else:
|
||||
return set()
|
||||
return list()
|
||||
|
||||
## Get all actions that need to be performed upon first start of a given machine.
|
||||
# Note that contrary to required / supported actions a list is returned (as it could be required to run the same
|
||||
@ -126,7 +137,7 @@ class MachineActionManager(QObject):
|
||||
# \param definition_id The ID of the definition that you want to get the "on added" actions for.
|
||||
# \returns List of actions.
|
||||
@pyqtSlot(str, result="QVariantList")
|
||||
def getFirstStartActions(self, definition_id):
|
||||
def getFirstStartActions(self, definition_id: str) -> List["MachineAction"]:
|
||||
if definition_id in self._first_start_actions:
|
||||
return self._first_start_actions[definition_id]
|
||||
else:
|
||||
@ -134,7 +145,7 @@ class MachineActionManager(QObject):
|
||||
|
||||
## Remove Machine action from manager
|
||||
# \param action to remove
|
||||
def removeMachineAction(self, action):
|
||||
def removeMachineAction(self, action: "MachineAction") -> None:
|
||||
try:
|
||||
del self._machine_actions[action.getKey()]
|
||||
except KeyError:
|
||||
@ -143,7 +154,7 @@ class MachineActionManager(QObject):
|
||||
## Get MachineAction by key
|
||||
# \param key String of key to select
|
||||
# \return Machine action if found, None otherwise
|
||||
def getMachineAction(self, key):
|
||||
def getMachineAction(self, key: str) -> Optional["MachineAction"]:
|
||||
if key in self._machine_actions:
|
||||
return self._machine_actions[key]
|
||||
else:
|
||||
|
@ -50,7 +50,7 @@ class PrinterOutputModel(QObject):
|
||||
self._printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in
|
||||
self._extruders]
|
||||
|
||||
self._camera = None
|
||||
self._camera = None # type: Optional[NetworkCamera]
|
||||
|
||||
@pyqtProperty(str, constant = True)
|
||||
def firmwareVersion(self) -> str:
|
||||
|
@ -145,13 +145,11 @@ class CuraContainerStack(ContainerStack):
|
||||
def setDefinition(self, new_definition: DefinitionContainerInterface) -> None:
|
||||
self.replaceContainer(_ContainerIndexes.Definition, new_definition)
|
||||
|
||||
## Get the definition container.
|
||||
#
|
||||
# \return The definition container. Should always be a valid container, but can be equal to the empty InstanceContainer.
|
||||
@pyqtProperty(QObject, fset = setDefinition, notify = pyqtContainersChanged)
|
||||
def definition(self) -> DefinitionContainer:
|
||||
def getDefinition(self) -> "DefinitionContainer":
|
||||
return cast(DefinitionContainer, self._containers[_ContainerIndexes.Definition])
|
||||
|
||||
definition = pyqtProperty(QObject, fget = getDefinition, fset = setDefinition, notify = pyqtContainersChanged)
|
||||
|
||||
@override(ContainerStack)
|
||||
def getBottom(self) -> "DefinitionContainer":
|
||||
return self.definition
|
||||
|
@ -20,7 +20,6 @@ from UM.Message import Message
|
||||
from UM.Settings.SettingFunction import SettingFunction
|
||||
from UM.Signal import postponeSignals, CompressTechnique
|
||||
|
||||
import cura.CuraApplication
|
||||
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
|
||||
from cura.PrinterOutputDevice import PrinterOutputDevice
|
||||
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
|
||||
@ -29,6 +28,9 @@ from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
|
||||
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
from cura.Settings.ExtruderStack import ExtruderStack
|
||||
from cura.Settings.cura_empty_instance_containers import (empty_definition_changes_container, empty_variant_container,
|
||||
empty_material_container, empty_quality_container,
|
||||
empty_quality_changes_container)
|
||||
|
||||
from .CuraStackBuilder import CuraStackBuilder
|
||||
|
||||
@ -36,6 +38,7 @@ from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Settings.CuraContainerStack import CuraContainerStack
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
from cura.Machines.MaterialManager import MaterialManager
|
||||
@ -47,7 +50,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class MachineManager(QObject):
|
||||
def __init__(self, parent: QObject = None) -> None:
|
||||
def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
self._active_container_stack = None # type: Optional[ExtruderStack]
|
||||
@ -66,9 +69,10 @@ class MachineManager(QObject):
|
||||
self._instance_container_timer.setSingleShot(True)
|
||||
self._instance_container_timer.timeout.connect(self.__emitChangedSignals)
|
||||
|
||||
self._application = cura.CuraApplication.CuraApplication.getInstance() #type: cura.CuraApplication.CuraApplication
|
||||
self._application = application
|
||||
self._container_registry = self._application.getContainerRegistry()
|
||||
self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged)
|
||||
self._application.getContainerRegistry().containerLoadComplete.connect(self._onContainersChanged)
|
||||
self._container_registry.containerLoadComplete.connect(self._onContainersChanged)
|
||||
|
||||
## When the global container is changed, active material probably needs to be updated.
|
||||
self.globalContainerChanged.connect(self.activeMaterialChanged)
|
||||
@ -80,13 +84,6 @@ class MachineManager(QObject):
|
||||
|
||||
self._stacks_have_errors = None # type: Optional[bool]
|
||||
|
||||
self._empty_container = CuraContainerRegistry.getInstance().getEmptyInstanceContainer() #type: InstanceContainer
|
||||
self._empty_definition_changes_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_definition_changes")[0] #type: InstanceContainer
|
||||
self._empty_variant_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_variant")[0] #type: InstanceContainer
|
||||
self._empty_material_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_material")[0] #type: InstanceContainer
|
||||
self._empty_quality_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_quality")[0] #type: InstanceContainer
|
||||
self._empty_quality_changes_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_quality_changes")[0] #type: InstanceContainer
|
||||
|
||||
self._onGlobalContainerChanged()
|
||||
|
||||
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
|
||||
@ -192,21 +189,21 @@ class MachineManager(QObject):
|
||||
for extruder in self._global_container_stack.extruders.values():
|
||||
extruder_configuration = ExtruderConfigurationModel()
|
||||
# For compare just the GUID is needed at this moment
|
||||
mat_type = extruder.material.getMetaDataEntry("material") if extruder.material != self._empty_material_container else None
|
||||
mat_guid = extruder.material.getMetaDataEntry("GUID") if extruder.material != self._empty_material_container else None
|
||||
mat_color = extruder.material.getMetaDataEntry("color_name") if extruder.material != self._empty_material_container else None
|
||||
mat_brand = extruder.material.getMetaDataEntry("brand") if extruder.material != self._empty_material_container else None
|
||||
mat_name = extruder.material.getMetaDataEntry("name") if extruder.material != self._empty_material_container else None
|
||||
mat_type = extruder.material.getMetaDataEntry("material") if extruder.material != empty_material_container else None
|
||||
mat_guid = extruder.material.getMetaDataEntry("GUID") if extruder.material != empty_material_container else None
|
||||
mat_color = extruder.material.getMetaDataEntry("color_name") if extruder.material != empty_material_container else None
|
||||
mat_brand = extruder.material.getMetaDataEntry("brand") if extruder.material != empty_material_container else None
|
||||
mat_name = extruder.material.getMetaDataEntry("name") if extruder.material != empty_material_container else None
|
||||
material_model = MaterialOutputModel(mat_guid, mat_type, mat_color, mat_brand, mat_name)
|
||||
|
||||
extruder_configuration.position = int(extruder.getMetaDataEntry("position"))
|
||||
extruder_configuration.material = material_model
|
||||
extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != self._empty_variant_container else None
|
||||
extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != empty_variant_container else None
|
||||
self._current_printer_configuration.extruderConfigurations.append(extruder_configuration)
|
||||
|
||||
# an empty build plate configuration from the network printer is presented as an empty string, so use "" for an
|
||||
# empty build plate.
|
||||
self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value") if self._global_container_stack.variant != self._empty_variant_container else ""
|
||||
self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value") if self._global_container_stack.variant != empty_variant_container else ""
|
||||
self.currentConfigurationChanged.emit()
|
||||
|
||||
@pyqtSlot(QObject, result = bool)
|
||||
@ -260,14 +257,14 @@ class MachineManager(QObject):
|
||||
|
||||
# Global stack can have only a variant if it is a buildplate
|
||||
global_variant = self._global_container_stack.variant
|
||||
if global_variant != self._empty_variant_container:
|
||||
if global_variant != empty_variant_container:
|
||||
if global_variant.getMetaDataEntry("hardware_type") != "buildplate":
|
||||
self._global_container_stack.setVariant(self._empty_variant_container)
|
||||
self._global_container_stack.setVariant(empty_variant_container)
|
||||
|
||||
# set the global material to empty as we now use the extruder stack at all times - CURA-4482
|
||||
global_material = self._global_container_stack.material
|
||||
if global_material != self._empty_material_container:
|
||||
self._global_container_stack.setMaterial(self._empty_material_container)
|
||||
if global_material != empty_material_container:
|
||||
self._global_container_stack.setMaterial(empty_material_container)
|
||||
|
||||
# Listen for changes on all extruder stacks
|
||||
for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
|
||||
@ -369,6 +366,10 @@ class MachineManager(QObject):
|
||||
return
|
||||
|
||||
global_stack = containers[0]
|
||||
|
||||
# Make sure that the default machine actions for this machine have been added
|
||||
self._application.getMachineActionManager().addDefaultMachineActions(global_stack)
|
||||
|
||||
ExtruderManager.getInstance()._fixSingleExtrusionMachineExtruderDefinition(global_stack)
|
||||
if not global_stack.isValid():
|
||||
# Mark global stack as invalid
|
||||
@ -595,7 +596,7 @@ class MachineManager(QObject):
|
||||
def globalVariantName(self) -> str:
|
||||
if self._global_container_stack:
|
||||
variant = self._global_container_stack.variant
|
||||
if variant and not isinstance(variant, type(self._empty_variant_container)):
|
||||
if variant and not isinstance(variant, type(empty_variant_container)):
|
||||
return variant.getName()
|
||||
return ""
|
||||
|
||||
@ -783,7 +784,7 @@ class MachineManager(QObject):
|
||||
if not stack.isEnabled:
|
||||
continue
|
||||
material_container = stack.material
|
||||
if material_container == self._empty_material_container:
|
||||
if material_container == empty_material_container:
|
||||
continue
|
||||
if material_container.getMetaDataEntry("buildplate_compatible"):
|
||||
buildplate_compatible = buildplate_compatible and material_container.getMetaDataEntry("buildplate_compatible")[self.activeVariantBuildplateName]
|
||||
@ -805,7 +806,7 @@ class MachineManager(QObject):
|
||||
extruder_stacks = self._global_container_stack.extruders.values()
|
||||
for stack in extruder_stacks:
|
||||
material_container = stack.material
|
||||
if material_container == self._empty_material_container:
|
||||
if material_container == empty_material_container:
|
||||
continue
|
||||
buildplate_compatible = material_container.getMetaDataEntry("buildplate_compatible")[self.activeVariantBuildplateName] if material_container.getMetaDataEntry("buildplate_compatible") else True
|
||||
buildplate_usable = material_container.getMetaDataEntry("buildplate_recommended")[self.activeVariantBuildplateName] if material_container.getMetaDataEntry("buildplate_recommended") else True
|
||||
@ -875,7 +876,7 @@ class MachineManager(QObject):
|
||||
extruder_manager = self._application.getExtruderManager()
|
||||
|
||||
definition_changes_container = self._global_container_stack.definitionChanges
|
||||
if not self._global_container_stack or definition_changes_container == self._empty_definition_changes_container:
|
||||
if not self._global_container_stack or definition_changes_container == empty_definition_changes_container:
|
||||
return
|
||||
|
||||
previous_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
|
||||
@ -1074,7 +1075,7 @@ class MachineManager(QObject):
|
||||
for stack in active_stacks:
|
||||
variant_container = stack.variant
|
||||
position = stack.getMetaDataEntry("position")
|
||||
if variant_container and variant_container != self._empty_variant_container:
|
||||
if variant_container and variant_container != empty_variant_container:
|
||||
result[position] = variant_container.getName()
|
||||
|
||||
return result
|
||||
@ -1088,11 +1089,11 @@ class MachineManager(QObject):
|
||||
return
|
||||
self._current_quality_group = None
|
||||
self._current_quality_changes_group = None
|
||||
self._global_container_stack.quality = self._empty_quality_container
|
||||
self._global_container_stack.qualityChanges = self._empty_quality_changes_container
|
||||
self._global_container_stack.quality = empty_quality_container
|
||||
self._global_container_stack.qualityChanges = empty_quality_changes_container
|
||||
for extruder in self._global_container_stack.extruders.values():
|
||||
extruder.quality = self._empty_quality_container
|
||||
extruder.qualityChanges = self._empty_quality_changes_container
|
||||
extruder.quality = empty_quality_container
|
||||
extruder.qualityChanges = empty_quality_changes_container
|
||||
|
||||
self.activeQualityGroupChanged.emit()
|
||||
self.activeQualityChangesGroupChanged.emit()
|
||||
@ -1117,13 +1118,13 @@ class MachineManager(QObject):
|
||||
# Set quality and quality_changes for the GlobalStack
|
||||
self._global_container_stack.quality = quality_group.node_for_global.getContainer()
|
||||
if empty_quality_changes:
|
||||
self._global_container_stack.qualityChanges = self._empty_quality_changes_container
|
||||
self._global_container_stack.qualityChanges = empty_quality_changes_container
|
||||
|
||||
# Set quality and quality_changes for each ExtruderStack
|
||||
for position, node in quality_group.nodes_for_extruders.items():
|
||||
self._global_container_stack.extruders[str(position)].quality = node.getContainer()
|
||||
if empty_quality_changes:
|
||||
self._global_container_stack.extruders[str(position)].qualityChanges = self._empty_quality_changes_container
|
||||
self._global_container_stack.extruders[str(position)].qualityChanges = empty_quality_changes_container
|
||||
|
||||
self.activeQualityGroupChanged.emit()
|
||||
self.activeQualityChangesGroupChanged.emit()
|
||||
@ -1149,8 +1150,8 @@ class MachineManager(QObject):
|
||||
if quality_group is None:
|
||||
self._fixQualityChangesGroupToNotSupported(quality_changes_group)
|
||||
|
||||
quality_changes_container = self._empty_quality_changes_container
|
||||
quality_container = self._empty_quality_container # type: Optional[InstanceContainer]
|
||||
quality_changes_container = empty_quality_changes_container
|
||||
quality_container = empty_quality_container # type: Optional[InstanceContainer]
|
||||
if quality_changes_group.node_for_global and quality_changes_group.node_for_global.getContainer():
|
||||
quality_changes_container = cast(InstanceContainer, quality_changes_group.node_for_global.getContainer())
|
||||
if quality_group is not None and quality_group.node_for_global and quality_group.node_for_global.getContainer():
|
||||
@ -1165,8 +1166,8 @@ class MachineManager(QObject):
|
||||
if quality_group is not None:
|
||||
quality_node = quality_group.nodes_for_extruders.get(position)
|
||||
|
||||
quality_changes_container = self._empty_quality_changes_container
|
||||
quality_container = self._empty_quality_container
|
||||
quality_changes_container = empty_quality_changes_container
|
||||
quality_container = empty_quality_container
|
||||
if quality_changes_node and quality_changes_node.getContainer():
|
||||
quality_changes_container = cast(InstanceContainer, quality_changes_node.getContainer())
|
||||
if quality_node and quality_node.getContainer():
|
||||
@ -1200,7 +1201,7 @@ class MachineManager(QObject):
|
||||
self._global_container_stack.extruders[position].material = container_node.getContainer()
|
||||
root_material_id = container_node.getMetaDataEntry("base_file", None)
|
||||
else:
|
||||
self._global_container_stack.extruders[position].material = self._empty_material_container
|
||||
self._global_container_stack.extruders[position].material = empty_material_container
|
||||
root_material_id = None
|
||||
# The _current_root_material_id is used in the MaterialMenu to see which material is selected
|
||||
if root_material_id != self._current_root_material_id[position]:
|
||||
@ -1275,7 +1276,7 @@ class MachineManager(QObject):
|
||||
|
||||
current_material_base_name = extruder.material.getMetaDataEntry("base_file")
|
||||
current_nozzle_name = None
|
||||
if extruder.variant.getId() != self._empty_variant_container.getId():
|
||||
if extruder.variant.getId() != empty_variant_container.getId():
|
||||
current_nozzle_name = extruder.variant.getMetaDataEntry("name")
|
||||
|
||||
from UM.Settings.Interfaces import PropertyEvaluationContext
|
||||
@ -1350,12 +1351,12 @@ class MachineManager(QObject):
|
||||
if variant_container_node:
|
||||
self._setVariantNode(position, variant_container_node)
|
||||
else:
|
||||
self._global_container_stack.extruders[position].variant = self._empty_variant_container
|
||||
self._global_container_stack.extruders[position].variant = empty_variant_container
|
||||
|
||||
if material_container_node:
|
||||
self._setMaterial(position, material_container_node)
|
||||
else:
|
||||
self._global_container_stack.extruders[position].material = self._empty_material_container
|
||||
self._global_container_stack.extruders[position].material = empty_material_container
|
||||
self.updateMaterialWithVariant(position)
|
||||
|
||||
if configuration.buildplateConfiguration is not None:
|
||||
@ -1363,9 +1364,9 @@ class MachineManager(QObject):
|
||||
if global_variant_container_node:
|
||||
self._setGlobalVariant(global_variant_container_node)
|
||||
else:
|
||||
self._global_container_stack.variant = self._empty_variant_container
|
||||
self._global_container_stack.variant = empty_variant_container
|
||||
else:
|
||||
self._global_container_stack.variant = self._empty_variant_container
|
||||
self._global_container_stack.variant = empty_variant_container
|
||||
self._updateQualityWithMaterial()
|
||||
|
||||
# See if we need to show the Discard or Keep changes screen
|
||||
@ -1483,7 +1484,7 @@ class MachineManager(QObject):
|
||||
# This is not changing the quality for the active machine !!!!!!!!
|
||||
global_stack.quality = quality_group.node_for_global.getContainer()
|
||||
for extruder_nr, extruder_stack in global_stack.extruders.items():
|
||||
quality_container = self._empty_quality_container
|
||||
quality_container = empty_quality_container
|
||||
if extruder_nr in quality_group.nodes_for_extruders:
|
||||
container = quality_group.nodes_for_extruders[extruder_nr].getContainer()
|
||||
quality_container = container if container is not None else quality_container
|
||||
@ -1527,7 +1528,7 @@ class MachineManager(QObject):
|
||||
|
||||
@pyqtProperty(str, notify = activeQualityGroupChanged)
|
||||
def activeQualityOrQualityChangesName(self) -> str:
|
||||
name = self._empty_quality_container.getName()
|
||||
name = empty_quality_container.getName()
|
||||
if self._current_quality_changes_group:
|
||||
name = self._current_quality_changes_group.name
|
||||
elif self._current_quality_group:
|
||||
|
@ -5,6 +5,19 @@ import pytest
|
||||
|
||||
from cura.MachineAction import MachineAction
|
||||
from cura.MachineActionManager import NotUniqueMachineActionError, UnknownMachineActionError
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def global_stack():
|
||||
gs = GlobalStack("test_global_stack")
|
||||
gs._metadata = {
|
||||
"supported_actions": ["supported_action_1", "supported_action_2"],
|
||||
"required_actions": ["required_action_1", "required_action_2"],
|
||||
"first_start_actions": ["first_start_actions_1", "first_start_actions_2"]
|
||||
}
|
||||
return gs
|
||||
|
||||
|
||||
class Machine:
|
||||
def __init__(self, key = ""):
|
||||
@ -13,6 +26,32 @@ class Machine:
|
||||
def getKey(self):
|
||||
return self._key
|
||||
|
||||
|
||||
def test_addDefaultMachineActions(machine_action_manager, global_stack):
|
||||
# The actions need to be registered first as "available actions" in the manager,
|
||||
# same as the "machine_action" type does when registering a plugin.
|
||||
all_actions = []
|
||||
for action_key_list in global_stack._metadata.values():
|
||||
for key in action_key_list:
|
||||
all_actions.append(MachineAction(key = key))
|
||||
for action in all_actions:
|
||||
machine_action_manager.addMachineAction(action)
|
||||
|
||||
# Only the actions in the definition that were registered first will be added to the machine.
|
||||
# For the sake of this test, all the actions were previouly added.
|
||||
machine_action_manager.addDefaultMachineActions(global_stack)
|
||||
definition_id = global_stack.getDefinition().getId()
|
||||
|
||||
support_action_keys = [a.getKey() for a in machine_action_manager.getSupportedActions(definition_id)]
|
||||
assert support_action_keys == global_stack.getMetaDataEntry("supported_actions")
|
||||
|
||||
required_action_keys = [a.getKey() for a in machine_action_manager.getRequiredActions(definition_id)]
|
||||
assert required_action_keys == global_stack.getMetaDataEntry("required_actions")
|
||||
|
||||
first_start_action_keys = [a.getKey() for a in machine_action_manager.getFirstStartActions(definition_id)]
|
||||
assert first_start_action_keys == global_stack.getMetaDataEntry("first_start_actions")
|
||||
|
||||
|
||||
def test_addMachineAction(machine_action_manager):
|
||||
|
||||
test_action = MachineAction(key = "test_action")
|
||||
@ -44,7 +83,7 @@ def test_addMachineAction(machine_action_manager):
|
||||
assert machine_action_manager.getSupportedActions(test_machine) == [test_action, test_action_2]
|
||||
|
||||
# Check that the machine has no required actions yet.
|
||||
assert machine_action_manager.getRequiredActions(test_machine) == set()
|
||||
assert machine_action_manager.getRequiredActions(test_machine) == list()
|
||||
|
||||
## Ensure that only known actions can be added.
|
||||
with pytest.raises(UnknownMachineActionError):
|
||||
@ -65,12 +104,3 @@ def test_addMachineAction(machine_action_manager):
|
||||
machine_action_manager.addFirstStartAction(test_machine, "test_action")
|
||||
machine_action_manager.addFirstStartAction(test_machine, "test_action")
|
||||
assert machine_action_manager.getFirstStartActions(test_machine) == [test_action, test_action]
|
||||
|
||||
# Check if inserting an action works
|
||||
machine_action_manager.addFirstStartAction(test_machine, "test_action_2", index = 1)
|
||||
assert machine_action_manager.getFirstStartActions(test_machine) == [test_action, test_action_2, test_action]
|
||||
|
||||
# Check that adding a unknown action doesn't change anything.
|
||||
machine_action_manager.addFirstStartAction(test_machine, "key_that_doesnt_exist", index = 1)
|
||||
assert machine_action_manager.getFirstStartActions(test_machine) == [test_action, test_action_2, test_action]
|
||||
|
||||
|
@ -13,7 +13,6 @@ from cura.CuraApplication import CuraApplication
|
||||
from cura.MachineActionManager import MachineActionManager
|
||||
|
||||
|
||||
|
||||
# Create a CuraApplication object that will be shared among all tests. It needs to be initialized.
|
||||
# Since we need to use it more that once, we create the application the first time and use its instance afterwards.
|
||||
@pytest.fixture()
|
||||
|
Loading…
x
Reference in New Issue
Block a user