header widths and dynamic resizing and stuff

This commit is contained in:
billy 2025-10-04 15:39:12 -04:00
parent f1d018f7ce
commit 753117dacc
2 changed files with 105 additions and 85 deletions

View File

@ -24,6 +24,7 @@ from PyQt5.QtWidgets import (
from PyQt5.QtCore import (
QItemSelectionModel,
QSortFilterProxyModel,
QTimer,
Qt,
QModelIndex,
pyqtSignal,
@ -74,13 +75,13 @@ class MusicTable(QTableView):
super().__init__(parent)
# why do i need this?
self.application_window = application_window
self.config = ConfigParser()
# Config
cfg_file = (
self.config = ConfigParser()
self.cfg_file = (
Path(user_config_dir(appname="musicpom", appauthor="billypom"))
/ "config.ini"
)
_ = self.config.read(cfg_file)
_ = self.config.read(self.cfg_file)
debug(f"music table config: {self.config}")
# NOTE:
@ -125,7 +126,6 @@ class MusicTable(QTableView):
# header
self.horizontal_header: QHeaderView = self.horizontalHeader()
assert self.horizontal_header is not None # i hate look at linting errors
self.horizontal_header.setStretchLastSection(False)
self.horizontal_header.setSectionResizeMode(QHeaderView.Interactive)
# dumb vertical estupido
self.vertical_header: QHeaderView = self.verticalHeader()
@ -142,7 +142,6 @@ class MusicTable(QTableView):
# Final actions
# self.load_music_table()
self.setup_keyboard_shortcuts()
self.load_header_widths()
# _________________
# | |
@ -165,11 +164,26 @@ class MusicTable(QTableView):
"""
self.focusLeaveSignal.emit()
def resizeEvent(self, e: typing.Optional[QResizeEvent]) -> None:
"""Do something when the QTableView is resized"""
"""
Do something when the QTableView is resized
We will recalculate column widths based on the new table width,
retaining the ratio of the original column widths.
"""
super().resizeEvent(e)
if e is None:
raise Exception
super().resizeEvent(e)
self.load_header_widths(self.saved_column_ratios)
def showEvent(self, a0):
# Restore scroll position
super().showEvent(a0)
# widths = []
# for _ in self.saved_column_ratios:
# widths.append('0.001')
# self.load_header_widths(widths)
QTimer.singleShot(0, lambda: self.load_header_widths(self.saved_column_ratios))
def paintEvent(self, e):
"""Override paint event to highlight the current cell"""
@ -267,7 +281,7 @@ class MusicTable(QTableView):
_ = worker.signals.signal_result.connect(self.on_get_audio_files_recursively_finished)
_ = worker.signals.signal_finished.connect(self.load_music_table)
if self.qapp:
threadpool = self.qapp.threadpool
threadpool = self.qapp.threadpool # type: ignore
threadpool.start(worker)
if files:
self.add_files_to_library(files)
@ -327,9 +341,6 @@ class MusicTable(QTableView):
else: # Default behavior
super().keyPressEvent(e)
def showEvent(self, a0):
# Restore scroll position
super().showEvent(a0)
# ____________________
# | |
@ -370,8 +381,8 @@ class MusicTable(QTableView):
col_count = self.model2.columnCount()
qtableview_width = self.size().width()
sum_of_cols = self.horizontal_header.length()
debug(f'qtable_width: {qtableview_width}')
debug(f'sum of cols: {sum_of_cols}')
# debug(f'qtable_width: {qtableview_width}')
# debug(f'sum of cols: {sum_of_cols}')
if sum_of_cols != qtableview_width: # check for discrepancy
if logicalIndex < col_count: # if not the last header
@ -448,6 +459,55 @@ class MusicTable(QTableView):
# | |
# |____________________|
def get_current_header_width_ratios(self) -> list[str]:
"""
Get the current header widths, as ratios
"""
total_table_width = self.size().width()
column_ratios = []
for i in range(self.model2.columnCount() - 1):
column_width = self.columnWidth(i)
ratio = column_width / total_table_width
column_ratios.append(str(round(ratio, 4)))
# debug(f'get_current_header_width_ratios = {column_ratios}')
return column_ratios
def save_header_ratios(self):
"""
Saves the current header widths to memory and file, as ratios
"""
# WARNING: DOES NOT WORK and is not used.
# the same functionality is implemented in main.py closeEvent()
self.saved_column_ratios = self.get_current_header_width_ratios()
column_ratios_as_string = ",".join(self.saved_column_ratios)
self.config["table"]["column_ratios"] = column_ratios_as_string
# Save the config
try:
with open(self.cfg_file, "w") as configfile:
self.config.write(configfile)
except Exception as e:
debug(f"wtf man {e}")
debug(f"Saved column ratios: {self.saved_column_ratios}")
def load_header_widths(self, ratios: list[str] | None = None):
"""
Loads the header widths, based on saved ratios
or pass in a list of ratios to be loaded
"""
self.horizontal_header.setStretchLastSection(True)
if ratios is None:
column_ratios = self.get_current_header_width_ratios()
else:
column_ratios = ratios
total_table_width = self.size().width()
column_widths = []
for ratio in column_ratios:
column_widths.append(float(ratio) * total_table_width)
if isinstance(column_widths, list):
for i in range(self.model2.columnCount() - 1):
self.setColumnWidth(i, int(column_widths[i]))
def set_qmodel_index(self, index: QModelIndex):
self.current_song_qmodel_index = index
@ -469,11 +529,11 @@ class MusicTable(QTableView):
"""
debug('add_files_to_library()')
worker = Worker(add_files_to_database, files, None)
_ = worker.signals.signal_progress.connect(self.qapp.handle_progress)
_ = 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_finished.connect(self.load_music_table)
if self.qapp:
threadpool = self.qapp.threadpool
threadpool = self.qapp.threadpool # type: ignore
threadpool.start(worker)
else:
error("Application window could not be found")
@ -820,17 +880,6 @@ class MusicTable(QTableView):
self.proxymodel.setSourceModel(self.model2)
self.setModel(self.proxymodel)
def load_header_widths(self):
"""
Loads the header widths from the last application close.
"""
table_view_column_widths = str(
self.config["table"]["column_widths"]).split(",")
debug(f"loaded header widths: {table_view_column_widths}")
if not isinstance(table_view_column_widths, list):
for i in range(self.model2.columnCount() - 1):
self.setColumnWidth(i, int(table_view_column_widths[i]))
def sort_table_by_multiple_columns(self):
"""
Sorts the data in QTableView (self) by multiple columns

89
main.py
View File

@ -98,14 +98,14 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
# widget bits
self.tableView: MusicTable
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.player: QMediaPlayer = MediaPlayer()
# set index on choose song
# index is the model2's row number? i guess?
self.probe: QAudioProbe = QAudioProbe() # Gets audio buffer data
self.audio_visualizer: AudioVisualizer = AudioVisualizer(
self.player, self.probe, self.PlotWidget
)
self.audio_visualizer: AudioVisualizer = AudioVisualizer(self.player, self.probe, self.PlotWidget)
self.timer: QTimer = QTimer(parent=self) # for playback slider and such
# Button styles
@ -146,26 +146,17 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
self.albumGraphicsView.setFixedSize(250, 250)
# Connections
self.playbackSlider.sliderReleased.connect(
lambda: self.player.setPosition(self.playbackSlider.value())
) # sliderReleased works better than sliderMoved
self.volumeSlider.sliderMoved[int].connect(
lambda: self.on_volume_changed())
self.speedSlider.sliderMoved.connect(
lambda: self.on_speed_changed(self.speedSlider.value())
)
self.playbackSlider.sliderReleased.connect(lambda: self.player.setPosition(self.playbackSlider.value())) # sliderReleased works better than sliderMoved
self.volumeSlider.sliderMoved[int].connect(lambda: self.on_volume_changed())
self.speedSlider.sliderMoved.connect(lambda: self.on_speed_changed(self.speedSlider.value()))
# self.speedSlider.doubleClicked.connect(lambda: self.on_speed_changed(1))
self.playButton.clicked.connect(
self.on_play_clicked) # Click to play/pause
self.playButton.clicked.connect(self.on_play_clicked) # Click to play/pause
self.previousButton.clicked.connect(self.on_prev_clicked)
self.nextButton.clicked.connect(
self.on_next_clicked) # Click to next song
self.nextButton.clicked.connect(self.on_next_clicked) # Click to next song
# FILE MENU
self.actionOpenFiles.triggered.connect(
self.open_files) # Open files window
self.actionNewPlaylist.triggered.connect(
self.playlistTreeView.create_playlist)
self.actionOpenFiles.triggered.connect(self.open_files) # Open files window
self.actionNewPlaylist.triggered.connect(self.playlistTreeView.create_playlist)
self.actionExportPlaylist.triggered.connect(self.export_playlist)
# EDIT MENU
@ -175,9 +166,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
# QUICK ACTIONS MENU
self.actionScanLibraries.triggered.connect(self.scan_libraries)
self.actionDeleteDatabase.triggered.connect(self.delete_database)
self.actionSortColumns.triggered.connect(
self.tableView.sort_table_by_multiple_columns
)
self.actionSortColumns.triggered.connect(self.tableView.sort_table_by_multiple_columns)
# QTableView
# for drag & drop functionality
@ -187,36 +176,23 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
self.lineEditSearch: QLineEdit
# CONNECTIONS
self.lineEditSearch.textTypedSignal.connect(
self.handle_search_box_text)
self.lineEditSearch.textTypedSignal.connect(self.handle_search_box_text)
# tableView
self.tableView.playSignal.connect(self.play_audio_file)
self.tableView.playPauseSignal.connect(
self.on_play_clicked
) # Spacebar toggle play/pause signal
self.tableView.playPauseSignal.connect(self.on_play_clicked) # Spacebar toggle play/pause signal
self.tableView.handleProgressSignal.connect(self.handle_progress)
self.tableView.searchBoxSignal.connect(
self.handle_search_box_visibility)
self.tableView.playlistStatsSignal.connect(
self.set_permanent_status_bar_message
)
self.tableView.searchBoxSignal.connect(self.handle_search_box_visibility)
self.tableView.playlistStatsSignal.connect(self.set_permanent_status_bar_message)
self.tableView.load_music_table()
self.player.playlistNextSignal.connect(self.on_next_clicked)
# playlistTreeView
self.playlistTreeView.playlistChoiceSignal.connect(
self.tableView.load_music_table
)
self.playlistTreeView.allSongsSignal.connect(
self.tableView.load_music_table)
self.playlistTreeView.playlistChoiceSignal.connect(self.tableView.load_music_table)
self.playlistTreeView.allSongsSignal.connect(self.tableView.load_music_table)
# albumGraphicsView
self.albumGraphicsView.albumArtDropped.connect(
self.set_album_art_for_selected_songs
)
self.albumGraphicsView.albumArtDeleted.connect(
self.delete_album_art_for_current_song
)
self.albumGraphicsView.albumArtDropped.connect(self.set_album_art_for_selected_songs)
self.albumGraphicsView.albumArtDeleted.connect(self.delete_album_art_for_current_song)
# _________________
# | |
@ -233,23 +209,22 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
def closeEvent(self, a0: QCloseEvent | None) -> None:
"""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
# 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"]["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())
# Save the config
try:
with open(self.cfg_file, "w") as configfile:
self.config.write(configfile)
except Exception as e:
debug(f"wtf man {e}")
# auto export any playlists that want it
try:
with DBA.DBAccess() as db:
@ -343,12 +318,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
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.db_list.index("filepath")
).data()
next_index: QModelIndex = self.tableView.proxymodel.index(next_row, index.column())
next_filepath = next_index.siblingAtColumn(self.headers.db_list.index("filepath")).data()
if next_filepath is None:
return
self.play_audio_file(next_filepath)