Commit b78662c3 authored by Luke Campagnola's avatar Luke Campagnola
Browse files

Minor updates for exporting

  - curves enable antialiasing when exporting to image
  - plotitems hide button during export
parent 7c94b5a7
......@@ -59,12 +59,12 @@ class GraphicsScene(QtGui.QGraphicsScene):
move in a drag.
"""
_addressCache = weakref.WeakValueDictionary()
sigMouseHover = QtCore.Signal(object) ## emits a list of objects hovered over
sigMouseMoved = QtCore.Signal(object) ## emits position of mouse on every move
sigMouseClicked = QtCore.Signal(object) ## emitted when MouseClickEvent is not accepted by any items under the click.
_addressCache = weakref.WeakValueDictionary()
ExportDirectory = None
@classmethod
......
......@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'exportDialogTemplate.ui'
#
# Created: Sat Mar 10 17:54:53 2012
# Created: Thu Mar 22 13:13:06 2012
# by: PyQt4 UI code generator 4.8.5
#
# WARNING! All changes made in this file will be lost!
......@@ -18,7 +18,7 @@ class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(241, 367)
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Export", None, QtGui.QApplication.UnicodeUTF8))
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
......
......@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>Export</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="spacing">
......
......@@ -75,8 +75,74 @@ class Exporter(object):
else:
return self.item.mapRectToDevice(self.item.boundingRect())
def setExportMode(self, export, opts=None):
"""
Call setExportMode(export, opts) on all items that will
be painted during the export. This informs the item
that it is about to be painted for export, allowing it to
alter its appearance temporarily
*export* - bool; must be True before exporting and False afterward
*opts* - dict; common parameters are 'antialias' and 'background'
"""
if opts is None:
opts = {}
for item in self.getPaintItems():
if hasattr(item, 'setExportMode'):
item.setExportMode(export, opts)
def getPaintItems(self, root=None):
"""Return a list of all items that should be painted in the correct order."""
if root is None:
root = self.item
preItems = []
postItems = []
if isinstance(root, QtGui.QGraphicsScene):
childs = [i for i in root.items() if i.parentItem() is None]
rootItem = []
else:
childs = root.childItems()
rootItem = [root]
childs.sort(lambda a,b: cmp(a.zValue(), b.zValue()))
while len(childs) > 0:
ch = childs.pop(0)
tree = self.getPaintItems(ch)
if int(ch.flags() & ch.ItemStacksBehindParent) > 0 or (ch.zValue() < 0 and int(ch.flags() & ch.ItemNegativeZStacksBehindParent) > 0):
preItems.extend(tree)
else:
postItems.extend(tree)
return preItems + rootItem + postItems
def render(self, painter, sourcRect, targetRect, item=None)
#if item is None:
#item = self.item
#preItems = []
#postItems = []
#if isinstance(item, QtGui.QGraphicsScene):
#childs = [i for i in item.items() if i.parentItem() is None]
#rootItem = []
#else:
#childs = item.childItems()
#rootItem = [item]
#childs.sort(lambda a,b: cmp(a.zValue(), b.zValue()))
#while len(childs) > 0:
#ch = childs.pop(0)
#if int(ch.flags() & ch.ItemStacksBehindParent) > 0 or (ch.zValue() < 0 and int(ch.flags() & ch.ItemNegativeZStacksBehindParent) > 0):
#preItems.extend(tree)
#else:
#postItems.extend(tree)
#for ch in preItems:
#self.render(painter, sourceRect, targetRect, item=ch)
### paint root here
#for ch in postItems:
#self.render(painter, sourceRect, targetRect, item=ch)
self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
#def writePs(self, fileName=None, item=None):
#if fileName is None:
......
......@@ -57,6 +57,12 @@ class ImageExporter(Exporter):
bg[:,:,3] = color.alpha()
self.png = pg.makeQImage(bg, alpha=True)
painter = QtGui.QPainter(self.png)
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
try:
self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background']})
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
finally:
self.setExportMode(False)
self.png.save(fileName)
painter.end()
\ No newline at end of file
painter.end()
\ No newline at end of file
from Exporter import Exporter
from pyqtgraph.parametertree import Parameter
from pyqtgraph.Qt import QtGui, QtCore, QtSvg
import re
#__all__ = ['PrintExporter']
__all__ = [] ## Printer is disabled for now--does not work very well.
class PrintExporter(Exporter):
Name = "Printer"
def __init__(self, item):
Exporter.__init__(self, item)
tr = self.getTargetRect()
self.params = Parameter(name='params', type='group', children=[
{'name': 'width', 'type': 'float', 'value': 0.1, 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
{'name': '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)
def widthChanged(self):
sr = self.getSourceRect()
ar = sr.height() / sr.width()
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('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
def parameters(self):
return self.params
def export(self, fileName=None):
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
dialog = QtGui.QPrintDialog(printer)
dialog.setWindowTitle("Print Document")
if dialog.exec_() != QtGui.QDialog.Accepted:
return;
#self.svg.setSize(QtCore.QSize(100,100))
#self.svg.setResolution(600)
res = printer.resolution()
rect = printer.pageRect()
center = rect.center()
h = self.params['height'] * res * 100. / 2.54
w = self.params['width'] * res * 100. / 2.54
x = center.x() - w/2.
y = center.y() - h/2.
targetRect = QtCore.QRect(x, y, w, h)
sourceRect = self.getSourceRect()
painter = QtGui.QPainter(printer)
try:
self.setExportMode(True)
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
finally:
self.setExportMode(False)
painter.end()
......@@ -42,7 +42,11 @@ class SVGExporter(Exporter):
targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
sourceRect = self.getSourceRect()
painter = QtGui.QPainter(self.svg)
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
try:
self.setExportMode(True)
self.render(painter, QtCore.QRectF(targetRect), sourceRect)
finally:
self.setExportMode(False)
painter.end()
## Workaround to set pen widths correctly
......
from SVGExporter import *
from ImageExporter import *
Exporters = [SVGExporter, ImageExporter]
Exporters = []
import os, sys
d = os.path.split(__file__)[0]
files = []
for f in os.listdir(d):
if os.path.isdir(os.path.join(d, f)):
files.append(f)
elif f[-3:] == '.py' and f not in ['__init__.py', 'Exporter.py']:
files.append(f[:-3])
for modName in files:
mod = __import__(modName, globals(), locals(), fromlist=['*'])
if hasattr(mod, '__all__'):
names = mod.__all__
else:
names = [n for n in dir(mod) if n[0] != '_']
for k in names:
if hasattr(mod, k):
Exporters.append(getattr(mod, k))
def listExporters():
return Exporters[:]
......
......@@ -261,6 +261,9 @@ class AxisItem(GraphicsWidget):
def drawPicture(self, p):
p.setRenderHint(p.Antialiasing, False)
p.setRenderHint(p.TextAntialiasing, True)
prof = debug.Profiler("AxisItem.paint", disabled=True)
p.setPen(self.pen)
......
......@@ -27,6 +27,8 @@ class PlotCurveItem(GraphicsObject):
self.clear()
self.path = None
self.fillPath = None
self.exportOpts = False
self.antialias = False
if y is not None:
self.updateData(y, x)
......@@ -364,6 +366,14 @@ class PlotCurveItem(GraphicsObject):
#pen.setColor(c)
##pen.setCosmetic(True)
if self.exportOpts is not False:
aa = self.exportOpts['antialias']
else:
aa = self.antialias
p.setRenderHint(p.Antialiasing, aa)
if sp is not None:
p.setPen(sp)
p.drawPath(path)
......@@ -410,7 +420,13 @@ class PlotCurveItem(GraphicsObject):
ev.accept()
self.sigClicked.emit(self)
def setExportMode(self, export, opts):
if export:
self.exportOpts = opts
if 'antialias' not in opts:
self.exportOpts['antialias'] = True
else:
self.exportOpts = False
class ROIPlotItem(PlotCurveItem):
"""Plot curve that monitors an ROI and image for changes to automatically replot."""
......
......@@ -64,6 +64,20 @@ class PlotItem(GraphicsWidget):
managers = {}
def __init__(self, parent=None, name=None, labels=None, title=None, **kargs):
"""
Create a new PlotItem. All arguments are optional.
Any extra keyword arguments are passed to PlotItem.plot().
Arguments:
*title* - Title to display at the top of the item. Html is allowed.
*labels* - A dictionary specifying the axis labels to display.
{'left': (args), 'bottom': (args), ...}
The name of each axis and the corresponding arguments are passed to PlotItem.setLabel()
Optionally, PlotItem my also be initialized with the keyword arguments left,
right, top, or bottom to achieve the same effect.
*name* - Registers a name for this view so that others may link to it
"""
GraphicsWidget.__init__(self, parent)
self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
......@@ -250,12 +264,16 @@ class PlotItem(GraphicsWidget):
#if name is not None:
#self.registerPlot(name)
if labels is not None:
for k in labels:
if isinstance(labels[k], basestring):
labels[k] = (labels[k],)
self.setLabel(k, *labels[k])
if labels is None:
labels = {}
for label in self.scales.keys():
if label in kargs:
labels[label] = kargs[label]
del kargs[label]
for k in labels:
if isinstance(labels[k], basestring):
labels[k] = (labels[k],)
self.setLabel(k, *labels[k])
if title is not None:
self.setTitle(title)
......@@ -263,7 +281,7 @@ class PlotItem(GraphicsWidget):
if len(kargs) > 0:
self.plot(**kargs)
self.enableAutoRange()
#self.enableAutoRange()
def implements(self, interface=None):
return interface in ['ViewBoxWrapper']
......@@ -365,6 +383,8 @@ class PlotItem(GraphicsWidget):
#print " Referrers are:", refs
#raise
def updateGrid(self, *args):
g = self.ctrl.gridGroup.isChecked()
if g:
......@@ -1313,18 +1333,24 @@ class PlotItem(GraphicsWidget):
return c
def saveSvgClicked(self):
self.writeSvg()
#def saveSvgClicked(self):
#self.writeSvg()
def saveSvgCurvesClicked(self):
self.writeSvgCurves()
#def saveSvgCurvesClicked(self):
#self.writeSvgCurves()
def saveImgClicked(self):
self.writeImage()
#def saveImgClicked(self):
#self.writeImage()
def saveCsvClicked(self):
self.writeCsv()
#def saveCsvClicked(self):
#self.writeCsv()
def setExportMode(self, export, opts):
if export:
self.autoBtn.hide()
else:
self.autoBtn.show()
#class PlotWidgetManager(QtCore.QObject):
......
......@@ -2,8 +2,8 @@
# Form implementation generated from reading ui file 'axisCtrlTemplate.ui'
#
# Created: Fri Jan 20 12:41:24 2012
# by: PyQt4 UI code generator 4.8.3
# Created: Thu Mar 22 13:13:14 2012
# by: PyQt4 UI code generator 4.8.5
#
# WARNING! All changes made in this file will be lost!
......@@ -19,41 +19,51 @@ class Ui_Form(object):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(182, 120)
Form.setMaximumSize(QtCore.QSize(200, 16777215))
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.mouseCheck = QtGui.QCheckBox(Form)
self.mouseCheck.setText(QtGui.QApplication.translate("Form", "Mouse Enabled", None, QtGui.QApplication.UnicodeUTF8))
self.mouseCheck.setChecked(True)
self.mouseCheck.setObjectName(_fromUtf8("mouseCheck"))
self.gridLayout.addWidget(self.mouseCheck, 0, 1, 1, 2)
self.manualRadio = QtGui.QRadioButton(Form)
self.manualRadio.setText(QtGui.QApplication.translate("Form", "Manual", None, QtGui.QApplication.UnicodeUTF8))
self.manualRadio.setObjectName(_fromUtf8("manualRadio"))
self.gridLayout.addWidget(self.manualRadio, 1, 0, 1, 1)
self.minText = QtGui.QLineEdit(Form)
self.minText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
self.minText.setObjectName(_fromUtf8("minText"))
self.gridLayout.addWidget(self.minText, 1, 1, 1, 1)
self.maxText = QtGui.QLineEdit(Form)
self.maxText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
self.maxText.setObjectName(_fromUtf8("maxText"))
self.gridLayout.addWidget(self.maxText, 1, 2, 1, 1)
self.autoRadio = QtGui.QRadioButton(Form)
self.autoRadio.setText(QtGui.QApplication.translate("Form", "Auto", None, QtGui.QApplication.UnicodeUTF8))
self.autoRadio.setChecked(True)
self.autoRadio.setObjectName(_fromUtf8("autoRadio"))
self.gridLayout.addWidget(self.autoRadio, 2, 0, 1, 1)
self.autoPercentSpin = QtGui.QSpinBox(Form)
self.autoPercentSpin.setEnabled(True)
self.autoPercentSpin.setSuffix(QtGui.QApplication.translate("Form", "%", None, QtGui.QApplication.UnicodeUTF8))
self.autoPercentSpin.setMinimum(1)
self.autoPercentSpin.setMaximum(100)
self.autoPercentSpin.setSingleStep(1)
self.autoPercentSpin.setProperty(_fromUtf8("value"), 100)
self.autoPercentSpin.setProperty("value", 100)
self.autoPercentSpin.setObjectName(_fromUtf8("autoPercentSpin"))
self.gridLayout.addWidget(self.autoPercentSpin, 2, 1, 1, 2)
self.autoPanCheck = QtGui.QCheckBox(Form)
self.autoPanCheck.setText(QtGui.QApplication.translate("Form", "Auto Pan Only", None, QtGui.QApplication.UnicodeUTF8))
self.autoPanCheck.setObjectName(_fromUtf8("autoPanCheck"))
self.gridLayout.addWidget(self.autoPanCheck, 3, 1, 1, 2)
self.linkCombo = QtGui.QComboBox(Form)
self.linkCombo.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
self.linkCombo.setObjectName(_fromUtf8("linkCombo"))
self.gridLayout.addWidget(self.linkCombo, 4, 1, 1, 2)
self.label = QtGui.QLabel(Form)
self.label.setText(QtGui.QApplication.translate("Form", "Link Axis:", None, QtGui.QApplication.UnicodeUTF8))
self.label.setObjectName(_fromUtf8("label"))
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
......@@ -61,13 +71,5 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.mouseCheck.setText(QtGui.QApplication.translate("Form", "Mouse Enabled", None, QtGui.QApplication.UnicodeUTF8))
self.manualRadio.setText(QtGui.QApplication.translate("Form", "Manual", None, QtGui.QApplication.UnicodeUTF8))
self.minText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
self.maxText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
self.autoRadio.setText(QtGui.QApplication.translate("Form", "Auto", None, QtGui.QApplication.UnicodeUTF8))
self.autoPercentSpin.setSuffix(QtGui.QApplication.translate("Form", "%", None, QtGui.QApplication.UnicodeUTF8))
self.autoPanCheck.setText(QtGui.QApplication.translate("Form", "Auto Pan Only", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Form", "Link Axis:", None, QtGui.QApplication.UnicodeUTF8))
pass
......@@ -94,7 +94,11 @@
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="linkCombo"/>
<widget class="QComboBox" name="linkCombo">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment