PrintMonitor.qml 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  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. Column
  10. {
  11. id: printMonitor
  12. property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? 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: Math.floor(childrenRect.height + UM.Theme.getSize("default_margin").height * 2)
  23. color: UM.Theme.getColor("setting_category")
  24. Label
  25. {
  26. id: connectedPrinterNameLabel
  27. font: UM.Theme.getFont("large")
  28. color: UM.Theme.getColor("text")
  29. anchors.left: parent.left
  30. anchors.top: parent.top
  31. anchors.margins: UM.Theme.getSize("default_margin").width
  32. text: connectedPrinter != null ? connectedPrinter.name : catalog.i18nc("@info:status", "No printer connected")
  33. }
  34. Label
  35. {
  36. id: connectedPrinterAddressLabel
  37. text: (connectedPrinter != null && connectedPrinter.address != null) ? connectedPrinter.address : ""
  38. font: UM.Theme.getFont("small")
  39. color: UM.Theme.getColor("text_inactive")
  40. anchors.top: parent.top
  41. anchors.right: parent.right
  42. anchors.margins: UM.Theme.getSize("default_margin").width
  43. }
  44. Label
  45. {
  46. text: connectedPrinter != null ? connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.")
  47. color: connectedPrinter != null && connectedPrinter.acceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
  48. font: UM.Theme.getFont("very_small")
  49. wrapMode: Text.WordWrap
  50. anchors.left: parent.left
  51. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  52. anchors.right: parent.right
  53. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  54. anchors.top: connectedPrinterNameLabel.bottom
  55. }
  56. }
  57. Rectangle
  58. {
  59. color: UM.Theme.getColor("sidebar_lining")
  60. width: parent.width
  61. height: childrenRect.height
  62. Flow
  63. {
  64. id: extrudersGrid
  65. spacing: UM.Theme.getSize("sidebar_lining_thin").width
  66. width: parent.width
  67. Repeater
  68. {
  69. id: extrudersRepeater
  70. model: machineExtruderCount.properties.value
  71. delegate: Rectangle
  72. {
  73. id: extruderRectangle
  74. color: UM.Theme.getColor("sidebar")
  75. width: index == machineExtruderCount.properties.value - 1 && index % 2 == 0 ? extrudersGrid.width : Math.floor(extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2)
  76. height: UM.Theme.getSize("sidebar_extruder_box").height
  77. Label //Extruder name.
  78. {
  79. text: Cura.ExtruderManager.getExtruderName(index) != "" ? Cura.ExtruderManager.getExtruderName(index) : catalog.i18nc("@label", "Extruder")
  80. color: UM.Theme.getColor("text")
  81. font: UM.Theme.getFont("default")
  82. anchors.left: parent.left
  83. anchors.top: parent.top
  84. anchors.margins: UM.Theme.getSize("default_margin").width
  85. }
  86. Label //Target temperature.
  87. {
  88. id: extruderTargetTemperature
  89. text: (connectedPrinter != null && connectedPrinter.hotendIds[index] != null && connectedPrinter.targetHotendTemperatures[index] != null) ? Math.round(connectedPrinter.targetHotendTemperatures[index]) + "°C" : ""
  90. font: UM.Theme.getFont("small")
  91. color: UM.Theme.getColor("text_inactive")
  92. anchors.right: parent.right
  93. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  94. anchors.bottom: extruderTemperature.bottom
  95. MouseArea //For tooltip.
  96. {
  97. id: extruderTargetTemperatureTooltipArea
  98. hoverEnabled: true
  99. anchors.fill: parent
  100. onHoveredChanged:
  101. {
  102. if (containsMouse)
  103. {
  104. base.showTooltip(
  105. base,
  106. {x: 0, y: extruderTargetTemperature.mapToItem(base, 0, -parent.height / 4).y},
  107. catalog.i18nc("@tooltip", "The target temperature of the hotend. The hotend will heat up or cool down towards this temperature. If this is 0, the hotend heating is turned off.")
  108. );
  109. }
  110. else
  111. {
  112. base.hideTooltip();
  113. }
  114. }
  115. }
  116. }
  117. Label //Temperature indication.
  118. {
  119. id: extruderTemperature
  120. text: (connectedPrinter != null && connectedPrinter.hotendIds[index] != null && connectedPrinter.hotendTemperatures[index] != null) ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : ""
  121. color: UM.Theme.getColor("text")
  122. font: UM.Theme.getFont("large")
  123. anchors.right: extruderTargetTemperature.left
  124. anchors.top: parent.top
  125. anchors.margins: UM.Theme.getSize("default_margin").width
  126. MouseArea //For tooltip.
  127. {
  128. id: extruderTemperatureTooltipArea
  129. hoverEnabled: true
  130. anchors.fill: parent
  131. onHoveredChanged:
  132. {
  133. if (containsMouse)
  134. {
  135. base.showTooltip(
  136. base,
  137. {x: 0, y: parent.mapToItem(base, 0, -parent.height / 4).y},
  138. catalog.i18nc("@tooltip", "The current temperature of this extruder.")
  139. );
  140. }
  141. else
  142. {
  143. base.hideTooltip();
  144. }
  145. }
  146. }
  147. }
  148. Rectangle //Material colour indication.
  149. {
  150. id: materialColor
  151. width: Math.floor(materialName.height * 0.75)
  152. height: Math.floor(materialName.height * 0.75)
  153. radius: width / 2
  154. color: (connectedPrinter != null && connectedPrinter.materialColors[index] != null && connectedPrinter.materialIds[index] != "") ? connectedPrinter.materialColors[index] : "#00000000"
  155. border.width: UM.Theme.getSize("default_lining").width
  156. border.color: UM.Theme.getColor("lining")
  157. visible: connectedPrinter != null && connectedPrinter.materialColors[index] != null && connectedPrinter.materialIds[index] != ""
  158. anchors.left: parent.left
  159. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  160. anchors.verticalCenter: materialName.verticalCenter
  161. MouseArea //For tooltip.
  162. {
  163. id: materialColorTooltipArea
  164. hoverEnabled: true
  165. anchors.fill: parent
  166. onHoveredChanged:
  167. {
  168. if (containsMouse)
  169. {
  170. base.showTooltip(
  171. base,
  172. {x: 0, y: parent.mapToItem(base, 0, -parent.height / 2).y},
  173. catalog.i18nc("@tooltip", "The colour of the material in this extruder.")
  174. );
  175. }
  176. else
  177. {
  178. base.hideTooltip();
  179. }
  180. }
  181. }
  182. }
  183. Label //Material name.
  184. {
  185. id: materialName
  186. text: (connectedPrinter != null && connectedPrinter.materialNames[index] != null && connectedPrinter.materialIds[index] != "") ? connectedPrinter.materialNames[index] : ""
  187. font: UM.Theme.getFont("default")
  188. color: UM.Theme.getColor("text")
  189. anchors.left: materialColor.right
  190. anchors.bottom: parent.bottom
  191. anchors.margins: UM.Theme.getSize("default_margin").width
  192. MouseArea //For tooltip.
  193. {
  194. id: materialNameTooltipArea
  195. hoverEnabled: true
  196. anchors.fill: parent
  197. onHoveredChanged:
  198. {
  199. if (containsMouse)
  200. {
  201. base.showTooltip(
  202. base,
  203. {x: 0, y: parent.mapToItem(base, 0, 0).y},
  204. catalog.i18nc("@tooltip", "The material in this extruder.")
  205. );
  206. }
  207. else
  208. {
  209. base.hideTooltip();
  210. }
  211. }
  212. }
  213. }
  214. Label //Variant name.
  215. {
  216. id: variantName
  217. text: (connectedPrinter != null && connectedPrinter.hotendIds[index] != null) ? connectedPrinter.hotendIds[index] : ""
  218. font: UM.Theme.getFont("default")
  219. color: UM.Theme.getColor("text")
  220. anchors.right: parent.right
  221. anchors.bottom: parent.bottom
  222. anchors.margins: UM.Theme.getSize("default_margin").width
  223. MouseArea //For tooltip.
  224. {
  225. id: variantNameTooltipArea
  226. hoverEnabled: true
  227. anchors.fill: parent
  228. onHoveredChanged:
  229. {
  230. if (containsMouse)
  231. {
  232. base.showTooltip(
  233. base,
  234. {x: 0, y: parent.mapToItem(base, 0, -parent.height / 4).y},
  235. catalog.i18nc("@tooltip", "The nozzle inserted in this extruder.")
  236. );
  237. }
  238. else
  239. {
  240. base.hideTooltip();
  241. }
  242. }
  243. }
  244. }
  245. }
  246. }
  247. }
  248. }
  249. Rectangle
  250. {
  251. color: UM.Theme.getColor("sidebar_lining")
  252. width: parent.width
  253. height: UM.Theme.getSize("sidebar_lining_thin").width
  254. }
  255. Rectangle
  256. {
  257. color: UM.Theme.getColor("sidebar")
  258. width: parent.width
  259. height: machineHeatedBed.properties.value == "True" ? UM.Theme.getSize("sidebar_extruder_box").height : 0
  260. visible: machineHeatedBed.properties.value == "True"
  261. Label //Build plate label.
  262. {
  263. text: catalog.i18nc("@label", "Build plate")
  264. font: UM.Theme.getFont("default")
  265. color: UM.Theme.getColor("text")
  266. anchors.left: parent.left
  267. anchors.top: parent.top
  268. anchors.margins: UM.Theme.getSize("default_margin").width
  269. }
  270. Label //Target temperature.
  271. {
  272. id: bedTargetTemperature
  273. text: connectedPrinter != null ? connectedPrinter.targetBedTemperature + "°C" : ""
  274. font: UM.Theme.getFont("small")
  275. color: UM.Theme.getColor("text_inactive")
  276. anchors.right: parent.right
  277. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  278. anchors.bottom: bedCurrentTemperature.bottom
  279. MouseArea //For tooltip.
  280. {
  281. id: bedTargetTemperatureTooltipArea
  282. hoverEnabled: true
  283. anchors.fill: parent
  284. onHoveredChanged:
  285. {
  286. if (containsMouse)
  287. {
  288. base.showTooltip(
  289. base,
  290. {x: 0, y: bedTargetTemperature.mapToItem(base, 0, -parent.height / 4).y},
  291. catalog.i18nc("@tooltip", "The target temperature of the heated bed. The bed will heat up or cool down towards this temperature. If this is 0, the bed heating is turned off.")
  292. );
  293. }
  294. else
  295. {
  296. base.hideTooltip();
  297. }
  298. }
  299. }
  300. }
  301. Label //Current temperature.
  302. {
  303. id: bedCurrentTemperature
  304. text: connectedPrinter != null ? connectedPrinter.bedTemperature + "°C" : ""
  305. font: UM.Theme.getFont("large")
  306. color: UM.Theme.getColor("text")
  307. anchors.right: bedTargetTemperature.left
  308. anchors.top: parent.top
  309. anchors.margins: UM.Theme.getSize("default_margin").width
  310. MouseArea //For tooltip.
  311. {
  312. id: bedTemperatureTooltipArea
  313. hoverEnabled: true
  314. anchors.fill: parent
  315. onHoveredChanged:
  316. {
  317. if (containsMouse)
  318. {
  319. base.showTooltip(
  320. base,
  321. {x: 0, y: bedCurrentTemperature.mapToItem(base, 0, -parent.height / 4).y},
  322. catalog.i18nc("@tooltip", "The current temperature of the heated bed.")
  323. );
  324. }
  325. else
  326. {
  327. base.hideTooltip();
  328. }
  329. }
  330. }
  331. }
  332. Rectangle //Input field for pre-heat temperature.
  333. {
  334. id: preheatTemperatureControl
  335. color: !enabled ? UM.Theme.getColor("setting_control_disabled") : showError ? UM.Theme.getColor("setting_validation_error_background") : UM.Theme.getColor("setting_validation_ok")
  336. property var showError:
  337. {
  338. if(bedTemperature.properties.maximum_value != "None" && bedTemperature.properties.maximum_value < Math.floor(preheatTemperatureInput.text))
  339. {
  340. return true;
  341. } else
  342. {
  343. return false;
  344. }
  345. }
  346. enabled:
  347. {
  348. if (connectedPrinter == null)
  349. {
  350. return false; //Can't preheat if not connected.
  351. }
  352. if (!connectedPrinter.acceptsCommands)
  353. {
  354. return false; //Not allowed to do anything.
  355. }
  356. if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "paused" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline")
  357. {
  358. return false; //Printer is in a state where it can't react to pre-heating.
  359. }
  360. return true;
  361. }
  362. border.width: UM.Theme.getSize("default_lining").width
  363. border.color: !enabled ? UM.Theme.getColor("setting_control_disabled_border") : preheatTemperatureInputMouseArea.containsMouse ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border")
  364. anchors.left: parent.left
  365. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  366. anchors.bottom: parent.bottom
  367. anchors.bottomMargin: UM.Theme.getSize("default_margin").height
  368. width: UM.Theme.getSize("setting_control").width
  369. height: UM.Theme.getSize("setting_control").height
  370. visible: connectedPrinter != null ? connectedPrinter.canPreHeatBed: true
  371. Rectangle //Highlight of input field.
  372. {
  373. anchors.fill: parent
  374. anchors.margins: UM.Theme.getSize("default_lining").width
  375. color: UM.Theme.getColor("setting_control_highlight")
  376. opacity: preheatTemperatureControl.hovered ? 1.0 : 0
  377. }
  378. Label //Maximum temperature indication.
  379. {
  380. text: (bedTemperature.properties.maximum_value != "None" ? bedTemperature.properties.maximum_value : "") + "°C"
  381. color: UM.Theme.getColor("setting_unit")
  382. font: UM.Theme.getFont("default")
  383. anchors.right: parent.right
  384. anchors.rightMargin: UM.Theme.getSize("setting_unit_margin").width
  385. anchors.verticalCenter: parent.verticalCenter
  386. }
  387. MouseArea //Change cursor on hovering.
  388. {
  389. id: preheatTemperatureInputMouseArea
  390. hoverEnabled: true
  391. anchors.fill: parent
  392. cursorShape: Qt.IBeamCursor
  393. onHoveredChanged:
  394. {
  395. if (containsMouse)
  396. {
  397. base.showTooltip(
  398. base,
  399. {x: 0, y: preheatTemperatureInputMouseArea.mapToItem(base, 0, 0).y},
  400. catalog.i18nc("@tooltip of temperature input", "The temperature to pre-heat the bed to.")
  401. );
  402. }
  403. else
  404. {
  405. base.hideTooltip();
  406. }
  407. }
  408. }
  409. TextInput
  410. {
  411. id: preheatTemperatureInput
  412. font: UM.Theme.getFont("default")
  413. color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text")
  414. selectByMouse: true
  415. maximumLength: 10
  416. enabled: parent.enabled
  417. validator: RegExpValidator { regExp: /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } //Floating point regex.
  418. anchors.left: parent.left
  419. anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width
  420. anchors.right: parent.right
  421. anchors.verticalCenter: parent.verticalCenter
  422. renderType: Text.NativeRendering
  423. Component.onCompleted:
  424. {
  425. if (!bedTemperature.properties.value)
  426. {
  427. text = "";
  428. }
  429. if ((bedTemperature.resolve != "None" && bedTemperature.resolve) && (bedTemperature.stackLevels[0] != 0) && (bedTemperature.stackLevels[0] != 1))
  430. {
  431. // We have a resolve function. Indicates that the setting is not settable per extruder and that
  432. // we have to choose between the resolved value (default) and the global value
  433. // (if user has explicitly set this).
  434. text = bedTemperature.resolve;
  435. }
  436. else
  437. {
  438. text = bedTemperature.properties.value;
  439. }
  440. }
  441. }
  442. }
  443. UM.RecolorImage
  444. {
  445. id: preheatCountdownIcon
  446. width: UM.Theme.getSize("save_button_specs_icons").width
  447. height: UM.Theme.getSize("save_button_specs_icons").height
  448. sourceSize.width: width
  449. sourceSize.height: height
  450. color: UM.Theme.getColor("text")
  451. visible: preheatCountdown.visible
  452. source: UM.Theme.getIcon("print_time")
  453. anchors.right: preheatCountdown.left
  454. anchors.rightMargin: Math.floor(UM.Theme.getSize("default_margin").width / 2)
  455. anchors.verticalCenter: preheatCountdown.verticalCenter
  456. }
  457. Timer
  458. {
  459. id: preheatUpdateTimer
  460. 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.
  461. running: connectedPrinter != null && connectedPrinter.preheatBedRemainingTime != ""
  462. repeat: true
  463. onTriggered: update()
  464. 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.
  465. function update()
  466. {
  467. preheatCountdown.text = ""
  468. if (connectedPrinter != null)
  469. {
  470. preheatCountdown.text = connectedPrinter.preheatBedRemainingTime;
  471. }
  472. if (preheatCountdown.text == "") //Either time elapsed or not connected.
  473. {
  474. stop();
  475. }
  476. }
  477. }
  478. Label
  479. {
  480. id: preheatCountdown
  481. text: connectedPrinter != null ? connectedPrinter.preheatBedRemainingTime : ""
  482. visible: text != "" //Has no direct effect, but just so that we can link visibility of clock icon to visibility of the countdown text.
  483. font: UM.Theme.getFont("default")
  484. color: UM.Theme.getColor("text")
  485. anchors.right: preheatButton.left
  486. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  487. anchors.verticalCenter: preheatButton.verticalCenter
  488. }
  489. Button //The pre-heat button.
  490. {
  491. id: preheatButton
  492. height: UM.Theme.getSize("setting_control").height
  493. visible: connectedPrinter != null ? connectedPrinter.canPreHeatBed: true
  494. enabled:
  495. {
  496. if (!preheatTemperatureControl.enabled)
  497. {
  498. return false; //Not connected, not authenticated or printer is busy.
  499. }
  500. if (preheatUpdateTimer.running)
  501. {
  502. return true; //Can always cancel if the timer is running.
  503. }
  504. if (bedTemperature.properties.minimum_value != "None" && Math.floor(preheatTemperatureInput.text) < Math.floor(bedTemperature.properties.minimum_value))
  505. {
  506. return false; //Target temperature too low.
  507. }
  508. if (bedTemperature.properties.maximum_value != "None" && Math.floor(preheatTemperatureInput.text) > Math.floor(bedTemperature.properties.maximum_value))
  509. {
  510. return false; //Target temperature too high.
  511. }
  512. if (Math.floor(preheatTemperatureInput.text) == 0)
  513. {
  514. return false; //Setting the temperature to 0 is not allowed (since that cancels the pre-heating).
  515. }
  516. return true; //Preconditions are met.
  517. }
  518. anchors.right: parent.right
  519. anchors.bottom: parent.bottom
  520. anchors.margins: UM.Theme.getSize("default_margin").width
  521. style: ButtonStyle {
  522. background: Rectangle
  523. {
  524. border.width: UM.Theme.getSize("default_lining").width
  525. implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("default_margin").width * 2)
  526. border.color:
  527. {
  528. if(!control.enabled)
  529. {
  530. return UM.Theme.getColor("action_button_disabled_border");
  531. }
  532. else if(control.pressed)
  533. {
  534. return UM.Theme.getColor("action_button_active_border");
  535. }
  536. else if(control.hovered)
  537. {
  538. return UM.Theme.getColor("action_button_hovered_border");
  539. }
  540. else
  541. {
  542. return UM.Theme.getColor("action_button_border");
  543. }
  544. }
  545. color:
  546. {
  547. if(!control.enabled)
  548. {
  549. return UM.Theme.getColor("action_button_disabled");
  550. }
  551. else if(control.pressed)
  552. {
  553. return UM.Theme.getColor("action_button_active");
  554. }
  555. else if(control.hovered)
  556. {
  557. return UM.Theme.getColor("action_button_hovered");
  558. }
  559. else
  560. {
  561. return UM.Theme.getColor("action_button");
  562. }
  563. }
  564. Behavior on color
  565. {
  566. ColorAnimation
  567. {
  568. duration: 50
  569. }
  570. }
  571. Label
  572. {
  573. id: actualLabel
  574. anchors.centerIn: parent
  575. color:
  576. {
  577. if(!control.enabled)
  578. {
  579. return UM.Theme.getColor("action_button_disabled_text");
  580. }
  581. else if(control.pressed)
  582. {
  583. return UM.Theme.getColor("action_button_active_text");
  584. }
  585. else if(control.hovered)
  586. {
  587. return UM.Theme.getColor("action_button_hovered_text");
  588. }
  589. else
  590. {
  591. return UM.Theme.getColor("action_button_text");
  592. }
  593. }
  594. font: UM.Theme.getFont("action_button")
  595. text: preheatUpdateTimer.running ? catalog.i18nc("@button Cancel pre-heating", "Cancel") : catalog.i18nc("@button", "Pre-heat")
  596. }
  597. }
  598. }
  599. onClicked:
  600. {
  601. if (!preheatUpdateTimer.running)
  602. {
  603. connectedPrinter.preheatBed(preheatTemperatureInput.text, connectedPrinter.preheatBedTimeout);
  604. preheatUpdateTimer.start();
  605. preheatUpdateTimer.update(); //Update once before the first timer is triggered.
  606. }
  607. else
  608. {
  609. connectedPrinter.cancelPreheatBed();
  610. preheatUpdateTimer.update();
  611. }
  612. }
  613. onHoveredChanged:
  614. {
  615. if (hovered)
  616. {
  617. base.showTooltip(
  618. base,
  619. {x: 0, y: preheatButton.mapToItem(base, 0, 0).y},
  620. 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.")
  621. );
  622. }
  623. else
  624. {
  625. base.hideTooltip();
  626. }
  627. }
  628. }
  629. }
  630. UM.SettingPropertyProvider
  631. {
  632. id: bedTemperature
  633. containerStackId: Cura.MachineManager.activeMachineId
  634. key: "material_bed_temperature"
  635. watchedProperties: ["value", "minimum_value", "maximum_value", "resolve"]
  636. storeIndex: 0
  637. property var resolve: Cura.MachineManager.activeStackId != Cura.MachineManager.activeMachineId ? properties.resolve : "None"
  638. }
  639. UM.SettingPropertyProvider
  640. {
  641. id: machineExtruderCount
  642. containerStackId: Cura.MachineManager.activeMachineId
  643. key: "machine_extruder_count"
  644. watchedProperties: ["value"]
  645. }
  646. Column
  647. {
  648. visible: connectedPrinter != null ? connectedPrinter.canControlManually : false
  649. enabled:
  650. {
  651. if (connectedPrinter == null)
  652. {
  653. return false; //Can't control the printer if not connected.
  654. }
  655. if (!connectedPrinter.acceptsCommands)
  656. {
  657. return false; //Not allowed to do anything.
  658. }
  659. if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline")
  660. {
  661. return false; //Printer is in a state where it can't react to manual control
  662. }
  663. return true;
  664. }
  665. Loader
  666. {
  667. sourceComponent: monitorSection
  668. property string label: catalog.i18nc("@label", "Printer control")
  669. }
  670. Row
  671. {
  672. width: base.width - 2 * UM.Theme.getSize("default_margin").width
  673. height: childrenRect.height + UM.Theme.getSize("default_margin").width
  674. anchors.left: parent.left
  675. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  676. spacing: UM.Theme.getSize("default_margin").width
  677. Label
  678. {
  679. text: catalog.i18nc("@label", "Jog Position")
  680. color: UM.Theme.getColor("setting_control_text")
  681. font: UM.Theme.getFont("default")
  682. width: Math.floor(parent.width * 0.4) - UM.Theme.getSize("default_margin").width
  683. height: UM.Theme.getSize("setting_control").height
  684. verticalAlignment: Text.AlignVCenter
  685. }
  686. GridLayout
  687. {
  688. columns: 3
  689. rows: 4
  690. rowSpacing: UM.Theme.getSize("default_lining").width
  691. columnSpacing: UM.Theme.getSize("default_lining").height
  692. Label
  693. {
  694. text: catalog.i18nc("@label", "X/Y")
  695. color: UM.Theme.getColor("setting_control_text")
  696. font: UM.Theme.getFont("default")
  697. width: height
  698. height: UM.Theme.getSize("setting_control").height
  699. verticalAlignment: Text.AlignVCenter
  700. horizontalAlignment: Text.AlignHCenter
  701. Layout.row: 1
  702. Layout.column: 2
  703. Layout.preferredWidth: width
  704. Layout.preferredHeight: height
  705. }
  706. Button
  707. {
  708. Layout.row: 2
  709. Layout.column: 2
  710. Layout.preferredWidth: width
  711. Layout.preferredHeight: height
  712. iconSource: UM.Theme.getIcon("arrow_top");
  713. style: monitorButtonStyle
  714. width: height
  715. height: UM.Theme.getSize("setting_control").height
  716. onClicked:
  717. {
  718. connectedPrinter.moveHead(0, distancesRow.currentDistance, 0)
  719. }
  720. }
  721. Button
  722. {
  723. Layout.row: 3
  724. Layout.column: 1
  725. Layout.preferredWidth: width
  726. Layout.preferredHeight: height
  727. iconSource: UM.Theme.getIcon("arrow_left");
  728. style: monitorButtonStyle
  729. width: height
  730. height: UM.Theme.getSize("setting_control").height
  731. onClicked:
  732. {
  733. connectedPrinter.moveHead(-distancesRow.currentDistance, 0, 0)
  734. }
  735. }
  736. Button
  737. {
  738. Layout.row: 3
  739. Layout.column: 3
  740. Layout.preferredWidth: width
  741. Layout.preferredHeight: height
  742. iconSource: UM.Theme.getIcon("arrow_right");
  743. style: monitorButtonStyle
  744. width: height
  745. height: UM.Theme.getSize("setting_control").height
  746. onClicked:
  747. {
  748. connectedPrinter.moveHead(distancesRow.currentDistance, 0, 0)
  749. }
  750. }
  751. Button
  752. {
  753. Layout.row: 4
  754. Layout.column: 2
  755. Layout.preferredWidth: width
  756. Layout.preferredHeight: height
  757. iconSource: UM.Theme.getIcon("arrow_bottom");
  758. style: monitorButtonStyle
  759. width: height
  760. height: UM.Theme.getSize("setting_control").height
  761. onClicked:
  762. {
  763. connectedPrinter.moveHead(0, -distancesRow.currentDistance, 0)
  764. }
  765. }
  766. Button
  767. {
  768. Layout.row: 3
  769. Layout.column: 2
  770. Layout.preferredWidth: width
  771. Layout.preferredHeight: height
  772. iconSource: UM.Theme.getIcon("home");
  773. style: monitorButtonStyle
  774. width: height
  775. height: UM.Theme.getSize("setting_control").height
  776. onClicked:
  777. {
  778. connectedPrinter.homeHead()
  779. }
  780. }
  781. }
  782. Column
  783. {
  784. spacing: UM.Theme.getSize("default_lining").height
  785. Label
  786. {
  787. text: catalog.i18nc("@label", "Z")
  788. color: UM.Theme.getColor("setting_control_text")
  789. font: UM.Theme.getFont("default")
  790. width: UM.Theme.getSize("section").height
  791. height: UM.Theme.getSize("setting_control").height
  792. verticalAlignment: Text.AlignVCenter
  793. horizontalAlignment: Text.AlignHCenter
  794. }
  795. Button
  796. {
  797. iconSource: UM.Theme.getIcon("arrow_top");
  798. style: monitorButtonStyle
  799. width: height
  800. height: UM.Theme.getSize("setting_control").height
  801. onClicked:
  802. {
  803. connectedPrinter.moveHead(0, 0, distancesRow.currentDistance)
  804. }
  805. }
  806. Button
  807. {
  808. iconSource: UM.Theme.getIcon("home");
  809. style: monitorButtonStyle
  810. width: height
  811. height: UM.Theme.getSize("setting_control").height
  812. onClicked:
  813. {
  814. connectedPrinter.homeBed()
  815. }
  816. }
  817. Button
  818. {
  819. iconSource: UM.Theme.getIcon("arrow_bottom");
  820. style: monitorButtonStyle
  821. width: height
  822. height: UM.Theme.getSize("setting_control").height
  823. onClicked:
  824. {
  825. connectedPrinter.moveHead(0, 0, -distancesRow.currentDistance)
  826. }
  827. }
  828. }
  829. }
  830. Row
  831. {
  832. id: distancesRow
  833. width: base.width - 2 * UM.Theme.getSize("default_margin").width
  834. height: childrenRect.height + UM.Theme.getSize("default_margin").width
  835. anchors.left: parent.left
  836. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  837. spacing: UM.Theme.getSize("default_margin").width
  838. property real currentDistance: 10
  839. Label
  840. {
  841. text: catalog.i18nc("@label", "Jog Distance")
  842. color: UM.Theme.getColor("setting_control_text")
  843. font: UM.Theme.getFont("default")
  844. width: Math.floor(parent.width * 0.4) - UM.Theme.getSize("default_margin").width
  845. height: UM.Theme.getSize("setting_control").height
  846. verticalAlignment: Text.AlignVCenter
  847. }
  848. Row
  849. {
  850. Repeater
  851. {
  852. model: distancesModel
  853. delegate: Button
  854. {
  855. height: UM.Theme.getSize("setting_control").height
  856. width: height + UM.Theme.getSize("default_margin").width
  857. text: model.label
  858. exclusiveGroup: distanceGroup
  859. checkable: true
  860. checked: distancesRow.currentDistance == model.value
  861. onClicked: distancesRow.currentDistance = model.value
  862. style: ButtonStyle {
  863. background: Rectangle {
  864. border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width
  865. border.color:
  866. {
  867. if(!control.enabled)
  868. {
  869. return UM.Theme.getColor("action_button_disabled_border");
  870. }
  871. else if (control.checked || control.pressed)
  872. {
  873. return UM.Theme.getColor("action_button_active_border");
  874. }
  875. else if(control.hovered)
  876. {
  877. return UM.Theme.getColor("action_button_hovered_border");
  878. }
  879. return UM.Theme.getColor("action_button_border");
  880. }
  881. color:
  882. {
  883. if(!control.enabled)
  884. {
  885. return UM.Theme.getColor("action_button_disabled");
  886. }
  887. else if (control.checked || control.pressed)
  888. {
  889. return UM.Theme.getColor("action_button_active");
  890. }
  891. else if (control.hovered)
  892. {
  893. return UM.Theme.getColor("action_button_hovered");
  894. }
  895. return UM.Theme.getColor("action_button");
  896. }
  897. Behavior on color { ColorAnimation { duration: 50; } }
  898. Label {
  899. anchors.left: parent.left
  900. anchors.right: parent.right
  901. anchors.verticalCenter: parent.verticalCenter
  902. anchors.leftMargin: UM.Theme.getSize("default_lining").width * 2
  903. anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2
  904. color:
  905. {
  906. if(!control.enabled)
  907. {
  908. return UM.Theme.getColor("action_button_disabled_text");
  909. }
  910. else if (control.checked || control.pressed)
  911. {
  912. return UM.Theme.getColor("action_button_active_text");
  913. }
  914. else if (control.hovered)
  915. {
  916. return UM.Theme.getColor("action_button_hovered_text");
  917. }
  918. return UM.Theme.getColor("action_button_text");
  919. }
  920. font: UM.Theme.getFont("default")
  921. text: control.text
  922. horizontalAlignment: Text.AlignHCenter
  923. elide: Text.ElideMiddle
  924. }
  925. }
  926. label: Item { }
  927. }
  928. }
  929. }
  930. }
  931. }
  932. ListModel
  933. {
  934. id: distancesModel
  935. ListElement { label: "0.1"; value: 0.1 }
  936. ListElement { label: "1"; value: 1 }
  937. ListElement { label: "10"; value: 10 }
  938. ListElement { label: "100"; value: 100 }
  939. }
  940. ExclusiveGroup { id: distanceGroup }
  941. }
  942. Loader
  943. {
  944. sourceComponent: monitorSection
  945. property string label: catalog.i18nc("@label", "Active print")
  946. }
  947. Loader
  948. {
  949. sourceComponent: monitorItem
  950. property string label: catalog.i18nc("@label", "Job Name")
  951. property string value: connectedPrinter != null ? connectedPrinter.jobName : ""
  952. }
  953. Loader
  954. {
  955. sourceComponent: monitorItem
  956. property string label: catalog.i18nc("@label", "Printing Time")
  957. property string value: connectedPrinter != null ? getPrettyTime(connectedPrinter.timeTotal) : ""
  958. }
  959. Loader
  960. {
  961. sourceComponent: monitorItem
  962. property string label: catalog.i18nc("@label", "Estimated time left")
  963. property string value: connectedPrinter != null ? getPrettyTime(connectedPrinter.timeTotal - connectedPrinter.timeElapsed) : ""
  964. visible: connectedPrinter != null && (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "paused")
  965. }
  966. Component
  967. {
  968. id: monitorItem
  969. Row
  970. {
  971. height: UM.Theme.getSize("setting_control").height
  972. width: Math.floor(base.width - 2 * UM.Theme.getSize("default_margin").width)
  973. anchors.left: parent.left
  974. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  975. Label
  976. {
  977. width: Math.floor(parent.width * 0.4)
  978. anchors.verticalCenter: parent.verticalCenter
  979. text: label
  980. color: connectedPrinter != null && connectedPrinter.acceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
  981. font: UM.Theme.getFont("default")
  982. elide: Text.ElideRight
  983. }
  984. Label
  985. {
  986. width: Math.floor(parent.width * 0.6)
  987. anchors.verticalCenter: parent.verticalCenter
  988. text: value
  989. color: connectedPrinter != null && connectedPrinter.acceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
  990. font: UM.Theme.getFont("default")
  991. elide: Text.ElideRight
  992. }
  993. }
  994. }
  995. Component
  996. {
  997. id: monitorSection
  998. Rectangle
  999. {
  1000. color: UM.Theme.getColor("setting_category")
  1001. width: base.width
  1002. height: UM.Theme.getSize("section").height
  1003. Label
  1004. {
  1005. anchors.verticalCenter: parent.verticalCenter
  1006. anchors.left: parent.left
  1007. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  1008. text: label
  1009. font: UM.Theme.getFont("setting_category")
  1010. color: UM.Theme.getColor("setting_category_text")
  1011. }
  1012. }
  1013. }
  1014. Component
  1015. {
  1016. id: monitorButtonStyle
  1017. ButtonStyle
  1018. {
  1019. background: Rectangle
  1020. {
  1021. border.width: UM.Theme.getSize("default_lining").width
  1022. border.color:
  1023. {
  1024. if(!control.enabled)
  1025. {
  1026. return UM.Theme.getColor("action_button_disabled_border");
  1027. }
  1028. else if(control.pressed)
  1029. {
  1030. return UM.Theme.getColor("action_button_active_border");
  1031. }
  1032. else if(control.hovered)
  1033. {
  1034. return UM.Theme.getColor("action_button_hovered_border");
  1035. }
  1036. return UM.Theme.getColor("action_button_border");
  1037. }
  1038. color:
  1039. {
  1040. if(!control.enabled)
  1041. {
  1042. return UM.Theme.getColor("action_button_disabled");
  1043. }
  1044. else if(control.pressed)
  1045. {
  1046. return UM.Theme.getColor("action_button_active");
  1047. }
  1048. else if(control.hovered)
  1049. {
  1050. return UM.Theme.getColor("action_button_hovered");
  1051. }
  1052. return UM.Theme.getColor("action_button");
  1053. }
  1054. Behavior on color
  1055. {
  1056. ColorAnimation
  1057. {
  1058. duration: 50
  1059. }
  1060. }
  1061. }
  1062. label: Item
  1063. {
  1064. UM.RecolorImage
  1065. {
  1066. anchors.verticalCenter: parent.verticalCenter
  1067. anchors.horizontalCenter: parent.horizontalCenter
  1068. width: Math.floor(control.width / 2)
  1069. height: Math.floor(control.height / 2)
  1070. sourceSize.width: width
  1071. sourceSize.height: width
  1072. color:
  1073. {
  1074. if(!control.enabled)
  1075. {
  1076. return UM.Theme.getColor("action_button_disabled_text");
  1077. }
  1078. else if(control.pressed)
  1079. {
  1080. return UM.Theme.getColor("action_button_active_text");
  1081. }
  1082. else if(control.hovered)
  1083. {
  1084. return UM.Theme.getColor("action_button_hovered_text");
  1085. }
  1086. return UM.Theme.getColor("action_button_text");
  1087. }
  1088. source: control.iconSource
  1089. }
  1090. }
  1091. }
  1092. }
  1093. }