MonitorPrinterCard.qml 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. // Copyright (c) 2019 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.3
  4. import QtQuick.Controls 2.0
  5. import QtQuick.Dialogs 1.1
  6. import UM 1.3 as UM
  7. import Cura 1.0 as Cura
  8. /**
  9. * A Printer Card is has two main components: the printer portion and the print job portion, the latter being paired in
  10. * the UI when a print job is paired a printer in-cluster.
  11. *
  12. * NOTE: For most labels, a fixed height with vertical alignment is used to make layouts more deterministic (like the
  13. * fixed-size textboxes used in original mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
  14. * with '// FIXED-LINE-HEIGHT:'.
  15. */
  16. Item
  17. {
  18. id: base
  19. // The printer which all printer data is derived from
  20. property var printer: null
  21. property var borderSize: 1 * screenScaleFactor // TODO: Theme, and remove from here
  22. // If the printer card's controls are enabled. This is used by the carousel to prevent opening the context menu or
  23. // camera while the printer card is not "in focus"
  24. property var enabled: true
  25. // If the printer is a cloud printer or not. Other items base their enabled state off of this boolean. In the future
  26. // they might not need to though.
  27. property bool cloudConnection: Cura.MachineManager.activeMachineIsUsingCloudConnection
  28. width: 834 * screenScaleFactor // TODO: Theme!
  29. height: childrenRect.height
  30. Rectangle
  31. {
  32. id: background
  33. anchors.fill: parent
  34. // color: UM.Theme.getColor("monitor_card_background")
  35. color: "red"
  36. border
  37. {
  38. color: UM.Theme.getColor("monitor_card_border")
  39. width: borderSize // TODO: Remove once themed
  40. }
  41. radius: 2 * screenScaleFactor // TODO: Theme!
  42. }
  43. // Printer portion
  44. Item
  45. {
  46. id: printerInfo
  47. width: parent.width
  48. height: 144 * screenScaleFactor // TODO: Theme!
  49. Row
  50. {
  51. anchors
  52. {
  53. left: parent.left
  54. leftMargin: 36 * screenScaleFactor // TODO: Theme!
  55. verticalCenter: parent.verticalCenter
  56. }
  57. spacing: 18 * screenScaleFactor // TODO: Theme!
  58. Rectangle
  59. {
  60. id: printerImage
  61. width: 108 * screenScaleFactor // TODO: Theme!
  62. height: 108 * screenScaleFactor // TODO: Theme!
  63. color: printer ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
  64. radius: 8 // TODO: Theme!
  65. Image
  66. {
  67. anchors.fill: parent
  68. fillMode: Image.PreserveAspectFit
  69. source: printer ? "../png/" + printer.type + ".png" : ""
  70. mipmap: true
  71. }
  72. }
  73. Item
  74. {
  75. anchors
  76. {
  77. verticalCenter: parent.verticalCenter
  78. }
  79. width: 180 * screenScaleFactor // TODO: Theme!
  80. height: childrenRect.height
  81. Rectangle
  82. {
  83. id: printerNameLabel
  84. color: printer ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
  85. height: 18 * screenScaleFactor // TODO: Theme!
  86. width: parent.width
  87. radius: 2 * screenScaleFactor // TODO: Theme!
  88. Label
  89. {
  90. text: printer && printer.name ? printer.name : ""
  91. color: UM.Theme.getColor("monitor_text_primary")
  92. elide: Text.ElideRight
  93. font: UM.Theme.getFont("large") // 16pt, bold
  94. width: parent.width
  95. visible: printer
  96. // FIXED-LINE-HEIGHT:
  97. height: parent.height
  98. verticalAlignment: Text.AlignVCenter
  99. renderType: Text.NativeRendering
  100. }
  101. }
  102. Rectangle
  103. {
  104. color: UM.Theme.getColor("monitor_skeleton_loading")
  105. height: 18 * screenScaleFactor // TODO: Theme!
  106. radius: 2 * screenScaleFactor // TODO: Theme!
  107. visible: !printer
  108. width: 48 * screenScaleFactor // TODO: Theme!
  109. }
  110. MonitorPrinterPill
  111. {
  112. id: printerFamilyPill
  113. anchors
  114. {
  115. top: printerNameLabel.bottom
  116. topMargin: 6 * screenScaleFactor // TODO: Theme!
  117. left: printerNameLabel.left
  118. }
  119. text: printer ? printer.type : ""
  120. }
  121. Item
  122. {
  123. id: managePrinterLink
  124. anchors {
  125. top: printerFamilyPill.bottom
  126. topMargin: 6 * screenScaleFactor
  127. }
  128. height: 18 * screenScaleFactor // TODO: Theme!
  129. width: childrenRect.width
  130. Label
  131. {
  132. id: managePrinterText
  133. anchors.verticalCenter: managePrinterLink.verticalCenter
  134. color: UM.Theme.getColor("monitor_text_link")
  135. font: UM.Theme.getFont("default")
  136. linkColor: UM.Theme.getColor("monitor_text_link")
  137. text: catalog.i18nc("@label link to Connect and Cloud interfaces", "Manage printer")
  138. renderType: Text.NativeRendering
  139. }
  140. UM.RecolorImage
  141. {
  142. id: externalLinkIcon
  143. anchors
  144. {
  145. left: managePrinterText.right
  146. leftMargin: 6 * screenScaleFactor
  147. verticalCenter: managePrinterText.verticalCenter
  148. }
  149. color: UM.Theme.getColor("monitor_text_link")
  150. source: UM.Theme.getIcon("external_link")
  151. width: 12 * screenScaleFactor
  152. height: 12 * screenScaleFactor
  153. }
  154. }
  155. MouseArea
  156. {
  157. anchors.fill: managePrinterLink
  158. onClicked: OutputDevice.openPrintJobControlPanel()
  159. onEntered:
  160. {
  161. manageQueueText.font.underline = true
  162. }
  163. onExited:
  164. {
  165. manageQueueText.font.underline = false
  166. }
  167. }
  168. }
  169. MonitorPrinterConfiguration
  170. {
  171. id: printerConfiguration
  172. anchors.verticalCenter: parent.verticalCenter
  173. buildplate: printer ? catalog.i18nc("@label", "Glass") : null // 'Glass' as a default
  174. configurations:
  175. {
  176. var configs = []
  177. if (printer)
  178. {
  179. configs.push(printer.printerConfiguration.extruderConfigurations[0])
  180. configs.push(printer.printerConfiguration.extruderConfigurations[1])
  181. }
  182. else
  183. {
  184. configs.push(null, null)
  185. }
  186. return configs
  187. }
  188. height: 72 * screenScaleFactor // TODO: Theme!te theRect's x property
  189. }
  190. }
  191. MonitorContextMenuButton
  192. {
  193. id: contextMenuButton
  194. anchors
  195. {
  196. right: parent.right
  197. rightMargin: 12 * screenScaleFactor // TODO: Theme!
  198. top: parent.top
  199. topMargin: 12 * screenScaleFactor // TODO: Theme!
  200. }
  201. width: 36 * screenScaleFactor // TODO: Theme!
  202. height: 36 * screenScaleFactor // TODO: Theme!
  203. enabled: OutputDevice.supportsPrintJobActions
  204. onClicked: enabled ? contextMenu.switchPopupState() : {}
  205. visible:
  206. {
  207. if (!printer || !printer.activePrintJob) {
  208. return false
  209. }
  210. var states = ["queued", "error", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"]
  211. return states.indexOf(printer.activePrintJob.state) !== -1
  212. }
  213. }
  214. MonitorContextMenu
  215. {
  216. id: contextMenu
  217. printJob: printer ? printer.activePrintJob : null
  218. target: contextMenuButton
  219. }
  220. // For cloud printing, add this mouse area over the disabled contextButton to indicate that it's not available
  221. MouseArea
  222. {
  223. id: contextMenuDisabledButtonArea
  224. anchors.fill: contextMenuButton
  225. hoverEnabled: contextMenuButton.visible && !contextMenuButton.enabled
  226. onEntered: contextMenuDisabledInfo.open()
  227. onExited: contextMenuDisabledInfo.close()
  228. enabled: !contextMenuButton.enabled
  229. }
  230. // TODO: uncomment this tooltip as soon as the required firmware is released
  231. // MonitorInfoBlurb
  232. // {
  233. // id: contextMenuDisabledInfo
  234. // text: catalog.i18nc("@info", "Please update your printer's firmware to manage the queue remotely.")
  235. // target: contextMenuButton
  236. // }
  237. CameraButton
  238. {
  239. id: cameraButton
  240. anchors
  241. {
  242. right: parent.right
  243. rightMargin: 20 * screenScaleFactor // TODO: Theme!
  244. bottom: parent.bottom
  245. bottomMargin: 20 * screenScaleFactor // TODO: Theme!
  246. }
  247. iconSource: "../svg/icons/camera.svg"
  248. enabled: !cloudConnection
  249. visible: printer
  250. }
  251. // For cloud printing, add this mouse area over the disabled cameraButton to indicate that it's not available
  252. MouseArea
  253. {
  254. id: cameraDisabledButtonArea
  255. anchors.fill: cameraButton
  256. hoverEnabled: cameraButton.visible && !cameraButton.enabled
  257. onEntered: cameraDisabledInfo.open()
  258. onExited: cameraDisabledInfo.close()
  259. enabled: !cameraButton.enabled
  260. }
  261. MonitorInfoBlurb
  262. {
  263. id: cameraDisabledInfo
  264. text: catalog.i18nc("@info", "The webcam is not available because you are monitoring a cloud printer.")
  265. target: cameraButton
  266. }
  267. }
  268. // Divider
  269. Rectangle
  270. {
  271. anchors
  272. {
  273. top: printJobInfo.top
  274. left: printJobInfo.left
  275. right: printJobInfo.right
  276. }
  277. height: borderSize // Remove once themed
  278. color: background.border.color
  279. }
  280. // Print job portion
  281. Rectangle
  282. {
  283. id: printJobInfo
  284. anchors
  285. {
  286. top: printerInfo.bottom
  287. topMargin: -borderSize * screenScaleFactor // TODO: Theme!
  288. }
  289. border
  290. {
  291. color: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? UM.Theme.getColor("warning") : "transparent" // TODO: Theme!
  292. width: borderSize // TODO: Remove once themed
  293. }
  294. color: "transparent" // TODO: Theme!
  295. height: 84 * screenScaleFactor + borderSize // TODO: Remove once themed
  296. width: parent.width
  297. Row
  298. {
  299. anchors
  300. {
  301. fill: parent
  302. topMargin: 12 * screenScaleFactor + borderSize // TODO: Theme!
  303. bottomMargin: 12 * screenScaleFactor // TODO: Theme!
  304. leftMargin: 36 * screenScaleFactor // TODO: Theme!
  305. }
  306. height: childrenRect.height
  307. spacing: 18 * screenScaleFactor // TODO: Theme!
  308. Label
  309. {
  310. id: printerStatus
  311. anchors
  312. {
  313. verticalCenter: parent.verticalCenter
  314. }
  315. color: printer ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
  316. font: UM.Theme.getFont("large_bold") // 16pt, bold
  317. text: {
  318. if (!printer) {
  319. return catalog.i18nc("@label:status", "Loading...")
  320. }
  321. if (printer && printer.state == "disabled")
  322. {
  323. return catalog.i18nc("@label:status", "Unavailable")
  324. }
  325. if (printer && printer.state == "unreachable")
  326. {
  327. return catalog.i18nc("@label:status", "Unreachable")
  328. }
  329. if (printer && !printer.activePrintJob && printer.state == "idle")
  330. {
  331. return catalog.i18nc("@label:status", "Idle")
  332. }
  333. return ""
  334. }
  335. visible: text !== ""
  336. renderType: Text.NativeRendering
  337. }
  338. Item
  339. {
  340. anchors
  341. {
  342. verticalCenter: parent.verticalCenter
  343. }
  344. width: printerImage.width
  345. height: 60 * screenScaleFactor // TODO: Theme!
  346. MonitorPrintJobPreview
  347. {
  348. anchors.centerIn: parent
  349. printJob: printer ? printer.activePrintJob : null
  350. size: parent.height
  351. }
  352. visible: printer && printer.activePrintJob && !printerStatus.visible
  353. }
  354. Item
  355. {
  356. anchors
  357. {
  358. verticalCenter: parent.verticalCenter
  359. }
  360. width: 180 * screenScaleFactor // TODO: Theme!
  361. height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
  362. visible: printer && printer.activePrintJob && !printerStatus.visible
  363. Label
  364. {
  365. id: printerJobNameLabel
  366. color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
  367. elide: Text.ElideRight
  368. font: UM.Theme.getFont("large") // 16pt, bold
  369. text: printer && printer.activePrintJob ? printer.activePrintJob.name : catalog.i18nc("@label", "Untitled")
  370. width: parent.width
  371. // FIXED-LINE-HEIGHT:
  372. height: 18 * screenScaleFactor // TODO: Theme!
  373. verticalAlignment: Text.AlignVCenter
  374. renderType: Text.NativeRendering
  375. }
  376. Label
  377. {
  378. id: printerJobOwnerLabel
  379. anchors
  380. {
  381. top: printerJobNameLabel.bottom
  382. topMargin: 6 * screenScaleFactor // TODO: Theme!
  383. left: printerJobNameLabel.left
  384. }
  385. color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
  386. elide: Text.ElideRight
  387. font: UM.Theme.getFont("default") // 12pt, regular
  388. text: printer && printer.activePrintJob ? printer.activePrintJob.owner : catalog.i18nc("@label", "Anonymous")
  389. width: parent.width
  390. // FIXED-LINE-HEIGHT:
  391. height: 18 * screenScaleFactor // TODO: Theme!
  392. verticalAlignment: Text.AlignVCenter
  393. renderType: Text.NativeRendering
  394. }
  395. }
  396. MonitorPrintJobProgressBar
  397. {
  398. anchors
  399. {
  400. verticalCenter: parent.verticalCenter
  401. }
  402. printJob: printer && printer.activePrintJob
  403. visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length === 0 && !printerStatus.visible
  404. }
  405. Label
  406. {
  407. anchors
  408. {
  409. verticalCenter: parent.verticalCenter
  410. }
  411. font: UM.Theme.getFont("default")
  412. text: catalog.i18nc("@label:status", "Requires configuration changes")
  413. visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 && !printerStatus.visible
  414. color: UM.Theme.getColor("monitor_text_primary")
  415. // FIXED-LINE-HEIGHT:
  416. height: 18 * screenScaleFactor // TODO: Theme!
  417. verticalAlignment: Text.AlignVCenter
  418. renderType: Text.NativeRendering
  419. }
  420. }
  421. Button
  422. {
  423. id: detailsButton
  424. anchors
  425. {
  426. verticalCenter: parent.verticalCenter
  427. right: parent.right
  428. rightMargin: 18 * screenScaleFactor // TODO: Theme!
  429. }
  430. background: Rectangle
  431. {
  432. color: UM.Theme.getColor("monitor_secondary_button_shadow")
  433. radius: 2 * screenScaleFactor // Todo: Theme!
  434. Rectangle
  435. {
  436. anchors.fill: parent
  437. anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
  438. color: detailsButton.hovered ? UM.Theme.getColor("monitor_secondary_button_hover") : UM.Theme.getColor("monitor_secondary_button")
  439. radius: 2 * screenScaleFactor // Todo: Theme!
  440. }
  441. }
  442. contentItem: Label
  443. {
  444. anchors.fill: parent
  445. anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
  446. color: UM.Theme.getColor("monitor_secondary_button_text")
  447. font: UM.Theme.getFont("medium") // 14pt, regular
  448. text: catalog.i18nc("@action:button","Details");
  449. verticalAlignment: Text.AlignVCenter
  450. horizontalAlignment: Text.AlignHCenter
  451. height: 18 * screenScaleFactor // TODO: Theme!
  452. renderType: Text.NativeRendering
  453. }
  454. implicitHeight: 32 * screenScaleFactor // TODO: Theme!
  455. implicitWidth: 96 * screenScaleFactor // TODO: Theme!
  456. visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 && !printerStatus.visible
  457. onClicked: base.enabled ? overrideConfirmationDialog.open() : {}
  458. }
  459. }
  460. MonitorConfigOverrideDialog
  461. {
  462. id: overrideConfirmationDialog
  463. printer: base.printer
  464. }
  465. }