227 lines
8.2 KiB
Python
227 lines
8.2 KiB
Python
"""
|
|
dance_info_dialog.py — Rediger info om en dans: koreograf, video, step sheet, noter.
|
|
"""
|
|
|
|
from PyQt6.QtWidgets import (
|
|
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
|
QPushButton, QTextEdit, QComboBox, QFrame, QMessageBox,
|
|
QTabWidget, QWidget,
|
|
)
|
|
from PyQt6.QtCore import Qt, QUrl
|
|
from PyQt6.QtGui import QDesktopServices
|
|
|
|
|
|
class DanceInfoDialog(QDialog):
|
|
"""Vis og rediger info om danse tilknyttet en sang."""
|
|
|
|
def __init__(self, song: dict, parent=None):
|
|
super().__init__(parent)
|
|
self._song = song
|
|
self._dances = [] # [{dance_id, name, level_name, ...}]
|
|
self._current_idx = 0
|
|
|
|
self.setWindowTitle(f"Dans-info — {song.get('title', '')}")
|
|
self.setMinimumSize(560, 420)
|
|
self.resize(620, 460)
|
|
|
|
self._load_dances()
|
|
self._build_ui()
|
|
if self._dances:
|
|
self._show_dance(0)
|
|
|
|
def _load_dances(self):
|
|
try:
|
|
from local.local_db import get_dances_for_song, get_alt_dances_for_song, new_conn
|
|
conn = new_conn()
|
|
|
|
rows = conn.execute("""
|
|
SELECT d.id, d.name, d.level_id, d.choreographer,
|
|
d.video_url, d.stepsheet_url, d.notes,
|
|
dl.name as level_name
|
|
FROM song_dances sd
|
|
JOIN dances d ON d.id = sd.dance_id
|
|
LEFT JOIN dance_levels dl ON dl.id = d.level_id
|
|
WHERE sd.song_id=? ORDER BY sd.dance_order
|
|
""", (self._song.get("id"),)).fetchall()
|
|
|
|
for row in rows:
|
|
self._dances.append({
|
|
"dance_id": row["id"],
|
|
"name": row["name"],
|
|
"level_name": row["level_name"] or "",
|
|
"choreographer": row["choreographer"] or "",
|
|
"video_url": row["video_url"] or "",
|
|
"stepsheet_url": row["stepsheet_url"] or "",
|
|
"notes": row["notes"] or "",
|
|
"is_alt": False,
|
|
})
|
|
|
|
# Alternativ-danse
|
|
alt_rows = conn.execute("""
|
|
SELECT d.id, d.name, d.level_id, d.choreographer,
|
|
d.video_url, d.stepsheet_url, d.notes,
|
|
dl.name as level_name
|
|
FROM song_alt_dances sad
|
|
JOIN dances d ON d.id = sad.dance_id
|
|
LEFT JOIN dance_levels dl ON dl.id = d.level_id
|
|
WHERE sad.song_id=? ORDER BY d.name
|
|
""", (self._song.get("id"),)).fetchall()
|
|
|
|
for row in alt_rows:
|
|
self._dances.append({
|
|
"dance_id": row["id"],
|
|
"name": row["name"],
|
|
"level_name": row["level_name"] or "",
|
|
"choreographer": row["choreographer"] or "",
|
|
"video_url": row["video_url"] or "",
|
|
"stepsheet_url": row["stepsheet_url"] or "",
|
|
"notes": row["notes"] or "",
|
|
"is_alt": True,
|
|
})
|
|
conn.close()
|
|
except Exception as e:
|
|
print(f"DanceInfoDialog load fejl: {e}")
|
|
|
|
def _build_ui(self):
|
|
layout = QVBoxLayout(self)
|
|
layout.setContentsMargins(12, 12, 12, 12)
|
|
layout.setSpacing(8)
|
|
|
|
# Sang-info
|
|
info = QFrame()
|
|
info.setObjectName("track_display")
|
|
il = QHBoxLayout(info)
|
|
il.setContentsMargins(10, 8, 10, 8)
|
|
lbl = QLabel(self._song.get("title", "—"))
|
|
lbl.setObjectName("track_title")
|
|
il.addWidget(lbl, stretch=1)
|
|
layout.addWidget(info)
|
|
|
|
if not self._dances:
|
|
layout.addWidget(QLabel("Ingen danse tagget på denne sang."))
|
|
btn_close = QPushButton("Luk")
|
|
btn_close.clicked.connect(self.reject)
|
|
layout.addWidget(btn_close)
|
|
return
|
|
|
|
# Dans-vælger
|
|
top = QHBoxLayout()
|
|
top.addWidget(QLabel("Dans:"))
|
|
self._dance_combo = QComboBox()
|
|
for d in self._dances:
|
|
prefix = "↪ " if d["is_alt"] else ""
|
|
lvl = f" / {d['level_name']}" if d["level_name"] else ""
|
|
self._dance_combo.addItem(f"{prefix}{d['name']}{lvl}")
|
|
self._dance_combo.currentIndexChanged.connect(self._on_dance_changed)
|
|
top.addWidget(self._dance_combo, stretch=1)
|
|
layout.addLayout(top)
|
|
|
|
# Formular
|
|
form_frame = QFrame()
|
|
form_frame.setObjectName("track_display")
|
|
form = QVBoxLayout(form_frame)
|
|
form.setContentsMargins(12, 10, 12, 10)
|
|
form.setSpacing(8)
|
|
|
|
# Koreograf
|
|
row1 = QHBoxLayout()
|
|
row1.addWidget(QLabel("Koreograf:"))
|
|
self._choreo = QLineEdit()
|
|
self._choreo.setPlaceholderText("Koreografens navn...")
|
|
row1.addWidget(self._choreo)
|
|
form.addLayout(row1)
|
|
|
|
# Step sheet URL
|
|
row2 = QHBoxLayout()
|
|
row2.addWidget(QLabel("Step sheet:"))
|
|
self._stepsheet = QLineEdit()
|
|
self._stepsheet.setPlaceholderText("https://www.copperknob.co.uk/...")
|
|
row2.addWidget(self._stepsheet)
|
|
btn_ss = QPushButton("↗")
|
|
btn_ss.setFixedWidth(28)
|
|
btn_ss.setToolTip("Åbn i browser")
|
|
btn_ss.clicked.connect(lambda: self._open_url(self._stepsheet.text()))
|
|
row2.addWidget(btn_ss)
|
|
form.addLayout(row2)
|
|
|
|
# Video URL
|
|
row3 = QHBoxLayout()
|
|
row3.addWidget(QLabel("Video:"))
|
|
self._video = QLineEdit()
|
|
self._video.setPlaceholderText("https://www.youtube.com/...")
|
|
row3.addWidget(self._video)
|
|
btn_v = QPushButton("↗")
|
|
btn_v.setFixedWidth(28)
|
|
btn_v.setToolTip("Åbn i browser")
|
|
btn_v.clicked.connect(lambda: self._open_url(self._video.text()))
|
|
row3.addWidget(btn_v)
|
|
form.addLayout(row3)
|
|
|
|
# Noter
|
|
form.addWidget(QLabel("Noter:"))
|
|
self._notes = QTextEdit()
|
|
self._notes.setPlaceholderText("Egne noter om dansen...")
|
|
self._notes.setMaximumHeight(80)
|
|
form.addWidget(self._notes)
|
|
|
|
layout.addWidget(form_frame, stretch=1)
|
|
|
|
# Knapper
|
|
btn_row = QHBoxLayout()
|
|
btn_row.addStretch()
|
|
btn_cancel = QPushButton("Luk")
|
|
btn_cancel.clicked.connect(self.reject)
|
|
btn_row.addWidget(btn_cancel)
|
|
btn_save = QPushButton("💾 Gem")
|
|
btn_save.setObjectName("btn_play")
|
|
btn_save.clicked.connect(self._save)
|
|
btn_row.addWidget(btn_save)
|
|
layout.addLayout(btn_row)
|
|
|
|
def _on_dance_changed(self, idx: int):
|
|
self._save_to_cache(self._current_idx)
|
|
self._current_idx = idx
|
|
self._show_dance(idx)
|
|
|
|
def _show_dance(self, idx: int):
|
|
if not 0 <= idx < len(self._dances):
|
|
return
|
|
d = self._dances[idx]
|
|
self._choreo.setText(d["choreographer"])
|
|
self._stepsheet.setText(d["stepsheet_url"])
|
|
self._video.setText(d["video_url"])
|
|
self._notes.setPlainText(d["notes"])
|
|
|
|
def _save_to_cache(self, idx: int):
|
|
"""Gem UI-værdier til cache så de ikke mistes ved dans-skift."""
|
|
if not 0 <= idx < len(self._dances):
|
|
return
|
|
self._dances[idx]["choreographer"] = self._choreo.text().strip()
|
|
self._dances[idx]["stepsheet_url"] = self._stepsheet.text().strip()
|
|
self._dances[idx]["video_url"] = self._video.text().strip()
|
|
self._dances[idx]["notes"] = self._notes.toPlainText().strip()
|
|
|
|
def _save(self):
|
|
self._save_to_cache(self._current_idx)
|
|
try:
|
|
from local.local_db import update_dance_info
|
|
for d in self._dances:
|
|
update_dance_info(
|
|
d["dance_id"],
|
|
choreographer = d["choreographer"],
|
|
video_url = d["video_url"],
|
|
stepsheet_url = d["stepsheet_url"],
|
|
notes = d["notes"],
|
|
)
|
|
self.accept()
|
|
except Exception as e:
|
|
QMessageBox.warning(self, "Fejl", f"Kunne ikke gemme: {e}")
|
|
|
|
def _open_url(self, url: str):
|
|
url = url.strip()
|
|
if not url:
|
|
return
|
|
if not url.startswith("http"):
|
|
url = "https://" + url
|
|
QDesktopServices.openUrl(QUrl(url))
|