Hello community,

here is the log from the commit of package Photini for openSUSE:Factory checked 
in at 2020-11-02 09:42:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/Photini (Old)
 and      /work/SRC/openSUSE:Factory/.Photini.new.3463 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "Photini"

Mon Nov  2 09:42:59 2020 rev:16 rq:845173 version:2020.10.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/Photini/Photini.changes  2020-04-28 
22:33:30.857881819 +0200
+++ /work/SRC/openSUSE:Factory/.Photini.new.3463/Photini.changes        
2020-11-02 09:43:40.665799018 +0100
@@ -1,0 +2,12 @@
+Sat Oct 31 11:23:54 UTC 2020 - Luigi Baldoni <aloi...@gmx.com>
+
+- Update to version 2020.10.1
+  * Fix bug when using --root option on Linux installer.
+  version 2020.10.0:
+  * Fix bug when copying files from a high speed device.
+  * Fix Google Photos uploader bug when folder has no name.
+  * Improved installation, particularly start menu shortcuts.
+  * Minor other fixes and improvements.
+- Spec cleanup
+
+-------------------------------------------------------------------

Old:
----
  Photini-2020.4.0.tar.gz

New:
----
  Photini-2020.10.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ Photini.spec ++++++
--- /var/tmp/diff_new_pack.EnDYG3/_old  2020-11-02 09:43:42.881801144 +0100
+++ /var/tmp/diff_new_pack.EnDYG3/_new  2020-11-02 09:43:42.885801148 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           Photini
-Version:        2020.4.0
+Version:        2020.10.1
 Release:        0
 Summary:        Digital photograph metadata (EXIF, IPTC, XMP) editing 
application
 License:        GPL-3.0-or-later
@@ -57,25 +57,22 @@
 
 %prep
 %setup -q
-sed '/^Icon/cIcon=photini' -i src/linux/photini.desktop
-# remove shebang
-sed -e '1d' -i src/photini/importer.py src/photini/spelling.py 
src/photini/editor.py
+sed -e 's/{exec_path}/photini/' -e 's/{icon_path}/photini/' -i 
src/linux/photini.desktop.template
 
 %build
 python3 setup.py build
-for s in 22 32 48 64 96 128 192 256; do
-    convert -strip src/windows/icon.ico[0] -resize ${s}x${s} ${s}.png
+for s in 22 32 48 64 96 128 192 256 512; do
+    convert -strip src/misc/icon_master.png -resize ${s}x${s} ${s}.png
 done
 
 %install
-python3 setup.py install --prefix=%{_prefix} --root %{buildroot}
-for s in 22 32 48 64 96 128 192 256; do
+python3 setup.py install --prefix=%{_prefix} --root=%{buildroot}
+for s in 22 32 48 64 96 128 192 256 512; do
 mkdir -pv %{buildroot}%{_datadir}/icons//hicolor/${s}x${s}/apps
 install -m0644 ${s}.png -T \
                
%{buildroot}%{_datadir}/icons//hicolor/${s}x${s}/apps/photini.png
 done
-chmod -x %{buildroot}%{_datadir}/applications/photini.desktop
-%fdupes -s %{buildroot}
+%fdupes %{buildroot}
 
 %files
 %doc CHANGELOG.txt README.rst

++++++ Photini-2020.4.0.tar.gz -> Photini-2020.10.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/CHANGELOG.txt 
new/Photini-2020.10.1/CHANGELOG.txt
--- old/Photini-2020.4.0/CHANGELOG.txt  2020-04-28 15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/CHANGELOG.txt 2020-10-31 11:20:51.000000000 +0100
@@ -16,6 +16,16 @@
 along with this program.  If not, see
 <http://www.gnu.org/licenses/>.
 
+Changes in v2020.10.1:
+  1/ Fix bug when using --root option on Linux installer.
+
+Changes in v2020.10.0:
+  1/ Fix bug with non-ascii file or directory names on Windows.
+  2/ Fix bug when copying files from a high speed device.
+  3/ Fix Google Photos uploader bug when folder has no name.
+  4/ Improved installation, particularly start menu shortcuts.
+  5/ Minor other fixes and improvements.
+
 Changes in v2020.4.0:
   1/ Stopped using deprecated MapBox tile layers.
   2/ Many minor bug fixes and performance improvements.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/README.rst 
new/Photini-2020.10.1/README.rst
--- old/Photini-2020.4.0/README.rst     2020-04-28 15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/README.rst    2020-10-31 11:20:51.000000000 +0100
@@ -14,6 +14,9 @@
 Why is it called Photini?
 Read my `blog post`_ on how I chose a name.
 
+.. contents::
+   :backlinks: top
+
 Features
 --------
 
@@ -94,7 +97,7 @@
 
 | Photini - a simple photo metadata editor.
 | http://github.com/jim-easterbrook/Photini
-| Copyright (C) 2012-19  Jim Easterbrook  j...@jim-easterbrook.me.uk
+| Copyright (C) 2012-20  Jim Easterbrook  j...@jim-easterbrook.me.uk
 
 | German translation by Jan Rimmek
 | Spanish translation by Esteban Martinena & Cristos Ruiz
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/setup.py 
new/Photini-2020.10.1/setup.py
--- old/Photini-2020.4.0/setup.py       2020-04-28 15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/setup.py      2020-10-31 11:20:51.000000000 +0100
@@ -17,12 +17,14 @@
 #  <http://www.gnu.org/licenses/>.
 
 from datetime import date
+from distutils import log
 from distutils.cmd import Command
 from distutils.command.upload import upload
 from distutils.errors import DistutilsExecError, DistutilsOptionError
 import os
 import re
 from setuptools import setup
+from setuptools.command.install import install
 import sys
 
 # read current version info without importing package
@@ -131,6 +133,72 @@
 
 cmdclass['upload'] = upload_and_tag
 
+
+# add command to create start menu entries
+class install_menu(Command):
+    description = 'install start menu entries'
+    user_options = []
+    boolean_options = ['user']
+
+    def initialize_options(self):
+        self.user = None
+        self.install_data = None
+        self.script_dir = None
+        self.lib_dir = None
+        self.build_temp = None
+
+    def finalize_options(self):
+        self.set_undefined_options('install',
+                                   ('user', 'user'),
+                                   ('install_data', 'install_data'),
+                                   ('install_scripts', 'script_dir'),
+                                   ('install_lib', 'lib_dir'))
+        self.set_undefined_options('build',
+                                   ('build_temp', 'build_temp'))
+
+    def run(self):
+        self.outfiles = []
+        if sys.platform == 'win32':
+            exec_path = os.path.join(self.script_dir, 'photini.exe')
+            icon_path = os.path.join(
+                self.lib_dir, 'photini/data/icons/win/icon.ico')
+            temp_file = os.path.abspath(os.path.join(
+                self.build_temp, 'new_files.txt'))
+            log.info('Creating menu shortcuts')
+            if not self.dry_run:
+                self.mkpath(os.path.dirname(temp_file))
+                args = ['cscript', '/nologo',
+                        'src/windows/install_shortcuts.vbs',
+                        exec_path, icon_path, sys.prefix, temp_file]
+                if self.user:
+                    args.append('/user')
+                self.spawn(args)
+                with open(temp_file) as f:
+                    for line in f.readlines():
+                        self.outfiles.append(line.strip())
+        elif sys.platform.startswith('linux'):
+            desktop_path = os.path.join(
+                self.install_data, 'share/applications/photini.desktop')
+            exec_path = os.path.join(self.script_dir, 'photini')
+            icon_path = os.path.join(
+                self.lib_dir, 'photini/data/icons/48/photini.png')
+            log.info('Installing desktop file %s', desktop_path)
+            if not self.dry_run:
+                self.mkpath(os.path.dirname(desktop_path))
+                with open('src/linux/photini.desktop.template', 'r') as src:
+                    template = src.read()
+                with open(desktop_path, 'w') as dst:
+                    dst.write(template.format(
+                        exec_path=exec_path, icon_path=icon_path))
+            self.outfiles.append(desktop_path)
+
+    def get_outputs(self):
+        return self.outfiles or []
+
+cmdclass['install_menu'] = install_menu
+install.sub_commands.append(('install_menu', lambda self:True))
+
+
 # set options for building distributions
 command_options['sdist'] = {
     'formats'        : ('setup.py', 'gztar'),
@@ -285,17 +353,6 @@
         'output_dir' : ('setup.py', 'src/lang/doc'),
         }
 
-data_files = []
-if sys.platform.startswith('linux'):
-    # install application menu shortcut
-    data_files.append(('share/icons/hicolor/48x48/apps',
-                       ['src/photini/data/icons/48/photini.png']))
-    data_files.append(('share/applications', ['src/linux/photini.desktop']))
-    command_options['install'] = {
-        'single_version_externally_managed' : ('setup.py', '1'),
-        'record'                            : ('setup.py', 'install.txt'),
-        }
-
 with open('README.rst') as ldf:
     long_description = ldf.read()
 url = 'https://github.com/jim-easterbrook/Photini'
@@ -324,11 +381,11 @@
       packages = ['photini'],
       package_dir = {'' : 'src'},
       package_data = {
-          'photini' : ['data/*.txt', 'data/*.png', 'data/icons/*/photini.png',
+          'photini' : ['data/*.txt', 'data/*.png',
+                       'data/icons/*/photini.png', 'data/icons/win/icon.ico',
                        'data/*map/script.js', 'data/openstreetmap/*.js',
                        'data/lang/*.qm'],
           },
-      data_files = data_files,
       cmdclass = cmdclass,
       command_options = command_options,
       entry_points = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/doc/conf.py 
new/Photini-2020.10.1/src/doc/conf.py
--- old/Photini-2020.4.0/src/doc/conf.py        2020-04-28 15:04:39.000000000 
+0200
+++ new/Photini-2020.10.1/src/doc/conf.py       2020-10-31 11:20:51.000000000 
+0100
@@ -67,7 +67,7 @@
 
 # General information about the project.
 project = u'Photini'
-copyright = u'2012-19, Jim Easterbrook'
+copyright = u'2012-20, Jim Easterbrook'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -152,7 +152,7 @@
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
 #html_favicon = None
-html_favicon = '../windows/icon.ico'
+html_favicon = '../photini/data/icons/win/icon.ico'
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/doc/manual/google_photos.rst 
new/Photini-2020.10.1/src/doc/manual/google_photos.rst
--- old/Photini-2020.4.0/src/doc/manual/google_photos.rst       2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/doc/manual/google_photos.rst      2020-10-31 
11:20:51.000000000 +0100
@@ -1,5 +1,5 @@
 .. This is part of the Photini documentation.
-   Copyright (C)  2019  Jim Easterbrook.
+   Copyright (C)  2019-20  Jim Easterbrook.
    See the file ../DOC_LICENSE.txt for copying conditions.
 
 Google Photos uploader
@@ -19,7 +19,7 @@
 The first time you click ``Log in`` Photini connects your web browser to 
Google Photos, from where you can log in and give Photini permission to access 
Google Photos on your behalf.
 
 .. note::
-   Photini has not yet been authorised by Google, so you will be presented 
with several warning messages during the authentication process, and a warning 
email may be sent to your GMail account.
+   Unfortunately Google won't verify Photini because it continues to be 
developed, so you will be presented with several warning messages during the 
authentication process, and a warning email may be sent to your GMail account.
 
 .. image:: ../images/screenshot_171.png
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/doc/other/installation.rst 
new/Photini-2020.10.1/src/doc/other/installation.rst
--- old/Photini-2020.4.0/src/doc/other/installation.rst 2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/doc/other/installation.rst        2020-10-31 
11:20:51.000000000 +0100
@@ -1,5 +1,5 @@
 .. This is part of the Photini documentation.
-   Copyright (C)  2012-19  Jim Easterbrook.
+   Copyright (C)  2012-20  Jim Easterbrook.
    See the file DOC_LICENSE.txt for copying conditions.
 
 Installation
@@ -14,14 +14,13 @@
 ------------------------------
 
 The Windows installers create a standalone MSYS2_ installation with all the 
dependencies needed to run Photini.
-This is a cut-down MSYS2 and Python system, and should not conflict with any 
other Python version installed on your computer, or any other MSYS2 
installation.
+This is a minimal MSYS2 and Python system, and should not conflict with any 
other Python version installed on your computer, or any other MSYS2 
installation.
 
 Previous installers (from before May 2019) used a "portable Python" system 
based on WinPython_.
 If you have a Photini installation from one of these installers you should 
remove it using the "Programs and Features" control panel item, and ensure the 
installation folder (e.g. ``C:\Program Files (x86)\Photini`` has been removed, 
before using the new installer.
 
-You can download the latest Windows installer from the `GitHub releases`_ page.
-Look for the most recent release with a ``.exe`` file listed in its "assets", 
e.g. ``photini-win64-2019.5.0.exe``.
-This is a Windows installer for the latest version of Photini, even if it's 
listed under an older release.
+You can download the Windows installers from the `GitHub releases`_ `Windows 
installers`_ page.
+These install the latest version of Photini, even if the installer is older.
 There are installers for 32 bit and 64 bit Windows, and they should work on 
any version since Windows XP.
 
 When you run the installer you will probably get a security warning because 
the installer is not signed by a recognised authority.
@@ -35,75 +34,90 @@
 Upgrading all-in-one installation
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Before upgrading Photini you should check the `GitHub releases`_ page to see 
if a new Windows installer has been released since you last downloaded it.
+Before upgrading Photini you should check the `Windows installers`_ page to 
see if a new Windows installer has been released since you last downloaded it.
 If there is a new installer available then you should use it to create a fresh 
installation, after using the "Programs and Features" control panel item to 
uninstall the old version of Photini.
 
-To upgrade an existing installation you need to run an MSYS2 "command shell".
+To upgrade an existing installation you need to run an MSYS2_ "command shell".
 Open the folder where Photini is installed (probably ``C:\Program Files 
(x86)\Photini``) and run the ``mingw64.exe`` program in the ``msys2`` folder 
(use ``mingw32.exe`` if you have a 32-bit installation).
 This program needs to be run as administrator.
-Use this command to upgrade Photini::
+Then follow the instructions in :ref:`upgrading MSYS2 installation 
<upgrading-msys2>` below.
 
-   pip3 install -U photini
+MSYS2 (Windows)
+---------------
 
-If you would like to upgrade or install the Flickr uploader components you can 
also use pip_::
+An alternative to the Windows standalone installer is to use a full 
installation of MSYS2_.
+This is not that difficult to do, but will need almost 3 GBytes of disc space, 
and half an hour of your time.
+Installing Photini this way ensures its dependencies are up to date and should 
be easier to update in future.
 
-   pip3 install -U flickrapi keyring
+The following instructions assume you are using 64-bit Windows.
+If you are on a 32-bit machine you'll need to install the 32-bit (``i686`` 
instead of ``x86_64``) versions of everything.
+Note that the 32-bit version of MSYS2_ is no longer supported.
 
-Installing the spell checker components uses pacman_::
+First install MSYS2_ and update the packages as described on the MSYS2 
homepage.
+You do not need to install it as ``C:\msys64``, but you probably should avoid 
using spaces in the directory name.
+You should also avoid installing in ``C:\Program Files`` or ``C:\Program Files 
(x86)`` so you don't have to use administrator privileges to make any changes.
+Run the ``C:\msys64\mingw64.exe`` shell and use pacman_ to install Photini's 
dependencies::
 
-   pacman -S mingw-w64-x86_64-gspell
+   pacman -S 
$MINGW_PACKAGE_PREFIX-{gexiv2,python-gobject,python-pyqt5,python-pip,python-pillow}
 
-You'll also need to install one or more dictionaries.
-To get a list of available dictionaries::
+This will take some time as over 300 MByte will be downloaded.
+(The Qt package itself is 175 MByte!)
+When it's finished you can free up some disc space with the ``pacman -Scc`` 
command.
 
-   pacman -Ss dictionar
+Use pip_ to install Photini::
 
-Note the use of ``dictionar`` as a search term - it matches ``dictionary`` or 
``dictionaries``.
-To install the French dictionaries::
+   python -m pip install photini flickrapi keyring gpxpy
 
-   pacman -S mingw-w64-x86_64-aspell-fr
+Then run Photini::
 
-The MSYS2 repositories only provide dictionaries for a few languages, but it 
is possible to install from other sources.
-See the :ref:`configuration page <configuration-spell>` for more information.
+   python -m photini.editor
 
-When you've finished you can close the command shell with the ``exit`` command.
+.. _upgrading-msys2:
 
-MSYS2 (Windows)
----------------
+Upgrading MSYS2 installation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-An alternative to the Windows standalone installer is to use a full 
installation of MSYS2_.
-This is not that difficult to do, but will need about 10 GBytes of disc space, 
and an hour of your time.
-The following instructions assume you are using 64-bit Windows.
-If you are on a 32-bit machine you'll need to install the 32-bit (``i686`` 
instead of ``x86_64``) versions of everything.
+Run the ``mingw64.exe`` shell and update pacman_, then use it to update all 
installed packages::
 
-First install MSYS2_ and update the packages as described on the MSYS2 
homepage.
-Run the ``C:\msys64\mingw64.exe`` shell and use pacman_ to install Photini's 
dependencies::
+   pacman -Syu
+   pacman -Su
 
-   pacman -S mingw-w64-x86_64-gexiv2 mingw-w64-x86_64-python3-gobject 
mingw-w64-x86_64-python3-pyqt5 mingw-w64-x86_64-python3-pip
+Use pip_ to update Photini::
 
-This will take some time as the Qt download is well over 1 GByte.
-When it's finished you can free up some disc space with the ``pacman -Scc`` 
command.
+   python -m pip install -U photini gpxpy
 
-Use pip_ to install Photini::
+Note that pip_ may warn that you are using an old version of pip and instruct 
you to update it with pip.
+DO NOT DO THIS!
+The MSYS2_ installation of pip has been patched to work with Windows paths and 
should only be upgraded using pacman_.
 
-   pip3 install photini flickrapi keyring
+If you use the Flickr uploader this can also be updated with pip_::
 
-Then run Photini::
+   python -m pip install -U flickrapi keyring
 
-   python3 -m photini.editor
+Installing the spell checker components uses pacman_::
 
-If you want to use Photini's spelling checker then you need to install 
``Gspell`` and one or more dictionaries, for example::
+   pacman -S $MINGW_PACKAGE_PREFIX-gspell
 
-   pacman -S mingw-w64-x86_64-gspell mingw-w64-x86_64-aspell-en 
mingw-w64-x86_64-aspell-fr
+You'll also need to install one or more dictionaries.
+To get a list of available dictionaries::
 
-To create a desktop shortcut to run Photini, right-click on the desktop and 
select ``New -> Shortcut``.
-Set "location of the item" to the following::
+   pacman -Ss dictionar
 
-   C:\msys64\mingw64\bin\python3w.exe -m photini.editor
+Note the use of ``dictionar`` as a search term - it matches ``dictionary`` or 
``dictionaries``.
+This search will show 32-bit and 64-bit versions of the dictionary packages.
+Make sure you choose the correct one, prefaced by ``mingw32`` or ``mingw64``.
+For example, to install the 64-bit French dictionaries::
 
-Choose a suitable name for the shortcut, such as Photini, and click "finish".
-Note the use of ``python3w.exe`` rather than ``python3.exe``.
-This runs Photini without opening a shell window.
+   pacman -S mingw-w64-x86_64-aspell-fr
+
+The MSYS2 repositories only provide dictionaries for a few languages, but it 
is possible to install from other sources.
+See the :ref:`configuration page <configuration-spell>` for more information.
+
+The FFmpeg_ package is needed to read metadata from video files::
+
+   pacman -S $MINGW_PACKAGE_PREFIX-ffmpeg
+
+When you've finished you can close the command shell with the ``exit`` command.
 
 Package manager (some Linux distributions)
 ------------------------------------------
@@ -184,7 +198,11 @@
 
    sudo pip install photini
 
-This will install Photini and any Python packages it requires.
+This will install Photini and any Python packages it requires, for all users.
+If you prefer a single-user installation, which doesn't require root 
permission, you can use the ``--user`` option::
+
+   pip install photini --user
+
 You can also use pip to install the optional dependencies when you install 
Photini::
 
    sudo pip install photini[flickr,google,importer]
@@ -198,10 +216,13 @@
 
 This can be useful during development as the script should also work within an 
IDE.
 
-The development version can be built and installed in the usual way::
+The development version can be built and installed using pip::
+
+   sudo python -m pip install .
+
+or::
 
-   python setup.py build
-   sudo python setup.py install
+   python -m pip install . --user
 
 You will need to install the optional dependencies separately.
 
@@ -290,10 +311,11 @@
 Open ``doc/html/index.html`` with a web browser to read the local 
documentation.
 
 .. _Exiv2:             http://exiv2.org/
-.. _FFmpeg:       https://ffmpeg.org/
+.. _FFmpeg:            https://ffmpeg.org/
 .. _flickrapi:         https://stuvel.eu/flickrapi/
 .. _gexiv2:            https://wiki.gnome.org/Projects/gexiv2
 .. _GitHub releases:   https://github.com/jim-easterbrook/Photini/releases
+.. _Windows installers: 
https://github.com/jim-easterbrook/Photini/releases/tag/2020.4.0-win
 .. _gpxpy:             https://pypi.org/project/gpxpy/
 .. _Gspell:            https://wiki.gnome.org/Projects/gspell
 .. _keyring:           https://keyring.readthedocs.io/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/doc/other/localisation.rst 
new/Photini-2020.10.1/src/doc/other/localisation.rst
--- old/Photini-2020.4.0/src/doc/other/localisation.rst 2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/doc/other/localisation.rst        2020-10-31 
11:20:51.000000000 +0100
@@ -1,5 +1,5 @@
 .. This is part of the Photini documentation.
-   Copyright (C)  2015-19  Jim Easterbrook.
+   Copyright (C)  2015-20  Jim Easterbrook.
    See the file DOC_LICENSE.txt for copying conditions.
 
 "Localisation"
@@ -155,7 +155,7 @@
 Now you can install Photini with your new translation(s)::
 
    python setup.py build
-   sudo python setup.py install
+   sudo python -m pip install .
 
 Photini should use your new language if your computer's ``LANG`` environment 
variable is set appropriately.
 You can force this when running Photini from the command line::
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/linux/photini.desktop 
new/Photini-2020.10.1/src/linux/photini.desktop
--- old/Photini-2020.4.0/src/linux/photini.desktop      2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/linux/photini.desktop     1970-01-01 
01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-[Desktop Entry]
-Type=Application
-Name=Photini
-GenericName=Photini metadata editor
-Exec=photini
-Terminal=false
-Categories=Graphics;Photography;
-Icon=../icons/hicolor/48x48/apps/photini.png
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/linux/photini.desktop.template 
new/Photini-2020.10.1/src/linux/photini.desktop.template
--- old/Photini-2020.4.0/src/linux/photini.desktop.template     1970-01-01 
01:00:00.000000000 +0100
+++ new/Photini-2020.10.1/src/linux/photini.desktop.template    2020-10-31 
11:20:51.000000000 +0100
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Type=Application
+Name=Photini
+Comment=An easy to use digital photograph metadata (EXIF, IPTC, XMP) editing 
application.
+GenericName=Photini metadata editor
+Exec={exec_path} %F
+Terminal=false
+Categories=Graphics;Photography;
+Icon={icon_path}
+MimeType=image/jpeg;image/jpeg2000;image/tiff;image/png;image/gif;image/svg+xml;image/x-dcraw;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/__init__.py 
new/Photini-2020.10.1/src/photini/__init__.py
--- old/Photini-2020.4.0/src/photini/__init__.py        2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/photini/__init__.py       2020-10-31 
11:20:51.000000000 +0100
@@ -1,4 +1,4 @@
 from __future__ import unicode_literals
 
-__version__ = '2020.4.0'
-build = '1483 (d07f122)'
+__version__ = '2020.10.1'
+build = '1514 (14750df)'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/data/bingmap/script.js 
new/Photini-2020.10.1/src/photini/data/bingmap/script.js
--- old/Photini-2020.4.0/src/photini/data/bingmap/script.js     2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/photini/data/bingmap/script.js    2020-10-31 
11:20:51.000000000 +0100
@@ -1,6 +1,6 @@
 //  Photini - a simple photo metadata editor.
 //  http://github.com/jim-easterbrook/Photini
-//  Copyright (C) 2012-19  Jim Easterbrook  j...@jim-easterbrook.me.uk
+//  Copyright (C) 2012-20  Jim Easterbrook  j...@jim-easterbrook.me.uk
 //
 //  This program is free software: you can redistribute it and/or
 //  modify it under the terms of the GNU General Public License as
@@ -27,6 +27,7 @@
         zoom: zoom,
         mapTypeId: Microsoft.Maps.MapTypeId.road,
         disableBirdseye: true,
+        disableStreetside: true,
         enableSearchLogo: false,
         showLocateMeButton: false,
         maxZoom: 20,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Photini-2020.4.0/src/photini/data/googlemap/script.js 
new/Photini-2020.10.1/src/photini/data/googlemap/script.js
--- old/Photini-2020.4.0/src/photini/data/googlemap/script.js   2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/photini/data/googlemap/script.js  2020-10-31 
11:20:51.000000000 +0100
@@ -1,6 +1,6 @@
 //  Photini - a simple photo metadata editor.
 //  http://github.com/jim-easterbrook/Photini
-//  Copyright (C) 2012-19  Jim Easterbrook  j...@jim-easterbrook.me.uk
+//  Copyright (C) 2012-20  Jim Easterbrook  j...@jim-easterbrook.me.uk
 //
 //  This program is free software: you can redistribute it and/or
 //  modify it under the terms of the GNU General Public License as
@@ -28,6 +28,7 @@
         fullscreenControl: false,
         scaleControl: true,
         streetViewControl: false,
+        tilt: 0,
         zoom: zoom,
         maxZoom: 20,
         mapTypeId: google.maps.MapTypeId.ROADMAP,
Binary files old/Photini-2020.4.0/src/photini/data/icons/win/icon.ico and 
new/Photini-2020.10.1/src/photini/data/icons/win/icon.ico differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/data/keys.txt 
new/Photini-2020.10.1/src/photini/data/keys.txt
--- old/Photini-2020.4.0/src/photini/data/keys.txt      2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/photini/data/keys.txt     2020-10-31 
11:20:51.000000000 +0100
@@ -25,10 +25,10 @@
 client_secret = dnkwV3UtYWVmMmlYeTJXZ2lVaUZDOFlB
 
 [googlemap]
-api_key = QUl6YVN5QTkyWVlqbmVzTDR0Q0I4eXdnNUE1LXVTdUJUN2JqQ0Jz
+api_key = QUl6YVN5QkNDY1VUdG41aVJuTHZ0MV9JZ0VrT19sdE9wNUJqdm93
 
 [bingmap]
-api_key = 
QXBUUU91WHJSczhCajlsUUxQem5RdjVrcjZxUm93UmpUSkItSnFUWXBPNmNHOFY5LWdrS2M3Q1M0S1VMUUQydQ==
+api_key = 
QWo2bHdHTG8taEVRMXYzeWx5eVk3eDQxcmVTNURnY0tQNWdxZ3BnSnJ3MVNhTF84dW5WdzViOHluUE90dlh5Vg==
 
 [openstreetmap]
 api_key =
@@ -37,4 +37,4 @@
 api_key = YWE3YjIwMTE3ZTBkNGE4NDk4NzQzMTc3MTI0NmY1NjU=
 
 [mapboxmap]
-api_key = 
cGsuZXlKMUlqb2lhbWx0TFdWaGMzUmxjbUp5YjI5cklpd2lZU0k2SW1Ock5XWTBZbVZ2WVRCdVpUUXpiMjFqYVhweWEzQm1aMlVpZlEuaEdQSzNBLUt5bGEwTHhickI3QVBHZw==
+api_key = 
cGsuZXlKMUlqb2lhbWx0TFdWaGMzUmxjbUp5YjI5cklpd2lZU0k2SW1OclpURXhNM05pTnpGc2IzSXllbTloZW5KaE1IUmpZV3NpZlEuZTd5YjlDWHRpdDExM2VOQ2tWeHBzdw==
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Photini-2020.4.0/src/photini/data/mapboxmap/script.js 
new/Photini-2020.10.1/src/photini/data/mapboxmap/script.js
--- old/Photini-2020.4.0/src/photini/data/mapboxmap/script.js   2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/photini/data/mapboxmap/script.js  2020-10-31 
11:20:51.000000000 +0100
@@ -18,9 +18,12 @@
 
 function loadMap(lat, lng, zoom)
 {
-    var streets = L.mapbox.styleLayer('mapbox://styles/mapbox/streets-v11');
-    var outdoors = L.mapbox.styleLayer('mapbox://styles/mapbox/outdoors-v11');
-    var satellite = L.mapbox.styleLayer('mapbox://styles/mapbox/satellite-v9');
+    var streets = L.mapbox.styleLayer(
+        'mapbox://styles/mapbox/streets-v11', {tileSize: 512, zoomOffset: -1});
+    var outdoors = L.mapbox.styleLayer(
+        'mapbox://styles/mapbox/outdoors-v11', {tileSize: 512, zoomOffset: 
-1});
+    var satellite = L.mapbox.styleLayer(
+        'mapbox://styles/mapbox/satellite-v9', {tileSize: 512, zoomOffset: 
-1});
     map = L.mapbox.map(document.getElementById("mapDiv"))
     map.setView([lat, lng], zoom);
     var baseMaps = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/exiv2.py 
new/Photini-2020.10.1/src/photini/exiv2.py
--- old/Photini-2020.4.0/src/photini/exiv2.py   2020-04-28 15:04:39.000000000 
+0200
+++ new/Photini-2020.10.1/src/photini/exiv2.py  2020-10-31 11:20:51.000000000 
+0100
@@ -18,10 +18,15 @@
 
 from __future__ import unicode_literals
 
+from contextlib import contextmanager
 import codecs
 import locale
 import logging
 import os
+import random
+import shutil
+import string
+import sys
 
 import six
 
@@ -63,10 +68,46 @@
 del data
 
 
+@contextmanager
+def temp_rename(path):
+    # Rename path to an ascii-safe file, further up the directory path
+    # if necessary, then restore to the original name and directory on
+    # completion. Only needed for workaround for bug in GExiv2 on
+    # Windows
+    dir_name, file_name = os.path.split(path)
+    while dir_name.encode('ascii', 'replace').decode('ascii') != dir_name:
+        dir_name = os.path.dirname(dir_name)
+    while True:
+        tmp_path = os.path.join(dir_name, file_name)
+        if (tmp_path.encode('ascii', 'replace').decode('ascii') == tmp_path
+                and not os.path.exists(tmp_path)):
+            break
+        file_name = ''.join(
+            random.choices(string.ascii_lowercase, k=8)) + '.tmp'
+    try:
+        logger.warning('Renaming %s to %s', path, tmp_path)
+        shutil.move(path, tmp_path)
+        yield tmp_path
+    finally:
+        logger.warning('Renaming %s to %s', tmp_path, path)
+        shutil.move(tmp_path, path)
+
+
 class Exiv2Metadata(GExiv2.Metadata):
     def __init__(self, path, buf=None):
         super(Exiv2Metadata, self).__init__()
         self._path = path
+        # workaround for bug in GExiv2 on Windows
+        # https://gitlab.gnome.org/GNOME/gexiv2/-/issues/59
+        self._gexiv_unsafe = False
+        if sys.platform == 'win32':
+            try:
+                self._path.encode('ascii')
+            except UnicodeEncodeError:
+                self._gexiv_unsafe = True
+        if self._gexiv_unsafe and not buf:
+            with open(self._path, 'rb') as f:
+                buf = f.read()
         if buf:
             # read metadata from buffer
             self.open_buf(buf)
@@ -311,7 +352,11 @@
         elif not self.has_iptc:
             self.clear_iptc()
         try:
-            self.save_file(self._path)
+            if self._gexiv_unsafe:
+                with temp_rename(self._path) as tmp_file:
+                    self.save_file(tmp_file)
+            else:
+                self.save_file(self._path)
             if file_times:
                 os.utime(self._path, file_times)
         except Exception as ex:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/ffmpeg.py 
new/Photini-2020.10.1/src/photini/ffmpeg.py
--- old/Photini-2020.4.0/src/photini/ffmpeg.py  2020-04-28 15:04:39.000000000 
+0200
+++ new/Photini-2020.10.1/src/photini/ffmpeg.py 2020-10-31 11:20:51.000000000 
+0100
@@ -20,13 +20,22 @@
 
 import json
 import subprocess
+import sys
 
 import six
 
 
+def startupinfo():
+    if sys.platform.startswith('win'):
+        startupinfo = subprocess.STARTUPINFO()
+        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+        return startupinfo
+    return None
+
 try:
     ffmpeg_version = subprocess.check_output(
-        ['ffmpeg', '-hide_banner', '-loglevel', 'warning', '-version'])
+        ['ffmpeg', '-hide_banner', '-loglevel', 'warning', '-version'],
+        startupinfo=startupinfo())
     if not six.PY2:
         ffmpeg_version = ffmpeg_version.decode('utf-8')
     ffmpeg_version = ffmpeg_version.splitlines()[0]
@@ -44,7 +53,8 @@
         cmd += options
         cmd += ['-print_format', 'json', path]
         p = subprocess.Popen(
-            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+            startupinfo=startupinfo())
         output, error = p.communicate()
         if p.returncode:
             if not six.PY2:
@@ -78,7 +88,8 @@
         cmd += ['-sws_flags', 'sinc', '-f', 'image2pipe',
                 '-vcodec', 'mjpeg', '-q:v', str(quality), 'pipe:1']
         p = subprocess.Popen(
-            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+            startupinfo=startupinfo())
         output, error = p.communicate()
         if p.returncode:
             if not six.PY2:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/gi.py 
new/Photini-2020.10.1/src/photini/gi.py
--- old/Photini-2020.4.0/src/photini/gi.py      2020-04-28 15:04:39.000000000 
+0200
+++ new/Photini-2020.10.1/src/photini/gi.py     2020-10-31 11:20:51.000000000 
+0100
@@ -1,6 +1,6 @@
 ##  Photini - a simple photo metadata editor.
 ##  http://github.com/jim-easterbrook/Photini
-##  Copyright (C) 2018-19  Jim Easterbrook  j...@jim-easterbrook.me.uk
+##  Copyright (C) 2018-20  Jim Easterbrook  j...@jim-easterbrook.me.uk
 ##
 ##  This program is free software: you can redistribute it and/or
 ##  modify it under the terms of the GNU General Public License as
@@ -67,7 +67,7 @@
     raise RuntimeError('Failed to initialise GExiv2')
 GExiv2.log_use_glib_logging()
 
-if GLib.glib_version >= (2, 46):
+if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) >= (2, 46):
     # the numeric values of GLib.LogLevelFlags suggest ERROR is more
     # severe than CRITICAL, Python's logging has them the other way
     # round
@@ -94,7 +94,8 @@
 gi_version = '{} {}, GExiv2 {}.{}.{}, GObject {}'.format(
     ('PyGObject', 'pgi')[using_pgi], gi.__version__, gexiv2_version[0],
     gexiv2_version[1], gexiv2_version[2], GObject._version)
-gi_version += ', GLib {}.{}.{}'.format(*GLib.glib_version)
+gi_version += ', GLib {}.{}.{}'.format(
+    GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION)
 if Gspell:
     gi_version += ', Gspell {}'.format(Gspell._version)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/googlephotos.py 
new/Photini-2020.10.1/src/photini/googlephotos.py
--- old/Photini-2020.4.0/src/photini/googlephotos.py    2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/photini/googlephotos.py   2020-10-31 
11:20:51.000000000 +0100
@@ -1,6 +1,6 @@
 ##  Photini - a simple photo metadata editor.
 ##  http://github.com/jim-easterbrook/Photini
-##  Copyright (C) 2019  Jim Easterbrook  j...@jim-easterbrook.me.uk
+##  Copyright (C) 2019-20  Jim Easterbrook  j...@jim-easterbrook.me.uk
 ##
 ##  This program is free software: you can redistribute it and/or
 ##  modify it under the terms of the GNU General Public License as
@@ -149,7 +149,12 @@
             if 'albums' not in rsp:
                 break
             for album in rsp['albums']:
-                yield album
+                if 'id' in album:
+                    safe_album = {'title': '', 'isWriteable': False}
+                    safe_album.update(album)
+                    yield safe_album
+                else:
+                    logger.info('Malformed album', album)
             if 'nextPageToken' not in rsp:
                 break
             params['pageToken'] = rsp['nextPageToken']
@@ -266,7 +271,7 @@
     def add_album(self, album, index=-1):
         widget = QtWidgets.QCheckBox(album['title'].replace('&', '&&'))
         widget.setProperty('id', album['id'])
-        widget.setEnabled('isWriteable' in album and album['isWriteable'])
+        widget.setEnabled(album['isWriteable'])
         if index >= 0:
             self.sets_widget.layout().insertWidget(index, widget)
         else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/imagelist.py 
new/Photini-2020.10.1/src/photini/imagelist.py
--- old/Photini-2020.4.0/src/photini/imagelist.py       2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/photini/imagelist.py      2020-10-31 
11:20:51.000000000 +0100
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 ##  Photini - a simple photo metadata editor.
 ##  http://github.com/jim-easterbrook/Photini
-##  Copyright (C) 2012-19  Jim Easterbrook  j...@jim-easterbrook.me.uk
+##  Copyright (C) 2012-20  Jim Easterbrook  j...@jim-easterbrook.me.uk
 ##
 ##  This program is free software: you can redistribute it and/or
 ##  modify it under the terms of the GNU General Public License as
@@ -656,7 +656,7 @@
         self.size_slider.setTracking(False)
         self.size_slider.setRange(4, 9)
         self.size_slider.setPageStep(1)
-        self.size_slider.setValue(self.thumb_size / 20)
+        self.size_slider.setValue(self.thumb_size // 20)
         self.size_slider.setTickPosition(QtWidgets.QSlider.TicksBelow)
         width = self.size_slider.sizeHint().width()
         self.size_slider.setMinimumWidth(width * 7 // 4)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/photini/importer.py 
new/Photini-2020.10.1/src/photini/importer.py
--- old/Photini-2020.4.0/src/photini/importer.py        2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/photini/importer.py       2020-10-31 
11:20:51.000000000 +0100
@@ -180,11 +180,12 @@
 class FileCopier(QtCore.QObject):
     output = QtCore.pyqtSignal(dict, six.text_type)
 
-    def __init__(self, source, copy_list, move, *args, **kwds):
+    def __init__(self, source, copy_list, move, updating, *args, **kwds):
         super(FileCopier, self).__init__(*args, **kwds)
         self.source = source
         self.copy_list = copy_list
         self.move = move
+        self.updating = updating
         self.running = True
 
     @QtCore.pyqtSlot()
@@ -193,7 +194,10 @@
         status = 'ok'
         try:
             for info in self.source.copy_files(self.copy_list, self.move):
+                # don't display image until previous one has been displayed
+                self.updating.lock()
                 self.output.emit(info, status)
+                self.updating.unlock()
                 if not self.running:
                     break
         except Exception as ex:
@@ -286,6 +290,7 @@
         self.file_list = []
         self.source = None
         self.file_copier = None
+        self.updating = QtCore.QMutex()
         # source selector
         box = QtWidgets.QHBoxLayout()
         box.setContentsMargins(0, 0, 0, 0)
@@ -604,7 +609,8 @@
             self.move_button.setEnabled(False)
         self.last_file_copied = None, datetime.min
         # start file copier in a separate thread
-        self.file_copier = FileCopier(self.source, copy_list, move)
+        self.file_copier = FileCopier(
+            self.source, copy_list, move, self.updating)
         self.file_copier_thread = QtCore.QThread(self)
         self.file_copier.moveToThread(self.file_copier_thread)
         self.file_copier.output.connect(self.file_copied)
@@ -629,7 +635,10 @@
         if status != 'ok':
             self._fail()
             return
+        # block copier thread until image has been displayed
+        self.updating.lock()
         self.image_list.open_file(info['dest_path'])
+        self.updating.unlock()
         if self.last_file_copied[1] < info['timestamp']:
             self.last_file_copied = info['dest_path'], info['timestamp']
         for n in range(self.file_list_widget.count()):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/windows/README.txt 
new/Photini-2020.10.1/src/windows/README.txt
--- old/Photini-2020.4.0/src/windows/README.txt 2020-04-28 15:04:39.000000000 
+0200
+++ new/Photini-2020.10.1/src/windows/README.txt        2020-10-31 
11:20:51.000000000 +0100
@@ -7,25 +7,18 @@
 1/ Install Inno Setup from http://www.jrsoftware.org/isinfo.php
 
 64-bit:
-1/ Install 64-bit MSYS2 and Photini dependencies to C:\photini64:
-   pacman -Syuu
-   pacman -S 
mingw-w64-x86_64-{gexiv2,python3-gobject,python3-pyqt5,python3-pip}
-   pip install appdirs gpxpy pip PyGObject requests six
-2/ Edit C:\photini64\etc\pacman.conf and comment out the [mingw32] section.
-3/ Remove unneeded packages:
-   pacman -Rdd mingw-w64-x86_64-{icu-debug-libs,tcl,tk}
-   pacman -Scc
-4/ Run clean_mingw32-64.py to remove unneeded files.
-5/ Run create_installer_64bit.iss to create the installer.
+1/ Install 64-bit MSYS2 as normal to C:/msys64.
+Using C:/msys64/mingw64.exe shell:
+2/ Install pacman-contrib, $MINGW_PACKAGE_PREFIX-python and any other software 
you like.
+3/ Run 'python src/windows/copy_base_system.py' to copy essential files only 
to C:/photini_temp_64.
+4/ Run create_installer_64bit.iss to create the installer.
+5/ Delete C:/photini_temp_64.
 
 32-bit:
-1/ Install 32-bit MSYS2 and Photini dependencies to C:\photini32:
-   pacman -Syuu
-   pacman -S mingw-w64-i686-{gexiv2,python3-gobject,python3-pyqt5,python3-pip}
-   pip install appdirs gpxpy pip PyGObject requests six
-2/ Edit C:\photini32\etc\pacman.conf and comment out the [mingw64] section.
-3/ Remove unneeded packages:
-   pacman -Rdd mingw-w64-i686-{icu-debug-libs,tcl,tk}
-   pacman -Scc
-4/ Run clean_mingw32-64.py to remove unneeded files.
+1/ Install 32-bit MSYS2 as normal to C:/msys32.
+Using C:/msys32/mingw32.exe shell:
+2/ Edit /etc/pacman.conf and change SigLevel to Never, then run pacman -Syu 
and so on.
+3/ Install pacman-contrib, $MINGW_PACKAGE_PREFIX-python and any other software 
you like.
+4/ Run 'python src/windows/copy_base_system.py' to copy essential files only 
to C:/photini_temp_32.
 5/ Run create_installer_32bit.iss to create the installer.
+6/ Delete C:/photini_temp_32.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/windows/clean_mingw32-64.py 
new/Photini-2020.10.1/src/windows/clean_mingw32-64.py
--- old/Photini-2020.4.0/src/windows/clean_mingw32-64.py        2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/windows/clean_mingw32-64.py       1970-01-01 
01:00:00.000000000 +0100
@@ -1,123 +0,0 @@
-import os
-import sys
-
-
-def main():
-    for params in ({'TARGET': 'C:/photini32',
-                    '+'     : '32',
-                    '-'     : '64'},
-                   {'TARGET': 'C:/photini64',
-                    '+'     : '64',
-                    '-'     : '32'}
-                   ):
-        # remove unwanted directories
-        for path in (
-                '/clang{-}',
-                '/mingw{-}',
-                '/mingw{+}/lib/cmake',
-                '/mingw{+}/lib/include',
-                '/mingw{+}/lib/pkgconfig',
-                '/mingw{+}/lib/python2.7',
-                '/mingw{+}/lib/python3.7/test',
-                '/mingw{+}/share/doc',
-                '/mingw{+}/share/gtk-doc',
-                '/mingw{+}/share/man',
-                '/mingw{+}/share/qt5/doc',
-                '/mingw{+}/share/qt5/examples',
-                '/mingw{+}/share/qt5/plugins/designer',
-                '/mingw{+}/share/qt5/plugins/geoservices',
-                '/mingw{+}/share/qt5/plugins/qmltooling',
-                '/mingw{+}/share/qt5/qml',
-                '/usr/share/doc',
-                '/usr/share/man',
-                ):
-            root_dir = params['TARGET'] + path.format(**params)
-            if not os.path.isdir(root_dir):
-                continue
-            for root, dirs, files in os.walk(root_dir, topdown=False):
-                for name in files:
-                    test_name = name.lower()
-                    for word in (
-                            'copying', 'copyright', 'licence', 'license'):
-                        if word in test_name:
-                            break
-                    else:
-                        full_path = os.path.join(root, name)
-                        print('Delete', full_path)
-                        os.unlink(full_path)
-                for name in dirs:
-                    test_name = name.lower()
-                    for word in (
-                            'copying', 'copyright', 'licence', 'license'):
-                        if word in test_name:
-                            break
-                    else:
-                        full_path = os.path.join(root, name)
-                        if not os.listdir(full_path):
-                            print('Delete', full_path)
-                            os.rmdir(full_path)
-            if not os.listdir(root_dir):
-                print('Delete', root_dir)
-                os.rmdir(root_dir)
-        # remove Qt5 debug files
-        for path in ('/mingw{+}/bin/',
-                     '/mingw{+}/lib/',
-                     '/mingw{+}/share/qt5/plugins/'):
-            root_dir = params['TARGET'] + path.format(**params)
-            for root, dirs, files in os.walk(root_dir):
-                for name in files:
-                    if 'd.' in name and ('Qt5' in name or 'qt5' in root):
-                        normal_name = name.replace('d.', '.')
-                        if normal_name in files:
-                            debug_path = os.path.join(root, name)
-                            print('Delete', debug_path)
-                            os.unlink(debug_path)
-        # remove unwanted terminfo
-        for path in (
-                '/mingw{+}/lib/terminfo',
-                '/mingw{+}/share/terminfo',
-                '/usr/lib/terminfo',
-                '/usr/share/terminfo'):
-            root_dir = params['TARGET'] + path.format(**params)
-            for root, dirs, files in os.walk(root_dir):
-                for name in files:
-                    if 'linux' in name.lower() or 'xterm' in name.lower():
-                        continue
-                    debug_path = os.path.join(root, name)
-                    print('Delete', debug_path)
-                    os.unlink(debug_path)
-        # remove unwanted files
-        for path in (
-                '/maintenancetool.exe',
-                '/maintenancetool.ini',
-                '/maintenancetool.dat',
-                '/mingw{-}.exe',
-                '/mingw{-}.ini',
-                '/mingw{+}/bin/qdoc.exe',
-                '/mingw{+}/bin/Qt53D*',
-                '/mingw{+}/bin/Qt5Designer*',
-                '/mingw{+}/lib/Qt53D*',
-                '/mingw{+}/lib/Qt5Designer*',
-                '/mingw{+}/lib/libQt53D*',
-                '/mingw{+}/lib/libQt5Designer*',
-                '/var/lib/pacman/sync/mingw{-}.db',
-                '/var/lib/pacman/sync/mingw{-}.db.sig',
-                ):
-            target_path = params['TARGET'] + path.format(**params)
-            if target_path[-1] == '*':
-                dir_name, base_name = os.path.split(target_path)
-                base_name = base_name[:-1]
-                for file_name in os.listdir(dir_name):
-                    if file_name.startswith(base_name):
-                        target_file = os.path.join(dir_name, file_name)
-                        print('Delete', target_file)
-                        os.unlink(target_file)
-            else:
-                if os.path.exists(target_path):
-                    print('Delete', target_path)
-                    os.unlink(target_path)
-    return 0
-
-
-if __name__ == '__main__':
-    sys.exit(main())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/windows/copy_base_system.py 
new/Photini-2020.10.1/src/windows/copy_base_system.py
--- old/Photini-2020.4.0/src/windows/copy_base_system.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/Photini-2020.10.1/src/windows/copy_base_system.py       2020-10-31 
11:20:51.000000000 +0100
@@ -0,0 +1,68 @@
+##  Photini - a simple photo metadata editor.
+##  http://github.com/jim-easterbrook/Photini
+##  Copyright (C) 2020  Jim Easterbrook  j...@jim-easterbrook.me.uk
+##
+##  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, either version 3 of the
+##  License, or (at your option) any later version.
+##
+##  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, see
+##  <http://www.gnu.org/licenses/>.
+
+import os
+import shutil
+import subprocess
+import sys
+
+
+def get_dependencies(name):
+    packages = subprocess.check_output(['pactree', '-u', name])
+    for package in packages.splitlines():
+        yield package.decode('utf-8')
+
+
+def get_files(name):
+    files = subprocess.check_output(['pacman', '-Qlq', name])
+    for name in files.splitlines():
+        yield name.decode('utf-8')
+
+
+def main():
+    if sys.maxsize > 2**32:
+        root = 'C:/msys64'
+        install = 'C:/photini_temp_64'
+        packages = ('base', 'pacman')
+    else:
+        root = 'C:/msys32'
+        install = 'C:/photini_temp_32'
+        packages = ('filesystem', 'msys2-launcher', 'pacman')
+    dependencies = []
+    for package in packages:
+        for dependency in get_dependencies(package):
+            if dependency in dependencies:
+                continue
+            dependencies.append(dependency)
+            for path in get_files(dependency):
+                dest = install + path
+                if os.path.exists(dest):
+                    continue
+                src = root + path
+                if not os.path.exists(src):
+                    continue
+                print(dest)
+                if os.path.isdir(src):
+                    os.makedirs(dest)
+                else:
+                    shutil.copy2(src, dest, follow_symlinks=False)
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Photini-2020.4.0/src/windows/create_installer_32bit.iss 
new/Photini-2020.10.1/src/windows/create_installer_32bit.iss
--- old/Photini-2020.4.0/src/windows/create_installer_32bit.iss 2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/windows/create_installer_32bit.iss        
2020-10-31 11:20:51.000000000 +0100
@@ -1,8 +1,9 @@
 #define MSYS "{app}\msys2";
-#define PythonW "{app}\msys2\mingw32\bin\python3w.exe";
+#define PythonW "{app}\msys2\mingw32\bin\pythonw.exe";
 #define Shell "{app}\msys2\usr\bin\env.exe";
-#define SrcDir "C:\photini32"
-#define Version "2019.10.0"
+#define SrcDir "C:\photini_temp_32"
+#define SrcIcon "..\photini\data\icons\win\icon.ico"
+#define Version "2020.10.0"
 
 [Setup]
 VersionInfoVersion={#Version}
@@ -12,8 +13,8 @@
 AppVerName=Photini
 AppPublisher=Jim Easterbrook
 AppPublisherURL=https://github.com/jim-easterbrook/Photini
-AppCopyright=Copyright (C) 2012-19 Jim Easterbrook
-DefaultDirName={pf}\Photini
+AppCopyright=Copyright (C) 2012-20 Jim Easterbrook
+DefaultDirName={autopf}\Photini
 DefaultGroupName=Photini
 AllowNoIcons=yes
 OutputBaseFilename=photini-win32-{#Version}
@@ -22,9 +23,9 @@
 SolidCompression=yes
 LicenseFile=..\..\LICENSE.txt
 InfoBeforeFile=info.txt
-SetupIconFile=icon.ico
+SetupIconFile={#SrcIcon}
 UninstallDisplayIcon={app}\icon.ico
-ExtraDiskSpaceRequired=8684130
+ExtraDiskSpaceRequired=1568000000
 
 [Languages]
 Name: "english"; MessagesFile: "compiler:Default.isl"
@@ -35,9 +36,8 @@
 
 [Files]
 Source: "{#SrcDir}\*"; DestDir: "{#MSYS}"; \
-  Excludes: 
"\dev,\home\*,\proc,\tmp\*,\var\log\*,cache,cmake,include,pkgconfig,__pycache__,*.a,*.h,*.prl";
 \
   Flags: ignoreversion recursesubdirs createallsubdirs
-Source: "icon.ico"; DestDir: "{app}"; Flags: ignoreversion
+Source: {#SrcIcon}; DestDir: "{app}"; Flags: ignoreversion
 Source: "install_photini_32.cmd"; DestDir: "{app}"; Flags: ignoreversion
 
 [Icons]
@@ -45,6 +45,8 @@
   Parameters: "-m photini.editor"; Comment: "Photo metadata editor"; \
   IconFileName: {app}\icon.ico
 Name: "{group}\Photini documentation"; Filename: 
"https://photini.readthedocs.io/";
+Name: "{group}\MinGW"; Filename: "{app}\msys2\mingw32.exe"; \
+  Comment: "MSYS2 command shell"; IconFileName: {app}\msys2\mingw32.ico
 Name: "{commondesktop}\Photini"; Filename: "{#PythonW}"; \
   Parameters: "-m photini.editor"; Comment: "Photo metadata editor"; \
   IconFileName: {app}\icon.ico; Tasks: desktopicon
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Photini-2020.4.0/src/windows/create_installer_64bit.iss 
new/Photini-2020.10.1/src/windows/create_installer_64bit.iss
--- old/Photini-2020.4.0/src/windows/create_installer_64bit.iss 2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/windows/create_installer_64bit.iss        
2020-10-31 11:20:51.000000000 +0100
@@ -1,8 +1,9 @@
 #define MSYS "{app}\msys2";
-#define PythonW "{app}\msys2\mingw64\bin\python3w.exe";
+#define PythonW "{app}\msys2\mingw64\bin\pythonw.exe";
 #define Shell "{app}\msys2\usr\bin\env.exe";
-#define SrcDir "C:\photini64"
-#define Version "2019.10.0"
+#define SrcDir "C:\photini_temp_64"
+#define SrcIcon "..\photini\data\icons\win\icon.ico"
+#define Version "2020.10.0"
 
 [Setup]
 VersionInfoVersion={#Version}
@@ -12,8 +13,8 @@
 AppVerName=Photini
 AppPublisher=Jim Easterbrook
 AppPublisherURL=https://github.com/jim-easterbrook/Photini
-AppCopyright=Copyright (C) 2012-19 Jim Easterbrook
-DefaultDirName={pf}\Photini
+AppCopyright=Copyright (C) 2012-20 Jim Easterbrook
+DefaultDirName={autopf}\Photini
 DefaultGroupName=Photini
 AllowNoIcons=yes
 OutputBaseFilename=photini-win64-{#Version}
@@ -22,9 +23,9 @@
 SolidCompression=yes
 LicenseFile=..\..\LICENSE.txt
 InfoBeforeFile=info.txt
-SetupIconFile=icon.ico
+SetupIconFile={#SrcIcon}
 UninstallDisplayIcon={app}\icon.ico
-ExtraDiskSpaceRequired=8684130
+ExtraDiskSpaceRequired=1622000000
 
 [Languages]
 Name: "english"; MessagesFile: "compiler:Default.isl"
@@ -35,16 +36,17 @@
 
 [Files]
 Source: "{#SrcDir}\*"; DestDir: "{#MSYS}"; \
-  Excludes: 
"\dev,\home\*,\proc,\tmp\*,\var\log\*,cache,cmake,include,pkgconfig,__pycache__,*.a,*.h,*.prl";
 \
   Flags: ignoreversion recursesubdirs createallsubdirs
-Source: "icon.ico"; DestDir: "{app}"; Flags: ignoreversion
+Source: {#SrcIcon}; DestDir: "{app}"; Flags: ignoreversion
 Source: "install_photini_64.cmd"; DestDir: "{app}"; Flags: ignoreversion
 
 [Icons]
 Name: "{group}\Photini"; Filename: "{#PythonW}"; \
   Parameters: "-m photini.editor"; Comment: "Photo metadata editor"; \
   IconFileName: {app}\icon.ico
-Name: "{group}\Photini documentation"; Filename: 
"https://photini.readthedocs.io/";
+Name: "{group}\Photini documentation"; Filename: 
"https://photini.readthedocs.io/";
+Name: "{group}\MinGW"; Filename: "{app}\msys2\mingw64.exe"; \
+  Comment: "MSYS2 command shell"; IconFileName: {app}\msys2\mingw64.ico
 Name: "{commondesktop}\Photini"; Filename: "{#PythonW}"; \
   Parameters: "-m photini.editor"; Comment: "Photo metadata editor"; \
   IconFileName: {app}\icon.ico; Tasks: desktopicon
Binary files old/Photini-2020.4.0/src/windows/icon.ico and 
new/Photini-2020.10.1/src/windows/icon.ico differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/windows/info.txt 
new/Photini-2020.10.1/src/windows/info.txt
--- old/Photini-2020.4.0/src/windows/info.txt   2020-04-28 15:04:39.000000000 
+0200
+++ new/Photini-2020.10.1/src/windows/info.txt  2020-10-31 11:20:51.000000000 
+0100
@@ -1 +1 @@
-This installer downloads some components, ensuring you get the latest 
versions. Please ensure your computer has a working internet connection during 
the installation process. A console window will open while these components are 
downloaded and installed. This is nothing to worry about.
+This installer downloads 3-400 MByte of additional software. Please ensure 
your computer has a working internet connection during the installation 
process. A console window will open while these components are downloaded and 
installed. This is nothing to worry about.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/windows/install_photini_32.cmd 
new/Photini-2020.10.1/src/windows/install_photini_32.cmd
--- old/Photini-2020.4.0/src/windows/install_photini_32.cmd     2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/windows/install_photini_32.cmd    2020-10-31 
11:20:51.000000000 +0100
@@ -2,39 +2,42 @@
 SETLOCAL
 
 SET bash=msys2\usr\bin\env.exe MSYSTEM=MINGW32 /bin/bash -l -c
-SET group=mingw-w64-i686
 
-%bash% "qtbinpatcher --nobackup --qt-dir=/mingw32/bin || sleep 300"
+%bash% "pacman -Syu --noconfirm || sleep 300"
 
-%bash% "python3 -m pip install -U --no-cache-dir --disable-pip-version-check 
photini || sleep 300"
+%bash% "pacman -Su --noconfirm || sleep 300"
+
+%bash% "pacman -S --noconfirm 
$MINGW_PACKAGE_PREFIX-{gexiv2,python-gobject,python-pyqt5,python-pip} || sleep 
300"
+
+%bash% "python -m pip install -U --no-cache-dir --disable-pip-version-check 
photini gpxpy || sleep 300"
 
 FOR %%G IN (%*) DO (
   IF %%G==upload (
-    %bash% "python3 -m pip install -U --no-cache-dir 
--disable-pip-version-check requests-oauthlib keyring || sleep 300"
+    %bash% "python -m pip install -U --no-cache-dir 
--disable-pip-version-check requests-oauthlib keyring || sleep 300"
   )
   IF %%G==upload\flickr (
-    %bash% "python3 -m pip install -U --no-cache-dir 
--disable-pip-version-check flickrapi || sleep 300"
+    %bash% "python -m pip install -U --no-cache-dir 
--disable-pip-version-check flickrapi || sleep 300"
   )
   IF %%G==spell (
-    %bash% "pacman -S --noconfirm %group%-gspell || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-gspell || sleep 300"
   )
   IF %%G==spell\en (
-    %bash% "pacman -S --noconfirm %group%-aspell-en || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-en || sleep 300"
   )
   IF %%G==spell\fr (
-    %bash% "pacman -S --noconfirm %group%-aspell-fr || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-fr || sleep 300"
   )
   IF %%G==spell\de (
-    %bash% "pacman -S --noconfirm %group%-aspell-de || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-de || sleep 300"
   )
   IF %%G==spell\ru (
-    %bash% "pacman -S --noconfirm %group%-aspell-ru || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-ru || sleep 300"
   )
   IF %%G==spell\es (
-    %bash% "pacman -S --noconfirm %group%-aspell-es || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-es || sleep 300"
   )
   IF %%G==ffmpeg (
-    %bash% "pacman -S --noconfirm %group%-ffmpeg || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-ffmpeg || sleep 300"
   )
 )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/windows/install_photini_64.cmd 
new/Photini-2020.10.1/src/windows/install_photini_64.cmd
--- old/Photini-2020.4.0/src/windows/install_photini_64.cmd     2020-04-28 
15:04:39.000000000 +0200
+++ new/Photini-2020.10.1/src/windows/install_photini_64.cmd    2020-10-31 
11:20:51.000000000 +0100
@@ -2,39 +2,42 @@
 SETLOCAL
 
 SET bash=msys2\usr\bin\env.exe MSYSTEM=MINGW64 /bin/bash -l -c
-SET group=mingw-w64-x86_64
 
-%bash% "qtbinpatcher --nobackup --qt-dir=/mingw64/bin || sleep 300"
+%bash% "pacman -Syu --noconfirm || sleep 300"
 
-%bash% "python3 -m pip install -U --no-cache-dir --disable-pip-version-check 
photini || sleep 300"
+%bash% "pacman -Su --noconfirm || sleep 300"
+
+%bash% "pacman -S --noconfirm 
$MINGW_PACKAGE_PREFIX-{gexiv2,python-gobject,python-pyqt5,python-pip} || sleep 
300"
+
+%bash% "python -m pip install -U --no-cache-dir --disable-pip-version-check 
photini gpxpy || sleep 300"
 
 FOR %%G IN (%*) DO (
   IF %%G==upload (
-    %bash% "python3 -m pip install -U --no-cache-dir 
--disable-pip-version-check requests-oauthlib keyring || sleep 300"
+    %bash% "python -m pip install -U --no-cache-dir 
--disable-pip-version-check requests-oauthlib keyring || sleep 300"
   )
   IF %%G==upload\flickr (
-    %bash% "python3 -m pip install -U --no-cache-dir 
--disable-pip-version-check flickrapi || sleep 300"
+    %bash% "python -m pip install -U --no-cache-dir 
--disable-pip-version-check flickrapi || sleep 300"
   )
   IF %%G==spell (
-    %bash% "pacman -S --noconfirm %group%-gspell || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-gspell || sleep 300"
   )
   IF %%G==spell\en (
-    %bash% "pacman -S --noconfirm %group%-aspell-en || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-en || sleep 300"
   )
   IF %%G==spell\fr (
-    %bash% "pacman -S --noconfirm %group%-aspell-fr || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-fr || sleep 300"
   )
   IF %%G==spell\de (
-    %bash% "pacman -S --noconfirm %group%-aspell-de || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-de || sleep 300"
   )
   IF %%G==spell\ru (
-    %bash% "pacman -S --noconfirm %group%-aspell-ru || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-ru || sleep 300"
   )
   IF %%G==spell\es (
-    %bash% "pacman -S --noconfirm %group%-aspell-es || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-aspell-es || sleep 300"
   )
   IF %%G==ffmpeg (
-    %bash% "pacman -S --noconfirm %group%-ffmpeg || sleep 300"
+    %bash% "pacman -S --noconfirm $MINGW_PACKAGE_PREFIX-ffmpeg || sleep 300"
   )
 )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2020.4.0/src/windows/install_shortcuts.vbs 
new/Photini-2020.10.1/src/windows/install_shortcuts.vbs
--- old/Photini-2020.4.0/src/windows/install_shortcuts.vbs      1970-01-01 
01:00:00.000000000 +0100
+++ new/Photini-2020.10.1/src/windows/install_shortcuts.vbs     2020-10-31 
11:20:51.000000000 +0100
@@ -0,0 +1,83 @@
+Set args = WScript.Arguments.Unnamed
+Set options = WScript.Arguments.Named
+strTargetPath = args(0)
+strIconPath = args(1)
+strSystemPrefix = args(2)
+
+Set objShell = WScript.CreateObject("Wscript.Shell")
+
+If options.Exists("user") Then
+  'Use this user's start menu and desktop
+  strDesktop = objShell.SpecialFolders("Desktop")
+  strGroup = objShell.SpecialFolders("StartMenu") & "\Photini"
+Else
+  'Use all users' start menu and desktop
+  strDesktop = objShell.SpecialFolders("AllUsersDesktop")
+  strGroup = objShell.SpecialFolders("AllUsersStartMenu") & "\Photini"
+End If
+
+strDesktopLink = strDesktop & "\Photini.lnk"
+strShortcutLink = strGroup & "\Photini.lnk"
+strDocumentationLink = strGroup & "\Photini documentation.url"
+strShellLink = strGroup & "\MinGW.lnk"
+
+On Error Resume Next
+
+Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
+
+If args.count > 3 Then
+    'Write paths to result file
+    strResultFile = args(3)
+    Set objResult = FSO.CreateTextFile(strResultFile, True)
+    If Err.Number <> 0 then WScript.Quit Err.Number
+    objResult.WriteLine strDesktopLink
+    objResult.WriteLine strShortcutLink
+    objResult.WriteLine strDocumentationLink
+    objResult.WriteLine strShellLink
+    objResult.Close()
+End If
+
+If Not (options.Exists("user") Or options.Exists("elevated")) Then
+    'Re-run this script as administrator
+    Set appShell = CreateObject("Shell.Application")
+    appShell.ShellExecute "cscript.exe", """" & WScript.ScriptFullName & """" 
& _
+      " """ & strTargetPath & """ """ & strIconPath & """ """ & 
strSystemPrefix & _
+      """ /elevated", , "runas", 0
+    WScript.Quit Err.Number
+End If
+
+'Create start menu group
+If Not FSO.FolderExists(strGroup) Then
+    FSO.CreateFolder(strGroup)
+    If Err.Number <> 0 then WScript.Quit Err.Number
+End If
+
+'Create program desktop shortcut
+Set objShortcut = objShell.CreateShortcut(strDesktopLink)
+objShortcut.TargetPath = strTargetPath
+objShortcut.Description = "Photini metadata editor"
+objShortcut.IconLocation = strIconPath
+objShortcut.Save
+If Err.Number <> 0 then WScript.Quit Err.Number
+
+'Create program start menu shortcut
+Set objShortcut = objShell.CreateShortcut(strShortcutLink)
+objShortcut.TargetPath = strTargetPath
+objShortcut.Description = "Photini metadata editor"
+objShortcut.IconLocation = strIconPath
+objShortcut.Save
+If Err.Number <> 0 then WScript.Quit Err.Number
+
+'Create documentation start menu shortcut
+Set objShortcut = objShell.CreateShortcut(strDocumentationLink)
+objShortcut.TargetPath = "https://photini.readthedocs.io/";
+objShortcut.Save
+If Err.Number <> 0 then WScript.Quit Err.Number
+
+'Create command shell start menu shortcut
+Set objShortcut = objShell.CreateShortcut(strShellLink)
+objShortcut.TargetPath = strSystemPrefix & ".exe"
+objShortcut.Description = "MSYS2 MinGW command shell"
+objShortcut.IconLocation = strSystemPrefix & ".ico"
+objShortcut.Save
+If Err.Number <> 0 then WScript.Quit Err.Number


Reply via email to