MaterialsPage.qml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // Copyright (c) 2021 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.7
  4. import QtQuick.Controls 1.4
  5. import QtQuick.Layouts 1.3
  6. import QtQuick.Dialogs 1.2
  7. import UM 1.2 as UM
  8. import Cura 1.5 as Cura
  9. Item
  10. {
  11. id: base
  12. // Keep PreferencesDialog happy
  13. property var resetEnabled: false
  14. property var currentItem: null
  15. property var materialManagementModel: CuraApplication.getMaterialManagementModel()
  16. property var hasCurrentItem: base.currentItem != null
  17. property var isCurrentItemActivated:
  18. {
  19. if (!hasCurrentItem)
  20. {
  21. return false
  22. }
  23. const extruder_position = Cura.ExtruderManager.activeExtruderIndex
  24. const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]
  25. return base.currentItem.root_material_id == root_material_id
  26. }
  27. property string newRootMaterialIdToSwitchTo: ""
  28. property bool toActivateNewMaterial: false
  29. property var extruder_position: Cura.ExtruderManager.activeExtruderIndex
  30. property var active_root_material_id: Cura.MachineManager.currentRootMaterialId[extruder_position]
  31. UM.I18nCatalog
  32. {
  33. id: catalog
  34. name: "cura"
  35. }
  36. function resetExpandedActiveMaterial()
  37. {
  38. materialListView.expandActiveMaterial(active_root_material_id)
  39. }
  40. function setExpandedActiveMaterial(root_material_id)
  41. {
  42. materialListView.expandActiveMaterial(root_material_id)
  43. }
  44. // When loaded, try to select the active material in the tree
  45. Component.onCompleted:
  46. {
  47. resetExpandedActiveMaterial()
  48. base.newRootMaterialIdToSwitchTo = active_root_material_id
  49. }
  50. // Every time the selected item has changed, notify to the details panel
  51. onCurrentItemChanged:
  52. {
  53. forceActiveFocus()
  54. if(materialDetailsPanel.currentItem != currentItem)
  55. {
  56. materialDetailsPanel.currentItem = currentItem
  57. // CURA-6679 If the current item is gone after the model update, reset the current item to the active material.
  58. if (currentItem == null)
  59. {
  60. resetExpandedActiveMaterial()
  61. }
  62. }
  63. }
  64. // Main layout
  65. Label
  66. {
  67. id: titleLabel
  68. anchors
  69. {
  70. top: parent.top
  71. left: parent.left
  72. right: parent.right
  73. margins: 5 * screenScaleFactor
  74. }
  75. font.pointSize: 18
  76. text: catalog.i18nc("@title:tab", "Materials")
  77. }
  78. // Button Row
  79. Row
  80. {
  81. id: buttonRow
  82. anchors
  83. {
  84. left: parent.left
  85. right: parent.right
  86. top: titleLabel.bottom
  87. }
  88. height: childrenRect.height
  89. // Activate button
  90. Button
  91. {
  92. id: activateMenuButton
  93. text: catalog.i18nc("@action:button", "Activate")
  94. iconName: "list-activate"
  95. enabled: !isCurrentItemActivated && Cura.MachineManager.activeMachine.hasMaterials
  96. onClicked:
  97. {
  98. forceActiveFocus()
  99. // Set the current material as the one to be activated (needed to force the UI update)
  100. base.newRootMaterialIdToSwitchTo = base.currentItem.root_material_id
  101. const extruder_position = Cura.ExtruderManager.activeExtruderIndex
  102. Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node)
  103. }
  104. }
  105. // Create button
  106. Button
  107. {
  108. id: createMenuButton
  109. text: catalog.i18nc("@action:button", "Create")
  110. iconName: "list-add"
  111. enabled: Cura.MachineManager.activeMachine.hasMaterials
  112. onClicked:
  113. {
  114. forceActiveFocus();
  115. base.newRootMaterialIdToSwitchTo = base.materialManagementModel.createMaterial();
  116. base.toActivateNewMaterial = true;
  117. }
  118. }
  119. // Duplicate button
  120. Button
  121. {
  122. id: duplicateMenuButton
  123. text: catalog.i18nc("@action:button", "Duplicate");
  124. iconName: "list-add"
  125. enabled: base.hasCurrentItem
  126. onClicked:
  127. {
  128. forceActiveFocus();
  129. base.newRootMaterialIdToSwitchTo = base.materialManagementModel.duplicateMaterial(base.currentItem.container_node);
  130. base.toActivateNewMaterial = true;
  131. }
  132. }
  133. // Remove button
  134. Button
  135. {
  136. id: removeMenuButton
  137. text: catalog.i18nc("@action:button", "Remove")
  138. iconName: "list-remove"
  139. enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManagementModel.canMaterialBeRemoved(base.currentItem.container_node)
  140. onClicked:
  141. {
  142. forceActiveFocus();
  143. confirmRemoveMaterialDialog.open();
  144. }
  145. }
  146. // Import button
  147. Button
  148. {
  149. id: importMenuButton
  150. text: catalog.i18nc("@action:button", "Import")
  151. iconName: "document-import"
  152. onClicked:
  153. {
  154. forceActiveFocus();
  155. importMaterialDialog.open();
  156. }
  157. enabled: Cura.MachineManager.activeMachine.hasMaterials
  158. }
  159. // Export button
  160. Button
  161. {
  162. id: exportMenuButton
  163. text: catalog.i18nc("@action:button", "Export")
  164. iconName: "document-export"
  165. onClicked:
  166. {
  167. forceActiveFocus();
  168. exportMaterialDialog.open();
  169. }
  170. enabled: base.hasCurrentItem
  171. }
  172. //Sync button.
  173. Button
  174. {
  175. id: syncMaterialsButton
  176. text: catalog.i18nc("@action:button Sending materials to printers", "Sync with Printers")
  177. iconName: "sync-synchronizing"
  178. onClicked:
  179. {
  180. forceActiveFocus();
  181. base.materialManagementModel.openSyncAllWindow();
  182. }
  183. visible: Cura.MachineManager.activeMachine.supportsMaterialExport
  184. }
  185. }
  186. Item {
  187. id: contentsItem
  188. anchors
  189. {
  190. top: titleLabel.bottom
  191. left: parent.left
  192. right: parent.right
  193. bottom: parent.bottom
  194. margins: 5 * screenScaleFactor
  195. bottomMargin: 0
  196. }
  197. clip: true
  198. }
  199. Item
  200. {
  201. anchors
  202. {
  203. top: buttonRow.bottom
  204. topMargin: UM.Theme.getSize("default_margin").height
  205. left: parent.left
  206. right: parent.right
  207. bottom: parent.bottom
  208. }
  209. SystemPalette { id: palette }
  210. Label
  211. {
  212. id: captionLabel
  213. anchors
  214. {
  215. top: parent.top
  216. left: parent.left
  217. }
  218. visible: text != ""
  219. text:
  220. {
  221. var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachine.name;
  222. if (Cura.MachineManager.activeMachine.hasVariants)
  223. {
  224. var activeVariantName = ""
  225. if(Cura.MachineManager.activeStack != null)
  226. {
  227. activeVariantName = Cura.MachineManager.activeStack.variant.name
  228. }
  229. caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + activeVariantName;
  230. }
  231. return caption;
  232. }
  233. width: materialScrollView.width
  234. elide: Text.ElideRight
  235. }
  236. ScrollView
  237. {
  238. id: materialScrollView
  239. anchors
  240. {
  241. top: captionLabel.visible ? captionLabel.bottom : parent.top
  242. topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0
  243. bottom: parent.bottom
  244. left: parent.left
  245. }
  246. Rectangle
  247. {
  248. parent: viewport
  249. anchors.fill: parent
  250. color: palette.light
  251. }
  252. width: (parent.width * 0.4) | 0
  253. frameVisible: true
  254. horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
  255. MaterialsList
  256. {
  257. id: materialListView
  258. width: materialScrollView.viewport.width
  259. }
  260. }
  261. MaterialsDetailsPanel
  262. {
  263. id: materialDetailsPanel
  264. anchors
  265. {
  266. left: materialScrollView.right
  267. leftMargin: UM.Theme.getSize("default_margin").width
  268. top: parent.top
  269. bottom: parent.bottom
  270. right: parent.right
  271. }
  272. }
  273. }
  274. // Dialogs
  275. MessageDialog
  276. {
  277. id: confirmRemoveMaterialDialog
  278. icon: StandardIcon.Question;
  279. title: catalog.i18nc("@title:window", "Confirm Remove")
  280. property string materialName: base.currentItem !== null ? base.currentItem.name : ""
  281. text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(materialName)
  282. standardButtons: StandardButton.Yes | StandardButton.No
  283. modality: Qt.ApplicationModal
  284. onYes:
  285. {
  286. // Set the active material as the fallback. It will be selected when the current material is deleted
  287. base.newRootMaterialIdToSwitchTo = base.active_root_material_id
  288. base.materialManagementModel.removeMaterial(base.currentItem.container_node);
  289. }
  290. }
  291. FileDialog
  292. {
  293. id: importMaterialDialog
  294. title: catalog.i18nc("@title:window", "Import Material")
  295. selectExisting: true
  296. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  297. folder: CuraApplication.getDefaultPath("dialog_material_path")
  298. onAccepted:
  299. {
  300. var result = Cura.ContainerManager.importMaterialContainer(fileUrl);
  301. messageDialog.title = catalog.i18nc("@title:window", "Import Material");
  302. 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);
  303. if (result.status == "success")
  304. {
  305. messageDialog.icon = StandardIcon.Information;
  306. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully imported material <filename>%1</filename>").arg(fileUrl);
  307. }
  308. else if (result.status == "duplicate")
  309. {
  310. messageDialog.icon = StandardIcon.Warning;
  311. }
  312. else
  313. {
  314. messageDialog.icon = StandardIcon.Critical;
  315. }
  316. messageDialog.open();
  317. CuraApplication.setDefaultPath("dialog_material_path", folder);
  318. }
  319. }
  320. FileDialog
  321. {
  322. id: exportMaterialDialog
  323. title: catalog.i18nc("@title:window", "Export Material")
  324. selectExisting: false
  325. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  326. folder: CuraApplication.getDefaultPath("dialog_material_path")
  327. onAccepted:
  328. {
  329. var result = Cura.ContainerManager.exportContainer(base.currentItem.root_material_id, selectedNameFilter, fileUrl);
  330. messageDialog.title = catalog.i18nc("@title:window", "Export Material");
  331. if (result.status == "error")
  332. {
  333. messageDialog.icon = StandardIcon.Critical;
  334. 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);
  335. messageDialog.open();
  336. }
  337. else if (result.status == "success")
  338. {
  339. messageDialog.icon = StandardIcon.Information;
  340. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully exported material to <filename>%1</filename>").arg(result.path);
  341. messageDialog.open();
  342. }
  343. CuraApplication.setDefaultPath("dialog_material_path", folder);
  344. }
  345. }
  346. MessageDialog
  347. {
  348. id: messageDialog
  349. }
  350. }