MaterialsPage.qml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  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. Button
  122. {
  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. {
  128. forceActiveFocus();
  129. Cura.MachineManager.setActiveMaterial(base.currentItem.id)
  130. currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item.
  131. }
  132. },
  133. Button
  134. {
  135. text: catalog.i18nc("@action:button", "Create")
  136. iconName: "list-add"
  137. onClicked:
  138. {
  139. forceActiveFocus();
  140. var material_id = Cura.ContainerManager.createMaterial()
  141. if(material_id == "")
  142. {
  143. return
  144. }
  145. if(Cura.MachineManager.hasMaterials)
  146. {
  147. Cura.MachineManager.setActiveMaterial(material_id)
  148. }
  149. base.objectList.currentIndex = base.getIndexById(material_id);
  150. }
  151. },
  152. Button
  153. {
  154. text: catalog.i18nc("@action:button", "Duplicate");
  155. iconName: "list-add";
  156. enabled: base.currentItem != null
  157. onClicked:
  158. {
  159. forceActiveFocus();
  160. var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file")
  161. // We need to copy the base container instead of the specific variant.
  162. var material_id = base_file == "" ? Cura.ContainerManager.duplicateMaterial(base.currentItem.id): Cura.ContainerManager.duplicateMaterial(base_file)
  163. if(material_id == "")
  164. {
  165. return
  166. }
  167. if(Cura.MachineManager.hasMaterials)
  168. {
  169. Cura.MachineManager.setActiveMaterial(material_id)
  170. }
  171. // TODO: this doesn't work because the source is a bit delayed
  172. base.objectList.currentIndex = base.getIndexById(material_id);
  173. }
  174. },
  175. Button
  176. {
  177. text: catalog.i18nc("@action:button", "Remove");
  178. iconName: "list-remove";
  179. enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id)
  180. onClicked:
  181. {
  182. forceActiveFocus();
  183. confirmDialog.open();
  184. }
  185. },
  186. Button
  187. {
  188. text: catalog.i18nc("@action:button", "Import");
  189. iconName: "document-import";
  190. onClicked:
  191. {
  192. forceActiveFocus();
  193. importDialog.open();
  194. }
  195. visible: true;
  196. },
  197. Button
  198. {
  199. text: catalog.i18nc("@action:button", "Export")
  200. iconName: "document-export"
  201. onClicked:
  202. {
  203. forceActiveFocus();
  204. exportDialog.open();
  205. }
  206. enabled: currentItem != null
  207. }
  208. ]
  209. Item {
  210. visible: base.currentItem != null
  211. anchors.fill: parent
  212. Item
  213. {
  214. id: profileName
  215. width: parent.width;
  216. height: childrenRect.height
  217. Label { text: materialProperties.name; font: UM.Theme.getFont("large"); }
  218. }
  219. MaterialView
  220. {
  221. anchors
  222. {
  223. left: parent.left
  224. right: parent.right
  225. top: profileName.bottom
  226. topMargin: UM.Theme.getSize("default_margin").height
  227. bottom: parent.bottom
  228. }
  229. editingEnabled: base.currentItem != null && !base.currentItem.readOnly
  230. properties: materialProperties
  231. containerId: base.currentItem != null ? base.currentItem.id : ""
  232. property alias pane: base
  233. }
  234. QtObject
  235. {
  236. id: materialProperties
  237. property string guid: "00000000-0000-0000-0000-000000000000"
  238. property string name: "Unknown";
  239. property string profile_type: "Unknown";
  240. property string supplier: "Unknown";
  241. property string material_type: "Unknown";
  242. property string color_name: "Yellow";
  243. property color color_code: "yellow";
  244. property real density: 0.0;
  245. property real diameter: 0.0;
  246. property string approximate_diameter: "0";
  247. property real spool_cost: 0.0;
  248. property real spool_weight: 0.0;
  249. property real spool_length: 0.0;
  250. property real cost_per_meter: 0.0;
  251. property string description: "";
  252. property string adhesion_info: "";
  253. }
  254. UM.ConfirmRemoveDialog
  255. {
  256. id: confirmDialog
  257. object: base.currentItem != null ? base.currentItem.name : ""
  258. onYes:
  259. {
  260. // A material container can actually be multiple items, so we need to find (and remove) all of them.
  261. var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file")
  262. if(base_file == "")
  263. {
  264. base_file = base.currentItem.id
  265. }
  266. var guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID")
  267. // remove base container first, it otherwise triggers loading the base file while removing other containers
  268. var base_containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "id": base_file, "base_file": base_file, "type": "material"})
  269. for(var i in base_containers)
  270. {
  271. Cura.ContainerManager.removeContainer(base_containers[i]);
  272. }
  273. var containers = Cura.ContainerManager.findInstanceContainers({"GUID": guid, "base_file": base_file, "type": "material"})
  274. for(var i in containers)
  275. {
  276. Cura.ContainerManager.removeContainer(containers[i]);
  277. }
  278. if(base.objectList.currentIndex > 0)
  279. {
  280. base.objectList.currentIndex--;
  281. }
  282. currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item.
  283. }
  284. }
  285. FileDialog
  286. {
  287. id: importDialog;
  288. title: catalog.i18nc("@title:window", "Import Material");
  289. selectExisting: true;
  290. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  291. folder: CuraApplication.getDefaultPath("dialog_material_path")
  292. onAccepted:
  293. {
  294. var result = Cura.ContainerManager.importContainer(fileUrl)
  295. messageDialog.title = catalog.i18nc("@title:window", "Import Material")
  296. 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)
  297. if(result.status == "success")
  298. {
  299. messageDialog.icon = StandardIcon.Information
  300. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully imported material <filename>%1</filename>").arg(fileUrl)
  301. }
  302. else if(result.status == "duplicate")
  303. {
  304. messageDialog.icon = StandardIcon.Warning
  305. }
  306. else
  307. {
  308. messageDialog.icon = StandardIcon.Critical
  309. }
  310. messageDialog.open()
  311. CuraApplication.setDefaultPath("dialog_material_path", folder)
  312. }
  313. }
  314. FileDialog
  315. {
  316. id: exportDialog;
  317. title: catalog.i18nc("@title:window", "Export Material");
  318. selectExisting: false;
  319. nameFilters: Cura.ContainerManager.getContainerNameFilters("material")
  320. folder: CuraApplication.getDefaultPath("dialog_material_path")
  321. onAccepted:
  322. {
  323. if(base.currentItem.metadata.base_file)
  324. {
  325. var result = Cura.ContainerManager.exportContainer(base.currentItem.metadata.base_file, selectedNameFilter, fileUrl)
  326. }
  327. else
  328. {
  329. var result = Cura.ContainerManager.exportContainer(base.currentItem.id, selectedNameFilter, fileUrl)
  330. }
  331. messageDialog.title = catalog.i18nc("@title:window", "Export Material")
  332. if(result.status == "error")
  333. {
  334. messageDialog.icon = StandardIcon.Critical
  335. 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)
  336. messageDialog.open()
  337. }
  338. else if(result.status == "success")
  339. {
  340. messageDialog.icon = StandardIcon.Information
  341. messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag <filename>!", "Successfully exported material to <filename>%1</filename>").arg(result.path)
  342. messageDialog.open()
  343. }
  344. CuraApplication.setDefaultPath("dialog_material_path", folder)
  345. }
  346. }
  347. MessageDialog
  348. {
  349. id: messageDialog
  350. }
  351. UM.SettingPropertyProvider
  352. {
  353. id: materialDiameterProvider
  354. containerStackId: Cura.ExtruderManager.activeExtruderStackId
  355. key: "material_diameter"
  356. watchedProperties: [ "value" ]
  357. storeIndex: 5
  358. }
  359. UM.I18nCatalog { id: catalog; name: "cura"; }
  360. SystemPalette { id: palette }
  361. }
  362. onCurrentItemChanged:
  363. {
  364. if(currentItem == null)
  365. {
  366. return
  367. }
  368. materialProperties.name = currentItem.name;
  369. materialProperties.guid = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "GUID");
  370. if(currentItem.metadata != undefined && currentItem.metadata != null)
  371. {
  372. materialProperties.supplier = currentItem.metadata.brand ? currentItem.metadata.brand : "Unknown";
  373. materialProperties.material_type = currentItem.metadata.material ? currentItem.metadata.material : "Unknown";
  374. materialProperties.color_name = currentItem.metadata.color_name ? currentItem.metadata.color_name : "Yellow";
  375. materialProperties.color_code = currentItem.metadata.color_code ? currentItem.metadata.color_code : "yellow";
  376. materialProperties.description = currentItem.metadata.description ? currentItem.metadata.description : "";
  377. materialProperties.adhesion_info = currentItem.metadata.adhesion_info ? currentItem.metadata.adhesion_info : "";
  378. if(currentItem.metadata.properties != undefined && currentItem.metadata.properties != null)
  379. {
  380. materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0;
  381. materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0;
  382. materialProperties.approximate_diameter = currentItem.metadata.approximate_diameter ? currentItem.metadata.approximate_diameter : "0";
  383. }
  384. else
  385. {
  386. materialProperties.density = 0.0;
  387. materialProperties.diameter = 0.0;
  388. materialProperties.approximate_diameter = "0";
  389. }
  390. }
  391. }
  392. }