En del opdateringer
This commit is contained in:
@@ -35,9 +35,10 @@ def _get_conn() -> sqlite3.Connection:
|
||||
|
||||
def new_conn() -> sqlite3.Connection:
|
||||
"""Åbn en frisk forbindelse til brug i tag_editor og dialogs."""
|
||||
conn = sqlite3.connect(str(DB_PATH), check_same_thread=False)
|
||||
conn = sqlite3.connect(str(DB_PATH), check_same_thread=False, timeout=10)
|
||||
conn.row_factory = sqlite3.Row
|
||||
conn.execute("PRAGMA foreign_keys=OFF") # FK checker forhindrer level_id gem
|
||||
conn.execute("PRAGMA journal_mode=WAL")
|
||||
conn.execute("PRAGMA foreign_keys=OFF")
|
||||
return conn
|
||||
|
||||
|
||||
@@ -186,11 +187,16 @@ def init_db():
|
||||
count = conn.execute("SELECT COUNT(*) FROM dance_levels").fetchone()[0]
|
||||
if count == 0:
|
||||
defaults = [
|
||||
(1, "Begynder", "Passer til alle"),
|
||||
(2, "Let øvet", "Lidt erfaring kræves"),
|
||||
(3, "Øvet", "Kræver regelmæssig træning"),
|
||||
(4, "Erfaren", "For dedikerede dansere"),
|
||||
(5, "Ekspert", "Konkurrenceniveau"),
|
||||
(10, "Absolute Beginner", "Ingen tidligere danse-erfaring kræves"),
|
||||
(20, "Beginner", "Lidt tidligere erfaring"),
|
||||
(30, "High Beginner", "God begynder, klar til mere"),
|
||||
(40, "Low Improver", "Begyndende øvet"),
|
||||
(50, "Improver", "Grundlæggende færdigheder på plads"),
|
||||
(60, "High Improver", "Stærk øvet, næsten intermediate"),
|
||||
(70, "Low Intermediate", "Begyndende intermediate"),
|
||||
(80, "Intermediate", "Erfaren danser"),
|
||||
(90, "High Intermediate", "Stærk intermediate"),
|
||||
(99, "Advanced", "Fuld beherskelse af trin og teknik"),
|
||||
]
|
||||
for row in defaults:
|
||||
conn.execute(
|
||||
@@ -261,6 +267,40 @@ MIGRATIONS: dict[int, list[str]] = {
|
||||
"""ALTER TABLE songs ADD COLUMN mbid TEXT""",
|
||||
"""ALTER TABLE songs ADD COLUMN acoustid TEXT""",
|
||||
],
|
||||
9: [
|
||||
# Opdater niveau-navne til korrekte betegnelser i rigtig rækkefølge
|
||||
"DELETE FROM dance_levels",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (10, 'Absolute Beginner', 'Ingen tidligere danse-erfaring kræves')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (20, 'Beginner', 'Lidt tidligere erfaring')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (30, 'High Beginner', 'God begynder, klar til mere')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (40, 'Low Improver', 'Begyndende øvet')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (50, 'Improver', 'Grundlæggende færdigheder på plads')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (60, 'High Improver', 'Stærk øvet, næsten intermediate')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (70, 'Low Intermediate', 'Begyndende intermediate')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (80, 'Intermediate', 'Erfaren danser')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (90, 'High Intermediate', 'Stærk intermediate')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (99, 'Advanced', 'Fuld beherskelse af trin og teknik')",
|
||||
],
|
||||
10: [
|
||||
# Ret stavefejl i eksisterende data
|
||||
"UPDATE dance_levels SET name='Low Intermediate' WHERE name='Low Intermidiate' OR name='Low Intermidiat'",
|
||||
"UPDATE dance_levels SET name='Intermediate' WHERE name='Intermidiate' OR name='Intermidate'",
|
||||
"UPDATE dance_levels SET name='High Intermediate' WHERE name='High Intermidiate' OR name='High Intermidiat'",
|
||||
],
|
||||
11: [
|
||||
# Genopret dance_levels med korrekte navne og rækkefølge
|
||||
"DELETE FROM dance_levels",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (10, 'Absolute Beginner', 'Ingen tidligere danse-erfaring kræves')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (20, 'Beginner', 'Lidt tidligere erfaring')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (30, 'High Beginner', 'God begynder, klar til mere')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (40, 'Low Improver', 'Begyndende øvet')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (50, 'Improver', 'Grundlæggende færdigheder på plads')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (60, 'High Improver', 'Stærk øvet, næsten intermediate')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (70, 'Low Intermediate', 'Begyndende intermediate')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (80, 'Intermediate', 'Erfaren danser')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (90, 'High Intermediate', 'Stærk intermediate')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (99, 'Advanced', 'Fuld beherskelse af trin og teknik')",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -442,24 +482,31 @@ def get_song_by_path(local_path: str) -> sqlite3.Row | None:
|
||||
|
||||
|
||||
def search_songs(query: str, limit: int = 50) -> list[sqlite3.Row]:
|
||||
"""Søg i alle tags — titel, artist, album, danse og alle øvrige tags."""
|
||||
"""Søg i titel, artist, album, dans, koreograf, niveau og øvrige tags."""
|
||||
import logging as _log
|
||||
_log.getLogger(__name__).info(f"search_songs: '{query}'")
|
||||
pattern = f"%{query}%"
|
||||
with get_db() as conn:
|
||||
return conn.execute("""
|
||||
rows = conn.execute("""
|
||||
SELECT DISTINCT s.* FROM songs s
|
||||
LEFT JOIN song_dances sd ON sd.song_id = s.id
|
||||
LEFT JOIN dances d ON d.id = sd.dance_id
|
||||
LEFT JOIN dance_levels dl ON dl.id = d.level_id
|
||||
WHERE s.file_missing = 0
|
||||
AND (
|
||||
s.title LIKE ? OR
|
||||
s.artist LIKE ? OR
|
||||
s.album LIKE ? OR
|
||||
d.name LIKE ? OR
|
||||
s.extra_tags LIKE ?
|
||||
s.title LIKE ? OR
|
||||
s.artist LIKE ? OR
|
||||
s.album LIKE ? OR
|
||||
d.name LIKE ? OR
|
||||
d.choreographer LIKE ? OR
|
||||
dl.name LIKE ? OR
|
||||
s.extra_tags LIKE ?
|
||||
)
|
||||
ORDER BY s.artist, s.title
|
||||
LIMIT ?
|
||||
""", (pattern, pattern, pattern, pattern, pattern, limit)).fetchall()
|
||||
""", (pattern,)*7 + (limit,)).fetchall()
|
||||
_log.getLogger(__name__).info(f"search_songs: '{query}' → {len(rows)} resultater")
|
||||
return rows
|
||||
|
||||
|
||||
def get_songs_for_library(library_id: int) -> list[sqlite3.Row]:
|
||||
@@ -672,10 +719,11 @@ def update_dance_info(dance_id: int, choreographer: str = "",
|
||||
|
||||
|
||||
def get_or_create_dance(name: str, level_id: int | None,
|
||||
conn=None) -> int:
|
||||
conn=None, choreographer: str = "") -> int:
|
||||
"""Find eller opret en dans (name + level_id kombination).
|
||||
Returnerer dance_id. conn er valgfri — bruges ved nested kald."""
|
||||
name = name.strip()
|
||||
name = name.strip()
|
||||
choreo = choreographer.strip()
|
||||
close = False
|
||||
if conn is None:
|
||||
conn = new_conn()
|
||||
@@ -687,13 +735,15 @@ def get_or_create_dance(name: str, level_id: int | None,
|
||||
).fetchone()
|
||||
if existing:
|
||||
conn.execute(
|
||||
"UPDATE dances SET use_count=use_count+1 WHERE id=?",
|
||||
(existing["id"],)
|
||||
"UPDATE dances SET use_count=use_count+1"
|
||||
+ (", choreographer=?" if choreo else "") +
|
||||
" WHERE id=?",
|
||||
((choreo, existing["id"]) if choreo else (existing["id"],))
|
||||
)
|
||||
return existing["id"]
|
||||
conn.execute(
|
||||
"INSERT INTO dances (name, level_id, use_count, source) VALUES (?,?,1,'local')",
|
||||
(name, level_id)
|
||||
"INSERT INTO dances (name, level_id, choreographer, use_count, source) VALUES (?,?,?,1,'local')",
|
||||
(name, level_id, choreo)
|
||||
)
|
||||
return conn.execute(
|
||||
"SELECT id FROM dances WHERE name=? COLLATE NOCASE AND level_id IS ?",
|
||||
@@ -705,19 +755,34 @@ def get_or_create_dance(name: str, level_id: int | None,
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_choreographer_suggestions(prefix: str, limit: int = 20) -> list[str]:
|
||||
"""Returnerer koreografer der starter med prefix, sorteret alfabetisk."""
|
||||
with get_db() as conn:
|
||||
rows = conn.execute("""
|
||||
SELECT DISTINCT choreographer
|
||||
FROM dances
|
||||
WHERE choreographer LIKE ? COLLATE NOCASE
|
||||
AND choreographer != ''
|
||||
ORDER BY choreographer
|
||||
LIMIT ?
|
||||
""", (f"{prefix}%", limit)).fetchall()
|
||||
return [r["choreographer"] for r in rows]
|
||||
|
||||
|
||||
def get_dance_suggestions(prefix: str, limit: int = 20) -> list[dict]:
|
||||
"""Returnerer danse der starter med prefix som {id, name, level_id, level_name}.
|
||||
"""Returnerer danse der matcher prefix i navn ELLER koreograf.
|
||||
Sorteret efter popularitet — bruges til autoudfyld."""
|
||||
with get_db() as conn:
|
||||
rows = conn.execute("""
|
||||
SELECT d.id, d.name, d.level_id, d.use_count,
|
||||
SELECT d.id, d.name, d.level_id, d.use_count, d.choreographer,
|
||||
dl.name as level_name, dl.sort_order
|
||||
FROM dances d
|
||||
LEFT JOIN dance_levels dl ON dl.id = d.level_id
|
||||
WHERE d.name LIKE ? COLLATE NOCASE
|
||||
OR d.choreographer LIKE ? COLLATE NOCASE
|
||||
ORDER BY d.use_count DESC, dl.sort_order, d.name
|
||||
LIMIT ?
|
||||
""", (f"{prefix}%", limit)).fetchall()
|
||||
""", (f"%{prefix}%", f"%{prefix}%", limit)).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
|
||||
@@ -725,7 +790,7 @@ def get_dances_for_song(song_id: str) -> list[dict]:
|
||||
"""Hent hoveddanse for en sang med niveau-info og workshop-flag."""
|
||||
with get_db() as conn:
|
||||
rows = conn.execute("""
|
||||
SELECT d.id as dance_id, d.name, d.level_id,
|
||||
SELECT d.id as dance_id, d.name, d.level_id, d.choreographer,
|
||||
dl.name as level_name, sd.dance_order,
|
||||
sd.id as song_dance_id, sd.is_workshop
|
||||
FROM song_dances sd
|
||||
|
||||
Reference in New Issue
Block a user