RecommendedInfillDensitySelector.qml 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Copyright (c) 2022 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.7
  4. import QtQuick.Controls 2.15
  5. import UM 1.5 as UM
  6. import Cura 1.0 as Cura
  7. //
  8. // Infill
  9. //
  10. Item
  11. {
  12. id: infillRow
  13. height: childrenRect.height
  14. property real labelColumnWidth: Math.round(width / 3)
  15. // Create a binding to update the icon when the infill density changes
  16. Binding
  17. {
  18. target: infillRowTitle
  19. property: "source"
  20. value:
  21. {
  22. var density = parseInt(infillDensity.properties.value)
  23. if (parseInt(infillSteps.properties.value) != 0)
  24. {
  25. return UM.Theme.getIcon("InfillGradual")
  26. }
  27. if (density <= 0)
  28. {
  29. return UM.Theme.getIcon("Infill0")
  30. }
  31. if (density < 40)
  32. {
  33. return UM.Theme.getIcon("Infill3")
  34. }
  35. if (density < 90)
  36. {
  37. return UM.Theme.getIcon("Infill2")
  38. }
  39. return UM.Theme.getIcon("Infill100")
  40. }
  41. }
  42. // We use a binding to make sure that after manually setting infillSlider.value it is still bound to the property provider
  43. Binding
  44. {
  45. target: infillSlider
  46. property: "value"
  47. value: {
  48. // The infill slider has a max value of 100. When it is given a value > 100 onValueChanged updates the setting to be 100.
  49. // When changing to an intent with infillDensity > 100, it would always be clamped to 100.
  50. // This will force the slider to ignore the first onValueChanged for values > 100 so higher values can be set.
  51. var density = parseInt(infillDensity.properties.value)
  52. if (density > 100) {
  53. infillSlider.ignoreValueChange = true
  54. }
  55. return density
  56. }
  57. }
  58. // Here are the elements that are shown in the left column
  59. Cura.IconWithText
  60. {
  61. id: infillRowTitle
  62. anchors.top: parent.top
  63. anchors.left: parent.left
  64. source: UM.Theme.getIcon("Infill1")
  65. text: catalog.i18nc("@label", "Infill") + " (%)"
  66. font: UM.Theme.getFont("medium")
  67. width: labelColumnWidth
  68. iconSize: UM.Theme.getSize("medium_button_icon").width
  69. tooltipText: catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top.")
  70. }
  71. Item
  72. {
  73. id: infillSliderContainer
  74. height: childrenRect.height
  75. anchors
  76. {
  77. left: infillRowTitle.right
  78. right: parent.right
  79. verticalCenter: infillRowTitle.verticalCenter
  80. }
  81. Slider
  82. {
  83. id: infillSlider
  84. property var ignoreValueChange: false
  85. width: parent.width
  86. height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider
  87. from: 0
  88. to: 100
  89. stepSize: 1
  90. // disable slider when gradual support is enabled
  91. enabled: parseInt(infillSteps.properties.value) == 0
  92. // set initial value from stack
  93. value: parseInt(infillDensity.properties.value)
  94. //Draw line
  95. background: Rectangle
  96. {
  97. id: backgroundLine
  98. height: UM.Theme.getSize("print_setup_slider_groove").height
  99. width: parent.width - UM.Theme.getSize("print_setup_slider_handle").width
  100. anchors.horizontalCenter: parent.horizontalCenter
  101. anchors.verticalCenter: parent.verticalCenter
  102. color: infillSlider.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  103. Repeater
  104. {
  105. id: repeater
  106. anchors.fill: parent
  107. model: infillSlider.to / infillSlider.stepSize + 1
  108. Rectangle
  109. {
  110. color: infillSlider.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  111. implicitWidth: UM.Theme.getSize("print_setup_slider_tickmarks").width
  112. implicitHeight: UM.Theme.getSize("print_setup_slider_tickmarks").height
  113. anchors.verticalCenter: parent.verticalCenter
  114. // Do not use Math.round otherwise the tickmarks won't be aligned
  115. // (space between steps) * index of step
  116. x: (backgroundLine.width / (repeater.count - 1)) * index
  117. radius: Math.round(implicitWidth / 2)
  118. visible: (index % 10) == 0 // Only show steps of 10%
  119. UM.Label
  120. {
  121. text: index
  122. visible: (index % 20) == 0 // Only show steps of 20%
  123. anchors.horizontalCenter: parent.horizontalCenter
  124. y: UM.Theme.getSize("thin_margin").height
  125. color: UM.Theme.getColor("quality_slider_available")
  126. }
  127. }
  128. }
  129. }
  130. handle: Rectangle
  131. {
  132. id: handleButton
  133. x: infillSlider.leftPadding + infillSlider.visualPosition * (infillSlider.availableWidth - width)
  134. y: infillSlider.topPadding + infillSlider.availableHeight / 2 - height / 2
  135. color: infillSlider.enabled ? UM.Theme.getColor("primary") : UM.Theme.getColor("quality_slider_unavailable")
  136. implicitWidth: UM.Theme.getSize("print_setup_slider_handle").width
  137. implicitHeight: implicitWidth
  138. radius: Math.round(implicitWidth / 2)
  139. border.color: UM.Theme.getColor("slider_groove_fill")
  140. border.width: UM.Theme.getSize("default_lining").height
  141. }
  142. Connections
  143. {
  144. target: infillSlider
  145. function onValueChanged()
  146. {
  147. if (infillSlider.ignoreValueChange)
  148. {
  149. infillSlider.ignoreValueChange = false
  150. return
  151. }
  152. // Don't update if the setting value, if the slider has the same value
  153. if (parseInt(infillDensity.properties.value) == infillSlider.value)
  154. {
  155. return
  156. }
  157. // Round the slider value to the nearest multiple of 10 (simulate step size of 10)
  158. var roundedSliderValue = Math.round(infillSlider.value / 10) * 10
  159. // Update the slider value to represent the rounded value
  160. infillSlider.value = roundedSliderValue
  161. // Update value only if the Recommended mode is Active,
  162. // Otherwise if I change the value in the Custom mode the Recommended view will try to repeat
  163. // same operation
  164. const active_mode = UM.Preferences.getValue("cura/active_mode")
  165. if (visible // Workaround: 'visible' is checked because on startup in Windows it spuriously gets an 'onValueChanged' with value '0' if this isn't checked.
  166. && (active_mode == 0 || active_mode == "simple"))
  167. {
  168. Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", roundedSliderValue)
  169. Cura.MachineManager.resetSettingForAllExtruders("infill_line_distance")
  170. }
  171. }
  172. }
  173. }
  174. }
  175. // Gradual Support Infill Checkbox
  176. UM.CheckBox
  177. {
  178. id: enableGradualInfillCheckBox
  179. property alias _hovered: enableGradualInfillMouseArea.containsMouse
  180. anchors.top: infillSliderContainer.bottom
  181. anchors.topMargin: UM.Theme.getSize("wide_margin").height
  182. anchors.left: infillSliderContainer.left
  183. text: catalog.i18nc("@label", "Gradual infill")
  184. enabled: recommendedPrintSetup.settingsEnabled
  185. visible: infillSteps.properties.enabled == "True"
  186. checked: parseInt(infillSteps.properties.value) > 0
  187. MouseArea
  188. {
  189. id: enableGradualInfillMouseArea
  190. anchors.fill: parent
  191. hoverEnabled: true
  192. enabled: true
  193. property var previousInfillDensity: parseInt(infillDensity.properties.value)
  194. onClicked:
  195. {
  196. // Set to 90% only when enabling gradual infill
  197. var newInfillDensity;
  198. if (parseInt(infillSteps.properties.value) == 0)
  199. {
  200. previousInfillDensity = parseInt(infillDensity.properties.value)
  201. newInfillDensity = 90
  202. } else {
  203. newInfillDensity = previousInfillDensity
  204. }
  205. Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity))
  206. var infill_steps_value = 0
  207. if (parseInt(infillSteps.properties.value) == 0)
  208. {
  209. infill_steps_value = 5
  210. }
  211. Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value)
  212. }
  213. onEntered: base.showTooltip(enableGradualInfillCheckBox, Qt.point(-infillSliderContainer.x - UM.Theme.getSize("thick_margin").width, 0),
  214. catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top."))
  215. onExited: base.hideTooltip()
  216. }
  217. }
  218. UM.SettingPropertyProvider
  219. {
  220. id: infillDensity
  221. containerStackId: Cura.MachineManager.activeStackId
  222. key: "infill_sparse_density"
  223. watchedProperties: [ "value" ]
  224. storeIndex: 0
  225. }
  226. UM.SettingPropertyProvider
  227. {
  228. id: infillSteps
  229. containerStackId: Cura.MachineManager.activeStackId
  230. key: "gradual_infill_steps"
  231. watchedProperties: ["value", "enabled"]
  232. storeIndex: 0
  233. }
  234. }