Merge branch 'master' into CURA--6683_icons_per_object_settings

This commit is contained in:
Diego Prado Gesto 2019-09-17 14:16:51 +02:00
commit 4dd6c5b03a
32 changed files with 273 additions and 193 deletions

View file

@ -269,10 +269,11 @@ class BuildVolume(SceneNode):
continue
# Mark the node as outside build volume if the set extruder is disabled
extruder_position = node.callDecoration("getActiveExtruderPosition")
if extruder_position not in self._global_container_stack.extruders:
continue
if not self._global_container_stack.extruders[extruder_position].isEnabled:
node.setOutsideBuildArea(True)
try:
if not self._global_container_stack.extruderList[int(extruder_position)].isEnabled:
node.setOutsideBuildArea(True)
continue
except IndexError:
continue
node.setOutsideBuildArea(False)
@ -319,7 +320,7 @@ class BuildVolume(SceneNode):
# Mark the node as outside build volume if the set extruder is disabled
extruder_position = node.callDecoration("getActiveExtruderPosition")
if not self._global_container_stack.extruders[extruder_position].isEnabled:
if not self._global_container_stack.extruderList[int(extruder_position)].isEnabled:
node.setOutsideBuildArea(True)
return
@ -549,7 +550,7 @@ class BuildVolume(SceneNode):
return
old_raft_thickness = self._raft_thickness
if self._global_container_stack.extruders:
if self._global_container_stack.extruderList:
# This might be called before the extruder stacks have initialised, in which case getting the adhesion_type fails
self._adhesion_type = self._global_container_stack.getProperty("adhesion_type", "value")
self._raft_thickness = 0.0
@ -1098,7 +1099,7 @@ class BuildVolume(SceneNode):
# not part of the collision radius, such as bed adhesion (skirt/brim/raft)
# and travel avoid distance.
def getEdgeDisallowedSize(self):
if not self._global_container_stack or not self._global_container_stack.extruders:
if not self._global_container_stack or not self._global_container_stack.extruderList:
return 0
container_stack = self._global_container_stack

View file

@ -660,14 +660,14 @@ class CuraApplication(QtApplication):
def discardOrKeepProfileChangesClosed(self, option: str) -> None:
global_stack = self.getGlobalContainerStack()
if option == "discard":
for extruder in global_stack.extruders.values():
for extruder in global_stack.extruderList:
extruder.userChanges.clear()
global_stack.userChanges.clear()
# if the user decided to keep settings then the user settings should be re-calculated and validated for errors
# before slicing. To ensure that slicer uses right settings values
elif option == "keep":
for extruder in global_stack.extruders.values():
for extruder in global_stack.extruderList:
extruder.userChanges.update()
global_stack.userChanges.update()
@ -1668,7 +1668,7 @@ class CuraApplication(QtApplication):
arranger = Arrange.create(x = machine_width, y = machine_depth, fixed_nodes = fixed_nodes)
min_offset = 8
default_extruder_position = self.getMachineManager().defaultExtruderPosition
default_extruder_id = self._global_container_stack.extruders[default_extruder_position].getId()
default_extruder_id = self._global_container_stack.extruderList[int(default_extruder_position)].getId()
select_models_on_load = self.getPreferences().getValue("cura/select_models_on_load")

View file

@ -67,7 +67,7 @@ class MachineErrorChecker(QObject):
self._global_stack.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
self._global_stack.containersChanged.disconnect(self.startErrorCheck)
for extruder in self._global_stack.extruders.values():
for extruder in self._global_stack.extruderList:
extruder.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.disconnect(self.startErrorCheck)
@ -77,7 +77,7 @@ class MachineErrorChecker(QObject):
self._global_stack.propertyChanged.connect(self.startErrorCheckPropertyChanged)
self._global_stack.containersChanged.connect(self.startErrorCheck)
for extruder in self._global_stack.extruders.values():
for extruder in self._global_stack.extruderList:
extruder.propertyChanged.connect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.connect(self.startErrorCheck)
@ -127,7 +127,7 @@ class MachineErrorChecker(QObject):
# Populate the (stack, key) tuples to check
self._stacks_and_keys_to_check = deque()
for stack in global_stack.extruders.values():
for stack in global_stack.extruderList:
for key in stack.getAllKeys():
self._stacks_and_keys_to_check.append((stack, key))

View file

@ -70,7 +70,12 @@ class BaseMaterialsModel(ListModel):
if self._extruder_stack is not None:
self._extruder_stack.pyqtContainersChanged.disconnect(self._update)
self._extruder_stack.approximateMaterialDiameterChanged.disconnect(self._update)
self._extruder_stack = global_stack.extruders.get(str(self._extruder_position))
try:
self._extruder_stack = global_stack.extruderList[self._extruder_position]
except IndexError:
self._extruder_stack = None
if self._extruder_stack is not None:
self._extruder_stack.pyqtContainersChanged.connect(self._update)
self._extruder_stack.approximateMaterialDiameterChanged.connect(self._update)
@ -113,12 +118,11 @@ class BaseMaterialsModel(ListModel):
if global_stack is None or not self._enabled:
return False
extruder_position = str(self._extruder_position)
if extruder_position not in global_stack.extruders:
try:
extruder_stack = global_stack.extruderList[self._extruder_position]
except IndexError:
return False
extruder_stack = global_stack.extruders[extruder_position]
self._available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
if self._available_materials is None:
return False

View file

@ -50,7 +50,7 @@ class UserChangesModel(ListModel):
return
stacks = [global_stack]
stacks.extend(global_stack.extruders.values())
stacks.extend(global_stack.extruderList)
# Check if the definition container has a translation file and ensure it's loaded.
definition = global_stack.getBottom()

View file

@ -154,8 +154,13 @@ class QualityManager(QObject):
def _updateQualityGroupsAvailability(self, machine: "GlobalStack", quality_group_list) -> None:
used_extruders = set()
for i in range(machine.getProperty("machine_extruder_count", "value")):
if str(i) in machine.extruders and machine.extruders[str(i)].isEnabled:
used_extruders.add(str(i))
try:
extruder = machine.extruderList[int(i)]
except IndexError:
pass
else:
if extruder.isEnabled:
used_extruders.add(str(i))
# Update the "is_available" flag for each quality group.
for quality_group in quality_group_list:

View file

@ -199,8 +199,6 @@ class AuthorizationService:
self._unable_to_get_data_message.hide()
self._unable_to_get_data_message = Message(i18n_catalog.i18nc("@info", "Unable to reach the Ultimaker account server."), title = i18n_catalog.i18nc("@info:title", "Warning"))
self._unable_to_get_data_message.addAction("retry", i18n_catalog.i18nc("@action:button", "Retry"), "[no_icon]", "[no_description]")
self._unable_to_get_data_message.actionTriggered.connect(self._onMessageActionTriggered)
self._unable_to_get_data_message.show()
except ValueError:
Logger.logException("w", "Could not load auth data from preferences")
@ -222,6 +220,3 @@ class AuthorizationService:
self.accessTokenChanged.emit()
def _onMessageActionTriggered(self, _, action):
if action == "retry":
self.loadAuthDataFromPreferences()

View file

@ -64,7 +64,7 @@ class PreviewPass(RenderPass):
self._shader.setUniformValue("u_ambientColor", [0.1, 0.1, 0.1, 1.0])
self._shader.setUniformValue("u_specularColor", [0.6, 0.6, 0.6, 1.0])
self._shader.setUniformValue("u_shininess", 20.0)
self._shader.setUniformValue("u_faceId", -1) # de-select any selected faces
self._shader.setUniformValue("u_faceId", -1) # Don't render any selected faces in the preview.
if not self._non_printing_shader:
if self._non_printing_shader:

View file

@ -40,8 +40,8 @@ class CuraFormulaFunctions:
global_stack = machine_manager.activeMachine
try:
extruder_stack = global_stack.extruders[str(extruder_position)]
except KeyError:
extruder_stack = global_stack.extruderList[int(extruder_position)]
except IndexError:
if extruder_position != 0:
Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. Returning the result form extruder 0 instead" % (property_key, extruder_position))
# This fixes a very specific fringe case; If a profile was created for a custom printer and one of the
@ -104,11 +104,14 @@ class CuraFormulaFunctions:
machine_manager = self._application.getMachineManager()
global_stack = machine_manager.activeMachine
extruder_stack = global_stack.extruders[str(extruder_position)]
try:
extruder_stack = global_stack.extruderList[extruder_position]
except IndexError:
Logger.log("w", "Unable to find extruder on in index %s", extruder_position)
else:
context = self.createContextForDefaultValueEvaluation(extruder_stack)
context = self.createContextForDefaultValueEvaluation(extruder_stack)
return self.getValueInExtruder(extruder_position, property_key, context = context)
return self.getValueInExtruder(extruder_position, property_key, context = context)
# Gets all default setting values as a list from all extruders of the currently active machine.
# The default values are those excluding the values in the user_changes container.

View file

@ -74,7 +74,7 @@ class ExtruderManager(QObject):
global_container_stack = self._application.getGlobalContainerStack()
if global_container_stack:
extruder_stack_ids = {position: extruder.id for position, extruder in global_container_stack.extruders.items()}
extruder_stack_ids = {extruder.getMetaDataEntry("position", ""): extruder.id for extruder in global_container_stack.extruderList}
return extruder_stack_ids
@ -360,10 +360,14 @@ class ExtruderManager(QObject):
def fixSingleExtrusionMachineExtruderDefinition(self, global_stack: "GlobalStack") -> None:
container_registry = ContainerRegistry.getInstance()
expected_extruder_definition_0_id = global_stack.getMetaDataEntry("machine_extruder_trains")["0"]
extruder_stack_0 = global_stack.extruders.get("0")
try:
extruder_stack_0 = global_stack.extruderList[0]
except IndexError:
extruder_stack_0 = None
# At this point, extruder stacks for this machine may not have been loaded yet. In this case, need to look in
# the container registry as well.
if not global_stack.extruders:
if not global_stack.extruderList:
extruder_trains = container_registry.findContainerStacks(type = "extruder_train",
machine = global_stack.getId())
if extruder_trains:

View file

@ -135,12 +135,15 @@ class ExtruderStack(CuraContainerStack):
if limit_to_extruder == -1:
limit_to_extruder = int(cura.CuraApplication.CuraApplication.getInstance().getMachineManager().defaultExtruderPosition)
limit_to_extruder = str(limit_to_extruder)
if (limit_to_extruder is not None and limit_to_extruder != "-1") and self.getMetaDataEntry("position") != str(limit_to_extruder):
if str(limit_to_extruder) in self.getNextStack().extruders:
result = self.getNextStack().extruders[str(limit_to_extruder)].getProperty(key, property_name, context)
try:
result = self.getNextStack().extruderList[int(limit_to_extruder)].getProperty(key, property_name, context)
if result is not None:
context.popContainer()
return result
except IndexError:
pass
result = super().getProperty(key, property_name, context)
context.popContainer()

View file

@ -184,7 +184,7 @@ class MachineManager(QObject):
# Create the configuration model with the current data in Cura
self._current_printer_configuration.printerType = self._global_container_stack.definition.getName()
self._current_printer_configuration.extruderConfigurations = []
for extruder in self._global_container_stack.extruders.values():
for extruder in self._global_container_stack.extruderList:
extruder_configuration = ExtruderConfigurationModel()
# For compare just the GUID is needed at this moment
mat_type = extruder.material.getMetaDataEntry("material") if extruder.material != empty_material_container else None
@ -201,7 +201,8 @@ class MachineManager(QObject):
# An empty build plate configuration from the network printer is presented as an empty string, so use "" for an
# empty build plate.
self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value") if self._global_container_stack.variant != 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._global_container_stack.getProperty("machine_buildplate_type", "default_value")
self.currentConfigurationChanged.emit()
@pyqtSlot(QObject, result = bool)
@ -294,13 +295,13 @@ class MachineManager(QObject):
## Given a global_stack, make sure that it's all valid by searching for this quality group and applying it again
def _initMachineState(self, global_stack: "CuraContainerStack") -> None:
material_dict = {}
for position, extruder in global_stack.extruders.items():
material_dict[position] = extruder.material.getMetaDataEntry("base_file")
for position, extruder in enumerate(global_stack.extruderList):
material_dict[str(position)] = extruder.material.getMetaDataEntry("base_file")
self._current_root_material_id = material_dict
# Update materials to make sure that the diameters match with the machine's
for position in global_stack.extruders:
self.updateMaterialWithVariant(position)
for position, _ in enumerate(global_stack.extruderList):
self.updateMaterialWithVariant(str(position))
global_quality = global_stack.quality
quality_type = global_quality.getMetaDataEntry("quality_type")
@ -686,7 +687,7 @@ class MachineManager(QObject):
def isCurrentSetupSupported(self) -> bool:
if not self._global_container_stack:
return False
for stack in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
for stack in [self._global_container_stack] + self._global_container_stack.extruderList:
for container in stack.getContainers():
if not container:
return False
@ -712,8 +713,8 @@ class MachineManager(QObject):
def copyAllValuesToExtruders(self) -> None:
if self._active_container_stack is None or self._global_container_stack is None:
return
extruder_stacks = list(self._global_container_stack.extruders.values())
for extruder_stack in extruder_stacks:
for extruder_stack in self._global_container_stack.extruderList:
if extruder_stack != self._active_container_stack:
for key in self._active_container_stack.userChanges.getAllKeys():
new_value = self._active_container_stack.getProperty(key, "value")
@ -843,8 +844,7 @@ class MachineManager(QObject):
return True
buildplate_compatible = True # It is compatible by default
extruder_stacks = self._global_container_stack.extruders.values()
for stack in extruder_stacks:
for stack in self._global_container_stack.extruderList:
if not stack.isEnabled:
continue
material_container = stack.material
@ -867,8 +867,8 @@ class MachineManager(QObject):
# (material_left_compatible or material_left_usable) and
# (material_right_compatible or material_right_usable)
result = not self.variantBuildplateCompatible
extruder_stacks = self._global_container_stack.extruders.values()
for stack in extruder_stacks:
for stack in self._global_container_stack.extruderList:
material_container = stack.material
if material_container == empty_material_container:
continue
@ -904,7 +904,7 @@ class MachineManager(QObject):
old_value = old_value(self._global_container_stack)
if int(old_value) < 0:
continue
if int(old_value) >= extruder_count or not self._global_container_stack.extruders[str(old_value)].isEnabled:
if int(old_value) >= extruder_count or not self._global_container_stack.extruderList[int(old_value)].isEnabled:
result.append(setting_key)
Logger.log("d", "Reset setting [%s] in [%s] because its old value [%s] is no longer valid", setting_key, container, old_value)
return result
@ -993,18 +993,21 @@ class MachineManager(QObject):
@deprecated("use Cura.MachineManager.activeMachine.extruders instead", "4.2")
def _getExtruder(self, position) -> Optional[ExtruderStack]:
if self._global_container_stack:
return self._global_container_stack.extruders.get(str(position))
try:
return self._global_container_stack.extruderList[int(position)]
except IndexError:
return None
return None
def updateDefaultExtruder(self) -> None:
if self._global_container_stack is None:
return
extruder_items = sorted(self._global_container_stack.extruders.items())
old_position = self._default_extruder_position
new_default_position = "0"
for position, extruder in extruder_items:
for extruder in self._global_container_stack.extruderList:
if extruder.isEnabled:
new_default_position = position
new_default_position = extruder.getMetaDataEntry("position", "0")
break
if new_default_position != old_position:
self._default_extruder_position = new_default_position
@ -1016,7 +1019,7 @@ class MachineManager(QObject):
definition_changes_container = self._global_container_stack.definitionChanges
machine_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
extruder_count = 0
for position, extruder in self._global_container_stack.extruders.items():
for position, extruder in enumerate(self._global_container_stack.extruderList):
if extruder.isEnabled and int(position) < machine_extruder_count:
extruder_count += 1
if self.numberExtrudersEnabled != extruder_count:
@ -1040,7 +1043,7 @@ class MachineManager(QObject):
return
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
property_names = ["value", "resolve", "validationState"]
for container in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
for container in [self._global_container_stack] + self._global_container_stack.extruderList:
for setting_key in container.getAllKeys():
container.propertiesChanged.emit(setting_key, property_names)
@ -1089,7 +1092,7 @@ class MachineManager(QObject):
def setSettingForAllExtruders(self, setting_name: str, property_name: str, property_value: str) -> None:
if self._global_container_stack is None:
return
for key, extruder in self._global_container_stack.extruders.items():
for extruder in self._global_container_stack.extruderList:
container = extruder.userChanges
container.setProperty(setting_name, property_name, property_value)
@ -1099,7 +1102,7 @@ class MachineManager(QObject):
def resetSettingForAllExtruders(self, setting_name: str) -> None:
if self._global_container_stack is None:
return
for key, extruder in self._global_container_stack.extruders.items():
for extruder in self._global_container_stack.extruderList:
container = extruder.userChanges
container.removeInstance(setting_name)
@ -1117,8 +1120,9 @@ class MachineManager(QObject):
changed = False
if self._global_container_stack:
for position in self._global_container_stack.extruders:
material_id = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file")
for extruder in self._global_container_stack.extruderList:
material_id = extruder.material.getMetaDataEntry("base_file")
position = extruder.getMetaDataEntry("position")
if position not in self._current_root_material_id or material_id != self._current_root_material_id[position]:
changed = True
self._current_root_material_id[position] = material_id
@ -1155,7 +1159,7 @@ class MachineManager(QObject):
self._current_quality_changes_group = None
self._global_container_stack.quality = empty_quality_container
self._global_container_stack.qualityChanges = empty_quality_changes_container
for extruder in self._global_container_stack.extruders.values():
for extruder in self._global_container_stack.extruderList:
extruder.quality = empty_quality_container
extruder.qualityChanges = empty_quality_changes_container
@ -1186,9 +1190,12 @@ class MachineManager(QObject):
# Set quality and quality_changes for each ExtruderStack
for position, node in quality_group.nodes_for_extruders.items():
self._global_container_stack.extruders[str(position)].quality = node.getContainer()
if empty_quality_changes:
self._global_container_stack.extruders[str(position)].qualityChanges = empty_quality_changes_container
try:
self._global_container_stack.extruderList[int(position)].quality = node.getContainer()
if empty_quality_changes:
self._global_container_stack.extruderList[int(position)].qualityChanges = empty_quality_changes_container
except IndexError:
continue # This can be ignored as in some cases the quality group gets set for an extruder that's not active (eg custom fff printer)
self.activeQualityGroupChanged.emit()
self.activeQualityChangesGroupChanged.emit()
@ -1224,7 +1231,8 @@ class MachineManager(QObject):
self._global_container_stack.quality = quality_container
self._global_container_stack.qualityChanges = quality_changes_container
for position, extruder in self._global_container_stack.extruders.items():
for extruder in self._global_container_stack.extruderList:
position = int(extruder.getMetaDataEntry("position", "0"))
quality_changes_node = quality_changes_group.nodes_for_extruders.get(position)
quality_node = None
if quality_group is not None:
@ -1248,7 +1256,7 @@ class MachineManager(QObject):
def _setVariantNode(self, position: str, container_node: "ContainerNode") -> None:
if container_node.getContainer() is None or self._global_container_stack is None:
return
self._global_container_stack.extruders[position].variant = container_node.getContainer()
self._global_container_stack.extruderList[int(position)].variant = container_node.getContainer()
self.activeVariantChanged.emit()
def _setGlobalVariant(self, container_node: "ContainerNode") -> None:
@ -1262,10 +1270,10 @@ class MachineManager(QObject):
if self._global_container_stack is None:
return
if container_node and container_node.getContainer():
self._global_container_stack.extruders[position].material = container_node.getContainer()
self._global_container_stack.extruderList[int(position)].material = container_node.getContainer()
root_material_id = container_node.getMetaDataEntry("base_file", None)
else:
self._global_container_stack.extruders[position].material = empty_material_container
self._global_container_stack.extruderList[int(position)].material = empty_material_container
root_material_id = None
# The _current_root_material_id is used in the MaterialMenu to see which material is selected
if root_material_id != self._current_root_material_id[position]:
@ -1276,7 +1284,7 @@ class MachineManager(QObject):
# Check material - variant compatibility
if self._global_container_stack is not None:
if Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False)):
for position, extruder in self._global_container_stack.extruders.items():
for extruder in self._global_container_stack.extruderList:
if not extruder.isEnabled:
continue
if not extruder.material.getMetaDataEntry("compatible"):
@ -1336,7 +1344,10 @@ class MachineManager(QObject):
buildplate_name = self._global_container_stack.variant.getName()
for position_item in position_list:
extruder = self._global_container_stack.extruders[position_item]
try:
extruder = self._global_container_stack.extruderList[int(position_item)]
except IndexError:
continue
current_material_base_name = extruder.material.getMetaDataEntry("base_file")
current_nozzle_name = None
@ -1421,7 +1432,7 @@ class MachineManager(QObject):
extruders_to_disable.add(extruder_configuration.position)
# If there's no material and/or nozzle on the printer, enable the first extruder and disable the rest.
if len(extruders_to_disable) == len(self._global_container_stack.extruders):
if len(extruders_to_disable) == len(self._global_container_stack.extruderList):
extruders_to_disable.remove(min(extruders_to_disable))
for extruder_configuration in configuration.extruderConfigurations:
@ -1429,7 +1440,7 @@ class MachineManager(QObject):
# If the machine doesn't have a hotend or material, disable this extruder
if int(position) in extruders_to_disable:
self._global_container_stack.extruders[position].setEnabled(False)
self._global_container_stack.extruderList[int(position)].setEnabled(False)
need_to_show_message = True
disabled_used_extruder_position_set.add(int(position))
@ -1445,13 +1456,13 @@ class MachineManager(QObject):
if variant_container_node:
self._setVariantNode(position, variant_container_node)
else:
self._global_container_stack.extruders[position].variant = empty_variant_container
self._global_container_stack.extruderList[int(position)].variant = empty_variant_container
if material_container_node:
self._setMaterial(position, material_container_node)
else:
self._global_container_stack.extruders[position].material = empty_material_container
self._global_container_stack.extruders[position].setEnabled(True)
self._global_container_stack.extruderList[int(position)].material = empty_material_container
self._global_container_stack.extruderList[int(position)].setEnabled(True)
self.updateMaterialWithVariant(position)
self.updateDefaultExtruder()
@ -1473,7 +1484,7 @@ class MachineManager(QObject):
# Show human-readable extruder names such as "Extruder Left", "Extruder Front" instead of "Extruder 1, 2, 3".
extruder_names = []
for extruder_position in sorted(disabled_used_extruder_position_set):
extruder_stack = self._global_container_stack.extruders[str(extruder_position)]
extruder_stack = self._global_container_stack.extruderList[int(extruder_position)]
extruder_name = extruder_stack.definition.getName()
extruder_names.append(extruder_name)
extruders_str = ", ".join(extruder_names)
@ -1504,7 +1515,7 @@ class MachineManager(QObject):
machine_definition_id = self._global_container_stack.definition.id
position = str(position)
extruder_stack = self._global_container_stack.extruders[position]
extruder_stack = self._global_container_stack.extruderList[int(position)]
nozzle_name = extruder_stack.variant.getName()
material_diameter = extruder_stack.getApproximateMaterialDiameter()
material_node = self._material_manager.getMaterialNode(machine_definition_id, nozzle_name, buildplate_name,
@ -1516,7 +1527,7 @@ class MachineManager(QObject):
@pyqtSlot(str, "QVariant")
def setMaterial(self, position: str, container_node, global_stack: Optional["GlobalStack"] = None) -> None:
if global_stack is not None and global_stack != self._global_container_stack:
global_stack.extruders[position].material = container_node.getContainer()
global_stack.extruderList[int(position)].material = container_node.getContainer()
return
position = str(position)
self.blurSettings.emit()

View file

@ -39,8 +39,8 @@ class SimpleModeSettingsManager(QObject):
user_setting_keys.update(global_stack.userChanges.getAllKeys())
# check user settings in the extruder stacks
if global_stack.extruders:
for extruder_stack in global_stack.extruders.values():
if global_stack.extruderList:
for extruder_stack in global_stack.extruderList:
user_setting_keys.update(extruder_stack.userChanges.getAllKeys())
# remove settings that are visible in recommended (we don't show the reset button for those)

View file

@ -197,11 +197,7 @@ class PrintInformation(QObject):
material_preference_values = json.loads(self._application.getInstance().getPreferences().getValue("cura/material_settings"))
extruder_stacks = global_stack.extruders
for position in extruder_stacks:
extruder_stack = extruder_stacks[position]
index = int(position)
for index, extruder_stack in enumerate(global_stack.extruderList):
if index >= len(self._material_amounts):
continue
amount = self._material_amounts[index]

View file

@ -834,9 +834,8 @@ class CuraEngineBackend(QObject, Backend):
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onSettingChanged)
self._global_container_stack.containersChanged.disconnect(self._onChanged)
extruders = list(self._global_container_stack.extruders.values())
for extruder in extruders:
for extruder in self._global_container_stack.extruderList:
extruder.propertyChanged.disconnect(self._onSettingChanged)
extruder.containersChanged.disconnect(self._onChanged)
@ -845,8 +844,8 @@ class CuraEngineBackend(QObject, Backend):
if self._global_container_stack:
self._global_container_stack.propertyChanged.connect(self._onSettingChanged) # Note: Only starts slicing when the value changed.
self._global_container_stack.containersChanged.connect(self._onChanged)
extruders = list(self._global_container_stack.extruders.values())
for extruder in extruders:
for extruder in self._global_container_stack.extruderList:
extruder.propertyChanged.connect(self._onSettingChanged)
extruder.containersChanged.connect(self._onChanged)
self._onChanged()

View file

@ -76,7 +76,9 @@ class ModelChecker(QObject, Extension):
# This function can be triggered in the middle of a machine change, so do not proceed if the machine change
# has not done yet.
if str(node_extruder_position) not in global_container_stack.extruders:
try:
extruder = global_container_stack.extruderList[int(node_extruder_position)]
except IndexError:
Application.getInstance().callLater(lambda: self.onChanged.emit())
return False
@ -131,9 +133,9 @@ class ModelChecker(QObject, Extension):
material_shrinkage = {}
# Get all shrinkage values of materials used
for extruder_position, extruder in global_container_stack.extruders.items():
for extruder_position, extruder in enumerate(global_container_stack.extruderList):
shrinkage = extruder.material.getProperty("material_shrinkage_percentage", "value")
if shrinkage is None:
shrinkage = 0
material_shrinkage[extruder_position] = shrinkage
material_shrinkage[str(extruder_position)] = shrinkage
return material_shrinkage

View file

@ -367,6 +367,8 @@ class ChangeAtZ(Script):
modified_gcode = ""
lines = active_layer.split("\n")
for line in lines:
if line.strip() == "":
continue
if ";Generated with Cura_SteamEngine" in line:
TWinstances += 1
modified_gcode += ";ChangeAtZ instances: %d\n" % TWinstances

View file

@ -57,9 +57,12 @@ class SolidView(View):
# As the rendering is called a *lot* we really, dont want to re-evaluate the property every time. So we store em!
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
support_extruder_nr = global_container_stack.getExtruderPositionValueWithDefault("support_extruder_nr")
support_angle_stack = global_container_stack.extruders.get(str(support_extruder_nr))
if support_angle_stack:
support_extruder_nr = int(global_container_stack.getExtruderPositionValueWithDefault("support_extruder_nr"))
try:
support_angle_stack = global_container_stack.extruderList[support_extruder_nr]
except IndexError:
pass
else:
self._support_angle = support_angle_stack.getProperty("support_angle", "value")
def beginRendering(self):

View file

@ -1,10 +1,11 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Dict, List, Optional
from typing import Dict, List, Optional
from PyQt5.QtCore import QTimer
from UM import i18nCatalog
from UM.Logger import Logger # To log errors talking to the API.
from UM.Signal import Signal
from cura.API import Account
from cura.CuraApplication import CuraApplication
@ -37,7 +38,7 @@ class CloudOutputDeviceManager:
# Persistent dict containing the remote clusters for the authenticated user.
self._remote_clusters = {} # type: Dict[str, CloudOutputDevice]
self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
self._api = CloudApiClient(self._account, on_error=lambda error: print(error))
self._api = CloudApiClient(self._account, on_error = lambda error: Logger.log("e", str(error)))
self._account.loginStateChanged.connect(self._onLoginStateChanged)
# Create a timer to update the remote cluster list

View file

@ -28,7 +28,7 @@ class CloudFlowMessage(Message):
lifetime=0,
dismissable=True,
option_state=False,
image_source=image_path,
image_source=QUrl.fromLocalFile(image_path),
image_caption=I18N_CATALOG.i18nc("@info:status Ultimaker Cloud should not be translated.",
"Connect to Ultimaker Cloud"),
)

View file

@ -2,7 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher.
from UM import i18nCatalog
from UM.Message import Message
from cura.CuraApplication import CuraApplication
I18N_CATALOG = i18nCatalog("cura")
@ -13,16 +13,25 @@ class CloudPrinterDetectedMessage(Message):
# Singleton used to prevent duplicate messages of this type at the same time.
__is_visible = False
# Store in preferences to hide this message in the future.
_preference_key = "cloud/block_new_printers_popup"
def __init__(self) -> None:
super().__init__(
title=I18N_CATALOG.i18nc("@info:title", "New cloud printers found"),
text=I18N_CATALOG.i18nc("@info:message", "New printers have been found connected to your account, "
"you can find them in your list of discovered printers."),
lifetime=10,
dismissable=True
lifetime=0,
dismissable=True,
option_state=False,
option_text=I18N_CATALOG.i18nc("@info:option_text", "Do not show this message again")
)
self.optionToggled.connect(self._onDontAskMeAgain)
CuraApplication.getInstance().getPreferences().addPreference(self._preference_key, False)
def show(self) -> None:
if CuraApplication.getInstance().getPreferences().getValue(self._preference_key):
return
if CloudPrinterDetectedMessage.__is_visible:
return
super().show()
@ -31,3 +40,6 @@ class CloudPrinterDetectedMessage(Message):
def hide(self, send_signal = True) -> None:
super().hide(send_signal)
CloudPrinterDetectedMessage.__is_visible = False
def _onDontAskMeAgain(self, checked: bool) -> None:
CuraApplication.getInstance().getPreferences().setValue(self._preference_key, checked)

View file

@ -1,5 +1,6 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional, Dict, List, Callable, Any
from PyQt5.QtGui import QDesktopServices
@ -8,6 +9,7 @@ from PyQt5.QtNetwork import QNetworkReply
from UM.FileHandler.FileHandler import FileHandler
from UM.i18n import i18nCatalog
from UM.Logger import Logger
from UM.Scene.SceneNode import SceneNode
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
@ -167,5 +169,5 @@ class LocalClusterOutputDevice(UltimakerNetworkedPrinterOutputDevice):
## Get the API client instance.
def _getApiClient(self) -> ClusterApiClient:
if not self._cluster_api:
self._cluster_api = ClusterApiClient(self.address, on_error=lambda error: print(error))
self._cluster_api = ClusterApiClient(self.address, on_error = lambda error: Logger.log("e", str(error)))
return self._cluster_api

View file

@ -1,5 +1,6 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Dict, Optional, Callable, List
from UM import i18nCatalog
@ -66,7 +67,7 @@ class LocalClusterOutputDeviceManager:
## Add a networked printer manually by address.
def addManualDevice(self, address: str, callback: Optional[Callable[[bool, str], None]] = None) -> None:
api_client = ClusterApiClient(address, lambda error: print(error))
api_client = ClusterApiClient(address, lambda error: Logger.log("e", str(error)))
api_client.getSystem(lambda status: self._onCheckManualDeviceResponse(address, status, callback))
## Remove a manually added networked printer.

View file

@ -475,6 +475,23 @@
}
}
},
"TrimeshReader": {
"package_info": {
"package_id": "TrimeshReader",
"package_type": "plugin",
"display_name": "Trimesh Reader",
"description": "Provides support for reading model files.",
"package_version": "1.0.0",
"sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
}
}
},
"Toolbox": {
"package_info": {
"package_id": "Toolbox",

View file

@ -1,5 +1,4 @@
{
"id": "Mark2_for_Ultimaker2",
"version": 2,
"name": "Mark2 for Ultimaker2",
"inherits": "ultimaker2_plus",

View file

@ -7563,7 +7563,7 @@
"small_feature_speed_factor":
{
"label": "Small Feature Speed",
"description": "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy.",
"description": "Small features will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy.",
"unit": "%",
"type": "float",
"default_value": 50,
@ -7575,7 +7575,7 @@
"small_feature_speed_factor_0":
{
"label": "First Layer Speed",
"description": "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhestion and accuracy.",
"description": "Small features on the first layer will be printed at this percentage of their normal print speed. Slower printing can help with adhesion and accuracy.",
"unit": "%",
"type": "float",
"default_value": 50,

View file

@ -19,13 +19,13 @@
"default_value": true
},
"machine_width": {
"default_value": 240
"default_value": 260
},
"machine_height": {
"default_value": 285
},
"machine_depth": {
"default_value": 240
"default_value": 260
},
"machine_center_is_zero": {
"default_value": true

View file

@ -107,8 +107,9 @@ Item
Cura.PrinterTypeLabel
{
id: printerTypeLabel
text: Cura.MachineManager.getAbbreviatedMachineName(section)
text: section
anchors.verticalCenter: parent.verticalCenter //One default margin above and one below.
autoFit: true
}
}

View file

@ -51,5 +51,21 @@ Button
border.color: objectItemButton.checked ? UM.Theme.getColor("primary") : "transparent"
}
TextMetrics
{
id: buttonTextMetrics
text: buttonText.text
font: buttonText.font
elide: buttonText.elide
elideWidth: buttonText.width
}
Cura.ToolTip
{
id: tooltip
tooltipText: objectItemButton.text
visible: objectItemButton.hovered && buttonTextMetrics.elidedText != buttonText.text
}
onClicked: Cura.SceneController.changeSelection(index)
}

View file

@ -72,6 +72,7 @@ Button
verticalCenter: parent.verticalCenter
}
spacing: UM.Theme.getSize("narrow_margin").width
visible: (updatePrinterTypesOnlyWhenChecked && machineSelectorButton.checked) || !updatePrinterTypesOnlyWhenChecked
Repeater
{

View file

@ -1,80 +1,82 @@
#!/usr/bin/env python
import os
import sys
import subprocess
# A quick Python implementation of unix 'where' command.
def where(exe_name: str, search_path: str = os.getenv("PATH")) -> str:
if search_path is None:
search_path = ""
paths = search_path.split(os.pathsep)
result = ""
print(" -> sys.executable location: %s" % sys.executable)
sys_exec_dir = os.path.dirname(sys.executable)
root_dir = os.path.dirname(sys_exec_dir)
paths += [sys_exec_dir,
os.path.join(root_dir, "bin"),
os.path.join(root_dir, "scripts"),
]
paths = set(paths)
for path in sorted(paths):
print(" -> Searching %s" % path)
candidate_path = os.path.join(path, exe_name)
if os.path.exists(candidate_path):
result = candidate_path
break
return result
def findModules(path):
result = []
for entry in os.scandir(path):
if entry.is_dir() and os.path.exists(os.path.join(path, entry.name, "__init__.py")):
result.append(entry.name)
return result
def main():
# Find Uranium via the PYTHONPATH var
uraniumUMPath = where("UM", os.getenv("PYTHONPATH"))
if uraniumUMPath is None:
uraniumUMPath = os.path.join("..", "Uranium")
uraniumPath = os.path.dirname(uraniumUMPath)
mypy_path_parts = [".", os.path.join(".", "plugins"), os.path.join(".", "plugins", "VersionUpgrade"),
uraniumPath, os.path.join(uraniumPath, "stubs")]
if sys.platform == "win32":
os.putenv("MYPYPATH", ";".join(mypy_path_parts))
else:
os.putenv("MYPYPATH", ":".join(mypy_path_parts))
# Mypy really needs to be run via its Python script otherwise it can't find its data files.
mypy_exe_name = "mypy.exe" if sys.platform == "win32" else "mypy"
mypy_exe_dir = where(mypy_exe_name)
mypy_module = os.path.join(os.path.dirname(mypy_exe_dir), mypy_exe_name)
print("Found mypy exe path: %s" % mypy_exe_dir)
print("Found mypy module path: %s" % mypy_module)
plugins = findModules("plugins")
plugins.sort()
mods = ["cura"] + plugins + findModules("plugins/VersionUpgrade")
for mod in mods:
print("------------- Checking module {mod}".format(**locals()))
if sys.platform == "win32":
result = subprocess.run([mypy_module, "-p", mod, "--ignore-missing-imports"])
else:
result = subprocess.run([sys.executable, mypy_module, "-p", mod, "--ignore-missing-imports"])
if result.returncode != 0:
print("\nModule {mod} failed checking. :(".format(**locals()))
return 1
else:
print("\n\nDone checking. All is good.")
return 0
if __name__ == "__main__":
sys.exit(main())
#!/usr/bin/env python
import os
import sys
import subprocess
# A quick Python implementation of unix 'where' command.
def where(exe_name: str, search_path: str = os.getenv("PATH")) -> str:
if search_path is None:
search_path = ""
paths = search_path.split(os.pathsep)
result = ""
print(" -> sys.executable location: %s" % sys.executable)
sys_exec_dir = os.path.dirname(sys.executable)
root_dir = os.path.dirname(sys_exec_dir)
paths += [sys_exec_dir,
os.path.join(root_dir, "bin"),
os.path.join(root_dir, "scripts"),
]
paths = set(paths)
for path in sorted(paths):
print(" -> Searching %s" % path)
candidate_path = os.path.join(path, exe_name)
if os.path.exists(candidate_path):
result = candidate_path
break
return result
def findModules(path):
result = []
for entry in os.scandir(path):
if entry.is_dir() and os.path.exists(os.path.join(path, entry.name, "__init__.py")):
result.append(entry.name)
return result
def main():
# Find Uranium via the PYTHONPATH var
uraniumUMPath = where("UM", os.getenv("PYTHONPATH"))
if uraniumUMPath is None:
uraniumUMPath = os.path.join("..", "Uranium")
uraniumPath = os.path.dirname(uraniumUMPath)
mypy_path_parts = [".", os.path.join(".", "plugins"), os.path.join(".", "plugins", "VersionUpgrade"),
uraniumPath, os.path.join(uraniumPath, "stubs")]
if sys.platform == "win32":
os.putenv("MYPYPATH", ";".join(mypy_path_parts))
else:
os.putenv("MYPYPATH", ":".join(mypy_path_parts))
# Mypy really needs to be run via its Python script otherwise it can't find its data files.
mypy_exe_name = "mypy.exe" if sys.platform == "win32" else "mypy"
mypy_exe_dir = where(mypy_exe_name)
mypy_module = os.path.join(os.path.dirname(mypy_exe_dir), mypy_exe_name)
print("Found mypy exe path: %s" % mypy_exe_dir)
print("Found mypy module path: %s" % mypy_module)
plugins = findModules("plugins")
plugins.sort()
mods = ["cura"] + plugins + findModules("plugins/VersionUpgrade")
success_code = 0
for mod in mods:
print("------------- Checking module {mod}".format(**locals()))
if sys.platform == "win32":
result = subprocess.run([mypy_module, "-p", mod, "--ignore-missing-imports"])
else:
result = subprocess.run([sys.executable, mypy_module, "-p", mod, "--ignore-missing-imports"])
if result.returncode != 0:
print("\nModule {mod} failed checking. :(".format(**locals()))
success_code = 1
if success_code:
print("\n\nSome modules failed checking!")
else:
print("\n\nDone checking. All is good.")
return success_code
if __name__ == "__main__":
sys.exit(main())

View file

@ -142,7 +142,7 @@ def test_resetSettingForAllExtruders(machine_manager):
extruder_2 = createMockedExtruder("extruder_2")
extruder_1.userChanges = createMockedInstanceContainer("settings_1")
extruder_2.userChanges = createMockedInstanceContainer("settings_2")
global_stack.extruders = {"1": extruder_1, "2": extruder_2}
global_stack.extruderList = [extruder_1, extruder_2]
machine_manager.resetSettingForAllExtruders("whatever")