Merge branch 'master' of github.com:Ultimaker/Cura

This commit is contained in:
Ghostkeeper 2017-05-10 11:40:24 +02:00
commit 1a96cdfdb7
No known key found for this signature in database
GPG Key ID: C5F96EE2BC0F7E75
4 changed files with 78 additions and 62 deletions

View File

@ -1,11 +1,11 @@
# Copyright (c) 2016 Ultimaker B.V. # Copyright (c) 2016 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, pyqtSlot from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer
import UM.Qt.ListModel import UM.Qt.ListModel
from UM.Application import Application from UM.Application import Application
import UM.FlameProfiler
from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderManager import ExtruderManager
## Model that holds extruders. ## Model that holds extruders.
@ -58,6 +58,11 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
self.addRoleName(self.MaterialRole, "material") self.addRoleName(self.MaterialRole, "material")
self.addRoleName(self.VariantRole, "variant") self.addRoleName(self.VariantRole, "variant")
self._update_extruder_timer = QTimer()
self._update_extruder_timer.setInterval(250)
self._update_extruder_timer.setSingleShot(True)
self._update_extruder_timer.timeout.connect(self.__updateExtruders)
self._add_global = False self._add_global = False
self._simple_names = False self._simple_names = False
@ -111,17 +116,21 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
active_extruder_stack.containersChanged.connect(self._onExtruderStackContainersChanged) active_extruder_stack.containersChanged.connect(self._onExtruderStackContainersChanged)
self._active_extruder_stack = active_extruder_stack self._active_extruder_stack = active_extruder_stack
def _onExtruderStackContainersChanged(self, container): def _onExtruderStackContainersChanged(self, container):
# The ExtrudersModel needs to be updated when the material-name or -color changes, because the user identifies extruders by material-name if container.getMetaDataEntry("type") == "material":
self._updateExtruders() # The ExtrudersModel needs to be updated when the material-name or -color changes, because the user identifies extruders by material-name
self._updateExtruders()
modelChanged = pyqtSignal() modelChanged = pyqtSignal()
def _updateExtruders(self):
self._update_extruder_timer.start()
## Update the list of extruders. ## Update the list of extruders.
# #
# This should be called whenever the list of extruders changes. # This should be called whenever the list of extruders changes.
def _updateExtruders(self): @UM.FlameProfiler.profile
def __updateExtruders(self):
changed = False changed = False
if self.rowCount() != 0: if self.rowCount() != 0:
@ -132,7 +141,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
global_container_stack = Application.getInstance().getGlobalContainerStack() global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack: if global_container_stack:
if self._add_global: if self._add_global:
material = global_container_stack.findContainer({ "type": "material" }) material = global_container_stack.material
color = material.getMetaDataEntry("color_code", default = self.defaultColors[0]) if material else self.defaultColors[0] color = material.getMetaDataEntry("color_code", default = self.defaultColors[0]) if material else self.defaultColors[0]
item = { item = {
"id": global_container_stack.getId(), "id": global_container_stack.getId(),
@ -147,9 +156,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value") machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
manager = ExtruderManager.getInstance() manager = ExtruderManager.getInstance()
for extruder in manager.getMachineExtruders(global_container_stack.getId()): for extruder in manager.getMachineExtruders(global_container_stack.getId()):
extruder_name = extruder.getName()
material = extruder.findContainer({ "type": "material" })
variant = extruder.findContainer({"type": "variant"})
position = extruder.getMetaDataEntry("position", default = "0") # Get the position position = extruder.getMetaDataEntry("position", default = "0") # Get the position
try: try:
position = int(position) position = int(position)
@ -157,6 +163,9 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
position = -1 position = -1
if position >= machine_extruder_count: if position >= machine_extruder_count:
continue continue
extruder_name = extruder.getName()
material = extruder.material
variant = extruder.variant
default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0] default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0]
color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color

View File

@ -20,6 +20,7 @@ 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.Settings.Validator import ValidatorState
from UM.Signal import postponeSignals from UM.Signal import postponeSignals
import UM.FlameProfiler
from cura.QualityManager import QualityManager from cura.QualityManager import QualityManager
from cura.PrinterOutputDevice import PrinterOutputDevice from cura.PrinterOutputDevice import PrinterOutputDevice
@ -810,13 +811,13 @@ class MachineManager(QObject):
# Quality profile come in two flavours: type=quality and type=quality_changes # Quality profile come in two flavours: type=quality and type=quality_changes
# If we found a quality_changes profile then look up its parent quality profile. # If we found a quality_changes profile then look up its parent quality profile.
container_type = containers[0].getMetaDataEntry("type") container_type = containers[0].getMetaDataEntry("type")
quality_name = containers[0].getName()
quality_type = containers[0].getMetaDataEntry("quality_type")
# Get quality container and optionally the quality_changes container. # Get quality container and optionally the quality_changes container.
if container_type == "quality": if container_type == "quality":
quality_type = containers[0].getMetaDataEntry("quality_type")
new_quality_settings_list = self.determineQualityAndQualityChangesForQualityType(quality_type) new_quality_settings_list = self.determineQualityAndQualityChangesForQualityType(quality_type)
elif container_type == "quality_changes": elif container_type == "quality_changes":
quality_name = containers[0].getName()
new_quality_settings_list = self._determineQualityAndQualityChangesForQualityChanges(quality_name) new_quality_settings_list = self._determineQualityAndQualityChangesForQualityChanges(quality_name)
else: else:
Logger.log("e", "Tried to set quality to a container that is not of the right type") Logger.log("e", "Tried to set quality to a container that is not of the right type")
@ -855,6 +856,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
def determineQualityAndQualityChangesForQualityType(self, quality_type): def determineQualityAndQualityChangesForQualityType(self, quality_type):
quality_manager = QualityManager.getInstance() quality_manager = QualityManager.getInstance()
result = [] result = []
@ -952,12 +954,16 @@ class MachineManager(QObject):
# Disconnect the signal handling from the old container. # Disconnect the signal handling from the old container.
container_type = container.getMetaDataEntry("type") container_type = container.getMetaDataEntry("type")
if container_type == "quality": if container_type == "quality":
if stack.quality == container:
return # Nothing to do
stack.quality.nameChanged.disconnect(self._onQualityNameChanged) stack.quality.nameChanged.disconnect(self._onQualityNameChanged)
stack.setQuality(container) stack.setQuality(container)
stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged) stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged)
elif container_type == "quality_changes" or container_type is None: elif container_type == "quality_changes" or container_type is None:
# If the container is an empty container, we need to change the quality_changes. # If the container is an empty container, we need to change the quality_changes.
# Quality can never be set to empty. # Quality can never be set to empty.
if stack.qualityChanges == container:
return # Nothing to do
stack.qualityChanges.nameChanged.disconnect(self._onQualityNameChanged) stack.qualityChanges.nameChanged.disconnect(self._onQualityNameChanged)
stack.setQualityChanges(container) stack.setQualityChanges(container)
stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged) stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged)

View File

@ -89,7 +89,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
Logger.log("w", "Unknown container stack type '%s' from %s in %s", Logger.log("w", "Unknown container stack type '%s' from %s in %s",
stack_type, file_name, project_file_name) stack_type, file_name, project_file_name)
return global_stack_file_list, extruder_stack_file_list if len(global_stack_file_list) != 1:
raise RuntimeError("More than one global stack file found: [%s]" % str(global_stack_file_list))
return global_stack_file_list[0], extruder_stack_file_list
## read some info so we can make decisions ## read some info so we can make decisions
# \param file_name # \param file_name
@ -195,12 +198,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
Job.yieldThread() Job.yieldThread()
# Load ContainerStack files and ExtruderStack files # Load ContainerStack files and ExtruderStack files
container_stack_files, extruder_stack_files = self._determineGlobalAndExtruderStackFiles( global_stack_file, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(
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 quality_changes_conflict = False
for container_stack_file in container_stack_files + 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")
if machine_name == "": if machine_name == "":
@ -408,7 +411,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# 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...")
container_stack_files, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(file_name, global_stack_file, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(file_name,
cura_file_names) cura_file_names)
global_stack = None global_stack = None
@ -457,52 +460,52 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# load global stack file # load global stack file
try: try:
for container_stack_file in container_stack_files: container_id = self._stripFileToId(global_stack_file)
container_id = self._stripFileToId(container_stack_file)
# Check if a stack by this ID already exists; # Check if a stack by this ID already exists;
container_stacks = self._container_registry.findContainerStacks(id = container_id) container_stacks = self._container_registry.findContainerStacks(id = container_id)
if container_stacks: if container_stacks:
stack = container_stacks[0] stack = container_stacks[0]
if self._resolve_strategies["machine"] == "override":
# TODO: HACK
# There is a machine, check if it has authentication data. If so, keep that data.
network_authentication_id = container_stacks[0].getMetaDataEntry("network_authentication_id")
network_authentication_key = container_stacks[0].getMetaDataEntry("network_authentication_key")
container_stacks[0].deserialize(archive.open(container_stack_file).read().decode("utf-8"))
if network_authentication_id:
container_stacks[0].addMetaDataEntry("network_authentication_id", network_authentication_id)
if network_authentication_key:
container_stacks[0].addMetaDataEntry("network_authentication_key", network_authentication_key)
elif self._resolve_strategies["machine"] == "new":
new_id = self.getNewId(container_id)
stack = GlobalStack(new_id)
stack.deserialize(archive.open(container_stack_file).read().decode("utf-8"))
# Ensure a unique ID and name if self._resolve_strategies["machine"] == "override":
stack._id = new_id # TODO: HACK
# There is a machine, check if it has authentication data. If so, keep that data.
network_authentication_id = container_stacks[0].getMetaDataEntry("network_authentication_id")
network_authentication_key = container_stacks[0].getMetaDataEntry("network_authentication_key")
container_stacks[0].deserialize(archive.open(global_stack_file).read().decode("utf-8"))
if network_authentication_id:
container_stacks[0].addMetaDataEntry("network_authentication_id", network_authentication_id)
if network_authentication_key:
container_stacks[0].addMetaDataEntry("network_authentication_key", network_authentication_key)
elif self._resolve_strategies["machine"] == "new":
new_id = self.getNewId(container_id)
stack = GlobalStack(new_id)
stack.deserialize(archive.open(global_stack_file).read().decode("utf-8"))
# Extruder stacks are "bound" to a machine. If we add the machine as a new one, the id of the # Ensure a unique ID and name
# bound machine also needs to change. stack._id = new_id
if stack.getMetaDataEntry("machine", None):
stack.setMetaDataEntry("machine", self.getNewId(stack.getMetaDataEntry("machine")))
# Only machines need a new name, stacks may be non-unique # Extruder stacks are "bound" to a machine. If we add the machine as a new one, the id of the
stack.setName(self._container_registry.uniqueName(stack.getName())) # bound machine also needs to change.
container_stacks_added.append(stack) if stack.getMetaDataEntry("machine", None):
self._container_registry.addContainer(stack) stack.setMetaDataEntry("machine", self.getNewId(stack.getMetaDataEntry("machine")))
else:
Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"]) # Only machines need a new name, stacks may be non-unique
else: stack.setName(self._container_registry.uniqueName(stack.getName()))
# no existing container stack, so we create a new one
stack = GlobalStack(container_id)
# Deserialize stack by converting read data from bytes to string
stack.deserialize(archive.open(container_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)
else:
Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"])
else:
# no existing container stack, so we create a new one
stack = GlobalStack(container_id)
# Deserialize stack by converting read data from bytes to string
stack.deserialize(archive.open(global_stack_file).read().decode("utf-8"))
container_stacks_added.append(stack)
self._container_registry.addContainer(stack)
global_stack = stack global_stack = stack
Job.yieldThread() Job.yieldThread()
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.
@ -585,10 +588,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# if we are reusing an existing global stack, it can already have extruders associated, so we need to remove # if we are reusing an existing global stack, it can already have extruders associated, so we need to remove
# them first # them first
if global_stack.extruders: if global_stack.extruders:
old_extruder_stacks = global_stack.extruders for extruder_stack in global_stack.extruders:
for extruder_stack in old_extruder_stacks: if extruder_stack not in extruder_stacks_added: # skip new ones
self._container_registry.removeContainer(extruder_stack) self._container_registry.removeContainer(extruder_stack.getId())
global_stack._extruders = []
for stack in extruder_stacks: for stack in extruder_stacks:
stack.setNextStack(global_stack) stack.setNextStack(global_stack)

View File

@ -251,7 +251,7 @@ class MachineSettingsAction(MachineAction):
if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False): if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False):
has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode" has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
material_container = self._global_container_stack.findContainer({"type": "material"}) material_container = self._global_container_stack.material
material_index = self._global_container_stack.getContainerIndex(material_container) material_index = self._global_container_stack.getContainerIndex(material_container)
if has_materials: if has_materials:
@ -272,7 +272,6 @@ class MachineSettingsAction(MachineAction):
if "has_materials" in self._global_container_stack.getMetaData(): if "has_materials" in self._global_container_stack.getMetaData():
self._global_container_stack.removeMetaDataEntry("has_materials") self._global_container_stack.removeMetaDataEntry("has_materials")
empty_material = self._container_registry.findInstanceContainers(id = "empty_material")[0] self._global_container_stack.material = ContainerRegistry.getInstance().getEmptyInstanceContainer()
self._global_container_stack.replaceContainer(material_index, empty_material)
Application.getInstance().globalContainerStackChanged.emit() Application.getInstance().globalContainerStackChanged.emit()