MaterialView.qml 18 KB

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