From 02b978272f2b76aba61ebde5a5ecc31978675bbb Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 27 Apr 2017 11:19:46 +0200 Subject: [PATCH 01/17] Add "Create" button to create a new, unique material. The new custom material is still based on generic_pla, but it gets a new GUID and uses itself as base_file so it is not conjoined to another material. --- cura/Settings/ContainerManager.py | 28 +++++++++++++++++++++ resources/qml/Preferences/MaterialsPage.qml | 17 +++++++++++++ 2 files changed, 45 insertions(+) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index bac11f78cf..912129e822 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -3,6 +3,7 @@ import os.path import urllib +import uuid from typing import Dict, Union from PyQt5.QtCore import QObject, QUrl, QVariant @@ -694,6 +695,33 @@ class ContainerManager(QObject): duplicated_container.setDirty(True) self._container_registry.addContainer(duplicated_container) + @pyqtSlot(result = str) + def createMaterial(self) -> str: + # Ensure all settings are saved. + Application.getInstance().saveSettings() + + containers = self._container_registry.findInstanceContainers(id="generic_pla") + if not containers: + Logger.log("d", "Unable to creata a new material by cloning generic_pla, because it doesn't exist.") + return "" + + # Create a new ID & container to hold the data. + new_id = self._container_registry.uniqueName("custom_material") + container_type = type(containers[0]) # Could be either a XMLMaterialProfile or a InstanceContainer + duplicated_container = container_type(new_id) + + # Instead of duplicating we load the data from the basefile again. + # This ensures that the inheritance goes well and all "cut up" subclasses of the xmlMaterial profile + # are also correctly created. + with open(containers[0].getPath(), encoding="utf-8") as f: + duplicated_container.deserialize(f.read()) + + duplicated_container.setMetaDataEntry("base_file", new_id) + duplicated_container.setMetaDataEntry("GUID", str(uuid.uuid4())) + duplicated_container.setName(catalog.i18nc("@label", "Custom Material")) + + self._container_registry.addContainer(duplicated_container) + ## Get the singleton instance for this class. @classmethod def getInstance(cls) -> "ContainerManager": diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 08cb6d4d13..7d7b647969 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -135,6 +135,23 @@ UM.ManagementPage } }, Button + { + text: catalog.i18nc("@action:button", "Create") + iconName: "list-add" + onClicked: + { + var material_id = Cura.ContainerManager.createMaterial() + if(material_id == "") + { + return + } + if(Cura.MachineManager.hasMaterials) + { + Cura.MachineManager.setActiveMaterial(material_id) + } + } + }, + Button { text: catalog.i18nc("@action:button", "Duplicate"); iconName: "list-add"; From 23cd6b1c2c800669425c388c7b99037fdf85fe9c Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 29 Apr 2017 16:43:26 +0200 Subject: [PATCH 02/17] Fix rendering of readonly description/adhesion info --- resources/qml/Preferences/ReadOnlyTextArea.qml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/resources/qml/Preferences/ReadOnlyTextArea.qml b/resources/qml/Preferences/ReadOnlyTextArea.qml index 1c457eb5d2..db92c7d2b0 100644 --- a/resources/qml/Preferences/ReadOnlyTextArea.qml +++ b/resources/qml/Preferences/ReadOnlyTextArea.qml @@ -45,17 +45,4 @@ Item } } } - - Label - { - visible: base.readOnly - text: textArea.text - - anchors.fill: parent - anchors.margins: textArea.__style ? textArea.__style.textMargin : 4 - - color: palette.buttonText - } - - SystemPalette { id: palette } } From 67b8302d40af45ce989d51ebb7bf11edf80b65c9 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 29 Apr 2017 19:49:12 +0200 Subject: [PATCH 03/17] Add a notice to linked materials and allow "unlinking" a material. --- cura/Settings/ContainerManager.py | 36 +++++++++++++++++++++- resources/qml/Preferences/MaterialView.qml | 27 ++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 912129e822..e9b3518fa3 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -695,6 +695,7 @@ class ContainerManager(QObject): duplicated_container.setDirty(True) self._container_registry.addContainer(duplicated_container) + # Create a new material by cloning Generic PLA and setting the GUID to something unqiue @pyqtSlot(result = str) def createMaterial(self) -> str: # Ensure all settings are saved. @@ -702,7 +703,7 @@ class ContainerManager(QObject): containers = self._container_registry.findInstanceContainers(id="generic_pla") if not containers: - Logger.log("d", "Unable to creata a new material by cloning generic_pla, because it doesn't exist.") + Logger.log("d", "Unable to create a new material by cloning generic_pla, because it doesn't exist.") return "" # Create a new ID & container to hold the data. @@ -722,6 +723,39 @@ class ContainerManager(QObject): self._container_registry.addContainer(duplicated_container) + @pyqtSlot(str, result = "QStringList") + def getLinkedMaterials(self, material_id: str): + containers = self._container_registry.findInstanceContainers(id=material_id) + if not containers: + Logger.log("d", "Unable to find materials linked to material with id %s, because it doesn't exist.", material_id) + return [] + + material_container = containers[0] + material_guid = material_container.getMetaDataEntry("GUID", "") + if not material_guid: + Logger.log("d", "Unable to find materials linked to material with id %s, because it doesn't have a GUID.", material_id) + return [] + + containers = self._container_registry.findInstanceContainers(type = "material", GUID = material_guid) + linked_material_names = [] + for container in containers: + if container.getId() == material_id or container.getMetaDataEntry("base_file") != container.getId(): + continue + + linked_material_names.append(container.getName()) + return linked_material_names + + @pyqtSlot(str) + def unlinkMaterial(self, material_id: str): + containers = self._container_registry.findInstanceContainers(id=material_id) + if not containers: + Logger.log("d", "Unable to make the material with id %s unique, because it doesn't exist.", material_id) + return "" + + containers[0].setMetaDataEntry("base_file", material_id) + containers[0].setMetaDataEntry("GUID", str(uuid.uuid4())) + + ## Get the singleton instance for this class. @classmethod def getInstance(cls) -> "ContainerManager": diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 226fd349bf..956af88139 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -24,6 +24,16 @@ TabView property double spoolLength: calculateSpoolLength() property real costPerMeter: calculateCostPerMeter() + property string linkedMaterialNames: + { + if(!base.containerId || !base.editingEnabled) + { + return "" + } + var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.containerId); + return linkedMaterials.join(", "); + } + Tab { title: catalog.i18nc("@title","Information") @@ -196,6 +206,23 @@ TabView height: parent.rowHeight } + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height; visible: unlinkMaterialButton.visible } + Label + { + width: parent.width + verticalAlignment: Qt.AlignVCenter + text: catalog.i18nc("@label", "This material is linked to %1 and shares some of its properties.").arg(base.linkedMaterialNames) + wrapMode: Text.WordWrap + visible: unlinkMaterialButton.visible + } + Button + { + id: unlinkMaterialButton + text: catalog.i18nc("@label", "Unlink Material") + visible: base.linkedMaterialNames != "" + onClicked: Cura.ContainerManager.unlinkMaterial(base.containerId) + } + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Description") } From a1d9b1a37f33c86396a1e90c31b100f6d75ffddd Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 29 Apr 2017 21:19:54 +0200 Subject: [PATCH 04/17] Force update after unlinking material. --- resources/qml/Preferences/MaterialView.qml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 956af88139..ec92e8cbcd 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -24,8 +24,13 @@ TabView property double spoolLength: calculateSpoolLength() property real costPerMeter: calculateCostPerMeter() + property bool reevaluateLinkedMaterials: false property string linkedMaterialNames: { + if (reevaluateLinkedMaterials) + { + reevaluateLinkedMaterials = false; + } if(!base.containerId || !base.editingEnabled) { return "" @@ -220,7 +225,11 @@ TabView id: unlinkMaterialButton text: catalog.i18nc("@label", "Unlink Material") visible: base.linkedMaterialNames != "" - onClicked: Cura.ContainerManager.unlinkMaterial(base.containerId) + onClicked: + { + Cura.ContainerManager.unlinkMaterial(base.containerId) + base.reevaluateLinkedMaterials = true + } } Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } From 577a8d0a3efe52f1ed85f49f58fd0765e60e68b0 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sun, 30 Apr 2017 10:28:03 +0200 Subject: [PATCH 05/17] Fix MaterialView layout issues Make scrollview look more in line with the scrollview on the profiles page --- resources/qml/Preferences/MaterialView.qml | 67 +++++++++++----------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index ec92e8cbcd..a44b8a0f08 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -43,62 +43,62 @@ TabView { title: catalog.i18nc("@title","Information") - anchors - { - leftMargin: UM.Theme.getSize("default_margin").width - topMargin: UM.Theme.getSize("default_margin").height - bottomMargin: UM.Theme.getSize("default_margin").height - rightMargin: 0 - } + anchors.margins: UM.Theme.getSize("default_margin").width ScrollView { + id: scrollView anchors.fill: parent horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff flickableItem.flickableDirection: Flickable.VerticalFlick + frameVisible: true + + property real columnWidth: Math.floor(viewport.width * 0.5) - UM.Theme.getSize("default_margin").width Flow { id: containerGrid - width: base.width; + x: UM.Theme.getSize("default_margin").width + y: UM.Theme.getSize("default_lining").height - property real rowHeight: textField.height; + width: base.width + property real rowHeight: textField.height + UM.Theme.getSize("default_lining").height - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Display Name") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Display Name") } ReadOnlyTextField { id: displayNameTextField; - width: base.secondColumnWidth; + width: scrollView.columnWidth; text: properties.name; readOnly: !base.editingEnabled; onEditingFinished: base.setName(properties.name, text) } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") } ReadOnlyTextField { id: textField; - width: base.secondColumnWidth; + width: scrollView.columnWidth; text: properties.supplier; readOnly: !base.editingEnabled; onEditingFinished: base.setMetaDataEntry("brand", properties.supplier, text) } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") } ReadOnlyTextField { - width: base.secondColumnWidth; + width: scrollView.columnWidth; text: properties.material_type; readOnly: !base.editingEnabled; onEditingFinished: base.setMetaDataEntry("material", properties.material_type, text) } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } Row { - width: base.secondColumnWidth; + width: scrollView.columnWidth; height: parent.rowHeight; spacing: UM.Theme.getSize("default_margin").width/2 @@ -130,11 +130,11 @@ TabView Label { width: parent.width; height: parent.rowHeight; font.bold: true; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Properties") } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") } ReadOnlySpinBox { id: densitySpinBox - width: base.secondColumnWidth + width: scrollView.columnWidth value: properties.density decimals: 2 suffix: " g/cm³" @@ -145,11 +145,11 @@ TabView onValueChanged: updateCostPerMeter() } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") } ReadOnlySpinBox { id: diameterSpinBox - width: base.secondColumnWidth + width: scrollView.columnWidth value: properties.diameter decimals: 2 suffix: " mm" @@ -160,11 +160,11 @@ TabView onValueChanged: updateCostPerMeter() } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") } SpinBox { id: spoolCostSpinBox - width: base.secondColumnWidth + width: scrollView.columnWidth value: base.getMaterialPreferenceValue(properties.guid, "spool_cost") prefix: base.currency + " " decimals: 2 @@ -176,11 +176,11 @@ TabView } } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") } SpinBox { id: spoolWeightSpinBox - width: base.secondColumnWidth + width: scrollView.columnWidth value: base.getMaterialPreferenceValue(properties.guid, "spool_weight") suffix: " g" stepSize: 100 @@ -193,19 +193,19 @@ TabView } } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") } Label { - width: base.secondColumnWidth + width: scrollView.columnWidth text: "~ %1 m".arg(Math.round(base.spoolLength)) verticalAlignment: Qt.AlignVCenter height: parent.rowHeight } - Label { width: base.firstColumnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter") } + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter") } Label { - width: base.secondColumnWidth + width: scrollView.columnWidth text: "~ %1 %2/m".arg(base.costPerMeter.toFixed(2)).arg(base.currency) verticalAlignment: Qt.AlignVCenter height: parent.rowHeight @@ -214,7 +214,7 @@ TabView Item { width: parent.width; height: UM.Theme.getSize("default_margin").height; visible: unlinkMaterialButton.visible } Label { - width: parent.width + width: 2 * scrollView.columnWidth verticalAlignment: Qt.AlignVCenter text: catalog.i18nc("@label", "This material is linked to %1 and shares some of its properties.").arg(base.linkedMaterialNames) wrapMode: Text.WordWrap @@ -239,7 +239,7 @@ TabView ReadOnlyTextArea { text: properties.description; - width: base.firstColumnWidth + base.secondColumnWidth + width: 2 * scrollView.columnWidth wrapMode: Text.WordWrap readOnly: !base.editingEnabled; @@ -252,13 +252,15 @@ TabView ReadOnlyTextArea { text: properties.adhesion_info; - width: base.firstColumnWidth + base.secondColumnWidth + width: 2 * scrollView.columnWidth wrapMode: Text.WordWrap readOnly: !base.editingEnabled; onEditingFinished: base.setMetaDataEntry("adhesion_info", properties.adhesion_info, text) } + + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } } function updateCostPerMeter() @@ -304,6 +306,7 @@ TabView width: base.firstColumnWidth; height: spinBox.height text: model.label + elide: Text.ElideRight } ReadOnlySpinBox { From f3c2df3ab48475e46c453dc5fefe5f632abe515c Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 8 May 2017 10:22:41 +0200 Subject: [PATCH 06/17] Properly return a string when creating/duplicating a material --- cura/Settings/ContainerManager.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index e9b3518fa3..6c0d1948b2 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -672,6 +672,8 @@ class ContainerManager(QObject): return new_change_instances + ## Create a duplicate of a material, which has the same GUID and base_file metadata + # \return \type{str} the id of the newly created container. @pyqtSlot(str, result = str) def duplicateMaterial(self, material_id: str) -> str: containers = self._container_registry.findInstanceContainers(id=material_id) @@ -694,8 +696,10 @@ class ContainerManager(QObject): duplicated_container.deserialize(f.read()) duplicated_container.setDirty(True) self._container_registry.addContainer(duplicated_container) + return new_id - # Create a new material by cloning Generic PLA and setting the GUID to something unqiue + ## Create a new material by cloning Generic PLA and setting the GUID to something unqiue + # \return \type{str} the id of the newly created container. @pyqtSlot(result = str) def createMaterial(self) -> str: # Ensure all settings are saved. @@ -722,6 +726,7 @@ class ContainerManager(QObject): duplicated_container.setName(catalog.i18nc("@label", "Custom Material")) self._container_registry.addContainer(duplicated_container) + return new_id @pyqtSlot(str, result = "QStringList") def getLinkedMaterials(self, material_id: str): From 00f3cf409b1e2395d988611eec257826bc8f87fd Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 8 May 2017 10:38:25 +0200 Subject: [PATCH 07/17] Select newly created material --- resources/qml/Preferences/MaterialsPage.qml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 7d7b647969..24415a5fc9 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -91,9 +91,11 @@ UM.ManagementPage } activeId: Cura.MachineManager.activeMaterialId - activeIndex: { + activeIndex: getIndexById(activeId) + function getIndexById(material_id) + { for(var i = 0; i < model.rowCount(); i++) { - if (model.getItem(i).id == Cura.MachineManager.activeMaterialId) { + if (model.getItem(i).id == material_id) { return i; } } @@ -149,6 +151,7 @@ UM.ManagementPage { Cura.MachineManager.setActiveMaterial(material_id) } + base.objectList.currentIndex = base.getIndexById(material_id); } }, Button @@ -169,6 +172,7 @@ UM.ManagementPage { Cura.MachineManager.setActiveMaterial(material_id) } + base.objectList.currentIndex = base.getIndexById(material_id); } }, Button From b4f56d10d71f950135a049f5c1930dcbbbf32eb4 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 8 May 2017 11:17:10 +0200 Subject: [PATCH 08/17] Set currentIndex to a more logical successor when deleting a material --- resources/qml/Preferences/MaterialsPage.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 24415a5fc9..7b807d718f 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -272,6 +272,10 @@ UM.ManagementPage { Cura.ContainerManager.removeContainer(containers[i]) } + if(base.objectList.currentIndex > 0) + { + base.objectList.currentIndex--; + } currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. } } From 836cf27266ef273831459ac411642395951fb7c0 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 8 May 2017 11:36:18 +0200 Subject: [PATCH 09/17] Keep material selected when editing its name, brand or type Editing a material name, brand or type may change its position in the materials list. We now reselect the material after editing one of these values. --- resources/qml/Preferences/MaterialView.qml | 13 +++++++++++-- resources/qml/Preferences/MaterialsPage.qml | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index a44b8a0f08..d849007432 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -82,7 +82,11 @@ TabView width: scrollView.columnWidth; text: properties.supplier; readOnly: !base.editingEnabled; - onEditingFinished: base.setMetaDataEntry("brand", properties.supplier, text) + onEditingFinished: + { + base.setMetaDataEntry("brand", properties.supplier, text); + pane.objectList.currentIndex = pane.getIndexById(base.containerId); + } } Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") } @@ -91,7 +95,11 @@ TabView width: scrollView.columnWidth; text: properties.material_type; readOnly: !base.editingEnabled; - onEditingFinished: base.setMetaDataEntry("material", properties.material_type, text) + onEditingFinished: + { + base.setMetaDataEntry("material", properties.material_type, text); + pane.objectList.currentIndex = pane.getIndexById(base.containerId) + } } Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } @@ -419,6 +427,7 @@ TabView Cura.ContainerManager.setContainerName(base.containerId, new_value); // update material name label. not so pretty, but it works materialProperties.name = new_value; + pane.objectList.currentIndex = pane.getIndexById(base.containerId) } } } diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 7b807d718f..ba822b9522 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -227,6 +227,8 @@ UM.ManagementPage properties: materialProperties containerId: base.currentItem != null ? base.currentItem.id : "" + + property alias pane: base } QtObject From eba75a726eece3ebfaa82868c4a8e8ea6ea4b569 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 9 May 2017 12:58:50 +0200 Subject: [PATCH 10/17] Set brand and material to "Custom" so it is less like copying Generic PLA --- cura/Settings/ContainerManager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 6c0d1948b2..4c408806b9 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -723,6 +723,8 @@ class ContainerManager(QObject): duplicated_container.setMetaDataEntry("base_file", new_id) duplicated_container.setMetaDataEntry("GUID", str(uuid.uuid4())) + duplicated_container.setMetaDataEntry("brand", catalog.i18nc("@label", "Custom")) + duplicated_container.setMetaDataEntry("material", catalog.i18nc("@label", "Custom")) duplicated_container.setName(catalog.i18nc("@label", "Custom Material")) self._container_registry.addContainer(duplicated_container) From 8f792b25047f3833e26df5dec917a07acf9c4f4f Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 9 May 2017 13:03:49 +0200 Subject: [PATCH 11/17] Tweak Print Settings layout to match the rest of the UI. --- resources/qml/Preferences/MaterialView.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index d849007432..9290126502 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -312,9 +312,10 @@ TabView { id: label width: base.firstColumnWidth; - height: spinBox.height + height: spinBox.height + UM.Theme.getSize("default_lining").height text: model.label elide: Text.ElideRight + verticalAlignment: Qt.AlignVCenter } ReadOnlySpinBox { From 0d67d42300c51e43d4bf6f6a7ef0db81975bce56 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 11 May 2017 12:53:53 +0200 Subject: [PATCH 12/17] Fix created materials being a linked to themselves --- cura/Settings/ContainerManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index ff83134ce8..24f7c64e7a 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -738,6 +738,7 @@ class ContainerManager(QObject): return [] material_container = containers[0] + material_base_file = material_container.getMetaDataEntry("base_file", "") material_guid = material_container.getMetaDataEntry("GUID", "") if not material_guid: Logger.log("d", "Unable to find materials linked to material with id %s, because it doesn't have a GUID.", material_id) @@ -746,7 +747,7 @@ class ContainerManager(QObject): containers = self._container_registry.findInstanceContainers(type = "material", GUID = material_guid) linked_material_names = [] for container in containers: - if container.getId() == material_id or container.getMetaDataEntry("base_file") != container.getId(): + if container.getId() in [material_id, material_base_file] or container.getMetaDataEntry("base_file") != container.getId(): continue linked_material_names.append(container.getName()) From 5339055f9a38b3fb2e3195f68077af989f4a372c Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 11 May 2017 13:10:32 +0200 Subject: [PATCH 13/17] Fix unlinking materials --- cura/Settings/ContainerManager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 24f7c64e7a..13381221a4 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -721,7 +721,6 @@ class ContainerManager(QObject): with open(containers[0].getPath(), encoding="utf-8") as f: duplicated_container.deserialize(f.read()) - duplicated_container.setMetaDataEntry("base_file", new_id) duplicated_container.setMetaDataEntry("GUID", str(uuid.uuid4())) duplicated_container.setMetaDataEntry("brand", catalog.i18nc("@label", "Custom")) duplicated_container.setMetaDataEntry("material", catalog.i18nc("@label", "Custom")) @@ -760,7 +759,6 @@ class ContainerManager(QObject): Logger.log("d", "Unable to make the material with id %s unique, because it doesn't exist.", material_id) return "" - containers[0].setMetaDataEntry("base_file", material_id) containers[0].setMetaDataEntry("GUID", str(uuid.uuid4())) From 6fa83a91105ca8baccbfb3d4d1374f5cafaa9dc7 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 11 May 2017 13:22:14 +0200 Subject: [PATCH 14/17] Fix selecting a material when an edit field has the focus --- resources/qml/Preferences/MaterialsPage.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index ba822b9522..d4d9a2dec7 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -81,6 +81,7 @@ UM.ManagementPage anchors.fill: parent; onClicked: { + forceActiveFocus(); if(!parent.ListView.isCurrentItem) { parent.ListView.view.currentIndex = index; From 24159aaf6672daa4681a24c35083b3f600ba56c0 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 11 May 2017 14:08:15 +0200 Subject: [PATCH 15/17] Fix activating newly created materials --- cura/Settings/ContainerManager.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 13381221a4..476d0c5b58 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -9,6 +9,7 @@ from typing import Dict, Union from PyQt5.QtCore import QObject, QUrl, QVariant from UM.FlameProfiler import pyqtSlot from PyQt5.QtWidgets import QMessageBox +from UM.Util import parseBool from UM.PluginRegistry import PluginRegistry from UM.SaveFile import SaveFile @@ -696,7 +697,7 @@ class ContainerManager(QObject): duplicated_container.deserialize(f.read()) duplicated_container.setDirty(True) self._container_registry.addContainer(duplicated_container) - return new_id + return self._getMaterialContainerIdForActiveMachine(new_id) ## Create a new material by cloning Generic PLA and setting the GUID to something unqiue # \return \type{str} the id of the newly created container. @@ -727,7 +728,27 @@ class ContainerManager(QObject): duplicated_container.setName(catalog.i18nc("@label", "Custom Material")) self._container_registry.addContainer(duplicated_container) - return new_id + return self._getMaterialContainerIdForActiveMachine(new_id) + + def _getMaterialContainerIdForActiveMachine(self, base_file): + global_stack = Application.getInstance().getGlobalContainerStack() + if not global_stack: + return base_file + + has_machine_materials = parseBool(global_stack.getMetaDataEntry("has_machine_materials", default = False)) + has_variant_materials = parseBool(global_stack.getMetaDataEntry("has_variant_materials", default = False)) + has_variants = parseBool(global_stack.getMetaDataEntry("has_variants", default = False)) + if has_machine_materials or has_variant_materials: + if has_variants: + materials = self._container_registry.findInstanceContainers(type = "material", base_file = base_file, definition = global_stack.getBottom().getId(), variant = self._machine_manager.activeVariantId) + else: + materials = self._container_registry.findInstanceContainers(type = "material", base_file = base_file, definition = global_stack.getBottom().getId()) + + if materials: + return materials[0].getId() + return "" # do not activate a new material if a container can not be found + + return base_file @pyqtSlot(str, result = "QStringList") def getLinkedMaterials(self, material_id: str): From f5347a4593b6eafd5ce6559db98c50b7400f182b Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 11 May 2017 16:37:32 +0200 Subject: [PATCH 16/17] Add documentation and a spot of logging --- cura/Settings/ContainerManager.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 476d0c5b58..6cd3ad0630 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -674,6 +674,7 @@ class ContainerManager(QObject): return new_change_instances ## Create a duplicate of a material, which has the same GUID and base_file metadata + # # \return \type{str} the id of the newly created container. @pyqtSlot(str, result = str) def duplicateMaterial(self, material_id: str) -> str: @@ -700,6 +701,7 @@ class ContainerManager(QObject): return self._getMaterialContainerIdForActiveMachine(new_id) ## Create a new material by cloning Generic PLA and setting the GUID to something unqiue + # # \return \type{str} the id of the newly created container. @pyqtSlot(result = str) def createMaterial(self) -> str: @@ -730,6 +732,10 @@ class ContainerManager(QObject): self._container_registry.addContainer(duplicated_container) return self._getMaterialContainerIdForActiveMachine(new_id) + ## Find the id of a material container based on the new material + # Utilty function that is shared between duplicateMaterial and createMaterial + # + # \param base_file \type{str} the id of the created container. def _getMaterialContainerIdForActiveMachine(self, base_file): global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: @@ -746,10 +752,16 @@ class ContainerManager(QObject): if materials: return materials[0].getId() + + Logger.log("w", "Unable to find a suitable container based on %s for the current machine .", base_file) return "" # do not activate a new material if a container can not be found return base_file + ## Get a list of materials that have the same GUID as the reference material + # + # \param material_id \type{str} the id of the material for which to get the linked materials. + # \return \type{list} a list of names of materials with the same GUID @pyqtSlot(str, result = "QStringList") def getLinkedMaterials(self, material_id: str): containers = self._container_registry.findInstanceContainers(id=material_id) @@ -773,6 +785,8 @@ class ContainerManager(QObject): linked_material_names.append(container.getName()) return linked_material_names + ## Unlink a material from all other materials by creating a new GUID + # \param material_id \type{str} the id of the material to create a new GUID for. @pyqtSlot(str) def unlinkMaterial(self, material_id: str): containers = self._container_registry.findInstanceContainers(id=material_id) From a727e4ffd09d365dfaa3f532c912a952f30e7089 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 11 May 2017 18:16:36 +0200 Subject: [PATCH 17/17] Make sure all materials are shown Without this workaround, some materials that are listed above the generic materials do not show up untill the user scrolls the scrollview. --- resources/qml/Preferences/MaterialsPage.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index d4d9a2dec7..c46b482d10 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -14,6 +14,12 @@ UM.ManagementPage title: catalog.i18nc("@title:tab", "Materials"); + Component.onCompleted: + { + // Workaround to make sure all of the items are visible + objectList.positionViewAtBeginning(); + } + model: UM.InstanceContainersModel { filter: