""" 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()