SidebarSimple.qml 43 KB

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