diff --git a/CHANGELOG b/CHANGELOG index 9fa10984..64a030d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,35 @@ +pyqtgraph-0.9.9 [unreleased] + + API / behavior changes: + - Dynamic import system abandoned; pg now uses static imports throughout. + - Flowcharts and exporters have new pluggin systems + - Version strings: + - __init__.py in git repo now contains latest release version string + (previously, only packaged releases had version strings). + - installing from git checkout that does not correspond to a release + commit will result in a more descriptive version string. + - Speed improvements in functions.makeARGB + - ImageItem is faster by avoiding makeQImage(transpose=True) + + New Features: + - New HDF5 example for working with very large datasets + - Added Qt.loadUiType function for PySide + - Simplified Profilers; can be activated with environmental variables + - Added Dock.raiseDock() method + + Bugfixes: + - PlotCurveItem now has correct clicking behavior--clicks within a few px + of the line will trigger a signal. + - Fixes related to CSV exporter: + - CSV headers include data names, if available + - Exporter correctly handles items with no data + - pg.plot() avoids creating empty data item + - removed call to reduce() from exporter; not available in python 3 + - Gave .name() methods to PlotDataItem, PlotCurveItem, and ScatterPlotItem + - fixed ImageItem handling of rgb images + - fixed makeARGB re-ordering of color channels + + pyqtgraph-0.9.8 2013-11-24 API / behavior changes: diff --git a/examples/FlowchartCustomNode.py b/examples/FlowchartCustomNode.py index bce37982..25ea5c77 100644 --- a/examples/FlowchartCustomNode.py +++ b/examples/FlowchartCustomNode.py @@ -83,9 +83,8 @@ class ImageViewNode(Node): else: self.view.setImage(data) -## register the class so it will appear in the menu of node types. -## It will appear in the 'display' sub-menu. -fclib.registerNodeType(ImageViewNode, [('Display',)]) + + ## We will define an unsharp masking filter node as a subclass of CtrlNode. ## CtrlNode is just a convenience class that automatically creates its @@ -113,12 +112,25 @@ class UnsharpMaskNode(CtrlNode): strength = self.ctrls['strength'].value() output = dataIn - (strength * scipy.ndimage.gaussian_filter(dataIn, (sigma,sigma))) return {'dataOut': output} + + +## To make our custom node classes available in the flowchart context menu, +## we can either register them with the default node library or make a +## new library. + -## register the class so it will appear in the menu of node types. -## It will appear in a new 'image' sub-menu. -fclib.registerNodeType(UnsharpMaskNode, [('Image',)]) - - +## Method 1: Register to global default library: +#fclib.registerNodeType(ImageViewNode, [('Display',)]) +#fclib.registerNodeType(UnsharpMaskNode, [('Image',)]) + +## Method 2: If we want to make our custom node available only to this flowchart, +## then instead of registering the node type globally, we can create a new +## NodeLibrary: +library = fclib.LIBRARY.copy() # start with the default node set +library.addNodeType(ImageViewNode, [('Display',)]) +library.addNodeType(UnsharpMaskNode, [('Image',)]) +fc.setLibrary(library) + ## Now we will programmatically add nodes to define the function of the flowchart. ## Normally, the user will do this manually or by loading a pre-generated diff --git a/pyqtgraph/__init__.py b/pyqtgraph/__init__.py index f25d1c3a..77b7c590 100644 --- a/pyqtgraph/__init__.py +++ b/pyqtgraph/__init__.py @@ -130,56 +130,119 @@ if __version__ is None and not hasattr(sys, 'frozen') and sys.version_info[0] == ## Import almost everything to make it available from a single namespace ## don't import the more complex systems--canvas, parametertree, flowchart, dockarea ## these must be imported separately. -from . import frozenSupport -def importModules(path, globals, locals, excludes=()): - """Import all modules residing within *path*, return a dict of name: module pairs. +#from . import frozenSupport +#def importModules(path, globals, locals, excludes=()): + #"""Import all modules residing within *path*, return a dict of name: module pairs. - Note that *path* MUST be relative to the module doing the import. - """ - d = os.path.join(os.path.split(globals['__file__'])[0], path) - files = set() - for f in frozenSupport.listdir(d): - if frozenSupport.isdir(os.path.join(d, f)) and f not in ['__pycache__', 'tests']: - files.add(f) - elif f[-3:] == '.py' and f != '__init__.py': - files.add(f[:-3]) - elif f[-4:] == '.pyc' and f != '__init__.pyc': - files.add(f[:-4]) + #Note that *path* MUST be relative to the module doing the import. + #""" + #d = os.path.join(os.path.split(globals['__file__'])[0], path) + #files = set() + #for f in frozenSupport.listdir(d): + #if frozenSupport.isdir(os.path.join(d, f)) and f not in ['__pycache__', 'tests']: + #files.add(f) + #elif f[-3:] == '.py' and f != '__init__.py': + #files.add(f[:-3]) + #elif f[-4:] == '.pyc' and f != '__init__.pyc': + #files.add(f[:-4]) - mods = {} - path = path.replace(os.sep, '.') - for modName in files: - if modName in excludes: - continue - try: - if len(path) > 0: - modName = path + '.' + modName - #mod = __import__(modName, globals, locals, fromlist=['*']) - mod = __import__(modName, globals, locals, ['*'], 1) - mods[modName] = mod - except: - import traceback - traceback.print_stack() - sys.excepthook(*sys.exc_info()) - print("[Error importing module: %s]" % modName) + #mods = {} + #path = path.replace(os.sep, '.') + #for modName in files: + #if modName in excludes: + #continue + #try: + #if len(path) > 0: + #modName = path + '.' + modName + #print( "from .%s import * " % modName) + #mod = __import__(modName, globals, locals, ['*'], 1) + #mods[modName] = mod + #except: + #import traceback + #traceback.print_stack() + #sys.excepthook(*sys.exc_info()) + #print("[Error importing module: %s]" % modName) - return mods + #return mods -def importAll(path, globals, locals, excludes=()): - """Given a list of modules, import all names from each module into the global namespace.""" - mods = importModules(path, globals, locals, excludes) - for mod in mods.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): - globals[k] = getattr(mod, k) +#def importAll(path, globals, locals, excludes=()): + #"""Given a list of modules, import all names from each module into the global namespace.""" + #mods = importModules(path, globals, locals, excludes) + #for mod in mods.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): + #globals[k] = getattr(mod, k) -importAll('graphicsItems', globals(), locals()) -importAll('widgets', globals(), locals(), - excludes=['MatplotlibWidget', 'RawImageWidget', 'RemoteGraphicsView']) +# Dynamic imports are disabled. This causes too many problems. +#importAll('graphicsItems', globals(), locals()) +#importAll('widgets', globals(), locals(), + #excludes=['MatplotlibWidget', 'RawImageWidget', 'RemoteGraphicsView']) + +from .graphicsItems.VTickGroup import * +from .graphicsItems.GraphicsWidget import * +from .graphicsItems.ScaleBar import * +from .graphicsItems.PlotDataItem import * +from .graphicsItems.GraphItem import * +from .graphicsItems.TextItem import * +from .graphicsItems.GraphicsLayout import * +from .graphicsItems.UIGraphicsItem import * +from .graphicsItems.GraphicsObject import * +from .graphicsItems.PlotItem import * +from .graphicsItems.ROI import * +from .graphicsItems.InfiniteLine import * +from .graphicsItems.HistogramLUTItem import * +from .graphicsItems.GridItem import * +from .graphicsItems.GradientLegend import * +from .graphicsItems.GraphicsItem import * +from .graphicsItems.BarGraphItem import * +from .graphicsItems.ViewBox import * +from .graphicsItems.ArrowItem import * +from .graphicsItems.ImageItem import * +from .graphicsItems.AxisItem import * +from .graphicsItems.LabelItem import * +from .graphicsItems.CurvePoint import * +from .graphicsItems.GraphicsWidgetAnchor import * +from .graphicsItems.PlotCurveItem import * +from .graphicsItems.ButtonItem import * +from .graphicsItems.GradientEditorItem import * +from .graphicsItems.MultiPlotItem import * +from .graphicsItems.ErrorBarItem import * +from .graphicsItems.IsocurveItem import * +from .graphicsItems.LinearRegionItem import * +from .graphicsItems.FillBetweenItem import * +from .graphicsItems.LegendItem import * +from .graphicsItems.ScatterPlotItem import * +from .graphicsItems.ItemGroup import * + +from .widgets.MultiPlotWidget import * +from .widgets.ScatterPlotWidget import * +from .widgets.ColorMapWidget import * +from .widgets.FileDialog import * +from .widgets.ValueLabel import * +from .widgets.HistogramLUTWidget import * +from .widgets.CheckTable import * +from .widgets.BusyCursor import * +from .widgets.PlotWidget import * +from .widgets.ComboBox import * +from .widgets.GradientWidget import * +from .widgets.DataFilterWidget import * +from .widgets.SpinBox import * +from .widgets.JoystickButton import * +from .widgets.GraphicsLayoutWidget import * +from .widgets.TreeWidget import * +from .widgets.PathButton import * +from .widgets.VerticalLabel import * +from .widgets.FeedbackButton import * +from .widgets.ColorButton import * +from .widgets.DataTreeWidget import * +from .widgets.GraphicsView import * +from .widgets.LayoutWidget import * +from .widgets.TableWidget import * +from .widgets.ProgressDialog import * from .imageview import * from .WidgetGroup import * @@ -194,6 +257,7 @@ from .SignalProxy import * from .colormap import * from .ptime import time + ############################################################## ## PyQt and PySide both are prone to crashing on exit. ## There are two general approaches to dealing with this: diff --git a/pyqtgraph/exporters/CSVExporter.py b/pyqtgraph/exporters/CSVExporter.py index 3ff2af31..c6386655 100644 --- a/pyqtgraph/exporters/CSVExporter.py +++ b/pyqtgraph/exporters/CSVExporter.py @@ -60,6 +60,6 @@ class CSVExporter(Exporter): fd.write('\n') fd.close() - +CSVExporter.register() diff --git a/pyqtgraph/exporters/Exporter.py b/pyqtgraph/exporters/Exporter.py index 6371a3b9..281fbb9a 100644 --- a/pyqtgraph/exporters/Exporter.py +++ b/pyqtgraph/exporters/Exporter.py @@ -11,6 +11,14 @@ 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 + Exporters = [] + + @classmethod + def register(cls): + """ + Used to register Exporter classes to appear in the export dialog. + """ + Exporter.Exporters.append(cls) def __init__(self, item): """ @@ -20,9 +28,6 @@ class Exporter(object): 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.") @@ -131,45 +136,4 @@ class Exporter(object): 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 diff --git a/pyqtgraph/exporters/ImageExporter.py b/pyqtgraph/exporters/ImageExporter.py index 9fb77e2a..40a76fbd 100644 --- a/pyqtgraph/exporters/ImageExporter.py +++ b/pyqtgraph/exporters/ImageExporter.py @@ -98,4 +98,5 @@ class ImageExporter(Exporter): else: self.png.save(fileName) +ImageExporter.register() \ No newline at end of file diff --git a/pyqtgraph/exporters/Matplotlib.py b/pyqtgraph/exporters/Matplotlib.py index 76f878d2..42008468 100644 --- a/pyqtgraph/exporters/Matplotlib.py +++ b/pyqtgraph/exporters/Matplotlib.py @@ -57,6 +57,7 @@ class MatplotlibExporter(Exporter): else: raise Exception("Matplotlib export currently only works with plot items") +MatplotlibExporter.register() class MatplotlibWindow(QtGui.QMainWindow): @@ -72,3 +73,5 @@ class MatplotlibWindow(QtGui.QMainWindow): def closeEvent(self, ev): MatplotlibExporter.windows.remove(self) + + diff --git a/pyqtgraph/exporters/PrintExporter.py b/pyqtgraph/exporters/PrintExporter.py index 5b31b45d..ef35c2f8 100644 --- a/pyqtgraph/exporters/PrintExporter.py +++ b/pyqtgraph/exporters/PrintExporter.py @@ -63,3 +63,6 @@ class PrintExporter(Exporter): finally: self.setExportMode(False) painter.end() + + +#PrintExporter.register() diff --git a/pyqtgraph/exporters/SVGExporter.py b/pyqtgraph/exporters/SVGExporter.py index 19a7a6a7..425f48e9 100644 --- a/pyqtgraph/exporters/SVGExporter.py +++ b/pyqtgraph/exporters/SVGExporter.py @@ -404,6 +404,10 @@ def correctCoordinates(node, item): if removeTransform: grp.removeAttribute('transform') + +SVGExporter.register() + + def itemTransform(item, root): ## Return the transformation mapping item to root ## (actually to parent coordinate system of root) diff --git a/pyqtgraph/exporters/__init__.py b/pyqtgraph/exporters/__init__.py index 3f3c1f1d..e2a81bc2 100644 --- a/pyqtgraph/exporters/__init__.py +++ b/pyqtgraph/exporters/__init__.py @@ -1,27 +1,24 @@ -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)) +#Exporters = [] +#from pyqtgraph import importModules +#import os +#d = os.path.split(__file__)[0] +#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)) + +from .Exporter import Exporter +from .ImageExporter import * +from .SVGExporter import * +from .Matplotlib import * +from .CSVExporter import * +from .PrintExporter import * def listExporters(): - return Exporters[:] + return Exporter.Exporters[:] diff --git a/pyqtgraph/flowchart/Flowchart.py b/pyqtgraph/flowchart/Flowchart.py index 81f9e163..f566e97c 100644 --- a/pyqtgraph/flowchart/Flowchart.py +++ b/pyqtgraph/flowchart/Flowchart.py @@ -14,7 +14,7 @@ else: from .Terminal import Terminal from numpy import ndarray -from . import library +from .library import LIBRARY from pyqtgraph.debug import printExc import pyqtgraph.configfile as configfile import pyqtgraph.dockarea as dockarea @@ -67,7 +67,8 @@ class Flowchart(Node): sigChartLoaded = QtCore.Signal() sigStateChanged = QtCore.Signal() - def __init__(self, terminals=None, name=None, filePath=None): + def __init__(self, terminals=None, name=None, filePath=None, library=None): + self.library = library or LIBRARY if name is None: name = "Flowchart" if terminals is None: @@ -105,6 +106,10 @@ class Flowchart(Node): for name, opts in terminals.items(): self.addTerminal(name, **opts) + def setLibrary(self, lib): + self.library = lib + self.widget().chartWidget.buildMenu() + def setInput(self, **args): """Set the input values of the flowchart. This will automatically propagate the new values throughout the flowchart, (possibly) causing the output to change. @@ -194,7 +199,7 @@ class Flowchart(Node): break n += 1 - node = library.getNodeType(nodeType)(name) + node = self.library.getNodeType(nodeType)(name) self.addNode(node, name, pos) return node @@ -846,13 +851,13 @@ class FlowchartWidget(dockarea.DockArea): self.nodeMenu.triggered.disconnect(self.nodeMenuTriggered) self.nodeMenu = None self.subMenus = [] - library.loadLibrary(reloadLibs=True) + self.chart.library.reload() self.buildMenu() def buildMenu(self, pos=None): self.nodeMenu = QtGui.QMenu() self.subMenus = [] - for section, nodes in library.getNodeTree().items(): + for section, nodes in self.chart.library.getNodeTree().items(): menu = QtGui.QMenu(section) self.nodeMenu.addMenu(menu) for name in nodes: diff --git a/pyqtgraph/flowchart/NodeLibrary.py b/pyqtgraph/flowchart/NodeLibrary.py new file mode 100644 index 00000000..20d0085e --- /dev/null +++ b/pyqtgraph/flowchart/NodeLibrary.py @@ -0,0 +1,84 @@ +from pyqtgraph.pgcollections import OrderedDict +from .Node import Node + +def isNodeClass(cls): + try: + if not issubclass(cls, Node): + return False + except: + return False + return hasattr(cls, 'nodeName') + + + +class NodeLibrary: + """ + A library of flowchart Node types. Custom libraries may be built to provide + each flowchart with a specific set of allowed Node types. + """ + + def __init__(self): + self.nodeList = OrderedDict() + self.nodeTree = OrderedDict() + + def addNodeType(self, nodeClass, paths, override=False): + """ + Register a new node type. If the type's name is already in use, + an exception will be raised (unless override=True). + + Arguments: + + nodeClass - a subclass of Node (must have typ.nodeName) + paths - list of tuples specifying the location(s) this + type will appear in the library tree. + override - if True, overwrite any class having the same name + """ + if not isNodeClass(nodeClass): + raise Exception("Object %s is not a Node subclass" % str(nodeClass)) + + name = nodeClass.nodeName + if not override and name in self.nodeList: + raise Exception("Node type name '%s' is already registered." % name) + + self.nodeList[name] = nodeClass + for path in paths: + root = self.nodeTree + for n in path: + if n not in root: + root[n] = OrderedDict() + root = root[n] + root[name] = nodeClass + + def getNodeType(self, name): + try: + return self.nodeList[name] + except KeyError: + raise Exception("No node type called '%s'" % name) + + def getNodeTree(self): + return self.nodeTree + + def copy(self): + """ + Return a copy of this library. + """ + lib = NodeLibrary() + lib.nodeList = self.nodeList.copy() + lib.nodeTree = self.treeCopy(self.nodeTree) + return lib + + @staticmethod + def treeCopy(tree): + copy = OrderedDict() + for k,v in tree.items(): + if isNodeClass(v): + copy[k] = v + else: + copy[k] = NodeLibrary.treeCopy(v) + return copy + + def reload(self): + """ + Reload Node classes in this library. + """ + raise NotImplementedError() diff --git a/pyqtgraph/flowchart/library/__init__.py b/pyqtgraph/flowchart/library/__init__.py index 1e44edff..32a17b58 100644 --- a/pyqtgraph/flowchart/library/__init__.py +++ b/pyqtgraph/flowchart/library/__init__.py @@ -1,103 +1,102 @@ # -*- coding: utf-8 -*- from pyqtgraph.pgcollections import OrderedDict -from pyqtgraph import importModules +#from pyqtgraph import importModules import os, types from pyqtgraph.debug import printExc -from ..Node import Node +#from ..Node import Node +from ..NodeLibrary import NodeLibrary, isNodeClass import pyqtgraph.reload as reload -NODE_LIST = OrderedDict() ## maps name:class for all registered Node subclasses -NODE_TREE = OrderedDict() ## categorized tree of Node subclasses +# Build default library +LIBRARY = NodeLibrary() -def getNodeType(name): - try: - return NODE_LIST[name] - except KeyError: - raise Exception("No node type called '%s'" % name) +# For backward compatibility, expose the default library's properties here: +NODE_LIST = LIBRARY.nodeList +NODE_TREE = LIBRARY.nodeTree +registerNodeType = LIBRARY.addNodeType +getNodeTree = LIBRARY.getNodeTree +getNodeType = LIBRARY.getNodeType -def getNodeTree(): - return NODE_TREE - -def registerNodeType(cls, paths, override=False): - """ - Register a new node type. If the type's name is already in use, - an exception will be raised (unless override=True). +# Add all nodes to the default library +from . import Data, Display, Filters, Operators +for mod in [Data, Display, Filters, Operators]: + #mod = getattr(__import__('', fromlist=[modName], level=1), modName) + #mod = __import__(modName, level=1) + nodes = [getattr(mod, name) for name in dir(mod) if isNodeClass(getattr(mod, name))] + for node in nodes: + LIBRARY.addNodeType(node, [(mod.__name__.split('.')[-1],)]) - Arguments: - cls - a subclass of Node (must have typ.nodeName) - paths - list of tuples specifying the location(s) this - type will appear in the library tree. - override - if True, overwrite any class having the same name - """ - if not isNodeClass(cls): - raise Exception("Object %s is not a Node subclass" % str(cls)) +#NODE_LIST = OrderedDict() ## maps name:class for all registered Node subclasses +#NODE_TREE = OrderedDict() ## categorized tree of Node subclasses + +#def getNodeType(name): + #try: + #return NODE_LIST[name] + #except KeyError: + #raise Exception("No node type called '%s'" % name) + +#def getNodeTree(): + #return NODE_TREE + +#def registerNodeType(cls, paths, override=False): + #""" + #Register a new node type. If the type's name is already in use, + #an exception will be raised (unless override=True). - name = cls.nodeName - if not override and name in NODE_LIST: - raise Exception("Node type name '%s' is already registered." % name) + #Arguments: + #cls - a subclass of Node (must have typ.nodeName) + #paths - list of tuples specifying the location(s) this + #type will appear in the library tree. + #override - if True, overwrite any class having the same name + #""" + #if not isNodeClass(cls): + #raise Exception("Object %s is not a Node subclass" % str(cls)) - NODE_LIST[name] = cls - for path in paths: - root = NODE_TREE - for n in path: - if n not in root: - root[n] = OrderedDict() - root = root[n] - root[name] = cls - - - -def isNodeClass(cls): - try: - if not issubclass(cls, Node): - return False - except: - return False - return hasattr(cls, 'nodeName') - -def loadLibrary(reloadLibs=False, libPath=None): - """Import all Node subclasses found within files in the library module.""" - - global NODE_LIST, NODE_TREE - #if libPath is None: - #libPath = os.path.dirname(os.path.abspath(__file__)) + #name = cls.nodeName + #if not override and name in NODE_LIST: + #raise Exception("Node type name '%s' is already registered." % name) - if reloadLibs: - reload.reloadAll(libPath) + #NODE_LIST[name] = cls + #for path in paths: + #root = NODE_TREE + #for n in path: + #if n not in root: + #root[n] = OrderedDict() + #root = root[n] + #root[name] = cls + + + +#def isNodeClass(cls): + #try: + #if not issubclass(cls, Node): + #return False + #except: + #return False + #return hasattr(cls, 'nodeName') + +#def loadLibrary(reloadLibs=False, libPath=None): + #"""Import all Node subclasses found within files in the library module.""" + + #global NODE_LIST, NODE_TREE + + #if reloadLibs: + #reload.reloadAll(libPath) - mods = importModules('', globals(), locals()) - #for f in frozenSupport.listdir(libPath): - #pathName, ext = os.path.splitext(f) - #if ext not in ('.py', '.pyc') or '__init__' in pathName or '__pycache__' in pathName: - #continue - #try: - ##print "importing from", f - #mod = __import__(pathName, globals(), locals()) - #except: - #printExc("Error loading flowchart library %s:" % pathName) - #continue + #mods = importModules('', globals(), locals()) - for name, mod in mods.items(): - nodes = [] - for n in dir(mod): - o = getattr(mod, n) - if isNodeClass(o): - #print " ", str(o) - registerNodeType(o, [(name,)], override=reloadLibs) - #nodes.append((o.nodeName, o)) - #if len(nodes) > 0: - #NODE_TREE[name] = OrderedDict(nodes) - #NODE_LIST.extend(nodes) - #NODE_LIST = OrderedDict(NODE_LIST) + #for name, mod in mods.items(): + #nodes = [] + #for n in dir(mod): + #o = getattr(mod, n) + #if isNodeClass(o): + #registerNodeType(o, [(name,)], override=reloadLibs) -def reloadLibrary(): - loadLibrary(reloadLibs=True) +#def reloadLibrary(): + #loadLibrary(reloadLibs=True) -loadLibrary() -#NODE_LIST = [] -#for o in locals().values(): - #if type(o) is type(AddNode) and issubclass(o, Node) and o is not Node and hasattr(o, 'nodeName'): - #NODE_LIST.append((o.nodeName, o)) -#NODE_LIST.sort(lambda a,b: cmp(a[0], b[0])) -#NODE_LIST = OrderedDict(NODE_LIST) \ No newline at end of file +#loadLibrary() + + + diff --git a/pyqtgraph/opengl/__init__.py b/pyqtgraph/opengl/__init__.py index 5345e187..d10932a5 100644 --- a/pyqtgraph/opengl/__init__.py +++ b/pyqtgraph/opengl/__init__.py @@ -1,28 +1,20 @@ from .GLViewWidget import GLViewWidget -from pyqtgraph import importAll -#import os -#def importAll(path): - #d = os.path.join(os.path.split(__file__)[0], path) - #files = [] - #for f in os.listdir(d): - #if os.path.isdir(os.path.join(d, f)) and f != '__pycache__': - #files.append(f) - #elif f[-3:] == '.py' and f != '__init__.py': - #files.append(f[:-3]) - - #for modName in files: - #mod = __import__(path+"."+modName, globals(), locals(), fromlist=['*']) - #if hasattr(mod, '__all__'): - #names = mod.__all__ - #else: - #names = [n for n in dir(mod) if n[0] != '_'] - #for k in names: - #if hasattr(mod, k): - #globals()[k] = getattr(mod, k) +## dynamic imports cause too many problems. +#from pyqtgraph import importAll +#importAll('items', globals(), locals()) + +from .items.GLGridItem import * +from .items.GLBarGraphItem import * +from .items.GLScatterPlotItem import * +from .items.GLMeshItem import * +from .items.GLLinePlotItem import * +from .items.GLAxisItem import * +from .items.GLImageItem import * +from .items.GLSurfacePlotItem import * +from .items.GLBoxItem import * +from .items.GLVolumeItem import * -importAll('items', globals(), locals()) -\ from .MeshData import MeshData ## for backward compatibility: #MeshData.MeshData = MeshData ## breaks autodoc.