SidebarSimple.qml 46 KB

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