Rettelsaer
This commit is contained in:
@@ -130,6 +130,12 @@ class PlaylistBrowserDialog(QDialog):
|
||||
btn_tags = QPushButton("🏷 Rediger tags")
|
||||
btn_tags.clicked.connect(self._edit_tags)
|
||||
btn_row.addWidget(btn_tags)
|
||||
btn_share = QPushButton("↗ Del...")
|
||||
btn_share.clicked.connect(self._share_selected)
|
||||
btn_row.addWidget(btn_share)
|
||||
btn_shared = QPushButton("🌐 Hent delte")
|
||||
btn_shared.clicked.connect(self._fetch_shared)
|
||||
btn_row.addWidget(btn_shared)
|
||||
|
||||
btn_row.addStretch()
|
||||
btn_cancel = QPushButton("Annuller")
|
||||
@@ -344,3 +350,167 @@ class PlaylistBrowserDialog(QDialog):
|
||||
self._load_data()
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Fejl", f"Kunne ikke slette: {e}")
|
||||
|
||||
def _share_selected(self):
|
||||
"""Åbn del-dialog for den valgte playliste."""
|
||||
item = self._list.currentItem()
|
||||
if not item:
|
||||
QMessageBox.information(self, "Del", "Vælg en playliste først.")
|
||||
return
|
||||
pl = item.data(Qt.ItemDataRole.UserRole)
|
||||
if not isinstance(pl, dict):
|
||||
return
|
||||
|
||||
# Hent server-info fra settings
|
||||
try:
|
||||
from ui.settings_dialog import load_settings
|
||||
s = load_settings()
|
||||
server_url = s.get("server_url", "")
|
||||
token = self._get_token()
|
||||
if not token:
|
||||
QMessageBox.warning(self, "Ikke logget ind",
|
||||
"Du skal være logget ind for at dele.")
|
||||
return
|
||||
|
||||
# Find server-ID for playlisten
|
||||
server_id = pl.get("api_project_id")
|
||||
if not server_id:
|
||||
QMessageBox.warning(self, "Ikke synkroniseret",
|
||||
"Synkroniser playlisten til serveren først\n"
|
||||
"(Filer → Synkroniser nu).")
|
||||
return
|
||||
|
||||
from ui.share_dialog import ShareDialog
|
||||
dlg = ShareDialog(server_id, pl["name"], server_url, token,
|
||||
parent=self)
|
||||
dlg.exec()
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Fejl", str(e))
|
||||
|
||||
def _get_token(self) -> str | None:
|
||||
"""Hent JWT token fra main_window."""
|
||||
mw = self.parent()
|
||||
while mw and not hasattr(mw, "_api_token"):
|
||||
mw = mw.parent()
|
||||
return getattr(mw, "_api_token", None) if mw else None
|
||||
|
||||
def _fetch_shared(self):
|
||||
"""Hent playlister der er delt med mig fra serveren."""
|
||||
try:
|
||||
from ui.settings_dialog import load_settings
|
||||
s = load_settings()
|
||||
server_url = s.get("server_url", "").rstrip("/")
|
||||
token = self._get_token()
|
||||
if not token:
|
||||
QMessageBox.warning(self, "Ikke logget ind",
|
||||
"Du skal være logget ind for at hente delte lister.")
|
||||
return
|
||||
|
||||
import urllib.request, json
|
||||
req = urllib.request.Request(
|
||||
f"{server_url}/sharing/playlists/shared-with-me",
|
||||
headers={"Authorization": f"Bearer {token}"}
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=10) as resp:
|
||||
shared = json.loads(resp.read())
|
||||
|
||||
if not shared:
|
||||
QMessageBox.information(self, "Ingen delte lister",
|
||||
"Ingen playlister er delt med dig.")
|
||||
return
|
||||
|
||||
# Vis valgdialog
|
||||
from PyQt6.QtWidgets import QInputDialog
|
||||
options = [
|
||||
f"{p['name']} (af {p['owner']}, {p['song_count']} sange, {p['permission']})"
|
||||
for p in shared
|
||||
]
|
||||
choice, ok = QInputDialog.getItem(
|
||||
self, "Hent delt playliste",
|
||||
"Vælg en playliste at hente:",
|
||||
options, 0, False
|
||||
)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
idx = options.index(choice)
|
||||
chosen = shared[idx]
|
||||
|
||||
# Hent indholdet
|
||||
req2 = urllib.request.Request(
|
||||
f"{server_url}/sharing/playlists/{chosen['project_id']}",
|
||||
headers={"Authorization": f"Bearer {token}"}
|
||||
)
|
||||
with urllib.request.urlopen(req2, timeout=10) as resp:
|
||||
pl_data = json.loads(resp.read())
|
||||
|
||||
self._import_shared_playlist(pl_data, server_url, token,
|
||||
permission=chosen.get("permission", "view"))
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Fejl", f"Kunne ikke hente: {e}")
|
||||
|
||||
def _import_shared_playlist(self, pl_data: dict, server_url: str, token: str,
|
||||
permission: str = "view"):
|
||||
"""Importer en delt playliste som en linket liste."""
|
||||
import sqlite3
|
||||
from local.local_db import DB_PATH, get_db, add_song_to_playlist
|
||||
|
||||
name = pl_data["name"]
|
||||
server_id = pl_data["id"]
|
||||
|
||||
conn = sqlite3.connect(str(DB_PATH))
|
||||
conn.row_factory = sqlite3.Row
|
||||
|
||||
# Tjek om listen allerede er linket
|
||||
existing = conn.execute(
|
||||
"SELECT id FROM playlists WHERE api_project_id=?", (server_id,)
|
||||
).fetchone()
|
||||
conn.close()
|
||||
|
||||
if existing:
|
||||
# Opdater eksisterende
|
||||
pl_id = existing["id"]
|
||||
with get_db() as c:
|
||||
c.execute("DELETE FROM playlist_songs WHERE playlist_id=?", (pl_id,))
|
||||
else:
|
||||
# Opret ny linket playliste
|
||||
with get_db() as c:
|
||||
c.execute(
|
||||
"INSERT INTO playlists (name, api_project_id, is_linked, server_permission) "
|
||||
"VALUES (?, ?, 1, ?)",
|
||||
(name, server_id, permission)
|
||||
)
|
||||
pl_id = c.execute("SELECT last_insert_rowid()").fetchone()[0]
|
||||
|
||||
# Indsæt sange med sang-matching
|
||||
matched = 0
|
||||
with get_db() as c:
|
||||
for song_data in pl_data.get("songs", []):
|
||||
local = c.execute(
|
||||
"SELECT id FROM songs WHERE title=? AND artist=? AND file_missing=0",
|
||||
(song_data["title"], song_data["artist"])
|
||||
).fetchone()
|
||||
if local:
|
||||
c.execute(
|
||||
"INSERT INTO playlist_songs "
|
||||
"(playlist_id, song_id, position, status, is_workshop, dance_override) "
|
||||
"VALUES (?,?,?,?,?,?)",
|
||||
(pl_id, local["id"], song_data["position"],
|
||||
song_data.get("status", "pending"),
|
||||
1 if song_data.get("is_workshop") else 0,
|
||||
song_data.get("dance_override") or "")
|
||||
)
|
||||
matched += 1
|
||||
|
||||
self._load_data()
|
||||
self.playlist_selected.emit(pl_id, name)
|
||||
perm_text = {"view": "se", "copy": "kopiere", "edit": "redigere"}.get(
|
||||
permission, permission
|
||||
)
|
||||
QMessageBox.information(
|
||||
self, "Linket",
|
||||
f"'{name}' er nu linket til server-listen.\n"
|
||||
f"Du har rettighed til at {perm_text} listen.\n\n"
|
||||
f"{matched} af {len(pl_data.get('songs', []))} sange fundet lokalt."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user