Sidebar.qml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  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. import "Menus"
  10. Rectangle
  11. {
  12. id: base;
  13. property int currentModeIndex;
  14. property bool hideSettings: PrintInformation.preSliced
  15. // Is there an output device for this printer?
  16. property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
  17. property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
  18. property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
  19. property int backendState: UM.Backend.state
  20. property bool monitoringPrint: false
  21. property variant printDuration: PrintInformation.currentPrintTime
  22. property variant printDurationPerFeature: PrintInformation.printTimesPerFeature
  23. property variant printMaterialLengths: PrintInformation.materialLengths
  24. property variant printMaterialWeights: PrintInformation.materialWeights
  25. property variant printMaterialCosts: PrintInformation.materialCosts
  26. color: UM.Theme.getColor("sidebar")
  27. UM.I18nCatalog { id: catalog; name:"cura"}
  28. Timer {
  29. id: tooltipDelayTimer
  30. interval: 500
  31. repeat: false
  32. property var item
  33. property string text
  34. onTriggered:
  35. {
  36. base.showTooltip(base, {x: 0, y: item.y}, text);
  37. }
  38. }
  39. function showTooltip(item, position, text)
  40. {
  41. tooltip.text = text;
  42. position = item.mapToItem(base, position.x - UM.Theme.getSize("default_arrow").width, position.y);
  43. tooltip.show(position);
  44. }
  45. function hideTooltip()
  46. {
  47. tooltip.hide();
  48. }
  49. function strPadLeft(string, pad, length) {
  50. return (new Array(length + 1).join(pad) + string).slice(-length);
  51. }
  52. function getPrettyTime(time)
  53. {
  54. var hours = Math.floor(time / 3600)
  55. time -= hours * 3600
  56. var minutes = Math.floor(time / 60);
  57. time -= minutes * 60
  58. var seconds = Math.floor(time);
  59. var finalTime = strPadLeft(hours, "0", 2) + ':' + strPadLeft(minutes,'0',2)+ ':' + strPadLeft(seconds,'0',2);
  60. return finalTime;
  61. }
  62. MouseArea
  63. {
  64. anchors.fill: parent
  65. acceptedButtons: Qt.AllButtons;
  66. onWheel:
  67. {
  68. wheel.accepted = true;
  69. }
  70. }
  71. SidebarHeader {
  72. id: header
  73. width: parent.width
  74. visible: machineExtruderCount.properties.value > 1 || Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariants
  75. onShowTooltip: base.showTooltip(item, location, text)
  76. onHideTooltip: base.hideTooltip()
  77. }
  78. Rectangle {
  79. id: headerSeparator
  80. width: parent.width
  81. visible: settingsModeSelection.visible && header.visible
  82. height: visible ? UM.Theme.getSize("sidebar_lining").height : 0
  83. color: UM.Theme.getColor("sidebar_lining")
  84. anchors.top: header.bottom
  85. anchors.topMargin: visible ? UM.Theme.getSize("sidebar_margin").height : 0
  86. }
  87. onCurrentModeIndexChanged:
  88. {
  89. UM.Preferences.setValue("cura/active_mode", currentModeIndex);
  90. if(modesListModel.count > base.currentModeIndex)
  91. {
  92. sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "replace": true });
  93. }
  94. }
  95. Text {
  96. id: settingsModeLabel
  97. text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox","Print Setup disabled\nG-code files cannot be modified");
  98. anchors.left: parent.left
  99. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  100. anchors.top: headerSeparator.bottom
  101. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  102. width: parent.width * 0.45
  103. font: UM.Theme.getFont("large")
  104. color: UM.Theme.getColor("text")
  105. visible: !monitoringPrint
  106. elide: Text.ElideRight
  107. }
  108. Rectangle {
  109. id: settingsModeSelection
  110. color: "transparent"
  111. width: parent.width * 0.55
  112. height: UM.Theme.getSize("sidebar_header_mode_toggle").height
  113. anchors.right: parent.right
  114. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  115. anchors.top: headerSeparator.bottom
  116. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  117. visible: !monitoringPrint && !hideSettings
  118. Component{
  119. id: wizardDelegate
  120. Button {
  121. height: settingsModeSelection.height
  122. anchors.left: parent.left
  123. anchors.leftMargin: model.index * (settingsModeSelection.width / 2)
  124. anchors.verticalCenter: parent.verticalCenter
  125. width: 0.5 * parent.width
  126. text: model.text
  127. exclusiveGroup: modeMenuGroup;
  128. checkable: true;
  129. checked: base.currentModeIndex == index
  130. onClicked: base.currentModeIndex = index
  131. onHoveredChanged: {
  132. if (hovered)
  133. {
  134. tooltipDelayTimer.item = settingsModeSelection
  135. tooltipDelayTimer.text = model.tooltipText
  136. tooltipDelayTimer.start();
  137. }
  138. else
  139. {
  140. tooltipDelayTimer.stop();
  141. base.hideTooltip();
  142. }
  143. }
  144. style: ButtonStyle {
  145. background: Rectangle {
  146. border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width
  147. border.color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active_border") :
  148. control.hovered ? UM.Theme.getColor("action_button_hovered_border") :
  149. UM.Theme.getColor("action_button_border")
  150. color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active") :
  151. control.hovered ? UM.Theme.getColor("action_button_hovered") :
  152. UM.Theme.getColor("action_button")
  153. Behavior on color { ColorAnimation { duration: 50; } }
  154. Label {
  155. anchors.centerIn: parent
  156. color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active_text") :
  157. control.hovered ? UM.Theme.getColor("action_button_hovered_text") :
  158. UM.Theme.getColor("action_button_text")
  159. font: (control.checked || control.pressed) ? UM.Theme.getFont("default_little_big") : UM.Theme.getFont("default")
  160. text: control.text;
  161. }
  162. }
  163. label: Item { }
  164. }
  165. }
  166. }
  167. ExclusiveGroup { id: modeMenuGroup; }
  168. ListView
  169. {
  170. id: modesList
  171. property var index: 0
  172. model: modesListModel
  173. delegate: wizardDelegate
  174. anchors.top: parent.top
  175. anchors.left: parent.left
  176. width: parent.width
  177. }
  178. }
  179. Item
  180. {
  181. id: globalProfileRow
  182. height: UM.Theme.getSize("sidebar_setup").height
  183. visible: !sidebar.monitoringPrint && !sidebar.hideSettings
  184. anchors
  185. {
  186. top: settingsModeSelection.bottom
  187. topMargin: UM.Theme.getSize("sidebar_margin").height
  188. left: parent.left
  189. leftMargin: UM.Theme.getSize("sidebar_margin").width
  190. right: parent.right
  191. rightMargin: UM.Theme.getSize("sidebar_margin").width
  192. }
  193. Text
  194. {
  195. id: globalProfileLabel
  196. text: catalog.i18nc("@label","Profile:");
  197. width: parent.width * 0.45 - UM.Theme.getSize("sidebar_margin").width - 2
  198. font: UM.Theme.getFont("default");
  199. color: UM.Theme.getColor("text");
  200. verticalAlignment: Text.AlignVCenter
  201. anchors.top: parent.top
  202. anchors.bottom: parent.bottom
  203. }
  204. ToolButton
  205. {
  206. id: globalProfileSelection
  207. text: {
  208. var result = Cura.MachineManager.activeQualityName;
  209. if (Cura.MachineManager.activeQualityLayerHeight > 0) {
  210. result += " <font color=\"" + UM.Theme.getColor("text_detail") + "\">";
  211. result += " - ";
  212. result += Cura.MachineManager.activeQualityLayerHeight + "mm";
  213. result += "</font>";
  214. }
  215. return result;
  216. }
  217. enabled: !header.currentExtruderVisible || header.currentExtruderIndex > -1
  218. width: parent.width * 0.55
  219. height: UM.Theme.getSize("setting_control").height
  220. anchors.left: globalProfileLabel.right
  221. anchors.right: parent.right
  222. tooltip: Cura.MachineManager.activeQualityName
  223. style: UM.Theme.styles.sidebar_header_button
  224. activeFocusOnPress: true;
  225. menu: ProfileMenu { }
  226. UM.SimpleButton
  227. {
  228. id: customisedSettings
  229. visible: Cura.MachineManager.hasUserSettings
  230. height: parent.height * 0.6
  231. width: parent.height * 0.6
  232. anchors.verticalCenter: parent.verticalCenter
  233. anchors.right: parent.right
  234. anchors.rightMargin: UM.Theme.getSize("setting_preferences_button_margin").width - UM.Theme.getSize("sidebar_margin").width
  235. color: hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button");
  236. iconSource: UM.Theme.getIcon("star");
  237. onClicked:
  238. {
  239. forceActiveFocus();
  240. Cura.Actions.manageProfiles.trigger()
  241. }
  242. onEntered:
  243. {
  244. var content = catalog.i18nc("@tooltip","Some setting/override values are different from the values stored in the profile.\n\nClick to open the profile manager.")
  245. base.showTooltip(globalProfileRow, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), content)
  246. }
  247. onExited: base.hideTooltip()
  248. }
  249. }
  250. }
  251. StackView
  252. {
  253. id: sidebarContents
  254. anchors.bottom: footerSeparator.top
  255. anchors.top: globalProfileRow.bottom
  256. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  257. anchors.left: base.left
  258. anchors.right: base.right
  259. visible: !monitoringPrint && !hideSettings
  260. delegate: StackViewDelegate
  261. {
  262. function transitionFinished(properties)
  263. {
  264. properties.exitItem.opacity = 1
  265. }
  266. pushTransition: StackViewTransition
  267. {
  268. PropertyAnimation
  269. {
  270. target: enterItem
  271. property: "opacity"
  272. from: 0
  273. to: 1
  274. duration: 100
  275. }
  276. PropertyAnimation
  277. {
  278. target: exitItem
  279. property: "opacity"
  280. from: 1
  281. to: 0
  282. duration: 100
  283. }
  284. }
  285. }
  286. }
  287. Loader
  288. {
  289. id: controlItem
  290. anchors.bottom: footerSeparator.top
  291. anchors.top: headerSeparator.bottom
  292. anchors.left: base.left
  293. anchors.right: base.right
  294. sourceComponent:
  295. {
  296. if(monitoringPrint && connectedPrinter != null)
  297. {
  298. if(connectedPrinter.controlItem != null)
  299. {
  300. return connectedPrinter.controlItem
  301. }
  302. }
  303. return null
  304. }
  305. }
  306. Loader
  307. {
  308. anchors.bottom: footerSeparator.top
  309. anchors.top: headerSeparator.bottom
  310. anchors.left: base.left
  311. anchors.right: base.right
  312. source:
  313. {
  314. if(controlItem.sourceComponent == null)
  315. {
  316. if(monitoringPrint)
  317. {
  318. return "PrintMonitor.qml"
  319. } else
  320. {
  321. return "SidebarContents.qml"
  322. }
  323. }
  324. else
  325. {
  326. return ""
  327. }
  328. }
  329. }
  330. Rectangle
  331. {
  332. id: footerSeparator
  333. width: parent.width
  334. height: UM.Theme.getSize("sidebar_lining").height
  335. color: UM.Theme.getColor("sidebar_lining")
  336. anchors.bottom: printSpecs.top
  337. anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height * 2 + UM.Theme.getSize("progressbar").height + UM.Theme.getFont("default_bold").pixelSize
  338. }
  339. Rectangle
  340. {
  341. id: printSpecs
  342. anchors.left: parent.left
  343. anchors.bottom: parent.bottom
  344. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  345. anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height
  346. height: childrenRect.height
  347. visible: !monitoringPrint
  348. UM.TooltipArea
  349. {
  350. id: timeSpecPerFeatureTooltipArea
  351. width: timeSpec.width
  352. height: timeSpec.height
  353. anchors.left: parent.left
  354. anchors.bottom: timeSpecDescription.top
  355. text: {
  356. var order = ["inset_0", "inset_x", "skin", "infill", "support_infill", "support_interface", "support", "travel", "retract", "none"];
  357. var visible_names = {
  358. "inset_0": catalog.i18nc("@tooltip", "Outer Wall"),
  359. "inset_x": catalog.i18nc("@tooltip", "Inner Walls"),
  360. "skin": catalog.i18nc("@tooltip", "Skin"),
  361. "infill": catalog.i18nc("@tooltip", "Infill"),
  362. "support_infill": catalog.i18nc("@tooltip", "Support Infill"),
  363. "support_interface": catalog.i18nc("@tooltip", "Support Interface"),
  364. "support": catalog.i18nc("@tooltip", "Support"),
  365. "travel": catalog.i18nc("@tooltip", "Travel"),
  366. "retract": catalog.i18nc("@tooltip", "Retractions"),
  367. "none": catalog.i18nc("@tooltip", "Other")
  368. };
  369. var result = "";
  370. for(var feature in order)
  371. {
  372. feature = order[feature];
  373. if(base.printDurationPerFeature[feature] && base.printDurationPerFeature[feature].totalSeconds > 0)
  374. {
  375. result += "<br/>" + visible_names[feature] + ": " + base.printDurationPerFeature[feature].getDisplayString(UM.DurationFormat.Short);
  376. }
  377. }
  378. result = result.replace(/^\<br\/\>/, ""); // remove newline before first item
  379. return result;
  380. }
  381. Text
  382. {
  383. id: timeSpec
  384. anchors.left: parent.left
  385. anchors.bottom: parent.bottom
  386. font: UM.Theme.getFont("large")
  387. color: UM.Theme.getColor("text_subtext")
  388. text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short)
  389. }
  390. }
  391. Text
  392. {
  393. id: timeSpecDescription
  394. anchors.left: parent.left
  395. anchors.bottom: lengthSpec.top
  396. font: UM.Theme.getFont("very_small")
  397. color: UM.Theme.getColor("text_subtext")
  398. text: catalog.i18nc("@description", "Print time")
  399. }
  400. Text
  401. {
  402. id: lengthSpec
  403. anchors.left: parent.left
  404. anchors.bottom: parent.bottom
  405. font: UM.Theme.getFont("very_small")
  406. color: UM.Theme.getColor("text_subtext")
  407. text:
  408. {
  409. var lengths = [];
  410. var weights = [];
  411. var costs = [];
  412. var someCostsKnown = false;
  413. if(base.printMaterialLengths) {
  414. for(var index = 0; index < base.printMaterialLengths.length; index++)
  415. {
  416. if(base.printMaterialLengths[index] > 0)
  417. {
  418. lengths.push(base.printMaterialLengths[index].toFixed(2));
  419. weights.push(String(Math.floor(base.printMaterialWeights[index])));
  420. var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2);
  421. costs.push(cost);
  422. if(cost > 0)
  423. {
  424. someCostsKnown = true;
  425. }
  426. }
  427. }
  428. }
  429. if(lengths.length == 0)
  430. {
  431. lengths = ["0.00"];
  432. weights = ["0"];
  433. costs = ["0.00"];
  434. }
  435. if(someCostsKnown)
  436. {
  437. return catalog.i18nc("@label", "%1m / ~ %2g / ~ %4 %3").arg(lengths.join(" + "))
  438. .arg(weights.join(" + ")).arg(costs.join(" + ")).arg(UM.Preferences.getValue("cura/currency"));
  439. }
  440. else
  441. {
  442. return catalog.i18nc("@label", "%1m / ~ %2g").arg(lengths.join(" + ")).arg(weights.join(" + "));
  443. }
  444. }
  445. }
  446. }
  447. // SaveButton and MonitorButton are actually the bottom footer panels.
  448. // "!monitoringPrint" currently means "show-settings-mode"
  449. SaveButton
  450. {
  451. id: saveButton
  452. implicitWidth: base.width
  453. anchors.top: footerSeparator.bottom
  454. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  455. anchors.bottom: parent.bottom
  456. visible: !monitoringPrint
  457. }
  458. MonitorButton
  459. {
  460. id: monitorButton
  461. implicitWidth: base.width
  462. anchors.top: footerSeparator.bottom
  463. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  464. anchors.bottom: parent.bottom
  465. visible: monitoringPrint
  466. }
  467. SidebarTooltip
  468. {
  469. id: tooltip;
  470. }
  471. // Setting mode: Recommended or Custom
  472. ListModel
  473. {
  474. id: modesListModel;
  475. }
  476. SidebarSimple
  477. {
  478. id: sidebarSimple;
  479. visible: false;
  480. onShowTooltip: base.showTooltip(item, location, text)
  481. onHideTooltip: base.hideTooltip()
  482. }
  483. SidebarAdvanced
  484. {
  485. id: sidebarAdvanced;
  486. visible: false;
  487. onShowTooltip: base.showTooltip(item, location, text)
  488. onHideTooltip: base.hideTooltip()
  489. }
  490. Component.onCompleted:
  491. {
  492. modesListModel.append({
  493. text: catalog.i18nc("@title:tab", "Recommended"),
  494. tooltipText: catalog.i18nc("@tooltip", "<b>Recommended Print Setup</b><br/><br/>Print with the recommended settings for the selected printer, material and quality."),
  495. item: sidebarSimple
  496. })
  497. modesListModel.append({
  498. text: catalog.i18nc("@title:tab", "Custom"),
  499. tooltipText: catalog.i18nc("@tooltip", "<b>Custom Print Setup</b><br/><br/>Print with finegrained control over every last bit of the slicing process."),
  500. item: sidebarAdvanced
  501. })
  502. sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "immediate": true });
  503. var index = parseInt(UM.Preferences.getValue("cura/active_mode"))
  504. if(index)
  505. {
  506. currentModeIndex = index;
  507. }
  508. }
  509. UM.SettingPropertyProvider
  510. {
  511. id: machineExtruderCount
  512. containerStackId: Cura.MachineManager.activeMachineId
  513. key: "machine_extruder_count"
  514. watchedProperties: [ "value" ]
  515. storeIndex: 0
  516. }
  517. UM.SettingPropertyProvider
  518. {
  519. id: machineHeatedBed
  520. containerStackId: Cura.MachineManager.activeMachineId
  521. key: "machine_heated_bed"
  522. watchedProperties: [ "value" ]
  523. storeIndex: 0
  524. }
  525. }