dataclass swag

This commit is contained in:
billypom on debian 2025-04-19 22:45:02 -04:00
parent 466b38ce2e
commit 491e134d94
5 changed files with 62 additions and 25 deletions

View File

@ -1,9 +1,18 @@
from configparser import ConfigParser from configparser import ConfigParser
from pathlib import Path from pathlib import Path
from appdirs import user_config_dir from appdirs import user_config_dir
from dataclasses import dataclass, asdict
from typing import Optional
@dataclass
class SQLiteMap():
title: str
artist: str
album: Optional[str] = None
class HeaderTags:
class HeaderTags():
""" """
Utility class to converting between different "standards" for tags (headers, id3, etc) Utility class to converting between different "standards" for tags (headers, id3, etc)
@ -22,7 +31,7 @@ class HeaderTags:
) )
self.config = ConfigParser() self.config = ConfigParser()
self.config.read(cfg_file) self.config.read(cfg_file)
self.user_headers = str(self.config["table"]["columns"]).split(",") self.user_headers: list = str(self.config["table"]["columns"]).split(",")
self.db: dict = { self.db: dict = {
"title": "title", "title": "title",
"artist": "artist", "artist": "artist",

View File

@ -342,12 +342,12 @@ class MusicTable(QTableView):
def on_sort(self): def on_sort(self):
debug("on_sort") debug("on_sort")
search_col_num = list(self.headers.gui.values()).index("path") search_col_num = self.headers.user_headers.index("filepath")
selected_qmodel_index = self.find_qmodel_index_by_value( selected_qmodel_index = self.find_qmodel_index_by_value(
self.model2, search_col_num, self.selected_song_filepath self.proxymodel, search_col_num, self.selected_song_filepath
) )
current_qmodel_index = self.find_qmodel_index_by_value( current_qmodel_index = self.find_qmodel_index_by_value(
self.model2, search_col_num, self.current_song_filepath self.proxymodel, search_col_num, self.current_song_filepath
) )
# Update the 2 QModelIndexes that we track # Update the 2 QModelIndexes that we track
self.set_selected_song_qmodel_index(selected_qmodel_index) self.set_selected_song_qmodel_index(selected_qmodel_index)
@ -360,7 +360,7 @@ class MusicTable(QTableView):
When a cell is clicked, do some stuff :) When a cell is clicked, do some stuff :)
- this func also runs when double click happens, fyi - this func also runs when double click happens, fyi
""" """
print(index.row(), index.column()) # print(index.row(), index.column())
self.set_selected_song_filepath() self.set_selected_song_filepath()
self.set_selected_song_qmodel_index() self.set_selected_song_qmodel_index()
self.viewport().update() # type: ignore self.viewport().update() # type: ignore
@ -407,7 +407,8 @@ class MusicTable(QTableView):
filepath = self.model2.data(filepath_index) filepath = self.model2.data(filepath_index)
# update the ID3 information # update the ID3 information
user_input_data = topLeft.data() user_input_data = topLeft.data()
edited_column_name = self.database_columns[topLeft.column()] # edited_column_name = self.database_columns[topLeft.column()]
edited_column_name = self.headers.user_headers[topLeft.column()]
debug(f"on_cell_data_changed | edited column name: {edited_column_name}") debug(f"on_cell_data_changed | edited column name: {edited_column_name}")
response = set_tag(filepath, edited_column_name, user_input_data) response = set_tag(filepath, edited_column_name, user_input_data)
if response: if response:
@ -545,6 +546,8 @@ class MusicTable(QTableView):
"""Moves screen to the currently playing song, then selects the row""" """Moves screen to the currently playing song, then selects the row"""
debug("jump_to_current_song") debug("jump_to_current_song")
# get the proxy model index # get the proxy model index
debug(self.current_song_filepath)
debug(self.current_song_qmodel_index)
proxy_index = self.proxymodel.mapFromSource(self.current_song_qmodel_index) proxy_index = self.proxymodel.mapFromSource(self.current_song_qmodel_index)
self.scrollTo(proxy_index) self.scrollTo(proxy_index)
self.selectRow(proxy_index.row()) self.selectRow(proxy_index.row())
@ -724,6 +727,18 @@ class MusicTable(QTableView):
item.setData(id, Qt.ItemDataRole.UserRole) item.setData(id, Qt.ItemDataRole.UserRole)
self.model2.appendRow(items) self.model2.appendRow(items)
# reloading the model destroys and makes new indexes
# so we look for the new index of the current song on load
current_song_filepath = self.get_current_song_filepath()
print(f'load music table current filepath: {current_song_filepath}')
for row in range(self.model2.rowCount()):
real_index = self.model2.index(row, self.headers.user_headers.index("filepath"))
if real_index.data() == current_song_filepath:
print('is it true?')
print(f'{real_index.data()} == {current_song_filepath}')
print('load music table real index:')
print(real_index)
self.current_song_qmodel_index = real_index
self.model2.layoutChanged.emit() # emits a signal that the view should be updated self.model2.layoutChanged.emit() # emits a signal that the view should be updated
self.playlistStatsSignal.emit(f"Songs: {row_count} | Total time: {total_time}") self.playlistStatsSignal.emit(f"Songs: {row_count} | Total time: {total_time}")
self.loadMusicTableSignal.emit() self.loadMusicTableSignal.emit()
@ -871,11 +886,11 @@ class MusicTable(QTableView):
from the current selected row index from the current selected row index
""" """
# update the filepath # update the filepath
self.current_song_filepath: str = ( if not filepath:
self.current_song_qmodel_index.siblingAtColumn( path = self.current_song_qmodel_index.siblingAtColumn(self.headers.user_headers.index("filepath")).data()
list(self.headers.gui.values()).index("path") self.current_song_filepath: str = path
).data() else:
) self.current_song_filepath = filepath
def set_current_song_qmodel_index(self, index=None): def set_current_song_qmodel_index(self, index=None):
""" """
@ -886,8 +901,8 @@ class MusicTable(QTableView):
if index is None: if index is None:
index = self.currentIndex() index = self.currentIndex()
# map proxy (sortable) model to the original model (used for interactions) # map proxy (sortable) model to the original model (used for interactions)
model_index: QModelIndex = self.proxymodel.mapToSource(index) real_index: QModelIndex = self.proxymodel.mapToSource(index)
self.current_song_qmodel_index: QModelIndex = model_index self.current_song_qmodel_index: QModelIndex = real_index
def set_selected_song_qmodel_index(self, index=None): def set_selected_song_qmodel_index(self, index=None):
""" """
@ -898,8 +913,8 @@ class MusicTable(QTableView):
if index is None: if index is None:
index = self.currentIndex() index = self.currentIndex()
# map proxy (sortable) model to the original model (used for interactions) # map proxy (sortable) model to the original model (used for interactions)
model_index: QModelIndex = self.proxymodel.mapToSource(index) real_index: QModelIndex = self.proxymodel.mapToSource(index)
self.selected_song_qmodel_index: QModelIndex = model_index self.selected_song_qmodel_index: QModelIndex = real_index
def load_qapp(self, qapp) -> None: def load_qapp(self, qapp) -> None:
"""Necessary for using members and methods of main application window""" """Necessary for using members and methods of main application window"""

19
main.py
View File

@ -328,7 +328,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
file_url = media.canonicalUrl().toLocalFile() file_url = media.canonicalUrl().toLocalFile()
metadata = id3_remap(get_tags(file_url)[0]) metadata = id3_remap(get_tags(file_url)[0])
if metadata is not None: if metadata is not None:
self.set_ui_metadata(metadata["title"], metadata["artist"], metadata["album"]) self.set_ui_metadata(metadata["title"], metadata["artist"], metadata["album"], file_url)
def on_volume_changed(self) -> None: def on_volume_changed(self) -> None:
"""Handles volume changes""" """Handles volume changes"""
@ -368,26 +368,39 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
def on_prev_clicked(self) -> None: def on_prev_clicked(self) -> None:
"""click previous - go to previous song""" """click previous - go to previous song"""
current_real_index = self.tableView.current_song_qmodel_index current_real_index = self.tableView.current_song_qmodel_index
try:
index = self.tableView.proxymodel.mapFromSource(current_real_index) index = self.tableView.proxymodel.mapFromSource(current_real_index)
except:
return
row: int = index.row() row: int = index.row()
prev_row: int = row - 1 prev_row: int = row - 1
prev_index: QModelIndex = self.tableView.proxymodel.index(prev_row, index.column()) prev_index: QModelIndex = self.tableView.proxymodel.index(prev_row, index.column())
prev_filepath = prev_index.siblingAtColumn(self.headers.user_headers.index("filepath")).data() prev_filepath = prev_index.siblingAtColumn(self.headers.user_headers.index("filepath")).data()
if prev_filepath is None:
return
self.play_audio_file(prev_filepath) self.play_audio_file(prev_filepath)
self.tableView.set_current_song_qmodel_index(prev_index) self.tableView.set_current_song_qmodel_index(prev_index)
self.tableView.set_current_song_filepath(prev_filepath)
def on_next_clicked(self) -> None: def on_next_clicked(self) -> None:
"""click next (or song ended) - go to next song""" """click next (or song ended) - go to next song"""
current_real_index = self.tableView.current_song_qmodel_index current_real_index = self.tableView.current_song_qmodel_index
try:
# FIXME: seg fault here but only sometimes???
# when playing song in lib, switch to playlist, back to lib, next song
index = self.tableView.proxymodel.mapFromSource(current_real_index) index = self.tableView.proxymodel.mapFromSource(current_real_index)
except:
return
row: int = index.row() row: int = index.row()
next_row: int = row + 1 next_row: int = row + 1
next_index: QModelIndex = self.tableView.proxymodel.index(next_row, index.column()) next_index: QModelIndex = self.tableView.proxymodel.index(next_row, index.column())
next_filepath = next_index.siblingAtColumn(self.headers.user_headers.index("filepath")).data() next_filepath = next_index.siblingAtColumn(self.headers.user_headers.index("filepath")).data()
if next_filepath is None:
return
self.play_audio_file(next_filepath) self.play_audio_file(next_filepath)
self.tableView.set_current_song_qmodel_index(next_index) self.tableView.set_current_song_qmodel_index(next_index)
self.tableView.set_current_song_filepath(next_filepath)
# ____________________ # ____________________
# | | # | |
@ -458,9 +471,9 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
filepath default value = `tableView.current_song_filepath` filepath default value = `tableView.current_song_filepath`
""" """
print('play audio file')
if not filepath: if not filepath:
filepath = self.tableView.get_selected_song_filepath() filepath = self.tableView.get_selected_song_filepath()
file_url = QUrl.fromLocalFile(filepath)
metadata = id3_remap(get_tags(filepath)[0]) metadata = id3_remap(get_tags(filepath)[0])
# read the file # read the file
url = QUrl.fromLocalFile(filepath) url = QUrl.fromLocalFile(filepath)

View File

@ -9,7 +9,6 @@ def get_album_art(file: str | None) -> bytes:
# Returns # Returns
bytes for album art or placeholder artwork bytes for album art or placeholder artwork
""" """
debug(f'try album art: {file}')
default_image_path = "./assets/default_album_art.jpg" default_image_path = "./assets/default_album_art.jpg"
if file: if file:
try: try:
@ -23,5 +22,5 @@ def get_album_art(file: str | None) -> bytes:
error(f"Error retrieving album art: {e}") error(f"Error retrieving album art: {e}")
return bytes() return bytes()
with open(default_image_path, "rb") as f: with open(default_image_path, "rb") as f:
debug("loading placeholder album art") # debug("loading placeholder album art")
return f.read() return f.read()

View File

@ -1,5 +1,6 @@
from logging import debug, error from logging import debug, error
from components import ErrorDialog, HeaderTags from components import ErrorDialog
from components.HeaderTags import HeaderTags
# from utils import convert_date_str_to_tyer_tdat_id3_tag # from utils import convert_date_str_to_tyer_tdat_id3_tag
from mutagen.id3 import ID3 from mutagen.id3 import ID3
@ -120,7 +121,7 @@ def set_tag(filepath: str, tag_name: str, value: str):
return True return True
# Convert any ID3 tag or nice name (that i chose) into into the Mutagen Frame object # Convert any ID3 tag or nice name (that i chose) into into the Mutagen Frame object
if tag_name in list(headers.id3_keys.values()): if tag_name in list(headers.id3_keys.values()):
tag_nice_name = headers.id3_keys[tag_name] tag_nice_name = headers.id3[tag_name]
else: else:
tag_nice_name = tag_name tag_nice_name = tag_name
# Other # Other