MaterialsPage.qml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. //Copyright (c) 2017 Ultimaker B.V.
  2. //Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.1
  4. import QtQuick.Controls 1.1
  5. import QtQuick.Dialogs 1.2
  6. import UM 1.2 as UM
  7. import Cura 1.0 as Cura
  8. UM.ManagementPage
  9. {
  10. id: base;
  11. title: catalog.i18nc("@title:tab", "Materials");
  12. Component.onCompleted:
  13. {
  14. // Workaround to make sure all of the items are visible
  15. objectList.positionViewAtBeginning();
  16. }
  17. model: Cura.MaterialsModel
  18. {
  19. filter:
  20. {
  21. var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() }
  22. if(Cura.MachineManager.filterMaterialsByMachine)
  23. {
  24. result.definition = Cura.MachineManager.activeQualityDefinitionId;
  25. if(Cura.MachineManager.hasVariants)
  26. {
  27. result.variant = Cura.MachineManager.activeQualityVariantId;
  28. }
  29. }
  30. else
  31. {
  32. result.definition = "fdmprinter";
  33. result.compatible = true; //NB: Only checks for compatibility in global version of material, but we don't have machine-specific materials anyway.
  34. }
  35. return result
  36. }
  37. sectionProperty: "brand"
  38. }
  39. delegate: Rectangle
  40. {
  41. width: objectList.width;
  42. height: childrenRect.height;
  43. color: isCurrentItem ? palette.highlight : index % 2 ? palette.base : palette.alternateBase
  44. property bool isCurrentItem: ListView.isCurrentItem
  45. Row
  46. {
  47. spacing: (UM.Theme.getSize("default_margin").width / 2) | 0
  48. anchors.left: parent.left
  49. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  50. anchors.right: parent.right
  51. Rectangle
  52. {
  53. width: (parent.height * 0.8) | 0
  54. height: (parent.height * 0.8) | 0
  55. color: model.metadata.color_code
  56. border.color: isCurrentItem ? palette.highlightedText : palette.text;
  57. anchors.verticalCenter: parent.verticalCenter
  58. }
  59. Label
  60. {
  61. width: Math.floor((parent.width * 0.3))
  62. text: model.metadata.material
  63. elide: Text.ElideRight
  64. font.italic: model.id == activeId
  65. color: isCurrentItem ? palette.highlightedText : palette.text;
  66. }
  67. Label
  68. {
  69. text: (model.name != model.metadata.material) ? model.name : ""
  70. elide: Text.ElideRight
  71. font.italic: model.id == activeId
  72. color: isCurrentItem ? palette.highlightedText : palette.text;
  73. }
  74. }
  75. MouseArea
  76. {
  77. anchors.fill: parent;
  78. onClicked:
  79. {
  80. forceActiveFocus();
  81. if(!parent.ListView.isCurrentItem)
  82. {
  83. parent.ListView.view.currentIndex = index;
  84. base.itemActivated();
  85. }
  86. }
  87. }
  88. }
  89. activeId: Cura.MachineManager.activeMaterialId
  90. activeIndex: getIndexById(activeId)
  91. function getIndexById(material_id)
  92. {
  93. for(var i = 0; i < model.rowCount(); i++) {
  94. if (model.getItem(i).id == material_id) {
  95. return i;
  96. }
  97. }
  98. return -1;
  99. }
  100. scrollviewCaption:
  101. {
  102. if (Cura.MachineManager.hasVariants)
  103. {
  104. catalog.i18nc("@action:label %1 is printer name, %2 is how this printer names variants, %3 is variant name", "Printer: %1, %2: %3").arg(Cura.MachineManager.activeMachineName).arg(Cura.MachineManager.activeDefinitionVariantsName).arg(Cura.MachineManager.activeVariantName)
  105. }
  106. else
  107. {
  108. catalog.i18nc("@action:label %1 is printer name","Printer: %1").arg(Cura.MachineManager.activeMachineName)
  109. }
  110. }
  111. detailsVisible: true
  112. section.property: "section"
  113. section.delegate: Label
  114. {
  115. text: section
  116. font.bold: true
  117. anchors.left: parent.left;
  118. anchors.leftMargin: UM.Theme.getSize("default_lining").width;
  119. }
  120. buttons: [
  121. // Activate button
  122. Button {
  123. text: catalog.i18nc("@action:button", "Activate")
  124. iconName: "list-activate";
  125. enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials
  126. onClicked: {
  127. forceActiveFocus()
  128. Cura.MachineManager.setActiveMaterial(base.currentItem.id)
  129. currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item.
  130. }
  131. },
  132. // Create button
  133. Button {
  134. text: catalog.i18nc("@action:button", "Create")
  135. iconName: "list-add"
  136. onClicked: {
  137. forceActiveFocus()
  138. Cura.ContainerManager.createMaterial()
  139. }
  140. },
  141. // Duplicate button
  142. Button {
  143. text: catalog.i18nc("@action:button", "Duplicate");
  144. iconName: "list-add";
  145. enabled: base.currentItem != null
  146. onClicked: {
  147. forceActiveFocus()
  148. Cura.ContainerManager.duplicateOriginalMaterial(base.currentItem.id)
  149. }
  150. },
  151. // Remove button
  152. Button {
  153. text: catalog.i18nc("@action:button", "Remove")
  154. iconName: "list-remove"
  155. enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id)
  156. onClicked: {
  157. forceActiveFocus()
  158. confirmDialog.open()
  159. }
  160. },
  161. // Import button
  162. Button {
  163. text: catalog.i18nc("@action:button", "Import")
  164. iconName: "document-import"
  165. onClicked: {
  166. forceActiveFocus()
  167. importDialog.open()
  168. }
  169. visible: true
  170. },
  171. // Export button
  172. Button {
  173. text: catalog.i18nc("@action:button", "Export")
  174. iconName: "document-export"
  175. onClicked: {
  176. forceActiveFocus()
  177. exportDialog.open()
  178. }
  179. enabled: currentItem != null
  180. }
  181. ]
  182. Item {
  183. visible: base.currentItem != null
  184. anchors.fill: parent
  185. Item
  186. {
  187. id: profileName
  188. width: parent.width;
  189. height: childrenRect.height
  190. Label { text: materialProperties.name; font: UM.Theme.getFont("large"); }
  191. }
  192. MaterialView
  193. {
  194. anchors
  195. {
  196. left: parent.left
  197. right: parent.right
  198. top: profileName.bottom
  199. topMargin: UM.Theme.getSize("default_margin").height
  200. bottom: parent.bottom
  201. }
  202. editingEnabled: base.currentItem != null && !base.currentItem.readOnly
  203. properties: materialProperties
  204. containerId: base.currentItem != null ? base.currentItem.id : ""
  205. property alias pane: base
  206. }
  207. QtObject
  208. {
  209. id: materialProperties
  210. property string guid: "00000000-0000-0000-0000-000000000000"
  211. property string name: "Unknown";
  212. property string profile_type: "Unknown";
  213. property string supplier: "Unknown";
  214. property string material_type: "Unknown";
  215. property string color_name: "Yellow";
  216. property color color_code: "yellow";
  217. property real density: 0.0;
  218. property real diameter: 0.0;
  219. property string approximate_diameter: "0";
  220. property real spool_cost: 0.0;
  221. property real spool_weight: 0.0;
  222. property real spool_length: 0.0;
  223. property real cost_per_meter: 0.0;
  224. property string description: "";
  225. property string adhesion_info: "";
  226. }
  227. UM.ConfirmRemoveDialog
  228. {
  229. id: confirmDialog
  230. object: base.currentItem != null ? base.currentItem.name : ""
  231. onYes:
  232. {
  233. // A material container can actually be multiple items, so we need to find (and remove) all of them.
  234. var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file")
  235. if(base_file == "")
  236. {
  237. base_file = base.currentItem.id
  238. }
  239. var guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID")
  240. // remove base container first, it otherwise triggers loading the base file while removing other containers
  241. var base_containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "id": base_file, "base_file": base_file, "type": "material"})
  242. for(var i in base_containers)
  243. {
  244. Cura.ContainerManager.removeContainer(base_containers[i]);
  245. }
  246. var containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "base_file": base_file, "type": "material"})
  247. for(var i in containers)
  248. {
  249. Cura.ContainerManager.removeContainer(containers[i]);
  250. }
  251. if(base.objectList.currentIndex > 0)
  252. {
  253. base.objectList.currentIndex--;
  254. }
  255. currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item.
  256. }
  257. }
  258. FileDialog
  259. {
  260. id: importDialog;
  261. title: catalog.i18nc("@title:window", "Import Material");
  262. selectExisting: true;
  263. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  264. folder: CuraApplication.getDefaultPath("dialog_material_path")
  265. onAccepted:
  266. {
  267. var result = Cura.ContainerManager.importContainer(fileUrl)
  268. messageDialog.title = catalog.i18nc("@title:window", "Import Material")
  269. 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)
  270. if(result.status == "success")
  271. {
  272. messageDialog.icon = StandardIcon.Information
  273. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully imported material <filename>%1</filename>").arg(fileUrl)
  274. }
  275. else if(result.status == "duplicate")
  276. {
  277. messageDialog.icon = StandardIcon.Warning
  278. }
  279. else
  280. {
  281. messageDialog.icon = StandardIcon.Critical
  282. }
  283. messageDialog.open()
  284. CuraApplication.setDefaultPath("dialog_material_path", folder)
  285. }
  286. }
  287. FileDialog
  288. {
  289. id: exportDialog;
  290. title: catalog.i18nc("@title:window", "Export Material");
  291. selectExisting: false;
  292. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  293. folder: CuraApplication.getDefaultPath("dialog_material_path")
  294. onAccepted:
  295. {
  296. if(base.currentItem.metadata.base_file)
  297. {
  298. var result = Cura.ContainerManager.exportContainer(base.currentItem.metadata.base_file, selectedNameFilter, fileUrl)
  299. }
  300. else
  301. {
  302. var result = Cura.ContainerManager.exportContainer(base.currentItem.id, selectedNameFilter, fileUrl)
  303. }
  304. messageDialog.title = catalog.i18nc("@title:window", "Export Material")
  305. if(result.status == "error")
  306. {
  307. messageDialog.icon = StandardIcon.Critical
  308. 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)
  309. messageDialog.open()
  310. }
  311. else if(result.status == "success")
  312. {
  313. messageDialog.icon = StandardIcon.Information
  314. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully exported material to <filename>%1</filename>").arg(result.path)
  315. messageDialog.open()
  316. }
  317. CuraApplication.setDefaultPath("dialog_material_path", folder)
  318. }
  319. }
  320. MessageDialog
  321. {
  322. id: messageDialog
  323. }
  324. UM.SettingPropertyProvider
  325. {
  326. id: materialDiameterProvider
  327. containerStackId: Cura.ExtruderManager.activeExtruderStackId
  328. key: "material_diameter"
  329. watchedProperties: [ "value" ]
  330. storeIndex: 5
  331. }
  332. UM.I18nCatalog { id: catalog; name: "cura"; }
  333. SystemPalette { id: palette }
  334. }
  335. onCurrentItemChanged:
  336. {
  337. if(currentItem == null)
  338. {
  339. return
  340. }
  341. materialProperties.name = currentItem.name;
  342. materialProperties.guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID");
  343. if(currentItem.metadata != undefined && currentItem.metadata != null)
  344. {
  345. materialProperties.supplier = currentItem.metadata.brand ? currentItem.metadata.brand : "Unknown";
  346. materialProperties.material_type = currentItem.metadata.material ? currentItem.metadata.material : "Unknown";
  347. materialProperties.color_name = currentItem.metadata.color_name ? currentItem.metadata.color_name : "Yellow";
  348. materialProperties.color_code = currentItem.metadata.color_code ? currentItem.metadata.color_code : "yellow";
  349. materialProperties.description = currentItem.metadata.description ? currentItem.metadata.description : "";
  350. materialProperties.adhesion_info = currentItem.metadata.adhesion_info ? currentItem.metadata.adhesion_info : "";
  351. if(currentItem.metadata.properties != undefined && currentItem.metadata.properties != null)
  352. {
  353. materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0;
  354. materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0;
  355. materialProperties.approximate_diameter = currentItem.metadata.approximate_diameter ? currentItem.metadata.approximate_diameter : "0";
  356. }
  357. else
  358. {
  359. materialProperties.density = 0.0;
  360. materialProperties.diameter = 0.0;
  361. materialProperties.approximate_diameter = "0";
  362. }
  363. }
  364. }
  365. }