diff --git a/.travis.yml b/.travis.yml index d898521..ea21be9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,43 +1,32 @@ language: objective-c -osx_image: xcode7.3 +osx_image: xcode6.4 branches: only: - - pyside2 + - qtpy-pyside1 script: -- python buildPy2app.py py2app +- python buildPy2app.py py2app fix before_install: -- curl -O https://raw.githubusercontent.com/Homebrew/homebrew-core/fdfc724dd532345f5c6cdf47dc43e99654e6a5fd/Formula/qt5.rb -- brew install ./qt5.rb -- which python -- which pip -- pip install http://syncplay.s3.amazonaws.com/PySide2-5.6-cp27-cp27m-macosx_10_11_x86_64.whl -- ln -s /usr/local/lib/python2.7/site-packages/PySide2/libshiboken2-python2.7v.2.0.0.dylib /usr/local/lib/ -- ln -s /usr/local/lib/python2.7/site-packages/PySide2/libshiboken2-python2.7v.2.0.dylib /usr/local/lib/ -- ln -s /usr/local/lib/python2.7/site-packages/PySide2/libshiboken2-python2.7v.dylib /usr/local/lib/ -- ln -s /usr/local/lib/python2.7/site-packages/PySide2/libpyside2-python2.7v.2.0.0.dylib /usr/local/lib/ -- ln -s /usr/local/lib/python2.7/site-packages/PySide2/libpyside2-python2.7v.2.0.dylib /usr/local/lib/ -- ln -s /usr/local/lib/python2.7/site-packages/PySide2/libpyside2-python2.7v.dylib /usr/local/lib/ -- python -c "from PySide2 import QtCore" -- hg clone https://alby128@bitbucket.org/alby128/py2app -- cd py2app -- python setup.py install -- python -c "from py2app.recipes import pyside2" +- brew install python +- brew tap cartr/qt4 +- brew tap-pin cartr/qt4 +- brew install pyside install: - -- pip install twisted appnope pyobjc -- git clone -b pyside2 https://github.com/alby128/syncplay.git syncplay_PySide2 -- cd syncplay_PySide2 -- git checkout pyside2 +- export PATH=/usr/local/bin:$PATH +- export QT_PREFERRED_BINDING="PySide" +- pip install twisted appnope pyobjc py2app +- git clone -b qtpy-pyside1 https://github.com/alby128/syncplay.git syncplay-qtpy-pyside1 +- cd syncplay-qtpy-pyside1 +- git checkout qtpy-pyside1 before_deploy: - pip install dmgbuild - mkdir dist_dmg - mv resources/macos_vlc_install.command resources/.macos_vlc_install.command -- dmgbuild -s appdmg.py "Syncplay" dist_dmg/Syncplay-PySide2.dmg +- dmgbuild -s appdmg.py "Syncplay" dist_dmg/Syncplay-qtpy-pyside1.dmg deploy: provider: s3 @@ -49,4 +38,4 @@ deploy: region: eu-central-1 local_dir: dist_dmg on: - branch: pyside2 \ No newline at end of file + branch: qtpy-pyside1 \ No newline at end of file diff --git a/buildPy2app.py b/buildPy2app.py index 4ed17d9..963089a 100644 --- a/buildPy2app.py +++ b/buildPy2app.py @@ -5,20 +5,23 @@ Usage: python setup.py py2app """ -from setuptools import setup +from setuptools import setup, Command from glob import glob +import shutil import syncplay +cmdlist = {} + APP = ['syncplayClient.py'] DATA_FILES = [ ('resources', glob('resources/*.png') + glob('resources/*.rtf')), ] OPTIONS = { 'iconfile':'resources/icon.icns', - 'includes': {'PySide2.QtCore', 'PySide2.QtUiTools', 'PySide2.QtGui','PySide2.QtWidgets'}, - 'excludes': {'PySide', 'PySide.QtCore', 'PySide.QtUiTools', 'PySide.QtGui'}, - 'qt_plugins': ['platforms/libqcocoa.dylib', 'platforms/libqminimal.dylib','platforms/libqoffscreen.dylib'], - 'plist': { + 'includes': {'PySide.QtCore', 'PySide.QtUiTools', 'PySide.QtGui'}, + 'excludes': {'PySide2', 'PySide2.QtCore', 'PySide2.QtUiTools', 'PySide2.QtGui','PySide2.QtWidgets', 'PyQt5'}, + 'dylib_excludes': {'QtDesigner.framework', 'QtScript.framework'}, + 'plist': { 'CFBundleName':'Syncplay', 'CFBundleShortVersionString':syncplay.version, 'CFBundleIdentifier':'pl.syncplay.Syncplay', @@ -26,10 +29,32 @@ OPTIONS = { } } +class Fix(Command): + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def trim_packages(self): + """Remove big files in external dependencies that Syncplay doesn't need""" + + shutil.rmtree('dist/Syncplay.app/Contents/Frameworks/QtDesigner.framework', ignore_errors=True) + shutil.rmtree('dist/Syncplay.app/Contents/Frameworks/QtScript.framework', ignore_errors=True) + shutil.rmtree('dist/Syncplay.app/Contents/Frameworks/QtXml.framework', ignore_errors=True) + + def run(self): + self.trim_packages() + +cmdlist['fix'] = Fix + setup( app=APP, name='Syncplay', data_files=DATA_FILES, options={'py2app': OPTIONS}, setup_requires=['py2app'], + cmdclass=cmdlist ) diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py index aeb282d..f607c7e 100755 --- a/syncplay/ui/ConfigurationGetter.py +++ b/syncplay/ui/ConfigurationGetter.py @@ -400,19 +400,19 @@ class ConfigurationGetter(object): sys.exit() self._overrideConfigWithArgs(args) if not self._config['noGui']: - try: - from syncplay.vendor.Qt import QtWidgets - from syncplay.vendor.Qt.QtCore import QCoreApplication - from syncplay.vendor import qt5reactor - if QCoreApplication.instance() is None: - self.app = QtWidgets.QApplication(sys.argv) - qt5reactor.install() - if sys.platform.startswith('darwin'): - import appnope - appnope.nope() - except ImportError: - print getMessage("unable-import-gui-error") - self._config['noGui'] = True + # try: + from syncplay.vendor.Qt import QtWidgets + from syncplay.vendor.Qt.QtCore import QCoreApplication + from syncplay.vendor import qt5reactor + if QCoreApplication.instance() is None: + self.app = QtWidgets.QApplication(sys.argv) + qt5reactor.install() + if sys.platform.startswith('darwin'): + import appnope + appnope.nope() + # except ImportError: + # print getMessage("unable-import-gui-error") + # self._config['noGui'] = True if self._config['file'] and self._config['file'][:2] == "--": self._config['playerArgs'].insert(0, self._config['file']) self._config['file'] = None diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 10e1d42..c1b4f07 100755 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -1,8 +1,7 @@ from syncplay.vendor.Qt import QtCore, QtWidgets, QtGui, __binding__ from syncplay.vendor.Qt.QtCore import Qt, QSettings, QCoreApplication, QSize, QPoint, QUrl, QLine from syncplay.vendor.Qt.QtWidgets import QApplication, QLineEdit, QLabel, QCheckBox, QButtonGroup, QRadioButton, QDoubleSpinBox, QPlainTextEdit -from syncplay.vendor.Qt.QtGui import QCursor, QIcon, QImage -from PySide2.QtCore import QStandardPaths +from syncplay.vendor.Qt.QtGui import QCursor, QIcon, QImage, QDesktopServices from syncplay.players.playerFactory import PlayerFactory from datetime import datetime from syncplay import utils @@ -347,10 +346,10 @@ class ConfigDialog(QtWidgets.QDialog): defaultdirectory = self.config["mediaSearchDirectories"][0] elif os.path.isdir(self.mediadirectory): defaultdirectory = self.mediadirectory - 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] + elif os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.MoviesLocation)): + defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.MoviesLocation) + elif os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.HomeLocation)): + defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.HomeLocation) else: defaultdirectory = "" browserfilter = "All files (*)" diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py index 49beef2..9acc4e5 100755 --- a/syncplay/ui/gui.py +++ b/syncplay/ui/gui.py @@ -1,7 +1,6 @@ from syncplay.vendor import Qt from syncplay.vendor.Qt import QtWidgets, QtGui, __binding__ from syncplay.vendor.Qt.QtCore import Qt, QSettings, QSize, QPoint, QUrl, QLine, QDateTime -from PySide2.QtCore import QStandardPaths from syncplay import utils, constants, version, release_number from syncplay.messages import getMessage import sys @@ -13,6 +12,8 @@ import os from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration, RoomPasswordProvider, formatSize, isURL from functools import wraps from twisted.internet import task +if sys.platform.startswith('darwin'): + from Foundation import NSURL lastCheckedForUpdates = None class UserlistItemDelegate(QtWidgets.QStyledItemDelegate): @@ -214,7 +215,10 @@ class MainWindow(QtWidgets.QMainWindow): indexRow = window.playlist.count() if window.clearedPlaylistNote else 0 for url in urls[::-1]: - dropfilepath = os.path.abspath(unicode(url.toLocalFile())) + if sys.platform.startswith('darwin'): + dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) + else: + dropfilepath = os.path.abspath(unicode(url.toLocalFile())) if os.path.isfile(dropfilepath): window.addFileToPlaylist(dropfilepath, indexRow) elif os.path.isdir(dropfilepath): @@ -316,7 +320,10 @@ class MainWindow(QtWidgets.QMainWindow): if indexRow == -1: indexRow = window.playlist.count() for url in urls[::-1]: - dropfilepath = os.path.abspath(unicode(url.toLocalFile())) + if sys.platform.startswith('darwin'): + dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) + else: + dropfilepath = os.path.abspath(unicode(url.toLocalFile())) if os.path.isfile(dropfilepath): window.addFileToPlaylist(dropfilepath, indexRow) elif os.path.isdir(dropfilepath): @@ -819,10 +826,10 @@ class MainWindow(QtWidgets.QMainWindow): defaultdirectory = self.config["mediaSearchDirectories"][0] elif includeUserSpecifiedDirectories and os.path.isdir(self.mediadirectory): defaultdirectory = self.mediadirectory - 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] + 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) else: defaultdirectory = "" return defaultdirectory @@ -834,7 +841,10 @@ class MainWindow(QtWidgets.QMainWindow): return self.loadMediaBrowseSettings() - options = QtWidgets.QFileDialog.Options() + if sys.platform.startswith('darwin'): + options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.DontUseNativeDialog) + else: + 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): @@ -859,7 +869,10 @@ class MainWindow(QtWidgets.QMainWindow): return self.loadMediaBrowseSettings() - options = QtWidgets.QFileDialog.Options() + if sys.platform.startswith('darwin'): + options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.DontUseNativeDialog) + else: + 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): @@ -1007,7 +1020,12 @@ class MainWindow(QtWidgets.QMainWindow): @needsClient def openAddMediaDirectoryDialog(self, MediaDirectoriesTextbox, MediaDirectoriesDialog): - folderName = unicode(QtWidgets.QFileDialog.getExistingDirectory(self,None,self.getInitialMediaDirectory(includeUserSpecifiedDirectories=False),QtWidgets.QFileDialog.ShowDirsOnly)) + if sys.platform.startswith('darwin'): + options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog) + else: + options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly) + folderName = unicode(QtGui.QFileDialog.getExistingDirectory(self,None,self.getInitialMediaDirectory(includeUserSpecifiedDirectories=False),options)) + if folderName: existingMediaDirs = MediaDirectoriesTextbox.toPlainText() if existingMediaDirs == "": @@ -1543,7 +1561,10 @@ class MainWindow(QtWidgets.QMainWindow): data = event.mimeData() urls = data.urls() if urls and urls[0].scheme() == 'file': - dropfilepath = os.path.abspath(unicode(event.mimeData().urls()[0].toLocalFile())) + if sys.platform.startswith('darwin'): + dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) + else: + dropfilepath = os.path.abspath(unicode(url.toLocalFile())) if rewindFile == False: self._syncplayClient._player.openFile(dropfilepath) else: diff --git a/syncplay/vendor/Qt.py b/syncplay/vendor/Qt.py index 5115221..ee87d1b 100755 --- a/syncplay/vendor/Qt.py +++ b/syncplay/vendor/Qt.py @@ -1032,7 +1032,7 @@ def _pyside2(): def _pyside(): """Initialise PySide""" - + import PySide as module _setup(module, ["QtUiTools"]) @@ -1433,6 +1433,7 @@ def _cli(args): def _install(): # Default order (customise order and content via QT_PREFERRED_BINDING) default_order = ("PySide2", "PyQt5", "PySide", "PyQt4") + preferred_order = list( b for b in QT_PREFERRED_BINDING.split(os.pathsep) if b ) diff --git a/syncplay/vendor/qt5reactor.py b/syncplay/vendor/qt5reactor.py index b53e97b..cde2b5e 100644 --- a/syncplay/vendor/qt5reactor.py +++ b/syncplay/vendor/qt5reactor.py @@ -106,7 +106,7 @@ Subsequent port by therve import sys -from PySide2.QtCore import ( +from syncplay.vendor.Qt.QtCore import ( QCoreApplication, QEventLoop, QObject, QSocketNotifier, QTimer, Signal) from twisted.internet import posixbase from twisted.internet.interfaces import IReactorFDSet