SidebarSimple.qml 22 KB

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