musicpom/components/MusicTable.py

157 lines
6.2 KiB
Python

import DBA
from PyQt5.QtGui import QStandardItem, QStandardItemModel
from PyQt5.QtWidgets import QTableView
from PyQt5.QtCore import QTimer, Qt, pyqtSignal
from tinytag import TinyTag
from utils import add_files_to_library
from utils import get_id3_tags
from utils import get_album_art
import logging
class MusicTable(QTableView):
playPauseSignal = pyqtSignal()
enterKey = pyqtSignal()
def __init__(self, parent=None, qapp=None):
QTableView.__init__(self, parent)
self.headers = ['title', 'artist', 'album', 'genre', 'codec', 'year', 'path']
self.songChanged = None
self.selected_song_filepath = None
self.current_song_filepath = None
self.qapp = None
# self.tableView.resizeColumnsToContents()
self.clicked.connect(self.set_selected_song_filepath)
self.doubleClicked.connect(self.set_current_song_filepath) # listens for emitted signal, runs set_current_song_filepath
self.enterKey.connect(self.set_current_song_filepath)
self.fetch_library()
def keyPressEvent(self, event):
"""Press a key. Do a thing"""
key = event.key()
if key == Qt.Key_Space: # Spacebar to play/pause
self.toggle_play_pause()
elif key == Qt.Key_Up: # Arrow key navigation
current_index = self.currentIndex()
new_index = self.model.index(current_index.row() - 1, current_index.column())
if new_index.isValid():
self.setCurrentIndex(new_index)
elif key == Qt.Key_Down: # Arrow key navigation
current_index = self.currentIndex()
new_index = self.model.index(current_index.row() + 1, current_index.column())
if new_index.isValid():
self.setCurrentIndex(new_index)
elif key in (Qt.Key_Return, Qt.Key_Enter):
self.enterKey.emit() # Enter key detected
else: # Default behavior
super().keyPressEvent(event)
def mousePressEvent(self, event):
"""Press mouse button. Do thing"""
self.last = "Click"
QTableView.mousePressEvent(self, event) # Keep original functionality
def mouseReleaseEvent(self, event):
"""Release mouse button. Do thing"""
if self.last == "Click":
QTimer.singleShot(self.qapp.instance().doubleClickInterval(),
self.performSingleClickAction)
else:
# Perform double click action.
self.set_current_song_filepath
self.message = "Double Click"
self.update()
QTableView.mouseReleaseEvent(self, event) # Keep original functionality
def mouseDoubleClickEvent(self, event):
self.last = "Double Click"
self.doubleClicked.emit(self.selectionModel().currentIndex()) # emits the current index of the double clicked song
QTableView.mouseDoubleClickEvent(self, event) # Keep original functionality
def performSingleClickAction(self):
if self.last == "Click":
self.message = "Click"
self.update()
def toggle_play_pause(self):
"""Toggles the currently playing song by emitting a signal"""
if not self.current_song_filepath:
self.set_current_song_filepath()
self.playPauseSignal.emit()
def choose_new_song(self):
"""Starts the playback of a new song by emitting a signal"""
def get_selected_rows(self):
"""Returns a list of indexes for every selected row"""
rows = []
for idx in self.selectionModel().siblingAtColumn():
rows.append(idx.row())
return rows
def set_selected_song_filepath(self):
"""Sets the filepath of the currently selected song"""
self.selected_song_filepath = self.currentIndex().siblingAtColumn(self.headers.index('path')).data()
print(f'Selected song: {self.selected_song_filepath}')
def set_current_song_filepath(self):
"""Sets the filepath of the currently playing/chosen song"""
# 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_filepath = self.currentIndex().siblingAtColumn(self.headers.index('path')).data()
print(f'Current song: {self.current_song_filepath}')
def get_selected_song_filepath(self):
"""Returns the selected song filepath"""
return self.selected_song_filepath
def get_selected_song_metadata(self):
"""Returns the current/chosen song's ID3 tags"""
return get_id3_tags(self.selected_song_filepath)
def get_current_song_filepath(self):
"""Returns the current/chosen song filepath"""
return self.current_song_filepath
def get_current_song_metadata(self):
"""Returns the current/chosen song's ID3 tags"""
return get_id3_tags(self.current_song_filepath)
def get_current_song_album_art(self):
"""Returns the APIC data for the currently playing song"""
return get_album_art(self.current_song_filepath)
def fetch_library(self):
"""Initialize the tableview model"""
self.model = QStandardItemModel()
self.model.setHorizontalHeaderLabels(self.headers)
# Fetch library data
with DBA.DBAccess() as db:
data = db.query('SELECT title, artist, album, genre, codec, album_date, filepath FROM library;', ())
# Populate the model
for row_data in data:
items = [QStandardItem(str(item)) for item in row_data]
self.model.appendRow(items)
# Set the model to the tableView (we are the tableview)
self.setModel(self.model)
# self.update()
self.viewport().update()
def add_files(self, files):
"""When song(s) added to the library, update the tableview model
- Drag & Drop song(s) on tableView
- File > Open > List of song(s)
"""
print(f'tableView - adding files: {files}')
number_of_files_added = add_files_to_library(files)
if number_of_files_added:
self.fetch_library()
def load_qapp(self, qapp):
self.qapp = qapp