New GuiConfig etc, upver to 1.2.6

This commit is contained in:
Et0h 2014-07-11 20:44:01 +01:00
parent e385afcc8e
commit e8cabc03d3
18 changed files with 491 additions and 208 deletions

View File

@ -578,7 +578,8 @@ guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png', 'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
'resources/timeline_marker.png','resources/control_play_blue.png', 'resources/timeline_marker.png','resources/control_play_blue.png',
'resources/mpc-hc.png','resources/mpc-hc64.png','resources/mplayer.png', 'resources/mpc-hc.png','resources/mpc-hc64.png','resources/mplayer.png',
'resources/mpv.png','resources/vlc.png' 'resources/mpv.png','resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/bullet_black.png'
] ]
resources = ["resources/icon.ico", "resources/syncplay.png"] resources = ["resources/icon.ico", "resources/syncplay.png"]
resources.extend(guiIcons) resources.extend(guiIcons)

BIN
resources/bullet_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

BIN
resources/cog_delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

BIN
resources/comments.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

BIN
resources/eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

BIN
resources/film_link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

BIN
resources/house.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

View File

@ -1,3 +1,3 @@
version = '1.2.8' version = '1.2.9'
milestone = 'Hammer' milestone = 'Hammer'
projectURL = 'http://syncplay.pl/' projectURL = 'http://syncplay.pl/'

View File

@ -55,6 +55,12 @@ class SyncClientFactory(ClientFactory):
class SyncplayClient(object): class SyncplayClient(object):
def __init__(self, playerClass, ui, config): def __init__(self, playerClass, ui, config):
constants.SHOW_OSD = config['showOSD']
constants.SHOW_OSD_WARNINGS = config['showOSDWarnings']
constants.SHOW_SLOWDOWN_OSD = config['showSlowdownOSD']
constants.SHOW_DIFFERENT_ROOM_OSD = config['showDifferentRoomOSD']
constants.SHOW_SAME_ROOM_OSD = config['showSameRoomOSD']
constants.SHOW_DURATION_NOTIFICATION = config['showDurationNotification']
self.lastLeftTime = 0 self.lastLeftTime = 0
self.lastLeftUser = u"" self.lastLeftUser = u""
self.protocolFactory = SyncClientFactory(self) self.protocolFactory = SyncClientFactory(self)
@ -226,11 +232,10 @@ class SyncplayClient(object):
self._lastGlobalUpdate = time.time() self._lastGlobalUpdate = time.time()
if doSeek: if doSeek:
madeChangeOnPlayer = self._serverSeeked(position, setBy) madeChangeOnPlayer = self._serverSeeked(position, setBy)
if diff > self._config['rewindThreshold'] and not doSeek and not self._config['rewindThreshold'] == 0.0: if diff > self._config['rewindThreshold'] and not doSeek and not self._config['rewindOnDesync'] == False:
madeChangeOnPlayer = self._rewindPlayerDueToTimeDifference(position, setBy) 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):
if self._config['slowMeOnDesync'] == constants.OPTION_ALWAYS or (self._config['slowMeOnDesync'] == constants.OPTION_AUTO and self._player.speedRecommended): madeChangeOnPlayer = self._slowDownToCoverTimeDifference(diff, setBy)
madeChangeOnPlayer = self._slowDownToCoverTimeDifference(diff, setBy)
if paused == False and pauseChanged: if paused == False and pauseChanged:
madeChangeOnPlayer = self._serverUnpaused(setBy) madeChangeOnPlayer = self._serverUnpaused(setBy)
elif paused == True and pauseChanged: elif paused == True and pauseChanged:
@ -357,6 +362,9 @@ class SyncplayClient(object):
def getRoom(self): def getRoom(self):
return self.userlist.currentUser.room return self.userlist.currentUser.room
def getConfig(self):
return self._config
def getUserList(self): def getUserList(self):
if self._protocol and self._protocol.logged: if self._protocol and self._protocol.logged:
self._protocol.sendList() self._protocol.sendList()
@ -501,7 +509,7 @@ class SyncplayUserlist(object):
def __showUserChangeMessage(self, username, room, file_, oldRoom=None): def __showUserChangeMessage(self, username, room, file_, oldRoom=None):
if room: if room:
if self.isRoomSame(room) or self.isRoomSame(oldRoom): if self.isRoomSame(room) or self.isRoomSame(oldRoom):
showOnOSD = constants.SHOW_SAME_ROOM_OSD showOnOSD = constants.SHOW_OSD_WARNINGS
else: else:
showOnOSD = constants.SHOW_DIFFERENT_ROOM_OSD showOnOSD = constants.SHOW_DIFFERENT_ROOM_OSD
hideFromOSD = not showOnOSD hideFromOSD = not showOnOSD

View File

@ -10,29 +10,33 @@ DEFAULT_CONFIG_NAME_WINDOWS = "syncplay.ini"
DEFAULT_CONFIG_NAME_LINUX = ".syncplay" DEFAULT_CONFIG_NAME_LINUX = ".syncplay"
RECENT_CLIENT_THRESHOLD = "1.2.8" #This and higher considered 'recent' clients (no warnings) RECENT_CLIENT_THRESHOLD = "1.2.8" #This and higher considered 'recent' clients (no warnings)
WARN_OLD_CLIENTS = True #Use MOTD to inform old clients to upgrade WARN_OLD_CLIENTS = True #Use MOTD to inform old clients to upgrade
SHOW_OSD = True # Sends Syncplay messages to media player OSD
SHOW_OSD_WARNINGS = True # Show warnings if playing different file, alone in room
SHOW_SLOWDOWN_OSD = True # Show notifications of slowing down / reverting on time difference
SHOW_SAME_ROOM_OSD = True # Show OSD notifications for events relating to room user is in
SHOW_DIFFERENT_ROOM_OSD = False # Show OSD notifications for events relating to room user is not in
LIST_RELATIVE_CONFIGS = True # Print list of relative configs loaded LIST_RELATIVE_CONFIGS = True # Print list of relative configs loaded
SHOW_CONTACT_INFO = True # Displays dev contact details below list in GUI SHOW_CONTACT_INFO = True # Displays dev contact details below list in GUI
SHOW_BUTTON_LABELS = True # If disabled, only shows icons for main GUI buttons SHOW_BUTTON_LABELS = True # If disabled, only shows icons for main GUI buttons
SHOW_TOOLTIPS = True SHOW_TOOLTIPS = True
#Overriden by config
SHOW_OSD = True # Sends Syncplay messages to media player OSD
SHOW_OSD_WARNINGS = True # Show warnings if playing different file, alone in room
SHOW_SLOWDOWN_OSD = True # Show notifications of slowing down / reverting on time difference
SHOW_SAME_ROOM_OSD = True # Show OSD notifications for events relating to room user is in
SHOW_DIFFERENT_ROOM_OSD = False # Show OSD notifications for events relating to room user is not in
SHOW_DURATION_NOTIFICATION = True
#Changing these might be ok #Changing these might be ok
DEFAULT_REWIND_THRESHOLD = 4 DEFAULT_REWIND_THRESHOLD = 4
MINIMUM_REWIND_THRESHOLD = 3
SEEK_THRESHOLD = 1 SEEK_THRESHOLD = 1
SLOWDOWN_RATE = 0.95 SLOWDOWN_RATE = 0.95
DEFAULT_SLOWDOWN_KICKIN_THRESHOLD = 1.5 DEFAULT_SLOWDOWN_KICKIN_THRESHOLD = 1.5
MINIMUM_SLOWDOWN_THRESHOLD = 1.3
SLOWDOWN_RESET_THRESHOLD = 0.1 SLOWDOWN_RESET_THRESHOLD = 0.1
MINIMUM_SLOWDOWN_THRESHOLD = 0.2
DIFFFERENT_DURATION_THRESHOLD = 2.5 DIFFFERENT_DURATION_THRESHOLD = 2.5
PROTOCOL_TIMEOUT = 12.5 PROTOCOL_TIMEOUT = 12.5
RECONNECT_RETRIES = 10 RECONNECT_RETRIES = 10
SERVER_STATE_INTERVAL = 1 SERVER_STATE_INTERVAL = 1
WARNING_OSD_MESSAGES_LOOP_INTERVAL = 1 WARNING_OSD_MESSAGES_LOOP_INTERVAL = 1
MERGE_PLAYPAUSE_BUTTONS = False MERGE_PLAYPAUSE_BUTTONS = True
SYNC_ON_PAUSE = True # Client seek to global position - subtitles may disappear on some media players SYNC_ON_PAUSE = True # Client seek to global position - subtitles may disappear on some media players
#Usually there's no need to adjust these #Usually there's no need to adjust these
FILENAME_STRIP_REGEX = u"[-~_\.\[\](): ]" FILENAME_STRIP_REGEX = u"[-~_\.\[\](): ]"
@ -87,6 +91,17 @@ VLC_MIN_PORT = 10000
VLC_MAX_PORT = 55000 VLC_MAX_PORT = 55000
#These are not changes you're looking for #These are not changes you're looking for
STYLE_TABLIST = "QListWidget::item { color: black; border-style: solid; border-width: 1px; border-radius: 2px; } QListWidget::item:selected { background: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(242, 248, 255, 255), stop:1 rgba(208, 229, 255, 255)); border-color: #84ACDD; } QListWidget::item:!selected { border-color: transparent; } QListWidget::item:!selected:hover { background: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(248, 248, 248, 255), stop:1 rgba(229, 229, 229, 255)); border-color: silver; }"
STYLE_SUBCHECKBOX = "QCheckBox, QLabel {{ margin-left: 8px; padding-left: 18px; background:url('{}') left no-repeat }}" #Graphic path
STYLE_SUBLABEL = "QCheckBox, QLabel {{ margin-left: 8px; padding-left: 14px; background:url('{}') left no-repeat }}" #Graphic path
STYLE_ERRORLABEL = "QLabel { color : black; border-style: outset; border-width: 2px; border-radius: 7px; border-color: red; padding: 2px; background: #FFAAAA; }"
STYLE_SUCCESSLABEL = "QLabel { color : black; border-style: outset; border-width: 2px; border-radius: 7px; border-color: green; padding: 2px; background: #AAFFAA; }"
STYLE_NOTIFICATIONBOX = "Username { color: #367AA9; font-weight:bold; }"
STYLE_USERNAME = "color: #367AA9; font-weight:bold;"
STYLE_ERRORNOTIFICATION = "color: red;"
STYLE_DIFFERENTITEM_COLOR = 'red'
STYLE_NOFILEITEM_COLOR = 'blue'
MPLAYER_SLAVE_ARGS = ['-slave', '--hr-seek=always', '-nomsgcolor', '-msglevel', 'all=1:global=4:cplayer=4'] MPLAYER_SLAVE_ARGS = ['-slave', '--hr-seek=always', '-nomsgcolor', '-msglevel', 'all=1:global=4:cplayer=4']
# --quiet works with both mpv 0.2 and 0.3 # --quiet works with both mpv 0.2 and 0.3
MPV_SLAVE_ARGS = ['--slave-broken', '--hr-seek=always', '--quiet', '--keep-open'] MPV_SLAVE_ARGS = ['--slave-broken', '--hr-seek=always', '--quiet', '--keep-open']
@ -104,6 +119,3 @@ PRIVACY_SENDRAW_MODE = "SendRaw"
PRIVACY_SENDHASHED_MODE = "SendHashed" PRIVACY_SENDHASHED_MODE = "SendHashed"
PRIVACY_DONTSEND_MODE = "DoNotSend" PRIVACY_DONTSEND_MODE = "DoNotSend"
PRIVACY_HIDDENFILENAME = "**Hidden filename**" PRIVACY_HIDDENFILENAME = "**Hidden filename**"
OPTION_AUTO = "Automatic"
OPTION_ALWAYS = "Always"
OPTION_NEVER = "Never"

View File

@ -4,6 +4,8 @@ from syncplay import constants
en = { en = {
# Client notifications # Client notifications
"config-cleared-notification" : "Settings cleared. Changes will be saved when you store a valid configuration.",
"relative-config-notification" : "Loaded relative configuration file(s): {}", "relative-config-notification" : "Loaded relative configuration file(s): {}",
"connection-attempt-notification" : "Attempting to connect to {}:{}", # Port, IP "connection-attempt-notification" : "Attempting to connect to {}:{}", # Port, IP
@ -131,14 +133,25 @@ en = {
"privacy-dontsend-option" : "Don't send", "privacy-dontsend-option" : "Don't send",
"filename-privacy-label" : "Filename information:", "filename-privacy-label" : "Filename information:",
"filesize-privacy-label" : "File size information:", "filesize-privacy-label" : "File size information:",
"slowdown-label" : "Slow down on desync:", "slowondesync-label" : "Slow down on minor desync (not supported on MPC-HC)",
"slowdown-auto-option" : "Automatic",
"slowdown-always-option" : "Always",
"slowdown-never-option" : "Never",
"dontslowdownwithme-label" : "Never slow down or rewind others", "dontslowdownwithme-label" : "Never slow down or rewind others",
"pauseonleave-label" : "Pause when user leaves", "pauseonleave-label" : "Pause when user leaves (e.g. if they are disconnected)",
"forceguiprompt-label" : "Do not always show this dialog", # (Inverted) "forceguiprompt-label" : "Don't always show this dialog", # (Inverted)
"nostore-label" : "Do not store this configuration", # (Inverted) "nostore-label" : "Don't store this configuration", # (Inverted)
"showosd-label" : "Enable OSD Messages",
"showosdwarnings-label" : "Include warnings (e.g. when files are different)",
"showsameroomosd-label" : "Include events in your room",
"showdifferentroomosd-label" : "Include events in other rooms",
"showslowdownosd-label" :"Include slowing down / reverting notification",
"showcontactinfo-label" : "Show contact info box",
"showbuttonlabels-label" : "Show labels on buttons",
"showtooltips-label" : "Show tooltips",
"showdurationnotification-label" : "Warn about media duration mismatches",
"basics-label" : "Basics",
"sync-label" : "Sync",
"messages-label" : "Messages",
"privacy-label" : "Privacy",
"help-label" : "Help", "help-label" : "Help",
"run-label" : "Run Syncplay", "run-label" : "Run Syncplay",
@ -186,20 +199,28 @@ en = {
"more-tooltip" : "Display less frequently used settings.", "more-tooltip" : "Display less frequently used settings.",
"slowdown-threshold-tooltip" : "Time ahead of slowest client before temporarily reducing playback speed (default: {} secs).".format(constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD), "slowdown-threshold-tooltip" : "Time ahead of slowest client before temporarily reducing playback speed (default: {} secs).".format(constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD),
"rewind-threshold-tooltip" : "Time ahead slowest client before seeking to get back in sync (default: {} secs). 'Never' can result in major desync!".format(constants.DEFAULT_REWIND_THRESHOLD), "rewind-threshold-tooltip" : "Time ahead slowest client before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_REWIND_THRESHOLD),
"filename-privacy-tooltip" : "Privacy mode for sending currently playing filename to server.", "filename-privacy-tooltip" : "Privacy mode for sending currently playing filename to server.",
"filesize-privacy-tooltip" : "Privacy mode for sending size of currently playing file to server.", "filesize-privacy-tooltip" : "Privacy mode for sending size of currently playing file to server.",
"privacy-sendraw-tooltip" : "Send this information without obfuscation. This is the default option with most functionality.", "privacy-sendraw-tooltip" : "Send this information without obfuscation. This is the default option with most functionality.",
"privacy-sendhashed-tooltip" : "Send a hashed version of the information, making it less visible to other clients.", "privacy-sendhashed-tooltip" : "Send a hashed version of the information, making it less visible to other clients.",
"privacy-dontsend-tooltip" : "Do not send this information to the server. This provides for maximum privacy.", "privacy-dontsend-tooltip" : "Do not send this information to the server. This provides for maximum privacy.",
"slowdown-tooltip" : "Reduce playback rate temporarily when needed to bring you back in sync with other viewers.", "slowondesync-tooltip" : "Reduce playback rate temporarily when needed to bring you back in sync with other viewers. Not supported on MPC-HC.",
"slowdown-auto-tooltip" : "Slow down on desync unless it causes problems (i.e. MPC-HC).",
"slowdown-always-tooltip" : "Always slow down on desync (even on players where this causes playback issues).",
"slowdown-never-tooltip" : "Never slow down on desync (even on players where this is probably better than rewinding).",
"dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging.", "dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging.",
"pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.", "pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.",
"rewindondesync-label" : "Rewind on major desync (highly recommended)",
"forceguiprompt-tooltip" : "Configuration dialogue is not shown when opening a file with Syncplay.", # (Inverted) "forceguiprompt-tooltip" : "Configuration dialogue is not shown when opening a file with Syncplay.", # (Inverted)
"nostore-tooltip" : "Run Syncplay with the given configuration, but do not permanently store the changes.", # (Inverted) "nostore-tooltip" : "Run Syncplay with the given configuration, but do not permanently store the changes.", # (Inverted)
"rewindondesync-tooltip" : "Jump back when needed to get back in sync. Disabling this option can result in major desyncs!",
"showosd-tooltip" : "Sends Syncplay messages to media player OSD.",
"showosdwarnings-tooltip" : "Show warnings if playing different file, alone in room.",
"showsameroomosd-tooltip" : "Show OSD notifications for events relating to room user is in.",
"showdifferentroomosd-tooltip" : "Show OSD notifications for events relating to room user is not in.",
"showslowdownosd-tooltip" :"Show notifications of slowing down / reverting on time difference.",
"showcontactinfo-tooltip" : "Show information box about contacting Syncplay developers in main Syncplay window.",
"showbuttonlabels-tooltip" : "Show the text alongside the icons for buttons in the main UI.",
"showtooltips-tooltip" : "Show tooltip help messages when you mouseover an input element in Syncplay.",
"showdurationnotification-tooltip" : "Useful for when a segment in a multi-part file is missing, but can result in false positives.",
"help-tooltip" : "Opens the Syncplay.pl user guide.", "help-tooltip" : "Opens the Syncplay.pl user guide.",

View File

@ -306,7 +306,6 @@ class MpcHcApi:
class MPCHCAPIPlayer(BasePlayer): class MPCHCAPIPlayer(BasePlayer):
speedSupported = False speedSupported = False
speedRecommended = False
def __init__(self, client): def __init__(self, client):
from twisted.internet import reactor from twisted.internet import reactor
@ -383,8 +382,6 @@ class MPCHCAPIPlayer(BasePlayer):
self.__mpcVersion = self._mpcApi.version.split('.') self.__mpcVersion = self._mpcApi.version.split('.')
if self.__mpcVersion[0:3] == ['1', '6', '4']: if self.__mpcVersion[0:3] == ['1', '6', '4']:
self.__switchPauseCalls = True self.__switchPauseCalls = True
if self.__mpcVersion[0:3] >= ['1', '6', '5']:
self.speedSupported = True
if filePath: if filePath:
self.openFile(filePath) self.openFile(filePath)

View File

@ -8,7 +8,6 @@ import os
class MplayerPlayer(BasePlayer): class MplayerPlayer(BasePlayer):
speedSupported = True speedSupported = True
speedRecommended = True
RE_ANSWER = re.compile(constants.MPLAYER_ANSWER_REGEX) RE_ANSWER = re.compile(constants.MPLAYER_ANSWER_REGEX)
SLAVE_ARGS = constants.MPLAYER_SLAVE_ARGS SLAVE_ARGS = constants.MPLAYER_SLAVE_ARGS
POSITION_QUERY = 'time_pos' POSITION_QUERY = 'time_pos'

View File

@ -14,7 +14,6 @@ import time
class VlcPlayer(BasePlayer): class VlcPlayer(BasePlayer):
speedSupported = True speedSupported = True
speedRecommended = True
RE_ANSWER = re.compile(constants.VLC_ANSWER_REGEX) RE_ANSWER = re.compile(constants.VLC_ANSWER_REGEX)
SLAVE_ARGS = constants.VLC_SLAVE_ARGS SLAVE_ARGS = constants.VLC_SLAVE_ARGS
if not sys.platform.startswith('darwin'): if not sys.platform.startswith('darwin'):

View File

@ -35,15 +35,28 @@ class ConfigurationGetter(object):
"playerClass": None, "playerClass": None,
"slowdownThreshold": constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD, "slowdownThreshold": constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD,
"rewindThreshold": constants.DEFAULT_REWIND_THRESHOLD, "rewindThreshold": constants.DEFAULT_REWIND_THRESHOLD,
"slowMeOnDesync": constants.OPTION_AUTO, "rewindOnDesync": True,
"slowOnDesync": True,
"dontSlowDownWithMe": False, "dontSlowDownWithMe": False,
"filenamePrivacyMode": constants.PRIVACY_SENDRAW_MODE, "filenamePrivacyMode": constants.PRIVACY_SENDRAW_MODE,
"filesizePrivacyMode": constants.PRIVACY_SENDRAW_MODE, "filesizePrivacyMode": constants.PRIVACY_SENDRAW_MODE,
"pauseOnLeave": False, "pauseOnLeave": False,
"clearGUIData": False, "clearGUIData": False,
"language" : "" "language" : "",
"resetConfig" : False,
"showOSD" : True,
"showOSDWarnings" : True,
"showSlowdownOSD" : True,
"showDifferentRoomOSD" : False,
"showSameRoomOSD" : True,
"showContactInfo" : True,
"showButtonLabels" : True,
"showTooltips" : True,
"showDurationNotification" : True
} }
self._defaultConfig = self._config.copy()
# #
# Custom validation in self._validateArguments # Custom validation in self._validateArguments
# #
@ -62,18 +75,39 @@ class ConfigurationGetter(object):
"noStore", "noStore",
"dontSlowDownWithMe", "dontSlowDownWithMe",
"pauseOnLeave", "pauseOnLeave",
"clearGUIData" "clearGUIData",
"rewindOnDesync",
"slowOnDesync",
"pauseOnLeave",
"clearGUIData",
"resetConfig",
"showOSD",
"showOSDWarnings",
"showSlowdownOSD",
"showDifferentRoomOSD",
"showSameRoomOSD",
"showContactInfo" ,
"showButtonLabels",
"showTooltips",
"showDurationNotification"
] ]
self._iniStructure = { self._iniStructure = {
"server_data": ["host", "port", "password"], "server_data": ["host", "port", "password"],
"client_settings": ["name", "room", "playerPath", "slowdownThreshold", "rewindThreshold", "slowMeOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "pauseOnLeave"], "client_settings": ["name", "room", "playerPath", "slowdownThreshold", "rewindThreshold", "slowOnDesync", "rewindOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "pauseOnLeave"],
"gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD", "showDifferentRoomOSD", "showSameRoomOSD", "showContactInfo" , "showButtonLabels", "showTooltips", "showDurationNotification"],
"general": ["language"] "general": ["language"]
} }
self._playerFactory = PlayerFactory() self._playerFactory = PlayerFactory()
def _validateArguments(self): def _validateArguments(self):
if self._config['resetConfig']:
language = self._config['language']
self._config = self._defaultConfig
self._config['language'] = language
raise InvalidConfigValue("*"+getMessage("config-cleared-notification"))
def _isPortValid(varToTest): def _isPortValid(varToTest):
try: try:
if varToTest == "" or varToTest is None: if varToTest == "" or varToTest is None:

View File

@ -9,7 +9,8 @@ from syncplay.messages import getMessage
from syncplay import constants from syncplay import constants
class GuiConfiguration: class GuiConfiguration:
def __init__(self, config, error=None): def __init__(self, config, error=None, defaultConfig=None):
self.defaultConfig = defaultConfig
self.config = config self.config = config
self._availablePlayerPaths = [] self._availablePlayerPaths = []
self.error = error self.error = error
@ -18,7 +19,7 @@ class GuiConfiguration:
def run(self): def run(self):
if QCoreApplication.instance() is None: if QCoreApplication.instance() is None:
self.app = QtGui.QApplication(sys.argv) self.app = QtGui.QApplication(sys.argv)
dialog = ConfigDialog(self.config, self._availablePlayerPaths, self.error) dialog = ConfigDialog(self.config, self._availablePlayerPaths, self.error, self.defaultConfig)
dialog.exec_() dialog.exec_()
def setAvailablePaths(self, paths): def setAvailablePaths(self, paths):
@ -39,21 +40,25 @@ class ConfigDialog(QtGui.QDialog):
if self.moreToggling == False: if self.moreToggling == False:
self.moreToggling = True self.moreToggling = True
if self.showmoreCheckbox.isChecked() and self.showmoreCheckbox.isVisible(): if self.showmoreCheckbox.isChecked():
self.showmoreCheckbox.setChecked(False) self.tabListFrame.show()
self.moreSettingsGroup.setChecked(True) self.resetButton.show()
self.moreSettingsGroup.show() self.nostoreCheckbox.show()
self.showmoreCheckbox.hide() self.alwaysshowCheckbox.show()
self.saveMoreState(True) self.saveMoreState(True)
self.tabListWidget.setCurrentRow(0)
self.ensureTabListIsVisible()
else: else:
self.moreSettingsGroup.setChecked(False) self.tabListFrame.hide()
self.moreSettingsGroup.hide() self.resetButton.hide()
self.showmoreCheckbox.show() self.nostoreCheckbox.hide()
self.alwaysshowCheckbox.hide()
self.saveMoreState(False) self.saveMoreState(False)
self.stackedLayout.setCurrentIndex(0)
self.moreToggling = False
self.adjustSize() self.adjustSize()
self.setFixedSize(self.sizeHint()) self.setFixedSize(self.sizeHint())
self.moreToggling = False
def runButtonTextUpdate(self): def runButtonTextUpdate(self):
if self.nostoreCheckbox.isChecked(): if self.nostoreCheckbox.isChecked():
@ -181,7 +186,10 @@ class ConfigDialog(QtGui.QDialog):
def _saveDataAndLeave(self): def _saveDataAndLeave(self):
self.processWidget(self, lambda w: self.saveValues(w)) self.processWidget(self, lambda w: self.saveValues(w))
self.config['host'] = self.hostTextbox.text() if ":" in self.hostTextbox.text() else self.hostTextbox.text() + ":" + unicode(constants.DEFAULT_PORT) if self.hostTextbox.text():
self.config['host'] = self.hostTextbox.text() if ":" in self.hostTextbox.text() else self.hostTextbox.text() + ":" + unicode(constants.DEFAULT_PORT)
else:
self.config['host'] = None
self.config['playerPath'] = unicode(self.executablepathCombobox.currentText()) self.config['playerPath'] = unicode(self.executablepathCombobox.currentText())
if self.mediapathTextbox.text() == "": if self.mediapathTextbox.text() == "":
self.config['file'] = None self.config['file'] = None
@ -234,7 +242,7 @@ class ConfigDialog(QtGui.QDialog):
def loadTooltips(self, widget): def loadTooltips(self, widget):
tooltipName = widget.objectName().lower().split(":")[0] + "-tooltip" tooltipName = widget.objectName().lower().split(":")[0] + "-tooltip"
if tooltipName[:1] == "*" or tooltipName[:1] == "!": if tooltipName[:1] == "*" or tooltipName[:1] == "!": # * is for notifications
tooltipName = tooltipName[1:] tooltipName = tooltipName[1:]
widget.setToolTip(getMessage(tooltipName)) widget.setToolTip(getMessage(tooltipName))
@ -276,36 +284,13 @@ class ConfigDialog(QtGui.QDialog):
elif isinstance(widget, QLineEdit): elif isinstance(widget, QLineEdit):
self.config[valueName] = widget.text() self.config[valueName] = widget.text()
def __init__(self, config, playerpaths, error): def addBasicTab(self):
config = self.config
from syncplay import utils playerpaths = self.playerpaths
self.config = config resourcespath = self.resourcespath
self.datacleared = False error = self.error
if self.datacleared == True:
if config['clearGUIData'] == True: error = "*{}".format(getMessage("gui-data-cleared-notification"))
settings = QSettings("Syncplay", "PlayerList")
settings.clear()
settings = QSettings("Syncplay", "MediaBrowseDialog")
settings.clear()
settings = QSettings("Syncplay", "MainWindow")
settings.clear()
settings = QSettings("Syncplay", "MoreSettings")
settings.clear()
self.datacleared = True
self.QtGui = QtGui
self.error = error
if sys.platform.startswith('windows'):
resourcespath = utils.findWorkingDir() + "\\resources\\"
else:
resourcespath = utils.findWorkingDir() + "/resources/"
self.resourcespath = resourcespath
super(ConfigDialog, self).__init__()
self.setWindowTitle(getMessage("config-window-title"))
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
self.setWindowIcon(QtGui.QIcon(resourcespath + "syncplay.png"))
if config['host'] == None: if config['host'] == None:
host = "" host = ""
elif ":" in config['host']: elif ":" in config['host']:
@ -356,8 +341,7 @@ class ConfigDialog(QtGui.QDialog):
self.executablepathCombobox.setEditable(True) self.executablepathCombobox.setEditable(True)
self.executablepathCombobox.currentIndexChanged.connect(self.updateExecutableIcon) self.executablepathCombobox.currentIndexChanged.connect(self.updateExecutableIcon)
self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'], playerpaths)) self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'], playerpaths))
self.executablepathCombobox.setMinimumWidth(200) self.executablepathCombobox.setFixedWidth(165)
self.executablepathCombobox.setMaximumWidth(200)
self.executablepathCombobox.editTextChanged.connect(self.updateExecutableIcon) self.executablepathCombobox.editTextChanged.connect(self.updateExecutableIcon)
self.executablepathLabel = QLabel(getMessage("executable-path-label"), self) self.executablepathLabel = QLabel(getMessage("executable-path-label"), self)
@ -383,11 +367,55 @@ class ConfigDialog(QtGui.QDialog):
self.mediaplayerSettingsLayout.addWidget(self.mediabrowseButton , 1, 3) self.mediaplayerSettingsLayout.addWidget(self.mediabrowseButton , 1, 3)
self.mediaplayerSettingsGroup.setLayout(self.mediaplayerSettingsLayout) self.mediaplayerSettingsGroup.setLayout(self.mediaplayerSettingsLayout)
self.moreSettingsGroup = QtGui.QGroupBox(getMessage("more-title")) self.showmoreCheckbox = QCheckBox(getMessage("more-title"))
self.showmoreCheckbox.setObjectName("!more")
self.moreSettingsGroup.setCheckable(True) self.basicOptionsFrame = QtGui.QFrame()
self.basicOptionsLayout = QtGui.QVBoxLayout()
if error:
self.errorLabel = QLabel(self)
if error[:1] != "*":
self.errorLabel.setStyleSheet(constants.STYLE_ERRORLABEL)
else:
error = error[1:]
self.errorLabel.setStyleSheet(constants.STYLE_SUCCESSLABEL)
self.errorLabel.setText(error)
self.errorLabel.setAlignment(Qt.AlignCenter)
self.basicOptionsLayout.addWidget(self.errorLabel, 0, 0)
self.basicOptionsLayout.addWidget(self.connectionSettingsGroup)
self.basicOptionsLayout.addSpacing(12)
self.basicOptionsLayout.addWidget(self.mediaplayerSettingsGroup)
self.basicOptionsFrame.setLayout(self.basicOptionsLayout)
self.stackedLayout.addWidget(self.basicOptionsFrame)
def addSyncTab(self):
self.syncSettingsFrame = QtGui.QFrame()
self.syncSettingsLayout = QtGui.QVBoxLayout()
self.desyncSettingsGroup = QtGui.QGroupBox("If others are lagging behind...")
self.desyncOptionsFrame = QtGui.QFrame()
self.desyncSettingsOptionsLayout = QtGui.QHBoxLayout()
config = self.config
self.slowdownCheckbox = QCheckBox(getMessage("slowondesync-label"))
self.slowdownCheckbox.setObjectName("slowOnDesync")
self.rewindCheckbox = QCheckBox(getMessage("rewindondesync-label"))
self.rewindCheckbox.setObjectName("rewindOnDesync")
self.spaceLabel = QLabel()
self.spaceLabel.setFixedHeight(5)
self.desyncSettingsLayout = QtGui.QGridLayout()
self.desyncSettingsLayout.setSpacing(2)
self.desyncFrame = QtGui.QFrame()
self.desyncFrame.setLineWidth(0)
self.desyncFrame.setMidLineWidth(0)
self.slowdownThresholdLabel = QLabel(getMessage("slowdown-threshold-label"), self) self.slowdownThresholdLabel = QLabel(getMessage("slowdown-threshold-label"), self)
self.slowdownThresholdLabel.setStyleSheet(constants.STYLE_SUBLABEL.format(self.posixresourcespath + "bullet_black.png"))
self.slowdownThresholdSpinbox = QDoubleSpinBox() self.slowdownThresholdSpinbox = QDoubleSpinBox()
try: try:
self.slowdownThresholdSpinbox.setValue(float(config['slowdownThreshold'])) self.slowdownThresholdSpinbox.setValue(float(config['slowdownThreshold']))
@ -402,6 +430,7 @@ class ConfigDialog(QtGui.QDialog):
self.slowdownThresholdSpinbox.adjustSize() self.slowdownThresholdSpinbox.adjustSize()
self.rewindThresholdLabel = QLabel(getMessage("rewind-threshold-label"), self) self.rewindThresholdLabel = QLabel(getMessage("rewind-threshold-label"), self)
self.rewindThresholdLabel.setStyleSheet(constants.STYLE_SUBLABEL.format(self.posixresourcespath + "bullet_black.png"))
self.rewindThresholdSpinbox = QDoubleSpinBox() self.rewindThresholdSpinbox = QDoubleSpinBox()
try: try:
self.rewindThresholdSpinbox.setValue(float(config['rewindThreshold'])) self.rewindThresholdSpinbox.setValue(float(config['rewindThreshold']))
@ -410,9 +439,8 @@ class ConfigDialog(QtGui.QDialog):
self.rewindThresholdSpinbox.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) self.rewindThresholdSpinbox.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
self.rewindThresholdSpinbox.setMinimumWidth(80) self.rewindThresholdSpinbox.setMinimumWidth(80)
self.rewindThresholdSpinbox.setMaximumWidth(80) self.rewindThresholdSpinbox.setMaximumWidth(80)
self.rewindThresholdSpinbox.setMinimum(0) self.rewindThresholdSpinbox.setMinimum(constants.MINIMUM_REWIND_THRESHOLD)
self.rewindThresholdSpinbox.setSingleStep(0.1) self.rewindThresholdSpinbox.setSingleStep(0.1)
self.rewindThresholdSpinbox.setSpecialValueText(getMessage("never-rewind-value"))
self.rewindThresholdSpinbox.setSuffix(getMessage("seconds-suffix")) self.rewindThresholdSpinbox.setSuffix(getMessage("seconds-suffix"))
self.rewindThresholdSpinbox.adjustSize() self.rewindThresholdSpinbox.adjustSize()
@ -421,14 +449,114 @@ class ConfigDialog(QtGui.QDialog):
self.rewindThresholdLabel.setObjectName("rewind-threshold") self.rewindThresholdLabel.setObjectName("rewind-threshold")
self.rewindThresholdSpinbox.setObjectName("rewind-threshold") self.rewindThresholdSpinbox.setObjectName("rewind-threshold")
self.slowdownLabel = QLabel(getMessage("slowdown-label"), self) self.desyncSettingsLayout.addWidget(self.slowdownCheckbox, 0, 0, 1, 2, Qt.AlignLeft)
self.slowdownButtonGroup = QButtonGroup() self.desyncSettingsLayout.addWidget(self.slowdownThresholdLabel, 1, 0, 1, 1, Qt.AlignLeft)
self.slowdownAutoOption = QRadioButton(getMessage("slowdown-auto-option")) self.desyncSettingsLayout.addWidget(self.slowdownThresholdSpinbox, 1, 1, 1, 1, Qt.AlignLeft)
self.slowdownAlwaysOption = QRadioButton(getMessage("slowdown-always-option")) self.desyncSettingsLayout.addWidget(self.spaceLabel, 2, 0,1,2, Qt.AlignLeft)
self.slowdownNeverOption = QRadioButton(getMessage("slowdown-never-option")) self.desyncSettingsLayout.addWidget(self.rewindCheckbox, 3, 0,1,2, Qt.AlignLeft)
self.slowdownButtonGroup.addButton(self.slowdownAutoOption) self.desyncSettingsLayout.addWidget(self.rewindThresholdLabel, 4, 0, 1, 1, Qt.AlignLeft)
self.slowdownButtonGroup.addButton(self.slowdownAlwaysOption) self.desyncSettingsLayout.addWidget(self.rewindThresholdSpinbox, 4, 1, Qt.AlignLeft)
self.slowdownButtonGroup.addButton(self.slowdownNeverOption)
self.desyncSettingsLayout.setAlignment(Qt.AlignLeft)
self.desyncSettingsGroup.setLayout(self.desyncSettingsLayout)
self.desyncSettingsOptionsLayout.addWidget(self.desyncFrame)
self.syncSettingsLayout.addWidget(self.desyncSettingsGroup)
self.desyncFrame.setLayout(self.syncSettingsLayout)
self.othersyncSettingsGroup = QtGui.QGroupBox("Other sync options")
self.othersyncOptionsFrame = QtGui.QFrame()
self.othersyncSettingsLayout = QtGui.QGridLayout()
self.dontslowwithmeCheckbox = QCheckBox(getMessage("dontslowdownwithme-label"))
self.pauseonleaveCheckbox = QCheckBox(getMessage("pauseonleave-label"))
self.othersyncSettingsLayout.addWidget(self.dontslowwithmeCheckbox)
self.othersyncSettingsLayout.addWidget(self.pauseonleaveCheckbox)
self.dontslowwithmeCheckbox.setObjectName("dontSlowDownWithMe")
self.pauseonleaveCheckbox.setObjectName("pauseOnLeave")
self.othersyncSettingsGroup.setLayout(self.othersyncSettingsLayout)
self.syncSettingsLayout.addWidget(self.othersyncSettingsGroup)
self.syncSettingsFrame.setLayout(self.syncSettingsLayout)
self.desyncSettingsGroup.setMaximumHeight(self.desyncSettingsGroup.minimumSizeHint().height())
self.syncSettingsLayout.setAlignment(Qt.AlignTop)
self.stackedLayout.addWidget(self.syncSettingsFrame)
def addMessageTab(self):
self.messageFrame = QtGui.QFrame()
self.messageLayout = QtGui.QVBoxLayout()
# OSD
self.osdSettingsGroup = QtGui.QGroupBox("On-screen Display settings")
self.osdSettingsLayout = QtGui.QVBoxLayout()
self.osdSettingsFrame = QtGui.QFrame()
self.showOSDCheckbox = QCheckBox(getMessage("showosd-label"))
self.showOSDCheckbox.setObjectName("showOSD")
self.osdSettingsLayout.addWidget(self.showOSDCheckbox)
self.showSameRoomOSDCheckbox = QCheckBox(getMessage("showsameroomosd-label"))
self.showSameRoomOSDCheckbox.setObjectName("showSameRoomOSD")
self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "bullet_black.png"))
self.osdSettingsLayout.addWidget(self.showSameRoomOSDCheckbox)
self.showDifferentRoomOSDCheckbox = QCheckBox(getMessage("showdifferentroomosd-label"))
self.showDifferentRoomOSDCheckbox.setObjectName("showDifferentRoomOSD")
self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "bullet_black.png"))
self.osdSettingsLayout.addWidget(self.showDifferentRoomOSDCheckbox)
self.slowdownOSDCheckbox = QCheckBox(getMessage("showslowdownosd-label"))
self.slowdownOSDCheckbox.setObjectName("showSlowdownOSD")
self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "bullet_black.png"))
self.osdSettingsLayout.addWidget(self.slowdownOSDCheckbox)
self.showOSDWarningsCheckbox = QCheckBox(getMessage("showosdwarnings-label"))
self.showOSDWarningsCheckbox.setObjectName("showOSDWarnings")
self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "bullet_black.png"))
self.osdSettingsLayout.addWidget(self.showOSDWarningsCheckbox)
self.osdSettingsGroup.setLayout(self.osdSettingsLayout)
self.osdSettingsLayout.setAlignment(Qt.AlignTop)
self.messageLayout.addWidget(self.osdSettingsGroup)
# Other display
self.displaySettingsGroup = QtGui.QGroupBox("Other display settings")
self.displaySettingsLayout = QtGui.QVBoxLayout()
self.displaySettingsFrame = QtGui.QFrame()
self.showDurationNotificationCheckbox = QCheckBox(getMessage("showdurationnotification-label"))
self.showDurationNotificationCheckbox.setObjectName("showDurationNotification")
self.displaySettingsLayout.addWidget(self.showDurationNotificationCheckbox)
self.showcontactinfoCheckbox = QCheckBox(getMessage("showcontactinfo-label"))
self.showcontactinfoCheckbox.setObjectName("showContactInfo")
self.displaySettingsLayout.addWidget(self.showcontactinfoCheckbox)
self.showButtonLabelsCheckbox = QCheckBox(getMessage("showbuttonlabels-label"))
self.showButtonLabelsCheckbox.setObjectName("showButtonLabels")
self.displaySettingsLayout.addWidget(self.showButtonLabelsCheckbox)
self.showTooltipsCheckbox = QCheckBox(getMessage("showtooltips-label"))
self.showTooltipsCheckbox.setObjectName("showTooltips")
self.displaySettingsLayout.addWidget(self.showTooltipsCheckbox)
self.displaySettingsGroup.setLayout(self.displaySettingsLayout)
self.displaySettingsLayout.setAlignment(Qt.AlignTop)
self.messageLayout.addWidget(self.displaySettingsGroup)
# messageFrame
self.messageFrame.setLayout(self.messageLayout)
self.stackedLayout.addWidget(self.messageFrame)
def addPrivacyTab(self):
self.privacySettingsGroup = QtGui.QGroupBox("Privacy settings")
self.privacySettingsLayout = QtGui.QVBoxLayout()
self.privacySettingsFrame = QtGui.QFrame()
self.privacyFrame = QtGui.QFrame()
self.privacyLayout = QtGui.QGridLayout()
self.filenameprivacyLabel = QLabel(getMessage("filename-privacy-label"), self) self.filenameprivacyLabel = QLabel(getMessage("filename-privacy-label"), self)
self.filenameprivacyButtonGroup = QButtonGroup() self.filenameprivacyButtonGroup = QButtonGroup()
@ -448,11 +576,6 @@ class ConfigDialog(QtGui.QDialog):
self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacySendHashedOption) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacySendHashedOption)
self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacyDontSendOption) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacyDontSendOption)
self.dontslowwithmeCheckbox = QCheckBox(getMessage("dontslowdownwithme-label"))
self.pauseonleaveCheckbox = QCheckBox(getMessage("pauseonleave-label"))
self.alwaysshowCheckbox = QCheckBox(getMessage("forceguiprompt-label"))
self.nostoreCheckbox = QCheckBox(getMessage("nostore-label"))
self.filenameprivacyLabel.setObjectName("filename-privacy") self.filenameprivacyLabel.setObjectName("filename-privacy")
self.filenameprivacySendRawOption.setObjectName("privacy-sendraw:filenamePrivacyMode="+ constants.PRIVACY_SENDRAW_MODE) self.filenameprivacySendRawOption.setObjectName("privacy-sendraw:filenamePrivacyMode="+ constants.PRIVACY_SENDRAW_MODE)
self.filenameprivacySendHashedOption.setObjectName("privacy-sendhashed:filenamePrivacyMode=" + constants.PRIVACY_SENDHASHED_MODE) self.filenameprivacySendHashedOption.setObjectName("privacy-sendhashed:filenamePrivacyMode=" + constants.PRIVACY_SENDHASHED_MODE)
@ -462,103 +585,169 @@ class ConfigDialog(QtGui.QDialog):
self.filesizeprivacySendHashedOption.setObjectName("privacy-sendhashed:filesizePrivacyMode=" + constants.PRIVACY_SENDHASHED_MODE) self.filesizeprivacySendHashedOption.setObjectName("privacy-sendhashed:filesizePrivacyMode=" + constants.PRIVACY_SENDHASHED_MODE)
self.filesizeprivacyDontSendOption.setObjectName("privacy-dontsend:filesizePrivacyMode=" + constants.PRIVACY_DONTSEND_MODE) self.filesizeprivacyDontSendOption.setObjectName("privacy-dontsend:filesizePrivacyMode=" + constants.PRIVACY_DONTSEND_MODE)
self.privacyLayout.addWidget(self.filenameprivacyLabel, 1, 0)
self.privacyLayout.addWidget(self.filenameprivacySendRawOption, 1, 1, Qt.AlignLeft)
self.privacyLayout.addWidget(self.filenameprivacySendHashedOption, 1, 2, Qt.AlignLeft)
self.privacyLayout.addWidget(self.filenameprivacyDontSendOption, 1, 3, Qt.AlignLeft)
self.privacyLayout.addWidget(self.filesizeprivacyLabel, 2, 0)
self.privacyLayout.addWidget(self.filesizeprivacySendRawOption, 2, 1, Qt.AlignLeft)
self.privacyLayout.addWidget(self.filesizeprivacySendHashedOption, 2, 2, Qt.AlignLeft)
self.privacyLayout.addWidget(self.filesizeprivacyDontSendOption, 2, 3, Qt.AlignLeft)
self.slowdownLabel.setObjectName("slowdown") self.privacyFrame.setLayout(self.privacyLayout)
self.slowdownAutoOption.setObjectName("slowdown-auto:slowMeOnDesync=" + constants.OPTION_AUTO) self.privacySettingsGroup.setLayout(self.privacyLayout)
self.slowdownAlwaysOption.setObjectName("slowdown-always:slowMeOnDesync=" + constants.OPTION_ALWAYS) self.privacySettingsGroup.setMaximumHeight(self.privacySettingsGroup.minimumSizeHint().height())
self.slowdownNeverOption.setObjectName("slowdown-never:slowMeOnDesync=" + constants.OPTION_NEVER) self.privacySettingsLayout.addWidget(self.privacySettingsGroup)
self.privacySettingsLayout.setAlignment(Qt.AlignTop)
self.privacyFrame.setLayout(self.privacySettingsLayout)
self.stackedLayout.addWidget(self.privacyFrame)
self.dontslowwithmeCheckbox.setObjectName("dontSlowDownWithMe") def addBottomLayout(self):
self.pauseonleaveCheckbox.setObjectName("pauseOnLeave") config = self.config
self.alwaysshowCheckbox.setObjectName("*forceGuiPrompt") resourcespath = self.resourcespath
self.nostoreCheckbox.setObjectName("noStore")
self.moreSettingsLayout = QtGui.QGridLayout() self.bottomButtonFrame = QtGui.QFrame()
self.bottomButtonLayout = QtGui.QHBoxLayout()
self.thresholdSettingsLayout = QtGui.QGridLayout() self.helpButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'help.png'), getMessage("help-label"))
self.thresholdFrame = QtGui.QFrame()
self.thresholdFrame.setLineWidth(0)
self.thresholdFrame.setMidLineWidth(0)
self.thresholdSettingsLayout.setContentsMargins(0, 0, 0, 0)
self.thresholdSettingsLayout.addWidget(self.slowdownThresholdLabel, 0, 0, Qt.AlignLeft)
self.thresholdSettingsLayout.addWidget(self.slowdownThresholdSpinbox, 0, 1, Qt.AlignLeft)
self.thresholdSettingsLayout.addWidget(self.rewindThresholdLabel, 0, 2, Qt.AlignLeft)
self.thresholdSettingsLayout.addWidget(self.rewindThresholdSpinbox, 0, 3, Qt.AlignLeft)
self.thresholdFrame.setLayout(self.thresholdSettingsLayout)
self.moreSettingsLayout.addWidget(self.thresholdFrame, 0, 0, 1, 4, Qt.AlignLeft)
self.privacySettingsLayout = QtGui.QGridLayout()
self.radioFrame = QtGui.QFrame()
self.radioFrame.setLineWidth(0)
self.radioFrame.setMidLineWidth(0)
self.privacySettingsLayout.setContentsMargins(0, 0, 0, 0)
self.privacySettingsLayout.addWidget(self.slowdownLabel, 0, 0)
self.privacySettingsLayout.addWidget(self.slowdownAutoOption, 0, 1, Qt.AlignLeft)
self.privacySettingsLayout.addWidget(self.slowdownAlwaysOption, 0, 2, Qt.AlignLeft)
self.privacySettingsLayout.addWidget(self.slowdownNeverOption, 0, 3, Qt.AlignLeft)
self.privacySettingsLayout.addWidget(self.filenameprivacyLabel, 1, 0)
self.privacySettingsLayout.addWidget(self.filenameprivacySendRawOption, 1, 1, Qt.AlignLeft)
self.privacySettingsLayout.addWidget(self.filenameprivacySendHashedOption, 1, 2, Qt.AlignLeft)
self.privacySettingsLayout.addWidget(self.filenameprivacyDontSendOption, 1, 3, Qt.AlignLeft)
self.privacySettingsLayout.addWidget(self.filesizeprivacyLabel, 2, 0)
self.privacySettingsLayout.addWidget(self.filesizeprivacySendRawOption, 2, 1, Qt.AlignLeft)
self.privacySettingsLayout.addWidget(self.filesizeprivacySendHashedOption, 2, 2, Qt.AlignLeft)
self.privacySettingsLayout.addWidget(self.filesizeprivacyDontSendOption, 2, 3, Qt.AlignLeft)
self.radioFrame.setLayout(self.privacySettingsLayout)
self.moreSettingsLayout.addWidget(self.radioFrame, 1, 0, 1, 4)
self.moreSettingsLayout.addWidget(self.dontslowwithmeCheckbox, 4, 0, 1, 2)
self.moreSettingsLayout.addWidget(self.pauseonleaveCheckbox, 5, 0, 1, 2)
self.moreSettingsLayout.addWidget(self.alwaysshowCheckbox, 4, 2, 1, 2)
self.moreSettingsLayout.addWidget(self.nostoreCheckbox, 5, 2, 1, 2)
self.moreSettingsGroup.setLayout(self.moreSettingsLayout)
self.showmoreCheckbox = QCheckBox(getMessage("more-title"))
if self.getMoreState() == False:
self.showmoreCheckbox.setChecked(False)
self.moreSettingsGroup.hide()
else:
self.showmoreCheckbox.hide()
self.showmoreCheckbox.toggled.connect(self.moreToggled)
self.moreSettingsGroup.toggled.connect(self.moreToggled)
self.showmoreCheckbox.setObjectName("!more")
self.nostoreCheckbox.toggled.connect(self.runButtonTextUpdate)
self.mainLayout = QtGui.QVBoxLayout()
if error:
self.errorLabel = QLabel(error, self)
self.errorLabel.setAlignment(Qt.AlignCenter)
self.errorLabel.setStyleSheet("QLabel { color : red; }")
self.mainLayout.addWidget(self.errorLabel)
self.mainLayout.addWidget(self.connectionSettingsGroup)
self.mainLayout.addSpacing(12)
self.mainLayout.addWidget(self.mediaplayerSettingsGroup)
self.mainLayout.addSpacing(12)
self.mainLayout.addWidget(self.showmoreCheckbox)
self.mainLayout.addWidget(self.moreSettingsGroup)
self.mainLayout.addSpacing(12)
self.topLayout = QtGui.QHBoxLayout()
self.helpButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'help.png'), getMessage("help-label"))
self.helpButton.setObjectName("help") self.helpButton.setObjectName("help")
self.helpButton.setMaximumSize(self.helpButton.sizeHint()) self.helpButton.setMaximumSize(self.helpButton.sizeHint())
self.helpButton.pressed.connect(self.openHelp) self.helpButton.pressed.connect(self.openHelp)
self.resetButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'cog_delete.png'),"Reset settings")
self.resetButton.setMaximumSize(self.resetButton.sizeHint())
self.resetButton.pressed.connect(self.resetSettings)
self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("storeandrun-label")) self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("storeandrun-label"))
self.runButton.pressed.connect(self._saveDataAndLeave) self.runButton.pressed.connect(self._saveDataAndLeave)
self.bottomButtonLayout.addWidget(self.helpButton)
self.bottomButtonLayout.addWidget(self.resetButton)
self.bottomButtonLayout.addWidget(self.runButton)
self.bottomButtonFrame.setLayout(self.bottomButtonLayout)
if config['noStore'] == True: if config['noStore'] == True:
self.runButton.setText(getMessage("run-label")) self.runButton.setText(getMessage("run-label"))
self.topLayout.addWidget(self.helpButton, Qt.AlignLeft) self.bottomButtonLayout.setContentsMargins(5,0,5,0)
self.topLayout.addWidget(self.runButton, Qt.AlignRight) self.mainLayout.addWidget(self.bottomButtonFrame, 1, 0, 1, 2)
self.mainLayout.addLayout(self.topLayout)
self.bottomCheckboxFrame = QtGui.QFrame()
self.bottomCheckboxFrame.setContentsMargins(0,0,0,0)
self.bottomCheckboxLayout = QtGui.QGridLayout()
self.alwaysshowCheckbox = QCheckBox(getMessage("forceguiprompt-label"))
self.nostoreCheckbox = QCheckBox(getMessage("nostore-label"))
self.bottomCheckboxLayout.addWidget(self.showmoreCheckbox)
self.bottomCheckboxLayout.addWidget(self.alwaysshowCheckbox, 0, 1, Qt.AlignLeft)
self.bottomCheckboxLayout.addWidget(self.nostoreCheckbox, 0, 2, Qt.AlignRight)
self.alwaysshowCheckbox.setObjectName("*forceGuiPrompt")
self.nostoreCheckbox.setObjectName("noStore")
self.nostoreCheckbox.toggled.connect(self.runButtonTextUpdate)
self.bottomCheckboxFrame.setLayout(self.bottomCheckboxLayout)
self.mainLayout.addWidget(self.bottomCheckboxFrame, 2, 0, 1, 2)
def tabList(self):
self.tabListLayout = QtGui.QHBoxLayout()
self.tabListFrame = QtGui.QFrame()
self.tabListWidget = QtGui.QListWidget()
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "house.png"),getMessage("basics-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "film_link.png"),getMessage("sync-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "comments.png"),getMessage("messages-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "eye.png"),getMessage("privacy-label")))
self.tabListLayout.addWidget(self.tabListWidget)
self.tabListFrame.setLayout(self.tabListLayout)
self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width())
self.tabListWidget.setStyleSheet(constants.STYLE_TABLIST)
self.tabListWidget.currentItemChanged.connect(self.tabChange)
self.tabListWidget.itemClicked.connect(self.tabChange)
self.tabListWidget.itemPressed.connect(self.tabChange)
self.mainLayout.addWidget(self.tabListFrame, 0, 0, 1, 1)
def ensureTabListIsVisible(self):
self.stackedFrame.setFixedWidth(self.stackedFrame.width())
while self.tabListWidget.horizontalScrollBar().isVisible() and self.tabListFrame.width() < 200:
self.tabListFrame.setFixedWidth(self.tabListFrame.width()+1)
def tabChange(self):
self.setFocus()
self.stackedLayout.setCurrentIndex(self.tabListWidget.currentRow())
def resetSettings(self):
self.clearGUIData(leaveMore=True)
self.config['resetConfig'] = True
self.pressedclosebutton = True
self.close()
def showEvent(self, *args, **kwargs):
self.ensureTabListIsVisible()
def clearGUIData(self, leaveMore=False):
settings = QSettings("Syncplay", "PlayerList")
settings.clear()
settings = QSettings("Syncplay", "MediaBrowseDialog")
settings.clear()
settings = QSettings("Syncplay", "MainWindow")
settings.clear()
if not leaveMore:
settings = QSettings("Syncplay", "MoreSettings")
settings.clear()
self.datacleared = True
def __init__(self, config, playerpaths, error, defaultConfig):
from syncplay import utils
self.config = config
self.defaultConfig = defaultConfig
self.playerpaths = playerpaths
self.datacleared = False
self.config['resetConfig'] = False
if self.config['clearGUIData'] == True:
self.config['clearGUIData'] = False
self.clearGUIData()
self.QtGui = QtGui
self.error = error
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + "\\resources\\"
else:
resourcespath = utils.findWorkingDir() + "/resources/"
self.posixresourcespath = utils.findWorkingDir().replace("\\","/") + "/resources/"
self.resourcespath = resourcespath
super(ConfigDialog, self).__init__()
self.setWindowTitle(getMessage("config-window-title"))
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
self.setWindowIcon(QtGui.QIcon(resourcespath + "syncplay.png"))
self.stackedLayout = QtGui.QStackedLayout()
self.stackedFrame = QtGui.QFrame()
self.stackedFrame.setLayout(self.stackedLayout)
self.mainLayout = QtGui.QGridLayout()
self.mainLayout.setSpacing(0)
self.mainLayout.setContentsMargins(0,0,0,0)
self.addBasicTab()
self.addSyncTab()
self.addMessageTab()
self.addPrivacyTab()
self.tabList()
self.mainLayout.addWidget(self.stackedFrame, 0, 1)
self.addBottomLayout()
if self.getMoreState() == False:
self.tabListFrame.hide()
self.nostoreCheckbox.hide()
self.alwaysshowCheckbox.hide()
self.resetButton.hide()
else:
self.showmoreCheckbox.setChecked(True)
self.tabListWidget.setCurrentRow(0)
self.showmoreCheckbox.toggled.connect(self.moreToggled)
self.mainLayout.addStretch(1)
self.setLayout(self.mainLayout) self.setLayout(self.mainLayout)
self.runButton.setFocus() self.runButton.setFocus()
self.setFixedSize(self.sizeHint()) self.setFixedSize(self.sizeHint())
@ -566,7 +755,4 @@ class ConfigDialog(QtGui.QDialog):
if constants.SHOW_TOOLTIPS: if constants.SHOW_TOOLTIPS:
self.processWidget(self, lambda w: self.loadTooltips(w)) self.processWidget(self, lambda w: self.loadTooltips(w))
self.processWidget(self, lambda w: self.loadValues(w)) self.processWidget(self, lambda w: self.loadValues(w))
if self.datacleared == True:
QtGui.QMessageBox.information(self, "Syncplay", getMessage("gui-data-cleared-notification"))

View File

@ -5,13 +5,38 @@ from syncplay.messages import getMessage
import sys import sys
import time import time
import re import re
import os import os
import threading
from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration
class MainWindow(QtGui.QMainWindow): class MainWindow(QtGui.QMainWindow):
def addClient(self, client): def addClient(self, client):
self._syncplayClient = client self._syncplayClient = client
self.roomInput.setText(self._syncplayClient.getRoom()) self.roomInput.setText(self._syncplayClient.getRoom())
self.config = self._syncplayClient.getConfig()
try:
if self.contactLabel and not self.config['showContactInfo']:
self.contactLabel.hide()
if not self.config['showButtonLabels']:
if constants.MERGE_PLAYPAUSE_BUTTONS:
self.playpauseButton.setText("")
else:
self.playButton.setText("")
self.playButton.setFixedWidth(self.playButton.minimumSizeHint().width())
self.pauseButton.setText("")
self.pauseButton.setFixedWidth(self.pauseButton.minimumSizeHint().width())
self.roomButton.setText("")
self.roomButton.setFixedWidth(self.roomButton.minimumSizeHint().width())
self.seekButton.setText("")
self.seekButton.setFixedWidth(self.seekButton.minimumSizeHint().width())
self.unseekButton.setText("")
self.unseekButton.setFixedWidth(self.unseekButton.minimumSizeHint().width())
self.roomGroup.setFixedWidth(self.roomGroup.sizeHint().width())
self.seekGroup.setFixedWidth(self.seekGroup.minimumSizeHint().width())
self.miscGroup.setFixedWidth(self.miscGroup.minimumSizeHint().width())
except ():
pass
def promptFor(self, prompt=">", message=""): def promptFor(self, prompt=">", message=""):
#TODO: Prompt user #TODO: Prompt user
@ -20,7 +45,7 @@ class MainWindow(QtGui.QMainWindow):
def showMessage(self, message, noTimestamp=False): def showMessage(self, message, noTimestamp=False):
message = unicode(message) message = unicode(message)
message = message.replace("&", "&amp;").replace('"', "&quot;").replace("<", "&lt;").replace(">", "&gt;") message = message.replace("&", "&amp;").replace('"', "&quot;").replace("<", "&lt;").replace(">", "&gt;")
message = message.replace("&lt;", "<span style=\"color:#367AA9;font-weight:bold;\">&lt;") message = message.replace("&lt;", "<span style=\"{}\">&lt;".format(constants.STYLE_USERNAME))
message = message.replace("&gt;", "&gt;</span>") message = message.replace("&gt;", "&gt;</span>")
message = message.replace("\n", "<br />") message = message.replace("\n", "<br />")
if noTimestamp: if noTimestamp:
@ -65,11 +90,11 @@ class MainWindow(QtGui.QMainWindow):
elif differentDuration: elif differentDuration:
fileitem = QtGui.QStandardItem(u"{} ({}) ({})".format(user.file['name'], formatTime(user.file['duration']), getMessage("differentduration-note"))) fileitem = QtGui.QStandardItem(u"{} ({}) ({})".format(user.file['name'], formatTime(user.file['duration']), getMessage("differentduration-note")))
if sameRoom and (differentName or differentSize or differentDuration): if sameRoom and (differentName or differentSize or differentDuration):
fileitem.setForeground(QtGui.QBrush(QtGui.QColor('red'))) fileitem.setForeground(QtGui.QBrush(QtGui.QColor(constants.STYLE_DIFFERENTITEM_COLOR)))
else: else:
fileitem = QtGui.QStandardItem(getMessage("nofile-note")) fileitem = QtGui.QStandardItem(getMessage("nofile-note"))
if room == currentUser.room: if room == currentUser.room:
fileitem.setForeground(QtGui.QBrush(QtGui.QColor('blue'))) fileitem.setForeground(QtGui.QBrush(QtGui.QColor(constants.STYLE_NOFILEITEM_COLOR)))
if currentUser.username == user.username: if currentUser.username == user.username:
font = QtGui.QFont() font = QtGui.QFont()
font.setWeight(QtGui.QFont.Bold) font.setWeight(QtGui.QFont.Bold)
@ -102,7 +127,7 @@ class MainWindow(QtGui.QMainWindow):
QtGui.QMessageBox.critical(self,"Syncplay", message) QtGui.QMessageBox.critical(self,"Syncplay", message)
message = message.replace("&", "&amp;").replace('"', "&quot;").replace("<", "&lt;").replace(">", "&gt;") message = message.replace("&", "&amp;").replace('"', "&quot;").replace("<", "&lt;").replace(">", "&gt;")
message = message.replace("\n", "<br />") message = message.replace("\n", "<br />")
message = "<span style=\"color:#FF0000;\">" + message + "</span>" message = "<span style=\"{}\">".format(constants.STYLE_ERRORNOTIFICATION) + message + "</span>"
self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message + "<br />") self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message + "<br />")
def joinRoom(self, room = None): def joinRoom(self, room = None):
@ -230,7 +255,7 @@ class MainWindow(QtGui.QMainWindow):
window.outputLayout = QtGui.QVBoxLayout() window.outputLayout = QtGui.QVBoxLayout()
window.outputbox = QtGui.QTextEdit() window.outputbox = QtGui.QTextEdit()
window.outputbox.setReadOnly(True) window.outputbox.setReadOnly(True)
window.outputlabel = QtGui.QLabel(getMessage("notifications-heading-label")) window.outputlabel = QtGui.QLabel(getMessage("notifications-heading-label"))
window.outputFrame = QtGui.QFrame() window.outputFrame = QtGui.QFrame()
window.outputFrame.setLineWidth(0) window.outputFrame.setLineWidth(0)
@ -252,17 +277,16 @@ class MainWindow(QtGui.QMainWindow):
window.listLayout.setContentsMargins(0,0,0,0) window.listLayout.setContentsMargins(0,0,0,0)
window.listLayout.addWidget(window.listlabel) window.listLayout.addWidget(window.listlabel)
window.listLayout.addWidget(window.listTreeView) window.listLayout.addWidget(window.listTreeView)
if constants.SHOW_CONTACT_INFO: window.contactLabel = QtGui.QLabel()
window.contactLabel = QtGui.QLabel() window.contactLabel.setWordWrap(True)
window.contactLabel.setWordWrap(True) window.contactLabel.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken)
window.contactLabel.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken) window.contactLabel.setLineWidth(1)
window.contactLabel.setLineWidth(1) window.contactLabel.setMidLineWidth(0)
window.contactLabel.setMidLineWidth(0) window.contactLabel.setMargin(2)
window.contactLabel.setMargin(2) window.contactLabel.setText(getMessage("contact-label"))
window.contactLabel.setText(getMessage("contact-label")) window.contactLabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
window.contactLabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse) window.contactLabel.setOpenExternalLinks(True)
window.contactLabel.setOpenExternalLinks(True) window.listLayout.addWidget(window.contactLabel)
window.listLayout.addWidget(window.contactLabel)
window.listFrame.setLayout(window.listLayout) window.listFrame.setLayout(window.listLayout)
window.topSplit.addWidget(window.outputFrame) window.topSplit.addWidget(window.outputFrame)

View File

@ -176,7 +176,9 @@ def sameFilesize (filesize1, filesize2):
return False return False
def sameFileduration (duration1, duration2): def sameFileduration (duration1, duration2):
if abs(round(duration1) - round(duration2)) < constants.DIFFFERENT_DURATION_THRESHOLD: if not constants.SHOW_DURATION_NOTIFICATION:
return True
elif abs(round(duration1) - round(duration2)) < constants.DIFFFERENT_DURATION_THRESHOLD:
return True return True
else: else:
return False return False