diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index b1ec388f48..eee0ecabe0 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -54,7 +54,7 @@ from UM.Settings.SettingFunction import SettingFunction from cura.Settings.MachineNameValidator import MachineNameValidator from cura.Machines.Models.NozzleModel import NozzleModel from cura.Settings.ProfilesModel import ProfilesModel, NewQualityProfilesModel, NewCustomQualityProfilesModel -from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel +from cura.Settings.MaterialsModel import MaterialsModel, BrandMaterialsModel, GenericMaterialsModel, NewMaterialsModel from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesModel from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.UserProfilesModel import UserProfilesModel @@ -944,6 +944,7 @@ class CuraApplication(QtApplication): qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") + qmlRegisterType(NewMaterialsModel, "Cura", 1, 0, "NewMaterialsModel") qmlRegisterSingletonType(NewQualityProfilesModel, "Cura", 1, 0, "NewQualityProfilesModel", self.getNewQualityProfileModel) qmlRegisterSingletonType(NewCustomQualityProfilesModel, "Cura", 1, 0, "NewCustomQualityProfilesModel", self.getNewCustomQualityProfilesModel) diff --git a/cura/Settings/MaterialsModel.py b/cura/Settings/MaterialsModel.py index ad3256ba32..f133684032 100644 --- a/cura/Settings/MaterialsModel.py +++ b/cura/Settings/MaterialsModel.py @@ -1,17 +1,16 @@ # Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Any, List -from PyQt5.QtCore import Qt - +from typing import Any, List, Optional +from PyQt5.QtCore import Qt, QObject from UM.Logger import Logger from UM.Qt.ListModel import ListModel -from UM.Settings.ContainerRegistry import ContainerRegistry #To listen for changes to the materials. -from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel #We're extending this class. +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel -def getAvailableMaterials(): +def getAvailableMaterials(extruder_position: Optional[int] = None): from cura.CuraApplication import CuraApplication machine_manager = CuraApplication.getInstance().getMachineManager() extruder_manager = CuraApplication.getInstance().getExtruderManager() @@ -19,18 +18,21 @@ def getAvailableMaterials(): material_manager = CuraApplication.getInstance()._material_manager active_global_stack = machine_manager._global_container_stack - active_extruder_stack = extruder_manager.getActiveExtruderStack() + 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 active_extruder_stack is None: + 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, active_extruder_stack) + active_global_stack, extruder_stack) return machine_definition_id = active_global_stack.definition.getId() variant_name = None - if active_extruder_stack.variant.getId() != "empty_variant": - variant_name = active_extruder_stack.variant.getName() - diameter = active_extruder_stack.getProperty("material_diameter", "value") + if extruder_stack.variant.getId() != "empty_variant": + variant_name = extruder_stack.variant.getName() + diameter = extruder_stack.getProperty("material_diameter", "value") # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. result_dict = material_manager.getAvailableMaterials(machine_definition_id, variant_name, diameter) @@ -44,7 +46,7 @@ class BaseMaterialsModel(ListModel): BrandRole = Qt.UserRole + 4 MaterialRole = Qt.UserRole + 5 ColorRole = Qt.UserRole + 6 - ContainerNodeRole = Qt.UserRole + 6 + ContainerNodeRole = Qt.UserRole + 7 def __init__(self, parent = None): super().__init__(parent) @@ -184,6 +186,90 @@ class BrandMaterialsModel(ListModel): self.setItems(brand_item_list) +# +# This model is for the Material management page. +# +class NewMaterialsModel(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 + + 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") + + from cura.CuraApplication import CuraApplication + machine_manager = CuraApplication.getInstance().getMachineManager() + extruder_manager = CuraApplication.getInstance().getExtruderManager() + material_manager = CuraApplication.getInstance()._material_manager + + machine_manager.globalContainerChanged.connect(self._update) + extruder_manager.activeExtruderChanged.connect(self._update) + material_manager.materialsUpdated.connect(self._update) + + self._update() + + def _update(self): + 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", ""), + } + + 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"], k["name"])) + self.setItems(material_list) + + ## A model that shows a list of currently valid materials. Used by management page. class MaterialsModel(InstanceContainersModel): def __init__(self, parent = None): diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 5fdc8a24eb..50eb3d3e99 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -1,8 +1,8 @@ // Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.1 -import QtQuick.Controls 1.3 +import QtQuick 2.8 +import QtQuick.Controls 1.4 import QtQuick.Dialogs 1.2 import UM 1.2 as UM @@ -357,8 +357,18 @@ TabView onEditingFinished: materialPropertyProvider.setPropertyValue("value", value) } - UM.ContainerPropertyProvider { id: materialPropertyProvider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key } - UM.ContainerPropertyProvider { id: machinePropertyProvider; containerId: Cura.MachineManager.activeDefinitionId; watchedProperties: [ "value" ]; key: model.key } + UM.ContainerPropertyProvider { + id: materialPropertyProvider + containerId: base.containerId + watchedProperties: [ "value" ] + key: model.key + } + UM.ContainerPropertyProvider { + id: machinePropertyProvider + containerId: Cura.MachineManager.activeDefinitionId + watchedProperties: [ "value" ] + key: model.key + } } } } diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 3a72f66cfc..cf8cd959bf 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -1,147 +1,61 @@ -//Copyright (c) 2017 Ultimaker B.V. -//Cura is released under the terms of the LGPLv3 or higher. +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. -import QtQuick 2.1 -import QtQuick.Controls 1.1 -import QtQuick.Dialogs 1.2 +import QtQuick 2.8 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 import UM 1.2 as UM import Cura 1.0 as Cura -UM.ManagementPage + +Item { - id: base; + id: base + property var resetEnabled: false // Keep PreferencesDialog happy - title: catalog.i18nc("@title:tab", "Materials"); + UM.I18nCatalog { id: catalog; name: "cura"; } - Component.onCompleted: - { - // Workaround to make sure all of the items are visible - objectList.positionViewAtBeginning(); + Cura.NewMaterialsModel { + id: materialsModel } - model: Cura.MaterialsModel - { - filter: - { - var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() } - if(Cura.MachineManager.filterMaterialsByMachine) - { - result.definition = Cura.MachineManager.activeQualityDefinitionId; - if(Cura.MachineManager.hasVariants) - { - result.variant_name = Cura.MachineManager.activeQualityVariantName; - } - } - else - { - result.definition = "fdmprinter"; - result.compatible = true; //NB: Only checks for compatibility in global version of material, but we don't have machine-specific materials anyway. - } - return result + Label { + id: titleLabel + + anchors { + top: parent.top + left: parent.left + right: parent.right + margins: 5 * screenScaleFactor } - sectionProperty: "brand" + font.pointSize: 18 + text: catalog.i18nc("@title:tab", "Materials") } - delegate: Rectangle + Row // Button Row { - width: objectList.width; - height: childrenRect.height; - color: isCurrentItem ? palette.highlight : index % 2 ? palette.base : palette.alternateBase - property bool isCurrentItem: ListView.isCurrentItem - - Row - { - spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - Rectangle - { - width: Math.round(parent.height * 0.8) - height: Math.round(parent.height * 0.8) - color: model.metadata.color_code - border.color: isCurrentItem ? palette.highlightedText : palette.text; - anchors.verticalCenter: parent.verticalCenter - } - Label - { - width: Math.round((parent.width * 0.3)) - text: model.metadata.material - elide: Text.ElideRight - font.italic: model.id == activeId - color: isCurrentItem ? palette.highlightedText : palette.text; - } - Label - { - text: (model.name != model.metadata.material) ? model.name : "" - elide: Text.ElideRight - font.italic: model.id == activeId - color: isCurrentItem ? palette.highlightedText : palette.text; - } + id: buttonRow + anchors { + left: parent.left + right: parent.right + top: titleLabel.bottom } - - MouseArea - { - anchors.fill: parent; - onClicked: - { - forceActiveFocus(); - if(!parent.ListView.isCurrentItem) - { - parent.ListView.view.currentIndex = index; - base.itemActivated(); - } - } - } - } - - activeId: Cura.MachineManager.activeMaterialId - activeIndex: getIndexById(activeId) - function getIndexById(material_id) - { - for(var i = 0; i < model.rowCount(); i++) { - if (model.getItem(i).id == material_id) { - return i; - } - } - return -1; - } - - scrollviewCaption: - { - var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; - if (Cura.MachineManager.hasVariants) - { - caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; - } - return caption; - } - detailsVisible: true - - section.property: "section" - section.delegate: Label - { - text: section - font.bold: true - anchors.left: parent.left; - anchors.leftMargin: UM.Theme.getSize("default_lining").width; - } - - buttons: [ + height: childrenRect.height // Activate button Button { text: catalog.i18nc("@action:button", "Activate") - iconName: "list-activate"; - enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials + iconName: "list-activate" + //enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials + enabled: true // TODO onClicked: { forceActiveFocus() Cura.MachineManager.setActiveMaterial(base.currentItem.id) currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. } - }, + } // Create button Button { @@ -149,31 +63,32 @@ UM.ManagementPage iconName: "list-add" onClicked: { forceActiveFocus() - Cura.ContainerManager.createMaterial() + // TODO } - }, + } // Duplicate button Button { text: catalog.i18nc("@action:button", "Duplicate"); - iconName: "list-add"; - enabled: base.currentItem != null + iconName: "list-add" + enabled: true //TODO onClicked: { forceActiveFocus() - Cura.ContainerManager.duplicateOriginalMaterial(base.currentItem.id) + // TODO } - }, + } // Remove button Button { text: catalog.i18nc("@action:button", "Remove") iconName: "list-remove" - enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) + //enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) + enabled: true // TODO onClicked: { forceActiveFocus() - confirmDialog.open() + // TODO } - }, + } // Import button Button { @@ -181,10 +96,10 @@ UM.ManagementPage iconName: "document-import" onClicked: { forceActiveFocus() - importDialog.open() + // TODO } visible: true - }, + } // Export button Button { @@ -192,221 +107,262 @@ UM.ManagementPage iconName: "document-export" onClicked: { forceActiveFocus() - exportDialog.open() + // TODO } enabled: currentItem != null } - - ] + } Item { - visible: base.currentItem != null - anchors.fill: parent + id: contentsItem + + anchors { + top: titleLabel.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + margins: 5 * screenScaleFactor + bottomMargin: 0 + } + + clip: true + } + + Item + { + anchors { + top: buttonRow.bottom + topMargin: UM.Theme.getSize("default_margin").height + left: parent.left + right: parent.right + bottom: parent.bottom + } + + SystemPalette { id: palette } + + Label + { + id: captionLabel + anchors { + top: parent.top + left: parent.left + } + text: "TODO" + width: materialScrollView.width + elide: Text.ElideRight + } + + ScrollView + { + id: materialScrollView + anchors { + top: captionLabel.visible ? captionLabel.bottom : parent.top + topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0 + bottom: parent.bottom + left: parent.left + } + + Rectangle { + parent: viewport + anchors.fill: parent + color: palette.light + } + + width: true ? (parent.width * 0.4) | 0 : parent.width + + ListView + { + id: materialListView + + model: materialsModel + + section.property: "brand" + section.criteria: ViewSection.FullString + section.delegate: Rectangle + { + width: materialScrollView.width + height: childrenRect.height + color: palette.light + + Label + { + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_lining").width + text: section + font.bold: true + color: palette.text + } + } + + delegate: Rectangle + { + width: materialScrollView.width + height: childrenRect.height + color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase + + Row + { + spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + Rectangle + { + width: Math.floor(parent.height * 0.8) + height: Math.floor(parent.height * 0.8) + color: model.color_code + border.color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; + anchors.verticalCenter: parent.verticalCenter + } + Label + { + width: Math.floor((parent.width * 0.3)) + text: model.material + elide: Text.ElideRight + font.italic: { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return model.root_material_id == root_material_id; // TODO + } + color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; + } + Label + { + text: (model.name != model.material) ? model.name : "" + elide: Text.ElideRight + font.italic: { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return model.root_material_id == root_material_id; // TODO + } + color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text; + } + } + + MouseArea + { + anchors.fill: parent + onClicked: { + parent.ListView.view.currentIndex = model.index; + } + } + } + + onCurrentIndexChanged: + { + var model = materialsModel.getItem(currentIndex); + materialDetailsView.containerId = model.container_id; + + detailsPanel.updateMaterialPropertiesObject(); + } + } + } + Item { - id: profileName + id: detailsPanel - width: parent.width; - height: childrenRect.height - - Label { text: materialProperties.name; font: UM.Theme.getFont("large"); } - } - - MaterialView - { - anchors - { - left: parent.left - right: parent.right - top: profileName.bottom - topMargin: UM.Theme.getSize("default_margin").height + anchors { + left: materialScrollView.right + leftMargin: UM.Theme.getSize("default_margin").width + top: parent.top bottom: parent.bottom + right: parent.right } - editingEnabled: base.currentItem != null && !base.currentItem.readOnly - - properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.id : "" - - property alias pane: base - } - - QtObject - { - id: materialProperties - - property string guid: "00000000-0000-0000-0000-000000000000" - property string name: "Unknown"; - property string profile_type: "Unknown"; - property string supplier: "Unknown"; - property string material_type: "Unknown"; - - property string color_name: "Yellow"; - property color color_code: "yellow"; - - property real density: 0.0; - property real diameter: 0.0; - property string approximate_diameter: "0"; - - property real spool_cost: 0.0; - property real spool_weight: 0.0; - property real spool_length: 0.0; - property real cost_per_meter: 0.0; - - property string description: ""; - property string adhesion_info: ""; - } - - UM.ConfirmRemoveDialog - { - id: confirmDialog - object: base.currentItem != null ? base.currentItem.name : "" - onYes: + function updateMaterialPropertiesObject() { - // A material container can actually be multiple items, so we need to find (and remove) all of them. - var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file") - if(base_file == "") - { - base_file = base.currentItem.id - } - var guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID") - // remove base container first, it otherwise triggers loading the base file while removing other containers - var base_containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "id": base_file, "base_file": base_file, "type": "material"}) - for(var i in base_containers) - { - Cura.ContainerManager.removeContainer(base_containers[i]); - } - var containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "base_file": base_file, "type": "material"}) - for(var i in containers) - { - Cura.ContainerManager.removeContainer(containers[i]); - } - if(base.objectList.currentIndex > 0) - { - base.objectList.currentIndex--; - } - currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. - } - } + var currentItem = materialsModel.getItem(materialListView.currentIndex); - FileDialog - { - id: importDialog; - title: catalog.i18nc("@title:window", "Import Material"); - selectExisting: true; - nameFilters: Cura.ContainerManager.getContainerNameFilters("material") - folder: CuraApplication.getDefaultPath("dialog_material_path") - onAccepted: - { - var result = Cura.ContainerManager.importMaterialContainer(fileUrl) + materialProperties.name = currentItem.name; + materialProperties.guid = currentItem.guid; - messageDialog.title = catalog.i18nc("@title:window", "Import Material") - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags or !", "Could not import material %1: %2").arg(fileUrl).arg(result.message) - if(result.status == "success") + materialProperties.supplier = currentItem.brand ? currentItem.brand : "Unknown"; + materialProperties.material_type = currentItem.material ? currentItem.material : "Unknown"; + materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; + materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; + + materialProperties.description = currentItem.description ? currentItem.description : ""; + materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; + + if(currentItem.properties != undefined && currentItem.properties != null) { - messageDialog.icon = StandardIcon.Information - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl) - } - else if(result.status == "duplicate") - { - messageDialog.icon = StandardIcon.Warning + materialProperties.density = currentItem.density ? currentItem.density : 0.0; + materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; + materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; } else { - messageDialog.icon = StandardIcon.Critical + materialProperties.density = 0.0; + materialProperties.diameter = 0.0; + materialProperties.approximate_diameter = "0"; } - messageDialog.open() - CuraApplication.setDefaultPath("dialog_material_path", folder) } - } - FileDialog - { - id: exportDialog; - title: catalog.i18nc("@title:window", "Export Material"); - selectExisting: false; - nameFilters: Cura.ContainerManager.getContainerNameFilters("material") - folder: CuraApplication.getDefaultPath("dialog_material_path") - onAccepted: + Item { - if(base.currentItem.metadata.base_file) + anchors.fill: parent + + Item // Material title Label { - var result = Cura.ContainerManager.exportContainer(base.currentItem.metadata.base_file, selectedNameFilter, fileUrl) - } - else - { - var result = Cura.ContainerManager.exportContainer(base.currentItem.id, selectedNameFilter, fileUrl) + id: profileName + + width: parent.width + height: childrenRect.height + + Label { + text: materialProperties.name + font: UM.Theme.getFont("large") + } } - messageDialog.title = catalog.i18nc("@title:window", "Export Material") - if(result.status == "error") + MaterialView // Material detailed information view below the title Label { - messageDialog.icon = StandardIcon.Critical - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags and !", "Failed to export material to %1: %2").arg(fileUrl).arg(result.message) - messageDialog.open() + id: materialDetailsView + anchors + { + left: parent.left + right: parent.right + top: profileName.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: parent.bottom + } + + editingEnabled: base.currentItem != null && !base.currentItem.readOnly + + properties: materialProperties + containerId: base.currentItem != null ? base.currentItem.id : "" + + property alias pane: base } - else if(result.status == "success") + + QtObject { - messageDialog.icon = StandardIcon.Information - messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully exported material to %1").arg(result.path) - messageDialog.open() + id: materialProperties + + property string guid: "00000000-0000-0000-0000-000000000000" + property string name: "Unknown"; + property string profile_type: "Unknown"; + property string supplier: "Unknown"; + property string material_type: "Unknown"; + + property string color_name: "Yellow"; + property color color_code: "yellow"; + + property real density: 0.0; + property real diameter: 0.0; + property string approximate_diameter: "0"; + + property real spool_cost: 0.0; + property real spool_weight: 0.0; + property real spool_length: 0.0; + property real cost_per_meter: 0.0; + + property string description: ""; + property string adhesion_info: ""; } - CuraApplication.setDefaultPath("dialog_material_path", folder) } } - - MessageDialog - { - id: messageDialog - } - - UM.SettingPropertyProvider - { - id: materialDiameterProvider - - containerStackId: Cura.ExtruderManager.activeExtruderStackId - key: "material_diameter" - watchedProperties: [ "value" ] - storeIndex: 5 - } - - UM.I18nCatalog { id: catalog; name: "cura"; } - SystemPalette { id: palette } - } - - onCurrentItemChanged: - { - if(currentItem == null) - { - return - } - materialProperties.name = currentItem.name; - materialProperties.guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID"); - - if(currentItem.metadata != undefined && currentItem.metadata != null) - { - materialProperties.supplier = currentItem.metadata.brand ? currentItem.metadata.brand : "Unknown"; - materialProperties.material_type = currentItem.metadata.material ? currentItem.metadata.material : "Unknown"; - materialProperties.color_name = currentItem.metadata.color_name ? currentItem.metadata.color_name : "Yellow"; - materialProperties.color_code = currentItem.metadata.color_code ? currentItem.metadata.color_code : "yellow"; - - materialProperties.description = currentItem.metadata.description ? currentItem.metadata.description : ""; - materialProperties.adhesion_info = currentItem.metadata.adhesion_info ? currentItem.metadata.adhesion_info : ""; - - if(currentItem.metadata.properties != undefined && currentItem.metadata.properties != null) - { - materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0; - materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0; - materialProperties.approximate_diameter = currentItem.metadata.approximate_diameter ? currentItem.metadata.approximate_diameter : "0"; - } - else - { - materialProperties.density = 0.0; - materialProperties.diameter = 0.0; - materialProperties.approximate_diameter = "0"; - } - - } } } diff --git a/resources/qml/Preferences/OldMaterialView.qml b/resources/qml/Preferences/OldMaterialView.qml new file mode 100644 index 0000000000..1b3a3b93a8 --- /dev/null +++ b/resources/qml/Preferences/OldMaterialView.qml @@ -0,0 +1,467 @@ +// Copyright (c) 2017 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.8 +import QtQuick.Controls 1.4 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +TabView +{ + id: base + + property QtObject properties; + + property bool editingEnabled: false; + property string currency: UM.Preferences.getValue("cura/currency") ? UM.Preferences.getValue("cura/currency") : "€" + property real firstColumnWidth: (width * 0.50) | 0 + 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 double spoolLength: calculateSpoolLength() + property real costPerMeter: calculateCostPerMeter() + + property bool reevaluateLinkedMaterials: false + property string linkedMaterialNames: + { + if (reevaluateLinkedMaterials) + { + reevaluateLinkedMaterials = false; + } + if(!base.containerId || !base.editingEnabled) + { + return "" + } + var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.containerId); + return linkedMaterials.join(", "); + } + + Tab + { + title: catalog.i18nc("@title", "Information") + + 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: (viewport.width * 0.5 - UM.Theme.getSize("default_margin").width) | 0 + + Flow + { + id: containerGrid + + x: UM.Theme.getSize("default_margin").width + y: UM.Theme.getSize("default_lining").height + + width: base.width + property real rowHeight: textField.height + UM.Theme.getSize("default_lining").height + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Display Name") } + ReadOnlyTextField + { + id: displayNameTextField; + width: scrollView.columnWidth; + text: properties.name; + readOnly: !base.editingEnabled; + onEditingFinished: base.updateMaterialDisplayName(properties.name, text) + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") } + ReadOnlyTextField + { + id: textField; + width: scrollView.columnWidth; + text: properties.supplier; + readOnly: !base.editingEnabled; + onEditingFinished: base.updateMaterialSupplier(properties.supplier, text) + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") } + ReadOnlyTextField + { + width: scrollView.columnWidth; + text: properties.material_type; + readOnly: !base.editingEnabled; + onEditingFinished: base.updateMaterialType(properties.material_type, text) + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } + Row { + width: scrollView.columnWidth + height: parent.rowHeight + spacing: Math.floor(UM.Theme.getSize("default_margin").width / 2) + + // color indicator square + Rectangle { + id: colorSelector + color: properties.color_code + + width: Math.floor(colorLabel.height * 0.75) + height: Math.floor(colorLabel.height * 0.75) + border.width: UM.Theme.getSize("default_lining").height + + anchors.verticalCenter: parent.verticalCenter + + // open the color selection dialog on click + MouseArea { + anchors.fill: parent + onClicked: colorDialog.open() + enabled: base.editingEnabled + } + } + + // pretty color name text field + ReadOnlyTextField { + id: colorLabel; + text: properties.color_name; + readOnly: !base.editingEnabled + onEditingFinished: base.setMetaDataEntry("color_name", properties.color_name, text) + } + + // popup dialog to select a new color + // if successful it sets the properties.color_code value to the new color + ColorDialog { + id: colorDialog + color: properties.color_code + onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color) + } + } + + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } + + Label { width: parent.width; height: parent.rowHeight; font.bold: true; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Properties") } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") } + ReadOnlySpinBox + { + id: densitySpinBox + width: scrollView.columnWidth + value: properties.density + decimals: 2 + suffix: " g/cm³" + stepSize: 0.01 + readOnly: !base.editingEnabled + + onEditingFinished: base.setMetaDataEntry("properties/density", properties.density, value) + onValueChanged: updateCostPerMeter() + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") } + ReadOnlySpinBox + { + id: diameterSpinBox + width: scrollView.columnWidth + value: properties.diameter + decimals: 2 + suffix: " mm" + stepSize: 0.01 + readOnly: !base.editingEnabled + + onEditingFinished: + { + // This does not use a SettingPropertyProvider, because we need to make the change to all containers + // which derive from the same base_file + var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString(); + var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); + base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, Math.round(value).toString()); + base.setMetaDataEntry("properties/diameter", properties.diameter, value); + var new_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter"); + if (Cura.MachineManager.filterMaterialsByMachine && new_approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) + { + Cura.MaterialManager.showMaterialWarningMessage(base.containerId, old_diameter); + } + Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value); + } + onValueChanged: updateCostPerMeter() + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") } + SpinBox + { + id: spoolCostSpinBox + width: scrollView.columnWidth + value: base.getMaterialPreferenceValue(properties.guid, "spool_cost") + prefix: base.currency + " " + decimals: 2 + maximumValue: 100000000 + + onValueChanged: { + base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value)) + updateCostPerMeter() + } + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") } + SpinBox + { + id: spoolWeightSpinBox + width: scrollView.columnWidth + value: base.getMaterialPreferenceValue(properties.guid, "spool_weight") + suffix: " g" + stepSize: 100 + decimals: 0 + maximumValue: 10000 + + onValueChanged: { + base.setMaterialPreferenceValue(properties.guid, "spool_weight", parseFloat(value)) + updateCostPerMeter() + } + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") } + Label + { + width: scrollView.columnWidth + text: "~ %1 m".arg(Math.round(base.spoolLength)) + verticalAlignment: Qt.AlignVCenter + height: parent.rowHeight + } + + Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter") } + Label + { + width: scrollView.columnWidth + text: "~ %1 %2/m".arg(base.costPerMeter.toFixed(2)).arg(base.currency) + verticalAlignment: Qt.AlignVCenter + height: parent.rowHeight + } + + Item { width: parent.width; height: UM.Theme.getSize("default_margin").height; visible: unlinkMaterialButton.visible } + Label + { + 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 + visible: unlinkMaterialButton.visible + } + Button + { + id: unlinkMaterialButton + text: catalog.i18nc("@label", "Unlink Material") + visible: base.linkedMaterialNames != "" + onClicked: + { + Cura.ContainerManager.unlinkMaterial(base.containerId) + base.reevaluateLinkedMaterials = true + } + } + + 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") } + + ReadOnlyTextArea + { + text: properties.description; + width: 2 * scrollView.columnWidth + wrapMode: Text.WordWrap + + readOnly: !base.editingEnabled; + + onEditingFinished: base.setMetaDataEntry("description", properties.description, text) + } + + Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Adhesion Information") } + + ReadOnlyTextArea + { + text: properties.adhesion_info; + 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() + { + base.spoolLength = calculateSpoolLength(diameterSpinBox.value, densitySpinBox.value, spoolWeightSpinBox.value); + base.costPerMeter = calculateCostPerMeter(spoolCostSpinBox.value); + } + } + } + + Tab + { + title: catalog.i18nc("@label", "Print settings") + anchors + { + leftMargin: UM.Theme.getSize("default_margin").width + topMargin: UM.Theme.getSize("default_margin").height + bottomMargin: UM.Theme.getSize("default_margin").height + rightMargin: 0 + } + + ScrollView + { + anchors.fill: parent; + + ListView + { + model: UM.SettingDefinitionsModel + { + containerId: Cura.MachineManager.activeDefinitionId + visibilityHandler: Cura.MaterialSettingsVisibilityHandler { } + expanded: ["*"] + } + + delegate: UM.TooltipArea + { + width: childrenRect.width + height: childrenRect.height + text: model.description + Label + { + id: label + width: base.firstColumnWidth; + height: spinBox.height + UM.Theme.getSize("default_lining").height + text: model.label + elide: Text.ElideRight + verticalAlignment: Qt.AlignVCenter + } + ReadOnlySpinBox + { + id: spinBox + anchors.left: label.right + value: { + if (!isNaN(parseFloat(materialPropertyProvider.properties.value))) + { + return parseFloat(materialPropertyProvider.properties.value); + } + if (!isNaN(parseFloat(machinePropertyProvider.properties.value))) + { + return parseFloat(machinePropertyProvider.properties.value); + } + return 0; + } + width: base.secondColumnWidth + readOnly: !base.editingEnabled + suffix: " " + model.unit + maximumValue: 99999 + decimals: model.unit == "mm" ? 2 : 0 + + onEditingFinished: materialPropertyProvider.setPropertyValue("value", value) + } + + UM.ContainerPropertyProvider { id: materialPropertyProvider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key } + UM.ContainerPropertyProvider { id: machinePropertyProvider; containerId: Cura.MachineManager.activeDefinitionId; watchedProperties: [ "value" ]; key: model.key } + } + } + } + } + + function calculateSpoolLength(diameter, density, spoolWeight) + { + if(!diameter) + { + diameter = properties.diameter; + } + if(!density) + { + density = properties.density; + } + if(!spoolWeight) + { + spoolWeight = base.getMaterialPreferenceValue(properties.guid, "spool_weight"); + } + + if (diameter == 0 || density == 0 || spoolWeight == 0) + { + return 0; + } + var area = Math.PI * Math.pow(diameter / 2, 2); // in mm2 + var volume = (spoolWeight / density); // in cm3 + return volume / area; // in m + } + + function calculateCostPerMeter(spoolCost) + { + if(!spoolCost) + { + spoolCost = base.getMaterialPreferenceValue(properties.guid, "spool_cost"); + } + + if (spoolLength == 0) + { + return 0; + } + return spoolCost / spoolLength; + } + + // Tiny convenience function to check if a value really changed before trying to set it. + function setMetaDataEntry(entry_name, old_value, new_value) { + if (old_value != new_value) { + Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, entry_name, new_value) + // make sure the UI properties are updated as well since we don't re-fetch the entire model here + // When the entry_name is something like properties/diameter, we take the last part of the entry_name + var list = entry_name.split("/") + var key = list[list.length - 1] + properties[key] = new_value + } + } + + function setMaterialPreferenceValue(material_guid, entry_name, new_value) + { + if(!(material_guid in materialPreferenceValues)) + { + materialPreferenceValues[material_guid] = {}; + } + if(entry_name in materialPreferenceValues[material_guid] && materialPreferenceValues[material_guid][entry_name] == new_value) + { + // value has not changed + return + } + materialPreferenceValues[material_guid][entry_name] = new_value; + + // store preference + UM.Preferences.setValue("cura/material_settings", JSON.stringify(materialPreferenceValues)); + } + + function getMaterialPreferenceValue(material_guid, entry_name) + { + if(material_guid in materialPreferenceValues && entry_name in materialPreferenceValues[material_guid]) + { + return materialPreferenceValues[material_guid][entry_name]; + } + return 0; + } + + // update the display name of the material + function updateMaterialDisplayName (old_name, new_name) { + + // don't change when new name is the same + if (old_name == new_name) { + return + } + + // update the values + Cura.ContainerManager.setContainerName(base.containerId, new_name) + materialProperties.name = new_name + } + + // update the type of the material + function updateMaterialType (old_type, new_type) { + base.setMetaDataEntry("material", old_type, new_type) + materialProperties.material_type = new_type + } + + // update the supplier of the material + function updateMaterialSupplier (old_supplier, new_supplier) { + base.setMetaDataEntry("brand", old_supplier, new_supplier) + materialProperties.supplier = new_supplier + } +} diff --git a/resources/qml/Preferences/OldMaterialsPage.qml b/resources/qml/Preferences/OldMaterialsPage.qml new file mode 100644 index 0000000000..0a24b9c663 --- /dev/null +++ b/resources/qml/Preferences/OldMaterialsPage.qml @@ -0,0 +1,412 @@ +//Copyright (c) 2017 Ultimaker B.V. +//Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.8 +import QtQuick.Controls 1.4 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + + +UM.ManagementPage +{ + id: base + title: catalog.i18nc("@title:tab", "Materials") + + Component.onCompleted: + { + // Workaround to make sure all of the items are visible + objectList.positionViewAtBeginning(); + } + + model: Cura.MaterialsModel + { + filter: + { + var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() } + if(Cura.MachineManager.filterMaterialsByMachine) + { + result.definition = Cura.MachineManager.activeQualityDefinitionId; + if(Cura.MachineManager.hasVariants) + { + result.variant_name = Cura.MachineManager.activeQualityVariantName; + } + } + else + { + result.definition = "fdmprinter"; + result.compatible = true; //NB: Only checks for compatibility in global version of material, but we don't have machine-specific materials anyway. + } + return result + } + + sectionProperty: "brand" + } + + delegate: Rectangle + { + width: objectList.width; + height: childrenRect.height; + color: isCurrentItem ? palette.highlight : index % 2 ? palette.base : palette.alternateBase + property bool isCurrentItem: ListView.isCurrentItem + + Row + { + spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + Rectangle + { + width: Math.floor(parent.height * 0.8) + height: Math.floor(parent.height * 0.8) + color: model.metadata.color_code + border.color: isCurrentItem ? palette.highlightedText : palette.text; + anchors.verticalCenter: parent.verticalCenter + } + Label + { + width: Math.floor((parent.width * 0.3)) + text: model.metadata.material + elide: Text.ElideRight + font.italic: model.id == activeId + color: isCurrentItem ? palette.highlightedText : palette.text; + } + Label + { + text: (model.name != model.metadata.material) ? model.name : "" + elide: Text.ElideRight + font.italic: model.id == activeId + color: isCurrentItem ? palette.highlightedText : palette.text; + } + } + + MouseArea + { + anchors.fill: parent; + onClicked: + { + forceActiveFocus(); + if(!parent.ListView.isCurrentItem) + { + parent.ListView.view.currentIndex = index; + base.itemActivated(); + } + } + } + } + + activeId: Cura.MachineManager.activeMaterialId + activeIndex: getIndexById(activeId) + function getIndexById(material_id) + { + for(var i = 0; i < model.rowCount(); i++) { + if (model.getItem(i).id == material_id) { + return i; + } + } + return -1; + } + + scrollviewCaption: + { + var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; + if (Cura.MachineManager.hasVariants) + { + caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; + } + return caption; + } + detailsVisible: true + + section.property: "section" + section.delegate: Label + { + text: section + font.bold: true + anchors.left: parent.left; + anchors.leftMargin: UM.Theme.getSize("default_lining").width; + } + + buttons: [ + + // Activate button + Button { + text: catalog.i18nc("@action:button", "Activate") + iconName: "list-activate"; + enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials + onClicked: { + forceActiveFocus() + Cura.MachineManager.setActiveMaterial(base.currentItem.id) + currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. + } + }, + + // Create button + Button { + text: catalog.i18nc("@action:button", "Create") + iconName: "list-add" + onClicked: { + forceActiveFocus() + Cura.ContainerManager.createMaterial() + } + }, + + // Duplicate button + Button { + text: catalog.i18nc("@action:button", "Duplicate"); + iconName: "list-add"; + enabled: base.currentItem != null + onClicked: { + forceActiveFocus() + Cura.ContainerManager.duplicateOriginalMaterial(base.currentItem.id) + } + }, + + // Remove button + Button { + text: catalog.i18nc("@action:button", "Remove") + iconName: "list-remove" + enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) + onClicked: { + forceActiveFocus() + confirmDialog.open() + } + }, + + // Import button + Button { + text: catalog.i18nc("@action:button", "Import") + iconName: "document-import" + onClicked: { + forceActiveFocus() + importDialog.open() + } + visible: true + }, + + // Export button + Button { + text: catalog.i18nc("@action:button", "Export") + iconName: "document-export" + onClicked: { + forceActiveFocus() + exportDialog.open() + } + enabled: currentItem != null + } + + ] + + Item { + visible: base.currentItem != null + anchors.fill: parent + + Item // Material title Label + { + id: profileName + + width: parent.width; + height: childrenRect.height + + Label { text: materialProperties.name; font: UM.Theme.getFont("large"); } + } + + MaterialView // Material detailed information view below the title Label + { + anchors + { + left: parent.left + right: parent.right + top: profileName.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: parent.bottom + } + + editingEnabled: base.currentItem != null && !base.currentItem.readOnly + + properties: materialProperties + containerId: base.currentItem != null ? base.currentItem.id : "" + + property alias pane: base + } + + QtObject + { + id: materialProperties + + property string guid: "00000000-0000-0000-0000-000000000000" + property string name: "Unknown"; + property string profile_type: "Unknown"; + property string supplier: "Unknown"; + property string material_type: "Unknown"; + + property string color_name: "Yellow"; + property color color_code: "yellow"; + + property real density: 0.0; + property real diameter: 0.0; + property string approximate_diameter: "0"; + + property real spool_cost: 0.0; + property real spool_weight: 0.0; + property real spool_length: 0.0; + property real cost_per_meter: 0.0; + + property string description: ""; + property string adhesion_info: ""; + } + + UM.ConfirmRemoveDialog + { + id: confirmDialog + object: base.currentItem != null ? base.currentItem.name : "" + onYes: + { + // A material container can actually be multiple items, so we need to find (and remove) all of them. + var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file") + if(base_file == "") + { + base_file = base.currentItem.id + } + var guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID") + // remove base container first, it otherwise triggers loading the base file while removing other containers + var base_containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "id": base_file, "base_file": base_file, "type": "material"}) + for(var i in base_containers) + { + Cura.ContainerManager.removeContainer(base_containers[i]); + } + var containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "base_file": base_file, "type": "material"}) + for(var i in containers) + { + Cura.ContainerManager.removeContainer(containers[i]); + } + if(base.objectList.currentIndex > 0) + { + base.objectList.currentIndex--; + } + currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. + } + } + + FileDialog + { + id: importDialog; + title: catalog.i18nc("@title:window", "Import Material"); + selectExisting: true; + nameFilters: Cura.ContainerManager.getContainerNameFilters("material") + folder: CuraApplication.getDefaultPath("dialog_material_path") + onAccepted: + { + var result = Cura.ContainerManager.importMaterialContainer(fileUrl) + + messageDialog.title = catalog.i18nc("@title:window", "Import Material") + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags or !", "Could not import material %1: %2").arg(fileUrl).arg(result.message) + if(result.status == "success") + { + messageDialog.icon = StandardIcon.Information + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl) + } + else if(result.status == "duplicate") + { + messageDialog.icon = StandardIcon.Warning + } + else + { + messageDialog.icon = StandardIcon.Critical + } + messageDialog.open() + CuraApplication.setDefaultPath("dialog_material_path", folder) + } + } + + FileDialog + { + id: exportDialog; + title: catalog.i18nc("@title:window", "Export Material"); + selectExisting: false; + nameFilters: Cura.ContainerManager.getContainerNameFilters("material") + folder: CuraApplication.getDefaultPath("dialog_material_path") + onAccepted: + { + if(base.currentItem.metadata.base_file) + { + var result = Cura.ContainerManager.exportContainer(base.currentItem.metadata.base_file, selectedNameFilter, fileUrl) + } + else + { + var result = Cura.ContainerManager.exportContainer(base.currentItem.id, selectedNameFilter, fileUrl) + } + + messageDialog.title = catalog.i18nc("@title:window", "Export Material") + if(result.status == "error") + { + messageDialog.icon = StandardIcon.Critical + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags and !", "Failed to export material to %1: %2").arg(fileUrl).arg(result.message) + messageDialog.open() + } + else if(result.status == "success") + { + messageDialog.icon = StandardIcon.Information + messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully exported material to %1").arg(result.path) + messageDialog.open() + } + CuraApplication.setDefaultPath("dialog_material_path", folder) + } + } + + MessageDialog + { + id: messageDialog + } + + UM.SettingPropertyProvider + { + id: materialDiameterProvider + + containerStackId: Cura.ExtruderManager.activeExtruderStackId + key: "material_diameter" + watchedProperties: [ "value" ] + storeIndex: 5 + } + + UM.I18nCatalog { id: catalog; name: "cura"; } + SystemPalette { id: palette } + } + + onCurrentItemChanged: + { + if(currentItem == null) + { + return + } + materialProperties.name = currentItem.name; + materialProperties.guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID"); + + if(currentItem.metadata != undefined && currentItem.metadata != null) + { + materialProperties.supplier = currentItem.metadata.brand ? currentItem.metadata.brand : "Unknown"; + materialProperties.material_type = currentItem.metadata.material ? currentItem.metadata.material : "Unknown"; + materialProperties.color_name = currentItem.metadata.color_name ? currentItem.metadata.color_name : "Yellow"; + materialProperties.color_code = currentItem.metadata.color_code ? currentItem.metadata.color_code : "yellow"; + + materialProperties.description = currentItem.metadata.description ? currentItem.metadata.description : ""; + materialProperties.adhesion_info = currentItem.metadata.adhesion_info ? currentItem.metadata.adhesion_info : ""; + + if(currentItem.metadata.properties != undefined && currentItem.metadata.properties != null) + { + materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0; + materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0; + materialProperties.approximate_diameter = currentItem.metadata.approximate_diameter ? currentItem.metadata.approximate_diameter : "0"; + } + else + { + materialProperties.density = 0.0; + materialProperties.diameter = 0.0; + materialProperties.approximate_diameter = "0"; + } + + } + } +}