Creating a user-friendly Windows installer of SchoolTool clients
================================================================

XXX As wxclient is deprecated, this document is no longer useful.

First, make sure that py2exe[1] and Nullsoft Scriptable Install System[2] are
installed.

[1] http://starship.python.net/crew/theller/py2exe/
[2] http://nsis.sourceforge.net/

Set up a working installation of SchoolTool (you will need to compile the
extension modules as described in building-with-mingw.txt).  The NSIS script
later assumes that SchoolTool is installed in C:\schooltool, so you might as
well start with this location.  You may want to run the tests to make sure that
everything is OK.

Next, apply *this* file (it has a diff section at the end) as a patch in the
main SchoolTool directory.  (You can use 'patch' from cygwin or apply the patch
elsewhere (on a Linux system) and copy the updated files manually.)  Several
changes will be made to the client source and setup.py, and a script that
creates the final executable, 'build-win32-dist.py', will be created.

Next, take a look at build-win32-dist.py and see if anything needs to be
changed. Then just run build-win32-dist.py. If all went fine, you should have a
Setup.exe ready in a minute.

The NSIS template was created by using the wizard in HM NIS Edit [3], and
it can be used again should the need arise.

[3] http://hmne.sourceforge.net/

You will probably want to test the installer before making it public.

XXX Currently we don't deal with translations.  After they are available, it
    would make sense to include the .mo files in the package as well.

--- diff section follows ---

Index: build-win32-dist.py
===================================================================
--- build-win32-dist.py	(revision 0)
+++ build-win32-dist.py	(revision 0)
@@ -0,0 +1,165 @@
+#!/bin/env python
+
+import sys
+import os
+import shutil
+
+VERSION = "Milestone 6"
+
+def die(msg):
+    print >> sys.stderr, msg
+    sys.exit(1)
+
+basedir = os.path.abspath(os.path.dirname(sys.argv[0]))
+distdir = os.path.join(basedir, 'dist')
+nsiscript = 'clients.nsi'
+makensis = 'C:\Progra~1\Nsis\makensis.exe'
+
+os.environ['PYTHONPATH'] = os.path.join(basedir, 'src') # needed for py2exe
+
+# Remove the old binaries
+try:
+    shutil.rmtree(distdir)
+except OSError:
+    pass
+
+# Create the binaries
+retval = os.system('setup.py py2exe')
+if retval:
+    die('`setup.py py2exe` returned %d.' % retval)
+elif not os.path.exists(distdir):
+    die('%s has not been created by py2exe.' % distdir)
+
+# Create the NSI script
+NSI_TEMPLATE = """\
+; Script generated by the HM NIS Edit Script Wizard.
+
+; HM NIS Edit Wizard helper defines
+!define PRODUCT_NAME "SchoolTool Client"
+!define PRODUCT_VERSION "%s"
+!define PRODUCT_PUBLISHER "Shuttleworth Foundation"
+!define PRODUCT_WEB_SITE "http://www.schooltool.org"
+!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\wxclient.exe"
+!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+!define PRODUCT_UNINST_ROOT_KEY "HKLM"
+
+SetCompressor lzma
+
+; MUI 1.67 compatible ------
+!include "MUI.nsh"
+
+; MUI Settings
+!define MUI_ABORTWARNING
+!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
+!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
+
+; Welcome page
+!insertmacro MUI_PAGE_WELCOME
+; License page
+!insertmacro MUI_PAGE_LICENSE "C:\schooltool\GPL"
+; Directory page
+!insertmacro MUI_PAGE_DIRECTORY
+; Instfiles page
+!insertmacro MUI_PAGE_INSTFILES
+; Finish page
+!define MUI_FINISHPAGE_RUN "$INSTDIR\wxclient.exe"
+!insertmacro MUI_PAGE_FINISH
+
+; Uninstaller pages
+!insertmacro MUI_UNPAGE_INSTFILES
+
+; Language files
+!insertmacro MUI_LANGUAGE "English"
+
+; Reserve files
+!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
+
+; MUI end ------
+
+Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
+OutFile "Setup.exe"
+InstallDir "$PROGRAMFILES\SchoolTool"
+InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
+ShowInstDetails show
+ShowUnInstDetails show
+
+Section "MainSection" SEC01
+  SetOutPath "$INSTDIR"
+  SetOverwrite ifnewer
+  CreateDirectory "$SMPROGRAMS\SchoolTool"
+  CreateShortCut "$SMPROGRAMS\SchoolTool\SchoolTool.lnk" "$INSTDIR\wxclient.exe"
+  CreateShortCut "$SMPROGRAMS\SchoolTool\Import Sample School.lnk" "$INSTDIR\import-sampleschool.exe" "--interactive" "$INSTDIR\schooltool.ico"
+  CreateShortCut "$DESKTOP\SchoolTool.lnk" "$INSTDIR\wxclient.exe"
+
+%s
+
+SectionEnd
+
+Section -AdditionalIcons
+  WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
+  CreateShortCut "$SMPROGRAMS\SchoolTool\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
+  CreateShortCut "$SMPROGRAMS\SchoolTool\Uninstall.lnk" "$INSTDIR\uninst.exe"
+SectionEnd
+
+Section -Post
+  WriteUninstaller "$INSTDIR\uninst.exe"
+  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\wxclient.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\wxclient.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+SectionEnd
+
+
+Function un.onUninstSuccess
+  HideWindow
+  MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer."
+FunctionEnd
+
+Function un.onInit
+  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2
+  Abort
+FunctionEnd
+
+Section Uninstall
+  Delete "$INSTDIR\${PRODUCT_NAME}.url"
+
+%s
+
+  Delete "$SMPROGRAMS\SchoolTool\Uninstall.lnk"
+  Delete "$SMPROGRAMS\SchoolTool\Website.lnk"
+  Delete "$DESKTOP\SchoolTool.lnk"
+  Delete "$SMPROGRAMS\SchoolTool\SchoolTool.lnk"
+  Delete "$SMPROGRAMS\SchoolTool\Import Sample School.lnk"
+
+  RMDir "$SMPROGRAMS\SchoolTool"
+  RMDir "$INSTDIR"
+
+  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+  DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
+  SetAutoClose true
+SectionEnd
+""" # % (version, install_files, delete_files)
+
+files = os.listdir(distdir)
+install_files = "".join(
+        ['  File "%s"\n' % os.path.join(distdir, f) for f in files])
+delete_files = "".join(['  Delete "$INSTDIR\%s"\n' % f for f in files])
+
+f = open(nsiscript, 'w')
+f.seek(0)
+f.truncate()
+f.write(NSI_TEMPLATE % (VERSION, install_files, delete_files))
+f.close()
+
+# Invoke NSIS to create Setup.exe
+retval = os.system('"%s" /V4 %s' % (makensis, nsiscript))
+if retval:
+    die('makensis returned %d' % retval)
+
+if not os.path.exists('Setup.exe'):
+    die('Setup.exe not created.')
+
+print "You're done!"
Index: setup.py
===================================================================
--- setup.py    (revision 1034)
+++ setup.py    (working copy)
@@ -66,6 +66,7 @@
 #
 
 from distutils.core import setup, Extension
+import py2exe
 
 # Set up dependencies for the BTrees package
 base_btrees_depends = [
@@ -138,4 +139,16 @@
 setup(name="schooltool",
       version="0.6",
       package_dir={'': 'src'},
-      ext_modules=ext_modules)
+      ext_modules=ext_modules,
+      console=["src/schooltool/clients/client.py",
+               "import-sampleschool.py"],
+      windows=[{'script': "src/schooltool/clients/wxclient.py",
+                'icon_resources': [(0,'src/schooltool/clients/schooltool.ico')]
+               }],
+      data_files=[('.', ["src/schooltool/clients/nophoto.png",
+                         "src/schooltool/clients/schooltool.xpm",
+                         "src/schooltool/clients/schooltool.ico",
+                         "groups.csv", "pupils.csv", "teachers.csv",
+                         "resources.csv", "ttconfig.data"])],
+      options = {"py2exe": {"packages": ["encodings"]}},
+     )
Index: src/schooltool/clients/wxclient.py
===================================================================
--- src/schooltool/clients/wxclient.py  (revision 1031)
+++ src/schooltool/clients/wxclient.py  (working copy)
@@ -54,6 +54,9 @@
 
 __metaclass__ = type
 
+# __file__ is not defined in py2exe archives
+import sys
+__file__ = sys.argv[0]
 
 #
 # Common sets of window style flags
