MaterialView.qml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. // Copyright (c) 2016 Ultimaker B.V.
  2. // Uranium is released under the terms of the AGPLv3 or higher.
  3. import QtQuick 2.1
  4. import QtQuick.Controls 1.3
  5. import QtQuick.Dialogs 1.2
  6. import UM 1.2 as UM
  7. import Cura 1.0 as Cura
  8. TabView
  9. {
  10. id: base
  11. property QtObject properties;
  12. property bool editingEnabled: false;
  13. property string currency: UM.Preferences.getValue("cura/currency") ? UM.Preferences.getValue("cura/currency") : "€"
  14. property real firstColumnWidth: width * 0.45
  15. property real secondColumnWidth: width * 0.45
  16. property string containerId: ""
  17. property var materialPreferenceValues: UM.Preferences.getValue("cura/material_settings") ? JSON.parse(UM.Preferences.getValue("cura/material_settings")) : {}
  18. property double spoolLength: calculateSpoolLength()
  19. property real costPerMeter: calculateCostPerMeter()
  20. property bool reevaluateLinkedMaterials: false
  21. property string linkedMaterialNames:
  22. {
  23. if (reevaluateLinkedMaterials)
  24. {
  25. reevaluateLinkedMaterials = false;
  26. }
  27. if(!base.containerId || !base.editingEnabled)
  28. {
  29. return ""
  30. }
  31. var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.containerId);
  32. return linkedMaterials.join(", ");
  33. }
  34. Tab
  35. {
  36. title: catalog.i18nc("@title","Information")
  37. anchors.margins: UM.Theme.getSize("default_margin").width
  38. ScrollView
  39. {
  40. id: scrollView
  41. anchors.fill: parent
  42. horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
  43. flickableItem.flickableDirection: Flickable.VerticalFlick
  44. frameVisible: true
  45. property real columnWidth: Math.floor(viewport.width * 0.5) - UM.Theme.getSize("default_margin").width
  46. Flow
  47. {
  48. id: containerGrid
  49. x: UM.Theme.getSize("default_margin").width
  50. y: UM.Theme.getSize("default_lining").height
  51. width: base.width
  52. property real rowHeight: textField.height + UM.Theme.getSize("default_lining").height
  53. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Display Name") }
  54. ReadOnlyTextField
  55. {
  56. id: displayNameTextField;
  57. width: scrollView.columnWidth;
  58. text: properties.name;
  59. readOnly: !base.editingEnabled;
  60. onEditingFinished: base.setName(properties.name, text)
  61. }
  62. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Brand") }
  63. ReadOnlyTextField
  64. {
  65. id: textField;
  66. width: scrollView.columnWidth;
  67. text: properties.supplier;
  68. readOnly: !base.editingEnabled;
  69. onEditingFinished:
  70. {
  71. base.setMetaDataEntry("brand", properties.supplier, text);
  72. pane.objectList.currentIndex = pane.getIndexById(base.containerId);
  73. }
  74. }
  75. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Material Type") }
  76. ReadOnlyTextField
  77. {
  78. width: scrollView.columnWidth;
  79. text: properties.material_type;
  80. readOnly: !base.editingEnabled;
  81. onEditingFinished:
  82. {
  83. base.setMetaDataEntry("material", properties.material_type, text);
  84. pane.objectList.currentIndex = pane.getIndexById(base.containerId)
  85. }
  86. }
  87. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") }
  88. Row
  89. {
  90. width: scrollView.columnWidth;
  91. height: parent.rowHeight;
  92. spacing: UM.Theme.getSize("default_margin").width/2
  93. Rectangle
  94. {
  95. id: colorSelector
  96. color: properties.color_code
  97. width: colorLabel.height * 0.75
  98. height: colorLabel.height * 0.75
  99. border.width: UM.Theme.getSize("default_lining").height
  100. anchors.verticalCenter: parent.verticalCenter
  101. MouseArea { anchors.fill: parent; onClicked: colorDialog.open(); enabled: base.editingEnabled }
  102. }
  103. ReadOnlyTextField
  104. {
  105. id: colorLabel;
  106. text: properties.color_name;
  107. readOnly: !base.editingEnabled
  108. onEditingFinished: base.setMetaDataEntry("color_name", properties.color_name, text)
  109. }
  110. ColorDialog { id: colorDialog; color: properties.color_code; onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color) }
  111. }
  112. Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
  113. Label { width: parent.width; height: parent.rowHeight; font.bold: true; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Properties") }
  114. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") }
  115. ReadOnlySpinBox
  116. {
  117. id: densitySpinBox
  118. width: scrollView.columnWidth
  119. value: properties.density
  120. decimals: 2
  121. suffix: " g/cm³"
  122. stepSize: 0.01
  123. readOnly: !base.editingEnabled
  124. onEditingFinished: base.setMetaDataEntry("properties/density", properties.density, value)
  125. onValueChanged: updateCostPerMeter()
  126. }
  127. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") }
  128. ReadOnlySpinBox
  129. {
  130. id: diameterSpinBox
  131. width: scrollView.columnWidth
  132. value: properties.diameter
  133. decimals: 2
  134. suffix: " mm"
  135. stepSize: 0.01
  136. readOnly: !base.editingEnabled
  137. onEditingFinished:
  138. {
  139. // This does not use a SettingPropertyProvider, because we need to make the change to all containers
  140. // which derive from the same base_file
  141. Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value)
  142. base.setMetaDataEntry("properties/diameter", properties.diameter, value)
  143. }
  144. onValueChanged: updateCostPerMeter()
  145. }
  146. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") }
  147. SpinBox
  148. {
  149. id: spoolCostSpinBox
  150. width: scrollView.columnWidth
  151. value: base.getMaterialPreferenceValue(properties.guid, "spool_cost")
  152. prefix: base.currency + " "
  153. decimals: 2
  154. maximumValue: 100000000
  155. onValueChanged: {
  156. base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value))
  157. updateCostPerMeter()
  158. }
  159. }
  160. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") }
  161. SpinBox
  162. {
  163. id: spoolWeightSpinBox
  164. width: scrollView.columnWidth
  165. value: base.getMaterialPreferenceValue(properties.guid, "spool_weight")
  166. suffix: " g"
  167. stepSize: 100
  168. decimals: 0
  169. maximumValue: 10000
  170. onValueChanged: {
  171. base.setMaterialPreferenceValue(properties.guid, "spool_weight", parseFloat(value))
  172. updateCostPerMeter()
  173. }
  174. }
  175. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") }
  176. Label
  177. {
  178. width: scrollView.columnWidth
  179. text: "~ %1 m".arg(Math.round(base.spoolLength))
  180. verticalAlignment: Qt.AlignVCenter
  181. height: parent.rowHeight
  182. }
  183. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter") }
  184. Label
  185. {
  186. width: scrollView.columnWidth
  187. text: "~ %1 %2/m".arg(base.costPerMeter.toFixed(2)).arg(base.currency)
  188. verticalAlignment: Qt.AlignVCenter
  189. height: parent.rowHeight
  190. }
  191. Item { width: parent.width; height: UM.Theme.getSize("default_margin").height; visible: unlinkMaterialButton.visible }
  192. Label
  193. {
  194. width: 2 * scrollView.columnWidth
  195. verticalAlignment: Qt.AlignVCenter
  196. text: catalog.i18nc("@label", "This material is linked to %1 and shares some of its properties.").arg(base.linkedMaterialNames)
  197. wrapMode: Text.WordWrap
  198. visible: unlinkMaterialButton.visible
  199. }
  200. Button
  201. {
  202. id: unlinkMaterialButton
  203. text: catalog.i18nc("@label", "Unlink Material")
  204. visible: base.linkedMaterialNames != ""
  205. onClicked:
  206. {
  207. Cura.ContainerManager.unlinkMaterial(base.containerId)
  208. base.reevaluateLinkedMaterials = true
  209. }
  210. }
  211. Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
  212. Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Description") }
  213. ReadOnlyTextArea
  214. {
  215. text: properties.description;
  216. width: 2 * scrollView.columnWidth
  217. wrapMode: Text.WordWrap
  218. readOnly: !base.editingEnabled;
  219. onEditingFinished: base.setMetaDataEntry("description", properties.description, text)
  220. }
  221. Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Adhesion Information") }
  222. ReadOnlyTextArea
  223. {
  224. text: properties.adhesion_info;
  225. width: 2 * scrollView.columnWidth
  226. wrapMode: Text.WordWrap
  227. readOnly: !base.editingEnabled;
  228. onEditingFinished: base.setMetaDataEntry("adhesion_info", properties.adhesion_info, text)
  229. }
  230. Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
  231. }
  232. function updateCostPerMeter()
  233. {
  234. base.spoolLength = calculateSpoolLength(diameterSpinBox.value, densitySpinBox.value, spoolWeightSpinBox.value);
  235. base.costPerMeter = calculateCostPerMeter(spoolCostSpinBox.value);
  236. }
  237. }
  238. }
  239. Tab
  240. {
  241. title: catalog.i18nc("@label", "Print settings")
  242. anchors
  243. {
  244. leftMargin: UM.Theme.getSize("default_margin").width
  245. topMargin: UM.Theme.getSize("default_margin").height
  246. bottomMargin: UM.Theme.getSize("default_margin").height
  247. rightMargin: 0
  248. }
  249. ScrollView
  250. {
  251. anchors.fill: parent;
  252. ListView
  253. {
  254. model: UM.SettingDefinitionsModel
  255. {
  256. containerId: Cura.MachineManager.activeDefinitionId
  257. visibilityHandler: Cura.MaterialSettingsVisibilityHandler { }
  258. expanded: ["*"]
  259. }
  260. delegate: UM.TooltipArea
  261. {
  262. width: childrenRect.width
  263. height: childrenRect.height
  264. text: model.description
  265. Label
  266. {
  267. id: label
  268. width: base.firstColumnWidth;
  269. height: spinBox.height + UM.Theme.getSize("default_lining").height
  270. text: model.label
  271. elide: Text.ElideRight
  272. verticalAlignment: Qt.AlignVCenter
  273. }
  274. ReadOnlySpinBox
  275. {
  276. id: spinBox
  277. anchors.left: label.right
  278. value: {
  279. if (!isNaN(parseFloat(materialPropertyProvider.properties.value)))
  280. {
  281. return parseFloat(materialPropertyProvider.properties.value);
  282. }
  283. if (!isNaN(parseFloat(machinePropertyProvider.properties.value)))
  284. {
  285. return parseFloat(machinePropertyProvider.properties.value);
  286. }
  287. return 0;
  288. }
  289. width: base.secondColumnWidth
  290. readOnly: !base.editingEnabled
  291. suffix: " " + model.unit
  292. maximumValue: 99999
  293. decimals: model.unit == "mm" ? 2 : 0
  294. onEditingFinished: materialPropertyProvider.setPropertyValue("value", value)
  295. }
  296. UM.ContainerPropertyProvider { id: materialPropertyProvider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key }
  297. UM.ContainerPropertyProvider { id: machinePropertyProvider; containerId: Cura.MachineManager.activeDefinitionId; watchedProperties: [ "value" ]; key: model.key }
  298. }
  299. }
  300. }
  301. }
  302. function calculateSpoolLength(diameter, density, spoolWeight)
  303. {
  304. if(!diameter)
  305. {
  306. diameter = properties.diameter;
  307. }
  308. if(!density)
  309. {
  310. density = properties.density;
  311. }
  312. if(!spoolWeight)
  313. {
  314. spoolWeight = base.getMaterialPreferenceValue(properties.guid, "spool_weight");
  315. }
  316. if (diameter == 0 || density == 0 || spoolWeight == 0)
  317. {
  318. return 0;
  319. }
  320. var area = Math.PI * Math.pow(diameter / 2, 2); // in mm2
  321. var volume = (spoolWeight / density); // in cm3
  322. return volume / area; // in m
  323. }
  324. function calculateCostPerMeter(spoolCost)
  325. {
  326. if(!spoolCost)
  327. {
  328. spoolCost = base.getMaterialPreferenceValue(properties.guid, "spool_cost");
  329. }
  330. if (spoolLength == 0)
  331. {
  332. return 0;
  333. }
  334. return spoolCost / spoolLength;
  335. }
  336. // Tiny convenience function to check if a value really changed before trying to set it.
  337. function setMetaDataEntry(entry_name, old_value, new_value)
  338. {
  339. if(old_value != new_value)
  340. {
  341. Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, entry_name, new_value);
  342. }
  343. }
  344. function setMaterialPreferenceValue(material_guid, entry_name, new_value)
  345. {
  346. if(!(material_guid in materialPreferenceValues))
  347. {
  348. materialPreferenceValues[material_guid] = {};
  349. }
  350. if(entry_name in materialPreferenceValues[material_guid] && materialPreferenceValues[material_guid][entry_name] == new_value)
  351. {
  352. // value has not changed
  353. return
  354. }
  355. materialPreferenceValues[material_guid][entry_name] = new_value;
  356. // store preference
  357. UM.Preferences.setValue("cura/material_settings", JSON.stringify(materialPreferenceValues));
  358. }
  359. function getMaterialPreferenceValue(material_guid, entry_name)
  360. {
  361. if(material_guid in materialPreferenceValues && entry_name in materialPreferenceValues[material_guid])
  362. {
  363. return materialPreferenceValues[material_guid][entry_name];
  364. }
  365. return 0;
  366. }
  367. function setName(old_value, new_value)
  368. {
  369. if(old_value != new_value)
  370. {
  371. Cura.ContainerManager.setContainerName(base.containerId, new_value);
  372. // update material name label. not so pretty, but it works
  373. materialProperties.name = new_value;
  374. pane.objectList.currentIndex = pane.getIndexById(base.containerId)
  375. }
  376. }
  377. }