Initial commit
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
"""
|
||||
Server connection dialog for adding/editing Navidrome servers
|
||||
"""
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QFormLayout,
|
||||
QLineEdit, QPushButton, QLabel, QMessageBox, QCheckBox
|
||||
)
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
from src.api.client import SubsonicClient, SubsonicError
|
||||
from src.config.settings import Settings
|
||||
|
||||
|
||||
class ServerDialog(QDialog):
|
||||
"""Dialog for configuring a Navidrome server connection"""
|
||||
|
||||
def __init__(self, settings: Settings, serverName: str = None, parent=None):
|
||||
"""
|
||||
Initialize the server dialog
|
||||
|
||||
Args:
|
||||
settings: Application settings instance
|
||||
serverName: Name of existing server to edit (None for new server)
|
||||
parent: Parent widget
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.settings = settings
|
||||
self.editingServer = serverName
|
||||
self.isNew = serverName is None
|
||||
|
||||
self.setWindowTitle("Add Server" if self.isNew else "Edit Server")
|
||||
self.setModal(True)
|
||||
self.setMinimumWidth(400)
|
||||
|
||||
self.setupUi()
|
||||
self.loadExistingData()
|
||||
|
||||
def setupUi(self):
|
||||
"""Setup the dialog UI"""
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
# Form layout for inputs
|
||||
formLayout = QFormLayout()
|
||||
|
||||
# Server name
|
||||
self.nameEdit = QLineEdit()
|
||||
self.nameEdit.setAccessibleName("Server Name")
|
||||
self.nameEdit.setAccessibleDescription("A friendly name for this server")
|
||||
nameLabel = QLabel("&Name:")
|
||||
nameLabel.setBuddy(self.nameEdit)
|
||||
formLayout.addRow(nameLabel, self.nameEdit)
|
||||
|
||||
# Server URL
|
||||
self.urlEdit = QLineEdit()
|
||||
self.urlEdit.setAccessibleName("Server URL")
|
||||
self.urlEdit.setAccessibleDescription("The full URL to your Navidrome server, for example https://music.example.com")
|
||||
self.urlEdit.setPlaceholderText("https://music.example.com")
|
||||
urlLabel = QLabel("&URL:")
|
||||
urlLabel.setBuddy(self.urlEdit)
|
||||
formLayout.addRow(urlLabel, self.urlEdit)
|
||||
|
||||
# Username
|
||||
self.usernameEdit = QLineEdit()
|
||||
self.usernameEdit.setAccessibleName("Username")
|
||||
usernameLabel = QLabel("U&sername:")
|
||||
usernameLabel.setBuddy(self.usernameEdit)
|
||||
formLayout.addRow(usernameLabel, self.usernameEdit)
|
||||
|
||||
# Password
|
||||
self.passwordEdit = QLineEdit()
|
||||
self.passwordEdit.setEchoMode(QLineEdit.Password)
|
||||
self.passwordEdit.setAccessibleName("Password")
|
||||
passwordLabel = QLabel("&Password:")
|
||||
passwordLabel.setBuddy(self.passwordEdit)
|
||||
formLayout.addRow(passwordLabel, self.passwordEdit)
|
||||
|
||||
# Set as default checkbox
|
||||
self.defaultCheckbox = QCheckBox("Set as &default server")
|
||||
self.defaultCheckbox.setAccessibleName("Set as default server")
|
||||
formLayout.addRow("", self.defaultCheckbox)
|
||||
|
||||
layout.addLayout(formLayout)
|
||||
|
||||
# Status label for connection test
|
||||
self.statusLabel = QLabel("")
|
||||
self.statusLabel.setAccessibleName("Connection Status")
|
||||
self.statusLabel.setWordWrap(True)
|
||||
layout.addWidget(self.statusLabel)
|
||||
|
||||
# Button layout
|
||||
buttonLayout = QHBoxLayout()
|
||||
|
||||
self.testButton = QPushButton("&Test Connection")
|
||||
self.testButton.setAccessibleName("Test Connection")
|
||||
self.testButton.clicked.connect(self.testConnection)
|
||||
buttonLayout.addWidget(self.testButton)
|
||||
|
||||
buttonLayout.addStretch()
|
||||
|
||||
self.cancelButton = QPushButton("&Cancel")
|
||||
self.cancelButton.setAccessibleName("Cancel")
|
||||
self.cancelButton.clicked.connect(self.reject)
|
||||
buttonLayout.addWidget(self.cancelButton)
|
||||
|
||||
self.saveButton = QPushButton("&Save")
|
||||
self.saveButton.setAccessibleName("Save")
|
||||
self.saveButton.setDefault(True)
|
||||
self.saveButton.clicked.connect(self.saveServer)
|
||||
buttonLayout.addWidget(self.saveButton)
|
||||
|
||||
layout.addLayout(buttonLayout)
|
||||
|
||||
# Set initial focus
|
||||
self.nameEdit.setFocus()
|
||||
|
||||
def loadExistingData(self):
|
||||
"""Load existing server data if editing"""
|
||||
if not self.isNew and self.editingServer:
|
||||
server = self.settings.getServer(self.editingServer)
|
||||
if server:
|
||||
self.nameEdit.setText(self.editingServer)
|
||||
self.nameEdit.setReadOnly(True) # Can't change name when editing
|
||||
self.urlEdit.setText(server.get('url', ''))
|
||||
self.usernameEdit.setText(server.get('username', ''))
|
||||
self.passwordEdit.setText(server.get('password', ''))
|
||||
|
||||
# Check if this is the default server
|
||||
defaultServer = self.settings.getDefaultServer()
|
||||
self.defaultCheckbox.setChecked(defaultServer == self.editingServer)
|
||||
|
||||
def testConnection(self):
|
||||
"""Test connection to the server"""
|
||||
url = self.urlEdit.text().strip()
|
||||
username = self.usernameEdit.text().strip()
|
||||
password = self.passwordEdit.text()
|
||||
|
||||
if not url or not username or not password:
|
||||
self.statusLabel.setText("Please fill in all fields")
|
||||
return
|
||||
|
||||
self.statusLabel.setText("Testing connection...")
|
||||
self.testButton.setEnabled(False)
|
||||
|
||||
try:
|
||||
client = SubsonicClient(url, username, password)
|
||||
if client.ping():
|
||||
self.statusLabel.setText("Connection successful!")
|
||||
else:
|
||||
self.statusLabel.setText("Connection failed: Invalid response")
|
||||
except SubsonicError as e:
|
||||
self.statusLabel.setText(f"Connection failed: {e.message}")
|
||||
except Exception as e:
|
||||
self.statusLabel.setText(f"Connection failed: {str(e)}")
|
||||
finally:
|
||||
self.testButton.setEnabled(True)
|
||||
|
||||
def saveServer(self):
|
||||
"""Save the server configuration"""
|
||||
name = self.nameEdit.text().strip()
|
||||
url = self.urlEdit.text().strip()
|
||||
username = self.usernameEdit.text().strip()
|
||||
password = self.passwordEdit.text()
|
||||
|
||||
# Validate inputs
|
||||
if not name:
|
||||
QMessageBox.warning(self, "Validation Error", "Please enter a server name")
|
||||
self.nameEdit.setFocus()
|
||||
return
|
||||
|
||||
if not url:
|
||||
QMessageBox.warning(self, "Validation Error", "Please enter the server URL")
|
||||
self.urlEdit.setFocus()
|
||||
return
|
||||
|
||||
if not username:
|
||||
QMessageBox.warning(self, "Validation Error", "Please enter a username")
|
||||
self.usernameEdit.setFocus()
|
||||
return
|
||||
|
||||
if not password:
|
||||
QMessageBox.warning(self, "Validation Error", "Please enter a password")
|
||||
self.passwordEdit.setFocus()
|
||||
return
|
||||
|
||||
# Check for duplicate name when adding new server
|
||||
if self.isNew and self.settings.getServer(name):
|
||||
QMessageBox.warning(
|
||||
self, "Validation Error",
|
||||
f"A server named '{name}' already exists. Please choose a different name."
|
||||
)
|
||||
self.nameEdit.setFocus()
|
||||
return
|
||||
|
||||
# Save the server
|
||||
self.settings.addServer(name, url, username, password)
|
||||
|
||||
# Set as default if checked
|
||||
if self.defaultCheckbox.isChecked():
|
||||
self.settings.setDefaultServer(name)
|
||||
|
||||
self.accept()
|
||||
|
||||
def getServerName(self) -> str:
|
||||
"""Get the name of the saved server"""
|
||||
return self.nameEdit.text().strip()
|
||||
Reference in New Issue
Block a user