MachineSettingsAction.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. # Copyright (c) 2019 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from typing import Optional, TYPE_CHECKING
  4. from PyQt5.QtCore import pyqtProperty
  5. import UM.i18n
  6. from UM.FlameProfiler import pyqtSlot
  7. from UM.Settings.ContainerRegistry import ContainerRegistry
  8. from UM.Settings.DefinitionContainer import DefinitionContainer
  9. from cura.MachineAction import MachineAction
  10. from cura.Settings.CuraStackBuilder import CuraStackBuilder
  11. from cura.Settings.cura_empty_instance_containers import isEmptyContainer
  12. if TYPE_CHECKING:
  13. from PyQt5.QtCore import QObject
  14. catalog = UM.i18n.i18nCatalog("cura")
  15. ## This action allows for certain settings that are "machine only") to be modified.
  16. # It automatically detects machine definitions that it knows how to change and attaches itself to those.
  17. class MachineSettingsAction(MachineAction):
  18. def __init__(self, parent: Optional["QObject"] = None) -> None:
  19. super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings"))
  20. self._qml_url = "MachineSettingsAction.qml"
  21. from cura.CuraApplication import CuraApplication
  22. self._application = CuraApplication.getInstance()
  23. from cura.Settings.CuraContainerStack import _ContainerIndexes
  24. self._store_container_index = _ContainerIndexes.DefinitionChanges
  25. self._container_registry = ContainerRegistry.getInstance()
  26. self._container_registry.containerAdded.connect(self._onContainerAdded)
  27. # The machine settings dialog blocks auto-slicing when it's shown, and re-enables it when it's finished.
  28. self._backend = self._application.getBackend()
  29. self.onFinished.connect(self._onFinished)
  30. # Which container index in a stack to store machine setting changes.
  31. @pyqtProperty(int, constant = True)
  32. def storeContainerIndex(self) -> int:
  33. return self._store_container_index
  34. def _onContainerAdded(self, container):
  35. # Add this action as a supported action to all machine definitions
  36. if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine":
  37. self._application.getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
  38. def _reset(self):
  39. global_stack = self._application.getMachineManager().activeMachine
  40. if not global_stack:
  41. return
  42. # Make sure there is a definition_changes container to store the machine settings
  43. definition_changes_id = global_stack.definitionChanges.getId()
  44. if isEmptyContainer(definition_changes_id):
  45. CuraStackBuilder.createDefinitionChangesContainer(global_stack,
  46. global_stack.getName() + "_settings")
  47. # Disable auto-slicing while the MachineAction is showing
  48. if self._backend: # This sometimes triggers before backend is loaded.
  49. self._backend.disableTimer()
  50. def _onFinished(self):
  51. # Restore auto-slicing when the machine action is dismissed
  52. if self._backend and self._backend.determineAutoSlicing():
  53. self._backend.enableTimer()
  54. self._backend.tickle()
  55. @pyqtSlot(int)
  56. def setMachineExtruderCount(self, extruder_count: int) -> None:
  57. # Note: this method was in this class before, but since it's quite generic and other plugins also need it
  58. # it was moved to the machine manager instead. Now this method just calls the machine manager.
  59. self._application.getMachineManager().setActiveMachineExtruderCount(extruder_count)
  60. @pyqtSlot()
  61. def forceUpdate(self) -> None:
  62. # Force rebuilding the build volume by reloading the global container stack.
  63. # This is a bit of a hack, but it seems quick enough.
  64. self._application.getMachineManager().globalContainerChanged.emit()
  65. @pyqtSlot()
  66. def updateHasMaterialsMetadata(self) -> None:
  67. global_stack = self._application.getMachineManager().activeMachine
  68. # Updates the has_materials metadata flag after switching gcode flavor
  69. if not global_stack:
  70. return
  71. definition = global_stack.getDefinition()
  72. if definition.getProperty("machine_gcode_flavor", "value") != "UltiGCode" or definition.getMetaDataEntry("has_materials", False):
  73. # In other words: only continue for the UM2 (extended), but not for the UM2+
  74. return
  75. machine_manager = self._application.getMachineManager()
  76. material_manager = self._application.getMaterialManager()
  77. extruder_positions = list(global_stack.extruders.keys())
  78. has_materials = global_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
  79. material_node = None
  80. if has_materials:
  81. global_stack.setMetaDataEntry("has_materials", True)
  82. else:
  83. # The metadata entry is stored in an ini, and ini files are parsed as strings only.
  84. # Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.
  85. if "has_materials" in global_stack.getMetaData():
  86. global_stack.removeMetaDataEntry("has_materials")
  87. # set materials
  88. for position in extruder_positions:
  89. if has_materials:
  90. material_node = material_manager.getDefaultMaterial(global_stack, position, None)
  91. machine_manager.setMaterial(position, material_node)
  92. self._application.globalContainerStackChanged.emit()
  93. @pyqtSlot(int)
  94. def updateMaterialForDiameter(self, extruder_position: int) -> None:
  95. # Updates the material container to a material that matches the material diameter set for the printer
  96. self._application.getMachineManager().updateMaterialWithVariant(str(extruder_position))