dataclass swag
This commit is contained in:
parent
466b38ce2e
commit
491e134d94
@ -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",
|
||||||
|
|||||||
@ -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"""
|
||||||
|
|||||||
23
main.py
23
main.py
@ -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
|
||||||
index = self.tableView.proxymodel.mapFromSource(current_real_index)
|
try:
|
||||||
|
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
|
||||||
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()
|
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)
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user