TableControlPage.qml 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. import QtQuick 2.15
  2. import QtQuick.Controls 2.15
  3. import QtQuick.Layouts 1.15
  4. import QtQuick.Effects
  5. import "../components"
  6. Page {
  7. id: page
  8. property var backend: null
  9. property var serialPorts: []
  10. property string selectedPort: ""
  11. property bool isSerialConnected: false
  12. property int currentSpeed: 130
  13. property bool autoPlayOnBoot: false
  14. property int screenTimeoutMinutes: 0
  15. // Backend signal connections
  16. Connections {
  17. target: backend
  18. function onSerialPortsUpdated(ports) {
  19. console.log("Serial ports updated:", ports)
  20. serialPorts = ports
  21. }
  22. function onSerialConnectionChanged(connected) {
  23. console.log("Serial connection changed:", connected)
  24. isSerialConnected = connected
  25. }
  26. function onCurrentPortChanged(port) {
  27. console.log("Current port changed:", port)
  28. if (port) {
  29. selectedPort = port
  30. }
  31. }
  32. function onSpeedChanged(speed) {
  33. console.log("Speed changed:", speed)
  34. currentSpeed = speed
  35. }
  36. function onSettingsLoaded() {
  37. console.log("Settings loaded")
  38. if (backend) {
  39. autoPlayOnBoot = backend.autoPlayOnBoot
  40. currentSpeed = backend.currentSpeed
  41. isSerialConnected = backend.serialConnected
  42. screenTimeoutMinutes = Math.round(backend.screenTimeout / 60)
  43. if (backend.currentPort) {
  44. selectedPort = backend.currentPort
  45. }
  46. }
  47. }
  48. }
  49. // Refresh serial ports on page load
  50. Component.onCompleted: {
  51. refreshSerialPorts()
  52. loadSettings()
  53. }
  54. function refreshSerialPorts() {
  55. if (backend) {
  56. backend.refreshSerialPorts()
  57. }
  58. }
  59. function loadSettings() {
  60. if (backend) {
  61. backend.loadControlSettings()
  62. }
  63. }
  64. Rectangle {
  65. anchors.fill: parent
  66. color: "#f5f5f5"
  67. }
  68. ColumnLayout {
  69. anchors.fill: parent
  70. spacing: 0
  71. // Header
  72. Rectangle {
  73. Layout.fillWidth: true
  74. Layout.preferredHeight: 50
  75. color: "white"
  76. Rectangle {
  77. anchors.bottom: parent.bottom
  78. width: parent.width
  79. height: 1
  80. color: "#e5e7eb"
  81. }
  82. RowLayout {
  83. anchors.fill: parent
  84. anchors.leftMargin: 15
  85. anchors.rightMargin: 10
  86. ConnectionStatus {
  87. backend: page.backend
  88. Layout.rightMargin: 8
  89. }
  90. Label {
  91. text: "Table Control"
  92. font.pixelSize: 18
  93. font.bold: true
  94. color: "#333"
  95. }
  96. Item {
  97. Layout.fillWidth: true
  98. }
  99. }
  100. }
  101. // Main Content
  102. ScrollView {
  103. Layout.fillWidth: true
  104. Layout.fillHeight: true
  105. contentWidth: availableWidth
  106. ColumnLayout {
  107. width: parent.width
  108. anchors.margins: 10
  109. spacing: 10
  110. // Serial Connection Section
  111. Rectangle {
  112. Layout.fillWidth: true
  113. Layout.preferredHeight: 160
  114. Layout.margins: 10
  115. radius: 8
  116. color: "white"
  117. ColumnLayout {
  118. anchors.fill: parent
  119. anchors.margins: 15
  120. spacing: 10
  121. Label {
  122. text: "Serial Connection"
  123. font.pixelSize: 16
  124. font.bold: true
  125. color: "#333"
  126. }
  127. RowLayout {
  128. Layout.fillWidth: true
  129. spacing: 10
  130. Rectangle {
  131. Layout.fillWidth: true
  132. Layout.preferredHeight: 40
  133. radius: 6
  134. color: isSerialConnected ? "#e8f5e8" : "#f8f9fa"
  135. border.color: isSerialConnected ? "#4CAF50" : "#e5e7eb"
  136. border.width: 1
  137. RowLayout {
  138. anchors.fill: parent
  139. anchors.margins: 8
  140. Label {
  141. text: isSerialConnected ?
  142. (selectedPort ? `Connected: ${selectedPort}` : "Connected") :
  143. (selectedPort || "No port selected")
  144. color: isSerialConnected ? "#2e7d32" : (selectedPort ? "#333" : "#999")
  145. font.pixelSize: 12
  146. font.bold: isSerialConnected
  147. Layout.fillWidth: true
  148. }
  149. Text {
  150. text: "▼"
  151. color: "#666"
  152. font.pixelSize: 10
  153. visible: !isSerialConnected
  154. }
  155. }
  156. MouseArea {
  157. anchors.fill: parent
  158. enabled: !isSerialConnected
  159. onClicked: portMenu.open()
  160. }
  161. Menu {
  162. id: portMenu
  163. y: parent.height
  164. Repeater {
  165. model: serialPorts
  166. MenuItem {
  167. text: modelData
  168. onTriggered: {
  169. selectedPort = modelData
  170. }
  171. }
  172. }
  173. MenuSeparator {}
  174. MenuItem {
  175. text: "Refresh Ports"
  176. onTriggered: refreshSerialPorts()
  177. }
  178. }
  179. }
  180. ModernControlButton {
  181. Layout.preferredWidth: 150
  182. Layout.preferredHeight: 40
  183. text: isSerialConnected ? "Disconnect" : "Connect"
  184. icon: isSerialConnected ? "🔌" : "🔗"
  185. buttonColor: isSerialConnected ? "#dc2626" : "#059669"
  186. fontSize: 11
  187. enabled: isSerialConnected || selectedPort !== ""
  188. onClicked: {
  189. if (backend) {
  190. if (isSerialConnected) {
  191. backend.disconnectSerial()
  192. } else {
  193. backend.connectSerial(selectedPort)
  194. }
  195. }
  196. }
  197. }
  198. }
  199. RowLayout {
  200. Layout.fillWidth: true
  201. spacing: 8
  202. visible: !isSerialConnected
  203. ModernControlButton {
  204. Layout.fillWidth: true
  205. Layout.preferredHeight: 35
  206. text: "Refresh Ports"
  207. icon: "🔄"
  208. buttonColor: "#6b7280"
  209. fontSize: 10
  210. onClicked: refreshSerialPorts()
  211. }
  212. }
  213. }
  214. }
  215. // Hardware Movement Section
  216. Rectangle {
  217. Layout.fillWidth: true
  218. Layout.preferredHeight: 180
  219. Layout.margins: 10
  220. radius: 8
  221. color: "white"
  222. ColumnLayout {
  223. anchors.fill: parent
  224. anchors.margins: 15
  225. spacing: 10
  226. Label {
  227. text: "Table Movement"
  228. font.pixelSize: 16
  229. font.bold: true
  230. color: "#333"
  231. }
  232. GridLayout {
  233. Layout.fillWidth: true
  234. columns: 3
  235. rowSpacing: 8
  236. columnSpacing: 8
  237. ModernControlButton {
  238. Layout.fillWidth: true
  239. Layout.preferredHeight: 45
  240. text: "Home"
  241. icon: "🏠"
  242. buttonColor: "#2563eb"
  243. fontSize: 12
  244. enabled: isSerialConnected
  245. onClicked: {
  246. if (backend) backend.sendHome()
  247. }
  248. }
  249. ModernControlButton {
  250. Layout.fillWidth: true
  251. Layout.preferredHeight: 45
  252. text: "Center"
  253. icon: "🎯"
  254. buttonColor: "#2563eb"
  255. fontSize: 12
  256. enabled: isSerialConnected
  257. onClicked: {
  258. if (backend) backend.moveToCenter()
  259. }
  260. }
  261. ModernControlButton {
  262. Layout.fillWidth: true
  263. Layout.preferredHeight: 45
  264. text: "Perimeter"
  265. icon: "⭕"
  266. buttonColor: "#2563eb"
  267. fontSize: 12
  268. enabled: isSerialConnected
  269. onClicked: {
  270. if (backend) backend.moveToPerimeter()
  271. }
  272. }
  273. }
  274. }
  275. }
  276. // Speed Control Section
  277. Rectangle {
  278. Layout.fillWidth: true
  279. Layout.preferredHeight: 120
  280. Layout.margins: 10
  281. radius: 8
  282. color: "white"
  283. ColumnLayout {
  284. anchors.fill: parent
  285. anchors.margins: 15
  286. spacing: 10
  287. Label {
  288. text: "Speed Control"
  289. font.pixelSize: 16
  290. font.bold: true
  291. color: "#333"
  292. }
  293. RowLayout {
  294. Layout.fillWidth: true
  295. spacing: 10
  296. Label {
  297. text: "Speed:"
  298. font.pixelSize: 12
  299. color: "#666"
  300. }
  301. Slider {
  302. id: speedSlider
  303. Layout.fillWidth: true
  304. from: 10
  305. to: 500
  306. value: currentSpeed
  307. stepSize: 10
  308. onValueChanged: {
  309. currentSpeed = Math.round(value)
  310. }
  311. onPressedChanged: {
  312. if (!pressed && backend) {
  313. backend.setSpeed(currentSpeed)
  314. }
  315. }
  316. }
  317. Label {
  318. text: currentSpeed
  319. font.pixelSize: 12
  320. font.bold: true
  321. color: "#333"
  322. Layout.preferredWidth: 40
  323. }
  324. }
  325. }
  326. }
  327. // Auto Play on Boot Section
  328. Rectangle {
  329. Layout.fillWidth: true
  330. Layout.preferredHeight: 160
  331. Layout.margins: 10
  332. radius: 8
  333. color: "white"
  334. ColumnLayout {
  335. anchors.fill: parent
  336. anchors.margins: 15
  337. spacing: 10
  338. Label {
  339. text: "Auto Play Settings"
  340. font.pixelSize: 16
  341. font.bold: true
  342. color: "#333"
  343. }
  344. RowLayout {
  345. Layout.fillWidth: true
  346. spacing: 10
  347. Label {
  348. text: "Auto play on boot:"
  349. font.pixelSize: 12
  350. color: "#666"
  351. Layout.fillWidth: true
  352. }
  353. Switch {
  354. id: autoPlaySwitch
  355. checked: autoPlayOnBoot
  356. onToggled: {
  357. autoPlayOnBoot = checked
  358. if (backend) {
  359. backend.setAutoPlayOnBoot(checked)
  360. }
  361. }
  362. }
  363. }
  364. RowLayout {
  365. Layout.fillWidth: true
  366. spacing: 10
  367. Label {
  368. text: "Screen timeout:"
  369. font.pixelSize: 12
  370. color: "#666"
  371. }
  372. SpinBox {
  373. id: timeoutSpinBox
  374. Layout.preferredWidth: 120
  375. from: 0
  376. to: 120
  377. value: screenTimeoutMinutes
  378. stepSize: 5
  379. textFromValue: function(value, locale) {
  380. return value === 0 ? "Never" : value + " min"
  381. }
  382. onValueModified: {
  383. screenTimeoutMinutes = value
  384. if (backend) {
  385. // Convert minutes to seconds for backend
  386. backend.screenTimeout = value * 60
  387. }
  388. }
  389. }
  390. Item { Layout.fillWidth: true }
  391. }
  392. }
  393. }
  394. // Debug Screen Control Section (remove this later)
  395. Rectangle {
  396. Layout.fillWidth: true
  397. Layout.preferredHeight: 120
  398. Layout.margins: 10
  399. radius: 8
  400. color: "white"
  401. border.color: "#ff0000"
  402. border.width: 2
  403. ColumnLayout {
  404. anchors.fill: parent
  405. anchors.margins: 15
  406. spacing: 10
  407. Label {
  408. text: "DEBUG: Screen Control (Remove Later)"
  409. font.pixelSize: 12
  410. font.bold: true
  411. color: "#ff0000"
  412. }
  413. RowLayout {
  414. Layout.fillWidth: true
  415. spacing: 10
  416. ModernControlButton {
  417. Layout.fillWidth: true
  418. Layout.preferredHeight: 35
  419. text: "Screen OFF"
  420. icon: "💤"
  421. buttonColor: "#dc2626"
  422. fontSize: 10
  423. onClicked: {
  424. console.log("DEBUG: Manual screen off clicked")
  425. backend.turnScreenOff()
  426. }
  427. }
  428. ModernControlButton {
  429. Layout.fillWidth: true
  430. Layout.preferredHeight: 35
  431. text: "Screen ON"
  432. icon: "💡"
  433. buttonColor: "#059669"
  434. fontSize: 10
  435. onClicked: {
  436. console.log("DEBUG: Manual screen on clicked")
  437. backend.turnScreenOn()
  438. }
  439. }
  440. ModernControlButton {
  441. Layout.fillWidth: true
  442. Layout.preferredHeight: 35
  443. text: "Reset Timer"
  444. icon: "⏰"
  445. buttonColor: "#2563eb"
  446. fontSize: 10
  447. onClicked: {
  448. console.log("DEBUG: Reset activity timer clicked")
  449. backend.resetActivityTimer()
  450. }
  451. }
  452. }
  453. }
  454. }
  455. // Add some bottom spacing for better scrolling
  456. Item {
  457. Layout.preferredHeight: 20
  458. }
  459. }
  460. }
  461. }
  462. }