MaterialsPage.qml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // Copyright (c) 2022 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.7
  4. import QtQuick.Controls 2.15
  5. import QtQuick.Dialogs 1.2
  6. import UM 1.5 as UM
  7. import Cura 1.5 as Cura
  8. UM.ManagementPage
  9. {
  10. id: base
  11. // Keep PreferencesDialog happy
  12. property var resetEnabled: false
  13. property var currentItem: null
  14. property var materialManagementModel: CuraApplication.getMaterialManagementModel()
  15. property var hasCurrentItem: base.currentItem != null
  16. property var isCurrentItemActivated:
  17. {
  18. if (!hasCurrentItem)
  19. {
  20. return false
  21. }
  22. const extruder_position = Cura.ExtruderManager.activeExtruderIndex
  23. const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]
  24. return base.currentItem.root_material_id == root_material_id
  25. }
  26. property string newRootMaterialIdToSwitchTo: ""
  27. property bool toActivateNewMaterial: false
  28. property var extruder_position: Cura.ExtruderManager.activeExtruderIndex
  29. property var active_root_material_id: Cura.MachineManager.currentRootMaterialId[extruder_position]
  30. function resetExpandedActiveMaterial()
  31. {
  32. materialListView.expandActiveMaterial(active_root_material_id)
  33. }
  34. function setExpandedActiveMaterial(root_material_id)
  35. {
  36. materialListView.expandActiveMaterial(root_material_id)
  37. }
  38. // When loaded, try to select the active material in the tree
  39. Component.onCompleted:
  40. {
  41. resetExpandedActiveMaterial()
  42. base.newRootMaterialIdToSwitchTo = active_root_material_id
  43. }
  44. // Every time the selected item has changed, notify to the details panel
  45. onCurrentItemChanged:
  46. {
  47. forceActiveFocus()
  48. if(materialDetailsPanel.currentItem != currentItem)
  49. {
  50. materialDetailsPanel.currentItem = currentItem
  51. // CURA-6679 If the current item is gone after the model update, reset the current item to the active material.
  52. if (currentItem == null)
  53. {
  54. resetExpandedActiveMaterial()
  55. }
  56. }
  57. }
  58. title: catalog.i18nc("@title:tab", "Materials")
  59. detailsPlaneCaption: currentItem ? currentItem.name: ""
  60. scrollviewCaption: catalog.i18nc("@label", "Materials compatible with active printer:") + `<br /><b>${Cura.MachineManager.activeMachine.name}</b>`
  61. buttons: [
  62. Cura.SecondaryButton
  63. {
  64. id: createMenuButton
  65. text: catalog.i18nc("@action:button", "Create new")
  66. enabled: Cura.MachineManager.activeMachine.hasMaterials
  67. onClicked:
  68. {
  69. forceActiveFocus();
  70. base.newRootMaterialIdToSwitchTo = base.materialManagementModel.createMaterial();
  71. base.toActivateNewMaterial = true;
  72. }
  73. },
  74. Cura.SecondaryButton
  75. {
  76. id: importMenuButton
  77. text: catalog.i18nc("@action:button", "Import")
  78. onClicked:
  79. {
  80. forceActiveFocus();
  81. importMaterialDialog.open();
  82. }
  83. enabled: Cura.MachineManager.activeMachine.hasMaterials
  84. },
  85. Cura.SecondaryButton
  86. {
  87. id: syncMaterialsButton
  88. text: catalog.i18nc("@action:button", "Sync with Printers")
  89. onClicked:
  90. {
  91. forceActiveFocus();
  92. base.materialManagementModel.openSyncAllWindow();
  93. }
  94. visible: Cura.MachineManager.activeMachine.supportsMaterialExport
  95. }
  96. ]
  97. onHamburgeButtonClicked: {
  98. const hamburerButtonHeight = hamburger_button.height;
  99. menu.popup(hamburger_button, -menu.width + hamburger_button.width / 2, hamburger_button.height);
  100. // for some reason the height of the hamburger changes when opening the popup
  101. // reset height to initial heigt
  102. hamburger_button.height = hamburerButtonHeight;
  103. }
  104. listContent: ScrollView
  105. {
  106. id: materialScrollView
  107. anchors.fill: parent
  108. anchors.margins: parent.border.width
  109. width: (parent.width * 0.4) | 0
  110. clip: true
  111. ScrollBar.vertical: UM.ScrollBar
  112. {
  113. id: materialScrollBar
  114. parent: materialScrollView.parent
  115. anchors
  116. {
  117. top: parent.top
  118. right: parent.right
  119. bottom: parent.bottom
  120. }
  121. }
  122. contentHeight: materialListView.height //For some reason, this is not determined automatically with this ScrollView. Very weird!
  123. MaterialsList
  124. {
  125. id: materialListView
  126. width: materialScrollView.width - materialScrollBar.width
  127. }
  128. }
  129. MaterialsDetailsPanel
  130. {
  131. id: materialDetailsPanel
  132. anchors.fill: parent
  133. }
  134. Item
  135. {
  136. Cura.Menu
  137. {
  138. id: menu
  139. Cura.MenuItem
  140. {
  141. id: activateMenuButton
  142. text: catalog.i18nc("@action:button", "Activate")
  143. onClicked:
  144. {
  145. forceActiveFocus()
  146. // Set the current material as the one to be activated (needed to force the UI update)
  147. base.newRootMaterialIdToSwitchTo = base.currentItem.root_material_id
  148. const extruder_position = Cura.ExtruderManager.activeExtruderIndex
  149. Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node)
  150. }
  151. }
  152. Cura.MenuItem
  153. {
  154. id: duplicateMenuButton
  155. text: catalog.i18nc("@action:button", "Duplicate");
  156. enabled: base.hasCurrentItem
  157. onClicked:
  158. {
  159. forceActiveFocus();
  160. base.newRootMaterialIdToSwitchTo = base.materialManagementModel.duplicateMaterial(base.currentItem.container_node);
  161. base.toActivateNewMaterial = true;
  162. }
  163. }
  164. Cura.MenuItem
  165. {
  166. id: removeMenuButton
  167. text: catalog.i18nc("@action:button", "Remove")
  168. enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManagementModel.canMaterialBeRemoved(base.currentItem.container_node)
  169. onClicked:
  170. {
  171. forceActiveFocus();
  172. confirmRemoveMaterialDialog.open();
  173. }
  174. }
  175. Cura.MenuItem
  176. {
  177. id: exportMenuButton
  178. text: catalog.i18nc("@action:button", "Export")
  179. onClicked:
  180. {
  181. forceActiveFocus();
  182. exportMaterialDialog.open();
  183. }
  184. enabled: base.hasCurrentItem
  185. }
  186. }
  187. // Dialogs
  188. Cura.MessageDialog
  189. {
  190. id: confirmRemoveMaterialDialog
  191. title: catalog.i18nc("@title:window", "Confirm Remove")
  192. property string materialName: base.currentItem !== null ? base.currentItem.name : ""
  193. text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(materialName)
  194. standardButtons: Dialog.Yes | Dialog.No
  195. onAccepted:
  196. {
  197. // Set the active material as the fallback. It will be selected when the current material is deleted
  198. base.newRootMaterialIdToSwitchTo = base.active_root_material_id
  199. base.materialManagementModel.removeMaterial(base.currentItem.container_node);
  200. }
  201. }
  202. FileDialog
  203. {
  204. id: importMaterialDialog
  205. title: catalog.i18nc("@title:window", "Import Material")
  206. selectExisting: true
  207. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  208. folder: CuraApplication.getDefaultPath("dialog_material_path")
  209. onAccepted:
  210. {
  211. const result = Cura.ContainerManager.importMaterialContainer(fileUrl);
  212. const messageDialog = Qt.createQmlObject("import Cura 1.5 as Cura; Cura.MessageDialog { onClosed: destroy() }", base);
  213. messageDialog.standardButtons = Dialog.Ok;
  214. messageDialog.title = catalog.i18nc("@title:window", "Import Material");
  215. switch (result.status)
  216. {
  217. case "success":
  218. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully imported material <filename>%1</filename>").arg(fileUrl);
  219. break;
  220. default:
  221. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags <filename> or <message>!", "Could not import material <filename>%1</filename>: <message>%2</message>").arg(fileUrl).arg(result.message);
  222. break;
  223. }
  224. messageDialog.open();
  225. CuraApplication.setDefaultPath("dialog_material_path", folder);
  226. }
  227. }
  228. FileDialog
  229. {
  230. id: exportMaterialDialog
  231. title: catalog.i18nc("@title:window", "Export Material")
  232. selectExisting: false
  233. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  234. folder: CuraApplication.getDefaultPath("dialog_material_path")
  235. onAccepted:
  236. {
  237. const result = Cura.ContainerManager.exportContainer(base.currentItem.root_material_id, selectedNameFilter, fileUrl);
  238. const messageDialog = Qt.createQmlObject("import Cura 1.5 as Cura; Cura.MessageDialog { onClosed: destroy() }", base);
  239. messageDialog.title = catalog.i18nc("@title:window", "Export Material");
  240. messageDialog.standardButtons = Dialog.Ok;
  241. switch (result.status)
  242. {
  243. case "error":
  244. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tags <filename> and <message>!", "Failed to export material to <filename>%1</filename>: <message>%2</message>").arg(fileUrl).arg(result.message);
  245. break;
  246. case "success":
  247. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully exported material to <filename>%1</filename>").arg(result.path);
  248. break;
  249. }
  250. messageDialog.open();
  251. CuraApplication.setDefaultPath("dialog_material_path", folder);
  252. }
  253. }
  254. }
  255. }