ManualPrinterControl.qml 21 KB

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