diff --git a/CHANGELOG b/CHANGELOG
index 9fa1098425456073717959c0084a5392a6967acf..64a030d60ab5ce412b0d6f01ffd87cfb35314595 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 bce37982ea40164239caa9a90cdde847b59b9c0a..25ea5c778c409293fdf5d7050c88df24943aab5d 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 f25d1c3a698bbb302f0a9e84ab108faf0e28dd4b..77b7c5905c1ba88ec0e3fece4f11b3200a5d1244 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
-
-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'])
+    #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)
+
+# 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 3ff2af31586a039fcb9f1b0b980ce8ee025f7aa6..c6386655bd99c2d6cd311cf8d2b48c3daaa46816 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 6371a3b973e712c4cafee423a26d26d5cfcb6e81..281fbb9aea55993c553b8d01c94ba392b0bf6672 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 9fb77e2afad5eed1dea183ae01136d96c8cdea16..40a76fbdb6f1ebd21d9b94a3e97a6fe1d918549a 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 76f878d292e24c45bb09320c257f06fe115b6c9e..420084685a3ef92101fdbf7d74397bdff82b75b2 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 5b31b45de4c510ec77a7e64ce664c4a1edc8ad00..ef35c2f846056d85b5e5a48e1b1ddb798fa09cd0 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 19a7a6a7791899ed68247f563ce07a980aa5c4c7..425f48e99475e88799b8d3a16549696d83457342 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 3f3c1f1d74c59224a8c028f7cee3caa42664817d..e2a81bc2b8c3f3a36a947dbe8d19bcc59e7bd0f6 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 81f9e1637712c356c1af502eb9fde35c62a6dd41..f566e97c4e710db11e3ad78ec20a8b06bfd95356 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 0000000000000000000000000000000000000000..20d0085e1edb0d82af9bb1c0c1864a1c1af84f9b
--- /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 1e44edff008a38fbcb01e24809918a07cb9b4d05..32a17b5840a97ff8629e868fd3472bb6ee9aacfe 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
+# 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],)])
+    
+#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).
+#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).
     
-    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))
+    #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))
     
-    name = cls.nodeName
-    if not override and name in NODE_LIST:
-        raise Exception("Node type name '%s' is already registered." % name)
+    #name = cls.nodeName
+    #if not override and name in NODE_LIST:
+        #raise Exception("Node type name '%s' is already registered." % name)
     
-    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
+    #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 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."""
+#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__))
+    #global NODE_LIST, NODE_TREE
     
-    if reloadLibs:
-        reload.reloadAll(libPath)
+    #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 5345e1872f9a1b45d60fbe819295d3aafaf97ae7..d10932a50529e40b34a077bf2683e23333b6700c 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.