fixes and fonts and such

This commit is contained in:
billy 2025-10-04 23:43:06 -04:00
parent 80dd2df74b
commit 1add0bc85a
5 changed files with 38 additions and 162 deletions

View File

@ -1,8 +1,5 @@
from configparser import ConfigParser
from pathlib import Path
from typing import Optional from typing import Optional
from appdirs import user_config_dir from dataclasses import dataclass
from dataclasses import dataclass, asdict
from mutagen.id3._frames import ( from mutagen.id3._frames import (
TIT2, TIT2,
TPE1, TPE1,
@ -80,22 +77,6 @@ mutagen_id3_tag_mapping = {
} }
@dataclass
class SQLiteMap:
title: str | TIT2 | None = None
artist: str | TPE1 | None = None
album: str | TALB | None = None
album_artist: str | TPE2 | None = None
track_number: str | TRCK | None = None
genre: str | TCON | None = None
length_ms: str | TLEN | None = None
album_date: str | TDRC | None = None
codec: str | None = None
filepath: str | None = None
bitrate: str | None = None
# lyrics: str | USLT | None = None
# album_art: str | APIC | None = None
@dataclass @dataclass
class ID3Field: class ID3Field:
db: str # e.g., "title" db: str # e.g., "title"
@ -134,114 +115,3 @@ class HeaderTags2:
def get_editable_db_list(self) -> list: def get_editable_db_list(self) -> list:
return [f.db for f in self.headers if f.editable] return [f.db for f in self.headers if f.editable]
class HeaderTags:
"""
Utility class to converting between different "standards" for tags (headers, id3, etc)
`db`: dict = "db name": "db name string"
`gui`: dict = "db name": "gui string"
`id3`: dict = "db name": "id3 tag string"
`id3_keys`: dict = "id3 tag string": "db name"
`editable_fields`: list = "list of db names that are user editable"
`user_fields`: list = "list of db headers that the user has chosen to see in gui"
"""
def __init__(self):
cfg_file = (
Path(user_config_dir(appname="musicpom", appauthor="billypom"))
/ "config.ini"
)
self.config = ConfigParser()
self.config.read(cfg_file)
# print("header tag config")
# print(self.config)
self.user_fields: list = str(self.config["table"]["columns"]).split(",")
self.editable_fields: list = [
"title",
"artist",
"album_artist",
"album",
"track_number",
"genre",
"album_date",
]
self.fields = SQLiteMap()
self.headers = SQLiteMap(
title="title",
artist="artist",
album="album",
album_artist="alb artist",
track_number="track",
genre="genre",
album_date="year",
codec="codec",
length_ms="length",
filepath="path",
bitrate="bitrate",
)
# self.id3 = SQLiteMap(
# title = "TIT2",
# artist = "TPE1",
# album = "TALB",
# album_artist = "TPE2",
# track_number = "TRCK",
# genre = "TCON",
# length_seconds = "TLEN",
# album_date = "TDRC",
# codec = None,
# filepath = None
# )
self.db: dict = {
"title": "title",
"artist": "artist",
"album": "album",
"album_artist": "album_artist",
"track_number": "track_number",
"genre": "genre",
"album_date": "album_date",
"codec": "codec",
"length_seconds": "length_seconds",
"filepath": "filepath",
"bitrate": "bitrate",
}
self.gui: dict = {
"title": "title",
"artist": "artist",
"album": "album",
"album_artist": "alb artist",
"track_number": "track",
"genre": "genre",
"album_date": "year",
"codec": "codec",
"length_seconds": "length",
"filepath": "path",
"bitrate": "bitrate",
}
self.id3: dict = {
"title": "TIT2",
"artist": "TPE1",
"album_artist": "TPE2",
"album": "TALB",
"track_number": "TRCK",
"genre": "TCON",
"album_date": "TDRC",
"codec": None,
"length_seconds": "TLEN",
"filepath": None,
"bitrate": "TBIT",
}
# id3 is the key
self.id3_keys: dict = {}
for k, v in self.id3.items():
if v is not None:
self.id3_keys[v] = k
def get_user_gui_headers(self) -> list:
"""Returns a list of headers for the GUI"""
gui_headers = []
for db, gui in asdict(self.headers).items():
if db in self.user_fields:
gui_headers.append(gui)
return gui_headers

View File

@ -2,6 +2,7 @@ import DBA
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QColor, QColor,
QDragMoveEvent, QDragMoveEvent,
QFont,
QPainter, QPainter,
QPen, QPen,
QStandardItem, QStandardItem,
@ -83,6 +84,10 @@ class MusicTable(QTableView):
) )
_ = self.config.read(self.cfg_file) _ = self.config.read(self.cfg_file)
font: QFont = QFont()
font.setPointSize(11)
self.setFont(font)
# NOTE: # NOTE:
# QTableView model2 = QSortFilterProxyModel(QStandardItemModel) # QTableView model2 = QSortFilterProxyModel(QStandardItemModel)
# #
@ -765,9 +770,13 @@ class MusicTable(QTableView):
hint: You get a `playlist_id` from the signal emitted from PlaylistsPane as a tuple (1,) hint: You get a `playlist_id` from the signal emitted from PlaylistsPane as a tuple (1,)
""" """
if playlist_id:
if self.selected_playlist_id == playlist_id[0]:
# Don't reload if we clicked the same item
return
# self.disconnect_data_changed() # self.disconnect_data_changed()
# self.disconnect_layout_changed() # self.disconnect_layout_changed()
self.save_scroll_position(self.current_playlist_id) # self.save_scroll_position(self.current_playlist_id)
self.model2.clear() self.model2.clear()
# self.model2.setHorizontalHeaderLabels(self.headers.get_user_gui_headers()) # self.model2.setHorizontalHeaderLabels(self.headers.get_user_gui_headers())
self.model2.setHorizontalHeaderLabels(self.headers.db_list) self.model2.setHorizontalHeaderLabels(self.headers.db_list)
@ -780,10 +789,15 @@ class MusicTable(QTableView):
params = "" params = ""
is_playlist = 0 is_playlist = 0
if len(playlist_id) > 0: if len(playlist_id) > 0:
if playlist_id[0] == 0:
self.selected_playlist_id = 0
is_playlist = 0
else:
self.selected_playlist_id = playlist_id[0] self.selected_playlist_id = playlist_id[0]
is_playlist = 1 is_playlist = 1
else: else:
self.selected_playlist_id = None self.selected_playlist_id = 0
is_playlist = 0
# try: # try:
# # Check cache for already loaded QTableView QStandardItemModel # # Check cache for already loaded QTableView QStandardItemModel
@ -1097,13 +1111,13 @@ class MusicTable(QTableView):
except Exception: except Exception:
pass pass
def connect_layout_changed(self): # def connect_layout_changed(self):
"""Connects the layoutChanged signal from QTableView.model""" # """Connects the layoutChanged signal from QTableView.model"""
try: # try:
pass # pass
_ = self.model2.layoutChanged.connect(self.restore_scroll_position) # _ = self.model2.layoutChanged.connect(self.restore_scroll_position)
except Exception: # except Exception:
pass # pass
# QT Roles # QT Roles

View File

@ -1,3 +1,4 @@
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAction, QAction,
QInputDialog, QInputDialog,
@ -42,6 +43,10 @@ class PlaylistsPane(QTreeWidget):
self.customContextMenuRequested.connect(self.showContextMenu) self.customContextMenuRequested.connect(self.showContextMenu)
self.currentItemChanged.connect(self.playlist_clicked) self.currentItemChanged.connect(self.playlist_clicked)
self.playlist_db_id_choice: int | None = None self.playlist_db_id_choice: int | None = None
font: QFont = QFont()
font.setPointSize(16)
font.setBold(True)
self.setFont(font)
def reload_playlists(self, progress_callback=None): def reload_playlists(self, progress_callback=None):
""" """
@ -50,7 +55,7 @@ class PlaylistsPane(QTreeWidget):
""" """
# take all children away # take all children away
self._playlists_root.takeChildren() self._playlists_root.takeChildren()
# NOTE: implement user sorting by adding a column to playlist db table for 'rank' or something # TODO: implement user sorting by adding a column to playlist db table for 'rank' or something
with DBA.DBAccess() as db: with DBA.DBAccess() as db:
playlists = db.query( playlists = db.query(
"SELECT id, name FROM playlist ORDER BY date_created DESC;", () "SELECT id, name FROM playlist ORDER BY date_created DESC;", ()
@ -144,7 +149,7 @@ class PlaylistsPane(QTreeWidget):
if item == self._playlists_root or item == self._library_root: if item == self._playlists_root or item == self._library_root:
self.playlist_db_id_choice = None self.playlist_db_id_choice = None
# self.all_songs_selected() # self.all_songs_selected()
self.allSongsSignal.emit() self.playlistChoiceSignal.emit(0)
elif isinstance(item, PlaylistWidgetItem): elif isinstance(item, PlaylistWidgetItem):
# debug(f"ID: {item.id}, name: {item.text(0)}") # debug(f"ID: {item.id}, name: {item.text(0)}")
self.playlist_db_id_choice = item.id self.playlist_db_id_choice = item.id
@ -153,9 +158,3 @@ class PlaylistsPane(QTreeWidget):
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"""
self.qapp = qapp self.qapp = qapp
# def all_songs_selected(self):
# """Emits a signal to display all songs in the library"""
# # I have no idea why this has to be in its own function, but it does
# # or else it doesn't work
# self.allSongsSignal.emit()

View File

@ -11,6 +11,6 @@ from .CreatePlaylistWindow import CreatePlaylistWindow
from .PlaylistsPane import PlaylistsPane from .PlaylistsPane import PlaylistsPane
from .ExportPlaylistWindow import ExportPlaylistWindow from .ExportPlaylistWindow import ExportPlaylistWindow
from .QuestionBoxDetails import QuestionBoxDetails from .QuestionBoxDetails import QuestionBoxDetails
from .HeaderTags import HeaderTags, HeaderTags2 from .HeaderTags import HeaderTags2
from .MediaPlayer import MediaPlayer from .MediaPlayer import MediaPlayer
from .SearchLineEdit import SearchLineEdit from .SearchLineEdit import SearchLineEdit

15
main.py
View File

@ -157,7 +157,6 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
self.actionOpenFiles.triggered.connect(self.open_files) # Open files window self.actionOpenFiles.triggered.connect(self.open_files) # Open files window
self.actionNewPlaylist.triggered.connect(self.playlistTreeView.create_playlist) self.actionNewPlaylist.triggered.connect(self.playlistTreeView.create_playlist)
self.actionExportPlaylist.triggered.connect(self.export_playlist) self.actionExportPlaylist.triggered.connect(self.export_playlist)
# EDIT MENU # EDIT MENU
self.actionPreferences.triggered.connect(self.open_preferences) self.actionPreferences.triggered.connect(self.open_preferences)
# VIEW MENU # VIEW MENU
@ -207,14 +206,6 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
def closeEvent(self, a0: QCloseEvent | None) -> None: def closeEvent(self, a0: QCloseEvent | None) -> None:
"""Save settings when closing the application""" """Save settings when closing the application"""
# MusicTable/tableView column widths
# list_of_column_widths = []
# for i in range(self.tableView.model2.columnCount()):
# list_of_column_widths.append(str(self.tableView.columnWidth(i)))
# column_widths_as_string = ",".join(list_of_column_widths)
# debug(f"saving column widths: {column_widths_as_string}")
# self.config["table"]["column_widths"] = column_widths_as_string
self.config["settings"]["volume"] = str(self.current_volume) self.config["settings"]["volume"] = str(self.current_volume)
self.config["settings"]["window_size"] = (str(self.width()) + "," + str(self.height())) self.config["settings"]["window_size"] = (str(self.width()) + "," + str(self.height()))
self.config['table']['column_ratios'] = ",".join(self.tableView.get_current_header_width_ratios()) self.config['table']['column_ratios'] = ",".join(self.tableView.get_current_header_width_ratios())
@ -687,8 +678,10 @@ if __name__ == "__main__":
handlers=handlers, handlers=handlers,
) )
debug('--------- musicpom debug started') debug('--------- musicpom debug started')
debug('---------------------| ') debug('--------------------------------')
debug(f'----------------------> {handlers} ') debug(handlers)
debug('--------------------------------')
debug('--------------------------------')
# Initialization # Initialization
config: ConfigParser = update_config_file() config: ConfigParser = update_config_file()
if not update_database_file(): if not update_database_file():