263 lines
10 KiB
Python
263 lines
10 KiB
Python
"""
|
|
settings_dialog.py — Indstillinger for LineDance Player.
|
|
Gemmes via QSettings og læses ved opstart.
|
|
"""
|
|
|
|
from PyQt6.QtWidgets import (
|
|
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
|
QPushButton, QComboBox, QSpinBox, QCheckBox, QFrame,
|
|
QTabWidget, QWidget, QFileDialog, QGroupBox, QFormLayout,
|
|
)
|
|
from PyQt6.QtCore import Qt, QSettings
|
|
|
|
|
|
SETTINGS_KEY_THEME = "appearance/dark_theme"
|
|
SETTINGS_KEY_DEMO_SEC = "playback/demo_seconds"
|
|
SETTINGS_KEY_MAIL_CLIENT = "mail/client" # "auto"|"thunderbird"|"outlook"|"mailto"
|
|
SETTINGS_KEY_MAIL_PATH = "mail/custom_path"
|
|
SETTINGS_KEY_AUTO_LOGIN = "online/auto_login"
|
|
SETTINGS_KEY_USERNAME = "online/username"
|
|
SETTINGS_KEY_PASSWORD = "online/password" # gemt i klartekst — ikke ideelt, men funktionelt
|
|
|
|
|
|
def load_settings() -> dict:
|
|
"""Indlæs alle indstillinger med fornuftige standardværdier."""
|
|
s = QSettings("LineDance", "Player")
|
|
return {
|
|
"dark_theme": s.value(SETTINGS_KEY_THEME, True, type=bool),
|
|
"demo_seconds": s.value(SETTINGS_KEY_DEMO_SEC, 10, type=int),
|
|
"mail_client": s.value(SETTINGS_KEY_MAIL_CLIENT, "auto"),
|
|
"mail_path": s.value(SETTINGS_KEY_MAIL_PATH, ""),
|
|
"auto_login": s.value(SETTINGS_KEY_AUTO_LOGIN, False, type=bool),
|
|
"username": s.value(SETTINGS_KEY_USERNAME, ""),
|
|
"password": s.value(SETTINGS_KEY_PASSWORD, ""),
|
|
}
|
|
|
|
|
|
def save_settings(values: dict):
|
|
s = QSettings("LineDance", "Player")
|
|
s.setValue(SETTINGS_KEY_THEME, values.get("dark_theme", True))
|
|
s.setValue(SETTINGS_KEY_DEMO_SEC, values.get("demo_seconds", 10))
|
|
s.setValue(SETTINGS_KEY_MAIL_CLIENT, values.get("mail_client", "auto"))
|
|
s.setValue(SETTINGS_KEY_MAIL_PATH, values.get("mail_path", ""))
|
|
s.setValue(SETTINGS_KEY_AUTO_LOGIN, values.get("auto_login", False))
|
|
s.setValue(SETTINGS_KEY_USERNAME, values.get("username", ""))
|
|
s.setValue(SETTINGS_KEY_PASSWORD, values.get("password", ""))
|
|
|
|
|
|
class SettingsDialog(QDialog):
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
self.setWindowTitle("Indstillinger")
|
|
self.setMinimumWidth(480)
|
|
self.setModal(True)
|
|
self._values = load_settings()
|
|
self._build_ui()
|
|
self._populate()
|
|
|
|
def _build_ui(self):
|
|
layout = QVBoxLayout(self)
|
|
layout.setContentsMargins(16, 16, 16, 16)
|
|
layout.setSpacing(12)
|
|
|
|
tabs = QTabWidget()
|
|
tabs.addTab(self._build_appearance_tab(), "🎨 Udseende")
|
|
tabs.addTab(self._build_playback_tab(), "▶ Afspilning")
|
|
tabs.addTab(self._build_mail_tab(), "✉ Mail")
|
|
tabs.addTab(self._build_online_tab(), "🌐 Online")
|
|
layout.addWidget(tabs)
|
|
|
|
# Knapper
|
|
btn_row = QHBoxLayout()
|
|
btn_row.addStretch()
|
|
btn_cancel = QPushButton("Annuller")
|
|
btn_cancel.clicked.connect(self.reject)
|
|
btn_row.addWidget(btn_cancel)
|
|
btn_save = QPushButton("💾 Gem indstillinger")
|
|
btn_save.setObjectName("btn_play")
|
|
btn_save.setDefault(True)
|
|
btn_save.clicked.connect(self._save_and_close)
|
|
btn_row.addWidget(btn_save)
|
|
layout.addLayout(btn_row)
|
|
|
|
# ── Fane: Udseende ────────────────────────────────────────────────────────
|
|
|
|
def _build_appearance_tab(self) -> QWidget:
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(12)
|
|
|
|
grp = QGroupBox("Standard tema")
|
|
grp_layout = QVBoxLayout(grp)
|
|
|
|
self._chk_dark = QCheckBox("Start med mørkt tema")
|
|
grp_layout.addWidget(self._chk_dark)
|
|
|
|
note = QLabel("Du kan altid skifte tema mens programmet kører via topbar-knappen.")
|
|
note.setObjectName("result_count")
|
|
note.setWordWrap(True)
|
|
grp_layout.addWidget(note)
|
|
layout.addWidget(grp)
|
|
layout.addStretch()
|
|
return tab
|
|
|
|
# ── Fane: Afspilning ──────────────────────────────────────────────────────
|
|
|
|
def _build_playback_tab(self) -> QWidget:
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(12)
|
|
|
|
grp = QGroupBox("Forspil (▶ N SEK knappen)")
|
|
grp_layout = QFormLayout(grp)
|
|
|
|
self._spin_demo = QSpinBox()
|
|
self._spin_demo.setRange(3, 60)
|
|
self._spin_demo.setSuffix(" sekunder")
|
|
self._spin_demo.setFixedWidth(140)
|
|
grp_layout.addRow("Forspil-længde:", self._spin_demo)
|
|
|
|
note = QLabel(
|
|
"Forspillet afspiller begyndelsen af sangen så arrangøren kan bekræfte\n"
|
|
"at det er den rigtige sang og dans inden eventet starter."
|
|
)
|
|
note.setObjectName("result_count")
|
|
note.setWordWrap(True)
|
|
grp_layout.addRow(note)
|
|
layout.addWidget(grp)
|
|
layout.addStretch()
|
|
return tab
|
|
|
|
# ── Fane: Mail ────────────────────────────────────────────────────────────
|
|
|
|
def _build_mail_tab(self) -> QWidget:
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(12)
|
|
|
|
grp = QGroupBox("Mailklient")
|
|
grp_layout = QFormLayout(grp)
|
|
|
|
self._mail_combo = QComboBox()
|
|
self._mail_combo.addItem("Auto-detekter (Thunderbird → Outlook → mailto:)", "auto")
|
|
self._mail_combo.addItem("Thunderbird", "thunderbird")
|
|
self._mail_combo.addItem("Outlook (Windows)", "outlook")
|
|
self._mail_combo.addItem("Brugerdefineret sti", "custom")
|
|
self._mail_combo.addItem("Kun mailto: (ingen vedhæftning)", "mailto")
|
|
self._mail_combo.currentIndexChanged.connect(self._on_mail_combo_changed)
|
|
grp_layout.addRow("Klient:", self._mail_combo)
|
|
|
|
path_row = QHBoxLayout()
|
|
self._mail_path = QLineEdit()
|
|
self._mail_path.setPlaceholderText("/usr/bin/thunderbird eller C:\\...\\thunderbird.exe")
|
|
path_row.addWidget(self._mail_path)
|
|
btn_browse = QPushButton("...")
|
|
btn_browse.setFixedWidth(32)
|
|
btn_browse.clicked.connect(self._browse_mail_path)
|
|
path_row.addWidget(btn_browse)
|
|
self._mail_path_row_widget = QWidget()
|
|
self._mail_path_row_widget.setLayout(path_row)
|
|
grp_layout.addRow("Sti:", self._mail_path_row_widget)
|
|
|
|
note = QLabel(
|
|
"Med Thunderbird og Outlook åbnes et nyt compose-vindue med filen vedhæftet.\n"
|
|
"mailto: åbner standard-mailprogrammet men uden automatisk vedhæftning."
|
|
)
|
|
note.setObjectName("result_count")
|
|
note.setWordWrap(True)
|
|
grp_layout.addRow(note)
|
|
layout.addWidget(grp)
|
|
layout.addStretch()
|
|
return tab
|
|
|
|
def _on_mail_combo_changed(self, idx: int):
|
|
is_custom = self._mail_combo.currentData() == "custom"
|
|
self._mail_path_row_widget.setVisible(is_custom)
|
|
|
|
def _browse_mail_path(self):
|
|
path, _ = QFileDialog.getOpenFileName(self, "Vælg mailklient")
|
|
if path:
|
|
self._mail_path.setText(path)
|
|
|
|
# ── Fane: Online ──────────────────────────────────────────────────────────
|
|
|
|
def _build_online_tab(self) -> QWidget:
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(12)
|
|
|
|
grp = QGroupBox("Automatisk login ved opstart")
|
|
grp_layout = QFormLayout(grp)
|
|
|
|
self._chk_auto_login = QCheckBox("Log automatisk ind når programmet starter")
|
|
self._chk_auto_login.stateChanged.connect(self._on_auto_login_changed)
|
|
grp_layout.addRow(self._chk_auto_login)
|
|
|
|
self._user_input = QLineEdit()
|
|
self._user_input.setPlaceholderText("dit-brugernavn")
|
|
grp_layout.addRow("Brugernavn:", self._user_input)
|
|
|
|
self._pass_input = QLineEdit()
|
|
self._pass_input.setEchoMode(QLineEdit.EchoMode.Password)
|
|
self._pass_input.setPlaceholderText("••••••••")
|
|
grp_layout.addRow("Kodeord:", self._pass_input)
|
|
|
|
note = QLabel(
|
|
"⚠ Kodeordet gemmes lokalt på denne computer.\n"
|
|
"Brug kun dette på en personlig maskine."
|
|
)
|
|
note.setObjectName("result_count")
|
|
note.setWordWrap(True)
|
|
grp_layout.addRow(note)
|
|
layout.addWidget(grp)
|
|
layout.addStretch()
|
|
return tab
|
|
|
|
def _on_auto_login_changed(self, state: int):
|
|
enabled = state == Qt.CheckState.Checked.value
|
|
self._user_input.setEnabled(enabled)
|
|
self._pass_input.setEnabled(enabled)
|
|
|
|
# ── Populer fra gemte værdier ─────────────────────────────────────────────
|
|
|
|
def _populate(self):
|
|
v = self._values
|
|
self._chk_dark.setChecked(v.get("dark_theme", True))
|
|
self._spin_demo.setValue(v.get("demo_seconds", 10))
|
|
|
|
# Mail
|
|
client = v.get("mail_client", "auto")
|
|
for i in range(self._mail_combo.count()):
|
|
if self._mail_combo.itemData(i) == client:
|
|
self._mail_combo.setCurrentIndex(i)
|
|
break
|
|
self._mail_path.setText(v.get("mail_path", ""))
|
|
self._on_mail_combo_changed(self._mail_combo.currentIndex())
|
|
|
|
# Online
|
|
auto = v.get("auto_login", False)
|
|
self._chk_auto_login.setChecked(auto)
|
|
self._user_input.setText(v.get("username", ""))
|
|
self._pass_input.setText(v.get("password", ""))
|
|
self._user_input.setEnabled(auto)
|
|
self._pass_input.setEnabled(auto)
|
|
|
|
# ── Gem ───────────────────────────────────────────────────────────────────
|
|
|
|
def _save_and_close(self):
|
|
values = {
|
|
"dark_theme": self._chk_dark.isChecked(),
|
|
"demo_seconds": self._spin_demo.value(),
|
|
"mail_client": self._mail_combo.currentData(),
|
|
"mail_path": self._mail_path.text().strip(),
|
|
"auto_login": self._chk_auto_login.isChecked(),
|
|
"username": self._user_input.text().strip(),
|
|
"password": self._pass_input.text(),
|
|
}
|
|
save_settings(values)
|
|
self._values = values
|
|
self.accept()
|
|
|
|
def get_values(self) -> dict:
|
|
return self._values
|