Fix settings dialog for smaller screens with scroll area

The settings dialog was using a fixed 1200px height which exceeded
the available space on 1920x1080 displays, causing settings to be
cut off. Added scroll area and dynamic sizing based on screen size.

Changes:
- Added QScrollArea to wrap all settings content
- Dialog height now calculated as 80% of screen height (max 900px)
- Minimum size reduced to 700x500 for smaller screens
- Save/Cancel buttons remain fixed at bottom (outside scroll area)
- Horizontal scrollbar disabled, vertical scrollbar shown when needed

Benefits:
- Works on any screen size (1080p, 1440p, 4K, etc.)
- All settings always accessible via scrolling
- Buttons always visible at bottom
- More professional UX

Resolves: Settings dialog running off screen on 1920x1080

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-28 19:19:20 -08:00
parent d34d272cf0
commit aad7ab0713

View File

@@ -3,9 +3,10 @@
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QFormLayout, QDialog, QVBoxLayout, QHBoxLayout, QFormLayout,
QLabel, QLineEdit, QComboBox, QCheckBox, QSlider, QLabel, QLineEdit, QComboBox, QCheckBox, QSlider,
QPushButton, QMessageBox, QGroupBox QPushButton, QMessageBox, QGroupBox, QScrollArea, QWidget
) )
from PySide6.QtCore import Qt from PySide6.QtCore import Qt
from PySide6.QtGui import QScreen
from typing import Callable, List, Tuple from typing import Callable, List, Tuple
@@ -39,20 +40,42 @@ class SettingsDialog(QDialog):
# Window configuration # Window configuration
self.setWindowTitle("Settings") self.setWindowTitle("Settings")
self.setMinimumSize(700, 1200)
self.resize(700, 1200) # Set initial size
self.setModal(True) self.setModal(True)
# Calculate size based on screen size (80% of screen height, max 900px)
screen = QScreen.availableGeometry(parent.screen() if parent else None)
max_height = min(int(screen.height() * 0.8), 900)
self.setMinimumSize(700, 500)
self.resize(700, max_height)
self._create_widgets() self._create_widgets()
self._load_current_settings() self._load_current_settings()
def _create_widgets(self): def _create_widgets(self):
"""Create all settings widgets.""" """Create all settings widgets."""
# Main layout for the dialog (contains scroll area + buttons)
main_layout = QVBoxLayout() main_layout = QVBoxLayout()
main_layout.setSpacing(15) # Add spacing between groups main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.setContentsMargins(20, 20, 20, 20) # Add padding around dialog main_layout.setSpacing(0)
self.setLayout(main_layout) self.setLayout(main_layout)
# Create scroll area for settings content
scroll_area = QScrollArea()
scroll_area.setWidgetResizable(True)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
# Create content widget for scroll area
content_widget = QWidget()
content_layout = QVBoxLayout()
content_layout.setSpacing(15) # Add spacing between groups
content_layout.setContentsMargins(20, 20, 20, 20) # Add padding
content_widget.setLayout(content_layout)
scroll_area.setWidget(content_widget)
# Add scroll area to main layout
main_layout.addWidget(scroll_area)
# User Settings Group # User Settings Group
user_group = QGroupBox("User Settings") user_group = QGroupBox("User Settings")
user_layout = QFormLayout() user_layout = QFormLayout()
@@ -63,7 +86,7 @@ class SettingsDialog(QDialog):
user_layout.addRow("Display Name:", self.name_input) user_layout.addRow("Display Name:", self.name_input)
user_group.setLayout(user_layout) user_group.setLayout(user_layout)
main_layout.addWidget(user_group) content_layout.addWidget(user_group)
# Audio Settings Group # Audio Settings Group
audio_group = QGroupBox("Audio Settings") audio_group = QGroupBox("Audio Settings")
@@ -77,7 +100,7 @@ class SettingsDialog(QDialog):
audio_layout.addRow("Input Device:", self.audio_device_combo) audio_layout.addRow("Input Device:", self.audio_device_combo)
audio_group.setLayout(audio_layout) audio_group.setLayout(audio_layout)
main_layout.addWidget(audio_group) content_layout.addWidget(audio_group)
# Transcription Settings Group # Transcription Settings Group
transcription_group = QGroupBox("Transcription Settings") transcription_group = QGroupBox("Transcription Settings")
@@ -137,7 +160,7 @@ class SettingsDialog(QDialog):
transcription_layout.addRow("Beam Size:", self.beam_size_combo) transcription_layout.addRow("Beam Size:", self.beam_size_combo)
transcription_group.setLayout(transcription_layout) transcription_group.setLayout(transcription_layout)
main_layout.addWidget(transcription_group) content_layout.addWidget(transcription_group)
# Realtime Preview Group # Realtime Preview Group
realtime_group = QGroupBox("Realtime Preview (Optional)") realtime_group = QGroupBox("Realtime Preview (Optional)")
@@ -157,7 +180,7 @@ class SettingsDialog(QDialog):
realtime_layout.addRow("Preview Model:", self.realtime_model_combo) realtime_layout.addRow("Preview Model:", self.realtime_model_combo)
realtime_group.setLayout(realtime_layout) realtime_group.setLayout(realtime_layout)
main_layout.addWidget(realtime_group) content_layout.addWidget(realtime_group)
# VAD (Voice Activity Detection) Group # VAD (Voice Activity Detection) Group
vad_group = QGroupBox("Voice Activity Detection") vad_group = QGroupBox("Voice Activity Detection")
@@ -205,7 +228,7 @@ class SettingsDialog(QDialog):
vad_layout.addRow("ONNX Acceleration:", self.silero_onnx_check) vad_layout.addRow("ONNX Acceleration:", self.silero_onnx_check)
vad_group.setLayout(vad_layout) vad_group.setLayout(vad_layout)
main_layout.addWidget(vad_group) content_layout.addWidget(vad_group)
# Advanced Timing Group # Advanced Timing Group
timing_group = QGroupBox("Advanced Timing Settings") timing_group = QGroupBox("Advanced Timing Settings")
@@ -239,7 +262,7 @@ class SettingsDialog(QDialog):
timing_layout.addRow("Pre-Recording Buffer (s):", self.pre_buffer_input) timing_layout.addRow("Pre-Recording Buffer (s):", self.pre_buffer_input)
timing_group.setLayout(timing_layout) timing_group.setLayout(timing_layout)
main_layout.addWidget(timing_group) content_layout.addWidget(timing_group)
# Display Settings Group # Display Settings Group
display_group = QGroupBox("Display Settings") display_group = QGroupBox("Display Settings")
@@ -276,7 +299,7 @@ class SettingsDialog(QDialog):
display_layout.addRow("Fade After (seconds):", self.fade_seconds_input) display_layout.addRow("Fade After (seconds):", self.fade_seconds_input)
display_group.setLayout(display_layout) display_group.setLayout(display_layout)
main_layout.addWidget(display_group) content_layout.addWidget(display_group)
# Server Sync Group # Server Sync Group
server_group = QGroupBox("Multi-User Server Sync (Optional)") server_group = QGroupBox("Multi-User Server Sync (Optional)")
@@ -317,10 +340,15 @@ class SettingsDialog(QDialog):
server_layout.addRow("Passphrase:", self.server_passphrase_input) server_layout.addRow("Passphrase:", self.server_passphrase_input)
server_group.setLayout(server_layout) server_group.setLayout(server_layout)
main_layout.addWidget(server_group) content_layout.addWidget(server_group)
# Buttons # Add stretch to push everything to the top
content_layout.addStretch()
# Buttons (outside scroll area, always visible at bottom)
button_container = QWidget()
button_layout = QHBoxLayout() button_layout = QHBoxLayout()
button_layout.setContentsMargins(20, 10, 20, 10)
button_layout.addStretch() button_layout.addStretch()
self.cancel_button = QPushButton("Cancel") self.cancel_button = QPushButton("Cancel")
@@ -332,7 +360,8 @@ class SettingsDialog(QDialog):
self.save_button.setDefault(True) self.save_button.setDefault(True)
button_layout.addWidget(self.save_button) button_layout.addWidget(self.save_button)
main_layout.addLayout(button_layout) button_container.setLayout(button_layout)
main_layout.addWidget(button_container)
def _update_silero_label(self, value): def _update_silero_label(self, value):
"""Update the Silero sensitivity label.""" """Update the Silero sensitivity label."""