From 89b4df7a4adff7c45fc6bc8d648dd0e52b6ded1d Mon Sep 17 00:00:00 2001 From: alby128 Date: Thu, 7 Sep 2017 19:37:03 +0200 Subject: [PATCH] Ported GUI to PySide 2 --- buildPy2app.py | 32 ++ resources/icon.icns | Bin 0 -> 138875 bytes syncplay/ui/ConfigurationGetter.py | 12 +- syncplay/ui/GuiConfiguration.py | 180 +++++----- syncplay/ui/gui.py | 340 +++++++++--------- syncplay/utils.py | 2 + .../vendor/{qt4reactor.py => qt5reactor.py} | 265 ++++++++------ 7 files changed, 456 insertions(+), 375 deletions(-) create mode 100644 buildPy2app.py create mode 100644 resources/icon.icns rename syncplay/vendor/{qt4reactor.py => qt5reactor.py} (60%) diff --git a/buildPy2app.py b/buildPy2app.py new file mode 100644 index 0000000..5cc8ccb --- /dev/null +++ b/buildPy2app.py @@ -0,0 +1,32 @@ +""" +This is a setup.py script generated by py2applet + +Usage: + python setup.py py2app +""" + +from setuptools import setup +from glob import glob +import syncplay + +APP = ['syncplayClient.py'] +DATA_FILES = [ + ('resources', glob('resources/*.png')), +] +OPTIONS = { + 'iconfile':'resources/icon.icns', + 'plist': { + 'CFBundleName':'Syncplay', + 'CFBundleShortVersionString':syncplay.version, + 'CFBundleIdentifier':'pl.syncplay.Syncplay', + 'NSHumanReadableCopyright': '@ 2017 Syncplay All Rights Reserved' + } +} + +setup( + app=APP, + name='Syncplay', + data_files=DATA_FILES, + options={'py2app': OPTIONS}, + setup_requires=['py2app'], +) diff --git a/resources/icon.icns b/resources/icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..10fb7665bd2b8798ef31bf0a9ce50d9050d8e265 GIT binary patch literal 138875 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óXRII{ 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 literal 0 HcmV?d00001 diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py index c45c6cc..222a764 100755 --- a/syncplay/ui/ConfigurationGetter.py +++ b/syncplay/ui/ConfigurationGetter.py @@ -401,15 +401,15 @@ class ConfigurationGetter(object): self._overrideConfigWithArgs(args) if not self._config['noGui']: try: - from PySide import QtGui # @UnresolvedImport - from PySide.QtCore import QCoreApplication - from syncplay.vendor import qt4reactor + from PySide2 import QtWidgets + from PySide2.QtCore import QCoreApplication + from syncplay.vendor import qt5reactor if QCoreApplication.instance() is None: - self.app = QtGui.QApplication(sys.argv) - qt4reactor.install() + self.app = QtWidgets.QApplication(sys.argv) + qt5reactor.install() if sys.platform.startswith('darwin'): import appnope - appnope.nope() + appnope.nope() except ImportError: print getMessage("unable-import-gui-error") self._config['noGui'] = True diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index d8e832a..47a2412 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -1,6 +1,7 @@ -from PySide import QtCore, QtGui -from PySide.QtCore import QSettings, Qt, QCoreApplication, QUrl -from PySide.QtGui import QApplication, QLineEdit, QCursor, QLabel, QCheckBox, QDesktopServices, QIcon, QImage, QButtonGroup, QRadioButton, QDoubleSpinBox, QPlainTextEdit +from PySide2 import QtCore, QtWidgets, QtGui +from PySide2.QtCore import Qt, QSettings, QCoreApplication, QSize, QPoint, QUrl, QLine +from PySide2.QtWidgets import QApplication, QLineEdit, QLabel, QCheckBox, QButtonGroup, QRadioButton, QDoubleSpinBox, QPlainTextEdit +from PySide2.QtGui import QCursor, QIcon, QImage, QDesktopServices from syncplay.players.playerFactory import PlayerFactory from datetime import datetime from syncplay import utils @@ -19,7 +20,7 @@ class GuiConfiguration: def run(self): if QCoreApplication.instance() is None: - self.app = QtGui.QApplication(sys.argv) + self.app = QtWidgets.QApplication(sys.argv) dialog = ConfigDialog(self.config, self._availablePlayerPaths, self.error, self.defaultConfig) dialog.exec_() @@ -65,22 +66,22 @@ class GetPlayerIconThread(threading.Thread, QtCore.QObject): self.done.emit(iconpath, playerpath) -class ConfigDialog(QtGui.QDialog): +class ConfigDialog(QtWidgets.QDialog): pressedclosebutton = True moreToggling = False def automaticUpdatePromptCheck(self): if self.automaticupdatesCheckbox.checkState() == Qt.PartiallyChecked: - reply = QtGui.QMessageBox.question(self, "Syncplay", - getMessage("promptforupdate-label"), QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.No) - if reply == QtGui.QMessageBox.Yes: + reply = QtWidgets.QMessageBox.question(self, "Syncplay", + getMessage("promptforupdate-label"), QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No) + if reply == QtWidgets.QMessageBox.Yes: self.automaticupdatesCheckbox.setChecked(True) else: self.automaticupdatesCheckbox.setChecked(False) def moreToggled(self): - self.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) + self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) if self.moreToggling == False: self.moreToggling = True @@ -113,7 +114,7 @@ class ConfigDialog(QtGui.QDialog): self.executablepathCombobox.setFixedWidth(self.mediapathTextbox.width()) def openHelp(self): - self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/client/")) + self.QtWidgets.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/client/")) def safenormcaseandpath(self, path): if utils.isURL(path): @@ -210,10 +211,10 @@ class ConfigDialog(QtGui.QDialog): def languageChanged(self): setLanguage(unicode(self.languageCombobox.itemData(self.languageCombobox.currentIndex()))) - QtGui.QMessageBox.information(self, "Syncplay", getMessage("language-changed-msgbox-label")) + QtWidgets.QMessageBox.information(self, "Syncplay", getMessage("language-changed-msgbox-label")) def browsePlayerpath(self): - options = QtGui.QFileDialog.Options() + options = QtWidgets.QFileDialog.Options() defaultdirectory = "" browserfilter = "All files (*)" @@ -232,7 +233,7 @@ class ConfigDialog(QtGui.QDialog): elif "bsd" in sys.platform or sys.platform.startswith('dragonfly'): defaultdirectory = "/usr/local/bin" - fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, + fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self, "Browse for media player executable", defaultdirectory, browserfilter, "", options) @@ -336,11 +337,11 @@ class ConfigDialog(QtGui.QDialog): self.hostCombobox.setEditText(currentServer) def showErrorMessage(self, errorMessage): - QtGui.QMessageBox.warning(self, "Syncplay", errorMessage) + QtWidgets.QMessageBox.warning(self, "Syncplay", errorMessage) def browseMediapath(self): self.loadMediaBrowseSettings() - options = QtGui.QFileDialog.Options() + options = QtWidgets.QFileDialog.Options() if self.config["mediaSearchDirectories"] and os.path.isdir(self.config["mediaSearchDirectories"][0]): defaultdirectory = self.config["mediaSearchDirectories"][0] elif os.path.isdir(self.mediadirectory): @@ -352,7 +353,7 @@ class ConfigDialog(QtGui.QDialog): else: defaultdirectory = "" browserfilter = "All files (*)" - fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media files", defaultdirectory, + fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self, "Browse for media files", defaultdirectory, browserfilter, "", options) if fileName: self.mediapathTextbox.setText(os.path.normpath(fileName)) @@ -508,9 +509,9 @@ class ConfigDialog(QtGui.QDialog): self.mediaSearchDirectories = self.config["mediaSearchDirectories"] self.trustedDomains = self.config["trustedDomains"] - self.connectionSettingsGroup = QtGui.QGroupBox(getMessage("connection-group-title")) + self.connectionSettingsGroup = QtWidgets.QGroupBox(getMessage("connection-group-title")) self.loadSavedPublicServerList() - self.hostCombobox = QtGui.QComboBox(self) + self.hostCombobox = QtWidgets.QComboBox(self) if self.publicServers: i = 0 for publicServer in self.publicServers: @@ -521,7 +522,7 @@ class ConfigDialog(QtGui.QDialog): self.hostCombobox.setEditText(host) self.hostCombobox.setFixedWidth(165) self.hostLabel = QLabel(getMessage("host-label"), self) - self.findServerButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'arrow_refresh.png'), getMessage("update-server-list-label")) + self.findServerButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'arrow_refresh.png'), getMessage("update-server-list-label")) self.findServerButton.clicked.connect(self.updateServerList) self.findServerButton.setToolTip(getMessage("update-server-list-tooltip")) self.usernameTextbox = QLineEdit(self) @@ -545,7 +546,7 @@ class ConfigDialog(QtGui.QDialog): self.usernameTextbox.setMaxLength(constants.MAX_USERNAME_LENGTH) self.defaultroomTextbox.setMaxLength(constants.MAX_ROOM_NAME_LENGTH) - self.connectionSettingsLayout = QtGui.QGridLayout() + self.connectionSettingsLayout = QtWidgets.QGridLayout() self.connectionSettingsLayout.addWidget(self.hostLabel, 0, 0) self.connectionSettingsLayout.addWidget(self.hostCombobox, 0, 1) self.connectionSettingsLayout.addWidget(self.findServerButton, 0, 2) @@ -562,11 +563,11 @@ class ConfigDialog(QtGui.QDialog): self.playerargsTextbox.textEdited.connect(self.changedPlayerArgs) self.playerargsLabel = QLabel(getMessage("player-arguments-label"), self) - self.mediaplayerSettingsGroup = QtGui.QGroupBox(getMessage("media-setting-title")) + self.mediaplayerSettingsGroup = QtWidgets.QGroupBox(getMessage("media-setting-title")) self.executableiconImage = QtGui.QImage() self.executableiconLabel = QLabel(self) self.executableiconLabel.setMinimumWidth(16) - self.executablepathCombobox = QtGui.QComboBox(self) + self.executablepathCombobox = QtWidgets.QComboBox(self) self.executablepathCombobox.setEditable(True) self.executablepathCombobox.currentIndexChanged.connect(self.updateExecutableIcon) self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'], playerpaths)) @@ -574,11 +575,11 @@ class ConfigDialog(QtGui.QDialog): self.executablepathCombobox.editTextChanged.connect(self.updateExecutableIcon) self.executablepathLabel = QLabel(getMessage("executable-path-label"), self) - self.executablebrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("browse-label")) + self.executablebrowseButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("browse-label")) self.executablebrowseButton.clicked.connect(self.browsePlayerpath) self.mediapathTextbox = QLineEdit(config['file'], self) self.mediapathLabel = QLabel(getMessage("media-path-label"), self) - self.mediabrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("browse-label")) + self.mediabrowseButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("browse-label")) self.mediabrowseButton.clicked.connect(self.browseMediapath) self.executablepathLabel.setObjectName("executable-path") @@ -588,7 +589,7 @@ class ConfigDialog(QtGui.QDialog): self.playerargsLabel.setObjectName("player-arguments") self.playerargsTextbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "player-arguments") - self.mediaplayerSettingsLayout = QtGui.QGridLayout() + self.mediaplayerSettingsLayout = QtWidgets.QGridLayout() self.mediaplayerSettingsLayout.addWidget(self.executablepathLabel, 0, 0) self.mediaplayerSettingsLayout.addWidget(self.executableiconLabel, 0, 1) self.mediaplayerSettingsLayout.addWidget(self.executablepathCombobox, 0, 2) @@ -603,8 +604,8 @@ class ConfigDialog(QtGui.QDialog): self.showmoreCheckbox = QCheckBox(getMessage("more-title")) self.showmoreCheckbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "more") - self.basicOptionsFrame = QtGui.QFrame() - self.basicOptionsLayout = QtGui.QVBoxLayout() + self.basicOptionsFrame = QtWidgets.QFrame() + self.basicOptionsLayout = QtWidgets.QVBoxLayout() if error: self.errorLabel = QLabel(self) if error[:1] != constants.ERROR_MESSAGE_MARKER: @@ -620,19 +621,19 @@ class ConfigDialog(QtGui.QDialog): self.basicOptionsLayout.addWidget(self.connectionSettingsGroup) self.basicOptionsLayout.addSpacing(5) self.basicOptionsLayout.addWidget(self.mediaplayerSettingsGroup) - self.basicOptionsFrame.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) + self.basicOptionsFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) self.basicOptionsFrame.setLayout(self.basicOptionsLayout) self.stackedLayout.addWidget(self.basicOptionsFrame) def addReadinessTab(self): - self.readyFrame = QtGui.QFrame() - self.readyLayout = QtGui.QVBoxLayout() + self.readyFrame = QtWidgets.QFrame() + self.readyLayout = QtWidgets.QVBoxLayout() self.readyFrame.setLayout(self.readyLayout) # Initial state - self.readyInitialGroup = QtGui.QGroupBox(getMessage("readiness-title")) - self.readyInitialLayout = QtGui.QVBoxLayout() + self.readyInitialGroup = QtWidgets.QGroupBox(getMessage("readiness-title")) + self.readyInitialLayout = QtWidgets.QVBoxLayout() self.readyInitialGroup.setLayout(self.readyInitialLayout) self.readyatstartCheckbox = QCheckBox(getMessage("readyatstart-label")) self.readyatstartCheckbox.setObjectName("readyAtStart") @@ -640,8 +641,8 @@ class ConfigDialog(QtGui.QDialog): self.readyLayout.addWidget(self.readyInitialGroup) # Automatically pausing - self.readyPauseGroup = QtGui.QGroupBox(getMessage("pausing-title")) - self.readyPauseLayout = QtGui.QVBoxLayout() + self.readyPauseGroup = QtWidgets.QGroupBox(getMessage("pausing-title")) + self.readyPauseLayout = QtWidgets.QVBoxLayout() self.readyPauseGroup.setLayout(self.readyPauseLayout) self.pauseonleaveCheckbox = QCheckBox(getMessage("pauseonleave-label")) self.pauseonleaveCheckbox.setObjectName("pauseOnLeave") @@ -649,8 +650,8 @@ class ConfigDialog(QtGui.QDialog): self.readyLayout.addWidget(self.readyPauseGroup) # Unpausing - self.readyUnpauseGroup = QtGui.QGroupBox(getMessage("unpause-title")) - self.readyUnpauseLayout = QtGui.QVBoxLayout() + self.readyUnpauseGroup = QtWidgets.QGroupBox(getMessage("unpause-title")) + self.readyUnpauseLayout = QtWidgets.QVBoxLayout() self.readyUnpauseGroup.setLayout(self.readyUnpauseLayout) self.readyUnpauseButtonGroup = QButtonGroup() self.unpauseIfAlreadyReadyOption = QRadioButton(getMessage("unpause-ifalreadyready-option")) @@ -679,12 +680,12 @@ class ConfigDialog(QtGui.QDialog): self.stackedLayout.addWidget(self.readyFrame) def addMiscTab(self): - self.miscFrame = QtGui.QFrame() - self.miscLayout = QtGui.QVBoxLayout() + self.miscFrame = QtWidgets.QFrame() + self.miscLayout = QtWidgets.QVBoxLayout() self.miscFrame.setLayout(self.miscLayout) - self.coreSettingsGroup = QtGui.QGroupBox(getMessage("core-behaviour-title")) - self.coreSettingsLayout = QtGui.QGridLayout() + self.coreSettingsGroup = QtWidgets.QGroupBox(getMessage("core-behaviour-title")) + self.coreSettingsLayout = QtWidgets.QGridLayout() self.coreSettingsGroup.setLayout(self.coreSettingsLayout) ### Privacy: @@ -727,8 +728,8 @@ class ConfigDialog(QtGui.QDialog): ## Syncplay internals - self.internalSettingsGroup = QtGui.QGroupBox(getMessage("syncplay-internals-title")) - self.internalSettingsLayout = QtGui.QVBoxLayout() + self.internalSettingsGroup = QtWidgets.QGroupBox(getMessage("syncplay-internals-title")) + self.internalSettingsLayout = QtWidgets.QVBoxLayout() self.internalSettingsGroup.setLayout(self.internalSettingsLayout) self.alwaysshowCheckbox = QCheckBox(getMessage("forceguiprompt-label")) @@ -741,13 +742,13 @@ class ConfigDialog(QtGui.QDialog): ## Media path directories - self.mediasearchSettingsGroup = QtGui.QGroupBox(getMessage("syncplay-mediasearchdirectories-title")) - self.mediasearchSettingsLayout = QtGui.QVBoxLayout() + self.mediasearchSettingsGroup = QtWidgets.QGroupBox(getMessage("syncplay-mediasearchdirectories-title")) + self.mediasearchSettingsLayout = QtWidgets.QVBoxLayout() self.mediasearchSettingsGroup.setLayout(self.mediasearchSettingsLayout) self.mediasearchTextEdit = QPlainTextEdit(utils.getListAsMultilineString(self.mediaSearchDirectories)) self.mediasearchTextEdit.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "mediasearcdirectories-arguments") - self.mediasearchTextEdit.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) + self.mediasearchTextEdit.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) self.mediasearchSettingsLayout.addWidget(self.mediasearchTextEdit) self.mediasearchSettingsGroup.setMaximumHeight(self.mediasearchSettingsGroup.minimumSizeHint().height()) @@ -758,12 +759,12 @@ class ConfigDialog(QtGui.QDialog): self.stackedLayout.addWidget(self.miscFrame) def addSyncTab(self): - self.syncSettingsFrame = QtGui.QFrame() - self.syncSettingsLayout = QtGui.QVBoxLayout() + self.syncSettingsFrame = QtWidgets.QFrame() + self.syncSettingsLayout = QtWidgets.QVBoxLayout() - self.desyncSettingsGroup = QtGui.QGroupBox(getMessage("sync-otherslagging-title")) - self.desyncOptionsFrame = QtGui.QFrame() - self.desyncSettingsOptionsLayout = QtGui.QHBoxLayout() + self.desyncSettingsGroup = QtWidgets.QGroupBox(getMessage("sync-otherslagging-title")) + self.desyncOptionsFrame = QtWidgets.QFrame() + self.desyncSettingsOptionsLayout = QtWidgets.QHBoxLayout() config = self.config self.slowdownCheckbox = QCheckBox(getMessage("slowondesync-label")) @@ -773,9 +774,9 @@ class ConfigDialog(QtGui.QDialog): self.fastforwardCheckbox = QCheckBox(getMessage("fastforwardondesync-label")) self.fastforwardCheckbox.setObjectName("fastforwardOnDesync") - self.desyncSettingsLayout = QtGui.QGridLayout() + self.desyncSettingsLayout = QtWidgets.QGridLayout() self.desyncSettingsLayout.setSpacing(2) - self.desyncFrame = QtGui.QFrame() + self.desyncFrame = QtWidgets.QFrame() self.desyncFrame.setLineWidth(0) self.desyncFrame.setMidLineWidth(0) @@ -788,9 +789,9 @@ class ConfigDialog(QtGui.QDialog): self.desyncFrame.setLayout(self.syncSettingsLayout) - self.othersyncSettingsGroup = QtGui.QGroupBox(getMessage("sync-youlaggging-title")) - self.othersyncOptionsFrame = QtGui.QFrame() - self.othersyncSettingsLayout = QtGui.QGridLayout() + self.othersyncSettingsGroup = QtWidgets.QGroupBox(getMessage("sync-youlaggging-title")) + self.othersyncOptionsFrame = QtWidgets.QFrame() + self.othersyncSettingsLayout = QtWidgets.QGridLayout() self.dontslowwithmeCheckbox = QCheckBox(getMessage("dontslowdownwithme-label")) self.dontslowwithmeCheckbox.setObjectName("dontSlowDownWithMe") @@ -803,13 +804,13 @@ class ConfigDialog(QtGui.QDialog): ## Trusted domains - self.trusteddomainsSettingsGroup = QtGui.QGroupBox(getMessage("syncplay-trusteddomains-title")) - self.trusteddomainsSettingsLayout = QtGui.QVBoxLayout() + self.trusteddomainsSettingsGroup = QtWidgets.QGroupBox(getMessage("syncplay-trusteddomains-title")) + self.trusteddomainsSettingsLayout = QtWidgets.QVBoxLayout() self.trusteddomainsSettingsGroup.setLayout(self.trusteddomainsSettingsLayout) self.trusteddomainsTextEdit = QPlainTextEdit(utils.getListAsMultilineString(self.trustedDomains)) self.trusteddomainsTextEdit.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "trusteddomains-arguments") - self.trusteddomainsTextEdit.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) + self.trusteddomainsTextEdit.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) self.trusteddomainsSettingsLayout.addWidget(self.trusteddomainsTextEdit) self.trusteddomainsSettingsGroup.setMaximumHeight(self.trusteddomainsSettingsGroup.minimumSizeHint().height()) @@ -824,14 +825,14 @@ class ConfigDialog(QtGui.QDialog): self.stackedLayout.addWidget(self.syncSettingsFrame) def addMessageTab(self): - self.messageFrame = QtGui.QFrame() - self.messageLayout = QtGui.QVBoxLayout() + self.messageFrame = QtWidgets.QFrame() + self.messageLayout = QtWidgets.QVBoxLayout() self.messageLayout.setAlignment(Qt.AlignTop) # OSD - self.osdSettingsGroup = QtGui.QGroupBox(getMessage("messages-osd-title")) - self.osdSettingsLayout = QtGui.QVBoxLayout() - self.osdSettingsFrame = QtGui.QFrame() + self.osdSettingsGroup = QtWidgets.QGroupBox(getMessage("messages-osd-title")) + self.osdSettingsLayout = QtWidgets.QVBoxLayout() + self.osdSettingsFrame = QtWidgets.QFrame() self.showOSDCheckbox = QCheckBox(getMessage("showosd-label")) self.showOSDCheckbox.setObjectName("showOSD") @@ -871,23 +872,23 @@ class ConfigDialog(QtGui.QDialog): # Other display - self.displaySettingsGroup = QtGui.QGroupBox(getMessage("messages-other-title")) - self.displaySettingsLayout = QtGui.QVBoxLayout() + self.displaySettingsGroup = QtWidgets.QGroupBox(getMessage("messages-other-title")) + self.displaySettingsLayout = QtWidgets.QVBoxLayout() self.displaySettingsLayout.setAlignment(Qt.AlignTop & Qt.AlignLeft) - self.displaySettingsFrame = QtGui.QFrame() + self.displaySettingsFrame = QtWidgets.QFrame() self.showDurationNotificationCheckbox = QCheckBox(getMessage("showdurationnotification-label")) self.showDurationNotificationCheckbox.setObjectName("showDurationNotification") self.displaySettingsLayout.addWidget(self.showDurationNotificationCheckbox) - self.languageFrame = QtGui.QFrame() - self.languageLayout = QtGui.QHBoxLayout() + self.languageFrame = QtWidgets.QFrame() + self.languageLayout = QtWidgets.QHBoxLayout() self.languageLayout.setContentsMargins(0, 0, 0, 0) self.languageFrame.setLayout(self.languageLayout) - self.languageFrame.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) + self.languageFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) self.languageLayout.setAlignment(Qt.AlignTop & Qt.AlignLeft) self.languageLabel = QLabel(getMessage("language-label"), self) - self.languageCombobox = QtGui.QComboBox(self) + self.languageCombobox = QtWidgets.QComboBox(self) self.languageCombobox.addItem(getMessage("automatic-language").format(getMessage("LANGUAGE", getInitialLanguage()))) self.languages = getLanguages() @@ -917,22 +918,22 @@ class ConfigDialog(QtGui.QDialog): config = self.config resourcespath = self.resourcespath - self.bottomButtonFrame = QtGui.QFrame() - self.bottomButtonLayout = QtGui.QHBoxLayout() - self.helpButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + u'help.png'), getMessage("help-label")) + self.bottomButtonFrame = QtWidgets.QFrame() + self.bottomButtonLayout = QtWidgets.QHBoxLayout() + self.helpButton = QtWidgets.QPushButton(QtGui.QIcon(self.resourcespath + u'help.png'), getMessage("help-label")) self.helpButton.setObjectName("help") self.helpButton.setMaximumSize(self.helpButton.sizeHint()) self.helpButton.pressed.connect(self.openHelp) - self.resetButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + u'cog_delete.png'),getMessage("reset-label")) + self.resetButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'cog_delete.png'),getMessage("reset-label")) self.resetButton.setMaximumSize(self.resetButton.sizeHint()) self.resetButton.setObjectName("reset") self.resetButton.pressed.connect(self.resetSettings) - self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("run-label")) + self.runButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("run-label")) self.runButton.pressed.connect(self._runWithoutStoringConfig) self.runButton.setToolTip(getMessage("nostore-tooltip")) - self.storeAndRunButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("storeandrun-label")) + self.storeAndRunButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("storeandrun-label")) self.storeAndRunButton.pressed.connect(self._saveDataAndLeave) self.bottomButtonLayout.addWidget(self.helpButton) self.bottomButtonLayout.addWidget(self.resetButton) @@ -942,9 +943,9 @@ class ConfigDialog(QtGui.QDialog): self.bottomButtonLayout.setContentsMargins(5,0,5,0) self.mainLayout.addWidget(self.bottomButtonFrame, 1, 0, 1, 2) - self.bottomCheckboxFrame = QtGui.QFrame() + self.bottomCheckboxFrame = QtWidgets.QFrame() self.bottomCheckboxFrame.setContentsMargins(0,0,0,0) - self.bottomCheckboxLayout = QtGui.QGridLayout() + self.bottomCheckboxLayout = QtWidgets.QGridLayout() self.alwaysshowCheckbox = QCheckBox(getMessage("forceguiprompt-label")) self.enableplaylistsCheckbox = QCheckBox(getMessage("sharedplaylistenabled-label")) @@ -957,14 +958,14 @@ class ConfigDialog(QtGui.QDialog): 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 + u"house.png"),getMessage("basics-label"))) - self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"control_pause_blue.png"),getMessage("readiness-label"))) - self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"film_link.png"),getMessage("sync-label"))) - self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"comments.png"),getMessage("messages-label"))) - self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"cog.png"),getMessage("misc-label"))) + self.tabListLayout = QtWidgets.QHBoxLayout() + self.tabListFrame = QtWidgets.QFrame() + self.tabListWidget = QtWidgets.QListWidget() + self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"house.png"),getMessage("basics-label"))) + self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"control_pause_blue.png"),getMessage("readiness-label"))) + self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"film_link.png"),getMessage("sync-label"))) + self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"comments.png"),getMessage("messages-label"))) + self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"cog.png"),getMessage("misc-label"))) self.tabListLayout.addWidget(self.tabListWidget) self.tabListFrame.setLayout(self.tabListLayout) self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width()) @@ -1045,6 +1046,7 @@ class ConfigDialog(QtGui.QDialog): self.config['clearGUIData'] = False self.clearGUIData() + self.QtWidgets = QtWidgets self.QtGui = QtGui self.error = error if sys.platform.startswith('win'): @@ -1060,11 +1062,11 @@ class ConfigDialog(QtGui.QDialog): self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint) self.setWindowIcon(QtGui.QIcon(resourcespath + u"syncplay.png")) - self.stackedLayout = QtGui.QStackedLayout() - self.stackedFrame = QtGui.QFrame() + self.stackedLayout = QtWidgets.QStackedLayout() + self.stackedFrame = QtWidgets.QFrame() self.stackedFrame.setLayout(self.stackedLayout) - self.mainLayout = QtGui.QGridLayout() + self.mainLayout = QtWidgets.QGridLayout() self.mainLayout.setSpacing(0) self.mainLayout.setContentsMargins(0,0,0,0) diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py index 4250d6f..e7391d4 100644 --- a/syncplay/ui/gui.py +++ b/syncplay/ui/gui.py @@ -1,5 +1,5 @@ -from PySide import QtGui -from PySide.QtCore import Qt, QSettings, QSize, QPoint, QUrl, QLine +from PySide2 import QtWidgets, QtGui +from PySide2.QtCore import Qt, QSettings, QSize, QPoint, QUrl, QLine, QStandardPaths from syncplay import utils, constants, version from syncplay.messages import getMessage import sys @@ -13,12 +13,12 @@ from functools import wraps from twisted.internet import task lastCheckedForUpdates = None -class UserlistItemDelegate(QtGui.QStyledItemDelegate): +class UserlistItemDelegate(QtWidgets.QStyledItemDelegate): def __init__(self): - QtGui.QStyledItemDelegate.__init__(self) + QtWidgets.QStyledItemDelegate.__init__(self) def sizeHint(self, option, index): - size = QtGui.QStyledItemDelegate.sizeHint(self, option, index) + size = QtWidgets.QStyledItemDelegate.sizeHint(self, option, index) if (index.column() == constants.USERLIST_GUI_USERNAME_COLUMN): size.setWidth(size.width() + constants.USERLIST_GUI_USERNAME_OFFSET) return size @@ -82,9 +82,9 @@ class UserlistItemDelegate(QtGui.QStyledItemDelegate): midY - 8, streamSwitchIconQPixmap.scaled(16, 16, Qt.KeepAspectRatio)) optionQStyleOptionViewItem.rect.setX(optionQStyleOptionViewItem.rect.x()+16) - QtGui.QStyledItemDelegate.paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex) + QtWidgets.QStyledItemDelegate.paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex) -class MainWindow(QtGui.QMainWindow): +class MainWindow(QtWidgets.QMainWindow): insertPosition = None playlistState = [] updatingPlaylist = False @@ -97,7 +97,7 @@ class MainWindow(QtGui.QMainWindow): MainWindow.insertPosition = newPosition self.playlist.forceUpdate() - class PlaylistItemDelegate(QtGui.QStyledItemDelegate): + class PlaylistItemDelegate(QtWidgets.QStyledItemDelegate): def paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex): itemQPainter.save() currentQAbstractItemModel = indexQModelIndex.model() @@ -115,7 +115,7 @@ class MainWindow(QtGui.QMainWindow): currentlyplayingIconQPixmap.scaled(6, 16, Qt.KeepAspectRatio)) optionQStyleOptionViewItem.rect.setX(optionQStyleOptionViewItem.rect.x()+10) - QtGui.QStyledItemDelegate.paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex) + QtWidgets.QStyledItemDelegate.paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex) lineAbove = False lineBelow = False @@ -131,7 +131,7 @@ class MainWindow(QtGui.QMainWindow): itemQPainter.drawLine(line) itemQPainter.restore() - class PlaylistGroupBox(QtGui.QGroupBox): + class PlaylistGroupBox(QtWidgets.QGroupBox): def dragEnterEvent(self, event): data = event.mimeData() @@ -152,8 +152,8 @@ class MainWindow(QtGui.QMainWindow): if not window.playlist.isEnabled(): return window.setPlaylistInsertPosition(None) - if QtGui.QDropEvent.proposedAction(event) == Qt.MoveAction: - QtGui.QDropEvent.setDropAction(event, Qt.CopyAction) # Avoids file being deleted + if QtWidgets.QDropEvent.proposedAction(event) == Qt.MoveAction: + QtWidgets.QDropEvent.setDropAction(event, Qt.CopyAction) # Avoids file being deleted data = event.mimeData() urls = data.urls() @@ -169,7 +169,7 @@ class MainWindow(QtGui.QMainWindow): else: super(MainWindow.PlaylistWidget, self).dropEvent(event) - class PlaylistWidget(QtGui.QListWidget): + class PlaylistWidget(QtWidgets.QListWidget): selfWindow = None playlistIndexFilename = None @@ -188,7 +188,7 @@ class MainWindow(QtGui.QMainWindow): if fileIsUntrusted: self.item(item).setForeground(QtGui.QBrush(QtGui.QColor(constants.STYLE_UNTRUSTEDITEM_COLOR))) elif fileIsAvailable: - self.item(item).setForeground(QtGui.QBrush(QtGui.QColor(QtGui.QPalette.ColorRole(QtGui.QPalette.Text)))) + self.item(item).setForeground(QtGui.QBrush(QtGui.QColor(QtWidgets.QPalette.ColorRole(QtWidgets.QPalette.Text)))) else: self.item(item).setForeground(QtGui.QBrush(QtGui.QColor(constants.STYLE_DIFFERENTITEM_COLOR))) self.selfWindow._syncplayClient.fileSwitch.setFilenameWatchlist(self.selfWindow.newWatchlist) @@ -251,8 +251,8 @@ class MainWindow(QtGui.QMainWindow): if not window.playlist.isEnabled(): return window.setPlaylistInsertPosition(None) - if QtGui.QDropEvent.proposedAction(event) == Qt.MoveAction: - QtGui.QDropEvent.setDropAction(event, Qt.CopyAction) # Avoids file being deleted + if QtWidgets.QDropEvent.proposedAction(event) == Qt.MoveAction: + QtWidgets.QDropEvent.setDropAction(event, Qt.CopyAction) # Avoids file being deleted data = event.mimeData() urls = data.urls() @@ -273,17 +273,17 @@ class MainWindow(QtGui.QMainWindow): - class topSplitter(QtGui.QSplitter): + class topSplitter(QtWidgets.QSplitter): def createHandle(self): return self.topSplitterHandle(self.orientation(), self) - class topSplitterHandle(QtGui.QSplitterHandle): + class topSplitterHandle(QtWidgets.QSplitterHandle): def mouseReleaseEvent(self, event): - QtGui.QSplitterHandle.mouseReleaseEvent(self, event) + QtWidgets.QSplitterHandle.mouseReleaseEvent(self, event) self.parent().parent().parent().updateListGeometry() def mouseMoveEvent(self, event): - QtGui.QSplitterHandle.mouseMoveEvent(self, event) + QtWidgets.QSplitterHandle.mouseMoveEvent(self, event) self.parent().parent().parent().updateListGeometry() def needsClient(f): # @NoSelf @@ -408,11 +408,11 @@ class MainWindow(QtGui.QMainWindow): if isControlledRoom: if room == currentUser.room and currentUser.isController(): - roomitem.setIcon(QtGui.QIcon(self.resourcespath + 'lock_open.png')) + roomitem.setIcon(QtGui.QPixmap(self.resourcespath + 'lock_open.png')) else: - roomitem.setIcon(QtGui.QIcon(self.resourcespath + 'lock.png')) + roomitem.setIcon(QtGui.QPixmap(self.resourcespath + 'lock.png')) else: - roomitem.setIcon(QtGui.QIcon(self.resourcespath + 'chevrons_right.png')) + roomitem.setIcon(QtGui.QPixmap(self.resourcespath + 'chevrons_right.png')) for user in rooms[room]: useritem = QtGui.QStandardItem(user.username) @@ -506,7 +506,7 @@ class MainWindow(QtGui.QMainWindow): item = self.playlist.selectedIndexes()[0] else: item = None - menu = QtGui.QMenu() + menu = QtWidgets.QMenu() if item: firstFile = item.sibling(item.row(), 0).data() @@ -548,7 +548,7 @@ class MainWindow(QtGui.QMainWindow): else: return - menu = QtGui.QMenu() + menu = QtWidgets.QMenu() username = item.sibling(item.row(), 0).data() if username == self._syncplayClient.userlist.currentUser.username: shortUsername = getMessage("item-is-yours-indicator") @@ -596,15 +596,15 @@ class MainWindow(QtGui.QMainWindow): self.listTreeView.setFirstColumnSpanned(roomtocheck, self.listTreeView.rootIndex(), True) roomtocheck += 1 self.listTreeView.header().setStretchLastSection(False) - self.listTreeView.header().setResizeMode(0, QtGui.QHeaderView.ResizeToContents) - self.listTreeView.header().setResizeMode(1, QtGui.QHeaderView.ResizeToContents) - self.listTreeView.header().setResizeMode(2, QtGui.QHeaderView.ResizeToContents) - self.listTreeView.header().setResizeMode(3, QtGui.QHeaderView.ResizeToContents) + self.listTreeView.header().setResizeMode(0, QtWidgets.QHeaderView.ResizeToContents) + self.listTreeView.header().setResizeMode(1, QtWidgets.QHeaderView.ResizeToContents) + self.listTreeView.header().setResizeMode(2, QtWidgets.QHeaderView.ResizeToContents) + self.listTreeView.header().setResizeMode(3, QtWidgets.QHeaderView.ResizeToContents) NarrowTabsWidth = self.listTreeView.header().sectionSize(0)+self.listTreeView.header().sectionSize(1)+self.listTreeView.header().sectionSize(2) if self.listTreeView.header().width() < (NarrowTabsWidth+self.listTreeView.header().sectionSize(3)): self.listTreeView.header().resizeSection(3,self.listTreeView.header().width()-NarrowTabsWidth) else: - self.listTreeView.header().setResizeMode(3, QtGui.QHeaderView.Stretch) + self.listTreeView.header().setResizeMode(3, QtWidgets.QHeaderView.Stretch) self.listTreeView.expandAll() except: pass @@ -677,7 +677,7 @@ class MainWindow(QtGui.QMainWindow): def showErrorMessage(self, message, criticalerror=False): message = unicode(message) if criticalerror: - QtGui.QMessageBox.critical(self, "Syncplay", message) + QtWidgets.QMessageBox.critical(self, "Syncplay", message) message = message.replace(u"&", u"&").replace(u'"', u""").replace(u"<", u"<").replace(u">", u">") message = message.replace(u"\n", u"
") message = u"".format(constants.STYLE_ERRORNOTIFICATION) + message + u"" @@ -698,8 +698,8 @@ class MainWindow(QtGui.QMainWindow): self._syncplayClient.sendRoom() def seekPositionDialog(self): - seekTime, ok = QtGui.QInputDialog.getText(self, getMessage("seektime-menu-label"), - getMessage("seektime-msgbox-label"), QtGui.QLineEdit.Normal, + seekTime, ok = QtWidgets.QInputDialog.getText(self, getMessage("seektime-menu-label"), + getMessage("seektime-msgbox-label"), QtWidgets.QLineEdit.Normal, u"0:00") if ok and seekTime != '': self.seekPosition(seekTime) @@ -766,10 +766,10 @@ class MainWindow(QtGui.QMainWindow): defaultdirectory = self.config["mediaSearchDirectories"][0] elif includeUserSpecifiedDirectories and os.path.isdir(self.mediadirectory): defaultdirectory = self.mediadirectory - elif os.path.isdir(QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.MoviesLocation)): - defaultdirectory = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.MoviesLocation) - elif os.path.isdir(QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.HomeLocation)): - defaultdirectory = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.HomeLocation) + elif os.path.isdir(QStandardPaths.standardLocations(QStandardPaths.MoviesLocation)[0]): + defaultdirectory = QStandardPaths.standardLocations(QStandardPaths.MoviesLocation)[0] + elif os.path.isdir(QStandardPaths.standardLocations(QStandardPaths.HomeLocation)[0]): + defaultdirectory = QStandardPaths.standardLocations(QStandardPaths.HomeLocation)[0] else: defaultdirectory = "" return defaultdirectory @@ -781,7 +781,7 @@ class MainWindow(QtGui.QMainWindow): return self.loadMediaBrowseSettings() - options = QtGui.QFileDialog.Options() + options = QtWidgets.QFileDialog.Options() self.mediadirectory = "" currentdirectory = os.path.dirname(self._syncplayClient.userlist.currentUser.file["path"]) if self._syncplayClient.userlist.currentUser.file else None if currentdirectory and os.path.isdir(currentdirectory): @@ -789,7 +789,7 @@ class MainWindow(QtGui.QMainWindow): else: defaultdirectory = self.getInitialMediaDirectory() browserfilter = "All files (*)" - fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, getMessage("browseformedia-label"), defaultdirectory, + fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self, getMessage("browseformedia-label"), defaultdirectory, browserfilter, "", options) if fileName: if sys.platform.startswith('win'): @@ -806,7 +806,7 @@ class MainWindow(QtGui.QMainWindow): return self.loadMediaBrowseSettings() - options = QtGui.QFileDialog.Options() + options = QtWidgets.QFileDialog.Options() self.mediadirectory = "" currentdirectory = os.path.dirname(self._syncplayClient.userlist.currentUser.file["path"]) if self._syncplayClient.userlist.currentUser.file else None if currentdirectory and os.path.isdir(currentdirectory): @@ -814,7 +814,7 @@ class MainWindow(QtGui.QMainWindow): else: defaultdirectory = self.getInitialMediaDirectory() browserfilter = "All files (*)" - fileNames, filtr = QtGui.QFileDialog.getOpenFileNames(self, getMessage("browseformedia-label"), defaultdirectory, + fileNames, filtr = QtWidgets.QFileDialog.getOpenFileNames(self, getMessage("browseformedia-label"), defaultdirectory, browserfilter, "", options) self.updatingPlaylist = True if fileNames: @@ -830,17 +830,17 @@ class MainWindow(QtGui.QMainWindow): @needsClient def OpenAddURIsToPlaylistDialog(self): - URIsDialog = QtGui.QDialog() + URIsDialog = QtWidgets.QDialog() URIsDialog.setWindowTitle(getMessage("adduris-msgbox-label")) - URIsLayout = QtGui.QGridLayout() - URIsLabel = QtGui.QLabel(getMessage("adduris-msgbox-label")) + URIsLayout = QtWidgets.QGridLayout() + URIsLabel = QtWidgets.QLabel(getMessage("adduris-msgbox-label")) URIsLayout.addWidget(URIsLabel, 0, 0, 1, 1) - URIsTextbox = QtGui.QPlainTextEdit() - URIsTextbox.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) + URIsTextbox = QtWidgets.QPlainTextEdit() + URIsTextbox.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) URIsLayout.addWidget(URIsTextbox, 1, 0, 1, 1) - URIsButtonBox = QtGui.QDialogButtonBox() + URIsButtonBox = QtWidgets.QDialogButtonBox() URIsButtonBox.setOrientation(Qt.Horizontal) - URIsButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel) + URIsButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Cancel) URIsButtonBox.accepted.connect(URIsDialog.accept) URIsButtonBox.rejected.connect(URIsDialog.reject) URIsLayout.addWidget(URIsButtonBox, 2, 0, 1, 1) @@ -848,7 +848,7 @@ class MainWindow(QtGui.QMainWindow): URIsDialog.setModal(True) URIsDialog.show() result = URIsDialog.exec_() - if result == QtGui.QDialog.Accepted: + if result == QtWidgets.QDialog.Accepted: URIsToAdd = utils.convertMultilineStringToList(URIsTextbox.toPlainText()) self.updatingPlaylist = True for URI in URIsToAdd: @@ -866,17 +866,17 @@ class MainWindow(QtGui.QMainWindow): @needsClient def openEditPlaylistDialog(self): oldPlaylist = utils.getListAsMultilineString(self.getPlaylistState()) - editPlaylistDialog = QtGui.QDialog() + editPlaylistDialog = QtWidgets.QDialog() editPlaylistDialog.setWindowTitle(getMessage("editplaylist-msgbox-label")) - editPlaylistLayout = QtGui.QGridLayout() - editPlaylistLabel = QtGui.QLabel(getMessage("editplaylist-msgbox-label")) + editPlaylistLayout = QtWidgets.QGridLayout() + editPlaylistLabel = QtWidgets.QLabel(getMessage("editplaylist-msgbox-label")) editPlaylistLayout.addWidget(editPlaylistLabel, 0, 0, 1, 1) - editPlaylistTextbox = QtGui.QPlainTextEdit(oldPlaylist) - editPlaylistTextbox.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) + editPlaylistTextbox = QtWidgets.QPlainTextEdit(oldPlaylist) + editPlaylistTextbox.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) editPlaylistLayout.addWidget(editPlaylistTextbox, 1, 0, 1, 1) - editPlaylistButtonBox = QtGui.QDialogButtonBox() + editPlaylistButtonBox = QtWidgets.QDialogButtonBox() editPlaylistButtonBox.setOrientation(Qt.Horizontal) - editPlaylistButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel) + editPlaylistButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Cancel) editPlaylistButtonBox.accepted.connect(editPlaylistDialog.accept) editPlaylistButtonBox.rejected.connect(editPlaylistDialog.reject) editPlaylistLayout.addWidget(editPlaylistButtonBox, 2, 0, 1, 1) @@ -886,7 +886,7 @@ class MainWindow(QtGui.QMainWindow): editPlaylistDialog.setMinimumHeight(500) editPlaylistDialog.show() result = editPlaylistDialog.exec_() - if result == QtGui.QDialog.Accepted: + if result == QtWidgets.QDialog.Accepted: newPlaylist = utils.convertMultilineStringToList(editPlaylistTextbox.toPlainText()) if newPlaylist <> self.playlistState and self._syncplayClient and not self.updatingPlaylist: self.setPlaylist(newPlaylist) @@ -895,46 +895,46 @@ class MainWindow(QtGui.QMainWindow): @needsClient def openSetMediaDirectoriesDialog(self): - MediaDirectoriesDialog = QtGui.QDialog() + MediaDirectoriesDialog = QtWidgets.QDialog() MediaDirectoriesDialog.setWindowTitle(getMessage("syncplay-mediasearchdirectories-title")) # TODO: Move to messages_*.py - MediaDirectoriesLayout = QtGui.QGridLayout() - MediaDirectoriesLabel = QtGui.QLabel(getMessage("syncplay-mediasearchdirectories-title")) + MediaDirectoriesLayout = QtWidgets.QGridLayout() + MediaDirectoriesLabel = QtWidgets.QLabel(getMessage("syncplay-mediasearchdirectories-title")) MediaDirectoriesLayout.addWidget(MediaDirectoriesLabel, 0, 0, 1, 2) - MediaDirectoriesTextbox = QtGui.QPlainTextEdit() - MediaDirectoriesTextbox.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) + MediaDirectoriesTextbox = QtWidgets.QPlainTextEdit() + MediaDirectoriesTextbox.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) MediaDirectoriesTextbox.setPlainText(utils.getListAsMultilineString(self.config["mediaSearchDirectories"])) MediaDirectoriesLayout.addWidget(MediaDirectoriesTextbox, 1, 0, 1, 1) - MediaDirectoriesButtonBox = QtGui.QDialogButtonBox() + MediaDirectoriesButtonBox = QtWidgets.QDialogButtonBox() MediaDirectoriesButtonBox.setOrientation(Qt.Horizontal) - MediaDirectoriesButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel) + MediaDirectoriesButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Cancel) MediaDirectoriesButtonBox.accepted.connect(MediaDirectoriesDialog.accept) MediaDirectoriesButtonBox.rejected.connect(MediaDirectoriesDialog.reject) MediaDirectoriesLayout.addWidget(MediaDirectoriesButtonBox, 2, 0, 1, 1) - MediaDirectoriesAddFolderButton = QtGui.QPushButton(getMessage("addfolder-label")) + MediaDirectoriesAddFolderButton = QtWidgets.QPushButton(getMessage("addfolder-label")) MediaDirectoriesAddFolderButton.pressed.connect(lambda: self.openAddMediaDirectoryDialog(MediaDirectoriesTextbox, MediaDirectoriesDialog)) MediaDirectoriesLayout.addWidget(MediaDirectoriesAddFolderButton, 1, 1, 1, 1, Qt.AlignTop) MediaDirectoriesDialog.setLayout(MediaDirectoriesLayout) MediaDirectoriesDialog.setModal(True) MediaDirectoriesDialog.show() result = MediaDirectoriesDialog.exec_() - if result == QtGui.QDialog.Accepted: + if result == QtWidgets.QDialog.Accepted: newMediaDirectories = utils.convertMultilineStringToList(MediaDirectoriesTextbox.toPlainText()) self._syncplayClient.fileSwitch.changeMediaDirectories(newMediaDirectories) @needsClient def openSetTrustedDomainsDialog(self): - TrustedDomainsDialog = QtGui.QDialog() + TrustedDomainsDialog = QtWidgets.QDialog() TrustedDomainsDialog.setWindowTitle(getMessage("syncplay-trusteddomains-title")) - TrustedDomainsLayout = QtGui.QGridLayout() - TrustedDomainsLabel = QtGui.QLabel(getMessage("trusteddomains-msgbox-label")) + TrustedDomainsLayout = QtWidgets.QGridLayout() + TrustedDomainsLabel = QtWidgets.QLabel(getMessage("trusteddomains-msgbox-label")) TrustedDomainsLayout.addWidget(TrustedDomainsLabel, 0, 0, 1, 1) - TrustedDomainsTextbox = QtGui.QPlainTextEdit() - TrustedDomainsTextbox.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) + TrustedDomainsTextbox = QtWidgets.QPlainTextEdit() + TrustedDomainsTextbox.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) TrustedDomainsTextbox.setPlainText(utils.getListAsMultilineString(self.config["trustedDomains"])) TrustedDomainsLayout.addWidget(TrustedDomainsTextbox, 1, 0, 1, 1) - TrustedDomainsButtonBox = QtGui.QDialogButtonBox() + TrustedDomainsButtonBox = QtWidgets.QDialogButtonBox() TrustedDomainsButtonBox.setOrientation(Qt.Horizontal) - TrustedDomainsButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel) + TrustedDomainsButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Cancel) TrustedDomainsButtonBox.accepted.connect(TrustedDomainsDialog.accept) TrustedDomainsButtonBox.rejected.connect(TrustedDomainsDialog.reject) TrustedDomainsLayout.addWidget(TrustedDomainsButtonBox, 2, 0, 1, 1) @@ -942,7 +942,7 @@ class MainWindow(QtGui.QMainWindow): TrustedDomainsDialog.setModal(True) TrustedDomainsDialog.show() result = TrustedDomainsDialog.exec_() - if result == QtGui.QDialog.Accepted: + if result == QtWidgets.QDialog.Accepted: newTrustedDomains = utils.convertMultilineStringToList(TrustedDomainsTextbox.toPlainText()) self._syncplayClient.setTrustedDomains(newTrustedDomains) @needsClient @@ -954,7 +954,7 @@ class MainWindow(QtGui.QMainWindow): @needsClient def openAddMediaDirectoryDialog(self, MediaDirectoriesTextbox, MediaDirectoriesDialog): - folderName = unicode(QtGui.QFileDialog.getExistingDirectory(self,None,self.getInitialMediaDirectory(includeUserSpecifiedDirectories=False),QtGui.QFileDialog.ShowDirsOnly)) + folderName = unicode(QtWidgets.QFileDialog.getExistingDirectory(self,None,self.getInitialMediaDirectory(includeUserSpecifiedDirectories=False),QtWidgets.QFileDialog.ShowDirsOnly)) if folderName: existingMediaDirs = MediaDirectoriesTextbox.toPlainText() if existingMediaDirs == "": @@ -967,16 +967,16 @@ class MainWindow(QtGui.QMainWindow): @needsClient def promptForStreamURL(self): - streamURL, ok = QtGui.QInputDialog.getText(self, getMessage("promptforstreamurl-msgbox-label"), - getMessage("promptforstreamurlinfo-msgbox-label"), QtGui.QLineEdit.Normal, + streamURL, ok = QtWidgets.QInputDialog.getText(self, getMessage("promptforstreamurl-msgbox-label"), + getMessage("promptforstreamurlinfo-msgbox-label"), QtWidgets.QLineEdit.Normal, "") if ok and streamURL != '': self._syncplayClient._player.openFile(streamURL) @needsClient def createControlledRoom(self): - controlroom, ok = QtGui.QInputDialog.getText(self, getMessage("createcontrolledroom-msgbox-label"), - getMessage("controlledroominfo-msgbox-label"), QtGui.QLineEdit.Normal, + controlroom, ok = QtWidgets.QInputDialog.getText(self, getMessage("createcontrolledroom-msgbox-label"), + getMessage("controlledroominfo-msgbox-label"), QtWidgets.QLineEdit.Normal, utils.stripRoomName(self._syncplayClient.getRoom())) if ok and controlroom != '': self._syncplayClient.createControlledRoom(controlroom) @@ -985,7 +985,7 @@ class MainWindow(QtGui.QMainWindow): def identifyAsController(self): msgboxtitle = getMessage("identifyascontroller-msgbox-label") msgboxtext = getMessage("identifyinfo-msgbox-label") - controlpassword, ok = QtGui.QInputDialog.getText(self, msgboxtitle, msgboxtext, QtGui.QLineEdit.Normal, "") + controlpassword, ok = QtWidgets.QInputDialog.getText(self, msgboxtitle, msgboxtext, QtWidgets.QLineEdit.Normal, "") if ok and controlpassword != '': self._syncplayClient.identifyAsController(controlpassword) @@ -1000,8 +1000,8 @@ class MainWindow(QtGui.QMainWindow): @needsClient def setOffset(self): - newoffset, ok = QtGui.QInputDialog.getText(self, getMessage("setoffset-msgbox-label"), - getMessage("offsetinfo-msgbox-label"), QtGui.QLineEdit.Normal, + newoffset, ok = QtWidgets.QInputDialog.getText(self, getMessage("setoffset-msgbox-label"), + getMessage("offsetinfo-msgbox-label"), QtWidgets.QLineEdit.Normal, "") if ok and newoffset != '': o = re.match(constants.UI_OFFSET_REGEX, "o " + newoffset) @@ -1054,8 +1054,8 @@ class MainWindow(QtGui.QMainWindow): def addTopLayout(self, window): window.topSplit = self.topSplitter(Qt.Horizontal, self) - window.outputLayout = QtGui.QVBoxLayout() - window.outputbox = QtGui.QTextBrowser() + window.outputLayout = QtWidgets.QVBoxLayout() + window.outputbox = QtWidgets.QTextBrowser() window.outputbox.setReadOnly(True) window.outputbox.setTextInteractionFlags(window.outputbox.textInteractionFlags() | Qt.TextSelectableByKeyboard) window.outputbox.setOpenExternalLinks(True) @@ -1065,24 +1065,24 @@ class MainWindow(QtGui.QMainWindow): window.outputbox.moveCursor(QtGui.QTextCursor.End) window.outputbox.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) - window.outputlabel = QtGui.QLabel(getMessage("notifications-heading-label")) - window.chatInput = QtGui.QLineEdit() + window.outputlabel = QtWidgets.QLabel(getMessage("notifications-heading-label")) + window.chatInput = QtWidgets.QLineEdit() window.chatInput.setMaxLength(constants.MAX_CHAT_MESSAGE_LENGTH) window.chatInput.returnPressed.connect(self.sendChatMessage) - window.chatButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'email_go.png'), + window.chatButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + 'email_go.png'), getMessage("sendmessage-label")) window.chatButton.pressed.connect(self.sendChatMessage) - window.chatLayout = QtGui.QHBoxLayout() - window.chatFrame = QtGui.QFrame() + window.chatLayout = QtWidgets.QHBoxLayout() + window.chatFrame = QtWidgets.QFrame() window.chatFrame.setLayout(self.chatLayout) window.chatFrame.setContentsMargins(0,0,0,0) - window.chatFrame.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) + window.chatFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) window.chatLayout.setContentsMargins(0,0,0,0) self.chatButton.setToolTip(getMessage("sendmessage-tooltip")) window.chatLayout.addWidget(window.chatInput) window.chatLayout.addWidget(window.chatButton) window.chatFrame.setMaximumHeight(window.chatFrame.sizeHint().height()) - window.outputFrame = QtGui.QFrame() + window.outputFrame = QtWidgets.QFrame() window.outputFrame.setLineWidth(0) window.outputFrame.setMidLineWidth(0) window.outputLayout.setContentsMargins(0, 0, 0, 0) @@ -1091,47 +1091,47 @@ class MainWindow(QtGui.QMainWindow): window.outputLayout.addWidget(window.chatFrame) window.outputFrame.setLayout(window.outputLayout) - window.listLayout = QtGui.QVBoxLayout() + window.listLayout = QtWidgets.QVBoxLayout() window.listTreeModel = QtGui.QStandardItemModel() - window.listTreeView = QtGui.QTreeView() + window.listTreeView = QtWidgets.QTreeView() window.listTreeView.setModel(window.listTreeModel) window.listTreeView.setIndentation(21) window.listTreeView.doubleClicked.connect(self.roomClicked) self.listTreeView.setContextMenuPolicy(Qt.CustomContextMenu) - self.listTreeView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.listTreeView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.listTreeView.customContextMenuRequested.connect(self.openRoomMenu) - window.listlabel = QtGui.QLabel(getMessage("userlist-heading-label")) - window.listFrame = QtGui.QFrame() + window.listlabel = QtWidgets.QLabel(getMessage("userlist-heading-label")) + window.listFrame = QtWidgets.QFrame() window.listFrame.setLineWidth(0) window.listFrame.setMidLineWidth(0) - window.listFrame.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + window.listFrame.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) window.listLayout.setContentsMargins(0, 0, 0, 0) - window.userlistLayout = QtGui.QVBoxLayout() - window.userlistFrame = QtGui.QFrame() + window.userlistLayout = QtWidgets.QVBoxLayout() + window.userlistFrame = QtWidgets.QFrame() window.userlistFrame.setLineWidth(0) window.userlistFrame.setMidLineWidth(0) - window.userlistFrame.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + window.userlistFrame.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) window.userlistLayout.setContentsMargins(0, 0, 0, 0) window.userlistFrame.setLayout(window.userlistLayout) window.userlistLayout.addWidget(window.listlabel) window.userlistLayout.addWidget(window.listTreeView) - window.listSplit = QtGui.QSplitter(Qt.Vertical, self) + window.listSplit = QtWidgets.QSplitter(Qt.Vertical, self) window.listSplit.addWidget(window.userlistFrame) window.listLayout.addWidget(window.listSplit) - window.roomInput = QtGui.QLineEdit() + window.roomInput = QtWidgets.QLineEdit() window.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH) window.roomInput.returnPressed.connect(self.joinRoom) - window.roomButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'door_in.png'), + window.roomButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + 'door_in.png'), getMessage("joinroom-label")) window.roomButton.pressed.connect(self.joinRoom) - window.roomLayout = QtGui.QHBoxLayout() - window.roomFrame = QtGui.QFrame() + window.roomLayout = QtWidgets.QHBoxLayout() + window.roomFrame = QtWidgets.QFrame() window.roomFrame.setLayout(self.roomLayout) window.roomFrame.setContentsMargins(0,0,0,0) - window.roomFrame.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) + window.roomFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) window.roomLayout.setContentsMargins(0,0,0,0) self.roomButton.setToolTip(getMessage("joinroom-tooltip")) window.roomLayout.addWidget(window.roomInput) @@ -1146,11 +1146,11 @@ class MainWindow(QtGui.QMainWindow): window.topSplit.setStretchFactor(0,4) window.topSplit.setStretchFactor(1,5) window.mainLayout.addWidget(window.topSplit) - window.topSplit.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) + window.topSplit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) def addBottomLayout(self, window): - window.bottomLayout = QtGui.QHBoxLayout() - window.bottomFrame = QtGui.QFrame() + window.bottomLayout = QtWidgets.QHBoxLayout() + window.bottomFrame = QtWidgets.QFrame() window.bottomFrame.setLayout(window.bottomLayout) window.bottomLayout.setContentsMargins(0,0,0,0) @@ -1159,8 +1159,8 @@ class MainWindow(QtGui.QMainWindow): window.playlistGroup = self.PlaylistGroupBox(getMessage("sharedplaylistenabled-label")) window.playlistGroup.setCheckable(True) window.playlistGroup.toggled.connect(self.changePlaylistEnabledState) - window.playlistLayout = QtGui.QHBoxLayout() - window.playlistGroup.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + window.playlistLayout = QtWidgets.QHBoxLayout() + window.playlistGroup.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) window.playlistGroup.setAcceptDrops(True) window.playlist = self.PlaylistWidget() window.playlist.setWindow(window) @@ -1168,18 +1168,18 @@ class MainWindow(QtGui.QMainWindow): window.playlist.setDragEnabled(True) window.playlist.setAcceptDrops(True) window.playlist.setDropIndicatorShown(True) - window.playlist.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) + window.playlist.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) window.playlist.setDefaultDropAction(Qt.MoveAction) - window.playlist.setDragDropMode(QtGui.QAbstractItemView.InternalMove) + window.playlist.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove) window.playlist.doubleClicked.connect(self.playlistItemClicked) window.playlist.setContextMenuPolicy(Qt.CustomContextMenu) - window.playlist.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + window.playlist.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) window.playlist.customContextMenuRequested.connect(self.openPlaylistMenu) self.playlistUpdateTimer = task.LoopingCall(self.playlistChangeCheck) self.playlistUpdateTimer.start(0.1, True) noteFont = QtGui.QFont() noteFont.setItalic(True) - playlistItem = QtGui.QListWidgetItem(getMessage("playlist-instruction-item-message")) + playlistItem = QtWidgets.QListWidgetItem(getMessage("playlist-instruction-item-message")) playlistItem.setFont(noteFont) window.playlist.addItem(playlistItem) playlistItem.setFont(noteFont) @@ -1189,7 +1189,7 @@ class MainWindow(QtGui.QMainWindow): window.playlistGroup.setLayout(window.playlistLayout) window.listSplit.addWidget(window.playlistGroup) - window.readyPushButton = QtGui.QPushButton() + window.readyPushButton = QtWidgets.QPushButton() readyFont = QtGui.QFont() readyFont.setWeight(QtGui.QFont.Bold) window.readyPushButton.setText(getMessage("ready-guipushbuttonlabel")) @@ -1201,12 +1201,12 @@ class MainWindow(QtGui.QMainWindow): window.readyPushButton.setToolTip(getMessage("ready-tooltip")) window.listLayout.addWidget(window.readyPushButton, Qt.AlignRight) - window.autoplayLayout = QtGui.QHBoxLayout() - window.autoplayFrame = QtGui.QFrame() + window.autoplayLayout = QtWidgets.QHBoxLayout() + window.autoplayFrame = QtWidgets.QFrame() window.autoplayFrame.setVisible(False) window.autoplayLayout.setContentsMargins(0,0,0,0) window.autoplayFrame.setLayout(window.autoplayLayout) - window.autoplayPushButton = QtGui.QPushButton() + window.autoplayPushButton = QtWidgets.QPushButton() autoPlayFont = QtGui.QFont() autoPlayFont.setWeight(QtGui.QFont.Bold) window.autoplayPushButton.setText(getMessage("autoplay-guipushbuttonlabel")) @@ -1215,13 +1215,13 @@ class MainWindow(QtGui.QMainWindow): window.autoplayPushButton.toggled.connect(self.changeAutoplayState) window.autoplayPushButton.setFont(autoPlayFont) window.autoplayPushButton.setStyleSheet(constants.STYLE_AUTO_PLAY_PUSHBUTTON) - window.autoplayPushButton.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + window.autoplayPushButton.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) window.autoplayPushButton.setToolTip(getMessage("autoplay-tooltip")) - window.autoplayLabel = QtGui.QLabel(getMessage("autoplay-minimum-label")) - window.autoplayLabel.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) + window.autoplayLabel = QtWidgets.QLabel(getMessage("autoplay-minimum-label")) + window.autoplayLabel.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) window.autoplayLabel.setMaximumWidth(window.autoplayLabel.minimumSizeHint().width()) window.autoplayLabel.setToolTip(getMessage("autoplay-tooltip")) - window.autoplayThresholdSpinbox = QtGui.QSpinBox() + window.autoplayThresholdSpinbox = QtWidgets.QSpinBox() window.autoplayThresholdSpinbox.setMaximumWidth(window.autoplayThresholdSpinbox.minimumSizeHint().width()) window.autoplayThresholdSpinbox.setMinimum(2) window.autoplayThresholdSpinbox.setMaximum(99) @@ -1237,33 +1237,33 @@ class MainWindow(QtGui.QMainWindow): window.bottomFrame.setMaximumHeight(window.bottomFrame.minimumSizeHint().height()) def addPlaybackLayout(self, window): - window.playbackFrame = QtGui.QFrame() + window.playbackFrame = QtWidgets.QFrame() window.playbackFrame.setVisible(False) window.playbackFrame.setContentsMargins(0,0,0,0) - window.playbackLayout = QtGui.QHBoxLayout() + window.playbackLayout = QtWidgets.QHBoxLayout() window.playbackLayout.setAlignment(Qt.AlignLeft) window.playbackLayout.setContentsMargins(0,0,0,0) window.playbackFrame.setLayout(window.playbackLayout) - window.seekInput = QtGui.QLineEdit() + window.seekInput = QtWidgets.QLineEdit() window.seekInput.returnPressed.connect(self.seekFromButton) - window.seekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + u'clock_go.png'), "") + window.seekButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + u'clock_go.png'), "") window.seekButton.setToolTip(getMessage("seektime-menu-label")) window.seekButton.pressed.connect(self.seekFromButton) window.seekInput.setText("0:00") window.seekInput.setFixedWidth(60) window.playbackLayout.addWidget(window.seekInput) window.playbackLayout.addWidget(window.seekButton) - window.unseekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + u'arrow_undo.png'), "") + window.unseekButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + u'arrow_undo.png'), "") window.unseekButton.setToolTip(getMessage("undoseek-menu-label")) window.unseekButton.pressed.connect(self.undoSeek) - window.miscLayout = QtGui.QHBoxLayout() + window.miscLayout = QtWidgets.QHBoxLayout() window.playbackLayout.addWidget(window.unseekButton) - window.playButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + u'control_play_blue.png'), "") + window.playButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + u'control_play_blue.png'), "") window.playButton.setToolTip(getMessage("play-menu-label")) window.playButton.pressed.connect(self.play) window.playbackLayout.addWidget(window.playButton) - window.pauseButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'), "") + window.pauseButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + 'control_pause_blue.png'), "") window.pauseButton.setToolTip(getMessage("pause-menu-label")) window.pauseButton.pressed.connect(self.pause) window.playbackLayout.addWidget(window.pauseButton) @@ -1272,54 +1272,54 @@ class MainWindow(QtGui.QMainWindow): window.outputLayout.addWidget(window.playbackFrame) def addMenubar(self, window): - window.menuBar = QtGui.QMenuBar() + window.menuBar = QtWidgets.QMenuBar() # File menu - window.fileMenu = QtGui.QMenu(getMessage("file-menu-label"), self) - window.openAction = window.fileMenu.addAction(QtGui.QIcon(self.resourcespath + 'folder_explore.png'), + window.fileMenu = QtWidgets.QMenu(getMessage("file-menu-label"), self) + window.openAction = window.fileMenu.addAction(QtGui.QPixmap(self.resourcespath + 'folder_explore.png'), getMessage("openmedia-menu-label")) window.openAction.triggered.connect(self.browseMediapath) - window.openAction = window.fileMenu.addAction(QtGui.QIcon(self.resourcespath + 'world_explore.png'), + window.openAction = window.fileMenu.addAction(QtGui.QPixmap(self.resourcespath + 'world_explore.png'), getMessage("openstreamurl-menu-label")) window.openAction.triggered.connect(self.promptForStreamURL) - window.openAction = window.fileMenu.addAction(QtGui.QIcon(self.resourcespath + 'film_folder_edit.png'), + window.openAction = window.fileMenu.addAction(QtGui.QPixmap(self.resourcespath + 'film_folder_edit.png'), getMessage("setmediadirectories-menu-label")) window.openAction.triggered.connect(self.openSetMediaDirectoriesDialog) - window.exitAction = window.fileMenu.addAction(QtGui.QIcon(self.resourcespath + 'cross.png'), + window.exitAction = window.fileMenu.addAction(QtGui.QPixmap(self.resourcespath + 'cross.png'), getMessage("exit-menu-label")) window.exitAction.triggered.connect(self.exitSyncplay) window.menuBar.addMenu(window.fileMenu) # Playback menu - window.playbackMenu = QtGui.QMenu(getMessage("playback-menu-label"), self) - window.playAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'control_play_blue.png'), getMessage("play-menu-label")) + window.playbackMenu = QtWidgets.QMenu(getMessage("playback-menu-label"), self) + window.playAction = window.playbackMenu.addAction(QtGui.QPixmap(self.resourcespath + 'control_play_blue.png'), getMessage("play-menu-label")) window.playAction.triggered.connect(self.play) - window.pauseAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'), getMessage("pause-menu-label")) + window.pauseAction = window.playbackMenu.addAction(QtGui.QPixmap(self.resourcespath + 'control_pause_blue.png'), getMessage("pause-menu-label")) window.pauseAction.triggered.connect(self.pause) - window.seekAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'clock_go.png'), getMessage("seektime-menu-label")) + window.seekAction = window.playbackMenu.addAction(QtGui.QPixmap(self.resourcespath + 'clock_go.png'), getMessage("seektime-menu-label")) window.seekAction.triggered.connect(self.seekPositionDialog) - window.unseekAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'arrow_undo.png'), getMessage("undoseek-menu-label")) + window.unseekAction = window.playbackMenu.addAction(QtGui.QPixmap(self.resourcespath + 'arrow_undo.png'), getMessage("undoseek-menu-label")) window.unseekAction.triggered.connect(self.undoSeek) window.menuBar.addMenu(window.playbackMenu) # Advanced menu - window.advancedMenu = QtGui.QMenu(getMessage("advanced-menu-label"), self) - window.setoffsetAction = window.advancedMenu.addAction(QtGui.QIcon(self.resourcespath + 'timeline_marker.png'), + window.advancedMenu = QtWidgets.QMenu(getMessage("advanced-menu-label"), self) + window.setoffsetAction = window.advancedMenu.addAction(QtGui.QPixmap(self.resourcespath + 'timeline_marker.png'), getMessage("setoffset-menu-label")) window.setoffsetAction.triggered.connect(self.setOffset) - window.setTrustedDomainsAction = window.advancedMenu.addAction(QtGui.QIcon(self.resourcespath + 'shield_edit.png'), + window.setTrustedDomainsAction = window.advancedMenu.addAction(QtGui.QPixmap(self.resourcespath + 'shield_edit.png'), getMessage("settrusteddomains-menu-label")) window.setTrustedDomainsAction.triggered.connect(self.openSetTrustedDomainsDialog) window.createcontrolledroomAction = window.advancedMenu.addAction( - QtGui.QIcon(self.resourcespath + 'page_white_key.png'), getMessage("createcontrolledroom-menu-label")) + QtGui.QPixmap(self.resourcespath + 'page_white_key.png'), getMessage("createcontrolledroom-menu-label")) window.createcontrolledroomAction.triggered.connect(self.createControlledRoom) - window.identifyascontroller = window.advancedMenu.addAction(QtGui.QIcon(self.resourcespath + 'key_go.png'), + window.identifyascontroller = window.advancedMenu.addAction(QtGui.QPixmap(self.resourcespath + 'key_go.png'), getMessage("identifyascontroller-menu-label")) window.identifyascontroller.triggered.connect(self.identifyAsController) @@ -1327,7 +1327,7 @@ class MainWindow(QtGui.QMainWindow): # Window menu - window.windowMenu = QtGui.QMenu(getMessage("window-menu-label"), self) + window.windowMenu = QtWidgets.QMenu(getMessage("window-menu-label"), self) window.playbackAction = window.windowMenu.addAction(getMessage("playbackbuttons-menu-label")) window.playbackAction.setCheckable(True) @@ -1341,11 +1341,15 @@ class MainWindow(QtGui.QMainWindow): # Help menu - window.helpMenu = QtGui.QMenu(getMessage("help-menu-label"), self) - window.userguideAction = window.helpMenu.addAction(QtGui.QIcon(self.resourcespath + 'help.png'), + window.helpMenu = QtWidgets.QMenu(getMessage("help-menu-label"), self) + if sys.platform.startswith('darwin'): + window.about = window.helpMenu.addAction("&About") + window.about.triggered.connect(self.openAbout) + + window.userguideAction = window.helpMenu.addAction(QtGui.QPixmap(self.resourcespath + 'help.png'), getMessage("userguide-menu-label")) window.userguideAction.triggered.connect(self.openUserGuide) - window.updateAction = window.helpMenu.addAction(QtGui.QIcon(self.resourcespath + 'application_get.png'), + window.updateAction = window.helpMenu.addAction(QtGui.QPixmap(self.resourcespath + 'application_get.png'), getMessage("update-menu-label")) window.updateAction.triggered.connect(self.userCheckForUpdates) @@ -1353,8 +1357,11 @@ class MainWindow(QtGui.QMainWindow): if not sys.platform.startswith('darwin'): window.mainLayout.setMenuBar(window.menuBar) + def openAbout(self): + AboutMsgBox = QtGui.QMessageBox.about(self,"Syncplay","Syncplay v" + version) + def addMainFrame(self, window): - window.mainFrame = QtGui.QFrame() + window.mainFrame = QtWidgets.QFrame() window.mainFrame.setLineWidth(0) window.mainFrame.setMidLineWidth(0) window.mainFrame.setContentsMargins(0, 0, 0, 0) @@ -1414,16 +1421,16 @@ class MainWindow(QtGui.QMainWindow): def updateReadyIcon(self): ready = self.readyPushButton.isChecked() if ready: - self.readyPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'tick_checkbox.png')) + self.readyPushButton.setIcon(QtGui.QPixmap(self.resourcespath + 'tick_checkbox.png')) else: - self.readyPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'empty_checkbox.png')) + self.readyPushButton.setIcon(QtGui.QPixmap(self.resourcespath + 'empty_checkbox.png')) def updateAutoPlayIcon(self): ready = self.autoplayPushButton.isChecked() if ready: - self.autoplayPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'tick_checkbox.png')) + self.autoplayPushButton.setIcon(QtGui.QPixmap(self.resourcespath + 'tick_checkbox.png')) else: - self.autoplayPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'empty_checkbox.png')) + self.autoplayPushButton.setIcon(QtGui.QPixmap(self.resourcespath + 'empty_checkbox.png')) def automaticUpdateCheck(self): currentDateTime = datetime.utcnow() @@ -1459,12 +1466,12 @@ class MainWindow(QtGui.QMainWindow): if userInitiated == True: updateURL = constants.SYNCPLAY_DOWNLOAD_URL if updateURL is not None: - reply = QtGui.QMessageBox.question(self, "Syncplay", - updateMessage, QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.No) - if reply == QtGui.QMessageBox.Yes: + reply = QtWidgets.QMessageBox.question(self, "Syncplay", + updateMessage, QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No) + if reply == QtWidgets.QMessageBox.Yes: self.QtGui.QDesktopServices.openUrl(QUrl(updateURL)) elif userInitiated: - QtGui.QMessageBox.information(self, "Syncplay", updateMessage) + QtWidgets.QMessageBox.information(self, "Syncplay", updateMessage) else: self.showMessage(updateMessage) @@ -1476,8 +1483,8 @@ class MainWindow(QtGui.QMainWindow): def dropEvent(self, event): rewindFile = False - if QtGui.QDropEvent.proposedAction(event) == Qt.MoveAction: - QtGui.QDropEvent.setDropAction(event, Qt.CopyAction) # Avoids file being deleted + if QtWidgets.QDropEvent.proposedAction(event) == Qt.MoveAction: + QtWidgets.QDropEvent.setDropAction(event, Qt.CopyAction) # Avoids file being deleted rewindFile = True data = event.mimeData() urls = data.urls() @@ -1618,15 +1625,18 @@ class MainWindow(QtGui.QMainWindow): self.resourcespath = utils.findWorkingDir() + u"\\resources\\" else: self.resourcespath = utils.findWorkingDir() + u"/resources/" - self.setWindowFlags(self.windowFlags() & Qt.AA_DontUseNativeMenuBar) + if sys.platform.startswith('darwin'): + self.setWindowFlags(self.windowFlags()) + else: + self.setWindowFlags(self.windowFlags() & Qt.AA_DontUseNativeMenuBar) self.setWindowTitle("Syncplay v" + version) - self.mainLayout = QtGui.QVBoxLayout() + self.mainLayout = QtWidgets.QVBoxLayout() self.addTopLayout(self) self.addBottomLayout(self) self.addMenubar(self) self.addMainFrame(self) self.loadSettings() - self.setWindowIcon(QtGui.QIcon(self.resourcespath + u"syncplay.png")) + self.setWindowIcon(QtGui.QPixmap(self.resourcespath + u"syncplay.png")) self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & Qt.AA_DontUseNativeMenuBar & Qt.WindowMinimizeButtonHint & ~Qt.WindowContextHelpButtonHint) self.show() self.setAcceptDrops(True) diff --git a/syncplay/utils.py b/syncplay/utils.py index 1857127..5b8cbb4 100644 --- a/syncplay/utils.py +++ b/syncplay/utils.py @@ -124,6 +124,8 @@ def findWorkingDir(): path = os.path.dirname(os.path.dirname(__file__)) elif frozen in ('dll', 'console_exe', 'windows_exe'): path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) + elif frozen in ('macosx_app'): + path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))) else: path = "" return path diff --git a/syncplay/vendor/qt4reactor.py b/syncplay/vendor/qt5reactor.py similarity index 60% rename from syncplay/vendor/qt4reactor.py rename to syncplay/vendor/qt5reactor.py index a337099..b53e97b 100644 --- a/syncplay/vendor/qt4reactor.py +++ b/syncplay/vendor/qt5reactor.py @@ -1,5 +1,76 @@ -# Copyright (c) 2001-2011 Twisted Matrix Laboratories. -# See LICENSE for details. +# -*- coding: utf-8 -*- +# Copyright (c) 2001-2017 +# Allen Short +# Andy Gayton +# Andrew Bennetts +# Antoine Pitrou +# Apple Computer, Inc. +# Ashwini Oruganti +# bakbuk +# Benjamin Bruheim +# Bob Ippolito +# Burak Nehbit +# Canonical Limited +# Christopher Armstrong +# Christopher R. Wood +# David Reid +# Donovan Preston +# Elvis Stansvik +# Eric Mangold +# Eyal Lotem +# Glenn Tarbox +# Google Inc. +# Hybrid Logic Ltd. +# Hynek Schlawack +# Itamar Turner-Trauring +# James Knight +# Jason A. Mobarak +# Jean-Paul Calderone +# Jessica McKellar +# Jonathan Jacobs +# Jonathan Lange +# Jonathan D. Simms +# Jürgen Hermann +# Julian Berman +# Kevin Horn +# Kevin Turner +# Kyle Altendorf +# Laurens Van Houtven +# Mary Gardiner +# Matthew Lefkowitz +# Massachusetts Institute of Technology +# Moshe Zadka +# Paul Swartz +# Pavel Pergamenshchik +# Ralph Meijer +# Richard Wall +# Sean Riley +# Software Freedom Conservancy +# Tarashish Mishra +# Travis B. Hartwell +# Thijs Triemstra +# Thomas Herve +# Timothy Allen +# Tom Prince + +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ @@ -7,13 +78,8 @@ This module provides support for Twisted to be driven by the Qt mainloop. In order to use this support, simply do the following:: | app = QApplication(sys.argv) # your code to init Qt - | import qt4reactor - | qt4reactor.install() - -alternatively: - - | from twisted.application import reactors - | reactors.installReactor('qt4') + | import qt5reactor + | qt5reactor.install() Then use twisted.internet APIs as usual. The other methods here are not intended to be called directly. @@ -27,65 +93,61 @@ Twisted can be initialized after QApplication.exec_() with a call to reactor.runReturn(). calling reactor.stop() will unhook twisted but leave your Qt application running -API Stability: stable +Qt5 Port: U{Burak Nehbit} -Maintainer: U{Glenn H Tarbox, PhD} +Current maintainer: U{Christopher R. Wood} +Previous maintainer: U{Tarashish Mishra} +Previous maintainer: U{Glenn H Tarbox, PhD} Previous maintainer: U{Itamar Shtull-Trauring} Original port to QT4: U{Gabe Rudy} Subsequent port by therve """ import sys -import time -from zope.interface import implements + +from PySide2.QtCore import ( + QCoreApplication, QEventLoop, QObject, QSocketNotifier, QTimer, Signal) +from twisted.internet import posixbase from twisted.internet.interfaces import IReactorFDSet from twisted.python import log, runtime -from twisted.internet import posixbase -from twisted.python.runtime import platformType, platform - -try: - from PyQt4.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication - from PyQt4.QtCore import QEventLoop -except ImportError: - from PySide.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication - from PySide.QtCore import QEventLoop +from zope.interface import implementer class TwistedSocketNotifier(QObject): - """ - Connection between an fd event and reader/writer callbacks. - """ + """Connection between an fd event and reader/writer callbacks.""" + + activated = Signal(int) def __init__(self, parent, reactor, watcher, socketType): QObject.__init__(self, parent) self.reactor = reactor self.watcher = watcher - fd = watcher.fileno() - self.notifier = QSocketNotifier(fd, socketType, parent) + fd = self.watcher.fileno() + self.notifier = QSocketNotifier(watcher, socketType, parent) self.notifier.setEnabled(True) if socketType == QSocketNotifier.Read: self.fn = self.read else: self.fn = self.write - QObject.connect(self.notifier, SIGNAL("activated(int)"), self.fn) - + self.notifier.activated.connect(self.fn) def shutdown(self): self.notifier.setEnabled(False) - self.disconnect(self.notifier, SIGNAL("activated(int)"), self.fn) + self.notifier.activated.disconnect(self.fn) self.fn = self.watcher = None self.notifier.deleteLater() self.deleteLater() - def read(self, fd): if not self.watcher: return w = self.watcher - # doRead can cause self.shutdown to be called so keep a reference to self.watcher + # doRead can cause self.shutdown to be called so keep + # a reference to self.watcher + def _read(): - #Don't call me again, until the data has been read + # Don't call me again, until the data has been read self.notifier.setEnabled(False) why = None try: @@ -98,18 +160,20 @@ class TwistedSocketNotifier(QObject): if why: self.reactor._disconnectSelectable(w, why, inRead) elif self.watcher: - self.notifier.setEnabled(True) # Re enable notification following sucessfull read + self.notifier.setEnabled(True) + # Re enable notification following sucessfull read self.reactor._iterate(fromqt=True) + log.callWithLogger(w, _read) def write(self, sock): if not self.watcher: return w = self.watcher + def _write(): why = None self.notifier.setEnabled(False) - try: why = w.doWrite() except: @@ -120,12 +184,13 @@ class TwistedSocketNotifier(QObject): elif self.watcher: self.notifier.setEnabled(True) self.reactor._iterate(fromqt=True) + log.callWithLogger(w, _write) - +@implementer(IReactorFDSet) class QtReactor(posixbase.PosixReactorBase): - implements(IReactorFDSet) + # implements(IReactorFDSet) def __init__(self): self._reads = {} @@ -133,19 +198,17 @@ class QtReactor(posixbase.PosixReactorBase): self._notifiers = {} self._timer = QTimer() self._timer.setSingleShot(True) - QObject.connect(self._timer, SIGNAL("timeout()"), self.iterate) - + self._timer.timeout.connect(self.iterate_qt) if QCoreApplication.instance() is None: # Application Object has not been started yet - self.qApp=QCoreApplication([]) - self._ownApp=True + self.qApp = QCoreApplication([]) + self._ownApp = True else: self.qApp = QCoreApplication.instance() - self._ownApp=False + self._ownApp = False self._blockApp = None posixbase.PosixReactorBase.__init__(self) - def _add(self, xer, primary, type): """ Private method for adding a descriptor from the event loop. @@ -156,21 +219,14 @@ class QtReactor(posixbase.PosixReactorBase): if xer not in primary: primary[xer] = TwistedSocketNotifier(None, self, xer, type) - def addReader(self, reader): - """ - Add a FileDescriptor for notification of data available to read. - """ + """Add a FileDescriptor for notification of data available to read.""" self._add(reader, self._reads, QSocketNotifier.Read) - def addWriter(self, writer): - """ - Add a FileDescriptor for notification of data available to write. - """ + """Add a FileDescriptor for notification of data available to write.""" self._add(writer, self._writes, QSocketNotifier.Write) - def _remove(self, xer, primary): """ Private method for removing a descriptor from the event loop. @@ -182,81 +238,66 @@ class QtReactor(posixbase.PosixReactorBase): notifier = primary.pop(xer) notifier.shutdown() - def removeReader(self, reader): - """ - Remove a Selectable for notification of data available to read. - """ + """Remove a Selectable for notification of data available to read.""" self._remove(reader, self._reads) - def removeWriter(self, writer): - """ - Remove a Selectable for notification of data available to write. - """ + """Remove a Selectable for notification of data available to write.""" self._remove(writer, self._writes) - def removeAll(self): - """ - Remove all selectables, and return a list of them. - """ - rv = self._removeAll(self._reads, self._writes) - return rv - + """Remove all selectables, and return a list of them.""" + return self._removeAll(self._reads, self._writes) def getReaders(self): return self._reads.keys() - def getWriters(self): return self._writes.keys() - - def callLater(self,howlong, *args, **kargs): - rval = super(QtReactor,self).callLater(howlong, *args, **kargs) + def callLater(self, howlong, *args, **kargs): + rval = super(QtReactor, self).callLater(howlong, *args, **kargs) self.reactorInvocation() return rval - def reactorInvocation(self): self._timer.stop() self._timer.setInterval(0) self._timer.start() - def _iterate(self, delay=None, fromqt=False): - """See twisted.internet.interfaces.IReactorCore.iterate. - """ + """See twisted.internet.interfaces.IReactorCore.iterate.""" self.runUntilCurrent() - self.doIteration(delay, fromqt) + self.doIteration(delay, fromqt=fromqt) iterate = _iterate + def iterate_qt(self, delay=None): + self.iterate(delay=delay, fromqt=True) + def doIteration(self, delay=None, fromqt=False): - 'This method is called by a Qt timer or by network activity on a file descriptor' - + """This method is called by a Qt timer or by network activity on a file descriptor""" if not self.running and self._blockApp: self._blockApp.quit() self._timer.stop() + if delay is None: + delay = 0 delay = max(delay, 1) if not fromqt: self.qApp.processEvents(QEventLoop.AllEvents, delay * 1000) - if self.timeout() is None: - timeout = 0.1 - elif self.timeout() == 0: - timeout = 0 + t = self.timeout() + if t is None: + timeout = 0.01 else: - timeout = self.timeout() + timeout = min(t, 0.01) self._timer.setInterval(timeout * 1000) self._timer.start() - def runReturn(self, installSignalHandlers=True): self.startRunning(installSignalHandlers=installSignalHandlers) self.reactorInvocation() - def run(self, installSignalHandlers=True): if self._ownApp: self._blockApp = self.qApp @@ -264,6 +305,21 @@ class QtReactor(posixbase.PosixReactorBase): self._blockApp = QEventLoop() self.runReturn() self._blockApp.exec_() + if self.running: + self.stop() + self.runUntilCurrent() + + # def sigInt(self, *args): + # print('I received a sigint. BAIBAI') + # posixbase.PosixReactorBase.sigInt() + # + # def sigTerm(self, *args): + # print('I received a sigterm. BAIBAI') + # posixbase.PosixReactorBase.sigTerm() + # + # def sigBreak(self, *args): + # print('I received a sigbreak. BAIBAI') + # posixbase.PosixReactorBase.sigBreak() class QtEventReactor(QtReactor): @@ -271,22 +327,15 @@ class QtEventReactor(QtReactor): self._events = {} super(QtEventReactor, self).__init__() - def addEvent(self, event, fd, action): - """ - Add a new win32 event to the event loop. - """ + """Add a new win32 event to the event loop.""" self._events[event] = (fd, action) - def removeEvent(self, event): - """ - Remove an event. - """ + """Remove an event.""" if event in self._events: del self._events[event] - def doEvents(self): handles = self._events.keys() if len(handles) > 0: @@ -304,46 +353,33 @@ class QtEventReactor(QtReactor): #print 'Got an unexpected return of %r' % val return - def _runAction(self, action, fd): try: closed = getattr(fd, action)() except: closed = sys.exc_info()[1] log.deferr() - if closed: self._disconnectSelectable(fd, closed, action == 'doRead') - - def timeout(self): - t = super(QtEventReactor, self).timeout() - return min(t, 0.01) - - - def iterate(self, delay=None): - """See twisted.internet.interfaces.IReactorCore.iterate. - """ + def iterate(self, delay=None, fromqt=False): + """See twisted.internet.interfaces.IReactorCore.iterate.""" self.runUntilCurrent() self.doEvents() - self.doIteration(delay) + self.doIteration(delay, fromqt=fromqt) def posixinstall(): - """ - Install the Qt reactor. - """ - p = QtReactor() + """Install the Qt reactor.""" from twisted.internet.main import installReactor + p = QtReactor() installReactor(p) def win32install(): - """ - Install the Qt reactor. - """ - p = QtEventReactor() + """Install the Qt reactor.""" from twisted.internet.main import installReactor + p = QtEventReactor() installReactor(p) @@ -356,4 +392,3 @@ else: __all__ = ["install"] -