Bläddra i källkod

standardize common selection (speed, screen timeout, and pause between patterns)

tuanchris 4 månader sedan
förälder
incheckning
d805288d07

+ 173 - 3
dune-weaver-touch/backend.py

@@ -21,6 +21,34 @@ class Backend(QObject):
     SETTINGS_FILE = "touch_settings.json"
     DEFAULT_SCREEN_TIMEOUT = 300  # 5 minutes in seconds
     
+    # Predefined timeout options (in seconds)
+    TIMEOUT_OPTIONS = {
+        "30 seconds": 30,
+        "1 minute": 60, 
+        "5 minutes": 300,
+        "10 minutes": 600,
+        "Never": 0  # 0 means never timeout
+    }
+    
+    # Predefined speed options 
+    SPEED_OPTIONS = {
+        "50": 50,
+        "100": 100,
+        "200": 200,
+        "300": 300,
+        "500": 500
+    }
+    
+    # Predefined pause between patterns options (in seconds)
+    PAUSE_OPTIONS = {
+        "0s": 0,        # No pause
+        "1 min": 60,    # 1 minute
+        "5 min": 300,   # 5 minutes  
+        "15 min": 900,  # 15 minutes
+        "30 min": 1800, # 30 minutes
+        "1 hour": 3600  # 1 hour
+    }
+    
     # Signals
     statusChanged = Signal()
     progressChanged = Signal()
@@ -35,6 +63,7 @@ class Backend(QObject):
     settingsLoaded = Signal()
     screenStateChanged = Signal(bool)  # True = on, False = off
     screenTimeoutChanged = Signal(int)  # New signal for timeout changes
+    pauseBetweenPatternsChanged = Signal(int)  # New signal for pause changes
     
     def __init__(self):
         super().__init__()
@@ -56,6 +85,7 @@ class Backend(QObject):
         self._current_port = ""
         self._current_speed = 130
         self._auto_play_on_boot = False
+        self._pause_between_patterns = 0  # Default: no pause (0 seconds)
         
         # Screen management
         self._screen_on = True
@@ -552,9 +582,12 @@ class Backend(QObject):
                     settings = json.load(f)
                     
                 screen_timeout = settings.get('screen_timeout', self.DEFAULT_SCREEN_TIMEOUT)
-                if isinstance(screen_timeout, (int, float)) and screen_timeout > 0:
+                if isinstance(screen_timeout, (int, float)) and screen_timeout >= 0:
                     self._screen_timeout = int(screen_timeout)
-                    print(f"🖥️ Loaded screen timeout from local settings: {self._screen_timeout}s")
+                    if screen_timeout == 0:
+                        print(f"🖥️ Loaded screen timeout from local settings: Never (0s)")
+                    else:
+                        print(f"🖥️ Loaded screen timeout from local settings: {self._screen_timeout}s")
                 else:
                     print(f"⚠️ Invalid screen timeout in settings, using default: {self.DEFAULT_SCREEN_TIMEOUT}s")
             else:
@@ -644,6 +677,142 @@ class Backend(QObject):
             # Emit change signal for QML
             self.screenTimeoutChanged.emit(timeout)
     
+    @Slot(result='QStringList')
+    def getScreenTimeoutOptions(self):
+        """Get list of screen timeout options for QML"""
+        return list(self.TIMEOUT_OPTIONS.keys())
+    
+    @Slot(result=str)
+    def getCurrentScreenTimeoutOption(self):
+        """Get current screen timeout as option string"""
+        current_timeout = self._screen_timeout
+        for option, value in self.TIMEOUT_OPTIONS.items():
+            if value == current_timeout:
+                return option
+        # If custom value, return closest match or custom description
+        if current_timeout == 0:
+            return "Never"
+        elif current_timeout < 60:
+            return f"{current_timeout} seconds"
+        elif current_timeout < 3600:
+            minutes = current_timeout // 60
+            return f"{minutes} minute{'s' if minutes != 1 else ''}"
+        else:
+            hours = current_timeout // 3600
+            return f"{hours} hour{'s' if hours != 1 else ''}"
+    
+    @Slot(str)
+    def setScreenTimeoutByOption(self, option):
+        """Set screen timeout by option string"""
+        if option in self.TIMEOUT_OPTIONS:
+            timeout_value = self.TIMEOUT_OPTIONS[option]
+            # Don't call the setter method, just assign to trigger the property setter
+            if self._screen_timeout != timeout_value:
+                old_timeout = self._screen_timeout
+                self._screen_timeout = timeout_value
+                print(f"🖥️ Screen timeout changed from {old_timeout}s to {timeout_value}s ({option})")
+                
+                # Save to local settings
+                self._save_local_settings()
+                
+                # Emit change signal for QML
+                self.screenTimeoutChanged.emit(timeout_value)
+        else:
+            print(f"⚠️ Unknown timeout option: {option}")
+    
+    @Slot(result='QStringList')
+    def getSpeedOptions(self):
+        """Get list of speed options for QML"""
+        return list(self.SPEED_OPTIONS.keys())
+    
+    @Slot(result=str)
+    def getCurrentSpeedOption(self):
+        """Get current speed as option string"""
+        current_speed = self._current_speed
+        for option, value in self.SPEED_OPTIONS.items():
+            if value == current_speed:
+                return option
+        # If custom value, return as string
+        return str(current_speed)
+    
+    @Slot(str)
+    def setSpeedByOption(self, option):
+        """Set speed by option string"""
+        if option in self.SPEED_OPTIONS:
+            speed_value = self.SPEED_OPTIONS[option]
+            # Don't call setter method, just assign directly  
+            if self._current_speed != speed_value:
+                old_speed = self._current_speed
+                self._current_speed = speed_value
+                print(f"⚡ Speed changed from {old_speed} to {speed_value} ({option})")
+                
+                # Send to main application
+                asyncio.create_task(self._set_speed_async(speed_value))
+                
+                # Emit change signal for QML
+                self.speedChanged.emit(speed_value)
+        else:
+            print(f"⚠️ Unknown speed option: {option}")
+    
+    async def _set_speed_async(self, speed):
+        """Send speed to main application asynchronously"""
+        if not self.session:
+            return
+        try:
+            async with self.session.post(f"{self.base_url}/set_speed", json={"speed": speed}) as resp:
+                if resp.status == 200:
+                    print(f"✅ Speed set successfully: {speed}")
+                else:
+                    print(f"❌ Failed to set speed: {resp.status}")
+        except Exception as e:
+            print(f"💥 Exception setting speed: {e}")
+    
+    # Pause Between Patterns Methods
+    @Slot(result='QStringList')
+    def getPauseOptions(self):
+        """Get list of pause between patterns options for QML"""
+        return list(self.PAUSE_OPTIONS.keys())
+    
+    @Slot(result=str)
+    def getCurrentPauseOption(self):
+        """Get current pause between patterns as option string"""
+        current_pause = self._pause_between_patterns
+        for option, value in self.PAUSE_OPTIONS.items():
+            if value == current_pause:
+                return option
+        # If custom value, return descriptive string
+        if current_pause == 0:
+            return "0s"
+        elif current_pause < 60:
+            return f"{current_pause}s"
+        elif current_pause < 3600:
+            minutes = current_pause // 60
+            return f"{minutes} min"
+        else:
+            hours = current_pause // 3600
+            return f"{hours} hour"
+    
+    @Slot(str)
+    def setPauseByOption(self, option):
+        """Set pause between patterns by option string"""
+        if option in self.PAUSE_OPTIONS:
+            pause_value = self.PAUSE_OPTIONS[option]
+            if self._pause_between_patterns != pause_value:
+                old_pause = self._pause_between_patterns
+                self._pause_between_patterns = pause_value
+                print(f"⏸️ Pause between patterns changed from {old_pause}s to {pause_value}s ({option})")
+                
+                # Emit change signal for QML
+                self.pauseBetweenPatternsChanged.emit(pause_value)
+        else:
+            print(f"⚠️ Unknown pause option: {option}")
+    
+    # Property for pause between patterns
+    @Property(int, notify=pauseBetweenPatternsChanged)
+    def pauseBetweenPatterns(self):
+        """Get current pause between patterns in seconds"""
+        return self._pause_between_patterns
+    
     # Screen Control Methods
     @Slot()
     def turnScreenOn(self):
@@ -776,7 +945,7 @@ class Backend(QObject):
     
     def _check_screen_timeout(self):
         """Check if screen should be turned off due to inactivity"""
-        if self._screen_on:
+        if self._screen_on and self._screen_timeout > 0:  # Only check if timeout is enabled
             idle_time = time.time() - self._last_activity
             # Log every 10 seconds when getting close to timeout
             if idle_time > self._screen_timeout - 10 and idle_time % 10 < 1:
@@ -787,6 +956,7 @@ class Backend(QObject):
                 self._turn_screen_off()
                 # Add delay before starting touch monitoring to avoid catching residual events
                 QTimer.singleShot(1000, self._start_touch_monitoring)  # 1 second delay
+        # If timeout is 0 (Never), screen stays on indefinitely
     
     def _start_touch_monitoring(self):
         """Start monitoring touch input for wake-up"""

+ 185 - 32
dune-weaver-touch/qml/pages/ModernPlaylistPage.qml

@@ -18,7 +18,7 @@ Page {
     property var currentPlaylistPatterns: []
     
     // Playlist execution settings
-    property real pauseTime: 5.0
+    property real pauseTime: backend ? backend.pauseBetweenPatterns : 0
     property string clearPattern: "adaptive"
     property string runMode: "single"
     property bool shuffle: false
@@ -554,56 +554,209 @@ Page {
                                         }
                                     }
                                     
-                                    // Pause time
+                                    // Pause Between Patterns
                                     Column {
                                         Layout.fillWidth: true
-                                        spacing: 8
+                                        spacing: 15
                                         
                                         Label {
-                                            text: "Pause Between Patterns:"
+                                            text: "Pause between patterns:"
                                             font.pixelSize: 12
                                             color: "#666"
                                             font.bold: true
                                         }
                                         
+                                        // Touch-friendly button row for pause options
                                         RowLayout {
-                                            width: parent.width
-                                            spacing: 10
+                                            id: pauseGrid
+                                            Layout.fillWidth: true
+                                            spacing: 8
                                             
-                                            TextField {
-                                                Layout.preferredWidth: 140
-                                                Layout.preferredHeight: 20
-                                                text: Math.round(pauseTime).toString()
-                                                font.pixelSize: 12
-                                                horizontalAlignment: TextInput.AlignHCenter
-                                                maximumLength: 10
-                                                inputMethodHints: Qt.ImhDigitsOnly
-                                                validator: IntValidator {
-                                                    bottom: 0
-                                                    top: 99999
+                                            property string currentSelection: backend ? backend.getCurrentPauseOption() : "0s"
+                                            
+                                            // 0s button
+                                            Rectangle {
+                                                Layout.preferredWidth: 60
+                                                Layout.preferredHeight: 40
+                                                color: pauseGrid.currentSelection === "0s" ? "#2196F3" : "#f0f0f0"
+                                                border.color: pauseGrid.currentSelection === "0s" ? "#1976D2" : "#ccc"
+                                                border.width: 2
+                                                radius: 8
+                                                
+                                                Label {
+                                                    anchors.centerIn: parent
+                                                    text: "0s"
+                                                    font.pixelSize: 12
+                                                    font.bold: true
+                                                    color: pauseGrid.currentSelection === "0s" ? "white" : "#333"
                                                 }
-                                                onTextChanged: {
-                                                    var newValue = parseInt(text)
-                                                    if (!isNaN(newValue) && newValue >= 0 && newValue <= 99999) {
-                                                        pauseTime = newValue
+                                                
+                                                MouseArea {
+                                                    anchors.fill: parent
+                                                    onClicked: {
+                                                        if (backend) {
+                                                            backend.setPauseByOption("0s")
+                                                            pauseGrid.currentSelection = "0s"
+                                                            pauseTime = 0
+                                                        }
                                                     }
                                                 }
-                                                background: Rectangle {
-                                                    color: "white"
-                                                    border.color: "#e5e7eb"
-                                                    border.width: 1
-                                                    radius: 6
+                                            }
+                                            
+                                            // 1 min button
+                                            Rectangle {
+                                                Layout.preferredWidth: 60
+                                                Layout.preferredHeight: 40
+                                                color: pauseGrid.currentSelection === "1 min" ? "#2196F3" : "#f0f0f0"
+                                                border.color: pauseGrid.currentSelection === "1 min" ? "#1976D2" : "#ccc"
+                                                border.width: 2
+                                                radius: 8
+                                                
+                                                Label {
+                                                    anchors.centerIn: parent
+                                                    text: "1m"
+                                                    font.pixelSize: 12
+                                                    font.bold: true
+                                                    color: pauseGrid.currentSelection === "1 min" ? "white" : "#333"
+                                                }
+                                                
+                                                MouseArea {
+                                                    anchors.fill: parent
+                                                    onClicked: {
+                                                        if (backend) {
+                                                            backend.setPauseByOption("1 min")
+                                                            pauseGrid.currentSelection = "1 min"
+                                                            pauseTime = 60
+                                                        }
+                                                    }
                                                 }
                                             }
                                             
-                                            Label {
-                                                text: "seconds"
-                                                font.pixelSize: 11
-                                                color: "#666"
+                                            // 5 min button
+                                            Rectangle {
+                                                Layout.preferredWidth: 60
+                                                Layout.preferredHeight: 40
+                                                color: pauseGrid.currentSelection === "5 min" ? "#2196F3" : "#f0f0f0"
+                                                border.color: pauseGrid.currentSelection === "5 min" ? "#1976D2" : "#ccc"
+                                                border.width: 2
+                                                radius: 8
+                                                
+                                                Label {
+                                                    anchors.centerIn: parent
+                                                    text: "5m"
+                                                    font.pixelSize: 12
+                                                    font.bold: true
+                                                    color: pauseGrid.currentSelection === "5 min" ? "white" : "#333"
+                                                }
+                                                
+                                                MouseArea {
+                                                    anchors.fill: parent
+                                                    onClicked: {
+                                                        if (backend) {
+                                                            backend.setPauseByOption("5 min")
+                                                            pauseGrid.currentSelection = "5 min"
+                                                            pauseTime = 300
+                                                        }
+                                                    }
+                                                }
                                             }
                                             
-                                            Item { 
-                                                Layout.fillWidth: true 
+                                            // 15 min button
+                                            Rectangle {
+                                                Layout.preferredWidth: 60
+                                                Layout.preferredHeight: 40
+                                                color: pauseGrid.currentSelection === "15 min" ? "#2196F3" : "#f0f0f0"
+                                                border.color: pauseGrid.currentSelection === "15 min" ? "#1976D2" : "#ccc"
+                                                border.width: 2
+                                                radius: 8
+                                                
+                                                Label {
+                                                    anchors.centerIn: parent
+                                                    text: "15m"
+                                                    font.pixelSize: 12
+                                                    font.bold: true
+                                                    color: pauseGrid.currentSelection === "15 min" ? "white" : "#333"
+                                                }
+                                                
+                                                MouseArea {
+                                                    anchors.fill: parent
+                                                    onClicked: {
+                                                        if (backend) {
+                                                            backend.setPauseByOption("15 min")
+                                                            pauseGrid.currentSelection = "15 min"
+                                                            pauseTime = 900
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                            
+                                            // 30 min button
+                                            Rectangle {
+                                                Layout.preferredWidth: 60
+                                                Layout.preferredHeight: 40
+                                                color: pauseGrid.currentSelection === "30 min" ? "#2196F3" : "#f0f0f0"
+                                                border.color: pauseGrid.currentSelection === "30 min" ? "#1976D2" : "#ccc"
+                                                border.width: 2
+                                                radius: 8
+                                                
+                                                Label {
+                                                    anchors.centerIn: parent
+                                                    text: "30m"
+                                                    font.pixelSize: 12
+                                                    font.bold: true
+                                                    color: pauseGrid.currentSelection === "30 min" ? "white" : "#333"
+                                                }
+                                                
+                                                MouseArea {
+                                                    anchors.fill: parent
+                                                    onClicked: {
+                                                        if (backend) {
+                                                            backend.setPauseByOption("30 min")
+                                                            pauseGrid.currentSelection = "30 min"
+                                                            pauseTime = 1800
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                            
+                                            // 1 hour button
+                                            Rectangle {
+                                                Layout.preferredWidth: 60
+                                                Layout.preferredHeight: 40
+                                                color: pauseGrid.currentSelection === "1 hour" ? "#2196F3" : "#f0f0f0"
+                                                border.color: pauseGrid.currentSelection === "1 hour" ? "#1976D2" : "#ccc"
+                                                border.width: 2
+                                                radius: 8
+                                                
+                                                Label {
+                                                    anchors.centerIn: parent
+                                                    text: "1h"
+                                                    font.pixelSize: 12
+                                                    font.bold: true
+                                                    color: pauseGrid.currentSelection === "1 hour" ? "white" : "#333"
+                                                }
+                                                
+                                                MouseArea {
+                                                    anchors.fill: parent
+                                                    onClicked: {
+                                                        if (backend) {
+                                                            backend.setPauseByOption("1 hour")
+                                                            pauseGrid.currentSelection = "1 hour"
+                                                            pauseTime = 3600
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                            
+                                            // Update selection when backend changes
+                                            Connections {
+                                                target: backend
+                                                function onPauseBetweenPatternsChanged(pause) {
+                                                    if (backend) {
+                                                        pauseGrid.currentSelection = backend.getCurrentPauseOption()
+                                                        pauseTime = backend.pauseBetweenPatterns
+                                                    }
+                                                }
                                             }
                                         }
                                     }

+ 306 - 118
dune-weaver-touch/qml/pages/TableControlPage.qml

@@ -12,7 +12,6 @@ Page {
     property bool isSerialConnected: false
     property int currentSpeed: 130
     property bool autoPlayOnBoot: false
-    property int screenTimeoutMinutes: 0
     
     // Backend signal connections
     Connections {
@@ -46,7 +45,7 @@ Page {
                 autoPlayOnBoot = backend.autoPlayOnBoot
                 currentSpeed = backend.currentSpeed
                 isSerialConnected = backend.serialConnected
-                screenTimeoutMinutes = Math.round(backend.screenTimeout / 60)
+                // Screen timeout is now managed by button selection, no need to convert
                 if (backend.currentPort) {
                     selectedPort = backend.currentPort
                 }
@@ -143,7 +142,7 @@ Page {
                         
                         Label {
                             text: "Serial Connection"
-                            font.pixelSize: 16
+                            font.pixelSize: 14
                             font.bold: true
                             color: "#333"
                         }
@@ -266,7 +265,7 @@ Page {
                         
                         Label {
                             text: "Table Movement"
-                            font.pixelSize: 16
+                            font.pixelSize: 14
                             font.bold: true
                             color: "#333"
                         }
@@ -325,7 +324,7 @@ Page {
                 // Speed Control Section
                 Rectangle {
                     Layout.fillWidth: true
-                    Layout.preferredHeight: 120
+                    Layout.preferredHeight: 120  // Reduced from original for single row layout
                     Layout.margins: 10
                     radius: 8
                     color: "white"
@@ -333,50 +332,172 @@ Page {
                     ColumnLayout {
                         anchors.fill: parent
                         anchors.margins: 15
-                        spacing: 10
+                        spacing: 15
                         
                         Label {
-                            text: "Speed Control"
-                            font.pixelSize: 16
+                            text: "Speed:"
+                            font.pixelSize: 14
                             font.bold: true
                             color: "#333"
+                            Layout.alignment: Qt.AlignLeft
                         }
                         
+                        // Touch-friendly button row for speed options
                         RowLayout {
+                            id: speedGrid
                             Layout.fillWidth: true
-                            spacing: 10
+                            spacing: 8
                             
-                            Label {
-                                text: "Speed:"
-                                font.pixelSize: 12
-                                color: "#666"
+                            property string currentSelection: backend ? backend.getCurrentSpeedOption() : "200"
+                            
+                            // 50 button
+                            Rectangle {
+                                Layout.preferredWidth: 100
+                                Layout.preferredHeight: 50
+                                color: speedGrid.currentSelection === "50" ? "#2196F3" : "#f0f0f0"
+                                border.color: speedGrid.currentSelection === "50" ? "#1976D2" : "#ccc"
+                                border.width: 2
+                                radius: 8
+                                
+                                Label {
+                                    anchors.centerIn: parent
+                                    text: "50"
+                                    font.pixelSize: 14
+                                    font.bold: true
+                                    color: speedGrid.currentSelection === "50" ? "white" : "#333"
+                                }
+                                
+                                MouseArea {
+                                    anchors.fill: parent
+                                    onClicked: {
+                                        if (backend) {
+                                            backend.setSpeedByOption("50")
+                                            speedGrid.currentSelection = "50"
+                                        }
+                                    }
+                                }
                             }
                             
-                            Slider {
-                                id: speedSlider
-                                Layout.fillWidth: true
-                                from: 10
-                                to: 500
-                                value: currentSpeed
-                                stepSize: 10
+                            // 100 button
+                            Rectangle {
+                                Layout.preferredWidth: 100
+                                Layout.preferredHeight: 50
+                                color: speedGrid.currentSelection === "100" ? "#2196F3" : "#f0f0f0"
+                                border.color: speedGrid.currentSelection === "100" ? "#1976D2" : "#ccc"
+                                border.width: 2
+                                radius: 8
                                 
-                                onValueChanged: {
-                                    currentSpeed = Math.round(value)
+                                Label {
+                                    anchors.centerIn: parent
+                                    text: "100"
+                                    font.pixelSize: 14
+                                    font.bold: true
+                                    color: speedGrid.currentSelection === "100" ? "white" : "#333"
                                 }
                                 
-                                onPressedChanged: {
-                                    if (!pressed && backend) {
-                                        backend.setSpeed(currentSpeed)
+                                MouseArea {
+                                    anchors.fill: parent
+                                    onClicked: {
+                                        if (backend) {
+                                            backend.setSpeedByOption("100")
+                                            speedGrid.currentSelection = "100"
+                                        }
                                     }
                                 }
                             }
                             
-                            Label {
-                                text: currentSpeed
-                                font.pixelSize: 12
-                                font.bold: true
-                                color: "#333"
-                                Layout.preferredWidth: 40
+                            // 200 button
+                            Rectangle {
+                                Layout.preferredWidth: 100
+                                Layout.preferredHeight: 50
+                                color: speedGrid.currentSelection === "200" ? "#2196F3" : "#f0f0f0"
+                                border.color: speedGrid.currentSelection === "200" ? "#1976D2" : "#ccc"
+                                border.width: 2
+                                radius: 8
+                                
+                                Label {
+                                    anchors.centerIn: parent
+                                    text: "200"
+                                    font.pixelSize: 14
+                                    font.bold: true
+                                    color: speedGrid.currentSelection === "200" ? "white" : "#333"
+                                }
+                                
+                                MouseArea {
+                                    anchors.fill: parent
+                                    onClicked: {
+                                        if (backend) {
+                                            backend.setSpeedByOption("200")
+                                            speedGrid.currentSelection = "200"
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            // 300 button
+                            Rectangle {
+                                Layout.preferredWidth: 100
+                                Layout.preferredHeight: 50
+                                color: speedGrid.currentSelection === "300" ? "#2196F3" : "#f0f0f0"
+                                border.color: speedGrid.currentSelection === "300" ? "#1976D2" : "#ccc"
+                                border.width: 2
+                                radius: 8
+                                
+                                Label {
+                                    anchors.centerIn: parent
+                                    text: "300"
+                                    font.pixelSize: 14
+                                    font.bold: true
+                                    color: speedGrid.currentSelection === "300" ? "white" : "#333"
+                                }
+                                
+                                MouseArea {
+                                    anchors.fill: parent
+                                    onClicked: {
+                                        if (backend) {
+                                            backend.setSpeedByOption("300")
+                                            speedGrid.currentSelection = "300"
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            // 500 button
+                            Rectangle {
+                                Layout.preferredWidth: 100
+                                Layout.preferredHeight: 50
+                                color: speedGrid.currentSelection === "500" ? "#2196F3" : "#f0f0f0"
+                                border.color: speedGrid.currentSelection === "500" ? "#1976D2" : "#ccc"
+                                border.width: 2
+                                radius: 8
+                                
+                                Label {
+                                    anchors.centerIn: parent
+                                    text: "500"
+                                    font.pixelSize: 14
+                                    font.bold: true
+                                    color: speedGrid.currentSelection === "500" ? "white" : "#333"
+                                }
+                                
+                                MouseArea {
+                                    anchors.fill: parent
+                                    onClicked: {
+                                        if (backend) {
+                                            backend.setSpeedByOption("500")
+                                            speedGrid.currentSelection = "500"
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            // Update selection when backend changes
+                            Connections {
+                                target: backend
+                                function onSpeedChanged(speed) {
+                                    if (backend) {
+                                        speedGrid.currentSelection = backend.getCurrentSpeedOption()
+                                    }
+                                }
                             }
                         }
                     }
@@ -385,7 +506,7 @@ Page {
                 // Auto Play on Boot Section
                 Rectangle {
                     Layout.fillWidth: true
-                    Layout.preferredHeight: 160
+                    Layout.preferredHeight: 200  // Reduced from 280 for single row layout
                     Layout.margins: 10
                     radius: 8
                     color: "white"
@@ -397,7 +518,7 @@ Page {
                         
                         Label {
                             text: "Auto Play Settings"
-                            font.pixelSize: 16
+                            font.pixelSize: 14
                             font.bold: true
                             color: "#333"
                         }
@@ -426,107 +547,174 @@ Page {
                             }
                         }
                         
-                        RowLayout {
+                        ColumnLayout {
                             Layout.fillWidth: true
-                            spacing: 10
+                            spacing: 15
                             
                             Label {
                                 text: "Screen timeout:"
-                                font.pixelSize: 12
-                                color: "#666"
+                                font.pixelSize: 14
+                                font.bold: true
+                                color: "#333"
+                                Layout.alignment: Qt.AlignLeft
                             }
                             
-                            SpinBox {
-                                id: timeoutSpinBox
-                                Layout.preferredWidth: 120
-                                from: 0
-                                to: 120
-                                value: screenTimeoutMinutes
-                                stepSize: 5
+                            // Touch-friendly button row for timeout options
+                            RowLayout {
+                                id: timeoutGrid
+                                Layout.fillWidth: true
+                                spacing: 8
+                                
+                                property string currentSelection: backend ? backend.getCurrentScreenTimeoutOption() : "5 minutes"
+                                
+                                // 30 seconds button
+                                Rectangle {
+                                    Layout.preferredWidth: 100
+                                    Layout.preferredHeight: 50
+                                    color: timeoutGrid.currentSelection === "30 seconds" ? "#2196F3" : "#f0f0f0"
+                                    border.color: timeoutGrid.currentSelection === "30 seconds" ? "#1976D2" : "#ccc"
+                                    border.width: 2
+                                    radius: 8
+                                    
+                                    Label {
+                                        anchors.centerIn: parent
+                                        text: "30s"
+                                        font.pixelSize: 14
+                                        font.bold: true
+                                        color: timeoutGrid.currentSelection === "30 seconds" ? "white" : "#333"
+                                    }
+                                    
+                                    MouseArea {
+                                        anchors.fill: parent
+                                        onClicked: {
+                                            if (backend) {
+                                                backend.setScreenTimeoutByOption("30 seconds")
+                                                timeoutGrid.currentSelection = "30 seconds"
+                                            }
+                                        }
+                                    }
+                                }
                                 
-                                textFromValue: function(value, locale) {
-                                    return value === 0 ? "Never" : value + " min"
+                                // 1 minute button
+                                Rectangle {
+                                    Layout.preferredWidth: 100
+                                    Layout.preferredHeight: 50
+                                    color: timeoutGrid.currentSelection === "1 minute" ? "#2196F3" : "#f0f0f0"
+                                    border.color: timeoutGrid.currentSelection === "1 minute" ? "#1976D2" : "#ccc"
+                                    border.width: 2
+                                    radius: 8
+                                    
+                                    Label {
+                                        anchors.centerIn: parent
+                                        text: "1min"
+                                        font.pixelSize: 14
+                                        font.bold: true
+                                        color: timeoutGrid.currentSelection === "1 minute" ? "white" : "#333"
+                                    }
+                                    
+                                    MouseArea {
+                                        anchors.fill: parent
+                                        onClicked: {
+                                            if (backend) {
+                                                backend.setScreenTimeoutByOption("1 minute")
+                                                timeoutGrid.currentSelection = "1 minute"
+                                            }
+                                        }
+                                    }
                                 }
                                 
-                                onValueModified: {
-                                    screenTimeoutMinutes = value
-                                    if (backend) {
-                                        // Convert minutes to seconds for backend
-                                        backend.screenTimeout = value * 60
+                                // 5 minutes button
+                                Rectangle {
+                                    Layout.preferredWidth: 100
+                                    Layout.preferredHeight: 50
+                                    color: timeoutGrid.currentSelection === "5 minutes" ? "#2196F3" : "#f0f0f0"
+                                    border.color: timeoutGrid.currentSelection === "5 minutes" ? "#1976D2" : "#ccc"
+                                    border.width: 2
+                                    radius: 8
+                                    
+                                    Label {
+                                        anchors.centerIn: parent
+                                        text: "5min"
+                                        font.pixelSize: 14
+                                        font.bold: true
+                                        color: timeoutGrid.currentSelection === "5 minutes" ? "white" : "#333"
+                                    }
+                                    
+                                    MouseArea {
+                                        anchors.fill: parent
+                                        onClicked: {
+                                            if (backend) {
+                                                backend.setScreenTimeoutByOption("5 minutes")
+                                                timeoutGrid.currentSelection = "5 minutes"
+                                            }
+                                        }
                                     }
                                 }
-                            }
-                            
-                            Item { Layout.fillWidth: true }
-                        }
-                    }
-                }
-                
-                // Debug Screen Control Section (remove this later)
-                Rectangle {
-                    Layout.fillWidth: true
-                    Layout.preferredHeight: 120
-                    Layout.margins: 10
-                    radius: 8
-                    color: "white"
-                    border.color: "#ff0000"
-                    border.width: 2
-                    
-                    ColumnLayout {
-                        anchors.fill: parent
-                        anchors.margins: 15
-                        spacing: 10
-                        
-                        Label {
-                            text: "DEBUG: Screen Control (Remove Later)"
-                            font.pixelSize: 12
-                            font.bold: true
-                            color: "#ff0000"
-                        }
-                        
-                        RowLayout {
-                            Layout.fillWidth: true
-                            spacing: 10
-                            
-                            ModernControlButton {
-                                Layout.fillWidth: true
-                                Layout.preferredHeight: 35
-                                text: "Screen OFF"
-                                icon: "💤"
-                                buttonColor: "#dc2626"
-                                fontSize: 10
                                 
-                                onClicked: {
-                                    console.log("DEBUG: Manual screen off clicked")
-                                    backend.turnScreenOff()
+                                // 10 minutes button
+                                Rectangle {
+                                    Layout.preferredWidth: 100
+                                    Layout.preferredHeight: 50
+                                    color: timeoutGrid.currentSelection === "10 minutes" ? "#2196F3" : "#f0f0f0"
+                                    border.color: timeoutGrid.currentSelection === "10 minutes" ? "#1976D2" : "#ccc"
+                                    border.width: 2
+                                    radius: 8
+                                    
+                                    Label {
+                                        anchors.centerIn: parent
+                                        text: "10min"
+                                        font.pixelSize: 14
+                                        font.bold: true
+                                        color: timeoutGrid.currentSelection === "10 minutes" ? "white" : "#333"
+                                    }
+                                    
+                                    MouseArea {
+                                        anchors.fill: parent
+                                        onClicked: {
+                                            if (backend) {
+                                                backend.setScreenTimeoutByOption("10 minutes")
+                                                timeoutGrid.currentSelection = "10 minutes"
+                                            }
+                                        }
+                                    }
                                 }
-                            }
-                            
-                            ModernControlButton {
-                                Layout.fillWidth: true
-                                Layout.preferredHeight: 35
-                                text: "Screen ON"
-                                icon: "💡"
-                                buttonColor: "#059669"
-                                fontSize: 10
                                 
-                                onClicked: {
-                                    console.log("DEBUG: Manual screen on clicked")
-                                    backend.turnScreenOn()
+                                // Never button
+                                Rectangle {
+                                    Layout.preferredWidth: 100
+                                    Layout.preferredHeight: 50
+                                    color: timeoutGrid.currentSelection === "Never" ? "#FF9800" : "#f0f0f0"
+                                    border.color: timeoutGrid.currentSelection === "Never" ? "#F57C00" : "#ccc"
+                                    border.width: 2
+                                    radius: 8
+                                    
+                                    Label {
+                                        anchors.centerIn: parent
+                                        text: "Never"
+                                        font.pixelSize: 14
+                                        font.bold: true
+                                        color: timeoutGrid.currentSelection === "Never" ? "white" : "#333"
+                                    }
+                                    
+                                    MouseArea {
+                                        anchors.fill: parent
+                                        onClicked: {
+                                            if (backend) {
+                                                backend.setScreenTimeoutByOption("Never")
+                                                timeoutGrid.currentSelection = "Never"
+                                            }
+                                        }
+                                    }
                                 }
-                            }
-                            
-                            ModernControlButton {
-                                Layout.fillWidth: true
-                                Layout.preferredHeight: 35
-                                text: "Reset Timer"
-                                icon: "⏰"
-                                buttonColor: "#2563eb"
-                                fontSize: 10
                                 
-                                onClicked: {
-                                    console.log("DEBUG: Reset activity timer clicked")
-                                    backend.resetActivityTimer()
+                                // Update selection when backend changes
+                                Connections {
+                                    target: backend
+                                    function onScreenTimeoutChanged() {
+                                        if (backend) {
+                                            timeoutGrid.currentSelection = backend.getCurrentScreenTimeoutOption()
+                                        }
+                                    }
                                 }
                             }
                         }