TableControlPage.qml 23 KB

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