mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-14 17:15:56 +08:00
Merge branch 'master' of github.com:Ultimaker/Cura
This commit is contained in:
commit
0cc4f90920
4
.gitignore
vendored
4
.gitignore
vendored
@ -11,6 +11,10 @@ resources/firmware
|
|||||||
resources/materials
|
resources/materials
|
||||||
LC_MESSAGES
|
LC_MESSAGES
|
||||||
.cache
|
.cache
|
||||||
|
*.qmlc
|
||||||
|
|
||||||
|
#MacOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
# Editors and IDEs.
|
# Editors and IDEs.
|
||||||
*kdev*
|
*kdev*
|
||||||
|
@ -254,6 +254,10 @@ class CuraContainerStack(ContainerStack):
|
|||||||
def definition(self) -> DefinitionContainer:
|
def definition(self) -> DefinitionContainer:
|
||||||
return self._containers[_ContainerIndexes.Definition]
|
return self._containers[_ContainerIndexes.Definition]
|
||||||
|
|
||||||
|
@override(ContainerStack)
|
||||||
|
def getBottom(self) -> "DefinitionContainer":
|
||||||
|
return self.definition
|
||||||
|
|
||||||
## Check whether the specified setting has a 'user' value.
|
## Check whether the specified setting has a 'user' value.
|
||||||
#
|
#
|
||||||
# A user value here is defined as the setting having a value in either
|
# A user value here is defined as the setting having a value in either
|
||||||
|
@ -59,7 +59,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||||||
self.addRoleName(self.VariantRole, "variant")
|
self.addRoleName(self.VariantRole, "variant")
|
||||||
|
|
||||||
self._update_extruder_timer = QTimer()
|
self._update_extruder_timer = QTimer()
|
||||||
self._update_extruder_timer.setInterval(250)
|
self._update_extruder_timer.setInterval(100)
|
||||||
self._update_extruder_timer.setSingleShot(True)
|
self._update_extruder_timer.setSingleShot(True)
|
||||||
self._update_extruder_timer.timeout.connect(self.__updateExtruders)
|
self._update_extruder_timer.timeout.connect(self.__updateExtruders)
|
||||||
|
|
||||||
|
@ -11,14 +11,11 @@ from UM.Application import Application
|
|||||||
from UM.Preferences import Preferences
|
from UM.Preferences import Preferences
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.Decorators import deprecated
|
|
||||||
|
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
from UM.Settings.ContainerStack import ContainerStack
|
from UM.Settings.ContainerStack import ContainerStack
|
||||||
from UM.Settings.InstanceContainer import InstanceContainer
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
from UM.Settings.SettingDefinition import SettingDefinition
|
|
||||||
from UM.Settings.SettingFunction import SettingFunction
|
from UM.Settings.SettingFunction import SettingFunction
|
||||||
from UM.Settings.Validator import ValidatorState
|
|
||||||
from UM.Signal import postponeSignals
|
from UM.Signal import postponeSignals
|
||||||
import UM.FlameProfiler
|
import UM.FlameProfiler
|
||||||
|
|
||||||
@ -36,15 +33,17 @@ from typing import TYPE_CHECKING, Optional
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from UM.Settings.DefinitionContainer import DefinitionContainer
|
from UM.Settings.DefinitionContainer import DefinitionContainer
|
||||||
|
from cura.Settings.GlobalStack import GlobalStack
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
class MachineManager(QObject):
|
class MachineManager(QObject):
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self._active_container_stack = None # type: ContainerStack
|
self._active_container_stack = None # type: ContainerStack
|
||||||
self._global_container_stack = None # type: ContainerStack
|
self._global_container_stack = None # type: GlobalStack
|
||||||
|
|
||||||
self._error_check_timer = QTimer()
|
self._error_check_timer = QTimer()
|
||||||
self._error_check_timer.setInterval(250)
|
self._error_check_timer.setInterval(250)
|
||||||
@ -105,8 +104,6 @@ class MachineManager(QObject):
|
|||||||
self._material_incompatible_message = Message(catalog.i18nc("@info:status",
|
self._material_incompatible_message = Message(catalog.i18nc("@info:status",
|
||||||
"The selected material is incompatible with the selected machine or configuration."))
|
"The selected material is incompatible with the selected machine or configuration."))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value)
|
globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value)
|
||||||
activeMaterialChanged = pyqtSignal()
|
activeMaterialChanged = pyqtSignal()
|
||||||
activeVariantChanged = pyqtSignal()
|
activeVariantChanged = pyqtSignal()
|
||||||
@ -331,7 +328,7 @@ class MachineManager(QObject):
|
|||||||
def _onInstanceContainersChanged(self, container):
|
def _onInstanceContainersChanged(self, container):
|
||||||
self._instance_container_timer.start()
|
self._instance_container_timer.start()
|
||||||
|
|
||||||
def _onPropertyChanged(self, key, property_name):
|
def _onPropertyChanged(self, key: str, property_name: str):
|
||||||
if property_name == "value":
|
if property_name == "value":
|
||||||
# Notify UI items, such as the "changed" star in profile pull down menu.
|
# Notify UI items, such as the "changed" star in profile pull down menu.
|
||||||
self.activeStackValueChanged.emit()
|
self.activeStackValueChanged.emit()
|
||||||
@ -415,7 +412,7 @@ class MachineManager(QObject):
|
|||||||
## Delete a user setting from the global stack and all extruder stacks.
|
## Delete a user setting from the global stack and all extruder stacks.
|
||||||
# \param key \type{str} the name of the key to delete
|
# \param key \type{str} the name of the key to delete
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def clearUserSettingAllCurrentStacks(self, key):
|
def clearUserSettingAllCurrentStacks(self, key: str):
|
||||||
if not self._global_container_stack:
|
if not self._global_container_stack:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -571,7 +568,7 @@ class MachineManager(QObject):
|
|||||||
# \return The layer height of the currently active quality profile. If
|
# \return The layer height of the currently active quality profile. If
|
||||||
# there is no quality profile, this returns 0.
|
# there is no quality profile, this returns 0.
|
||||||
@pyqtProperty(float, notify=activeQualityChanged)
|
@pyqtProperty(float, notify=activeQualityChanged)
|
||||||
def activeQualityLayerHeight(self):
|
def activeQualityLayerHeight(self) -> float:
|
||||||
if not self._global_container_stack:
|
if not self._global_container_stack:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -588,7 +585,7 @@ class MachineManager(QObject):
|
|||||||
value = value(self._global_container_stack)
|
value = value(self._global_container_stack)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
return 0 #No quality profile.
|
return 0 # No quality profile.
|
||||||
|
|
||||||
## Get the Material ID associated with the currently active material
|
## Get the Material ID associated with the currently active material
|
||||||
# \returns MaterialID (string) if found, empty string otherwise
|
# \returns MaterialID (string) if found, empty string otherwise
|
||||||
@ -610,7 +607,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=activeQualityChanged)
|
@pyqtProperty(str, notify=activeQualityChanged)
|
||||||
def activeQualityName(self):
|
def activeQualityName(self) -> str:
|
||||||
if self._active_container_stack and self._global_container_stack:
|
if self._active_container_stack and self._global_container_stack:
|
||||||
quality = self._global_container_stack.qualityChanges
|
quality = self._global_container_stack.qualityChanges
|
||||||
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
||||||
@ -621,7 +618,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=activeQualityChanged)
|
@pyqtProperty(str, notify=activeQualityChanged)
|
||||||
def activeQualityId(self):
|
def activeQualityId(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
quality = self._active_container_stack.qualityChanges
|
quality = self._active_container_stack.qualityChanges
|
||||||
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
||||||
@ -632,7 +629,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=activeQualityChanged)
|
@pyqtProperty(str, notify=activeQualityChanged)
|
||||||
def globalQualityId(self):
|
def globalQualityId(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
quality = self._global_container_stack.qualityChanges
|
quality = self._global_container_stack.qualityChanges
|
||||||
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
|
||||||
@ -643,7 +640,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeQualityChanged)
|
@pyqtProperty(str, notify = activeQualityChanged)
|
||||||
def activeQualityType(self):
|
def activeQualityType(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
quality = self._active_container_stack.quality
|
quality = self._active_container_stack.quality
|
||||||
if quality:
|
if quality:
|
||||||
@ -651,7 +648,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = activeQualityChanged)
|
@pyqtProperty(bool, notify = activeQualityChanged)
|
||||||
def isActiveQualitySupported(self):
|
def isActiveQualitySupported(self) -> bool:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
quality = self._active_container_stack.quality
|
quality = self._active_container_stack.quality
|
||||||
if quality:
|
if quality:
|
||||||
@ -665,7 +662,7 @@ class MachineManager(QObject):
|
|||||||
# \todo Ideally, this method would be named activeQualityId(), and the other one
|
# \todo Ideally, this method would be named activeQualityId(), and the other one
|
||||||
# would be named something like activeQualityOrQualityChanges() for consistency
|
# would be named something like activeQualityOrQualityChanges() for consistency
|
||||||
@pyqtProperty(str, notify = activeQualityChanged)
|
@pyqtProperty(str, notify = activeQualityChanged)
|
||||||
def activeQualityContainerId(self):
|
def activeQualityContainerId(self) -> str:
|
||||||
# We're using the active stack instead of the global stack in case the list of qualities differs per extruder
|
# We're using the active stack instead of the global stack in case the list of qualities differs per extruder
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
quality = self._active_container_stack.quality
|
quality = self._active_container_stack.quality
|
||||||
@ -674,7 +671,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeQualityChanged)
|
@pyqtProperty(str, notify = activeQualityChanged)
|
||||||
def activeQualityChangesId(self):
|
def activeQualityChangesId(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
changes = self._active_container_stack.qualityChanges
|
changes = self._active_container_stack.qualityChanges
|
||||||
if changes and changes.getId() != "empty":
|
if changes and changes.getId() != "empty":
|
||||||
@ -691,7 +688,7 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
## Copy the value of the setting of the current extruder to all other extruders as well as the global container.
|
## Copy the value of the setting of the current extruder to all other extruders as well as the global container.
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def copyValueToExtruders(self, key):
|
def copyValueToExtruders(self, key: str):
|
||||||
if not self._active_container_stack or self._global_container_stack.getProperty("machine_extruder_count", "value") <= 1:
|
if not self._active_container_stack or self._global_container_stack.getProperty("machine_extruder_count", "value") <= 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -705,7 +702,7 @@ class MachineManager(QObject):
|
|||||||
## Set the active material by switching out a container
|
## Set the active material by switching out a container
|
||||||
# Depending on from/to material+current variant, a quality profile is chosen and set.
|
# Depending on from/to material+current variant, a quality profile is chosen and set.
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def setActiveMaterial(self, material_id):
|
def setActiveMaterial(self, material_id: str):
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
|
containers = ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
|
||||||
if not containers or not self._active_container_stack:
|
if not containers or not self._active_container_stack:
|
||||||
@ -721,7 +718,7 @@ class MachineManager(QObject):
|
|||||||
Logger.log("w", "While trying to set the active material, no material was found to replace it.")
|
Logger.log("w", "While trying to set the active material, no material was found to replace it.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if old_quality_changes and old_quality_changes.getId() == "empty_quality_changes":
|
if old_quality_changes and isinstance(old_quality_changes, type(self._empty_quality_changes_container)):
|
||||||
old_quality_changes = None
|
old_quality_changes = None
|
||||||
|
|
||||||
self.blurSettings.emit()
|
self.blurSettings.emit()
|
||||||
@ -754,7 +751,7 @@ class MachineManager(QObject):
|
|||||||
candidate_quality = quality_manager.findQualityByQualityType(quality_type,
|
candidate_quality = quality_manager.findQualityByQualityType(quality_type,
|
||||||
quality_manager.getWholeMachineDefinition(machine_definition),
|
quality_manager.getWholeMachineDefinition(machine_definition),
|
||||||
[material_container])
|
[material_container])
|
||||||
if not candidate_quality or candidate_quality.getId() == "empty_quality":
|
if not candidate_quality or isinstance(candidate_quality, type(self._empty_quality_changes_container)):
|
||||||
# Fall back to a quality (which must be compatible with all other extruders)
|
# Fall back to a quality (which must be compatible with all other extruders)
|
||||||
new_qualities = quality_manager.findAllUsableQualitiesForMachineAndExtruders(
|
new_qualities = quality_manager.findAllUsableQualitiesForMachineAndExtruders(
|
||||||
self._global_container_stack, ExtruderManager.getInstance().getExtruderStacks())
|
self._global_container_stack, ExtruderManager.getInstance().getExtruderStacks())
|
||||||
@ -770,7 +767,7 @@ class MachineManager(QObject):
|
|||||||
self.setActiveQuality(new_quality_id)
|
self.setActiveQuality(new_quality_id)
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def setActiveVariant(self, variant_id):
|
def setActiveVariant(self, variant_id: str):
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_id)
|
containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_id)
|
||||||
if not containers or not self._active_container_stack:
|
if not containers or not self._active_container_stack:
|
||||||
@ -793,7 +790,7 @@ class MachineManager(QObject):
|
|||||||
## set the active quality
|
## set the active quality
|
||||||
# \param quality_id The quality_id of either a quality or a quality_changes
|
# \param quality_id The quality_id of either a quality or a quality_changes
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def setActiveQuality(self, quality_id):
|
def setActiveQuality(self, quality_id: str):
|
||||||
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
with postponeSignals(*self._getContainerChangedSignals(), compress = True):
|
||||||
self.blurSettings.emit()
|
self.blurSettings.emit()
|
||||||
|
|
||||||
@ -852,7 +849,7 @@ class MachineManager(QObject):
|
|||||||
# \param quality_name \type{str} the name of the quality.
|
# \param quality_name \type{str} the name of the quality.
|
||||||
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
|
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
|
||||||
@UM.FlameProfiler.profile
|
@UM.FlameProfiler.profile
|
||||||
def determineQualityAndQualityChangesForQualityType(self, quality_type):
|
def determineQualityAndQualityChangesForQualityType(self, quality_type: str):
|
||||||
quality_manager = QualityManager.getInstance()
|
quality_manager = QualityManager.getInstance()
|
||||||
result = []
|
result = []
|
||||||
empty_quality_changes = self._empty_quality_changes_container
|
empty_quality_changes = self._empty_quality_changes_container
|
||||||
@ -889,7 +886,7 @@ class MachineManager(QObject):
|
|||||||
#
|
#
|
||||||
# \param quality_changes_name \type{str} the name of the quality changes.
|
# \param quality_changes_name \type{str} the name of the quality changes.
|
||||||
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
|
# \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
|
||||||
def _determineQualityAndQualityChangesForQualityChanges(self, quality_changes_name):
|
def _determineQualityAndQualityChangesForQualityChanges(self, quality_changes_name: str):
|
||||||
result = []
|
result = []
|
||||||
quality_manager = QualityManager.getInstance()
|
quality_manager = QualityManager.getInstance()
|
||||||
|
|
||||||
@ -964,7 +961,7 @@ class MachineManager(QObject):
|
|||||||
Application.getInstance().discardOrKeepProfileChanges()
|
Application.getInstance().discardOrKeepProfileChanges()
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeVariantChanged)
|
@pyqtProperty(str, notify = activeVariantChanged)
|
||||||
def activeVariantName(self):
|
def activeVariantName(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
variant = self._active_container_stack.variant
|
variant = self._active_container_stack.variant
|
||||||
if variant:
|
if variant:
|
||||||
@ -973,7 +970,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = activeVariantChanged)
|
@pyqtProperty(str, notify = activeVariantChanged)
|
||||||
def activeVariantId(self):
|
def activeVariantId(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
variant = self._active_container_stack.variant
|
variant = self._active_container_stack.variant
|
||||||
if variant:
|
if variant:
|
||||||
@ -982,7 +979,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify = globalContainerChanged)
|
@pyqtProperty(str, notify = globalContainerChanged)
|
||||||
def activeDefinitionId(self):
|
def activeDefinitionId(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
definition = self._global_container_stack.getBottom()
|
definition = self._global_container_stack.getBottom()
|
||||||
if definition:
|
if definition:
|
||||||
@ -991,7 +988,7 @@ class MachineManager(QObject):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
@pyqtProperty(str, notify=globalContainerChanged)
|
@pyqtProperty(str, notify=globalContainerChanged)
|
||||||
def activeDefinitionName(self):
|
def activeDefinitionName(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
definition = self._global_container_stack.getBottom()
|
definition = self._global_container_stack.getBottom()
|
||||||
if definition:
|
if definition:
|
||||||
@ -1003,7 +1000,7 @@ class MachineManager(QObject):
|
|||||||
# \returns DefinitionID (string) if found, empty string otherwise
|
# \returns DefinitionID (string) if found, empty string otherwise
|
||||||
# \sa getQualityDefinitionId
|
# \sa getQualityDefinitionId
|
||||||
@pyqtProperty(str, notify = globalContainerChanged)
|
@pyqtProperty(str, notify = globalContainerChanged)
|
||||||
def activeQualityDefinitionId(self):
|
def activeQualityDefinitionId(self) -> str:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return self.getQualityDefinitionId(self._global_container_stack.getBottom())
|
return self.getQualityDefinitionId(self._global_container_stack.getBottom())
|
||||||
return ""
|
return ""
|
||||||
@ -1012,14 +1009,14 @@ class MachineManager(QObject):
|
|||||||
# This is normally the id of the definition itself, but machines can specify a different definition to inherit qualities from
|
# This is normally the id of the definition itself, but machines can specify a different definition to inherit qualities from
|
||||||
# \param definition (DefinitionContainer) machine definition
|
# \param definition (DefinitionContainer) machine definition
|
||||||
# \returns DefinitionID (string) if found, empty string otherwise
|
# \returns DefinitionID (string) if found, empty string otherwise
|
||||||
def getQualityDefinitionId(self, definition):
|
def getQualityDefinitionId(self, definition: "DefinitionContainer") -> str:
|
||||||
return QualityManager.getInstance().getParentMachineDefinition(definition).getId()
|
return QualityManager.getInstance().getParentMachineDefinition(definition).getId()
|
||||||
|
|
||||||
## Get the Variant ID to use to select quality profiles for the currently active variant
|
## Get the Variant ID to use to select quality profiles for the currently active variant
|
||||||
# \returns VariantID (string) if found, empty string otherwise
|
# \returns VariantID (string) if found, empty string otherwise
|
||||||
# \sa getQualityVariantId
|
# \sa getQualityVariantId
|
||||||
@pyqtProperty(str, notify = activeVariantChanged)
|
@pyqtProperty(str, notify = activeVariantChanged)
|
||||||
def activeQualityVariantId(self):
|
def activeQualityVariantId(self) -> str:
|
||||||
if self._active_container_stack:
|
if self._active_container_stack:
|
||||||
variant = self._active_container_stack.variant
|
variant = self._active_container_stack.variant
|
||||||
if variant:
|
if variant:
|
||||||
@ -1030,9 +1027,9 @@ class MachineManager(QObject):
|
|||||||
# This is normally the id of the variant itself, but machines can specify a different definition
|
# This is normally the id of the variant itself, but machines can specify a different definition
|
||||||
# to inherit qualities from, which has consequences for the variant to use as well
|
# to inherit qualities from, which has consequences for the variant to use as well
|
||||||
# \param definition (DefinitionContainer) machine definition
|
# \param definition (DefinitionContainer) machine definition
|
||||||
# \param variant (DefinitionContainer) variant definition
|
# \param variant (InstanceContainer) variant definition
|
||||||
# \returns VariantID (string) if found, empty string otherwise
|
# \returns VariantID (string) if found, empty string otherwise
|
||||||
def getQualityVariantId(self, definition, variant):
|
def getQualityVariantId(self, definition: "DefinitionContainer", variant: "InstanceContainer") -> str:
|
||||||
variant_id = variant.getId()
|
variant_id = variant.getId()
|
||||||
definition_id = definition.getId()
|
definition_id = definition.getId()
|
||||||
quality_definition_id = self.getQualityDefinitionId(definition)
|
quality_definition_id = self.getQualityDefinitionId(definition)
|
||||||
@ -1044,7 +1041,7 @@ class MachineManager(QObject):
|
|||||||
## Gets how the active definition calls variants
|
## Gets how the active definition calls variants
|
||||||
# Caveat: per-definition-variant-title is currently not translated (though the fallback is)
|
# Caveat: per-definition-variant-title is currently not translated (though the fallback is)
|
||||||
@pyqtProperty(str, notify = globalContainerChanged)
|
@pyqtProperty(str, notify = globalContainerChanged)
|
||||||
def activeDefinitionVariantsName(self):
|
def activeDefinitionVariantsName(self) -> str:
|
||||||
fallback_title = catalog.i18nc("@label", "Nozzle")
|
fallback_title = catalog.i18nc("@label", "Nozzle")
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return self._global_container_stack.getBottom().getMetaDataEntry("variants_name", fallback_title)
|
return self._global_container_stack.getBottom().getMetaDataEntry("variants_name", fallback_title)
|
||||||
@ -1052,7 +1049,7 @@ class MachineManager(QObject):
|
|||||||
return fallback_title
|
return fallback_title
|
||||||
|
|
||||||
@pyqtSlot(str, str)
|
@pyqtSlot(str, str)
|
||||||
def renameMachine(self, machine_id, new_name):
|
def renameMachine(self, machine_id: str, new_name: str):
|
||||||
containers = ContainerRegistry.getInstance().findContainerStacks(id = machine_id)
|
containers = ContainerRegistry.getInstance().findContainerStacks(id = machine_id)
|
||||||
if containers:
|
if containers:
|
||||||
new_name = self._createUniqueName("machine", containers[0].getName(), new_name, containers[0].getBottom().getName())
|
new_name = self._createUniqueName("machine", containers[0].getName(), new_name, containers[0].getBottom().getName())
|
||||||
@ -1060,7 +1057,7 @@ class MachineManager(QObject):
|
|||||||
self.globalContainerChanged.emit()
|
self.globalContainerChanged.emit()
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def removeMachine(self, machine_id):
|
def removeMachine(self, machine_id: str):
|
||||||
# If the machine that is being removed is the currently active machine, set another machine as the active machine.
|
# If the machine that is being removed is the currently active machine, set another machine as the active machine.
|
||||||
activate_new_machine = (self._global_container_stack and self._global_container_stack.getId() == machine_id)
|
activate_new_machine = (self._global_container_stack and self._global_container_stack.getId() == machine_id)
|
||||||
|
|
||||||
@ -1078,14 +1075,14 @@ class MachineManager(QObject):
|
|||||||
|
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
def hasMaterials(self):
|
def hasMaterials(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return bool(self._global_container_stack.getMetaDataEntry("has_materials", False))
|
return bool(self._global_container_stack.getMetaDataEntry("has_materials", False))
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
def hasVariants(self):
|
def hasVariants(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return bool(self._global_container_stack.getMetaDataEntry("has_variants", False))
|
return bool(self._global_container_stack.getMetaDataEntry("has_variants", False))
|
||||||
|
|
||||||
@ -1094,7 +1091,7 @@ class MachineManager(QObject):
|
|||||||
## Property to indicate if a machine has "specialized" material profiles.
|
## Property to indicate if a machine has "specialized" material profiles.
|
||||||
# Some machines have their own material profiles that "override" the default catch all profiles.
|
# Some machines have their own material profiles that "override" the default catch all profiles.
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
def filterMaterialsByMachine(self):
|
def filterMaterialsByMachine(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return bool(self._global_container_stack.getMetaDataEntry("has_machine_materials", False))
|
return bool(self._global_container_stack.getMetaDataEntry("has_machine_materials", False))
|
||||||
|
|
||||||
@ -1103,7 +1100,7 @@ class MachineManager(QObject):
|
|||||||
## Property to indicate if a machine has "specialized" quality profiles.
|
## Property to indicate if a machine has "specialized" quality profiles.
|
||||||
# Some machines have their own quality profiles that "override" the default catch all profiles.
|
# Some machines have their own quality profiles that "override" the default catch all profiles.
|
||||||
@pyqtProperty(bool, notify = globalContainerChanged)
|
@pyqtProperty(bool, notify = globalContainerChanged)
|
||||||
def filterQualityByMachine(self):
|
def filterQualityByMachine(self) -> bool:
|
||||||
if self._global_container_stack:
|
if self._global_container_stack:
|
||||||
return bool(self._global_container_stack.getMetaDataEntry("has_machine_quality", False))
|
return bool(self._global_container_stack.getMetaDataEntry("has_machine_quality", False))
|
||||||
return False
|
return False
|
||||||
@ -1112,7 +1109,7 @@ class MachineManager(QObject):
|
|||||||
# \param machine_id string machine id to get the definition ID of
|
# \param machine_id string machine id to get the definition ID of
|
||||||
# \returns DefinitionID (string) if found, None otherwise
|
# \returns DefinitionID (string) if found, None otherwise
|
||||||
@pyqtSlot(str, result = str)
|
@pyqtSlot(str, result = str)
|
||||||
def getDefinitionByMachineId(self, machine_id):
|
def getDefinitionByMachineId(self, machine_id: str) -> str:
|
||||||
containers = ContainerRegistry.getInstance().findContainerStacks(id=machine_id)
|
containers = ContainerRegistry.getInstance().findContainerStacks(id=machine_id)
|
||||||
if containers:
|
if containers:
|
||||||
return containers[0].getBottom().getId()
|
return containers[0].getBottom().getId()
|
||||||
@ -1121,22 +1118,6 @@ class MachineManager(QObject):
|
|||||||
def createMachineManager(engine=None, script_engine=None):
|
def createMachineManager(engine=None, script_engine=None):
|
||||||
return MachineManager()
|
return MachineManager()
|
||||||
|
|
||||||
def _updateVariantContainer(self, definition: "DefinitionContainer"):
|
|
||||||
if not definition.getMetaDataEntry("has_variants"):
|
|
||||||
return self._empty_variant_container
|
|
||||||
machine_definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(definition)
|
|
||||||
containers = []
|
|
||||||
preferred_variant = definition.getMetaDataEntry("preferred_variant")
|
|
||||||
if preferred_variant:
|
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = machine_definition_id, id = preferred_variant)
|
|
||||||
if not containers:
|
|
||||||
containers = ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = machine_definition_id)
|
|
||||||
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
return self._empty_variant_container
|
|
||||||
|
|
||||||
def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None):
|
def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None):
|
||||||
if not definition.getMetaDataEntry("has_materials"):
|
if not definition.getMetaDataEntry("has_materials"):
|
||||||
return self._empty_material_container
|
return self._empty_material_container
|
||||||
@ -1174,110 +1155,6 @@ class MachineManager(QObject):
|
|||||||
Logger.log("w", "Unable to find a material container with provided criteria, returning an empty one instead.")
|
Logger.log("w", "Unable to find a material container with provided criteria, returning an empty one instead.")
|
||||||
return self._empty_material_container
|
return self._empty_material_container
|
||||||
|
|
||||||
def _updateQualityContainer(self, definition: "DefinitionContainer", variant_container: "ContainerStack", material_container = None, preferred_quality_name: Optional[str] = None):
|
|
||||||
container_registry = ContainerRegistry.getInstance()
|
|
||||||
search_criteria = { "type": "quality" }
|
|
||||||
|
|
||||||
if definition.getMetaDataEntry("has_machine_quality"):
|
|
||||||
search_criteria["definition"] = self.getQualityDefinitionId(definition)
|
|
||||||
|
|
||||||
if definition.getMetaDataEntry("has_materials") and material_container:
|
|
||||||
search_criteria["material"] = material_container.id
|
|
||||||
else:
|
|
||||||
search_criteria["definition"] = "fdmprinter"
|
|
||||||
|
|
||||||
if preferred_quality_name and preferred_quality_name != "empty":
|
|
||||||
search_criteria["name"] = preferred_quality_name
|
|
||||||
else:
|
|
||||||
preferred_quality = definition.getMetaDataEntry("preferred_quality")
|
|
||||||
if preferred_quality:
|
|
||||||
search_criteria["id"] = preferred_quality
|
|
||||||
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
if "material" in search_criteria:
|
|
||||||
# First check if we can solve our material not found problem by checking if we can find quality containers
|
|
||||||
# that are assigned to the parents of this material profile.
|
|
||||||
try:
|
|
||||||
inherited_files = material_container.getInheritedFiles()
|
|
||||||
except AttributeError: # Material_container does not support inheritance.
|
|
||||||
inherited_files = []
|
|
||||||
|
|
||||||
if inherited_files:
|
|
||||||
for inherited_file in inherited_files:
|
|
||||||
# Extract the ID from the path we used to load the file.
|
|
||||||
search_criteria["material"] = os.path.basename(inherited_file).split(".")[0]
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
# We still weren't able to find a quality for this specific material.
|
|
||||||
# Try to find qualities for a generic version of the material.
|
|
||||||
material_search_criteria = { "type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic"}
|
|
||||||
if definition.getMetaDataEntry("has_machine_quality"):
|
|
||||||
if material_container:
|
|
||||||
material_search_criteria["definition"] = material_container.getDefinition().id
|
|
||||||
|
|
||||||
if definition.getMetaDataEntry("has_variants"):
|
|
||||||
material_search_criteria["variant"] = material_container.getMetaDataEntry("variant")
|
|
||||||
else:
|
|
||||||
material_search_criteria["definition"] = self.getQualityDefinitionId(definition)
|
|
||||||
|
|
||||||
if definition.getMetaDataEntry("has_variants") and variant_container:
|
|
||||||
material_search_criteria["variant"] = self.getQualityVariantId(definition, variant_container)
|
|
||||||
else:
|
|
||||||
material_search_criteria["definition"] = "fdmprinter"
|
|
||||||
material_containers = container_registry.findInstanceContainers(**material_search_criteria)
|
|
||||||
# Try all materials to see if there is a quality profile available.
|
|
||||||
for material_container in material_containers:
|
|
||||||
search_criteria["material"] = material_container.getId()
|
|
||||||
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
if "name" in search_criteria or "id" in search_criteria:
|
|
||||||
# If a quality by this name can not be found, try a wider set of search criteria
|
|
||||||
search_criteria.pop("name", None)
|
|
||||||
search_criteria.pop("id", None)
|
|
||||||
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
# Notify user that we were unable to find a matching quality
|
|
||||||
message = Message(catalog.i18nc("@info:status", "Unable to find a quality profile for this combination. Default settings will be used instead."))
|
|
||||||
message.show()
|
|
||||||
return self._empty_quality_container
|
|
||||||
|
|
||||||
## Finds a quality-changes container to use if any other container
|
|
||||||
# changes.
|
|
||||||
#
|
|
||||||
# \param quality_type The quality type to find a quality-changes for.
|
|
||||||
# \param preferred_quality_changes_name The name of the quality-changes to
|
|
||||||
# pick, if any such quality-changes profile is available.
|
|
||||||
def _updateQualityChangesContainer(self, quality_type, preferred_quality_changes_name = None):
|
|
||||||
container_registry = ContainerRegistry.getInstance() # Cache.
|
|
||||||
search_criteria = { "type": "quality_changes" }
|
|
||||||
|
|
||||||
search_criteria["quality"] = quality_type
|
|
||||||
if preferred_quality_changes_name:
|
|
||||||
search_criteria["name"] = preferred_quality_changes_name
|
|
||||||
|
|
||||||
# Try to search with the name in the criteria first, since we prefer to have the correct name.
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers: # Found one!
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
if "name" in search_criteria:
|
|
||||||
del search_criteria["name"] # Not found, then drop the name requirement (if we had one) and search again.
|
|
||||||
containers = container_registry.findInstanceContainers(**search_criteria)
|
|
||||||
if containers:
|
|
||||||
return containers[0]
|
|
||||||
|
|
||||||
return self._empty_quality_changes_container # Didn't find anything with the required quality_type.
|
|
||||||
|
|
||||||
def _onMachineNameChanged(self):
|
def _onMachineNameChanged(self):
|
||||||
self.globalContainerChanged.emit()
|
self.globalContainerChanged.emit()
|
||||||
|
|
||||||
|
@ -109,7 +109,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
machine_type = ""
|
machine_type = ""
|
||||||
variant_type_name = i18n_catalog.i18nc("@label", "Nozzle")
|
variant_type_name = i18n_catalog.i18nc("@label", "Nozzle")
|
||||||
|
|
||||||
num_extruders = 0
|
|
||||||
# Check if there are any conflicts, so we can ask the user.
|
# Check if there are any conflicts, so we can ask the user.
|
||||||
archive = zipfile.ZipFile(file_name, "r")
|
archive = zipfile.ZipFile(file_name, "r")
|
||||||
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
||||||
@ -121,31 +120,41 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
instance_container_list = []
|
instance_container_list = []
|
||||||
material_container_list = []
|
material_container_list = []
|
||||||
|
|
||||||
|
#
|
||||||
|
# Read definition containers
|
||||||
|
#
|
||||||
|
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)]
|
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
|
||||||
for definition_container_file in definition_container_files:
|
for each_definition_container_file in definition_container_files:
|
||||||
container_id = self._stripFileToId(definition_container_file)
|
container_id = self._stripFileToId(each_definition_container_file)
|
||||||
definitions = self._container_registry.findDefinitionContainers(id=container_id)
|
definitions = self._container_registry.findDefinitionContainers(id=container_id)
|
||||||
|
|
||||||
if not definitions:
|
if not definitions:
|
||||||
definition_container = DefinitionContainer(container_id)
|
definition_container = DefinitionContainer(container_id)
|
||||||
definition_container.deserialize(archive.open(definition_container_file).read().decode("utf-8"))
|
definition_container.deserialize(archive.open(each_definition_container_file).read().decode("utf-8"))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
definition_container = definitions[0]
|
definition_container = definitions[0]
|
||||||
|
|
||||||
definition_container_list.append(definition_container)
|
definition_container_list.append(definition_container)
|
||||||
|
|
||||||
if definition_container.getMetaDataEntry("type") != "extruder":
|
definition_container_type = definition_container.getMetaDataEntry("type")
|
||||||
|
if definition_container_type == "machine":
|
||||||
machine_type = definition_container.getName()
|
machine_type = definition_container.getName()
|
||||||
variant_type_name = definition_container.getMetaDataEntry("variants_name", variant_type_name)
|
variant_type_name = definition_container.getMetaDataEntry("variants_name", variant_type_name)
|
||||||
|
|
||||||
|
machine_definition_container_count += 1
|
||||||
|
elif definition_container_type == "extruder":
|
||||||
|
extruder_definition_container_count += 1
|
||||||
else:
|
else:
|
||||||
num_extruders += 1
|
Logger.log("w", "Unknown definition container type %s for %s",
|
||||||
|
definition_container_type, each_definition_container_file)
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
# sanity check
|
||||||
if num_extruders == 0:
|
if machine_definition_container_count != 1:
|
||||||
num_extruders = 1 # No extruder stacks found, which means there is one extruder
|
msg = "Expecting one machine definition container but got %s" % machine_definition_container_count
|
||||||
|
Logger.log("e", msg)
|
||||||
extruders = num_extruders * [""]
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
material_labels = []
|
material_labels = []
|
||||||
material_conflict = False
|
material_conflict = False
|
||||||
@ -161,19 +170,22 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
if materials and not materials[0].isReadOnly(): # Only non readonly materials can be in conflict
|
if materials and not materials[0].isReadOnly(): # Only non readonly materials can be in conflict
|
||||||
material_conflict = True
|
material_conflict = True
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
|
||||||
# Check if any quality_changes instance container is in conflict.
|
# Check if any quality_changes instance container is in conflict.
|
||||||
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
|
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
|
||||||
quality_name = ""
|
quality_name = ""
|
||||||
quality_type = ""
|
quality_type = ""
|
||||||
num_settings_overriden_by_quality_changes = 0 # How many settings are changed by the quality changes
|
num_settings_overriden_by_quality_changes = 0 # How many settings are changed by the quality changes
|
||||||
|
num_settings_overriden_by_definition_changes = 0 # How many settings are changed by the definition changes
|
||||||
num_user_settings = 0
|
num_user_settings = 0
|
||||||
for instance_container_file in instance_container_files:
|
quality_changes_conflict = False
|
||||||
container_id = self._stripFileToId(instance_container_file)
|
definition_changes_conflict = False
|
||||||
|
for each_instance_container_file in instance_container_files:
|
||||||
|
container_id = self._stripFileToId(each_instance_container_file)
|
||||||
instance_container = InstanceContainer(container_id)
|
instance_container = InstanceContainer(container_id)
|
||||||
|
|
||||||
# Deserialize InstanceContainer by converting read data from bytes to string
|
# Deserialize InstanceContainer by converting read data from bytes to string
|
||||||
instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
instance_container.deserialize(archive.open(each_instance_container_file).read().decode("utf-8"))
|
||||||
|
|
||||||
instance_container_list.append(instance_container)
|
instance_container_list.append(instance_container)
|
||||||
|
|
||||||
container_type = instance_container.getMetaDataEntry("type")
|
container_type = instance_container.getMetaDataEntry("type")
|
||||||
@ -186,6 +198,13 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
# Check if there really is a conflict by comparing the values
|
# Check if there really is a conflict by comparing the values
|
||||||
if quality_changes[0] != instance_container:
|
if quality_changes[0] != instance_container:
|
||||||
quality_changes_conflict = True
|
quality_changes_conflict = True
|
||||||
|
elif container_type == "definition_changes":
|
||||||
|
definition_name = instance_container.getName()
|
||||||
|
num_settings_overriden_by_definition_changes += len(instance_container._instances)
|
||||||
|
definition_changes = self._container_registry.findDefinitionContainers(id = container_id)
|
||||||
|
if definition_changes:
|
||||||
|
if definition_changes[0] != instance_container:
|
||||||
|
definition_changes_conflict = True
|
||||||
elif container_type == "quality":
|
elif container_type == "quality":
|
||||||
# If the quality name is not set (either by quality or changes, set it now)
|
# If the quality name is not set (either by quality or changes, set it now)
|
||||||
# Quality changes should always override this (as they are "on top")
|
# Quality changes should always override this (as they are "on top")
|
||||||
@ -202,7 +221,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
file_name, cura_file_names)
|
file_name, cura_file_names)
|
||||||
self._resolve_strategies = {"machine": None, "quality_changes": None, "material": None}
|
self._resolve_strategies = {"machine": None, "quality_changes": None, "material": None}
|
||||||
machine_conflict = False
|
machine_conflict = False
|
||||||
quality_changes_conflict = False
|
|
||||||
for container_stack_file in [global_stack_file] + extruder_stack_files:
|
for container_stack_file in [global_stack_file] + extruder_stack_files:
|
||||||
container_id = self._stripFileToId(container_stack_file)
|
container_id = self._stripFileToId(container_stack_file)
|
||||||
serialized = archive.open(container_stack_file).read().decode("utf-8")
|
serialized = archive.open(container_stack_file).read().decode("utf-8")
|
||||||
@ -237,9 +255,17 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
if not show_dialog:
|
if not show_dialog:
|
||||||
return WorkspaceReader.PreReadResult.accepted
|
return WorkspaceReader.PreReadResult.accepted
|
||||||
|
|
||||||
|
# prepare data for the dialog
|
||||||
|
num_extruders = extruder_definition_container_count
|
||||||
|
if num_extruders == 0:
|
||||||
|
num_extruders = 1 # No extruder stacks found, which means there is one extruder
|
||||||
|
|
||||||
|
extruders = num_extruders * [""]
|
||||||
|
|
||||||
# Show the dialog, informing the user what is about to happen.
|
# Show the dialog, informing the user what is about to happen.
|
||||||
self._dialog.setMachineConflict(machine_conflict)
|
self._dialog.setMachineConflict(machine_conflict)
|
||||||
self._dialog.setQualityChangesConflict(quality_changes_conflict)
|
self._dialog.setQualityChangesConflict(quality_changes_conflict)
|
||||||
|
self._dialog.setDefinitionChangesConflict(definition_changes_conflict)
|
||||||
self._dialog.setMaterialConflict(material_conflict)
|
self._dialog.setMaterialConflict(material_conflict)
|
||||||
self._dialog.setNumVisibleSettings(num_visible_settings)
|
self._dialog.setNumVisibleSettings(num_visible_settings)
|
||||||
self._dialog.setQualityName(quality_name)
|
self._dialog.setQualityName(quality_name)
|
||||||
@ -262,6 +288,14 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
return WorkspaceReader.PreReadResult.cancelled
|
return WorkspaceReader.PreReadResult.cancelled
|
||||||
|
|
||||||
self._resolve_strategies = self._dialog.getResult()
|
self._resolve_strategies = self._dialog.getResult()
|
||||||
|
#
|
||||||
|
# There can be 3 resolve strategies coming from the dialog:
|
||||||
|
# - new: create a new container
|
||||||
|
# - override: override the existing container
|
||||||
|
# - None: There is no conflict, which means containers with the same IDs may or may not be there already.
|
||||||
|
# If they are there, there is no conflict between the them.
|
||||||
|
# In this case, you can either create a new one, or safely override the existing one.
|
||||||
|
#
|
||||||
# Default values
|
# Default values
|
||||||
for k, v in self._resolve_strategies.items():
|
for k, v in self._resolve_strategies.items():
|
||||||
if v is None:
|
if v is None:
|
||||||
@ -316,6 +350,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
extruder_stacks_added = []
|
extruder_stacks_added = []
|
||||||
container_stacks_added = []
|
container_stacks_added = []
|
||||||
|
|
||||||
|
containers_added = []
|
||||||
|
|
||||||
global_stack_id_original = self._stripFileToId(global_stack_file)
|
global_stack_id_original = self._stripFileToId(global_stack_file)
|
||||||
global_stack_id_new = global_stack_id_original
|
global_stack_id_new = global_stack_id_original
|
||||||
global_stack_need_rename = False
|
global_stack_need_rename = False
|
||||||
@ -325,7 +361,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
global_stack_id_new = self.getNewId(global_stack_id_original)
|
global_stack_id_new = self.getNewId(global_stack_id_original)
|
||||||
global_stack_need_rename = True
|
global_stack_need_rename = True
|
||||||
|
|
||||||
|
|
||||||
# TODO: For the moment we use pretty naive existence checking. If the ID is the same, we assume in quite a few
|
# TODO: For the moment we use pretty naive existence checking. If the ID is the same, we assume in quite a few
|
||||||
# TODO: cases that the container loaded is the same (most notable in materials & definitions).
|
# TODO: cases that the container loaded is the same (most notable in materials & definitions).
|
||||||
# TODO: It might be possible that we need to add smarter checking in the future.
|
# TODO: It might be possible that we need to add smarter checking in the future.
|
||||||
@ -352,21 +387,24 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
for material_container_file in material_container_files:
|
for material_container_file in material_container_files:
|
||||||
container_id = self._stripFileToId(material_container_file)
|
container_id = self._stripFileToId(material_container_file)
|
||||||
materials = self._container_registry.findInstanceContainers(id = container_id)
|
materials = self._container_registry.findInstanceContainers(id = container_id)
|
||||||
|
|
||||||
if not materials:
|
if not materials:
|
||||||
material_container = xml_material_profile(container_id)
|
material_container = xml_material_profile(container_id)
|
||||||
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
||||||
containers_to_add.append(material_container)
|
containers_to_add.append(material_container)
|
||||||
else:
|
else:
|
||||||
if not materials[0].isReadOnly(): # Only create new materials if they are not read only.
|
material_container = materials[0]
|
||||||
|
if not material_container.isReadOnly(): # Only create new materials if they are not read only.
|
||||||
if self._resolve_strategies["material"] == "override":
|
if self._resolve_strategies["material"] == "override":
|
||||||
materials[0].deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
||||||
elif self._resolve_strategies["material"] == "new":
|
elif self._resolve_strategies["material"] == "new":
|
||||||
# Note that we *must* deserialize it with a new ID, as multiple containers will be
|
# Note that we *must* deserialize it with a new ID, as multiple containers will be
|
||||||
# auto created & added.
|
# auto created & added.
|
||||||
material_container = xml_material_profile(self.getNewId(container_id))
|
material_container = xml_material_profile(self.getNewId(container_id))
|
||||||
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"))
|
||||||
containers_to_add.append(material_container)
|
containers_to_add.append(material_container)
|
||||||
material_containers.append(material_container)
|
|
||||||
|
material_containers.append(material_container)
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
|
||||||
Logger.log("d", "Workspace loading is checking instance containers...")
|
Logger.log("d", "Workspace loading is checking instance containers...")
|
||||||
@ -388,24 +426,28 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
if not user_containers:
|
if not user_containers:
|
||||||
containers_to_add.append(instance_container)
|
containers_to_add.append(instance_container)
|
||||||
else:
|
else:
|
||||||
|
instance_container = user_containers[0]
|
||||||
if self._resolve_strategies["machine"] == "override" or self._resolve_strategies["machine"] is None:
|
if self._resolve_strategies["machine"] == "override" or self._resolve_strategies["machine"] is None:
|
||||||
user_containers[0].deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
||||||
|
instance_container.setDirty(True)
|
||||||
elif self._resolve_strategies["machine"] == "new":
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
# The machine is going to get a spiffy new name, so ensure that the id's of user settings match.
|
# The machine is going to get a spiffy new name, so ensure that the id's of user settings match.
|
||||||
extruder_id = instance_container.getMetaDataEntry("extruder", None)
|
extruder_id = instance_container.getMetaDataEntry("extruder", None)
|
||||||
if extruder_id:
|
if extruder_id:
|
||||||
new_id = self.getNewId(extruder_id) + "_current_settings"
|
new_extruder_id = self.getNewId(extruder_id)
|
||||||
|
new_id = new_extruder_id + "_current_settings"
|
||||||
instance_container._id = new_id
|
instance_container._id = new_id
|
||||||
instance_container.setName(new_id)
|
instance_container.setName(new_id)
|
||||||
instance_container.setMetaDataEntry("extruder", self.getNewId(extruder_id))
|
instance_container.setMetaDataEntry("extruder", new_extruder_id)
|
||||||
containers_to_add.append(instance_container)
|
containers_to_add.append(instance_container)
|
||||||
|
|
||||||
machine_id = instance_container.getMetaDataEntry("machine", None)
|
machine_id = instance_container.getMetaDataEntry("machine", None)
|
||||||
if machine_id:
|
if machine_id:
|
||||||
new_id = self.getNewId(machine_id) + "_current_settings"
|
new_machine_id = self.getNewId(machine_id)
|
||||||
|
new_id = new_machine_id + "_current_settings"
|
||||||
instance_container._id = new_id
|
instance_container._id = new_id
|
||||||
instance_container.setName(new_id)
|
instance_container.setName(new_id)
|
||||||
instance_container.setMetaDataEntry("machine", self.getNewId(machine_id))
|
instance_container.setMetaDataEntry("machine", new_machine_id)
|
||||||
containers_to_add.append(instance_container)
|
containers_to_add.append(instance_container)
|
||||||
user_instance_containers.append(instance_container)
|
user_instance_containers.append(instance_container)
|
||||||
elif container_type in ("quality_changes", "definition_changes"):
|
elif container_type in ("quality_changes", "definition_changes"):
|
||||||
@ -415,7 +457,32 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
containers_to_add.append(instance_container)
|
containers_to_add.append(instance_container)
|
||||||
else:
|
else:
|
||||||
if self._resolve_strategies[container_type] == "override":
|
if self._resolve_strategies[container_type] == "override":
|
||||||
changes_containers[0].deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
instance_container = changes_containers[0]
|
||||||
|
instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
||||||
|
instance_container.setDirty(True)
|
||||||
|
elif self._resolve_strategies[container_type] == "new":
|
||||||
|
# TODO: how should we handle the case "new" for quality_changes and definition_changes?
|
||||||
|
|
||||||
|
new_changes_container_id = self.getNewId(instance_container.getId())
|
||||||
|
instance_container._id = new_changes_container_id
|
||||||
|
instance_container.setName(new_changes_container_id)
|
||||||
|
|
||||||
|
# TODO: we don't know the following is correct or not, need to verify
|
||||||
|
# AND REFACTOR!!!
|
||||||
|
if self._resolve_strategies["machine"] == "new":
|
||||||
|
# The machine is going to get a spiffy new name, so ensure that the id's of user settings match.
|
||||||
|
extruder_id = instance_container.getMetaDataEntry("extruder", None)
|
||||||
|
if extruder_id:
|
||||||
|
new_extruder_id = self.getNewId(extruder_id)
|
||||||
|
instance_container.setMetaDataEntry("extruder", new_extruder_id)
|
||||||
|
|
||||||
|
machine_id = instance_container.getMetaDataEntry("machine", None)
|
||||||
|
if machine_id:
|
||||||
|
new_machine_id = self.getNewId(machine_id)
|
||||||
|
instance_container.setMetaDataEntry("machine", new_machine_id)
|
||||||
|
|
||||||
|
containers_to_add.append(instance_container)
|
||||||
|
|
||||||
elif self._resolve_strategies[container_type] is None:
|
elif self._resolve_strategies[container_type] is None:
|
||||||
# The ID already exists, but nothing in the values changed, so do nothing.
|
# The ID already exists, but nothing in the values changed, so do nothing.
|
||||||
pass
|
pass
|
||||||
@ -432,73 +499,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
for container in containers_to_add:
|
for container in containers_to_add:
|
||||||
self._container_registry.addContainer(container)
|
self._container_registry.addContainer(container)
|
||||||
container.setDirty(True)
|
container.setDirty(True)
|
||||||
|
containers_added.append(container)
|
||||||
|
|
||||||
# Get the stack(s) saved in the workspace.
|
# Get the stack(s) saved in the workspace.
|
||||||
Logger.log("d", "Workspace loading is checking stacks containers...")
|
Logger.log("d", "Workspace loading is checking stacks containers...")
|
||||||
|
|
||||||
# load extruder stack files
|
# --
|
||||||
try:
|
|
||||||
for index, extruder_stack_file in enumerate(extruder_stack_files):
|
|
||||||
container_id = self._stripFileToId(extruder_stack_file)
|
|
||||||
|
|
||||||
container_stacks = self._container_registry.findContainerStacks(id = container_id)
|
|
||||||
if container_stacks:
|
|
||||||
# this container stack already exists, try to resolve
|
|
||||||
stack = container_stacks[0]
|
|
||||||
if self._resolve_strategies["machine"] == "override":
|
|
||||||
pass # do nothing
|
|
||||||
elif self._resolve_strategies["machine"] == "new":
|
|
||||||
# create a new extruder stack from this one
|
|
||||||
new_id = self.getNewId(container_id)
|
|
||||||
stack = ExtruderStack(new_id)
|
|
||||||
stack.deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
|
||||||
|
|
||||||
# Ensure a unique ID and name
|
|
||||||
stack._id = new_id
|
|
||||||
|
|
||||||
self._container_registry.addContainer(stack)
|
|
||||||
extruder_stacks_added.append(stack)
|
|
||||||
else:
|
|
||||||
if self._resolve_strategies["machine"] == "override":
|
|
||||||
global_stacks = self._container_registry.findContainerStacks(id = global_stack_id_original)
|
|
||||||
# deserialize new extruder stack over the current ones
|
|
||||||
if global_stacks:
|
|
||||||
old_extruder_stack_id = global_stacks[0].extruders[index].getId()
|
|
||||||
# HACK delete file
|
|
||||||
self._container_registry._deleteFiles(global_stacks[0].extruders[index])
|
|
||||||
global_stacks[0].extruders[index].deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
|
||||||
# HACK
|
|
||||||
global_stacks[0]._extruders = global_stacks[0]._extruders[:2]
|
|
||||||
# HACK update cache
|
|
||||||
del self._container_registry._id_container_cache[old_extruder_stack_id]
|
|
||||||
new_extruder_stack_id = global_stacks[0].extruders[index].getId()
|
|
||||||
self._container_registry._id_container_cache[new_extruder_stack_id] = global_stacks[0].extruders[index]
|
|
||||||
|
|
||||||
stack = global_stacks[0].extruders[index]
|
|
||||||
else:
|
|
||||||
Logger.log("w", "Could not find global stack, while I expected it: %s" % global_stack_id_original)
|
|
||||||
elif self._resolve_strategies["machine"] == "new":
|
|
||||||
# container not found, create a new one
|
|
||||||
stack = ExtruderStack(container_id)
|
|
||||||
stack.deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
|
||||||
self._container_registry.addContainer(stack)
|
|
||||||
extruder_stacks_added.append(stack)
|
|
||||||
else:
|
|
||||||
Logger.log("w", "Unknown resolve strategy: %s" % str(self._resolve_strategies["machine"]))
|
|
||||||
|
|
||||||
if global_stack_need_rename:
|
|
||||||
if stack.getMetaDataEntry("machine"):
|
|
||||||
stack.setMetaDataEntry("machine", global_stack_id_new)
|
|
||||||
extruder_stacks.append(stack)
|
|
||||||
|
|
||||||
except:
|
|
||||||
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
|
||||||
# Something went really wrong. Try to remove any data that we added.
|
|
||||||
for container in extruder_stacks:
|
|
||||||
self._container_registry.removeContainer(container.getId())
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
# load global stack file
|
# load global stack file
|
||||||
try:
|
try:
|
||||||
# Check if a stack by this ID already exists;
|
# Check if a stack by this ID already exists;
|
||||||
@ -541,82 +547,185 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||||||
stack.deserialize(archive.open(global_stack_file).read().decode("utf-8"))
|
stack.deserialize(archive.open(global_stack_file).read().decode("utf-8"))
|
||||||
container_stacks_added.append(stack)
|
container_stacks_added.append(stack)
|
||||||
self._container_registry.addContainer(stack)
|
self._container_registry.addContainer(stack)
|
||||||
|
containers_added.append(stack)
|
||||||
|
|
||||||
global_stack = stack
|
global_stack = stack
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
except:
|
||||||
|
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
||||||
|
# Something went really wrong. Try to remove any data that we added.
|
||||||
|
for container in containers_added:
|
||||||
|
self._container_registry.removeContainer(container.getId())
|
||||||
|
return
|
||||||
|
|
||||||
|
# --
|
||||||
|
# load extruder stack files
|
||||||
|
try:
|
||||||
|
for index, extruder_stack_file in enumerate(extruder_stack_files):
|
||||||
|
container_id = self._stripFileToId(extruder_stack_file)
|
||||||
|
|
||||||
|
container_stacks = self._container_registry.findContainerStacks(id = container_id)
|
||||||
|
if container_stacks:
|
||||||
|
# this container stack already exists, try to resolve
|
||||||
|
stack = container_stacks[0]
|
||||||
|
if self._resolve_strategies["machine"] == "override":
|
||||||
|
pass # do nothing
|
||||||
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
|
# create a new extruder stack from this one
|
||||||
|
new_id = self.getNewId(container_id)
|
||||||
|
stack = ExtruderStack(new_id)
|
||||||
|
stack.deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
||||||
|
|
||||||
|
# Ensure a unique ID and name
|
||||||
|
stack._id = new_id
|
||||||
|
|
||||||
|
self._container_registry.addContainer(stack)
|
||||||
|
extruder_stacks_added.append(stack)
|
||||||
|
containers_added.append(stack)
|
||||||
|
else:
|
||||||
|
if self._resolve_strategies["machine"] == "override":
|
||||||
|
global_stacks = self._container_registry.findContainerStacks(id = global_stack_id_original)
|
||||||
|
# deserialize new extruder stack over the current ones
|
||||||
|
if global_stacks:
|
||||||
|
old_extruder_stack_id = global_stacks[0].extruders[index].getId()
|
||||||
|
# HACK delete file
|
||||||
|
self._container_registry._deleteFiles(global_stacks[0].extruders[index])
|
||||||
|
global_stacks[0].extruders[index].deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
||||||
|
# HACK
|
||||||
|
global_stacks[0]._extruders = global_stacks[0]._extruders[:2]
|
||||||
|
# HACK update cache
|
||||||
|
del self._container_registry._id_container_cache[old_extruder_stack_id]
|
||||||
|
new_extruder_stack_id = global_stacks[0].extruders[index].getId()
|
||||||
|
self._container_registry._id_container_cache[new_extruder_stack_id] = global_stacks[0].extruders[index]
|
||||||
|
|
||||||
|
stack = global_stacks[0].extruders[index]
|
||||||
|
else:
|
||||||
|
Logger.log("w", "Could not find global stack, while I expected it: %s" % global_stack_id_original)
|
||||||
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
|
# container not found, create a new one
|
||||||
|
stack = ExtruderStack(container_id)
|
||||||
|
stack.deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
||||||
|
self._container_registry.addContainer(stack)
|
||||||
|
extruder_stacks_added.append(stack)
|
||||||
|
containers_added.append(stack)
|
||||||
|
else:
|
||||||
|
Logger.log("w", "Unknown resolve strategy: %s" % str(self._resolve_strategies["machine"]))
|
||||||
|
|
||||||
|
if global_stack_need_rename:
|
||||||
|
if stack.getMetaDataEntry("machine"):
|
||||||
|
stack.setMetaDataEntry("machine", global_stack_id_new)
|
||||||
|
extruder_stacks.append(stack)
|
||||||
except:
|
except:
|
||||||
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
||||||
# Something went really wrong. Try to remove any data that we added.
|
# Something went really wrong. Try to remove any data that we added.
|
||||||
for container in containers_to_add:
|
for container in containers_added:
|
||||||
self._container_registry.removeContainer(container.getId())
|
self._container_registry.removeContainer(container.getId())
|
||||||
|
return
|
||||||
|
|
||||||
for container in container_stacks_added:
|
#
|
||||||
self._container_registry.removeContainer(container.getId())
|
# Replacing the old containers if resolve is "new".
|
||||||
|
# When resolve is "new", some containers will get renamed, so all the other containers that reference to those
|
||||||
for container in extruder_stacks_added:
|
# MUST get updated too.
|
||||||
self._container_registry.removeContainer(container.getId())
|
#
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
if self._resolve_strategies["machine"] == "new":
|
if self._resolve_strategies["machine"] == "new":
|
||||||
# A new machine was made, but it was serialized with the wrong user container. Fix that now.
|
# A new machine was made, but it was serialized with the wrong user container. Fix that now.
|
||||||
for container in user_instance_containers:
|
for container in user_instance_containers:
|
||||||
|
# replacing the container ID for user instance containers for the extruders
|
||||||
extruder_id = container.getMetaDataEntry("extruder", None)
|
extruder_id = container.getMetaDataEntry("extruder", None)
|
||||||
if extruder_id:
|
if extruder_id:
|
||||||
for extruder in extruder_stacks:
|
for extruder in extruder_stacks:
|
||||||
if extruder.getId() == extruder_id:
|
if extruder.getId() == extruder_id:
|
||||||
extruder.replaceContainer(0, container)
|
extruder.userChanges = container
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# replacing the container ID for user instance containers for the machine
|
||||||
machine_id = container.getMetaDataEntry("machine", None)
|
machine_id = container.getMetaDataEntry("machine", None)
|
||||||
if machine_id:
|
if machine_id:
|
||||||
if global_stack.getId() == machine_id:
|
if global_stack.getId() == machine_id:
|
||||||
global_stack.replaceContainer(0, container)
|
global_stack.userChanges = container
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for container_type in ("quality_changes", "definition_changes"):
|
for changes_container_type in ("quality_changes", "definition_changes"):
|
||||||
if self._resolve_strategies[container_type] == "new":
|
if self._resolve_strategies[changes_container_type] == "new":
|
||||||
# Quality changes needs to get a new ID, added to registry and to the right stacks
|
# Quality changes needs to get a new ID, added to registry and to the right stacks
|
||||||
for container in quality_and_definition_changes_instance_containers:
|
for each_changes_container in quality_and_definition_changes_instance_containers:
|
||||||
old_id = container.getId()
|
old_id = each_changes_container.getId()
|
||||||
container.setName(self._container_registry.uniqueName(container.getName()))
|
each_changes_container.setName(self._container_registry.uniqueName(each_changes_container.getName()))
|
||||||
# We're not really supposed to change the ID in normal cases, but this is an exception.
|
# We're not really supposed to change the ID in normal cases, but this is an exception.
|
||||||
container._id = self.getNewId(container.getId())
|
each_changes_container._id = self.getNewId(each_changes_container.getId())
|
||||||
|
|
||||||
# The container was not added yet, as it didn't have an unique ID. It does now, so add it.
|
# The container was not added yet, as it didn't have an unique ID. It does now, so add it.
|
||||||
self._container_registry.addContainer(container)
|
self._container_registry.addContainer(each_changes_container)
|
||||||
|
|
||||||
# Replace the quality/definition changes container
|
# Find the old (current) changes container in the global stack
|
||||||
if container_type == "quality_changes":
|
if changes_container_type == "quality_changes":
|
||||||
old_container = global_stack.qualityChanges
|
old_container = global_stack.qualityChanges
|
||||||
elif container_type == "definition_changes":
|
elif changes_container_type == "definition_changes":
|
||||||
old_container = global_stack.definitionChanges
|
old_container = global_stack.definitionChanges
|
||||||
# old_container = global_stack.findContainer({"type": container_type})
|
|
||||||
|
# sanity checks
|
||||||
|
# NOTE: The following cases SHOULD NOT happen!!!!
|
||||||
|
if not old_container:
|
||||||
|
Logger.log("e", "We try to get [%s] from the global stack [%s] but we got None instead!",
|
||||||
|
changes_container_type, global_stack.getId())
|
||||||
|
|
||||||
|
# Replace the quality/definition changes container if it's in the GlobalStack
|
||||||
|
# NOTE: we can get an empty container here, but the IDs will not match,
|
||||||
|
# so this comparison is fine.
|
||||||
if old_container.getId() == old_id:
|
if old_container.getId() == old_id:
|
||||||
changes_index = global_stack.getContainerIndex(old_container)
|
if changes_container_type == "quality_changes":
|
||||||
global_stack.replaceContainer(changes_index, container)
|
global_stack.qualityChanges = each_changes_container
|
||||||
|
elif changes_container_type == "definition_changes":
|
||||||
|
global_stack.definitionChanges = each_changes_container
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for stack in extruder_stacks:
|
# Replace the quality/definition changes container if it's in one of the ExtruderStacks
|
||||||
old_container = stack.findContainer({"type": container_type})
|
for each_extruder_stack in extruder_stacks:
|
||||||
if old_container.getId() == old_id:
|
changes_container = None
|
||||||
changes_index = stack.getContainerIndex(old_container)
|
if changes_container_type == "quality_changes":
|
||||||
stack.replaceContainer(changes_index, container)
|
changes_container = each_extruder_stack.qualityChanges
|
||||||
|
elif changes_container_type == "definition_changes":
|
||||||
|
changes_container = each_extruder_stack.definitionChanges
|
||||||
|
|
||||||
|
# sanity checks
|
||||||
|
# NOTE: The following cases SHOULD NOT happen!!!!
|
||||||
|
if not changes_container:
|
||||||
|
Logger.log("e", "We try to get [%s] from the extruder stack [%s] but we got None instead!",
|
||||||
|
changes_container_type, each_extruder_stack.getId())
|
||||||
|
|
||||||
|
# NOTE: we can get an empty container here, but the IDs will not match,
|
||||||
|
# so this comparison is fine.
|
||||||
|
if changes_container.getId() == old_id:
|
||||||
|
if changes_container_type == "quality_changes":
|
||||||
|
each_extruder_stack.qualityChanges = each_changes_container
|
||||||
|
elif changes_container_type == "definition_changes":
|
||||||
|
each_extruder_stack.definitionChanges = each_changes_container
|
||||||
|
|
||||||
if self._resolve_strategies["material"] == "new":
|
if self._resolve_strategies["material"] == "new":
|
||||||
for material in material_containers:
|
for each_material in material_containers:
|
||||||
old_material = global_stack.findContainer({"type": "material"})
|
old_material = global_stack.material
|
||||||
if old_material.getId() in self._id_mapping:
|
|
||||||
material_index = global_stack.getContainerIndex(old_material)
|
# check if the old material container has been renamed to this material container ID
|
||||||
global_stack.replaceContainer(material_index, material)
|
# if the container hasn't been renamed, we do nothing.
|
||||||
|
new_id = self._id_mapping.get(old_material.getId())
|
||||||
|
if new_id is None or new_id != each_material.getId():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for stack in extruder_stacks:
|
if old_material.getId() in self._id_mapping:
|
||||||
old_material = stack.findContainer({"type": "material"})
|
global_stack.material = each_material
|
||||||
if old_material.getId() in self._id_mapping:
|
|
||||||
material_index = stack.getContainerIndex(old_material)
|
for each_extruder_stack in extruder_stacks:
|
||||||
stack.replaceContainer(material_index, material)
|
old_material = each_extruder_stack.material
|
||||||
|
|
||||||
|
# check if the old material container has been renamed to this material container ID
|
||||||
|
# if the container hasn't been renamed, we do nothing.
|
||||||
|
new_id = self._id_mapping.get(old_material.getId())
|
||||||
|
if new_id is None or new_id != each_material.getId():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if old_material.getId() in self._id_mapping:
|
||||||
|
each_extruder_stack.material = each_material
|
||||||
|
|
||||||
if extruder_stacks:
|
if extruder_stacks:
|
||||||
for stack in extruder_stacks:
|
for stack in extruder_stacks:
|
||||||
ExtruderManager.getInstance().registerExtruder(stack, global_stack.getId())
|
ExtruderManager.getInstance().registerExtruder(stack, global_stack.getId())
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
"file_formats": "text/x-gcode",
|
"file_formats": "text/x-gcode",
|
||||||
"icon": "icon_ultimaker2.png",
|
"icon": "icon_ultimaker2.png",
|
||||||
"platform": "ultimaker2_platform.obj",
|
"platform": "ultimaker2_platform.obj",
|
||||||
"platform_texture": "Ultimaker2Extendedbackplate.png",
|
"platform_texture": "Ultimaker2Extendedbackplate.png"
|
||||||
"supported_actions": ["UpgradeFirmware"]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
// Copyright (c) 2015 Ultimaker B.V.
|
|
||||||
// Cura is released under the terms of the AGPLv3 or higher.
|
|
||||||
|
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
import UM 1.1 as UM
|
|
||||||
|
|
||||||
UM.Dialog
|
|
||||||
{
|
|
||||||
id: base
|
|
||||||
|
|
||||||
//: Dialog title
|
|
||||||
title: catalog.i18nc("@title:window", "Multiply Model")
|
|
||||||
|
|
||||||
minimumWidth: 400 * Screen.devicePixelRatio
|
|
||||||
minimumHeight: 80 * Screen.devicePixelRatio
|
|
||||||
width: minimumWidth
|
|
||||||
height: minimumHeight
|
|
||||||
|
|
||||||
property var objectId: 0;
|
|
||||||
onAccepted: CuraApplication.multiplyObject(base.objectId, parseInt(copiesField.text))
|
|
||||||
|
|
||||||
property variant catalog: UM.I18nCatalog { name: "cura" }
|
|
||||||
|
|
||||||
signal reset()
|
|
||||||
onReset: {
|
|
||||||
copiesField.text = "1";
|
|
||||||
copiesField.selectAll();
|
|
||||||
copiesField.focus = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Row
|
|
||||||
{
|
|
||||||
spacing: UM.Theme.getSize("default_margin").width
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: "Number of copies:"
|
|
||||||
anchors.verticalCenter: copiesField.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
TextField {
|
|
||||||
id: copiesField
|
|
||||||
validator: RegExpValidator { regExp: /^\d{0,2}/ }
|
|
||||||
maximumLength: 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
rightButtons:
|
|
||||||
[
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@action:button","OK")
|
|
||||||
onClicked: base.accept()
|
|
||||||
enabled: base.objectId != 0 && parseInt(copiesField.text) > 0
|
|
||||||
},
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
text: catalog.i18nc("@action:button","Cancel")
|
|
||||||
onClicked: base.reject()
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -125,7 +125,7 @@ Item
|
|||||||
{
|
{
|
||||||
id: infillIcon
|
id: infillIcon
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
anchors.margins: UM.Theme.getSize("infill_button_margin").width
|
anchors.margins: 2
|
||||||
|
|
||||||
sourceSize.width: width
|
sourceSize.width: width
|
||||||
sourceSize.height: width
|
sourceSize.height: width
|
||||||
@ -185,7 +185,7 @@ Item
|
|||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
{
|
{
|
||||||
infillModel.append({
|
infillModel.append({
|
||||||
name: catalog.i18nc("@label", "Empty"),
|
name: catalog.i18nc("@label", "0%"),
|
||||||
percentage: 0,
|
percentage: 0,
|
||||||
steps: 0,
|
steps: 0,
|
||||||
percentageMin: -1,
|
percentageMin: -1,
|
||||||
@ -196,7 +196,7 @@ Item
|
|||||||
icon: "hollow"
|
icon: "hollow"
|
||||||
})
|
})
|
||||||
infillModel.append({
|
infillModel.append({
|
||||||
name: catalog.i18nc("@label", "Light"),
|
name: catalog.i18nc("@label", "20%"),
|
||||||
percentage: 20,
|
percentage: 20,
|
||||||
steps: 0,
|
steps: 0,
|
||||||
percentageMin: 0,
|
percentageMin: 0,
|
||||||
@ -207,7 +207,7 @@ Item
|
|||||||
icon: "sparse"
|
icon: "sparse"
|
||||||
})
|
})
|
||||||
infillModel.append({
|
infillModel.append({
|
||||||
name: catalog.i18nc("@label", "Dense"),
|
name: catalog.i18nc("@label", "50%"),
|
||||||
percentage: 50,
|
percentage: 50,
|
||||||
steps: 0,
|
steps: 0,
|
||||||
percentageMin: 30,
|
percentageMin: 30,
|
||||||
@ -218,7 +218,7 @@ Item
|
|||||||
icon: "dense"
|
icon: "dense"
|
||||||
})
|
})
|
||||||
infillModel.append({
|
infillModel.append({
|
||||||
name: catalog.i18nc("@label", "Solid"),
|
name: catalog.i18nc("@label", "100%"),
|
||||||
percentage: 100,
|
percentage: 100,
|
||||||
steps: 0,
|
steps: 0,
|
||||||
percentageMin: 70,
|
percentageMin: 70,
|
||||||
|
@ -13,13 +13,10 @@ UM.Dialog
|
|||||||
{
|
{
|
||||||
title: catalog.i18nc("@title:window", "Save Project")
|
title: catalog.i18nc("@title:window", "Save Project")
|
||||||
|
|
||||||
width: 550 * Screen.devicePixelRatio
|
width: 500
|
||||||
minimumWidth: 550 * Screen.devicePixelRatio
|
height: 400
|
||||||
|
|
||||||
height: 350 * Screen.devicePixelRatio
|
property int spacerHeight: 10
|
||||||
minimumHeight: 350 * Screen.devicePixelRatio
|
|
||||||
|
|
||||||
property int spacerHeight: 10 * Screen.devicePixelRatio
|
|
||||||
|
|
||||||
property bool dontShowAgain: true
|
property bool dontShowAgain: true
|
||||||
|
|
||||||
@ -42,7 +39,6 @@ UM.Dialog
|
|||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 20 * Screen.devicePixelRatio
|
|
||||||
|
|
||||||
UM.SettingDefinitionsModel
|
UM.SettingDefinitionsModel
|
||||||
{
|
{
|
||||||
@ -232,42 +228,48 @@ UM.Dialog
|
|||||||
height: spacerHeight
|
height: spacerHeight
|
||||||
width: height
|
width: height
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: buttonRow
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: childrenRect.height
|
||||||
|
|
||||||
CheckBox
|
CheckBox
|
||||||
{
|
{
|
||||||
id: dontShowAgainCheckbox
|
id: dontShowAgainCheckbox
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
text: catalog.i18nc("@action:label", "Don't show project summary on save again")
|
text: catalog.i18nc("@action:label", "Don't show project summary on save again")
|
||||||
checked: dontShowAgain
|
checked: dontShowAgain
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: ok_button
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
Button
|
text: catalog.i18nc("@action:button","Save");
|
||||||
{
|
enabled: true
|
||||||
id: ok_button
|
onClicked: {
|
||||||
text: catalog.i18nc("@action:button","Save");
|
close()
|
||||||
enabled: true
|
yes()
|
||||||
onClicked: {
|
}
|
||||||
close()
|
|
||||||
yes()
|
|
||||||
}
|
}
|
||||||
anchors.bottomMargin: - 0.5 * height
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
}
|
|
||||||
|
|
||||||
Button
|
Button
|
||||||
{
|
{
|
||||||
id: cancel_button
|
id: cancel_button
|
||||||
text: catalog.i18nc("@action:button","Cancel");
|
anchors.right: ok_button.left
|
||||||
enabled: true
|
anchors.rightMargin: 2
|
||||||
onClicked: close()
|
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: ok_button.left
|
|
||||||
anchors.bottomMargin: - 0.5 * height
|
|
||||||
anchors.rightMargin:2
|
|
||||||
|
|
||||||
|
text: catalog.i18nc("@action:button","Cancel");
|
||||||
|
enabled: true
|
||||||
|
onClicked: close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user