MaterialsPage.qml 20 KB

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