From e458ba60addda0b2e18d044939dd65f7ff4dfeaa Mon Sep 17 00:00:00 2001 From: Etoh Date: Sat, 18 May 2013 19:51:15 +0200 Subject: [PATCH 01/11] Set seek threshold back to >1 second --- syncplay/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncplay/constants.py b/syncplay/constants.py index 2c1c5cb..54283fb 100644 --- a/syncplay/constants.py +++ b/syncplay/constants.py @@ -9,7 +9,7 @@ DEFAULT_CONFIG_NAME = ".syncplay" #Changing these might be ok REWIND_THRESHOLD = 4 -SEEK_THRESHOLD = 0.9 +SEEK_THRESHOLD = 1 SLOWDOWN_RATE = 0.95 SLOWDOWN_KICKIN_THRESHOLD = 1.5 SLOWDOWN_RESET_THRESHOLD = 0.1 From e1671fa701bc87cc6b5a585f4c6128a2a17fbad5 Mon Sep 17 00:00:00 2001 From: Etoh Date: Sat, 18 May 2013 19:56:47 +0200 Subject: [PATCH 02/11] Respect "slowdown on desync" setting --- syncplay/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncplay/client.py b/syncplay/client.py index c055d93..8be0f93 100644 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -212,7 +212,7 @@ class SyncplayClient(object): madeChangeOnPlayer = self._serverSeeked(position, setBy) if (diff > constants.REWIND_THRESHOLD and not doSeek): madeChangeOnPlayer = self._rewindPlayerDueToTimeDifference(position, setBy) - if (self._player.speedSupported and not doSeek and not paused): + if (self._player.speedSupported and not doSeek and not paused and not self._config['slowOnDesync'] == False): madeChangeOnPlayer = self._slowDownToCoverTimeDifference(diff, setBy) if (paused == False and pauseChanged): madeChangeOnPlayer = self._serverUnpaused(setBy) From 23d5bfc501816cccfd65fcd73db2d863ac7b042d Mon Sep 17 00:00:00 2001 From: Etoh Date: Sat, 18 May 2013 21:29:53 +0200 Subject: [PATCH 03/11] Recall playerPath in GuiConfiguration --- syncplay/ui/GuiConfiguration.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 453b1ff..64fe2cc 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -51,9 +51,13 @@ class GuiConfiguration: self.userEntry = self._addLabeledEntryToVbox(getMessage("en", "username-label"), config['name'], vbox, lambda __, _: self._saveDataAndLeave()) self.roomEntry = self._addLabeledEntryToVbox(getMessage("en", "room-label"), config['room'], vbox, lambda __, _: self._saveDataAndLeave()) self.passEntry = self._addLabeledEntryToVbox(getMessage("en", "password-label"), config['password'], vbox, lambda __, _: self._saveDataAndLeave()) - self.mpcEntry = self._addLabeledEntryToVbox(getMessage("en", "path-label"), self._tryToFillPlayerPath(), vbox, lambda __, _: self._saveDataAndLeave()) + self.mpcEntry = self._addLabeledEntryToVbox(getMessage("en", "path-label"), self._tryToFillPlayerPath(config['playerPath']), vbox, lambda __, _: self._saveDataAndLeave()) + + + def _tryToFillPlayerPath(self, playerpath): + if os.path.isfile(playerpath): + return playerpath - def _tryToFillPlayerPath(self): for path in self._availablePlayerPaths: if(os.path.isfile(path)): return path From 42778029c8f587577166fe497c54d59d23c7a98e Mon Sep 17 00:00:00 2001 From: Etoh Date: Sat, 18 May 2013 22:09:03 +0200 Subject: [PATCH 04/11] Fix GuiConfiguration playerpath indent --- syncplay/ui/GuiConfiguration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 64fe2cc..35810fe 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -55,7 +55,7 @@ class GuiConfiguration: def _tryToFillPlayerPath(self, playerpath): - if os.path.isfile(playerpath): + if os.path.isfile(playerpath): return playerpath for path in self._availablePlayerPaths: From d40576d0fe8cdcf0c5ab56054a3e592090b3a628 Mon Sep 17 00:00:00 2001 From: Etoh Date: Thu, 23 May 2013 18:32:06 +0200 Subject: [PATCH 05/11] Attempt to fix VLC file chane state issue --- syncplay/players/vlc.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/syncplay/players/vlc.py b/syncplay/players/vlc.py index e763a14..fb07709 100644 --- a/syncplay/players/vlc.py +++ b/syncplay/players/vlc.py @@ -28,6 +28,7 @@ class VlcPlayer(BasePlayer): self._duration = None self._filename = None self._filepath = None + self._filechanged = False self._durationAsk = threading.Event() self._filenameAsk = threading.Event() @@ -68,12 +69,16 @@ class VlcPlayer(BasePlayer): self.setPosition(self._client.getGlobalPosition()) def askForStatus(self): + self._filechanged = False self._positionAsk.clear() self._pausedAsk.clear() self._listener.sendLine(".") - self._positionAsk.wait() - self._pausedAsk.wait() - self._client.updatePlayerStatus(self._paused, self._position) + if self._filechanged == False: + self._positionAsk.wait() + self._pausedAsk.wait() + self._client.updatePlayerStatus(self._paused, self._position) + else: + self._client.updatePlayerStatus(self._client.getGlobalPaused(), self._client.getGlobalPosition()) def displayMessage(self, message, duration = constants.OSD_DURATION * 1000): duration /= 1000 @@ -101,10 +106,12 @@ class VlcPlayer(BasePlayer): name, value = match.group('command'), match.group('argument') if(line == "filepath-change-notification"): + self._filechanged = True t = threading.Thread(target=self._onFileUpdate) t.setDaemon(True) t.start() elif (name == "filepath" and value != "no-input"): + self._filechanged = True if("file://" in value): value = value.replace("file://", "") if(not os.path.isfile(value)): @@ -115,12 +122,13 @@ class VlcPlayer(BasePlayer): self._duration = float(value.replace(",", ".")) self._durationAsk.set() elif(name == "playstate"): - self._paused = bool(value != 'playing') if(value != "no-input") else self._client.getGlobalPaused() + self._paused = bool(value != 'playing') if(value != "no-input" and self._filechanged == False) else self._client.getGlobalPaused() self._pausedAsk.set() elif(name == "position"): - self._position = float(value.replace(",", ".")) if (value != "no-input") else self._client.getGlobalPosition() + self._position = float(value.replace(",", ".")) if (value != "no-input" and self._filechanged == False) else self._client.getGlobalPosition() self._positionAsk.set() elif(name == "filename"): + self._filechanged = True self._filename = value self._filenameAsk.set() elif (line[:16] == "VLC media player"): @@ -217,4 +225,4 @@ class VlcPlayer(BasePlayer): def sendLine(self, line): if(self.connected): # print "send: {}".format(line) - self.push(line + "\n") + self.push(line + "\n") From e0bbfd2fd8b04eb08187a88978c79e2c6691397f Mon Sep 17 00:00:00 2001 From: Etoh Date: Sun, 26 May 2013 17:05:40 +0200 Subject: [PATCH 06/11] Fix empty .syncplay playerpath bug --- syncplay/ui/GuiConfiguration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 35810fe..7c50616 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -55,7 +55,7 @@ class GuiConfiguration: def _tryToFillPlayerPath(self, playerpath): - if os.path.isfile(playerpath): + if playerpath != None and os.path.isfile(playerpath): return playerpath for path in self._availablePlayerPaths: From f979bb809a2cba0ba406ac460ef5327022b95507 Mon Sep 17 00:00:00 2001 From: Etoh Date: Tue, 28 May 2013 22:50:42 +0200 Subject: [PATCH 07/11] Reconfigure buildPy2exe for PySide --- buildPy2exe.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/buildPy2exe.py b/buildPy2exe.py index 6b2cb7c..21dc5fe 100644 --- a/buildPy2exe.py +++ b/buildPy2exe.py @@ -209,7 +209,7 @@ NSIS_SCRIPT_TEMPLATE = r""" Pop $$CheckBox_QuickLaunchShortcut $${If} $$CheckBox_Associate_State == $${BST_CHECKED} - $${NSD_Check} $$CheckBox_Associate + $${NSD_Check} $$CheckBox_Associate $${EndIf} $${If} $$CheckBox_VLC_State == $${BST_CHECKED} @@ -522,9 +522,10 @@ info = dict( console=[{"script":"syncplayClient.py", "icon_resources":[(1, "resources\\icon.ico")], 'dest_base': "Syncplay"}, 'syncplayServer.py'], options={'py2exe': { 'dist_dir': OUT_DIR, - 'includes': 'cairo, pango, pangocairo, atk, gobject, twisted', + 'packages': 'PySide.QtUiTools', + 'includes': 'cairo, pango, pangocairo, atk, gobject, twisted, sys, encodings, datetime, os, time, math, PySide', 'excludes': 'venv, _ssl, doctest, pdb, unittest, win32clipboard, win32event, win32file, win32pdh, win32security, win32trace, win32ui, winxpgui, win32pipe, win32process', - 'dll_excludes': 'msvcr71.dll', + 'dll_excludes': 'msvcr71.dll, MSVCP90.dll', 'optimize': 2, 'compressed': 1 } @@ -536,4 +537,3 @@ info = dict( sys.argv.extend(['py2exe', '-p win32com ', '-i twisted.web.resource']) setup(**info) - From 91b217685e3174738283165ee94555e81d9aa8b2 Mon Sep 17 00:00:00 2001 From: Etoh Date: Tue, 28 May 2013 22:52:05 +0200 Subject: [PATCH 08/11] Move UI from GTK to PySide + other improvements --- syncplay/ui/GuiConfiguration.py | 335 ++++++++++++++++++++------------ 1 file changed, 216 insertions(+), 119 deletions(-) diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 7c50616..bedac7a 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -1,136 +1,233 @@ -import pygtk +from PySide import QtCore, QtGui +from PySide.QtCore import QSettings, Qt +from PySide.QtGui import QApplication, QLineEdit, QCursor, QLabel, QCheckBox + import os -pygtk.require('2.0') -import gtk -gtk.set_interactive(False) -import cairo, gio, pango, atk, pangocairo, gobject #@UnusedImport +import sys from syncplay.messages import getMessage class GuiConfiguration: def __init__(self, config): self.config = config self._availablePlayerPaths = [] - self.closedAndNotSaved = False - + def run(self): - self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.window.set_title(getMessage("en", "config-window-title")) - self.window.connect("delete_event", lambda w, e: self._windowClosed()) - vbox = gtk.VBox(False, 0) - self.window.add(vbox) - vbox.show() - self._addLabeledEntries(self.config, vbox) - self._addCheckboxEntries(self.config, vbox) - self.hostEntry.select_region(0, len(self.hostEntry.get_text())) - button = gtk.Button(stock=gtk.STOCK_SAVE) - button.connect("clicked", lambda w: self._saveDataAndLeave()) - guideLink = gtk.LinkButton("http://syncplay.pl/guide/", "Configuration Guide") - guideLink.show() - vbox.add(guideLink) - vbox.pack_start(button, True, True, 0) - button.set_flags(gtk.CAN_DEFAULT) - button.grab_default() - button.show() - self.window.show() - gtk.main() - - def _windowClosed(self): - self.window.destroy() - gtk.main_quit() - self.closedAndNotSaved = True + self.app = QtGui.QApplication(sys.argv) + dialog = ConfigDialog(self.config, self._availablePlayerPaths) + dialog.exec_() + + def setAvailablePaths(self, paths): + self._availablePlayerPaths = paths + + def getProcessedConfiguration(self): + return self.config + + class WindowClosed(Exception): + pass + +class ConfigDialog(QtGui.QDialog): + + pressedclosebutton = False + + malToggling = False + + def malToggled(self): + if self.malToggling == False: + self.malToggling = True + + if self.malenabledCheckbox.isChecked() and self.malenabledCheckbox.isVisible(): + self.malenabledCheckbox.setChecked(False) + self.malSettingsGroup.setChecked(True) + self.malSettingsGroup.show() + self.malpasswordLabel.show() + self.malpasswordTextbox.show() + self.malusernameLabel.show() + self.malusernameTextbox.show() + self.malenabledCheckbox.hide() + else: + self.malSettingsGroup.setChecked(False) + self.malSettingsGroup.hide() + self.malpasswordLabel.hide() + self.malpasswordTextbox.hide() + self.malusernameLabel.hide() + self.malusernameTextbox.hide() + self.malenabledCheckbox.show() + + self.malToggling = False + self.adjustSize() + self.setFixedSize(self.sizeHint()) + + def runButtonTextUpdate(self): + if (self.donotstoreCheckbox.isChecked()): + self.runButton.setText("Run Syncplay") + else: + self.runButton.setText("Store configuration and run Syncplay") + + def _tryToFillPlayerPath(self, playerpath, playerpathlist): + foundpath = "" - def _addLabeledEntries(self, config, vbox): + if playerpath != None and playerpath != "" and os.path.isfile(playerpath): + foundpath = playerpath + self.executablepathCombobox.addItem(foundpath) + + for path in playerpathlist: + if(os.path.isfile(path) and path.lower() != foundpath.lower()): + self.executablepathCombobox.addItem(path) + if foundpath == None: + foundpath = path + + if foundpath: + return(foundpath) + else: + return("") + + def browsePlayerpath(self): + options = QtGui.QFileDialog.Options() + + fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, + "Browse for media player executable", + "", + "Windows Executables (*.exe);;All Files (*)", "", options) + if fileName: + self.executablepathCombobox.setEditText(fileName) + + def _saveDataAndLeave(self): + self.config['host'] = self.hostTextbox.text() + self.config['name'] = self.usernameTextbox.text() + self.config['room'] = self.defaultroomTextbox.text() + self.config['password'] = self.serverpassTextbox.text() + self.config['playerPath'] = self.executablepathCombobox.currentText() + if self.alwaysshowCheckbox.isChecked() == True: + self.config['forceGuiPrompt'] = True + else: + self.config['forceGuiPrompt'] = False + if self.donotstoreCheckbox.isChecked() == True: + self.config['noStore'] = True + else: + self.config['noStore'] = False + if self.slowdownCheckbox.isChecked() == True: + self.config['slowOnDesync'] = True + else: + self.config['slowOnDesync'] = False + self.config['malUsername'] = self.malusernameTextbox.text() + if self.malSettingsGroup.isChecked(): + self.config['malPassword'] = self.malpasswordTextbox.text() + else: + self.config['malPassword'] = "" + self.pressedclosebutton = True + self.close() + return + + def closeEvent(self, event): + if self.pressedclosebutton == False: + sys.exit() + raise GuiConfiguration.WindowClosed + event.accept() + + def __init__(self, config, playerpaths): + + self.config = config + + super(ConfigDialog, self).__init__() + + self.setWindowTitle(getMessage("en", "config-window-title")) + if(config['host'] == None): host = "" elif(":" in config['host']): host = config['host'] else: host = config['host']+":"+str(config['port']) - - self.hostEntry = self._addLabeledEntryToVbox(getMessage("en", "host-label"), host, vbox, lambda __, _: self._saveDataAndLeave()) - self.userEntry = self._addLabeledEntryToVbox(getMessage("en", "username-label"), config['name'], vbox, lambda __, _: self._saveDataAndLeave()) - self.roomEntry = self._addLabeledEntryToVbox(getMessage("en", "room-label"), config['room'], vbox, lambda __, _: self._saveDataAndLeave()) - self.passEntry = self._addLabeledEntryToVbox(getMessage("en", "password-label"), config['password'], vbox, lambda __, _: self._saveDataAndLeave()) - self.mpcEntry = self._addLabeledEntryToVbox(getMessage("en", "path-label"), self._tryToFillPlayerPath(config['playerPath']), vbox, lambda __, _: self._saveDataAndLeave()) + + self.connectionSettingsGroup = QtGui.QGroupBox("Connection Settings") + self.hostTextbox = QLineEdit(host, self) + self.hostLabel = QLabel(getMessage("en", "host-label"), self) + self.usernameTextbox = QLineEdit(config['name'],self) + self.serverpassLabel = QLabel(getMessage("en", "password-label"), self) + self.defaultroomTextbox = QLineEdit(config['room'],self) + self.usernameLabel = QLabel(getMessage("en", "username-label"), self) + self.serverpassTextbox = QLineEdit(config['password'],self) + self.defaultroomLabel = QLabel(getMessage("en", "room-label"), self) + self.connectionSettingsLayout = QtGui.QGridLayout() + self.connectionSettingsLayout.addWidget(self.hostLabel, 0, 0) + self.connectionSettingsLayout.addWidget(self.hostTextbox, 0, 1) + self.connectionSettingsLayout.addWidget(self.serverpassLabel, 1, 0) + self.connectionSettingsLayout.addWidget(self.serverpassTextbox, 1, 1) + self.connectionSettingsLayout.addWidget(self.usernameLabel, 2, 0) + self.connectionSettingsLayout.addWidget(self.usernameTextbox, 2, 1) + self.connectionSettingsLayout.addWidget(self.defaultroomLabel, 3, 0) + self.connectionSettingsLayout.addWidget(self.defaultroomTextbox, 3, 1) + self.connectionSettingsGroup.setLayout(self.connectionSettingsLayout) + + self.mediaplayerSettingsGroup = QtGui.QGroupBox("Media Player Settings") + self.executablepathCombobox = QtGui.QComboBox(self) + self.executablepathCombobox.setEditable(True) + self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'],playerpaths)) + self.executablepathCombobox.setMinimumWidth(200) + self.executablepathCombobox.setMaximumWidth(200) + self.executablepathLabel = QLabel("Path to player executable:", self) + self.executablebrowseButton = QtGui.QPushButton("Browse") + self.executablebrowseButton.clicked.connect(self.browsePlayerpath) + self.slowdownCheckbox = QCheckBox("Slow down on desync") + self.mediaplayerSettingsLayout = QtGui.QGridLayout() + self.mediaplayerSettingsLayout.addWidget(self.executablepathLabel, 0, 0) + self.mediaplayerSettingsLayout.addWidget(self.executablepathCombobox , 0, 1) + self.mediaplayerSettingsLayout.addWidget(self.executablebrowseButton , 0, 2) + self.mediaplayerSettingsLayout.addWidget(self.slowdownCheckbox, 1, 0) + self.mediaplayerSettingsGroup.setLayout(self.mediaplayerSettingsLayout) + if config['slowOnDesync'] == True: + self.slowdownCheckbox.setChecked(True) - - def _tryToFillPlayerPath(self, playerpath): - if playerpath != None and os.path.isfile(playerpath): - return playerpath - - for path in self._availablePlayerPaths: - if(os.path.isfile(path)): - return path - return self.config["playerPath"] - - def getProcessedConfiguration(self): - if(self.closedAndNotSaved): - raise self.WindowClosed - return self.config - - def _saveDataAndLeave(self): - self.config['host'] = self.hostEntry.get_text() - self.config['name'] = self.userEntry.get_text() - self.config['room'] = self.roomEntry.get_text() - self.config['password'] = self.passEntry.get_text() - self.config['playerPath'] = self.mpcEntry.get_text() - if self.alwaysShowCheck.get_active() == True: - self.config['forceGuiPrompt'] = True + self.malSettingsGroup = QtGui.QGroupBox("Enable MyAnimeList Updater (EXPERIMENTAL)") + self.malSettingsGroup.setCheckable(True) + self.malSettingsGroup.toggled.connect(self.malToggled) + self.malSettingsSplit = QtGui.QSplitter(self) + self.malusernameTextbox = QLineEdit(config['malUsername'],self) + self.malusernameLabel = QLabel("MAL Username:", self) + self.malpasswordTextbox = QLineEdit(config['malPassword'],self) + self.malpasswordTextbox.setEchoMode(QtGui.QLineEdit.Password) + self.malpasswordLabel = QLabel("MAL Password:", self) + self.malSettingsLayout = QtGui.QGridLayout() + self.malSettingsLayout.addWidget(self.malusernameLabel , 0, 0) + self.malSettingsLayout.addWidget(self.malusernameTextbox, 0, 1) + self.malSettingsLayout.addWidget(self.malpasswordLabel , 1, 0) + self.malSettingsLayout.addWidget(self.malpasswordTextbox, 1, 1) + self.malSettingsGroup.setLayout(self.malSettingsLayout) + + self.malenabledCheckbox = QCheckBox("Enable MyAnimeList Updater (EXPERIMENTAL)") + self.malenabledCheckbox.toggled.connect(self.malToggled) + if config['malPassword'] == None or config['malPassword'] == "": + self.malenabledCheckbox.setChecked(False) + self.malSettingsGroup.hide() else: - self.config['forceGuiPrompt'] = False - if self.storeConfigCheck.get_active() == True: - self.config['noStore'] = True - else: - self.config['noStore'] = False - if self.slowOnDesyncCheck.get_active() == True: - self.config['slowOnDesync'] = True - else: - self.config['slowOnDesync'] = False - self.window.destroy() - gtk.main_quit() - - def _addLabeledEntryToVbox(self, label, initialEntryValue, vbox, callback): - hbox = gtk.HBox(False, 0) - hbox.set_border_width(3) - vbox.pack_start(hbox, False, False, 0) - hbox.show() - label_ = gtk.Label() - label_.set_text(label) - label_.set_alignment(xalign=0, yalign=0.5) - hbox.pack_start(label_, False, False, 0) - label_.show() - entry = gtk.Entry() - entry.connect("activate", callback, entry) - if(initialEntryValue == None): - initialEntryValue = "" - entry.set_text(initialEntryValue) - hbox.pack_end(entry, False, False, 0) - entry.set_usize(200, -1) - entry.show() - return entry - - def _addCheckboxEntries(self, config, vbox): - CheckVbox = gtk.VBox(False, 0) - vbox.pack_start(CheckVbox, False, False, 0) - self.alwaysShowCheck = gtk.CheckButton("Always Show This Dialog") - if self.config['forceGuiPrompt'] == True: - self.alwaysShowCheck.set_active(True) - self.alwaysShowCheck.show() - self.storeConfigCheck = gtk.CheckButton("Do Not Store This Configuration") - if self.config['noStore'] == True: - self.storeConfigCheck.set_active(True) - self.storeConfigCheck.show() - self.slowOnDesyncCheck = gtk.CheckButton("Slow Down On Desync") - if self.config['slowOnDesync'] == True: - self.slowOnDesyncCheck.set_active(True) - self.slowOnDesyncCheck.show() - CheckVbox.pack_start(self.alwaysShowCheck, False, False, 0) - CheckVbox.add(self.storeConfigCheck) - CheckVbox.add(self.slowOnDesyncCheck) - CheckVbox.show() - - def setAvailablePaths(self, paths): - self._availablePlayerPaths = paths - - class WindowClosed(Exception): - pass + self.malenabledCheckbox.hide() + + self.alwaysshowCheckbox = QCheckBox("Always Show This Dialog") + if config['forceGuiPrompt'] == True: + self.alwaysshowCheckbox.setChecked(True) + + self.donotstoreCheckbox = QCheckBox("Do Not Store This Configuration") + if config['noStore'] == True: + self.donotstoreCheckbox.setChecked(True) + + self.runButton = QtGui.QPushButton("Store configuration and run Syncplay") + self.runButton.pressed.connect(self._saveDataAndLeave) + self.runButtonTextUpdate + self.donotstoreCheckbox.toggled.connect(self.runButtonTextUpdate) + + self.mainLayout = QtGui.QVBoxLayout() + self.mainLayout.addWidget(self.connectionSettingsGroup) + self.mainLayout.addSpacing(12) + self.mainLayout.addWidget(self.mediaplayerSettingsGroup) + self.mainLayout.addSpacing(12) + self.mainLayout.addWidget(self.malenabledCheckbox) + self.mainLayout.addWidget(self.malSettingsGroup) + + self.mainLayout.addWidget(self.alwaysshowCheckbox) + self.mainLayout.addWidget(self.donotstoreCheckbox) + self.mainLayout.addWidget(self.runButton) + + self.mainLayout.addStretch(1) + + self.setLayout(self.mainLayout) + self.setFixedSize(self.sizeHint()) From 69f165de7497754b26b93d95e1996814ec2892a9 Mon Sep 17 00:00:00 2001 From: Etoh Date: Wed, 29 May 2013 00:08:04 +0200 Subject: [PATCH 09/11] Improved browse dialog settings (thanks Dan) --- syncplay/ui/GuiConfiguration.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index bedac7a..e77b2a9 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -83,11 +83,22 @@ class ConfigDialog(QtGui.QDialog): def browsePlayerpath(self): options = QtGui.QFileDialog.Options() + defaultdirectory = "" + browserfilter = "All Files (*)" + + if os.name == 'nt': + browserfilter = "Executable files (*.exe);;All Files (*)" + if os.environ["ProgramFiles(x86)"] != "" and os.environ["ProgramFiles(x86)"] != None: + defaultdirectory = os.environ["ProgramFiles(x86)"] + elif os.environ["ProgramFiles"] != os.environ["ProgramFiles"] != None: + defaultdirectory = os.environ["ProgramFiles"] + elif sys.platform.startswith('linux'): + defaultdirectory = "/usr/bin" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media player executable", - "", - "Windows Executables (*.exe);;All Files (*)", "", options) + defaultdirectory, + browserfilter, "", options) if fileName: self.executablepathCombobox.setEditText(fileName) From 6b7cdf6225e9443ee26e1787d8b53d8041fb985f Mon Sep 17 00:00:00 2001 From: Etoh Date: Fri, 31 May 2013 18:23:07 +0200 Subject: [PATCH 10/11] Fix GuiConfig ProgramFiles environ check --- syncplay/ui/GuiConfiguration.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index e77b2a9..44fbac8 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -88,10 +88,12 @@ class ConfigDialog(QtGui.QDialog): if os.name == 'nt': browserfilter = "Executable files (*.exe);;All Files (*)" - if os.environ["ProgramFiles(x86)"] != "" and os.environ["ProgramFiles(x86)"] != None: + if "PROGRAMFILES(X86)" in os.environ: defaultdirectory = os.environ["ProgramFiles(x86)"] - elif os.environ["ProgramFiles"] != os.environ["ProgramFiles"] != None: - defaultdirectory = os.environ["ProgramFiles"] + elif "PROGRAMFILES" in os.environ: + defaultdirectory = os.environ["ProgramFiles"] + elif "PROGRAMW6432" in os.environ: + defaultdirectory = os.environ["ProgramW6432"] elif sys.platform.startswith('linux'): defaultdirectory = "/usr/bin" From 58b5e0cd0f63a495b3e6cea26298f8d922bd60f9 Mon Sep 17 00:00:00 2001 From: Etoh Date: Fri, 31 May 2013 19:15:02 +0200 Subject: [PATCH 11/11] Add help button to GuiConfiguration --- syncplay/ui/GuiConfiguration.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 44fbac8..adc8cba 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -1,6 +1,6 @@ from PySide import QtCore, QtGui from PySide.QtCore import QSettings, Qt -from PySide.QtGui import QApplication, QLineEdit, QCursor, QLabel, QCheckBox +from PySide.QtGui import QApplication, QLineEdit, QCursor, QLabel, QCheckBox, QDesktopServices import os import sys @@ -62,6 +62,9 @@ class ConfigDialog(QtGui.QDialog): self.runButton.setText("Run Syncplay") else: self.runButton.setText("Store configuration and run Syncplay") + + def openHelp(self): + self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/") def _tryToFillPlayerPath(self, playerpath, playerpathlist): foundpath = "" @@ -140,6 +143,7 @@ class ConfigDialog(QtGui.QDialog): def __init__(self, config, playerpaths): self.config = config + self.QtGui = QtGui super(ConfigDialog, self).__init__() @@ -223,9 +227,6 @@ class ConfigDialog(QtGui.QDialog): if config['noStore'] == True: self.donotstoreCheckbox.setChecked(True) - self.runButton = QtGui.QPushButton("Store configuration and run Syncplay") - self.runButton.pressed.connect(self._saveDataAndLeave) - self.runButtonTextUpdate self.donotstoreCheckbox.toggled.connect(self.runButtonTextUpdate) self.mainLayout = QtGui.QVBoxLayout() @@ -236,9 +237,18 @@ class ConfigDialog(QtGui.QDialog): self.mainLayout.addWidget(self.malenabledCheckbox) self.mainLayout.addWidget(self.malSettingsGroup) + self.topLayout = QtGui.QHBoxLayout() + self.helpButton = QtGui.QPushButton("Help") + self.helpButton.setMaximumSize(self.helpButton.sizeHint()) + self.helpButton.pressed.connect(self.openHelp) + self.runButton = QtGui.QPushButton("Store configuration and run Syncplay") + self.runButton.pressed.connect(self._saveDataAndLeave) + self.runButtonTextUpdate + self.topLayout.addWidget(self.helpButton, Qt.AlignLeft) + self.topLayout.addWidget(self.runButton, Qt.AlignRight) self.mainLayout.addWidget(self.alwaysshowCheckbox) self.mainLayout.addWidget(self.donotstoreCheckbox) - self.mainLayout.addWidget(self.runButton) + self.mainLayout.addLayout(self.topLayout) self.mainLayout.addStretch(1)