Merge branch 'feature_intent_container_tree' of https://github.com/Ultimaker/Cura into feature_intent_container_tree

This commit is contained in:
Remco Burema 2019-08-27 15:50:21 +02:00
commit c333e980dc
7 changed files with 97 additions and 29 deletions

View file

@ -85,6 +85,7 @@ from cura.Machines.Models.FirstStartMachineActionsModel import FirstStartMachine
from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel
from cura.Machines.Models.GlobalStacksModel import GlobalStacksModel
from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel
from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel
from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
from cura.Machines.Models.NozzleModel import NozzleModel
from cura.Machines.Models.QualityManagementModel import QualityManagementModel
@ -221,6 +222,7 @@ class CuraApplication(QtApplication):
self._machine_error_checker = None
self._machine_settings_manager = MachineSettingsManager(self, parent = self)
self._material_management_model = MaterialManagementModel()
self._discovered_printer_model = DiscoveredPrintersModel(self, parent = self)
self._first_start_machine_actions_model = FirstStartMachineActionsModel(self, parent = self)
@ -975,6 +977,10 @@ class CuraApplication(QtApplication):
def getMachineActionManager(self, *args):
return self._machine_action_manager
@pyqtSlot(result = QObject)
def getMaterialManagementModel(self):
return self._material_management_model
def getSimpleModeSettingsManager(self, *args):
if self._simple_mode_settings_manager is None:
self._simple_mode_settings_manager = SimpleModeSettingsManager()
@ -1054,6 +1060,7 @@ class CuraApplication(QtApplication):
qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel")
qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel")
qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
qmlRegisterSingletonType(MaterialManagementModel, "Cura", 1, 5, "MaterialManagementModel", self.getMaterialManagementModel)
qmlRegisterType(DiscoveredPrintersModel, "Cura", 1, 0, "DiscoveredPrintersModel")

View file

@ -1,5 +1,6 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from collections import defaultdict
import copy
import uuid
@ -7,19 +8,16 @@ from typing import Dict, Optional, TYPE_CHECKING, Any, List, cast
from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
from UM.Decorators import deprecated
from UM.Logger import Logger
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.SettingFunction import SettingFunction
from UM.Util import parseBool
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.Settings.CuraContainerRegistry import CuraContainerRegistry
from .MaterialNode import MaterialNode
from .MaterialGroup import MaterialGroup
from .VariantType import VariantType
if TYPE_CHECKING:
from UM.Settings.DefinitionContainer import DefinitionContainer
@ -248,7 +246,7 @@ class MaterialManager(QObject):
def removeMaterialByRootId(self, root_material_id: str):
container_registry = CuraContainerRegistry.getInstance()
results = container_registry.findContainers(id=root_material_id)
results = container_registry.findContainers(id = root_material_id)
if not results:
container_registry.addWrongContainerId(root_material_id)
@ -260,8 +258,8 @@ class MaterialManager(QObject):
# Check if the material is active in any extruder train. In that case, the material shouldn't be removed!
# In the future we might enable this again, but right now, it's causing a ton of issues if we do (since it
# corrupts the configuration)
root_material_id = material_node.container.getMetaDataEntry("base_file")
ids_to_remove = [metadata.get("id", "") for metadata in CuraContainerRegistry.getInstance().findInstanceContainersMetadata(base_file=root_material_id)]
root_material_id = material_node.base_file
ids_to_remove = {metadata.get("id", "") for metadata in CuraContainerRegistry.getInstance().findInstanceContainersMetadata(base_file = root_material_id)}
for extruder_stack in CuraContainerRegistry.getInstance().findContainerStacks(type = "extruder_train"):
if extruder_stack.material.getId() in ids_to_remove:

View file

@ -31,8 +31,13 @@ class BaseMaterialsModel(ListModel):
self._container_registry = self._application.getInstance().getContainerRegistry()
self._machine_manager = self._application.getMachineManager()
self._extruder_position = 0
self._extruder_stack = None
self._enabled = True
# Update the stack and the model data when the machine changes
self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack)
self._updateExtruderStack()
# Update this model when switching machines, when adding materials or changing their metadata.
self._machine_manager.activeStackChanged.connect(self._update)
@ -55,12 +60,8 @@ class BaseMaterialsModel(ListModel):
self.addRoleName(Qt.UserRole + 15, "container_node")
self.addRoleName(Qt.UserRole + 16, "is_favorite")
self._extruder_position = 0
self._extruder_stack = None
self._available_materials = None # type: Optional[Dict[str, MaterialNode]]
self._favorite_ids = set() # type: Set[str]
self._enabled = True
def _updateExtruderStack(self):
global_stack = self._machine_manager.activeMachine

View file

@ -0,0 +1,65 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import QObject, pyqtSlot # To allow the preference page proxy to be used from the actual preferences page.
from typing import TYPE_CHECKING
from UM.Logger import Logger
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry # To find the sets of materials belonging to each other, and currently loaded extruder stacks.
if TYPE_CHECKING:
from cura.Machines.MaterialNode import MaterialNode
## Proxy class to the materials page in the preferences.
#
# This class handles the actions in that page, such as creating new materials,
# renaming them, etc.
class MaterialManagementModel(QObject):
## Can a certain material be deleted, or is it still in use in one of the
# container stacks anywhere?
#
# We forbid the user from deleting a material if it's in use in any stack.
# Deleting it while it's in use can lead to corrupted stacks. In the
# future we might enable this functionality again (deleting the material
# from those stacks) but for now it is easier to prevent the user from
# doing this.
# \param material_node The ContainerTree node of the material to check.
# \return Whether or not the material can be removed.
@pyqtSlot("QVariant", result = bool)
def canMaterialBeRemoved(self, material_node: "MaterialNode"):
container_registry = CuraContainerRegistry.getInstance()
ids_to_remove = {metadata.get("id", "") for metadata in container_registry.findInstanceContainersMetadata(base_file = material_node.base_file)}
for extruder_stack in container_registry.findContainerStacks(type = "extruder_train"):
if extruder_stack.material.getId() in ids_to_remove:
return False
return True
## Change the user-visible name of a material.
# \param material_node The ContainerTree node of the material to rename.
# \param name The new name for the material.
@pyqtSlot("QVariant", str)
def setMaterialName(self, material_node: "MaterialNode", name: str) -> None:
container_registry = CuraContainerRegistry.getInstance()
root_material_id = material_node.base_file
if container_registry.isReadOnly(root_material_id):
Logger.log("w", "Cannot set name of read-only container %s.", root_material_id)
return
return container_registry.findContainers(id = root_material_id)[0].setName(name)
## Deletes a material from Cura.
#
# This function does not do any safety checking any more. Please call this
# function only if:
# - The material is not read-only.
# - The material is not used in any stacks.
# If the material was not lazy-loaded yet, this will fully load the
# container. When removing this material node, all other materials with
# the same base fill will also be removed.
# \param material_node The material to remove.
@pyqtSlot("QVariant")
def removeMaterial(self, material_node: "MaterialNode") -> None:
container_registry = CuraContainerRegistry.getInstance()
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"])

View file

@ -223,10 +223,10 @@ class XmlMaterialProfile(InstanceContainer):
for instance in self.findInstances():
self._addSettingElement(builder, instance)
machine_container_map = {} # type: Dict[str, InstanceContainer]
machine_variant_map = {} # type: Dict[str, Dict[str, Any]]
machine_container_map = {} # type: Dict[str, InstanceContainer]
machine_variant_map = {} # type: Dict[str, Dict[str, Any]]
variant_manager = CuraApplication.getInstance().getVariantManager()
container_tree = ContainerTree.getInstance()
root_material_id = self.getMetaDataEntry("base_file") # if basefile is self.getId, this is a basefile.
all_containers = registry.findInstanceContainers(base_file = root_material_id)
@ -243,16 +243,12 @@ class XmlMaterialProfile(InstanceContainer):
machine_variant_map[definition_id] = {}
variant_name = container.getMetaDataEntry("variant_name")
if variant_name:
variant_node = variant_manager.getVariantNode(definition_id, variant_name)
if variant_node is None:
continue
variant_dict = {"variant_node":variant_node ,
"material_container": container}
machine_variant_map[definition_id][variant_name] = variant_dict
continue
if not variant_name:
machine_container_map[definition_id] = container
machine_container_map[definition_id] = container
variant_dict = {"variant_type": container.getMetaDataEntry("hardware_type", str(VariantType.NOZZLE)),
"material_container": container}
machine_variant_map[definition_id][variant_name] = variant_dict
# Map machine human-readable names to IDs
product_id_map = self.getProductIdMap()
@ -285,8 +281,7 @@ class XmlMaterialProfile(InstanceContainer):
# Find all hotend sub-profiles corresponding to this material and machine and add them to this profile.
buildplate_dict = {} # type: Dict[str, Any]
for variant_name, variant_dict in machine_variant_map[definition_id].items():
variant_type = variant_dict["variant_node"].getMetaDataEntry("hardware_type", str(VariantType.NOZZLE))
variant_type = VariantType(variant_type)
variant_type = VariantType(variant_dict["variant_type"])
if variant_type == VariantType.NOZZLE:
# The hotend identifier is not the containers name, but its "name".
builder.start("hotend", {"id": variant_name})

View file

@ -7,7 +7,7 @@ import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import UM 1.2 as UM
import Cura 1.0 as Cura
import Cura 1.5 as Cura
Item
{
@ -18,6 +18,7 @@ Item
property var currentItem: null
property var materialManager: CuraApplication.getMaterialManager()
property var materialManagementModel: CuraApplication.getMaterialManagementModel()
property var hasCurrentItem: base.currentItem != null
property var isCurrentItemActivated:
@ -147,7 +148,7 @@ Item
id: removeMenuButton
text: catalog.i18nc("@action:button", "Remove")
iconName: "list-remove"
enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManager.canMaterialBeRemoved(base.currentItem.container_node)
enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManagementModel.canMaterialBeRemoved(base.currentItem.container_node)
onClicked:
{
@ -297,7 +298,7 @@ Item
{
// Set the active material as the fallback. It will be selected when the current material is deleted
base.newRootMaterialIdToSwitchTo = base.active_root_material_id
base.materialManager.removeMaterial(base.currentItem.container_node);
base.materialManagementModel.removeMaterial(base.currentItem.container_node);
}
}

View file

@ -23,6 +23,7 @@ TabView
property real secondColumnWidth: (width * 0.40) | 0
property string containerId: ""
property var materialPreferenceValues: UM.Preferences.getValue("cura/material_settings") ? JSON.parse(UM.Preferences.getValue("cura/material_settings")) : {}
property var materialManagementModel: CuraApplication.getMaterialManagementModel()
property double spoolLength: calculateSpoolLength()
property real costPerMeter: calculateCostPerMeter()
@ -565,7 +566,7 @@ TabView
}
// update the values
CuraApplication.getMaterialManager().setMaterialName(base.currentMaterialNode, new_name)
base.materialManagementModel.setMaterialName(base.currentMaterialNode, new_name)
properties.name = new_name
}