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

This commit is contained in:
Jaime van Kessel 2018-11-27 17:55:13 +01:00
commit 94c4366194
5 changed files with 48 additions and 45 deletions

View File

@ -3,7 +3,7 @@
from PyQt5.QtCore import QObject, QUrl from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtGui import QDesktopServices from PyQt5.QtGui import QDesktopServices
from typing import List, TYPE_CHECKING from typing import List, TYPE_CHECKING, cast
from UM.Event import CallFunctionEvent from UM.Event import CallFunctionEvent
from UM.FlameProfiler import pyqtSlot from UM.FlameProfiler import pyqtSlot
@ -61,8 +61,10 @@ class CuraActions(QObject):
operation = GroupedOperation() operation = GroupedOperation()
for node in Selection.getAllSelectedObjects(): for node in Selection.getAllSelectedObjects():
current_node = node current_node = node
while current_node.getParent() and current_node.getParent().callDecoration("isGroup"): parent_node = current_node.getParent()
current_node = current_node.getParent() while parent_node and parent_node.callDecoration("isGroup"):
current_node = parent_node
parent_node = current_node.getParent()
# This was formerly done with SetTransformOperation but because of # This was formerly done with SetTransformOperation but because of
# unpredictable matrix deconstruction it was possible that mirrors # unpredictable matrix deconstruction it was possible that mirrors
@ -150,13 +152,13 @@ class CuraActions(QObject):
root = cura.CuraApplication.CuraApplication.getInstance().getController().getScene().getRoot() root = cura.CuraApplication.CuraApplication.getInstance().getController().getScene().getRoot()
nodes_to_change = [] nodes_to_change = [] # type: List[SceneNode]
for node in Selection.getAllSelectedObjects(): for node in Selection.getAllSelectedObjects():
parent_node = node # Find the parent node to change instead parent_node = node # Find the parent node to change instead
while parent_node.getParent() != root: while parent_node.getParent() != root:
parent_node = parent_node.getParent() parent_node = cast(SceneNode, parent_node.getParent())
for single_node in BreadthFirstIterator(parent_node): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. for single_node in BreadthFirstIterator(parent_node): # type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
nodes_to_change.append(single_node) nodes_to_change.append(single_node)
if not nodes_to_change: if not nodes_to_change:

View File

@ -14,8 +14,7 @@ from UM.Logger import Logger
from UM.Qt.Duration import Duration from UM.Qt.Duration import Duration
from UM.Scene.SceneNode import SceneNode from UM.Scene.SceneNode import SceneNode
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.MimeTypeDatabase import MimeTypeDatabase from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -361,7 +360,7 @@ class PrintInformation(QObject):
try: try:
mime_type = MimeTypeDatabase.getMimeTypeForFile(name) mime_type = MimeTypeDatabase.getMimeTypeForFile(name)
data = mime_type.stripExtension(name) data = mime_type.stripExtension(name)
except: except MimeTypeNotFoundError:
Logger.log("w", "Unsupported Mime Type Database file extension %s", name) Logger.log("w", "Unsupported Mime Type Database file extension %s", name)
if data is not None and check_name is not None: if data is not None and check_name is not None:
@ -402,7 +401,7 @@ class PrintInformation(QObject):
return ''.join(char for char in unicodedata.normalize('NFD', to_strip) if unicodedata.category(char) != 'Mn') return ''.join(char for char in unicodedata.normalize('NFD', to_strip) if unicodedata.category(char) != 'Mn')
@pyqtSlot(result = "QVariantMap") @pyqtSlot(result = "QVariantMap")
def getFeaturePrintTimes(self): def getFeaturePrintTimes(self) -> Dict[str, Duration]:
result = {} result = {}
if self._active_build_plate not in self._print_times_per_feature: if self._active_build_plate not in self._print_times_per_feature:
self._initPrintTimesPerFeature(self._active_build_plate) self._initPrintTimesPerFeature(self._active_build_plate)

View File

@ -66,7 +66,7 @@ class MachineManager(QObject):
self.machine_extruder_material_update_dict = collections.defaultdict(list) #type: Dict[str, List[Callable[[], None]]] self.machine_extruder_material_update_dict = collections.defaultdict(list) #type: Dict[str, List[Callable[[], None]]]
self._instance_container_timer = QTimer() #type: QTimer self._instance_container_timer = QTimer() # type: QTimer
self._instance_container_timer.setInterval(250) self._instance_container_timer.setInterval(250)
self._instance_container_timer.setSingleShot(True) self._instance_container_timer.setSingleShot(True)
self._instance_container_timer.timeout.connect(self.__emitChangedSignals) self._instance_container_timer.timeout.connect(self.__emitChangedSignals)
@ -76,7 +76,7 @@ class MachineManager(QObject):
self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged) self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged)
self._container_registry.containerLoadComplete.connect(self._onContainersChanged) self._container_registry.containerLoadComplete.connect(self._onContainersChanged)
## When the global container is changed, active material probably needs to be updated. # When the global container is changed, active material probably needs to be updated.
self.globalContainerChanged.connect(self.activeMaterialChanged) self.globalContainerChanged.connect(self.activeMaterialChanged)
self.globalContainerChanged.connect(self.activeVariantChanged) self.globalContainerChanged.connect(self.activeVariantChanged)
self.globalContainerChanged.connect(self.activeQualityChanged) self.globalContainerChanged.connect(self.activeQualityChanged)
@ -117,15 +117,15 @@ 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."),
title = catalog.i18nc("@info:title", "Incompatible Material")) #type: Message title = catalog.i18nc("@info:title", "Incompatible Material")) # type: Message
containers = CuraContainerRegistry.getInstance().findInstanceContainers(id = self.activeMaterialId) #type: List[InstanceContainer] containers = CuraContainerRegistry.getInstance().findInstanceContainers(id = self.activeMaterialId) # type: List[InstanceContainer]
if containers: if containers:
containers[0].nameChanged.connect(self._onMaterialNameChanged) containers[0].nameChanged.connect(self._onMaterialNameChanged)
self._material_manager = self._application.getMaterialManager() #type: MaterialManager self._material_manager = self._application.getMaterialManager() # type: MaterialManager
self._variant_manager = self._application.getVariantManager() #type: VariantManager self._variant_manager = self._application.getVariantManager() # type: VariantManager
self._quality_manager = self._application.getQualityManager() #type: QualityManager self._quality_manager = self._application.getQualityManager() # type: QualityManager
# When the materials lookup table gets updated, it can mean that a material has its name changed, which should # When the materials lookup table gets updated, it can mean that a material has its name changed, which should
# be reflected on the GUI. This signal emission makes sure that it happens. # be reflected on the GUI. This signal emission makes sure that it happens.
@ -158,7 +158,7 @@ class MachineManager(QObject):
blurSettings = pyqtSignal() # Emitted to force fields in the advanced sidebar to un-focus, so they update properly blurSettings = pyqtSignal() # Emitted to force fields in the advanced sidebar to un-focus, so they update properly
outputDevicesChanged = pyqtSignal() outputDevicesChanged = pyqtSignal()
currentConfigurationChanged = pyqtSignal() # Emitted every time the current configurations of the machine changes currentConfigurationChanged = pyqtSignal() # Emitted every time the current configurations of the machine changes
printerConnectedStatusChanged = pyqtSignal() # Emitted every time the active machine change or the outputdevices change printerConnectedStatusChanged = pyqtSignal() # Emitted every time the active machine change or the outputdevices change
rootMaterialChanged = pyqtSignal() rootMaterialChanged = pyqtSignal()
@ -203,7 +203,7 @@ class MachineManager(QObject):
extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != empty_variant_container else None extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != empty_variant_container else None
self._current_printer_configuration.extruderConfigurations.append(extruder_configuration) self._current_printer_configuration.extruderConfigurations.append(extruder_configuration)
# an empty build plate configuration from the network printer is presented as an empty string, so use "" for an # An empty build plate configuration from the network printer is presented as an empty string, so use "" for an
# empty build plate. # empty build plate.
self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value") if self._global_container_stack.variant != empty_variant_container else "" self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value") if self._global_container_stack.variant != empty_variant_container else ""
self.currentConfigurationChanged.emit() self.currentConfigurationChanged.emit()
@ -249,7 +249,7 @@ class MachineManager(QObject):
self.updateNumberExtrudersEnabled() self.updateNumberExtrudersEnabled()
self.globalContainerChanged.emit() self.globalContainerChanged.emit()
# after switching the global stack we reconnect all the signals and set the variant and material references # After switching the global stack we reconnect all the signals and set the variant and material references
if self._global_container_stack: if self._global_container_stack:
self._application.getPreferences().setValue("cura/active_machine", self._global_container_stack.getId()) self._application.getPreferences().setValue("cura/active_machine", self._global_container_stack.getId())
@ -263,7 +263,7 @@ class MachineManager(QObject):
if global_variant.getMetaDataEntry("hardware_type") != "buildplate": if global_variant.getMetaDataEntry("hardware_type") != "buildplate":
self._global_container_stack.setVariant(empty_variant_container) self._global_container_stack.setVariant(empty_variant_container)
# set the global material to empty as we now use the extruder stack at all times - CURA-4482 # Set the global material to empty as we now use the extruder stack at all times - CURA-4482
global_material = self._global_container_stack.material global_material = self._global_container_stack.material
if global_material != empty_material_container: if global_material != empty_material_container:
self._global_container_stack.setMaterial(empty_material_container) self._global_container_stack.setMaterial(empty_material_container)
@ -421,7 +421,7 @@ class MachineManager(QObject):
# Not a very pretty solution, but the extruder manager doesn't really know how many extruders there are # Not a very pretty solution, but the extruder manager doesn't really know how many extruders there are
machine_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value") machine_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks() extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
count = 1 # we start with the global stack count = 1 # We start with the global stack
for stack in extruder_stacks: for stack in extruder_stacks:
md = stack.getMetaData() md = stack.getMetaData()
if "position" in md and int(md["position"]) >= machine_extruder_count: if "position" in md and int(md["position"]) >= machine_extruder_count:
@ -648,7 +648,7 @@ class MachineManager(QObject):
new_value = self._active_container_stack.getProperty(key, "value") new_value = self._active_container_stack.getProperty(key, "value")
extruder_stacks = [stack for stack in ExtruderManager.getInstance().getActiveExtruderStacks()] extruder_stacks = [stack for stack in ExtruderManager.getInstance().getActiveExtruderStacks()]
# check in which stack the value has to be replaced # Check in which stack the value has to be replaced
for extruder_stack in extruder_stacks: for extruder_stack in extruder_stacks:
if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value:
extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved
@ -664,7 +664,7 @@ class MachineManager(QObject):
for key in self._active_container_stack.userChanges.getAllKeys(): for key in self._active_container_stack.userChanges.getAllKeys():
new_value = self._active_container_stack.getProperty(key, "value") new_value = self._active_container_stack.getProperty(key, "value")
# check if the value has to be replaced # Check if the value has to be replaced
extruder_stack.userChanges.setProperty(key, "value", new_value) extruder_stack.userChanges.setProperty(key, "value", new_value)
@pyqtProperty(str, notify = activeVariantChanged) @pyqtProperty(str, notify = activeVariantChanged)
@ -733,7 +733,7 @@ class MachineManager(QObject):
# 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)
# activate a new machine before removing a machine because this is safer # Activate a new machine before removing a machine because this is safer
if activate_new_machine: if activate_new_machine:
machine_stacks = CuraContainerRegistry.getInstance().findContainerStacksMetadata(type = "machine") machine_stacks = CuraContainerRegistry.getInstance().findContainerStacksMetadata(type = "machine")
other_machine_stacks = [s for s in machine_stacks if s["id"] != machine_id] other_machine_stacks = [s for s in machine_stacks if s["id"] != machine_id]
@ -917,9 +917,12 @@ class MachineManager(QObject):
if settable_per_extruder: if settable_per_extruder:
limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder")) limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder"))
extruder_position = str(max(0, limit_to_extruder)) extruder_position = max(0, limit_to_extruder)
extruder_stack = self._global_container_stack.extruders[extruder_position] extruder_stack = self.getExtruder(extruder_position)
extruder_stack.userChanges.setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value")) if extruder_stack:
extruder_stack.userChanges.setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value"))
else:
Logger.log("e", "Unable to find extruder on position %s", extruder_position)
global_user_container.removeInstance(setting_key) global_user_container.removeInstance(setting_key)
# Signal that the global stack has changed # Signal that the global stack has changed
@ -928,10 +931,9 @@ class MachineManager(QObject):
@pyqtSlot(int, result = QObject) @pyqtSlot(int, result = QObject)
def getExtruder(self, position: int) -> Optional[ExtruderStack]: def getExtruder(self, position: int) -> Optional[ExtruderStack]:
extruder = None
if self._global_container_stack: if self._global_container_stack:
extruder = self._global_container_stack.extruders.get(str(position)) return self._global_container_stack.extruders.get(str(position))
return extruder return None
def updateDefaultExtruder(self) -> None: def updateDefaultExtruder(self) -> None:
if self._global_container_stack is None: if self._global_container_stack is None:
@ -997,12 +999,12 @@ class MachineManager(QObject):
if not enabled and position == ExtruderManager.getInstance().activeExtruderIndex: if not enabled and position == ExtruderManager.getInstance().activeExtruderIndex:
ExtruderManager.getInstance().setActiveExtruderIndex(int(self._default_extruder_position)) ExtruderManager.getInstance().setActiveExtruderIndex(int(self._default_extruder_position))
# ensure that the quality profile is compatible with current combination, or choose a compatible one if available # Ensure that the quality profile is compatible with current combination, or choose a compatible one if available
self._updateQualityWithMaterial() self._updateQualityWithMaterial()
self.extruderChanged.emit() self.extruderChanged.emit()
# update material compatibility color # Update material compatibility color
self.activeQualityGroupChanged.emit() self.activeQualityGroupChanged.emit()
# update items in SettingExtruder # Update items in SettingExtruder
ExtruderManager.getInstance().extrudersChanged.emit(self._global_container_stack.getId()) ExtruderManager.getInstance().extrudersChanged.emit(self._global_container_stack.getId())
# Make sure the front end reflects changes # Make sure the front end reflects changes
self.forceUpdateAllSettings() self.forceUpdateAllSettings()
@ -1076,7 +1078,6 @@ class MachineManager(QObject):
return result return result
#
# Sets all quality and quality_changes containers to empty_quality and empty_quality_changes containers # Sets all quality and quality_changes containers to empty_quality and empty_quality_changes containers
# for all stacks in the currently active machine. # for all stacks in the currently active machine.
# #
@ -1135,7 +1136,7 @@ class MachineManager(QObject):
def _setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None: def _setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None:
if self._global_container_stack is None: if self._global_container_stack is None:
return #Can't change that. return # Can't change that.
quality_type = quality_changes_group.quality_type quality_type = quality_changes_group.quality_type
# A custom quality can be created based on "not supported". # A custom quality can be created based on "not supported".
# In that case, do not set quality containers to empty. # In that case, do not set quality containers to empty.
@ -1205,7 +1206,7 @@ class MachineManager(QObject):
self.rootMaterialChanged.emit() self.rootMaterialChanged.emit()
def activeMaterialsCompatible(self) -> bool: def activeMaterialsCompatible(self) -> bool:
# check material - variant compatibility # Check material - variant compatibility
if self._global_container_stack is not None: if self._global_container_stack is not None:
if Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False)): if Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False)):
for position, extruder in self._global_container_stack.extruders.items(): for position, extruder in self._global_container_stack.extruders.items():
@ -1415,7 +1416,7 @@ class MachineManager(QObject):
material_diameter, root_material_id) material_diameter, root_material_id)
self.setMaterial(position, material_node) self.setMaterial(position, material_node)
## global_stack: if you want to provide your own global_stack instead of the current active one ## Global_stack: if you want to provide your own global_stack instead of the current active one
# if you update an active machine, special measures have to be taken. # if you update an active machine, special measures have to be taken.
@pyqtSlot(str, "QVariant") @pyqtSlot(str, "QVariant")
def setMaterial(self, position: str, container_node, global_stack: Optional["GlobalStack"] = None) -> None: def setMaterial(self, position: str, container_node, global_stack: Optional["GlobalStack"] = None) -> None:

View File

@ -55,14 +55,14 @@ class PostProcessingPlugin(QObject, Extension):
def selectedScriptDefinitionId(self) -> Optional[str]: def selectedScriptDefinitionId(self) -> Optional[str]:
try: try:
return self._script_list[self._selected_script_index].getDefinitionId() return self._script_list[self._selected_script_index].getDefinitionId()
except: except IndexError:
return "" return ""
@pyqtProperty(str, notify=selectedIndexChanged) @pyqtProperty(str, notify=selectedIndexChanged)
def selectedScriptStackId(self) -> Optional[str]: def selectedScriptStackId(self) -> Optional[str]:
try: try:
return self._script_list[self._selected_script_index].getStackId() return self._script_list[self._selected_script_index].getStackId()
except: except IndexError:
return "" return ""
## Execute all post-processing scripts on the gcode. ## Execute all post-processing scripts on the gcode.

View File

@ -3,6 +3,7 @@
from UM.Job import Job from UM.Job import Job
from UM.Logger import Logger from UM.Logger import Logger
from plugins.USBPrinting.avr_isp import ispBase
from .avr_isp.stk500v2 import Stk500v2 from .avr_isp.stk500v2 import Stk500v2
@ -14,12 +15,12 @@ from serial import Serial, SerialException
# It tries a pre-set list of baud rates. All these baud rates are validated by requesting the temperature a few times # It tries a pre-set list of baud rates. All these baud rates are validated by requesting the temperature a few times
# and checking if the results make sense. If getResult() is not None, it was able to find a correct baud rate. # and checking if the results make sense. If getResult() is not None, it was able to find a correct baud rate.
class AutoDetectBaudJob(Job): class AutoDetectBaudJob(Job):
def __init__(self, serial_port): def __init__(self, serial_port: int) -> None:
super().__init__() super().__init__()
self._serial_port = serial_port self._serial_port = serial_port
self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600] self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600]
def run(self): def run(self) -> None:
Logger.log("d", "Auto detect baud rate started.") Logger.log("d", "Auto detect baud rate started.")
wait_response_timeouts = [3, 15, 30] wait_response_timeouts = [3, 15, 30]
wait_bootloader_times = [1.5, 5, 15] wait_bootloader_times = [1.5, 5, 15]
@ -32,7 +33,7 @@ class AutoDetectBaudJob(Job):
try: try:
programmer.connect(self._serial_port) programmer.connect(self._serial_port)
serial = programmer.leaveISP() serial = programmer.leaveISP()
except: except ispBase.IspError:
programmer.close() programmer.close()
for retry in range(tries): for retry in range(tries):
@ -58,7 +59,7 @@ class AutoDetectBaudJob(Job):
# We already have a serial connection, just change the baud rate. # We already have a serial connection, just change the baud rate.
try: try:
serial.baudrate = baud_rate serial.baudrate = baud_rate
except: except ValueError:
continue continue
sleep(wait_bootloader) # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number sleep(wait_bootloader) # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number
successful_responses = 0 successful_responses = 0
@ -81,5 +82,5 @@ class AutoDetectBaudJob(Job):
return return
serial.write(b"M105\n") serial.write(b"M105\n")
sleep(15) # Give the printer some time to init and try again. sleep(15) # Give the printer some time to init and try again.
self.setResult(None) # Unable to detect the correct baudrate. self.setResult(None) # Unable to detect the correct baudrate.