Update settings.py

This commit is contained in:
Broque Thomas 2025-07-19 18:54:59 -07:00
parent d45c2170d3
commit 92d0f060f4

View file

@ -1,6 +1,6 @@
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QFrame, QPushButton, QLineEdit, QComboBox, QFrame, QPushButton, QLineEdit, QComboBox,
QCheckBox, QSpinBox, QTextEdit, QGroupBox, QFormLayout, QMessageBox) QCheckBox, QSpinBox, QTextEdit, QGroupBox, QFormLayout, QMessageBox, QSizePolicy)
from PyQt6.QtCore import Qt from PyQt6.QtCore import Qt
from PyQt6.QtGui import QFont from PyQt6.QtGui import QFont
from config.settings import config_manager from config.settings import config_manager
@ -42,8 +42,8 @@ class SettingsPage(QWidget):
""") """)
main_layout = QVBoxLayout(self) main_layout = QVBoxLayout(self)
main_layout.setContentsMargins(30, 30, 30, 30) main_layout.setContentsMargins(20, 16, 20, 20)
main_layout.setSpacing(25) main_layout.setSpacing(16)
# Header # Header
header = self.create_header() header = self.create_header()
@ -51,7 +51,7 @@ class SettingsPage(QWidget):
# Settings content # Settings content
content_layout = QHBoxLayout() content_layout = QHBoxLayout()
content_layout.setSpacing(30) content_layout.setSpacing(24)
# Left column # Left column
left_column = self.create_left_column() left_column = self.create_left_column()
@ -102,6 +102,7 @@ class SettingsPage(QWidget):
self.slskd_url_input.setText(soulseek_config.get('slskd_url', '')) self.slskd_url_input.setText(soulseek_config.get('slskd_url', ''))
self.api_key_input.setText(soulseek_config.get('api_key', '')) self.api_key_input.setText(soulseek_config.get('api_key', ''))
self.download_path_input.setText(soulseek_config.get('download_path', './downloads')) self.download_path_input.setText(soulseek_config.get('download_path', './downloads'))
self.transfer_path_input.setText(soulseek_config.get('transfer_path', './Transfer'))
except Exception as e: except Exception as e:
QMessageBox.warning(self, "Error", f"Failed to load configuration: {e}") QMessageBox.warning(self, "Error", f"Failed to load configuration: {e}")
@ -121,6 +122,7 @@ class SettingsPage(QWidget):
config_manager.set('soulseek.slskd_url', self.slskd_url_input.text()) config_manager.set('soulseek.slskd_url', self.slskd_url_input.text())
config_manager.set('soulseek.api_key', self.api_key_input.text()) config_manager.set('soulseek.api_key', self.api_key_input.text())
config_manager.set('soulseek.download_path', self.download_path_input.text()) config_manager.set('soulseek.download_path', self.download_path_input.text())
config_manager.set('soulseek.transfer_path', self.transfer_path_input.text())
# Show success message # Show success message
QMessageBox.information(self, "Success", "Settings saved successfully!") QMessageBox.information(self, "Success", "Settings saved successfully!")
@ -291,11 +293,26 @@ class SettingsPage(QWidget):
if selected_path: if selected_path:
self.download_path_input.setText(selected_path) self.download_path_input.setText(selected_path)
def browse_transfer_path(self):
"""Open a directory dialog to select transfer path"""
from PyQt6.QtWidgets import QFileDialog
current_path = self.transfer_path_input.text()
selected_path = QFileDialog.getExistingDirectory(
self,
"Select Transfer Directory",
current_path if current_path else ".",
QFileDialog.Option.ShowDirsOnly
)
if selected_path:
self.transfer_path_input.setText(selected_path)
def create_header(self): def create_header(self):
header = QWidget() header = QWidget()
layout = QVBoxLayout(header) layout = QVBoxLayout(header)
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(5) layout.setSpacing(8)
# Title # Title
title_label = QLabel("Settings") title_label = QLabel("Settings")
@ -315,80 +332,113 @@ class SettingsPage(QWidget):
def create_left_column(self): def create_left_column(self):
column = QWidget() column = QWidget()
layout = QVBoxLayout(column) layout = QVBoxLayout(column)
layout.setSpacing(20) layout.setSpacing(18)
# API Configuration # API Configuration
api_group = SettingsGroup("API Configuration") api_group = SettingsGroup("API Configuration")
api_layout = QVBoxLayout(api_group) api_layout = QVBoxLayout(api_group)
api_layout.setContentsMargins(20, 25, 20, 20) api_layout.setContentsMargins(16, 20, 16, 16)
api_layout.setSpacing(15) api_layout.setSpacing(12)
# Spotify settings # Spotify settings
spotify_frame = QFrame() spotify_frame = QFrame()
spotify_layout = QFormLayout(spotify_frame) spotify_layout = QVBoxLayout(spotify_frame)
spotify_layout.setSpacing(10) spotify_layout.setSpacing(8)
spotify_title = QLabel("Spotify") spotify_title = QLabel("Spotify")
spotify_title.setFont(QFont("Arial", 12, QFont.Weight.Bold)) spotify_title.setFont(QFont("Arial", 12, QFont.Weight.Bold))
spotify_title.setStyleSheet("color: #1db954;") spotify_title.setStyleSheet("color: #1db954;")
spotify_layout.addWidget(spotify_title)
# Client ID
client_id_label = QLabel("Client ID:")
client_id_label.setStyleSheet("color: #ffffff; font-size: 11px;")
spotify_layout.addWidget(client_id_label)
self.client_id_input = QLineEdit() self.client_id_input = QLineEdit()
self.client_id_input.setStyleSheet(self.get_input_style()) self.client_id_input.setStyleSheet(self.get_input_style())
self.client_id_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.form_inputs['spotify.client_id'] = self.client_id_input self.form_inputs['spotify.client_id'] = self.client_id_input
spotify_layout.addWidget(self.client_id_input)
# Client Secret
client_secret_label = QLabel("Client Secret:")
client_secret_label.setStyleSheet("color: #ffffff; font-size: 11px;")
spotify_layout.addWidget(client_secret_label)
self.client_secret_input = QLineEdit() self.client_secret_input = QLineEdit()
self.client_secret_input.setEchoMode(QLineEdit.EchoMode.Password) self.client_secret_input.setEchoMode(QLineEdit.EchoMode.Password)
self.client_secret_input.setStyleSheet(self.get_input_style()) self.client_secret_input.setStyleSheet(self.get_input_style())
self.client_secret_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.form_inputs['spotify.client_secret'] = self.client_secret_input self.form_inputs['spotify.client_secret'] = self.client_secret_input
spotify_layout.addWidget(self.client_secret_input)
spotify_layout.addRow(spotify_title)
spotify_layout.addRow("Client ID:", self.client_id_input)
spotify_layout.addRow("Client Secret:", self.client_secret_input)
# Plex settings # Plex settings
plex_frame = QFrame() plex_frame = QFrame()
plex_layout = QFormLayout(plex_frame) plex_layout = QVBoxLayout(plex_frame)
plex_layout.setSpacing(10) plex_layout.setSpacing(8)
plex_title = QLabel("Plex") plex_title = QLabel("Plex")
plex_title.setFont(QFont("Arial", 12, QFont.Weight.Bold)) plex_title.setFont(QFont("Arial", 12, QFont.Weight.Bold))
plex_title.setStyleSheet("color: #e5a00d;") plex_title.setStyleSheet("color: #e5a00d;")
plex_layout.addWidget(plex_title)
# Server URL
plex_url_label = QLabel("Server URL:")
plex_url_label.setStyleSheet("color: #ffffff; font-size: 11px;")
plex_layout.addWidget(plex_url_label)
self.plex_url_input = QLineEdit() self.plex_url_input = QLineEdit()
self.plex_url_input.setStyleSheet(self.get_input_style()) self.plex_url_input.setStyleSheet(self.get_input_style())
self.plex_url_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.form_inputs['plex.base_url'] = self.plex_url_input self.form_inputs['plex.base_url'] = self.plex_url_input
plex_layout.addWidget(self.plex_url_input)
# Token
plex_token_label = QLabel("Token:")
plex_token_label.setStyleSheet("color: #ffffff; font-size: 11px;")
plex_layout.addWidget(plex_token_label)
self.plex_token_input = QLineEdit() self.plex_token_input = QLineEdit()
self.plex_token_input.setEchoMode(QLineEdit.EchoMode.Password) self.plex_token_input.setEchoMode(QLineEdit.EchoMode.Password)
self.plex_token_input.setStyleSheet(self.get_input_style()) self.plex_token_input.setStyleSheet(self.get_input_style())
self.plex_token_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.form_inputs['plex.token'] = self.plex_token_input self.form_inputs['plex.token'] = self.plex_token_input
plex_layout.addWidget(self.plex_token_input)
plex_layout.addRow(plex_title)
plex_layout.addRow("Server URL:", self.plex_url_input)
plex_layout.addRow("Token:", self.plex_token_input)
# Soulseek settings # Soulseek settings
soulseek_frame = QFrame() soulseek_frame = QFrame()
soulseek_layout = QFormLayout(soulseek_frame) soulseek_layout = QVBoxLayout(soulseek_frame)
soulseek_layout.setSpacing(10) soulseek_layout.setSpacing(8)
soulseek_title = QLabel("Soulseek") soulseek_title = QLabel("Soulseek")
soulseek_title.setFont(QFont("Arial", 12, QFont.Weight.Bold)) soulseek_title.setFont(QFont("Arial", 12, QFont.Weight.Bold))
soulseek_title.setStyleSheet("color: #ff6b35;") soulseek_title.setStyleSheet("color: #ff6b35;")
soulseek_layout.addWidget(soulseek_title)
# slskd URL
slskd_url_label = QLabel("slskd URL:")
slskd_url_label.setStyleSheet("color: #ffffff; font-size: 11px;")
soulseek_layout.addWidget(slskd_url_label)
self.slskd_url_input = QLineEdit() self.slskd_url_input = QLineEdit()
self.slskd_url_input.setStyleSheet(self.get_input_style()) self.slskd_url_input.setStyleSheet(self.get_input_style())
self.slskd_url_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.form_inputs['soulseek.slskd_url'] = self.slskd_url_input self.form_inputs['soulseek.slskd_url'] = self.slskd_url_input
soulseek_layout.addWidget(self.slskd_url_input)
# API Key
api_key_label = QLabel("API Key:")
api_key_label.setStyleSheet("color: #ffffff; font-size: 11px;")
soulseek_layout.addWidget(api_key_label)
self.api_key_input = QLineEdit() self.api_key_input = QLineEdit()
self.api_key_input.setPlaceholderText("Enter your slskd API key") self.api_key_input.setPlaceholderText("Enter your slskd API key")
self.api_key_input.setEchoMode(QLineEdit.EchoMode.Password) self.api_key_input.setEchoMode(QLineEdit.EchoMode.Password)
self.api_key_input.setStyleSheet(self.get_input_style()) self.api_key_input.setStyleSheet(self.get_input_style())
self.api_key_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.form_inputs['soulseek.api_key'] = self.api_key_input self.form_inputs['soulseek.api_key'] = self.api_key_input
soulseek_layout.addWidget(self.api_key_input)
soulseek_layout.addRow(soulseek_title)
soulseek_layout.addRow("slskd URL:", self.slskd_url_input)
soulseek_layout.addRow("API Key:", self.api_key_input)
api_layout.addWidget(spotify_frame) api_layout.addWidget(spotify_frame)
api_layout.addWidget(plex_frame) api_layout.addWidget(plex_frame)
@ -396,20 +446,23 @@ class SettingsPage(QWidget):
# Test connections # Test connections
test_layout = QHBoxLayout() test_layout = QHBoxLayout()
test_layout.setSpacing(10) test_layout.setSpacing(12)
test_spotify = QPushButton("Test Spotify") test_spotify = QPushButton("Test Spotify")
test_spotify.setFixedHeight(30) test_spotify.setFixedHeight(30)
test_spotify.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
test_spotify.clicked.connect(self.test_spotify_connection) test_spotify.clicked.connect(self.test_spotify_connection)
test_spotify.setStyleSheet(self.get_test_button_style()) test_spotify.setStyleSheet(self.get_test_button_style())
test_plex = QPushButton("Test Plex") test_plex = QPushButton("Test Plex")
test_plex.setFixedHeight(30) test_plex.setFixedHeight(30)
test_plex.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
test_plex.clicked.connect(self.test_plex_connection) test_plex.clicked.connect(self.test_plex_connection)
test_plex.setStyleSheet(self.get_test_button_style()) test_plex.setStyleSheet(self.get_test_button_style())
test_soulseek = QPushButton("Test Soulseek") test_soulseek = QPushButton("Test Soulseek")
test_soulseek.setFixedHeight(30) test_soulseek.setFixedHeight(30)
test_soulseek.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
test_soulseek.clicked.connect(self.test_soulseek_connection) test_soulseek.clicked.connect(self.test_soulseek_connection)
test_soulseek.setStyleSheet(self.get_test_button_style()) test_soulseek.setStyleSheet(self.get_test_button_style())
@ -427,13 +480,13 @@ class SettingsPage(QWidget):
def create_right_column(self): def create_right_column(self):
column = QWidget() column = QWidget()
layout = QVBoxLayout(column) layout = QVBoxLayout(column)
layout.setSpacing(20) layout.setSpacing(18)
# Download Settings # Download Settings
download_group = SettingsGroup("Download Settings") download_group = SettingsGroup("Download Settings")
download_layout = QVBoxLayout(download_group) download_layout = QVBoxLayout(download_group)
download_layout.setContentsMargins(20, 25, 20, 20) download_layout.setContentsMargins(16, 20, 16, 16)
download_layout.setSpacing(15) download_layout.setSpacing(12)
# Quality preference # Quality preference
quality_layout = QHBoxLayout() quality_layout = QHBoxLayout()
@ -444,10 +497,10 @@ class SettingsPage(QWidget):
quality_combo.addItems(["FLAC", "320 kbps MP3", "256 kbps MP3", "192 kbps MP3", "Any"]) quality_combo.addItems(["FLAC", "320 kbps MP3", "256 kbps MP3", "192 kbps MP3", "Any"])
quality_combo.setCurrentText("FLAC") quality_combo.setCurrentText("FLAC")
quality_combo.setStyleSheet(self.get_combo_style()) quality_combo.setStyleSheet(self.get_combo_style())
quality_combo.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
quality_layout.addWidget(quality_label) quality_layout.addWidget(quality_label)
quality_layout.addWidget(quality_combo) quality_layout.addWidget(quality_combo)
quality_layout.addStretch()
# Max concurrent downloads # Max concurrent downloads
concurrent_layout = QHBoxLayout() concurrent_layout = QHBoxLayout()
@ -458,10 +511,10 @@ class SettingsPage(QWidget):
concurrent_spin.setRange(1, 10) concurrent_spin.setRange(1, 10)
concurrent_spin.setValue(5) concurrent_spin.setValue(5)
concurrent_spin.setStyleSheet(self.get_spin_style()) concurrent_spin.setStyleSheet(self.get_spin_style())
concurrent_spin.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
concurrent_layout.addWidget(concurrent_label) concurrent_layout.addWidget(concurrent_label)
concurrent_layout.addWidget(concurrent_spin) concurrent_layout.addWidget(concurrent_spin)
concurrent_layout.addStretch()
# Download timeout # Download timeout
timeout_layout = QHBoxLayout() timeout_layout = QHBoxLayout()
@ -472,38 +525,62 @@ class SettingsPage(QWidget):
timeout_spin.setRange(30, 600) timeout_spin.setRange(30, 600)
timeout_spin.setValue(300) timeout_spin.setValue(300)
timeout_spin.setStyleSheet(self.get_spin_style()) timeout_spin.setStyleSheet(self.get_spin_style())
timeout_spin.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
timeout_layout.addWidget(timeout_label) timeout_layout.addWidget(timeout_label)
timeout_layout.addWidget(timeout_spin) timeout_layout.addWidget(timeout_spin)
timeout_layout.addStretch()
# Download path # Download path
path_layout = QHBoxLayout() path_container = QVBoxLayout()
path_label = QLabel("Download Path:") path_label = QLabel("Slskd Download Dir:")
path_label.setStyleSheet("color: #ffffff; font-size: 12px;") path_label.setStyleSheet("color: #ffffff; font-size: 12px;")
path_container.addWidget(path_label)
path_input_layout = QHBoxLayout()
self.download_path_input = QLineEdit("./downloads") self.download_path_input = QLineEdit("./downloads")
self.download_path_input.setStyleSheet(self.get_input_style()) self.download_path_input.setStyleSheet(self.get_input_style())
self.download_path_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
browse_btn = QPushButton("Browse") browse_btn = QPushButton("Browse")
browse_btn.setFixedSize(70, 30) browse_btn.setFixedSize(70, 30)
browse_btn.clicked.connect(self.browse_download_path) browse_btn.clicked.connect(self.browse_download_path)
browse_btn.setStyleSheet(self.get_test_button_style()) browse_btn.setStyleSheet(self.get_test_button_style())
path_layout.addWidget(path_label) path_input_layout.addWidget(self.download_path_input)
path_layout.addWidget(self.download_path_input) path_input_layout.addWidget(browse_btn)
path_layout.addWidget(browse_btn) path_container.addLayout(path_input_layout)
# Transfer folder path
transfer_path_container = QVBoxLayout()
transfer_path_label = QLabel("Matched Transfer Dir:")
transfer_path_label.setStyleSheet("color: #ffffff; font-size: 12px;")
transfer_path_container.addWidget(transfer_path_label)
transfer_input_layout = QHBoxLayout()
self.transfer_path_input = QLineEdit("./Transfer")
self.transfer_path_input.setStyleSheet(self.get_input_style())
self.transfer_path_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
transfer_browse_btn = QPushButton("Browse")
transfer_browse_btn.setFixedSize(70, 30)
transfer_browse_btn.clicked.connect(self.browse_transfer_path)
transfer_browse_btn.setStyleSheet(self.get_test_button_style())
transfer_input_layout.addWidget(self.transfer_path_input)
transfer_input_layout.addWidget(transfer_browse_btn)
transfer_path_container.addLayout(transfer_input_layout)
download_layout.addLayout(quality_layout) download_layout.addLayout(quality_layout)
download_layout.addLayout(concurrent_layout) download_layout.addLayout(concurrent_layout)
download_layout.addLayout(timeout_layout) download_layout.addLayout(timeout_layout)
download_layout.addLayout(path_layout) download_layout.addLayout(path_container)
download_layout.addLayout(transfer_path_container)
# Sync Settings # Sync Settings
sync_group = SettingsGroup("Sync Settings") sync_group = SettingsGroup("Sync Settings")
sync_layout = QVBoxLayout(sync_group) sync_layout = QVBoxLayout(sync_group)
sync_layout.setContentsMargins(20, 25, 20, 20) sync_layout.setContentsMargins(16, 20, 16, 16)
sync_layout.setSpacing(15) sync_layout.setSpacing(12)
# Auto-sync checkbox # Auto-sync checkbox
auto_sync = QCheckBox("Auto-sync playlists every hour") auto_sync = QCheckBox("Auto-sync playlists every hour")
@ -519,10 +596,10 @@ class SettingsPage(QWidget):
interval_spin.setRange(5, 1440) # 5 minutes to 24 hours interval_spin.setRange(5, 1440) # 5 minutes to 24 hours
interval_spin.setValue(60) interval_spin.setValue(60)
interval_spin.setStyleSheet(self.get_spin_style()) interval_spin.setStyleSheet(self.get_spin_style())
interval_spin.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
interval_layout.addWidget(interval_label) interval_layout.addWidget(interval_label)
interval_layout.addWidget(interval_spin) interval_layout.addWidget(interval_spin)
interval_layout.addStretch()
sync_layout.addWidget(auto_sync) sync_layout.addWidget(auto_sync)
sync_layout.addLayout(interval_layout) sync_layout.addLayout(interval_layout)
@ -530,8 +607,8 @@ class SettingsPage(QWidget):
# Logging Settings # Logging Settings
logging_group = SettingsGroup("Logging Settings") logging_group = SettingsGroup("Logging Settings")
logging_layout = QVBoxLayout(logging_group) logging_layout = QVBoxLayout(logging_group)
logging_layout.setContentsMargins(20, 25, 20, 20) logging_layout.setContentsMargins(16, 20, 16, 16)
logging_layout.setSpacing(15) logging_layout.setSpacing(12)
# Log level # Log level
log_level_layout = QHBoxLayout() log_level_layout = QHBoxLayout()
@ -542,24 +619,24 @@ class SettingsPage(QWidget):
log_level_combo.addItems(["DEBUG", "INFO", "WARNING", "ERROR"]) log_level_combo.addItems(["DEBUG", "INFO", "WARNING", "ERROR"])
log_level_combo.setCurrentText("DEBUG") log_level_combo.setCurrentText("DEBUG")
log_level_combo.setStyleSheet(self.get_combo_style()) log_level_combo.setStyleSheet(self.get_combo_style())
log_level_combo.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
log_level_layout.addWidget(log_level_label) log_level_layout.addWidget(log_level_label)
log_level_layout.addWidget(log_level_combo) log_level_layout.addWidget(log_level_combo)
log_level_layout.addStretch()
# Log file path # Log file path
log_path_layout = QHBoxLayout() log_path_container = QVBoxLayout()
log_path_label = QLabel("Log File Path:") log_path_label = QLabel("Log File Path:")
log_path_label.setStyleSheet("color: #ffffff; font-size: 12px;") log_path_label.setStyleSheet("color: #ffffff; font-size: 12px;")
log_path_container.addWidget(log_path_label)
log_path_input = QLineEdit("logs/app.log") log_path_input = QLineEdit("logs/app.log")
log_path_input.setStyleSheet(self.get_input_style()) log_path_input.setStyleSheet(self.get_input_style())
log_path_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
log_path_layout.addWidget(log_path_label) log_path_container.addWidget(log_path_input)
log_path_layout.addWidget(log_path_input)
logging_layout.addLayout(log_level_layout) logging_layout.addLayout(log_level_layout)
logging_layout.addLayout(log_path_layout) logging_layout.addLayout(log_path_container)
layout.addWidget(download_group) layout.addWidget(download_group)
layout.addWidget(sync_group) layout.addWidget(sync_group)