// 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
import UM 1.5 as UM
import Cura 1.5 as Cura
UM.ManagementPage
{
id: base
Item { enabled: false; UM.I18nCatalog { id: catalog; name: "cura"} }
// 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")
detailsPlaneCaption: currentItem ? 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.parent
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")
fileMode: FileDialog.OpenFile
nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
currentFolder: CuraApplication.getDefaultPath("dialog_material_path")
onAccepted:
{
const result = Cura.ContainerManager.importMaterialContainer(selectedFile);
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(selectedFile);
break;
default:
messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags or !", "Could not import material %1: %2").arg(selectedFile).arg(result.message);
break;
}
messageDialog.open();
CuraApplication.setDefaultPath("dialog_material_path", currentFolder);
}
}
FileDialog
{
id: exportMaterialDialog
title: catalog.i18nc("@title:window", "Export Material")
fileMode: FileDialog.SaveFile
nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
currentFolder: CuraApplication.getDefaultPath("dialog_material_path")
onAccepted:
{
const nameFilterString = selectedNameFilter.index >= 0 ? nameFilters[selectedNameFilter.index] : nameFilters[0];
const result = Cura.ContainerManager.exportContainer(base.currentItem.root_material_id, nameFilterString, selectedFile);
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(selectedFile).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", currentFolder);
}
}
}
}