Bugfix/wrong translate implementation (#1520)
* Removes all translate call on the parameter name and moves them into the title instead allowing to decouple visualization from code logic * Removes all translate calls from the Exporter class property Name and moves the translation logic when setting the QListWidgetItems for the formatList * Adds missing call to translation function for the export action on GraphicsScene
This commit is contained in:
parent
b094945dbc
commit
3f02b30140
@ -116,7 +116,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
||||
self.lastHoverEvent = None
|
||||
self.minDragTime = 0.5 # drags shorter than 0.5 sec are interpreted as clicks
|
||||
|
||||
self.contextMenu = [QtGui.QAction("Export...", self)]
|
||||
self.contextMenu = [QtGui.QAction(QtCore.QCoreApplication.translate("GraphicsScene", "Export..."), self)]
|
||||
self.contextMenu[0].triggered.connect(self.showExportDialog)
|
||||
|
||||
self.exportDialog = None
|
||||
|
@ -1,4 +1,4 @@
|
||||
from ..Qt import QtCore, QtGui, QT_LIB
|
||||
from ..Qt import QtCore, QtGui, QtWidgets, QT_LIB
|
||||
from .. import exporters as exporters
|
||||
from .. import functions as fn
|
||||
from ..graphicsItems.ViewBox import ViewBox
|
||||
@ -9,6 +9,12 @@ ui_template = importlib.import_module(
|
||||
f'.exportDialogTemplate_{QT_LIB.lower()}', package=__package__)
|
||||
|
||||
|
||||
class FormatExportListWidgetItem(QtWidgets.QListWidgetItem):
|
||||
def __init__(self, expClass, *args, **kwargs):
|
||||
QtWidgets.QListWidgetItem.__init__(self, *args, **kwargs)
|
||||
self.expClass = expClass
|
||||
|
||||
|
||||
class ExportDialog(QtGui.QWidget):
|
||||
def __init__(self, scene):
|
||||
QtGui.QWidget.__init__(self)
|
||||
@ -94,16 +100,14 @@ class ExportDialog(QtGui.QWidget):
|
||||
|
||||
def updateFormatList(self):
|
||||
current = self.ui.formatList.currentItem()
|
||||
if current is not None:
|
||||
current = str(current.text())
|
||||
|
||||
self.ui.formatList.clear()
|
||||
self.exporterClasses = {}
|
||||
gotCurrent = False
|
||||
for exp in exporters.listExporters():
|
||||
self.ui.formatList.addItem(exp.Name)
|
||||
self.exporterClasses[exp.Name] = exp
|
||||
if exp.Name == current:
|
||||
self.ui.formatList.setCurrentRow(self.ui.formatList.count()-1)
|
||||
item = FormatExportListWidgetItem(exp, QtCore.QCoreApplication.translate('Exporter', exp.Name))
|
||||
self.ui.formatList.addItem(item)
|
||||
if item == current:
|
||||
self.ui.formatList.setCurrentRow(self.ui.formatList.count() - 1)
|
||||
gotCurrent = True
|
||||
|
||||
if not gotCurrent:
|
||||
@ -114,7 +118,7 @@ class ExportDialog(QtGui.QWidget):
|
||||
self.currentExporter = None
|
||||
self.ui.paramTree.clear()
|
||||
return
|
||||
expClass = self.exporterClasses[str(item.text())]
|
||||
expClass = item.expClass
|
||||
exp = expClass(item=self.ui.itemTree.currentItem().gitem)
|
||||
|
||||
params = exp.parameters()
|
||||
|
@ -11,14 +11,14 @@ __all__ = ['CSVExporter']
|
||||
|
||||
|
||||
class CSVExporter(Exporter):
|
||||
Name = translate("Exporter", "CSV from plot data")
|
||||
Name = "CSV from plot data"
|
||||
windows = []
|
||||
def __init__(self, item):
|
||||
Exporter.__init__(self, item)
|
||||
self.params = Parameter(name='params', type='group', children=[
|
||||
{'name': translate("Exporter", 'separator'), 'type': 'list', 'value': 'comma', 'values': ['comma', 'tab']},
|
||||
{'name': translate("Exporter", 'precision'), 'type': 'int', 'value': 10, 'limits': [0, None]},
|
||||
{'name': translate("Exporter", 'columnMode'), 'type': 'list', 'values': ['(x,y) per plot', '(x,y,y,y) for all plots']}
|
||||
{'name': 'separator', 'title': translate("Exporter", 'separator'), 'type': 'list', 'value': 'comma', 'values': ['comma', 'tab']},
|
||||
{'name': 'precision', 'title': translate("Exporter", 'precision'), 'type': 'int', 'value': 10, 'limits': [0, None]},
|
||||
{'name': 'columnMode', 'title': translate("Exporter", 'columnMode'), 'type': 'list', 'values': ['(x,y) per plot', '(x,y,y,y) for all plots']}
|
||||
])
|
||||
|
||||
def parameters(self):
|
||||
@ -83,5 +83,3 @@ class CSVExporter(Exporter):
|
||||
|
||||
|
||||
CSVExporter.register()
|
||||
|
||||
|
||||
|
@ -16,15 +16,16 @@ __all__ = ['HDF5Exporter']
|
||||
|
||||
|
||||
class HDF5Exporter(Exporter):
|
||||
Name = translate("Exporter", "HDF5 Export: plot (x,y)")
|
||||
Name = "HDF5 Export: plot (x,y)"
|
||||
windows = []
|
||||
allowCopy = False
|
||||
|
||||
def __init__(self, item):
|
||||
Exporter.__init__(self, item)
|
||||
self.params = Parameter(name='params', type='group', children=[
|
||||
{'name': translate("Exporter", 'Name'), 'type': 'str', 'value': 'Export',},
|
||||
{'name': translate("Exporter", 'columnMode'), 'type': 'list', 'values': ['(x,y) per plot', '(x,y,y,y) for all plots']},
|
||||
{'name': 'Name', 'title': translate("Exporter", 'Name'), 'type': 'str', 'value': 'Export', },
|
||||
{'name': 'columnMode', 'title': translate("Exporter", 'columnMode'), 'type': 'list',
|
||||
'values': ['(x,y) per plot', '(x,y,y,y) for all plots']},
|
||||
])
|
||||
|
||||
def parameters(self):
|
||||
@ -41,11 +42,11 @@ class HDF5Exporter(Exporter):
|
||||
if fileName is None:
|
||||
self.fileSaveDialog(filter=["*.h5", "*.hdf", "*.hd5"])
|
||||
return
|
||||
dsname = self.params[translate("Exporter", 'Name')]
|
||||
fd = h5py.File(fileName, 'a') # forces append to file... 'w' doesn't seem to "delete/overwrite"
|
||||
dsname = self.params['Name']
|
||||
fd = h5py.File(fileName, 'a') # forces append to file... 'w' doesn't seem to "delete/overwrite"
|
||||
data = []
|
||||
|
||||
appendAllX = self.params[translate("Exporter", 'columnMode')] == '(x,y) per plot'
|
||||
appendAllX = self.params['columnMode'] == '(x,y) per plot'
|
||||
# Check if the arrays are ragged
|
||||
len_first = len(self.item.curves[0].getData()[0]) if self.item.curves[0] else None
|
||||
ragged = any(len(i.getData()[0]) != len_first for i in self.item.curves)
|
||||
|
@ -8,7 +8,7 @@ translate = QtCore.QCoreApplication.translate
|
||||
__all__ = ['ImageExporter']
|
||||
|
||||
class ImageExporter(Exporter):
|
||||
Name = f"{translate('Exporter', 'Image File')} (PNG, TIF, JPG, ...)"
|
||||
Name = "Image File (PNG, TIF, JPG, ...)"
|
||||
allowCopy = True
|
||||
|
||||
def __init__(self, item):
|
||||
@ -22,26 +22,28 @@ class ImageExporter(Exporter):
|
||||
bg = bgbrush.color()
|
||||
if bgbrush.style() == QtCore.Qt.NoBrush:
|
||||
bg.setAlpha(0)
|
||||
|
||||
|
||||
self.params = Parameter(name='params', type='group', children=[
|
||||
{'name': translate("Exporter", 'width'), 'type': 'int', 'value': int(tr.width()), 'limits': (0, None)},
|
||||
{'name': translate("Exporter", 'height'), 'type': 'int', 'value': int(tr.height()), 'limits': (0, None)},
|
||||
{'name': translate("Exporter", 'antialias'), 'type': 'bool', 'value': True},
|
||||
{'name': translate("Exporter", 'background'), 'type': 'color', 'value': bg},
|
||||
{'name': translate("Exporter", 'invertValue'), 'type': 'bool', 'value': False}
|
||||
{'name': 'width', 'title': translate("Exporter", 'width'), 'type': 'int', 'value': int(tr.width()),
|
||||
'limits': (0, None)},
|
||||
{'name': 'height', 'title': translate("Exporter", 'height'), 'type': 'int', 'value': int(tr.height()),
|
||||
'limits': (0, None)},
|
||||
{'name': 'antialias', 'title': translate("Exporter", 'antialias'), 'type': 'bool', 'value': True},
|
||||
{'name': 'background', 'title': translate("Exporter", 'background'), 'type': 'color', 'value': bg},
|
||||
{'name': 'invertValue', 'title': translate("Exporter", 'invertValue'), 'type': 'bool', 'value': False}
|
||||
])
|
||||
self.params.param(translate("Exporter", 'width')).sigValueChanged.connect(self.widthChanged)
|
||||
self.params.param(translate("Exporter", 'height')).sigValueChanged.connect(self.heightChanged)
|
||||
self.params.param('width').sigValueChanged.connect(self.widthChanged)
|
||||
self.params.param('height').sigValueChanged.connect(self.heightChanged)
|
||||
|
||||
def widthChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = float(sr.height()) / sr.width()
|
||||
self.params.param(translate("Exporter", 'height')).setValue(int(self.params[translate("Exporter", 'width')] * ar), blockSignal=self.heightChanged)
|
||||
self.params.param('height').setValue(int(self.params['width'] * ar), blockSignal=self.heightChanged)
|
||||
|
||||
def heightChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = float(sr.width()) / sr.height()
|
||||
self.params.param(translate("Exporter", 'width')).setValue(int(self.params[translate("Exporter", 'height')] * ar), blockSignal=self.widthChanged)
|
||||
self.params.param('width').setValue(int(self.params['height'] * ar), blockSignal=self.widthChanged)
|
||||
|
||||
def parameters(self):
|
||||
return self.params
|
||||
@ -62,8 +64,8 @@ class ImageExporter(Exporter):
|
||||
self.fileSaveDialog(filter=filter)
|
||||
return
|
||||
|
||||
w = int(self.params[translate("Exporter", 'width')])
|
||||
h = int(self.params[translate("Exporter", 'height')])
|
||||
w = int(self.params['width'])
|
||||
h = int(self.params['height'])
|
||||
if w == 0 or h == 0:
|
||||
raise Exception("Cannot export image with size=0 (requested "
|
||||
"export size is %dx%d)" % (w, h))
|
||||
@ -72,7 +74,7 @@ class ImageExporter(Exporter):
|
||||
sourceRect = self.getSourceRect()
|
||||
|
||||
bg = np.empty((h, w, 4), dtype=np.ubyte)
|
||||
color = self.params[translate("Exporter", 'background')]
|
||||
color = self.params['background']
|
||||
bg[:,:,0] = color.blue()
|
||||
bg[:,:,1] = color.green()
|
||||
bg[:,:,2] = color.red()
|
||||
@ -91,11 +93,11 @@ class ImageExporter(Exporter):
|
||||
#dtr = painter.deviceTransform()
|
||||
try:
|
||||
self.setExportMode(True, {
|
||||
'antialias': self.params[translate("Exporter", 'antialias')],
|
||||
'background': self.params[translate("Exporter", 'background')],
|
||||
'antialias': self.params['antialias'],
|
||||
'background': self.params['background'],
|
||||
'painter': painter,
|
||||
'resolutionScale': resolutionScale})
|
||||
painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params[translate("Exporter", 'antialias')])
|
||||
painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias'])
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
|
||||
finally:
|
||||
self.setExportMode(False)
|
||||
@ -114,5 +116,4 @@ class ImageExporter(Exporter):
|
||||
else:
|
||||
return self.png.save(fileName)
|
||||
|
||||
ImageExporter.register()
|
||||
|
||||
ImageExporter.register()
|
||||
|
@ -4,8 +4,6 @@ from .Exporter import Exporter
|
||||
from .. import PlotItem
|
||||
from .. import functions as fn
|
||||
|
||||
translate = QtCore.QCoreApplication.translate
|
||||
|
||||
__all__ = ['MatplotlibExporter']
|
||||
|
||||
"""
|
||||
@ -32,7 +30,7 @@ publication. Fonts are not vectorized (outlined), and window colors are white.
|
||||
"""
|
||||
|
||||
class MatplotlibExporter(Exporter):
|
||||
Name = translate('Exporter', "Matplotlib Window")
|
||||
Name = "Matplotlib Window"
|
||||
windows = []
|
||||
|
||||
def __init__(self, item):
|
||||
|
@ -14,8 +14,10 @@ class PrintExporter(Exporter):
|
||||
Exporter.__init__(self, item)
|
||||
tr = self.getTargetRect()
|
||||
self.params = Parameter(name='params', type='group', children=[
|
||||
{'name': translate("Exporter", 'width'), 'type': 'float', 'value': 0.1, 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
|
||||
{'name': translate("Exporter", 'height'), 'type': 'float', 'value': (0.1 * tr.height()) / tr.width(), 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
|
||||
{'name': 'width', 'title': translate("Exporter", 'width'), 'type': 'float', 'value': 0.1,
|
||||
'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
|
||||
{'name': 'height', 'title': translate("Exporter", 'height'), 'type': 'float',
|
||||
'value': (0.1 * tr.height()) / tr.width(), 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
|
||||
])
|
||||
self.params.param('width').sigValueChanged.connect(self.widthChanged)
|
||||
self.params.param('height').sigValueChanged.connect(self.heightChanged)
|
||||
@ -23,13 +25,13 @@ class PrintExporter(Exporter):
|
||||
def widthChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = sr.height() / sr.width()
|
||||
self.params.param(translate("Exporter", 'height')).setValue(self.params[translate("Exporter", 'width')] * ar, blockSignal=self.heightChanged)
|
||||
|
||||
self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
|
||||
|
||||
def heightChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = sr.width() / sr.height()
|
||||
self.params.param(translate("Exporter", 'width')).setValue(self.params[translate("Exporter", 'height')] * ar, blockSignal=self.widthChanged)
|
||||
|
||||
self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
|
||||
|
||||
def parameters(self):
|
||||
return self.params
|
||||
|
||||
|
@ -13,7 +13,7 @@ translate = QtCore.QCoreApplication.translate
|
||||
__all__ = ['SVGExporter']
|
||||
|
||||
class SVGExporter(Exporter):
|
||||
Name = translate("Exporter", "Scalable Vector Graphics (SVG)")
|
||||
Name = "Scalable Vector Graphics (SVG)"
|
||||
allowCopy=True
|
||||
|
||||
def __init__(self, item):
|
||||
@ -30,26 +30,28 @@ class SVGExporter(Exporter):
|
||||
bg.setAlpha(0)
|
||||
|
||||
self.params = Parameter(name='params', type='group', children=[
|
||||
{'name': translate("Exporter", 'background'), 'type': 'color', 'value': bg},
|
||||
{'name': translate("Exporter", 'width'), 'type': 'float', 'value': tr.width(), 'limits': (0, None)},
|
||||
{'name': translate("Exporter", 'height'), 'type': 'float', 'value': tr.height(), 'limits': (0, None)},
|
||||
{'name': 'background', 'title': translate("Exporter", 'background'), 'type': 'color', 'value': bg},
|
||||
{'name': 'width', 'title': translate("Exporter", 'width'), 'type': 'float', 'value': tr.width(),
|
||||
'limits': (0, None)},
|
||||
{'name': 'height', 'title': translate("Exporter", 'height'), 'type': 'float', 'value': tr.height(),
|
||||
'limits': (0, None)},
|
||||
#{'name': 'viewbox clipping', 'type': 'bool', 'value': True},
|
||||
#{'name': 'normalize coordinates', 'type': 'bool', 'value': True},
|
||||
{'name': translate("Exporter", 'scaling stroke'), 'type': 'bool', 'value': False, 'tip': "If False, strokes are non-scaling, "
|
||||
{'name': 'scaling stroke', 'title': translate("Exporter", 'scaling stroke'), 'type': 'bool', 'value': False, 'tip': "If False, strokes are non-scaling, "
|
||||
"which means that they appear the same width on screen regardless of how they are scaled or how the view is zoomed."},
|
||||
])
|
||||
self.params.param(translate("Exporter", 'width')).sigValueChanged.connect(self.widthChanged)
|
||||
self.params.param(translate("Exporter", 'height')).sigValueChanged.connect(self.heightChanged)
|
||||
self.params.param('width').sigValueChanged.connect(self.widthChanged)
|
||||
self.params.param('height').sigValueChanged.connect(self.heightChanged)
|
||||
|
||||
def widthChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = sr.height() / sr.width()
|
||||
self.params.param(translate("Exporter", 'height')).setValue(self.params[translate("Exporter", 'width')] * ar, blockSignal=self.heightChanged)
|
||||
self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
|
||||
|
||||
def heightChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = sr.width() / sr.height()
|
||||
self.params.param(translate("Exporter", 'width')).setValue(self.params[translate("Exporter", 'height')] * ar, blockSignal=self.widthChanged)
|
||||
self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
|
||||
|
||||
def parameters(self):
|
||||
return self.params
|
||||
@ -63,9 +65,9 @@ class SVGExporter(Exporter):
|
||||
## Instead, we will use Qt to generate SVG for each item independently,
|
||||
## then manually reconstruct the entire document.
|
||||
options = {ch.name():ch.value() for ch in self.params.children()}
|
||||
options['background'] = self.params[translate("Exporter", 'background')]
|
||||
options['width'] = self.params[translate("Exporter", 'width')]
|
||||
options['height'] = self.params[translate("Exporter", 'height')]
|
||||
options['background'] = self.params['background']
|
||||
options['width'] = self.params['width']
|
||||
options['height'] = self.params['height']
|
||||
xml = generateSvg(self.item, options)
|
||||
|
||||
if toBytes:
|
||||
@ -127,9 +129,9 @@ def _generateItemSvg(item, nodes=None, root=None, options={}):
|
||||
## 1) Qt SVG does not implement clipping paths. This is absurd.
|
||||
## The solution is to let Qt generate SVG for each item independently,
|
||||
## then glue them together manually with clipping.
|
||||
##
|
||||
##
|
||||
## The format Qt generates for all items looks like this:
|
||||
##
|
||||
##
|
||||
## <g>
|
||||
## <g transform="matrix(...)">
|
||||
## one or more of: <path/> or <polyline/> or <text/>
|
||||
@ -139,21 +141,21 @@ def _generateItemSvg(item, nodes=None, root=None, options={}):
|
||||
## </g>
|
||||
## . . .
|
||||
## </g>
|
||||
##
|
||||
##
|
||||
## 2) There seems to be wide disagreement over whether path strokes
|
||||
## should be scaled anisotropically.
|
||||
## should be scaled anisotropically.
|
||||
## see: http://web.mit.edu/jonas/www/anisotropy/
|
||||
## Given that both inkscape and illustrator seem to prefer isotropic
|
||||
## scaling, we will optimize for those cases.
|
||||
##
|
||||
## 3) Qt generates paths using non-scaling-stroke from SVG 1.2, but
|
||||
## inkscape only supports 1.1.
|
||||
##
|
||||
## scaling, we will optimize for those cases.
|
||||
##
|
||||
## 3) Qt generates paths using non-scaling-stroke from SVG 1.2, but
|
||||
## inkscape only supports 1.1.
|
||||
##
|
||||
## Both 2 and 3 can be addressed by drawing all items in world coordinates.
|
||||
|
||||
profiler = debug.Profiler()
|
||||
|
||||
if nodes is None: ## nodes maps all node IDs to their XML element.
|
||||
if nodes is None: ## nodes maps all node IDs to their XML element.
|
||||
## this allows us to ensure all elements receive unique names.
|
||||
nodes = {}
|
||||
|
||||
@ -424,7 +426,7 @@ def itemTransform(item, root):
|
||||
tr.translate(pos.x(), pos.y())
|
||||
tr = item.transform() * tr
|
||||
else:
|
||||
## find next parent that is either the root item or
|
||||
## find next parent that is either the root item or
|
||||
## an item that ignores its transformation
|
||||
nextRoot = item
|
||||
while True:
|
||||
|
Loading…
Reference in New Issue
Block a user