Hello community,

here is the log from the commit of package Photini for openSUSE:Factory checked 
in at 2017-08-19 10:56:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/Photini (Old)
 and      /work/SRC/openSUSE:Factory/.Photini.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "Photini"

Sat Aug 19 10:56:25 2017 rev:4 rq:517592 version:2017.8.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/Photini/Photini.changes  2017-08-10 
14:13:39.863264210 +0200
+++ /work/SRC/openSUSE:Factory/.Photini.new/Photini.changes     2017-08-19 
10:56:28.891916068 +0200
@@ -1,0 +2,10 @@
+Fri Aug 18 13:41:32 UTC 2017 - aloi...@gmx.com
+
+- Update to 2017.08.1
+  * Added option to preserve file timestamps. 
+  * Added option to change copyright boilerplate text. 
+  * Added config file option to change application style. 
+  * Fix bug with importing files with spaces in their names. 
+  * Changed importer template marker from () to {}.
+
+-------------------------------------------------------------------

Old:
----
  Photini-2017.8.0.tar.gz

New:
----
  Photini-2017.8.1.tar.gz

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

Other differences:
------------------
++++++ Photini.spec ++++++
--- /var/tmp/diff_new_pack.8OlvPa/_old  2017-08-19 10:56:30.003759304 +0200
+++ /var/tmp/diff_new_pack.8OlvPa/_new  2017-08-19 10:56:30.011758176 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           Photini
-Version:        2017.8.0
+Version:        2017.8.1
 Release:        0
 Summary:        Digital photograph metadata (EXIF, IPTC, XMP) editing 
application
 License:        GPL-3.0+

++++++ Photini-2017.8.0.tar.gz -> Photini-2017.8.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/CHANGELOG.txt 
new/Photini-2017.8.1/CHANGELOG.txt
--- old/Photini-2017.8.0/CHANGELOG.txt  2017-08-09 13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/CHANGELOG.txt  2017-08-18 15:00:23.000000000 +0200
@@ -16,6 +16,13 @@
 along with this program.  If not, see
 <http://www.gnu.org/licenses/>.
 
+Changes in v2017.8.1:
+  1/ Added option to preserve file timestamps.
+  2/ Added option to change copyright boilerplate text.
+  3/ Added config file option to change application style.
+  4/ Fix bug with importing files with spaces in their names.
+  5/ Changed importer template marker from () to {}.
+
 Changes in v2017.8.0:
   1/ Use Exif/Xmp thumbnails instead of computing from image data.
   2/ Improved video file metadata reading.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/README.rst 
new/Photini-2017.8.1/README.rst
--- old/Photini-2017.8.0/README.rst     2017-08-09 13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/README.rst     2017-08-18 15:00:23.000000000 +0200
@@ -1,7 +1,7 @@
 Photini
 =======
 
-A free, easy to use, digital photograph metadata (EXIF, IPTC, XMP) editing 
application.
+A free, easy to use, digital photograph metadata (Exif, IPTC, XMP) editing 
application.
 
 "Metadata" is said to mean "data about data".
 In the context of digital photographs this means information that isn't 
essential in order to display the image, but tells you something about it.
@@ -26,12 +26,12 @@
 *   Spell checking of some fields (optional).
 *   Can set metadata for multiple images simultaneously.
 *   Can adjust picture date & time and time zone (of multiple images 
simultaneously).
-*   Reads EXIF, IPTC and XMP metadata, writes all three to maximise 
compatibility with other software.
+*   Reads Exif, IPTC and XMP metadata, writes all three to maximise 
compatibility with other software.
 *   Writes metadata to image files or to XMP "sidecar" files.
 *   Can import photographs from many digital cameras.
 *   Upload to Flickr_ and/or Facebook_ and/or `Google Photos`_ with reuse of 
metadata.
 
-.. image:: http://photini.readthedocs.io/en/latest/_images/screenshot_66.png
+.. image:: http://photini.readthedocs.io/en/latest/_images/screenshot_69.png
    :alt: Geotagging screenshot
 
 *   Geotagging - search map to find named places.
@@ -75,6 +75,7 @@
 ------------
 
 If you encounter any problems installing or running Photini, please email 
j...@jim-easterbrook.me.uk and I'll respond as soon as I can.
+There is also an email list or forum for discussions about Photini at 
https://groups.google.com/forum/#!forum/photini.
 If you discover a bug and have a GitHub account then please file a bug report 
on the GitHub `"issues" page`_.
 
 Internationalisation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/setup.py 
new/Photini-2017.8.1/setup.py
--- old/Photini-2017.8.0/setup.py       2017-08-09 13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/setup.py       2017-08-18 15:00:23.000000000 +0200
@@ -234,7 +234,9 @@
       description = 'Simple photo metadata editor',
       long_description = long_description,
       classifiers = [
-          'Development Status :: 4 - Beta',
+          'Development Status :: 5 - Production/Stable',
+          'Environment :: Win32 (MS Windows)',
+          'Environment :: X11 Applications :: Qt',
           'Intended Audience :: End Users/Desktop',
           'License :: OSI Approved :: GNU General Public License v3 or later 
(GPLv3+)',
           'Operating System :: OS Independent',
@@ -249,7 +251,6 @@
       package_data = {
           'photini' : ['data/*.txt', 'data/*.png', 'data/icons/*/photini.png',
                        'data/*map/grey_marker.png', 'data/*map/script.js',
-                       'data/bingmap/grey_marker_v8.png',
                        'data/lang/*.qm'],
           },
       data_files = data_files,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/doc/conf.py 
new/Photini-2017.8.1/src/doc/conf.py
--- old/Photini-2017.8.0/src/doc/conf.py        2017-08-09 13:20:13.000000000 
+0200
+++ new/Photini-2017.8.1/src/doc/conf.py        2017-08-18 15:00:23.000000000 
+0200
@@ -1,5 +1,22 @@
 # -*- coding: utf-8 -*-
-#
+##  Photini - a simple photo metadata editor.
+##  http://github.com/jim-easterbrook/Photini
+##  Copyright (C) 2012-17  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/>.
+
 # Photini documentation build configuration file, created by
 # sphinx-quickstart on Sun Sep 30 21:53:44 2012.
 #
@@ -32,6 +49,13 @@
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
 
+rst_epilog = """
+----
+
+Comments or questions? Please subscribe to the Photini mailing list
+https://groups.google.com/forum/#!forum/photini and let us know.
+"""
+
 # The suffix of source filenames.
 source_suffix = '.rst'
 
Binary files old/Photini-2017.8.0/src/doc/images/screenshot_31.png and 
new/Photini-2017.8.1/src/doc/images/screenshot_31.png differ
Binary files old/Photini-2017.8.0/src/doc/images/screenshot_32.png and 
new/Photini-2017.8.1/src/doc/images/screenshot_32.png differ
Binary files old/Photini-2017.8.0/src/doc/images/screenshot_33.png and 
new/Photini-2017.8.1/src/doc/images/screenshot_33.png differ
Binary files old/Photini-2017.8.0/src/doc/images/screenshot_34.png and 
new/Photini-2017.8.1/src/doc/images/screenshot_34.png differ
Binary files old/Photini-2017.8.0/src/doc/images/screenshot_35.png and 
new/Photini-2017.8.1/src/doc/images/screenshot_35.png differ
Binary files old/Photini-2017.8.0/src/doc/images/screenshot_36.png and 
new/Photini-2017.8.1/src/doc/images/screenshot_36.png differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/doc/manual/configuration.rst 
new/Photini-2017.8.1/src/doc/manual/configuration.rst
--- old/Photini-2017.8.0/src/doc/manual/configuration.rst       2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/doc/manual/configuration.rst       2017-08-18 
15:00:23.000000000 +0200
@@ -11,8 +11,14 @@
 
 .. image:: ../images/screenshot_36.png
 
-This allows you to edit the names used to auto-generate some descriptive 
metadata, reset the Flickr or Picasa authorisation (requiring you to 
re-authenticate next time you use them) and adjust how Photini uses "sidecar" 
files and IPTC metadata.
+The top three items can be used to adjust the auto-generated copyright and 
creator fields on the descriptive metadata tab.
+The ``copyright text`` entry has place-holders where the photograph's "taken" 
year and the copyright holder's name are inserted.
+You might want to change the surrounding text to suit the law in your country, 
or even to make your photographs rights free if you like.
 
+The next three items allow you to delete Photini's "Oauth tokens" for Flickr, 
Google Photos or Facebook.
+This forces you to re-authenticate next time you use any of these services, 
just like clicking ``Log out`` on the relevant tab.
+
+The next items adjust how Photini uses "sidecar" files and IPTC metadata.
 Sidecar files allow metadata to be stored without needing to write to the 
actual image file.
 If you deselect "write to image" then sidecars will always be created.
 Otherwise, you can choose to have them always created (storing data in 
parallel with the image file), only created when necessary (e.g. an image file 
is write protected), or deleted when possible (if metadata can be copied to the 
image file the sidecar is deleted).
@@ -21,6 +27,10 @@
 Photini has an option to always write IPTC metadata.
 You may need this if you use some other software that reads IPTC but not Exif 
or XMP.
 
+Finally there is an option to preserve file timestamps.
+This allows Photini to write metadata to an image file without changing the 
file's "modification time" as displayed in a file browser.
+You may find this useful if you often use a browser to sort files by date.
+
 Spell checking
 ^^^^^^^^^^^^^^
 
@@ -44,6 +54,7 @@
    [pyqt]
    using_pyqt5 = auto
    using_qtwebengine = auto
+   native_dialog = True
 
 To force use of PyQt4 set the value of ``using_pyqt5`` to ``False``.
 To force the use of QtWebKit set the value of ``using_qtwebengine`` to 
``False``.
@@ -51,6 +62,48 @@
 
    python -m photini.editor --version
 
+Setting the ``native_dialog`` option to ``False`` makes Photini use a Qt 
dialog to select files to open instead of the normal operating system dialog.
+This may be useful if your operating system has a case sensitive file filter, 
so selecting "Images" or "Videos" doesn't work properly if your files have 
upper case names.
+
 Note that there is no GUI to set these options.
-You should only need to adjust them if Photini crashes on startup, in which 
case the GUI would be unusable.
+You may need to adjust them if Photini crashes on startup, in which case the 
GUI would be unusable.
 The configuration file can be edited with any plain text editing program.
+
+.. _configuration-style:
+
+Application style
+^^^^^^^^^^^^^^^^^
+
+Qt applications can have their appearance changed by selecting different 
"styles".
+Normally a style is automatically chosen that suits the operating system, but 
you may want to override this if you prefer something different.
+For example, on one of my computers the default style doesn't draw lines round 
the grouped elements on the uploader tabs, so I change the style to one that 
does.
+
+To find out what styles are available on your computer you can use Photini's 
``--version`` flag.
+(You need to run Photini from a command window to do this, see the 
:ref:`installation troubleshooting<installation-troubleshooting>` section.)
+You can then try one of these styles as follows::
+
+   jim@brains:~$ python3 -m photini.editor --version
+   Photini 2017.8.1, build 898 (a98bfac)
+     Python 3.4.5 (default, Jul 03 2016, 13:32:18) [GCC]
+     pgi 0.0.11.1, GExiv2 0.10.6, GObject 2.0
+     PyQt 5.4, Qt 5.5.0, using QtWebKit
+     enchant 1.6.6
+     flickrapi 2.2.1
+     available styles: Breeze, Windows, GTK+, Fusion
+   jim@brains:~$ python3 -m photini.editor -style breeze
+
+Note that the style names are not case sensitive.
+If none of the available styles is to your liking you may be able to install 
extra ones.
+For example, on some Ubuntu Linux systems the package ``qt5-style-plugins`` is 
available.
+
+Once you find a style that you like, you can set Photini to use that style by 
editing the configuration file as described above.
+Add a line such as ``style = breeze`` to the ``[pyqt]`` section to set your 
chosen style.
+Note that after doing this you can not set a different style on the command 
line unless you remove the ``style = ...`` line from your config file.
+
+.. code-block:: guess
+
+   [pyqt]
+   using_pyqt5 = auto
+   using_qtwebengine = auto
+   native_dialog = True
+   style = breeze
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/doc/manual/image_selector.rst 
new/Photini-2017.8.1/src/doc/manual/image_selector.rst
--- old/Photini-2017.8.0/src/doc/manual/image_selector.rst      2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/doc/manual/image_selector.rst      2017-08-18 
15:00:23.000000000 +0200
@@ -7,6 +7,7 @@
 
 When you start the Photini editor it displays a GUI (graphical user interface) 
as shown below.
 The exact appearance will depend on your operating system and window manager 
preferences, but the same functional elements should be present.
+(The appearance can be altered by setting a different style, see the 
:ref:`configuration section <configuration-style>` for more detail.)
 
 .. image:: ../images/screenshot_01.png
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/doc/manual/importer.rst 
new/Photini-2017.8.1/src/doc/manual/importer.rst
--- old/Photini-2017.8.0/src/doc/manual/importer.rst    2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/doc/manual/importer.rst    2017-08-18 
15:00:23.000000000 +0200
@@ -1,5 +1,5 @@
 .. This is part of the Photini documentation.
-   Copyright (C)  2012-15  Jim Easterbrook.
+   Copyright (C)  2012-17  Jim Easterbrook.
    See the file ../DOC_LICENSE.txt for copying condidions.
 
 Image importer
@@ -22,18 +22,18 @@
 ========  ==================================  =======
 keyword   meaning                             example
 ========  ==================================  =======
-(camera)  the camera model name               Canon_PowerShot_A1100_IS
-(name)    the complete file name              IMG_9999.JPG
-(number)  the numeric part of the file name   9999
-(root)    the filename without its extension  IMG_9999
-(ext)     the filename extension              .JPG
+{camera}  the camera model name               Canon_PowerShot_A1100_IS
+{name}    the complete file name              IMG_9999.JPG
+{number}  the numeric part of the file name   9999
+{root}    the filename without its extension  IMG_9999
+{ext}     the filename extension              .JPG
 ========  ==================================  =======
 
 Below the ``Target format`` field is an example generated from the current 
format to help you edit it correctly.
 
 Note that Photini stores a different target format for each camera or source 
folder that you use.
 This can be useful if you have two cameras that use the same file names.
-For example, I use 
``/home/jim/Pictures/from_camera/%Y/%Y_%m_%d/IMGe(number)(ext)`` for my DSLR to 
rename files from ``IMG_9999.JPG`` to ``IMGe9999.JPG`` so they don't clash with 
files from my compact camera, which also uses names like ``IMG_9999.JPG``.
+For example, I use ``/home/jim/Pictures/from_camera/%Y/%Y_%m_%d/100D_{name}`` 
for my DSLR to rename files from ``IMG_9999.JPG`` to ``100D_IMG_9999.JPG`` so 
they don't clash with files from my compact camera, which also uses names like 
``IMG_9999.JPG``.
 
 .. image:: ../images/screenshot_31.png
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/doc/other/installation.rst 
new/Photini-2017.8.1/src/doc/other/installation.rst
--- old/Photini-2017.8.0/src/doc/other/installation.rst 2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/doc/other/installation.rst 2017-08-18 
15:00:23.000000000 +0200
@@ -300,6 +300,8 @@
 
 If the installation has been successful you should be able to run Photini from 
the "Start" menu (Windows) or application launcher (Linux).
 
+.. _installation-troubleshooting:
+
 Troubleshooting
 ^^^^^^^^^^^^^^^
 
@@ -322,6 +324,12 @@
 Some versions of PyQt may fail to work properly with Photini, even causing a 
crash at startup.
 If this happens you may be able to circumvent the problem by editing the 
:ref:`Photini configuration file <configuration-pyqt>` before running Photini.
 
+Mailing list
+------------
+
+For more general discussion of Photini (e.g. release announcements, questions 
about using it, problems with installing, etc.) there is an email list or forum 
hosted on Google Groups.
+You can view previous messages and ask to join the group at 
https://groups.google.com/forum/#!forum/photini.
+
 .. _installation-documentation:
 
 Photini documentation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/__init__.py 
new/Photini-2017.8.1/src/photini/__init__.py
--- old/Photini-2017.8.0/src/photini/__init__.py        2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/photini/__init__.py        2017-08-18 
15:00:23.000000000 +0200
@@ -1,4 +1,4 @@
 from __future__ import unicode_literals
 
-__version__ = '2017.8.0'
-build = '884 (3c56fdd)'
+__version__ = '2017.8.1'
+build = '901 (e02d573)'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/descriptive.py 
new/Photini-2017.8.1/src/photini/descriptive.py
--- old/Photini-2017.8.0/src/photini/descriptive.py     2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/photini/descriptive.py     2017-08-18 
15:00:23.000000000 +0200
@@ -247,15 +247,16 @@
                 self.config_store.set('user', 'copyright_name', name)
             else:
                 name = ''
+        copyright_text = self.config_store.get(
+            'user', 'copyright_text',
+            self.trUtf8('Copyright ©{year} {name}. All rights reserved.'))
         for image in self.image_list.get_selected_images():
             date_taken = image.metadata.date_taken
             if date_taken is None:
                 date_taken = datetime.now()
             else:
                 date_taken = date_taken.datetime
-            value = self.trUtf8(
-                'Copyright ©{0:d} {1}. All rights reserved.').format(
-                    date_taken.year, name)
+            value = copyright_text.format(year=date_taken.year, name=name)
             image.metadata.copyright = value
         self._update_widget('copyright')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/editor.py 
new/Photini-2017.8.1/src/photini/editor.py
--- old/Photini-2017.8.0/src/photini/editor.py  2017-08-09 13:20:13.000000000 
+0200
+++ new/Photini-2017.8.1/src/photini/editor.py  2017-08-18 15:00:23.000000000 
+0200
@@ -389,6 +389,8 @@
     if FlickrUploader:
         from photini.flickr import flickr_version
         version += '\n  ' + flickr_version
+    version += '\n  available styles: {}'.format(
+        ', '.join(QtWidgets.QStyleFactory.keys()))
     parser = OptionParser(
         usage=six.text_type(QtCore.QCoreApplication.translate(
             'main', 'Usage: %prog [options] [file_name, ...]')),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/editsettings.py 
new/Photini-2017.8.1/src/photini/editsettings.py
--- old/Photini-2017.8.0/src/photini/editsettings.py    2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/photini/editsettings.py    2017-08-18 
15:00:23.000000000 +0200
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #  Photini - a simple photo metadata editor.
 #  http://github.com/jim-easterbrook/Photini
-#  Copyright (C) 2012-16  Jim Easterbrook  j...@jim-easterbrook.me.uk
+#  Copyright (C) 2012-17  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
@@ -37,6 +37,8 @@
         self.layout().addWidget(scroll_area)
         panel = QtWidgets.QWidget()
         panel.setLayout(QtWidgets.QFormLayout())
+        panel.layout().setRowWrapPolicy(max(QtWidgets.QFormLayout.WrapLongRows,
+                                            panel.layout().rowWrapPolicy()))
         # apply & cancel buttons
         self.button_box = QtWidgets.QDialogButtonBox(
             QtWidgets.QDialogButtonBox.Apply | 
QtWidgets.QDialogButtonBox.Cancel)
@@ -47,12 +49,18 @@
         self.copyright_name.setText(
             self.config_store.get('user', 'copyright_name', ''))
         self.copyright_name.setMinimumWidth(200)
-        panel.layout().addRow(self.tr('Copyright holder'), self.copyright_name)
+        panel.layout().addRow(self.tr('Copyright holder name'), 
self.copyright_name)
+        # copyright text
+        self.copyright_text = QtWidgets.QLineEdit()
+        self.copyright_text.setText(
+            self.config_store.get('user', 'copyright_text', ''))
+        self.copyright_name.setMinimumWidth(300)
+        panel.layout().addRow(self.tr('Copyright text'), self.copyright_text)
         # creator name
         self.creator_name = QtWidgets.QLineEdit()
         self.creator_name.setText(
             self.config_store.get('user', 'creator_name', ''))
-        panel.layout().addRow(self.tr('Creator'), self.creator_name)
+        panel.layout().addRow(self.tr('Creator name'), self.creator_name)
         # reset flickr
         self.reset_flickr = QtWidgets.QCheckBox()
         panel.layout().addRow(self.tr('Disconnect from Flickr'), 
self.reset_flickr)
@@ -97,6 +105,13 @@
         self.write_if.setChecked(if_mode)
         self.write_if.clicked.connect(self.new_write_if)
         panel.layout().addRow(self.tr('Write to image'), self.write_if)
+        # preserve file timestamps
+        keep_time = eval(
+            self.config_store.get('files', 'preserve_timestamps', 'False'))
+        self.keep_time = QtWidgets.QCheckBox()
+        self.keep_time.setChecked(keep_time)
+        panel.layout().addRow(
+            self.tr('Preserve file timestamps'), self.keep_time)
         # add panel to scroll area after its size is known
         scroll_area.setWidget(panel)
 
@@ -114,6 +129,7 @@
             return self.reject()
         # change config
         self.config_store.set('user', 'copyright_name', 
self.copyright_name.text())
+        self.config_store.set('user', 'copyright_text', 
self.copyright_text.text())
         self.config_store.set('user', 'creator_name', self.creator_name.text())
         if (self.reset_flickr.isChecked() and
                             keyring.get_password('photini', 'flickr')):
@@ -134,4 +150,6 @@
             sc_mode = 'delete'
         self.config_store.set('files', 'sidecar', sc_mode)
         self.config_store.set('files', 'image', str(self.write_if.isChecked()))
+        self.config_store.set(
+            'files', 'preserve_timestamps', str(self.keep_time.isChecked()))
         return self.accept()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/imagelist.py 
new/Photini-2017.8.1/src/photini/imagelist.py
--- old/Photini-2017.8.0/src/photini/imagelist.py       2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/photini/imagelist.py       2017-08-18 
15:00:23.000000000 +0200
@@ -56,6 +56,8 @@
         self.thumb_size = thumb_size
         # read metadata
         self.metadata = Metadata(self.path, new_status=self.show_status)
+        self.file_times = (os.path.getatime(self.path),
+                           os.path.getmtime(self.path))
         # set file type
         self.file_type = self.metadata.get_mime_type()
         if not self.file_type:
@@ -627,13 +629,17 @@
         sc_mode = self.app.config_store.get('files', 'sidecar', 'auto')
         force_iptc = eval(
             self.app.config_store.get('files', 'force_iptc', 'False'))
+        keep_time = eval(
+            self.app.config_store.get('files', 'preserve_timestamps', 'False'))
+        if not images:
+            images = self.images
         with Busy():
-            if images:
-                for image in images:
-                    image.metadata.save(if_mode, sc_mode, force_iptc)
-            else:
-                for image in self.images:
-                    image.metadata.save(if_mode, sc_mode, force_iptc)
+            for image in images:
+                if keep_time:
+                    file_times = image.file_times
+                else:
+                    file_times = None
+                image.metadata.save(if_mode, sc_mode, force_iptc, file_times)
         unsaved = False
         for image in self.images:
             if image.metadata.changed():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/importer.py 
new/Photini-2017.8.1/src/photini/importer.py
--- old/Photini-2017.8.0/src/photini/importer.py        2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/photini/importer.py        2017-08-18 
15:00:23.000000000 +0200
@@ -155,17 +155,6 @@
     @QtCore.pyqtSlot(str)
     def new_format(self, format_string):
         self.format_string = format_string
-        # extract bracket delimited words from string
-        self.parts = []
-        while format_string:
-            parts = format_string.split('(', 1)
-            if len(parts) > 1:
-                parts[1:] = parts[1].split(')', 1)
-            if len(parts) < 3:
-                self.parts.append((format_string, ''))
-                break
-            self.parts.append((parts[0], parts[1]))
-            format_string = parts[2]
         self.refresh_example()
 
     def set_example(self, example):
@@ -187,14 +176,11 @@
         subst['root'], subst['ext'] = os.path.splitext(name)
         subst['camera'] = file_data['camera'] or 'unknown_camera'
         subst['camera'] = subst['camera'].replace(' ', '_')
-        result = ''
-        # process (...) parts first
-        for left, right in self.parts:
-            result += left
-            if right in subst:
-                result += subst[right]
-            else:
-                result += right
+        # process {...} parts first
+        try:
+            result = self.format_string.format(**subst)
+        except (KeyError, ValueError):
+            result = self.format_string
         # then do timestamp
         return file_data['timestamp'].strftime(result)
 
@@ -277,7 +263,7 @@
         else:
             path = os.path.expanduser('~/Pictures')
         self.path_format.setText(
-            os.path.join(path, '%Y', '%Y_%m_%d', '(name)'))
+            os.path.join(path, '%Y', '%Y_%m_%d', '{name}'))
         self.refresh()
         self.list_files()
 
@@ -295,6 +281,7 @@
         path_format = self.path_format.text()
         path_format = self.config_store.get(
             self.config_section, 'path_format', path_format)
+        path_format = path_format.replace('(', '{').replace(')', '}')
         self.path_format.setText(path_format)
         self.file_list_widget.clear()
         # allow 100ms for display to update before getting file list
@@ -443,6 +430,7 @@
             dest_path = self.nm.transform(file_data)
             file_data['dest_path'] = dest_path
             item = QtWidgets.QListWidgetItem(name + ' -> ' + dest_path)
+            item.setData(Qt.UserRole, name)
             if os.path.exists(dest_path):
                 item.setFlags(Qt.NoItemFlags)
             else:
@@ -486,7 +474,7 @@
             item = self.file_list_widget.item(row)
             if not (item.flags() & Qt.ItemIsSelectable):
                 continue
-            name = item.text().split()[0]
+            name = item.data(Qt.UserRole)
             timestamp = self.file_data[name]['timestamp']
             if timestamp > since:
                 if not first_active:
@@ -506,7 +494,7 @@
         self.import_in_progress = True
         copy_list = []
         for item in self.file_list_widget.selectedItems():
-            name = item.text().split()[0]
+            name = item.data(Qt.UserRole)
             copy_list.append(self.file_data[name])
         last_item = None, datetime.min
         with self.session() as session:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/metadata.py 
new/Photini-2017.8.1/src/photini/metadata.py
--- old/Photini-2017.8.0/src/photini/metadata.py        2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/photini/metadata.py        2017-08-18 
15:00:23.000000000 +0200
@@ -934,7 +934,10 @@
                     ns_defined = True
             if no_bag:
                 # create empty container
-                self.set_xmp_tag_struct(bag, GExiv2.StructureType.ALT)
+                if '[' in container:
+                    self.set_xmp_tag_struct(bag, GExiv2.StructureType.ALT)
+                else:
+                    self.set_xmp_tag_struct(bag, GExiv2.StructureType.SEQ)
             if not ns_defined:
                 # create some XMP data with the correct namespace
                 data = '''<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
@@ -987,28 +990,30 @@
             tag = tag[0]
         return GExiv2.Metadata.is_xmp_tag(tag)
 
-    def save(self):
+    def save(self, file_times):
         try:
             self.save_file(self._path)
+            if file_times:
+                os.utime(self._path, file_times)
         except Exception as ex:
             self._logger.exception(ex)
             return False
         return True
 
-    def copy(self, other, exif=True, iptc=True, xmp=True):
+    def clone(self, other):
         # copy from other to self
-        if exif:
-            for tag in other.get_exif_tags():
+        for tag in other.get_exif_tags():
+            self.set_string(tag, other.get_string(tag))
+        for tag in other.get_iptc_tags():
+            self.set_multiple(tag, other.get_multiple(tag))
+        for tag in other.get_xmp_tags():
+            if not self._is_sidecar and tag.startswith('Xmp.xmp.Thumbnails'):
+                # don't try and fit a thumbnail in 64k Xmp segment
+                continue
+            if self.get_tag_type(tag) == 'XmpText':
                 self.set_string(tag, other.get_string(tag))
-        if iptc:
-            for tag in other.get_iptc_tags():
+            else:
                 self.set_multiple(tag, other.get_multiple(tag))
-        if xmp:
-            for tag in other.get_xmp_tags():
-                if self.get_tag_type(tag) == 'XmpText':
-                    self.set_string(tag, other.get_string(tag))
-                else:
-                    self.set_multiple(tag, other.get_multiple(tag))
 
     def get_all_tags(self):
         return self.get_exif_tags() + self.get_iptc_tags() + 
self.get_xmp_tags()
@@ -1241,9 +1246,9 @@
         except Exception as ex:
             self.logger.exception(ex)
         if self._sc and self._if:
-            self._sc.copy(self._if)
+            self._sc.clone(self._if)
 
-    def save(self, if_mode, sc_mode, force_iptc):
+    def save(self, if_mode, sc_mode, force_iptc, file_times):
         if not self._unsaved:
             return
         self.software = 'Photini editor v' + __version__
@@ -1264,10 +1269,10 @@
                 for tag in self._clear_tags[name]:
                     self.set_value(tag, None)
         if self._if and sc_mode == 'delete' and self._sc:
-            self._if.copy(self._sc)
+            self._if.clone(self._sc)
         OK = False
         if self._if and if_mode:
-            OK = self._if.save()
+            OK = self._if.save(file_times)
             if OK:
                 # check that data really was saved
                 saved_tags = MetadataHandler(self._path).get_all_tags()
@@ -1283,7 +1288,7 @@
         if sc_mode == 'always' and not self._sc:
             self.create_side_car()
         if self._sc:
-            OK = self._sc.save()
+            OK = self._sc.save(file_times)
         self._set_unsaved(not OK)
 
     # getters: use sidecar if tag is present, otherwise use image file
@@ -1334,14 +1339,14 @@
         # copy from other to self, sidecar over-rides image
         if self._sc:
             if other._if:
-                self._sc.copy(other._if)
+                self._sc.clone(other._if)
             if other._sc:
-                self._sc.copy(other._sc)
+                self._sc.clone(other._sc)
         if self._if:
             if other._if:
-                self._if.copy(other._if)
+                self._if.clone(other._if)
             if other._sc:
-                self._if.copy(other._sc)
+                self._if.clone(other._sc)
         self._set_unsaved(True)
 
     def set_thumbnail(self, thumb, fmt, w, h):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/pyqt.py 
new/Photini-2017.8.1/src/photini/pyqt.py
--- old/Photini-2017.8.0/src/photini/pyqt.py    2017-08-09 13:20:13.000000000 
+0200
+++ new/Photini-2017.8.1/src/photini/pyqt.py    2017-08-18 15:00:23.000000000 
+0200
@@ -29,8 +29,6 @@
 config = BaseConfigStore('editor')
 using_pyqt5 = config.get('pyqt', 'using_pyqt5', 'auto') != 'False'
 using_qtwebengine = config.get('pyqt', 'using_qtwebengine', 'auto') != 'False'
-config.save()
-del config
 
 if using_pyqt5:
     try:
@@ -69,6 +67,12 @@
     from PyQt4.QtCore import Qt
     from PyQt4.QtNetwork import QNetworkProxy
 
+style = config.get('pyqt', 'style')
+if style:
+    QtWidgets.QApplication.setStyle(style)
+config.save()
+del config, style
+
 qt_version_info = namedtuple(
     'qt_version_info', ('major', 'minor', 'micro'))._make(
         map(int, QtCore.QT_VERSION_STR.split('.')))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Photini-2017.8.0/src/photini/uploader.py 
new/Photini-2017.8.1/src/photini/uploader.py
--- old/Photini-2017.8.0/src/photini/uploader.py        2017-08-09 
13:20:13.000000000 +0200
+++ new/Photini-2017.8.1/src/photini/uploader.py        2017-08-18 
15:00:23.000000000 +0200
@@ -245,7 +245,7 @@
         # copy metadata, forcing IPTC creation
         md = Metadata(path)
         md.copy(image.metadata)
-        md.save(True, 'none', True)
+        md.save(True, 'none', True, None)
 
     def convert_to_jpeg(self, image):
         im = QtGui.QImage(image.path)


Reply via email to