Sidebar.qml 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. // Copyright (c) 2017 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 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. property bool hideView: Cura.MachineManager.activeMachineName == ""
  16. // Is there an output device for this printer?
  17. property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
  18. property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
  19. property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
  20. property int backendState: UM.Backend.state
  21. property bool monitoringPrint: false
  22. property variant printDuration: PrintInformation.currentPrintTime
  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. Label {
  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: Math.floor(parent.width * 0.45)
  103. font: UM.Theme.getFont("large")
  104. color: UM.Theme.getColor("text")
  105. visible: !monitoringPrint && !hideView
  106. }
  107. Rectangle {
  108. id: settingsModeSelection
  109. color: "transparent"
  110. width: Math.floor(parent.width * 0.55)
  111. height: UM.Theme.getSize("sidebar_header_mode_toggle").height
  112. anchors.right: parent.right
  113. anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width
  114. anchors.top:
  115. {
  116. if (settingsModeLabel.contentWidth >= parent.width - width - UM.Theme.getSize("sidebar_margin").width * 2)
  117. {
  118. return settingsModeLabel.bottom;
  119. }
  120. else
  121. {
  122. return headerSeparator.bottom;
  123. }
  124. }
  125. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  126. visible: !monitoringPrint && !hideSettings && !hideView
  127. Component{
  128. id: wizardDelegate
  129. Button {
  130. height: settingsModeSelection.height
  131. anchors.left: parent.left
  132. anchors.leftMargin: model.index * (settingsModeSelection.width / 2)
  133. anchors.verticalCenter: parent.verticalCenter
  134. width: Math.floor(0.5 * parent.width)
  135. text: model.text
  136. exclusiveGroup: modeMenuGroup;
  137. checkable: true;
  138. checked: base.currentModeIndex == index
  139. onClicked: base.currentModeIndex = index
  140. onHoveredChanged: {
  141. if (hovered)
  142. {
  143. tooltipDelayTimer.item = settingsModeSelection
  144. tooltipDelayTimer.text = model.tooltipText
  145. tooltipDelayTimer.start();
  146. }
  147. else
  148. {
  149. tooltipDelayTimer.stop();
  150. base.hideTooltip();
  151. }
  152. }
  153. style: ButtonStyle {
  154. background: Rectangle {
  155. border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width
  156. border.color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active_border") :
  157. control.hovered ? UM.Theme.getColor("action_button_hovered_border") :
  158. UM.Theme.getColor("action_button_border")
  159. color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active") :
  160. control.hovered ? UM.Theme.getColor("action_button_hovered") :
  161. UM.Theme.getColor("action_button")
  162. Behavior on color { ColorAnimation { duration: 50; } }
  163. Label {
  164. anchors.left: parent.left
  165. anchors.right: parent.right
  166. anchors.verticalCenter: parent.verticalCenter
  167. anchors.leftMargin: UM.Theme.getSize("default_lining").width * 2
  168. anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2
  169. color: (control.checked || control.pressed) ? UM.Theme.getColor("action_button_active_text") :
  170. control.hovered ? UM.Theme.getColor("action_button_hovered_text") :
  171. UM.Theme.getColor("action_button_text")
  172. font: UM.Theme.getFont("default")
  173. text: control.text
  174. horizontalAlignment: Text.AlignHCenter
  175. elide: Text.ElideMiddle
  176. }
  177. }
  178. label: Item { }
  179. }
  180. }
  181. }
  182. ExclusiveGroup { id: modeMenuGroup; }
  183. ListView
  184. {
  185. id: modesList
  186. property var index: 0
  187. model: modesListModel
  188. delegate: wizardDelegate
  189. anchors.top: parent.top
  190. anchors.left: parent.left
  191. width: parent.width
  192. }
  193. }
  194. StackView
  195. {
  196. id: sidebarContents
  197. anchors.bottom: footerSeparator.top
  198. anchors.top: settingsModeSelection.bottom
  199. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  200. anchors.left: base.left
  201. anchors.right: base.right
  202. visible: !monitoringPrint && !hideSettings
  203. delegate: StackViewDelegate
  204. {
  205. function transitionFinished(properties)
  206. {
  207. properties.exitItem.opacity = 1
  208. }
  209. pushTransition: StackViewTransition
  210. {
  211. PropertyAnimation
  212. {
  213. target: enterItem
  214. property: "opacity"
  215. from: 0
  216. to: 1
  217. duration: 100
  218. }
  219. PropertyAnimation
  220. {
  221. target: exitItem
  222. property: "opacity"
  223. from: 1
  224. to: 0
  225. duration: 100
  226. }
  227. }
  228. }
  229. }
  230. Loader
  231. {
  232. id: controlItem
  233. anchors.bottom: footerSeparator.top
  234. anchors.top: headerSeparator.bottom
  235. anchors.left: base.left
  236. anchors.right: base.right
  237. sourceComponent:
  238. {
  239. if(monitoringPrint && connectedPrinter != null)
  240. {
  241. if(connectedPrinter.controlItem != null)
  242. {
  243. return connectedPrinter.controlItem
  244. }
  245. }
  246. return null
  247. }
  248. }
  249. Loader
  250. {
  251. anchors.bottom: footerSeparator.top
  252. anchors.top: headerSeparator.bottom
  253. anchors.left: base.left
  254. anchors.right: base.right
  255. source:
  256. {
  257. if(controlItem.sourceComponent == null)
  258. {
  259. if(monitoringPrint)
  260. {
  261. return "PrintMonitor.qml"
  262. } else
  263. {
  264. return "SidebarContents.qml"
  265. }
  266. }
  267. else
  268. {
  269. return ""
  270. }
  271. }
  272. }
  273. Rectangle
  274. {
  275. id: footerSeparator
  276. width: parent.width
  277. height: UM.Theme.getSize("sidebar_lining").height
  278. color: UM.Theme.getColor("sidebar_lining")
  279. anchors.bottom: printSpecs.top
  280. anchors.bottomMargin: Math.floor(UM.Theme.getSize("sidebar_margin").height * 2 + UM.Theme.getSize("progressbar").height + UM.Theme.getFont("default_bold").pixelSize)
  281. }
  282. Rectangle
  283. {
  284. id: printSpecs
  285. anchors.left: parent.left
  286. anchors.bottom: parent.bottom
  287. anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width
  288. anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height
  289. height: timeDetails.height + timeSpecDescription.height + lengthSpec.height
  290. visible: !monitoringPrint
  291. Label
  292. {
  293. id: timeDetails
  294. anchors.left: parent.left
  295. anchors.bottom: timeSpecDescription.top
  296. font: UM.Theme.getFont("large")
  297. color: UM.Theme.getColor("text_subtext")
  298. text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label Hours and minutes", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short)
  299. MouseArea
  300. {
  301. id: infillMouseArea
  302. anchors.fill: parent
  303. hoverEnabled: true
  304. //enabled: base.settingsEnabled
  305. onEntered:
  306. {
  307. if(base.printDuration.valid && !base.printDuration.isTotalDurationZero)
  308. {
  309. // All the time information for the different features is achieved
  310. var print_time = PrintInformation.getFeaturePrintTimes()
  311. // A message is created and displayed when the user hover the time label
  312. var content = catalog.i18nc("@tooltip", "<b>Time information</b>")
  313. for(var feature in print_time)
  314. {
  315. if(!print_time[feature].isTotalDurationZero)
  316. {
  317. content += "<br /><i>" + feature + "</i>: " + print_time[feature].getDisplayString(UM.DurationFormat.Short)
  318. }
  319. }
  320. base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), content)
  321. }
  322. }
  323. onExited:
  324. {
  325. base.hideTooltip();
  326. }
  327. }
  328. }
  329. Label
  330. {
  331. id: timeSpecDescription
  332. anchors.left: parent.left
  333. anchors.bottom: lengthSpec.top
  334. font: UM.Theme.getFont("very_small")
  335. color: UM.Theme.getColor("text_subtext")
  336. text: catalog.i18nc("@description", "Print time")
  337. }
  338. Label
  339. {
  340. id: lengthSpec
  341. anchors.left: parent.left
  342. anchors.bottom: parent.bottom
  343. font: UM.Theme.getFont("very_small")
  344. color: UM.Theme.getColor("text_subtext")
  345. text:
  346. {
  347. var lengths = [];
  348. var weights = [];
  349. var costs = [];
  350. var someCostsKnown = false;
  351. if(base.printMaterialLengths) {
  352. for(var index = 0; index < base.printMaterialLengths.length; index++)
  353. {
  354. if(base.printMaterialLengths[index] > 0)
  355. {
  356. lengths.push(base.printMaterialLengths[index].toFixed(2));
  357. weights.push(String(Math.floor(base.printMaterialWeights[index])));
  358. var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2);
  359. costs.push(cost);
  360. if(cost > 0)
  361. {
  362. someCostsKnown = true;
  363. }
  364. }
  365. }
  366. }
  367. if(lengths.length == 0)
  368. {
  369. lengths = ["0.00"];
  370. weights = ["0"];
  371. costs = ["0.00"];
  372. }
  373. if(someCostsKnown)
  374. {
  375. return catalog.i18nc("@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost", "%1m / ~ %2g / ~ %4 %3").arg(lengths.join(" + "))
  376. .arg(weights.join(" + ")).arg(costs.join(" + ")).arg(UM.Preferences.getValue("cura/currency"));
  377. }
  378. else
  379. {
  380. return catalog.i18nc("@label Print estimates: m for meters, g for grams", "%1m / ~ %2g").arg(lengths.join(" + ")).arg(weights.join(" + "));
  381. }
  382. }
  383. }
  384. }
  385. // SaveButton and MonitorButton are actually the bottom footer panels.
  386. // "!monitoringPrint" currently means "show-settings-mode"
  387. SaveButton
  388. {
  389. id: saveButton
  390. implicitWidth: base.width
  391. anchors.top: footerSeparator.bottom
  392. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  393. anchors.bottom: parent.bottom
  394. visible: !monitoringPrint
  395. }
  396. MonitorButton
  397. {
  398. id: monitorButton
  399. implicitWidth: base.width
  400. anchors.top: footerSeparator.bottom
  401. anchors.topMargin: UM.Theme.getSize("sidebar_margin").height
  402. anchors.bottom: parent.bottom
  403. visible: monitoringPrint
  404. }
  405. SidebarTooltip
  406. {
  407. id: tooltip;
  408. }
  409. // Setting mode: Recommended or Custom
  410. ListModel
  411. {
  412. id: modesListModel;
  413. }
  414. SidebarSimple
  415. {
  416. id: sidebarSimple;
  417. visible: false;
  418. onShowTooltip: base.showTooltip(item, location, text)
  419. onHideTooltip: base.hideTooltip()
  420. }
  421. SidebarAdvanced
  422. {
  423. id: sidebarAdvanced;
  424. visible: false;
  425. onShowTooltip: base.showTooltip(item, location, text)
  426. onHideTooltip: base.hideTooltip()
  427. }
  428. Component.onCompleted:
  429. {
  430. modesListModel.append({
  431. text: catalog.i18nc("@title:tab", "Recommended"),
  432. tooltipText: catalog.i18nc("@tooltip", "<b>Recommended Print Setup</b><br/><br/>Print with the recommended settings for the selected printer, material and quality."),
  433. item: sidebarSimple
  434. })
  435. modesListModel.append({
  436. text: catalog.i18nc("@title:tab", "Custom"),
  437. tooltipText: catalog.i18nc("@tooltip", "<b>Custom Print Setup</b><br/><br/>Print with finegrained control over every last bit of the slicing process."),
  438. item: sidebarAdvanced
  439. })
  440. sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "immediate": true });
  441. var index = Math.floor(UM.Preferences.getValue("cura/active_mode"))
  442. if(index)
  443. {
  444. currentModeIndex = index;
  445. }
  446. }
  447. UM.SettingPropertyProvider
  448. {
  449. id: machineExtruderCount
  450. containerStackId: Cura.MachineManager.activeMachineId
  451. key: "machine_extruder_count"
  452. watchedProperties: [ "value" ]
  453. storeIndex: 0
  454. }
  455. UM.SettingPropertyProvider
  456. {
  457. id: machineHeatedBed
  458. containerStackId: Cura.MachineManager.activeMachineId
  459. key: "machine_heated_bed"
  460. watchedProperties: [ "value" ]
  461. storeIndex: 0
  462. }
  463. }