Merge branch 'master' into CURA-6793_performance

This commit is contained in:
Ghostkeeper 2019-10-16 15:47:41 +02:00
commit c12817170c
No known key found for this signature in database
GPG key ID: 86BEF881AE2CF276
31 changed files with 537 additions and 94 deletions

View file

@ -46,6 +46,8 @@ class IntentCategoryModel(ListModel):
self.addRoleName(self.WeightRole, "weight") self.addRoleName(self.WeightRole, "weight")
self.addRoleName(self.QualitiesRole, "qualities") self.addRoleName(self.QualitiesRole, "qualities")
application = cura.CuraApplication.CuraApplication.getInstance()
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange) ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange)
ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange) ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange)
machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager() machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
@ -53,6 +55,9 @@ class IntentCategoryModel(ListModel):
machine_manager.activeVariantChanged.connect(self.update) machine_manager.activeVariantChanged.connect(self.update)
machine_manager.extruderChanged.connect(self.update) machine_manager.extruderChanged.connect(self.update)
extruder_manager = application.getExtruderManager()
extruder_manager.extrudersChanged.connect(self.update)
self.update() self.update()
## Updates the list of intents if an intent profile was added or removed. ## Updates the list of intents if an intent profile was added or removed.

View file

@ -8,6 +8,7 @@ import uuid # To generate new GUIDs for new materials.
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.Logger import Logger from UM.Logger import Logger
from UM.Signal import postponeSignals, CompressTechnique
import cura.CuraApplication # Imported like this to prevent circular imports. import cura.CuraApplication # Imported like this to prevent circular imports.
from cura.Machines.ContainerTree import ContainerTree from cura.Machines.ContainerTree import ContainerTree
@ -73,8 +74,20 @@ class MaterialManagementModel(QObject):
def removeMaterial(self, material_node: "MaterialNode") -> None: def removeMaterial(self, material_node: "MaterialNode") -> None:
container_registry = CuraContainerRegistry.getInstance() container_registry = CuraContainerRegistry.getInstance()
materials_this_base_file = container_registry.findContainersMetadata(base_file = material_node.base_file) materials_this_base_file = container_registry.findContainersMetadata(base_file = material_node.base_file)
for material_metadata in materials_this_base_file:
container_registry.removeContainer(material_metadata["id"]) # The material containers belonging to the same material file are supposed to work together. This postponeSignals()
# does two things:
# - optimizing the signal emitting.
# - making sure that the signals will only be emitted after all the material containers have been removed.
with postponeSignals(container_registry.containerRemoved, compress = CompressTechnique.CompressPerParameterValue):
# CURA-6886: Some containers may not have been loaded. If remove one material container, its material file
# will be removed. If later we remove a sub-material container which hasn't been loaded previously, it will
# crash because removeContainer() requires to load the container first, but the material file was already
# gone.
for material_metadata in materials_this_base_file:
container_registry.findInstanceContainers(id = material_metadata["id"])
for material_metadata in materials_this_base_file:
container_registry.removeContainer(material_metadata["id"])
## Creates a duplicate of a material with the same GUID and base_file ## Creates a duplicate of a material with the same GUID and base_file
# metadata. # metadata.
@ -128,15 +141,33 @@ class MaterialManagementModel(QObject):
new_container.getMetaData().update(new_metadata) new_container.getMetaData().update(new_metadata)
new_containers.append(new_container) new_containers.append(new_container)
for container_to_add in new_containers: # CURA-6863: Nodes in ContainerTree will be updated upon ContainerAdded signals, one at a time. It will use the
container_to_add.setDirty(True) # best fit material container at the time it sees one. For example, if you duplicate and get generic_pva #2,
container_registry.addContainer(container_to_add) # if the node update function sees the containers in the following order:
#
# - generic_pva #2
# - generic_pva #2_um3_aa04
#
# It will first use "generic_pva #2" because that's the best fit it has ever seen, and later "generic_pva #2_um3_aa04"
# once it sees that. Because things run in the Qt event loop, they don't happen at the same time. This means if
# between those two events, the ContainerTree will have nodes that contain invalid data.
#
# This sort fixes the problem by emitting the most specific containers first.
new_containers = sorted(new_containers, key = lambda x: x.getId(), reverse = True)
# If the duplicated material was favorite then the new material should also be added to the favorites. # Optimization. Serving the same purpose as the postponeSignals() in removeMaterial()
favorites_set = set(application.getPreferences().getValue("cura/favorite_materials").split(";")) # postpone the signals emitted when duplicating materials. This is easier on the event loop; changes the
if base_file in favorites_set: # behavior to be like a transaction. Prevents concurrency issues.
favorites_set.add(new_base_id) with postponeSignals(container_registry.containerAdded, compress=CompressTechnique.CompressPerParameterValue):
application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites_set)) for container_to_add in new_containers:
container_to_add.setDirty(True)
container_registry.addContainer(container_to_add)
# If the duplicated material was favorite then the new material should also be added to the favorites.
favorites_set = set(application.getPreferences().getValue("cura/favorite_materials").split(";"))
if base_file in favorites_set:
favorites_set.add(new_base_id)
application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites_set))
return new_base_id return new_base_id

View file

@ -2,7 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from typing import Any, cast, Dict, Optional, TYPE_CHECKING from typing import Any, cast, Dict, Optional, TYPE_CHECKING
from PyQt5.QtCore import pyqtSlot, QObject, Qt from PyQt5.QtCore import pyqtSlot, QObject, Qt, QTimer
from UM.Logger import Logger from UM.Logger import Logger
from UM.Qt.ListModel import ListModel from UM.Qt.ListModel import ListModel
@ -51,14 +51,27 @@ class QualityManagementModel(ListModel):
application = cura.CuraApplication.CuraApplication.getInstance() application = cura.CuraApplication.CuraApplication.getInstance()
container_registry = application.getContainerRegistry() container_registry = application.getContainerRegistry()
self._machine_manager = application.getMachineManager() self._machine_manager = application.getMachineManager()
self._extruder_manager = application.getExtruderManager() self._machine_manager.activeQualityGroupChanged.connect(self._onChange)
self._machine_manager.activeStackChanged.connect(self._onChange)
self._machine_manager.extruderChanged.connect(self._onChange)
self._machine_manager.globalContainerChanged.connect(self._onChange)
self._extruder_manager = application.getExtruderManager()
self._extruder_manager.extrudersChanged.connect(self._onChange)
self._machine_manager.globalContainerChanged.connect(self._update)
container_registry.containerAdded.connect(self._qualityChangesListChanged) container_registry.containerAdded.connect(self._qualityChangesListChanged)
container_registry.containerRemoved.connect(self._qualityChangesListChanged) container_registry.containerRemoved.connect(self._qualityChangesListChanged)
container_registry.containerMetaDataChanged.connect(self._qualityChangesListChanged) container_registry.containerMetaDataChanged.connect(self._qualityChangesListChanged)
self._update() self._update_timer = QTimer()
self._update_timer.setInterval(100)
self._update_timer.setSingleShot(True)
self._update_timer.timeout.connect(self._update)
self._onChange()
def _onChange(self) -> None:
self._update_timer.start()
## Deletes a custom profile. It will be gone forever. ## Deletes a custom profile. It will be gone forever.
# \param quality_changes_group The quality changes group representing the # \param quality_changes_group The quality changes group representing the

View file

@ -44,6 +44,9 @@ class QualityProfilesDropDownMenuModel(ListModel):
machine_manager.activeVariantChanged.connect(self._onChange) machine_manager.activeVariantChanged.connect(self._onChange)
machine_manager.extruderChanged.connect(self._onChange) machine_manager.extruderChanged.connect(self._onChange)
extruder_manager = application.getExtruderManager()
extruder_manager.extrudersChanged.connect(self._onChange)
self._layer_height_unit = "" # This is cached self._layer_height_unit = "" # This is cached
self._update_timer = QTimer() # type: QTimer self._update_timer = QTimer() # type: QTimer

View file

@ -1,15 +1,18 @@
# Copyright (c) 2019 Ultimaker B.V. # Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional, TYPE_CHECKING from typing import Optional, TYPE_CHECKING
from UM.Logger import Logger from UM.Logger import Logger
from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.Interfaces import ContainerInterface from UM.Settings.Interfaces import ContainerInterface
from UM.Signal import Signal from UM.Signal import Signal
from cura.Settings.cura_empty_instance_containers import empty_variant_container
from cura.Machines.ContainerNode import ContainerNode from cura.Machines.ContainerNode import ContainerNode
from cura.Machines.MaterialNode import MaterialNode from cura.Machines.MaterialNode import MaterialNode
import UM.FlameProfiler import UM.FlameProfiler
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Dict from typing import Dict
from cura.Machines.MachineNode import MachineNode from cura.Machines.MachineNode import MachineNode
@ -101,6 +104,14 @@ class VariantNode(ContainerNode):
def _materialAdded(self, container: ContainerInterface) -> None: def _materialAdded(self, container: ContainerInterface) -> None:
if container.getMetaDataEntry("type") != "material": if container.getMetaDataEntry("type") != "material":
return # Not interested. return # Not interested.
if not ContainerRegistry.getInstance().findContainersMetadata(id = container.getId()):
# CURA-6889
# containerAdded and removed signals may be triggered in the next event cycle. If a container gets added
# and removed in the same event cycle, in the next cycle, the connections should just ignore the signals.
# The check here makes sure that the container in the signal still exists.
Logger.log("d", "Got container added signal for container [%s] but it no longer exists, do nothing.",
container.getId())
return
if not self.machine.has_materials: if not self.machine.has_materials:
return # We won't add any materials. return # We won't add any materials.
material_definition = container.getMetaDataEntry("definition") material_definition = container.getMetaDataEntry("definition")
@ -111,18 +122,18 @@ class VariantNode(ContainerNode):
if base_file not in self.materials: # Completely new base file. Always better than not having a file as long as it matches our set-up. if base_file not in self.materials: # Completely new base file. Always better than not having a file as long as it matches our set-up.
if material_definition != "fdmprinter" and material_definition != self.machine.container_id: if material_definition != "fdmprinter" and material_definition != self.machine.container_id:
return return
material_variant = container.getMetaDataEntry("variant_name", "empty") material_variant = container.getMetaDataEntry("variant_name", empty_variant_container.getName())
if material_variant != "empty" and material_variant != self.variant_name: if material_variant != self.variant_name:
return return
else: # We already have this base profile. Replace the base profile if the new one is more specific. else: # We already have this base profile. Replace the base profile if the new one is more specific.
new_definition = container.getMetaDataEntry("definition") new_definition = container.getMetaDataEntry("definition")
if new_definition == "fdmprinter": if new_definition == "fdmprinter":
return # Just as unspecific or worse. return # Just as unspecific or worse.
if new_definition != self.machine.container_id: material_variant = container.getMetaDataEntry("variant_name")
if new_definition != self.machine.container_id or material_variant != self.variant_name:
return # Doesn't match this set-up. return # Doesn't match this set-up.
original_metadata = ContainerRegistry.getInstance().findContainersMetadata(id = self.materials[base_file].container_id)[0] original_metadata = ContainerRegistry.getInstance().findContainersMetadata(id = self.materials[base_file].container_id)[0]
original_variant = original_metadata.get("variant_name", "empty") if "variant_name" in original_metadata or material_variant is None:
if original_variant != "empty" or container.getMetaDataEntry("variant_name", "empty") == "empty":
return # Original was already specific or just as unspecific as the new one. return # Original was already specific or just as unspecific as the new one.
if "empty_material" in self.materials: if "empty_material" in self.materials:

View file

@ -25,9 +25,10 @@ class ExtruderConfigurationModel(QObject):
return self._position return self._position
def setMaterial(self, material: Optional[MaterialOutputModel]) -> None: def setMaterial(self, material: Optional[MaterialOutputModel]) -> None:
if self._material != material: if material is None or self._material == material:
self._material = material return
self.extruderConfigurationChanged.emit() self._material = material
self.extruderConfigurationChanged.emit()
@pyqtProperty(QObject, fset = setMaterial, notify = extruderConfigurationChanged) @pyqtProperty(QObject, fset = setMaterial, notify = extruderConfigurationChanged)
def activeMaterial(self) -> Optional[MaterialOutputModel]: def activeMaterial(self) -> Optional[MaterialOutputModel]:

View file

@ -78,6 +78,8 @@ class IntentManager(QObject):
final_intent_ids = set() # type: Set[str] final_intent_ids = set() # type: Set[str]
current_definition_id = global_stack.definition.getId() current_definition_id = global_stack.definition.getId()
for extruder_stack in global_stack.extruderList: for extruder_stack in global_stack.extruderList:
if not extruder_stack.isEnabled:
continue
nozzle_name = extruder_stack.variant.getMetaDataEntry("name") nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
material_id = extruder_stack.material.getMetaDataEntry("base_file") material_id = extruder_stack.material.getMetaDataEntry("base_file")
final_intent_ids |= {metadata["id"] for metadata in self.intentMetadatas(current_definition_id, nozzle_name, material_id) if metadata.get("quality_type") in available_quality_types} final_intent_ids |= {metadata["id"] for metadata in self.intentMetadatas(current_definition_id, nozzle_name, material_id) if metadata.get("quality_type") in available_quality_types}
@ -104,6 +106,8 @@ class IntentManager(QObject):
current_definition_id = global_stack.definition.getId() current_definition_id = global_stack.definition.getId()
final_intent_categories = set() # type: Set[str] final_intent_categories = set() # type: Set[str]
for extruder_stack in global_stack.extruderList: for extruder_stack in global_stack.extruderList:
if not extruder_stack.isEnabled:
continue
nozzle_name = extruder_stack.variant.getMetaDataEntry("name") nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
material_id = extruder_stack.material.getMetaDataEntry("base_file") material_id = extruder_stack.material.getMetaDataEntry("base_file")
final_intent_categories.update(self.intentCategories(current_definition_id, nozzle_name, material_id)) final_intent_categories.update(self.intentCategories(current_definition_id, nozzle_name, material_id))

View file

@ -1322,7 +1322,8 @@ class MachineManager(QObject):
# changed. # changed.
# \param position The extruder stack to update. If provided with None, all # \param position The extruder stack to update. If provided with None, all
# extruder stacks will be updated. # extruder stacks will be updated.
def updateMaterialWithVariant(self, position: Optional[str]) -> None: @pyqtSlot()
def updateMaterialWithVariant(self, position: Optional[str] = None) -> None:
if self._global_container_stack is None: if self._global_container_stack is None:
return return
if position is None: if position is None:
@ -1353,10 +1354,9 @@ class MachineManager(QObject):
self._setMaterial(position_item, new_material) self._setMaterial(position_item, new_material)
else: else:
# The current material is not available, find the preferred one. # The current material is not available, find the preferred one.
if position is not None: approximate_material_diameter = int(self._global_container_stack.extruderList[int(position_item)].getApproximateMaterialDiameter())
approximate_material_diameter = int(self._global_container_stack.extruderList[int(position_item)].getApproximateMaterialDiameter()) material_node = nozzle_node.preferredMaterial(approximate_material_diameter)
material_node = nozzle_node.preferredMaterial(approximate_material_diameter) self._setMaterial(position_item, material_node)
self._setMaterial(position_item, material_node)
## Given a printer definition name, select the right machine instance. In case it doesn't exist, create a new ## Given a printer definition name, select the right machine instance. In case it doesn't exist, create a new
# instance with the same network key. # instance with the same network key.

View file

@ -162,6 +162,8 @@ class PauseAtHeight(Script):
# use offset to calculate the current height: <current_height> = <current_z> - <layer_0_z> # use offset to calculate the current height: <current_height> = <current_z> - <layer_0_z>
layer_0_z = 0 layer_0_z = 0
current_z = 0 current_z = 0
current_height = 0
current_layer = 0
current_extrusion_f = 0 current_extrusion_f = 0
got_first_g_cmd_on_layer_0 = False got_first_g_cmd_on_layer_0 = False
current_t = 0 #Tracks the current extruder for tracking the target temperature. current_t = 0 #Tracks the current extruder for tracking the target temperature.
@ -263,8 +265,8 @@ class PauseAtHeight(Script):
# the nozzle) # the nozzle)
x, y = self.getNextXY(layer) x, y = self.getNextXY(layer)
prev_lines = prev_layer.split("\n") prev_lines = prev_layer.split("\n")
for line in prev_lines: for lin in prev_lines:
new_e = self.getValue(line, 'E', current_e) new_e = self.getValue(lin, "E", current_e)
if new_e != current_e: if new_e != current_e:
current_e = new_e current_e = new_e
break break

View file

@ -30,7 +30,7 @@ UM.Dialog
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
text: licenseDialog.pluginName + catalog.i18nc("@label", "This plugin contains a license.\nYou need to accept this license to install this plugin.\nDo you agree with the terms below?") text: licenseDialog.pluginName + ": " + catalog.i18nc("@label", "This plugin contains a license.\nYou need to accept this license to install this plugin.\nDo you agree with the terms below?")
wrapMode: Text.Wrap wrapMode: Text.Wrap
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View file

@ -328,7 +328,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
def _setFirmwareName(self, name): def _setFirmwareName(self, name):
new_name = re.findall(r"FIRMWARE_NAME:(.*);", str(name)) new_name = re.findall(r"FIRMWARE_NAME:(.*);", str(name))
if new_name: if new_name:
self._firmware_name = new_name[0] self._firmware_name = new_name[0]
Logger.log("i", "USB output device Firmware name: %s", self._firmware_name) Logger.log("i", "USB output device Firmware name: %s", self._firmware_name)
else: else:

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Quick
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = smooth
quality_type = draft
material = generic_abs
variant = AA 0.4
[values]
speed_infill = =speed_print
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
speed_layer_0 = 20
top_bottom_thickness = =wall_thickness
wall_thickness = =line_width * 2
fill_perimeter_gaps = nowhere
infill_sparse_density = 15
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
wall_line_width_x = =line_width

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Accurate
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = engineering
quality_type = fast
material = generic_abs
variant = AA 0.4
[values]
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3
xy_offset = =- layer_height * 0.2

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Accurate
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = engineering
quality_type = normal
material = generic_abs
variant = AA 0.4
[values]
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3
xy_offset = =- layer_height * 0.2

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Quick
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = smooth
quality_type = draft
material = generic_pla
variant = AA 0.4
[values]
speed_infill = =speed_print
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
speed_layer_0 = 20
top_bottom_thickness = =wall_thickness
wall_thickness = =line_width * 2
fill_perimeter_gaps = nowhere
infill_sparse_density = 15
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
wall_line_width_x = =line_width

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Accurate
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = engineering
quality_type = fast
material = generic_pla
variant = AA 0.4
[values]
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3
xy_offset = =- layer_height * 0.2

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Accurate
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = engineering
quality_type = normal
material = generic_pla
variant = AA 0.4
[values]
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3
xy_offset = =- layer_height * 0.2

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Quick
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = smooth
quality_type = draft
material = generic_tough_pla
variant = AA 0.4
[values]
speed_infill = =speed_print
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
speed_layer_0 = 20
top_bottom_thickness = =wall_thickness
wall_thickness = =line_width * 2
fill_perimeter_gaps = nowhere
infill_sparse_density = 15
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
wall_line_width_x = =line_width

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Accurate
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = engineering
quality_type = fast
material = generic_tough_pla
variant = AA 0.4
[values]
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3
xy_offset = =- layer_height * 0.2

View file

@ -0,0 +1,34 @@
[general]
version = 4
name = Accurate
definition = ultimaker_s5
[metadata]
setting_version = 10
type = intent
intent_category = engineering
quality_type = normal
material = generic_tough_pla
variant = AA 0.4
[values]
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3
xy_offset = =- layer_height * 0.2

View file

@ -19,6 +19,7 @@ Item
property alias color: label.color property alias color: label.color
property alias text: label.text property alias text: label.text
property alias font: label.font property alias font: label.font
property alias elide: label.elide
property real margin: UM.Theme.getSize("narrow_margin").width property real margin: UM.Theme.getSize("narrow_margin").width
// These properties can be used in combination with layouts. // These properties can be used in combination with layouts.

View file

@ -13,8 +13,12 @@ Menu
title: catalog.i18nc("@label:category menu label", "Material") title: catalog.i18nc("@label:category menu label", "Material")
property int extruderIndex: 0 property int extruderIndex: 0
property var currentRootMaterialId: Cura.MachineManager.currentRootMaterialId[extruderIndex] property string currentRootMaterialId: Cura.MachineManager.currentRootMaterialId[extruderIndex]
property string activeMaterialId: Cura.MachineManager.activeMachine.extruderList[extruderIndex] ? Cura.MachineManager.activeMachine.extruderList[extruderIndex].material.id : "" property string activeMaterialId:
{
var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex]
return (extruder === undefined) ? "" : extruder.material.id
}
property bool updateModels: true property bool updateModels: true
Cura.FavoriteMaterialsModel Cura.FavoriteMaterialsModel
{ {
@ -73,7 +77,11 @@ Menu
{ {
text: model.name text: model.name
checkable: true checkable: true
enabled: Cura.MachineManager.activeMachine.extruderList[extruderIndex].isEnabled enabled:
{
var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex]
return (extruder === undefined) ? false : extruder.isEnabled
}
checked: model.root_material_id === menu.currentRootMaterialId checked: model.root_material_id === menu.currentRootMaterialId
exclusiveGroup: group exclusiveGroup: group
onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node)
@ -112,7 +120,11 @@ Menu
{ {
text: model.name text: model.name
checkable: true checkable: true
enabled: Cura.MachineManager.activeMachine.extruderList[extruderIndex].isEnabled enabled:
{
var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex]
return (extruder === undefined) ? false : extruder.isEnabled
}
checked: model.id === menu.activeMaterialId checked: model.id === menu.activeMaterialId
exclusiveGroup: group exclusiveGroup: group
onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node)

View file

@ -29,10 +29,14 @@ Menu
checkable: true checkable: true
checked: { checked: {
var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex] var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex]
return extruder.variant.name == model.hotend_name return (extruder === undefined) ? false : (extruder.variant.name == model.hotend_name)
} }
exclusiveGroup: group exclusiveGroup: group
enabled: Cura.MachineManager.activeMachine.extruderList[extruderIndex].isEnabled enabled:
{
var extruder = Cura.MachineManager.activeMachine.extruderList[extruderIndex]
return (extruder === undefined) ? false : extruder.isEnabled
}
onTriggered: { onTriggered: {
Cura.MachineManager.setVariant(menu.extruderIndex, model.container_node); Cura.MachineManager.setVariant(menu.extruderIndex, model.container_node);
} }

View file

@ -64,8 +64,10 @@ Item
height: childrenRect.height height: childrenRect.height
Label { Label {
width: parent.width
text: materialProperties.name text: materialProperties.name
font: UM.Theme.getFont("large_bold") font: UM.Theme.getFont("large_bold")
elide: Text.ElideRight
} }
} }

View file

@ -114,7 +114,7 @@ Item
if (base.toActivateNewMaterial) if (base.toActivateNewMaterial)
{ {
var position = Cura.ExtruderManager.activeExtruderIndex var position = Cura.ExtruderManager.activeExtruderIndex
Cura.MachineManager.setMaterial(position, base.currentItem.container_node) Cura.MachineManager.setMaterialById(position, base.newRootMaterialIdToSwitchTo)
} }
base.newRootMaterialIdToSwitchTo = "" base.newRootMaterialIdToSwitchTo = ""
base.toActivateNewMaterial = false base.toActivateNewMaterial = false

View file

@ -21,6 +21,7 @@ Item
property var colorsModel: materialType != null ? materialType.colors: null property var colorsModel: materialType != null ? materialType.colors: null
height: childrenRect.height height: childrenRect.height
width: parent.width width: parent.width
anchors.left: parent.left
Rectangle Rectangle
{ {
id: material_type_header_background id: material_type_header_background

View file

@ -111,6 +111,8 @@ TabView
{ {
base.setMetaDataEntry("approximate_diameter", old_approximate_diameter_value, getApproximateDiameter(new_diameter_value).toString()); base.setMetaDataEntry("approximate_diameter", old_approximate_diameter_value, getApproximateDiameter(new_diameter_value).toString());
base.setMetaDataEntry("properties/diameter", properties.diameter, new_diameter_value); base.setMetaDataEntry("properties/diameter", properties.diameter, new_diameter_value);
// CURA-6868 Make sure to update the extruder to user a diameter-compatible material.
Cura.MachineManager.updateMaterialWithVariant()
base.resetSelectedMaterial() base.resetSelectedMaterial()
} }

View file

@ -4,6 +4,7 @@
import QtQuick 2.10 import QtQuick 2.10
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
import QtQuick.Controls 1.4 as OldControls import QtQuick.Controls 1.4 as OldControls
import QtQuick.Layouts 1.3
import UM 1.3 as UM import UM 1.3 as UM
import Cura 1.6 as Cura import Cura 1.6 as Cura
@ -66,7 +67,6 @@ Item
{ {
id: intentSelection id: intentSelection
onClicked: menu.opened ? menu.close() : menu.open() onClicked: menu.opened ? menu.close() : menu.open()
text: generateActiveQualityText()
anchors.right: parent.right anchors.right: parent.right
width: UM.Theme.getSize("print_setup_big_item").width width: UM.Theme.getSize("print_setup_big_item").width
@ -75,18 +75,67 @@ Item
baselineOffset: null // If we don't do this, there is a binding loop. WHich is a bit weird, since we override the contentItem anyway... baselineOffset: null // If we don't do this, there is a binding loop. WHich is a bit weird, since we override the contentItem anyway...
contentItem: Label contentItem: RowLayout
{ {
id: textLabel spacing: 0
text: intentSelection.text
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
anchors.left: parent.left anchors.left: parent.left
anchors.right: customisedSettings.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.verticalCenter: intentSelection.verticalCenter
height: contentHeight Label
verticalAlignment: Text.AlignVCenter {
renderType: Text.NativeRendering id: textLabel
text: Cura.MachineManager.activeQualityDisplayNameMap["main"]
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
Layout.margins: 0
Layout.maximumWidth: Math.floor(parent.width * 0.7) // Always leave >= 30% for the rest of the row.
height: contentHeight
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
elide: Text.ElideRight
}
Label
{
text: activeQualityDetailText()
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_detail")
Layout.margins: 0
Layout.fillWidth: true
height: contentHeight
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
elide: Text.ElideRight
function activeQualityDetailText()
{
var resultMap = Cura.MachineManager.activeQualityDisplayNameMap
var resultSuffix = resultMap["suffix"]
var result = ""
if (Cura.MachineManager.isActiveQualityExperimental)
{
resultSuffix += " (Experimental)"
}
if (Cura.MachineManager.isActiveQualitySupported)
{
if (Cura.MachineManager.activeQualityLayerHeight > 0)
{
if (resultSuffix)
{
result += " - " + resultSuffix
}
result += " - "
result += Cura.MachineManager.activeQualityLayerHeight + "mm"
}
}
return result
}
}
} }
background: Rectangle background: Rectangle
@ -98,46 +147,6 @@ Item
color: UM.Theme.getColor("main_background") color: UM.Theme.getColor("main_background")
} }
function generateActiveQualityText()
{
var resultMap = Cura.MachineManager.activeQualityDisplayNameMap
var resultMain = resultMap["main"]
var resultSuffix = resultMap["suffix"]
var result = ""
if (Cura.MachineManager.isActiveQualityExperimental)
{
resultSuffix += " (Experimental)"
}
if (Cura.MachineManager.isActiveQualityCustom)
{
result = resultMain
}
if (Cura.MachineManager.isActiveQualitySupported)
{
if (Cura.MachineManager.activeQualityLayerHeight > 0)
{
result = resultMain
if (resultSuffix)
{
result += " - "
}
result += "<font color=\"" + UM.Theme.getColor("text_detail") + "\">"
if (resultSuffix)
{
result += resultSuffix
}
result += " - "
result += Cura.MachineManager.activeQualityLayerHeight + "mm"
result += "</font>"
}
}
return result
}
UM.SimpleButton UM.SimpleButton
{ {
id: customisedSettings id: customisedSettings
@ -169,7 +178,6 @@ Item
{ {
id: downArrow id: downArrow
source: UM.Theme.getIcon("arrow_bottom") source: UM.Theme.getIcon("arrow_bottom")
width: UM.Theme.getSize("standard_arrow").width width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height height: UM.Theme.getSize("standard_arrow").height

View file

@ -37,6 +37,7 @@ RowLayout
return "" return ""
} }
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")
elide: Text.ElideMiddle
UM.SettingPropertyProvider UM.SettingPropertyProvider
{ {

View file

@ -20,29 +20,64 @@ Row
{ {
iconSource: UM.Theme.getIcon("view_3d") iconSource: UM.Theme.getIcon("view_3d")
onClicked: Cura.Actions.view3DCamera.trigger() onClicked: Cura.Actions.view3DCamera.trigger()
UM.TooltipArea
{
anchors.fill: parent
text: catalog.i18nc("@info:tooltip", "3D View")
acceptedButtons: Qt.NoButton
}
} }
ViewOrientationButton ViewOrientationButton
{ {
iconSource: UM.Theme.getIcon("view_front") iconSource: UM.Theme.getIcon("view_front")
onClicked: Cura.Actions.viewFrontCamera.trigger() onClicked: Cura.Actions.viewFrontCamera.trigger()
UM.TooltipArea
{
anchors.fill: parent
text: catalog.i18nc("@info:tooltip", "Front View")
acceptedButtons: Qt.NoButton
}
} }
ViewOrientationButton ViewOrientationButton
{ {
iconSource: UM.Theme.getIcon("view_top") iconSource: UM.Theme.getIcon("view_top")
onClicked: Cura.Actions.viewTopCamera.trigger() onClicked: Cura.Actions.viewTopCamera.trigger()
UM.TooltipArea
{
anchors.fill: parent
text: catalog.i18nc("@info:tooltip", "Top View")
acceptedButtons: Qt.NoButton
}
} }
ViewOrientationButton ViewOrientationButton
{ {
iconSource: UM.Theme.getIcon("view_left") iconSource: UM.Theme.getIcon("view_left")
onClicked: Cura.Actions.viewLeftSideCamera.trigger() onClicked: Cura.Actions.viewLeftSideCamera.trigger()
UM.TooltipArea
{
anchors.fill: parent
text: catalog.i18nc("@info:tooltip", "Left View")
acceptedButtons: Qt.NoButton
}
} }
ViewOrientationButton ViewOrientationButton
{ {
iconSource: UM.Theme.getIcon("view_right") iconSource: UM.Theme.getIcon("view_right")
onClicked: Cura.Actions.viewRightSideCamera.trigger() onClicked: Cura.Actions.viewRightSideCamera.trigger()
UM.TooltipArea
{
anchors.fill: parent
text: catalog.i18nc("@info:tooltip", "Right View")
acceptedButtons: Qt.NoButton
}
} }
} }

View file

@ -104,10 +104,11 @@ def test_variantNodeInit_excludedMaterial(container_registry, machine_node):
def test_materialAdded(container_registry, machine_node, metadata, material_result_list): def test_materialAdded(container_registry, machine_node, metadata, material_result_list):
variant_node = createVariantNode("machine_1", machine_node, container_registry) variant_node = createVariantNode("machine_1", machine_node, container_registry)
machine_node.exclude_materials = ["material_3"] machine_node.exclude_materials = ["material_3"]
with patch("cura.Machines.VariantNode.MaterialNode"): # We're not testing the material node here, so patch it out. with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value = container_registry)):
with patch.dict(metadata_dict, metadata): with patch("cura.Machines.VariantNode.MaterialNode"): # We're not testing the material node here, so patch it out.
mocked_container = createMockedInstanceContainer() with patch.dict(metadata_dict, metadata):
variant_node._materialAdded(mocked_container) mocked_container = createMockedInstanceContainer()
variant_node._materialAdded(mocked_container)
assert len(material_result_list) == len(variant_node.materials) assert len(material_result_list) == len(variant_node.materials)
for name in material_result_list: for name in material_result_list: