playtypus/playtypus/threads.py

163 lines
6.3 KiB
Python

"""
The :mod:`threads` module contains functions to make working with QThreads easier
"""
import requests
import qtawesome as qta
from PyQt5 import QtCore, QtGui, QtWidgets
class ThreadWorker(QtCore.QObject):
"""
The :class:`~threads.ThreadWorker` class provides a base class for thread workers.
In Qt5, all work is done in workers, rather than actual QThread classes, and this case class provides
some utility signals and slots to make it easier to use threads and thread workers.
"""
quit = QtCore.pyqtSignal()
error = QtCore.pyqtSignal(str, str)
def start(self):
"""
The start method is how the worker runs. Basically, put your code here.
"""
raise NotImplementedError('Your class needs to override this method and run self.quit.emit() when complete')
class AlbumWorker(ThreadWorker):
"""
A thread worker to fetch the album art
"""
ALBUM_TEMPLATE = "{title}\n{artist}\n{year}"
window = None
def start(self):
if not self.window:
self.error.emit('No window set', 'The window attribute was not set')
self.quit.emit()
return
self.window.albumListWidget.clear()
for album in self.window.funkwhale.albums.list()['results']:
details = {
'title': album['title'],
'year': album['release_date'][:4] if album.get('release_date') else '',
'artist': album['artist']['name']
}
album_item = QtWidgets.QListWidgetItem(self.ALBUM_TEMPLATE.format(**details))
album_item.setData(QtCore.Qt.UserRole, album)
self.window.albumListWidget.addItem(album_item)
if album['cover'] and album['cover'].get('urls') and album['cover']['urls'].get('medium_square_crop'):
artwork_worker = AlbumArtWorker()
artwork_worker.album_item = album_item
artwork_worker.artwork_url = album['cover']['urls']['medium_square_crop']
self.window.run_thread(artwork_worker, 'album-{}'.format(album['title']))
else:
album_item.setIcon(qta.icon('mdi.album'))
self.window.update_album_total(self.window.albumListWidget.count())
self.quit.emit()
class AlbumArtWorker(ThreadWorker):
album_item = None
artwork_url = None
def start(self):
if not self.album_item:
self.error.emit('No album QListWidgetItem set', 'The album_item attribute was not set')
self.quit.emit()
return
if not self.artwork_url:
self.error.emit('No artwork URL set', 'The artwork_url attribute was not set')
self.quit.emit()
return
response = requests.get(self.artwork_url)
if response.status_code == 200:
pixmap = QtGui.QPixmap()
pixmap.loadFromData(response.content)
self.album_item.setIcon(QtGui.QIcon(pixmap))
else:
self.album_item.setIcon(qta.icon('mdi.album'))
self.quit.emit()
class ArtistWorker(ThreadWorker):
window = None
def start(self):
if not self.window:
self.error.emit('No window set', 'The window attribute was not set')
self.quit.emit()
return
self.window.artistListWidget.clear()
for artist in self.window.funkwhale.artists.list()['results']:
artist_item = QtWidgets.QListWidgetItem(artist['name'])
artist_item.setData(QtCore.Qt.UserRole, artist)
self.window.artistListWidget.addItem(artist_item)
if artist['cover'] and artist['cover'].get('urls') and artist['cover']['urls'].get('medium_square_crop'):
artwork_worker = ArtistArtWorker()
artwork_worker.artist_item = artist_item
artwork_worker.artwork_url = artist['cover']['urls']['medium_square_crop']
self.window.run_thread(artwork_worker, 'artist-{}'.format(artist['name']))
else:
artist_item.setIcon(qta.icon('mdi.account'))
self.window.update_artist_total(self.window.artistListWidget.count())
self.quit.emit()
class ArtistArtWorker(ThreadWorker):
artist_item = None
artwork_url = None
def start(self):
if not self.artist_item:
self.error.emit('No artist QListWidgetItem set', 'The artist_item attribute was not set')
self.quit.emit()
return
if not self.artwork_url:
self.error.emit('No artwork URL set', 'The artwork_url attribute was not set')
self.quit.emit()
return
response = requests.get(self.artwork_url)
if response.status_code == 200:
pixmap = QtGui.QPixmap()
pixmap.loadFromData(response.content)
self.artist_item.setIcon(QtGui.QIcon(pixmap))
else:
self.artist_item.setIcon(qta.icon('mdi.account'))
self.quit.emit()
class PlaylistWorker(ThreadWorker):
window = None
def start(self):
if not self.window:
self.error.emit('No window set', 'The window attribute was not set')
self.quit.emit()
return
self.window.playlistListWidget.clear()
for playlist in self.window.funkwhale.playlists.list()['results']:
playlist_item = QtWidgets.QListWidgetItem(playlist['name'])
playlist_item.setIcon(qta.icon('mdi.playlist-music'))
playlist_item.setData(QtCore.Qt.UserRole, playlist)
self.window.playlistListWidget.addItem(playlist_item)
self.window.update_playlist_total(self.window.playlistListWidget.count())
self.quit.emit()
class RadioWorker(ThreadWorker):
window = None
def start(self):
if not self.window:
self.error.emit('No window set', 'The window attribute was not set')
self.quit.emit()
return
self.window.radioListWidget.clear()
for radio in self.window.funkwhale.radios.list()['results']:
radio_item = QtWidgets.QListWidgetItem(radio['name'])
radio_item.setIcon(qta.icon('mdi.radio-music'))
radio_item.setData(QtCore.Qt.UserRole, radio)
self.window.radioListWidget.addItem(radio_item)
self.window.update_radio_total(self.window.radioListWidget.count())
self.quit.emit()