Fix merge conflicts

This commit is contained in:
Lipu Fei 2019-10-15 13:08:00 +02:00
commit 43fa4337f9
12 changed files with 114 additions and 73 deletions

View file

@ -134,6 +134,9 @@ class MachineNode(ContainerNode):
groups_by_name[name] = QualityChangesGroup(name, quality_type = quality_changes["quality_type"], groups_by_name[name] = QualityChangesGroup(name, quality_type = quality_changes["quality_type"],
intent_category = quality_changes.get("intent_category", "default"), intent_category = quality_changes.get("intent_category", "default"),
parent = CuraApplication.getInstance()) parent = CuraApplication.getInstance())
# CURA-6882
# Custom qualities are always available, even if they are based on the "not supported" profile.
groups_by_name[name].is_available = True
elif groups_by_name[name].intent_category == "default": # Intent category should be stored as "default" if everything is default or as the intent if any of the extruder have an actual intent. elif groups_by_name[name].intent_category == "default": # Intent category should be stored as "default" if everything is default or as the intent if any of the extruder have an actual intent.
groups_by_name[name].intent_category = quality_changes.get("intent_category", "default") groups_by_name[name].intent_category = quality_changes.get("intent_category", "default")
@ -142,14 +145,6 @@ class MachineNode(ContainerNode):
else: # Global profile. else: # Global profile.
groups_by_name[name].metadata_for_global = quality_changes groups_by_name[name].metadata_for_global = quality_changes
quality_groups = self.getQualityGroups(variant_names, material_bases, extruder_enabled)
for quality_changes_group in groups_by_name.values():
if quality_changes_group.quality_type not in quality_groups:
quality_changes_group.is_available = False
else:
# Quality changes group is available iff the quality group it depends on is available. Irrespective of whether the intent category is available.
quality_changes_group.is_available = quality_groups[quality_changes_group.quality_type].is_available
return list(groups_by_name.values()) return list(groups_by_name.values())
## Gets the preferred global quality node, going by the preferred quality ## Gets the preferred global quality node, going by the preferred quality

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.
@ -142,15 +155,17 @@ class MaterialManagementModel(QObject):
# This sort fixes the problem by emitting the most specific containers first. # This sort fixes the problem by emitting the most specific containers first.
new_containers = sorted(new_containers, key = lambda x: x.getId(), reverse = True) new_containers = sorted(new_containers, key = lambda x: x.getId(), reverse = True)
for container_to_add in new_containers: # Optimization. Serving the same purpose as the postponeSignals() in removeMaterial()
container_to_add.setDirty(True) with postponeSignals(container_registry.containerAdded, compress=CompressTechnique.CompressPerParameterValue):
container_registry.addContainer(container_to_add) 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. # 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(";")) favorites_set = set(application.getPreferences().getValue("cura/favorite_materials").split(";"))
if base_file in favorites_set: if base_file in favorites_set:
favorites_set.add(new_base_id) favorites_set.add(new_base_id)
application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites_set)) application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites_set))
return new_base_id return new_base_id

View file

@ -13,6 +13,7 @@ from cura.Settings.ContainerManager import ContainerManager
from cura.Machines.ContainerTree import ContainerTree from cura.Machines.ContainerTree import ContainerTree
from cura.Settings.cura_empty_instance_containers import empty_quality_changes_container from cura.Settings.cura_empty_instance_containers import empty_quality_changes_container
from cura.Settings.IntentManager import IntentManager from cura.Settings.IntentManager import IntentManager
from cura.Machines.Models.MachineModelUtils import fetchLayerHeight
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
@ -295,6 +296,8 @@ class QualityManagementModel(ListModel):
if not quality_group.is_available: if not quality_group.is_available:
continue continue
layer_height = fetchLayerHeight(quality_group)
item = {"name": quality_group.name, item = {"name": quality_group.name,
"is_read_only": True, "is_read_only": True,
"quality_group": quality_group, "quality_group": quality_group,
@ -302,10 +305,11 @@ class QualityManagementModel(ListModel):
"quality_changes_group": None, "quality_changes_group": None,
"intent_category": "default", "intent_category": "default",
"section_name": catalog.i18nc("@label", "Default"), "section_name": catalog.i18nc("@label", "Default"),
"layer_height": layer_height, # layer_height is only used for sorting
} }
item_list.append(item) item_list.append(item)
# Sort by quality names # Sort by layer_height for built-in qualities
item_list = sorted(item_list, key = lambda x: x["name"].upper()) item_list = sorted(item_list, key = lambda x: x["layer_height"])
# Create intent items (non-default) # Create intent items (non-default)
available_intent_list = IntentManager.getInstance().getCurrentAvailableIntents() available_intent_list = IntentManager.getInstance().getCurrentAvailableIntents()

View file

@ -104,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")

View file

@ -1514,7 +1514,8 @@ class MachineManager(QObject):
if self._global_container_stack is None: if self._global_container_stack is None:
return return
machine_definition_id = self._global_container_stack.definition.id machine_definition_id = self._global_container_stack.definition.id
variant_node = self._variant_manager.getVariantNode(machine_definition_id, variant_name) machine_node = ContainerTree.getInstance().machines.get(machine_definition_id)
variant_node = machine_node.variants.get(variant_name)
self.setVariant(position, variant_node) self.setVariant(position, variant_node)
@pyqtSlot(str, "QVariant") @pyqtSlot(str, "QVariant")

View file

@ -125,7 +125,7 @@
"overrides": { "overrides": {
"machine_name": { "default_value": "Creawsome Base Printer" }, "machine_name": { "default_value": "Creawsome Base Printer" },
"machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n" }, "machine_start_gcode": { "default_value": "M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration\nM203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate\nM204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration\nM205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\n\nG28 ;Home\n\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n" },
"machine_end_gcode": { "default_value": "G91 ;Relative positionning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positionning\n\nG1 X0 Y{machine_depth} ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n" }, "machine_end_gcode": { "default_value": "G91 ;Relative positioning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positionning\n\nG1 X0 Y{machine_depth} ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n" },
"machine_max_feedrate_x": { "value": 500 }, "machine_max_feedrate_x": { "value": 500 },
"machine_max_feedrate_y": { "value": 500 }, "machine_max_feedrate_y": { "value": 500 },

View file

@ -4,7 +4,7 @@
"inherits": "creality_base", "inherits": "creality_base",
"overrides": { "overrides": {
"machine_name": { "default_value": "Creality Ender-5" }, "machine_name": { "default_value": "Creality Ender-5" },
"machine_end_gcode": { "default_value": "G91 ;Relative positionning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positionning\n\nG1 X0 Y0 ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n" }, "machine_end_gcode": { "default_value": "G91 ;Relative positioning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positionning\n\nG1 X0 Y0 ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n" },
"machine_width": { "default_value": 220 }, "machine_width": { "default_value": 220 },
"machine_depth": { "default_value": 220 }, "machine_depth": { "default_value": 220 },
"machine_height": { "default_value": 300 }, "machine_height": { "default_value": 300 },

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

@ -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

@ -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,41 +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.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
@ -164,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

@ -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: