PerObjectSettingsPanel.qml 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. // Copyright (c) 2017 Ultimaker B.V.
  2. // Uranium is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.2
  4. import QtQuick.Controls 1.2
  5. import QtQuick.Controls.Styles 1.2
  6. import UM 1.2 as UM
  7. import Cura 1.0 as Cura
  8. import ".."
  9. Item
  10. {
  11. id: base
  12. width: childrenRect.width
  13. height: childrenRect.height
  14. property var all_categories_except_support: [ "machine_settings", "resolution", "shell", "infill", "material", "speed",
  15. "travel", "cooling", "platform_adhesion", "dual", "meshfix", "blackmagic", "experimental"]
  16. readonly property string normal_mesh_type: ""
  17. readonly property string support_mesh_type: "support_mesh"
  18. readonly property string cutting_mesh_type: "cutting_mesh"
  19. readonly property string infill_mesh_type: "infill_mesh"
  20. readonly property string anti_overhang_mesh_type: "anti_overhang_mesh"
  21. property var currentMeshType: UM.ActiveTool.properties.getValue("MeshType")
  22. // Update the view every time the currentMeshType changes
  23. onCurrentMeshTypeChanged:
  24. {
  25. // set checked state of mesh type buttons
  26. normalButton.checked = currentMeshType === normal_mesh_type
  27. supportMeshButton.checked = currentMeshType === support_mesh_type
  28. overhangMeshButton.checked = currentMeshType === infill_mesh_type || currentMeshType === cutting_mesh_type
  29. antiOverhangMeshButton.checked = currentMeshType === anti_overhang_mesh_type
  30. // update active type label
  31. for (var button in meshTypeButtons.children)
  32. {
  33. if (meshTypeButtons.children[button].checked)
  34. {
  35. meshTypeLabel.text = catalog.i18nc("@label","Mesh Type") + ": " + meshTypeButtons.children[button].text
  36. break
  37. }
  38. }
  39. }
  40. function setOverhangsMeshType()
  41. {
  42. if (infillOnlyCheckbox.checked)
  43. {
  44. setMeshType(infill_mesh_type)
  45. }
  46. else
  47. {
  48. setMeshType(cutting_mesh_type)
  49. }
  50. }
  51. function setMeshType(type)
  52. {
  53. UM.ActiveTool.setProperty("MeshType", type)
  54. }
  55. UM.I18nCatalog { id: catalog; name: "uranium"}
  56. Column
  57. {
  58. id: items
  59. anchors.top: parent.top;
  60. anchors.left: parent.left;
  61. spacing: UM.Theme.getSize("default_margin").height
  62. Row // Mesh type buttons
  63. {
  64. id: meshTypeButtons
  65. spacing: UM.Theme.getSize("default_margin").width
  66. Button
  67. {
  68. id: normalButton
  69. text: catalog.i18nc("@label", "Normal model")
  70. iconSource: UM.Theme.getIcon("pos_normal");
  71. property bool needBorder: true
  72. checkable: true
  73. onClicked: setMeshType(normal_mesh_type);
  74. style: UM.Theme.styles.tool_button;
  75. z: 4
  76. }
  77. Button
  78. {
  79. id: supportMeshButton
  80. text: catalog.i18nc("@label", "Print as support")
  81. iconSource: UM.Theme.getIcon("pos_print_as_support");
  82. property bool needBorder: true
  83. checkable:true
  84. onClicked: setMeshType(support_mesh_type)
  85. style: UM.Theme.styles.tool_button;
  86. z: 3
  87. }
  88. Button
  89. {
  90. id: overhangMeshButton
  91. text: catalog.i18nc("@label", "Modify settings for overlays")
  92. iconSource: UM.Theme.getIcon("pos_modify_overlaps");
  93. property bool needBorder: true
  94. checkable:true
  95. onClicked: setMeshType(infill_mesh_type)
  96. style: UM.Theme.styles.tool_button;
  97. z: 2
  98. }
  99. Button
  100. {
  101. id: antiOverhangMeshButton
  102. text: catalog.i18nc("@label", "Don't support overlaps")
  103. iconSource: UM.Theme.getIcon("pos_modify_dont_support_overlap");
  104. property bool needBorder: true
  105. checkable: true
  106. onClicked: setMeshType(anti_overhang_mesh_type)
  107. style: UM.Theme.styles.tool_button;
  108. z: 1
  109. }
  110. }
  111. Label
  112. {
  113. id: meshTypeLabel
  114. font: UM.Theme.getFont("default")
  115. color: UM.Theme.getColor("text")
  116. height: UM.Theme.getSize("setting").height
  117. verticalAlignment: Text.AlignVCenter
  118. }
  119. CheckBox
  120. {
  121. id: infillOnlyCheckbox
  122. text: catalog.i18nc("@action:checkbox","Infill only");
  123. style: UM.Theme.styles.checkbox;
  124. visible: currentMeshType === infill_mesh_type || currentMeshType === cutting_mesh_type
  125. onClicked: setOverhangsMeshType()
  126. Binding
  127. {
  128. target: infillOnlyCheckbox
  129. property: "checked"
  130. value: currentMeshType === infill_mesh_type
  131. }
  132. }
  133. Column // Settings Dialog
  134. {
  135. // This is to ensure that the panel is first increasing in size up to 200 and then shows a scrollbar.
  136. // It kinda looks ugly otherwise (big panel, no content on it)
  137. id: currentSettings
  138. property int maximumHeight: 200 * screenScaleFactor
  139. height: Math.min(contents.count * (UM.Theme.getSize("section").height + UM.Theme.getSize("default_lining").height), maximumHeight)
  140. visible: currentMeshType != "anti_overhang_mesh"
  141. ScrollView
  142. {
  143. height: parent.height
  144. width: UM.Theme.getSize("setting").width + UM.Theme.getSize("default_margin").width
  145. style: UM.Theme.styles.scrollview
  146. ListView
  147. {
  148. id: contents
  149. spacing: UM.Theme.getSize("default_lining").height
  150. model: UM.SettingDefinitionsModel
  151. {
  152. id: addedSettingsModel
  153. containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
  154. expanded: [ "*" ]
  155. filter:
  156. {
  157. if (printSequencePropertyProvider.properties.value == "one_at_a_time")
  158. {
  159. return {"settable_per_meshgroup": true}
  160. }
  161. return {"settable_per_mesh": true}
  162. }
  163. exclude:
  164. {
  165. var excluded_settings = [ "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ]
  166. if(currentMeshType == "support_mesh")
  167. {
  168. excluded_settings = excluded_settings.concat(base.all_categories_except_support)
  169. }
  170. return excluded_settings
  171. }
  172. visibilityHandler: Cura.PerObjectSettingVisibilityHandler
  173. {
  174. selectedObjectId: UM.ActiveTool.properties.getValue("SelectedObjectId")
  175. }
  176. // For some reason the model object is updated after removing him from the memory and
  177. // it happens only on Windows. For this reason, set the destroyed value manually.
  178. Component.onDestruction:
  179. {
  180. setDestroyed(true)
  181. }
  182. }
  183. delegate: Row
  184. {
  185. spacing: - UM.Theme.getSize("default_margin").width
  186. Loader
  187. {
  188. id: settingLoader
  189. width: UM.Theme.getSize("setting").width
  190. height: UM.Theme.getSize("section").height
  191. property var definition: model
  192. property var settingDefinitionsModel: addedSettingsModel
  193. property var propertyProvider: provider
  194. property var globalPropertyProvider: inheritStackProvider
  195. property var externalResetHandler: false
  196. //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
  197. //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
  198. //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
  199. asynchronous: model.type != "enum" && model.type != "extruder"
  200. onLoaded:
  201. {
  202. settingLoader.item.showRevertButton = false
  203. settingLoader.item.showInheritButton = false
  204. settingLoader.item.showLinkedSettingIcon = false
  205. settingLoader.item.doDepthIndentation = false
  206. settingLoader.item.doQualityUserSettingEmphasis = false
  207. }
  208. sourceComponent:
  209. {
  210. switch(model.type)
  211. {
  212. case "int":
  213. return settingTextField
  214. case "[int]":
  215. return settingTextField
  216. case "float":
  217. return settingTextField
  218. case "enum":
  219. return settingComboBox
  220. case "extruder":
  221. return settingExtruder
  222. case "optional_extruder":
  223. return settingOptionalExtruder
  224. case "bool":
  225. return settingCheckBox
  226. case "str":
  227. return settingTextField
  228. case "category":
  229. return settingCategory
  230. default:
  231. return settingUnknown
  232. }
  233. }
  234. }
  235. Button
  236. {
  237. width: Math.round(UM.Theme.getSize("setting").height / 2)
  238. height: UM.Theme.getSize("setting").height
  239. onClicked: addedSettingsModel.setVisible(model.key, false)
  240. style: ButtonStyle
  241. {
  242. background: Item
  243. {
  244. UM.RecolorImage
  245. {
  246. anchors.verticalCenter: parent.verticalCenter
  247. width: parent.width
  248. height: width
  249. sourceSize.height: width
  250. color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
  251. source: UM.Theme.getIcon("minus")
  252. }
  253. }
  254. }
  255. }
  256. // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events
  257. // so we bypass that to make a dedicated provider).
  258. UM.SettingPropertyProvider
  259. {
  260. id: provider
  261. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  262. key: model.key
  263. watchedProperties: [ "value", "enabled", "validationState" ]
  264. storeIndex: 0
  265. removeUnusedValue: false
  266. }
  267. UM.SettingPropertyProvider
  268. {
  269. id: inheritStackProvider
  270. containerStackId: UM.ActiveTool.properties.getValue("ContainerID")
  271. key: model.key
  272. watchedProperties: [ "limit_to_extruder" ]
  273. }
  274. Connections
  275. {
  276. target: inheritStackProvider
  277. onPropertiesChanged:
  278. {
  279. provider.forcePropertiesChanged()
  280. }
  281. }
  282. Connections
  283. {
  284. target: UM.ActiveTool
  285. onPropertiesChanged:
  286. {
  287. // the values cannot be bound with UM.ActiveTool.properties.getValue() calls,
  288. // so here we connect to the signal and update the those values.
  289. if (typeof UM.ActiveTool.properties.getValue("SelectedObjectId") !== "undefined")
  290. {
  291. const selectedObjectId = UM.ActiveTool.properties.getValue("SelectedObjectId")
  292. if (addedSettingsModel.visibilityHandler.selectedObjectId != selectedObjectId)
  293. {
  294. addedSettingsModel.visibilityHandler.selectedObjectId = selectedObjectId
  295. }
  296. }
  297. if (typeof UM.ActiveTool.properties.getValue("ContainerID") !== "undefined")
  298. {
  299. const containerId = UM.ActiveTool.properties.getValue("ContainerID")
  300. if (provider.containerStackId != containerId)
  301. {
  302. provider.containerStackId = containerId
  303. }
  304. if (inheritStackProvider.containerStackId != containerId)
  305. {
  306. inheritStackProvider.containerStackId = containerId
  307. }
  308. }
  309. }
  310. }
  311. }
  312. }
  313. }
  314. }
  315. Cura.SecondaryButton
  316. {
  317. id: customiseSettingsButton;
  318. height: UM.Theme.getSize("setting_control").height;
  319. visible: currentSettings.visible
  320. text: catalog.i18nc("@action:button", "Select settings");
  321. onClicked:
  322. {
  323. settingPickDialog.visible = true;
  324. if (currentMeshType == "support_mesh")
  325. {
  326. settingPickDialog.additional_excluded_settings = base.all_categories_except_support;
  327. }
  328. else
  329. {
  330. settingPickDialog.additional_excluded_settings = []
  331. }
  332. }
  333. }
  334. }
  335. UM.Dialog
  336. {
  337. id: settingPickDialog
  338. title: catalog.i18nc("@title:window", "Select Settings to Customize for this model")
  339. width: screenScaleFactor * 360
  340. property var additional_excluded_settings
  341. onVisibilityChanged:
  342. {
  343. // force updating the model to sync it with addedSettingsModel
  344. if(visible)
  345. {
  346. // Set skip setting, it will prevent from resetting selected mesh_type
  347. contents.model.visibilityHandler.addSkipResetSetting(currentMeshType)
  348. listview.model.forceUpdate()
  349. updateFilter()
  350. }
  351. }
  352. function updateFilter()
  353. {
  354. var new_filter = {}
  355. new_filter["settable_per_mesh"] = true
  356. // Don't filter on "settable_per_meshgroup" any more when `printSequencePropertyProvider.properties.value`
  357. // is set to "one_at_a_time", because the current backend architecture isn't ready for that.
  358. if(filterInput.text != "")
  359. {
  360. new_filter["i18n_label"] = "*" + filterInput.text
  361. }
  362. listview.model.filter = new_filter
  363. }
  364. TextField
  365. {
  366. id: filterInput
  367. anchors
  368. {
  369. top: parent.top
  370. left: parent.left
  371. right: toggleShowAll.left
  372. rightMargin: UM.Theme.getSize("default_margin").width
  373. }
  374. placeholderText: catalog.i18nc("@label:textbox", "Filter...")
  375. onTextChanged: settingPickDialog.updateFilter()
  376. }
  377. CheckBox
  378. {
  379. id: toggleShowAll
  380. anchors
  381. {
  382. top: parent.top
  383. right: parent.right
  384. }
  385. text: catalog.i18nc("@label:checkbox", "Show all")
  386. checked: listview.model.showAll
  387. onClicked:
  388. {
  389. listview.model.showAll = checked
  390. }
  391. }
  392. ScrollView
  393. {
  394. id: scrollView
  395. anchors
  396. {
  397. top: filterInput.bottom
  398. left: parent.left
  399. right: parent.right
  400. bottom: parent.bottom
  401. }
  402. ListView
  403. {
  404. id:listview
  405. model: UM.SettingDefinitionsModel
  406. {
  407. id: definitionsModel
  408. containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
  409. visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
  410. expanded: [ "*" ]
  411. exclude:
  412. {
  413. var excluded_settings = [ "machine_settings", "command_line_settings", "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ]
  414. excluded_settings = excluded_settings.concat(settingPickDialog.additional_excluded_settings)
  415. return excluded_settings
  416. }
  417. }
  418. delegate:Loader
  419. {
  420. id: loader
  421. width: parent.width
  422. height: model.type != undefined ? UM.Theme.getSize("section").height : 0
  423. property var definition: model
  424. property var settingDefinitionsModel: definitionsModel
  425. asynchronous: true
  426. source:
  427. {
  428. switch(model.type)
  429. {
  430. case "category":
  431. return "PerObjectCategory.qml"
  432. default:
  433. return "PerObjectItem.qml"
  434. }
  435. }
  436. }
  437. Component.onCompleted: settingPickDialog.updateFilter()
  438. }
  439. }
  440. rightButtons: [
  441. Button
  442. {
  443. text: catalog.i18nc("@action:button", "Close")
  444. onClicked: settingPickDialog.visible = false
  445. }
  446. ]
  447. }
  448. UM.SettingPropertyProvider
  449. {
  450. id: machineExtruderCount
  451. containerStack: Cura.MachineManager.activeMachine
  452. key: "machine_extruder_count"
  453. watchedProperties: [ "value" ]
  454. storeIndex: 0
  455. }
  456. UM.SettingPropertyProvider
  457. {
  458. id: printSequencePropertyProvider
  459. containerStack: Cura.MachineManager.activeMachine
  460. key: "print_sequence"
  461. watchedProperties: [ "value" ]
  462. storeIndex: 0
  463. }
  464. SystemPalette { id: palette }
  465. Component
  466. {
  467. id: settingTextField
  468. Cura.SettingTextField { }
  469. }
  470. Component
  471. {
  472. id: settingComboBox
  473. Cura.SettingComboBox { }
  474. }
  475. Component
  476. {
  477. id: settingExtruder
  478. Cura.SettingExtruder { }
  479. }
  480. Component
  481. {
  482. id: settingOptionalExtruder
  483. Cura.SettingOptionalExtruder { }
  484. }
  485. Component
  486. {
  487. id: settingCheckBox
  488. Cura.SettingCheckBox { }
  489. }
  490. Component
  491. {
  492. id: settingCategory
  493. Cura.SettingCategory { }
  494. }
  495. Component
  496. {
  497. id: settingUnknown
  498. Cura.SettingUnknown { }
  499. }
  500. }