...
 
Commits (3)
Changes in 3.0.1:
* Change in build system to use qmake to find Qt locations. This is to fix
the build inside Anaconda. Also Qt and sip parameters can now be given
as environment variables.
* Fix problem when picking points with too many non-finite values
* Change default SVG export DPI to 96 to match inkscape and provide
option in dialog to choose export DPI
* Allow %PAGE% and %PAGENAME% in export filename for single page output
* Fix failing fitting due to iminuit differences
* Fix crash if both ends of part of broken axis widget are the same for
EMF exporting
Changes in 3.0:
* New 3D support for plotting points, functions, surfaces and volumes
* Add --export-option parameter for command line exporting control
......
......@@ -129,7 +129,7 @@
.\" ========================================================================
.\"
.IX Title "VEUSZ 1"
.TH VEUSZ 1 "2018-04-22" "3.0" "Veusz"
.TH VEUSZ 1 "2018-04-22" "3.0.1" "Veusz"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......
......@@ -90,4 +90,4 @@ COPYRIGHT
On Debian GNU/Linux systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL'.
3.0 2018-04-22 VEUSZ(1)
3.0.1 2018-04-22 VEUSZ(1)
......@@ -189,7 +189,7 @@ Export
:command:`Export(filename, color=True, page=0, dpi=100,
antialias=True, quality=85, backcolor='#ffffff00', pdfdpi=150,
svgtextastext=False)`
svgdpi=96, svgtextastext=False)`
Export the page given to the filename given. The :command:`filename`
must end with the correct extension to get the right sort of output
......@@ -204,7 +204,8 @@ True. :command:`quality` is a quality parameter for jpeg
output. :command:`backcolor` is the background color for bitmap files,
which is a name or a #RRGGBBAA value (red, green, blue,
alpha). :command:`pdfdpi` is the dpi to use when exporting EPS or PDF
files. :command:`svgtextastext` says whether to export SVG text as
files. :command:`svgdpi` is the dpi to use when exporting to SVG files.
:command:`svgtextastext` says whether to export SVG text as
text, rather than curves.
FilterDatasets
......
# 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: ee03a8ceaa41d8d3226de6536feef811
config: ee14a1d4fb737826e199e9a6fa6eb104
tags: 645f666f9bcd5a90fca523b33c5a78b7
......@@ -189,7 +189,7 @@ Export
:command:`Export(filename, color=True, page=0, dpi=100,
antialias=True, quality=85, backcolor='#ffffff00', pdfdpi=150,
svgtextastext=False)`
svgdpi=96, svgtextastext=False)`
Export the page given to the filename given. The :command:`filename`
must end with the correct extension to get the right sort of output
......@@ -204,7 +204,8 @@ True. :command:`quality` is a quality parameter for jpeg
output. :command:`backcolor` is the background color for bitmap files,
which is a name or a #RRGGBBAA value (red, green, blue,
alpha). :command:`pdfdpi` is the dpi to use when exporting EPS or PDF
files. :command:`svgtextastext` says whether to export SVG text as
files. :command:`svgdpi` is the dpi to use when exporting to SVG files.
:command:`svgtextastext` says whether to export SVG text as
text, rather than curves.
FilterDatasets
......
......@@ -4,7 +4,7 @@
*
* Sphinx stylesheet -- basic theme.
*
* :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
* :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
......@@ -332,6 +332,11 @@ table.docutils {
border-collapse: collapse;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
table caption span.caption-number {
font-style: italic;
}
......@@ -398,6 +403,13 @@ table.field-list td, table.field-list th {
margin: 0;
}
.field-name {
-moz-hyphens: manual;
-ms-hyphens: manual;
-webkit-hyphens: manual;
hyphens: manual;
}
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
......@@ -438,10 +450,14 @@ dd {
margin-left: 30px;
}
dt:target, .highlighted {
dt:target, span.highlighted {
background-color: #fbe54e;
}
rect.highlighted {
fill: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
......
......@@ -4,7 +4,7 @@
*
* Sphinx JavaScript utilities for all documentation.
*
* :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
* :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
......@@ -45,7 +45,7 @@ jQuery.urlencode = encodeURIComponent;
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s == 'undefined')
if (typeof s === 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
......@@ -66,29 +66,53 @@ jQuery.getQueryParameters = function(s) {
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node) {
if (node.nodeType == 3) {
function highlight(node, addItems) {
if (node.nodeType === 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
var span = document.createElement("span");
span.className = className;
var span;
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.className = className;
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
var bbox = span.getBBox();
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute('class', className);
var parentOfText = node.parentNode.parentNode;
addItems.push({
"parent": node.parentNode,
"target": rect});
}
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this);
highlight(this, addItems);
});
}
}
return this.each(function() {
highlight(this);
var addItems = [];
var result = this.each(function() {
highlight(this, addItems);
});
for (var i = 0; i < addItems.length; ++i) {
jQuery(addItems[i].parent).before(addItems[i].target);
}
return result;
};
/*
......@@ -131,21 +155,21 @@ var Documentation = {
* i18n support
*/
TRANSLATIONS : {},
PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
LOCALE : 'unknown',
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext : function(string) {
var translated = Documentation.TRANSLATIONS[string];
if (typeof translated == 'undefined')
if (typeof translated === 'undefined')
return string;
return (typeof translated == 'string') ? translated : translated[0];
return (typeof translated === 'string') ? translated : translated[0];
},
ngettext : function(singular, plural, n) {
var translated = Documentation.TRANSLATIONS[singular];
if (typeof translated == 'undefined')
if (typeof translated === 'undefined')
return (n == 1) ? singular : plural;
return translated[Documentation.PLURALEXPR(n)];
},
......@@ -180,7 +204,7 @@ var Documentation = {
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash)
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
......@@ -216,7 +240,7 @@ var Documentation = {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
$('tr.cg-' + idnum).toggle();
if (src.substr(-9) == 'minus.png')
if (src.substr(-9) === 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
......@@ -248,7 +272,7 @@ var Documentation = {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this == '..')
if (this === '..')
parts.pop();
});
var url = parts.join('/');
......
This diff is collapsed.
......@@ -4,7 +4,7 @@
*
* Sphinx JavaScript utilities for the full-text search.
*
* :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
* :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
......@@ -540,6 +540,9 @@ var Search = {
});
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX;
if (suffix === undefined) {
suffix = '.txt';
}
$.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].slice(-suffix.length) === suffix ? '' : suffix),
dataType: "text",
complete: function(jqxhr, textstatus) {
......
......@@ -4,7 +4,7 @@
*
* sphinx.websupport utilities for all documentation.
*
* :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
* :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
......
This diff is collapsed.
This diff is collapsed.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Index &#8212; Veusz 3.0 documentation</title>
<title>Index &#8212; Veusz 3.0.1 documentation</title>
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0',
VERSION: '3.0.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
......@@ -33,7 +30,7 @@
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
</head>
<body role="document">
<body>
<div class="document">
......@@ -81,7 +78,7 @@
&copy;2003-2018, Jeremy Sanders.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 1.5.6</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 1.6.7</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.8</a>
</div>
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Veusz documentation &#8212; Veusz 3.0 documentation</title>
<title>Veusz documentation &#8212; Veusz 3.0.1 documentation</title>
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0',
VERSION: '3.0.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
......@@ -33,7 +30,7 @@
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
</head>
<body role="document">
<body>
<div class="document">
......@@ -234,7 +231,7 @@ scientific plotting package with a graphical user interface.</p>
&copy;2003-2018, Jeremy Sanders.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 1.5.6</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 1.6.7</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.8</a>
|
......
This diff is collapsed.
# Sphinx inventory version 2
# Project: Veusz
# Version: 3.0
# Version: 3.0.1
# The remainder of this file is compressed using zlib.
xڕ͎ Fy
KEH3R7u9V"pbpg<}/vU|gl 0>4ߩ' puLFI Mm`CӇ̈́31S<nMDyzc}36epe4Hт'r&2cy8HlNk9ŕJjJ6ef;c(,:G(Y{pMr=c9 =^F!'O{94$S!G42c}|% ?FjU RN.|ΏdHㄡnkjwe%3x- S"{DHիj/a|'x _MƄ'TΓWx=EߒR _d*\S+"au$3G\1zR;HIP]viF(4h+B7ZДY׈dڹb_L{ɔd~XtS1$nL%#w؁̮oΗ#z:k&zv7^qN/rnzLW^=t[٘]$x8H7O.C)3LA3: l"-WΜN9|Ci&_a^q*Дp12"y13}-߀v(pg,pxeO&aS2b<cЁj-&Z*gXP^/p5V O˿IJ76\Ο2}?bY>;؏eݾןqϰ \4 G=02
\ No newline at end of file
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Search &#8212; Veusz 3.0 documentation</title>
<title>Search &#8212; Veusz 3.0.1 documentation</title>
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0',
VERSION: '3.0.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
......@@ -40,7 +37,7 @@
</head>
<body role="document">
<body>
<div class="document">
......@@ -91,7 +88,7 @@
&copy;2003-2018, Jeremy Sanders.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 1.5.6</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 1.6.7</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.8</a>
</div>
......
This diff is collapsed.
......@@ -39,11 +39,11 @@ pyemf for Python 3 can be found at https://github.com/jeremysanders/pyemf.
There are a number of ways to install programs using distutils. I will
list a few of the possible method here:
To install on linux to the standard location on the hard disk follow
these instructions (note python in theres commands can be replaced by
python3 to do a python3 installation).
To install on Linux to the standard location on the hard disk follow
these instructions (note python in these commands should be replaced
by python3 to do a Python 3 installation).
# cd veusz-2.2.2
# cd veusz-3.0.1
# python setup.py build
# su
[enter root password]
......@@ -74,6 +74,11 @@ graphical environment to create a hidden X11 server:
# xvfb-run -a --server-args "-screen 0 640x480x24" \
python tests/runselftest.py
Alternatively, the Qt platform can be switched to minimal to avoid the
use of X11:
# QT_QPA_PLATFORM=minimal python tests/runselftest.py
1.1.2 Separate resources directory
==================================
By default, setup.py installs certain resource files (VERSION, icons,
......@@ -98,6 +103,7 @@ resources directory to point to the location of the example files.
1.1.3 SIP parameters
====================
By default the location of the SIP executable, the SIP include file
location and the SIP files are obtained from sipconfig. sipconfig is
now deprecated. If sipconfig is not found, the build will look for the
......@@ -111,6 +117,29 @@ stage before build, with the parameters:
--sip-include-dir=DIR SIP include directory (location of sip.h)
--sip-dir=DIR base directory for SIP files
Alternatively, these can be given as environment variables SIP_EXE,
SIP_INCLUDE_DIR and SIP_DIR, respectively. Environment variables have
the advantage that the build_ext stage does not have to be done
separately.
1.1.4 Qt build parameters
=========================
By default, the qmake executable is used to find the locations of the
Qt include and library directories. The build searches for qmake under
the names qmake-qt5, qmake, qmake5.exe and qmake.exe. The location of
qmake and its return values can be overriden with the following
build_ext options:
--qmake-exe=EXE qmake exe
--qt-include-dir=DIR base Qt include directory
--qt-library-dir=DIR Qt library directory
Alternatively, these can be overridden with the enviroment variables
QMAKE_EXE, QT_INCLUDE_DIR and QT_LIBRARY_DIR, respectively.
Environment variables have the advantage that the build_ext stage does
not have to be done separately.
1.3 Running in-place
====================
......@@ -119,8 +148,8 @@ can currently be run from its own directory. Before this can work, the
helper modules must be compiled and copied into the appropriate
location.
# tar xzf veusz-2.2.2.tar.gz [change version here]
# cd veusz-2.2.2
# tar xzf veusz-3.0.1.tar.gz [change version here]
# cd veusz-3.0.1
# python setup.py build [or use python3 here]
# cp build/*/veusz/helpers/*.so veusz/helpers/
......@@ -141,8 +170,8 @@ work on all distributions due to glibc/library
incompatibilities. Simply unpack the tar file and run the main
executable:
# tar xf veusz-2.2.2-linux-x86.tar.xz [change version here]
# cd veusz-2.2.2-linux-x86
# tar xf veusz-3.0.1-linux-x86.tar.xz [change version here]
# cd veusz-3.0.1-linux-x86
# ./veusz
2.2 Installing in Windows
......
Metadata-Version: 1.1
Name: veusz
Version: 3.0
Version: 3.0.1
Summary: A scientific plotting package
Home-page: https://veusz.github.io/
Author: Jeremy Sanders
......
Veusz 3.0
---------
Veusz 3.0.1
-----------
https://veusz.github.io
Veusz is a 2D and 3D scientific plotting package. It is designed to
......@@ -12,6 +12,20 @@ SAMP interfaces to its plotting facilities. It also allows for
manipulation and editing of datasets. Data can be captured from
external sources such as Internet sockets or other programs.
Changes in 3.0.1:
* Change in build system to use qmake to find Qt locations. This is to fix
the build inside Anaconda. Also Qt and sip parameters can now be given
as environment variables.
* Fix problem when picking points with too many non-finite values
* Change default SVG export DPI to 96 to match inkscape and provide
option in dialog to choose export DPI
* Allow %PAGE% and %PAGENAME% in export filename for single page output
* Fix failing fitting due to iminuit differences
* Fix crash if both ends of part of broken axis widget are the same for
EMF exporting
* Update to Qt 5.11.1 and update PyQt and sip in Windows binary
* Build Mac and Linux binaries with EMF export
Changes in 3.0:
* New 3D support for plotting points, functions, surfaces and volumes
* Add --export-option parameter for command line exporting control
......
......@@ -8,6 +8,7 @@ from __future__ import division, print_function, absolute_import
import os
import sys
import sysconfig
import subprocess
from distutils.sysconfig import customize_compiler
import distutils.command.build_ext
......@@ -18,13 +19,6 @@ import PyQt5.QtCore
##################################################################
# try to get various useful things we need in order to build
QT_LIB_DIR = PyQt5.QtCore.QLibraryInfo.location(
PyQt5.QtCore.QLibraryInfo.LibrariesPath)
QT_INC_DIR = PyQt5.QtCore.QLibraryInfo.location(
PyQt5.QtCore.QLibraryInfo.HeadersPath)
QT_IS_FRAMEWORK = os.path.exists(
os.path.join(QT_LIB_DIR, 'QtCore.framework') )
SIP_FLAGS = PyQt5.QtCore.PYQT_CONFIGURATION['sip_flags']
try:
......@@ -43,19 +37,33 @@ else:
##################################################################
def findSipOnPath():
'''Get SIP executable from PATH.'''
def replace_suffix(path, new_suffix):
return os.path.splitext(path)[0] + new_suffix
def find_on_path(names, mainname):
"""From a list of names of executables, find the 1st one on a path.
mainname is the generic name to report
"""
path = os.getenv('PATH', os.path.defpath)
pathparts = path.split(os.path.pathsep)
for cmd in 'sip', 'sip5', 'sip.exe', 'sip5.exe':
for cmd in names:
for dirname in pathparts:
cmdtry = os.path.join(dirname.strip('"'), cmd)
if os.path.isfile(cmdtry) and os.access(cmdtry, os.X_OK):
return cmdtry
raise RuntimeError('Could not find SIP executable')
def replace_suffix(path, new_suffix):
return os.path.splitext(path)[0] + new_suffix
raise RuntimeError('Could not find %s executable' % mainname)
def read_command_output(cmd):
"""Get text from a run command."""
p = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
universal_newlines=True)
stdout, stderr = p.communicate()
if p.returncode != 0:
raise RuntimeError('Command %s returned error' % str(cmd))
return stdout.strip()
class build_ext(distutils.command.build_ext.build_ext):
......@@ -69,6 +77,12 @@ class build_ext(distutils.command.build_ext.build_ext):
'override sip file directory'),
('sip-include-dir=', None,
'override sip include directory'),
('qmake-exe=', None,
'override qmake executable'),
('qt-include-dir=', None,
'override Qt include directory'),
('qt-library-dir=', None,
'override Qt library directory'),
]
def initialize_options(self):
......@@ -76,6 +90,9 @@ class build_ext(distutils.command.build_ext.build_ext):
self.sip_exe = None
self.sip_dir = None
self.sip_include_dir = None
self.qmake_exe = None
self.qt_include_dir = None
self.qt_library_dir = None
def _get_sip_output_list(self, sbf):
'''
......@@ -91,14 +108,82 @@ class build_ext(distutils.command.build_ext.build_ext):
return out
raise RuntimeError('cannot parse SIP-generated "%s"' % sbf)
def get_cpp_includes(self):
incdirs = [QT_INC_DIR]
def _get_sip_exe(self, build_cmd):
"""Get exe for sip. Sources are:
--sip-exe option, environment, DEF_SIP_BIN, search on path."""
return (
build_cmd.sip_exe or
os.environ.get('SIP_EXE') or
DEF_SIP_BIN or
find_on_path(
('sip5', 'sip-qt5', 'sip', 'sip5.exe', 'sip.exe'), 'sip')
)
def _get_sip_inc_dir(self, build_cmd):
"""Get include directory for sip."""
return (
build_cmd.sip_include_dir or
os.environ.get('SIP_INCLUDE_DIR') or
DEF_SIP_INC_DIR or
sysconfig.get_path('include')
)
def _get_sip_dir(self, build_cmd):
"""Get sip directory."""
data_dir = sys.prefix if sys.platform=='win32' else sys.prefix+'/share'
return (
build_cmd.sip_dir or
os.environ.get('SIP_DIR') or
DEF_SIP_DIR or
os.path.join(data_dir, 'sip')
)
def _get_qmake(self, build_cmd):
"""Get qmake executable."""
return (
build_cmd.qmake_exe or
os.environ.get('QMAKE_EXE') or
find_on_path(
('qmake-qt5', 'qmake5', 'qmake', 'qmake5.exe', 'qmake.exe'),
'qmake')
)
def _get_qt_inc_dir(self, build_cmd):
"""Get Qt include directory."""
return (
build_cmd.qt_include_dir or
os.environ.get('QT_INCLUDE_DIR') or
read_command_output(
[self._get_qmake(build_cmd), '-query', 'QT_INSTALL_HEADERS'])
)
def _get_qt_library_dir(self, build_cmd):
"""Get Qt library directory."""
return (
build_cmd.qt_library_dir or
os.environ.get('QT_LIBRARY_DIR') or
read_command_output(
[self._get_qmake(build_cmd), '-query', 'QT_INSTALL_LIBS'])
)
def _is_qt_framework(self, build_cmd):
"""Is the Qt a framework?"""
return os.path.exists(
os.path.join(
self._get_qt_library_dir(build_cmd), 'QtCore.framework'))
def _get_cpp_includes(self, build_cmd):
"""Get list of include directories to add."""
inc_dir = self._get_qt_inc_dir(build_cmd)
incdirs = [inc_dir]
for mod in ('QtCore', 'QtGui', 'QtWidgets', 'QtXml'):
if QT_IS_FRAMEWORK:
if self._is_qt_framework(build_cmd):
incdirs.append(
os.path.join(QT_LIB_DIR, mod + '.framework', 'Headers') )
os.path.join(
self._get_qt_library_dir(build_cmd),
mod+'.framework', 'Headers') )
else:
incdirs.append( os.path.join(QT_INC_DIR, mod) )
incdirs.append(os.path.join(inc_dir, mod))
return incdirs
def swig_sources(self, sources, extension=None):
......@@ -110,15 +195,11 @@ class build_ext(distutils.command.build_ext.build_ext):
build_cmd = self.get_finalized_command('build_ext')
# executable in order of priority using or
sip_exe = build_cmd.sip_exe or DEF_SIP_BIN or findSipOnPath()
sip_inc_dir = (
build_cmd.sip_include_dir or DEF_SIP_INC_DIR or
sysconfig.get_path('include'))
sip_exe = self._get_sip_exe(build_cmd)
sip_inc_dir = self._get_sip_inc_dir(build_cmd)
# python data directory
data_dir = sys.prefix if sys.platform=='win32' else sys.prefix+'/share'
sip_dir = (
build_cmd.sip_dir or DEF_SIP_DIR or
os.path.join(data_dir, 'sip'))
sip_dir = self._get_sip_dir(build_cmd)
# add directory of input files as include path
indirs = list(set([os.path.dirname(x) for x in sources]))
......@@ -128,26 +209,26 @@ class build_ext(distutils.command.build_ext.build_ext):
# link against libraries
if extension.language == 'c++':
extension.include_dirs += self.get_cpp_includes()
if QT_IS_FRAMEWORK:
extension.include_dirs += self._get_cpp_includes(build_cmd)
lib_dir = self._get_qt_library_dir(build_cmd)
if self._is_qt_framework(build_cmd):
# Mac OS framework
extension.extra_link_args = [
'-F', os.path.join(QT_LIB_DIR),
'-F', os.path.join(lib_dir),
'-framework', 'QtGui',
'-framework', 'QtCore',
'-framework', 'QtXml',
'-framework', 'QtWidgets',
'-Wl,-rpath,@executable_path/Frameworks',
'-Wl,-rpath,' + QT_LIB_DIR
'-Wl,-rpath,' + lib_dir
]
extension.extra_compile_args = [
'-F', QT_LIB_DIR,
'-F', lib_dir,
]
else:
extension.libraries = [
'Qt5Gui', 'Qt5Core', 'Qt5Xml', 'Qt5Widgets']
extension.library_dirs = [QT_LIB_DIR]
extension.library_dirs = [lib_dir]
# may cause problems with compilers which don't allow this
if self.compiler.compiler_type == 'unix':
......@@ -185,12 +266,17 @@ class build_ext(distutils.command.build_ext.build_ext):
return generated_sources + other_sources
def _sip_compile(self, sip_exe, sip_dir, source, sbf):
self.spawn([sip_exe,
'-c', self.build_temp,
] + SIP_FLAGS.split() + [
'-I', os.path.join(sip_dir, 'PyQt5'),
'-b', sbf,
source])
"""Compile sip file to sources."""
self.spawn(
[
sip_exe,
'-c', self.build_temp
] + SIP_FLAGS.split() + [
'-I', os.path.join(sip_dir, 'PyQt5'),
'-b', sbf,
source
]
)
def build_extensions(self):
# remove annoying flag which causes warning for c++ sources
......
......@@ -60,7 +60,8 @@ from distutils.command.install_data import install_data
import pyqtdistutils
# get version
version = open('VERSION').read().strip()
with open('VERSION') as verf:
version = verf.read().strip()
class install(orig_install):
user_options = orig_install.user_options + [
......
......@@ -29,12 +29,15 @@ This program requires the veusz module to be on the PYTHONPATH.
On Unix/Linux, Qt requires the DISPLAY environment to be set to an X11
server for the self test to run. In a non graphical environment Xvfb
can be used to create a hidden X11 server.
can be used to create a hidden X11 server. Alternatively, set the
environment variable QT_QPA_PLATFORM=minimal to avoid the X11
dependency.
The comparison files are close to being SVG files, but use XPM for any
images and use a fixed (hacked) font metric to give the same results
on each platform. In addition Unicode characters are expanded to their
Unicode code to work around different font handling on platforms.
"""
# messes up loaded files if set
......@@ -171,7 +174,6 @@ def renderVszTest(invsz, outfile, test_saves=False, test_unlink=False):
def renderPyTest(inpy, outfile):
"""Render py embedded script to create outfile."""
retn = subprocess.call([sys.executable, inpy, outfile])
return retn == 0
......@@ -291,8 +293,6 @@ if __name__ == '__main__':
del utils.textrender.part_commands[r'\underline']
# dpi (use old values)
svg_export.dpi = 90.
svg_export.scale = 1.
svg_export.fltStr = fltStr
parser = optparse.OptionParser()
......
......@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>540</width>
<height>646</height>
<height>680</height>
</rect>
</property>
<property name="windowTitle">
......@@ -164,7 +164,7 @@
<string>Windows embedded metafile</string>
</property>
<property name="text">
<string>EMF</string>
<string>E&amp;MF</string>
</property>
</widget>
</item>
......@@ -227,6 +227,23 @@
<string>Options</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="labelCheckOverwrite">
<property name="text">
<string>Overwrite without confirmation</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkOverwrite">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Overwrite any files with the same name without confirmation&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelDPI">
<property name="text">
......@@ -273,13 +290,30 @@ This is recommended for most purposes.</string>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelDPISVG">
<property name="text">
<string>SVG DPI</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="exportDPISVG">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The number of dots per inch used for writing SVG files. Modern inkscape uses 96.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelBackgroundButton">
<property name="text">
<string>Bitmap background</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QPushButton" name="exportBackgroundButton">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The background color for bitmap files. Use alpha channel values of 0 for transparency&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
......@@ -289,14 +323,14 @@ This is recommended for most purposes.</string>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="5" column="0">
<widget class="QLabel" name="labelQuality">
<property name="text">
<string>Jpeg quality</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QSpinBox" name="exportQuality">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Choose Jpeg quality setting. Lower values give poorer quality results and are more compressed, but have smaller file sizes.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
......@@ -312,14 +346,14 @@ This is recommended for most purposes.</string>
</property>
</widget>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QLabel" name="labelColor">
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QComboBox" name="exportColor">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Output Postscript or PDF as full color, or convert to greyscale&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
......@@ -336,14 +370,14 @@ This is recommended for most purposes.</string>
</item>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QLabel" name="labelSVGTextAsText">
<property name="text">
<string>Editable text in SVG</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="QCheckBox" name="exportSVGTextAsText">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Exports text in SVG files as text, rather than curves. Curves mean that the file will display the same on any system, but text can be edited easily in other programs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
......@@ -353,23 +387,6 @@ This is recommended for most purposes.</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkOverwrite">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Overwrite any files with the same name without confirmation&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelCheckOverwrite">
<property name="text">
<string>Overwrite without confirmation</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
......
Metadata-Version: 1.1
Name: veusz
Version: 3.0
Version: 3.0.1
Summary: A scientific plotting package
Home-page: https://veusz.github.io/
Author: Jeremy Sanders
......
......@@ -122,12 +122,12 @@ class ExportDialog(VeuszDialog):
self.exportQuality.setValue(setdb['export_quality'])
# validate and set DPIs
dpis = ('75', '90', '100', '150', '200', '300')
self.exportDPI.addItems(dpis)
self.exportDPIPDF.addItems(dpis)
self.exportDPI.setValidator(qt4.QIntValidator(10, 10000, self))
dpis = ('72', '75', '90', '96', '100', '150', '200', '300')
for cntrl in self.exportDPI, self.exportDPISVG, self.exportDPIPDF:
cntrl.addItems(dpis)
cntrl.setValidator(qt4.QIntValidator(10, 10000, self))
self.exportDPI.setEditText(str(setdb['export_DPI']))
self.exportDPIPDF.setValidator(qt4.QIntValidator(10, 10000, self))
self.exportDPISVG.setEditText(str(setdb['export_DPI_SVG']))
self.exportDPIPDF.setEditText(str(setdb['export_DPI_PDF']))
# button to change bitmap background
......@@ -177,7 +177,8 @@ class ExportDialog(VeuszDialog):
for c in (self.exportQuality, self.labelQuality):
c.setVisible(fmt == 'jpg')
for c in (self.exportSVGTextAsText, self.labelSVGTextAsText):
for c in (self.exportSVGTextAsText, self.labelSVGTextAsText,
self.exportDPISVG, self.labelDPISVG):
c.setVisible(fmt == 'svg')
self.updateSingleMulti()
......@@ -248,11 +249,11 @@ class ExportDialog(VeuszDialog):
def isMultiFile(self):
"""Is output going to be multiple pages?"""
multipage = self.pageselected != 'single'
multifile = self.pageselected != 'single'
if (self.formatselected in multipageformats and
self.checkMultiPage.isChecked()):
multipage = False
return multipage
multifile = False
return multifile
def updateSingleMulti(self, _oldmulti=[None]):
"""Change filename according to selected single or multi button."""
......@@ -376,8 +377,10 @@ class ExportDialog(VeuszDialog):
# update dpi if possible
# FIXME: requires some sort of visual notification of validator
for cntrl, setn in ((self.exportDPI, 'export_DPI'),
(self.exportDPIPDF, 'export_DPI_PDF')):
for cntrl, setn in (
(self.exportDPI, 'export_DPI'),
(self.exportDPIPDF, 'export_DPI_PDF'),
(self.exportDPISVG, 'export_DPI_SVG')):
try:
text = cntrl.currentText()
valid = cntrl.validator().validate(text, 0)[0]
......@@ -397,6 +400,7 @@ class ExportDialog(VeuszDialog):
quality=setdb['export_quality'],
backcolor=setdb['export_background'],
svgtextastext=setdb['export_SVG_text_as_text'],
svgdpi=setdb['export_DPI_SVG'],
)
def _overwriteQuestion(filename):
......@@ -444,7 +448,7 @@ class ExportDialog(VeuszDialog):
else:
qt4.QApplication.restoreOverrideCursor()
if self.isMultiFile():
if self.isMultiFile() or len(pages)==1:
# write pages to multiple files
for page in pages:
pagename = self.document.getPage(page).name
......@@ -459,8 +463,13 @@ class ExportDialog(VeuszDialog):
_checkAndExport()
else:
# write page/pages to single file
fname = filename.replace('%PAGE%', _('none'))
fname = fname.replace('%PAGE00%', _('none'))
fname = fname.replace('%PAGE000%', _('none'))
fname = fname.replace('%PAGENAME%', _('none'))
export.pagenumbers = pages
export.filename = filename
export.filename = fname
_checkAndExport()
dirname = os.path.dirname(filename)
......
......@@ -748,7 +748,7 @@ class CommandInterface(qt4.QObject):
def Export(self, filename, color=True, page=[0], dpi=100,
antialias=True, quality=85, backcolor='#ffffff00',
pdfdpi=150, svgtextastext=False):
pdfdpi=150, svgdpi=96, svgtextastext=False):
"""Export plot to filename.
color is True or False if color is requested in output file
......@@ -759,6 +759,7 @@ class CommandInterface(qt4.QObject):
backcolor is the background color for bitmap files, which is a name or
a #RRGGBBAA value (red, green, blue, alpha)
pdfdpi is the dpi to use when exporting eps or pdf files
svgdpi is the dpi to use when exporting svg files
svgtextastext: write text in SVG as text, rather than curves
"""
......@@ -772,7 +773,8 @@ class CommandInterface(qt4.QObject):
self.document, filename, pages, color=color,
bitmapdpi=dpi, antialias=antialias,
quality=quality, backcolor=backcolor,
pdfdpi=pdfdpi, svgtextastext=svgtextastext)
pdfdpi=pdfdpi,
svgdpi=svgdpi, svgtextastext=svgtextastext)
e.export()
def Rename(self, widget, newname):
......
......@@ -184,7 +184,7 @@ class Export(object):
def __init__(self, doc, filename, pagenumbers, color=True, bitmapdpi=100,
antialias=True, quality=85, backcolor='#ffffff00',
pdfdpi=150, svgtextastext=False):
pdfdpi=150, svgdpi=96, svgtextastext=False):
"""Initialise export class. Parameters are:
doc: document to write
filename: output filename
......@@ -195,6 +195,7 @@ class Export(object):
quality: compression factor for bitmaps
backcolor: background color default for bitmaps (default transparent).
pdfdpi: dpi for pdf and eps files
svgdpi: dpi for svg files
svgtextastext: write text in SVG as text, rather than curves
"""
......@@ -207,6 +208,7 @@ class Export(object):
self.quality = quality
self.backcolor = backcolor
self.pdfdpi = pdfdpi
self.svgdpi = svgdpi
self.svgtextastext = svgtextastext
def export(self):
......@@ -387,27 +389,30 @@ class Export(object):
page = self.getSinglePage()
dpi = svg_export.dpi * 1.
scale = 0.1
sdpi = self.svgdpi/scale
size = self.doc.pageSize(
page, dpi=(dpi,dpi), integer=False)
page, dpi=(sdpi,sdpi), integer=False)
with codecs.open(filename, 'w', 'utf-8') as f:
paintdev = svg_export.SVGPaintDevice(
f, size[0]/dpi, size[1]/dpi, writetextastext=self.svgtextastext)
f, size[0]/sdpi, size[1]/sdpi,
writetextastext=self.svgtextastext,
dpi=self.svgdpi, scale=scale)
painter = painthelper.DirectPainter(paintdev)
self.renderPage(page, size, (dpi,dpi), painter)
self.renderPage(page, size, (sdpi,sdpi), painter)
def exportSelfTest(self, filename):
"""Export document for testing"""
page = self.getSinglePage()
dpi = svg_export.dpi * 1.
dpi = 90
size = width, height = self.doc.pageSize(
page, dpi=(dpi,dpi), integer=False)
with open(filename, 'w') as fout:
paintdev = selftest_export.SelfTestPaintDevice(
fout, width/dpi, height/dpi)
fout, width/dpi, height/dpi, dpi=dpi)
painter = painthelper.DirectPainter(paintdev)
self.renderPage(page, size, (dpi,dpi), painter)
......
......@@ -24,11 +24,8 @@ from . import svg_export
class SelfTestPaintEngine(svg_export.SVGPaintEngine):
"""Paint engine class for self testing output."""
def __init__(self, width_in, height_in):
"""Create the class, using width and height as size of canvas
in inches."""
svg_export.SVGPaintEngine.__init__(self, width_in, height_in)
def __init__(self):
svg_export.SVGPaintEngine.__init__(self)
# ppm images are simple and should be same on all platforms
self.imageformat = 'ppm'
......@@ -37,17 +34,26 @@ class SelfTestPaintEngine(svg_export.SVGPaintEngine):
text = textitem.text().encode('ascii', 'xmlcharrefreplace').decode(
'ascii')
svg_export.SVGElement(self.celement, 'text',
'x="%s" y="%s" font-size="%gpt" fill="%s"' %
(svg_export.fltStr(pt.x()*svg_export.scale),
svg_export.fltStr(pt.y()*svg_export.scale),
textitem.font().pointSize(),
self.pen.color().name()),
text=text)
svg_export.SVGElement(
self.celement, 'text',
'x="%s" y="%s" font-size="%gpt" fill="%s"' % (
svg_export.fltStr(pt.x()),
svg_export.fltStr(pt.y()),
textitem.font().pointSize(),
self.pen.color().name()
),
text=text
)
class SelfTestPaintDevice(svg_export.SVGPaintDevice):
"""Paint device for SVG paint engine."""
"""Paint device for SVG paint engine.
Note: this device is different to SVGPaintDevice because it
switches scaling to 1 by default.
"""
def __init__(self, fileobj, width_in, height_in):
svg_export.SVGPaintDevice.__init__(self, fileobj, width_in, height_in)
self.engine = SelfTestPaintEngine(width_in, height_in)
def __init__(self, fileobj, width_in, height_in, dpi=90):
"""Initialise with output file, and dimensions in inches."""
svg_export.SVGPaintDevice.__init__(
self, fileobj, width_in, height_in, dpi=dpi, scale=1)
self.engine = SelfTestPaintEngine()
This diff is collapsed.
......@@ -34,6 +34,7 @@ defaultValues = {
# export options
'export_DPI': 100,
'export_DPI_PDF': 150,
'export_DPI_SVG': 96,
'export_color': True,
'export_antialias': True,
'export_quality': 85,
......
......@@ -17,21 +17,20 @@
##############################################################################
from __future__ import division, print_function
import sys
from .settings import Settings
from . import setting
from . import collections
from .. import qtall as qt4
from .. import qtall as qt
def _(text, disambiguation=None, context="Setting"):
"""Translate text."""
return qt4.QCoreApplication.translate(context, text, disambiguation)
return qt.QCoreApplication.translate(context, text, disambiguation)
class StyleSheet(Settings):
"""A class for handling default values of settings.
Settings are registered to be added to the stylesheet."""
registeredsettings = []
......@@ -73,18 +72,22 @@ StyleSheet.register(StylesheetLine)
def _registerFontStyleSheet():
"""Get fonts, and register default with StyleSheet and Text class."""
families = qt4.QFontDatabase().families()
families = qt.QFontDatabase().families()
deffont = None
for f in ('Times New Roman', 'Bitstream Vera Serif', 'Times', 'Utopia',
'Serif'):
if f in families:
deffont = f
break
if deffont is None:
print("Warning: did not find a sensible default font. Choosing first font.", file=sys.stderr)
deffont = families[0]
if len(families) == 0:
# testing - no fonts available
deffont = 'Serif'
families = ['Serif']
elif deffont is None:
print("Warning: did not find a default font. Choosing Qt default font.")
deffont = qt.QFontDatabase.systemFont(qt.QFontDatabase.GeneralFont).family()
collections.Text.defaultfamily = deffont
collections.Text.families = families
......
......@@ -387,6 +387,9 @@ class AxisBroken(axis.Axis):
for i in crange(self.breakvnum):
self.switchBreak(i, posn)
if self.plottedrange[0]==self.plottedrange[1]:
continue
# plot coordinates of ticks
coordticks = self._graphToPlotter(self.majorticklist[i])
coordminorticks = self._graphToPlotter(self.minorticklist[i])
......
......@@ -84,7 +84,7 @@ def minuitFit(evalfunc, params, names, values, xvals, yvals, yserr):
have_symerr = True
m.minos()
have_err = True
except minuit.MinuitError as e:
except Exception as e:
print(e)
if str(e).startswith('Discovered a new minimum'):
# the initial fit really failed
......@@ -112,7 +112,7 @@ def minuitFit(evalfunc, params, names, values, xvals, yvals, yserr):
print("chi^2 = %g, dof = %i, reduced-chi^2 = %g" % (retchi2, dof, redchi2))
vals = m.values
vals = dict(m.values)
return vals, retchi2, dof
class Fit(FunctionPlotter):
......@@ -338,20 +338,20 @@ class Fit(FunctionPlotter):
return
if minuit is not None:
vals, chi2, dof = minuitFit(evalfunc, params, paramnames, s.values,
xvals, yvals, yserr)
vals, chi2, dof = minuitFit(
evalfunc, params, paramnames, s.values,
xvals, yvals, yserr)
else:
print(_('Minuit not available, falling back to simple L-M fitting:'))
retn, chi2, dof = utils.fitLM(evalfunc, params,
xvals,
yvals, yserr)
retn, chi2, dof = utils.fitLM(
evalfunc, params, xvals, yvals, yserr)
vals = {}
for i, v in czip(paramnames, retn):
vals[i] = float(v)
# list of operations do we can undo the changes
operations = []
# populate the return parameters
operations.append( document.OperationSettingSet(s.get('values'), vals) )
......@@ -374,15 +374,15 @@ class Fit(FunctionPlotter):
# actually change all the settings
d.applyOperation(
document.OperationMultiple(operations, descr=_('fit')) )
def generateOutputExpr(self, vals):
"""Try to generate text form of output expression.
vals is a dict of variable: value pairs
returns the expression
"""
paramvals = vals.copy()
paramvals = dict(vals)
s = self.settings
# also substitute in data name for variable
......@@ -398,7 +398,7 @@ class Fit(FunctionPlotter):
# replace part by things in paramvals, if they exist
for i, p in enumerate(parts):
if p in paramvals:
parts[i] = str( paramvals[p] )
parts[i] = str(paramvals[p])
return ''.join(parts)
......
......@@ -123,6 +123,10 @@ class GenericPickable:
else:
p = self.xgraph[pi], self.ygraph[pi]
if p is None and m is None:
# only 1 point after removing non-finite points
return 1
return _chooseOrderingSign(m, c, p)
def pickPoint(self, x0, y0, bounds, distance_direction):
......