diff --git a/syncplay/client.py b/syncplay/client.py index a712390..6a2a5ae 100755 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -533,6 +533,13 @@ class SyncplayClient(object): # TODO: Properly add message for setting trusted domains! # TODO: Handle cases where users add www. to start of domain + def setRoomList(self, newRoomList): + from syncplay.ui.ConfigurationGetter import ConfigurationGetter + ConfigurationGetter().setConfigOption("roomList", newRoomList) + oldRoomList = self._config['roomList'] + if oldRoomList != newRoomList: + self._config['roomList'] = newRoomList + def isUntrustedTrustableURI(self, URIToTest): if utils.isURL(URIToTest): for trustedProtocol in constants.TRUSTABLE_WEB_PROTOCOLS: diff --git a/syncplay/messages_de.py b/syncplay/messages_de.py index fea05f3..0354e46 100755 --- a/syncplay/messages_de.py +++ b/syncplay/messages_de.py @@ -184,6 +184,7 @@ de = { "name-label": "Benutzername (optional):", "password-label": "Server-Passwort (falls nötig):", "room-label": "Standard-Raum:", + "roomlist-msgbox-label": "Edit room list (one per line)", # TODO: Translate "media-setting-title": "Media-Player Einstellungen", "executable-path-label": "Pfad zum Media-Player:", @@ -373,6 +374,8 @@ de = { "password-tooltip": "Passwörter sind nur bei Verbindung zu privaten Servern nötig.", "room-tooltip": "Der Raum, der betreten werden soll, kann ein x-beliebiger sein. Allerdings werden nur Clients im selben Raum synchronisiert.", + "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate + "executable-path-tooltip": "Pfad zum ausgewählten, unterstützten Mediaplayer (mpv, mpv.net, VLC, MPC-HC/BE or mplayer2).", "media-path-tooltip": "Pfad zum wiederzugebenden Video oder Stream. Notwendig für mplayer2.", "player-arguments-tooltip": "Zusätzliche Kommandozeilenparameter/-schalter für diesen Mediaplayer.", diff --git a/syncplay/messages_en.py b/syncplay/messages_en.py index 548f42a..aed1a40 100755 --- a/syncplay/messages_en.py +++ b/syncplay/messages_en.py @@ -184,6 +184,7 @@ en = { "name-label": "Username (optional):", "password-label": "Server password (if any):", "room-label": "Default room: ", + "roomlist-msgbox-label": "Edit room list (one per line)", "media-setting-title": "Media player settings", "executable-path-label": "Path to media player:", @@ -374,6 +375,8 @@ en = { "password-tooltip": "Passwords are only needed for connecting to private servers.", "room-tooltip": "Room to join upon connection can be almost anything, but you will only be synchronised with people in the same room.", + "edit-rooms-tooltip": "Edit room list.", + "executable-path-tooltip": "Location of your chosen supported media player (mpv, mpv.net, VLC, MPC-HC/BE or mplayer2).", "media-path-tooltip": "Location of video or stream to be opened. Necessary for mplayer2.", "player-arguments-tooltip": "Additional command line arguments / switches to pass on to this media player.", diff --git a/syncplay/messages_es.py b/syncplay/messages_es.py index edd2878..e286294 100644 --- a/syncplay/messages_es.py +++ b/syncplay/messages_es.py @@ -184,6 +184,7 @@ es = { "name-label": "Nombre de usuario (opcional):", "password-label": "Contraseña del servidor (si corresponde):", "room-label": "Sala por defecto: ", + "roomlist-msgbox-label": "Edit room list (one per line)", # TODO: Translate "media-setting-title": "Configuración del reproductor multimedia", "executable-path-label": "Ruta al reproductor multimedia:", @@ -374,6 +375,8 @@ es = { "password-tooltip": "Las contraseñas son sólo necesarias para conectarse a servidores privados.", "room-tooltip": "La sala para unirse en la conexión puede ser casi cualquier cosa, pero sólo se sincronizará con las personas en la misma sala.", + "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate + "executable-path-tooltip": "Ubicación de tu reproductor multimedia compatible elegido (mpv, mpv.net, VLC, MPC-HC/BE o mplayer2).", "media-path-tooltip": "Ubicación del video o flujo que se abrirá. Necesario para mplayer2.", "player-arguments-tooltip": "Arguementos de línea de comandos adicionales / parámetros para pasar a este reproductor multimedia.", diff --git a/syncplay/messages_it.py b/syncplay/messages_it.py index 6eae224..9976a63 100755 --- a/syncplay/messages_it.py +++ b/syncplay/messages_it.py @@ -184,6 +184,7 @@ it = { "name-label": "Username (opzionale):", "password-label": "Password del server (se necessaria):", "room-label": "Stanza di default: ", + "roomlist-msgbox-label": "Edit room list (one per line)", # TODO: Translate "media-setting-title": "Impostazioni del media player", "executable-path-label": "Percorso del media player:", @@ -374,6 +375,8 @@ it = { "password-tooltip": "La password è necessaria solo in caso di connessione a server privati.", "room-tooltip": "La stanza in cui entrare dopo la connessione. Può assumere qualsiasi nome, ma ricorda che sarai sincronizzato solo con gli utenti nella stessa stanza.", + "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate + "executable-path-tooltip": "Percorso del media player desiderato (scegliere tra mpv, mpv.net, VLC, MPC-HC/BE or mplayer2).", "media-path-tooltip": "Percorso del video o stream da aprire. Necessario per mplayer2.", "player-arguments-tooltip": "Argomenti da linea di comando aggiuntivi da passare al media player scelto.", diff --git a/syncplay/messages_pt_BR.py b/syncplay/messages_pt_BR.py index 8631499..199be1b 100644 --- a/syncplay/messages_pt_BR.py +++ b/syncplay/messages_pt_BR.py @@ -184,6 +184,7 @@ pt_BR = { "name-label": "Nome de usuário (opcional): ", "password-label": "Senha do servidor (se existir): ", "room-label": "Sala padrão: ", + "roomlist-msgbox-label": "Edit room list (one per line)", # TODO: Translate "media-setting-title": "Configurações do reprodutor de mídia", "executable-path-label": "Executável do reprodutor:", @@ -374,6 +375,8 @@ pt_BR = { "password-tooltip": "Senhas são necessárias apenas para servidores privados.", "room-tooltip": "O nome da sala para se conectar pode ser praticamente qualquer coisa, mas você só irá se sincronizar com pessoas na mesma sala.", + "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate + "executable-path-tooltip": "Localização do seu reprodutor de mídia preferido (mpv, mpv.net, VLC, MPC-HC/BE ou mplayer2).", "media-path-tooltip": "Localização do vídeo ou transmissão a ser aberto. Necessário com o mplayer2.", "player-arguments-tooltip": "Argumentos de comando de linha adicionais para serem repassados ao reprodutor de mídia.", diff --git a/syncplay/messages_pt_PT.py b/syncplay/messages_pt_PT.py index 5c4e10a..1138e76 100644 --- a/syncplay/messages_pt_PT.py +++ b/syncplay/messages_pt_PT.py @@ -184,6 +184,7 @@ pt_PT = { "name-label": "Nome de utilizador (opcional): ", "password-label": "Senha do servidor (se existir): ", "room-label": "Sala padrão: ", + "roomlist-msgbox-label": "Edit room list (one per line)", # TODO: Translate "media-setting-title": "Configurações do reprodutor de mídia", "executable-path-label": "Executável do reprodutor:", @@ -374,6 +375,8 @@ pt_PT = { "password-tooltip": "Senhas são necessárias apenas para servidores privados.", "room-tooltip": "O nome da sala para se conectar pode ser praticamente qualquer coisa, mas você só irá se sincronizar com utilizadores na mesma sala.", + "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate + "executable-path-tooltip": "Localização do seu reprodutor de mídia preferido (mpv, mpv.net, VLC, MPC-HC/BE ou mplayer2).", "media-path-tooltip": "Localização do vídeo ou transmissão a ser aberto. Necessário com o mplayer2.", "player-arguments-tooltip": "Argumentos de comando de linha adicionais para serem repassados ao reprodutor de mídia.", diff --git a/syncplay/messages_ru.py b/syncplay/messages_ru.py index db66581..225c49e 100755 --- a/syncplay/messages_ru.py +++ b/syncplay/messages_ru.py @@ -185,6 +185,7 @@ ru = { "name-label": "Имя пользователя (не обязательно):", "password-label": "Пароль сервера (если требуется):", "room-label": "Комната:", + "roomlist-msgbox-label": "Edit room list (one per line)", # TODO: Translate "media-setting-title": "Воспроизведение", "executable-path-label": "Путь к проигрывателю:", @@ -377,6 +378,8 @@ ru = { "password-tooltip": "Пароли нужны для подключения к приватным серверам.", "room-tooltip": "Комната, в которую Вы попадете сразу после подключения. Синхронизация возможна только между людьми в одной и той же комнате.", + "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate + "executable-path-tooltip": "Расположение Вашего видеопроигрывателя (mpv, mpv.net, VLC, MPC-HC/BE или mplayer2).", "media-path-tooltip": "Расположение видеофайла или потока для просмотра. Обязательно для mplayer2.", # TODO: Confirm translation "player-arguments-tooltip": "Передавать дополнительные аргументы командной строки этому проигрывателю.", diff --git a/syncplay/resources/bullet_edit_centered.png b/syncplay/resources/bullet_edit_centered.png new file mode 100644 index 0000000..99d91fa Binary files /dev/null and b/syncplay/resources/bullet_edit_centered.png differ diff --git a/syncplay/resources/door_open_edit.png b/syncplay/resources/door_open_edit.png new file mode 100644 index 0000000..4a0bdd3 Binary files /dev/null and b/syncplay/resources/door_open_edit.png differ diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py index 876748f..dac9290 100755 --- a/syncplay/ui/ConfigurationGetter.py +++ b/syncplay/ui/ConfigurationGetter.py @@ -29,7 +29,7 @@ class ConfigurationGetter(object): "noGui": False, "noStore": False, "room": "", - "roomhistory": [], + "roomList": [], "password": None, "playerPath": None, "perPlayerArguments": None, @@ -150,7 +150,7 @@ class ConfigurationGetter(object): ] self._serialised = [ - "roomhistory", + "roomList", "perPlayerArguments", "mediaSearchDirectories", "trustedDomains", @@ -183,7 +183,7 @@ class ConfigurationGetter(object): self._iniStructure = { "server_data": ["host", "port", "password"], "client_settings": [ - "name", "room", "roomhistory", "playerPath", + "name", "room", "roomList", "playerPath", "perPlayerArguments", "slowdownThreshold", "rewindThreshold", "fastforwardThreshold", "slowOnDesync", "rewindOnDesync", diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 45879f2..70287eb 100755 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -158,25 +158,27 @@ class ConfigDialog(QtWidgets.QDialog): def openRoomsDialog(self): RoomsDialog = QtWidgets.QDialog() - RoomsDialog.setWindowFlags(Qt.FramelessWindowHint) RoomsLayout = QtWidgets.QGridLayout() RoomsTextbox = QtWidgets.QPlainTextEdit() + RoomsDialog.setWindowTitle(getMessage("roomlist-msgbox-label")) + RoomsPlaylistLabel = QtWidgets.QLabel(getMessage("roomlist-msgbox-label")) RoomsTextbox.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) - RoomsTextbox.setPlainText(utils.getListAsMultilineString(self.config['roomhistory'])) - RoomsLayout.addWidget(RoomsTextbox, 0, 0, 1, 1) + RoomsTextbox.setPlainText(utils.getListAsMultilineString(self.config['roomList'])) + RoomsLayout.addWidget(RoomsPlaylistLabel, 0, 0, 1, 1) + RoomsLayout.addWidget(RoomsTextbox, 1, 0, 1, 1) RoomsButtonBox = QtWidgets.QDialogButtonBox() RoomsButtonBox.setOrientation(Qt.Horizontal) RoomsButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel) RoomsButtonBox.accepted.connect(RoomsDialog.accept) RoomsButtonBox.rejected.connect(RoomsDialog.reject) - RoomsLayout.addWidget(RoomsButtonBox, 1, 0, 1, 1) + RoomsLayout.addWidget(RoomsButtonBox, 2, 0, 1, 1) RoomsDialog.setLayout(RoomsLayout) RoomsDialog.setModal(True) RoomsDialog.show() result = RoomsDialog.exec_() if result == QtWidgets.QDialog.Accepted: newRooms = utils.convertMultilineStringToList(RoomsTextbox.toPlainText()) - self.relistRoomHistory(newRooms) + self.relistRoomList(newRooms) def safenormcaseandpath(self, path): if utils.isURL(path): @@ -403,25 +405,27 @@ class ConfigDialog(QtWidgets.QDialog): self.hostCombobox.setEditText(currentServer) def fillRoomsCombobox(self): + previousRoomSelection = self.roomsCombobox.currentText() self.roomsCombobox.clear() - for roomHistoryValue in self.config['roomhistory']: - self.roomsCombobox.addItem(roomHistoryValue) + for roomListValue in self.config['roomList']: + self.roomsCombobox.addItem(roomListValue) + self.roomsCombobox.setEditText(previousRoomSelection) - def relistRoomHistory(self, newRooms): + def relistRoomList(self, newRooms): filteredNewRooms = [room for room in newRooms if room and not room.isspace()] - self.config['roomhistory'] = filteredNewRooms + self.config['roomList'] = filteredNewRooms self.fillRoomsCombobox() - def addRoomToHistory(self, newRoom=None): + def addRoomToList(self, newRoom=None): if newRoom is None: newRoom = self.roomsCombobox.currentText() if not newRoom: return - roomHistory = self.config['roomhistory'] - if newRoom in roomHistory: - roomHistory.remove(newRoom) - roomHistory.insert(0, newRoom) - self.config['roomhistory'] = roomHistory + roomList = self.config['roomList'] + if newRoom in roomList: + roomList.remove(newRoom) + roomList.insert(0, newRoom) + self.config['roomList'] = roomList def showErrorMessage(self, errorMessage): QtWidgets.QMessageBox.warning(self, "Syncplay", errorMessage) @@ -645,14 +649,16 @@ class ConfigDialog(QtWidgets.QDialog): self.serverpassLabel = QLabel(getMessage("password-label"), self) self.roomsCombobox = QtWidgets.QComboBox(self) self.roomsCombobox.setEditable(True) - self.addRoomToHistory(config['room']) + # self.addRoomToHistory(config['room']) - TO DO: Make this optional self.fillRoomsCombobox() + self.roomsCombobox.setEditText(config['room']) self.usernameLabel = QLabel(getMessage("name-label"), self) self.serverpassTextbox = QLineEdit(self) self.serverpassTextbox.setText(self.storedPassword) self.defaultroomLabel = QLabel(getMessage("room-label"), self) self.editRoomsButton = QtWidgets.QToolButton() - self.editRoomsButton.setIcon(QtGui.QIcon(resourcespath + 'eye.png')) + self.editRoomsButton.setIcon(QtGui.QIcon(resourcespath + 'bullet_edit_centered.png')) + self.editRoomsButton.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "edit-rooms") self.editRoomsButton.released.connect(self.openRoomsDialog) self.hostLabel.setObjectName("host") @@ -674,7 +680,7 @@ class ConfigDialog(QtWidgets.QDialog): 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.editRoomsButton, 3, 0, Qt.AlignRight) + self.connectionSettingsLayout.addWidget(self.editRoomsButton, 3, 2, Qt.AlignRight) self.connectionSettingsLayout.addWidget(self.roomsCombobox, 3, 1) self.connectionSettingsLayout.setSpacing(10) self.connectionSettingsGroup.setLayout(self.connectionSettingsLayout) diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py index 5dfec61..ec3d30a 100755 --- a/syncplay/ui/gui.py +++ b/syncplay/ui/gui.py @@ -244,6 +244,7 @@ class MainWindow(QtWidgets.QMainWindow): sslInformation = "N/A" sslMode = False + def setPlaylistInsertPosition(self, newPosition): if not self.playlist.isEnabled(): return @@ -459,12 +460,21 @@ class MainWindow(QtWidgets.QMainWindow): return f(self, *args, **kwds) return wrapper + def fillRoomsCombobox(self): + previousRoomSelection = self.roomsCombobox.currentText() + self.roomsCombobox.clear() + for roomListValue in self.config['roomList']: + self.roomsCombobox.addItem(roomListValue) + self.roomsCombobox.setEditText(previousRoomSelection) + + def addClient(self, client): self._syncplayClient = client if self.console: self.console.addClient(client) - self.roomInput.setText(self._syncplayClient.getRoom()) self.config = self._syncplayClient.getConfig() + self.roomsCombobox.setEditText(self._syncplayClient.getRoom()) + self.fillRoomsCombobox() try: self.playlistGroup.blockSignals(True) self.playlistGroup.setChecked(self.config['sharedPlaylistEnabled']) @@ -502,7 +512,7 @@ class MainWindow(QtWidgets.QMainWindow): if not featureList["sharedPlaylists"]: self.playlistGroup.setEnabled(False) self.chatInput.setMaxLength(constants.MAX_CHAT_MESSAGE_LENGTH) - self.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH) + #self.roomsCombobox.setMaxLength(constants.MAX_ROOM_NAME_LENGTH) def setSSLMode(self, sslMode, sslInformation): self.sslMode = sslMode @@ -868,7 +878,7 @@ class MainWindow(QtWidgets.QMainWindow): self.playlist.updatePlaylistIndexIcon() def updateRoomName(self, room=""): - self.roomInput.setText(room) + self.roomsCombobox.setEditText(room) def showDebugMessage(self, message): print(message) @@ -889,13 +899,13 @@ class MainWindow(QtWidgets.QMainWindow): @needsClient def joinRoom(self, room=None): if room is None: - room = self.roomInput.text() + room = self.roomsCombobox.currentText() if room == "": if self._syncplayClient.userlist.currentUser.file: room = self._syncplayClient.userlist.currentUser.file["name"] else: room = self._syncplayClient.defaultRoom - self.roomInput.setText(room) + self.roomsCombobox.setEditText(room) if room != self._syncplayClient.getRoom(): self._syncplayClient.setRoom(room, resetAutoplay=True) self._syncplayClient.sendRoom() @@ -1121,6 +1131,36 @@ class MainWindow(QtWidgets.QMainWindow): self.addStreamToPlaylist(URI) self.updatingPlaylist = False + def openEditRoomsDialog(self): + RoomsDialog = QtWidgets.QDialog() + RoomsLayout = QtWidgets.QGridLayout() + RoomsTextbox = QtWidgets.QPlainTextEdit() + RoomsDialog.setWindowTitle(getMessage("roomlist-msgbox-label")) + RoomsPlaylistLabel = QtWidgets.QLabel(getMessage("roomlist-msgbox-label")) + RoomsTextbox.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) + RoomsTextbox.setPlainText(utils.getListAsMultilineString(self.config['roomList'])) + RoomsLayout.addWidget(RoomsPlaylistLabel, 0, 0, 1, 1) + RoomsLayout.addWidget(RoomsTextbox, 1, 0, 1, 1) + RoomsButtonBox = QtWidgets.QDialogButtonBox() + RoomsButtonBox.setOrientation(Qt.Horizontal) + RoomsButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel) + RoomsButtonBox.accepted.connect(RoomsDialog.accept) + RoomsButtonBox.rejected.connect(RoomsDialog.reject) + RoomsLayout.addWidget(RoomsButtonBox, 2, 0, 1, 1) + RoomsDialog.setLayout(RoomsLayout) + RoomsDialog.setModal(True) + RoomsDialog.show() + result = RoomsDialog.exec_() + if result == QtWidgets.QDialog.Accepted: + newRooms = utils.convertMultilineStringToList(RoomsTextbox.toPlainText()) + self.relistRoomList(newRooms) + self._syncplayClient.setRoomList(newRooms) + + def relistRoomList(self, newRooms): + filteredNewRooms = [room for room in newRooms if room and not room.isspace()] + self.config['roomList'] = filteredNewRooms + self.fillRoomsCombobox() + @needsClient def openEditPlaylistDialog(self): oldPlaylist = utils.getListAsMultilineString(self.getPlaylistState()) @@ -1422,14 +1462,14 @@ class MainWindow(QtWidgets.QMainWindow): window.listSplit = QtWidgets.QSplitter(Qt.Vertical, self) window.listSplit.addWidget(window.userlistFrame) window.listLayout.addWidget(window.listSplit) - - window.roomInput = QtWidgets.QLineEdit() - window.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH) - window.roomInput.returnPressed.connect(self.joinRoom) + window.roomsCombobox = QtWidgets.QComboBox(self) + window.roomsCombobox.setEditable(True) + #window.roomsCombobox.setMaxLength(constants.MAX_ROOM_NAME_LENGTH) window.roomButton = QtWidgets.QPushButton( QtGui.QPixmap(resourcespath + 'door_in.png'), getMessage("joinroom-label")) window.roomButton.pressed.connect(self.joinRoom) + window.roomButton.setFixedWidth(window.roomButton.sizeHint().width()) window.roomLayout = QtWidgets.QHBoxLayout() window.roomFrame = QtWidgets.QFrame() window.roomFrame.setLayout(self.roomLayout) @@ -1441,7 +1481,7 @@ class MainWindow(QtWidgets.QMainWindow): window.roomFrame.setContentsMargins(0, 0, 0, 0) window.roomLayout.setContentsMargins(0, 0, 0, 0) self.roomButton.setToolTip(getMessage("joinroom-tooltip")) - window.roomLayout.addWidget(window.roomInput) + window.roomLayout.addWidget(window.roomsCombobox) window.roomLayout.addWidget(window.roomButton) window.roomFrame.setMaximumHeight(window.roomFrame.sizeHint().height()) window.listLayout.addWidget(window.roomFrame, Qt.AlignRight) @@ -1673,6 +1713,9 @@ class MainWindow(QtWidgets.QMainWindow): window.autoplayAction = window.windowMenu.addAction(getMessage("autoplay-menu-label")) window.autoplayAction.setCheckable(True) window.autoplayAction.triggered.connect(self.updateAutoplayVisibility) + + window.editroomsAction = window.windowMenu.addAction(QtGui.QPixmap(resourcespath + 'door_open_edit.png'), getMessage("roomlist-msgbox-label")) + window.editroomsAction.triggered.connect(self.openEditRoomsDialog) window.menuBar.addMenu(window.windowMenu) # Help menu