MaterialsPage.qml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. // Copyright (c) 2018 Ultimaker B.V.
  2. // Uranium 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.0 as Cura
  9. Item
  10. {
  11. id: base
  12. property QtObject materialManager: CuraApplication.getMaterialManager()
  13. property var resetEnabled: false // Keep PreferencesDialog happy
  14. UM.I18nCatalog
  15. {
  16. id: catalog
  17. name: "cura"
  18. }
  19. Cura.BrandMaterialsModel
  20. {
  21. id: materialsModel
  22. }
  23. Cura.GenericMaterialsModel
  24. {
  25. id: genericMaterialsModel
  26. }
  27. Label
  28. {
  29. id: titleLabel
  30. anchors
  31. {
  32. top: parent.top
  33. left: parent.left
  34. right: parent.right
  35. margins: 5 * screenScaleFactor
  36. }
  37. font.pointSize: 18
  38. text: catalog.i18nc("@title:tab", "Materials")
  39. }
  40. property var hasCurrentItem: materialListView.currentItem != null
  41. property var currentItem:
  42. { // is soon to be overwritten
  43. var current_index = materialListView.currentIndex;
  44. return materialsModel.getItem(current_index);
  45. }
  46. property var isCurrentItemActivated:
  47. {
  48. const extruder_position = Cura.ExtruderManager.activeExtruderIndex;
  49. const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position];
  50. return base.currentItem.root_material_id == root_material_id;
  51. }
  52. Component.onCompleted:
  53. {
  54. // Select the activated material when this page shows up
  55. const extruder_position = Cura.ExtruderManager.activeExtruderIndex;
  56. const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position];
  57. var itemIndex = -1;
  58. for (var i = 0; i < materialsModel.rowCount(); ++i)
  59. {
  60. var item = materialsModel.getItem(i);
  61. if (item.root_material_id == active_root_material_id)
  62. {
  63. itemIndex = i;
  64. break;
  65. }
  66. }
  67. materialListView.currentIndex = itemIndex;
  68. }
  69. Row // Button Row
  70. {
  71. id: buttonRow
  72. anchors
  73. {
  74. left: parent.left
  75. right: parent.right
  76. top: titleLabel.bottom
  77. }
  78. height: childrenRect.height
  79. // Activate button
  80. Button
  81. {
  82. text: catalog.i18nc("@action:button", "Activate")
  83. iconName: "list-activate"
  84. enabled: !isCurrentItemActivated
  85. onClicked:
  86. {
  87. forceActiveFocus()
  88. const extruder_position = Cura.ExtruderManager.activeExtruderIndex;
  89. Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node);
  90. }
  91. }
  92. // Create button
  93. Button
  94. {
  95. text: catalog.i18nc("@action:button", "Create")
  96. iconName: "list-add"
  97. onClicked:
  98. {
  99. forceActiveFocus();
  100. base.newRootMaterialIdToSwitchTo = base.materialManager.createMaterial();
  101. base.toActivateNewMaterial = true;
  102. }
  103. }
  104. // Duplicate button
  105. Button
  106. {
  107. text: catalog.i18nc("@action:button", "Duplicate");
  108. iconName: "list-add"
  109. enabled: base.hasCurrentItem
  110. onClicked:
  111. {
  112. forceActiveFocus();
  113. base.newRootMaterialIdToSwitchTo = base.materialManager.duplicateMaterial(base.currentItem.container_node);
  114. base.toActivateNewMaterial = true;
  115. }
  116. }
  117. // Remove button
  118. Button
  119. {
  120. text: catalog.i18nc("@action:button", "Remove")
  121. iconName: "list-remove"
  122. enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated
  123. onClicked:
  124. {
  125. forceActiveFocus();
  126. confirmRemoveMaterialDialog.open();
  127. }
  128. }
  129. // Import button
  130. Button
  131. {
  132. text: catalog.i18nc("@action:button", "Import")
  133. iconName: "document-import"
  134. onClicked:
  135. {
  136. forceActiveFocus();
  137. importMaterialDialog.open();
  138. }
  139. visible: true
  140. }
  141. // Export button
  142. Button
  143. {
  144. text: catalog.i18nc("@action:button", "Export")
  145. iconName: "document-export"
  146. onClicked:
  147. {
  148. forceActiveFocus();
  149. exportMaterialDialog.open();
  150. }
  151. enabled: currentItem != null
  152. }
  153. }
  154. property string newRootMaterialIdToSwitchTo: ""
  155. property bool toActivateNewMaterial: false
  156. // This connection makes sure that we will switch to the new
  157. Connections
  158. {
  159. target: materialsModel
  160. onItemsChanged:
  161. {
  162. var currentItemId = base.currentItem == null ? "" : base.currentItem.root_material_id;
  163. var position = Cura.ExtruderManager.activeExtruderIndex;
  164. // try to pick the currently selected item; it may have been moved
  165. if (base.newRootMaterialIdToSwitchTo == "")
  166. {
  167. base.newRootMaterialIdToSwitchTo = currentItemId;
  168. }
  169. for (var idx = 0; idx < materialsModel.rowCount(); ++idx)
  170. {
  171. var item = materialsModel.getItem(idx);
  172. if (item.root_material_id == base.newRootMaterialIdToSwitchTo)
  173. {
  174. // Switch to the newly created profile if needed
  175. materialListView.currentIndex = idx;
  176. materialListView.activateDetailsWithIndex(materialListView.currentIndex);
  177. if (base.toActivateNewMaterial)
  178. {
  179. Cura.MachineManager.setMaterial(position, item.container_node);
  180. }
  181. base.newRootMaterialIdToSwitchTo = "";
  182. base.toActivateNewMaterial = false;
  183. return
  184. }
  185. }
  186. materialListView.currentIndex = 0;
  187. materialListView.activateDetailsWithIndex(materialListView.currentIndex);
  188. if (base.toActivateNewMaterial)
  189. {
  190. Cura.MachineManager.setMaterial(position, materialsModel.getItem(0).container_node);
  191. }
  192. base.newRootMaterialIdToSwitchTo = "";
  193. base.toActivateNewMaterial = false;
  194. }
  195. }
  196. MessageDialog
  197. {
  198. id: confirmRemoveMaterialDialog
  199. icon: StandardIcon.Question;
  200. title: catalog.i18nc("@title:window", "Confirm Remove")
  201. text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(base.currentItem.name)
  202. standardButtons: StandardButton.Yes | StandardButton.No
  203. modality: Qt.ApplicationModal
  204. onYes:
  205. {
  206. base.materialManager.removeMaterial(base.currentItem.container_node);
  207. }
  208. }
  209. FileDialog
  210. {
  211. id: importMaterialDialog
  212. title: catalog.i18nc("@title:window", "Import Material")
  213. selectExisting: true
  214. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  215. folder: CuraApplication.getDefaultPath("dialog_material_path")
  216. onAccepted:
  217. {
  218. var result = Cura.ContainerManager.importMaterialContainer(fileUrl);
  219. messageDialog.title = catalog.i18nc("@title:window", "Import Material");
  220. 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);
  221. if (result.status == "success")
  222. {
  223. messageDialog.icon = StandardIcon.Information;
  224. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully imported material <filename>%1</filename>").arg(fileUrl);
  225. }
  226. else if (result.status == "duplicate")
  227. {
  228. messageDialog.icon = StandardIcon.Warning;
  229. }
  230. else
  231. {
  232. messageDialog.icon = StandardIcon.Critical;
  233. }
  234. messageDialog.open();
  235. CuraApplication.setDefaultPath("dialog_material_path", folder);
  236. }
  237. }
  238. FileDialog
  239. {
  240. id: exportMaterialDialog
  241. title: catalog.i18nc("@title:window", "Export Material")
  242. selectExisting: false
  243. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  244. folder: CuraApplication.getDefaultPath("dialog_material_path")
  245. onAccepted:
  246. {
  247. var result = Cura.ContainerManager.exportContainer(base.currentItem.root_material_id, selectedNameFilter, fileUrl);
  248. messageDialog.title = catalog.i18nc("@title:window", "Export Material");
  249. if (result.status == "error")
  250. {
  251. messageDialog.icon = StandardIcon.Critical;
  252. 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);
  253. messageDialog.open();
  254. }
  255. else if (result.status == "success")
  256. {
  257. messageDialog.icon = StandardIcon.Information;
  258. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully exported material to <filename>%1</filename>").arg(result.path);
  259. messageDialog.open();
  260. }
  261. CuraApplication.setDefaultPath("dialog_material_path", folder);
  262. }
  263. }
  264. MessageDialog
  265. {
  266. id: messageDialog
  267. }
  268. Item {
  269. id: contentsItem
  270. anchors
  271. {
  272. top: titleLabel.bottom
  273. left: parent.left
  274. right: parent.right
  275. bottom: parent.bottom
  276. margins: 5 * screenScaleFactor
  277. bottomMargin: 0
  278. }
  279. clip: true
  280. }
  281. Item
  282. {
  283. anchors
  284. {
  285. top: buttonRow.bottom
  286. topMargin: UM.Theme.getSize("default_margin").height
  287. left: parent.left
  288. right: parent.right
  289. bottom: parent.bottom
  290. }
  291. SystemPalette { id: palette }
  292. Label
  293. {
  294. id: captionLabel
  295. anchors
  296. {
  297. top: parent.top
  298. left: parent.left
  299. }
  300. visible: text != ""
  301. text:
  302. {
  303. var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName;
  304. if (Cura.MachineManager.hasVariants)
  305. {
  306. caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName;
  307. }
  308. return caption;
  309. }
  310. width: materialScrollView.width
  311. elide: Text.ElideRight
  312. }
  313. ScrollView
  314. {
  315. id: materialScrollView
  316. anchors
  317. {
  318. top: captionLabel.visible ? captionLabel.bottom : parent.top
  319. topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0
  320. bottom: parent.bottom
  321. left: parent.left
  322. }
  323. Rectangle
  324. {
  325. parent: viewport
  326. anchors.fill: parent
  327. color: palette.light
  328. }
  329. width: true ? (parent.width * 0.4) | 0 : parent.width
  330. frameVisible: true
  331. MaterialsList {}
  332. }
  333. Item
  334. {
  335. id: detailsPanel
  336. anchors
  337. {
  338. left: materialScrollView.right
  339. leftMargin: UM.Theme.getSize("default_margin").width
  340. top: parent.top
  341. bottom: parent.bottom
  342. right: parent.right
  343. }
  344. function updateMaterialPropertiesObject( currentItem )
  345. {
  346. // var currentItem = materialsModel.getItem(materialListView.currentIndex);
  347. materialProperties.name = currentItem.name ? currentItem.name : "Unknown";
  348. materialProperties.guid = currentItem.guid;
  349. materialProperties.container_id = currentItem.container_id;
  350. materialProperties.brand = currentItem.brand ? currentItem.brand : "Unknown";
  351. materialProperties.material = currentItem.material ? currentItem.material : "Unknown";
  352. materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow";
  353. materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow";
  354. materialProperties.description = currentItem.description ? currentItem.description : "";
  355. materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : "";
  356. materialProperties.density = currentItem.density ? currentItem.density : 0.0;
  357. materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0;
  358. materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0";
  359. }
  360. Item
  361. {
  362. anchors.fill: parent
  363. Item // Material title Label
  364. {
  365. id: profileName
  366. width: parent.width
  367. height: childrenRect.height
  368. Label {
  369. text: materialProperties.name
  370. font: UM.Theme.getFont("large")
  371. }
  372. }
  373. MaterialView // Material detailed information view below the title Label
  374. {
  375. id: materialDetailsView
  376. anchors
  377. {
  378. left: parent.left
  379. right: parent.right
  380. top: profileName.bottom
  381. topMargin: UM.Theme.getSize("default_margin").height
  382. bottom: parent.bottom
  383. }
  384. editingEnabled: base.currentItem != null && !base.currentItem.is_read_only
  385. properties: materialProperties
  386. containerId: base.currentItem != null ? base.currentItem.container_id : ""
  387. currentMaterialNode: base.currentItem.container_node
  388. property alias pane: base
  389. }
  390. QtObject
  391. {
  392. id: materialProperties
  393. property string guid: "00000000-0000-0000-0000-000000000000"
  394. property string container_id: "Unknown";
  395. property string name: "Unknown";
  396. property string profile_type: "Unknown";
  397. property string brand: "Unknown";
  398. property string material: "Unknown"; // This needs to be named as "material" to be consistent with
  399. // the material container's metadata entry
  400. property string color_name: "Yellow";
  401. property color color_code: "yellow";
  402. property real density: 0.0;
  403. property real diameter: 0.0;
  404. property string approximate_diameter: "0";
  405. property real spool_cost: 0.0;
  406. property real spool_weight: 0.0;
  407. property real spool_length: 0.0;
  408. property real cost_per_meter: 0.0;
  409. property string description: "";
  410. property string adhesion_info: "";
  411. }
  412. }
  413. }
  414. }
  415. }