SidebarSimple.qml 39 KB

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