Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Huge improvements in:

- the installer logic (python detection, ALLUSERS handling, etc)
- our PyGTK_CustomizeDlg
- runtime init cleanup
- aio installer builder
- more elaborate README
  • Loading branch information...
commit 27ca365e68d2d552bec47525bf5e7a42e1780739 1 parent 2293ecf
@dieterv authored
View
105 README.rst
@@ -3,28 +3,71 @@ WARNING
=======
The all-in-one installer should be considered as a proof of concept.
-Please do not use it on productions systems just yet!
+Please do not use it on production systems just yet!
-===============
-pygtk-installer
-===============
+====================================
+Using the PyGTK All-in-one installer
+====================================
-The pygtk-installer project provides a set of tools to build the PyGTK
-all-in-one installer and it's various dependencies.
-There are currently versions of the all-in-one installer targeting Python 2.6
-and Python 2.7.
+The PyGTK All-in-one version number
+===================================
-Included tools:
+The all-in-one installers' version number does not map directly to the
+pygtk version number. This is a requirement to support windows installer
+major upgrades. The version number is constructed as follows::
-- build_glade.sh: a tool that builds glade3 binaries for mswindows with
- "Python Widgets Support" for each supported Python version.
-- build_bindings.sh: a tool that builds windows installer packages (both .exe
- and .msi) for pycairo, pygobject, pygtk, pygoocanvas, pygtksourceview and
- pyrsvg for each supported Python version.
-- build_installer.py: a tool that generates an all-in-one installer bundling
- the separate .msi installers created by build_bindings.sh, the glade binaries
- created by build_glade.sh and various gtk+ runtime packages from
- ftp.gnome.org/pub/GNOME/binaries/win32/.
+ PYGTK_MAJOR.PYGTK_MINOR.INSTALLER_REVISION
+
+Stable releases are kept available for download, testing revisions are removed
+from the download area once they are superseded by newer versions.
+
+What file should I use?
+=======================
+
+All the .msi files are named as follows:
+
+ pygtk-all-in-one-X.X.X.win32-py2.6.msi
+
+Where X.X.X is the PyGTK All-in-one version number and
+Y.Y is the Python version number the installer supports.
+
+Migrating from pycairo+pygobject+pygtk packages
+===============================================
+
+If you have some or all of the separate pycaior, pygobject, pygtk, pygoocanvas,
+pygtksourceview2 or pyrsvg packages, please ensure they are uninstalled before
+you begin with the PyGTK All-in-one installer.
+
+The all-in-one installer does not check for their presence and will happily
+overwrite files that belong to the separate packages. If you forget to check
+for this you risk the following scenario:
+
+ - install Python
+ - install pycairo, pygtk and pygobject
+ - install pygtk all-in-one
+ - uninstall pycairo, pygtk and pygobject
+ you now have a *broken* pygtk all-in-one installation
+
+Now would also be a good time to uninstall the gtk+ runtime you've used
+with the separate pyg* packages and to clean your PATH environment variable.
+
+Automatic installation
+======================
+
+An automatic PyGTK All-in-one installation automatically detects the correct
+Python installation directory and if Python was installed for all users or just
+yourself. These values are then used by the PyGTK All-in-one installer.
+
+* If you want to generate a log file you can execute the following command from a
+ Command Prompt (change X to the correct version numbers)::
+
+ %WINDIR%\system32\msiexec.exe /i pygtk-all-in-one-X.X.X.winX-pyX.X.msi /l*v install.log
+
+ Note that having an installation log is the only way we can provide help should
+ something have gone wrong.
+
+* If you do not want to generate an installation log file you can simply double
+ click the .msi file that matches the Python version where you want to install PyGTK All-in-one.
=============================
Things you might want to know
@@ -65,15 +108,23 @@ Things you might want to know
- study both install.log and import.log...
-==========
-Versioning
-==========
+=======================
+Installer build scripts
+=======================
-The all-in-one installers' version number does not map directly to the
-pygtk version number. This is a requirement to support windows installer
-major upgrades. The version number is constructed as follows::
+The pygtk-installer project provides a set of tools to build the PyGTK
+all-in-one installer and it's various dependencies.
+There are currently versions of the all-in-one installer supporting Python 2.6
+and Python 2.7.
- PYGTK_MAJOR.PYGTK_MINOR.INSTALLER_REVISION
+Included tools:
-Stable releases are kept available for download, testing revisions are removed
-from the download area once they are superseeded by newer versions.
+- build_glade.sh: a tool that builds glade3 binaries for mswindows with
+ "Python Widgets Support" for each supported Python version.
+- build_bindings.sh: a tool that builds windows installer packages (both .exe
+ and .msi) for pycairo, pygobject, pygtk, pygoocanvas, pygtksourceview and
+ pyrsvg for each supported Python version.
+- build_installer.py: a tool that generates an all-in-one installer bundling
+ the separate .msi installers created by build_bindings.sh, the glade binaries
+ created by build_glade.sh and various gtk+ runtime packages from
+ ftp.gnome.org/pub/GNOME/binaries/win32/.
View
249 bin/build_installer.py
@@ -25,9 +25,10 @@
from copy import copy, deepcopy
from datetime import datetime
+from distutils.spawn import find_executable
from hashlib import md5
from optparse import OptionParser
-from os.path import abspath, dirname, isabs, isdir, isfile, join
+from os.path import abspath, basename, dirname, isabs, isdir, isfile, join
from shutil import copyfile, rmtree
from subprocess import Popen, PIPE
from urllib2 import urlopen, URLError
@@ -58,9 +59,8 @@
# Everything we need to know about the WiX toolset...
WIX_VERSION = '3.5.2305.0'
-WIX_NAMESPACE = 'http://schemas.microsoft.com/wix/2006/wi'
-WIX_NSMAP = {None : WIX_NAMESPACE}
-WIX_DIR = None
+WIX_NS = 'http://schemas.microsoft.com/wix/2006/wi'
+WIX_NSMAP = {None : WIX_NS}
WIX_HEAT = None
WIX_DARK = None
WIX_CANDLE = None
@@ -68,7 +68,7 @@
# Everything we need to know about xmllint...
XML_LINT_VERSION = 20707
-XML_LINT = 'xmllint'
+XML_LINT = None
def info(message, level=0):
@@ -99,27 +99,40 @@ def copytree(srcdir, dstdir):
srcnames = os.listdir(srcdir)
for name in srcnames:
- srcfname = join(srcdir, name)
- dstfname = join(dstdir, name)
+ srcname = join(srcdir, name)
+ dstname = join(dstdir, name)
- if isdir(srcfname):
- if not isdir(dstfname):
- os.mkdir(dstfname)
+ if isdir(srcname):
+ if not isdir(dstname):
+ os.mkdir(dstname)
- copytree(srcfname, dstfname)
- elif isfile(srcfname):
- sf = open(srcfname, 'rb')
- df = open(dstfname, 'wb')
+ copytree(srcname, dstname)
+ elif isfile(srcname):
+ sf = open(srcname, 'rb')
+ df = open(dstname, 'wb')
df.write(sf.read())
df.close()
sf.close()
+def get_md5(file):
+ m = md5()
+ f = open(file, 'rb')
+
+ while True:
+ t = f.read(1024)
+ if len(t) == 0: break # end of file
+ m.update(t)
+
+ f.close()
+
+ return m.hexdigest()
+
class Builder(object):
def __init__(self, arguments=None):
self.parse_options(arguments)
- self.validate_environment_wix()
- self.validate_environment_xmllint()
+ self.validate_wix()
+ self.validate_xmllint()
self.parse_build_description()
def parse_options(self, arguments=None):
@@ -133,23 +146,23 @@ def parse_options(self, arguments=None):
if not len(self.args) == 1:
error(parser.get_usage())
- def validate_environment_wix(self):
- global WIX_DIR
- global WIX_DARK
- global WIX_HEAT
- global WIX_CANDLE
- global WIX_LIGHT
-
- # Get WiX path from environment variable
+ def validate_wix(self):
+ # Get WiX installation directory from the WIX environment variable
if not os.environ.has_key('WIX'):
error('Please verify WiX has been installed and the WIX environment '
'variable points to it\'s installation directory.')
- WIX_DIR = join(abspath(os.environ['WIX']), 'bin')
+ WIX_DIR = abspath(join(os.environ['WIX'], 'bin'))
if not os.path.isdir(WIX_DIR):
- error('WiX bin directory does not seem to exist.')
+ error('Please verify WiX has been installed and the WIX environment '
+ 'variable points to it\'s installation directory, not it\'s '
+ 'bin directory.')
+ global WIX_DARK
+ global WIX_HEAT
+ global WIX_CANDLE
+ global WIX_LIGHT
WIX_HEAT = join(WIX_DIR, 'heat.exe')
WIX_DARK = join(WIX_DIR, 'dark.exe')
WIX_CANDLE = join(WIX_DIR, 'candle.exe')
@@ -165,70 +178,77 @@ def validate_environment_wix(self):
wix_version = re.compile(r"(version )(.*?)($)", re.S|re.M).search(output).group(2)
if not int(WIX_VERSION.replace('.', '')) <= int(wix_version.replace('.', '')):
- error('Your WiX (version %s) is too old. A mininmum of version %s is required.' % (wix_version, WIX_VERSION))
+ error('Your WiX (version %s) is too old. At least version %s is required.' % (wix_version, WIX_VERSION))
- def validate_environment_xmllint(self):
- #TODO: why global?
+ def validate_xmllint(self):
global XML_LINT
+ XML_LINT = find_executable('xmllint', os.environ['PATH'])
- try:
- output = Popen([XML_LINT,
- '--version'],
- stdout=PIPE,
- stderr=PIPE,
- universal_newlines=True).communicate()[1]
- except WindowsError as e:
- error('Please verify xmllint (part of libxml2) has been installed '
- 'and it\'s bin directory is on the PATH environment variable')
- else:
- xml_lint_version = re.compile(r"(version )(.*?)($)", re.S|re.M).search(output).group(2)
+ if not XML_LINT or not os.path.isfile(XML_LINT):
+ error('Please verify xmllint has been installed and the PATH environment '
+ 'variable points to it\'s installation directory.')
- if not XML_LINT_VERSION <= int(xml_lint_version):
- error('Your xmllint (version %s) is too old. A mininmum of version %s is required.' % (xml_lint_version, XML_LINT_VERSION))
+ # Validate xmllint version
+ output = Popen([XML_LINT,
+ '--version'],
+ stdout=PIPE,
+ stderr=PIPE,
+ universal_newlines=True).communicate()[1]
+
+ xml_lint_version = re.compile(r"(version )(.*?)($)", re.S|re.M).search(output).group(2)
+
+ if not XML_LINT_VERSION <= int(xml_lint_version):
+ error('Your xmllint (version %s) is too old. At least version %s is required.' % (xml_lint_version, XML_LINT_VERSION))
def parse_build_description(self):
- global CACHEDIR
+ target = self.args[0].split('.')
+ version = '%s.%s.%s' % (target[0], target[1], target[2])
+ platform = target[3]
- version = self.args[0]
- CACHEDIR = join(TMPDIR, 'cache', version)
+ global CACHEDIR
+ CACHEDIR = join(TMPDIR, 'cache', self.args[0])
+ buildfile = join(WIXDIR, '%s.xml' % self.args[0])
schemafile = join(WIXDIR, 'build.xsd')
- buildfile = join(WIXDIR, '%s.xml' % version)
if not isdir(CACHEDIR):
os.makedirs(CACHEDIR)
if not isfile(buildfile):
- error('Unable to load product "%s".' % buildfile)
+ error('Unable to load build description "%s".' % buildfile)
#schema = etree.XMLSchema(file=schemafile)
#parser = etree.XMLParser(schema=schema)
#self.buildfile = objectify.parse(buildfile, parser=parser).getroot()
self.buildfile = objectify.parse(buildfile).getroot()
+
+ # Store version number
etree.SubElement(self.buildfile, 'Version', Version=version)
- info('Loaded product "%s" (loaded from "%s").' % (version, buildfile))
+ # Store target platform
+ if platform in PLATFORMS.keys():
+ global WIN_PLATFORM
+ global WIX_PLATFORM
+ WIN_PLATFORM = platform
+ WIX_PLATFORM = PLATFORMS[platform]
+ else:
+ error('Unknown platform (%s).' % platform)
+
+ info('Loaded build description "%s" (loaded from "%s").' % (version, buildfile))
def build(self):
for child in self.buildfile.Interpreters.iterchildren():
if child.tag == 'Interpreter':
- if not child.get('Version') in PYTHON_VERSIONS:
+ if child.get('Version') in PYTHON_VERSIONS:
+ global PYTHON_FULLVERSION
+ global PYTHON_VERSION
+ PYTHON_FULLVERSION = child.get('Version')
+ PYTHON_VERSION = child.get('Version')
+
+ product = Product(self.buildfile)
+ product.merge()
+ else:
error('Unknown interpreter version (%s).' % child.get('Version'))
- if not child.get('Platform') in PLATFORMS.keys():
- error('Unknown platform (%s).' % child.get('Platform'))
-
- global WIN_PLATFORM
- global WIX_PLATFORM
- global PYTHON_FULLVERSION
- global PYTHON_VERSION
- WIN_PLATFORM = child.get('Platform')
- WIX_PLATFORM = PLATFORMS[child.get('Platform')]
- PYTHON_FULLVERSION = child.get('Version')
- PYTHON_VERSION = child.get('Version')
-
- product = Product(self.buildfile)
- product.merge()
-
class Product(object):
def __init__(self, buildfile):
@@ -240,7 +260,7 @@ def __init__(self, buildfile):
self.wixobjfilename = '%s.wixobj' % self.packageid
self.msifilename = '%s.msi' % self.packageid
- self.builddir = join(TMPDIR, 'build', '%s-%s' % (PYTHON_FULLVERSION, WIN_PLATFORM), self.packageid)
+ self.builddir = join(TMPDIR, 'build', '%s-py%s' % (WIN_PLATFORM, PYTHON_FULLVERSION), self.packageid)
self.tmpwxsfile = join(self.builddir, '%s.unformatted' % self.wxsfilename)
self.wxsfile = join(self.builddir, self.wxsfilename)
self.wixobjfile = join(self.builddir, self.wixobjfilename)
@@ -255,10 +275,7 @@ def merge(self):
self.do_transform()
self.do_compile()
self.do_link()
-
- f = open(join(self.builddir, 'install.cmd'), 'w')
- f.write('@echo off\r\nmsiexec /i %s /l*vx install.log\r\n' % self.msifile)
- f.close()
+ self.do_post_build()
info('Success: .msi installer targeting Python %s has been created ("%s")' % (PYTHON_FULLVERSION, self.msifile))
@@ -332,8 +349,8 @@ def transform_variables(self, wxsfile):
def transform_includes(self, wxsfile):
#TODO: there has to be a better way to get at elements than .find + .getnext... XPath???
- product = wxsfile.find('{%s}Product' % WIX_NAMESPACE)
- package = product.find('{%s}Package' % WIX_NAMESPACE)
+ product = wxsfile.find('{%s}Product' % WIX_NS)
+ package = product.find('{%s}Package' % WIX_NS)
def transform(element):
for child in element.iterchildren():
@@ -376,9 +393,9 @@ def transform(element, parent):
if 'Container' in element.keys() and element.get('Container').lower() == 'true':
# A Feature should always reference at least one component.
- # If we do not do this, the SelectionTree widget will ignore
- # the AllowAdvertise, InstallDefault and TypicalDefault
- # attributes set above. In other words,
+ # If we do not do this, the SelectionTree widget seems to
+ # ignore the AllowAdvertise, InstallDefault and
+ # TypicalDefault attributes set above. In other words:
etree.SubElement(feature, 'ComponentRef', Id='Empty')
for child in element.iterchildren():
@@ -386,7 +403,7 @@ def transform(element, parent):
elif element.tag == 'Package':
def traverse(child, parent):
- if child.tag == '{%s}Component' % WIX_NAMESPACE:
+ if child.tag == '{%s}Component' % WIX_NS:
etree.SubElement(parent, 'ComponentRef', Id=child.get('Id'))
else:
for x in child:
@@ -394,14 +411,14 @@ def traverse(child, parent):
wxifile = element.get('wxifile_%s' % PYTHON_VERSION)
iroot = etree.parse(wxifile).getroot()
- ITARGETDIR = iroot.find('{%s}DirectoryRef' % WIX_NAMESPACE)
+ ITARGETDIR = iroot.find('{%s}DirectoryRef' % WIX_NS)
assert ITARGETDIR.get('Id') == 'TARGETDIR'
for ichild in ITARGETDIR.iterchildren():
traverse(ichild, parent)
- product = wxsfile.find('{%s}Product' % WIX_NAMESPACE)
- feature = product.find('{%s}Feature' % WIX_NAMESPACE)
+ product = wxsfile.find('{%s}Product' % WIX_NS)
+ feature = product.find('{%s}Feature' % WIX_NS)
for child in self.buildfile.Product.Features.iterchildren():
transform(child, feature)
@@ -452,6 +469,13 @@ def do_link(self):
file.close()
+ def do_post_build(self):
+ # Create .md5 file
+ hexdigest = get_md5(self.msifile)
+ f = open(join(self.builddir, '%s.md5' % self.msifile), 'w')
+ f.write('%s *%s' % (hexdigest, self.msifilename))
+ f.close()
+
class SourcePackage(object):
@staticmethod
@@ -472,7 +496,7 @@ def __init__(self, buildfile, package):
self.package.set('Url', '%s/' % self.package.get('Url'))
self.cachefile = join(CACHEDIR, self.filename)
- self.builddir = join(TMPDIR, 'build', '%s-%s' % (PYTHON_FULLVERSION, WIN_PLATFORM), self.package.get('Id'))
+ self.builddir = join(TMPDIR, 'build', '%s-py%s' % (WIN_PLATFORM, PYTHON_FULLVERSION), self.package.get('Id'))
self.wxsfile = join(self.builddir, '%s.wxs' % self.package.get('Id'))
self.tmpwxifile = join(self.builddir, '%s.wxi.unformatted' % self.package.get('Id'))
self.wxifile = join(self.builddir, '%s.wxi' % self.package.get('Id'))
@@ -480,15 +504,7 @@ def __init__(self, buildfile, package):
self.package.set('wxifile_%s' % PYTHON_VERSION, self.wxifile)
def _check_md5(self, file, digest):
- m = md5()
- f = open(file, 'rb')
-
- while True:
- t = f.read(1024)
- if len(t) == 0: break # end of file
- m.update(t)
-
- hexdigest = m.hexdigest()
+ hexdigest = get_md5(file)
if digest == hexdigest:
return True
@@ -651,12 +667,12 @@ def do_build(self):
# Get the Wix/Product/Directory node
root = etree.parse(self.wxsfile).getroot()
- product = root.find('{%s}Product' % WIX_NAMESPACE)
- include = product.find('{%s}Directory' % WIX_NAMESPACE)
+ product = root.find('{%s}Product' % WIX_NS)
+ include = product.find('{%s}Directory' % WIX_NS)
# deepcopy the Wix/Product/Directory node into a new tree
- newroot = etree.Element('{%s}Include' % WIX_NAMESPACE, nsmap=WIX_NSMAP)
- newinclude = etree.SubElement(newroot, '{%s}DirectoryRef' % WIX_NAMESPACE, Id='TARGETDIR')
+ newroot = etree.Element('{%s}Include' % WIX_NS, nsmap=WIX_NSMAP)
+ newinclude = etree.SubElement(newroot, '{%s}DirectoryRef' % WIX_NS, Id='TARGETDIR')
for child in include:
newinclude.append(deepcopy(child))
@@ -679,7 +695,7 @@ def transform_remove_targetdirs(self, element):
Remove "TARGETDIR $(var.PythonVersion)" and "TARGETDIRX" elements so
they can be recreated with "RemoveFile" elements included.
'''
- tmp = element.find('{%s}DirectoryRef' % WIX_NAMESPACE)
+ tmp = element.find('{%s}DirectoryRef' % WIX_NS)
for child in tmp:
if child.get('Id').startswith('TARGETDIR'):
@@ -758,25 +774,25 @@ def do_build(self):
info('WiX "heat" reported error(s). Please review "%s".' % logfile, 4)
root = etree.parse(self.wxsfile).getroot()
- product = root.find('{%s}Product' % WIX_NAMESPACE)
- include = product.find('{%s}Directory' % WIX_NAMESPACE)
+ product = root.find('{%s}Product' % WIX_NS)
+ include = product.find('{%s}Directory' % WIX_NS)
# deepcopy the Wix/Product/Directory node into a new tree
- newroot = etree.Element('{%s}Include' % WIX_NAMESPACE, nsmap=WIX_NSMAP)
+ newroot = etree.Element('{%s}Include' % WIX_NS, nsmap=WIX_NSMAP)
targetdir = etree.SubElement(newroot,
- '{%s}DirectoryRef' % WIX_NAMESPACE,
+ '{%s}DirectoryRef' % WIX_NS,
Id='TARGETDIR')
libdir = etree.SubElement(targetdir,
- '{%s}Directory' % WIX_NAMESPACE,
+ '{%s}Directory' % WIX_NS,
Name='Lib', Id='Lib')
spdir = etree.SubElement(libdir,
- '{%s}Directory' % WIX_NAMESPACE,
+ '{%s}Directory' % WIX_NS,
Name='site-packages', Id='site_packages')
gtkdir = etree.SubElement(spdir,
- '{%s}Directory' % WIX_NAMESPACE,
+ '{%s}Directory' % WIX_NS,
Name='gtk-2.0', Id='gtk_2.0')
rtdir = etree.SubElement(gtkdir,
- '{%s}Directory' % WIX_NAMESPACE,
+ '{%s}Directory' % WIX_NS,
Name='runtime', Id='runtime')
for child in include:
@@ -791,10 +807,41 @@ def do_transform(self):
info ('Transforming variables...', 4)
self.transform_variables(self.include)
+ info ('Transforming RemoveFile elements for *.py files', 4)
+ self.transform_py_files(self.include)
+
def transform_variables(self, element):
pi = etree.ProcessingInstruction('define', '%s_sourcedir = "%s"' % (self.package.get('Id'), join(self.builddir, 'File')))
element.insert(0, pi)
+ def transform_py_files(self, element):
+ '''
+ Create a RemoveFile element instructing windows installer to remove
+ .pyc and .pyo files for each .py file we encounter.
+ '''
+ def transform(element):
+ if element.tag == '{%s}File' % WIX_NS and basename(element.get('Source')).endswith('.py'):
+ component = element.getparent()
+ directory = component.getparent()
+
+ etree.SubElement(component,
+ '{%s}RemoveFile' % WIX_NS,
+ Id='%sc' % element.get('Id'),
+ Directory=directory.get('Id'),
+ Name='%sc' % basename(element.get('Source')),
+ On='uninstall')
+ etree.SubElement(component,
+ '{%s}RemoveFile' % WIX_NS,
+ Id='%so' % element.get('Id'),
+ Directory=directory.get('Id'),
+ Name='%so' % basename(element.get('Source')),
+ On='uninstall')
+
+ for child in element:
+ transform(child)
+
+ transform(element)
+
def main():
start = datetime.now()
View
44 wix/2.22.2.xml → wix/2.22.3.win32.xml
@@ -2,28 +2,26 @@
<Build>
<!-- <Build xmlns="http://schemas.pygtk.org/2010/build"> -->
- <!-- Currently only 2.6 (x86) and 2.7 (x86) are supported (until I
- can get my hands on a 64bit machine...) -->
<Interpreters>
- <Interpreter Version="2.6" Platform="win32" />
- <!-- <Interpreter Version="2.6" Platform="win64" /> -->
- <Interpreter Version="2.7" Platform="win32" />
- <!-- <Interpreter Version="2.7" Platform="win64" /> -->
+ <Interpreter Version="2.6" />
+ <Interpreter Version="2.7" />
</Interpreters>
<!-- Some notes about the Level attribute of the Feature tag:
- - Level 0 : disable the feature and prevent it from being displayed
- in the user interface
- - Level 1 : default value of INSTALLLEVEL property
- - Level 3 : WiX Mondo UI Typical installation
- - Level 1000: WiX Mondo UI Complete installation -->
+ - Level 0 : do not install (disable the feature and prevent it from
+ being displayed in the user interface
+ - Level 1 : install by default (enable the feature and display it in
+ the user interface)
+ - Level 2 : install if requested (disable the feature but display it
+ in the user interface) -->
<Product>
<Features>
<Feature Id = "PythonExtensionModules"
- Title = "Python extension modules"
- Description = "Installs Python extension modules."
+ Title = "Python $(var.PythonVersion) extension modules"
+ Description = "Installs Python $(var.PythonVersion) extension modules."
Display = "expand"
+ Absent = "disallow"
Level = "1"
Container = "true">
@@ -79,7 +77,7 @@
Title = "PyGtkSourceView2 2.10.1"
Description = "Installs the gtksourceview2 Python extension module."
Absent = "allow"
- Level = "10">
+ Level = "2">
<Package Id = "pygtksourceview2"
Type = "MsiSourcePackage"
@@ -106,7 +104,7 @@
Title = "PyGooCanvas 0.14.2"
Description = "Installs the goocanvas Python extension module."
Absent = "allow"
- Level = "10">
+ Level = "2">
<Package Id = "pygoocanvas"
Type = "MsiSourcePackage"
@@ -133,7 +131,7 @@
Title = "PyRsvg 2.32.1"
Description = "Installs the rsvg Python extension module."
Absent = "allow"
- Level = "10">
+ Level = "2">
<Package Id = "pyrsvg"
Type = "MsiSourcePackage"
@@ -150,13 +148,13 @@
Description = "Installs development tools."
Absent = "allow"
Display = "expand"
- Level = "10"
+ Level = "2"
Container = "true">
<Feature Id = "glade"
Title = "Glade UI Designer 3.6.7"
Description = "Installs Glade UI Designer."
- Level = "10"
+ Level = "2"
Absent = "allow">
<Package Type = "ArchiveSourcePackage"
@@ -171,7 +169,7 @@
<Feature Id = "langtools"
Title = "Language Tools"
Description = "Installs intltool, gettext tools and libiconv."
- Level = "10"
+ Level = "2"
Absent = "allow">
<Package Id = "libiconv"
@@ -217,9 +215,9 @@
<Feature Id = "gtk_runtime"
Title = "GTK+ Runtime 2.22.0"
- Description = "Installs the GTK+ runtime"
- Level = "1"
- Absent = "disallow">
+ Description = "Installs the GTK+ runtime."
+ Absent = "disallow"
+ Level = "1">
<Package Type = "ArchiveSourcePackage"
Id = "gtk_runtime"
@@ -227,8 +225,6 @@
archive = "gtk+-bundle_2.22.0-20101016_win32.zip"
digest = "b0a879b50e5c86190c6fed4d7377aa5d">
- <!-- TODO: how do we add RemoveFile elements into the .wxs
- file for .pyc and .pyo files??? -->
<CopyFile Id="__init__.py" Src="overlays/runtime/" Dest="" />
<CopyFile Id="reconfig.cmd" Src="overlays/runtime/bin/" Dest="bin" />
<CopyFile Id="gtkrc" Src="overlays/runtime/etc/gtk-2.0/" Dest="etc/gtk-2.0/" />
View
315 wix/2.22.3.win64.xml
@@ -0,0 +1,315 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Build>
+<!-- <Build xmlns="http://schemas.pygtk.org/2010/build"> -->
+
+<!-- Currently 64bit installers are not supported (at least until I can get my
+ hands on a 64bit machine...) -->
+
+ <Interpreters>
+ <Interpreter Version="2.6" />
+ <Interpreter Version="2.7" />
+ </Interpreters>
+
+ <!-- Some notes about the Level attribute of the Feature tag:
+ - Level 0 : do not install (disable the feature and prevent it from
+ being displayed in the user interface
+ - Level 1 : install by default (enable the feature and display it in
+ the user interface)
+ - Level 2 : install if requested (disable the feature but display it
+ in the user interface) -->
+
+ <Product>
+ <Features>
+ <Feature Id = "PythonExtensionModules"
+ Title = "Python $(var.PythonVersion) extension modules"
+ Description = "Installs Python $(var.PythonVersion) extension modules."
+ Display = "expand"
+ Absent = "disallow"
+ Level = "1"
+ Container = "true">
+
+ <Feature Id = "PythonExtensionModulePyGtk"
+ Title = "PyGtk 2.22.0"
+ Description = "Installs the gtk, glade, pango, pangocairo and atk Python extension modules."
+ Absent = "disallow"
+ Level = "1">
+
+ <Package Type = "MsiSourcePackage"
+ Id = "pygtk"
+ Url = ""
+ Msi_26 = ""
+ Digest_26 = ""
+ Msi_27 = ""
+ Digest_27 = "" />
+ </Feature>
+
+ <Feature Id = "PythonExtensionModulePyGobject"
+ Title = "PyGobject 2.26.0"
+ Description = "Installs the gobject and gio Python extension modules."
+ Absent = "disallow"
+ Level = "1">
+
+ <Package Type = "MsiSourcePackage"
+ Id = "pygobject"
+ Url = ""
+ Msi_26 = ""
+ Digest_26 = ""
+ Msi_27 = ""
+ Digest_27 = "">
+
+ <CopyFile Id="pygtk.pth" Src="overlays/pygobject/" Dest=""/>
+ </Package>
+ </Feature>
+
+ <Feature Id = "PythonExtensionModulePyCairo"
+ Title = "PyGairo 1.8.10"
+ Description = "Installs the cairo Python extension module."
+ Absent = "disallow"
+ Level = "1">
+
+ <Package Type = "MsiSourcePackage"
+ Id = "pycairo"
+ Url = ""
+ Msi_26 = ""
+ Digest_26 = ""
+ Msi_27 = ""
+ Digest_27 = "" />
+ </Feature>
+
+ <Feature Id = "PythonExtensionModulePyGtkSourceview2"
+ Title = "PyGtkSourceView2 2.10.1"
+ Description = "Installs the gtksourceview2 Python extension module."
+ Absent = "allow"
+ Level = "2">
+
+ <Package Id = "pygtksourceview2"
+ Type = "MsiSourcePackage"
+ Url = ""
+ Msi_26 = ""
+ Msi_27 = ""
+ Digest_26 = ""
+ Digest_27 = "" />
+
+ <Package Id = "libgtksourceview"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Id = "libgtksourceview_dev"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+ </Feature>
+
+ <Feature Id = "PythonExtensionModulePyGoocanvas"
+ Title = "PyGooCanvas 0.14.2"
+ Description = "Installs the goocanvas Python extension module."
+ Absent = "allow"
+ Level = "2">
+
+ <Package Id = "pygoocanvas"
+ Type = "MsiSourcePackage"
+ Url = ""
+ Msi_26 = ""
+ Msi_27 = ""
+ Digest_26 = ""
+ Digest_27 = "" />
+
+ <Package Id = "libgoocanvas"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Id = "libgoocanvas_dev"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+ </Feature>
+
+ <Feature Id = "PythonExtensionModulePyRsvg"
+ Title = "PyRsvg 2.32.1"
+ Description = "Installs the rsvg Python extension module."
+ Absent = "allow"
+ Level = "2">
+
+ <Package Id = "pyrsvg"
+ Type = "MsiSourcePackage"
+ Url = ""
+ Msi_26 = ""
+ Msi_27 = ""
+ Digest_26 = ""
+ Digest_27 = "" />
+ </Feature>
+ </Feature>
+
+ <Feature Id = "DevelopmentTools"
+ Title = "Development Tools"
+ Description = "Installs development tools."
+ Absent = "allow"
+ Display = "expand"
+ Level = "2"
+ Container = "true">
+
+ <Feature Id = "glade"
+ Title = "Glade UI Designer 3.6.7"
+ Description = "Installs Glade UI Designer."
+ Level = "2"
+ Absent = "allow">
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "glade3"
+ Url = ""
+ Archive_26 = ""
+ Archive_27 = ""
+ Digest_26 = ""
+ Digest_27 = "" />
+ </Feature>
+
+ <Feature Id = "langtools"
+ Title = "Language Tools"
+ Description = "Installs intltool, gettext tools and libiconv."
+ Level = "2"
+ Absent = "allow">
+
+ <Package Id = "libiconv"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Id = "gettext_tools"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Id = "gettext_tools_dev"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Id = "intltool"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Id = "intltool_dev"
+ Type = "ArchiveSourcePackage"
+ Url = ""
+ archive = ""
+ digest = "" />
+ </Feature>
+ </Feature>
+
+ <Feature Id = "gtk_runtime"
+ Title = "GTK+ Runtime 2.22.0"
+ Description = "Installs the GTK+ runtime."
+ Absent = "disallow"
+ Level = "1">
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "gtk_runtime"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "libglade"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "libglade_dev"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "libxml2"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "libxml2_dev"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "librsvg"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "librsvg_dev"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "svg_gdk_pixbuf_loader"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "svg_gtk_engine"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "libcroco"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "libcroco_dev"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "libgsf"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "libgsf_dev"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "hicolor_icon_theme"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "icon_nameing_utils"
+ Url = ""
+ archive = ""
+ digest = "" />
+
+ <Package Type = "ArchiveSourcePackage"
+ Id = "tango_icon_theme"
+ Url = ""
+ archive = ""
+ digest = "" />
+ </Feature>
+ </Features>
+ </Product>
+</Build>
View
40 wix/build.xsd
@@ -25,9 +25,6 @@
</xs:annotation>
<xs:element name="Build">
- <xs:annotation><xs:documentation>
- This is the top-level container element for every build description file.
- </xs:documentation></xs:annotation>
<xs:complexType>
<xs:choice minOccurs="0">
<xs:sequence>
@@ -39,4 +36,41 @@
</xs:choice>
</xs:complexType>
</xs:element>
+
+ <xs:element name="Interpreters">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="Interpreter"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="Interpreter">
+ <xs:complexType>
+ <xs:attribute name="Version" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="Product">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="1" maxOccurs="1">
+ <xs:element ref="Features"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="Features"><!--
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="1" maxOccurs="1">
+ <xs:element ref="Features"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ --></xs:element>
+
</xs:schema>
View
44 wix/overlays/runtime/__init__.py
@@ -34,56 +34,46 @@ def _putenv(name, value):
# Update the copy maintained by Windows (so SysInternals Process Explorer sees it)
try:
result = windll.kernel32.SetEnvironmentVariableW(name, value)
-
- if result == 0:
- raise Warning
-
+ if result == 0: raise Warning
+ except Exception:
if sys.flags.verbose:
- sys.stderr.write('* pygtk-runtime: "kernel32.SetEnvironmentVariableW" successful\n')
+ sys.stderr.write('* pygtk-runtime: "kernel32.SetEnvironmentVariableW" failed\n')
sys.stderr.flush()
-
- except Exception as inst:
+ else:
if sys.flags.verbose:
- sys.stderr.write('* pygtk-runtime: "kernel32.SetEnvironmentVariableW" failed\n')
+ sys.stderr.write('* pygtk-runtime: "kernel32.SetEnvironmentVariableW" successful\n')
sys.stderr.flush()
- # Updated the copy maintained by msvcrt (used by gtk+ runtime)
+ # Update the copy maintained by msvcrt (used by gtk+ runtime)
try:
result = cdll.msvcrt._putenv('%s=%s' % (name, value))
-
- if result != 0:
- raise Warning
-
+ if result != 0: raise Warning
+ except Exception:
if sys.flags.verbose:
- sys.stderr.write('* pygtk-runtime: "msvcrt._putenv" successful\n')
+ sys.stderr.write('* pygtk-runtime: "msvcrt._putenv" failed\n')
sys.stderr.flush()
-
- except Exception as inst:
+ else:
if sys.flags.verbose:
- sys.stderr.write('* pygtk-runtime: "msvcrt._putenv" failed\n')
+ sys.stderr.write('* pygtk-runtime: "msvcrt._putenv" successful\n')
sys.stderr.flush()
# Update the copy maintained by whatever c runtime is used by Python
try:
msvcrt = find_msvcrt()
msvcrtname = str(msvcrt).split('.')[0] if '.' in msvcrt else str(msvcrt)
-
result = cdll.LoadLibrary(msvcrt)._putenv('%s=%s' % (name, value))
-
- if result != 0:
- raise Warning
-
+ if result != 0: raise Warning
+ except Exception:
if sys.flags.verbose:
- sys.stderr.write('* pygtk-runtime: "%s._putenv" successful\n' % msvcrtname)
+ sys.stderr.write('* pygtk-runtime: "%s._putenv" failed\n' % msvcrtname)
sys.stderr.flush()
-
- except Exception as inst:
+ else:
if sys.flags.verbose:
- sys.stderr.write('* pygtk-runtime: "%s._putenv" failed\n' % msvcrtname)
+ sys.stderr.write('* pygtk-runtime: "%s._putenv" successful\n' % msvcrtname)
sys.stderr.flush()
-if sys.platform == 'win32':
+if sys.platform == 'win32' or sys.platform == 'nt':
runtime = os.path.abspath(os.path.join(os.path.dirname(__file__), 'bin'))
PATH = os.environ['PATH'].split(os.pathsep)
ABSPATH = [os.path.abspath(x) for x in PATH]
View
0  wix/overlays/runtime/__init__.pyc
No changes.
View
63 wix/template/PyGtk.wxs
@@ -57,18 +57,18 @@
</Condition>
<Upgrade Id="$(var.UpgradeCode)">
- <UpgradeVersion Minimum='$(var.ProductVersion)'
+ <UpgradeVersion Minimum="$(var.ProductVersion)"
IncludeMinimum="no"
- OnlyDetect='yes'
+ OnlyDetect="yes"
Language="1033"
- Property='NEWPRODUCTFOUND' />
+ Property="DOWNGRADEFOUND" />
- <UpgradeVersion Minimum='$(var.OriginalProductVersion)'
+ <UpgradeVersion Minimum="$(var.OriginalProductVersion)"
IncludeMinimum="yes"
- Maximum='$(var.ProductVersion)'
+ Maximum="$(var.ProductVersion)"
IncludeMaximum="no"
Language="1033"
- Property='UPGRADEFOUND' />
+ Property="UPGRADEFOUND" />
</Upgrade>
<Media Id="1"
@@ -88,7 +88,6 @@
<Icon Id="PyGtkIcon" SourceFile="$(var.SrcImages)/PyGtkIcon.ico" />
<Property Id="ARPPRODUCTICON" Value="PyGtkIcon" />
- <Property Id="_BrowseProperty" Value="TARGETDIR" />
<Property Id="PYTHON.MACHINE">
<RegistrySearch Id="PYTHON.MACHINE" Root="HKLM" Key="SOFTWARE\Python\PythonCore\$(var.PythonVersion)\InstallPath" Type="raw" />
</Property>
@@ -97,34 +96,46 @@
</Property>
<CustomAction Id="PreventDowngrading" Error="A newer version of $(var.ProductName) is already installed." />
- <CustomAction Id="PythonX" Property="PYTHONDIR" Value="[WindowsVolume]PythonX" Execute="firstSequence" />
- <CustomAction Id="PythonFromMachine" Property="PYTHONDIR" Value="[PYTHON.MACHINE]" Execute="firstSequence" />
- <CustomAction Id="PythonFromUser" Property="PYTHONDIR" Value="[PYTHON.USER]" Execute="firstSequence" />
- <CustomAction Id="PythonDetected" Property="PythonDetected" Value="PYTHON.MACHINE Or PYTHON.USER" Execute="firstSequence" />
- <CustomAction Id="InitialTargetDir" Property="TARGETDIR" Value="[PYTHONDIR]" Execute="firstSequence" />
+ <CustomAction Id="AllUsersFromParam" Property="AllUsersFromParam" Value="[ALLUSERS]" Execute="firstSequence" />
+ <CustomAction Id="TargetDirFromParam" Property="TargetDirFromParam" Value="[TARGETDIR]" Execute="firstSequence" />
+ <CustomAction Id="PythonX" Property="PythonDir" Value="[WindowsVolume]PythonX" Execute="firstSequence" />
+ <CustomAction Id="PythonFromMachine" Property="PythonDir" Value="[PYTHON.MACHINE]" Execute="firstSequence" />
+ <CustomAction Id="PythonFromUser" Property="PythonDir" Value="[PYTHON.USER]" Execute="firstSequence" />
+ <CustomAction Id="PythonDetected" Property="PythonDetected" Value="1" Execute="firstSequence" />
+ <CustomAction Id="InitialTargetDir" Property="TARGETDIR" Value="[PythonDir]" Execute="firstSequence" />
+ <CustomAction Id="InstallForJustMe" Property="ALLUSERS" Value="{}" Execute="firstSequence" />
+ <CustomAction Id="InstallForEveryone" Property="ALLUSERS" Value="1" Execute="firstSequence" />
<InstallExecuteSequence>
- <Custom Action="PreventDowngrading" Sequence="201">NEWPRODUCTFOUND</Custom>
- <Custom Action="PythonX" Sequence="401" />
- <Custom Action="PythonFromMachine" Sequence="402">PYTHON.MACHINE</Custom>
- <Custom Action="PythonFromUser" Sequence="403">PYTHON.USER</Custom>
- <Custom Action="PythonDetected" Sequence="404">PythonDetected</Custom>
- <Custom Action="InitialTargetDir" Sequence="405" />
+ <Custom Action="PreventDowngrading" Sequence="201">DOWNGRADEFOUND</Custom>
+ <Custom Action="AllUsersFromParam" Sequence="401" />
+ <Custom Action="TargetDirFromParam" Sequence="402" />
+ <Custom Action="PythonX" Sequence="403">NOT TargetDirFromParam</Custom>
+ <Custom Action="PythonFromMachine" Sequence="404">PYTHON.MACHINE AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="InstallForEveryone" Sequence="405">PYTHON.MACHINE AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="PythonFromUser" Sequence="406">PYTHON.USER AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="InstallForJustMe" Sequence="407">PYTHON.USER AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="PythonDetected" Sequence="408">(PYTHON.MACHINE OR PYTHON.USER) AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="InitialTargetDir" Sequence="409">NOT TargetDirFromParam</Custom>
<RemoveExistingProducts Sequence="1401" />
</InstallExecuteSequence>
<InstallUISequence>
- <Custom Action="PreventDowngrading" Sequence="201">NEWPRODUCTFOUND</Custom>
- <Custom Action="PythonX" Sequence="401" />
- <Custom Action="PythonFromMachine" Sequence="402">PYTHON.MACHINE</Custom>
- <Custom Action="PythonFromUser" Sequence="403">PYTHON.USER</Custom>
- <Custom Action="PythonDetected" Sequence="404">PythonDetected</Custom>
- <Custom Action="InitialTargetDir" Sequence="405" />
+ <Custom Action="PreventDowngrading" Sequence="201">DOWNGRADEFOUND</Custom>
+ <Custom Action="AllUsersFromParam" Sequence="401" />
+ <Custom Action="TargetDirFromParam" Sequence="402" />
+ <Custom Action="PythonX" Sequence="403">NOT TargetDirFromParam</Custom>
+ <Custom Action="PythonFromMachine" Sequence="404">PYTHON.MACHINE AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="InstallForEveryone" Sequence="405">PYTHON.MACHINE AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="PythonFromUser" Sequence="406">PYTHON.USER AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="InstallForJustMe" Sequence="407">PYTHON.USER AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="PythonDetected" Sequence="408">(PYTHON.MACHINE OR PYTHON.USER) AND NOT AllUsersFromParam AND NOT TargetDirFromParam</Custom>
+ <Custom Action="InitialTargetDir" Sequence="409">NOT TargetDirFromParam</Custom>
</InstallUISequence>
<Feature Id="PyGTKAllInOne"
Title="PyGTK All-in-one"
- Description="Installs everything you need for PyGTK development except Python"
+ Description="Installs everything you need for PyGTK development except a Python $(var.PythonVersion) interpreter."
ConfigurableDirectory="TARGETDIR"
Absent="disallow"
Display="expand"
@@ -136,7 +147,7 @@
<Directory Id="TARGETDIR" Name="SourceDir">
<!-- Referenced by container Features -->
- <Component Id="Empty" KeyPath='yes' Guid="{2957BDC1-E807-49fb-A46D-F70834B326C4}">
+ <Component Id="Empty" KeyPath="yes" Guid="{2957BDC1-E807-49fb-A46D-F70834B326C4}">
<CreateFolder />
</Component>
</Directory>
View
132 wix/template/WixUI_PyGtk.wxs
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- This file is an adaptation of src/ext/UIExtension/wixlib/WixUI_PyGtk.wxs
+ This file is an adaptation of src/ext/UIExtension/wixlib/WixUI_FeatureTree.wxs
and src/ext/UIExtension/wixlib/CustomizeDlg.wxs as distributed by the WiX
project.
-->
@@ -20,112 +20,98 @@
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">
<UI Id="WixUI_PyGTK">
- <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
- <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
- <TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
+ <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
+ <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
+ <TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
- <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
- <Property Id="WixUI_Mode" Value="FeatureTree" />
+ <Property Id="_BrowseProperty" Value="TARGETDIR" />
+ <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
+ <Property Id="WixUI_Mode" Value="FeatureTree" />
- <DialogRef Id="ErrorDlg" />
- <DialogRef Id="FatalError" />
- <DialogRef Id="FilesInUse" />
- <DialogRef Id="MsiRMFilesInUse" />
- <DialogRef Id="PrepareDlg" />
- <DialogRef Id="ProgressDlg" />
- <DialogRef Id="ResumeDlg" />
- <DialogRef Id="UserExit" />
+ <DialogRef Id="ErrorDlg" />
+ <DialogRef Id="FatalError" />
+ <DialogRef Id="FilesInUse" />
+ <DialogRef Id="MsiRMFilesInUse" />
+ <DialogRef Id="PrepareDlg" />
+ <DialogRef Id="ProgressDlg" />
+ <DialogRef Id="ResumeDlg" />
+ <DialogRef Id="UserExit" />
- <Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
+ <Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
- <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="PyGTK_CustomizeDlg">NOT Installed</Publish>
- <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
+ <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="PyGTK_CustomizeDlg">NOT Installed</Publish>
+ <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
- <Publish Dialog="PyGTK_CustomizeDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="1">Installed</Publish>
- <Publish Dialog="PyGTK_CustomizeDlg" Control="Back" Event="NewDialog" Value="PyGTK_CustomizeDlg" Order="2">NOT Installed</Publish>
- <Publish Dialog="PyGTK_CustomizeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
+ <Publish Dialog="PyGTK_CustomizeDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="1">Installed</Publish>
+ <Publish Dialog="PyGTK_CustomizeDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">NOT Installed</Publish>
+ <Publish Dialog="PyGTK_CustomizeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
- <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="PyGTK_CustomizeDlg" Order="1">NOT Installed OR WixUI_InstallMode = "Change"</Publish>
- <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
- <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3">Installed AND PATCH</Publish>
+ <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="PyGTK_CustomizeDlg" Order="1">NOT Installed OR WixUI_InstallMode = "Change"</Publish>
+ <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
+ <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3">Installed AND PATCH</Publish>
- <Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
+ <Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
- <Publish Dialog="MaintenanceTypeDlg" Control="ChangeButton" Event="NewDialog" Value="PyGTK_CustomizeDlg">1</Publish>
- <Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
- <Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
- <Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
+ <Publish Dialog="MaintenanceTypeDlg" Control="ChangeButton" Event="NewDialog" Value="PyGTK_CustomizeDlg">1</Publish>
+ <Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
+ <Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
+ <Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
<Dialog Id="PyGTK_CustomizeDlg" Width="370" Height="270" Title="!(loc.CustomizeDlg_Title)" TrackDiskSpace="yes">
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.CustomizeDlgBannerBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
+
<Control Id="Title" Type="Text" X="15" Y="6" Width="210" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.CustomizeDlgTitle)" />
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.CustomizeDlgDescription)" />
- <Control Id="Text" Type="Text" X="25" Y="55" Width="320" Height="20" Text="!(loc.CustomizeDlgText)" />
- <Control Id="Tree" Type="SelectionTree" X="25" Y="85" Width="200" Height="115" Property="_BrowseProperty" Sunken="yes" TabSkip="no" Text="!(loc.CustomizeDlgTree)" />
- <Control Id="Box" Type="GroupBox" X="235" Y="81" Width="125" Height="118" />
- <Control Id="ItemDescription" Type="Text" X="240" Y="90" Width="106" Height="50" Text="!(loc.CustomizeDlgItemDescription)">
+
+ <Control Id="Tree" Type="SelectionTree" X="10" Y="55" Width="225" Height="135" Property="_BrowseProperty" Sunken="yes" TabSkip="no" Text="!(loc.CustomizeDlgTree)" />
+ <Control Id="Box" Type="GroupBox" X="245" Y="51" Width="115" Height="140" />
+ <Control Id="ItemDescription" Type="Text" X="250" Y="60" Width="96" Height="60" Text="!(loc.CustomizeDlgItemDescription)">
<Subscribe Event="SelectionDescription" Attribute="Text" />
</Control>
- <Control Id="ItemSize" Type="Text" X="240" Y="140" Width="106" Height="50" Text="!(loc.CustomizeDlgItemSize)">
+ <Control Id="ItemSize" Type="Text" X="250" Y="129" Width="96" Height="60" Text="!(loc.CustomizeDlgItemSize)">
<Subscribe Event="SelectionSize" Attribute="Text" />
</Control>
- <Control Id="LocationLabel" Type="Text" X="25" Y="210" Width="65" Height="10" Text="!(loc.CustomizeDlgLocationLabel)">
- <Condition Action="hide">Installed</Condition>
+
+ <Control Id="LocationLabelCustomPerMachine" Type="Text" Hidden="yes" X="15" Y="200" Width="249" Height="10" Text="Location specified by TARGETDIR parameter (install for all users):">
+ <Condition Action="show"><![CDATA[TargetDirFromParam AND ALLUSERS=1]]></Condition>
+ </Control>
+ <Control Id="LocationLabelCustomPerUser" Type="Text" Hidden="yes" X="15" Y="200" Width="249" Height="10" Text="Location specified by TARGETDIR parameter (install just for me):">
+ <Condition Action="show"><![CDATA[TargetDirFromParam AND ALLUSERS<>1]]></Condition>
+ </Control>
+ <Control Id="LocationLabelPythonNotDetected" Type="Text" Hidden="yes" X="15" Y="200" Width="249" Height="10" Text="Custom location (Python $(var.PythonVersion) not detected):">
+ <Condition Action="show">NOT TargetDirFromParam AND NOT PythonDetected</Condition>
</Control>
- <Control Id="Location" Type="Text" X="90" Y="210" Width="200" Height="20" Text="[TARGETDIR]">
- <Condition Action="hide">Installed</Condition>
+ <Control Id="LocationLabelPythonPerMachine" Type="Text" Hidden="yes" X="15" Y="200" Width="249" Height="10" Text="Python $(var.PythonVersion) (install for all users):">
+ <Condition Action="show">NOT TargetDirFromParam AND PYTHON.MACHINE</Condition>
</Control>
- <Control Id="Browse" Type="PushButton" X="294" Y="210" Width="66" Height="17" Text="!(loc.CustomizeDlgBrowse)">
- <Publish Event="SelectionBrowse" Value="PyGtkBrowseDlg">1</Publish>
- <Condition Action="hide">Installed</Condition>
- <Condition Action="disable">Installed</Condition>
+ <Control Id="LocationLabelPythonPerUser" Type="Text" Hidden="yes" X="15" Y="200" Width="249" Height="10" Text="Python $(var.PythonVersion) (install just for me):">
+ <Condition Action="show">NOT TargetDirFromParam AND PYTHON.USER</Condition>
</Control>
+ <Control Id="Location" Type="Text" X="25" Y="215" Width="200" Height="20" Text="[TARGETDIR]" />
+ <Control Id="Browse" Type="PushButton" Disabled="yes" Hidden="yes" X="294" Y="210" Width="66" Height="17" Text="!(loc.CustomizeDlgBrowse)">
+ <Publish Event="SelectionBrowse" Value="BrowseDlg">1</Publish>
+ <Condition Action="show">NOT Installed AND NOT TargetDirFromParam AND NOT PythonDetected</Condition>
+ <Condition Action="enable">NOT Installed AND NOT TargetDirFromParam AND NOT PythonDetected</Condition>
+ </Control>
+
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
- <Control Id="Reset" Type="PushButton" X="10" Y="243" Width="81" Height="17" Text="!(loc.CustomizeDlgReset)">
+ <Control Id="Reset" Type="PushButton" X="10" Y="243" Width="56" Height="17" Text="!(loc.CustomizeDlgReset)">
<Publish Event="Reset" Value="0">1</Publish>
<Subscribe Event="SelectionNoItems" Attribute="Enabled" />
</Control>
- <Control Id="DiskCost" Type="PushButton" X="91" Y="243" Width="100" Height="17" Text="!(loc.CustomizeDlgDiskCost)">
+ <Control Id="DiskCost" Type="PushButton" X="66" Y="243" Width="56" Height="17" Text="!(loc.CustomizeDlgDiskCost)">
<Publish Event="SpawnDialog" Value="DiskCostDlg">1</Publish>
<Subscribe Event="SelectionNoItems" Attribute="Enabled" />
</Control>
- <Control Id="Back" Type="PushButton" X="192" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
- <Control Id="Next" Type="PushButton" X="248" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
+ <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
+ <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Subscribe Event="SelectionNoItems" Attribute="Enabled" />
</Control>
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
</Dialog>
- <Dialog Id="PyGtkBrowseDlg" Width="370" Height="270" Title="!(loc.BrowseDlg_Title)">
- <Control Id="PathEdit" Type="PathEdit" X="25" Y="202" Width="320" Height="18" Property="_BrowseProperty" Indirect="yes" />
- <Control Id="OK" Type="PushButton" X="240" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUIOK)">
- <Publish Event="SetTargetPath" Value="[_BrowseProperty]">1</Publish>
- <Publish Event="EndDialog" Value="Return">1</Publish>
- </Control>
- <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
- <Publish Event="Reset" Value="0">1</Publish>
- <Publish Event="EndDialog" Value="Return">1</Publish>
- </Control>
- <Control Id="ComboLabel" Type="Text" X="25" Y="58" Width="44" Height="10" TabSkip="no" Text="!(loc.BrowseDlgComboLabel)" />
- <Control Id="DirectoryCombo" Type="DirectoryCombo" X="70" Y="55" Width="220" Height="80" Property="_BrowseProperty" Indirect="yes" Fixed="yes" Remote="yes">
- <Subscribe Event="IgnoreChange" Attribute="IgnoreChange" />
- </Control>
- <Control Id="WixUI_Bmp_Up" Type="PushButton" X="298" Y="55" Width="19" Height="19" ToolTip="!(loc.BrowseDlgWixUI_Bmp_UpTooltip)" Icon="yes" FixedSize="yes" IconSize="16" Text="!(loc.BrowseDlgWixUI_Bmp_Up)">
- <Publish Event="DirectoryListUp" Value="0">1</Publish>
- </Control>
- <Control Id="NewFolder" Type="PushButton" X="325" Y="55" Width="19" Height="19" ToolTip="!(loc.BrowseDlgNewFolderTooltip)" Icon="yes" FixedSize="yes" IconSize="16" Text="!(loc.BrowseDlgNewFolder)">
- <Publish Event="DirectoryListNew" Value="0">1</Publish>
- </Control>
- <Control Id="DirectoryList" Type="DirectoryList" X="25" Y="83" Width="320" Height="98" Property="_BrowseProperty" Sunken="yes" Indirect="yes" TabSkip="no" />
- <Control Id="PathLabel" Type="Text" X="25" Y="190" Width="320" Height="10" TabSkip="no" Text="!(loc.BrowseDlgPathLabel)" />
- <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.BrowseDlgBannerBitmap)" />
- <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
- <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
- <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.BrowseDlgDescription)" />
- <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.BrowseDlgTitle)" />
- </Dialog>
</UI>
<UIRef Id="WixUI_Common" />
Please sign in to comment.
Something went wrong with that request. Please try again.