diff --git a/openlp.pyw b/openlp.pyw index 85ba81fba..ad06cfe0f 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -273,6 +273,9 @@ def main(): qInitResources() # Now create and actually run the application. app = OpenLP(qt_args) + if sys.platform == 'darwin': + OpenLP.addLibraryPath(QtGui.QApplication.applicationDirPath() + + "/qt4_plugins") #i18n Set Language language = LanguageManager.get_language() appTranslator = LanguageManager.get_translator(language) diff --git a/resources/osx/Info.plist.master b/resources/osx/Info.plist.master new file mode 100755 index 000000000..e97e1faf5 --- /dev/null +++ b/resources/osx/Info.plist.master @@ -0,0 +1,32 @@ + + + + +CFBundleIdentifier +org.openlp +CFBundleShortVersionString +%(openlp_version)s +CFBundleVersion +%(openlp_version)s +CFBundleInfoDictionaryVersion +6.0 +CFBundleDisplayName +%(openlp_appname)s +CFBundleIconFile +openlp-logo-with-text.icns +CFBundleExecutable +MacOS/openlp +CFBundleName +%(openlp_appname)s +CFBundleGetInfoString +%(openlp_appname)s %(openlp_version)s +LSHasLocalizedDisplayName + +NSAppleScriptEnabled + +CFBundlePackageType +APPL +LSBackgroundOnly + + + diff --git a/resources/osx/Makefile b/resources/osx/Makefile new file mode 100644 index 000000000..422749da5 --- /dev/null +++ b/resources/osx/Makefile @@ -0,0 +1,28 @@ +all: + python build.py -c openlp.cfg + +view: + python build.py -c openlp.cfg --package-view --compress-view + +package: + + python build.py -c openlp.cfg --package --package-view + +bundle: + + python build.py -c openlp.cfg --compress --compress-view + +clean: + # remove old configuration files + rm -f openlp.spec + rm -f Info.plist + rm -f .version + + # remove old build artifacts + rm -rf build + rm -rf dist + rm -rf Macopenlp.app + rm -rf OpenLP.app + rm -f warnopenlp.txt + rm -f *dmg + diff --git a/resources/osx/applescript-adjustview-10-5.master b/resources/osx/applescript-adjustview-10-5.master new file mode 100755 index 000000000..abc0e5a8d --- /dev/null +++ b/resources/osx/applescript-adjustview-10-5.master @@ -0,0 +1,74 @@ +on saveImageWithItselfAsIcon(icon_image_file) + -- save icon_image_file with itself as icon + set icon_image_file_string to icon_image_file as string + tell application "Image Events" + launch + set icon_image to open file icon_image_file_string + save icon_image with icon + close icon_image + end tell +end saveImageWithItselfAsIcon + +on copyIconOfTo(aFileOrFolderWithIcon, aFileOrFolder) + tell application "Finder" to set f to aFileOrFolderWithIcon as alias + -- grab the file's icon + my CopyOrPaste(f, "c") + -- now the icon is in the clipboard + tell application "Finder" to set c to aFileOrFolder as alias + my CopyOrPaste(result, "v") +end copyIconOfTo + +on CopyOrPaste(i, cv) + tell application "Finder" + activate + open information window of i + end tell + tell application "System Events" to tell process "Finder" to tell window 1 + keystroke tab -- select icon button + keystroke (cv & "w") using command down (* (copy or paste) + close window *) + end tell -- window 1 then process Finder then System Events +end CopyOrPaste + +on run + set icon_image_file to POSIX file "%s" as alias + set dmg_file to POSIX file "/Volumes/%s" as alias + + my saveImageWithItselfAsIcon(icon_image_file) + -- wait for virus scanner + delay 2 + my copyIconOfTo(icon_image_file, dmg_file) + + tell application "Finder" + tell disk "%s" + open + set current view of container window to icon view + set toolbar visible of container window to false + set statusbar visible of container window to false + set the bounds of container window to {400, 100, 1100, 500} + set theViewOptions to the icon view options of container window + set arrangement of theViewOptions to not arranged + set icon size of theViewOptions to 128 + set background picture of theViewOptions to file ".installer-background.png" + if not exists file "Applications" then + make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"} + end if + delay 5 + set position of item "%s" of container window to {160, 200} + set position of item ".Trashes" of container window to {100, 500} + set position of item ".installer-background.png" of container window to {200, 500} + set position of item ".DS_Store" of container window to {400, 500} + set position of item "Applications" of container window to {550, 200} + set position of item ".VolumeIcon.icns" of container window to {500, 500} + set position of item ".fseventsd" of container window to {300, 500} + if exists POSIX file ".SymAVx86QSFile" then + set position of item ".SymAVx86QSFile" of container window to {600, 500} + end if + open + close + update without registering applications + -- wait until the virus scan completes + delay 5 + -- eject + end tell + end tell +end run diff --git a/resources/osx/applescript-adjustview-10-6.master b/resources/osx/applescript-adjustview-10-6.master new file mode 100755 index 000000000..2b5a0c000 --- /dev/null +++ b/resources/osx/applescript-adjustview-10-6.master @@ -0,0 +1,73 @@ +on saveImageWithItselfAsIcon(icon_image_file) + -- save icon_image_file with itself as icon + set icon_image_file_string to icon_image_file as string + tell application "Image Events" + launch + set icon_image to open file icon_image_file_string + save icon_image with icon + close icon_image + end tell +end saveImageWithItselfAsIcon + +on copyIconOfTo(aFileOrFolderWithIcon, aFileOrFolder) + tell application "Finder" to set f to aFileOrFolderWithIcon as alias + -- grab the file's icon + my CopyOrPaste(f, "c") + -- now the icon is in the clipboard + tell application "Finder" to set c to aFileOrFolder as alias + my CopyOrPaste(result, "v") +end copyIconOfTo + +on CopyOrPaste(i, cv) + tell application "Finder" + activate + set infoWindow to open information window of i + set infoWindowName to name of infoWindow + end tell + tell application "System Events" to tell process "Finder" to tell window infoWindowName + keystroke tab -- select icon button + keystroke (cv & "w") using command down (* (copy or paste) + close window *) + end tell -- window 1 then process Finder then System Events +end CopyOrPaste + +on run + set icon_image_file to POSIX file "%s" as alias + set dmg_file to POSIX file "/Volumes/%s" as alias + + my saveImageWithItselfAsIcon(icon_image_file) + -- wait for virus scanner + delay 2 + my copyIconOfTo(icon_image_file, dmg_file) + + tell application "Finder" + tell disk "%s" + open + set current view of container window to icon view + set toolbar visible of container window to false + set statusbar visible of container window to false + set the bounds of container window to {400, 100, 1100, 500} + set theViewOptions to the icon view options of container window + set arrangement of theViewOptions to not arranged + set icon size of theViewOptions to 128 + set background picture of theViewOptions to file ".installer-background.png" + make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"} + delay 5 + set position of item "%s" of container window to {160, 200} + set position of item ".Trashes" of container window to {100, 500} + set position of item ".installer-background.png" of container window to {200, 500} + set position of item ".DS_Store" of container window to {400, 500} + set position of item "Applications" of container window to {550, 200} + set position of item ".VolumeIcon.icns" of container window to {500, 500} + set position of item ".fseventsd" of container window to {300, 500} + if exists POSIX file ".SymAVx86QSFile" then + set position of item ".SymAVx86QSFile" of container window to {600, 500} + end if + open + close + update without registering applications + -- wait until the virus scan completes + delay 5 + -- eject + end tell + end tell +end run diff --git a/resources/osx/applescript-seticon-10-5.master b/resources/osx/applescript-seticon-10-5.master new file mode 100755 index 000000000..738c4b883 --- /dev/null +++ b/resources/osx/applescript-seticon-10-5.master @@ -0,0 +1,40 @@ +on saveImageWithItselfAsIcon(icon_image_file) + -- save icon_image_file with itself as icon + set icon_image_file_string to icon_image_file as string + tell application "Image Events" + launch + set icon_image to open file icon_image_file_string + save icon_image with icon + close icon_image + end tell +end saveImageWithItselfAsIcon + +on copyIconOfTo(aFileOrFolderWithIcon, aFileOrFolder) + tell application "Finder" to set f to aFileOrFolderWithIcon as alias + -- grab the file's icon + my CopyOrPaste(f, "c") + -- now the icon is in the clipboard + tell application "Finder" to set c to aFileOrFolder as alias + my CopyOrPaste(result, "v") +end copyIconOfTo + +on CopyOrPaste(i, cv) + tell application "Finder" + activate + open information window of i + end tell + tell application "System Events" to tell process "Finder" to tell window 1 + keystroke tab -- select icon button + keystroke (cv & "w") using command down (* (copy or paste) + close window *) + end tell -- window 1 then process Finder then System Events +end CopyOrPaste + +on run + set icon_image_file to POSIX file "%s" as alias + set dmg_file to POSIX file "%s" as alias + + my saveImageWithItselfAsIcon(icon_image_file) + -- wait for virus scanner + delay 2 + my copyIconOfTo(icon_image_file, dmg_file) +end run diff --git a/resources/osx/applescript-seticon-10-6.master b/resources/osx/applescript-seticon-10-6.master new file mode 100755 index 000000000..849f02344 --- /dev/null +++ b/resources/osx/applescript-seticon-10-6.master @@ -0,0 +1,41 @@ +on saveImageWithItselfAsIcon(icon_image_file) + -- save icon_image_file with itself as icon + set icon_image_file_string to icon_image_file as string + tell application "Image Events" + launch + set icon_image to open file icon_image_file_string + save icon_image with icon + close icon_image + end tell +end saveImageWithItselfAsIcon + +on copyIconOfTo(aFileOrFolderWithIcon, aFileOrFolder) + tell application "Finder" to set f to aFileOrFolderWithIcon as alias + -- grab the file's icon + my CopyOrPaste(f, "c") + -- now the icon is in the clipboard + tell application "Finder" to set c to aFileOrFolder as alias + my CopyOrPaste(result, "v") +end copyIconOfTo + +on CopyOrPaste(i, cv) + tell application "Finder" + activate + set infoWindow to open information window of i + set infoWindowName to name of infoWindow + end tell + tell application "System Events" to tell process "Finder" to tell window infoWindowName + keystroke tab -- select icon button + keystroke (cv & "w") using command down (* (copy or paste) + close window *) + end tell -- window 1 then process Finder then System Events +end CopyOrPaste + +on run + set icon_image_file to POSIX file "%s" as alias + set dmg_file to POSIX file "%s" as alias + + my saveImageWithItselfAsIcon(icon_image_file) + -- wait for virus scanner + delay 2 + my copyIconOfTo(icon_image_file, dmg_file) +end run diff --git a/resources/osx/build.py b/resources/osx/build.py new file mode 100644 index 000000000..dfe0b897a --- /dev/null +++ b/resources/osx/build.py @@ -0,0 +1,412 @@ +#!/usr/bin/python +# -*- encoding: utf-8 -*- + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +""" +Mac OS X Build Script +--------------------- + +This script is used to build the OS X binary and the accompanying installer. +For this script to work out of the box, it depends on a number of things: + +Python 2.6 + This build script only works with Python 2.6. + +PyQt4 + You should already have this installed, OpenLP doesn't work without it. + The version the script expects is the packaged one available from River + Bank Computing. + +PyInstaller + PyInstaller should be a checkout of revision 1355 of trunk, and in a + directory which is configured in the openlp.cfg. The revision is very + important as there is just included a fix for builds on OS X. + + To install PyInstaller, first checkout trunk from Subversion. The + easiest way is to do a + + svn co http://svn.pyinstaller.org/trunk + + Then you need to copy the two hook-*.py files from the "pyinstaller" + subdirectory in OpenLP's "resources" directory into PyInstaller's + "hooks" directory. + +openlp.cfg + The configuration file contains settings of the version string to include + in the bundle as well as directory and file settings for different + purposes (e.g. PyInstaller location or installer background image) + +To start the build process do a + + make + +inside the resources/osx directory. The result should be a {openlp_dmgname}.dmg +file in the same directory. If something went wrong - this sometimes happen +with the graphical commands in the Apple script - do a + + make clean + +and start the build process again. If you want to execute only parts of the +build process you can specify different make targets + + make view -- runs the Apple scripts to set the icons + make package -- creates the dmg file and copies the application files + make bundle -- compresses the dmg file and sets the dmg file icon +""" + +import time +import os +import ConfigParser +import logging +import optparse +import sys +import platform +import re +import subprocess as subp + +# set the script name +script_name = "build" + +def build_application(settings, app_name_lower, app_dir): + logging.info('[%s] now building the app with pyinstaller at "%s"...', + script_name, settings['pyinstaller_basedir']) + result = os.system('python %s/pyinstaller.py openlp.spec' \ + % settings['pyinstaller_basedir']) + if (result != 0): + logging.error('[%s] The pyinstaller build reported an error, cannot \ + continue!', script_name) + sys.exit(1) + + logging.info('[%s] copying the qt_menu files...', script_name) + # see http://www.pyinstaller.org/ticket/157 + result = os.system('cp -R %(qt_menu_directory)s \ + %(application_directory)s/Contents/Resources' \ + % { 'qt_menu_directory' : settings['qt_menu_basedir'], + 'application_directory' : app_dir }) + if (result != 0): + logging.error('[%s] could not copy the qt_menu files, cannot \ + continue!', script_name) + sys.exit(1) + + dist_folder = os.getcwd() + '/dist/' + app_name_lower + + logging.info('[%s] copying the new plugins...', script_name) + result = os.system('cp -R %(openlp_directory)s/openlp/plugins \ + %(application_directory)s/Contents/MacOS' \ + % { 'openlp_directory' : settings['openlp_basedir'], + 'application_directory' : app_dir }) + if (result != 0): + logging.error('[%s] could not copy plugins, dmg creation failed!', + script_name) + sys.exit(1) + + logging.info('[%s] copying the icons to the resource directory...', + script_name) + result = os.system('cp %(icon_file)s \ + %(application_directory)s/Contents/Resources' \ + % { 'icon_file' : settings['openlp_icon_file'], + 'application_directory' : app_dir }) + if (result != 0): + logging.error('[%s] could not copy the icon, dmg creation failed!', + script_name) + sys.exit(1) + + logging.info('[%s] copying the version file...', script_name) + result = os.system('CpMac %s/.version %s/Contents/MacOS' % (os.getcwd(), + app_dir)) + if (result != 0): + logging.error('[%s] could not copy the version file, dmg creation \ + failed!', script_name) + sys.exit(1) + + logging.info('[%s] copying the new Info.plist...', script_name) + result = os.system('cp %(target_directory)s/Info.plist \ + %(application_directory)s/Contents' \ + % { 'target_directory' : os.getcwd(), + 'application_directory' : app_dir }) + if (result != 0): + logging.error('[%s] could not copy the info file, dmg creation \ + failed!', script_name) + sys.exit(1) + +def deploy_qt(settings): + logging.info('[%s] running mac deploy qt on %s.app...', script_name, + settings['openlp_appname']); + + result = os.system('macdeployqt %s.app' % settings['openlp_appname']); + if (result != 0): + logging.error('[%s] could not create dmg file!', script_name) + sys.exit(1) + +def create_dmg(settings): + logging.info('[%s] creating the dmg...', script_name) + dmg_file = os.getcwd() + '/' + settings['openlp_dmgname'] + '.dmg' + result = os.system('hdiutil create %(dmg_file)s~ -ov -megabytes \ + %(vol_size)s -fs HFS+ -volname %(vol_name)s' \ + % { 'dmg_file' : dmg_file, + 'vol_size' : '250', + 'vol_name' : settings['openlp_appname'] }) + if (result != 0): + logging.error('[%s] could not create dmg file!', script_name) + sys.exit(1) + + logging.info('[%s] mounting the dmg file...', script_name) + output = subp.Popen(["hdiutil", "attach", dmg_file + "~.dmg"], + stdout=subp.PIPE).communicate()[0] + logging.debug(output) + + p = re.compile('Apple_HFS\s+(.+?)\s*$') + result = p.search(output, re.M) + volume_basedir = '' + if result: + volume_basedir = result.group(1) + else: + logging.error('could not mount dmg file, cannot continue!') + sys.exit(1) + + logging.info('[%s] copying the app (from %s) to the dmg (at %s)...', + script_name, app_dir, volume_basedir) + result = os.system('CpMac -r %s %s' \ + % ( app_dir, volume_basedir )) + if (result != 0): + logging.error('[%s] could not copy application, dmg creation failed!', + script_name) + sys.exit(1) + + logging.info('[%s] copying the background image...', script_name) + # os.mkdir(volume_basedir + '/.background') + result = os.system('CpMac %s %s' + % (settings['installer_backgroundimage_file'], + volume_basedir + '/.installer-background.png')) + if (result != 0): + logging.error('[%s] could not copy the background image, dmg creation\ + failed!', script_name) + sys.exit(1) + + return (volume_basedir, dmg_file) + +def unmount_dmg(settings, volume_basedir): + logging.info('[%s] unmounting the dmg...', script_name) + result = os.system('hdiutil detach %s' % volume_basedir) + if (result != 0): + logging.error('[%s] could not unmount the dmg file, dmg creation \ + failed!', script_name) + sys.exit(1) + +def compress_view(settings, seticon_scriptname, dmg_file): + logging.info('[%s] setting icon of the dmg file...', script_name) + try: + f = open(seticon_scriptname) + p = subp.Popen(["osascript"], stdin=subp.PIPE) + p.communicate(f.read() % ((os.getcwd() + '/' + + settings['openlp_dmg_icon_file']), dmg_file)) + f.close() + result = p.returncode + if (result != 0): + logging.error('[%s] could not set the icon to the dmg file, \ + dmg creation failed!', script_name) + sys.exit(1) + except IOError, e: + logging.error('[%s] could not adjust the view (%s), dmg creation \ + failed!', script_name, e) + sys.exit(1) + except OSError, e: + logging.error('[%s] could not set the icon to the dmg file(%s), \ + dmg creation failed!', script_name, e) + sys.exit(1) + +def adjust_package_view(settings, adjustview_scriptname): + logging.info('[%s] making adjustments to the view...', script_name) + try: + f = open(adjustview_scriptname) + p = subp.Popen(["osascript"], stdin=subp.PIPE) + p.communicate(f.read() % ((os.getcwd() + '/' + \ + settings['openlp_dmg_icon_file']), + settings['openlp_appname'], + settings['openlp_appname'], + settings['openlp_appname'])) + f.close() + result = p.returncode + if (result != 0): + logging.error('[%s] could not adjust the view, dmg creation \ + failed!', script_name) + sys.exit(1) + except IOError, e: + logging.error('[%s] could not adjust the view (%s), dmg creation \ + failed!', script_name, e) + sys.exit(1) + except OSError, e: + logging.error('[%s] could not adjust the view (%s), dmg creation \ + failed!', script_name, e) + sys.exit(1) + +def compress_dmg(settings): + logging.info('[%s] compress the dmg file...', script_name) + result = os.system('hdiutil convert %s~.dmg -format UDZO \ + -imagekey zlib-level=9 -o %s' \ + % (dmg_file, dmg_file)) + if (result != 0): + logging.error('[%s] could not compress the dmg file, dmg creation \ + failed!', script_name) + sys.exit(1) + + +if __name__ == '__main__': + + # set default actions + do_build = True + do_compress_view = True + do_package_view = True + do_create_dmg = True + do_compress_dmg = True + do_deploy_qt = True + + parser = optparse.OptionParser() + parser.add_option('-c', '--config', dest='config', help='config file', + metavar='CONFIG') + parser.add_option('-v', '--package-view', dest='package_view', + help='triggers view adjustment scripts for package', + metavar='PACKAGEVIEWONLY', action='store_true', default=False) + parser.add_option('-y', '--compress-view', dest='compress_view', + help='triggers view adjustment scripts for dmg', + metavar='COMPRESSVIEWONLY', action='store_true', default=False) + parser.add_option('-p', '--package', dest='package', + help='package application folder to dmg', metavar='PACKAGE', + action='store_true', default=False) + parser.add_option('-z', '--compress', dest='compress', + help='compresses the existing dmg', metavar='COMPRESS', + action='store_true', default=False) + parser.add_option('-b', '--basedir', dest='basedir', + help='volume basedir like /Volumes/OpenLP', metavar='BASEDIR', + default='/Volumes/OpenLP') + + (options, args) = parser.parse_args() + + # if an option is set, false all + if (options.package_view is True or options.compress_view is True + or options.package is True or options.compress is True): + do_build = False + do_deploy_qt = False + do_package_view = options.package_view + do_compress_view = options.compress_view + do_create_dmg = options.package + do_compress_dmg = options.compress + + if not options.config: + parser.error('option --config|-c is required') + + logHandler = logging.StreamHandler() + logHandler.setFormatter(logging.Formatter( + '%(asctime)s %(levelname)-8s %(message)s', + '%a, %d %b %Y %H:%M:%S')) + logging.getLogger().addHandler(logHandler) + logging.getLogger().setLevel(logging.DEBUG) + + config = ConfigParser.RawConfigParser() + config.readfp(open(options.config, 'r')) + + if not config.has_section('openlp'): + logging.error('[%s] config file "%s" lacks an [openlp] section', + script_name, options.config) + sys.exit(1) + + if not sys.platform == "darwin": + logging.error('[%s] this script only works on Macintosh OS X systems,' + + 'not on %s', script_name, sys.platform) + sys.exit(1) + + version = platform.mac_ver()[0] + # we only need the differenciation between leopard and snow leopard + if version.startswith("10.6"): + SNOWLEOPARD = True + logging.info('[%s] using snow leopard scripts (version = %s)', + script_name, version) + adjustview_scriptname = "applescript-adjustview-10-6.master" + seticon_scriptname = "applescript-seticon-10-6.master" + else: + SNOWLEOPARD = False + logging.info('[%s] using leopard scripts (version = %s)', script_name, + version) + adjustview_scriptname = "applescript-adjustview-10-5.master" + seticon_scriptname = "applescript-seticon-10-5.master" + + if not os.path.isfile(adjustview_scriptname) \ + or not os.path.isfile(seticon_scriptname): + logging.error('[%s] could not find apple scripts for given OS X ' + + 'version %s', script_name, version) + sys.exit(1) + + settings = dict() + for k in config.options('openlp'): + settings[k] = config.get('openlp', k) + + # prepare the configuration files + os.system('python expander.py --config %(config_file)s \ + --template openlp.spec.master \ + --expandto %(target_directory)s/openlp.spec' \ + % { 'config_file' : options.config, 'target_directory' : os.getcwd() }) + os.system('python expander.py --config %(config_file)s \ + --template Info.plist.master \ + --expandto %(target_directory)s/Info.plist' \ + % { 'config_file' : options.config, 'target_directory' : os.getcwd() }) + os.system('python expander.py --config %(config_file)s \ + --template version.master \ + --expandto %(target_directory)s/.version' \ + % { 'config_file' : options.config, 'target_directory' : os.getcwd() }) + + # prepare variables + app_name_lower = settings['openlp_appname'].lower() + app_dir = os.getcwd() + '/' + settings['openlp_appname'] + '.app' + + # if the view option is set, skip the building steps + if (do_build is True): + build_application(settings, app_name_lower, app_dir) + + if (do_deploy_qt is True): + deploy_qt(settings) + + if (do_create_dmg is True): + (volume_basedir, dmg_file) = create_dmg(settings) + else: + # setting base dir + volume_basedir = options.basedir + dmg_file = os.getcwd() + '/' + settings['openlp_dmgname'] + '.dmg' + + if (do_package_view is True): + adjust_package_view(settings, adjustview_scriptname) + + if (do_create_dmg is True): + unmount_dmg(settings, volume_basedir) + + if (do_compress_dmg is True): + compress_dmg(settings) + + if (do_compress_view is True): + compress_view(settings, seticon_scriptname, dmg_file) + + if (do_compress_dmg is True): + logging.info('[%s] finished creating dmg file, resulting file is "%s"', + script_name, dmg_file) + diff --git a/resources/osx/expander.py b/resources/osx/expander.py new file mode 100755 index 000000000..77b0d1441 --- /dev/null +++ b/resources/osx/expander.py @@ -0,0 +1,202 @@ +#!/usr/bin/python +# -*- encoding: utf-8 -*- + +# TODOs: +# - defaults for non-supplied expansions: +# template contains + +import ConfigParser +import logging +import optparse +import os +import re +import sys + +# variable expansion: +# - %(dog)s --- normal python expansion +# - %(dog%)s --- no python expansion, leave as is (stripping the trailing %) +# - %(dog:cat) --- if there is an expansion for dog, dog will be used; +# otherwise if cat exists cat will be used +# - %(dog=cat) --- if there is an expansion for dog, dog will be used; +# otherwise "cat" will be used +# re_conf = re.compile(r'(?[^\(]+?)\)s') +re_conf = re.compile(r'(?P%?)%\((?P[^+=:&\)]+?)' + + '(?:(?P[+=:&])(?P[^\)]+))?\)(?Ps|d)') + +def expand_variable(match, expansions, errors): + key = match.group('key') + kind = match.group('kind') + default = match.group('default') + typ = match.group('type') + verbatim = match.group('verbatim') + + if verbatim: + return match.group(0)[1:] + + # literal default + if kind == '=': + if key in expansions: + return expansions[key] + return default + + # variable default + if kind == ':' and default in expansions: + return expansions[default] + + if kind == '+' and default in expansions: + if key in expansions: + key = expansions[key] + if typ == 's': + return '%s%s' % (key, expansions[default]) + if typ == 'd': + try: + return str(int(key) + int(expansions[default])) + except: + pass + + if kind == '&' and default in expansions: + if typ == 's': + return '%s%s' % (key, expansions[default]) + if typ == 'd': + try: + return str(int(key) + int(expansions[default])) + except: + pass + + if key in expansions: + return expansions[key] + + if not match.group(0) in errors: + errors.append(match.group(0)) + + return None + +options = None + +if __name__ == '__main__': + + # get config file + parser = optparse.OptionParser() + parser.add_option('-c', '--config', dest='config', + help='config file', metavar='CONFIG') + parser.add_option('-t', '--template', dest='template', + help='template file', metavar='TEMPLATE') + parser.add_option('-x', '--expandto', dest='expanded', + help='expanded file', metavar='EXPANDED') + parser.add_option('-e', '--echo', dest='echo', + help='echo variable', metavar='ECHOVAR') + + (options, args) = parser.parse_args() + + if not options.config: + parser.error('option --config|-c is required') + if not os.path.exists(options.config): + parser.error('config file "%s" does not exist' % options.config) + if not options.echo: + if not options.template: + parser.error('option --template|-t is required') + if not os.path.exists(options.template): + parser.error('template file "%s" does not exist' \ + % options.template) + if not options.expanded: + parser.error('option --expandto|-e is required') + + logHandler = logging.StreamHandler() + logHandler.setFormatter(logging.Formatter('%(asctime)s %(levelname)-8s ' + + ' %(message)s', '%a, %d %b %Y %H:%M:%S')) + logging.getLogger().addHandler(logHandler) + logging.getLogger().setLevel(logging.DEBUG) + + config = ConfigParser.RawConfigParser() + config.readfp(open(options.config, 'r')) + + if not config.has_section('openlp'): + logging.error('[expander] %s: config file "%s" lacks an [openlp] ' + + 'section', options.template, options.config) + + expansions = dict() + for k in config.options('openlp'): + expansions[k] = config.get('openlp', k) + + # commandline overrides? + for override in args: + if not '=' in override: + continue + + (k, v) = override.split('=', 2) + expansions[k] = v + + if options.echo: + if options.echo in expansions: + print expansions[options.echo] + sys.exit(0) + else: + sys.exit(1) + + # closure to capture expansions and errors variable + errors = [] + expanded = [] + + try: + # try to expand the template + line = 0 + faulty = False + + template = open(options.template, 'r') + raw = template.readlines() + template.close() + + def _expand(m): + return expand_variable(m, expansions = expansions, errors = errors) + + for l in raw: + line += 1 + exp = re_conf.sub(_expand, l) + if errors: + for key in errors: + logging.error('[expander] %s: line %d: could not expand ' + + 'key "%s"', options.template, line, key) + faulty = True + errors = [] + else: + expanded.append(exp) + + if faulty: + sys.exit(1) + + # successfully expanded template, now backup potentially existing + # target file + targetFile = options.expanded % expansions + if os.path.exists(targetFile): + if os.path.exists('%s~' % targetFile): + os.unlink('%s~' % targetFile) + os.rename(options.expanded, '%s~' % targetFile) + logging.info('[expander] %s: backed up existing target file "%s" ' + + 'to "%s"', options.template, targetFile, + '%s~' % options.expanded) + + # make sure that target directory exists + targetDir = os.path.dirname(targetFile) + if not os.path.exists(targetDir): + os.makedirs(targetDir) + + # write target file + try: + target = open(targetFile, 'w') + for exp in expanded: + target.write(exp) + target.close() + except Exception, e: + logging.error('[expander] %s: could not expand to "%s"', + options.template, options.expaned, e) + + # copy over file access mode from template + mode = os.stat(options.template) + os.chmod(options.expanded, mode.st_mode) + + logging.info('[expander] expanded "%s" to "%s"', + options.template, options.expanded) + + except: + pass + diff --git a/resources/osx/installation-background.png b/resources/osx/installation-background.png new file mode 100755 index 000000000..8a41d3b68 Binary files /dev/null and b/resources/osx/installation-background.png differ diff --git a/resources/osx/openlp-logo-420x420-background.png b/resources/osx/openlp-logo-420x420-background.png new file mode 100755 index 000000000..1008621d6 Binary files /dev/null and b/resources/osx/openlp-logo-420x420-background.png differ diff --git a/resources/osx/openlp-logo-420x420.png b/resources/osx/openlp-logo-420x420.png new file mode 100644 index 000000000..85457d8fb Binary files /dev/null and b/resources/osx/openlp-logo-420x420.png differ diff --git a/resources/osx/openlp-logo-with-text.icns b/resources/osx/openlp-logo-with-text.icns new file mode 100755 index 000000000..6066b111e Binary files /dev/null and b/resources/osx/openlp-logo-with-text.icns differ diff --git a/resources/osx/openlp-splash-screen.png b/resources/osx/openlp-splash-screen.png new file mode 100755 index 000000000..618e47c6e Binary files /dev/null and b/resources/osx/openlp-splash-screen.png differ diff --git a/resources/osx/openlp.cfg b/resources/osx/openlp.cfg new file mode 100755 index 000000000..1f04861b5 --- /dev/null +++ b/resources/osx/openlp.cfg @@ -0,0 +1,11 @@ +[openlp] +openlp_appname = OpenLP +openlp_dmgname = OpenLP-1.9.4-bzrXXXX +openlp_version = XXXX +openlp_full_version = 1.9.4-latest +openlp_basedir = /Users/openlp/trunk +openlp_icon_file = openlp-logo-with-text.icns +openlp_dmg_icon_file = openlp-logo-420x420.png +installer_backgroundimage_file = installation-background.png +pyinstaller_basedir = /Users/openlp/pyinstaller/trunk +qt_menu_basedir = /Library/Frameworks/QtGui.framework/Versions/4/Resources/qt_menu.nib diff --git a/resources/osx/openlp.spec.master b/resources/osx/openlp.spec.master new file mode 100755 index 000000000..94aec2a60 --- /dev/null +++ b/resources/osx/openlp.spec.master @@ -0,0 +1,24 @@ +# -*- mode: python -*- +a = Analysis([os.path.join(HOMEPATH,'support/_mountzlib.py'), os.path.join(HOMEPATH,'support/useUnicode.py'), '%(openlp_basedir)s/openlp.pyw'], + pathex=['%(pyinstaller_basedir)s'], hookspath=['%(openlp_basedir)s/resources/pyinstaller']) +pyz = PYZ(a.pure) +exe = EXE(pyz, + a.scripts, + exclude_binaries=1, + name=os.path.join('build/pyi.darwin/openlp', 'openlp'), + debug=False, + strip=False, + upx=True, + console=1 ) +coll = COLLECT( exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + name=os.path.join('dist', 'openlp')) +import sys +if sys.platform.startswith("darwin"): + app = BUNDLE(coll, + name='%(openlp_appname)s.app', + version='%(openlp_version)s') diff --git a/resources/osx/version.master b/resources/osx/version.master new file mode 100755 index 000000000..d517a51bc --- /dev/null +++ b/resources/osx/version.master @@ -0,0 +1 @@ +%(openlp_full_version)s