Merge branch 'feature_intent_container_tree' into feature_intent_upgrade

This commit is contained in:
Ghostkeeper 2019-09-16 15:20:41 +02:00
commit 8d21f75c40
No known key found for this signature in database
GPG Key ID: 86BEF881AE2CF276
19 changed files with 78 additions and 200 deletions

View File

@ -287,7 +287,8 @@ class MaterialManager(QObject):
if root_material_id is not None:
self.removeMaterialByRootId(root_material_id)
def duplicateMaterialByRootId(self, root_material_id, new_base_id: Optional[str] = None, new_metadata: Dict[str, Any] = None) -> Optional[str]:
def duplicateMaterialByRootId(self, root_material_id: str, new_base_id: Optional[str] = None,
new_metadata: Optional[Dict[str, Any]] = None) -> Optional[str]:
container_registry = CuraContainerRegistry.getInstance()
results = container_registry.findContainers(id=root_material_id)
@ -346,12 +347,14 @@ class MaterialManager(QObject):
# Returns the root material ID of the duplicated material if successful.
#
@pyqtSlot("QVariant", result = str)
def duplicateMaterial(self, material_node: MaterialNode, new_base_id: Optional[str] = None, new_metadata: Dict[str, Any] = None) -> Optional[str]:
def duplicateMaterial(self, material_node: MaterialNode, new_base_id: Optional[str] = None,
new_metadata: Optional[Dict[str, Any]] = None) -> str:
if material_node.container is None:
Logger.log("e", "Material node {0} doesn't have container.".format(material_node.container_id))
return "ERROR"
root_material_id = cast(str, material_node.container.getMetaDataEntry("base_file", ""))
return self.duplicateMaterialByRootId(root_material_id, new_base_id, new_metadata)
new_material_id = self.duplicateMaterialByRootId(root_material_id, new_base_id, new_metadata)
return new_material_id if new_material_id is not None else "ERROR"
# Create a new material by cloning Generic PLA for the current material diameter and generate a new GUID.
# Returns the ID of the newly created material.

View File

@ -74,6 +74,8 @@ class IntentModel(ListModel):
active_material_node = active_variant_node.materials[active_extruder.material.getMetaDataEntry("base_file")]
layer_heights_added = []
for quality_id, quality_node in active_material_node.qualities.items():
if quality_node.quality_type not in quality_groups: # Don't add the empty quality type (or anything else that would crash, defensively).
continue
quality_group = quality_groups[quality_node.quality_type]
layer_height = self._fetchLayerHeight(quality_group)

View File

@ -12,7 +12,7 @@ import cura.CuraApplication # Imported this way to prevent circular dependencie
from cura.Machines.ContainerTree import ContainerTree
if TYPE_CHECKING:
from cura.Machines import QualityGroup
from cura.Machines.QualityGroup import QualityGroup
#

View File

@ -87,14 +87,15 @@ class ContainerManager(QObject):
Logger.log("w", "Container node {0} doesn't have a container.".format(container_node.container_id))
return False
root_material_id = container_node.container.getMetaDataEntry("base_file", "")
if cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().isReadOnly(root_material_id):
container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
if container_registry.isReadOnly(root_material_id):
Logger.log("w", "Cannot set metadata of read-only container %s.", root_material_id)
return False
material_group = MaterialManager.getInstance().getMaterialGroup(root_material_id)
if material_group is None:
Logger.log("w", "Unable to find material group for: %s.", root_material_id)
root_material_query = container_registry.findContainers(id = root_material_id)
if not root_material_query:
Logger.log("w", "Unable to find root material: {root_material}.".format(root_material = root_material_id))
return False
root_material = root_material_query[0]
entries = entry_name.split("/")
entry_name = entries.pop()
@ -102,7 +103,7 @@ class ContainerManager(QObject):
sub_item_changed = False
if entries:
root_name = entries.pop(0)
root = material_group.root_material_node.container.getMetaDataEntry(root_name)
root = root_material.getMetaDataEntry(root_name)
item = root
for _ in range(len(entries)):
@ -115,11 +116,9 @@ class ContainerManager(QObject):
entry_name = root_name
entry_value = root
container = material_group.root_material_node.container
if container is not None:
container.setMetaDataEntry(entry_name, entry_value)
if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed.
container.metaDataChanged.emit(container)
root_material.setMetaDataEntry(entry_name, entry_value)
if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed.
root_material.metaDataChanged.emit(root_material)
return True
@pyqtSlot(str, result = str)
@ -355,11 +354,11 @@ class ContainerManager(QObject):
if material_node.container is None:
Logger.log("w", "Material node {0} doesn't have a container.".format(material_node.container_id))
return
material_group = MaterialManager.getInstance().getMaterialGroup(material_node.container.getMetaDataEntry("base_file", ""))
if material_group is None:
root_material_query = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().findInstanceContainers(id = material_node.getMetaDataEntry("base_file", ""))
if not root_material_query:
Logger.log("w", "Unable to find material group for %s", material_node)
return
root_material = root_material_query[0]
# Generate a new GUID
new_guid = str(uuid.uuid4())
@ -367,9 +366,7 @@ class ContainerManager(QObject):
# Update the GUID
# NOTE: We only need to set the root material container because XmlMaterialProfile.setMetaDataEntry() will
# take care of the derived containers too
container = material_group.root_material_node.container
if container is not None:
container.setMetaDataEntry("GUID", new_guid)
root_material.setMetaDataEntry("GUID", new_guid)
def _performMerge(self, merge_into: InstanceContainer, merge: InstanceContainer, clear_settings: bool = True) -> None:
if merge == merge_into:

View File

@ -25,6 +25,9 @@ EMPTY_MATERIAL_CONTAINER_ID = "empty_material"
empty_material_container = copy.deepcopy(empty_container)
empty_material_container.setMetaDataEntry("id", EMPTY_MATERIAL_CONTAINER_ID)
empty_material_container.setMetaDataEntry("type", "material")
empty_material_container.setMetaDataEntry("base_file", "empty_material")
empty_material_container.setMetaDataEntry("GUID", "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")
empty_material_container.setMetaDataEntry("material", "empty")
# Empty quality
EMPTY_QUALITY_CONTAINER_ID = "empty_quality"

View File

@ -942,7 +942,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
extruder_info = self._machine_info.extruder_info_dict[position]
if extruder_info.variant_info is None:
# If there is no variant_info, try to use the default variant. Otherwise, leave it be.
node = variant_manager.getDefaultVariantNode(global_stack.definition, VariantType.NOZZLE, global_stack)
machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
node = machine_node.variants[machine_node.preferred_variant_name]
if node is not None and node.container is not None:
extruder_stack.variant = node.container
continue
@ -951,7 +952,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
variant_name = parser["general"]["name"]
variant_type = VariantType.NOZZLE
node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type)
node = ContainerTree.getInstance().machines[global_stack.definition.getId()].variants[variant_name]
if node is not None and node.container is not None:
extruder_stack.variant = node.container

View File

@ -1,4 +1,4 @@
#Copyright (c) 2018 Ultimaker B.V.
#Copyright (c) 2019 Ultimaker B.V.
#Cura is released under the terms of the LGPLv3 or higher.
from typing import cast
@ -7,13 +7,13 @@ from Charon.VirtualFile import VirtualFile #To open UFP files.
from Charon.OpenMode import OpenMode #To indicate that we want to write to UFP files.
from io import StringIO #For converting g-code to bytes.
from UM.Application import Application
from UM.Logger import Logger
from UM.Mesh.MeshWriter import MeshWriter #The writer we need to implement.
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
from UM.PluginRegistry import PluginRegistry #To get the g-code writer.
from PyQt5.QtCore import QBuffer
from cura.CuraApplication import CuraApplication
from cura.Snapshot import Snapshot
from cura.Utils.Threading import call_on_qt_thread
@ -79,9 +79,9 @@ class UFPWriter(MeshWriter):
Logger.log("d", "Thumbnail not created, cannot save it")
# Store the material.
application = Application.getInstance()
application = CuraApplication.getInstance()
machine_manager = application.getMachineManager()
material_manager = application.getMaterialManager()
container_registry = application.getContainerRegistry()
global_stack = machine_manager.activeMachine
material_extension = "xml.fdm_material"
@ -107,12 +107,12 @@ class UFPWriter(MeshWriter):
continue
material_root_id = material.getMetaDataEntry("base_file")
material_group = material_manager.getMaterialGroup(material_root_id)
if material_group is None:
Logger.log("e", "Cannot find material container with root id [%s]", material_root_id)
material_root_query = container_registry.findContainers(id = material_root_id)
if not material_root_query:
Logger.log("e", "Cannot find material container with root id {root_id}".format(root_id = material_root_id))
return False
material_container = material_root_query[0]
material_container = material_group.root_material_node.container
try:
serialized_material = material_container.serialize()
except NotImplementedError:

View File

@ -1,76 +0,0 @@
# Copyright (c) 2018 Ultimaker B.V.
# Uranium is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtSignal, pyqtProperty
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from UM.Application import Application
from UM.Util import parseBool
from cura.MachineAction import MachineAction
catalog = i18nCatalog("cura")
## The Ultimaker 2 can have a few revisions & upgrades.
class UM2UpgradeSelection(MachineAction):
def __init__(self):
super().__init__("UM2UpgradeSelection", catalog.i18nc("@action", "Select upgrades"))
self._qml_url = "UM2UpgradeSelectionMachineAction.qml"
self._container_registry = ContainerRegistry.getInstance()
self._current_global_stack = None
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
self._reset()
def _reset(self):
self.hasVariantsChanged.emit()
def _onGlobalStackChanged(self):
if self._current_global_stack:
self._current_global_stack.metaDataChanged.disconnect(self._onGlobalStackMetaDataChanged)
self._current_global_stack = Application.getInstance().getGlobalContainerStack()
if self._current_global_stack:
self._current_global_stack.metaDataChanged.connect(self._onGlobalStackMetaDataChanged)
self._reset()
def _onGlobalStackMetaDataChanged(self):
self._reset()
hasVariantsChanged = pyqtSignal()
def setHasVariants(self, has_variants = True):
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
variant_container = global_container_stack.extruders["0"].variant
if has_variants:
global_container_stack.setMetaDataEntry("has_variants", True)
# Set the variant container to a sane default
empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer()
if type(variant_container) == type(empty_container):
search_criteria = { "type": "variant", "definition": "ultimaker2", "id": "*0.4*" }
containers = self._container_registry.findInstanceContainers(**search_criteria)
if containers:
global_container_stack.extruders["0"].variant = containers[0]
else:
# The metadata entry is stored in an ini, and ini files are parsed as strings only.
# Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.
if "has_variants" in global_container_stack.getMetaData():
global_container_stack.removeMetaDataEntry("has_variants")
# Set the variant container to an empty variant
global_container_stack.extruders["0"].variant = ContainerRegistry.getInstance().getEmptyInstanceContainer()
Application.getInstance().globalContainerStackChanged.emit()
self._reset()
@pyqtProperty(bool, fset = setHasVariants, notify = hasVariantsChanged)
def hasVariants(self):
if self._current_global_stack:
return parseBool(self._current_global_stack.getMetaDataEntry("has_variants", "false"))

View File

@ -1,55 +0,0 @@
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.3 as UM
import Cura 1.1 as Cura
Cura.MachineAction
{
UM.I18nCatalog { id: catalog; name: "cura"; }
anchors.fill: parent
Item
{
id: upgradeSelectionMachineAction
anchors.fill: parent
anchors.topMargin: UM.Theme.getSize("default_margin").width * 5
anchors.leftMargin: UM.Theme.getSize("default_margin").width * 4
Label
{
id: pageDescription
anchors.top: parent.top
anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Please select any upgrades made to this Ultimaker 2.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
}
Cura.CheckBox
{
id: olssonBlockCheckBox
anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
height: UM.Theme.getSize("setting_control").height
text: catalog.i18nc("@label", "Olsson Block")
checked: manager.hasVariants
onClicked: manager.hasVariants = checked
Connections
{
target: manager
onHasVariantsChanged: olssonBlockCheckBox.checked = manager.hasVariants
}
}
}
}

View File

@ -1,9 +1,8 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from . import BedLevelMachineAction
from . import UMOUpgradeSelection
from . import UM2UpgradeSelection
def getMetaData():
return {}
@ -11,6 +10,5 @@ def getMetaData():
def register(app):
return { "machine_action": [
BedLevelMachineAction.BedLevelMachineAction(),
UMOUpgradeSelection.UMOUpgradeSelection(),
UM2UpgradeSelection.UM2UpgradeSelection()
UMOUpgradeSelection.UMOUpgradeSelection()
]}

View File

@ -75,37 +75,20 @@ class XmlMaterialProfile(InstanceContainer):
if k in self.__material_properties_setting_map:
new_setting_values_dict[self.__material_properties_setting_map[k]] = v
# Prevent recursion
if not apply_to_all:
super().setMetaDataEntry(key, value)
if not apply_to_all: # Historical: If you only want to modify THIS container. We only used that to prevent recursion but with the below code that's no longer necessary.
container_query = registry.findContainers(id = self.getId())
else:
container_query = registry.findContainers(base_file = self.getMetaDataEntry("base_file"))
for container in container_query:
if key not in container.getMetaData() or container.getMetaData()[key] != value:
container.getMetaData()[key] = value
container.setDirty(True)
container.metaDataChanged.emit(container)
for k, v in new_setting_values_dict.items():
self.setProperty(k, "value", v)
return
# Get the MaterialGroup
material_manager = CuraApplication.getInstance().getMaterialManager()
root_material_id = self.getMetaDataEntry("base_file") #if basefile is self.getId, this is a basefile.
material_group = material_manager.getMaterialGroup(root_material_id)
if not material_group: #If the profile is not registered in the registry but loose/temporary, it will not have a base file tree.
super().setMetaDataEntry(key, value)
for k, v in new_setting_values_dict.items():
self.setProperty(k, "value", v)
return
# Update the root material container
root_material_container = material_group.root_material_node.container
if root_material_container is not None:
root_material_container.setMetaDataEntry(key, value, apply_to_all = False)
for k, v in new_setting_values_dict.items():
root_material_container.setProperty(k, "value", v)
# Update all containers derived from it
for node in material_group.derived_material_node_list:
container = node.container
if container is not None:
container.setMetaDataEntry(key, value, apply_to_all = False)
for k, v in new_setting_values_dict.items():
container.setProperty(k, "value", v)
## Overridden from InstanceContainer, similar to setMetaDataEntry.
# without this function the setName would only set the name of the specific nozzle / material / machine combination container
# The function is a bit tricky. It will not set the name of all containers if it has the correct name itself.

View File

@ -14,8 +14,6 @@
"has_materials": false,
"has_machine_quality": true,
"preferred_variant_name": "0.4 mm",
"first_start_actions": ["UM2UpgradeSelection"],
"supported_actions":["UM2UpgradeSelection"],
"machine_extruder_trains":
{
"0": "ultimaker2_extruder_0"

View File

@ -0,0 +1,12 @@
{
"version": 2,
"name": "Ultimaker 2 Extended with Olsson",
"inherits": "ultimaker2_extended",
"metadata": {
"has_variants": true
},
"overrides": {
"machine_name": { "default_value": "Ultimaker 2 Extended with Olsson" }
}
}

View File

@ -11,7 +11,6 @@
"platform": "ultimaker2go_platform.obj",
"platform_texture": "Ultimaker2Gobackplate.png",
"platform_offset": [0, 0, 0],
"first_start_actions": [],
"machine_extruder_trains":
{
"0": "ultimaker2_go_extruder_0"

View File

@ -0,0 +1,13 @@
{
"version": 2,
"name": "Ultimaker 2 with Olsson Block",
"inherits": "ultimaker2",
"metadata": {
"has_variants": true,
"quality_definition": "ultimaker2"
},
"overrides": {
"machine_name": { "default_value": "Ultimaker 2 with Olsson Block" }
}
}

View File

@ -1,7 +1,7 @@
[general]
name = 0.25 mm
version = 4
definition = ultimaker2
definition = ultimaker2_olsson
[metadata]
setting_version = 10

View File

@ -1,7 +1,7 @@
[general]
name = 0.4 mm
version = 4
definition = ultimaker2
definition = ultimaker2_olsson
[metadata]
setting_version = 10

View File

@ -1,7 +1,7 @@
[general]
name = 0.6 mm
version = 4
definition = ultimaker2
definition = ultimaker2_olsson
[metadata]
setting_version = 10

View File

@ -1,7 +1,7 @@
[general]
name = 0.8 mm
version = 4
definition = ultimaker2
definition = ultimaker2_olsson
[metadata]
setting_version = 10