PrintMonitor.qml 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  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. Column
  10. {
  11. id: printMonitor
  12. property var connectedPrinter: printerConnected ? Cura.MachineManager.printerOutputDevices[0] : null
  13. Cura.ExtrudersModel
  14. {
  15. id: extrudersModel
  16. simpleNames: true
  17. }
  18. Rectangle
  19. {
  20. id: connectedPrinterHeader
  21. width: parent.width
  22. height: childrenRect.height + UM.Theme.getSize("default_margin").height * 2
  23. color: UM.Theme.getColor("setting_category")
  24. Label
  25. {
  26. id: connectedPrinterNameLabel
  27. text: printerConnected ? connectedPrinter.name : catalog.i18nc("@info:status", "No printer connected")
  28. font: UM.Theme.getFont("large")
  29. color: UM.Theme.getColor("text")
  30. anchors.left: parent.left
  31. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  32. anchors.top: parent.top
  33. anchors.topMargin: UM.Theme.getSize("default_margin").height
  34. anchors.right: parent.right
  35. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  36. }
  37. Label
  38. {
  39. id: connectedPrinterAddressLabel
  40. text: printerConnected ? connectedPrinter.address : ""
  41. font: UM.Theme.getFont("small")
  42. color: UM.Theme.getColor("text_inactive")
  43. anchors.left: parent.left
  44. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  45. anchors.top: parent.top
  46. anchors.topMargin: UM.Theme.getSize("default_margin").height
  47. anchors.right: parent.right
  48. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  49. horizontalAlignment: Text.AlignRight
  50. }
  51. Label
  52. {
  53. text: printerConnected ? connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.")
  54. color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
  55. font: UM.Theme.getFont("very_small")
  56. wrapMode: Text.WordWrap
  57. anchors.left: parent.left
  58. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  59. anchors.right: parent.right
  60. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  61. anchors.top: connectedPrinterNameLabel.bottom
  62. }
  63. }
  64. Rectangle
  65. {
  66. color: UM.Theme.getColor("sidebar_lining")
  67. width: parent.width
  68. height: childrenRect.height
  69. GridLayout
  70. {
  71. id: extrudersGrid
  72. columns: 2
  73. columnSpacing: UM.Theme.getSize("sidebar_lining_thin").width
  74. rowSpacing: UM.Theme.getSize("sidebar_lining_thin").height
  75. width: parent.width
  76. Repeater
  77. {
  78. model: machineExtruderCount.properties.value
  79. delegate: Rectangle
  80. {
  81. id: extruderRectangle
  82. color: UM.Theme.getColor("sidebar")
  83. width: extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2
  84. height: UM.Theme.getSize("sidebar_extruder_box").height
  85. Text //Extruder name.
  86. {
  87. text: machineExtruderCount.properties.value > 1 ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend")
  88. color: UM.Theme.getColor("text")
  89. anchors.left: parent.left
  90. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  91. anchors.top: parent.top
  92. anchors.topMargin: UM.Theme.getSize("default_margin").height
  93. }
  94. Text //Temperature indication.
  95. {
  96. text: printerConnected ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : ""
  97. font: UM.Theme.getFont("large")
  98. anchors.right: parent.right
  99. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  100. anchors.top: parent.top
  101. anchors.topMargin: UM.Theme.getSize("default_margin").height
  102. }
  103. Rectangle //Material colour indication.
  104. {
  105. id: materialColor
  106. width: materialName.height * 0.75
  107. height: materialName.height * 0.75
  108. color: printerConnected ? connectedPrinter.materialColors[index] : "#00000000" //Need to check for printerConnected or materialColors[index] gives an error.
  109. border.width: UM.Theme.getSize("default_lining").width
  110. border.color: UM.Theme.getColor("lining")
  111. visible: printerConnected
  112. anchors.left: parent.left
  113. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  114. anchors.verticalCenter: materialName.verticalCenter
  115. }
  116. Text //Material name.
  117. {
  118. id: materialName
  119. text: printerConnected ? connectedPrinter.materialNames[index] : ""
  120. font: UM.Theme.getFont("default")
  121. color: UM.Theme.getColor("text")
  122. anchors.left: materialColor.right
  123. anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width
  124. anchors.bottom: parent.bottom
  125. anchors.bottomMargin: UM.Theme.getSize("default_margin").height
  126. }
  127. Text //Variant name.
  128. {
  129. text: printerConnected ? connectedPrinter.hotendIds[index] : ""
  130. font: UM.Theme.getFont("default")
  131. color: UM.Theme.getColor("text")
  132. anchors.right: parent.right
  133. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  134. anchors.bottom: parent.bottom
  135. anchors.bottomMargin: UM.Theme.getSize("default_margin").height
  136. }
  137. }
  138. }
  139. }
  140. }
  141. Rectangle
  142. {
  143. color: UM.Theme.getColor("sidebar")
  144. width: parent.width
  145. height: machineHeatedBed.properties.value == "True" ? UM.Theme.getSize("sidebar_extruder_box").height : 0
  146. visible: machineHeatedBed.properties.value == "True"
  147. Label //Build plate label.
  148. {
  149. text: catalog.i18nc("@label", "Build plate")
  150. font: UM.Theme.getFont("default")
  151. color: UM.Theme.getColor("text")
  152. anchors.left: parent.left
  153. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  154. anchors.top: parent.top
  155. anchors.topMargin: UM.Theme.getSize("default_margin").height
  156. }
  157. Text //Target temperature.
  158. {
  159. id: bedTargetTemperature
  160. text: printerConnected ? connectedPrinter.targetBedTemperature + "°C" : ""
  161. font: UM.Theme.getFont("small")
  162. color: UM.Theme.getColor("text_inactive")
  163. anchors.right: parent.right
  164. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  165. anchors.bottom: bedCurrentTemperature.bottom
  166. }
  167. Text //Current temperature.
  168. {
  169. id: bedCurrentTemperature
  170. text: printerConnected ? connectedPrinter.bedTemperature + "°C" : ""
  171. font: UM.Theme.getFont("large")
  172. color: UM.Theme.getColor("text")
  173. anchors.right: bedTargetTemperature.left
  174. anchors.rightMargin: UM.Theme.getSize("setting_unit_margin").width
  175. anchors.top: parent.top
  176. anchors.topMargin: UM.Theme.getSize("default_margin").height
  177. }
  178. Rectangle //Input field for pre-heat temperature.
  179. {
  180. id: preheatTemperatureControl
  181. color: UM.Theme.getColor("setting_validation_ok")
  182. border.width: UM.Theme.getSize("default_lining").width
  183. border.color: mouseArea.containsMouse ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border")
  184. anchors.left: parent.left
  185. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  186. anchors.bottom: parent.bottom
  187. anchors.bottomMargin: UM.Theme.getSize("default_margin").height
  188. width: UM.Theme.getSize("setting_control").width
  189. height: UM.Theme.getSize("setting_control").height
  190. Rectangle //Highlight of input field.
  191. {
  192. anchors.fill: parent
  193. anchors.margins: UM.Theme.getSize("default_lining").width
  194. color: UM.Theme.getColor("setting_control_highlight")
  195. opacity: preheatTemperatureControl.hovered ? 1.0 : 0
  196. }
  197. Label //Maximum temperature indication.
  198. {
  199. text: bedTemperature.properties.maximum_value
  200. color: UM.Theme.getColor("setting_unit")
  201. font: UM.Theme.getFont("default")
  202. anchors.right: parent.right
  203. anchors.rightMargin: UM.Theme.getSize("setting_unit_margin").width
  204. anchors.verticalCenter: parent.verticalCenter
  205. }
  206. MouseArea //Change cursor on hovering.
  207. {
  208. id: mouseArea
  209. hoverEnabled: true
  210. anchors.fill: parent
  211. cursorShape: Qt.IBeamCursor
  212. }
  213. TextInput
  214. {
  215. id: preheatTemperatureInput
  216. font: UM.Theme.getFont("default")
  217. color: UM.Theme.getColor("setting_control_text")
  218. selectByMouse: true
  219. maximumLength: 10
  220. validator: RegExpValidator { regExp: /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } //Floating point regex.
  221. anchors.left: parent.left
  222. anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width
  223. anchors.right: parent.right
  224. anchors.verticalCenter: parent.verticalCenter
  225. Binding
  226. {
  227. target: preheatTemperatureInput
  228. property: "text"
  229. value:
  230. {
  231. // Stacklevels
  232. // 0: user -> unsaved change
  233. // 1: quality changes -> saved change
  234. // 2: quality
  235. // 3: material -> user changed material in materialspage
  236. // 4: variant
  237. // 5: machine_changes
  238. // 6: machine
  239. if ((bedTemperature.resolve != "None" && bedTemperature.resolve) && (bedTemperature.stackLevels[0] != 0) && (bedTemperature.stackLevels[0] != 1))
  240. {
  241. // We have a resolve function. Indicates that the setting is not settable per extruder and that
  242. // we have to choose between the resolved value (default) and the global value
  243. // (if user has explicitly set this).
  244. return bedTemperature.resolve;
  245. }
  246. else
  247. {
  248. return bedTemperature.properties.value;
  249. }
  250. }
  251. when: !preheatTemperatureInput.activeFocus
  252. }
  253. }
  254. }
  255. Timer
  256. {
  257. id: preheatCountdownTimer
  258. interval: 100 //Update every 100ms. You want to update every 1s, but then you have one timer for the updating running out of sync with the actual date timer and you might skip seconds.
  259. running: false
  260. repeat: true
  261. onTriggered: update()
  262. property var endTime: new Date() //Set initial endTime to be the current date, so that the endTime has initially already passed and the timer text becomes invisible if you were to update.
  263. function update()
  264. {
  265. var now = new Date();
  266. if (now.getTime() < endTime.getTime())
  267. {
  268. var remaining = endTime - now; //This is in milliseconds.
  269. var minutes = Math.floor(remaining / 60 / 1000);
  270. var seconds = Math.floor((remaining / 1000) % 60);
  271. preheatCountdown.text = minutes + ":" + (seconds < 10 ? "0" + seconds : seconds);
  272. preheatCountdown.visible = true;
  273. }
  274. else
  275. {
  276. preheatCountdown.visible = false;
  277. running = false;
  278. }
  279. }
  280. }
  281. Text
  282. {
  283. id: preheatCountdown
  284. text: "0:00"
  285. visible: false //It only becomes visible when the timer is running.
  286. font: UM.Theme.getFont("default")
  287. color: UM.Theme.getColor("text")
  288. anchors.right: preheatButton.left
  289. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  290. anchors.verticalCenter: preheatButton.verticalCenter
  291. }
  292. Button //The pre-heat button.
  293. {
  294. id: preheatButton
  295. text: catalog.i18nc("@button", "Pre-heat")
  296. tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.")
  297. height: UM.Theme.getSize("setting_control").height
  298. enabled: printerConnected
  299. anchors.right: parent.right
  300. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  301. anchors.bottom: parent.bottom
  302. anchors.bottomMargin: UM.Theme.getSize("default_margin").height
  303. style: ButtonStyle {
  304. background: Rectangle
  305. {
  306. border.width: UM.Theme.getSize("default_lining").width
  307. implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("default_margin").width * 2)
  308. border.color:
  309. {
  310. if(!control.enabled)
  311. {
  312. return UM.Theme.getColor("action_button_disabled_border");
  313. }
  314. else if(control.pressed)
  315. {
  316. return UM.Theme.getColor("action_button_active_border");
  317. }
  318. else if(control.hovered)
  319. {
  320. return UM.Theme.getColor("action_button_hovered_border");
  321. }
  322. else
  323. {
  324. return UM.Theme.getColor("action_button_border");
  325. }
  326. }
  327. color:
  328. {
  329. if(!control.enabled)
  330. {
  331. return UM.Theme.getColor("action_button_disabled");
  332. }
  333. else if(control.pressed)
  334. {
  335. return UM.Theme.getColor("action_button_active");
  336. }
  337. else if(control.hovered)
  338. {
  339. return UM.Theme.getColor("action_button_hovered");
  340. }
  341. else
  342. {
  343. return UM.Theme.getColor("action_button");
  344. }
  345. }
  346. Behavior on color
  347. {
  348. ColorAnimation
  349. {
  350. duration: 50
  351. }
  352. }
  353. Label
  354. {
  355. id: actualLabel
  356. anchors.centerIn: parent
  357. color:
  358. {
  359. if(!control.enabled)
  360. {
  361. return UM.Theme.getColor("action_button_disabled_text");
  362. }
  363. else if(control.pressed)
  364. {
  365. return UM.Theme.getColor("action_button_active_text");
  366. }
  367. else if(control.hovered)
  368. {
  369. return UM.Theme.getColor("action_button_hovered_text");
  370. }
  371. else
  372. {
  373. return UM.Theme.getColor("action_button_text");
  374. }
  375. }
  376. font: UM.Theme.getFont("action_button")
  377. text: control.text;
  378. }
  379. }
  380. label: Item
  381. {
  382. }
  383. }
  384. onClicked:
  385. {
  386. connectedPrinter.preheatBed(preheatTemperatureInput.text, 900);
  387. var now = new Date();
  388. var end_time = new Date();
  389. end_time.setTime(now.getTime() + 900 * 1000); //*1000 because time is in milliseconds here.
  390. preheatCountdownTimer.endTime = end_time;
  391. preheatCountdownTimer.start();
  392. preheatCountdownTimer.update(); //Update once before the first timer is triggered.
  393. }
  394. }
  395. }
  396. UM.SettingPropertyProvider
  397. {
  398. id: bedTemperature
  399. containerStackId: Cura.MachineManager.activeMachineId
  400. key: "material_bed_temperature"
  401. watchedProperties: ["value", "minimum_value", "maximum_value", "minimum_value_warning", "maximum_value_warning", "resolve"]
  402. storeIndex: 0
  403. property var resolve: Cura.MachineManager.activeStackId != Cura.MachineManager.activeMachineId ? properties.resolve : "None"
  404. }
  405. Loader
  406. {
  407. sourceComponent: monitorSection
  408. property string label: catalog.i18nc("@label", "Active print")
  409. }
  410. Loader
  411. {
  412. sourceComponent: monitorItem
  413. property string label: catalog.i18nc("@label", "Job Name")
  414. property string value: printerConnected ? connectedPrinter.jobName : ""
  415. }
  416. Loader
  417. {
  418. sourceComponent: monitorItem
  419. property string label: catalog.i18nc("@label", "Printing Time")
  420. property string value: printerConnected ? getPrettyTime(connectedPrinter.timeTotal) : ""
  421. }
  422. Loader
  423. {
  424. sourceComponent: monitorItem
  425. property string label: catalog.i18nc("@label", "Estimated time left")
  426. property string value: printerConnected ? getPrettyTime(connectedPrinter.timeTotal - connectedPrinter.timeElapsed) : ""
  427. }
  428. Component
  429. {
  430. id: monitorItem
  431. Row
  432. {
  433. height: UM.Theme.getSize("setting_control").height
  434. width: base.width - 2 * UM.Theme.getSize("default_margin").width
  435. anchors.left: parent.left
  436. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  437. Label
  438. {
  439. width: parent.width * 0.4
  440. anchors.verticalCenter: parent.verticalCenter
  441. text: label
  442. color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
  443. font: UM.Theme.getFont("default")
  444. elide: Text.ElideRight
  445. }
  446. Label
  447. {
  448. width: parent.width * 0.6
  449. anchors.verticalCenter: parent.verticalCenter
  450. text: value
  451. color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
  452. font: UM.Theme.getFont("default")
  453. elide: Text.ElideRight
  454. }
  455. }
  456. }
  457. Component
  458. {
  459. id: monitorSection
  460. Rectangle
  461. {
  462. color: UM.Theme.getColor("setting_category")
  463. width: base.width - 2 * UM.Theme.getSize("default_margin").width
  464. height: UM.Theme.getSize("section").height
  465. Label
  466. {
  467. anchors.verticalCenter: parent.verticalCenter
  468. anchors.left: parent.left
  469. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  470. text: label
  471. font: UM.Theme.getFont("setting_category")
  472. color: UM.Theme.getColor("setting_category_text")
  473. }
  474. }
  475. }
  476. }