jump to current song after sorting, model2, proxymodel
This commit is contained in:
parent
171583b2f7
commit
31f74f7276
@ -59,9 +59,10 @@ from configparser import ConfigParser
|
||||
|
||||
class MusicTable(QTableView):
|
||||
playPauseSignal = pyqtSignal()
|
||||
playSignal = pyqtSignal(str)
|
||||
enterKey = pyqtSignal()
|
||||
deleteKey = pyqtSignal()
|
||||
refreshMusicTable = pyqtSignal()
|
||||
refreshMusicTableSignal = pyqtSignal()
|
||||
handleProgressSignal = pyqtSignal(str)
|
||||
getThreadPoolSignal = pyqtSignal()
|
||||
|
||||
@ -81,9 +82,9 @@ class MusicTable(QTableView):
|
||||
# need a standard item model to do actions on cells
|
||||
self.model2: QStandardItemModel = QStandardItemModel()
|
||||
# proxy model for sorting i guess?
|
||||
proxymodel = QSortFilterProxyModel()
|
||||
proxymodel.setSourceModel(self.model2)
|
||||
self.setModel(proxymodel)
|
||||
self.proxymodel = QSortFilterProxyModel()
|
||||
self.proxymodel.setSourceModel(self.model2)
|
||||
self.setModel(self.proxymodel)
|
||||
self.setSortingEnabled(True)
|
||||
|
||||
# Config
|
||||
@ -124,7 +125,7 @@ class MusicTable(QTableView):
|
||||
self.selected_song_filepath = ""
|
||||
self.current_song_filepath = ""
|
||||
self.current_song_db_id = None
|
||||
self.current_song_qmodelindex: QModelIndex
|
||||
self.current_song_qmodel_index: QModelIndex
|
||||
|
||||
# Properties
|
||||
self.setAcceptDrops(True)
|
||||
@ -140,6 +141,7 @@ class MusicTable(QTableView):
|
||||
assert self.horizontal_header is not None # i hate look at linting errors
|
||||
self.horizontal_header.setStretchLastSection(True)
|
||||
self.horizontal_header.setSectionResizeMode(QHeaderView.Interactive)
|
||||
self.horizontal_header.sortIndicatorChanged.connect(self.on_sort)
|
||||
# dumb vertical estupido
|
||||
self.vertical_header: QHeaderView = self.verticalHeader()
|
||||
assert self.vertical_header is not None
|
||||
@ -148,8 +150,8 @@ class MusicTable(QTableView):
|
||||
# CONNECTIONS
|
||||
self.clicked.connect(self.on_cell_clicked)
|
||||
self.deleteKey.connect(self.delete_songs)
|
||||
# self.doubleClicked.connect(self.set_current_song_filepath)
|
||||
# self.enterKey.connect(self.set_current_song_filepath)
|
||||
self.doubleClicked.connect(self.play_audio_file)
|
||||
self.enterKey.connect(self.play_audio_file)
|
||||
self.model2.dataChanged.connect(self.on_cell_data_changed) # editing cells
|
||||
self.model2.layoutChanged.connect(self.restore_scroll_position)
|
||||
self.horizontal_header.sectionResized.connect(self.on_header_resized)
|
||||
@ -265,7 +267,9 @@ class MusicTable(QTableView):
|
||||
if directories:
|
||||
worker = Worker(self.get_audio_files_recursively, directories)
|
||||
worker.signals.signal_progress.connect(self.handle_progress)
|
||||
worker.signals.signal_result.connect(self.on_get_audio_files_recursively_finished)
|
||||
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
|
||||
@ -339,14 +343,38 @@ class MusicTable(QTableView):
|
||||
# | |
|
||||
# |____________________|
|
||||
|
||||
def find_qmodel_index_by_value(self, model, column: int, value) -> QModelIndex:
|
||||
for row in range(model.rowCount()):
|
||||
index = model.index(row, column)
|
||||
if index.data() == value:
|
||||
return index
|
||||
return QModelIndex() # Invalid index if not found
|
||||
|
||||
def on_sort(self):
|
||||
debug("on_sort")
|
||||
search_col_num = self.table_headers.index("path")
|
||||
qmodel_index = self.find_qmodel_index_by_value(
|
||||
self.model2, search_col_num, self.current_song_filepath
|
||||
)
|
||||
self.set_qmodel_index(qmodel_index)
|
||||
self.jump_to_current_song()
|
||||
|
||||
# ```python
|
||||
# (method) def match(
|
||||
# start: QModelIndex,
|
||||
# role: int,
|
||||
# value: Any,
|
||||
# hits: int = ...,
|
||||
# flags: MatchFlags | MatchFlag = ...
|
||||
# ) -> List[QModelIndex]
|
||||
# ```
|
||||
|
||||
def on_cell_clicked(self, index):
|
||||
"""
|
||||
When a cell is clicked, do some stuff :)
|
||||
- this func also runs when double click happens, fyi
|
||||
"""
|
||||
current_index = self.currentIndex()
|
||||
if index == current_index:
|
||||
return
|
||||
self.setCurrentIndex(index)
|
||||
debug("on_cell_clicked")
|
||||
self.set_selected_song_filepath()
|
||||
self.viewport().update() # type: ignore
|
||||
|
||||
@ -431,6 +459,17 @@ class MusicTable(QTableView):
|
||||
# | |
|
||||
# |____________________|
|
||||
|
||||
def set_qmodel_index(self, index: QModelIndex):
|
||||
self.current_song_qmodel_index = index
|
||||
|
||||
def play_audio_file(self):
|
||||
"""
|
||||
Sets the current song filepath
|
||||
Emits a signal that the current song should start playback
|
||||
"""
|
||||
self.set_current_song_filepath()
|
||||
self.playSignal.emit(self.current_song_filepath)
|
||||
|
||||
def add_files_to_library(self, files: list[str]) -> None:
|
||||
"""
|
||||
Spawns a worker thread - adds a list of filepaths to the library
|
||||
@ -495,14 +534,26 @@ class MusicTable(QTableView):
|
||||
|
||||
def jump_to_current_song(self):
|
||||
"""Moves screen to the currently playing song, and selects the row"""
|
||||
debug("jump_to_current_song")
|
||||
print(self.current_song_qmodel_index.model() == self.model2)
|
||||
print("is it?")
|
||||
print("current song qmodel index")
|
||||
print(self.current_song_qmodel_index)
|
||||
proxy_index = self.proxymodel.mapFromSource(self.current_song_qmodel_index)
|
||||
print(f"proxy index: {proxy_index}")
|
||||
self.scrollTo(proxy_index)
|
||||
row = proxy_index.row()
|
||||
print(f"proxy index row: {row}")
|
||||
self.selectRow(proxy_index.row())
|
||||
|
||||
# self.scrollTo(self.current_song_qmodel_index)
|
||||
# row = self.current_song_qmodel_index.row()
|
||||
# self.selectRow(row)
|
||||
|
||||
# FIXME: this doesn't work regardless of sorting
|
||||
# 1. play song 2. sort columns differently 3. jump to current song
|
||||
# this will jump to table index of where the song was when it started playing (its index was set)
|
||||
|
||||
self.scrollTo(self.current_song_qmodelindex)
|
||||
row = self.current_song_qmodelindex.row()
|
||||
self.selectRow(row)
|
||||
|
||||
def open_directory(self):
|
||||
"""Opens the currently selected song in the system file manager"""
|
||||
if self.get_selected_song_filepath() is None:
|
||||
@ -810,15 +861,17 @@ class MusicTable(QTableView):
|
||||
def set_current_song_filepath(self) -> None:
|
||||
"""
|
||||
Sets the current song filepath to the value in column 'path' with current selected row index
|
||||
also stores the QModelIndex for some useful other stuff
|
||||
also stores the QModelIndex for some useful navigation stuff
|
||||
"""
|
||||
# NOTE:
|
||||
# Setting the current song filepath automatically plays that song
|
||||
# self.tableView listens to this function and plays the audio file located at self.current_song_filepath
|
||||
self.current_song_qmodelindex: QModelIndex = self.currentIndex()
|
||||
self.current_song_filepath: str = self.current_song_qmodelindex.siblingAtColumn(
|
||||
self.table_headers.index("path")
|
||||
).data()
|
||||
# Get
|
||||
source_index = self.proxymodel.mapToSource(self.currentIndex())
|
||||
self.current_song_qmodel_index: QModelIndex = source_index
|
||||
|
||||
self.current_song_filepath: str = (
|
||||
self.current_song_qmodel_index.siblingAtColumn(
|
||||
self.table_headers.index("path")
|
||||
).data()
|
||||
)
|
||||
|
||||
def load_qapp(self, qapp) -> None:
|
||||
"""Necessary for using members and methods of main application window"""
|
||||
@ -859,6 +912,7 @@ class MusicTable(QTableView):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
# QT Roles
|
||||
|
||||
# In Qt, roles are used to specify different aspects or types of data associated with each item in a model. The roles are defined in the Qt.ItemDataRole enum. The three roles you asked about - DisplayRole, EditRole, and UserRole - are particularly important. Let's break them down:
|
||||
|
||||
16
main.py
16
main.py
@ -232,6 +232,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
# tableView
|
||||
self.tableView.doubleClicked.connect(self.play_audio_file)
|
||||
self.tableView.enterKey.connect(self.play_audio_file)
|
||||
self.tableView.playSignal.connect(self.play_audio_file)
|
||||
self.tableView.playPauseSignal.connect(
|
||||
self.on_play_clicked
|
||||
) # Spacebar toggle play/pause signal
|
||||
@ -390,11 +391,11 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
else:
|
||||
self.status_bar.showMessage(message)
|
||||
|
||||
def play_audio_file(self) -> None:
|
||||
def play_audio_file(self, filepath: str) -> None:
|
||||
"""
|
||||
Start playback of `tableView.current_song_filepath` & moves playback slider
|
||||
"""
|
||||
self.tableView.set_current_song_filepath()
|
||||
# self.tableView.set_current_song_filepath()
|
||||
# get metadata
|
||||
self.current_song_metadata = self.tableView.get_current_song_metadata()
|
||||
# read the file
|
||||
@ -568,6 +569,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
initialize_db()
|
||||
self.tableView.load_music_table()
|
||||
|
||||
|
||||
def update_database_file() -> bool:
|
||||
"""
|
||||
Reads the database file (specified by config file)
|
||||
@ -583,7 +585,9 @@ def update_database_file() -> bool:
|
||||
# If the database location isnt set at the config location, move it
|
||||
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}")
|
||||
debug(
|
||||
f"Set new config [db] database path: \n> Current: {db_filepath}\n> New:{new_path}"
|
||||
)
|
||||
config["db"]["database"] = new_path
|
||||
# Save the config
|
||||
with open(cfg_file, "w") as configfile:
|
||||
@ -595,12 +599,11 @@ def update_database_file() -> bool:
|
||||
db_path.pop()
|
||||
db_path = "/".join(db_path)
|
||||
|
||||
|
||||
if os.path.exists(db_filepath):
|
||||
try:
|
||||
size = os.path.getsize(db_filepath)
|
||||
except OSError:
|
||||
error('Database file exists but could not read.')
|
||||
error("Database file exists but could not read.")
|
||||
return False
|
||||
if size == 0:
|
||||
initialize_db()
|
||||
@ -611,6 +614,7 @@ def update_database_file() -> bool:
|
||||
initialize_db()
|
||||
return True
|
||||
|
||||
|
||||
def update_config_file() -> ConfigParser:
|
||||
"""
|
||||
If the user config file is not up to date, update it with examples from sample config
|
||||
@ -655,8 +659,6 @@ def update_config_file() -> ConfigParser:
|
||||
return config
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# logging setup
|
||||
file_handler = logging.FileHandler(filename="log", encoding="utf-8")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user