Commit 4464ca72 by devttys0

Added pyqtgraph into binwalk

parent cc7e4a64
...@@ -160,7 +160,16 @@ if "install" in sys.argv or "build" in sys.argv: ...@@ -160,7 +160,16 @@ if "install" in sys.argv or "build" in sys.argv:
fd.close() fd.close()
# The data files to install along with the module # The data files to install along with the module
install_data_files = ["magic/*", "config/*", "plugins/*", "modules/*", "core/*"] install_data_files = [os.path.join("pyqtgraph", "*.py")]
data_dirs = ["magic", "config", "plugins", "modules", "core"]
for data_dir in data_dirs:
install_data_files.append("%s%s*" % (data_dir, os.path.sep))
for (root, dirs, files) in os.walk(os.path.join(MODULE_NAME, "pyqtgraph")):
if dirs:
for directory in dirs:
install_data_files.append(os.path.join(os.path.sep.join(root.split(os.path.sep)[1:]), os.path.join(directory, "*.py")))
# Install the module, script, and support files # Install the module, script, and support files
setup(name = MODULE_NAME, setup(name = MODULE_NAME,
...@@ -169,7 +178,7 @@ setup(name = MODULE_NAME, ...@@ -169,7 +178,7 @@ setup(name = MODULE_NAME,
author = "Craig Heffner", author = "Craig Heffner",
url = "https://github.com/devttys0/%s" % MODULE_NAME, url = "https://github.com/devttys0/%s" % MODULE_NAME,
requires = ["magic", "pyqtgraph"], requires = [],
packages = [MODULE_NAME], packages = [MODULE_NAME],
package_data = {MODULE_NAME : install_data_files}, package_data = {MODULE_NAME : install_data_files},
scripts = [os.path.join("scripts", MODULE_NAME)], scripts = [os.path.join("scripts", MODULE_NAME)],
......
...@@ -48,8 +48,8 @@ class Plotter(Module): ...@@ -48,8 +48,8 @@ class Plotter(Module):
RESULT = None RESULT = None
def init(self): def init(self):
import pyqtgraph.opengl as gl import binwalk.pyqtgraph.opengl as gl
from pyqtgraph.Qt import QtGui from binwalk.pyqtgraph.Qt import QtGui
self.verbose = self.config.verbose self.verbose = self.config.verbose
self.offset = self.config.offset self.offset = self.config.offset
...@@ -190,7 +190,7 @@ class Plotter(Module): ...@@ -190,7 +190,7 @@ class Plotter(Module):
def _generate_plot(self, plot_points): def _generate_plot(self, plot_points):
import numpy as np import numpy as np
import pyqtgraph.opengl as gl import binwalk.pyqtgraph.opengl as gl
nitems = float(len(plot_points)) nitems = float(len(plot_points))
...@@ -230,7 +230,7 @@ class Plotter(Module): ...@@ -230,7 +230,7 @@ class Plotter(Module):
return scatter_plot return scatter_plot
def plot(self, wait=True): def plot(self, wait=True):
import pyqtgraph.opengl as gl import binwalk.pyqtgraph.opengl as gl
self.window.show() self.window.show()
...@@ -268,7 +268,7 @@ class Plotter(Module): ...@@ -268,7 +268,7 @@ class Plotter(Module):
self.wait() self.wait()
def wait(self): def wait(self):
from pyqtgraph.Qt import QtCore, QtGui from binwalk.pyqtgraph.Qt import QtCore, QtGui
t = QtCore.QTimer() t = QtCore.QTimer()
t.start(50) t.start(50)
......
...@@ -97,7 +97,7 @@ class Entropy(Module): ...@@ -97,7 +97,7 @@ class Entropy(Module):
self.footer() self.footer()
if self.do_plot and not self.save_plot: if self.do_plot and not self.save_plot:
from pyqtgraph.Qt import QtGui from binwalk.pyqtgraph.Qt import QtGui
QtGui.QApplication.instance().exec_() QtGui.QApplication.instance().exec_()
def calculate_file_entropy(self, fp): def calculate_file_entropy(self, fp):
...@@ -155,7 +155,7 @@ class Entropy(Module): ...@@ -155,7 +155,7 @@ class Entropy(Module):
def plot_entropy(self, fname): def plot_entropy(self, fname):
import numpy as np import numpy as np
import pyqtgraph as pg import binwalk.pyqtgraph as pg
i = 0 i = 0
x = [] x = []
......
from pyqtgraph.Qt import QtCore, QtGui, USE_PYSIDE
import pyqtgraph as pg
import pyqtgraph.exporters as exporters
if USE_PYSIDE:
from . import exportDialogTemplate_pyside as exportDialogTemplate
else:
from . import exportDialogTemplate_pyqt as exportDialogTemplate
class ExportDialog(QtGui.QWidget):
def __init__(self, scene):
QtGui.QWidget.__init__(self)
self.setVisible(False)
self.setWindowTitle("Export")
self.shown = False
self.currentExporter = None
self.scene = scene
self.selectBox = QtGui.QGraphicsRectItem()
self.selectBox.setPen(pg.mkPen('y', width=3, style=QtCore.Qt.DashLine))
self.selectBox.hide()
self.scene.addItem(self.selectBox)
self.ui = exportDialogTemplate.Ui_Form()
self.ui.setupUi(self)
self.ui.closeBtn.clicked.connect(self.close)
self.ui.exportBtn.clicked.connect(self.exportClicked)
self.ui.copyBtn.clicked.connect(self.copyClicked)
self.ui.itemTree.currentItemChanged.connect(self.exportItemChanged)
self.ui.formatList.currentItemChanged.connect(self.exportFormatChanged)
def show(self, item=None):
if item is not None:
## Select next exportable parent of the item originally clicked on
while not isinstance(item, pg.ViewBox) and not isinstance(item, pg.PlotItem) and item is not None:
item = item.parentItem()
## if this is a ViewBox inside a PlotItem, select the parent instead.
if isinstance(item, pg.ViewBox) and isinstance(item.parentItem(), pg.PlotItem):
item = item.parentItem()
self.updateItemList(select=item)
self.setVisible(True)
self.activateWindow()
self.raise_()
self.selectBox.setVisible(True)
if not self.shown:
self.shown = True
vcenter = self.scene.getViewWidget().geometry().center()
self.setGeometry(vcenter.x()-self.width()/2, vcenter.y()-self.height()/2, self.width(), self.height())
def updateItemList(self, select=None):
self.ui.itemTree.clear()
si = QtGui.QTreeWidgetItem(["Entire Scene"])
si.gitem = self.scene
self.ui.itemTree.addTopLevelItem(si)
self.ui.itemTree.setCurrentItem(si)
si.setExpanded(True)
for child in self.scene.items():
if child.parentItem() is None:
self.updateItemTree(child, si, select=select)
def updateItemTree(self, item, treeItem, select=None):
si = None
if isinstance(item, pg.ViewBox):
si = QtGui.QTreeWidgetItem(['ViewBox'])
elif isinstance(item, pg.PlotItem):
si = QtGui.QTreeWidgetItem(['Plot'])
if si is not None:
si.gitem = item
treeItem.addChild(si)
treeItem = si
if si.gitem is select:
self.ui.itemTree.setCurrentItem(si)
for ch in item.childItems():
self.updateItemTree(ch, treeItem, select=select)
def exportItemChanged(self, item, prev):
if item is None:
return
if item.gitem is self.scene:
newBounds = self.scene.views()[0].viewRect()
else:
newBounds = item.gitem.sceneBoundingRect()
self.selectBox.setRect(newBounds)
self.selectBox.show()
self.updateFormatList()
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)
gotCurrent = True
if not gotCurrent:
self.ui.formatList.setCurrentRow(0)
def exportFormatChanged(self, item, prev):
if item is None:
self.currentExporter = None
self.ui.paramTree.clear()
return
expClass = self.exporterClasses[str(item.text())]
exp = expClass(item=self.ui.itemTree.currentItem().gitem)
params = exp.parameters()
if params is None:
self.ui.paramTree.clear()
else:
self.ui.paramTree.setParameters(params)
self.currentExporter = exp
self.ui.copyBtn.setEnabled(exp.allowCopy)
def exportClicked(self):
self.selectBox.hide()
self.currentExporter.export()
def copyClicked(self):
self.selectBox.hide()
self.currentExporter.export(copy=True)
def close(self):
self.selectBox.setVisible(False)
self.setVisible(False)
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>241</width>
<height>367</height>
</rect>
</property>
<property name="windowTitle">
<string>Export</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>Item to export:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QTreeWidget" name="itemTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Export format</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QListWidget" name="formatList"/>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="exportBtn">
<property name="text">
<string>Export</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QPushButton" name="closeBtn">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="ParameterTree" name="paramTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Export options</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="copyBtn">
<property name="text">
<string>Copy</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ParameterTree</class>
<extends>QTreeWidget</extends>
<header>pyqtgraph.parametertree</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './GraphicsScene/exportDialogTemplate.ui'
#
# Created: Wed Jan 30 21:02:28 2013
# by: PyQt4 UI code generator 4.9.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(241, 367)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.label = QtGui.QLabel(Form)
self.label.setObjectName(_fromUtf8("label"))
self.gridLayout.addWidget(self.label, 0, 0, 1, 3)
self.itemTree = QtGui.QTreeWidget(Form)
self.itemTree.setObjectName(_fromUtf8("itemTree"))
self.itemTree.headerItem().setText(0, _fromUtf8("1"))
self.itemTree.header().setVisible(False)
self.gridLayout.addWidget(self.itemTree, 1, 0, 1, 3)
self.label_2 = QtGui.QLabel(Form)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 3)
self.formatList = QtGui.QListWidget(Form)
self.formatList.setObjectName(_fromUtf8("formatList"))
self.gridLayout.addWidget(self.formatList, 3, 0, 1, 3)
self.exportBtn = QtGui.QPushButton(Form)
self.exportBtn.setObjectName(_fromUtf8("exportBtn"))
self.gridLayout.addWidget(self.exportBtn, 6, 1, 1, 1)
self.closeBtn = QtGui.QPushButton(Form)
self.closeBtn.setObjectName(_fromUtf8("closeBtn"))
self.gridLayout.addWidget(self.closeBtn, 6, 2, 1, 1)
self.paramTree = ParameterTree(Form)
self.paramTree.setObjectName(_fromUtf8("paramTree"))
self.paramTree.headerItem().setText(0, _fromUtf8("1"))
self.paramTree.header().setVisible(False)
self.gridLayout.addWidget(self.paramTree, 5, 0, 1, 3)
self.label_3 = QtGui.QLabel(Form)
self.label_3.setObjectName(_fromUtf8("label_3"))
self.gridLayout.addWidget(self.label_3, 4, 0, 1, 3)
self.copyBtn = QtGui.QPushButton(Form)
self.copyBtn.setObjectName(_fromUtf8("copyBtn"))
self.gridLayout.addWidget(self.copyBtn, 6, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Export", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Form", "Item to export:", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("Form", "Export format", None, QtGui.QApplication.UnicodeUTF8))
self.exportBtn.setText(QtGui.QApplication.translate("Form", "Export", None, QtGui.QApplication.UnicodeUTF8))
self.closeBtn.setText(QtGui.QApplication.translate("Form", "Close", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("Form", "Export options", None, QtGui.QApplication.UnicodeUTF8))
self.copyBtn.setText(QtGui.QApplication.translate("Form", "Copy", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.parametertree import ParameterTree
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './GraphicsScene/exportDialogTemplate.ui'
#
# Created: Wed Jan 30 21:02:28 2013
# by: pyside-uic 0.2.13 running on PySide 1.1.1
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(241, 367)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName("gridLayout")
self.label = QtGui.QLabel(Form)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 3)
self.itemTree = QtGui.QTreeWidget(Form)
self.itemTree.setObjectName("itemTree")
self.itemTree.headerItem().setText(0, "1")
self.itemTree.header().setVisible(False)
self.gridLayout.addWidget(self.itemTree, 1, 0, 1, 3)
self.label_2 = QtGui.QLabel(Form)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 3)
self.formatList = QtGui.QListWidget(Form)
self.formatList.setObjectName("formatList")
self.gridLayout.addWidget(self.formatList, 3, 0, 1, 3)
self.exportBtn = QtGui.QPushButton(Form)
self.exportBtn.setObjectName("exportBtn")
self.gridLayout.addWidget(self.exportBtn, 6, 1, 1, 1)
self.closeBtn = QtGui.QPushButton(Form)
self.closeBtn.setObjectName("closeBtn")
self.gridLayout.addWidget(self.closeBtn, 6, 2, 1, 1)
self.paramTree = ParameterTree(Form)
self.paramTree.setObjectName("paramTree")
self.paramTree.headerItem().setText(0, "1")
self.paramTree.header().setVisible(False)
self.gridLayout.addWidget(self.paramTree, 5, 0, 1, 3)
self.label_3 = QtGui.QLabel(Form)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 4, 0, 1, 3)
self.copyBtn = QtGui.QPushButton(Form)
self.copyBtn.setObjectName("copyBtn")
self.gridLayout.addWidget(self.copyBtn, 6, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Export", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Form", "Item to export:", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("Form", "Export format", None, QtGui.QApplication.UnicodeUTF8))
self.exportBtn.setText(QtGui.QApplication.translate("Form", "Export", None, QtGui.QApplication.UnicodeUTF8))
self.closeBtn.setText(QtGui.QApplication.translate("Form", "Close", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("Form", "Export options", None, QtGui.QApplication.UnicodeUTF8))
self.copyBtn.setText(QtGui.QApplication.translate("Form", "Copy", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.parametertree import ParameterTree
The file Image.py is a drop-in replacement for the same file in PIL 1.1.6.
It adds support for reading 16-bit TIFF files and converting then to numpy arrays.
(I submitted the changes to the PIL folks long ago, but to my knowledge the code
is not being used by them.)
To use, copy this file into
/usr/lib/python2.6/dist-packages/PIL/
or
C:\Python26\lib\site-packages\PIL\
..or wherever your system keeps its python modules.
class PlotData(object):
"""
Class used for managing plot data
- allows data sharing between multiple graphics items (curve, scatter, graph..)
- each item may define the columns it needs
- column groupings ('pos' or x, y, z)
- efficiently appendable
- log, fft transformations
- color mode conversion (float/byte/qcolor)
- pen/brush conversion
- per-field cached masking
- allows multiple masking fields (different graphics need to mask on different criteria)
- removal of nan/inf values
- option for single value shared by entire column
- cached downsampling
- cached min / max / hasnan / isuniform
"""
def __init__(self):
self.fields = {}
self.maxVals = {} ## cache for max/min
self.minVals = {}
def addFields(self, **fields):
for f in fields:
if f not in self.fields:
self.fields[f] = None
def hasField(self, f):
return f in self.fields
def __getitem__(self, field):
return self.fields[field]
def __setitem__(self, field, val):
self.fields[field] = val
def max(self, field):
mx = self.maxVals.get(field, None)
if mx is None:
mx = np.max(self[field])
self.maxVals[field] = mx
return mx
def min(self, field):
mn = self.minVals.get(field, None)
if mn is None:
mn = np.min(self[field])
self.minVals[field] = mn
return mn
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Point.py - Extension of QPointF which adds a few missing methods.
Copyright 2010 Luke Campagnola
Distributed under MIT/X11 license. See license.txt for more infomation.
"""
from .Qt import QtCore
import numpy as np
def clip(x, mn, mx):
if x > mx:
return mx
if x < mn:
return mn
return x
class Point(QtCore.QPointF):
"""Extension of QPointF which adds a few missing methods."""
def __init__(self, *args):
if len(args) == 1:
if isinstance(args[0], QtCore.QSizeF):
QtCore.QPointF.__init__(self, float(args[0].width()), float(args[0].height()))
return
elif isinstance(args[0], float) or isinstance(args[0], int):
QtCore.QPointF.__init__(self, float(args[0]), float(args[0]))
return
elif hasattr(args[0], '__getitem__'):
QtCore.QPointF.__init__(self, float(args[0][0]), float(args[0][1]))
return
elif len(args) == 2:
QtCore.QPointF.__init__(self, args[0], args[1])
return
QtCore.QPointF.__init__(self, *args)
def __len__(self):
return 2
def __reduce__(self):
return (Point, (self.x(), self.y()))
def __getitem__(self, i):
if i == 0:
return self.x()
elif i == 1:
return self.y()
else:
raise IndexError("Point has no index %s" % str(i))
def __setitem__(self, i, x):
if i == 0:
return self.setX(x)
elif i == 1:
return self.setY(x)
else:
raise IndexError("Point has no index %s" % str(i))
def __radd__(self, a):
return self._math_('__radd__', a)
def __add__(self, a):
return self._math_('__add__', a)
def __rsub__(self, a):
return self._math_('__rsub__', a)
def __sub__(self, a):
return self._math_('__sub__', a)
def __rmul__(self, a):
return self._math_('__rmul__', a)
def __mul__(self, a):
return self._math_('__mul__', a)
def __rdiv__(self, a):
return self._math_('__rdiv__', a)
def __div__(self, a):
return self._math_('__div__', a)
def __truediv__(self, a):
return self._math_('__truediv__', a)
def __rtruediv__(self, a):
return self._math_('__rtruediv__', a)
def __rpow__(self, a):
return self._math_('__rpow__', a)
def __pow__(self, a):
return self._math_('__pow__', a)
def _math_(self, op, x):
#print "point math:", op
#try:
#fn = getattr(QtCore.QPointF, op)
#pt = fn(self, x)
#print fn, pt, self, x
#return Point(pt)
#except AttributeError:
x = Point(x)
return Point(getattr(self[0], op)(x[0]), getattr(self[1], op)(x[1]))
def length(self):
"""Returns the vector length of this Point."""
return (self[0]**2 + self[1]**2) ** 0.5
def norm(self):
"""Returns a vector in the same direction with unit length."""
return self / self.length()
def angle(self, a):
"""Returns the angle in degrees between this vector and the vector a."""
n1 = self.length()
n2 = a.length()
if n1 == 0. or n2 == 0.:
return None
## Probably this should be done with arctan2 instead..
ang = np.arccos(clip(self.dot(a) / (n1 * n2), -1.0, 1.0)) ### in radians
c = self.cross(a)
if c > 0:
ang *= -1.
return ang * 180. / np.pi
def dot(self, a):
"""Returns the dot product of a and this Point."""
a = Point(a)
return self[0]*a[0] + self[1]*a[1]
def cross(self, a):
a = Point(a)
return self[0]*a[1] - self[1]*a[0]
def proj(self, b):
"""Return the projection of this vector onto the vector b"""
b1 = b / b.length()
return self.dot(b1) * b1
def __repr__(self):
return "Point(%f, %f)" % (self[0], self[1])
def min(self):
return min(self[0], self[1])
def max(self):
return max(self[0], self[1])
def copy(self):
return Point(self)
def toQPoint(self):
return QtCore.QPoint(*self)
## Do all Qt imports from here to allow easier PyQt / PySide compatibility
import sys, re
## Automatically determine whether to use PyQt or PySide.
## This is done by first checking to see whether one of the libraries
## is already imported. If not, then attempt to import PyQt4, then PySide.
if 'PyQt4' in sys.modules:
USE_PYSIDE = False
elif 'PySide' in sys.modules:
USE_PYSIDE = True
else:
try:
import PyQt4
USE_PYSIDE = False
except ImportError:
try:
import PySide
USE_PYSIDE = True
except ImportError:
raise Exception("PyQtGraph requires either PyQt4 or PySide; neither package could be imported.")
if USE_PYSIDE:
from PySide import QtGui, QtCore, QtOpenGL, QtSvg
import PySide
VERSION_INFO = 'PySide ' + PySide.__version__
else:
from PyQt4 import QtGui, QtCore
try:
from PyQt4 import QtSvg
except ImportError:
pass
try:
from PyQt4 import QtOpenGL
except ImportError:
pass
QtCore.Signal = QtCore.pyqtSignal
VERSION_INFO = 'PyQt4 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
## Make sure we have Qt >= 4.7
versionReq = [4, 7]
QtVersion = PySide.QtCore.__version__ if USE_PYSIDE else QtCore.QT_VERSION_STR
m = re.match(r'(\d+)\.(\d+).*', QtVersion)
if m is not None and list(map(int, m.groups())) < versionReq:
print(map(int, m.groups()))
raise Exception('pyqtgraph requires Qt version >= %d.%d (your version is %s)' % (versionReq[0], versionReq[1], QtVersion))
# -*- coding: utf-8 -*-
from .Qt import QtCore, QtGui
from .Point import Point
import numpy as np
import pyqtgraph as pg
class SRTTransform(QtGui.QTransform):
"""Transform that can always be represented as a combination of 3 matrices: scale * rotate * translate
This transform has no shear; angles are always preserved.
"""
def __init__(self, init=None):
QtGui.QTransform.__init__(self)
self.reset()
if init is None:
return
elif isinstance(init, dict):
self.restoreState(init)
elif isinstance(init, SRTTransform):
self._state = {
'pos': Point(init._state['pos']),
'scale': Point(init._state['scale']),
'angle': init._state['angle']
}
self.update()
elif isinstance(init, QtGui.QTransform):
self.setFromQTransform(init)
elif isinstance(init, QtGui.QMatrix4x4):
self.setFromMatrix4x4(init)
else:
raise Exception("Cannot create SRTTransform from input type: %s" % str(type(init)))
def getScale(self):
return self._state['scale']
def getAngle(self):
## deprecated; for backward compatibility
return self.getRotation()
def getRotation(self):
return self._state['angle']
def getTranslation(self):
return self._state['pos']
def reset(self):
self._state = {
'pos': Point(0,0),
'scale': Point(1,1),
'angle': 0.0 ## in degrees
}
self.update()
def setFromQTransform(self, tr):
p1 = Point(tr.map(0., 0.))
p2 = Point(tr.map(1., 0.))
p3 = Point(tr.map(0., 1.))
dp2 = Point(p2-p1)
dp3 = Point(p3-p1)
## detect flipped axes
if dp2.angle(dp3) > 0:
#da = 180
da = 0
sy = -1.0
else:
da = 0
sy = 1.0
self._state = {
'pos': Point(p1),
'scale': Point(dp2.length(), dp3.length() * sy),
'angle': (np.arctan2(dp2[1], dp2[0]) * 180. / np.pi) + da
}
self.update()
def setFromMatrix4x4(self, m):
m = pg.SRTTransform3D(m)
angle, axis = m.getRotation()
if angle != 0 and (axis[0] != 0 or axis[1] != 0 or axis[2] != 1):
print("angle: %s axis: %s" % (str(angle), str(axis)))
raise Exception("Can only convert 4x4 matrix to 3x3 if rotation is around Z-axis.")
self._state = {
'pos': Point(m.getTranslation()),
'scale': Point(m.getScale()),
'angle': angle
}
self.update()
def translate(self, *args):
"""Acceptable arguments are:
x, y
[x, y]
Point(x,y)"""
t = Point(*args)
self.setTranslate(self._state['pos']+t)
def setTranslate(self, *args):
"""Acceptable arguments are:
x, y
[x, y]
Point(x,y)"""
self._state['pos'] = Point(*args)
self.update()
def scale(self, *args):
"""Acceptable arguments are:
x, y
[x, y]
Point(x,y)"""
s = Point(*args)
self.setScale(self._state['scale'] * s)
def setScale(self, *args):
"""Acceptable arguments are:
x, y
[x, y]
Point(x,y)"""
self._state['scale'] = Point(*args)
self.update()
def rotate(self, angle):
"""Rotate the transformation by angle (in degrees)"""
self.setRotate(self._state['angle'] + angle)
def setRotate(self, angle):
"""Set the transformation rotation to angle (in degrees)"""
self._state['angle'] = angle
self.update()
def __truediv__(self, t):
"""A / B == B^-1 * A"""
dt = t.inverted()[0] * self
return SRTTransform(dt)
def __div__(self, t):
return self.__truediv__(t)
def __mul__(self, t):
return SRTTransform(QtGui.QTransform.__mul__(self, t))
def saveState(self):
p = self._state['pos']
s = self._state['scale']
#if s[0] == 0:
#raise Exception('Invalid scale: %s' % str(s))
return {'pos': (p[0], p[1]), 'scale': (s[0], s[1]), 'angle': self._state['angle']}
def restoreState(self, state):
self._state['pos'] = Point(state.get('pos', (0,0)))
self._state['scale'] = Point(state.get('scale', (1.,1.)))
self._state['angle'] = state.get('angle', 0)
self.update()
def update(self):
QtGui.QTransform.reset(self)
## modifications to the transform are multiplied on the right, so we need to reverse order here.
QtGui.QTransform.translate(self, *self._state['pos'])
QtGui.QTransform.rotate(self, self._state['angle'])
QtGui.QTransform.scale(self, *self._state['scale'])
def __repr__(self):
return str(self.saveState())
def matrix(self):
return np.array([[self.m11(), self.m12(), self.m13()],[self.m21(), self.m22(), self.m23()],[self.m31(), self.m32(), self.m33()]])
if __name__ == '__main__':
from . import widgets
import GraphicsView
from .functions import *
app = QtGui.QApplication([])
win = QtGui.QMainWindow()
win.show()
cw = GraphicsView.GraphicsView()
#cw.enableMouse()
win.setCentralWidget(cw)
s = QtGui.QGraphicsScene()
cw.setScene(s)
win.resize(600,600)
cw.enableMouse()
cw.setRange(QtCore.QRectF(-100., -100., 200., 200.))
class Item(QtGui.QGraphicsItem):
def __init__(self):
QtGui.QGraphicsItem.__init__(self)
self.b = QtGui.QGraphicsRectItem(20, 20, 20, 20, self)
self.b.setPen(QtGui.QPen(mkPen('y')))
self.t1 = QtGui.QGraphicsTextItem(self)
self.t1.setHtml('<span style="color: #F00">R</span>')
self.t1.translate(20, 20)
self.l1 = QtGui.QGraphicsLineItem(10, 0, -10, 0, self)
self.l2 = QtGui.QGraphicsLineItem(0, 10, 0, -10, self)
self.l1.setPen(QtGui.QPen(mkPen('y')))
self.l2.setPen(QtGui.QPen(mkPen('y')))
def boundingRect(self):
return QtCore.QRectF()
def paint(self, *args):
pass
#s.addItem(b)
#s.addItem(t1)
item = Item()
s.addItem(item)
l1 = QtGui.QGraphicsLineItem(10, 0, -10, 0)
l2 = QtGui.QGraphicsLineItem(0, 10, 0, -10)
l1.setPen(QtGui.QPen(mkPen('r')))
l2.setPen(QtGui.QPen(mkPen('r')))
s.addItem(l1)
s.addItem(l2)
tr1 = SRTTransform()
tr2 = SRTTransform()
tr3 = QtGui.QTransform()
tr3.translate(20, 0)
tr3.rotate(45)
print("QTransform -> Transform:", SRTTransform(tr3))
print("tr1:", tr1)
tr2.translate(20, 0)
tr2.rotate(45)
print("tr2:", tr2)
dt = tr2/tr1
print("tr2 / tr1 = ", dt)
print("tr2 * tr1 = ", tr2*tr1)
tr4 = SRTTransform()
tr4.scale(-1, 1)
tr4.rotate(30)
print("tr1 * tr4 = ", tr1*tr4)
w1 = widgets.TestROI((19,19), (22, 22), invertible=True)
#w2 = widgets.TestROI((0,0), (150, 150))
w1.setZValue(10)
s.addItem(w1)
#s.addItem(w2)
w1Base = w1.getState()
#w2Base = w2.getState()
def update():
tr1 = w1.getGlobalTransform(w1Base)
#tr2 = w2.getGlobalTransform(w2Base)
item.setTransform(tr1)
#def update2():
#tr1 = w1.getGlobalTransform(w1Base)
#tr2 = w2.getGlobalTransform(w2Base)
#t1.setTransform(tr1)
#w1.setState(w1Base)
#w1.applyGlobalTransform(tr2)
w1.sigRegionChanged.connect(update)
#w2.sigRegionChanged.connect(update2)
\ No newline at end of file
# -*- coding: utf-8 -*-
from .Qt import QtCore
from .ptime import time
from . import ThreadsafeTimer
__all__ = ['SignalProxy']
class SignalProxy(QtCore.QObject):
"""Object which collects rapid-fire signals and condenses them
into a single signal or a rate-limited stream of signals.
Used, for example, to prevent a SpinBox from generating multiple
signals when the mouse wheel is rolled over it.
Emits sigDelayed after input signals have stopped for a certain period of time.
"""
sigDelayed = QtCore.Signal(object)
def __init__(self, signal, delay=0.3, rateLimit=0, slot=None):
"""Initialization arguments:
signal - a bound Signal or pyqtSignal instance
delay - Time (in seconds) to wait for signals to stop before emitting (default 0.3s)
slot - Optional function to connect sigDelayed to.
rateLimit - (signals/sec) if greater than 0, this allows signals to stream out at a
steady rate while they are being received.
"""
QtCore.QObject.__init__(self)
signal.connect(self.signalReceived)
self.signal = signal
self.delay = delay
self.rateLimit = rateLimit
self.args = None
self.timer = ThreadsafeTimer.ThreadsafeTimer()
self.timer.timeout.connect(self.flush)
self.block = False
self.slot = slot
self.lastFlushTime = None
if slot is not None:
self.sigDelayed.connect(slot)
def setDelay(self, delay):
self.delay = delay
def signalReceived(self, *args):
"""Received signal. Cancel previous timer and store args to be forwarded later."""
if self.block:
return
self.args = args
if self.rateLimit == 0:
self.timer.stop()
self.timer.start((self.delay*1000)+1)
else:
now = time()
if self.lastFlushTime is None:
leakTime = 0
else:
lastFlush = self.lastFlushTime
leakTime = max(0, (lastFlush + (1.0 / self.rateLimit)) - now)
self.timer.stop()
self.timer.start((min(leakTime, self.delay)*1000)+1)
def flush(self):
"""If there is a signal queued up, send it now."""
if self.args is None or self.block:
return False
#self.emit(self.signal, *self.args)
self.sigDelayed.emit(self.args)
self.args = None
self.timer.stop()
self.lastFlushTime = time()
return True
def disconnect(self):
self.block = True
try:
self.signal.disconnect(self.signalReceived)
except:
pass
try:
self.sigDelayed.disconnect(self.slot)
except:
pass
#def proxyConnect(source, signal, slot, delay=0.3):
#"""Connect a signal to a slot with delay. Returns the SignalProxy
#object that was created. Be sure to store this object so it is not
#garbage-collected immediately."""
#sp = SignalProxy(source, signal, delay)
#if source is None:
#sp.connect(sp, QtCore.SIGNAL('signal'), slot)
#else:
#sp.connect(sp, signal, slot)
#return sp
if __name__ == '__main__':
from .Qt import QtGui
app = QtGui.QApplication([])
win = QtGui.QMainWindow()
spin = QtGui.QSpinBox()
win.setCentralWidget(spin)
win.show()
def fn(*args):
print("Raw signal:", args)
def fn2(*args):
print("Delayed signal:", args)
spin.valueChanged.connect(fn)
#proxy = proxyConnect(spin, QtCore.SIGNAL('valueChanged(int)'), fn)
proxy = SignalProxy(spin.valueChanged, delay=0.5, slot=fn2)
\ No newline at end of file
from pyqtgraph.Qt import QtCore, QtGui
class ThreadsafeTimer(QtCore.QObject):
"""
Thread-safe replacement for QTimer.
"""
timeout = QtCore.Signal()
sigTimerStopRequested = QtCore.Signal()
sigTimerStartRequested = QtCore.Signal(object)
def __init__(self):
QtCore.QObject.__init__(self)
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.timerFinished)
self.timer.moveToThread(QtCore.QCoreApplication.instance().thread())
self.moveToThread(QtCore.QCoreApplication.instance().thread())
self.sigTimerStopRequested.connect(self.stop, QtCore.Qt.QueuedConnection)
self.sigTimerStartRequested.connect(self.start, QtCore.Qt.QueuedConnection)
def start(self, timeout):
isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
if isGuiThread:
#print "start timer", self, "from gui thread"
self.timer.start(timeout)
else:
#print "start timer", self, "from remote thread"
self.sigTimerStartRequested.emit(timeout)
def stop(self):
isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
if isGuiThread:
#print "stop timer", self, "from gui thread"
self.timer.stop()
else:
#print "stop timer", self, "from remote thread"
self.sigTimerStopRequested.emit()
def timerFinished(self):
self.timeout.emit()
\ No newline at end of file
# -*- coding: utf-8 -*-
from .Qt import QtCore, QtGui
import pyqtgraph as pg
import numpy as np
class Transform3D(QtGui.QMatrix4x4):
"""
Extension of QMatrix4x4 with some helpful methods added.
"""
def __init__(self, *args):
QtGui.QMatrix4x4.__init__(self, *args)
def matrix(self, nd=3):
if nd == 3:
return np.array(self.copyDataTo()).reshape(4,4)
elif nd == 2:
m = np.array(self.copyDataTo()).reshape(4,4)
m[2] = m[3]
m[:,2] = m[:,3]
return m[:3,:3]
else:
raise Exception("Argument 'nd' must be 2 or 3")
def map(self, obj):
"""
Extends QMatrix4x4.map() to allow mapping (3, ...) arrays of coordinates
"""
if isinstance(obj, np.ndarray) and obj.ndim >= 2 and obj.shape[0] in (2,3):
return pg.transformCoordinates(self, obj)
else:
return QtGui.QMatrix4x4.map(self, obj)
def inverted(self):
inv, b = QtGui.QMatrix4x4.inverted(self)
return Transform3D(inv), b
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Vector.py - Extension of QVector3D which adds a few missing methods.
Copyright 2010 Luke Campagnola
Distributed under MIT/X11 license. See license.txt for more infomation.
"""
from .Qt import QtGui, QtCore, USE_PYSIDE
import numpy as np
class Vector(QtGui.QVector3D):
"""Extension of QVector3D which adds a few helpful methods."""
def __init__(self, *args):
if len(args) == 1:
if isinstance(args[0], QtCore.QSizeF):
QtGui.QVector3D.__init__(self, float(args[0].width()), float(args[0].height()), 0)
return
elif isinstance(args[0], QtCore.QPoint) or isinstance(args[0], QtCore.QPointF):
QtGui.QVector3D.__init__(self, float(args[0].x()), float(args[0].y()), 0)
elif hasattr(args[0], '__getitem__'):
vals = list(args[0])
if len(vals) == 2:
vals.append(0)
if len(vals) != 3:
raise Exception('Cannot init Vector with sequence of length %d' % len(args[0]))
QtGui.QVector3D.__init__(self, *vals)
return
elif len(args) == 2:
QtGui.QVector3D.__init__(self, args[0], args[1], 0)
return
QtGui.QVector3D.__init__(self, *args)
def __len__(self):
return 3
def __add__(self, b):
# workaround for pyside bug. see https://bugs.launchpad.net/pyqtgraph/+bug/1223173
if USE_PYSIDE and isinstance(b, QtGui.QVector3D):
b = Vector(b)
return QtGui.QVector3D.__add__(self, b)
#def __reduce__(self):
#return (Point, (self.x(), self.y()))
def __getitem__(self, i):
if i == 0:
return self.x()
elif i == 1:
return self.y()
elif i == 2:
return self.z()
else:
raise IndexError("Point has no index %s" % str(i))
def __setitem__(self, i, x):
if i == 0:
return self.setX(x)
elif i == 1:
return self.setY(x)
elif i == 2:
return self.setZ(x)
else:
raise IndexError("Point has no index %s" % str(i))
def __iter__(self):
yield(self.x())
yield(self.y())
yield(self.z())
\ No newline at end of file
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
if not hasattr(QtCore, 'Signal'):
QtCore.Signal = QtCore.pyqtSignal
import weakref
class CanvasManager(QtCore.QObject):
SINGLETON = None
sigCanvasListChanged = QtCore.Signal()
def __init__(self):
if CanvasManager.SINGLETON is not None:
raise Exception("Can only create one canvas manager.")
CanvasManager.SINGLETON = self
QtCore.QObject.__init__(self)
self.canvases = weakref.WeakValueDictionary()
@classmethod
def instance(cls):
return CanvasManager.SINGLETON
def registerCanvas(self, canvas, name):
n2 = name
i = 0
while n2 in self.canvases:
n2 = "%s_%03d" % (name, i)
i += 1
self.canvases[n2] = canvas
self.sigCanvasListChanged.emit()
return n2
def unregisterCanvas(self, name):
c = self.canvases[name]
del self.canvases[name]
self.sigCanvasListChanged.emit()
def listCanvases(self):
return list(self.canvases.keys())
def getCanvas(self, name):
return self.canvases[name]
manager = CanvasManager()
class CanvasCombo(QtGui.QComboBox):
def __init__(self, parent=None):
QtGui.QComboBox.__init__(self, parent)
man = CanvasManager.instance()
man.sigCanvasListChanged.connect(self.updateCanvasList)
self.hostName = None
self.updateCanvasList()
def updateCanvasList(self):
canvases = CanvasManager.instance().listCanvases()
canvases.insert(0, "")
if self.hostName in canvases:
canvases.remove(self.hostName)
sel = self.currentText()
if sel in canvases:
self.blockSignals(True) ## change does not affect current selection; block signals during update
self.clear()
for i in canvases:
self.addItem(i)
if i == sel:
self.setCurrentIndex(self.count())
self.blockSignals(False)
def setHostName(self, name):
self.hostName = name
self.updateCanvasList()
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>490</width>
<height>414</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="GraphicsView" name="view"/>
<widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QPushButton" name="storeSvgBtn">
<property name="text">
<string>Store SVG</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="storePngBtn">
<property name="text">
<string>Store PNG</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="autoRangeBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Auto Range</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="redirectCheck">
<property name="toolTip">
<string>Check to display all local items in a remote canvas.</string>
</property>
<property name="text">
<string>Redirect</string>
</property>
</widget>
</item>
<item>
<widget class="CanvasCombo" name="redirectCombo"/>
</item>
</layout>
</item>
<item row="7" column="0" colspan="2">
<widget class="TreeWidget" name="itemList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>100</verstretch>
</sizepolicy>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="11" column="0" colspan="2">
<layout class="QGridLayout" name="ctrlLayout">
<property name="spacing">
<number>0</number>
</property>
</layout>
</item>
<item row="8" column="0">
<widget class="QPushButton" name="resetTransformsBtn">
<property name="text">
<string>Reset Transforms</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="mirrorSelectionBtn">
<property name="text">
<string>Mirror Selection</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="reflectSelectionBtn">
<property name="text">
<string>MirrorXY</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>TreeWidget</class>
<extends>QTreeWidget</extends>
<header>pyqtgraph.widgets.TreeWidget</header>
</customwidget>
<customwidget>
<class>GraphicsView</class>
<extends>QGraphicsView</extends>
<header>pyqtgraph.widgets.GraphicsView</header>
</customwidget>
<customwidget>
<class>CanvasCombo</class>
<extends>QComboBox</extends>
<header>CanvasManager</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './canvas/CanvasTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(490, 414)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setMargin(0)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.splitter = QtGui.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName(_fromUtf8("splitter"))
self.view = GraphicsView(self.splitter)
self.view.setObjectName(_fromUtf8("view"))
self.layoutWidget = QtGui.QWidget(self.splitter)
self.layoutWidget.setObjectName(_fromUtf8("layoutWidget"))
self.gridLayout_2 = QtGui.QGridLayout(self.layoutWidget)
self.gridLayout_2.setMargin(0)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.storeSvgBtn = QtGui.QPushButton(self.layoutWidget)
self.storeSvgBtn.setObjectName(_fromUtf8("storeSvgBtn"))
self.gridLayout_2.addWidget(self.storeSvgBtn, 1, 0, 1, 1)
self.storePngBtn = QtGui.QPushButton(self.layoutWidget)
self.storePngBtn.setObjectName(_fromUtf8("storePngBtn"))
self.gridLayout_2.addWidget(self.storePngBtn, 1, 1, 1, 1)
self.autoRangeBtn = QtGui.QPushButton(self.layoutWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(1)
sizePolicy.setHeightForWidth(self.autoRangeBtn.sizePolicy().hasHeightForWidth())
self.autoRangeBtn.setSizePolicy(sizePolicy)
self.autoRangeBtn.setObjectName(_fromUtf8("autoRangeBtn"))
self.gridLayout_2.addWidget(self.autoRangeBtn, 3, 0, 1, 2)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.redirectCheck = QtGui.QCheckBox(self.layoutWidget)
self.redirectCheck.setObjectName(_fromUtf8("redirectCheck"))
self.horizontalLayout.addWidget(self.redirectCheck)
self.redirectCombo = CanvasCombo(self.layoutWidget)
self.redirectCombo.setObjectName(_fromUtf8("redirectCombo"))
self.horizontalLayout.addWidget(self.redirectCombo)
self.gridLayout_2.addLayout(self.horizontalLayout, 6, 0, 1, 2)
self.itemList = TreeWidget(self.layoutWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(100)
sizePolicy.setHeightForWidth(self.itemList.sizePolicy().hasHeightForWidth())
self.itemList.setSizePolicy(sizePolicy)
self.itemList.setHeaderHidden(True)
self.itemList.setObjectName(_fromUtf8("itemList"))
self.itemList.headerItem().setText(0, _fromUtf8("1"))
self.gridLayout_2.addWidget(self.itemList, 7, 0, 1, 2)
self.ctrlLayout = QtGui.QGridLayout()
self.ctrlLayout.setSpacing(0)
self.ctrlLayout.setObjectName(_fromUtf8("ctrlLayout"))
self.gridLayout_2.addLayout(self.ctrlLayout, 11, 0, 1, 2)
self.resetTransformsBtn = QtGui.QPushButton(self.layoutWidget)
self.resetTransformsBtn.setObjectName(_fromUtf8("resetTransformsBtn"))
self.gridLayout_2.addWidget(self.resetTransformsBtn, 8, 0, 1, 1)
self.mirrorSelectionBtn = QtGui.QPushButton(self.layoutWidget)
self.mirrorSelectionBtn.setObjectName(_fromUtf8("mirrorSelectionBtn"))
self.gridLayout_2.addWidget(self.mirrorSelectionBtn, 4, 0, 1, 1)
self.reflectSelectionBtn = QtGui.QPushButton(self.layoutWidget)
self.reflectSelectionBtn.setObjectName(_fromUtf8("reflectSelectionBtn"))
self.gridLayout_2.addWidget(self.reflectSelectionBtn, 4, 1, 1, 1)
self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.storeSvgBtn.setText(QtGui.QApplication.translate("Form", "Store SVG", None, QtGui.QApplication.UnicodeUTF8))
self.storePngBtn.setText(QtGui.QApplication.translate("Form", "Store PNG", None, QtGui.QApplication.UnicodeUTF8))
self.autoRangeBtn.setText(QtGui.QApplication.translate("Form", "Auto Range", None, QtGui.QApplication.UnicodeUTF8))
self.redirectCheck.setToolTip(QtGui.QApplication.translate("Form", "Check to display all local items in a remote canvas.", None, QtGui.QApplication.UnicodeUTF8))
self.redirectCheck.setText(QtGui.QApplication.translate("Form", "Redirect", None, QtGui.QApplication.UnicodeUTF8))
self.resetTransformsBtn.setText(QtGui.QApplication.translate("Form", "Reset Transforms", None, QtGui.QApplication.UnicodeUTF8))
self.mirrorSelectionBtn.setText(QtGui.QApplication.translate("Form", "Mirror Selection", None, QtGui.QApplication.UnicodeUTF8))
self.reflectSelectionBtn.setText(QtGui.QApplication.translate("Form", "MirrorXY", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.GraphicsView import GraphicsView
from CanvasManager import CanvasCombo
from pyqtgraph.widgets.TreeWidget import TreeWidget
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './canvas/CanvasTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(490, 414)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName("gridLayout")
self.splitter = QtGui.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.view = GraphicsView(self.splitter)
self.view.setObjectName("view")
self.layoutWidget = QtGui.QWidget(self.splitter)
self.layoutWidget.setObjectName("layoutWidget")
self.gridLayout_2 = QtGui.QGridLayout(self.layoutWidget)
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
self.gridLayout_2.setObjectName("gridLayout_2")
self.storeSvgBtn = QtGui.QPushButton(self.layoutWidget)
self.storeSvgBtn.setObjectName("storeSvgBtn")
self.gridLayout_2.addWidget(self.storeSvgBtn, 1, 0, 1, 1)
self.storePngBtn = QtGui.QPushButton(self.layoutWidget)
self.storePngBtn.setObjectName("storePngBtn")
self.gridLayout_2.addWidget(self.storePngBtn, 1, 1, 1, 1)
self.autoRangeBtn = QtGui.QPushButton(self.layoutWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(1)
sizePolicy.setHeightForWidth(self.autoRangeBtn.sizePolicy().hasHeightForWidth())
self.autoRangeBtn.setSizePolicy(sizePolicy)
self.autoRangeBtn.setObjectName("autoRangeBtn")
self.gridLayout_2.addWidget(self.autoRangeBtn, 3, 0, 1, 2)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.redirectCheck = QtGui.QCheckBox(self.layoutWidget)
self.redirectCheck.setObjectName("redirectCheck")
self.horizontalLayout.addWidget(self.redirectCheck)
self.redirectCombo = CanvasCombo(self.layoutWidget)
self.redirectCombo.setObjectName("redirectCombo")
self.horizontalLayout.addWidget(self.redirectCombo)
self.gridLayout_2.addLayout(self.horizontalLayout, 6, 0, 1, 2)
self.itemList = TreeWidget(self.layoutWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(100)
sizePolicy.setHeightForWidth(self.itemList.sizePolicy().hasHeightForWidth())
self.itemList.setSizePolicy(sizePolicy)
self.itemList.setHeaderHidden(True)
self.itemList.setObjectName("itemList")
self.itemList.headerItem().setText(0, "1")
self.gridLayout_2.addWidget(self.itemList, 7, 0, 1, 2)
self.ctrlLayout = QtGui.QGridLayout()
self.ctrlLayout.setSpacing(0)
self.ctrlLayout.setObjectName("ctrlLayout")
self.gridLayout_2.addLayout(self.ctrlLayout, 11, 0, 1, 2)
self.resetTransformsBtn = QtGui.QPushButton(self.layoutWidget)
self.resetTransformsBtn.setObjectName("resetTransformsBtn")
self.gridLayout_2.addWidget(self.resetTransformsBtn, 8, 0, 1, 1)
self.mirrorSelectionBtn = QtGui.QPushButton(self.layoutWidget)
self.mirrorSelectionBtn.setObjectName("mirrorSelectionBtn")
self.gridLayout_2.addWidget(self.mirrorSelectionBtn, 4, 0, 1, 1)
self.reflectSelectionBtn = QtGui.QPushButton(self.layoutWidget)
self.reflectSelectionBtn.setObjectName("reflectSelectionBtn")
self.gridLayout_2.addWidget(self.reflectSelectionBtn, 4, 1, 1, 1)
self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.storeSvgBtn.setText(QtGui.QApplication.translate("Form", "Store SVG", None, QtGui.QApplication.UnicodeUTF8))
self.storePngBtn.setText(QtGui.QApplication.translate("Form", "Store PNG", None, QtGui.QApplication.UnicodeUTF8))
self.autoRangeBtn.setText(QtGui.QApplication.translate("Form", "Auto Range", None, QtGui.QApplication.UnicodeUTF8))
self.redirectCheck.setToolTip(QtGui.QApplication.translate("Form", "Check to display all local items in a remote canvas.", None, QtGui.QApplication.UnicodeUTF8))
self.redirectCheck.setText(QtGui.QApplication.translate("Form", "Redirect", None, QtGui.QApplication.UnicodeUTF8))
self.resetTransformsBtn.setText(QtGui.QApplication.translate("Form", "Reset Transforms", None, QtGui.QApplication.UnicodeUTF8))
self.mirrorSelectionBtn.setText(QtGui.QApplication.translate("Form", "Mirror Selection", None, QtGui.QApplication.UnicodeUTF8))
self.reflectSelectionBtn.setText(QtGui.QApplication.translate("Form", "MirrorXY", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.GraphicsView import GraphicsView
from CanvasManager import CanvasCombo
from pyqtgraph.widgets.TreeWidget import TreeWidget
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>224</width>
<height>117</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>1</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="translateLabel">
<property name="text">
<string>Translate:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rotateLabel">
<property name="text">
<string>Rotate:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="scaleLabel">
<property name="text">
<string>Scale:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="mirrorImageBtn">
<property name="toolTip">
<string extracomment="Mirror the item across the global Y axis"/>
</property>
<property name="text">
<string>Mirror</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="reflectImageBtn">
<property name="text">
<string>Reflect</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './canvas/TransformGuiTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(224, 117)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
Form.setSizePolicy(sizePolicy)
self.verticalLayout = QtGui.QVBoxLayout(Form)
self.verticalLayout.setSpacing(1)
self.verticalLayout.setMargin(0)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.translateLabel = QtGui.QLabel(Form)
self.translateLabel.setObjectName(_fromUtf8("translateLabel"))
self.verticalLayout.addWidget(self.translateLabel)
self.rotateLabel = QtGui.QLabel(Form)
self.rotateLabel.setObjectName(_fromUtf8("rotateLabel"))
self.verticalLayout.addWidget(self.rotateLabel)
self.scaleLabel = QtGui.QLabel(Form)
self.scaleLabel.setObjectName(_fromUtf8("scaleLabel"))
self.verticalLayout.addWidget(self.scaleLabel)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.mirrorImageBtn = QtGui.QPushButton(Form)
self.mirrorImageBtn.setToolTip(_fromUtf8(""))
self.mirrorImageBtn.setObjectName(_fromUtf8("mirrorImageBtn"))
self.horizontalLayout.addWidget(self.mirrorImageBtn)
self.reflectImageBtn = QtGui.QPushButton(Form)
self.reflectImageBtn.setObjectName(_fromUtf8("reflectImageBtn"))
self.horizontalLayout.addWidget(self.reflectImageBtn)
self.verticalLayout.addLayout(self.horizontalLayout)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.translateLabel.setText(QtGui.QApplication.translate("Form", "Translate:", None, QtGui.QApplication.UnicodeUTF8))
self.rotateLabel.setText(QtGui.QApplication.translate("Form", "Rotate:", None, QtGui.QApplication.UnicodeUTF8))
self.scaleLabel.setText(QtGui.QApplication.translate("Form", "Scale:", None, QtGui.QApplication.UnicodeUTF8))
self.mirrorImageBtn.setText(QtGui.QApplication.translate("Form", "Mirror", None, QtGui.QApplication.UnicodeUTF8))
self.reflectImageBtn.setText(QtGui.QApplication.translate("Form", "Reflect", None, QtGui.QApplication.UnicodeUTF8))
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './canvas/TransformGuiTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(224, 117)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
Form.setSizePolicy(sizePolicy)
self.verticalLayout = QtGui.QVBoxLayout(Form)
self.verticalLayout.setSpacing(1)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.translateLabel = QtGui.QLabel(Form)
self.translateLabel.setObjectName("translateLabel")
self.verticalLayout.addWidget(self.translateLabel)
self.rotateLabel = QtGui.QLabel(Form)
self.rotateLabel.setObjectName("rotateLabel")
self.verticalLayout.addWidget(self.rotateLabel)
self.scaleLabel = QtGui.QLabel(Form)
self.scaleLabel.setObjectName("scaleLabel")
self.verticalLayout.addWidget(self.scaleLabel)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.mirrorImageBtn = QtGui.QPushButton(Form)
self.mirrorImageBtn.setToolTip("")
self.mirrorImageBtn.setObjectName("mirrorImageBtn")
self.horizontalLayout.addWidget(self.mirrorImageBtn)
self.reflectImageBtn = QtGui.QPushButton(Form)
self.reflectImageBtn.setObjectName("reflectImageBtn")
self.horizontalLayout.addWidget(self.reflectImageBtn)
self.verticalLayout.addLayout(self.horizontalLayout)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.translateLabel.setText(QtGui.QApplication.translate("Form", "Translate:", None, QtGui.QApplication.UnicodeUTF8))
self.rotateLabel.setText(QtGui.QApplication.translate("Form", "Rotate:", None, QtGui.QApplication.UnicodeUTF8))
self.scaleLabel.setText(QtGui.QApplication.translate("Form", "Scale:", None, QtGui.QApplication.UnicodeUTF8))
self.mirrorImageBtn.setText(QtGui.QApplication.translate("Form", "Mirror", None, QtGui.QApplication.UnicodeUTF8))
self.reflectImageBtn.setText(QtGui.QApplication.translate("Form", "Reflect", None, QtGui.QApplication.UnicodeUTF8))
# -*- coding: utf-8 -*-
from .Canvas import *
from .CanvasItem import *
\ No newline at end of file
import numpy as np
import scipy.interpolate
from pyqtgraph.Qt import QtGui, QtCore
class ColorMap(object):
"""
A ColorMap defines a relationship between a scalar value and a range of colors.
ColorMaps are commonly used for false-coloring monochromatic images, coloring
scatter-plot points, and coloring surface plots by height.
Each color map is defined by a set of colors, each corresponding to a
particular scalar value. For example:
| 0.0 -> black
| 0.2 -> red
| 0.6 -> yellow
| 1.0 -> white
The colors for intermediate values are determined by interpolating between
the two nearest colors in either RGB or HSV color space.
To provide user-defined color mappings, see :class:`GradientWidget <pyqtgraph.GradientWidget>`.
"""
## color interpolation modes
RGB = 1
HSV_POS = 2
HSV_NEG = 3
## boundary modes
CLIP = 1
REPEAT = 2
MIRROR = 3
## return types
BYTE = 1
FLOAT = 2
QCOLOR = 3
enumMap = {
'rgb': RGB,
'hsv+': HSV_POS,
'hsv-': HSV_NEG,
'clip': CLIP,
'repeat': REPEAT,
'mirror': MIRROR,
'byte': BYTE,
'float': FLOAT,
'qcolor': QCOLOR,
}
def __init__(self, pos, color, mode=None):
"""
========= ==============================================================
Arguments
pos Array of positions where each color is defined
color Array of RGBA colors.
Integer data types are interpreted as 0-255; float data types
are interpreted as 0.0-1.0
mode Array of color modes (ColorMap.RGB, HSV_POS, or HSV_NEG)
indicating the color space that should be used when
interpolating between stops. Note that the last mode value is
ignored. By default, the mode is entirely RGB.
========= ==============================================================
"""
self.pos = pos
self.color = color
if mode is None:
mode = np.ones(len(pos))
self.mode = mode
self.stopsCache = {}
def map(self, data, mode='byte'):
"""
Return an array of colors corresponding to the values in *data*.
Data must be either a scalar position or an array (any shape) of positions.
The *mode* argument determines the type of data returned:
=========== ===============================================================
byte (default) Values are returned as 0-255 unsigned bytes.
float Values are returned as 0.0-1.0 floats.
qcolor Values are returned as an array of QColor objects.
=========== ===============================================================
"""
if isinstance(mode, basestring):
mode = self.enumMap[mode.lower()]
if mode == self.QCOLOR:
pos, color = self.getStops(self.BYTE)
else:
pos, color = self.getStops(mode)
data = np.clip(data, pos.min(), pos.max())
if not isinstance(data, np.ndarray):
interp = scipy.interpolate.griddata(pos, color, np.array([data]))[0]
else:
interp = scipy.interpolate.griddata(pos, color, data)
if mode == self.QCOLOR:
if not isinstance(data, np.ndarray):
return QtGui.QColor(*interp)
else:
return [QtGui.QColor(*x) for x in interp]
else:
return interp
def mapToQColor(self, data):
"""Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`."""
return self.map(data, mode=self.QCOLOR)
def mapToByte(self, data):
"""Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`."""
return self.map(data, mode=self.BYTE)
def mapToFloat(self, data):
"""Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`."""
return self.map(data, mode=self.FLOAT)
def getGradient(self, p1=None, p2=None):
"""Return a QLinearGradient object spanning from QPoints p1 to p2."""
if p1 == None:
p1 = QtCore.QPointF(0,0)
if p2 == None:
p2 = QtCore.QPointF(self.pos.max()-self.pos.min(),0)
g = QtGui.QLinearGradient(p1, p2)
pos, color = self.getStops(mode=self.BYTE)
color = [QtGui.QColor(*x) for x in color]
g.setStops(zip(pos, color))
#if self.colorMode == 'rgb':
#ticks = self.listTicks()
#g.setStops([(x, QtGui.QColor(t.color)) for t,x in ticks])
#elif self.colorMode == 'hsv': ## HSV mode is approximated for display by interpolating 10 points between each stop
#ticks = self.listTicks()
#stops = []
#stops.append((ticks[0][1], ticks[0][0].color))
#for i in range(1,len(ticks)):
#x1 = ticks[i-1][1]
#x2 = ticks[i][1]
#dx = (x2-x1) / 10.
#for j in range(1,10):
#x = x1 + dx*j
#stops.append((x, self.getColor(x)))
#stops.append((x2, self.getColor(x2)))
#g.setStops(stops)
return g
def getColors(self, mode=None):
"""Return list of all color stops converted to the specified mode.
If mode is None, then no conversion is done."""
if isinstance(mode, basestring):
mode = self.enumMap[mode.lower()]
color = self.color
if mode in [self.BYTE, self.QCOLOR] and color.dtype.kind == 'f':
color = (color * 255).astype(np.ubyte)
elif mode == self.FLOAT and color.dtype.kind != 'f':
color = color.astype(float) / 255.
if mode == self.QCOLOR:
color = [QtGui.QColor(*x) for x in color]
return color
def getStops(self, mode):
## Get fully-expanded set of RGBA stops in either float or byte mode.
if mode not in self.stopsCache:
color = self.color
if mode == self.BYTE and color.dtype.kind == 'f':
color = (color * 255).astype(np.ubyte)
elif mode == self.FLOAT and color.dtype.kind != 'f':
color = color.astype(float) / 255.
## to support HSV mode, we need to do a little more work..
#stops = []
#for i in range(len(self.pos)):
#pos = self.pos[i]
#color = color[i]
#imode = self.mode[i]
#if imode == self.RGB:
#stops.append((x,color))
#else:
#ns =
self.stopsCache[mode] = (self.pos, color)
return self.stopsCache[mode]
def getLookupTable(self, start=0.0, stop=1.0, nPts=512, alpha=None, mode='byte'):
"""
Return an RGB(A) lookup table (ndarray).
============= ============================================================================
**Arguments**
start The starting value in the lookup table (default=0.0)
stop The final value in the lookup table (default=1.0)
nPts The number of points in the returned lookup table.
alpha True, False, or None - Specifies whether or not alpha values are included
in the table. If alpha is None, it will be automatically determined.
mode Determines return type: 'byte' (0-255), 'float' (0.0-1.0), or 'qcolor'.
See :func:`map() <pyqtgraph.ColorMap.map>`.
============= ============================================================================
"""
if isinstance(mode, basestring):
mode = self.enumMap[mode.lower()]
if alpha is None:
alpha = self.usesAlpha()
x = np.linspace(start, stop, nPts)
table = self.map(x, mode)
if not alpha:
return table[:,:3]
else:
return table
def usesAlpha(self):
"""Return True if any stops have an alpha < 255"""
max = 1.0 if self.color.dtype.kind == 'f' else 255
return np.any(self.color[:,3] != max)
def isMapTrivial(self):
"""
Return True if the gradient has exactly two stops in it: black at 0.0 and white at 1.0.
"""
if len(self.pos) != 2:
return False
if self.pos[0] != 0.0 or self.pos[1] != 1.0:
return False
if self.color.dtype.kind == 'f':
return np.all(self.color == np.array([[0.,0.,0.,1.], [1.,1.,1.,1.]]))
else:
return np.all(self.color == np.array([[0,0,0,255], [255,255,255,255]]))
# -*- coding: utf-8 -*-
"""
configfile.py - Human-readable text configuration file library
Copyright 2010 Luke Campagnola
Distributed under MIT/X11 license. See license.txt for more infomation.
Used for reading and writing dictionary objects to a python-like configuration
file format. Data structures may be nested and contain any data type as long
as it can be converted to/from a string using repr and eval.
"""
import re, os, sys
from .pgcollections import OrderedDict
GLOBAL_PATH = None # so not thread safe.
from . import units
from .python2_3 import asUnicode
class ParseError(Exception):
def __init__(self, message, lineNum, line, fileName=None):
self.lineNum = lineNum
self.line = line
#self.message = message
self.fileName = fileName
Exception.__init__(self, message)
def __str__(self):
if self.fileName is None:
msg = "Error parsing string at line %d:\n" % self.lineNum
else:
msg = "Error parsing config file '%s' at line %d:\n" % (self.fileName, self.lineNum)
msg += "%s\n%s" % (self.line, self.message)
return msg
#raise Exception()
def writeConfigFile(data, fname):
s = genString(data)
fd = open(fname, 'w')
fd.write(s)
fd.close()
def readConfigFile(fname):
#cwd = os.getcwd()
global GLOBAL_PATH
if GLOBAL_PATH is not None:
fname2 = os.path.join(GLOBAL_PATH, fname)
if os.path.exists(fname2):
fname = fname2
GLOBAL_PATH = os.path.dirname(os.path.abspath(fname))
try:
#os.chdir(newDir) ## bad.
fd = open(fname)
s = asUnicode(fd.read())
fd.close()
s = s.replace("\r\n", "\n")
s = s.replace("\r", "\n")
data = parseString(s)[1]
except ParseError:
sys.exc_info()[1].fileName = fname
raise
except:
print("Error while reading config file %s:"% fname)
raise
#finally:
#os.chdir(cwd)
return data
def appendConfigFile(data, fname):
s = genString(data)
fd = open(fname, 'a')
fd.write(s)
fd.close()
def genString(data, indent=''):
s = ''
for k in data:
sk = str(k)
if len(sk) == 0:
print(data)
raise Exception('blank dict keys not allowed (see data above)')
if sk[0] == ' ' or ':' in sk:
print(data)
raise Exception('dict keys must not contain ":" or start with spaces [offending key is "%s"]' % sk)
if isinstance(data[k], dict):
s += indent + sk + ':\n'
s += genString(data[k], indent + ' ')
else:
s += indent + sk + ': ' + repr(data[k]) + '\n'
return s
def parseString(lines, start=0):
data = OrderedDict()
if isinstance(lines, basestring):
lines = lines.split('\n')
lines = [l for l in lines if re.search(r'\S', l) and not re.match(r'\s*#', l)] ## remove empty lines
indent = measureIndent(lines[start])
ln = start - 1
try:
while True:
ln += 1
#print ln
if ln >= len(lines):
break
l = lines[ln]
## Skip blank lines or lines starting with #
if re.match(r'\s*#', l) or not re.search(r'\S', l):
continue
## Measure line indentation, make sure it is correct for this level
lineInd = measureIndent(l)
if lineInd < indent:
ln -= 1
break
if lineInd > indent:
#print lineInd, indent
raise ParseError('Indentation is incorrect. Expected %d, got %d' % (indent, lineInd), ln+1, l)
if ':' not in l:
raise ParseError('Missing colon', ln+1, l)
(k, p, v) = l.partition(':')
k = k.strip()
v = v.strip()
## set up local variables to use for eval
local = units.allUnits.copy()
local['OrderedDict'] = OrderedDict
local['readConfigFile'] = readConfigFile
if len(k) < 1:
raise ParseError('Missing name preceding colon', ln+1, l)
if k[0] == '(' and k[-1] == ')': ## If the key looks like a tuple, try evaluating it.
try:
k1 = eval(k, local)
if type(k1) is tuple:
k = k1
except:
pass
if re.search(r'\S', v) and v[0] != '#': ## eval the value
try:
val = eval(v, local)
except:
ex = sys.exc_info()[1]
raise ParseError("Error evaluating expression '%s': [%s: %s]" % (v, ex.__class__.__name__, str(ex)), (ln+1), l)
else:
if ln+1 >= len(lines) or measureIndent(lines[ln+1]) <= indent:
#print "blank dict"
val = {}
else:
#print "Going deeper..", ln+1
(ln, val) = parseString(lines, start=ln+1)
data[k] = val
#print k, repr(val)
except ParseError:
raise
except:
ex = sys.exc_info()[1]
raise ParseError("%s: %s" % (ex.__class__.__name__, str(ex)), ln+1, l)
#print "Returning shallower..", ln+1
return (ln, data)
def measureIndent(s):
n = 0
while n < len(s) and s[n] == ' ':
n += 1
return n
if __name__ == '__main__':
import tempfile
fn = tempfile.mktemp()
tf = open(fn, 'w')
cf = """
key: 'value'
key2: ##comment
##comment
key21: 'value' ## comment
##comment
key22: [1,2,3]
key23: 234 #comment
"""
tf.write(cf)
tf.close()
print("=== Test:===")
num = 1
for line in cf.split('\n'):
print("%02d %s" % (num, line))
num += 1
print(cf)
print("============")
data = readConfigFile(fn)
print(data)
os.remove(fn)
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.python2_3 import asUnicode
class CmdInput(QtGui.QLineEdit):
sigExecuteCmd = QtCore.Signal(object)
def __init__(self, parent):
QtGui.QLineEdit.__init__(self, parent)
self.history = [""]
self.ptr = 0
#self.lastCmd = None
#self.setMultiline(False)
def keyPressEvent(self, ev):
#print "press:", ev.key(), QtCore.Qt.Key_Up, QtCore.Qt.Key_Down, QtCore.Qt.Key_Enter
if ev.key() == QtCore.Qt.Key_Up and self.ptr < len(self.history) - 1:
self.setHistory(self.ptr+1)
ev.accept()
return
elif ev.key() == QtCore.Qt.Key_Down and self.ptr > 0:
self.setHistory(self.ptr-1)
ev.accept()
return
elif ev.key() == QtCore.Qt.Key_Return:
self.execCmd()
else:
QtGui.QLineEdit.keyPressEvent(self, ev)
self.history[0] = asUnicode(self.text())
def execCmd(self):
cmd = asUnicode(self.text())
if len(self.history) == 1 or cmd != self.history[1]:
self.history.insert(1, cmd)
#self.lastCmd = cmd
self.history[0] = ""
self.setHistory(0)
self.sigExecuteCmd.emit(cmd)
def setHistory(self, num):
self.ptr = num
self.setText(self.history[self.ptr])
#def setMultiline(self, m):
#height = QtGui.QFontMetrics(self.font()).lineSpacing()
#if m:
#self.setFixedHeight(height*5)
#else:
#self.setFixedHeight(height+15)
#self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
#self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
#def sizeHint(self):
#hint = QtGui.QPlainTextEdit.sizeHint(self)
#height = QtGui.QFontMetrics(self.font()).lineSpacing()
#hint.setHeight(height)
#return hint
\ No newline at end of file
from .Console import ConsoleWidget
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>710</width>
<height>497</height>
</rect>
</property>
<property name="windowTitle">
<string>Console</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPlainTextEdit" name="output">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="CmdInput" name="input"/>
</item>
<item>
<widget class="QPushButton" name="historyBtn">
<property name="text">
<string>History..</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="exceptionBtn">
<property name="text">
<string>Exceptions..</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QListWidget" name="historyList">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
</widget>
<widget class="QGroupBox" name="exceptionGroup">
<property name="title">
<string>Exception Handling</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="1">
<widget class="QPushButton" name="catchAllExceptionsBtn">
<property name="text">
<string>Show All Exceptions</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="catchNextExceptionBtn">
<property name="text">
<string>Show Next Exception</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="onlyUncaughtCheck">
<property name="text">
<string>Only Uncaught Exceptions</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="5">
<widget class="QListWidget" name="exceptionStackList">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="5">
<widget class="QCheckBox" name="runSelectedFrameCheck">
<property name="text">
<string>Run commands in selected stack frame</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="5">
<widget class="QLabel" name="exceptionInfoLabel">
<property name="text">
<string>Exception Info</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="clearExceptionBtn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Clear Exception</string>
</property>
</widget>
</item>
<item row="0" column="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CmdInput</class>
<extends>QLineEdit</extends>
<header>.CmdInput</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './console/template.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(710, 497)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setMargin(0)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.splitter = QtGui.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Vertical)
self.splitter.setObjectName(_fromUtf8("splitter"))
self.layoutWidget = QtGui.QWidget(self.splitter)
self.layoutWidget.setObjectName(_fromUtf8("layoutWidget"))
self.verticalLayout = QtGui.QVBoxLayout(self.layoutWidget)
self.verticalLayout.setMargin(0)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.output = QtGui.QPlainTextEdit(self.layoutWidget)
font = QtGui.QFont()
font.setFamily(_fromUtf8("Monospace"))
self.output.setFont(font)
self.output.setReadOnly(True)
self.output.setObjectName(_fromUtf8("output"))
self.verticalLayout.addWidget(self.output)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.input = CmdInput(self.layoutWidget)
self.input.setObjectName(_fromUtf8("input"))
self.horizontalLayout.addWidget(self.input)
self.historyBtn = QtGui.QPushButton(self.layoutWidget)
self.historyBtn.setCheckable(True)
self.historyBtn.setObjectName(_fromUtf8("historyBtn"))
self.horizontalLayout.addWidget(self.historyBtn)
self.exceptionBtn = QtGui.QPushButton(self.layoutWidget)
self.exceptionBtn.setCheckable(True)
self.exceptionBtn.setObjectName(_fromUtf8("exceptionBtn"))
self.horizontalLayout.addWidget(self.exceptionBtn)
self.verticalLayout.addLayout(self.horizontalLayout)
self.historyList = QtGui.QListWidget(self.splitter)
font = QtGui.QFont()
font.setFamily(_fromUtf8("Monospace"))
self.historyList.setFont(font)
self.historyList.setObjectName(_fromUtf8("historyList"))
self.exceptionGroup = QtGui.QGroupBox(self.splitter)
self.exceptionGroup.setObjectName(_fromUtf8("exceptionGroup"))
self.gridLayout_2 = QtGui.QGridLayout(self.exceptionGroup)
self.gridLayout_2.setSpacing(0)
self.gridLayout_2.setContentsMargins(-1, 0, -1, 0)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.catchAllExceptionsBtn = QtGui.QPushButton(self.exceptionGroup)
self.catchAllExceptionsBtn.setCheckable(True)
self.catchAllExceptionsBtn.setObjectName(_fromUtf8("catchAllExceptionsBtn"))
self.gridLayout_2.addWidget(self.catchAllExceptionsBtn, 0, 1, 1, 1)
self.catchNextExceptionBtn = QtGui.QPushButton(self.exceptionGroup)
self.catchNextExceptionBtn.setCheckable(True)
self.catchNextExceptionBtn.setObjectName(_fromUtf8("catchNextExceptionBtn"))
self.gridLayout_2.addWidget(self.catchNextExceptionBtn, 0, 0, 1, 1)
self.onlyUncaughtCheck = QtGui.QCheckBox(self.exceptionGroup)
self.onlyUncaughtCheck.setChecked(True)
self.onlyUncaughtCheck.setObjectName(_fromUtf8("onlyUncaughtCheck"))
self.gridLayout_2.addWidget(self.onlyUncaughtCheck, 0, 2, 1, 1)
self.exceptionStackList = QtGui.QListWidget(self.exceptionGroup)
self.exceptionStackList.setAlternatingRowColors(True)
self.exceptionStackList.setObjectName(_fromUtf8("exceptionStackList"))
self.gridLayout_2.addWidget(self.exceptionStackList, 2, 0, 1, 5)
self.runSelectedFrameCheck = QtGui.QCheckBox(self.exceptionGroup)
self.runSelectedFrameCheck.setChecked(True)
self.runSelectedFrameCheck.setObjectName(_fromUtf8("runSelectedFrameCheck"))
self.gridLayout_2.addWidget(self.runSelectedFrameCheck, 3, 0, 1, 5)
self.exceptionInfoLabel = QtGui.QLabel(self.exceptionGroup)
self.exceptionInfoLabel.setObjectName(_fromUtf8("exceptionInfoLabel"))
self.gridLayout_2.addWidget(self.exceptionInfoLabel, 1, 0, 1, 5)
self.clearExceptionBtn = QtGui.QPushButton(self.exceptionGroup)
self.clearExceptionBtn.setEnabled(False)
self.clearExceptionBtn.setObjectName(_fromUtf8("clearExceptionBtn"))
self.gridLayout_2.addWidget(self.clearExceptionBtn, 0, 4, 1, 1)
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout_2.addItem(spacerItem, 0, 3, 1, 1)
self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Console", None, QtGui.QApplication.UnicodeUTF8))
self.historyBtn.setText(QtGui.QApplication.translate("Form", "History..", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionBtn.setText(QtGui.QApplication.translate("Form", "Exceptions..", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionGroup.setTitle(QtGui.QApplication.translate("Form", "Exception Handling", None, QtGui.QApplication.UnicodeUTF8))
self.catchAllExceptionsBtn.setText(QtGui.QApplication.translate("Form", "Show All Exceptions", None, QtGui.QApplication.UnicodeUTF8))
self.catchNextExceptionBtn.setText(QtGui.QApplication.translate("Form", "Show Next Exception", None, QtGui.QApplication.UnicodeUTF8))
self.onlyUncaughtCheck.setText(QtGui.QApplication.translate("Form", "Only Uncaught Exceptions", None, QtGui.QApplication.UnicodeUTF8))
self.runSelectedFrameCheck.setText(QtGui.QApplication.translate("Form", "Run commands in selected stack frame", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionInfoLabel.setText(QtGui.QApplication.translate("Form", "Exception Info", None, QtGui.QApplication.UnicodeUTF8))
self.clearExceptionBtn.setText(QtGui.QApplication.translate("Form", "Clear Exception", None, QtGui.QApplication.UnicodeUTF8))
from .CmdInput import CmdInput
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './console/template.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(710, 497)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName("gridLayout")
self.splitter = QtGui.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Vertical)
self.splitter.setObjectName("splitter")
self.layoutWidget = QtGui.QWidget(self.splitter)
self.layoutWidget.setObjectName("layoutWidget")
self.verticalLayout = QtGui.QVBoxLayout(self.layoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.output = QtGui.QPlainTextEdit(self.layoutWidget)
font = QtGui.QFont()
font.setFamily("Monospace")
self.output.setFont(font)
self.output.setReadOnly(True)
self.output.setObjectName("output")
self.verticalLayout.addWidget(self.output)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.input = CmdInput(self.layoutWidget)
self.input.setObjectName("input")
self.horizontalLayout.addWidget(self.input)
self.historyBtn = QtGui.QPushButton(self.layoutWidget)
self.historyBtn.setCheckable(True)
self.historyBtn.setObjectName("historyBtn")
self.horizontalLayout.addWidget(self.historyBtn)
self.exceptionBtn = QtGui.QPushButton(self.layoutWidget)
self.exceptionBtn.setCheckable(True)
self.exceptionBtn.setObjectName("exceptionBtn")
self.horizontalLayout.addWidget(self.exceptionBtn)
self.verticalLayout.addLayout(self.horizontalLayout)
self.historyList = QtGui.QListWidget(self.splitter)
font = QtGui.QFont()
font.setFamily("Monospace")
self.historyList.setFont(font)
self.historyList.setObjectName("historyList")
self.exceptionGroup = QtGui.QGroupBox(self.splitter)
self.exceptionGroup.setObjectName("exceptionGroup")
self.gridLayout_2 = QtGui.QGridLayout(self.exceptionGroup)
self.gridLayout_2.setSpacing(0)
self.gridLayout_2.setContentsMargins(-1, 0, -1, 0)
self.gridLayout_2.setObjectName("gridLayout_2")
self.catchAllExceptionsBtn = QtGui.QPushButton(self.exceptionGroup)
self.catchAllExceptionsBtn.setCheckable(True)
self.catchAllExceptionsBtn.setObjectName("catchAllExceptionsBtn")
self.gridLayout_2.addWidget(self.catchAllExceptionsBtn, 0, 1, 1, 1)
self.catchNextExceptionBtn = QtGui.QPushButton(self.exceptionGroup)
self.catchNextExceptionBtn.setCheckable(True)
self.catchNextExceptionBtn.setObjectName("catchNextExceptionBtn")
self.gridLayout_2.addWidget(self.catchNextExceptionBtn, 0, 0, 1, 1)
self.onlyUncaughtCheck = QtGui.QCheckBox(self.exceptionGroup)
self.onlyUncaughtCheck.setChecked(True)
self.onlyUncaughtCheck.setObjectName("onlyUncaughtCheck")
self.gridLayout_2.addWidget(self.onlyUncaughtCheck, 0, 2, 1, 1)
self.exceptionStackList = QtGui.QListWidget(self.exceptionGroup)
self.exceptionStackList.setAlternatingRowColors(True)
self.exceptionStackList.setObjectName("exceptionStackList")
self.gridLayout_2.addWidget(self.exceptionStackList, 2, 0, 1, 5)
self.runSelectedFrameCheck = QtGui.QCheckBox(self.exceptionGroup)
self.runSelectedFrameCheck.setChecked(True)
self.runSelectedFrameCheck.setObjectName("runSelectedFrameCheck")
self.gridLayout_2.addWidget(self.runSelectedFrameCheck, 3, 0, 1, 5)
self.exceptionInfoLabel = QtGui.QLabel(self.exceptionGroup)
self.exceptionInfoLabel.setObjectName("exceptionInfoLabel")
self.gridLayout_2.addWidget(self.exceptionInfoLabel, 1, 0, 1, 5)
self.clearExceptionBtn = QtGui.QPushButton(self.exceptionGroup)
self.clearExceptionBtn.setEnabled(False)
self.clearExceptionBtn.setObjectName("clearExceptionBtn")
self.gridLayout_2.addWidget(self.clearExceptionBtn, 0, 4, 1, 1)
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout_2.addItem(spacerItem, 0, 3, 1, 1)
self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Console", None, QtGui.QApplication.UnicodeUTF8))
self.historyBtn.setText(QtGui.QApplication.translate("Form", "History..", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionBtn.setText(QtGui.QApplication.translate("Form", "Exceptions..", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionGroup.setTitle(QtGui.QApplication.translate("Form", "Exception Handling", None, QtGui.QApplication.UnicodeUTF8))
self.catchAllExceptionsBtn.setText(QtGui.QApplication.translate("Form", "Show All Exceptions", None, QtGui.QApplication.UnicodeUTF8))
self.catchNextExceptionBtn.setText(QtGui.QApplication.translate("Form", "Show Next Exception", None, QtGui.QApplication.UnicodeUTF8))
self.onlyUncaughtCheck.setText(QtGui.QApplication.translate("Form", "Only Uncaught Exceptions", None, QtGui.QApplication.UnicodeUTF8))
self.runSelectedFrameCheck.setText(QtGui.QApplication.translate("Form", "Run commands in selected stack frame", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionInfoLabel.setText(QtGui.QApplication.translate("Form", "Exception Info", None, QtGui.QApplication.UnicodeUTF8))
self.clearExceptionBtn.setText(QtGui.QApplication.translate("Form", "Clear Exception", None, QtGui.QApplication.UnicodeUTF8))
from .CmdInput import CmdInput
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
import weakref
class Container(object):
#sigStretchChanged = QtCore.Signal() ## can't do this here; not a QObject.
def __init__(self, area):
object.__init__(self)
self.area = area
self._container = None
self._stretch = (10, 10)
self.stretches = weakref.WeakKeyDictionary()
def container(self):
return self._container
def containerChanged(self, c):
self._container = c
def type(self):
return None
def insert(self, new, pos=None, neighbor=None):
if not isinstance(new, list):
new = [new]
if neighbor is None:
if pos == 'before':
index = 0
else:
index = self.count()
else:
index = self.indexOf(neighbor)
if index == -1:
index = 0
if pos == 'after':
index += 1
for n in new:
#print "change container", n, " -> ", self
n.containerChanged(self)
#print "insert", n, " -> ", self, index
self._insertItem(n, index)
index += 1
n.sigStretchChanged.connect(self.childStretchChanged)
#print "child added", self
self.updateStretch()
def apoptose(self, propagate=True):
##if there is only one (or zero) item in this container, disappear.
cont = self._container
c = self.count()
if c > 1:
return
if self.count() == 1: ## if there is one item, give it to the parent container (unless this is the top)
if self is self.area.topContainer:
return
self.container().insert(self.widget(0), 'before', self)
#print "apoptose:", self
self.close()
if propagate and cont is not None:
cont.apoptose()
def close(self):
self.area = None
self._container = None
self.setParent(None)
def childEvent(self, ev):
ch = ev.child()
if ev.removed() and hasattr(ch, 'sigStretchChanged'):
#print "Child", ev.child(), "removed, updating", self
try:
ch.sigStretchChanged.disconnect(self.childStretchChanged)
except:
pass
self.updateStretch()
def childStretchChanged(self):
#print "child", QtCore.QObject.sender(self), "changed shape, updating", self
self.updateStretch()
def setStretch(self, x=None, y=None):
#print "setStretch", self, x, y
self._stretch = (x, y)
self.sigStretchChanged.emit()
def updateStretch(self):
###Set the stretch values for this container to reflect its contents
pass
def stretch(self):
"""Return the stretch factors for this container"""
return self._stretch
class SplitContainer(Container, QtGui.QSplitter):
"""Horizontal or vertical splitter with some changes:
- save/restore works correctly
"""
sigStretchChanged = QtCore.Signal()
def __init__(self, area, orientation):
QtGui.QSplitter.__init__(self)
self.setOrientation(orientation)
Container.__init__(self, area)
#self.splitterMoved.connect(self.restretchChildren)
def _insertItem(self, item, index):
self.insertWidget(index, item)
item.show() ## need to show since it may have been previously hidden by tab
def saveState(self):
sizes = self.sizes()
if all([x == 0 for x in sizes]):
sizes = [10] * len(sizes)
return {'sizes': sizes}
def restoreState(self, state):
sizes = state['sizes']
self.setSizes(sizes)
for i in range(len(sizes)):
self.setStretchFactor(i, sizes[i])
def childEvent(self, ev):
QtGui.QSplitter.childEvent(self, ev)
Container.childEvent(self, ev)
#def restretchChildren(self):
#sizes = self.sizes()
#tot = sum(sizes)
class HContainer(SplitContainer):
def __init__(self, area):
SplitContainer.__init__(self, area, QtCore.Qt.Horizontal)
def type(self):
return 'horizontal'
def updateStretch(self):
##Set the stretch values for this container to reflect its contents
#print "updateStretch", self
x = 0
y = 0
sizes = []
for i in range(self.count()):
wx, wy = self.widget(i).stretch()
x += wx
y = max(y, wy)
sizes.append(wx)
#print " child", self.widget(i), wx, wy
self.setStretch(x, y)
#print sizes
tot = float(sum(sizes))
if tot == 0:
scale = 1.0
else:
scale = self.width() / tot
self.setSizes([int(s*scale) for s in sizes])
class VContainer(SplitContainer):
def __init__(self, area):
SplitContainer.__init__(self, area, QtCore.Qt.Vertical)
def type(self):
return 'vertical'
def updateStretch(self):
##Set the stretch values for this container to reflect its contents
#print "updateStretch", self
x = 0
y = 0
sizes = []
for i in range(self.count()):
wx, wy = self.widget(i).stretch()
y += wy
x = max(x, wx)
sizes.append(wy)
#print " child", self.widget(i), wx, wy
self.setStretch(x, y)
#print sizes
tot = float(sum(sizes))
if tot == 0:
scale = 1.0
else:
scale = self.height() / tot
self.setSizes([int(s*scale) for s in sizes])
class TContainer(Container, QtGui.QWidget):
sigStretchChanged = QtCore.Signal()
def __init__(self, area):
QtGui.QWidget.__init__(self)
Container.__init__(self, area)
self.layout = QtGui.QGridLayout()
self.layout.setSpacing(0)
self.layout.setContentsMargins(0,0,0,0)
self.setLayout(self.layout)
self.hTabLayout = QtGui.QHBoxLayout()
self.hTabBox = QtGui.QWidget()
self.hTabBox.setLayout(self.hTabLayout)
self.hTabLayout.setSpacing(2)
self.hTabLayout.setContentsMargins(0,0,0,0)
self.layout.addWidget(self.hTabBox, 0, 1)
self.stack = QtGui.QStackedWidget()
self.layout.addWidget(self.stack, 1, 1)
self.stack.childEvent = self.stackChildEvent
self.setLayout(self.layout)
for n in ['count', 'widget', 'indexOf']:
setattr(self, n, getattr(self.stack, n))
def _insertItem(self, item, index):
if not isinstance(item, Dock.Dock):
raise Exception("Tab containers may hold only docks, not other containers.")
self.stack.insertWidget(index, item)
self.hTabLayout.insertWidget(index, item.label)
#QtCore.QObject.connect(item.label, QtCore.SIGNAL('clicked'), self.tabClicked)
item.label.sigClicked.connect(self.tabClicked)
self.tabClicked(item.label)
def tabClicked(self, tab, ev=None):
if ev is None or ev.button() == QtCore.Qt.LeftButton:
for i in range(self.count()):
w = self.widget(i)
if w is tab.dock:
w.label.setDim(False)
self.stack.setCurrentIndex(i)
else:
w.label.setDim(True)
def type(self):
return 'tab'
def saveState(self):
return {'index': self.stack.currentIndex()}
def restoreState(self, state):
self.stack.setCurrentIndex(state['index'])
def updateStretch(self):
##Set the stretch values for this container to reflect its contents
x = 0
y = 0
for i in range(self.count()):
wx, wy = self.widget(i).stretch()
x = max(x, wx)
y = max(y, wy)
self.setStretch(x, y)
def stackChildEvent(self, ev):
QtGui.QStackedWidget.childEvent(self.stack, ev)
Container.childEvent(self, ev)
from . import Dock
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
class DockDrop(object):
"""Provides dock-dropping methods"""
def __init__(self, allowedAreas=None):
object.__init__(self)
if allowedAreas is None:
allowedAreas = ['center', 'right', 'left', 'top', 'bottom']
self.allowedAreas = set(allowedAreas)
self.setAcceptDrops(True)
self.dropArea = None
self.overlay = DropAreaOverlay(self)
self.overlay.raise_()
def resizeOverlay(self, size):
self.overlay.resize(size)
def raiseOverlay(self):
self.overlay.raise_()
def dragEnterEvent(self, ev):
src = ev.source()
if hasattr(src, 'implements') and src.implements('dock'):
#print "drag enter accept"
ev.accept()
else:
#print "drag enter ignore"
ev.ignore()
def dragMoveEvent(self, ev):
#print "drag move"
ld = ev.pos().x()
rd = self.width() - ld
td = ev.pos().y()
bd = self.height() - td
mn = min(ld, rd, td, bd)
if mn > 30:
self.dropArea = "center"
elif (ld == mn or td == mn) and mn > self.height()/3.:
self.dropArea = "center"
elif (rd == mn or ld == mn) and mn > self.width()/3.:
self.dropArea = "center"
elif rd == mn:
self.dropArea = "right"
elif ld == mn:
self.dropArea = "left"
elif td == mn:
self.dropArea = "top"
elif bd == mn:
self.dropArea = "bottom"
if ev.source() is self and self.dropArea == 'center':
#print " no self-center"
self.dropArea = None
ev.ignore()
elif self.dropArea not in self.allowedAreas:
#print " not allowed"
self.dropArea = None
ev.ignore()
else:
#print " ok"
ev.accept()
self.overlay.setDropArea(self.dropArea)
def dragLeaveEvent(self, ev):
self.dropArea = None
self.overlay.setDropArea(self.dropArea)
def dropEvent(self, ev):
area = self.dropArea
if area is None:
return
if area == 'center':
area = 'above'
self.area.moveDock(ev.source(), area, self)
self.dropArea = None
self.overlay.setDropArea(self.dropArea)
class DropAreaOverlay(QtGui.QWidget):
"""Overlay widget that draws drop areas during a drag-drop operation"""
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
self.dropArea = None
self.hide()
self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
def setDropArea(self, area):
self.dropArea = area
if area is None:
self.hide()
else:
## Resize overlay to just the region where drop area should be displayed.
## This works around a Qt bug--can't display transparent widgets over QGLWidget
prgn = self.parent().rect()
rgn = QtCore.QRect(prgn)
w = min(30, prgn.width()/3.)
h = min(30, prgn.height()/3.)
if self.dropArea == 'left':
rgn.setWidth(w)
elif self.dropArea == 'right':
rgn.setLeft(rgn.left() + prgn.width() - w)
elif self.dropArea == 'top':
rgn.setHeight(h)
elif self.dropArea == 'bottom':
rgn.setTop(rgn.top() + prgn.height() - h)
elif self.dropArea == 'center':
rgn.adjust(w, h, -w, -h)
self.setGeometry(rgn)
self.show()
self.update()
def paintEvent(self, ev):
if self.dropArea is None:
return
p = QtGui.QPainter(self)
rgn = self.rect()
p.setBrush(QtGui.QBrush(QtGui.QColor(100, 100, 255, 50)))
p.setPen(QtGui.QPen(QtGui.QColor(50, 50, 150), 3))
p.drawRect(rgn)
from .DockArea import DockArea
from .Dock import Dock
\ No newline at end of file
# -*- coding: utf-8 -*-
"""This module installs a wrapper around sys.excepthook which allows multiple
new exception handlers to be registered.
Optionally, the wrapper also stops exceptions from causing long-term storage
of local stack frames. This has two major effects:
- Unhandled exceptions will no longer cause memory leaks
(If an exception occurs while a lot of data is present on the stack,
such as when loading large files, the data would ordinarily be kept
until the next exception occurs. We would rather release this memory
as soon as possible.)
- Some debuggers may have a hard time handling uncaught exceptions
The module also provides a callback mechanism allowing others to respond
to exceptions.
"""
import sys, time
#from lib.Manager import logMsg
import traceback
#from log import *
#logging = False
callbacks = []
clear_tracebacks = False
def register(fn):
"""
Register a callable to be invoked when there is an unhandled exception.
The callback will be passed the output of sys.exc_info(): (exception type, exception, traceback)
Multiple callbacks will be invoked in the order they were registered.
"""
callbacks.append(fn)
def unregister(fn):
"""Unregister a previously registered callback."""
callbacks.remove(fn)
def setTracebackClearing(clear=True):
"""
Enable or disable traceback clearing.
By default, clearing is disabled and Python will indefinitely store unhandled exception stack traces.
This function is provided since Python's default behavior can cause unexpected retention of
large memory-consuming objects.
"""
global clear_tracebacks
clear_tracebacks = clear
class ExceptionHandler(object):
def __call__(self, *args):
## call original exception handler first (prints exception)
global original_excepthook, callbacks, clear_tracebacks
print("===== %s =====" % str(time.strftime("%Y.%m.%d %H:%m:%S", time.localtime(time.time()))))
ret = original_excepthook(*args)
for cb in callbacks:
try:
cb(*args)
except:
print(" --------------------------------------------------------------")
print(" Error occurred during exception callback %s" % str(cb))
print(" --------------------------------------------------------------")
traceback.print_exception(*sys.exc_info())
## Clear long-term storage of last traceback to prevent memory-hogging.
## (If an exception occurs while a lot of data is present on the stack,
## such as when loading large files, the data would ordinarily be kept
## until the next exception occurs. We would rather release this memory
## as soon as possible.)
if clear_tracebacks is True:
sys.last_traceback = None
def implements(self, interface=None):
## this just makes it easy for us to detect whether an ExceptionHook is already installed.
if interface is None:
return ['ExceptionHandler']
else:
return interface == 'ExceptionHandler'
## replace built-in excepthook only if this has not already been done
if not (hasattr(sys.excepthook, 'implements') and sys.excepthook.implements('ExceptionHandler')):
original_excepthook = sys.excepthook
sys.excepthook = ExceptionHandler()
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from .Exporter import Exporter
from pyqtgraph.parametertree import Parameter
__all__ = ['CSVExporter']
class CSVExporter(Exporter):
Name = "CSV from plot data"
windows = []
def __init__(self, item):
Exporter.__init__(self, item)
self.params = Parameter(name='params', type='group', children=[
{'name': 'separator', 'type': 'list', 'value': 'comma', 'values': ['comma', 'tab']},
{'name': 'precision', 'type': 'int', 'value': 10, 'limits': [0, None]},
])
def parameters(self):
return self.params
def export(self, fileName=None):
if not isinstance(self.item, pg.PlotItem):
raise Exception("Must have a PlotItem selected for CSV export.")
if fileName is None:
self.fileSaveDialog(filter=["*.csv", "*.tsv"])
return
fd = open(fileName, 'w')
data = []
header = []
for c in self.item.curves:
data.append(c.getData())
header.extend(['x', 'y'])
if self.params['separator'] == 'comma':
sep = ','
else:
sep = '\t'
fd.write(sep.join(header) + '\n')
i = 0
numFormat = '%%0.%dg' % self.params['precision']
numRows = reduce(max, [len(d[0]) for d in data])
for i in range(numRows):
for d in data:
if i < len(d[0]):
fd.write(numFormat % d[0][i] + sep + numFormat % d[1][i] + sep)
else:
fd.write(' %s %s' % (sep, sep))
fd.write('\n')
fd.close()
from pyqtgraph.widgets.FileDialog import FileDialog
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore, QtSvg
from pyqtgraph.python2_3 import asUnicode
import os, re
LastExportDirectory = None
class Exporter(object):
"""
Abstract class used for exporting graphics to file / printer / whatever.
"""
allowCopy = False # subclasses set this to True if they can use the copy buffer
def __init__(self, item):
"""
Initialize with the item to be exported.
Can be an individual graphics item or a scene.
"""
object.__init__(self)
self.item = item
#def item(self):
#return self.item
def parameters(self):
"""Return the parameters used to configure this exporter."""
raise Exception("Abstract method must be overridden in subclass.")
def export(self, fileName=None, toBytes=False, copy=False):
"""
If *fileName* is None, pop-up a file dialog.
If *toBytes* is True, return a bytes object rather than writing to file.
If *copy* is True, export to the copy buffer rather than writing to file.
"""
raise Exception("Abstract method must be overridden in subclass.")
def fileSaveDialog(self, filter=None, opts=None):
## Show a file dialog, call self.export(fileName) when finished.
if opts is None:
opts = {}
self.fileDialog = FileDialog()
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
if filter is not None:
if isinstance(filter, basestring):
self.fileDialog.setNameFilter(filter)
elif isinstance(filter, list):
self.fileDialog.setNameFilters(filter)
global LastExportDirectory
exportDir = LastExportDirectory
if exportDir is not None:
self.fileDialog.setDirectory(exportDir)
self.fileDialog.show()
self.fileDialog.opts = opts
self.fileDialog.fileSelected.connect(self.fileSaveFinished)
return
def fileSaveFinished(self, fileName):
fileName = asUnicode(fileName)
global LastExportDirectory
LastExportDirectory = os.path.split(fileName)[0]
## If file name does not match selected extension, append it now
ext = os.path.splitext(fileName)[1].lower().lstrip('.')
selectedExt = re.search(r'\*\.(\w+)\b', asUnicode(self.fileDialog.selectedNameFilter()))
if selectedExt is not None:
selectedExt = selectedExt.groups()[0].lower()
if ext != selectedExt:
fileName = fileName + '.' + selectedExt.lstrip('.')
self.export(fileName=fileName, **self.fileDialog.opts)
def getScene(self):
if isinstance(self.item, pg.GraphicsScene):
return self.item
else:
return self.item.scene()
def getSourceRect(self):
if isinstance(self.item, pg.GraphicsScene):
w = self.item.getViewWidget()
return w.viewportTransform().inverted()[0].mapRect(w.rect())
else:
return self.item.sceneBoundingRect()
def getTargetRect(self):
if isinstance(self.item, pg.GraphicsScene):
return self.item.getViewWidget().rect()
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(key=lambda a: a.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, targetRect, sourceRect, 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:
#self.fileSaveDialog(self.writeSvg, filter="PostScript (*.ps)")
#return
#if item is None:
#item = self
#printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
#printer.setOutputFileName(fileName)
#painter = QtGui.QPainter(printer)
#self.render(painter)
#painter.end()
#def writeToPrinter(self):
#pass
from .Exporter import Exporter
from pyqtgraph.parametertree import Parameter
from pyqtgraph.Qt import QtGui, QtCore, QtSvg, USE_PYSIDE
import pyqtgraph as pg
import numpy as np
__all__ = ['ImageExporter']
class ImageExporter(Exporter):
Name = "Image File (PNG, TIF, JPG, ...)"
allowCopy = True
def __init__(self, item):
Exporter.__init__(self, item)
tr = self.getTargetRect()
if isinstance(item, QtGui.QGraphicsItem):
scene = item.scene()
else:
scene = item
bgbrush = scene.views()[0].backgroundBrush()
bg = bgbrush.color()
if bgbrush.style() == QtCore.Qt.NoBrush:
bg.setAlpha(0)
self.params = Parameter(name='params', type='group', children=[
{'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None)},
{'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None)},
{'name': 'antialias', 'type': 'bool', 'value': True},
{'name': 'background', 'type': 'color', 'value': bg},
])
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('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
def heightChanged(self):
sr = self.getSourceRect()
ar = float(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, toBytes=False, copy=False):
if fileName is None and not toBytes and not copy:
if USE_PYSIDE:
filter = ["*."+str(f) for f in QtGui.QImageWriter.supportedImageFormats()]
else:
filter = ["*."+bytes(f).decode('utf-8') for f in QtGui.QImageWriter.supportedImageFormats()]
preferred = ['*.png', '*.tif', '*.jpg']
for p in preferred[::-1]:
if p in filter:
filter.remove(p)
filter.insert(0, p)
self.fileSaveDialog(filter=filter)
return
targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
sourceRect = self.getSourceRect()
#self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
#self.png.fill(pyqtgraph.mkColor(self.params['background']))
w, h = self.params['width'], 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))
bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte)
color = self.params['background']
bg[:,:,0] = color.blue()
bg[:,:,1] = color.green()
bg[:,:,2] = color.red()
bg[:,:,3] = color.alpha()
self.png = pg.makeQImage(bg, alpha=True)
## set resolution of image:
origTargetRect = self.getTargetRect()
resolutionScale = targetRect.width() / origTargetRect.width()
#self.png.setDotsPerMeterX(self.png.dotsPerMeterX() * resolutionScale)
#self.png.setDotsPerMeterY(self.png.dotsPerMeterY() * resolutionScale)
painter = QtGui.QPainter(self.png)
#dtr = painter.deviceTransform()
try:
self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background'], 'painter': painter, 'resolutionScale': resolutionScale})
painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias'])
self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
finally:
self.setExportMode(False)
painter.end()
if copy:
QtGui.QApplication.clipboard().setImage(self.png)
elif toBytes:
return self.png
else:
self.png.save(fileName)
\ No newline at end of file
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from .Exporter import Exporter
__all__ = ['MatplotlibExporter']
class MatplotlibExporter(Exporter):
Name = "Matplotlib Window"
windows = []
def __init__(self, item):
Exporter.__init__(self, item)
def parameters(self):
return None
def export(self, fileName=None):
if isinstance(self.item, pg.PlotItem):
mpw = MatplotlibWindow()
MatplotlibExporter.windows.append(mpw)
fig = mpw.getFigure()
ax = fig.add_subplot(111)
ax.clear()
#ax.grid(True)
for item in self.item.curves:
x, y = item.getData()
opts = item.opts
pen = pg.mkPen(opts['pen'])
if pen.style() == QtCore.Qt.NoPen:
linestyle = ''
else:
linestyle = '-'
color = tuple([c/255. for c in pg.colorTuple(pen.color())])
symbol = opts['symbol']
if symbol == 't':
symbol = '^'
symbolPen = pg.mkPen(opts['symbolPen'])
symbolBrush = pg.mkBrush(opts['symbolBrush'])
markeredgecolor = tuple([c/255. for c in pg.colorTuple(symbolPen.color())])
markerfacecolor = tuple([c/255. for c in pg.colorTuple(symbolBrush.color())])
if opts['fillLevel'] is not None and opts['fillBrush'] is not None:
fillBrush = pg.mkBrush(opts['fillBrush'])
fillcolor = tuple([c/255. for c in pg.colorTuple(fillBrush.color())])
ax.fill_between(x=x, y1=y, y2=opts['fillLevel'], facecolor=fillcolor)
ax.plot(x, y, marker=symbol, color=color, linewidth=pen.width(), linestyle=linestyle, markeredgecolor=markeredgecolor, markerfacecolor=markerfacecolor)
xr, yr = self.item.viewRange()
ax.set_xbound(*xr)
ax.set_ybound(*yr)
mpw.draw()
else:
raise Exception("Matplotlib export currently only works with plot items")
class MatplotlibWindow(QtGui.QMainWindow):
def __init__(self):
import pyqtgraph.widgets.MatplotlibWidget
QtGui.QMainWindow.__init__(self)
self.mpl = pyqtgraph.widgets.MatplotlibWidget.MatplotlibWidget()
self.setCentralWidget(self.mpl)
self.show()
def __getattr__(self, attr):
return getattr(self.mpl, attr)
def closeEvent(self, ev):
MatplotlibExporter.windows.remove(self)
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;
#dpi = QtGui.QDesktopWidget().physicalDpiX()
#self.svg.setSize(QtCore.QSize(100,100))
#self.svg.setResolution(600)
#res = printer.resolution()
sr = self.getSourceRect()
#res = sr.width() * .4 / (self.params['width'] * 100 / 2.54)
res = QtGui.QDesktopWidget().physicalDpiX()
printer.setResolution(res)
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, {'painter': painter})
self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
finally:
self.setExportMode(False)
painter.end()
Exporters = []
from pyqtgraph import importModules
#from .. import frozenSupport
import os
d = os.path.split(__file__)[0]
#files = []
#for f in frozenSupport.listdir(d):
#if frozenSupport.isdir(os.path.join(d, f)) and f != '__pycache__':
#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=['*'])
for mod in importModules('', globals(), locals(), excludes=['Exporter']).values():
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[:]
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>217</width>
<height>499</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="verticalSpacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item row="1" column="0">
<widget class="QPushButton" name="loadBtn">
<property name="text">
<string>Load..</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="FeedbackButton" name="saveBtn">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="FeedbackButton" name="saveAsBtn">
<property name="text">
<string>As..</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="FeedbackButton" name="reloadBtn">
<property name="text">
<string>Reload Libs</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="2" colspan="2">
<widget class="QPushButton" name="showChartBtn">
<property name="text">
<string>Flowchart</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4">
<widget class="TreeWidget" name="ctrlList">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="fileNameLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>TreeWidget</class>
<extends>QTreeWidget</extends>
<header>pyqtgraph.widgets.TreeWidget</header>
</customwidget>
<customwidget>
<class>FeedbackButton</class>
<extends>QPushButton</extends>
<header>pyqtgraph.widgets.FeedbackButton</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './flowchart/FlowchartCtrlTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(217, 499)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setMargin(0)
self.gridLayout.setVerticalSpacing(0)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.loadBtn = QtGui.QPushButton(Form)
self.loadBtn.setObjectName(_fromUtf8("loadBtn"))
self.gridLayout.addWidget(self.loadBtn, 1, 0, 1, 1)
self.saveBtn = FeedbackButton(Form)
self.saveBtn.setObjectName(_fromUtf8("saveBtn"))
self.gridLayout.addWidget(self.saveBtn, 1, 1, 1, 2)
self.saveAsBtn = FeedbackButton(Form)
self.saveAsBtn.setObjectName(_fromUtf8("saveAsBtn"))
self.gridLayout.addWidget(self.saveAsBtn, 1, 3, 1, 1)
self.reloadBtn = FeedbackButton(Form)
self.reloadBtn.setCheckable(False)
self.reloadBtn.setFlat(False)
self.reloadBtn.setObjectName(_fromUtf8("reloadBtn"))
self.gridLayout.addWidget(self.reloadBtn, 4, 0, 1, 2)
self.showChartBtn = QtGui.QPushButton(Form)
self.showChartBtn.setCheckable(True)
self.showChartBtn.setObjectName(_fromUtf8("showChartBtn"))
self.gridLayout.addWidget(self.showChartBtn, 4, 2, 1, 2)
self.ctrlList = TreeWidget(Form)
self.ctrlList.setObjectName(_fromUtf8("ctrlList"))
self.ctrlList.headerItem().setText(0, _fromUtf8("1"))
self.ctrlList.header().setVisible(False)
self.ctrlList.header().setStretchLastSection(False)
self.gridLayout.addWidget(self.ctrlList, 3, 0, 1, 4)
self.fileNameLabel = QtGui.QLabel(Form)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.fileNameLabel.setFont(font)
self.fileNameLabel.setText(_fromUtf8(""))
self.fileNameLabel.setAlignment(QtCore.Qt.AlignCenter)
self.fileNameLabel.setObjectName(_fromUtf8("fileNameLabel"))
self.gridLayout.addWidget(self.fileNameLabel, 0, 1, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.loadBtn.setText(QtGui.QApplication.translate("Form", "Load..", None, QtGui.QApplication.UnicodeUTF8))
self.saveBtn.setText(QtGui.QApplication.translate("Form", "Save", None, QtGui.QApplication.UnicodeUTF8))
self.saveAsBtn.setText(QtGui.QApplication.translate("Form", "As..", None, QtGui.QApplication.UnicodeUTF8))
self.reloadBtn.setText(QtGui.QApplication.translate("Form", "Reload Libs", None, QtGui.QApplication.UnicodeUTF8))
self.showChartBtn.setText(QtGui.QApplication.translate("Form", "Flowchart", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.FeedbackButton import FeedbackButton
from pyqtgraph.widgets.TreeWidget import TreeWidget
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './flowchart/FlowchartCtrlTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(217, 499)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setVerticalSpacing(0)
self.gridLayout.setObjectName("gridLayout")
self.loadBtn = QtGui.QPushButton(Form)
self.loadBtn.setObjectName("loadBtn")
self.gridLayout.addWidget(self.loadBtn, 1, 0, 1, 1)
self.saveBtn = FeedbackButton(Form)
self.saveBtn.setObjectName("saveBtn")
self.gridLayout.addWidget(self.saveBtn, 1, 1, 1, 2)
self.saveAsBtn = FeedbackButton(Form)
self.saveAsBtn.setObjectName("saveAsBtn")
self.gridLayout.addWidget(self.saveAsBtn, 1, 3, 1, 1)
self.reloadBtn = FeedbackButton(Form)
self.reloadBtn.setCheckable(False)
self.reloadBtn.setFlat(False)
self.reloadBtn.setObjectName("reloadBtn")
self.gridLayout.addWidget(self.reloadBtn, 4, 0, 1, 2)
self.showChartBtn = QtGui.QPushButton(Form)
self.showChartBtn.setCheckable(True)
self.showChartBtn.setObjectName("showChartBtn")
self.gridLayout.addWidget(self.showChartBtn, 4, 2, 1, 2)
self.ctrlList = TreeWidget(Form)
self.ctrlList.setObjectName("ctrlList")
self.ctrlList.headerItem().setText(0, "1")
self.ctrlList.header().setVisible(False)
self.ctrlList.header().setStretchLastSection(False)
self.gridLayout.addWidget(self.ctrlList, 3, 0, 1, 4)
self.fileNameLabel = QtGui.QLabel(Form)
font = QtGui.QFont()
font.setWeight(75)
font.setBold(True)
self.fileNameLabel.setFont(font)
self.fileNameLabel.setText("")
self.fileNameLabel.setAlignment(QtCore.Qt.AlignCenter)
self.fileNameLabel.setObjectName("fileNameLabel")
self.gridLayout.addWidget(self.fileNameLabel, 0, 1, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.loadBtn.setText(QtGui.QApplication.translate("Form", "Load..", None, QtGui.QApplication.UnicodeUTF8))
self.saveBtn.setText(QtGui.QApplication.translate("Form", "Save", None, QtGui.QApplication.UnicodeUTF8))
self.saveAsBtn.setText(QtGui.QApplication.translate("Form", "As..", None, QtGui.QApplication.UnicodeUTF8))
self.reloadBtn.setText(QtGui.QApplication.translate("Form", "Reload Libs", None, QtGui.QApplication.UnicodeUTF8))
self.showChartBtn.setText(QtGui.QApplication.translate("Form", "Flowchart", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.FeedbackButton import FeedbackButton
from pyqtgraph.widgets.TreeWidget import TreeWidget
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.widgets.GraphicsView import GraphicsView
from pyqtgraph.GraphicsScene import GraphicsScene
from pyqtgraph.graphicsItems.ViewBox import ViewBox
#class FlowchartGraphicsView(QtGui.QGraphicsView):
class FlowchartGraphicsView(GraphicsView):
sigHoverOver = QtCore.Signal(object)
sigClicked = QtCore.Signal(object)
def __init__(self, widget, *args):
#QtGui.QGraphicsView.__init__(self, *args)
GraphicsView.__init__(self, *args, useOpenGL=False)
#self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(255,255,255)))
self._vb = FlowchartViewBox(widget, lockAspect=True, invertY=True)
self.setCentralItem(self._vb)
#self.scene().addItem(self.vb)
#self.setMouseTracking(True)
#self.lastPos = None
#self.setTransformationAnchor(self.AnchorViewCenter)
#self.setRenderHints(QtGui.QPainter.Antialiasing)
self.setRenderHint(QtGui.QPainter.Antialiasing, True)
#self.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
#self.setRubberBandSelectionMode(QtCore.Qt.ContainsItemBoundingRect)
def viewBox(self):
return self._vb
#def mousePressEvent(self, ev):
#self.moved = False
#self.lastPos = ev.pos()
#return QtGui.QGraphicsView.mousePressEvent(self, ev)
#def mouseMoveEvent(self, ev):
#self.moved = True
#callSuper = False
#if ev.buttons() & QtCore.Qt.RightButton:
#if self.lastPos is not None:
#dif = ev.pos() - self.lastPos
#self.scale(1.01**-dif.y(), 1.01**-dif.y())
#elif ev.buttons() & QtCore.Qt.MidButton:
#if self.lastPos is not None:
#dif = ev.pos() - self.lastPos
#self.translate(dif.x(), -dif.y())
#else:
##self.emit(QtCore.SIGNAL('hoverOver'), self.items(ev.pos()))
#self.sigHoverOver.emit(self.items(ev.pos()))
#callSuper = True
#self.lastPos = ev.pos()
#if callSuper:
#QtGui.QGraphicsView.mouseMoveEvent(self, ev)
#def mouseReleaseEvent(self, ev):
#if not self.moved:
##self.emit(QtCore.SIGNAL('clicked'), ev)
#self.sigClicked.emit(ev)
#return QtGui.QGraphicsView.mouseReleaseEvent(self, ev)
class FlowchartViewBox(ViewBox):
def __init__(self, widget, *args, **kwargs):
ViewBox.__init__(self, *args, **kwargs)
self.widget = widget
#self.menu = None
#self._subMenus = None ## need a place to store the menus otherwise they dissappear (even though they've been added to other menus) ((yes, it doesn't make sense))
def getMenu(self, ev):
## called by ViewBox to create a new context menu
self._fc_menu = QtGui.QMenu()
self._subMenus = self.getContextMenus(ev)
for menu in self._subMenus:
self._fc_menu.addMenu(menu)
return self._fc_menu
def getContextMenus(self, ev):
## called by scene to add menus on to someone else's context menu
menu = self.widget.buildMenu(ev.scenePos())
menu.setTitle("Add node")
return [menu, ViewBox.getMenu(self, ev)]
##class FlowchartGraphicsScene(QtGui.QGraphicsScene):
#class FlowchartGraphicsScene(GraphicsScene):
#sigContextMenuEvent = QtCore.Signal(object)
#def __init__(self, *args):
##QtGui.QGraphicsScene.__init__(self, *args)
#GraphicsScene.__init__(self, *args)
#def mouseClickEvent(self, ev):
##QtGui.QGraphicsScene.contextMenuEvent(self, ev)
#if not ev.button() in [QtCore.Qt.RightButton]:
#self.sigContextMenuEvent.emit(ev)
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>529</width>
<height>329</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="selInfoWidget" native="true">
<property name="geometry">
<rect>
<x>260</x>
<y>10</y>
<width>264</width>
<height>222</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="selDescLabel">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="selNameLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="DataTreeWidget" name="selectedTree">
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QTextEdit" name="hoverText">
<property name="geometry">
<rect>
<x>0</x>
<y>240</y>
<width>521</width>
<height>81</height>
</rect>
</property>
</widget>
<widget class="FlowchartGraphicsView" name="view">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>256</width>
<height>192</height>
</rect>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>DataTreeWidget</class>
<extends>QTreeWidget</extends>
<header>pyqtgraph.widgets.DataTreeWidget</header>
</customwidget>
<customwidget>
<class>FlowchartGraphicsView</class>
<extends>QGraphicsView</extends>
<header>pyqtgraph.flowchart.FlowchartGraphicsView</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './flowchart/FlowchartTemplate.ui'
#
# Created: Sun Feb 24 19:47:29 2013
# by: PyQt4 UI code generator 4.9.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(529, 329)
self.selInfoWidget = QtGui.QWidget(Form)
self.selInfoWidget.setGeometry(QtCore.QRect(260, 10, 264, 222))
self.selInfoWidget.setObjectName(_fromUtf8("selInfoWidget"))
self.gridLayout = QtGui.QGridLayout(self.selInfoWidget)
self.gridLayout.setMargin(0)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.selDescLabel = QtGui.QLabel(self.selInfoWidget)
self.selDescLabel.setText(_fromUtf8(""))
self.selDescLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.selDescLabel.setWordWrap(True)
self.selDescLabel.setObjectName(_fromUtf8("selDescLabel"))
self.gridLayout.addWidget(self.selDescLabel, 0, 0, 1, 1)
self.selNameLabel = QtGui.QLabel(self.selInfoWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.selNameLabel.setFont(font)
self.selNameLabel.setText(_fromUtf8(""))
self.selNameLabel.setObjectName(_fromUtf8("selNameLabel"))
self.gridLayout.addWidget(self.selNameLabel, 0, 1, 1, 1)
self.selectedTree = DataTreeWidget(self.selInfoWidget)
self.selectedTree.setObjectName(_fromUtf8("selectedTree"))
self.selectedTree.headerItem().setText(0, _fromUtf8("1"))
self.gridLayout.addWidget(self.selectedTree, 1, 0, 1, 2)
self.hoverText = QtGui.QTextEdit(Form)
self.hoverText.setGeometry(QtCore.QRect(0, 240, 521, 81))
self.hoverText.setObjectName(_fromUtf8("hoverText"))
self.view = FlowchartGraphicsView(Form)
self.view.setGeometry(QtCore.QRect(0, 0, 256, 192))
self.view.setObjectName(_fromUtf8("view"))
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.DataTreeWidget import DataTreeWidget
from pyqtgraph.flowchart.FlowchartGraphicsView import FlowchartGraphicsView
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './flowchart/FlowchartTemplate.ui'
#
# Created: Sun Feb 24 19:47:30 2013
# by: pyside-uic 0.2.13 running on PySide 1.1.1
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(529, 329)
self.selInfoWidget = QtGui.QWidget(Form)
self.selInfoWidget.setGeometry(QtCore.QRect(260, 10, 264, 222))
self.selInfoWidget.setObjectName("selInfoWidget")
self.gridLayout = QtGui.QGridLayout(self.selInfoWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.selDescLabel = QtGui.QLabel(self.selInfoWidget)
self.selDescLabel.setText("")
self.selDescLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.selDescLabel.setWordWrap(True)
self.selDescLabel.setObjectName("selDescLabel")
self.gridLayout.addWidget(self.selDescLabel, 0, 0, 1, 1)
self.selNameLabel = QtGui.QLabel(self.selInfoWidget)
font = QtGui.QFont()
font.setWeight(75)
font.setBold(True)
self.selNameLabel.setFont(font)
self.selNameLabel.setText("")
self.selNameLabel.setObjectName("selNameLabel")
self.gridLayout.addWidget(self.selNameLabel, 0, 1, 1, 1)
self.selectedTree = DataTreeWidget(self.selInfoWidget)
self.selectedTree.setObjectName("selectedTree")
self.selectedTree.headerItem().setText(0, "1")
self.gridLayout.addWidget(self.selectedTree, 1, 0, 1, 2)
self.hoverText = QtGui.QTextEdit(Form)
self.hoverText.setGeometry(QtCore.QRect(0, 240, 521, 81))
self.hoverText.setObjectName("hoverText")
self.view = FlowchartGraphicsView(Form)
self.view.setGeometry(QtCore.QRect(0, 0, 256, 192))
self.view.setObjectName("view")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.DataTreeWidget import DataTreeWidget
from pyqtgraph.flowchart.FlowchartGraphicsView import FlowchartGraphicsView
# -*- coding: utf-8 -*-
from .Flowchart import *
from .library import getNodeType, registerNodeType, getNodeTree
\ No newline at end of file
# -*- coding: utf-8 -*-
from numpy import ndarray, bool_
from pyqtgraph.metaarray import MetaArray
def eq(a, b):
"""The great missing equivalence function: Guaranteed evaluation to a single bool value."""
if a is b:
return True
try:
e = a==b
except ValueError:
return False
except AttributeError:
return False
except:
print("a:", str(type(a)), str(a))
print("b:", str(type(b)), str(b))
raise
t = type(e)
if t is bool:
return e
elif t is bool_:
return bool(e)
elif isinstance(e, ndarray) or (hasattr(e, 'implements') and e.implements('MetaArray')):
try: ## disaster: if a is an empty array and b is not, then e.all() is True
if a.shape != b.shape:
return False
except:
return False
if (hasattr(e, 'implements') and e.implements('MetaArray')):
return e.asarray().all()
else:
return e.all()
else:
raise Exception("== operator returned type %s" % str(type(e)))
# -*- coding: utf-8 -*-
from ..Node import Node
import weakref
#from pyqtgraph import graphicsItems
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.graphicsItems.ScatterPlotItem import ScatterPlotItem
from pyqtgraph.graphicsItems.PlotCurveItem import PlotCurveItem
from pyqtgraph import PlotDataItem
from .common import *
import numpy as np
class PlotWidgetNode(Node):
"""Connection to PlotWidget. Will plot arrays, metaarrays, and display event lists."""
nodeName = 'PlotWidget'
sigPlotChanged = QtCore.Signal(object)
def __init__(self, name):
Node.__init__(self, name, terminals={'In': {'io': 'in', 'multi': True}})
self.plot = None
self.items = {}
def disconnected(self, localTerm, remoteTerm):
if localTerm is self['In'] and remoteTerm in self.items:
self.plot.removeItem(self.items[remoteTerm])
del self.items[remoteTerm]
def setPlot(self, plot):
#print "======set plot"
self.plot = plot
self.sigPlotChanged.emit(self)
def getPlot(self):
return self.plot
def process(self, In, display=True):
if display:
#self.plot.clearPlots()
items = set()
for name, vals in In.items():
if vals is None:
continue
if type(vals) is not list:
vals = [vals]
for val in vals:
vid = id(val)
if vid in self.items and self.items[vid].scene() is self.plot.scene():
items.add(vid)
else:
#if isinstance(val, PlotCurveItem):
#self.plot.addItem(val)
#item = val
#if isinstance(val, ScatterPlotItem):
#self.plot.addItem(val)
#item = val
if isinstance(val, QtGui.QGraphicsItem):
self.plot.addItem(val)
item = val
else:
item = self.plot.plot(val)
self.items[vid] = item
items.add(vid)
for vid in list(self.items.keys()):
if vid not in items:
#print "remove", self.items[vid]
self.plot.removeItem(self.items[vid])
del self.items[vid]
def processBypassed(self, args):
for item in list(self.items.values()):
self.plot.removeItem(item)
self.items = {}
#def setInput(self, **args):
#for k in args:
#self.plot.plot(args[k])
class CanvasNode(Node):
"""Connection to a Canvas widget."""
nodeName = 'CanvasWidget'
def __init__(self, name):
Node.__init__(self, name, terminals={'In': {'io': 'in', 'multi': True}})
self.canvas = None
self.items = {}
def disconnected(self, localTerm, remoteTerm):
if localTerm is self.In and remoteTerm in self.items:
self.canvas.removeItem(self.items[remoteTerm])
del self.items[remoteTerm]
def setCanvas(self, canvas):
self.canvas = canvas
def getCanvas(self):
return self.canvas
def process(self, In, display=True):
if display:
items = set()
for name, vals in In.items():
if vals is None:
continue
if type(vals) is not list:
vals = [vals]
for val in vals:
vid = id(val)
if vid in self.items:
items.add(vid)
else:
self.canvas.addItem(val)
item = val
self.items[vid] = item
items.add(vid)
for vid in list(self.items.keys()):
if vid not in items:
#print "remove", self.items[vid]
self.canvas.removeItem(self.items[vid])
del self.items[vid]
class PlotCurve(CtrlNode):
"""Generates a plot curve from x/y data"""
nodeName = 'PlotCurve'
uiTemplate = [
('color', 'color'),
]
def __init__(self, name):
CtrlNode.__init__(self, name, terminals={
'x': {'io': 'in'},
'y': {'io': 'in'},
'plot': {'io': 'out'}
})
self.item = PlotDataItem()
def process(self, x, y, display=True):
#print "scatterplot process"
if not display:
return {'plot': None}
self.item.setData(x, y, pen=self.ctrls['color'].color())
return {'plot': self.item}
class ScatterPlot(CtrlNode):
"""Generates a scatter plot from a record array or nested dicts"""
nodeName = 'ScatterPlot'
uiTemplate = [
('x', 'combo', {'values': [], 'index': 0}),
('y', 'combo', {'values': [], 'index': 0}),
('sizeEnabled', 'check', {'value': False}),
('size', 'combo', {'values': [], 'index': 0}),
('absoluteSize', 'check', {'value': False}),
('colorEnabled', 'check', {'value': False}),
('color', 'colormap', {}),
('borderEnabled', 'check', {'value': False}),
('border', 'colormap', {}),
]
def __init__(self, name):
CtrlNode.__init__(self, name, terminals={
'input': {'io': 'in'},
'plot': {'io': 'out'}
})
self.item = ScatterPlotItem()
self.keys = []
#self.ui = QtGui.QWidget()
#self.layout = QtGui.QGridLayout()
#self.ui.setLayout(self.layout)
#self.xCombo = QtGui.QComboBox()
#self.yCombo = QtGui.QComboBox()
def process(self, input, display=True):
#print "scatterplot process"
if not display:
return {'plot': None}
self.updateKeys(input[0])
x = str(self.ctrls['x'].currentText())
y = str(self.ctrls['y'].currentText())
size = str(self.ctrls['size'].currentText())
pen = QtGui.QPen(QtGui.QColor(0,0,0,0))
points = []
for i in input:
pt = {'pos': (i[x], i[y])}
if self.ctrls['sizeEnabled'].isChecked():
pt['size'] = i[size]
if self.ctrls['borderEnabled'].isChecked():
pt['pen'] = QtGui.QPen(self.ctrls['border'].getColor(i))
else:
pt['pen'] = pen
if self.ctrls['colorEnabled'].isChecked():
pt['brush'] = QtGui.QBrush(self.ctrls['color'].getColor(i))
points.append(pt)
self.item.setPxMode(not self.ctrls['absoluteSize'].isChecked())
self.item.setPoints(points)
return {'plot': self.item}
def updateKeys(self, data):
if isinstance(data, dict):
keys = list(data.keys())
elif isinstance(data, list) or isinstance(data, tuple):
keys = data
elif isinstance(data, np.ndarray) or isinstance(data, np.void):
keys = data.dtype.names
else:
print("Unknown data type:", type(data), data)
return
for c in self.ctrls.values():
c.blockSignals(True)
for c in [self.ctrls['x'], self.ctrls['y'], self.ctrls['size']]:
cur = str(c.currentText())
c.clear()
for k in keys:
c.addItem(k)
if k == cur:
c.setCurrentIndex(c.count()-1)
for c in [self.ctrls['color'], self.ctrls['border']]:
c.setArgList(keys)
for c in self.ctrls.values():
c.blockSignals(False)
self.keys = keys
def saveState(self):
state = CtrlNode.saveState(self)
return {'keys': self.keys, 'ctrls': state}
def restoreState(self, state):
self.updateKeys(state['keys'])
CtrlNode.restoreState(self, state['ctrls'])
#class ImageItem(Node):
#"""Creates an ImageItem for display in a canvas from a file handle."""
#nodeName = 'Image'
#def __init__(self, name):
#Node.__init__(self, name, terminals={
#'file': {'io': 'in'},
#'image': {'io': 'out'}
#})
#self.imageItem = graphicsItems.ImageItem()
#self.handle = None
#def process(self, file, display=True):
#if not display:
#return {'image': None}
#if file != self.handle:
#self.handle = file
#data = file.read()
#self.imageItem.updateImage(data)
#pos = file.
\ No newline at end of file
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