diff --git a/buildPy2exe.py b/buildPy2exe.py index a4e7da3..0131519 100644 --- a/buildPy2exe.py +++ b/buildPy2exe.py @@ -654,7 +654,8 @@ guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock 'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png', 'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png', 'resources/world_explore.png', 'resources/application_get.png', 'resources/cog.png', - 'resources/film_go.png', 'resources/world_go.png', 'resources/arrow_refresh.png' + 'resources/film_go.png', 'resources/world_go.png', + 'resources/arrow_refresh.png', 'resources/spinner.mng' ] resources = ["resources/icon.ico", "resources/syncplay.png"] resources.extend(guiIcons) diff --git a/resources/spinner.mng b/resources/spinner.mng new file mode 100755 index 0000000..435d749 Binary files /dev/null and b/resources/spinner.mng differ diff --git a/syncplay/constants.py b/syncplay/constants.py index a39ec6a..5cc9e6a 100644 --- a/syncplay/constants.py +++ b/syncplay/constants.py @@ -181,4 +181,4 @@ SYNCPLAY_UPDATE_URL = u"http://syncplay.pl/checkforupdate?{}" # Params SYNCPLAY_DOWNLOAD_URL = "http://syncplay.pl/download/" SYNCPLAY_PUBLIC_SERVER_LIST_URL = u"http://syncplay.pl/listpublicservers?{}" # Params -PRIVATE_FILE_FIELDS = ["path"] \ No newline at end of file +PRIVATE_FILE_FIELDS = ["path"] diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index bfa92ec..9029f5f 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -6,6 +6,7 @@ from datetime import datetime from syncplay import utils import os import sys +import threading from syncplay.messages import getMessage, getLanguages, setLanguage, getInitialLanguage from syncplay import constants @@ -31,6 +32,39 @@ class GuiConfiguration: class WindowClosed(Exception): pass + +class GetPlayerIconThread(threading.Thread, QtCore.QObject): + daemon = True + done = QtCore.Signal(str, str) + + def __init__(self): + threading.Thread.__init__(self, name='GetPlayerIcon') + QtCore.QObject.__init__(self) + self.condvar = threading.Condition() + self.playerpath = None + + def setPlayerPath(self, playerpath): + self.condvar.acquire() + was_none = self.playerpath is None + self.playerpath = playerpath + if was_none: + self.condvar.notify() + self.condvar.release() + + def run(self): + while True: + self.condvar.acquire() + if self.playerpath is None: + self.condvar.wait() + playerpath = self.playerpath + self.playerpath = None + self.condvar.release() + + self.done.emit('spinner.mng', '') + iconpath = PlayerFactory().getPlayerIconByPath(playerpath) + self.done.emit(iconpath, playerpath) + + class ConfigDialog(QtGui.QDialog): pressedclosebutton = False @@ -140,15 +174,32 @@ class ConfigDialog(QtGui.QDialog): settings.endGroup() return foundpath - def updateExecutableIcon(self): - currentplayerpath = unicode(self.executablepathCombobox.currentText()) - iconpath = PlayerFactory().getPlayerIconByPath(currentplayerpath) - if iconpath != None and iconpath != "": - self.executableiconImage.load(self.resourcespath + iconpath) - self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage)) + @QtCore.Slot(str, str) + def _updateExecutableIcon(self, iconpath, playerpath): + if iconpath is not None and iconpath != "": + if iconpath.endswith('.mng'): + 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: 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._playerProbeThread.setPlayerPath(currentplayerpath) def updatePlayerArguments(self, currentplayerpath): argumentsForPath = utils.getPlayerArgumentsByPathAsText(self.perPlayerArgs, currentplayerpath) @@ -924,7 +975,6 @@ class ConfigDialog(QtGui.QDialog): self.hostCombobox.setEditText(currentServer) def __init__(self, config, playerpaths, error, defaultConfig): - self.config = config self.defaultConfig = defaultConfig self.playerpaths = playerpaths @@ -933,6 +983,10 @@ class ConfigDialog(QtGui.QDialog): self.subitems = {} self.publicServers = None + self._playerProbeThread = GetPlayerIconThread() + self._playerProbeThread.done.connect(self._updateExecutableIcon) + self._playerProbeThread.start() + if self.config['clearGUIData'] == True: self.config['clearGUIData'] = False self.clearGUIData() @@ -996,4 +1050,4 @@ class ConfigDialog(QtGui.QDialog): self.processWidget(self, lambda w: self.loadTooltips(w)) self.processWidget(self, lambda w: self.loadValues(w)) self.processWidget(self, lambda w: self.connectChildren(w)) - self.populateEmptyServerList() \ No newline at end of file + self.populateEmptyServerList()