better best gooder and great

This commit is contained in:
billy 2025-10-04 18:14:18 -04:00
parent 753117dacc
commit 80dd2df74b
3 changed files with 79 additions and 60 deletions

View File

@ -15,7 +15,7 @@ class EditPlaylistOptionsWindow(QDialog):
def __init__(self, playlist_id): def __init__(self, playlist_id):
super(EditPlaylistOptionsWindow, self).__init__() super(EditPlaylistOptionsWindow, self).__init__()
self.setWindowTitle("Playlist options") self.setWindowTitle("Playlist options")
# self.setMinimumSize(600, 400) self.setMinimumSize(800, 200)
self.playlist_id = playlist_id self.playlist_id = playlist_id
# self.playlist_path_prefix: str = self.config.get( # self.playlist_path_prefix: str = self.config.get(
# "settings", "playlist_path_prefix" # "settings", "playlist_path_prefix"

View File

@ -82,7 +82,6 @@ class MusicTable(QTableView):
/ "config.ini" / "config.ini"
) )
_ = self.config.read(self.cfg_file) _ = self.config.read(self.cfg_file)
debug(f"music table config: {self.config}")
# NOTE: # NOTE:
# QTableView model2 = QSortFilterProxyModel(QStandardItemModel) # QTableView model2 = QSortFilterProxyModel(QStandardItemModel)
@ -179,10 +178,10 @@ class MusicTable(QTableView):
def showEvent(self, a0): def showEvent(self, a0):
# Restore scroll position # Restore scroll position
super().showEvent(a0) super().showEvent(a0)
# widths = [] widths = []
# for _ in self.saved_column_ratios: for _ in self.saved_column_ratios:
# widths.append('0.001') widths.append('0.001')
# self.load_header_widths(widths) self.load_header_widths(widths)
QTimer.singleShot(0, lambda: self.load_header_widths(self.saved_column_ratios)) QTimer.singleShot(0, lambda: self.load_header_widths(self.saved_column_ratios))
def paintEvent(self, e): def paintEvent(self, e):
@ -261,7 +260,6 @@ class MusicTable(QTableView):
if e is None: if e is None:
return return
data = e.mimeData() data = e.mimeData()
debug("dropEvent")
if data and data.hasUrls(): if data and data.hasUrls():
directories: list[str] = [] directories: list[str] = []
files: list[str] = [] files: list[str] = []
@ -357,7 +355,6 @@ class MusicTable(QTableView):
return QModelIndex() # Invalid index if not found return QModelIndex() # Invalid index if not found
def on_sort(self): def on_sort(self):
debug("on_sort")
self.find_current_and_selected_bits() self.find_current_and_selected_bits()
self.jump_to_selected_song() self.jump_to_selected_song()
self.sortSignal.emit() self.sortSignal.emit()
@ -378,27 +375,27 @@ class MusicTable(QTableView):
pass pass
# https://stackoverflow.com/questions/46775438/how-to-limit-qheaderview-size-when-resizing-sections # https://stackoverflow.com/questions/46775438/how-to-limit-qheaderview-size-when-resizing-sections
col_count = self.model2.columnCount() # col_count = self.model2.columnCount()
qtableview_width = self.size().width() # qtableview_width = self.size().width()
sum_of_cols = self.horizontal_header.length() # sum_of_cols = self.horizontal_header.length()
# debug(f'qtable_width: {qtableview_width}') # # debug(f'qtable_width: {qtableview_width}')
# debug(f'sum of cols: {sum_of_cols}') # # debug(f'sum of cols: {sum_of_cols}')
#
if sum_of_cols != qtableview_width: # check for discrepancy # if sum_of_cols != qtableview_width: # check for discrepancy
if logicalIndex < col_count: # if not the last header # if logicalIndex < col_count: # if not the last header
next_header_size = self.horizontal_header.sectionSize(logicalIndex + 1) # next_header_size = self.horizontal_header.sectionSize(logicalIndex + 1)
if next_header_size > (sum_of_cols - qtableview_width): # if it should shrink # if next_header_size > (sum_of_cols - qtableview_width): # if it should shrink
self.horizontal_header.resizeSection( # self.horizontal_header.resizeSection(
logicalIndex + 1, # logicalIndex + 1,
next_header_size - (sum_of_cols - qtableview_width), # next_header_size - (sum_of_cols - qtableview_width),
) # shrink it # ) # shrink it
else: # else:
self.horizontal_header.resizeSection(logicalIndex, oldSize) # block the resize # self.horizontal_header.resizeSection(logicalIndex, oldSize) # block the resize
def on_cell_data_changed(self, topLeft: QModelIndex, bottomRight: QModelIndex): def on_cell_data_changed(self, topLeft: QModelIndex, bottomRight: QModelIndex):
"""Handles updating ID3 tags when data changes in a cell""" """Handles updating ID3 tags when data changes in a cell"""
# if isinstance(self.model2, QStandardItemModel): # if isinstance(self.model2, QStandardItemModel):
debug("on_cell_data_changed") # debug("on_cell_data_changed")
# get the ID of the row that was edited # get the ID of the row that was edited
id_index = self.model2.index(topLeft.row(), 0) id_index = self.model2.index(topLeft.row(), 0)
# get the db song_id from the row # get the db song_id from the row
@ -408,7 +405,7 @@ class MusicTable(QTableView):
# update the ID3 information # update the ID3 information
user_input_data: str = topLeft.data() user_input_data: str = topLeft.data()
edited_column_name: str = self.headers.db_list[topLeft.column()] edited_column_name: str = self.headers.db_list[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( response = set_tag(
filepath=filepath, filepath=filepath,
db_column=edited_column_name, db_column=edited_column_name,
@ -465,7 +462,8 @@ class MusicTable(QTableView):
""" """
total_table_width = self.size().width() total_table_width = self.size().width()
column_ratios = [] column_ratios = []
for i in range(self.model2.columnCount() - 1): for i in range(self.model2.columnCount()):
# for i in range(self.model2.columnCount() - 1):
column_width = self.columnWidth(i) column_width = self.columnWidth(i)
ratio = column_width / total_table_width ratio = column_width / total_table_width
column_ratios.append(str(round(ratio, 4))) column_ratios.append(str(round(ratio, 4)))
@ -504,7 +502,8 @@ class MusicTable(QTableView):
for ratio in column_ratios: for ratio in column_ratios:
column_widths.append(float(ratio) * total_table_width) column_widths.append(float(ratio) * total_table_width)
if isinstance(column_widths, list): if isinstance(column_widths, list):
for i in range(self.model2.columnCount() - 1): # for i in range(self.model2.columnCount() - 1):
for i in range(self.model2.columnCount()):
self.setColumnWidth(i, int(column_widths[i])) self.setColumnWidth(i, int(column_widths[i]))
@ -527,7 +526,7 @@ class MusicTable(QTableView):
- Drag & Drop song(s) on tableView - Drag & Drop song(s) on tableView
- File > Open > List of song(s) - File > Open > List of song(s)
""" """
debug('add_files_to_library()') # debug('add_files_to_library()')
worker = Worker(add_files_to_database, files, None) worker = Worker(add_files_to_database, files, None)
_ = worker.signals.signal_progress.connect(self.qapp.handle_progress) # type: ignore _ = worker.signals.signal_progress.connect(self.qapp.handle_progress) # type: ignore
_ = worker.signals.signal_result.connect(self.on_add_files_to_database_finished) _ = worker.signals.signal_result.connect(self.on_add_files_to_database_finished)
@ -579,21 +578,37 @@ class MusicTable(QTableView):
threadpool = self.qapp.threadpool # type: ignore threadpool = self.qapp.threadpool # type: ignore
threadpool.start(worker) threadpool.start(worker)
# def delete_selected_row_indices(self):
# """
# Removes rows from the QTableView based on a list of indices
# and then reload the table
# """
# debug('delete_selected_row_indices')
# selected_indices = self.get_selected_rows()
# for index in selected_indices:
# try:
# self.model2.removeRow(index)
# except Exception as e:
# debug(f"delete_selected_row_indices() failed | {e}")
# self.model2.layoutChanged.emit() # emits a signal that the view should be updated
# # self.viewport().update()
def delete_selected_row_indices(self): def delete_selected_row_indices(self):
""" """
Removes rows from the QTableView based on a list of indices Removes rows from the QTableView (which uses a proxy model)
and then reload the table by mapping selected proxy indices to the source model.
""" """
debug('delete_selected_row_indices') selected_proxy_indices = self.get_selected_rows()
selected_indices = self.get_selected_rows() selected_source_rows = [
self.disconnect_data_changed() self.proxymodel.mapToSource(self.proxymodel.index(row, 0)).row()
for index in selected_indices: for row in selected_proxy_indices
]
# Delete in reverse to maintain correct indexes to delete
for source_row in sorted(selected_source_rows, reverse=True):
try: try:
self.model2.removeRow(index) self.model2.removeRow(source_row)
except Exception as e: except Exception as e:
debug(f"delete_selected_row_indices() failed | {e}") debug(f"delete_selected_row_indices() failed | {e}")
self.connect_data_changed()
self.load_music_table(self.selected_playlist_id)
def edit_selected_files_metadata(self): def edit_selected_files_metadata(self):
"""Opens a form with metadata from the selected audio files""" """Opens a form with metadata from the selected audio files"""
@ -613,13 +628,15 @@ class MusicTable(QTableView):
def jump_to_current_song(self): def jump_to_current_song(self):
"""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")
# get the proxy model index # get the proxy model index
debug(self.current_song_filepath) try:
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()) except Exception as e:
debug(f'MusicTable.py | jump_to_current_song() | {self.current_song_filepath}')
debug(f'MusicTable.py | jump_to_current_song() | {self.current_song_qmodel_index}')
debug(f'MusicTable.py | jump_to_current_song() | Could not find current song in current table buffer - {e}')
def open_directory(self): def open_directory(self):
"""Opens the containing directory of the currently selected song, in the system file manager""" """Opens the containing directory of the currently selected song, in the system file manager"""
@ -748,8 +765,8 @@ 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,)
""" """
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())
@ -761,7 +778,6 @@ class MusicTable(QTableView):
else "" else ""
) )
params = "" params = ""
debug(f'playlist_id: {playlist_id}')
is_playlist = 0 is_playlist = 0
if len(playlist_id) > 0: if len(playlist_id) > 0:
self.selected_playlist_id = playlist_id[0] self.selected_playlist_id = playlist_id[0]
@ -777,7 +793,6 @@ class MusicTable(QTableView):
# except KeyError: # except KeyError:
# # Query for a playlist # # Query for a playlist
if is_playlist: if is_playlist:
debug('load music table a playlist')
try: try:
with DBA.DBAccess() as db: with DBA.DBAccess() as db:
query = f"SELECT id, { query = f"SELECT id, {
@ -800,7 +815,6 @@ class MusicTable(QTableView):
return return
# Query for the entire library # Query for the entire library
else: else:
debug('load music table a Whole Table')
try: try:
with DBA.DBAccess() as db: with DBA.DBAccess() as db:
query = f"SELECT id, {fields} FROM song" query = f"SELECT id, {fields} FROM song"
@ -823,13 +837,14 @@ class MusicTable(QTableView):
self.populate_model(data) self.populate_model(data)
self.current_playlist_id = self.selected_playlist_id self.current_playlist_id = self.selected_playlist_id
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
# reloading the model destroys and makes new indexes # reloading the model destroys and makes new indexes
# so we look for the new index of the current song on load # so we look for the new index of the current song on load
# current_song_filepath = self.get_current_song_filepath() # current_song_filepath = self.get_current_song_filepath()
# debug(f"load_music_table() | current filepath: {current_song_filepath}") # debug(f"load_music_table() | current filepath: {current_song_filepath}")
# for row in range(self.model2.rowCount()): # for row in range(self.model2.rowCount()):
# real_index = self.model2.index( # real_index = self.model2.index(
# row, self.headers.user_fields.index("filepath") # row, self.headers.db_list.index("filepath")
# ) # )
# if real_index.data() == current_song_filepath: # if real_index.data() == current_song_filepath:
# self.current_song_qmodel_index = real_index # self.current_song_qmodel_index = real_index
@ -838,21 +853,22 @@ class MusicTable(QTableView):
db_filename = self.config.get("settings", "db") db_filename = self.config.get("settings", "db")
self.playlistStatsSignal.emit(f"Songs: {self.model2.rowCount()} | {db_name} | {db_filename}") self.playlistStatsSignal.emit(f"Songs: {self.model2.rowCount()} | {db_name} | {db_filename}")
self.loadMusicTableSignal.emit() self.loadMusicTableSignal.emit()
self.connect_data_changed() # self.connect_data_changed()
self.connect_layout_changed() # self.connect_layout_changed()
# set the current song and such # set the current song and such
self.find_current_and_selected_bits() self.find_current_and_selected_bits()
self.jump_to_current_song()
# self.restore_scroll_position() # self.restore_scroll_position()
def find_current_and_selected_bits(self): def find_current_and_selected_bits(self):
""" """
When data changes in the model view, its nice to re-grab the current song. When data changes in the model view, its nice to re-grab the current song index information
might as well get the selected song too i guess? though nothing should be selected when reloading the table data might as well get the selected song too i guess? though nothing should be selected when reloading the table data
""" """
search_col_num = self.headers.db_list.index("filepath") search_col_num = self.headers.db_list.index("filepath")
selected_qmodel_index = self.find_qmodel_index_by_value(self.proxymodel, search_col_num, self.selected_song_filepath) selected_qmodel_index = self.find_qmodel_index_by_value(self.proxymodel, search_col_num, self.selected_song_filepath)
current_qmodel_index = self.find_qmodel_index_by_value(self.proxymodel, search_col_num, self.current_song_filepath) current_qmodel_index = self.find_qmodel_index_by_value(self.proxymodel, search_col_num, self.current_song_filepath)
# Update the 2 QModelIndexes that we track # Update the 2 proxy QModelIndexes that we track
self.set_selected_song_qmodel_index(selected_qmodel_index) self.set_selected_song_qmodel_index(selected_qmodel_index)
self.set_current_song_qmodel_index(current_qmodel_index) self.set_current_song_qmodel_index(current_qmodel_index)
@ -885,8 +901,8 @@ class MusicTable(QTableView):
Sorts the data in QTableView (self) by multiple columns Sorts the data in QTableView (self) by multiple columns
as defined in config.ini as defined in config.ini
""" """
self.disconnect_data_changed() # not needed? # self.disconnect_data_changed() # not needed?
self.disconnect_layout_changed() # not needed? # self.disconnect_layout_changed() # not needed?
self.horizontal_header.sortIndicatorChanged.disconnect() self.horizontal_header.sortIndicatorChanged.disconnect()
sort_orders = [] sort_orders = []
config_sort_orders: list[int] = [ config_sort_orders: list[int] = [
@ -911,18 +927,22 @@ class MusicTable(QTableView):
# maybe not a huge deal for a small music application...? # maybe not a huge deal for a small music application...?
# `len(config_sort_orders)` number of SELECTs # `len(config_sort_orders)` number of SELECTs
self.on_sort() self.on_sort()
self.connect_data_changed() # not needed? # self.connect_data_changed() # not needed?
self.connect_layout_changed() # not needed? # self.connect_layout_changed() # not needed?
self.model2.layoutChanged.emit() self.model2.layoutChanged.emit()
def save_scroll_position(self, playlist_id: int | None): def save_scroll_position(self, playlist_id: int | None):
"""Save the current scroll position of the table""" """Save the current scroll position of the table"""
# FIXME: does not work - except i'm using jump_to_current_song as a
# stand in for scroll position features
scroll_position = self.verticalScrollBar().value() scroll_position = self.verticalScrollBar().value()
self.playlist_scroll_positions[playlist_id] = scroll_position self.playlist_scroll_positions[playlist_id] = scroll_position
debug(f'save scroll position: {playlist_id}:{scroll_position}') debug(f'save scroll position: {playlist_id}:{scroll_position}')
def restore_scroll_position(self): def restore_scroll_position(self):
"""Set the scroll position to the given value""" """Set the scroll position to the given value"""
# FIXME: does not work - except i'm using jump_to_current_song as a
# stand in for scroll position features
if self.current_playlist_id in self.playlist_scroll_positions: if self.current_playlist_id in self.playlist_scroll_positions:
scroll_position = self.playlist_scroll_positions[self.current_playlist_id] scroll_position = self.playlist_scroll_positions[self.current_playlist_id]
# self.restore_scroll_position(scroll_position) # self.restore_scroll_position(scroll_position)
@ -1081,7 +1101,7 @@ class MusicTable(QTableView):
"""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

View File

@ -99,7 +99,6 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
# widget bits # widget bits
self.tableView: MusicTable self.tableView: MusicTable
self.tableView.saved_column_ratios: list[str] = str(self.config["table"]["column_ratios"]).split(",") # type: ignore self.tableView.saved_column_ratios: list[str] = str(self.config["table"]["column_ratios"]).split(",") # type: ignore
debug(f'AAAAA - {self.tableView.saved_column_ratios}')
self.album_art_scene: QGraphicsScene = QGraphicsScene() self.album_art_scene: QGraphicsScene = QGraphicsScene()
self.player: QMediaPlayer = MediaPlayer() self.player: QMediaPlayer = MediaPlayer()
# set index on choose song # set index on choose song