ManualPrinterControl.qml 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. // Copyright (c) 2017 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.10
  4. import QtQuick.Controls 1.4
  5. import QtQuick.Controls.Styles 1.4
  6. import QtQuick.Layouts 1.3
  7. import UM 1.3 as UM
  8. import Cura 1.0 as Cura
  9. import "."
  10. Item
  11. {
  12. property var printerModel: null
  13. property var activePrintJob: printerModel != null ? printerModel.activePrintJob : null
  14. property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
  15. implicitWidth: parent.width
  16. implicitHeight: childrenRect.height
  17. Column
  18. {
  19. enabled:
  20. {
  21. if (printerModel == null)
  22. {
  23. return false; //Can't control the printer if not connected
  24. }
  25. if (!connectedDevice.acceptsCommands)
  26. {
  27. return false; //Not allowed to do anything.
  28. }
  29. if(activePrintJob == null)
  30. {
  31. return true
  32. }
  33. if (activePrintJob.state == "printing" || activePrintJob.state == "resuming" || activePrintJob.state == "pausing" || activePrintJob.state == "error" || activePrintJob.state == "offline")
  34. {
  35. return false; //Printer is in a state where it can't react to manual control
  36. }
  37. return true;
  38. }
  39. MonitorSection
  40. {
  41. label: catalog.i18nc("@label", "Printer control")
  42. width: base.width
  43. }
  44. Row
  45. {
  46. width: base.width - 2 * UM.Theme.getSize("default_margin").width
  47. height: childrenRect.height + UM.Theme.getSize("default_margin").width
  48. anchors.left: parent.left
  49. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  50. spacing: UM.Theme.getSize("default_margin").width
  51. Label
  52. {
  53. text: catalog.i18nc("@label", "Jog Position")
  54. color: UM.Theme.getColor("setting_control_text")
  55. font: UM.Theme.getFont("default")
  56. width: Math.floor(parent.width * 0.4) - UM.Theme.getSize("default_margin").width
  57. height: UM.Theme.getSize("setting_control").height
  58. verticalAlignment: Text.AlignVCenter
  59. }
  60. GridLayout
  61. {
  62. columns: 3
  63. rows: 4
  64. rowSpacing: UM.Theme.getSize("default_lining").width
  65. columnSpacing: UM.Theme.getSize("default_lining").height
  66. Label
  67. {
  68. text: catalog.i18nc("@label", "X/Y")
  69. color: UM.Theme.getColor("setting_control_text")
  70. font: UM.Theme.getFont("default")
  71. width: height
  72. height: UM.Theme.getSize("setting_control").height
  73. verticalAlignment: Text.AlignVCenter
  74. horizontalAlignment: Text.AlignHCenter
  75. Layout.row: 1
  76. Layout.column: 2
  77. Layout.preferredWidth: width
  78. Layout.preferredHeight: height
  79. }
  80. Button
  81. {
  82. Layout.row: 2
  83. Layout.column: 2
  84. Layout.preferredWidth: width
  85. Layout.preferredHeight: height
  86. iconSource: UM.Theme.getIcon("arrow_top");
  87. style: UM.Theme.styles.monitor_button_style
  88. width: height
  89. height: UM.Theme.getSize("setting_control").height
  90. onClicked:
  91. {
  92. printerModel.moveHead(0, distancesRow.currentDistance, 0)
  93. }
  94. }
  95. Button
  96. {
  97. Layout.row: 3
  98. Layout.column: 1
  99. Layout.preferredWidth: width
  100. Layout.preferredHeight: height
  101. iconSource: UM.Theme.getIcon("arrow_left");
  102. style: UM.Theme.styles.monitor_button_style
  103. width: height
  104. height: UM.Theme.getSize("setting_control").height
  105. onClicked:
  106. {
  107. printerModel.moveHead(-distancesRow.currentDistance, 0, 0)
  108. }
  109. }
  110. Button
  111. {
  112. Layout.row: 3
  113. Layout.column: 3
  114. Layout.preferredWidth: width
  115. Layout.preferredHeight: height
  116. iconSource: UM.Theme.getIcon("arrow_right");
  117. style: UM.Theme.styles.monitor_button_style
  118. width: height
  119. height: UM.Theme.getSize("setting_control").height
  120. onClicked:
  121. {
  122. printerModel.moveHead(distancesRow.currentDistance, 0, 0)
  123. }
  124. }
  125. Button
  126. {
  127. Layout.row: 4
  128. Layout.column: 2
  129. Layout.preferredWidth: width
  130. Layout.preferredHeight: height
  131. iconSource: UM.Theme.getIcon("arrow_bottom");
  132. style: UM.Theme.styles.monitor_button_style
  133. width: height
  134. height: UM.Theme.getSize("setting_control").height
  135. onClicked:
  136. {
  137. printerModel.moveHead(0, -distancesRow.currentDistance, 0)
  138. }
  139. }
  140. Button
  141. {
  142. Layout.row: 3
  143. Layout.column: 2
  144. Layout.preferredWidth: width
  145. Layout.preferredHeight: height
  146. iconSource: UM.Theme.getIcon("home");
  147. style: UM.Theme.styles.monitor_button_style
  148. width: height
  149. height: UM.Theme.getSize("setting_control").height
  150. onClicked:
  151. {
  152. printerModel.homeHead()
  153. }
  154. }
  155. }
  156. Column
  157. {
  158. spacing: UM.Theme.getSize("default_lining").height
  159. Label
  160. {
  161. text: catalog.i18nc("@label", "Z")
  162. color: UM.Theme.getColor("setting_control_text")
  163. font: UM.Theme.getFont("default")
  164. width: UM.Theme.getSize("section").height
  165. height: UM.Theme.getSize("setting_control").height
  166. verticalAlignment: Text.AlignVCenter
  167. horizontalAlignment: Text.AlignHCenter
  168. }
  169. Button
  170. {
  171. iconSource: UM.Theme.getIcon("arrow_top");
  172. style: UM.Theme.styles.monitor_button_style
  173. width: height
  174. height: UM.Theme.getSize("setting_control").height
  175. onClicked:
  176. {
  177. printerModel.moveHead(0, 0, distancesRow.currentDistance)
  178. }
  179. }
  180. Button
  181. {
  182. iconSource: UM.Theme.getIcon("home");
  183. style: UM.Theme.styles.monitor_button_style
  184. width: height
  185. height: UM.Theme.getSize("setting_control").height
  186. onClicked:
  187. {
  188. printerModel.homeBed()
  189. }
  190. }
  191. Button
  192. {
  193. iconSource: UM.Theme.getIcon("arrow_bottom");
  194. style: UM.Theme.styles.monitor_button_style
  195. width: height
  196. height: UM.Theme.getSize("setting_control").height
  197. onClicked:
  198. {
  199. printerModel.moveHead(0, 0, -distancesRow.currentDistance)
  200. }
  201. }
  202. }
  203. }
  204. Row
  205. {
  206. id: distancesRow
  207. width: base.width - 2 * UM.Theme.getSize("default_margin").width
  208. height: childrenRect.height + UM.Theme.getSize("default_margin").width
  209. anchors.left: parent.left
  210. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  211. spacing: UM.Theme.getSize("default_margin").width
  212. property real currentDistance: 10
  213. Label
  214. {
  215. text: catalog.i18nc("@label", "Jog Distance")
  216. color: UM.Theme.getColor("setting_control_text")
  217. font: UM.Theme.getFont("default")
  218. width: Math.floor(parent.width * 0.4) - UM.Theme.getSize("default_margin").width
  219. height: UM.Theme.getSize("setting_control").height
  220. verticalAlignment: Text.AlignVCenter
  221. }
  222. Row
  223. {
  224. Repeater
  225. {
  226. model: distancesModel
  227. delegate: Button
  228. {
  229. height: UM.Theme.getSize("setting_control").height
  230. width: height + UM.Theme.getSize("default_margin").width
  231. text: model.label
  232. exclusiveGroup: distanceGroup
  233. checkable: true
  234. checked: distancesRow.currentDistance == model.value
  235. onClicked: distancesRow.currentDistance = model.value
  236. style: ButtonStyle {
  237. background: Rectangle {
  238. border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width
  239. border.color:
  240. {
  241. if(!control.enabled)
  242. {
  243. return UM.Theme.getColor("action_button_disabled_border");
  244. }
  245. else if (control.checked || control.pressed)
  246. {
  247. return UM.Theme.getColor("action_button_active_border");
  248. }
  249. else if(control.hovered)
  250. {
  251. return UM.Theme.getColor("action_button_hovered_border");
  252. }
  253. return UM.Theme.getColor("action_button_border");
  254. }
  255. color:
  256. {
  257. if(!control.enabled)
  258. {
  259. return UM.Theme.getColor("action_button_disabled");
  260. }
  261. else if (control.checked || control.pressed)
  262. {
  263. return UM.Theme.getColor("action_button_active");
  264. }
  265. else if (control.hovered)
  266. {
  267. return UM.Theme.getColor("action_button_hovered");
  268. }
  269. return UM.Theme.getColor("action_button");
  270. }
  271. Behavior on color { ColorAnimation { duration: 50; } }
  272. Label {
  273. anchors.left: parent.left
  274. anchors.right: parent.right
  275. anchors.verticalCenter: parent.verticalCenter
  276. anchors.leftMargin: UM.Theme.getSize("default_lining").width * 2
  277. anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2
  278. color:
  279. {
  280. if(!control.enabled)
  281. {
  282. return UM.Theme.getColor("action_button_disabled_text");
  283. }
  284. else if (control.checked || control.pressed)
  285. {
  286. return UM.Theme.getColor("action_button_active_text");
  287. }
  288. else if (control.hovered)
  289. {
  290. return UM.Theme.getColor("action_button_hovered_text");
  291. }
  292. return UM.Theme.getColor("action_button_text");
  293. }
  294. font: UM.Theme.getFont("default")
  295. text: control.text
  296. horizontalAlignment: Text.AlignHCenter
  297. elide: Text.ElideMiddle
  298. }
  299. }
  300. label: Item { }
  301. }
  302. }
  303. }
  304. }
  305. }
  306. Row
  307. {
  308. id: customCommandInputRow
  309. width: base.width - 2 * UM.Theme.getSize("default_margin").width
  310. height: childrenRect.height + UM.Theme.getSize("default_margin").width
  311. anchors.left: parent.left
  312. anchors.leftMargin: UM.Theme.getSize("default_margin").width
  313. spacing: UM.Theme.getSize("default_margin").width
  314. Label
  315. {
  316. text: catalog.i18nc("@label", "Send G-code")
  317. color: UM.Theme.getColor("setting_control_text")
  318. font: UM.Theme.getFont("default")
  319. width: Math.floor(parent.width * 0.4) - UM.Theme.getSize("default_margin").width
  320. height: UM.Theme.getSize("setting_control").height
  321. verticalAlignment: Text.AlignVCenter
  322. }
  323. Row
  324. {
  325. // Input field for custom G-code commands.
  326. Rectangle
  327. {
  328. id: customCommandControl
  329. // state
  330. visible: printerModel != null ? printerModel.canSendRawGcode: true
  331. enabled: {
  332. if (printerModel == null) {
  333. return false // Can't send custom commands if not connected.
  334. }
  335. if (connectedPrinter == null || !connectedPrinter.acceptsCommands) {
  336. return false // Not allowed to do anything
  337. }
  338. if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "paused" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline") {
  339. return false // Printer is in a state where it can't react to custom commands.
  340. }
  341. return true
  342. }
  343. // style
  344. color: !enabled ? UM.Theme.getColor("setting_control_disabled") : UM.Theme.getColor("setting_validation_ok")
  345. border.width: UM.Theme.getSize("default_lining").width
  346. border.color: !enabled ? UM.Theme.getColor("setting_control_disabled_border") : customCommandControlMouseArea.containsMouse ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border")
  347. // size
  348. width: UM.Theme.getSize("setting_control").width
  349. height: UM.Theme.getSize("setting_control").height
  350. // highlight
  351. Rectangle
  352. {
  353. anchors.fill: parent
  354. anchors.margins: UM.Theme.getSize("default_lining").width
  355. color: UM.Theme.getColor("setting_control_highlight")
  356. opacity: customCommandControl.hovered ? 1.0 : 0
  357. }
  358. // cursor hover popup
  359. MouseArea
  360. {
  361. id: customCommandControlMouseArea
  362. hoverEnabled: true
  363. anchors.fill: parent
  364. cursorShape: Qt.IBeamCursor
  365. onHoveredChanged:
  366. {
  367. if (containsMouse) {
  368. base.showTooltip(
  369. base,
  370. { x: 0, y: customCommandControlMouseArea.mapToItem(base, 0, 0).y },
  371. catalog.i18nc("@tooltip of G-code command input", "Send a custom G-code command to the connected printer. Press 'enter' to send the command.")
  372. )
  373. } else {
  374. base.hideTooltip()
  375. }
  376. }
  377. }
  378. TextInput
  379. {
  380. id: customCommandControlInput
  381. // style
  382. font: UM.Theme.getFont("default")
  383. color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text")
  384. selectByMouse: true
  385. clip: true
  386. enabled: parent.enabled
  387. renderType: Text.NativeRendering
  388. // anchors
  389. anchors.left: parent.left
  390. anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width
  391. anchors.right: parent.right
  392. anchors.verticalCenter: parent.verticalCenter
  393. // send the command when pressing enter
  394. // we also clear the text field
  395. Keys.onReturnPressed:
  396. {
  397. printerModel.sendRawCommand(customCommandControlInput.text)
  398. customCommandControlInput.text = ""
  399. }
  400. }
  401. }
  402. }
  403. }
  404. ListModel
  405. {
  406. id: distancesModel
  407. ListElement { label: "0.1"; value: 0.1 }
  408. ListElement { label: "1"; value: 1 }
  409. ListElement { label: "10"; value: 10 }
  410. ListElement { label: "100"; value: 100 }
  411. }
  412. ExclusiveGroup { id: distanceGroup }
  413. }
  414. }