fixes and idk
This commit is contained in:
parent
69ce4bc763
commit
d01a743c45
@ -75,58 +75,38 @@ class MusicTable(QTableView):
|
||||
focusEnterSignal = pyqtSignal()
|
||||
focusLeaveSignal = pyqtSignal()
|
||||
|
||||
def focusInEvent(self, e):
|
||||
"""
|
||||
Event filter: when self is focused
|
||||
"""
|
||||
self.focusEnterSignal.emit()
|
||||
# arrow keys act normal
|
||||
super().focusInEvent(e)
|
||||
|
||||
def focusOutEvent(self, e):
|
||||
"""
|
||||
Event filter: when self becomes unfocused
|
||||
"""
|
||||
self.focusLeaveSignal.emit()
|
||||
|
||||
def __init__(self, parent=None, application_window=None):
|
||||
super().__init__(parent)
|
||||
# why do i need this?
|
||||
self.application_window = application_window
|
||||
|
||||
# NOTE: wtf is actually going on here with the models?
|
||||
# Create QStandardItemModel
|
||||
# Create QSortFilterProxyModel
|
||||
# Set QSortFilterProxyModel source to QStandardItemModel
|
||||
# Set QTableView model to the Proxy model
|
||||
# so it looks like this, i guess:
|
||||
# QTableView model2 = QSortFilterProxyModel(QStandardItemModel)
|
||||
|
||||
# need a standard item model to do actions on cells
|
||||
self.model2: QStandardItemModel = QStandardItemModel()
|
||||
# proxy model for sorting i guess?
|
||||
self.proxymodel = QSortFilterProxyModel()
|
||||
self.proxymodel.setSourceModel(self.model2)
|
||||
self.setModel(self.proxymodel)
|
||||
self.setSortingEnabled(True)
|
||||
self.search_string = None
|
||||
|
||||
self.config = ConfigParser()
|
||||
# Config
|
||||
cfg_file = (
|
||||
Path(user_config_dir(appname="musicpom", appauthor="billypom"))
|
||||
/ "config.ini"
|
||||
)
|
||||
self.config = ConfigParser()
|
||||
self.config.read(cfg_file)
|
||||
debug(f"music table config: {self.config}")
|
||||
|
||||
# Threads
|
||||
self.threadpool = QThreadPool
|
||||
# headers class thing
|
||||
self.headers = HeaderTags()
|
||||
# NOTE:
|
||||
# QTableView model2 = QSortFilterProxyModel(QStandardItemModel)
|
||||
#
|
||||
# wtf is actually going on here with the models?
|
||||
# Create QStandardItemModel
|
||||
# Create QSortFilterProxyModel
|
||||
# Set QSortFilterProxyModel source to QStandardItemModel
|
||||
# Set QTableView model to the Proxy model
|
||||
# so it looks like that, i guess
|
||||
|
||||
# need a QStandardItemModel to do actions on cells
|
||||
self.model2: QStandardItemModel = QStandardItemModel()
|
||||
self.proxymodel = QSortFilterProxyModel()
|
||||
self.search_string = None
|
||||
self.threadpool = QThreadPool
|
||||
self.headers = HeaderTags()
|
||||
# db names of headers
|
||||
self.database_columns = str(self.config["table"]["columns"]).split(",")
|
||||
self.database_columns: list[str] = str(
|
||||
self.config["table"]["columns"]).split(",")
|
||||
self.vertical_scroll_position = 0
|
||||
self.selected_song_filepath = ""
|
||||
self.selected_song_qmodel_index: QModelIndex
|
||||
@ -135,6 +115,11 @@ class MusicTable(QTableView):
|
||||
self.current_song_qmodel_index: QModelIndex
|
||||
self.selected_playlist_id: int | None = None
|
||||
|
||||
# proxy model for sorting i guess?
|
||||
self.proxymodel.setSourceModel(self.model2)
|
||||
self.setModel(self.proxymodel)
|
||||
self.setSortingEnabled(True)
|
||||
|
||||
# Properties
|
||||
self.setAcceptDrops(True)
|
||||
self.setHorizontalScrollBarPolicy(
|
||||
@ -175,6 +160,20 @@ class MusicTable(QTableView):
|
||||
# | |
|
||||
# |_________________|
|
||||
|
||||
def focusInEvent(self, e):
|
||||
"""
|
||||
Event filter: when self is focused
|
||||
"""
|
||||
self.focusEnterSignal.emit()
|
||||
# arrow keys act normal
|
||||
super().focusInEvent(e)
|
||||
|
||||
def focusOutEvent(self, e):
|
||||
"""
|
||||
Event filter: when self becomes unfocused
|
||||
"""
|
||||
self.focusLeaveSignal.emit()
|
||||
|
||||
def resizeEvent(self, e: typing.Optional[QResizeEvent]) -> None:
|
||||
"""Do something when the QTableView is resized"""
|
||||
if e is None:
|
||||
@ -490,7 +489,8 @@ class MusicTable(QTableView):
|
||||
"""
|
||||
worker = Worker(add_files_to_database, files)
|
||||
_ = worker.signals.signal_progress.connect(self.qapp.handle_progress)
|
||||
_ = worker.signals.signal_result.connect(self.on_add_files_to_database_finished)
|
||||
_ = 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
|
||||
@ -660,7 +660,7 @@ class MusicTable(QTableView):
|
||||
def reorganize_files(self, filepaths, progress_callback=None):
|
||||
"""
|
||||
Reorganizes files into Artist/Album/Song,
|
||||
based on self.config['directories'][reorganize_destination']
|
||||
based on self.config['settings'][reorganize_destination']
|
||||
"""
|
||||
debug("reorganizing files")
|
||||
# FIXME: batch update, instead of doing 1 file at a time
|
||||
@ -671,7 +671,7 @@ class MusicTable(QTableView):
|
||||
# FIXME: change reorganize location in config, try to reorganize, failed - old reference
|
||||
|
||||
# Get target directory
|
||||
target_dir = str(self.config["directories"]["reorganize_destination"])
|
||||
target_dir = str(self.config["settings"]["reorganize_destination"])
|
||||
for filepath in filepaths:
|
||||
# Read file metadata
|
||||
artist, album = get_reorganize_vars(filepath)
|
||||
@ -737,7 +737,8 @@ class MusicTable(QTableView):
|
||||
self.selected_playlist_id = playlist_id[0]
|
||||
try:
|
||||
with DBA.DBAccess() as db:
|
||||
query = f"SELECT id, {fields} FROM song JOIN song_playlist sp ON id = sp.song_id WHERE sp.playlist_id = ?"
|
||||
query = f"SELECT id, {
|
||||
fields} FROM song JOIN song_playlist sp ON id = sp.song_id WHERE sp.playlist_id = ?"
|
||||
# fulltext search
|
||||
if self.search_string:
|
||||
# params = 3 * [self.search_string]
|
||||
@ -821,7 +822,8 @@ class MusicTable(QTableView):
|
||||
db_name: str = self.config.get("settings", "db").split("/").pop()
|
||||
db_filename = self.config.get("settings", "db")
|
||||
self.playlistStatsSignal.emit(
|
||||
f"Songs: {row_count} | Total time: {total_time} | {db_name} | {db_filename}"
|
||||
f"Songs: {row_count} | Total time: {
|
||||
total_time} | {db_name} | {db_filename}"
|
||||
)
|
||||
self.loadMusicTableSignal.emit()
|
||||
self.connect_data_changed()
|
||||
|
||||
70
main.py
70
main.py
@ -57,6 +57,8 @@ from utils import (
|
||||
add_files_to_database,
|
||||
set_album_art,
|
||||
id3_remap,
|
||||
get_album_art,
|
||||
Worker
|
||||
)
|
||||
from components import (
|
||||
HeaderTags,
|
||||
@ -68,9 +70,6 @@ from components import (
|
||||
ExportPlaylistWindow,
|
||||
SearchLineEdit,
|
||||
)
|
||||
from utils.get_album_art import get_album_art
|
||||
# from utils.Worker import Worker
|
||||
from utils import Worker
|
||||
|
||||
# good help with signals slots in threads
|
||||
# https://stackoverflow.com/questions/52993677/how-do-i-setup-signals-and-slots-in-pyqt-with-qthreads-in-both-directions
|
||||
@ -162,18 +161,23 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
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.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
|
||||
@ -195,14 +199,16 @@ 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.handleProgressSignal.connect(self.handle_progress)
|
||||
self.tableView.searchBoxSignal.connect(self.handle_search_box_visibility)
|
||||
self.tableView.searchBoxSignal.connect(
|
||||
self.handle_search_box_visibility)
|
||||
self.tableView.playlistStatsSignal.connect(
|
||||
self.set_permanent_status_bar_message
|
||||
)
|
||||
@ -213,7 +219,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
self.playlistTreeView.playlistChoiceSignal.connect(
|
||||
self.tableView.load_music_table
|
||||
)
|
||||
self.playlistTreeView.allSongsSignal.connect(self.tableView.load_music_table)
|
||||
self.playlistTreeView.allSongsSignal.connect(
|
||||
self.tableView.load_music_table)
|
||||
|
||||
# albumGraphicsView
|
||||
self.albumGraphicsView.albumArtDropped.connect(
|
||||
@ -315,7 +322,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
current_real_index = self.tableView.current_song_qmodel_index
|
||||
try:
|
||||
index = self.tableView.proxymodel.mapFromSource(current_real_index)
|
||||
except:
|
||||
except Exception:
|
||||
return
|
||||
row: int = index.row()
|
||||
prev_row: int = row - 1
|
||||
@ -392,7 +399,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
def load_config(self) -> None:
|
||||
"""does what it says"""
|
||||
cfg_file = (
|
||||
Path(user_config_dir(appname="musicpom", appauthor="billypom")) / "config.ini"
|
||||
Path(user_config_dir(appname="musicpom",
|
||||
appauthor="billypom")) / "config.ini"
|
||||
)
|
||||
self.config.read(cfg_file)
|
||||
debug("load_config()")
|
||||
@ -470,7 +478,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
selected_songs = self.tableView.get_selected_songs_filepaths()
|
||||
for song in selected_songs:
|
||||
debug(
|
||||
f"main.py set_album_art_for_selected_songs() | updating album art for {song}"
|
||||
f"main.py set_album_art_for_selected_songs() | updating album art for {
|
||||
song}"
|
||||
)
|
||||
set_album_art(song, album_art_path)
|
||||
|
||||
@ -497,7 +506,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
self.playbackSlider.setMaximum(self.player.duration())
|
||||
slider_position = self.player.position()
|
||||
self.playbackSlider.setValue(slider_position)
|
||||
current_minutes, current_seconds = divmod(slider_position / 1000, 60)
|
||||
current_minutes, current_seconds = divmod(
|
||||
slider_position / 1000, 60)
|
||||
duration_minutes, duration_seconds = divmod(
|
||||
self.player.duration() / 1000, 60
|
||||
)
|
||||
@ -548,7 +558,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
def create_playlist(self) -> None:
|
||||
"""Creates a database record for a playlist, given a name"""
|
||||
window = CreatePlaylistWindow(self.playlistCreatedSignal)
|
||||
window.playlistCreatedSignal.connect(self.add_latest_playlist_to_tree) # type: ignore
|
||||
window.playlistCreatedSignal.connect(
|
||||
self.add_latest_playlist_to_tree) # type: ignore
|
||||
window.exec_()
|
||||
|
||||
def import_playlist(self) -> None:
|
||||
@ -574,8 +585,10 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
preferences_window = PreferencesWindow(
|
||||
self.reloadConfigSignal, self.reloadDatabaseSignal
|
||||
)
|
||||
preferences_window.reloadConfigSignal.connect(self.load_config) # type: ignore
|
||||
preferences_window.reloadDatabaseSignal.connect(self.tableView.load_music_table) # type: ignore
|
||||
preferences_window.reloadConfigSignal.connect(
|
||||
self.load_config) # type: ignore
|
||||
preferences_window.reloadDatabaseSignal.connect(
|
||||
self.tableView.load_music_table) # type: ignore
|
||||
preferences_window.exec_() # Display the preferences window modally
|
||||
|
||||
# Quick Actions
|
||||
@ -609,9 +622,11 @@ def update_database_file() -> bool:
|
||||
Reads the database file (specified by config file)
|
||||
"""
|
||||
cfg_file = (
|
||||
Path(user_config_dir(appname="musicpom", appauthor="billypom")) / "config.ini"
|
||||
Path(user_config_dir(appname="musicpom",
|
||||
appauthor="billypom")) / "config.ini"
|
||||
)
|
||||
cfg_path = str(Path(user_config_dir(appname="musicpom", appauthor="billypom")))
|
||||
cfg_path = str(Path(user_config_dir(
|
||||
appname="musicpom", appauthor="billypom")))
|
||||
config = ConfigParser()
|
||||
config.read(cfg_file)
|
||||
db_filepath: str = config.get("settings", "db")
|
||||
@ -620,9 +635,10 @@ def update_database_file() -> bool:
|
||||
if not db_filepath.startswith(cfg_path):
|
||||
new_path = f"{cfg_path}/{db_filepath}"
|
||||
debug(
|
||||
f"Set new config [db] database path: \n> Current: {db_filepath}\n> New:{new_path}"
|
||||
f"Set new config [db] database path: \n> Current: {
|
||||
db_filepath}\n> New:{new_path}"
|
||||
)
|
||||
config["db"]["database"] = new_path
|
||||
config["settings"]["db"] = new_path
|
||||
# Save the config
|
||||
with open(cfg_file, "w") as configfile:
|
||||
config.write(configfile)
|
||||
@ -654,9 +670,11 @@ def update_config_file() -> ConfigParser:
|
||||
If the user config file is not up to date, update it with examples from sample config
|
||||
"""
|
||||
cfg_file = (
|
||||
Path(user_config_dir(appname="musicpom", appauthor="billypom")) / "config.ini"
|
||||
Path(user_config_dir(appname="musicpom",
|
||||
appauthor="billypom")) / "config.ini"
|
||||
)
|
||||
cfg_path = str(Path(user_config_dir(appname="musicpom", appauthor="billypom")))
|
||||
cfg_path = str(Path(user_config_dir(
|
||||
appname="musicpom", appauthor="billypom")))
|
||||
|
||||
# If config path doesn't exist, create it
|
||||
if not os.path.exists(cfg_path):
|
||||
@ -720,8 +738,8 @@ if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
clipboard = app.clipboard()
|
||||
# Dark theme >:3
|
||||
qdarktheme.setup_theme()
|
||||
# qdarktheme.setup_theme("auto") # this is supposed to work but doesnt
|
||||
# qdarktheme.setup_theme()
|
||||
qdarktheme.setup_theme("auto") # this is supposed to work but doesnt
|
||||
# Show the UI
|
||||
ui = ApplicationWindow(clipboard)
|
||||
# window size
|
||||
|
||||
@ -3,7 +3,8 @@ matplotlib
|
||||
appdirs
|
||||
pyqt5
|
||||
pydub
|
||||
pyqtdarktheme-fork; python_version > '3.11'
|
||||
pyqtdarktheme; python_version < '3.12'
|
||||
audioop-lts
|
||||
pyqtdarktheme-fork; python_version < '3.11'
|
||||
pyqtdarktheme; python_version > '3.12'
|
||||
pyqtgraph
|
||||
scipy
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user