// Copyright (c) 2022 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 import QtQuick.Controls 2.15 import QtQuick.Dialogs 1.2 import UM 1.5 as UM import Cura 1.5 as Cura UM.ManagementPage { id: base // Keep PreferencesDialog happy property var resetEnabled: false property var currentItem: null property var materialManagementModel: CuraApplication.getMaterialManagementModel() property var hasCurrentItem: base.currentItem != null property var isCurrentItemActivated: { if (!hasCurrentItem) { return false } const extruder_position = Cura.ExtruderManager.activeExtruderIndex const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position] return base.currentItem.root_material_id == root_material_id } property string newRootMaterialIdToSwitchTo: "" property bool toActivateNewMaterial: false property var extruder_position: Cura.ExtruderManager.activeExtruderIndex property var active_root_material_id: Cura.MachineManager.currentRootMaterialId[extruder_position] function resetExpandedActiveMaterial() { materialListView.expandActiveMaterial(active_root_material_id) } function setExpandedActiveMaterial(root_material_id) { materialListView.expandActiveMaterial(root_material_id) } // When loaded, try to select the active material in the tree Component.onCompleted: { resetExpandedActiveMaterial() base.newRootMaterialIdToSwitchTo = active_root_material_id } // Every time the selected item has changed, notify to the details panel onCurrentItemChanged: { forceActiveFocus() if(materialDetailsPanel.currentItem != currentItem) { materialDetailsPanel.currentItem = currentItem // CURA-6679 If the current item is gone after the model update, reset the current item to the active material. if (currentItem == null) { resetExpandedActiveMaterial() } } } title: catalog.i18nc("@title:tab", "Materials") detailsPlaneCation: currentItem.name scrollviewCaption: catalog.i18nc("@label", "Materials compatible with active printer:") + `
${Cura.MachineManager.activeMachine.name}` buttons: [ Cura.SecondaryButton { id: createMenuButton text: catalog.i18nc("@action:button", "Create new") enabled: Cura.MachineManager.activeMachine.hasMaterials onClicked: { forceActiveFocus(); base.newRootMaterialIdToSwitchTo = base.materialManagementModel.createMaterial(); base.toActivateNewMaterial = true; } }, Cura.SecondaryButton { id: importMenuButton text: catalog.i18nc("@action:button", "Import") onClicked: { forceActiveFocus(); importMaterialDialog.open(); } enabled: Cura.MachineManager.activeMachine.hasMaterials }, Cura.SecondaryButton { id: syncMaterialsButton text: catalog.i18nc("@action:button", "Sync with Printers") onClicked: { forceActiveFocus(); base.materialManagementModel.openSyncAllWindow(); } visible: Cura.MachineManager.activeMachine.supportsMaterialExport } ] onHamburgeButtonClicked: { const hamburerButtonHeight = hamburger_button.height; menu.popup(hamburger_button, -menu.width + hamburger_button.width / 2, hamburger_button.height); // for some reason the height of the hamburger changes when opening the popup // reset height to initial heigt hamburger_button.height = hamburerButtonHeight; } listContent: ScrollView { id: materialScrollView anchors.fill: parent anchors.margins: parent.border.width width: (parent.width * 0.4) | 0 clip: true ScrollBar.vertical: UM.ScrollBar { id: materialScrollBar parent: materialScrollView anchors { top: parent.top right: parent.right bottom: parent.bottom } } contentHeight: materialListView.height //For some reason, this is not determined automatically with this ScrollView. Very weird! MaterialsList { id: materialListView width: materialScrollView.width - materialScrollBar.width } } MaterialsDetailsPanel { id: materialDetailsPanel anchors.fill: parent } Item { Cura.Menu { id: menu Cura.MenuItem { id: activateMenuButton text: catalog.i18nc("@action:button", "Activate") onClicked: { forceActiveFocus() // Set the current material as the one to be activated (needed to force the UI update) base.newRootMaterialIdToSwitchTo = base.currentItem.root_material_id const extruder_position = Cura.ExtruderManager.activeExtruderIndex Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node) } } Cura.MenuItem { id: duplicateMenuButton text: catalog.i18nc("@action:button", "Duplicate"); enabled: base.hasCurrentItem onClicked: { forceActiveFocus(); base.newRootMaterialIdToSwitchTo = base.materialManagementModel.duplicateMaterial(base.currentItem.container_node); base.toActivateNewMaterial = true; } } Cura.MenuItem { id: removeMenuButton text: catalog.i18nc("@action:button", "Remove") enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManagementModel.canMaterialBeRemoved(base.currentItem.container_node) onClicked: { forceActiveFocus(); confirmRemoveMaterialDialog.open(); } } Cura.MenuItem { id: exportMenuButton text: catalog.i18nc("@action:button", "Export") onClicked: { forceActiveFocus(); exportMaterialDialog.open(); } enabled: base.hasCurrentItem } } // Dialogs Cura.MessageDialog { id: confirmRemoveMaterialDialog title: catalog.i18nc("@title:window", "Confirm Remove") property string materialName: base.currentItem !== null ? base.currentItem.name : "" text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(materialName) standardButtons: Dialog.Yes | Dialog.No onAccepted: { // Set the active material as the fallback. It will be selected when the current material is deleted base.newRootMaterialIdToSwitchTo = base.active_root_material_id base.materialManagementModel.removeMaterial(base.currentItem.container_node); } } FileDialog { id: importMaterialDialog title: catalog.i18nc("@title:window", "Import Material") selectExisting: true nameFilters: Cura.ContainerManager.getContainerNameFilters("material") folder: CuraApplication.getDefaultPath("dialog_material_path") onAccepted: { const result = Cura.ContainerManager.importMaterialContainer(fileUrl); const messageDialog = Qt.createQmlObject("import Cura 1.5 as Cura; Cura.MessageDialog { onClosed: destroy() }", base); messageDialog.standardButtons = Dialog.Ok; messageDialog.title = catalog.i18nc("@title:window", "Import Material"); switch (result.status) { case "success": messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl); break; default: messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags or !", "Could not import material %1: %2").arg(fileUrl).arg(result.message); break; } messageDialog.open(); CuraApplication.setDefaultPath("dialog_material_path", folder); } } FileDialog { id: exportMaterialDialog title: catalog.i18nc("@title:window", "Export Material") selectExisting: false nameFilters: Cura.ContainerManager.getContainerNameFilters("material") folder: CuraApplication.getDefaultPath("dialog_material_path") onAccepted: { const result = Cura.ContainerManager.exportContainer(base.currentItem.root_material_id, selectedNameFilter, fileUrl); const messageDialog = Qt.createQmlObject("import Cura 1.5 as Cura; Cura.MessageDialog { onClosed: destroy() }", base); messageDialog.title = catalog.i18nc("@title:window", "Export Material"); messageDialog.standardButtons = Dialog.Ok; switch (result.status) { case "error": 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); break; case "success": messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully exported material to %1").arg(result.path); break; } messageDialog.open(); CuraApplication.setDefaultPath("dialog_material_path", folder); } } } }