MaterialView.qml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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. Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value)
  140. base.setMetaDataEntry("properties/diameter", properties.diameter, value)
  141. }
  142. onValueChanged: updateCostPerMeter()
  143. }
  144. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") }
  145. SpinBox
  146. {
  147. id: spoolCostSpinBox
  148. width: scrollView.columnWidth
  149. value: base.getMaterialPreferenceValue(properties.guid, "spool_cost")
  150. prefix: base.currency + " "
  151. decimals: 2
  152. maximumValue: 100000000
  153. onValueChanged: {
  154. base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value))
  155. updateCostPerMeter()
  156. }
  157. }
  158. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") }
  159. SpinBox
  160. {
  161. id: spoolWeightSpinBox
  162. width: scrollView.columnWidth
  163. value: base.getMaterialPreferenceValue(properties.guid, "spool_weight")
  164. suffix: " g"
  165. stepSize: 100
  166. decimals: 0
  167. maximumValue: 10000
  168. onValueChanged: {
  169. base.setMaterialPreferenceValue(properties.guid, "spool_weight", parseFloat(value))
  170. updateCostPerMeter()
  171. }
  172. }
  173. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament length") }
  174. Label
  175. {
  176. width: scrollView.columnWidth
  177. text: "~ %1 m".arg(Math.round(base.spoolLength))
  178. verticalAlignment: Qt.AlignVCenter
  179. height: parent.rowHeight
  180. }
  181. Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Cost per Meter") }
  182. Label
  183. {
  184. width: scrollView.columnWidth
  185. text: "~ %1 %2/m".arg(base.costPerMeter.toFixed(2)).arg(base.currency)
  186. verticalAlignment: Qt.AlignVCenter
  187. height: parent.rowHeight
  188. }
  189. Item { width: parent.width; height: UM.Theme.getSize("default_margin").height; visible: unlinkMaterialButton.visible }
  190. Label
  191. {
  192. width: 2 * scrollView.columnWidth
  193. verticalAlignment: Qt.AlignVCenter
  194. text: catalog.i18nc("@label", "This material is linked to %1 and shares some of its properties.").arg(base.linkedMaterialNames)
  195. wrapMode: Text.WordWrap
  196. visible: unlinkMaterialButton.visible
  197. }
  198. Button
  199. {
  200. id: unlinkMaterialButton
  201. text: catalog.i18nc("@label", "Unlink Material")
  202. visible: base.linkedMaterialNames != ""
  203. onClicked:
  204. {
  205. Cura.ContainerManager.unlinkMaterial(base.containerId)
  206. base.reevaluateLinkedMaterials = true
  207. }
  208. }
  209. Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
  210. Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Description") }
  211. ReadOnlyTextArea
  212. {
  213. text: properties.description;
  214. width: 2 * scrollView.columnWidth
  215. wrapMode: Text.WordWrap
  216. readOnly: !base.editingEnabled;
  217. onEditingFinished: base.setMetaDataEntry("description", properties.description, text)
  218. }
  219. Label { width: parent.width; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Adhesion Information") }
  220. ReadOnlyTextArea
  221. {
  222. text: properties.adhesion_info;
  223. width: 2 * scrollView.columnWidth
  224. wrapMode: Text.WordWrap
  225. readOnly: !base.editingEnabled;
  226. onEditingFinished: base.setMetaDataEntry("adhesion_info", properties.adhesion_info, text)
  227. }
  228. Item { width: parent.width; height: UM.Theme.getSize("default_margin").height }
  229. }
  230. function updateCostPerMeter()
  231. {
  232. base.spoolLength = calculateSpoolLength(diameterSpinBox.value, densitySpinBox.value, spoolWeightSpinBox.value);
  233. base.costPerMeter = calculateCostPerMeter(spoolCostSpinBox.value);
  234. }
  235. }
  236. }
  237. Tab
  238. {
  239. title: catalog.i18nc("@label", "Print settings")
  240. anchors
  241. {
  242. leftMargin: UM.Theme.getSize("default_margin").width
  243. topMargin: UM.Theme.getSize("default_margin").height
  244. bottomMargin: UM.Theme.getSize("default_margin").height
  245. rightMargin: 0
  246. }
  247. ScrollView
  248. {
  249. anchors.fill: parent;
  250. ListView
  251. {
  252. model: UM.SettingDefinitionsModel
  253. {
  254. containerId: Cura.MachineManager.activeDefinitionId
  255. visibilityHandler: Cura.MaterialSettingsVisibilityHandler { }
  256. expanded: ["*"]
  257. }
  258. delegate: UM.TooltipArea
  259. {
  260. width: childrenRect.width
  261. height: childrenRect.height
  262. text: model.description
  263. Label
  264. {
  265. id: label
  266. width: base.firstColumnWidth;
  267. height: spinBox.height + UM.Theme.getSize("default_lining").height
  268. text: model.label
  269. elide: Text.ElideRight
  270. verticalAlignment: Qt.AlignVCenter
  271. }
  272. ReadOnlySpinBox
  273. {
  274. id: spinBox
  275. anchors.left: label.right
  276. value: {
  277. if (!isNaN(parseFloat(materialPropertyProvider.properties.value)))
  278. {
  279. return parseFloat(materialPropertyProvider.properties.value);
  280. }
  281. if (!isNaN(parseFloat(machinePropertyProvider.properties.value)))
  282. {
  283. return parseFloat(machinePropertyProvider.properties.value);
  284. }
  285. return 0;
  286. }
  287. width: base.secondColumnWidth
  288. readOnly: !base.editingEnabled
  289. suffix: " " + model.unit
  290. maximumValue: 99999
  291. decimals: model.unit == "mm" ? 2 : 0
  292. onEditingFinished: materialPropertyProvider.setPropertyValue("value", value)
  293. }
  294. UM.ContainerPropertyProvider { id: materialPropertyProvider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key }
  295. UM.ContainerPropertyProvider { id: machinePropertyProvider; containerId: Cura.MachineManager.activeDefinitionId; watchedProperties: [ "value" ]; key: model.key }
  296. }
  297. }
  298. }
  299. }
  300. function calculateSpoolLength(diameter, density, spoolWeight)
  301. {
  302. if(!diameter)
  303. {
  304. diameter = properties.diameter;
  305. }
  306. if(!density)
  307. {
  308. density = properties.density;
  309. }
  310. if(!spoolWeight)
  311. {
  312. spoolWeight = base.getMaterialPreferenceValue(properties.guid, "spool_weight");
  313. }
  314. if (diameter == 0 || density == 0 || spoolWeight == 0)
  315. {
  316. return 0;
  317. }
  318. var area = Math.PI * Math.pow(diameter / 2, 2); // in mm2
  319. var volume = (spoolWeight / density); // in cm3
  320. return volume / area; // in m
  321. }
  322. function calculateCostPerMeter(spoolCost)
  323. {
  324. if(!spoolCost)
  325. {
  326. spoolCost = base.getMaterialPreferenceValue(properties.guid, "spool_cost");
  327. }
  328. if (spoolLength == 0)
  329. {
  330. return 0;
  331. }
  332. return spoolCost / spoolLength;
  333. }
  334. // Tiny convenience function to check if a value really changed before trying to set it.
  335. function setMetaDataEntry(entry_name, old_value, new_value)
  336. {
  337. if(old_value != new_value)
  338. {
  339. Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, entry_name, new_value);
  340. }
  341. }
  342. function setMaterialPreferenceValue(material_guid, entry_name, new_value)
  343. {
  344. if(!(material_guid in materialPreferenceValues))
  345. {
  346. materialPreferenceValues[material_guid] = {};
  347. }
  348. if(entry_name in materialPreferenceValues[material_guid] && materialPreferenceValues[material_guid][entry_name] == new_value)
  349. {
  350. // value has not changed
  351. return
  352. }
  353. materialPreferenceValues[material_guid][entry_name] = new_value;
  354. // store preference
  355. UM.Preferences.setValue("cura/material_settings", JSON.stringify(materialPreferenceValues));
  356. }
  357. function getMaterialPreferenceValue(material_guid, entry_name)
  358. {
  359. if(material_guid in materialPreferenceValues && entry_name in materialPreferenceValues[material_guid])
  360. {
  361. return materialPreferenceValues[material_guid][entry_name];
  362. }
  363. return 0;
  364. }
  365. function setName(old_value, new_value)
  366. {
  367. if(old_value != new_value)
  368. {
  369. Cura.ContainerManager.setContainerName(base.containerId, new_value);
  370. // update material name label. not so pretty, but it works
  371. materialProperties.name = new_value;
  372. pane.objectList.currentIndex = pane.getIndexById(base.containerId)
  373. }
  374. }
  375. }