Sidebar.qml 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  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 monitoringPrint: false; // When adding more "tabs", one want to replace this bool with a ListModel
  15. property bool hideSettings: PrintInformation.preSliced
  16. Connections
  17. {
  18. target: Printer
  19. onShowPrintMonitor:
  20. {
  21. base.monitoringPrint = show;
  22. showSettings.checked = !show;
  23. showMonitor.checked = show;
  24. }
  25. }
  26. // Is there an output device for this printer?
  27. property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
  28. property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
  29. property int backendState: UM.Backend.state;
  30. color: UM.Theme.getColor("sidebar")
  31. UM.I18nCatalog { id: catalog; name:"cura"}
  32. Timer {
  33. id: tooltipDelayTimer
  34. interval: 500
  35. repeat: false
  36. property var item
  37. property string text
  38. onTriggered:
  39. {
  40. base.showTooltip(base, {x:1, y:item.y}, text);
  41. }
  42. }
  43. function showTooltip(item, position, text)
  44. {
  45. tooltip.text = text;
  46. position = item.mapToItem(base, position.x, position.y);
  47. tooltip.show(position);
  48. }
  49. function hideTooltip()
  50. {
  51. tooltip.hide();
  52. }
  53. function strPadLeft(string, pad, length) {
  54. return (new Array(length + 1).join(pad) + string).slice(-length);
  55. }
  56. function getPrettyTime(time)
  57. {
  58. var hours = Math.floor(time / 3600)
  59. time -= hours * 3600
  60. var minutes = Math.floor(time / 60);
  61. time -= minutes * 60
  62. var seconds = Math.floor(time);
  63. var finalTime = strPadLeft(hours, "0", 2) + ':' + strPadLeft(minutes,'0',2)+ ':' + strPadLeft(seconds,'0',2);
  64. return finalTime;
  65. }
  66. MouseArea
  67. {
  68. anchors.fill: parent
  69. acceptedButtons: Qt.AllButtons;
  70. onWheel:
  71. {
  72. wheel.accepted = true;
  73. }
  74. }
  75. // Printer selection and mode selection buttons for changing between Setting & Monitor print mode
  76. Rectangle
  77. {
  78. id: sidebarHeaderBar
  79. anchors.left: parent.left
  80. anchors.right: parent.right
  81. height: childrenRect.height
  82. color: UM.Theme.getColor("sidebar_header_bar")
  83. Row
  84. {
  85. anchors.left: parent.left
  86. anchors.right: parent.right
  87. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  88. spacing: UM.Theme.getSize("default_margin").width
  89. ToolButton
  90. {
  91. id: machineSelection
  92. text: Cura.MachineManager.activeMachineName
  93. width: parent.width - (showSettings.width + showMonitor.width + 2 * UM.Theme.getSize("default_margin").width)
  94. height: UM.Theme.getSize("sidebar_header").height
  95. tooltip: Cura.MachineManager.activeMachineName
  96. anchors.verticalCenter: parent.verticalCenter
  97. style: ButtonStyle {
  98. background: Rectangle {
  99. color: {
  100. if(control.pressed) {
  101. return UM.Theme.getColor("sidebar_header_active");
  102. } else if(control.hovered) {
  103. return UM.Theme.getColor("sidebar_header_hover");
  104. } else {
  105. return UM.Theme.getColor("sidebar_header_bar");
  106. }
  107. }
  108. Behavior on color { ColorAnimation { duration: 50; } }
  109. Rectangle {
  110. id: underline;
  111. anchors.left: parent.left
  112. anchors.right: parent.right
  113. anchors.bottom: parent.bottom
  114. height: UM.Theme.getSize("sidebar_header_highlight").height
  115. color: UM.Theme.getColor("sidebar_header_highlight_hover")
  116. visible: control.hovered || control.pressed
  117. }
  118. UM.RecolorImage {
  119. id: downArrow
  120. anchors.verticalCenter: parent.verticalCenter
  121. anchors.right: parent.right
  122. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  123. width: UM.Theme.getSize("standard_arrow").width
  124. height: UM.Theme.getSize("standard_arrow").height
  125. sourceSize.width: width
  126. sourceSize.height: width
  127. color: UM.Theme.getColor("text_reversed")
  128. source: UM.Theme.getIcon("arrow_bottom")
  129. }
  130. Label {
  131. id: sidebarComboBoxLabel
  132. color: UM.Theme.getColor("text_reversed")
  133. text: control.text;
  134. elide: Text.ElideRight;
  135. anchors.left: parent.left;
  136. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  137. anchors.right: downArrow.left;
  138. anchors.rightMargin: control.rightMargin;
  139. anchors.verticalCenter: parent.verticalCenter;
  140. font: UM.Theme.getFont("large")
  141. }
  142. }
  143. label: Label{}
  144. }
  145. menu: PrinterMenu { }
  146. }
  147. Button
  148. {
  149. id: showSettings
  150. width: height
  151. height: UM.Theme.getSize("sidebar_header").height
  152. onClicked: monitoringPrint = false
  153. iconSource: UM.Theme.getIcon("tab_settings");
  154. property color overlayColor: "transparent"
  155. property string overlayIconSource: ""
  156. checkable: true
  157. checked: !monitoringPrint
  158. exclusiveGroup: sidebarHeaderBarGroup
  159. property string tooltipText: catalog.i18nc("@tooltip", "<b>Print Setup</b><br/><br/>Edit or review the settings for the active print job.")
  160. onHoveredChanged: {
  161. if (hovered)
  162. {
  163. tooltipDelayTimer.item = showSettings
  164. tooltipDelayTimer.text = tooltipText
  165. tooltipDelayTimer.start();
  166. }
  167. else
  168. {
  169. tooltipDelayTimer.stop();
  170. base.hideTooltip();
  171. }
  172. }
  173. style: UM.Theme.styles.sidebar_header_tab
  174. }
  175. Button
  176. {
  177. id: showMonitor
  178. width: height
  179. height: UM.Theme.getSize("sidebar_header").height
  180. onClicked: monitoringPrint = true
  181. iconSource: printerConnected ? UM.Theme.getIcon("tab_monitor_with_status") : UM.Theme.getIcon("tab_monitor")
  182. property color overlayColor:
  183. {
  184. if(!printerAcceptsCommands)
  185. {
  186. return UM.Theme.getColor("status_unknown");
  187. }
  188. if(Cura.MachineManager.printerOutputDevices[0].printerState == "maintenance")
  189. {
  190. return UM.Theme.getColor("status_busy");
  191. }
  192. switch(Cura.MachineManager.printerOutputDevices[0].jobState)
  193. {
  194. case "printing":
  195. case "pre_print":
  196. case "wait_cleanup":
  197. case "pausing":
  198. case "resuming":
  199. return UM.Theme.getColor("status_busy");
  200. case "ready":
  201. case "":
  202. return UM.Theme.getColor("status_ready");
  203. case "paused":
  204. return UM.Theme.getColor("status_paused");
  205. case "error":
  206. return UM.Theme.getColor("status_stopped");
  207. case "offline":
  208. return UM.Theme.getColor("status_offline");
  209. default:
  210. return UM.Theme.getColor("text_reversed");
  211. }
  212. }
  213. property string overlayIconSource:
  214. {
  215. if(!printerConnected)
  216. {
  217. return "";
  218. }
  219. else if(!printerAcceptsCommands)
  220. {
  221. return UM.Theme.getIcon("tab_status_unknown");
  222. }
  223. if(Cura.MachineManager.printerOutputDevices[0].printerState == "maintenance")
  224. {
  225. return UM.Theme.getIcon("tab_status_busy");
  226. }
  227. switch(Cura.MachineManager.printerOutputDevices[0].jobState)
  228. {
  229. case "printing":
  230. case "pre_print":
  231. case "wait_cleanup":
  232. case "pausing":
  233. case "resuming":
  234. return UM.Theme.getIcon("tab_status_busy");
  235. case "ready":
  236. case "":
  237. return UM.Theme.getIcon("tab_status_connected")
  238. case "paused":
  239. return UM.Theme.getIcon("tab_status_paused")
  240. case "error":
  241. return UM.Theme.getIcon("tab_status_stopped")
  242. case "offline":
  243. return UM.Theme.getIcon("tab_status_offline")
  244. default:
  245. return ""
  246. }
  247. }
  248. checkable: true
  249. checked: monitoringPrint
  250. exclusiveGroup: sidebarHeaderBarGroup
  251. property string tooltipText: catalog.i18nc("@tooltip", "<b>Print Monitor</b><br/><br/>Monitor the state of the connected printer and the print job in progress.")
  252. onHoveredChanged: {
  253. if (hovered)
  254. {
  255. tooltipDelayTimer.item = showMonitor
  256. tooltipDelayTimer.text = tooltipText
  257. tooltipDelayTimer.start();
  258. }
  259. else
  260. {
  261. tooltipDelayTimer.stop();
  262. base.hideTooltip();
  263. }
  264. }
  265. style: UM.Theme.styles.sidebar_header_tab
  266. }
  267. ExclusiveGroup { id: sidebarHeaderBarGroup }
  268. }
  269. }
  270. SidebarHeader {
  271. id: header
  272. width: parent.width
  273. anchors.top: sidebarHeaderBar.bottom
  274. onShowTooltip: base.showTooltip(item, location, text)
  275. onHideTooltip: base.hideTooltip()
  276. }
  277. Rectangle {
  278. id: headerSeparator
  279. width: parent.width
  280. visible: !monitoringPrint && !hideSettings
  281. height: visible ? UM.Theme.getSize("sidebar_lining").height : 0
  282. color: UM.Theme.getColor("sidebar_lining")
  283. anchors.top: header.bottom
  284. anchors.topMargin: visible ? UM.Theme.getSize("default_margin").height : 0
  285. }
  286. onCurrentModeIndexChanged:
  287. {
  288. UM.Preferences.setValue("cura/active_mode", currentModeIndex);
  289. if(modesListModel.count > base.currentModeIndex)
  290. {
  291. sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "replace": true });
  292. }
  293. }
  294. Label {
  295. id: settingsModeLabel
  296. text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox","Print Setup disabled\nG-code files cannot be modified");
  297. anchors.left: parent.left
  298. anchors.leftMargin: UM.Theme.getSize("default_margin").width;
  299. anchors.top: headerSeparator.bottom
  300. anchors.topMargin: UM.Theme.getSize("default_margin").height
  301. width: parent.width * 0.45 - 2 * UM.Theme.getSize("default_margin").width
  302. font: UM.Theme.getFont("large")
  303. color: UM.Theme.getColor("text")
  304. visible: !monitoringPrint
  305. elide: Text.ElideRight
  306. }
  307. Rectangle {
  308. id: settingsModeSelection
  309. width: parent.width * 0.55
  310. height: UM.Theme.getSize("sidebar_header_mode_toggle").height
  311. anchors.right: parent.right
  312. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  313. anchors.top: headerSeparator.bottom
  314. anchors.topMargin: UM.Theme.getSize("default_margin").height
  315. visible: !monitoringPrint && !hideSettings
  316. Component{
  317. id: wizardDelegate
  318. Button {
  319. height: settingsModeSelection.height
  320. anchors.left: parent.left
  321. anchors.leftMargin: model.index * (settingsModeSelection.width / 2)
  322. anchors.verticalCenter: parent.verticalCenter
  323. width: 0.5 * parent.width - (model.showFilterButton ? toggleFilterButton.width : 0)
  324. text: model.text
  325. exclusiveGroup: modeMenuGroup;
  326. checkable: true;
  327. checked: base.currentModeIndex == index
  328. onClicked: base.currentModeIndex = index
  329. onHoveredChanged: {
  330. if (hovered)
  331. {
  332. tooltipDelayTimer.item = settingsModeSelection
  333. tooltipDelayTimer.text = model.tooltipText
  334. tooltipDelayTimer.start();
  335. }
  336. else
  337. {
  338. tooltipDelayTimer.stop();
  339. base.hideTooltip();
  340. }
  341. }
  342. style: ButtonStyle {
  343. background: Rectangle {
  344. border.width: UM.Theme.getSize("default_lining").width
  345. border.color: control.checked ? UM.Theme.getColor("toggle_checked_border") :
  346. control.pressed ? UM.Theme.getColor("toggle_active_border") :
  347. control.hovered ? UM.Theme.getColor("toggle_hovered_border") : UM.Theme.getColor("toggle_unchecked_border")
  348. color: control.checked ? UM.Theme.getColor("toggle_checked") :
  349. control.pressed ? UM.Theme.getColor("toggle_active") :
  350. control.hovered ? UM.Theme.getColor("toggle_hovered") : UM.Theme.getColor("toggle_unchecked")
  351. Behavior on color { ColorAnimation { duration: 50; } }
  352. Label {
  353. anchors.centerIn: parent
  354. color: control.checked ? UM.Theme.getColor("toggle_checked_text") :
  355. control.pressed ? UM.Theme.getColor("toggle_active_text") :
  356. control.hovered ? UM.Theme.getColor("toggle_hovered_text") : UM.Theme.getColor("toggle_unchecked_text")
  357. font: UM.Theme.getFont("default")
  358. text: control.text;
  359. }
  360. }
  361. label: Item { }
  362. }
  363. }
  364. }
  365. ExclusiveGroup { id: modeMenuGroup; }
  366. ListView{
  367. id: modesList
  368. property var index: 0
  369. model: modesListModel
  370. delegate: wizardDelegate
  371. anchors.top: parent.top
  372. anchors.left: parent.left
  373. width: parent.width
  374. }
  375. }
  376. Button
  377. {
  378. id: toggleFilterButton
  379. anchors.right: parent.right
  380. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  381. anchors.top: headerSeparator.bottom
  382. anchors.topMargin: UM.Theme.getSize("default_margin").height
  383. height: settingsModeSelection.height
  384. width: visible ? height : 0
  385. visible: !monitoringPrint && !hideSettings && modesListModel.get(base.currentModeIndex) != undefined && modesListModel.get(base.currentModeIndex).showFilterButton
  386. opacity: visible ? 1 : 0
  387. onClicked: sidebarContents.currentItem.toggleFilterField()
  388. style: ButtonStyle
  389. {
  390. background: Rectangle
  391. {
  392. border.width: UM.Theme.getSize("default_lining").width
  393. border.color: UM.Theme.getColor("toggle_checked_border")
  394. color: visible ? UM.Theme.getColor("toggle_checked") : UM.Theme.getColor("toggle_hovered")
  395. Behavior on color { ColorAnimation { duration: 50; } }
  396. }
  397. label: UM.RecolorImage
  398. {
  399. anchors.verticalCenter: parent.verticalCenter
  400. anchors.right: parent.right
  401. anchors.rightMargin: UM.Theme.getSize("default_margin").width / 2
  402. source: UM.Theme.getIcon("search")
  403. color: UM.Theme.getColor("toggle_checked_text")
  404. }
  405. }
  406. }
  407. StackView
  408. {
  409. id: sidebarContents
  410. anchors.bottom: footerSeparator.top
  411. anchors.top: settingsModeSelection.bottom
  412. anchors.topMargin: UM.Theme.getSize("default_margin").height
  413. anchors.left: base.left
  414. anchors.right: base.right
  415. visible: !monitoringPrint && !hideSettings
  416. delegate: StackViewDelegate
  417. {
  418. function transitionFinished(properties)
  419. {
  420. properties.exitItem.opacity = 1
  421. }
  422. pushTransition: StackViewTransition
  423. {
  424. PropertyAnimation
  425. {
  426. target: enterItem
  427. property: "opacity"
  428. from: 0
  429. to: 1
  430. duration: 100
  431. }
  432. PropertyAnimation
  433. {
  434. target: exitItem
  435. property: "opacity"
  436. from: 1
  437. to: 0
  438. duration: 100
  439. }
  440. }
  441. }
  442. }
  443. Loader
  444. {
  445. anchors.bottom: footerSeparator.top
  446. anchors.top: headerSeparator.bottom
  447. anchors.left: base.left
  448. anchors.right: base.right
  449. source: monitoringPrint ? "PrintMonitor.qml": "SidebarContents.qml"
  450. }
  451. Rectangle
  452. {
  453. id: footerSeparator
  454. width: parent.width
  455. height: UM.Theme.getSize("sidebar_lining").height
  456. color: UM.Theme.getColor("sidebar_lining")
  457. anchors.bottom: saveButton.top
  458. anchors.bottomMargin: UM.Theme.getSize("default_margin").height
  459. }
  460. // SaveButton and MonitorButton are actually the bottom footer panels.
  461. // "!monitoringPrint" currently means "show-settings-mode"
  462. SaveButton
  463. {
  464. id: saveButton
  465. implicitWidth: base.width
  466. implicitHeight: totalHeight
  467. anchors.bottom: parent.bottom
  468. visible: !monitoringPrint
  469. }
  470. MonitorButton
  471. {
  472. id: monitorButton
  473. implicitWidth: base.width
  474. implicitHeight: totalHeight
  475. anchors.bottom: parent.bottom
  476. visible: monitoringPrint
  477. }
  478. SidebarTooltip
  479. {
  480. id: tooltip;
  481. }
  482. // Setting mode: Recommended or Custom
  483. ListModel
  484. {
  485. id: modesListModel;
  486. }
  487. SidebarSimple
  488. {
  489. id: sidebarSimple;
  490. visible: false;
  491. onShowTooltip: base.showTooltip(item, location, text)
  492. onHideTooltip: base.hideTooltip()
  493. }
  494. SidebarAdvanced
  495. {
  496. id: sidebarAdvanced;
  497. visible: false;
  498. onShowTooltip: base.showTooltip(item, location, text)
  499. onHideTooltip: base.hideTooltip()
  500. }
  501. Component.onCompleted:
  502. {
  503. modesListModel.append({
  504. text: catalog.i18nc("@title:tab", "Recommended"),
  505. tooltipText: catalog.i18nc("@tooltip", "<b>Recommended Print Setup</b><br/><br/>Print with the recommended settings for the selected printer, material and quality."),
  506. item: sidebarSimple,
  507. showFilterButton: false
  508. })
  509. modesListModel.append({
  510. text: catalog.i18nc("@title:tab", "Custom"),
  511. tooltipText: catalog.i18nc("@tooltip", "<b>Custom Print Setup</b><br/><br/>Print with finegrained control over every last bit of the slicing process."),
  512. item: sidebarAdvanced,
  513. showFilterButton: true
  514. })
  515. sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "immediate": true });
  516. var index = parseInt(UM.Preferences.getValue("cura/active_mode"))
  517. if(index)
  518. {
  519. currentModeIndex = index;
  520. }
  521. }
  522. UM.SettingPropertyProvider
  523. {
  524. id: machineExtruderCount
  525. containerStackId: Cura.MachineManager.activeMachineId
  526. key: "machine_extruder_count"
  527. watchedProperties: [ "value" ]
  528. storeIndex: 0
  529. }
  530. UM.SettingPropertyProvider
  531. {
  532. id: machineHeatedBed
  533. containerStackId: Cura.MachineManager.activeMachineId
  534. key: "machine_heated_bed"
  535. watchedProperties: [ "value" ]
  536. storeIndex: 0
  537. }
  538. }