Merge branch 'refactoring_machine_manager' into feature_enable_disable_extruder

This commit is contained in:
Jack Ha 2018-03-01 13:14:10 +01:00
commit ac76d6ea52
29 changed files with 567 additions and 463 deletions

View file

@ -1,9 +1,12 @@
<!--
The following template is useful for filing new issues. Processing an issue will go much faster when this is filled out.
Before filing, please check if the issue already exists (either open or closed).
The following template is useful for filing new issues. Processing an issue will go much faster when this is filled out, and issues which do not use this template will be removed.
It is also helpful to attach a project (.3MF) file and Cura log file so we can debug issues quicker.
Information about how to find the log file can be found at https://github.com/Ultimaker/Cura/wiki/Cura-Preferences-and-Settings-Locations.
Before filing, PLEASE check if the issue already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment.
Also, please note the application version in the title of the issue. For example: "[3.2.1] Cannot connect to 3rd-party printer". Please do not write thigns like "Request:" or "[BUG]" in the title; this is what labels are for.
It is also helpful to attach a project (.3mf or .curaproject) file and Cura log file so we can debug issues quicker.
Information about how to find the log file can be found at https://github.com/Ultimaker/Cura/wiki/Cura-Preferences-and-Settings-Locations. To upload a project, we recommend http://wetransfer.com, but other file hosts like Google Drive or Dropbox work well too.
Thank you for using Cura!
-->

View file

@ -62,7 +62,10 @@ from cura.Machines.Models.CustomQualityProfilesModel import CustomQualityProfile
from cura.Machines.Models.Other.MultiBuildPlateModel import MultiBuildPlateModel
from cura.Machines.Models.MaterialsModel import BrandMaterialsModel, GenericMaterialsModel, MaterialsModel
from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel
from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel
from cura.Machines.Models.BrandMaterialsModel import BrandMaterialsModel
from cura.Settings.SettingInheritanceManager import SettingInheritanceManager
from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager
@ -954,7 +957,7 @@ class CuraApplication(QtApplication):
qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel")
qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel")
qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel")
qmlRegisterType(MaterialManagementModel, "Cura", 1, 0, "MaterialManagementModel")
qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
qmlRegisterSingletonType(QualityProfilesModel, "Cura", 1, 0, "QualityProfilesModel", self.getQualityProfileModel)
@ -1046,7 +1049,7 @@ class CuraApplication(QtApplication):
count = 0
scene_bounding_box = None
is_block_slicing_node = False
active_build_plate = self._multi_build_plate_model.activeBuildPlate
active_build_plate = self.getMultiBuildPlateModel().activeBuildPlate
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if (
not issubclass(type(node), CuraSceneNode) or
@ -1295,7 +1298,7 @@ class CuraApplication(QtApplication):
@pyqtSlot()
def arrangeAll(self):
nodes = []
active_build_plate = self._multi_build_plate_model.activeBuildPlate
active_build_plate = self.getMultiBuildPlateModel().activeBuildPlate
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if not isinstance(node, SceneNode):
continue
@ -1444,7 +1447,7 @@ class CuraApplication(QtApplication):
group_decorator = GroupDecorator()
group_node.addDecorator(group_decorator)
group_node.addDecorator(ConvexHullDecorator())
group_node.addDecorator(BuildPlateDecorator(self._multi_build_plate_model.activeBuildPlate))
group_node.addDecorator(BuildPlateDecorator(self.getMultiBuildPlateModel().activeBuildPlate))
group_node.setParent(self.getController().getScene().getRoot())
group_node.setSelectable(True)
center = Selection.getSelectionCenter()
@ -1589,7 +1592,7 @@ class CuraApplication(QtApplication):
arrange_objects_on_load = (
not Preferences.getInstance().getValue("cura/use_multi_build_plate") or
not Preferences.getInstance().getValue("cura/not_arrange_objects_on_load"))
target_build_plate = self._multi_build_plate_model.activeBuildPlate if arrange_objects_on_load else -1
target_build_plate = self.getMultiBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1
root = self.getController().getScene().getRoot()
fixed_nodes = []

View file

@ -1,35 +0,0 @@
from typing import List, Optional
from PyQt5.Qt import QObject, pyqtSlot
from cura.Machines.ContainerNode import ContainerNode
class ContainerGroup(QObject):
def __init__(self, name: str, parent = None):
super().__init__(parent)
self.name = name
self.node_for_global = None # type: Optional[ContainerNode]
self.nodes_for_extruders = dict()
@pyqtSlot(result = str)
def getName(self) -> str:
return self.name
def getAllKeys(self) -> set:
result = set()
for node in [self.node_for_global] + list(self.nodes_for_extruders.values()):
if node is None:
continue
for key in node.getContainer().getAllKeys():
result.add(key)
return result
def getAllNodes(self) -> List[ContainerNode]:
result = []
if self.node_for_global is not None:
result.append(self.node_for_global)
for extruder_node in self.nodes_for_extruders.values():
result.append(extruder_node)
return result

View file

@ -1,3 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
from collections import OrderedDict

View file

@ -1,25 +0,0 @@
from UM.Util import parseBool
#
# Gets the machine definition ID that can be used to search for Quality containers that are suitable for the given
# machine. The rule is as follows:
# 1. By default, the machine definition ID for quality container search will be "fdmprinter", which is the generic
# machine.
# 2. If a machine has its own machine quality (with "has_machine_quality = True"), we should use the given machine's
# own machine definition ID for quality search.
# Example: for an Ultimaker 3, the definition ID should be "ultimaker3".
# 3. When condition (2) is met, AND the machine has "quality_definition" defined in its definition file, then the
# definition ID specified in "quality_definition" should be used.
# Example: for an Ultimaker 3 Extended, it has "quality_definition = ultimaker3". This means Ultimaker 3 Extended
# shares the same set of qualities profiles as Ultimaker 3.
#
def getMachineDefinitionIDForQualitySearch(machine: "GlobalStack", default_definition_id: str = "fdmprinter") -> str:
machine_definition_id = default_definition_id
if parseBool(machine.getMetaDataEntry("has_machine_quality", False)):
# Only use the machine's own quality definition ID if this machine has machine quality.
machine_definition_id = machine.getMetaDataEntry("quality_definition")
if machine_definition_id is None:
machine_definition_id = machine.definition.getId()
return machine_definition_id

View file

@ -0,0 +1,25 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
#
# A MaterialGroup represents a group of material InstanceContainers that are derived from a single material profile.
# The main InstanceContainer which has the ID of the material profile file name is called the "root_material". For
# example: "generic_abs" is the root material (ID) of "generic_abs_ultimaker3" and "generic_abs_ultimaker3_AA_0.4",
# and "generic_abs_ultimaker3" and "generic_abs_ultimaker3_AA_0.4" are derived materials of "generic_abs".
#
# Using "generic_abs" as an example, the MaterialGroup for "generic_abs" will contain the following information:
# - name: "generic_abs", root_material_id
# - root_material_node: MaterialNode of "generic_abs"
# - derived_material_node_list: A list of MaterialNodes that are derived from "generic_abs",
# so "generic_abs_ultimaker3", "generic_abs_ultimaker3_AA_0.4", etc.
#
class MaterialGroup:
__slots__ = ("name", "root_material_node", "derived_material_node_list")
def __init__(self, name: str):
self.name = name
self.root_material_node = None
self.derived_material_node_list = []
def __str__(self) -> str:
return "%s[%s]" % (self.__class__.__name__, self.name)

View file

@ -1,3 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from collections import defaultdict, OrderedDict
from typing import Optional
@ -6,30 +9,20 @@ from PyQt5.Qt import QTimer, QObject, pyqtSignal
from UM.Logger import Logger
from UM.Settings import ContainerRegistry
from cura.Machines.ContainerNode import ContainerNode
class MaterialGroup:
__slots__ = ("name", "root_material_node", "derived_material_node_list")
def __init__(self, name: str):
self.name = name
self.root_material_node = None
self.derived_material_node_list = []
def __str__(self) -> str:
return "%s[%s]" % (self.__class__.__name__, self.name)
class MaterialNode(ContainerNode):
__slots__ = ("material_map", "children_map")
def __init__(self, metadata: Optional[dict] = None):
super().__init__(metadata = metadata)
self.material_map = {}
self.children_map = {}
from .MaterialNode import MaterialNode
from .MaterialGroup import MaterialGroup
#
# MaterialManager maintains a number of maps and trees for material lookup.
# The models GUI and QML use are now only dependent on the MaterialManager. That means as long as the data in
# MaterialManager gets updated correctly, the GUI models should be updated correctly too, and the same goes for GUI.
#
# For now, updating the lookup maps and trees here is very simple: we discard the old data completely and recreate them
# again. This means the update is exactly the same as initialization. There are performance concerns about this approach
# but so far the creation of the tables and maps is very fast and there is no noticeable slowness, we keep it like this
# because it's simple.
#
class MaterialManager(QObject):
materialsUpdated = pyqtSignal() # Emitted whenever the material lookup tables are updated.
@ -40,12 +33,12 @@ class MaterialManager(QObject):
self._fallback_materials_map = dict() # material_type -> generic material metadata
self._material_group_map = dict() # root_material_id -> MaterialGroup
self._diameter_machine_variant_material_map = dict() # diameter -> dict(machine_definition_id -> MaterialNode)
self._diameter_machine_variant_material_map = dict() # approximate diameter str -> dict(machine_definition_id -> MaterialNode)
# We're using these two maps to convert between the specific diameter material id and the generic material id
# because the generic material ids are used in qualities and definitions, while the specific diameter material is meant
# i.e. generic_pla -> generic_pla_175
self._material_diameter_map = defaultdict(dict) # root_material_id -> diameter -> root_material_id for that diameter
self._material_diameter_map = defaultdict(dict) # root_material_id -> approximate diameter str -> root_material_id for that diameter
self._diameter_material_map = dict() # material id including diameter (generic_pla_175) -> material root id (generic_pla)
# This is used in Legacy UM3 send material function and the material management page.
@ -56,6 +49,9 @@ class MaterialManager(QObject):
self._default_machine_definition_id = "fdmprinter"
self._default_approximate_diameter_for_quality_search = "3"
# When a material gets added/imported, there can be more than one InstanceContainers. In those cases, we don't
# want to react on every container/metadata changed signal. The timer here is to buffer it a bit so we don't
# react too many time.
self._update_timer = QTimer(self)
self._update_timer.setInterval(300)
self._update_timer.setSingleShot(True)
@ -233,7 +229,8 @@ class MaterialManager(QObject):
#
# Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup.
#
def getAvailableMaterials(self, machine_definition_id: str, variant_name: Optional[str], diameter: float) -> dict:
def getAvailableMaterials(self, machine_definition_id: str, extruder_variant_name: Optional[str],
diameter: float) -> dict:
# round the diameter to get the approximate diameter
rounded_diameter = str(round(diameter))
if rounded_diameter not in self._diameter_machine_variant_material_map:
@ -245,8 +242,8 @@ class MaterialManager(QObject):
machine_node = machine_variant_material_map.get(machine_definition_id)
default_machine_node = machine_variant_material_map.get(self._default_machine_definition_id)
variant_node = None
if variant_name is not None and machine_node is not None:
variant_node = machine_node.getChildNode(variant_name)
if extruder_variant_name is not None and machine_node is not None:
variant_node = machine_node.getChildNode(extruder_variant_name)
nodes_to_check = [variant_node, machine_node, default_machine_node]
@ -269,7 +266,8 @@ class MaterialManager(QObject):
# 1. the given machine doesn't have materials;
# 2. cannot find any material InstanceContainers with the given settings.
#
def getMaterialNode(self, machine_definition_id: str, variant_name: Optional[str], diameter: float, root_material_id: str) -> Optional["InstanceContainer"]:
def getMaterialNode(self, machine_definition_id: str, extruder_variant_name: Optional[str],
diameter: float, root_material_id: str) -> Optional["InstanceContainer"]:
# round the diameter to get the approximate diameter
rounded_diameter = str(round(diameter))
if rounded_diameter not in self._diameter_machine_variant_material_map:
@ -285,8 +283,8 @@ class MaterialManager(QObject):
# Fallback for "fdmprinter" if the machine-specific materials cannot be found
if machine_node is None:
machine_node = machine_variant_material_map.get(self._default_machine_definition_id)
if machine_node is not None and variant_name is not None:
variant_node = machine_node.getChildNode(variant_name)
if machine_node is not None and extruder_variant_name is not None:
variant_node = machine_node.getChildNode(extruder_variant_name)
# Fallback mechanism of finding materials:
# 1. variant-specific material
@ -309,10 +307,15 @@ class MaterialManager(QObject):
# For materials such as ultimaker_pla_orange, no quality profiles may be found, so we should fall back to use
# the generic material IDs to search for qualities.
#
# An example would be, suppose we have machine with preferred material set to "filo3d_pla" (1.75mm), but its
# extruders only use 2.85mm materials, then we won't be able to find the preferred material for this machine.
# A fallback would be to fetch a generic material of the same type "PLA" as "filo3d_pla", and in this case it will
# be "generic_pla". This function is intended to get a generic fallback material for the given material type.
#
# This function returns the generic root material ID for the given material type, where material types are "PLA",
# "ABS", etc.
#
def getFallbackMaterialId(self, material_type: str) -> str:
def getFallbackMaterialIdByMaterialType(self, material_type: str) -> str:
# For safety
if material_type not in self._fallback_materials_map:
Logger.log("w", "The material type [%s] does not have a fallback material" % material_type)

View file

@ -0,0 +1,21 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
from .ContainerNode import ContainerNode
#
# A MaterialNode is a node in the material lookup tree/map/table. It contains 2 (extra) fields:
# - material_map: a one-to-one map of "material_root_id" to material_node.
# - children_map: the key-value map for child nodes of this node. This is used in a lookup tree.
#
#
class MaterialNode(ContainerNode):
__slots__ = ("material_map", "children_map")
def __init__(self, metadata: Optional[dict] = None):
super().__init__(metadata = metadata)
self.material_map = {} # material_root_id -> material_node
self.children_map = {} # mapping for the child nodes

View file

@ -0,0 +1,70 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
from UM.Logger import Logger
from UM.Qt.ListModel import ListModel
def getAvailableMaterials(extruder_position: Optional[int] = None):
from cura.CuraApplication import CuraApplication
machine_manager = CuraApplication.getInstance().getMachineManager()
extruder_manager = CuraApplication.getInstance().getExtruderManager()
material_manager = CuraApplication.getInstance().getMaterialManager()
active_global_stack = machine_manager.activeMachine
extruder_stack = extruder_manager.getActiveExtruderStack()
if extruder_position is not None:
if active_global_stack is not None:
extruder_stack = active_global_stack.extruders.get(str(extruder_position))
if active_global_stack is None or extruder_stack is None:
Logger.log("d", "Active global stack [%s] or extruder stack [%s] is None, setting material list to empty.",
active_global_stack, extruder_stack)
return
machine_definition_id = active_global_stack.definition.getId()
variant_name = None
if extruder_stack.variant.getId() != "empty_variant":
variant_name = extruder_stack.variant.getName()
diameter = extruder_stack.approximateMaterialDiameter
# Fetch the available materials (ContainerNode) for the current active machine and extruder setup.
result_dict = material_manager.getAvailableMaterials(machine_definition_id, variant_name, diameter)
return result_dict
class BaseMaterialsModel(ListModel):
RootMaterialIdRole = Qt.UserRole + 1
IdRole = Qt.UserRole + 2
NameRole = Qt.UserRole + 3
BrandRole = Qt.UserRole + 4
MaterialRole = Qt.UserRole + 5
ColorRole = Qt.UserRole + 6
ContainerNodeRole = Qt.UserRole + 7
extruderPositionChanged = pyqtSignal()
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.RootMaterialIdRole, "root_material_id")
self.addRoleName(self.IdRole, "id")
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.BrandRole, "brand")
self.addRoleName(self.MaterialRole, "material")
self.addRoleName(self.ColorRole, "color_name")
self.addRoleName(self.ContainerNodeRole, "container_node")
self._extruder_position = 0
def setExtruderPosition(self, position: int):
if self._extruder_position != position:
self._extruder_position = position
self.extruderPositionChanged.emit()
@pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged)
def extruderPosition(self) -> int:
return self._extruder_positoin

View file

@ -0,0 +1,112 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
from UM.Qt.ListModel import ListModel
from .BaseMaterialsModel import BaseMaterialsModel, getAvailableMaterials
class MaterialsModelGroupedByType(ListModel):
NameRole = Qt.UserRole + 1
ColorsRole = Qt.UserRole + 2
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.ColorsRole, "colors")
## Brand --> Material Type -> list of materials
class BrandMaterialsModel(ListModel):
NameRole = Qt.UserRole + 1
MaterialsRole = Qt.UserRole + 2
extruderPositionChanged = pyqtSignal()
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.MaterialsRole, "materials")
self._extruder_position = 0
from cura.CuraApplication import CuraApplication
self._machine_manager = CuraApplication.getInstance().getMachineManager()
extruder_manager = CuraApplication.getInstance().getExtruderManager()
material_manager = CuraApplication.getInstance().getMaterialManager()
self._machine_manager.globalContainerChanged.connect(self._update)
extruder_manager.activeExtruderChanged.connect(self._update)
material_manager.materialsUpdated.connect(self._update)
self._update()
def setExtruderPosition(self, position: int):
if self._extruder_position != position:
self._extruder_position = position
self.extruderPositionChanged.emit()
@pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged)
def extruderPosition(self) -> int:
return self._extruder_position
def _update(self):
global_stack = self._machine_manager.activeMachine
if global_stack is None:
self.setItems([])
return
result_dict = getAvailableMaterials(self._extruder_position)
if result_dict is None:
self.setItems([])
return
brand_item_list = []
brand_group_dict = {}
for root_material_id, container_node in result_dict.items():
metadata = container_node.metadata
brand = metadata["brand"]
# Only add results for generic materials
if brand.lower() == "generic":
continue
if brand not in brand_group_dict:
brand_group_dict[brand] = {}
material_type = metadata["material"]
if material_type not in brand_group_dict[brand]:
brand_group_dict[brand][material_type] = []
item = {"root_material_id": root_material_id,
"id": metadata["id"],
"name": metadata["name"],
"brand": metadata["brand"],
"material": metadata["material"],
"color_name": metadata["color_name"],
"container_node": container_node
}
brand_group_dict[brand][material_type].append(item)
for brand, material_dict in brand_group_dict.items():
brand_item = {"name": brand,
"materials": MaterialsModelGroupedByType(self)}
material_type_item_list = []
for material_type, material_list in material_dict.items():
material_type_item = {"name": material_type,
"colors": BaseMaterialsModel(self)}
material_type_item["colors"].clear()
material_type_item["colors"].setItems(material_list)
material_type_item_list.append(material_type_item)
brand_item["materials"].setItems(material_type_item_list)
brand_item_list.append(brand_item)
self.setItems(brand_item_list)

View file

@ -1,3 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt
from UM.Application import Application

View file

@ -7,12 +7,15 @@ from UM.Logger import Logger
from cura.Machines.Models.QualityProfilesModel import QualityProfilesModel
#
# This model is used for the custom profile items in the profile drop down menu.
#
class CustomQualityProfilesModel(QualityProfilesModel):
def _update(self):
Logger.log("d", "Updating %s ...", self.__class__.__name__)
active_global_stack = Application.getInstance().getMachineManager()._global_container_stack
active_global_stack = Application.getInstance().getMachineManager().activeMachine
if active_global_stack is None:
self.setItems([])
Logger.log("d", "No active GlobalStack, set %s as empty.", self.__class__.__name__)

View file

@ -0,0 +1,54 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from .BaseMaterialsModel import BaseMaterialsModel, getAvailableMaterials
class GenericMaterialsModel(BaseMaterialsModel):
def __init__(self, parent = None):
super().__init__(parent)
from cura.CuraApplication import CuraApplication
self._machine_manager = CuraApplication.getInstance().getMachineManager()
self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
self._material_manager = CuraApplication.getInstance().getMaterialManager()
self._machine_manager.globalContainerChanged.connect(self._update)
self._extruder_manager.activeExtruderChanged.connect(self._update)
self._material_manager.materialsUpdated.connect(self._update)
self._update()
def _update(self):
global_stack = self._machine_manager.activeMachine
if global_stack is None:
self.setItems([])
return
result_dict = getAvailableMaterials(self._extruder_position)
if result_dict is None:
self.setItems([])
return
item_list = []
for root_material_id, container_node in result_dict.items():
metadata = container_node.metadata
# Only add results for generic materials
if metadata["brand"].lower() != "generic":
continue
item = {"root_material_id": root_material_id,
"id": metadata["id"],
"name": metadata["name"],
"brand": metadata["brand"],
"material": metadata["material"],
"color_name": metadata["color_name"],
"container_node": container_node
}
item_list.append(item)
# Sort the item list by material name alphabetically
item_list = sorted(item_list, key = lambda d: d["name"])
self.setItems(item_list)

View file

@ -0,0 +1,101 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtProperty
from UM.Qt.ListModel import ListModel
from .BaseMaterialsModel import getAvailableMaterials
#
# This model is for the Material management page.
#
class MaterialManagementModel(ListModel):
RootMaterialIdRole = Qt.UserRole + 1
DisplayNameRole = Qt.UserRole + 2
BrandRole = Qt.UserRole + 3
MaterialTypeRole = Qt.UserRole + 4
ColorNameRole = Qt.UserRole + 5
ColorCodeRole = Qt.UserRole + 6
ContainerNodeRole = Qt.UserRole + 7
ContainerIdRole = Qt.UserRole + 8
DescriptionRole = Qt.UserRole + 9
AdhesionInfoRole = Qt.UserRole + 10
ApproximateDiameterRole = Qt.UserRole + 11
GuidRole = Qt.UserRole + 12
DensityRole = Qt.UserRole + 13
DiameterRole = Qt.UserRole + 14
IsReadOnlyRole = Qt.UserRole + 15
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.RootMaterialIdRole, "root_material_id")
self.addRoleName(self.DisplayNameRole, "name")
self.addRoleName(self.BrandRole, "brand")
self.addRoleName(self.MaterialTypeRole, "material")
self.addRoleName(self.ColorNameRole, "color_name")
self.addRoleName(self.ColorCodeRole, "color_code")
self.addRoleName(self.ContainerNodeRole, "container_node")
self.addRoleName(self.ContainerIdRole, "container_id")
self.addRoleName(self.DescriptionRole, "description")
self.addRoleName(self.AdhesionInfoRole, "adhesion_info")
self.addRoleName(self.ApproximateDiameterRole, "approximate_diameter")
self.addRoleName(self.GuidRole, "guid")
self.addRoleName(self.DensityRole, "density")
self.addRoleName(self.DiameterRole, "diameter")
self.addRoleName(self.IsReadOnlyRole, "is_read_only")
from cura.CuraApplication import CuraApplication
self._container_registry = CuraApplication.getInstance().getContainerRegistry()
self._machine_manager = CuraApplication.getInstance().getMachineManager()
extruder_manager = CuraApplication.getInstance().getExtruderManager()
material_manager = CuraApplication.getInstance().getMaterialManager()
self._machine_manager.globalContainerChanged.connect(self._update)
extruder_manager.activeExtruderChanged.connect(self._update)
material_manager.materialsUpdated.connect(self._update)
self._update()
def _update(self):
global_stack = self._machine_manager.activeMachine
if global_stack is None:
self.setItems([])
return
result_dict = getAvailableMaterials()
if result_dict is None:
self.setItems([])
return
material_list = []
for root_material_id, container_node in result_dict.items():
keys_to_fetch = ("name",
"brand",
"material",
"color_name",
"color_code",
"description",
"adhesion_info",
"approximate_diameter",)
item = {"root_material_id": container_node.metadata["base_file"],
"container_node": container_node,
"guid": container_node.metadata["GUID"],
"container_id": container_node.metadata["id"],
"density": container_node.metadata.get("properties", {}).get("density", ""),
"diameter": container_node.metadata.get("properties", {}).get("diameter", ""),
"is_read_only": self._container_registry.isReadOnly(container_node.metadata["id"]),
}
for key in keys_to_fetch:
item[key] = container_node.metadata.get(key, "")
material_list.append(item)
material_list = sorted(material_list, key = lambda k: (k["brand"].lower(), k["name"]))
self.setItems(material_list)

View file

@ -1,317 +0,0 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
from UM.Logger import Logger
from UM.Qt.ListModel import ListModel
def getAvailableMaterials(extruder_position: Optional[int] = None):
from cura.CuraApplication import CuraApplication
machine_manager = CuraApplication.getInstance().getMachineManager()
extruder_manager = CuraApplication.getInstance().getExtruderManager()
material_manager = CuraApplication.getInstance()._material_manager
active_global_stack = machine_manager._global_container_stack
extruder_stack = extruder_manager.getActiveExtruderStack()
if extruder_position is not None:
if active_global_stack is not None:
extruder_stack = active_global_stack.extruders.get(str(extruder_position))
if active_global_stack is None or extruder_stack is None:
Logger.log("d", "Active global stack [%s] or extruder stack [%s] is None, setting material list to empty.",
active_global_stack, extruder_stack)
return
machine_definition_id = active_global_stack.definition.getId()
variant_name = None
if extruder_stack.variant.getId() != "empty_variant":
variant_name = extruder_stack.variant.getName()
diameter = extruder_stack.approximateMaterialDiameter
# Fetch the available materials (ContainerNode) for the current active machine and extruder setup.
result_dict = material_manager.getAvailableMaterials(machine_definition_id, variant_name, diameter)
return result_dict
class BaseMaterialsModel(ListModel):
RootMaterialIdRole = Qt.UserRole + 1
IdRole = Qt.UserRole + 2
NameRole = Qt.UserRole + 3
BrandRole = Qt.UserRole + 4
MaterialRole = Qt.UserRole + 5
ColorRole = Qt.UserRole + 6
ContainerNodeRole = Qt.UserRole + 7
extruderPositionChanged = pyqtSignal()
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.RootMaterialIdRole, "root_material_id")
self.addRoleName(self.IdRole, "id")
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.BrandRole, "brand")
self.addRoleName(self.MaterialRole, "material")
self.addRoleName(self.ColorRole, "color_name")
self.addRoleName(self.ContainerNodeRole, "container_node")
self._extruder_position = 0
def setExtruderPosition(self, position: int):
if self._extruder_position != position:
self._extruder_position = position
self.extruderPositionChanged.emit()
@pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged)
def extruderPosition(self) -> int:
return self._extruder_positoin
class GenericMaterialsModel(BaseMaterialsModel):
def __init__(self, parent = None):
super().__init__(parent)
from cura.CuraApplication import CuraApplication
self._machine_manager = CuraApplication.getInstance().getMachineManager()
self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
self._material_manager = CuraApplication.getInstance()._material_manager
self._machine_manager.globalContainerChanged.connect(self._update)
self._extruder_manager.activeExtruderChanged.connect(self._update)
self._material_manager.materialsUpdated.connect(self._update)
self._update()
def _update(self):
global_stack = self._machine_manager.activeMachine
if global_stack is None:
self.setItems([])
return
result_dict = getAvailableMaterials(self._extruder_position)
if result_dict is None:
self.setItems([])
return
item_list = []
for root_material_id, container_node in result_dict.items():
metadata = container_node.metadata
# Only add results for generic materials
if metadata["brand"].lower() != "generic":
continue
item = {"root_material_id": root_material_id,
"id": metadata["id"],
"name": metadata["name"],
"brand": metadata["brand"],
"material": metadata["material"],
"color_name": metadata["color_name"],
"container_node": container_node
}
item_list.append(item)
# Sort the item list by material name alphabetically
item_list = sorted(item_list, key = lambda d: d["name"])
self.setItems(item_list)
class MaterialsModelGroupedByType(ListModel):
NameRole = Qt.UserRole + 1
ColorsRole = Qt.UserRole + 2
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.ColorsRole, "colors")
## Brand --> Material Type -> list of materials
class BrandMaterialsModel(ListModel):
NameRole = Qt.UserRole + 1
MaterialsRole = Qt.UserRole + 2
extruderPositionChanged = pyqtSignal()
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.MaterialsRole, "materials")
self._extruder_position = 0
from cura.CuraApplication import CuraApplication
self._machine_manager = CuraApplication.getInstance().getMachineManager()
extruder_manager = CuraApplication.getInstance().getExtruderManager()
material_manager = CuraApplication.getInstance()._material_manager
self._machine_manager.globalContainerChanged.connect(self._update)
extruder_manager.activeExtruderChanged.connect(self._update)
material_manager.materialsUpdated.connect(self._update)
self._update()
def setExtruderPosition(self, position: int):
if self._extruder_position != position:
self._extruder_position = position
self.extruderPositionChanged.emit()
@pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged)
def extruderPosition(self) -> int:
return self._extruder_position
def _update(self):
global_stack = self._machine_manager.activeMachine
if global_stack is None:
self.setItems([])
return
result_dict = getAvailableMaterials(self._extruder_position)
if result_dict is None:
self.setItems([])
return
brand_item_list = []
brand_group_dict = {}
for root_material_id, container_node in result_dict.items():
metadata = container_node.metadata
brand = metadata["brand"]
# Only add results for generic materials
if brand.lower() == "generic":
continue
if brand not in brand_group_dict:
brand_group_dict[brand] = {}
material_type = metadata["material"]
if material_type not in brand_group_dict[brand]:
brand_group_dict[brand][material_type] = []
item = {"root_material_id": root_material_id,
"id": metadata["id"],
"name": metadata["name"],
"brand": metadata["brand"],
"material": metadata["material"],
"color_name": metadata["color_name"],
"container_node": container_node
}
brand_group_dict[brand][material_type].append(item)
for brand, material_dict in brand_group_dict.items():
brand_item = {"name": brand,
"materials": MaterialsModelGroupedByType(self)}
material_type_item_list = []
for material_type, material_list in material_dict.items():
material_type_item = {"name": material_type,
"colors": BaseMaterialsModel(self)}
material_type_item["colors"].clear()
material_type_item["colors"].setItems(material_list)
material_type_item_list.append(material_type_item)
brand_item["materials"].setItems(material_type_item_list)
brand_item_list.append(brand_item)
self.setItems(brand_item_list)
#
# This model is for the Material management page.
#
class MaterialsModel(ListModel):
RootMaterialIdRole = Qt.UserRole + 1
DisplayNameRole = Qt.UserRole + 2
BrandRole = Qt.UserRole + 3
MaterialTypeRole = Qt.UserRole + 4
ColorNameRole = Qt.UserRole + 5
ColorCodeRole = Qt.UserRole + 6
ContainerNodeRole = Qt.UserRole + 7
ContainerIdRole = Qt.UserRole + 8
DescriptionRole = Qt.UserRole + 9
AdhesionInfoRole = Qt.UserRole + 10
ApproximateDiameterRole = Qt.UserRole + 11
GuidRole = Qt.UserRole + 12
DensityRole = Qt.UserRole + 13
DiameterRole = Qt.UserRole + 14
IsReadOnlyRole = Qt.UserRole + 15
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.RootMaterialIdRole, "root_material_id")
self.addRoleName(self.DisplayNameRole, "name")
self.addRoleName(self.BrandRole, "brand")
self.addRoleName(self.MaterialTypeRole, "material")
self.addRoleName(self.ColorNameRole, "color_name")
self.addRoleName(self.ColorCodeRole, "color_code")
self.addRoleName(self.ContainerNodeRole, "container_node")
self.addRoleName(self.ContainerIdRole, "container_id")
self.addRoleName(self.DescriptionRole, "description")
self.addRoleName(self.AdhesionInfoRole, "adhesion_info")
self.addRoleName(self.ApproximateDiameterRole, "approximate_diameter")
self.addRoleName(self.GuidRole, "guid")
self.addRoleName(self.DensityRole, "density")
self.addRoleName(self.DiameterRole, "diameter")
self.addRoleName(self.IsReadOnlyRole, "is_read_only")
from cura.CuraApplication import CuraApplication
self._container_registry = CuraApplication.getInstance().getContainerRegistry()
self._machine_manager = CuraApplication.getInstance().getMachineManager()
extruder_manager = CuraApplication.getInstance().getExtruderManager()
material_manager = CuraApplication.getInstance()._material_manager
self._machine_manager.globalContainerChanged.connect(self._update)
extruder_manager.activeExtruderChanged.connect(self._update)
material_manager.materialsUpdated.connect(self._update)
self._update()
def _update(self):
global_stack = self._machine_manager.activeMachine
if global_stack is None:
self.setItems([])
return
result_dict = getAvailableMaterials()
if result_dict is None:
self.setItems([])
return
material_list = []
for root_material_id, container_node in result_dict.items():
keys_to_fetch = ("name",
"brand",
"material",
"color_name",
"color_code",
"description",
"adhesion_info",
"approximate_diameter",)
item = {"root_material_id": container_node.metadata["base_file"],
"container_node": container_node,
"guid": container_node.metadata["GUID"],
"container_id": container_node.metadata["id"],
"density": container_node.metadata.get("properties", {}).get("density", ""),
"diameter": container_node.metadata.get("properties", {}).get("diameter", ""),
"is_read_only": self._container_registry.isReadOnly(container_node.metadata["id"]),
}
for key in keys_to_fetch:
item[key] = container_node.metadata.get(key, "")
material_list.append(item)
material_list = sorted(material_list, key = lambda k: (k["brand"].lower(), k["name"]))
self.setItems(material_list)

View file

@ -8,6 +8,9 @@ from UM.Qt.ListModel import ListModel
from UM.Settings.ContainerRegistry import ContainerRegistry
#
# This model is used to show details settings of the selected quality in the quality management page.
#
class QualitySettingsModel(ListModel):
KeyRole = Qt.UserRole + 1
LabelRole = Qt.UserRole + 2
@ -33,7 +36,7 @@ class QualitySettingsModel(ListModel):
self._quality_manager = self._application._quality_manager
self._extruder_position = ""
self._quality_item = None
self._selected_quality_item = None # The selected quality in the quality management page
self._i18n_catalog = None
self._quality_manager.qualitiesUpdated.connect(self._update)
@ -41,7 +44,7 @@ class QualitySettingsModel(ListModel):
self._update()
extruderPositionChanged = pyqtSignal()
qualityItemChanged = pyqtSignal()
selectedQualityItemChanged = pyqtSignal()
def setExtruderPosition(self, extruder_position):
if extruder_position != self._extruder_position:
@ -53,18 +56,18 @@ class QualitySettingsModel(ListModel):
def extruderPosition(self):
return self._extruder_position
def setQualityItem(self, quality_item):
if quality_item != self._quality_item:
self._quality_item = quality_item
self.qualityItemChanged.emit()
def setSelectedQualityItem(self, selected_quality_item):
if selected_quality_item != self._selected_quality_item:
self._selected_quality_item = selected_quality_item
self.selectedQualityItemChanged.emit()
self._update()
@pyqtProperty("QVariantMap", fset = setQualityItem, notify = qualityItemChanged)
def qualityItem(self):
return self._quality_item
@pyqtProperty("QVariantMap", fset = setSelectedQualityItem, notify = selectedQualityItemChanged)
def selectedQualityItem(self):
return self._selected_quality_item
def _update(self):
if self._quality_item is None:
if self._selected_quality_item is None:
self.setItems([])
return
@ -73,8 +76,8 @@ class QualitySettingsModel(ListModel):
global_container_stack = Application.getInstance().getGlobalContainerStack()
definition_container = global_container_stack.definition
quality_group = self._quality_item["quality_group"]
quality_changes_group = self._quality_item["quality_changes_group"]
quality_group = self._selected_quality_item["quality_group"]
quality_changes_group = self._selected_quality_item["quality_changes_group"]
if self._extruder_position == "":
quality_node = quality_group.node_for_global

View file

@ -1,15 +1,15 @@
from typing import Optional
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.Qt import pyqtSignal
from PyQt5.QtCore import QObject, QTimer
from typing import Optional, List
from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot
from UM.Application import Application
from UM.Logger import Logger
from UM.Util import parseBool
from cura.Machines.ContainerGroup import ContainerGroup
from cura.Machines.ContainerNode import ContainerNode
from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch
#
@ -27,14 +27,50 @@ from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch
# + <quality_changes_name>
#
class QualityGroup(ContainerGroup):
#
# A QualityGroup represents a group of containers that must be applied to each ContainerStack when it's used.
# Some concrete examples are Quality and QualityChanges: when we select quality type "normal", this quality type
# must be applied to all stacks in a machine, although each stack can have different containers. Use an Ultimaker 3
# as an example, suppose we choose quality type "normal", the actual InstanceContainers on each stack may look
# as below:
# GlobalStack ExtruderStack 1 ExtruderStack 2
# quality container: um3_global_normal um3_aa04_pla_normal um3_aa04_abs_normal
#
# This QualityGroup is mainly used in quality and quality_changes to group the containers that can be applied to
# a machine, so when a quality/custom quality is selected, the container can be directly applied to each stack instead
# of looking them up again.
#
class QualityGroup(QObject):
def __init__(self, name: str, quality_type: str, parent = None):
super().__init__(name, parent)
super().__init__(parent)
self.name = name
self.node_for_global = None # type: Optional["QualityGroup"]
self.nodes_for_extruders = dict() # position str -> QualityGroup
self.quality_type = quality_type
self.is_available = False
@pyqtSlot(result = str)
def getName(self) -> str:
return self.name
def getAllKeys(self) -> set:
result = set()
for node in [self.node_for_global] + list(self.nodes_for_extruders.values()):
if node is None:
continue
for key in node.getContainer().getAllKeys():
result.add(key)
return result
def getAllNodes(self) -> List["QualityGroup"]:
result = []
if self.node_for_global is not None:
result.append(self.node_for_global)
for extruder_node in self.nodes_for_extruders.values():
result.append(extruder_node)
return result
class QualityChangesGroup(QualityGroup):
@ -111,6 +147,16 @@ class QualityNode(ContainerNode):
quality_changes_group.addNode(QualityNode(metadata))
#
# Similar to MaterialManager, QualityManager maintains a number of maps and trees for material lookup.
# The models GUI and QML use are now only dependent on the QualityManager. That means as long as the data in
# QualityManager gets updated correctly, the GUI models should be updated correctly too, and the same goes for GUI.
#
# For now, updating the lookup maps and trees here is very simple: we discard the old data completely and recreate them
# again. This means the update is exactly the same as initialization. There are performance concerns about this approach
# but so far the creation of the tables and maps is very fast and there is no noticeable slowness, we keep it like this
# because it's simple.
#
class QualityManager(QObject):
qualitiesUpdated = pyqtSignal()
@ -133,6 +179,9 @@ class QualityManager(QObject):
self._container_registry.containerAdded.connect(self._onContainerMetadataChanged)
self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged)
# When a custom quality gets added/imported, there can be more than one InstanceContainers. In those cases,
# we don't want to react on every container/metadata changed signal. The timer here is to buffer it a bit so
# we don't react too many time.
self._update_timer = QTimer(self)
self._update_timer.setInterval(300)
self._update_timer.setSingleShot(True)
@ -327,7 +376,7 @@ class QualityManager(QObject):
# Also try to get the fallback material
material_type = extruder.material.getMetaDataEntry("material")
fallback_root_material_id = self._material_manager.getFallbackMaterialId(material_type)
fallback_root_material_id = self._material_manager.getFallbackMaterialIdByMaterialType(material_type)
if fallback_root_material_id:
root_material_id_list.append(fallback_root_material_id)
@ -376,7 +425,7 @@ class QualityManager(QObject):
return quality_group_dict
def getQualityGroupsForMachineDefinition(self, machine: str) -> dict:
def getQualityGroupsForMachineDefinition(self, machine: "GlobalStack") -> dict:
# Get machine definition ID for quality search
machine_definition_id = getMachineDefinitionIDForQualitySearch(machine)
@ -399,3 +448,27 @@ class QualityManager(QObject):
break
return quality_group_dict
#
# Gets the machine definition ID that can be used to search for Quality containers that are suitable for the given
# machine. The rule is as follows:
# 1. By default, the machine definition ID for quality container search will be "fdmprinter", which is the generic
# machine.
# 2. If a machine has its own machine quality (with "has_machine_quality = True"), we should use the given machine's
# own machine definition ID for quality search.
# Example: for an Ultimaker 3, the definition ID should be "ultimaker3".
# 3. When condition (2) is met, AND the machine has "quality_definition" defined in its definition file, then the
# definition ID specified in "quality_definition" should be used.
# Example: for an Ultimaker 3 Extended, it has "quality_definition = ultimaker3". This means Ultimaker 3 Extended
# shares the same set of qualities profiles as Ultimaker 3.
#
def getMachineDefinitionIDForQualitySearch(machine: "GlobalStack", default_definition_id: str = "fdmprinter") -> str:
machine_definition_id = default_definition_id
if parseBool(machine.getMetaDataEntry("has_machine_quality", False)):
# Only use the machine's own quality definition ID if this machine has machine quality.
machine_definition_id = machine.getMetaDataEntry("quality_definition")
if machine_definition_id is None:
machine_definition_id = machine.definition.getId()
return machine_definition_id

View file

@ -29,7 +29,7 @@ from UM.i18n import i18nCatalog
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.ExtruderStack import ExtruderStack
from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
catalog = i18nCatalog("cura")

View file

@ -28,7 +28,7 @@ from . import GlobalStack
from .ExtruderManager import ExtruderManager
from cura.CuraApplication import CuraApplication
from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")

View file

@ -24,7 +24,7 @@ from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.SettingFunction import SettingFunction
from UM.Signal import postponeSignals, CompressTechnique
from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
from cura.PrinterOutputDevice import PrinterOutputDevice
from cura.Settings.ExtruderManager import ExtruderManager
@ -826,6 +826,12 @@ class MachineManager(QObject):
stacks.append(self._global_container_stack)
return [ s.containersChanged for s in stacks ]
@pyqtSlot(str, str, str)
def setSettingForAllExtruders(self, setting_name: str, property_name: str, property_value: str):
for key, extruder in self._global_container_stack.extruders.items():
container = extruder.userChanges
container.setProperty(setting_name, property_name, property_value)
#
# New
#

View file

@ -22,7 +22,7 @@ from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
from cura.Scene.ZOffsetDecorator import ZOffsetDecorator
from cura.Machines.MachineTools import getMachineDefinitionIDForQualitySearch
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
MYPY = False

View file

@ -241,8 +241,8 @@ Item {
height: UM.Theme.getSize("setting").height
onClicked: {
UM.ActiveTool.triggerAction("unsubscribeForSettingValidation", model.key)
addedSettingsModel.setVisible(model.key, false)
UM.ActiveTool.triggerAction("unsubscribeForSettingValidation", model.key)
}
style: ButtonStyle

View file

@ -396,7 +396,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
color = material_data["color"]
brand = material_data["brand"]
material_type = material_data["material"]
name = "Unknown"
name = "Empty" if material_data["material"] == "empty" else "Unknown"
material = MaterialOutputModel(guid=material_data["guid"], type=material_type,
brand=brand, color=color, name=name)

View file

@ -264,6 +264,7 @@ Rectangle
case "wait_for_configuration":
return catalog.i18nc("@label:status", "Reserved")
case "wait_cleanup":
case "wait_user_action":
return catalog.i18nc("@label:status", "Finished")
case "pre_print":
case "sent_to_printer":
@ -278,6 +279,7 @@ Rectangle
case "aborted":
return catalog.i18nc("@label:status", "Print aborted");
default:
// If print job has unknown status show printer.status
return printerStatusText(printer);
}
}

View file

@ -69,7 +69,6 @@ Item
property alias configureSettingVisibility: configureSettingVisibilityAction
property alias browsePlugins: browsePluginsAction
property alias configurePlugins: configurePluginsAction
UM.I18nCatalog{id: catalog; name:"cura"}
@ -425,13 +424,6 @@ Item
iconName: "plugins_browse"
}
Action
{
id: configurePluginsAction
text: catalog.i18nc("@action:menu", "Installed plugins...");
iconName: "plugins_configure"
}
Action
{
id: expandSidebarAction;

View file

@ -268,7 +268,6 @@ UM.MainWindow
title: catalog.i18nc("@title:menu menubar:toplevel", "P&lugins")
MenuItem { action: Cura.Actions.browsePlugins }
MenuItem { action: Cura.Actions.configurePlugins }
}
Menu

View file

@ -17,7 +17,7 @@ Item
UM.I18nCatalog { id: catalog; name: "cura"; }
Cura.MaterialsModel {
Cura.MaterialManagementModel {
id: materialsModel
}

View file

@ -86,7 +86,7 @@ Tab
{
id: qualitySettings
extruderPosition: base.extruderPosition
qualityItem: base.qualityItem
selectedQualityItem: base.qualityItem
}
SystemPalette { id: palette }

View file

@ -516,8 +516,7 @@ Item
// Update the slider value to represent the rounded value
infillSlider.value = roundedSliderValue
// Explicitly cast to string to make sure the value passed to Python is an integer.
infillDensity.setPropertyValue("value", String(roundedSliderValue))
Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", roundedSliderValue)
}
style: SliderStyle
@ -647,14 +646,20 @@ Item
onClicked: {
// Set to 90% only when enabling gradual infill
var newInfillDensity;
if (parseInt(infillSteps.properties.value) == 0) {
previousInfillDensity = parseInt(infillDensity.properties.value)
infillDensity.setPropertyValue("value", String(90))
newInfillDensity = 90;
} else {
infillDensity.setPropertyValue("value", String(previousInfillDensity))
newInfillDensity = previousInfillDensity;
}
Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity))
infillSteps.setPropertyValue("value", (parseInt(infillSteps.properties.value) == 0) ? 5 : 0)
var infill_steps_value = 0;
if (parseInt(infillSteps.properties.value) == 0)
infill_steps_value = 5;
Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value)
}
onEntered: {