MonitorPrinterCard.qml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. // Copyright (c) 2018 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. border
  36. {
  37. color: UM.Theme.getColor("monitor_card_border")
  38. width: borderSize // TODO: Remove once themed
  39. }
  40. radius: 2 * screenScaleFactor // TODO: Theme!
  41. }
  42. // Printer portion
  43. Item
  44. {
  45. id: printerInfo
  46. width: parent.width
  47. height: 144 * screenScaleFactor // TODO: Theme!
  48. Row
  49. {
  50. anchors
  51. {
  52. left: parent.left
  53. leftMargin: 36 * screenScaleFactor // TODO: Theme!
  54. verticalCenter: parent.verticalCenter
  55. }
  56. spacing: 18 * screenScaleFactor // TODO: Theme!
  57. Rectangle
  58. {
  59. id: printerImage
  60. width: 108 * screenScaleFactor // TODO: Theme!
  61. height: 108 * screenScaleFactor // TODO: Theme!
  62. color: printer ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
  63. radius: 8 // TODO: Theme!
  64. Image
  65. {
  66. anchors.fill: parent
  67. fillMode: Image.PreserveAspectFit
  68. source: printer ? "../png/" + printer.type + ".png" : ""
  69. mipmap: true
  70. }
  71. }
  72. Item
  73. {
  74. anchors
  75. {
  76. verticalCenter: parent.verticalCenter
  77. }
  78. width: 180 * screenScaleFactor // TODO: Theme!
  79. height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
  80. Rectangle
  81. {
  82. id: printerNameLabel
  83. color: printer ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
  84. height: 18 * screenScaleFactor // TODO: Theme!
  85. width: parent.width
  86. radius: 2 * screenScaleFactor // TODO: Theme!
  87. Label
  88. {
  89. text: printer && printer.name ? printer.name : ""
  90. color: UM.Theme.getColor("monitor_text_primary")
  91. elide: Text.ElideRight
  92. font: UM.Theme.getFont("large") // 16pt, bold
  93. width: parent.width
  94. visible: printer
  95. // FIXED-LINE-HEIGHT:
  96. height: parent.height
  97. verticalAlignment: Text.AlignVCenter
  98. }
  99. }
  100. Rectangle
  101. {
  102. color: UM.Theme.getColor("monitor_skeleton_loading")
  103. height: 18 * screenScaleFactor // TODO: Theme!
  104. radius: 2 * screenScaleFactor // TODO: Theme!
  105. visible: !printer
  106. width: 48 * screenScaleFactor // TODO: Theme!
  107. }
  108. MonitorPrinterPill
  109. {
  110. id: printerFamilyPill
  111. anchors
  112. {
  113. top: printerNameLabel.bottom
  114. topMargin: 6 * screenScaleFactor // TODO: Theme!
  115. left: printerNameLabel.left
  116. }
  117. text: printer ? printer.type : ""
  118. }
  119. }
  120. MonitorPrinterConfiguration
  121. {
  122. id: printerConfiguration
  123. anchors.verticalCenter: parent.verticalCenter
  124. buildplate: printer ? "Glass" : null // 'Glass' as a default
  125. configurations:
  126. {
  127. var configs = []
  128. if (printer)
  129. {
  130. configs.push(printer.printerConfiguration.extruderConfigurations[0])
  131. configs.push(printer.printerConfiguration.extruderConfigurations[1])
  132. }
  133. else
  134. {
  135. configs.push(null, null)
  136. }
  137. return configs
  138. }
  139. height: 72 * screenScaleFactor // TODO: Theme!te theRect's x property
  140. }
  141. }
  142. MonitorContextMenuButton
  143. {
  144. id: contextMenuButton
  145. anchors
  146. {
  147. right: parent.right
  148. rightMargin: 12 * screenScaleFactor // TODO: Theme!
  149. top: parent.top
  150. topMargin: 12 * screenScaleFactor // TODO: Theme!
  151. }
  152. width: 36 * screenScaleFactor // TODO: Theme!
  153. height: 36 * screenScaleFactor // TODO: Theme!
  154. enabled: !cloudConnection
  155. onClicked: enabled ? contextMenu.switchPopupState() : {}
  156. visible:
  157. {
  158. if (!printer || !printer.activePrintJob) {
  159. return false
  160. }
  161. var states = ["queued", "error", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"]
  162. return states.indexOf(printer.activePrintJob.state) !== -1
  163. }
  164. }
  165. MonitorContextMenu
  166. {
  167. id: contextMenu
  168. printJob: printer ? printer.activePrintJob : null
  169. target: contextMenuButton
  170. }
  171. // For cloud printing, add this mouse area over the disabled contextButton to indicate that it's not available
  172. MouseArea
  173. {
  174. id: contextMenuDisabledButtonArea
  175. anchors.fill: contextMenuButton
  176. hoverEnabled: contextMenuButton.visible && !contextMenuButton.enabled
  177. onEntered: contextMenuDisabledInfo.open()
  178. onExited: contextMenuDisabledInfo.close()
  179. enabled: !contextMenuButton.enabled
  180. }
  181. MonitorInfoBlurb
  182. {
  183. id: contextMenuDisabledInfo
  184. text: catalog.i18nc("@info", "These options are not available because you are monitoring a cloud printer.")
  185. target: contextMenuButton
  186. }
  187. CameraButton
  188. {
  189. id: cameraButton
  190. anchors
  191. {
  192. right: parent.right
  193. rightMargin: 20 * screenScaleFactor // TODO: Theme!
  194. bottom: parent.bottom
  195. bottomMargin: 20 * screenScaleFactor // TODO: Theme!
  196. }
  197. iconSource: "../svg/icons/camera.svg"
  198. enabled: !cloudConnection
  199. visible: printer
  200. }
  201. // For cloud printing, add this mouse area over the disabled cameraButton to indicate that it's not available
  202. MouseArea
  203. {
  204. id: cameraDisabledButtonArea
  205. anchors.fill: cameraButton
  206. hoverEnabled: cameraButton.visible && !cameraButton.enabled
  207. onEntered: cameraDisabledInfo.open()
  208. onExited: cameraDisabledInfo.close()
  209. enabled: !cameraButton.enabled
  210. }
  211. MonitorInfoBlurb
  212. {
  213. id: cameraDisabledInfo
  214. text: catalog.i18nc("@info", "The webcam is not available because you are monitoring a cloud printer.")
  215. target: cameraButton
  216. }
  217. }
  218. // Divider
  219. Rectangle
  220. {
  221. anchors
  222. {
  223. top: printJobInfo.top
  224. left: printJobInfo.left
  225. right: printJobInfo.right
  226. }
  227. height: borderSize // Remove once themed
  228. color: background.border.color
  229. }
  230. // Print job portion
  231. Rectangle
  232. {
  233. id: printJobInfo
  234. anchors
  235. {
  236. top: printerInfo.bottom
  237. topMargin: -borderSize * screenScaleFactor // TODO: Theme!
  238. }
  239. border
  240. {
  241. color: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? UM.Theme.getColor("warning") : "transparent" // TODO: Theme!
  242. width: borderSize // TODO: Remove once themed
  243. }
  244. color: "transparent" // TODO: Theme!
  245. height: 84 * screenScaleFactor + borderSize // TODO: Remove once themed
  246. width: parent.width
  247. Row
  248. {
  249. anchors
  250. {
  251. fill: parent
  252. topMargin: 12 * screenScaleFactor + borderSize // TODO: Theme!
  253. bottomMargin: 12 * screenScaleFactor // TODO: Theme!
  254. leftMargin: 36 * screenScaleFactor // TODO: Theme!
  255. }
  256. height: childrenRect.height
  257. spacing: 18 * screenScaleFactor // TODO: Theme!
  258. Label
  259. {
  260. id: printerStatus
  261. anchors
  262. {
  263. verticalCenter: parent.verticalCenter
  264. }
  265. color: printer ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
  266. font: UM.Theme.getFont("large_bold") // 16pt, bold
  267. text: {
  268. if (!printer) {
  269. return catalog.i18nc("@label:status", "Loading...")
  270. }
  271. if (printer && printer.state == "disabled")
  272. {
  273. return catalog.i18nc("@label:status", "Unavailable")
  274. }
  275. if (printer && printer.state == "unreachable")
  276. {
  277. return catalog.i18nc("@label:status", "Unreachable")
  278. }
  279. if (printer && !printer.activePrintJob && printer.state == "idle")
  280. {
  281. return catalog.i18nc("@label:status", "Idle")
  282. }
  283. return ""
  284. }
  285. visible: text !== ""
  286. }
  287. Item
  288. {
  289. anchors
  290. {
  291. verticalCenter: parent.verticalCenter
  292. }
  293. width: printerImage.width
  294. height: 60 * screenScaleFactor // TODO: Theme!
  295. MonitorPrintJobPreview
  296. {
  297. anchors.centerIn: parent
  298. printJob: printer ? printer.activePrintJob : null
  299. size: parent.height
  300. }
  301. visible: printer && printer.activePrintJob && !printerStatus.visible
  302. }
  303. Item
  304. {
  305. anchors
  306. {
  307. verticalCenter: parent.verticalCenter
  308. }
  309. width: 180 * screenScaleFactor // TODO: Theme!
  310. height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
  311. visible: printer && printer.activePrintJob && !printerStatus.visible
  312. Label
  313. {
  314. id: printerJobNameLabel
  315. color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
  316. elide: Text.ElideRight
  317. font: UM.Theme.getFont("large") // 16pt, bold
  318. text: printer && printer.activePrintJob ? printer.activePrintJob.name : catalog.i18nc("@label", "Untitled")
  319. width: parent.width
  320. // FIXED-LINE-HEIGHT:
  321. height: 18 * screenScaleFactor // TODO: Theme!
  322. verticalAlignment: Text.AlignVCenter
  323. }
  324. Label
  325. {
  326. id: printerJobOwnerLabel
  327. anchors
  328. {
  329. top: printerJobNameLabel.bottom
  330. topMargin: 6 * screenScaleFactor // TODO: Theme!
  331. left: printerJobNameLabel.left
  332. }
  333. color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
  334. elide: Text.ElideRight
  335. font: UM.Theme.getFont("default") // 12pt, regular
  336. text: printer && printer.activePrintJob ? printer.activePrintJob.owner : catalog.i18nc("@label", "Anonymous")
  337. width: parent.width
  338. // FIXED-LINE-HEIGHT:
  339. height: 18 * screenScaleFactor // TODO: Theme!
  340. verticalAlignment: Text.AlignVCenter
  341. }
  342. }
  343. MonitorPrintJobProgressBar
  344. {
  345. anchors
  346. {
  347. verticalCenter: parent.verticalCenter
  348. }
  349. printJob: printer && printer.activePrintJob
  350. visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length === 0 && !printerStatus.visible
  351. }
  352. Label
  353. {
  354. anchors
  355. {
  356. verticalCenter: parent.verticalCenter
  357. }
  358. font: UM.Theme.getFont("default")
  359. text: catalog.i18nc("@label:status", "Requires configuration changes")
  360. visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 && !printerStatus.visible
  361. color: UM.Theme.getColor("monitor_text_primary")
  362. // FIXED-LINE-HEIGHT:
  363. height: 18 * screenScaleFactor // TODO: Theme!
  364. verticalAlignment: Text.AlignVCenter
  365. }
  366. }
  367. Button
  368. {
  369. id: detailsButton
  370. anchors
  371. {
  372. verticalCenter: parent.verticalCenter
  373. right: parent.right
  374. rightMargin: 18 * screenScaleFactor // TODO: Theme!
  375. }
  376. background: Rectangle
  377. {
  378. color: UM.Theme.getColor("monitor_secondary_button_shadow")
  379. radius: 2 * screenScaleFactor // Todo: Theme!
  380. Rectangle
  381. {
  382. anchors.fill: parent
  383. anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
  384. color: detailsButton.hovered ? UM.Theme.getColor("monitor_secondary_button_hover") : UM.Theme.getColor("monitor_secondary_button")
  385. radius: 2 * screenScaleFactor // Todo: Theme!
  386. }
  387. }
  388. contentItem: Label
  389. {
  390. anchors.fill: parent
  391. anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
  392. color: UM.Theme.getColor("monitor_secondary_button_text")
  393. font: UM.Theme.getFont("medium") // 14pt, regular
  394. text: catalog.i18nc("@action:button","Details");
  395. verticalAlignment: Text.AlignVCenter
  396. horizontalAlignment: Text.AlignHCenter
  397. height: 18 * screenScaleFactor // TODO: Theme!
  398. }
  399. implicitHeight: 32 * screenScaleFactor // TODO: Theme!
  400. implicitWidth: 96 * screenScaleFactor // TODO: Theme!
  401. visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 && !printerStatus.visible
  402. onClicked: base.enabled ? overrideConfirmationDialog.open() : {}
  403. }
  404. }
  405. MonitorConfigOverrideDialog
  406. {
  407. id: overrideConfirmationDialog
  408. printer: base.printer
  409. }
  410. }