SidebarSimple.qml 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  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. anchors.fill: parent
  24. style: UM.Theme.styles.scrollview
  25. flickableItem.flickableDirection: Flickable.VerticalFlick
  26. Rectangle
  27. {
  28. width: childrenRect.width
  29. height: childrenRect.height
  30. Item
  31. {
  32. id: infillCellLeft
  33. anchors.top: parent.top
  34. anchors.left: parent.left
  35. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 0.8
  36. width: UM.Theme.getSize("sidebar").width * .45 - UM.Theme.getSize("sidebar_margin").width
  37. height: childrenRect.height
  38. Text
  39. {
  40. id: infillLabel
  41. //: Infill selection label
  42. text: catalog.i18nc("@label", "Infill");
  43. font: UM.Theme.getFont("default");
  44. color: UM.Theme.getColor("text");
  45. anchors.top: parent.top
  46. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  47. anchors.left: parent.left
  48. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  49. }
  50. }
  51. Row
  52. {
  53. id: infillCellRight
  54. height: childrenRect.height;
  55. width: UM.Theme.getSize("sidebar").width * .55
  56. spacing: UM.Theme.getSize("sidebar_margin").width
  57. anchors.left: infillCellLeft.right
  58. anchors.top: infillCellLeft.top
  59. Repeater
  60. {
  61. id: infillListView
  62. property int activeIndex:
  63. {
  64. for(var i = 0; i < infillModel.count; ++i)
  65. {
  66. var density = parseInt(infillDensity.properties.value);
  67. var steps = parseInt(infillSteps.properties.value);
  68. if(density > infillModel.get(i).percentageMin && density <= infillModel.get(i).percentageMax && steps > infillModel.get(i).stepsMin && steps <= infillModel.get(i).stepsMax)
  69. {
  70. return i;
  71. }
  72. }
  73. return -1;
  74. }
  75. model: infillModel;
  76. Item
  77. {
  78. width: childrenRect.width;
  79. height: childrenRect.height;
  80. Rectangle
  81. {
  82. id: infillIconLining
  83. width: (infillCellRight.width - ((infillModel.count - 1) * UM.Theme.getSize("sidebar_margin").width)) / (infillModel.count);
  84. height: width
  85. border.color:
  86. {
  87. if(!base.settingsEnabled)
  88. {
  89. return UM.Theme.getColor("setting_control_disabled_border")
  90. }
  91. else if(infillListView.activeIndex == index)
  92. {
  93. return UM.Theme.getColor("setting_control_selected")
  94. }
  95. else if(infillMouseArea.containsMouse)
  96. {
  97. return UM.Theme.getColor("setting_control_border_highlight")
  98. }
  99. return UM.Theme.getColor("setting_control_border")
  100. }
  101. border.width: UM.Theme.getSize("default_lining").width
  102. color:
  103. {
  104. if(infillListView.activeIndex == index)
  105. {
  106. if(!base.settingsEnabled)
  107. {
  108. return UM.Theme.getColor("setting_control_disabled_text")
  109. }
  110. return UM.Theme.getColor("setting_control_selected")
  111. }
  112. return "transparent"
  113. }
  114. UM.RecolorImage
  115. {
  116. id: infillIcon
  117. anchors.fill: parent;
  118. anchors.margins: 2
  119. sourceSize.width: width
  120. sourceSize.height: width
  121. source: UM.Theme.getIcon(model.icon);
  122. color: {
  123. if(infillListView.activeIndex == index)
  124. {
  125. return UM.Theme.getColor("text_emphasis")
  126. }
  127. if(!base.settingsEnabled)
  128. {
  129. return UM.Theme.getColor("setting_control_disabled_text")
  130. }
  131. return UM.Theme.getColor("setting_control_disabled_text")
  132. }
  133. }
  134. MouseArea
  135. {
  136. id: infillMouseArea
  137. anchors.fill: parent
  138. hoverEnabled: true
  139. enabled: base.settingsEnabled
  140. onClicked: {
  141. if (infillListView.activeIndex != index)
  142. {
  143. infillDensity.setPropertyValue("value", model.percentage)
  144. infillSteps.setPropertyValue("value", model.steps)
  145. }
  146. }
  147. onEntered:
  148. {
  149. base.showTooltip(infillCellRight, Qt.point(-infillCellRight.x, 0), model.text);
  150. }
  151. onExited:
  152. {
  153. base.hideTooltip();
  154. }
  155. }
  156. }
  157. Text
  158. {
  159. id: infillLabel
  160. width: (infillCellRight.width - ((infillModel.count - 1) * UM.Theme.getSize("sidebar_margin").width)) / (infillModel.count);
  161. horizontalAlignment: Text.AlignHCenter
  162. verticalAlignment: Text.AlignVCenter
  163. wrapMode: Text.WordWrap
  164. font: UM.Theme.getFont("default")
  165. anchors.top: infillIconLining.bottom
  166. anchors.horizontalCenter: infillIconLining.horizontalCenter
  167. color: infillListView.activeIndex == index ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_border")
  168. text: name
  169. }
  170. }
  171. }
  172. ListModel
  173. {
  174. id: infillModel
  175. Component.onCompleted:
  176. {
  177. infillModel.append({
  178. name: catalog.i18nc("@label", "0%"),
  179. percentage: 0,
  180. steps: 0,
  181. percentageMin: -1,
  182. percentageMax: 0,
  183. stepsMin: -1,
  184. stepsMax: 0,
  185. text: catalog.i18nc("@label", "Empty infill will leave your model hollow with low strength."),
  186. icon: "hollow"
  187. })
  188. infillModel.append({
  189. name: catalog.i18nc("@label", "20%"),
  190. percentage: 20,
  191. steps: 0,
  192. percentageMin: 0,
  193. percentageMax: 30,
  194. stepsMin: -1,
  195. stepsMax: 0,
  196. text: catalog.i18nc("@label", "Light (20%) infill will give your model an average strength."),
  197. icon: "sparse"
  198. })
  199. infillModel.append({
  200. name: catalog.i18nc("@label", "50%"),
  201. percentage: 50,
  202. steps: 0,
  203. percentageMin: 30,
  204. percentageMax: 70,
  205. stepsMin: -1,
  206. stepsMax: 0,
  207. text: catalog.i18nc("@label", "Dense (50%) infill will give your model an above average strength."),
  208. icon: "dense"
  209. })
  210. infillModel.append({
  211. name: catalog.i18nc("@label", "100%"),
  212. percentage: 100,
  213. steps: 0,
  214. percentageMin: 70,
  215. percentageMax: 9999999999,
  216. stepsMin: -1,
  217. stepsMax: 0,
  218. text: catalog.i18nc("@label", "Solid (100%) infill will make your model completely solid."),
  219. icon: "solid"
  220. })
  221. infillModel.append({
  222. name: catalog.i18nc("@label", "Gradual"),
  223. percentage: 90,
  224. steps: 5,
  225. percentageMin: 0,
  226. percentageMax: 9999999999,
  227. stepsMin: 0,
  228. stepsMax: 9999999999,
  229. infill_layer_height: 1.5,
  230. text: catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top."),
  231. icon: "gradual"
  232. })
  233. }
  234. }
  235. }
  236. Text
  237. {
  238. id: enableSupportLabel
  239. anchors.left: parent.left
  240. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  241. anchors.verticalCenter: enableSupportCheckBox.verticalCenter
  242. text: catalog.i18nc("@label", "Generate Support");
  243. font: UM.Theme.getFont("default");
  244. color: UM.Theme.getColor("text");
  245. }
  246. CheckBox
  247. {
  248. id: enableSupportCheckBox
  249. property alias _hovered: enableSupportMouseArea.containsMouse
  250. anchors.top: infillCellRight.bottom
  251. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  252. anchors.left: infillCellRight.left
  253. style: UM.Theme.styles.checkbox;
  254. enabled: base.settingsEnabled
  255. checked: supportEnabled.properties.value == "True";
  256. MouseArea
  257. {
  258. id: enableSupportMouseArea
  259. anchors.fill: parent
  260. hoverEnabled: true
  261. enabled: true
  262. onClicked:
  263. {
  264. // The value is a string "True" or "False"
  265. supportEnabled.setPropertyValue("value", supportEnabled.properties.value != "True");
  266. }
  267. onEntered:
  268. {
  269. base.showTooltip(enableSupportCheckBox, Qt.point(-enableSupportCheckBox.x, 0),
  270. catalog.i18nc("@label", "Generate structures to support parts of the model which have overhangs. Without these structures, such parts would collapse during printing."));
  271. }
  272. onExited:
  273. {
  274. base.hideTooltip();
  275. }
  276. }
  277. }
  278. Text
  279. {
  280. id: supportExtruderLabel
  281. visible: (supportEnabled.properties.value == "True") && (machineExtruderCount.properties.value > 1)
  282. anchors.left: parent.left
  283. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  284. anchors.verticalCenter: supportExtruderCombobox.verticalCenter
  285. text: catalog.i18nc("@label", "Support Extruder");
  286. font: UM.Theme.getFont("default");
  287. color: UM.Theme.getColor("text");
  288. }
  289. ComboBox
  290. {
  291. id: supportExtruderCombobox
  292. visible: (supportEnabled.properties.value == "True") && (machineExtruderCount.properties.value > 1)
  293. model: extruderModel
  294. property string color_override: "" // for manually setting values
  295. property string color: // is evaluated automatically, but the first time is before extruderModel being filled
  296. {
  297. var current_extruder = extruderModel.get(currentIndex);
  298. color_override = "";
  299. if (current_extruder === undefined) {
  300. return "";
  301. }
  302. var model_color = current_extruder.color;
  303. return (model_color) ? model_color : "";
  304. }
  305. textRole: 'text' // this solves that the combobox isn't populated in the first time Cura is started
  306. anchors.top: enableSupportCheckBox.bottom
  307. anchors.topMargin:
  308. {
  309. if ((supportEnabled.properties.value == "True") && (machineExtruderCount.properties.value > 1))
  310. {
  311. return UM.Theme.getSize("sidebar_margin").height;
  312. }
  313. else
  314. {
  315. return 0;
  316. }
  317. }
  318. anchors.left: infillCellRight.left
  319. width: UM.Theme.getSize("sidebar").width * .55
  320. height:
  321. {
  322. if ((supportEnabled.properties.value == "True") && (machineExtruderCount.properties.value > 1))
  323. {
  324. // default height when control is enabled
  325. return UM.Theme.getSize("setting_control").height;
  326. }
  327. else
  328. {
  329. return 0;
  330. }
  331. }
  332. Behavior on height { NumberAnimation { duration: 100 } }
  333. style: UM.Theme.styles.combobox_color
  334. enabled: base.settingsEnabled
  335. property alias _hovered: supportExtruderMouseArea.containsMouse
  336. currentIndex: supportExtruderNr.properties !== null ? parseFloat(supportExtruderNr.properties.value) : 0
  337. onActivated:
  338. {
  339. // Send the extruder nr as a string.
  340. supportExtruderNr.setPropertyValue("value", String(index));
  341. }
  342. MouseArea
  343. {
  344. id: supportExtruderMouseArea
  345. anchors.fill: parent
  346. hoverEnabled: true
  347. enabled: base.settingsEnabled
  348. acceptedButtons: Qt.NoButton
  349. onEntered:
  350. {
  351. base.showTooltip(supportExtruderCombobox, Qt.point(-supportExtruderCombobox.x, 0),
  352. 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."));
  353. }
  354. onExited:
  355. {
  356. base.hideTooltip();
  357. }
  358. }
  359. function updateCurrentColor()
  360. {
  361. var current_extruder = extruderModel.get(currentIndex);
  362. if (current_extruder !== undefined) {
  363. supportExtruderCombobox.color_override = current_extruder.color;
  364. }
  365. }
  366. }
  367. Text
  368. {
  369. id: adhesionHelperLabel
  370. anchors.left: parent.left
  371. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  372. anchors.verticalCenter: adhesionCheckBox.verticalCenter
  373. text: catalog.i18nc("@label", "Build Plate Adhesion");
  374. font: UM.Theme.getFont("default");
  375. color: UM.Theme.getColor("text");
  376. elide: Text.ElideRight
  377. }
  378. CheckBox
  379. {
  380. id: adhesionCheckBox
  381. property alias _hovered: adhesionMouseArea.containsMouse
  382. anchors.top: supportExtruderCombobox.bottom
  383. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  384. anchors.left: infillCellRight.left
  385. //: Setting enable printing build-plate adhesion helper checkbox
  386. style: UM.Theme.styles.checkbox;
  387. enabled: base.settingsEnabled
  388. checked: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none"
  389. MouseArea
  390. {
  391. id: adhesionMouseArea
  392. anchors.fill: parent
  393. hoverEnabled: true
  394. enabled: base.settingsEnabled
  395. onClicked:
  396. {
  397. var adhesionType = "skirt";
  398. if(!parent.checked)
  399. {
  400. // Remove the "user" setting to see if the rest of the stack prescribes a brim or a raft
  401. platformAdhesionType.removeFromContainer(0);
  402. adhesionType = platformAdhesionType.properties.value;
  403. if(adhesionType == "skirt")
  404. {
  405. // If the rest of the stack doesn't prescribe an adhesion-type, default to a brim
  406. adhesionType = "brim";
  407. }
  408. }
  409. platformAdhesionType.setPropertyValue("value", adhesionType);
  410. }
  411. onEntered:
  412. {
  413. base.showTooltip(adhesionCheckBox, Qt.point(-adhesionCheckBox.x, 0),
  414. 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."));
  415. }
  416. onExited:
  417. {
  418. base.hideTooltip();
  419. }
  420. }
  421. }
  422. ListModel
  423. {
  424. id: extruderModel
  425. Component.onCompleted: populateExtruderModel()
  426. }
  427. //: Model used to populate the extrudelModel
  428. Cura.ExtrudersModel
  429. {
  430. id: extruders
  431. onModelChanged: populateExtruderModel()
  432. }
  433. Item
  434. {
  435. id: tipsCell
  436. anchors.top: adhesionCheckBox.bottom
  437. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 2
  438. anchors.left: parent.left
  439. width: parent.width
  440. height: tipsText.contentHeight * tipsText.lineCount
  441. Text
  442. {
  443. id: tipsText
  444. anchors.left: parent.left
  445. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  446. anchors.right: parent.right
  447. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  448. anchors.top: parent.top
  449. wrapMode: Text.WordWrap
  450. //: Tips label
  451. 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") + "<img src='%1'></img>".arg(UM.Theme.getIcon("play"))
  452. font: UM.Theme.getFont("default");
  453. color: UM.Theme.getColor("text");
  454. linkColor: UM.Theme.getColor("text_link")
  455. onLinkActivated: Qt.openUrlExternally(link)
  456. }
  457. }
  458. UM.SettingPropertyProvider
  459. {
  460. id: infillExtruderNumber
  461. containerStackId: Cura.MachineManager.activeStackId
  462. key: "infill_extruder_nr"
  463. watchedProperties: [ "value" ]
  464. storeIndex: 0
  465. }
  466. Binding
  467. {
  468. target: infillDensity
  469. property: "containerStackId"
  470. value:
  471. {
  472. var activeMachineId = Cura.MachineManager.activeMachineId;
  473. if (machineExtruderCount.properties.value > 1)
  474. {
  475. var infillExtruderNr = parseInt(infillExtruderNumber.properties.value);
  476. if (infillExtruderNr >= 0)
  477. {
  478. activeMachineId = ExtruderManager.extruderIds[infillExtruderNumber.properties.value];
  479. }
  480. else if (ExtruderManager.activeExtruderStackId)
  481. {
  482. activeMachineId = ExtruderManager.activeExtruderStackId;
  483. }
  484. }
  485. infillSteps.containerStackId = activeMachineId;
  486. return activeMachineId;
  487. }
  488. }
  489. UM.SettingPropertyProvider
  490. {
  491. id: infillDensity
  492. containerStackId: Cura.MachineManager.activeStackId
  493. key: "infill_sparse_density"
  494. watchedProperties: [ "value" ]
  495. storeIndex: 0
  496. }
  497. UM.SettingPropertyProvider
  498. {
  499. id: infillSteps
  500. containerStackId: Cura.MachineManager.activeStackId
  501. key: "gradual_infill_steps"
  502. watchedProperties: [ "value" ]
  503. storeIndex: 0
  504. }
  505. UM.SettingPropertyProvider
  506. {
  507. id: platformAdhesionType
  508. containerStackId: Cura.MachineManager.activeMachineId
  509. key: "adhesion_type"
  510. watchedProperties: [ "value" ]
  511. storeIndex: 0
  512. }
  513. UM.SettingPropertyProvider
  514. {
  515. id: supportEnabled
  516. containerStackId: Cura.MachineManager.activeMachineId
  517. key: "support_enable"
  518. watchedProperties: [ "value", "description" ]
  519. storeIndex: 0
  520. }
  521. UM.SettingPropertyProvider
  522. {
  523. id: machineExtruderCount
  524. containerStackId: Cura.MachineManager.activeMachineId
  525. key: "machine_extruder_count"
  526. watchedProperties: [ "value" ]
  527. storeIndex: 0
  528. }
  529. UM.SettingPropertyProvider
  530. {
  531. id: supportExtruderNr
  532. containerStackId: Cura.MachineManager.activeMachineId
  533. key: "support_extruder_nr"
  534. watchedProperties: [ "value" ]
  535. storeIndex: 0
  536. }
  537. }
  538. }
  539. function populateExtruderModel()
  540. {
  541. extruderModel.clear();
  542. for(var extruderNumber = 0; extruderNumber < extruders.rowCount() ; extruderNumber++)
  543. {
  544. extruderModel.append({
  545. text: extruders.getItem(extruderNumber).name,
  546. color: extruders.getItem(extruderNumber).color
  547. })
  548. }
  549. supportExtruderCombobox.updateCurrentColor();
  550. }
  551. }