PerObjectSettingsPanel.qml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. //Copyright (c) 2022 Ultimaker B.V.
  2. //Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.2
  4. import QtQuick.Controls 2.15
  5. import UM 1.5 as UM
  6. import Cura 1.0 as Cura
  7. import ".."
  8. Item
  9. {
  10. id: base
  11. width: childrenRect.width
  12. height: childrenRect.height
  13. property var allCategoriesExceptSupport: [ "machine_settings", "resolution", "shell", "infill", "material", "speed",
  14. "travel", "cooling", "platform_adhesion", "dual", "meshfix", "blackmagic", "experimental"]
  15. readonly property string normalMeshType: ""
  16. readonly property string supportMeshType: "support_mesh"
  17. readonly property string cuttingMeshType: "cutting_mesh"
  18. readonly property string infillMeshType: "infill_mesh"
  19. readonly property string antiOverhangMeshType: "anti_overhang_mesh"
  20. property var currentMeshType: UM.ActiveTool.properties.getValue("MeshType")
  21. // Update the view every time the currentMeshType changes
  22. onCurrentMeshTypeChanged:
  23. {
  24. var type = currentMeshType
  25. // set checked state of mesh type buttons
  26. updateMeshTypeCheckedState(type)
  27. // update active type label
  28. for (var button in meshTypeButtons.children)
  29. {
  30. if (meshTypeButtons.children[button].checked)
  31. {
  32. meshTypeLabel.text = catalog.i18nc("@label", "Mesh Type") + ": " + meshTypeButtons.children[button].text
  33. break
  34. }
  35. }
  36. visibility_handler.addSkipResetSetting(currentMeshType)
  37. }
  38. function updateMeshTypeCheckedState(type)
  39. {
  40. // set checked state of mesh type buttons
  41. normalButton.checked = type === normalMeshType
  42. supportMeshButton.checked = type === supportMeshType
  43. overlapMeshButton.checked = type === infillMeshType || type === cuttingMeshType
  44. antiOverhangMeshButton.checked = type === antiOverhangMeshType
  45. }
  46. function setMeshType(type)
  47. {
  48. UM.ActiveTool.setProperty("MeshType", type)
  49. updateMeshTypeCheckedState(type)
  50. }
  51. UM.I18nCatalog { id: catalog; name: "cura"}
  52. Column
  53. {
  54. id: items
  55. anchors.top: parent.top;
  56. anchors.left: parent.left;
  57. spacing: UM.Theme.getSize("default_margin").height
  58. Row // Mesh type buttons
  59. {
  60. id: meshTypeButtons
  61. spacing: UM.Theme.getSize("default_margin").width
  62. UM.ToolbarButton
  63. {
  64. id: normalButton
  65. text: catalog.i18nc("@label", "Normal model")
  66. toolItem: UM.ColorImage
  67. {
  68. source: UM.Theme.getIcon("Infill0")
  69. color: UM.Theme.getColor("icon")
  70. }
  71. property bool needBorder: true
  72. checkable: true
  73. onClicked: setMeshType(normalMeshType);
  74. z: 4
  75. }
  76. UM.ToolbarButton
  77. {
  78. id: supportMeshButton
  79. text: catalog.i18nc("@label", "Print as support")
  80. toolItem: UM.ColorImage
  81. {
  82. source: UM.Theme.getIcon("MeshTypeSupport")
  83. color: UM.Theme.getColor("icon")
  84. }
  85. property bool needBorder: true
  86. checkable:true
  87. onClicked: setMeshType(supportMeshType)
  88. z: 3
  89. }
  90. UM.ToolbarButton
  91. {
  92. id: overlapMeshButton
  93. text: catalog.i18nc("@label", "Modify settings for overlaps")
  94. toolItem: UM.ColorImage
  95. {
  96. source: UM.Theme.getIcon("MeshTypeIntersect")
  97. color: UM.Theme.getColor("icon")
  98. }
  99. property bool needBorder: true
  100. checkable:true
  101. onClicked: setMeshType(infillMeshType)
  102. z: 2
  103. }
  104. UM.ToolbarButton
  105. {
  106. id: antiOverhangMeshButton
  107. text: catalog.i18nc("@label", "Don't support overlaps")
  108. toolItem: UM.ColorImage
  109. {
  110. source: UM.Theme.getIcon("BlockSupportOverlaps")
  111. color: UM.Theme.getColor("icon")
  112. }
  113. property bool needBorder: true
  114. checkable: true
  115. onClicked: setMeshType(antiOverhangMeshType)
  116. z: 1
  117. }
  118. }
  119. UM.Label
  120. {
  121. id: meshTypeLabel
  122. height: UM.Theme.getSize("setting").height
  123. }
  124. Cura.ComboBox
  125. {
  126. id: infillOnlyComboBox
  127. width: parent.width / 2 - UM.Theme.getSize("default_margin").width
  128. height: UM.Theme.getSize("setting_control").height
  129. textRole: "text"
  130. forceHighlight: base.hovered
  131. model: ListModel
  132. {
  133. id: infillOnlyComboBoxModel
  134. Component.onCompleted: {
  135. append({ text: catalog.i18nc("@item:inlistbox", "Infill mesh only") })
  136. append({ text: catalog.i18nc("@item:inlistbox", "Cutting mesh") })
  137. }
  138. }
  139. visible: currentMeshType === infillMeshType || currentMeshType === cuttingMeshType
  140. onActivated:
  141. {
  142. if (index == 0){
  143. setMeshType(infillMeshType)
  144. } else {
  145. setMeshType(cuttingMeshType)
  146. }
  147. }
  148. Binding
  149. {
  150. target: infillOnlyComboBox
  151. property: "currentIndex"
  152. value: currentMeshType === infillMeshType ? 0 : 1
  153. }
  154. }
  155. Column // List of selected Settings to override for the selected object
  156. {
  157. // This is to ensure that the panel is first increasing in size up to 200 and then shows a scrollbar.
  158. // It kinda looks ugly otherwise (big panel, no content on it)
  159. id: currentSettings
  160. property int maximumHeight: 200 * screenScaleFactor
  161. height: Math.min(contents.count * (UM.Theme.getSize("section").height + UM.Theme.getSize("narrow_margin").height + UM.Theme.getSize("default_lining").height), maximumHeight)
  162. visible: currentMeshType != "anti_overhang_mesh"
  163. ListView
  164. {
  165. id: contents
  166. height: parent.height
  167. width: UM.Theme.getSize("setting").width + UM.Theme.getSize("default_margin").width
  168. ScrollBar.vertical: UM.ScrollBar { id: scrollBar }
  169. clip: true
  170. spacing: UM.Theme.getSize("default_lining").height
  171. model: UM.SettingDefinitionsModel
  172. {
  173. id: addedSettingsModel
  174. containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
  175. expanded: [ "*" ]
  176. filter:
  177. {
  178. if (printSequencePropertyProvider.properties.value == "one_at_a_time")
  179. {
  180. return {"settable_per_meshgroup": true}
  181. }
  182. return {"settable_per_mesh": true}
  183. }
  184. exclude:
  185. {
  186. var excluded_settings = [ "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ]
  187. if (currentMeshType == "support_mesh")
  188. {
  189. excluded_settings = excluded_settings.concat(base.allCategoriesExceptSupport)
  190. }
  191. return excluded_settings
  192. }
  193. visibilityHandler: Cura.PerObjectSettingVisibilityHandler
  194. {
  195. id: visibility_handler
  196. selectedObjectId: UM.ActiveTool.properties.getValue("SelectedObjectId")
  197. }
  198. // For some reason the model object is updated after removing him from the memory and
  199. // it happens only on Windows. For this reason, set the destroyed value manually.
  200. Component.onDestruction:
  201. {
  202. setDestroyed(true)
  203. }
  204. }
  205. delegate: Row
  206. {
  207. spacing: UM.Theme.getSize("default_margin").width
  208. Loader
  209. {
  210. id: settingLoader
  211. width: UM.Theme.getSize("setting").width - removeButton.width - scrollBar.width
  212. height: UM.Theme.getSize("section").height + UM.Theme.getSize("narrow_margin").height
  213. enabled: provider.properties.enabled === "True"
  214. property var definition: model
  215. property var settingDefinitionsModel: addedSettingsModel
  216. property var propertyProvider: provider
  217. property var globalPropertyProvider: inheritStackProvider
  218. property var externalResetHandler: false
  219. //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
  220. //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
  221. //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
  222. asynchronous: model.type != "enum" && model.type != "extruder"
  223. onLoaded:
  224. {
  225. settingLoader.item.showRevertButton = false
  226. settingLoader.item.showInheritButton = false
  227. settingLoader.item.showLinkedSettingIcon = false
  228. settingLoader.item.doDepthIndentation = false
  229. settingLoader.item.doQualityUserSettingEmphasis = false
  230. }
  231. sourceComponent:
  232. {
  233. switch(model.type)
  234. {
  235. case "int":
  236. return settingTextField
  237. case "[int]":
  238. return settingTextField
  239. case "float":
  240. return settingTextField
  241. case "enum":
  242. return settingComboBox
  243. case "extruder":
  244. return settingExtruder
  245. case "optional_extruder":
  246. return settingOptionalExtruder
  247. case "bool":
  248. return settingCheckBox
  249. case "str":
  250. return settingTextField
  251. case "category":
  252. return settingCategory
  253. default:
  254. return settingUnknown
  255. }
  256. }
  257. }
  258. Button
  259. {
  260. id: removeButton
  261. width: UM.Theme.getSize("setting").height
  262. height: UM.Theme.getSize("setting").height + UM.Theme.getSize("narrow_margin").height
  263. onClicked: addedSettingsModel.setVisible(model.key, false)
  264. background: Item
  265. {
  266. UM.ColorImage
  267. {
  268. anchors.verticalCenter: parent.verticalCenter
  269. width: parent.width
  270. height: width
  271. color: parent.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
  272. source: UM.Theme.getIcon("Minus")
  273. }
  274. }
  275. }
  276. // Specialty provider that only watches global_inherits (we can't filter on what property changed we get events
  277. // so we bypass that to make a dedicated provider).
  278. UM.SettingPropertyProvider
  279. {
  280. id: provider
  281. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  282. key: model.key
  283. watchedProperties: [ "value", "enabled", "validationState" ]
  284. storeIndex: 0
  285. removeUnusedValue: false
  286. }
  287. UM.SettingPropertyProvider
  288. {
  289. id: inheritStackProvider
  290. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  291. key: model.key
  292. watchedProperties: [ "limit_to_extruder" ]
  293. }
  294. Connections
  295. {
  296. target: inheritStackProvider
  297. function onPropertiesChanged() { provider.forcePropertiesChanged() }
  298. }
  299. Connections
  300. {
  301. target: UM.ActiveTool
  302. function onPropertiesChanged()
  303. {
  304. // the values cannot be bound with UM.ActiveTool.properties.getValue() calls,
  305. // so here we connect to the signal and update the those values.
  306. if (typeof UM.ActiveTool.properties.getValue("SelectedObjectId") !== "undefined")
  307. {
  308. const selectedObjectId = UM.ActiveTool.properties.getValue("SelectedObjectId")
  309. if (addedSettingsModel.visibilityHandler.selectedObjectId != selectedObjectId)
  310. {
  311. addedSettingsModel.visibilityHandler.selectedObjectId = selectedObjectId
  312. }
  313. }
  314. if (typeof UM.ActiveTool.properties.getValue("ContainerID") !== "undefined")
  315. {
  316. const containerId = UM.ActiveTool.properties.getValue("ContainerID")
  317. if (provider.containerStackId != containerId)
  318. {
  319. provider.containerStackId = containerId
  320. }
  321. if (inheritStackProvider.containerStackId != containerId)
  322. {
  323. inheritStackProvider.containerStackId = containerId
  324. }
  325. }
  326. }
  327. }
  328. }
  329. }
  330. }
  331. Cura.SecondaryButton
  332. {
  333. id: customiseSettingsButton;
  334. height: UM.Theme.getSize("setting_control").height;
  335. visible: currentSettings.visible
  336. text: catalog.i18nc("@action:button", "Select settings");
  337. onClicked:
  338. {
  339. settingPickDialog.visible = true;
  340. if (currentMeshType == "support_mesh")
  341. {
  342. settingPickDialog.additional_excluded_settings = base.allCategoriesExceptSupport;
  343. }
  344. else
  345. {
  346. settingPickDialog.additional_excluded_settings = []
  347. }
  348. }
  349. }
  350. }
  351. SettingPickDialog
  352. {
  353. id: settingPickDialog
  354. }
  355. UM.SettingPropertyProvider
  356. {
  357. id: machineExtruderCount
  358. containerStack: Cura.MachineManager.activeMachine
  359. key: "machine_extruder_count"
  360. watchedProperties: [ "value" ]
  361. storeIndex: 0
  362. }
  363. UM.SettingPropertyProvider
  364. {
  365. id: printSequencePropertyProvider
  366. containerStack: Cura.MachineManager.activeMachine
  367. key: "print_sequence"
  368. watchedProperties: [ "value" ]
  369. storeIndex: 0
  370. }
  371. Component
  372. {
  373. id: settingTextField
  374. Cura.SettingTextField { }
  375. }
  376. Component
  377. {
  378. id: settingComboBox
  379. Cura.SettingComboBox { }
  380. }
  381. Component
  382. {
  383. id: settingExtruder
  384. Cura.SettingExtruder { }
  385. }
  386. Component
  387. {
  388. id: settingOptionalExtruder
  389. Cura.SettingOptionalExtruder { }
  390. }
  391. Component
  392. {
  393. id: settingCheckBox
  394. Cura.SettingCheckBox { }
  395. }
  396. Component
  397. {
  398. id: settingCategory
  399. Cura.SettingCategory { }
  400. }
  401. Component
  402. {
  403. id: settingUnknown
  404. Cura.SettingUnknown { }
  405. }
  406. }