diff -Nru veusz-3.3/ChangeLog veusz-3.3.1/ChangeLog --- veusz-3.3/ChangeLog 2020-11-29 08:23:38.000000000 +0000 +++ veusz-3.3.1/ChangeLog 2020-12-06 11:44:42.000000000 +0000 @@ -1,3 +1,14 @@ +Changes in 3.3.1: + * New tools for zooming into plot on click, zooming out, moving plot + center and resetting plot axes + * Double clicking on axis range resets endpoint to Auto + * Add key entries for histo widget + * MacOS improvements + * Big Sur compatibility fix + * Fix file associations + * Python 3.10 prerelease fixes + * Fix for reproducible builds + Changes in 3.3: * New histogramming widget (histo) * Add keyboard shortcut for showing/hiding widgets (Ctrl+[ and Ctrl+]) diff -Nru veusz-3.3/debian/changelog veusz-3.3.1/debian/changelog --- veusz-3.3/debian/changelog 2020-11-30 18:35:00.000000000 +0000 +++ veusz-3.3.1/debian/changelog 2020-12-06 12:45:00.000000000 +0000 @@ -1,3 +1,10 @@ +veusz (3.3.1-0~ppa1~focal1) focal; urgency=low + + [ Jeremy Sanders ] + * Update to Veusz-3.3.1 + + -- Jeremy Sanders Sun, 06 Dec 2020 13:45:00 +0100 + veusz (3.3-0~ppa2~focal1) focal; urgency=low [ Jeremy Sanders ] diff -Nru veusz-3.3/Documents/man-page/veusz.1 veusz-3.3.1/Documents/man-page/veusz.1 --- veusz-3.3/Documents/man-page/veusz.1 2020-11-29 08:23:44.000000000 +0000 +++ veusz-3.3.1/Documents/man-page/veusz.1 2020-12-06 11:44:50.000000000 +0000 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "VEUSZ 1" -.TH VEUSZ 1 "2020-11-29" "3.3" "Veusz" +.TH VEUSZ 1 "2020-12-06" "3.3.1" "Veusz" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -Nru veusz-3.3/Documents/man-page/veusz.man.txt veusz-3.3.1/Documents/man-page/veusz.man.txt --- veusz-3.3/Documents/man-page/veusz.man.txt 2020-11-29 08:23:44.000000000 +0000 +++ veusz-3.3.1/Documents/man-page/veusz.man.txt 2020-12-06 11:44:50.000000000 +0000 @@ -90,4 +90,4 @@ On Debian GNU/Linux systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL'. -3.3 2020-11-29 VEUSZ(1) +3.3.1 2020-12-06 VEUSZ(1) diff -Nru veusz-3.3/Documents/manual/html/api.html veusz-3.3.1/Documents/manual/html/api.html --- veusz-3.3/Documents/manual/html/api.html 2020-11-29 08:23:45.000000000 +0000 +++ veusz-3.3.1/Documents/manual/html/api.html 2020-12-06 11:44:51.000000000 +0000 @@ -6,7 +6,7 @@ - Veusz command line and embedding interface (API) — Veusz 3.3 documentation + Veusz command line and embedding interface (API) — Veusz 3.3.1 documentation @@ -873,7 +873,7 @@ import time import numpy -import veusz.embed as veusz +import veusz.embed as veusz # construct a Veusz embedded window # many of these can be opened at any time @@ -886,8 +886,8 @@ g.Add('xy', marker='tiehorz', MarkerFill__color='green') # this stops intelligent axis extending -g.Set('x/autoExtend', False) -g.Set('x/autoExtendZero', False) +g.Set('x/autoExtend', False) +g.Set('x/autoExtendZero', False) # zoom out g.Zoom(0.8) @@ -903,9 +903,9 @@ time.sleep(2) # let the user see the final result -print "Waiting for 10 seconds" +print "Waiting for 10 seconds" time.sleep(10) -print "Done!" +print "Done!" # close the window (this is not strictly necessary) g.Close() @@ -982,7 +982,7 @@

For instance, this constructs a simple x-squared plot which changes to x-cubed:

-
import veusz.embed as veusz
+
import veusz.embed as veusz
 import time
 
 #  open a new window and return a new Embedded object
@@ -1055,7 +1055,7 @@
 
        Methods are below."""
 
-    def WalkWidgets(self, widgettype=None):
+    def WalkWidgets(self, widgettype=None):
         """Generator to walk widget tree and get widgets below this
         WidgetNode of type given.
 
@@ -1097,15 +1097,15 @@
 
# old (from saved document file)
 Add('page', name='page1')
 To('page1')
-Add('graph', name='graph1', autoadd=False)
+Add('graph', name='graph1', autoadd=False)
 To('graph1')
 Add('axis', name='x')
 To('x')
-Set('label', '\\italic{x}')
+Set('label', '\\italic{x}')
 To('..')
 Add('axis', name='y')
 To('y')
-Set('label', 'sin \\italic{x}')
+Set('label', 'sin \\italic{x}')
 Set('direction', 'vertical')
 To('..')
 Add('xy', name='xy1')
@@ -1127,11 +1127,11 @@
 
 page = embed.Root.Add('page')
 # note: autoAdd=False stops graph automatically adding own axes (used in saved files)
-graph = page.Add('graph', autoadd=False)
+graph = page.Add('graph', autoadd=False)
 x = graph.Add('axis', name='x')
-x.label.val = '\\italic{x}'
+x.label.val = '\\italic{x}'
 y = graph.Add('axis', name='y')
-y.label.val = 'sin \\italic{x}'
+y.label.val = 'sin \\italic{x}'
 y.direction.val = 'vertical'
 xy = graph.Add('xy')
 xy.MarkerFill.color.val = 'cyan'
diff -Nru veusz-3.3/Documents/manual/html/.buildinfo veusz-3.3.1/Documents/manual/html/.buildinfo
--- veusz-3.3/Documents/manual/html/.buildinfo	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/.buildinfo	2020-12-06 11:44:51.000000000 +0000
@@ -1,4 +1,4 @@
 # Sphinx build info version 1
 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 2bd38ebfe56bd7ad63c812a6ebf87ae6
+config: 7d1e3bba9c32df701266a49f80763fdc
 tags: 645f666f9bcd5a90fca523b33c5a78b7
diff -Nru veusz-3.3/Documents/manual/html/datasets.html veusz-3.3.1/Documents/manual/html/datasets.html
--- veusz-3.3/Documents/manual/html/datasets.html	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/datasets.html	2020-12-06 11:44:51.000000000 +0000
@@ -6,7 +6,7 @@
   
     
     
-    Reading data — Veusz 3.3 documentation
+    Reading data — Veusz 3.3.1 documentation
     
     
     
diff -Nru veusz-3.3/Documents/manual/html/genindex.html veusz-3.3.1/Documents/manual/html/genindex.html
--- veusz-3.3/Documents/manual/html/genindex.html	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/genindex.html	2020-12-06 11:44:51.000000000 +0000
@@ -7,7 +7,7 @@
   
     
     
-    Index — Veusz 3.3 documentation
+    Index — Veusz 3.3.1 documentation
     
     
     
diff -Nru veusz-3.3/Documents/manual/html/index.html veusz-3.3.1/Documents/manual/html/index.html
--- veusz-3.3/Documents/manual/html/index.html	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/index.html	2020-12-06 11:44:51.000000000 +0000
@@ -6,7 +6,7 @@
   
     
     
-    Veusz documentation — Veusz 3.3 documentation
+    Veusz documentation — Veusz 3.3.1 documentation
     
     
     
diff -Nru veusz-3.3/Documents/manual/html/introduction.html veusz-3.3.1/Documents/manual/html/introduction.html
--- veusz-3.3/Documents/manual/html/introduction.html	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/introduction.html	2020-12-06 11:44:51.000000000 +0000
@@ -6,7 +6,7 @@
   
     
     
-    Introduction — Veusz 3.3 documentation
+    Introduction — Veusz 3.3.1 documentation
     
     
     
diff -Nru veusz-3.3/Documents/manual/html/objects.inv veusz-3.3.1/Documents/manual/html/objects.inv
--- veusz-3.3/Documents/manual/html/objects.inv	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/objects.inv	2020-12-06 11:44:51.000000000 +0000
@@ -1,6 +1,6 @@
 # Sphinx inventory version 2
 # Project: Veusz
-# Version: 3.3
+# Version: 3.3.1
 # The remainder of this file is compressed using zlib.
 xڕ͎ Fy
 KEH3R7u9V"pbpg<}/vU|gl 0>4ߩ'puLFI
Mm`CӇ̈́31S;؏eݾןqϰ	\4G=02
\ No newline at end of file
diff -Nru veusz-3.3/Documents/manual/html/search.html veusz-3.3.1/Documents/manual/html/search.html
--- veusz-3.3/Documents/manual/html/search.html	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/search.html	2020-12-06 11:44:51.000000000 +0000
@@ -6,7 +6,7 @@
   
     
     
-    Search — Veusz 3.3 documentation
+    Search — Veusz 3.3.1 documentation
     
     
     
diff -Nru veusz-3.3/Documents/manual/html/_static/documentation_options.js veusz-3.3.1/Documents/manual/html/_static/documentation_options.js
--- veusz-3.3/Documents/manual/html/_static/documentation_options.js	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/_static/documentation_options.js	2020-12-06 11:44:51.000000000 +0000
@@ -1,6 +1,6 @@
 var DOCUMENTATION_OPTIONS = {
     URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
-    VERSION: '3.3',
+    VERSION: '3.3.1',
     LANGUAGE: 'None',
     COLLAPSE_INDEX: false,
     FILE_SUFFIX: '.html',
diff -Nru veusz-3.3/Documents/manual/html/_static/pygments.css veusz-3.3.1/Documents/manual/html/_static/pygments.css
--- veusz-3.3/Documents/manual/html/_static/pygments.css	2020-11-29 08:23:45.000000000 +0000
+++ veusz-3.3.1/Documents/manual/html/_static/pygments.css	2020-12-06 11:44:51.000000000 +0000
@@ -1,5 +1,10 @@
+pre { line-height: 125%; margin: 0; }
+td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }
+span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }
+td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
+span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
 .highlight .hll { background-color: #ffffcc }
-.highlight  { background: #eeffcc; }
+.highlight { background: #eeffcc; }
 .highlight .c { color: #408090; font-style: italic } /* Comment */
 .highlight .err { border: 1px solid #FF0000 } /* Error */
 .highlight .k { color: #007020; font-weight: bold } /* Keyword */
Binary files /tmp/tmpw6y8qn/vdJJNoPxqf/veusz-3.3/Documents/manual/pdf/veusz.pdf and /tmp/tmpw6y8qn/oqXGafuR6u/veusz-3.3.1/Documents/manual/pdf/veusz.pdf differ
diff -Nru veusz-3.3/icons/veusz-zoom-graph-out.svg veusz-3.3.1/icons/veusz-zoom-graph-out.svg
--- veusz-3.3/icons/veusz-zoom-graph-out.svg	1970-01-01 00:00:00.000000000 +0000
+++ veusz-3.3.1/icons/veusz-zoom-graph-out.svg	2020-12-06 11:44:42.000000000 +0000
@@ -0,0 +1,103 @@
+
+
+
+
+  
+  
+  
+    
+      
+        image/svg+xml
+        
+        
+          
+            Jeremy Sanders
+          
+        
+        
+          
+            Copyright (C) Jeremy Sanders
+          
+        
+        
+        
+      
+    
+  
+  
+    
+    
+    
+    
+    
+  
+
diff -Nru veusz-3.3/icons/veusz-zoom-graph-recenter.svg veusz-3.3.1/icons/veusz-zoom-graph-recenter.svg
--- veusz-3.3/icons/veusz-zoom-graph-recenter.svg	1970-01-01 00:00:00.000000000 +0000
+++ veusz-3.3.1/icons/veusz-zoom-graph-recenter.svg	2020-12-06 11:44:42.000000000 +0000
@@ -0,0 +1,102 @@
+
+
+
+
+  
+  
+  
+    
+      
+        image/svg+xml
+        
+        
+          
+            Jeremy Sanders
+          
+        
+        
+          
+            Copyright (C) Jeremy Sanders
+          
+        
+        
+        
+      
+    
+  
+  
+    
+    
+    
+    
+    
+  
+
diff -Nru veusz-3.3/icons/veusz-zoom-graph.svg veusz-3.3.1/icons/veusz-zoom-graph.svg
--- veusz-3.3/icons/veusz-zoom-graph.svg	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/icons/veusz-zoom-graph.svg	2020-12-06 11:44:42.000000000 +0000
@@ -13,7 +13,7 @@
    height="16"
    id="svg2"
    sodipodi:version="0.32"
-   inkscape:version="0.48.5 r10040"
+   inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
    version="1.0"
    sodipodi:docname="veusz-zoom-graph.svg"
    inkscape:output_extension="org.inkscape.output.svg.inkscape">
@@ -29,18 +29,19 @@
      objecttolerance="10"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="20.594486"
-     inkscape:cx="2.478612"
-     inkscape:cy="8.4607504"
+     inkscape:zoom="50.25"
+     inkscape:cx="8"
+     inkscape:cy="8"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="false"
-     inkscape:window-width="1023"
-     inkscape:window-height="668"
-     inkscape:window-x="247"
-     inkscape:window-y="31"
+     inkscape:window-width="1920"
+     inkscape:window-height="1011"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
      showguides="true"
-     inkscape:guide-bbox="true" />
+     inkscape:guide-bbox="true"
+     inkscape:window-maximized="1" />
   
     
@@ -69,7 +70,7 @@
      inkscape:groupmode="layer"
      id="layer1">
     
     
     
-    
-      
-      
-    
-    
-      
-      
-    
+       x="5.304719"
+       y="4.2667017" />
+    
+    
   
 
diff -Nru veusz-3.3/icons/veusz-zoom-reset.svg veusz-3.3.1/icons/veusz-zoom-reset.svg
--- veusz-3.3/icons/veusz-zoom-reset.svg	1970-01-01 00:00:00.000000000 +0000
+++ veusz-3.3.1/icons/veusz-zoom-reset.svg	2020-12-06 11:44:42.000000000 +0000
@@ -0,0 +1,130 @@
+
+
+
+
+  
+  
+  
+    
+      
+        image/svg+xml
+        
+        
+          
+            Jeremy Sanders
+          
+        
+        
+          
+            Copyright (C) Jeremy Sanders
+          
+        
+        
+        
+      
+    
+  
+  
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  
+
diff -Nru veusz-3.3/INSTALL veusz-3.3.1/INSTALL
--- veusz-3.3/INSTALL	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/INSTALL	2020-12-06 11:44:42.000000000 +0000
@@ -42,7 +42,7 @@
 these instructions (note python in these commands should be replaced
 by python3 to do a Python 3 installation).
 
-# cd veusz-3.3
+# cd veusz-3.3.1
 # python setup.py build
 # su
 [enter root password]
@@ -147,8 +147,8 @@
 helper modules must be compiled and copied into the appropriate
 location.
 
-# tar xzf veusz-3.3.tar.gz                [change version here]
-# cd veusz-3.3
+# tar xzf veusz-3.3.1.tar.gz                [change version here]
+# cd veusz-3.3.1
 # python setup.py build                     [or use python3 here]
 # cp build/*/veusz/helpers/*.so veusz/helpers/
 
@@ -167,8 +167,8 @@
 incompatibilities. Simply unpack the tar file and run the main
 executable:
 
-# tar xf veusz-3.3-linux-x86_64.tar.xz   [change version here]
-# cd veusz-3.3-linux-x86_64
+# tar xf veusz-3.3.1-linux-x86_64.tar.xz   [change version here]
+# cd veusz-3.3.1-linux-x86_64
 # ./veusz.exe                    [note, it's not a windows exe!]
 
 2.2 Installing in Windows
@@ -177,9 +177,9 @@
 embed.py file to your PYTHONPATH if you want to use the embedding
 module.
 
-2.3 Installing on Mac OS X
-==========================
-A binary is available for Mac OS X. Simply drag the Veusz application
+2.3 Installing on MacOS
+=======================
+A binary is available for MacOS. Simply drag the Veusz application
 into your Applications directory.
 
 3. NOTES FOR PACKAGERS
diff -Nru veusz-3.3/PKG-INFO veusz-3.3.1/PKG-INFO
--- veusz-3.3/PKG-INFO	2020-11-29 08:23:53.510904800 +0000
+++ veusz-3.3.1/PKG-INFO	2020-12-06 11:44:59.181787300 +0000
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: veusz
-Version: 3.3
+Version: 3.3.1
 Summary: A scientific plotting package
 Home-page: https://veusz.github.io/
 Author: Jeremy Sanders
diff -Nru veusz-3.3/pyqtdistutils.py veusz-3.3.1/pyqtdistutils.py
--- veusz-3.3/pyqtdistutils.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/pyqtdistutils.py	2020-12-06 11:44:42.000000000 +0000
@@ -281,7 +281,7 @@
                 self._sip_compile(sip_exe, sip_dir, sip, sip_builddir)
             out = [
                 os.path.join(sip_builddir, fn)
-                for fn in os.listdir(sip_builddir)
+                for fn in sorted(os.listdir(sip_builddir))
                 if fn.endswith(".cpp")
             ]
             generated_sources.extend(out)
diff -Nru veusz-3.3/README.md veusz-3.3.1/README.md
--- veusz-3.3/README.md	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/README.md	2020-12-06 11:44:42.000000000 +0000
@@ -1,4 +1,4 @@
-# [Veusz 3.3](https://veusz.github.io)
+# [Veusz 3.3.1](https://veusz.github.io)
 
 Veusz is a scientific plotting package.  It is designed to produce
 publication-ready PDF or SVG output. Graphs are built-up by combining
@@ -10,6 +10,16 @@
 manipulation and editing of datasets. Data can be captured from
 external sources such as Internet sockets or other programs.
 
+## Changes in 3.3.1
+  * New tools for zooming into plot on click, zooming out, moving plot center and resetting plot axes
+  * Double clicking on axis range resets endpoint to Auto
+  * Add key entries for histo widget
+  * MacOS improvements
+    * Big Sur compatibility fix
+    * Fix file associations
+  * Python 3.10 prerelease fixes
+  * Fix for reproducible builds
+
 ## Changes in 3.3
   * New histogramming widget (histo)
   * Add keyboard shortcut for showing/hiding widgets (Ctrl+[ and Ctrl+])
diff -Nru veusz-3.3/setup.py veusz-3.3.1/setup.py
--- veusz-3.3/setup.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/setup.py	2020-12-06 11:44:42.000000000 +0000
@@ -37,7 +37,7 @@
     from setuptools import setup, Extension
     from setuptools.command.install import install as orig_install
 
-    extraoptions['install_requires'] = ['numpy', 'PyQt5', 'sip']
+    extraoptions['install_requires'] = ['numpy', 'PyQt5']
     extraoptions['extras_require'] = {
         "optional": ['astropy', 'pyemf', 'sampy', 'iminuit', 'h5py']
     }
diff -Nru veusz-3.3/tests/comparison/multixy.vsz.selftest veusz-3.3.1/tests/comparison/multixy.vsz.selftest
--- veusz-3.3/tests/comparison/multixy.vsz.selftest	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/tests/comparison/multixy.vsz.selftest	2020-12-06 11:44:42.000000000 +0000
@@ -126,13 +126,13 @@
 
 
 
-
+
 
 
 
 
 
-Datasets
+Datasets
 
 
 
diff -Nru veusz-3.3/VERSION veusz-3.3.1/VERSION
--- veusz-3.3/VERSION	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/VERSION	2020-12-06 11:44:42.000000000 +0000
@@ -1 +1 @@
-3.3
+3.3.1
diff -Nru veusz-3.3/veusz/document/painthelper.py veusz-3.3.1/veusz/document/painthelper.py
--- veusz-3.3/veusz/document/painthelper.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/document/painthelper.py	2020-12-06 11:44:42.000000000 +0000
@@ -41,8 +41,8 @@
 
         self.widget = widget
         self.record = RecordPaintDevice(
-            helper.pagesize[0], helper.pagesize[1],
-            helper.dpi[0], helper.dpi[1])
+            int(helper.pagesize[0]), int(helper.pagesize[1]),
+            int(helper.dpi[0]), int(helper.dpi[1]))
         self.bounds = bounds
         self.clip = clip
 
diff -Nru veusz-3.3/veusz/setting/collections.py veusz-3.3.1/veusz/setting/collections.py
--- veusz-3.3/veusz/setting/collections.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/setting/collections.py	2020-12-06 11:44:42.000000000 +0000
@@ -366,7 +366,7 @@
         if self.bold:
             weight = qt.QFont.Bold
 
-        f = qt.QFont(self.font, size,  weight, self.italic)
+        f = qt.QFont(self.font, int(size), weight, self.italic)
         if self.underline:
             f.setUnderline(True)
         f.setStyleHint(qt.QFont.Times)
diff -Nru veusz-3.3/veusz/utils/textrender.py veusz-3.3.1/veusz/utils/textrender.py
--- veusz-3.3/veusz/utils/textrender.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/utils/textrender.py	2020-12-06 11:44:42.000000000 +0000
@@ -1520,7 +1520,7 @@
         if ptsize < 0:
             ptsize = self.font.pixelSize() / self.painter.pixperpt
 
-        doc.setBaseFontPointSize(ptsize * upscale)
+        doc.setBaseFontPointSize(int(ptsize * upscale))
 
         # the output will be painted finally scaled
         self.drawscale = (
diff -Nru veusz-3.3/veusz/veusz_main.py veusz-3.3.1/veusz/veusz_main.py
--- veusz-3.3/veusz/veusz_main.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/veusz_main.py	2020-12-06 11:44:42.000000000 +0000
@@ -234,7 +234,7 @@
             for filename in docs:
                 if not emptywins:
                     MainWindow.CreateWindow(filename)
-                else:
+                elif filename:
                     emptywins[0].openFile(filename)
         else:
             # create blank window
diff -Nru veusz-3.3/veusz/widgets/axis.py veusz-3.3.1/veusz/widgets/axis.py
--- veusz-3.3/veusz/widgets/axis.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/widgets/axis.py	2020-12-06 11:44:42.000000000 +0000
@@ -1201,9 +1201,11 @@
         s = self.settings
 
         # make control item for axis
-        phelper.setControlGraph(self, [ controlgraph.ControlAxisLine(
-            self, phelper, s.direction, self.coordParr1,
-            self.coordParr2, self.coordPerp, posn) ])
+        phelper.setControlGraph(self, [
+            controlgraph.ControlAxisLine(
+                self, phelper, s.direction, self.coordParr1,
+                self.coordParr2, self.coordPerp, posn)
+        ])
 
         # get tick vals
         coordticks = self._graphToPlotter(self.majortickscalc)
@@ -1251,13 +1253,36 @@
         s = self.settings
         p = cgi.maxposn
 
-        if cgi.zoomed():
+        if cgi.done_reset():
+            c1, c2, c1delt, c2delt = self.plotterToGraphCoords(
+                cgi.maxposn, N.array([
+                    cgi.minzoom, cgi.maxzoom,
+                    cgi.minzoom+1, cgi.maxzoom-1
+                ]))
+            reset = cgi.reset
+            if c1 > c2:
+                reset = 1 - reset
+
+            ops = []
+            if reset == 0:
+                ops.append( document.OperationSettingSet(
+                    s.get('min'), 'Auto') )
+            elif reset == 1:
+                ops.append( document.OperationSettingSet(
+                    s.get('max'), 'Auto') )
+
+            self.document.applyOperation(
+                document.OperationMultiple(ops, descr=_('reset axis')))
+
+        elif cgi.zoomed():
             # zoom axis scale
             # we convert a neighbouring pixel to see how we should
             # round the text
             c1, c2, c1delt, c2delt = self.plotterToGraphCoords(
-                cgi.maxposn, N.array([cgi.minzoom, cgi.maxzoom,
-                                      cgi.minzoom+1, cgi.maxzoom-1]))
+                cgi.maxposn, N.array([
+                    cgi.minzoom, cgi.maxzoom,
+                    cgi.minzoom+1, cgi.maxzoom-1
+                ]))
             if c1 > c2:
                 c1, c2 = c2, c1
                 c1delt, c2delt = c2delt, c1delt
diff -Nru veusz-3.3/veusz/widgets/controlgraph.py veusz-3.3.1/veusz/widgets/controlgraph.py
--- veusz-3.3/veusz/widgets/controlgraph.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/widgets/controlgraph.py	2020-12-06 11:44:42.000000000 +0000
@@ -641,6 +641,8 @@
         qt.QGraphicsLineItem.mouseMoveEvent(self, event)
         self.parent.doLineUpdate()
 
+
+
 class ControlAxisLine(object):
     """Controlling position of an axis."""
 
@@ -655,6 +657,10 @@
         self.axisorigpos = self.axispos = axispos
         self.maxposn = maxposn
         self.cgscale = painthelper.cgscale
+        self.reset = None
+
+    def done_reset(self):
+        return self.reset is not None
 
     def zoomed(self):
         """Is this a zoom?"""
@@ -662,25 +668,41 @@
 
     def moved(self):
         """Has axis moved?"""
-        return ( self.minpos != self.minorig or self.maxpos != self.maxorig or
-                 self.axisorigpos != self.axispos )
+        return (
+            self.minpos != self.minorig or self.maxpos != self.maxorig or
+            self.axisorigpos != self.axispos
+        )
 
     def createGraphicsItem(self, parent):
         return _GraphAxisLine(parent, self)
 
+class _AxisRange(_ShapeCorner):
+    """A control item which allows double click for a reset."""
+
+    def mouseDoubleClickEvent(self, event):
+        qt.QGraphicsRectItem.mouseDoubleClickEvent(self, event)
+        self.parentItem().resetRange(self)
+
 class _GraphAxisLine(qt.QGraphicsItem):
 
-    curs = {True: qt.Qt.SizeVerCursor,
-            False: qt.Qt.SizeHorCursor}
-    curs_zoom = {True: qt.Qt.SplitVCursor,
-                 False: qt.Qt.SplitHCursor}
+    # cursors to use
+    curs = {
+        True: qt.Qt.SizeVerCursor,
+        False: qt.Qt.SizeHorCursor
+    }
+    curs_zoom = {
+        True: qt.Qt.SplitVCursor,
+        False: qt.Qt.SplitHCursor
+    }
 
     def __init__(self, parent, params):
         """Line is about to be shown."""
         qt.QGraphicsItem.__init__(self, parent)
         self.params = params
-        self.pts = [ _ShapeCorner(self, params), _ShapeCorner(self, params),
-                     _ShapeCorner(self, params), _ShapeCorner(self, params) ]
+        self.pts = [
+            _ShapeCorner(self, params), _ShapeCorner(self, params),
+            _AxisRange(self, params), _AxisRange(self, params)
+        ]
         self.line = _AxisGraphicsLineItem(self, params)
 
         # set cursors and tooltips for items
@@ -690,7 +712,7 @@
             p.setToolTip("Move axis ends")
         for p in self.pts[2:]:
             p.setCursor(self.curs_zoom[not self.horz])
-            p.setToolTip("Change axis scale")
+            p.setToolTip("Change axis scale. Double click to reset end.")
         self.line.setCursor( self.curs[self.horz] )
         self.line.setToolTip("Move axis position")
         self.setZValue(2.)
@@ -783,3 +805,12 @@
 
     def paint(self, painter, option, widget):
         """Intentionally empty painter."""
+
+    def resetRange(self, corner):
+        """User wants to reset range."""
+
+        if corner is self.pts[2]:
+            self.params.reset = 0
+        else:
+            self.params.reset = 1
+        self.updateWidget()
diff -Nru veusz-3.3/veusz/widgets/histo.py veusz-3.3.1/veusz/widgets/histo.py
--- veusz-3.3/veusz/widgets/histo.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/widgets/histo.py	2020-12-06 11:44:42.000000000 +0000
@@ -461,6 +461,29 @@
         if maxv is not None:
             axrange[1] = max(axrange[1], maxv)
 
+    def drawKeySymbol(self, number, painter, x, y, width, height):
+        """Draw the line fill for the key."""
+
+        s = self.settings
+
+        # draw fill setting
+        yp = y + height/2
+        for fill in s.Fill1, s.Fill2:
+            if not fill.hide:
+                if fill.mode =='over':
+                    y2 = yp-height*0.45
+                else:
+                    y2 = yp+height*0.45
+                path = qt.QPainterPath()
+                path.addRect(qt.QRectF(
+                    qt.QPointF(x, yp), qt.QPointF(x+width, y2)))
+                utils.brushExtFillPath(painter, fill, path)
+
+        # draw line
+        if not s.Line.hide:
+            painter.setPen( s.Line.makeQPen(painter) )
+            painter.drawLine( qt.QPointF(x, yp), qt.QPointF(x+width, yp) )
+
     def dataDraw(self, painter, axes, posn, cliprect):
         """Draw the histogram."""
 
diff -Nru veusz-3.3/veusz/widgets/key.py veusz-3.3.1/veusz/widgets/key.py
--- veusz-3.3/veusz/widgets/key.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/widgets/key.py	2020-12-06 11:44:42.000000000 +0000
@@ -402,7 +402,7 @@
         if s.title != '':
             titlefont = qt.QFont(font)
             painter.setPen(textpen)
-            titlefont.setPointSize(
+            titlefont.setPointSizeF(
                 max(font.pointSize() * 1.2, font.pointSize() + 2))
             titlewidth, titleheight = utils.Renderer(
                 painter, titlefont,
diff -Nru veusz-3.3/veusz/windows/plotwindow.py veusz-3.3.1/veusz/windows/plotwindow.py
--- veusz-3.3/veusz/windows/plotwindow.py	2020-11-29 08:23:38.000000000 +0000
+++ veusz-3.3.1/veusz/windows/plotwindow.py	2020-12-06 11:44:42.000000000 +0000
@@ -428,10 +428,30 @@
                       _('Read data points'),
                       None,
                       icon='veusz-pick-data'),
-                'view.zoomgraph':
-                    a(self, _('Zoom into graph'), _('Zoom graph'),
+                'view.graphzoom':
+                    a(self,
+                      _('Click or draw a rectangle to zoom graph axes'),
+                      _('Zoom into graph'),
                       None,
                       icon='veusz-zoom-graph'),
+                'view.graphzoomout':
+                    a(self,
+                      _('Click to zoom out of graph axes'),
+                      _('Zoom out of graph'),
+                      None,
+                      icon='veusz-zoom-graph-out'),
+                'view.graphrecenter':
+                    a(self,
+                      _('Click to recenter graph axes'),
+                      _('Recenter graph'),
+                      None,
+                      icon='veusz-zoom-graph-recenter'),
+                'view.graphreset':
+                    a(self,
+                      _('Click to reset graph axes'),
+                      _('Reset axes'),
+                      None,
+                      icon='veusz-zoom-reset'),
                 'view.fullscreen':
                     a(self, _('View plot full screen'), _('Full screen'),
                       self.slotFullScreen,
@@ -442,16 +462,18 @@
             # only construct menu if required
             menuitems = [
                 ('view', '', [
-                        'view.zoomin', 'view.zoomout',
-                        'view.zoom11', 'view.zoomwidth',
-                        'view.zoomheight', 'view.zoompage',
-                        '',
-                        'view.prevpage', 'view.nextpage',
-                        'view.fullscreen',
-                        '',
-                        'view.select', 'view.pick', 'view.zoomgraph',
-                        ]),
-                ]
+                    'view.zoomin', 'view.zoomout',
+                    'view.zoom11', 'view.zoomwidth',
+                    'view.zoomheight', 'view.zoompage',
+                    '',
+                    'view.prevpage', 'view.nextpage',
+                    'view.fullscreen',
+                    '',
+                    'view.select', 'view.pick',
+                    'view.graphzoom', 'view.graphzoomout',
+                    'view.graphrecenter', 'view.graphreset',
+                ]),
+            ]
             utils.constructMenus(menu, {'view': menu}, menuitems,
                                  actions)
 
@@ -468,13 +490,19 @@
                 'view.prevpage', 'view.nextpage',
                 'view.fullscreen',
                 'view.select', 'view.pick',
-                'view.zoomgraph', 'view.zoommenu',
+                'view.graphzoom', 'view.graphzoomout',
+                'view.graphrecenter', 'view.graphreset',
+                'view.zoommenu',
             ))
 
         # define action group for various different selection models
         grp = self.selectactiongrp = qt.QActionGroup(self)
         grp.setExclusive(True)
-        for a in ('view.select', 'view.pick', 'view.zoomgraph'):
+        for a in (
+                'view.select', 'view.pick', 'view.graphzoom',
+                'view.graphzoomout', 'view.graphrecenter',
+                'view.graphreset',
+        ):
             actions[a].setActionGroup(grp)
             actions[a].setCheckable(True)
         actions['view.select'].setChecked(True)
@@ -482,7 +510,32 @@
 
         return self.viewtoolbar
 
-    def doZoomRect(self, endpos):
+    def getAxesForPosition(self, pt):
+        """Given QPoint(pt), get axes associated with position.
+
+        This is not very nice. This should be abstracted somewhere else.
+        """
+
+        # try to work out in which widget the first point is in
+        widget = self.painthelper.pointInWidgetBounds(
+            pt.x(), pt.y(), widgets.Graph)
+        if widget is None:
+            return
+
+        # iterate over children, to look for plotters
+        axes = set()
+        for c in widget.children:
+            if isinstance(c, widgets.GenericPlotter):
+                # get axes associated with plotter
+                caxes = c.parent.getAxes(
+                    (c.settings.xAxis, c.settings.yAxis) )
+                for a in caxes:
+                    if a:
+                        axes.add(a)
+
+        return axes
+
+    def doGraphZoomRect(self, endpos):
         """Take the zoom rectangle drawn by the user and do the zooming.
         endpos is a QPoint end point
 
@@ -505,16 +558,15 @@
         # work out whether it's worthwhile to zoom: only zoom if there
         # are >=5 pixels movement
         if abs((pt2-pt1).x()) < 10 or abs((pt2-pt1).y()) < 10:
+            self.doGraphZoomOnPoint(self.winpos, inverse=True)
             return
 
         # scale into graph coordinates
         pt1 /= self.painthelper.cgscale
         pt2 /= self.painthelper.cgscale
 
-        # try to work out in which widget the first point is in
-        widget = self.painthelper.pointInWidgetBounds(
-            pt1.x(), pt1.y(), widgets.Graph)
-        if widget is None:
+        axes = self.getAxesForPosition(pt1)
+        if not axes:
             return
 
         # convert points on plotter to points on axis for each axis
@@ -525,19 +577,6 @@
         # build up operation list to do zoom
         operations = []
 
-        axes = {}
-        # iterate over children, to look for plotters
-        for c in [i for i in widget.children if
-                  isinstance(i, widgets.GenericPlotter)]:
-
-            # get axes associated with plotter
-            caxes = c.parent.getAxes( (c.settings.xAxis,
-                                      c.settings.yAxis) )
-
-            for a in caxes:
-                if a:
-                    axes[a] = True
-
         # iterate over each axis, and update the ranges
         for axis in axes:
             s = axis.settings
@@ -562,29 +601,32 @@
             # build up operations to change axis
             if s.min != r[0]:
                 operations.append( document.OperationSettingSet(
-                        s.get('min'),
-                        utils.round2delt(r[0], r[2])) )
+                    s.get('min'),
+                    utils.round2delt(r[0], r[2])) )
 
             if s.max != r[1]:
                 operations.append( document.OperationSettingSet(
-                        s.get('max'),
-                        utils.round2delt(r[1], r[3])) )
+                    s.get('max'),
+                    utils.round2delt(r[1], r[3])) )
 
         # finally change the axes
         self.document.applyOperation(
             document.OperationMultiple(operations,descr=_('zoom axes')) )
 
     def axesForPoint(self, mousepos):
-        """Find all the axes which contain the given mouse position"""
+        """Find all the axes which contain the given mouse position.
+
+        Returns a dict of axis: coordinate
+        """
 
+        axes = {}
         if self.painthelper is None:
-            return []
+            return axes
 
         pos = self.mapToScene(mousepos)
         px = pos.x() / self.painthelper.cgscale
         py = pos.y() / self.painthelper.cgscale
 
-        axes = []
         for widget, bounds in self.painthelper.widgetBoundsIterator(
             widgettype=widgets.Axis):
             # if widget is axis, and point lies within bounds
@@ -596,11 +638,91 @@
                     val = px
                 else:
                     val = py
-                coords=widget.plotterToGraphCoords(bounds, N.array([val]))
-                axes.append( (widget, coords[0]) )
+                coords = widget.plotterToGraphCoords(bounds, N.array([val]))
+                axes[widget] = coords[0]
 
         return axes
 
+    def doGraphZoomOnPoint(self, mousepos, factor=0.8, inverse=False):
+        """Zoom out of/into graph around position.
+
+        factor: zoom factor
+        inverse: reverse zoom factor
+        """
+
+        if inverse:
+            factor = 1/factor
+
+        axes = self.axesForPoint(mousepos)
+        if not axes:
+            return
+
+        pos = self.mapToScene(mousepos)
+        px = pos.x() / self.painthelper.cgscale
+        py = pos.y() / self.painthelper.cgscale
+
+        ops = []
+        for axis, val in axes.items():
+            ishorz = axis.settings.direction == 'horizontal'
+            bounds = self.painthelper.widgetBounds(axis)
+            if ishorz:
+                rng = bounds[2]-bounds[0]
+                b0, b1 = bounds[0], bounds[2]
+                clickpos = px
+            else:
+                rng = bounds[3]-bounds[1]
+                b0, b1 = bounds[1], bounds[3]
+                clickpos = py
+
+            delta = rng/factor/2
+            coords = axis.plotterToGraphCoords(
+                bounds, N.array([
+                    clickpos-delta,
+                    clickpos+delta,
+                    clickpos-delta+1,
+                    clickpos+delta+1,
+                ]))
+
+            poslo, poshi = [coords[0], coords[1]]
+            poslo1, poshi1 = [coords[2], coords[3]]
+            if not ishorz:
+                poshi, poslo = poslo, poshi
+                poshi1, poslo1 = poslo1, poshi1
+
+            ops.append( document.OperationSettingSet(
+                axis.settings.get('min'), float(poslo)) )
+            ops.append( document.OperationSettingSet(
+                axis.settings.get('max'), float(poshi)) )
+
+        if factor == 1:
+            descr = _('recenter graph')
+        elif factor < 1:
+            descr = _('zoom into axes')
+        else:
+            descr = _('zoom out of axes')
+
+        self.document.applyOperation(
+            document.OperationMultiple(ops, descr=descr))
+
+    def doGraphRecenterOnPoint(self, mousepos):
+        """Recentre graph on point."""
+        self.doGraphZoomOnPoint(mousepos, factor=1)
+
+    def doGraphReset(self, mousepos):
+        """Reset axes for graph."""
+
+        axes = self.axesForPoint(mousepos)
+        if not axes:
+            return
+        ops = []
+        for axis, val in axes.items():
+            ops.append( document.OperationSettingSet(
+                axis.settings.get('min'), 'Auto') )
+            ops.append( document.OperationSettingSet(
+                axis.settings.get('max'), 'Auto') )
+        self.document.applyOperation(
+            document.OperationMultiple(ops, descr=_("reset axes")))
+
     def emitPicked(self, pickinfo):
         """Report that a new point has been picked"""
 
@@ -692,8 +814,6 @@
                     0, 0)
                 self.zoomrect.show()
 
-                #self.label.drawRect(self.grabpos, self.grabpos)
-
             # record what mode we were clicked in
             self.currentclickmode = self.clickmode
 
@@ -731,16 +851,14 @@
                     max(self.grabpos.y(), pos2.y())),
                 ))
 
-        elif self.clickmode == 'select' or self.clickmode == 'pick':
-            # find axes which map to this position
-            axes = self.axesForPoint(event.pos())
-            vals = dict([ (a[0].name, a[1]) for a in axes ])
-
-            self.sigAxisValuesFromMouse.emit(vals)
-
-            if self.currentclickmode == 'pick':
-                # drag the picker around
-                self.doPick(event.pos())
+        # update position of mouse
+        axes = self.axesForPoint(event.pos())
+        vals = {a.name: v for a, v in axes.items()}
+        self.sigAxisValuesFromMouse.emit(vals)
+
+        if self.currentclickmode == 'pick':
+            # drag the picker around
+            self.doPick(event.pos())
 
     def mouseReleaseEvent(self, event):
         """If the mouse button is released, check whether the mouse
@@ -764,12 +882,18 @@
                 qt.QApplication.restoreOverrideCursor()
             elif self.currentclickmode == 'graphzoom':
                 self.zoomrect.hide()
-                self.doZoomRect(self.mapToScene(event.pos()))
+                self.doGraphZoomRect(self.mapToScene(event.pos()))
                 self.grabpos = None
             elif self.currentclickmode == 'viewgetclick':
                 self.clickmode = 'select'
             elif self.currentclickmode == 'pick':
                 self.currentclickmode = None
+            elif self.currentclickmode == 'graphzoomout':
+                self.doGraphZoomOnPoint(event.pos())
+            elif self.currentclickmode == 'graphrecenter':
+                self.doGraphRecenterOnPoint(event.pos())
+            elif self.currentclickmode == 'graphreset':
+                self.doGraphReset(event.pos())
 
     def keyPressEvent(self, event):
         """Keypad motion moves the picker if it has focus"""
@@ -1177,9 +1301,14 @@
     def slotSelectMode(self, action):
         """Called when the selection mode has changed."""
 
-        modecnvt = { self.vzactions['view.select'] : 'select',
-                     self.vzactions['view.pick'] : 'pick',
-                     self.vzactions['view.zoomgraph'] : 'graphzoom' }
+        modecnvt = {
+            self.vzactions['view.select'] : 'select',
+            self.vzactions['view.pick'] : 'pick',
+            self.vzactions['view.graphzoom'] : 'graphzoom',
+            self.vzactions['view.graphzoomout'] : 'graphzoomout',
+            self.vzactions['view.graphrecenter'] : 'graphrecenter',
+            self.vzactions['view.graphreset'] : 'graphreset',
+        }
 
         # close the current picker
         self.pickeritem.hide()
@@ -1190,7 +1319,8 @@
 
         if self.clickmode == 'select':
             self.pixmapitem.unsetCursor()
-        elif self.clickmode == 'graphzoom':
+        elif self.clickmode in (
+                'graphzoom', 'graphzoomout', 'graphrecenter', 'graphreset'):
             self.pixmapitem.setCursor(qt.Qt.CrossCursor)
         elif self.clickmode == 'pick':
             self.pixmapitem.setCursor(qt.Qt.CrossCursor)
diff -Nru veusz-3.3/veusz.egg-info/PKG-INFO veusz-3.3.1/veusz.egg-info/PKG-INFO
--- veusz-3.3/veusz.egg-info/PKG-INFO	2020-11-29 08:23:53.000000000 +0000
+++ veusz-3.3.1/veusz.egg-info/PKG-INFO	2020-12-06 11:44:58.000000000 +0000
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: veusz
-Version: 3.3
+Version: 3.3.1
 Summary: A scientific plotting package
 Home-page: https://veusz.github.io/
 Author: Jeremy Sanders
diff -Nru veusz-3.3/veusz.egg-info/requires.txt veusz-3.3.1/veusz.egg-info/requires.txt
--- veusz-3.3/veusz.egg-info/requires.txt	2020-11-29 08:23:53.000000000 +0000
+++ veusz-3.3.1/veusz.egg-info/requires.txt	2020-12-06 11:44:58.000000000 +0000
@@ -1,6 +1,5 @@
 PyQt5
 numpy
-sip
 
 [optional]
 astropy
diff -Nru veusz-3.3/veusz.egg-info/SOURCES.txt veusz-3.3.1/veusz.egg-info/SOURCES.txt
--- veusz-3.3/veusz.egg-info/SOURCES.txt	2020-11-29 08:23:53.000000000 +0000
+++ veusz-3.3.1/veusz.egg-info/SOURCES.txt	2020-12-06 11:44:59.000000000 +0000
@@ -265,7 +265,10 @@
 icons/veusz-pick-data.svg
 icons/veusz-shape-menu.svg
 icons/veusz-view-fullscreen.svg
+icons/veusz-zoom-graph-out.svg
+icons/veusz-zoom-graph-recenter.svg
 icons/veusz-zoom-graph.svg
+icons/veusz-zoom-reset.svg
 icons/veusz.icns
 icons/veusz.ico
 icons/veusz.png