From 491e134d9422f0b35b9a0c32f2c547e8e6d81843 Mon Sep 17 00:00:00 2001 From: billypom on debian Date: Sat, 19 Apr 2025 22:45:02 -0400 Subject: [PATCH] dataclass swag --- components/HeaderTags.py | 13 ++++++++++-- components/MusicTable.py | 43 +++++++++++++++++++++++++++------------- main.py | 23 ++++++++++++++++----- utils/get_album_art.py | 3 +-- utils/set_tag.py | 5 +++-- 5 files changed, 62 insertions(+), 25 deletions(-) diff --git a/components/HeaderTags.py b/components/HeaderTags.py index 43931cd..891313b 100644 --- a/components/HeaderTags.py +++ b/components/HeaderTags.py @@ -1,9 +1,18 @@ from configparser import ConfigParser from pathlib import Path 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) @@ -22,7 +31,7 @@ class HeaderTags: ) self.config = ConfigParser() 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 = { "title": "title", "artist": "artist", diff --git a/components/MusicTable.py b/components/MusicTable.py index ddddd56..9df428c 100644 --- a/components/MusicTable.py +++ b/components/MusicTable.py @@ -342,12 +342,12 @@ class MusicTable(QTableView): def on_sort(self): 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( - 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( - 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 self.set_selected_song_qmodel_index(selected_qmodel_index) @@ -360,7 +360,7 @@ class MusicTable(QTableView): When a cell is clicked, do some stuff :) - 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_qmodel_index() self.viewport().update() # type: ignore @@ -407,7 +407,8 @@ class MusicTable(QTableView): filepath = self.model2.data(filepath_index) # update the ID3 information 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}") response = set_tag(filepath, edited_column_name, user_input_data) if response: @@ -545,6 +546,8 @@ class MusicTable(QTableView): """Moves screen to the currently playing song, then selects the row""" debug("jump_to_current_song") # 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) self.scrollTo(proxy_index) self.selectRow(proxy_index.row()) @@ -724,6 +727,18 @@ class MusicTable(QTableView): item.setData(id, Qt.ItemDataRole.UserRole) 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.playlistStatsSignal.emit(f"Songs: {row_count} | Total time: {total_time}") self.loadMusicTableSignal.emit() @@ -871,11 +886,11 @@ class MusicTable(QTableView): from the current selected row index """ # update the filepath - self.current_song_filepath: str = ( - self.current_song_qmodel_index.siblingAtColumn( - list(self.headers.gui.values()).index("path") - ).data() - ) + if not filepath: + path = self.current_song_qmodel_index.siblingAtColumn(self.headers.user_headers.index("filepath")).data() + self.current_song_filepath: str = path + else: + self.current_song_filepath = filepath def set_current_song_qmodel_index(self, index=None): """ @@ -886,8 +901,8 @@ class MusicTable(QTableView): if index is None: index = self.currentIndex() # map proxy (sortable) model to the original model (used for interactions) - model_index: QModelIndex = self.proxymodel.mapToSource(index) - self.current_song_qmodel_index: QModelIndex = model_index + real_index: QModelIndex = self.proxymodel.mapToSource(index) + self.current_song_qmodel_index: QModelIndex = real_index def set_selected_song_qmodel_index(self, index=None): """ @@ -898,8 +913,8 @@ class MusicTable(QTableView): if index is None: index = self.currentIndex() # map proxy (sortable) model to the original model (used for interactions) - model_index: QModelIndex = self.proxymodel.mapToSource(index) - self.selected_song_qmodel_index: QModelIndex = model_index + real_index: QModelIndex = self.proxymodel.mapToSource(index) + self.selected_song_qmodel_index: QModelIndex = real_index def load_qapp(self, qapp) -> None: """Necessary for using members and methods of main application window""" diff --git a/main.py b/main.py index a6e4de8..973622d 100644 --- a/main.py +++ b/main.py @@ -328,7 +328,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow): file_url = media.canonicalUrl().toLocalFile() metadata = id3_remap(get_tags(file_url)[0]) 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: """Handles volume changes""" @@ -368,26 +368,39 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow): def on_prev_clicked(self) -> None: """click previous - go to previous song""" current_real_index = self.tableView.current_song_qmodel_index - index = self.tableView.proxymodel.mapFromSource(current_real_index) + try: + index = self.tableView.proxymodel.mapFromSource(current_real_index) + except: + return row: int = index.row() prev_row: int = row - 1 prev_index: QModelIndex = self.tableView.proxymodel.index(prev_row, index.column()) 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.tableView.set_current_song_qmodel_index(prev_index) + self.tableView.set_current_song_filepath(prev_filepath) def on_next_clicked(self) -> None: """click next (or song ended) - go to next song""" current_real_index = self.tableView.current_song_qmodel_index - index = self.tableView.proxymodel.mapFromSource(current_real_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) + except: + return row: int = index.row() next_row: int = row + 1 next_index: QModelIndex = self.tableView.proxymodel.index(next_row, index.column()) 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.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` """ + print('play audio file') if not filepath: filepath = self.tableView.get_selected_song_filepath() - file_url = QUrl.fromLocalFile(filepath) metadata = id3_remap(get_tags(filepath)[0]) # read the file url = QUrl.fromLocalFile(filepath) diff --git a/utils/get_album_art.py b/utils/get_album_art.py index 567ab64..516d12f 100644 --- a/utils/get_album_art.py +++ b/utils/get_album_art.py @@ -9,7 +9,6 @@ def get_album_art(file: str | None) -> bytes: # Returns bytes for album art or placeholder artwork """ - debug(f'try album art: {file}') default_image_path = "./assets/default_album_art.jpg" if file: try: @@ -23,5 +22,5 @@ def get_album_art(file: str | None) -> bytes: error(f"Error retrieving album art: {e}") return bytes() with open(default_image_path, "rb") as f: - debug("loading placeholder album art") + # debug("loading placeholder album art") return f.read() diff --git a/utils/set_tag.py b/utils/set_tag.py index a5da21f..32bdfe1 100644 --- a/utils/set_tag.py +++ b/utils/set_tag.py @@ -1,5 +1,6 @@ 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 mutagen.id3 import ID3 @@ -120,7 +121,7 @@ def set_tag(filepath: str, tag_name: str, value: str): return True # 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()): - tag_nice_name = headers.id3_keys[tag_name] + tag_nice_name = headers.id3[tag_name] else: tag_nice_name = tag_name # Other