SidebarSimple.qml 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  1. // Copyright (c) 2018 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.7
  4. import QtQuick.Controls 1.4
  5. import QtQuick.Controls.Styles 1.4
  6. import QtQuick.Layouts 1.3
  7. import UM 1.2 as UM
  8. import Cura 1.0 as Cura
  9. Item
  10. {
  11. id: base
  12. signal showTooltip(Item item, point location, string text);
  13. signal hideTooltip();
  14. property Action configureSettings;
  15. property variant minimumPrintTime: PrintInformation.minimumPrintTime;
  16. property variant maximumPrintTime: PrintInformation.maximumPrintTime;
  17. property bool settingsEnabled: Cura.ExtruderManager.activeExtruderStackId || extrudersEnabledCount.properties.value == 1
  18. Component.onCompleted: PrintInformation.enabled = true
  19. Component.onDestruction: PrintInformation.enabled = false
  20. UM.I18nCatalog { id: catalog; name: "cura" }
  21. ScrollView
  22. {
  23. visible: Cura.MachineManager.activeMachineName != "" // If no printers added then the view is invisible
  24. anchors.fill: parent
  25. style: UM.Theme.styles.scrollview
  26. flickableItem.flickableDirection: Flickable.VerticalFlick
  27. Rectangle
  28. {
  29. width: childrenRect.width
  30. height: childrenRect.height
  31. color: UM.Theme.getColor("sidebar")
  32. //
  33. // Quality profile
  34. //
  35. Item
  36. {
  37. id: qualityRow
  38. height: UM.Theme.getSize("sidebar_margin").height
  39. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  40. anchors.left: parent.left
  41. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  42. anchors.right: parent.right
  43. Timer
  44. {
  45. id: qualitySliderChangeTimer
  46. interval: 50
  47. running: false
  48. repeat: false
  49. onTriggered: {
  50. var item = Cura.QualityProfilesDropDownMenuModel.getItem(qualitySlider.value);
  51. Cura.MachineManager.activeQualityGroup = item.quality_group;
  52. }
  53. }
  54. Component.onCompleted: qualityModel.update()
  55. Connections
  56. {
  57. target: Cura.QualityProfilesDropDownMenuModel
  58. onItemsChanged: qualityModel.update()
  59. }
  60. Connections {
  61. target: base
  62. onVisibleChanged:
  63. {
  64. // update needs to be called when the widgets are visible, otherwise the step width calculation
  65. // will fail because the width of an invisible item is 0.
  66. if (visible) {
  67. qualityModel.update();
  68. }
  69. }
  70. }
  71. ListModel
  72. {
  73. id: qualityModel
  74. property var totalTicks: 0
  75. property var availableTotalTicks: 0
  76. property var existingQualityProfile: 0
  77. property var qualitySliderActiveIndex: 0
  78. property var qualitySliderStepWidth: 0
  79. property var qualitySliderAvailableMin: 0
  80. property var qualitySliderAvailableMax: 0
  81. property var qualitySliderMarginRight: 0
  82. function update () {
  83. reset()
  84. var availableMin = -1
  85. var availableMax = -1
  86. for (var i = 0; i < Cura.QualityProfilesDropDownMenuModel.rowCount(); i++) {
  87. var qualityItem = Cura.QualityProfilesDropDownMenuModel.getItem(i)
  88. // Add each quality item to the UI quality model
  89. qualityModel.append(qualityItem)
  90. // Set selected value
  91. if (Cura.MachineManager.activeQualityType == qualityItem.quality_type) {
  92. // set to -1 when switching to user created profile so all ticks are clickable
  93. if (Cura.SimpleModeSettingsManager.isProfileUserCreated) {
  94. qualityModel.qualitySliderActiveIndex = -1
  95. } else {
  96. qualityModel.qualitySliderActiveIndex = i
  97. }
  98. qualityModel.existingQualityProfile = 1
  99. }
  100. // Set min available
  101. if (qualityItem.available && availableMin == -1) {
  102. availableMin = i
  103. }
  104. // Set max available
  105. if (qualityItem.available) {
  106. availableMax = i
  107. }
  108. }
  109. // Set total available ticks for active slider part
  110. if (availableMin != -1) {
  111. qualityModel.availableTotalTicks = availableMax - availableMin + 1
  112. }
  113. // Calculate slider values
  114. calculateSliderStepWidth(qualityModel.totalTicks)
  115. calculateSliderMargins(availableMin, availableMax, qualityModel.totalTicks)
  116. qualityModel.qualitySliderAvailableMin = availableMin
  117. qualityModel.qualitySliderAvailableMax = availableMax
  118. }
  119. function calculateSliderStepWidth (totalTicks) {
  120. qualityModel.qualitySliderStepWidth = totalTicks != 0 ? Math.round((base.width * 0.55) / (totalTicks)) : 0
  121. }
  122. function calculateSliderMargins (availableMin, availableMax, totalTicks) {
  123. if (availableMin == -1 || (availableMin == 0 && availableMax == 0)) {
  124. qualityModel.qualitySliderMarginRight = Math.round(base.width * 0.55)
  125. } else if (availableMin == availableMax) {
  126. qualityModel.qualitySliderMarginRight = Math.round((totalTicks - availableMin) * qualitySliderStepWidth)
  127. } else {
  128. qualityModel.qualitySliderMarginRight = Math.round((totalTicks - availableMax) * qualitySliderStepWidth)
  129. }
  130. }
  131. function reset () {
  132. qualityModel.clear()
  133. qualityModel.availableTotalTicks = 0
  134. qualityModel.existingQualityProfile = 0
  135. // check, the ticks count cannot be less than zero
  136. qualityModel.totalTicks = Math.max(0, Cura.QualityProfilesDropDownMenuModel.rowCount() - 1)
  137. }
  138. }
  139. Label
  140. {
  141. id: qualityRowTitle
  142. text: catalog.i18nc("@label", "Layer Height")
  143. font: UM.Theme.getFont("default")
  144. color: UM.Theme.getColor("text")
  145. }
  146. // Show titles for the each quality slider ticks
  147. Item
  148. {
  149. y: -5;
  150. anchors.left: speedSlider.left
  151. Repeater
  152. {
  153. model: qualityModel
  154. Label
  155. {
  156. anchors.verticalCenter: parent.verticalCenter
  157. anchors.top: parent.top
  158. anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2)
  159. color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesDropDownMenuModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  160. text:
  161. {
  162. var result = ""
  163. if(Cura.MachineManager.activeMachine != null)
  164. {
  165. result = Cura.QualityProfilesDropDownMenuModel.getItem(index).layer_height
  166. if(result == undefined)
  167. {
  168. result = "";
  169. }
  170. else
  171. {
  172. result = Number(Math.round(result + "e+2") + "e-2"); //Round to 2 decimals. Javascript makes this difficult...
  173. if (result == undefined || result != result) //Parse failure.
  174. {
  175. result = "";
  176. }
  177. }
  178. }
  179. return result
  180. }
  181. x: {
  182. // Make sure the text aligns correctly with each tick
  183. if (qualityModel.totalTicks == 0) {
  184. // If there is only one tick, align it centrally
  185. return Math.round(((base.width * 0.55) - width) / 2)
  186. } else if (index == 0) {
  187. return Math.round(base.width * 0.55 / qualityModel.totalTicks) * index
  188. } else if (index == qualityModel.totalTicks) {
  189. return Math.round(base.width * 0.55 / qualityModel.totalTicks) * index - width
  190. } else {
  191. return Math.round((base.width * 0.55 / qualityModel.totalTicks) * index - (width / 2))
  192. }
  193. }
  194. }
  195. }
  196. }
  197. //Print speed slider
  198. Item
  199. {
  200. id: speedSlider
  201. width: Math.round(base.width * 0.55)
  202. height: UM.Theme.getSize("sidebar_margin").height
  203. anchors.right: parent.right
  204. anchors.top: parent.top
  205. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  206. // This Item is used only for tooltip, for slider area which is unavailable
  207. Item
  208. {
  209. function showTooltip (showTooltip)
  210. {
  211. if (showTooltip) {
  212. var content = catalog.i18nc("@tooltip", "This quality profile is not available for you current material and nozzle configuration. Please change these to enable this quality profile")
  213. base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, customisedSettings.height), content)
  214. }
  215. else {
  216. base.hideTooltip()
  217. }
  218. }
  219. id: unavailableLineToolTip
  220. height: 20 // hovered area height
  221. z: parent.z + 1 // should be higher, otherwise the area can be hovered
  222. x: 0
  223. anchors.verticalCenter: qualitySlider.verticalCenter
  224. Rectangle
  225. {
  226. id: leftArea
  227. width:
  228. {
  229. if (qualityModel.availableTotalTicks == 0) {
  230. return qualityModel.qualitySliderStepWidth * qualityModel.totalTicks
  231. }
  232. return qualityModel.qualitySliderStepWidth * qualityModel.qualitySliderAvailableMin - 10
  233. }
  234. height: parent.height
  235. color: "transparent"
  236. MouseArea
  237. {
  238. anchors.fill: parent
  239. hoverEnabled: true
  240. enabled: Cura.SimpleModeSettingsManager.isProfileUserCreated == false
  241. onEntered: unavailableLineToolTip.showTooltip(true)
  242. onExited: unavailableLineToolTip.showTooltip(false)
  243. }
  244. }
  245. Rectangle
  246. {
  247. id: rightArea
  248. width: {
  249. if(qualityModel.availableTotalTicks == 0)
  250. return 0
  251. return qualityModel.qualitySliderMarginRight - 10
  252. }
  253. height: parent.height
  254. color: "transparent"
  255. x: {
  256. if (qualityModel.availableTotalTicks == 0) {
  257. return 0
  258. }
  259. var leftUnavailableArea = qualityModel.qualitySliderStepWidth * qualityModel.qualitySliderAvailableMin
  260. var totalGap = qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks -1) + leftUnavailableArea + 10
  261. return totalGap
  262. }
  263. MouseArea {
  264. anchors.fill: parent
  265. hoverEnabled: true
  266. enabled: Cura.SimpleModeSettingsManager.isProfileUserCreated == false
  267. onEntered: unavailableLineToolTip.showTooltip(true)
  268. onExited: unavailableLineToolTip.showTooltip(false)
  269. }
  270. }
  271. }
  272. // Draw Unavailable line
  273. Rectangle
  274. {
  275. id: groovechildrect
  276. width: Math.round(base.width * 0.55)
  277. height: 2 * screenScaleFactor
  278. color: UM.Theme.getColor("quality_slider_unavailable")
  279. anchors.verticalCenter: qualitySlider.verticalCenter
  280. x: 0
  281. }
  282. // Draw ticks
  283. Repeater
  284. {
  285. id: qualityRepeater
  286. model: qualityModel.totalTicks > 0 ? qualityModel : 0
  287. Rectangle
  288. {
  289. anchors.verticalCenter: parent.verticalCenter
  290. color: Cura.QualityProfilesDropDownMenuModel.getItem(index).available ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  291. width: 1 * screenScaleFactor
  292. height: 6 * screenScaleFactor
  293. y: 0
  294. x: Math.round(qualityModel.qualitySliderStepWidth * index)
  295. }
  296. }
  297. Slider
  298. {
  299. id: qualitySlider
  300. height: UM.Theme.getSize("sidebar_margin").height
  301. anchors.bottom: speedSlider.bottom
  302. enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized
  303. visible: qualityModel.availableTotalTicks > 0
  304. updateValueWhileDragging : false
  305. minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0
  306. // maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly
  307. // speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available)
  308. maximumValue: qualityModel.qualitySliderAvailableMax >= 1 ? qualityModel.qualitySliderAvailableMax : 1
  309. stepSize: 1
  310. value: qualityModel.qualitySliderActiveIndex
  311. width: qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks - 1)
  312. anchors.right: parent.right
  313. anchors.rightMargin: qualityModel.qualitySliderMarginRight
  314. style: SliderStyle
  315. {
  316. //Draw Available line
  317. groove: Rectangle {
  318. implicitHeight: 2 * screenScaleFactor
  319. color: UM.Theme.getColor("quality_slider_available")
  320. radius: Math.round(height / 2)
  321. }
  322. handle: Item {
  323. Rectangle {
  324. id: qualityhandleButton
  325. anchors.centerIn: parent
  326. color: UM.Theme.getColor("quality_slider_available")
  327. implicitWidth: 10 * screenScaleFactor
  328. implicitHeight: implicitWidth
  329. radius: Math.round(implicitWidth / 2)
  330. visible: !Cura.SimpleModeSettingsManager.isProfileCustomized && !Cura.SimpleModeSettingsManager.isProfileUserCreated && qualityModel.existingQualityProfile
  331. }
  332. }
  333. }
  334. onValueChanged: {
  335. // only change if an active machine is set and the slider is visible at all.
  336. if (Cura.MachineManager.activeMachine != null && visible) {
  337. // prevent updating during view initializing. Trigger only if the value changed by user
  338. if (qualitySlider.value != qualityModel.qualitySliderActiveIndex && qualityModel.qualitySliderActiveIndex != -1) {
  339. // start updating with short delay
  340. qualitySliderChangeTimer.start()
  341. }
  342. }
  343. }
  344. }
  345. MouseArea
  346. {
  347. id: speedSliderMouseArea
  348. anchors.fill: parent
  349. hoverEnabled: true
  350. enabled: Cura.SimpleModeSettingsManager.isProfileUserCreated
  351. onEntered:
  352. {
  353. var content = catalog.i18nc("@tooltip","A custom profile is currently active. To enable the quality slider, choose a default quality profile in Custom tab")
  354. base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, customisedSettings.height), content)
  355. }
  356. onExited:
  357. {
  358. base.hideTooltip();
  359. }
  360. }
  361. }
  362. Label
  363. {
  364. id: speedLabel
  365. anchors.top: speedSlider.bottom
  366. anchors.left: parent.left
  367. text: catalog.i18nc("@label", "Print Speed")
  368. font: UM.Theme.getFont("default")
  369. color: UM.Theme.getColor("text")
  370. width: Math.round(UM.Theme.getSize("sidebar").width * 0.35)
  371. elide: Text.ElideRight
  372. }
  373. Label
  374. {
  375. anchors.bottom: speedLabel.bottom
  376. anchors.left: speedSlider.left
  377. text: catalog.i18nc("@label", "Slower")
  378. font: UM.Theme.getFont("default")
  379. color: (qualityModel.availableTotalTicks > 1) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  380. horizontalAlignment: Text.AlignLeft
  381. }
  382. Label
  383. {
  384. anchors.bottom: speedLabel.bottom
  385. anchors.right: speedSlider.right
  386. text: catalog.i18nc("@label", "Faster")
  387. font: UM.Theme.getFont("default")
  388. color: (qualityModel.availableTotalTicks > 1) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  389. horizontalAlignment: Text.AlignRight
  390. }
  391. UM.SimpleButton
  392. {
  393. id: customisedSettings
  394. visible: Cura.SimpleModeSettingsManager.isProfileCustomized || Cura.SimpleModeSettingsManager.isProfileUserCreated
  395. height: Math.round(speedSlider.height * 0.8)
  396. width: Math.round(speedSlider.height * 0.8)
  397. anchors.verticalCenter: speedSlider.verticalCenter
  398. anchors.right: speedSlider.left
  399. anchors.rightMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2)
  400. color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button");
  401. iconSource: UM.Theme.getIcon("reset");
  402. onClicked:
  403. {
  404. // if the current profile is user-created, switch to a built-in quality
  405. Cura.MachineManager.resetToUseDefaultQuality()
  406. }
  407. onEntered:
  408. {
  409. var content = catalog.i18nc("@tooltip","You have modified some profile settings. If you want to change these go to custom mode.")
  410. base.showTooltip(qualityRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, customisedSettings.height), content)
  411. }
  412. onExited: base.hideTooltip()
  413. }
  414. }
  415. //
  416. // Infill
  417. //
  418. Item
  419. {
  420. id: infillCellLeft
  421. anchors.top: qualityRow.bottom
  422. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 2
  423. anchors.left: parent.left
  424. width: Math.round(UM.Theme.getSize("sidebar").width * .45) - UM.Theme.getSize("sidebar_margin").width
  425. Label
  426. {
  427. id: infillLabel
  428. text: catalog.i18nc("@label", "Infill")
  429. font: UM.Theme.getFont("default")
  430. color: UM.Theme.getColor("text")
  431. anchors.top: parent.top
  432. anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 1.7)
  433. anchors.left: parent.left
  434. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  435. }
  436. }
  437. Item
  438. {
  439. id: infillCellRight
  440. height: infillSlider.height + UM.Theme.getSize("sidebar_margin").height + enableGradualInfillCheckBox.visible * (enableGradualInfillCheckBox.height + UM.Theme.getSize("sidebar_margin").height)
  441. width: Math.round(UM.Theme.getSize("sidebar").width * .55)
  442. anchors.left: infillCellLeft.right
  443. anchors.top: infillCellLeft.top
  444. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  445. Label {
  446. id: selectedInfillRateText
  447. //anchors.top: parent.top
  448. anchors.left: infillSlider.left
  449. anchors.leftMargin: Math.round((infillSlider.value / infillSlider.stepSize) * (infillSlider.width / (infillSlider.maximumValue / infillSlider.stepSize)) - 10 * screenScaleFactor)
  450. anchors.right: parent.right
  451. text: parseInt(infillDensity.properties.value) + "%"
  452. horizontalAlignment: Text.AlignLeft
  453. color: infillSlider.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  454. }
  455. // We use a binding to make sure that after manually setting infillSlider.value it is still bound to the property provider
  456. Binding {
  457. target: infillSlider
  458. property: "value"
  459. value: parseInt(infillDensity.properties.value)
  460. }
  461. Slider
  462. {
  463. id: infillSlider
  464. anchors.top: selectedInfillRateText.bottom
  465. anchors.left: parent.left
  466. anchors.right: infillIcon.left
  467. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  468. height: UM.Theme.getSize("sidebar_margin").height
  469. width: parseInt(infillCellRight.width - UM.Theme.getSize("sidebar_margin").width - style.handleWidth)
  470. minimumValue: 0
  471. maximumValue: 100
  472. stepSize: 1
  473. tickmarksEnabled: true
  474. // disable slider when gradual support is enabled
  475. enabled: parseInt(infillSteps.properties.value) == 0
  476. // set initial value from stack
  477. value: parseInt(infillDensity.properties.value)
  478. onValueChanged: {
  479. // Don't round the value if it's already the same
  480. if (parseInt(infillDensity.properties.value) == infillSlider.value) {
  481. return
  482. }
  483. // Round the slider value to the nearest multiple of 10 (simulate step size of 10)
  484. var roundedSliderValue = Math.round(infillSlider.value / 10) * 10
  485. // Update the slider value to represent the rounded value
  486. infillSlider.value = roundedSliderValue
  487. // Update value only if the Recomended mode is Active,
  488. // Otherwise if I change the value in the Custom mode the Recomended view will try to repeat
  489. // same operation
  490. var active_mode = UM.Preferences.getValue("cura/active_mode")
  491. if (active_mode == 0 || active_mode == "simple") {
  492. Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", roundedSliderValue)
  493. }
  494. }
  495. style: SliderStyle
  496. {
  497. groove: Rectangle {
  498. id: groove
  499. implicitWidth: 200 * screenScaleFactor
  500. implicitHeight: 2 * screenScaleFactor
  501. color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  502. radius: 1
  503. }
  504. handle: Item {
  505. Rectangle {
  506. id: handleButton
  507. anchors.centerIn: parent
  508. color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  509. implicitWidth: 10 * screenScaleFactor
  510. implicitHeight: 10 * screenScaleFactor
  511. radius: 10 * screenScaleFactor
  512. }
  513. }
  514. tickmarks: Repeater {
  515. id: repeater
  516. model: control.maximumValue / control.stepSize + 1
  517. // check if a tick should be shown based on it's index and wether the infill density is a multiple of 10 (slider step size)
  518. function shouldShowTick (index) {
  519. if (index % 10 == 0) {
  520. return true
  521. }
  522. return false
  523. }
  524. Rectangle {
  525. anchors.verticalCenter: parent.verticalCenter
  526. color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
  527. width: 1 * screenScaleFactor
  528. height: 6 * screenScaleFactor
  529. y: 0
  530. x: Math.round(styleData.handleWidth / 2 + index * ((repeater.width - styleData.handleWidth) / (repeater.count-1)))
  531. visible: shouldShowTick(index)
  532. }
  533. }
  534. }
  535. }
  536. Rectangle
  537. {
  538. id: infillIcon
  539. width: Math.round((parent.width / 5) - (UM.Theme.getSize("sidebar_margin").width))
  540. height: width
  541. anchors.right: parent.right
  542. anchors.top: parent.top
  543. anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2)
  544. // we loop over all density icons and only show the one that has the current density and steps
  545. Repeater
  546. {
  547. id: infillIconList
  548. model: infillModel
  549. anchors.fill: parent
  550. function activeIndex () {
  551. for (var i = 0; i < infillModel.count; i++) {
  552. var density = Math.round(infillDensity.properties.value)
  553. var steps = Math.round(infillSteps.properties.value)
  554. var infillModelItem = infillModel.get(i)
  555. if (infillModelItem != "undefined"
  556. && density >= infillModelItem.percentageMin
  557. && density <= infillModelItem.percentageMax
  558. && steps >= infillModelItem.stepsMin
  559. && steps <= infillModelItem.stepsMax
  560. ){
  561. return i
  562. }
  563. }
  564. return -1
  565. }
  566. Rectangle
  567. {
  568. anchors.fill: parent
  569. visible: infillIconList.activeIndex() == index
  570. border.width: UM.Theme.getSize("default_lining").width
  571. border.color: UM.Theme.getColor("quality_slider_unavailable")
  572. UM.RecolorImage {
  573. anchors.fill: parent
  574. anchors.margins: 2 * screenScaleFactor
  575. sourceSize.width: width
  576. sourceSize.height: width
  577. source: UM.Theme.getIcon(model.icon)
  578. color: UM.Theme.getColor("quality_slider_unavailable")
  579. }
  580. }
  581. }
  582. }
  583. // Gradual Support Infill Checkbox
  584. CheckBox {
  585. id: enableGradualInfillCheckBox
  586. property alias _hovered: enableGradualInfillMouseArea.containsMouse
  587. anchors.top: infillSlider.bottom
  588. anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height / 2) // closer to slider since it belongs to the same category
  589. anchors.left: infillCellRight.left
  590. style: UM.Theme.styles.checkbox
  591. enabled: base.settingsEnabled
  592. visible: infillSteps.properties.enabled == "True"
  593. checked: parseInt(infillSteps.properties.value) > 0
  594. MouseArea {
  595. id: enableGradualInfillMouseArea
  596. anchors.fill: parent
  597. hoverEnabled: true
  598. enabled: true
  599. property var previousInfillDensity: parseInt(infillDensity.properties.value)
  600. onClicked: {
  601. // Set to 90% only when enabling gradual infill
  602. var newInfillDensity;
  603. if (parseInt(infillSteps.properties.value) == 0) {
  604. previousInfillDensity = parseInt(infillDensity.properties.value)
  605. newInfillDensity = 90;
  606. } else {
  607. newInfillDensity = previousInfillDensity;
  608. }
  609. Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity))
  610. var infill_steps_value = 0;
  611. if (parseInt(infillSteps.properties.value) == 0)
  612. infill_steps_value = 5;
  613. Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value)
  614. }
  615. onEntered: {
  616. base.showTooltip(enableGradualInfillCheckBox, Qt.point(-infillCellRight.x, 0),
  617. catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top."))
  618. }
  619. onExited: {
  620. base.hideTooltip()
  621. }
  622. }
  623. Label {
  624. id: gradualInfillLabel
  625. anchors.left: enableGradualInfillCheckBox.right
  626. anchors.leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2)
  627. text: catalog.i18nc("@label", "Enable gradual")
  628. font: UM.Theme.getFont("default")
  629. color: UM.Theme.getColor("text")
  630. }
  631. }
  632. // Infill list model for mapping icon
  633. ListModel
  634. {
  635. id: infillModel
  636. Component.onCompleted:
  637. {
  638. infillModel.append({
  639. percentageMin: -1,
  640. percentageMax: 0,
  641. stepsMin: -1,
  642. stepsMax: 0,
  643. icon: "hollow"
  644. })
  645. infillModel.append({
  646. percentageMin: 0,
  647. percentageMax: 40,
  648. stepsMin: -1,
  649. stepsMax: 0,
  650. icon: "sparse"
  651. })
  652. infillModel.append({
  653. percentageMin: 40,
  654. percentageMax: 89,
  655. stepsMin: -1,
  656. stepsMax: 0,
  657. icon: "dense"
  658. })
  659. infillModel.append({
  660. percentageMin: 90,
  661. percentageMax: 9999999999,
  662. stepsMin: -1,
  663. stepsMax: 0,
  664. icon: "solid"
  665. })
  666. infillModel.append({
  667. percentageMin: 0,
  668. percentageMax: 9999999999,
  669. stepsMin: 1,
  670. stepsMax: 9999999999,
  671. icon: "gradual"
  672. })
  673. }
  674. }
  675. }
  676. //
  677. // Enable support
  678. //
  679. Label
  680. {
  681. id: enableSupportLabel
  682. visible: enableSupportCheckBox.visible
  683. anchors.top: infillCellRight.bottom
  684. anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 1.5)
  685. anchors.left: parent.left
  686. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  687. anchors.right: infillCellLeft.right
  688. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  689. anchors.verticalCenter: enableSupportCheckBox.verticalCenter
  690. text: catalog.i18nc("@label", "Generate Support");
  691. font: UM.Theme.getFont("default");
  692. color: UM.Theme.getColor("text");
  693. elide: Text.ElideRight
  694. }
  695. CheckBox
  696. {
  697. id: enableSupportCheckBox
  698. property alias _hovered: enableSupportMouseArea.containsMouse
  699. anchors.top: enableSupportLabel.top
  700. anchors.left: infillCellRight.left
  701. style: UM.Theme.styles.checkbox;
  702. enabled: base.settingsEnabled
  703. visible: supportEnabled.properties.enabled == "True"
  704. checked: supportEnabled.properties.value == "True";
  705. MouseArea
  706. {
  707. id: enableSupportMouseArea
  708. anchors.fill: parent
  709. hoverEnabled: true
  710. enabled: true
  711. onClicked:
  712. {
  713. // The value is a string "True" or "False"
  714. supportEnabled.setPropertyValue("value", supportEnabled.properties.value != "True");
  715. }
  716. onEntered:
  717. {
  718. base.showTooltip(enableSupportCheckBox, Qt.point(-enableSupportCheckBox.x, 0),
  719. catalog.i18nc("@label", "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing."));
  720. }
  721. onExited:
  722. {
  723. base.hideTooltip();
  724. }
  725. }
  726. }
  727. ComboBox
  728. {
  729. id: supportExtruderCombobox
  730. visible: enableSupportCheckBox.visible && (supportEnabled.properties.value == "True") && (extrudersEnabledCount.properties.value > 1)
  731. model: extruderModel
  732. property string color_override: "" // for manually setting values
  733. property string color: // is evaluated automatically, but the first time is before extruderModel being filled
  734. {
  735. var current_extruder = extruderModel.get(currentIndex);
  736. color_override = "";
  737. if (current_extruder === undefined) return ""
  738. return (current_extruder.color) ? current_extruder.color : "";
  739. }
  740. textRole: "text" // this solves that the combobox isn't populated in the first time Cura is started
  741. anchors.top: enableSupportCheckBox.top
  742. //anchors.topMargin: ((supportEnabled.properties.value === "True") && (machineExtruderCount.properties.value > 1)) ? UM.Theme.getSize("sidebar_margin").height : 0
  743. anchors.left: enableSupportCheckBox.right
  744. anchors.leftMargin: Math.round(UM.Theme.getSize("sidebar_margin").width / 2)
  745. width: Math.round(UM.Theme.getSize("sidebar").width * .55) - Math.round(UM.Theme.getSize("sidebar_margin").width / 2) - enableSupportCheckBox.width
  746. height: ((supportEnabled.properties.value == "True") && (machineExtruderCount.properties.value > 1)) ? UM.Theme.getSize("setting_control").height : 0
  747. Behavior on height { NumberAnimation { duration: 100 } }
  748. style: UM.Theme.styles.combobox_color
  749. enabled: base.settingsEnabled
  750. property alias _hovered: supportExtruderMouseArea.containsMouse
  751. currentIndex:
  752. {
  753. if (supportExtruderNr.properties == null)
  754. {
  755. return Cura.MachineManager.defaultExtruderPosition;
  756. }
  757. else
  758. {
  759. var extruder = parseInt(supportExtruderNr.properties.value);
  760. if ( extruder === -1)
  761. {
  762. return Cura.MachineManager.defaultExtruderPosition;
  763. }
  764. return extruder;
  765. }
  766. }
  767. onActivated:
  768. {
  769. // Send the extruder nr as a string.
  770. supportExtruderNr.setPropertyValue("value", String(index));
  771. }
  772. MouseArea
  773. {
  774. id: supportExtruderMouseArea
  775. anchors.fill: parent
  776. hoverEnabled: true
  777. enabled: base.settingsEnabled
  778. acceptedButtons: Qt.NoButton
  779. onEntered:
  780. {
  781. base.showTooltip(supportExtruderCombobox, Qt.point(-supportExtruderCombobox.x, 0),
  782. catalog.i18nc("@label", "Select which extruder to use for support. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air."));
  783. }
  784. onExited:
  785. {
  786. base.hideTooltip();
  787. }
  788. }
  789. function updateCurrentColor()
  790. {
  791. var current_extruder = extruderModel.get(currentIndex);
  792. if (current_extruder !== undefined) {
  793. supportExtruderCombobox.color_override = current_extruder.color;
  794. }
  795. }
  796. }
  797. Label
  798. {
  799. id: adhesionHelperLabel
  800. visible: adhesionCheckBox.visible
  801. text: catalog.i18nc("@label", "Build Plate Adhesion")
  802. font: UM.Theme.getFont("default")
  803. color: UM.Theme.getColor("text")
  804. elide: Text.ElideRight
  805. anchors {
  806. left: parent.left
  807. leftMargin: UM.Theme.getSize("sidebar_margin").width
  808. right: infillCellLeft.right
  809. rightMargin: UM.Theme.getSize("sidebar_margin").width
  810. verticalCenter: adhesionCheckBox.verticalCenter
  811. }
  812. }
  813. CheckBox
  814. {
  815. id: adhesionCheckBox
  816. property alias _hovered: adhesionMouseArea.containsMouse
  817. anchors.top: enableSupportCheckBox.bottom
  818. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  819. anchors.left: infillCellRight.left
  820. //: Setting enable printing build-plate adhesion helper checkbox
  821. style: UM.Theme.styles.checkbox;
  822. enabled: base.settingsEnabled
  823. visible: platformAdhesionType.properties.enabled == "True"
  824. checked: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none"
  825. MouseArea
  826. {
  827. id: adhesionMouseArea
  828. anchors.fill: parent
  829. hoverEnabled: true
  830. enabled: base.settingsEnabled
  831. onClicked:
  832. {
  833. var adhesionType = "skirt";
  834. if(!parent.checked)
  835. {
  836. // Remove the "user" setting to see if the rest of the stack prescribes a brim or a raft
  837. platformAdhesionType.removeFromContainer(0);
  838. adhesionType = platformAdhesionType.properties.value;
  839. if(adhesionType == "skirt" || adhesionType == "none")
  840. {
  841. // If the rest of the stack doesn't prescribe an adhesion-type, default to a brim
  842. adhesionType = "brim";
  843. }
  844. }
  845. platformAdhesionType.setPropertyValue("value", adhesionType);
  846. }
  847. onEntered:
  848. {
  849. base.showTooltip(adhesionCheckBox, Qt.point(-adhesionCheckBox.x, 0),
  850. catalog.i18nc("@label", "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards."));
  851. }
  852. onExited:
  853. {
  854. base.hideTooltip();
  855. }
  856. }
  857. }
  858. ListModel
  859. {
  860. id: extruderModel
  861. Component.onCompleted: populateExtruderModel()
  862. }
  863. //: Model used to populate the extrudelModel
  864. Cura.ExtrudersModel
  865. {
  866. id: extruders
  867. onModelChanged: populateExtruderModel()
  868. }
  869. Item
  870. {
  871. id: tipsCell
  872. anchors.top: adhesionCheckBox.visible ? adhesionCheckBox.bottom : (enableSupportCheckBox.visible ? supportExtruderCombobox.bottom : infillCellRight.bottom)
  873. anchors.topMargin: Math.round(UM.Theme.getSize("sidebar_margin").height * 2)
  874. anchors.left: parent.left
  875. width: parent.width
  876. height: tipsText.contentHeight * tipsText.lineCount
  877. Label
  878. {
  879. id: tipsText
  880. anchors.left: parent.left
  881. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  882. anchors.right: parent.right
  883. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  884. anchors.top: parent.top
  885. wrapMode: Text.WordWrap
  886. text: catalog.i18nc("@label", "Need help improving your prints?<br>Read the <a href='%1'>Ultimaker Troubleshooting Guides</a>").arg("https://ultimaker.com/en/troubleshooting")
  887. font: UM.Theme.getFont("default");
  888. color: UM.Theme.getColor("text");
  889. linkColor: UM.Theme.getColor("text_link")
  890. onLinkActivated: Qt.openUrlExternally(link)
  891. }
  892. }
  893. UM.SettingPropertyProvider
  894. {
  895. id: infillExtruderNumber
  896. containerStackId: Cura.MachineManager.activeStackId
  897. key: "infill_extruder_nr"
  898. watchedProperties: [ "value" ]
  899. storeIndex: 0
  900. }
  901. UM.SettingPropertyProvider
  902. {
  903. id: infillDensity
  904. containerStackId: Cura.MachineManager.activeStackId
  905. key: "infill_sparse_density"
  906. watchedProperties: [ "value" ]
  907. storeIndex: 0
  908. }
  909. UM.SettingPropertyProvider
  910. {
  911. id: infillSteps
  912. containerStackId: Cura.MachineManager.activeStackId
  913. key: "gradual_infill_steps"
  914. watchedProperties: ["value", "enabled"]
  915. storeIndex: 0
  916. }
  917. UM.SettingPropertyProvider
  918. {
  919. id: platformAdhesionType
  920. containerStackId: Cura.MachineManager.activeMachineId
  921. key: "adhesion_type"
  922. watchedProperties: [ "value", "enabled" ]
  923. storeIndex: 0
  924. }
  925. UM.SettingPropertyProvider
  926. {
  927. id: supportEnabled
  928. containerStackId: Cura.MachineManager.activeMachineId
  929. key: "support_enable"
  930. watchedProperties: [ "value", "enabled", "description" ]
  931. storeIndex: 0
  932. }
  933. UM.SettingPropertyProvider
  934. {
  935. id: extrudersEnabledCount
  936. containerStackId: Cura.MachineManager.activeMachineId
  937. key: "extruders_enabled_count"
  938. watchedProperties: [ "value" ]
  939. storeIndex: 0
  940. }
  941. UM.SettingPropertyProvider
  942. {
  943. id: supportExtruderNr
  944. containerStackId: Cura.MachineManager.activeMachineId
  945. key: "support_extruder_nr"
  946. watchedProperties: [ "value" ]
  947. storeIndex: 0
  948. }
  949. }
  950. }
  951. function populateExtruderModel()
  952. {
  953. extruderModel.clear();
  954. for(var extruderNumber = 0; extruderNumber < extruders.rowCount() ; extruderNumber++)
  955. {
  956. extruderModel.append({
  957. text: extruders.getItem(extruderNumber).name,
  958. color: extruders.getItem(extruderNumber).color
  959. })
  960. }
  961. supportExtruderCombobox.updateCurrentColor();
  962. }
  963. }