Med install
This commit is contained in:
@@ -169,10 +169,20 @@ class LibraryPanel(QWidget):
|
||||
q = self._search.text().strip().lower()
|
||||
for song in self._filtered:
|
||||
dances = song.get("dances", [])
|
||||
dance_str = " · " + " / ".join(dances) if dances else ""
|
||||
dance_levels = song.get("dance_levels", [])
|
||||
missing = song.get("file_missing", False)
|
||||
|
||||
# Byg dans-streng med niveau hvis tilgængeligt
|
||||
dance_parts = []
|
||||
for i, d in enumerate(dances):
|
||||
lvl = dance_levels[i] if i < len(dance_levels) else ""
|
||||
dance_parts.append(f"{d} / {lvl}" if lvl else d)
|
||||
dance_str = " · " + " | ".join(dance_parts) if dance_parts else ""
|
||||
|
||||
line1 = ("⚠ " if missing else "") + song.get("title", "—")
|
||||
line2 = f" {song.get('artist','—')} · {song.get('bpm',0)} BPM · {song.get('file_format','').upper()}{dance_str}"
|
||||
bpm = song.get("bpm", 0)
|
||||
bpm_str = f"{bpm} BPM" if bpm else "? BPM"
|
||||
line2 = f" {song.get('artist','—')} · {bpm_str} · {song.get('file_format','').upper()}{dance_str}"
|
||||
item = QListWidgetItem(f"{line1}\n{line2}")
|
||||
item.setData(Qt.ItemDataRole.UserRole, song)
|
||||
if missing:
|
||||
@@ -237,12 +247,16 @@ class LibraryPanel(QWidget):
|
||||
self.done.emit(bpm)
|
||||
|
||||
self._bpm_worker = BpmWorker(path, song_id)
|
||||
self._bpm_worker.done.connect(
|
||||
lambda bpm: (
|
||||
self._do_search(),
|
||||
print(f"BPM analyseret: {bpm}")
|
||||
)
|
||||
)
|
||||
|
||||
def on_bpm_done(bpm):
|
||||
# Opdater sangen i _all_songs listen direkte
|
||||
for s in self._all_songs:
|
||||
if s.get("id") == song_id:
|
||||
s["bpm"] = int(round(bpm))
|
||||
break
|
||||
self._do_search()
|
||||
|
||||
self._bpm_worker.done.connect(on_bpm_done)
|
||||
self._bpm_worker.start()
|
||||
|
||||
def _manage_libraries(self):
|
||||
|
||||
@@ -439,9 +439,11 @@ class MainWindow(QMainWindow):
|
||||
songs = []
|
||||
for row in songs_raw:
|
||||
with get_db() as conn:
|
||||
dances = conn.execute(
|
||||
"SELECT dance_name FROM song_dances "
|
||||
"WHERE song_id=? ORDER BY dance_order",
|
||||
dances_raw = conn.execute(
|
||||
"SELECT sd.dance_name, dl.name as level_name "
|
||||
"FROM song_dances sd "
|
||||
"LEFT JOIN dance_levels dl ON dl.id = sd.level_id "
|
||||
"WHERE sd.song_id=? ORDER BY sd.dance_order",
|
||||
(row["id"],)
|
||||
).fetchall()
|
||||
songs.append({
|
||||
@@ -454,7 +456,8 @@ class MainWindow(QMainWindow):
|
||||
"local_path": row["local_path"],
|
||||
"file_format": row["file_format"],
|
||||
"file_missing": bool(row["file_missing"]),
|
||||
"dances": [d["dance_name"] for d in dances],
|
||||
"dances": [d["dance_name"] for d in dances_raw],
|
||||
"dance_levels": [d["level_name"] or "" for d in dances_raw],
|
||||
})
|
||||
self._library_panel.load_songs(songs)
|
||||
count = len(songs)
|
||||
@@ -836,15 +839,13 @@ class MainWindow(QMainWindow):
|
||||
self._vu.reset()
|
||||
|
||||
# Markér den afspillede sang
|
||||
prev_idx = self._current_idx
|
||||
self._playlist_panel.mark_played(prev_idx)
|
||||
self._playlist_panel.mark_played(self._current_idx)
|
||||
|
||||
# Synkroniser event-status til den gemte navngivne liste
|
||||
self._sync_event_status_to_playlist()
|
||||
|
||||
# Find næste afspilbare sang — fra 0 hvis ingen sang var i gang
|
||||
search_from = max(0, prev_idx + 1)
|
||||
ni = self._playlist_panel.next_playable_idx(search_from)
|
||||
# Find første ikke-afspillede og ikke-skippede sang fra TOPPEN
|
||||
ni = self._playlist_panel.next_playable_idx()
|
||||
next_song = self._playlist_panel.get_song(ni) if ni is not None else None
|
||||
if next_song:
|
||||
self._current_idx = ni
|
||||
|
||||
@@ -215,7 +215,7 @@ class PlaylistPanel(QWidget):
|
||||
self._trigger_autosave()
|
||||
|
||||
# Find første afspilbare sang og udsend signal så afspilleren opdateres
|
||||
ni = self.next_playable_idx(0)
|
||||
ni = self.next_playable_idx()
|
||||
if ni is not None:
|
||||
self._current_idx = ni
|
||||
self._refresh()
|
||||
@@ -253,9 +253,9 @@ class PlaylistPanel(QWidget):
|
||||
print(f"Event-state gendan fejl: {e}")
|
||||
return False
|
||||
|
||||
def next_playable_idx(self, from_idx: int) -> int | None:
|
||||
"""Find næste sang der ikke er 'skipped' eller 'played' fra from_idx."""
|
||||
for i in range(from_idx, len(self._songs)):
|
||||
def next_playable_idx(self) -> int | None:
|
||||
"""Find første sang fra toppen der ikke er 'skipped' eller 'played'."""
|
||||
for i in range(len(self._songs)):
|
||||
if self._statuses[i] not in ("skipped", "played"):
|
||||
return i
|
||||
return None
|
||||
|
||||
@@ -391,6 +391,7 @@ class TagEditorDialog(QDialog):
|
||||
dances = [(r.get_name(), r.get_level_id())
|
||||
for r in self._my_dance_rows if r.get_name()]
|
||||
|
||||
dance_ids = []
|
||||
with get_db() as conn:
|
||||
# Slet eksisterende danse og alternativer
|
||||
old_dances = conn.execute(
|
||||
@@ -400,28 +401,34 @@ class TagEditorDialog(QDialog):
|
||||
conn.execute("DELETE FROM dance_alternatives WHERE song_dance_id=?", (od["id"],))
|
||||
conn.execute("DELETE FROM song_dances WHERE song_id=?", (song_id,))
|
||||
|
||||
# Indsæt nye danse
|
||||
dance_ids = []
|
||||
# Indsæt nye danse og hent IDs
|
||||
for i, (name, level_id) in enumerate(dances, start=1):
|
||||
cur = conn.execute(
|
||||
"INSERT INTO song_dances (song_id, dance_name, dance_order, level_id) VALUES (?,?,?,?)",
|
||||
conn.execute(
|
||||
"INSERT INTO song_dances (song_id, dance_name, dance_order, level_id) "
|
||||
"VALUES (?,?,?,?)",
|
||||
(song_id, name, i, level_id)
|
||||
)
|
||||
dance_ids.append(cur.lastrowid)
|
||||
new_id = conn.execute(
|
||||
"SELECT id FROM song_dances WHERE song_id=? AND dance_order=?",
|
||||
(song_id, i)
|
||||
).fetchone()["id"]
|
||||
dance_ids.append(new_id)
|
||||
register_dance_name(name)
|
||||
|
||||
# Indsæt alternativer (knyttet til første dans hvis flere)
|
||||
if dance_ids and self._my_alt_rows:
|
||||
first_dance_id = dance_ids[0]
|
||||
for row in self._my_alt_rows:
|
||||
name = row.get_name()
|
||||
if name:
|
||||
add_alternative(
|
||||
first_dance_id, name,
|
||||
level_id=row.get_level_id(),
|
||||
note=row.get_note(),
|
||||
source="local",
|
||||
)
|
||||
# Indsæt alternativer knyttet til første dans
|
||||
if dance_ids and self._my_alt_rows:
|
||||
first_dance_id = dance_ids[0]
|
||||
for row in self._my_alt_rows:
|
||||
name = row.get_name()
|
||||
if name:
|
||||
import uuid as _uuid
|
||||
conn.execute("""
|
||||
INSERT INTO dance_alternatives
|
||||
(id, song_dance_id, alt_dance_name, level_id, note, source)
|
||||
VALUES (?,?,?,?,?,'local')
|
||||
""", (str(_uuid.uuid4()), first_dance_id,
|
||||
name, row.get_level_id(), row.get_note()))
|
||||
register_dance_name(name)
|
||||
|
||||
# Skriv til fil
|
||||
if local_path and can_write_dances(local_path):
|
||||
|
||||
Reference in New Issue
Block a user