Bedre sync
This commit is contained in:
@@ -53,6 +53,8 @@ class SongAltDanceData(BaseModel):
|
|||||||
|
|
||||||
class PlaylistSongData(BaseModel):
|
class PlaylistSongData(BaseModel):
|
||||||
song_local_id: str
|
song_local_id: str
|
||||||
|
song_title: str = ""
|
||||||
|
song_artist: str = ""
|
||||||
position: int
|
position: int
|
||||||
status: str = "pending"
|
status: str = "pending"
|
||||||
is_workshop: bool = False
|
is_workshop: bool = False
|
||||||
@@ -182,7 +184,15 @@ def push(
|
|||||||
playlist_id_map[pl.local_id] = project.id
|
playlist_id_map[pl.local_id] = project.id
|
||||||
|
|
||||||
for ps in pl.songs:
|
for ps in pl.songs:
|
||||||
|
# Prøv først via song_id_map (lokal ID)
|
||||||
song_id = song_id_map.get(ps.song_local_id)
|
song_id = song_id_map.get(ps.song_local_id)
|
||||||
|
# Fallback: match på titel+artist
|
||||||
|
if not song_id and ps.song_title:
|
||||||
|
existing_song = db.query(Song).filter_by(
|
||||||
|
title=ps.song_title, artist=ps.song_artist
|
||||||
|
).first()
|
||||||
|
if existing_song:
|
||||||
|
song_id = existing_song.id
|
||||||
if not song_id:
|
if not song_id:
|
||||||
continue
|
continue
|
||||||
proj_song = ProjectSong(
|
proj_song = ProjectSong(
|
||||||
|
|||||||
@@ -189,11 +189,16 @@ class SyncManager:
|
|||||||
).fetchall():
|
).fetchall():
|
||||||
pl_songs = []
|
pl_songs = []
|
||||||
for ps in conn.execute("""
|
for ps in conn.execute("""
|
||||||
SELECT song_id, position, status, is_workshop, dance_override
|
SELECT s.id, s.title, s.artist,
|
||||||
FROM playlist_songs WHERE playlist_id=? ORDER BY position
|
ps.position, ps.status, ps.is_workshop, ps.dance_override
|
||||||
|
FROM playlist_songs ps
|
||||||
|
JOIN songs s ON s.id = ps.song_id
|
||||||
|
WHERE ps.playlist_id=? ORDER BY ps.position
|
||||||
""", (pl["id"],)).fetchall():
|
""", (pl["id"],)).fetchall():
|
||||||
pl_songs.append({
|
pl_songs.append({
|
||||||
"song_local_id": ps["song_id"] or "",
|
"song_local_id": str(ps["id"]),
|
||||||
|
"song_title": ps["title"] or "",
|
||||||
|
"song_artist": ps["artist"] or "",
|
||||||
"position": int(ps["position"] or 1),
|
"position": int(ps["position"] or 1),
|
||||||
"status": ps["status"] or "pending",
|
"status": ps["status"] or "pending",
|
||||||
"is_workshop": bool(ps["is_workshop"]),
|
"is_workshop": bool(ps["is_workshop"]),
|
||||||
|
|||||||
@@ -25,8 +25,12 @@ def main():
|
|||||||
if _sys.platform == "win32":
|
if _sys.platform == "win32":
|
||||||
from PyQt6.QtCore import qInstallMessageHandler, QtMsgType
|
from PyQt6.QtCore import qInstallMessageHandler, QtMsgType
|
||||||
def _qt_msg_handler(msg_type, context, message):
|
def _qt_msg_handler(msg_type, context, message):
|
||||||
if "registerTimer" in message or "Unhandled scheme" in message:
|
if any(x in message for x in [
|
||||||
return # ignorer
|
"registerTimer", "Unhandled scheme",
|
||||||
|
"Point size <= 0", "setPointSize",
|
||||||
|
"QFont::",
|
||||||
|
]):
|
||||||
|
return
|
||||||
print(message)
|
print(message)
|
||||||
qInstallMessageHandler(_qt_msg_handler)
|
qInstallMessageHandler(_qt_msg_handler)
|
||||||
|
|
||||||
|
|||||||
@@ -466,8 +466,8 @@ class MainWindow(QMainWindow):
|
|||||||
SELECT s.id, s.title, s.artist, s.album, s.bpm,
|
SELECT s.id, s.title, s.artist, s.album, s.bpm,
|
||||||
s.duration_sec, s.local_path, s.file_format,
|
s.duration_sec, s.local_path, s.file_format,
|
||||||
s.file_missing,
|
s.file_missing,
|
||||||
GROUP_CONCAT(DISTINCT d.name) AS dance_names,
|
GROUP_CONCAT(d.name, ',') AS dance_names,
|
||||||
GROUP_CONCAT(DISTINCT COALESCE(dl.name,'')) AS dance_levels,
|
GROUP_CONCAT(COALESCE(dl.name,''), ',') AS dance_levels,
|
||||||
GROUP_CONCAT(DISTINCT ad.name) AS alt_dance_names
|
GROUP_CONCAT(DISTINCT ad.name) AS alt_dance_names
|
||||||
FROM songs s
|
FROM songs s
|
||||||
LEFT JOIN song_dances sd ON sd.song_id = s.id
|
LEFT JOIN song_dances sd ON sd.song_id = s.id
|
||||||
|
|||||||
@@ -41,7 +41,10 @@ class PlaylistInfoWindow(QWidget):
|
|||||||
playlist_panel.playlist_changed.connect(self._update)
|
playlist_panel.playlist_changed.connect(self._update)
|
||||||
playlist_panel.status_changed.connect(lambda *_: self._update())
|
playlist_panel.status_changed.connect(lambda *_: self._update())
|
||||||
|
|
||||||
def _build_ui(self):
|
def moveEvent(self, event):
|
||||||
|
from PyQt6.QtCore import QSettings
|
||||||
|
QSettings("LineDance", "Player").setValue("window/info_pos", self.pos())
|
||||||
|
super().moveEvent(event)
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
layout.setContentsMargins(12, 12, 12, 12)
|
layout.setContentsMargins(12, 12, 12, 12)
|
||||||
layout.setSpacing(8)
|
layout.setSpacing(8)
|
||||||
|
|||||||
@@ -668,12 +668,26 @@ class PlaylistPanel(QWidget):
|
|||||||
|
|
||||||
from ui.playlist_info_dialog import PlaylistInfoWindow
|
from ui.playlist_info_dialog import PlaylistInfoWindow
|
||||||
from PyQt6.QtWidgets import QApplication
|
from PyQt6.QtWidgets import QApplication
|
||||||
|
from PyQt6.QtCore import QSettings
|
||||||
main = self.window()
|
main = self.window()
|
||||||
self._info_window = PlaylistInfoWindow(self, parent=main)
|
self._info_window = PlaylistInfoWindow(self, parent=main)
|
||||||
QApplication.instance().aboutToQuit.connect(self._info_window.close)
|
QApplication.instance().aboutToQuit.connect(self._info_window.close)
|
||||||
if main:
|
|
||||||
|
# Gendan gemt position eller placer ved siden af hovedvindue
|
||||||
|
s = QSettings("LineDance", "Player")
|
||||||
|
pos = s.value("window/info_pos")
|
||||||
|
if pos:
|
||||||
|
self._info_window.move(pos)
|
||||||
|
elif main:
|
||||||
geo = main.geometry()
|
geo = main.geometry()
|
||||||
self._info_window.move(geo.right() + 10, geo.top() + 100)
|
self._info_window.move(geo.right() + 10, geo.top())
|
||||||
|
|
||||||
|
# Sikr at vinduet er på skærmen
|
||||||
|
screen = QApplication.primaryScreen().availableGeometry()
|
||||||
|
w_geo = self._info_window.frameGeometry()
|
||||||
|
x = max(0, min(w_geo.x(), screen.right() - w_geo.width()))
|
||||||
|
y = max(0, min(w_geo.y(), screen.bottom() - w_geo.height()))
|
||||||
|
self._info_window.move(x, y)
|
||||||
self._info_window.show()
|
self._info_window.show()
|
||||||
|
|
||||||
def _change_dance(self, idx: int, song: dict):
|
def _change_dance(self, idx: int, song: dict):
|
||||||
|
|||||||
@@ -437,9 +437,14 @@ class TagEditorDialog(QDialog):
|
|||||||
# Skriv danse-navne til filen
|
# Skriv danse-navne til filen
|
||||||
if local_path and can_write_dances(local_path):
|
if local_path and can_write_dances(local_path):
|
||||||
dance_names = [d["name"] for d in dances]
|
dance_names = [d["name"] for d in dances]
|
||||||
|
try:
|
||||||
if not write_dances(local_path, dance_names):
|
if not write_dances(local_path, dance_names):
|
||||||
QMessageBox.warning(self, "Advarsel",
|
QMessageBox.warning(self, "Advarsel",
|
||||||
"Gemt i database, men kunne ikke skrive til filen.")
|
"Gemt i database, men kunne ikke skrive til mp3-filen.\n"
|
||||||
|
"(Filen understøtter ikke dans-tags)")
|
||||||
|
except Exception as write_err:
|
||||||
|
QMessageBox.warning(self, "Advarsel",
|
||||||
|
f"Gemt i database, men fejl ved skrivning til fil:\n{write_err}")
|
||||||
|
|
||||||
self.accept()
|
self.accept()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user