Perform player probing in a non-UI thread.

Network operations tend to be extremely slow when checking all user
inputs for player path, so perform those checks in a non-UI thread so
the GUI remains responsive. While queries are ongoing, the icon is a
"busy" spinner.
This commit is contained in:
Peter Marheine 2015-10-15 23:20:11 -06:00
parent 9752aad75d
commit c23fe6ad8f
3 changed files with 46 additions and 7 deletions

BIN
resources/spinner.mng Executable file

Binary file not shown.

View File

@ -6,6 +6,7 @@ from datetime import datetime
from syncplay import utils from syncplay import utils
import os import os
import sys import sys
import threading
from syncplay.messages import getMessage, getLanguages, setLanguage, getInitialLanguage from syncplay.messages import getMessage, getLanguages, setLanguage, getInitialLanguage
from syncplay import constants from syncplay import constants
@ -140,15 +141,52 @@ class ConfigDialog(QtGui.QDialog):
settings.endGroup() settings.endGroup()
return foundpath return foundpath
def updateExecutableIcon(self): class _GetIconPath(threading.Thread, QtCore.QObject):
currentplayerpath = unicode(self.executablepathCombobox.currentText()) daemon = True
iconpath = PlayerFactory().getPlayerIconByPath(currentplayerpath) done = QtCore.Signal(int, str, str)
def __init__(self, playerpath, seqnum):
threading.Thread.__init__(self)
QtCore.QObject.__init__(self)
self.playerpath = playerpath
self.seqnum = seqnum
def run(self):
iconpath = PlayerFactory().getPlayerIconByPath(self.playerpath)
self.done.emit(self.seqnum, iconpath, self.playerpath)
@QtCore.Slot(int, str, str)
def _updateExecutableIcon(self, seqnum, iconpath, playerpath):
if seqnum < self._lastThreadSeqnum:
return
if iconpath != None and iconpath != "": if iconpath != None and iconpath != "":
self.executableiconImage.load(self.resourcespath + iconpath) if iconpath.endswith('.mng'):
self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage)) movie = QtGui.QMovie(self.resourcespath + iconpath)
movie.setCacheMode(QtGui.QMovie.CacheMode.CacheAll)
self.executableiconLabel.setMovie(movie)
movie.start()
else:
self.executableiconImage.load(self.resourcespath + iconpath)
self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage))
else: else:
self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage())) self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage()))
self.updatePlayerArguments(currentplayerpath) self.updatePlayerArguments(playerpath)
def updateExecutableIcon(self):
"""
Start getting the icon path in another thread, which will set the GUI
icon if valid.
This is performed outside the main thread because networked players may
take a long time to perform their checks and hang the GUI while doing
so.
"""
currentplayerpath = unicode(self.executablepathCombobox.currentText())
self._lastThreadSeqnum += 1
thread = self._GetIconPath(currentplayerpath, self._lastThreadSeqnum)
thread.done.connect(self._updateExecutableIcon)
thread.done.emit(self._lastThreadSeqnum, 'spinner.mng', '')
thread.start()
def updatePlayerArguments(self, currentplayerpath): def updatePlayerArguments(self, currentplayerpath):
argumentsForPath = utils.getPlayerArgumentsByPathAsText(self.perPlayerArgs, currentplayerpath) argumentsForPath = utils.getPlayerArgumentsByPathAsText(self.perPlayerArgs, currentplayerpath)
@ -924,6 +962,7 @@ class ConfigDialog(QtGui.QDialog):
self.hostCombobox.setEditText(currentServer) self.hostCombobox.setEditText(currentServer)
def __init__(self, config, playerpaths, error, defaultConfig): def __init__(self, config, playerpaths, error, defaultConfig):
self._lastThreadSeqnum = 0
self.config = config self.config = config
self.defaultConfig = defaultConfig self.defaultConfig = defaultConfig