More precise design for plugins.... to be continued...
authoretisserant
Mon, 27 Aug 2007 17:54:55 +0200
changeset 13 f1f0edbeb313
parent 12 a1f9e514f708
child 14 eb9fdd316a40
More precise design for plugins.... to be continued...
Beremiz.py
plugger.py
plugins/__init__.py
plugins/__templates.py
plugins/canfestival/canfestival.py
plugins/svgui/svgui.py
--- a/Beremiz.py	Tue Aug 21 17:21:26 2007 +0200
+++ b/Beremiz.py	Mon Aug 27 17:54:55 2007 +0200
@@ -22,6 +22,8 @@
 #License along with this library; if not, write to the Free Software
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+__version__ = "$Revision$"
+
 import wx
 
 from time import localtime
@@ -41,43 +43,6 @@
 from plcopen.structures import IEC_KEYWORDS#, AddPlugin
 from PLCControler import PLCControler
 
-import plugins
-
-__version__ = "$Revision$"
-
-def create(parent):
-    return Beremiz(parent)
-
-def usage():
-    print "\nUsage of Beremiz.py :"
-    print "\n   %s [Projectpath]\n"%sys.argv[0]
-
-try:
-    opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
-except getopt.GetoptError:
-    # print help information and exit:
-    usage()
-    sys.exit(2)
-
-for o, a in opts:
-    if o in ("-h", "--help"):
-        usage()
-        sys.exit()
-
-projectOpen = None
-if len(args) > 1:
-    usage()
-    sys.exit()
-elif len(args) == 1:
-    projectOpen = args[0]
-CWD = sys.path[0]
-
-re_texts = {}
-re_texts["letter"] = "[A-Za-z]"
-re_texts["digit"] = "[0-9]"
-LOCATED_MODEL = re.compile("__LOCATED_VAR\(([A-Z]*),([_A-Za-z0-9]*)\)")
-
-
 class LogPseudoFile:
     """ Base class for file like objects to facilitate StdOut for the Shell."""
     def __init__(self, output = None):
@@ -328,8 +293,8 @@
               id=ID_BEREMIZDELETEBUSBUTTON)
         
         self._init_sizers()
-    
-    def __init__(self, parent):
+
+    def __init__(self, parent, projectOpen):
         self._init_ctrls(parent)
         
         for name in plugins.__all__:
@@ -680,6 +645,8 @@
         return (err, outdata, errdata)
 
     def BuildAutom(self):
+        LOCATED_MODEL = re.compile("__LOCATED_VAR\(([A-Z]*),([_A-Za-z0-9]*)\)")
+
         if self.PLCManager:
             self.TargetDir = os.path.join(self.CurrentProjectPath, "build")
             if not os.path.exists(self.TargetDir):
@@ -710,7 +677,7 @@
                 locations = []
                 lines = [line.strip() for line in location_file.readlines()]
                 for line in lines:
-                    result = LOCATED_MODEL.match(line)
+                    result = self.LOCATED_MODEL.match(line)
                     if result:
                         locations.append(result.groups())
                 self.Log.write("Generating Network Configurations...\n")
@@ -979,13 +946,37 @@
     sys.excepthook = handle_exception
 
 if __name__ == '__main__':
+    def usage():
+        print "\nUsage of Beremiz.py :"
+        print "\n   %s [Projectpath]\n"%sys.argv[0]
+    
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
+    except getopt.GetoptError:
+        # print help information and exit:
+        usage()
+        sys.exit(2)
+    
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+    
+    if len(args) > 1:
+        usage()
+        sys.exit()
+    elif len(args) == 1:
+        projectOpen = args[0]
+    else:
+        projectOpen = None
+    
     app = wx.PySimpleApp()
     wx.InitAllImageHandlers()
     
     # Install a exception handle for bug reports
     AddExceptHook(os.getcwd(),__version__)
     
-    frame = Beremiz(None)
+    frame = Beremiz(None, projectOpen)
 
     frame.Show()
     app.MainLoop()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugger.py	Mon Aug 27 17:54:55 2007 +0200
@@ -0,0 +1,90 @@
+import os
+import plugins
+from plugins import PlugTemplate
+
+
+class PluginsRoot(PlugTemplate):
+
+    # A special PlugChildsTypes
+    PlugChildsTypes = [(name,lambda : getattr(__import__("plugins." + name), name).RootClass) for name in plugins.__all__]
+
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:simpleType name="Win32Compiler">
+        <xsd:restriction base="xsd:string">
+          <xsd:enumeration value="Cygwin"/>
+          <xsd:enumeration value="MinGW"/>
+          <xsd:enumeration value="VC++"/>
+        </xsd:restriction>
+      </xsd:simpleType>
+      <xsd:element name="BeremizRoot">
+        <xsd:complexType>
+          <xsd:element name="TargetType">
+            <xsd:complexType>
+              <xsd:choice>
+                <xsd:element name="Win32">
+                  <xsd:complexType>
+                    <xsd:attribute name="ToolChain" type="ppx:Win32Compiler" use="required" default="MinGW"/>
+                    <xsd:attribute name="Priority" type="xsd:integer" use="required" default="0"/>
+                  </xsd:complexType>
+                </xsd:element>
+                <xsd:element name="Linux">
+                  <xsd:complexType>
+                    <xsd:attribute name="Compiler" type="xsd:string" use="required" default="0"/>
+                    <xsd:attribute name="Nice" type="xsd:integer" use="required" default="0"/>
+                  </xsd:complexType>
+                </xsd:element>
+                <xsd:element name="Xenomai">
+                  <xsd:complexType>
+                    <xsd:attribute name="xeno-config" type="xsd:string" use="required" default="0"/>
+                    <xsd:attribute name="Compiler" type="xsd:string" use="required" default="0"/>
+                    <xsd:attribute name="Priority" type="xsd:integer" use="required" default="0"/>
+                  </xsd:complexType>
+                </xsd:element>
+                <xsd:element name="RTAI">
+                  <xsd:complexType>
+                    <xsd:attribute name="xeno-config" type="xsd:string" use="required" default="0"/>
+                    <xsd:attribute name="Compiler" type="xsd:string" use="required" default="0"/>
+                    <xsd:attribute name="Priority" type="xsd:integer" use="required" default="0"/>
+                  </xsd:complexType>
+                </xsd:element>
+                <xsd:element name="Library">
+                  <xsd:complexType>
+                    <xsd:attribute name="Dynamic" type="xsd:boolean" default="true"/>
+                    <xsd:attribute name="Compiler" type="xsd:string" use="required" default="0"/>
+                  </xsd:complexType>
+                </xsd:element>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """
+
+    def __init__(self, ProjectPath):
+        # self is the parent
+        self.PlugParent = None
+        # Keep track of the plugin type name
+        self.PlugType = "Beremiz"
+        # Keep track of the root plugin (i.e. project path)
+        self.ProjectPath = ProjectPath
+        # Change XSD into class members
+        self._AddParamsMembers()
+        self.PluggedChilds = {}
+        # No IEC channel, name, etc...
+        self.MandatoryParams = []
+        # If dir have already be made, and file exist
+        if os.path.isdir(_self.PlugPath(PlugName)) and os.path.isfile(_self.PluginXmlFilePath(PlugName)):
+            #Load the plugin.xml file into parameters members
+            _self.LoadXMLParams()
+            #Load and init all the childs
+            _self.LoadChilds()
+
+    def PlugPath(self,PlugName=None):
+        return self.ProjectPath
+        
+    def PluginXmlFilePath(self, PlugName=None):
+        return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
+        
+    
--- a/plugins/__init__.py	Tue Aug 21 17:21:26 2007 +0200
+++ b/plugins/__init__.py	Mon Aug 27 17:54:55 2007 +0200
@@ -1,11 +1,10 @@
 from os import listdir, path
-from xmlclass import DeclareXSDClass
-from __templates import *
+from __templates import PlugTemplate
 
 _base_path = path.split(__file__)[0]
 
 __all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name != "CVS" or name.endswith(".py") and not name.startswith("__")]
 
-for name in __all__:
-    __import__(name, globals(), locals(), [])
+#for name in __all__:
+#    __import__(name, globals(), locals(), [])
 
--- a/plugins/__templates.py	Tue Aug 21 17:21:26 2007 +0200
+++ b/plugins/__templates.py	Mon Aug 27 17:54:55 2007 +0200
@@ -1,72 +1,289 @@
-" Here are base type definitions for plugins "
-
-class PluggableTemplate:
-
-    XSD = None
-    
-    def __init__(self, buspath):
-        pass
-
-    def TestModified(self):
-        return False
-        
-    def ReqSave(self):
-        return False
-
-    def Generate_C(self, dirpath, locations):
-        return [] # [filenames, ...]
-
-    def BlockTypesFactory(self):
-        return []
-
-    def STLibraryFactory(self):
-        return ""
-
-    ViewClass = None
-    View = None
-    def ViewFactory(self):
-        if self.ViewClass:
-            if not self.View:
-                def _onclose():
-                    self.View = None
-                self.View = self.ViewClass()
-                self.View.OnPluggClose = _onclose
-            return self.View
-        return None
-
-
-def _do_BaseParamsClasses():
-    Classes = {}
-    Types = {}
-    GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
+"""
+Base definitions for beremiz plugins
+"""
+
+import os
+import types
+import shutil
+from xml.dom import minidom
+
+_BaseParamsClass = GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
         <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
           <xsd:element name="BaseParams">
             <xsd:complexType>
-              <xsd:attribute name="Enabled" type="xsd:string" use="required" />
+              <xsd:attribute name="Name" type="xsd:string" use="required"/>
+              <xsd:attribute name="IEC_Channel" type="xsd:integer" use="required"  default="-1"/>
+              <xsd:attribute name="Enabled" type="xsd:boolean" use="required" default="true"/>
             </xsd:complexType>
           </xsd:element>
-        </xsd:schema>
-    """)
-    CreateClasses(Classes, Types)
-    
-    PluginsBaseParamsClass = Classes["BaseParams"]
-
-    Classes = {}
-    Types = {}
-    GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
-        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-          <xsd:element name="BaseParams">
-            <xsd:complexType>
-              <xsd:attribute name="BusId" type="xsd:integer" use="required" />
-              <xsd:attribute name="Name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:schema>
-    """)
-    CreateClasses(Classes, Types)
-    
-    BusBaseParamsClass = Classes["BaseParams"]
-    return PluginsBaseParamsClass, BusBaseParamsClass
-    
-PluginsBaseParamsClass, BusBaseParamsClass = _do_BaseParamsClasses()
-
+        </xsd:schema>""")[0]["BaseParams"]
+
+NameTypeSeparator = '@'
+
+class PlugTemplate:
+    """
+    This class is the one that define plugins.
+    """
+
+    XSD = None
+    PlugChildsTypes = []
+    PlugMaxCount = None
+    PluginMethods = []
+
+    def _AddParamsMembers(self):
+        Classes = GenerateClassesFromXSDstring(self.XSD)[0]
+        self.PlugParams = []
+        for name, XSDclass in Classes.items():
+            if XSDclass.IsBaseClass:
+                obj = XSDclass()
+                self.PlugParams.append( (name, obj) )
+                setattr(self, name, obj)
+
+    def __init__(self, PlugPath):
+        # Create BaseParam 
+        self.BaseParams = _BaseParamsClass()
+        self.MandatoryParams = [("BaseParams", self.BaseParams)]
+        self._AddParamsMembers()
+        self.PluggedChilds = {}
+    
+    def PluginXmlFilePath(self, PlugName=None):
+        return os.path.join(self.PlugPath(PlugName), "plugin.xml")
+
+    def PlugPath(self,PlugName=None):
+        if not PlugName:
+            PlugName = self.BaseParams.getName()
+        return os.path.join(self.PlugParent.PlugPath(), PlugName + NameTypeSeparator + self.PlugType)
+    
+    def PlugTestModified(self):
+        return False
+        
+    def OnPlugSave(self):
+        return True
+
+    def PlugRequestSave(self):
+        # If plugin do not have corresponding directory
+        if not os.path.isdir(self.PlugPath(PlugName)):
+            # Create it
+            os.mkdir(self.PlugPath(PlugName))
+
+        # generate XML for all XML parameters controllers of the plugin
+        XMLString = '<?xml version="1.0" encoding="UTF-8"?>'
+        for nodeName, XMLController in self.PlugParams + self.MandatoryParams:
+            XMLString += XMLController.generateXMLTextMethod(self, nodeName, 0)
+        XMLFile = open(self.PluginXmlFilePath(PlugName),'w')
+        XMLFile.write(XMLString)
+        XMLFile.close()
+        
+        # Call the plugin specific OnPlugSave method
+        self.OnPlugSave()
+        
+        # go through all childs and do the same
+        for PlugChild in self.IterChilds():
+            PlugChild.PlugRequestSave()
+    
+    def PlugImport(self, src_PlugPath):
+        shutil.copytree(src_PlugPath, self.PlugPath)
+        return True
+
+    def PlugGenerate_C(self, buildpath, current_location, locations):
+        """
+        Generate C code
+        @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
+        @param locations: List of complete variables locations \
+            [(IEC_loc, IEC_Direction IEC_Type, Name)]\
+            ex: [((0,0,4,5),'I','X','__IX_0_0_4_5'),...]
+        """
+        return [],""
+    
+    def _Generate_C(self, buildpath, current_location, locations):
+        # Generate plugins [(Cfiles, CFLAGS)], LDFLAGS
+        PlugCFilesAndCFLAGS, PlugLDFLAGS = self._Generate_C(buildpath, current_location, locations)
+        # recurse through all childs, and stack their results
+        for PlugChild in self.IterChilds():
+            # Get childs [(Cfiles, CFLAGS)], LDFLAGS
+            CFilesAndCFLAGS, LDFLAGS = \
+                PlugChild._Generate_C(
+                    #keep the same path
+                    buildpath,
+                    # but update location (add curent IEC channel at the end)
+                    current_location + (self.BaseParams.getIEC_Channel()),
+                    # filter locations that start with current IEC location
+                    [ (l,d,t,n) for l,d,t,n in locations if l[0:len(current_location)] == current_location ])
+            # stack the result
+            PlugCFilesAndCFLAGS += CFilesAndCFLAGS
+            PlugLDFLAGS += LDFLAGS
+        
+        return PlugCFilesAndCFLAGS,PlugLDFLAGS
+
+    def BlockTypesFactory(self):
+        return []
+
+    def STLibraryFactory(self):
+        return ""
+
+    def IterChilds(self):
+        for PlugType, PluggedChilds in self.PluggedChilds.items():
+            for PlugInstance in PluggedChilds:
+                   yield PlugInstance
+    
+    def _GetChildBySomething(self, sep, something, matching):
+        toks = matching.split(sep,1)
+        for PlugInstance in self.IterChilds:
+            # if match component of the name
+            if getattr(PlugInstance.BaseParams, something) == toks[0]:
+                # if Name have other components
+                if len(toks) == 2:
+                    # Recurse in order to find the latest object
+                    return PlugInstance._GetChildBySomething( sep, something, toks[1])
+                # No sub name -> found
+                return PlugInstance
+        # Not found
+        return None
+
+    def GetChildByName(self, Name):
+        return self._GetChildBySomething('.',"Name", Name)
+
+    def GetChildByIECLocation(self, Location):
+        return self._GetChildBySomething('_',"IEC_Channel", Name)
+    
+    def FindNewIEC_Channel(self, DesiredChannel):
+        """
+        Changes IEC Channel number to DesiredChannel if available, nearest available if not.
+        @param DesiredChannel: The desired IEC channel (int)
+        """
+        # Get Current IEC channel
+        CurrentChannel = self.BaseParams.getIEC_Channel()
+        # Do nothing if no change
+        if CurrentChannel == DesiredChannel: return CurrentChannel
+        # Build a list of used Channels out of parent's PluggedChilds
+        AllChannels=[]
+        for PlugInstance in self.PlugParent.IterChilds():
+            if PlugInstance != self:
+                AllChannels.append(PlugInstance.BaseParams.getIEC_Channel())
+        AllChannels.sort()
+
+        # Now, try to guess the nearest available channel
+        res = DesiredChannel
+        while res in AllChannels: # While channel not free
+            if res < CurrentChannel: # Want to go down ?
+                res -=  1 # Test for n-1
+                if res < 0 : return CurrentChannel # Can't go bellow 0, do nothing
+            else : # Want to go up ?
+                res +=  1 # Test for n-1
+        # Finally set IEC Channel
+        self.BaseParams.setIEC_Channel(res)
+        return res
+
+    def OnPlugClose(self):
+        return True
+
+    def _doRemoveChild(self, PlugInstance):
+        # Remove all childs of child
+        for SubPlugInstance in PlugInstance.IterChilds():
+            PlugInstance._doRemoveChild(SubPlugInstance)
+        # Call the OnCloseMethod
+        PlugInstance.OnPlugClose()
+        # Delete plugin dir
+        shutil.rmtree(PlugInstance.PlugPath())
+        # Remove child of PluggedChilds
+        self.PluggedChilds[PlugInstance.PlugType].remove(PlugInstance)
+        # Forget it... (View have to refresh)
+
+    def PlugRemoveChild(self, PlugName):
+        # Fetch the plugin
+        PlugInstance = self.GetChildByName(PlugName)
+        # Ask to his parent to remove it
+        PlugInstance.PlugParent._doRemoveChild(PlugInstance)
+
+    def PlugAddChild(self, PlugName, PlugType):
+        """
+        Create the plugins that may be added as child to this node self
+        @param PlugType: string desining the plugin class name (get name from PlugChildsTypes)
+        @param PlugName: string for the name of the plugin instance
+        """
+        PlugChildsTypes = dict(self.PlugChildsTypes)
+        # Check that adding this plugin is allowed
+        try:
+            PlugClass = PlugChildsTypes[PlugType]
+        except KeyError:
+            raise Exception, "Cannot create child %s of type %s "%(PlugName, PlugType)
+        
+        # if PlugClass is a class factory, call it. (prevent unneeded imports)
+        if type(PlugClass) == types.FunctionType:
+            PlugClass = PlugClass()
+        
+        # Eventualy Initialize child instance list for this class of plugin
+        PluggedChildsWithSameClass = self.PluggedChilds.setdefault(PlugType,list())
+        # Check count
+        if PlugClass.MaxCount and len(PluggedChildsWithSameClass) >= PlugClass.MaxCount:
+            raise Exception, "Max count (%d) reached for this plugin of type %s "%(PlugClass.MaxCount, PlugType)
+        
+        # create the final class, derived of provided plugin and template
+        class FinalPlugClass(PlugClass, PlugTemplate):
+            """
+            Plugin class is derivated into FinalPlugClass before being instanciated
+            This way __init__ is overloaded to ensure PlugTemplate.__init__ is called 
+            before PlugClass.__init__, and to do the file related stuff.
+            """
+            def __init__(_self):
+                # self is the parent
+                _self.PlugParent = self
+                # Keep track of the plugin type name
+                _self.PlugType = PlugType
+                # Call the base plugin template init - change XSD into class members
+                PlugTemplate.__init__(_self)
+                # If dir have already be made, and file exist
+                if os.path.isdir(_self.PlugPath(PlugName)) and os.path.isfile(_self.PluginXmlFilePath(PlugName)):
+                    #Load the plugin.xml file into parameters members
+                    _self.LoadXMLParams()
+                    # Call the plugin real __init__
+                    PlugClass.__init__(_self)
+                    #Load and init all the childs
+                    _self.LoadChilds()
+                    # Check that IEC_Channel is not already in use.
+                    self.FindNewIEC_Channel(self.BaseParams.getIEC_Channel())
+                else:
+                    # If plugin do not have corresponding file/dirs - they will be created on Save
+                    # Set plugin name
+                    _self.BaseParams.setName(PlugName)
+                    # Find an IEC number
+                    _self.FindNewIEC_Channel(0)
+                    # Call the plugin real __init__
+                    PlugClass.__init__(_self)
+
+        # Create the object out of the resulting class
+        newPluginOpj = FinalPlugClass()
+        # Store it in PluggedChils
+        PluggedChildsWithSameClass.append(newPluginOpj)
+        
+        return newPluginOpj
+            
+
+    def LoadXMLParams(self):
+        # PlugParams have been filled, make a local dict to work with
+        PlugParams = dict(self.PlugParams + self.MandatoryParams)
+        # Get the xml tree
+        xmlfile = open(self.PluginXmlFilePath(PlugName), 'r')
+        tree = minidom.parse(xmlfile)
+        xmlfile.close()
+        # for each root elements
+        for subtree in tree.childNodes:
+            # if a plugin specific parameter set
+            if subtree.nodeName in PlugParams:
+                #Load into associated xmlclass.
+                PlugParams[subtree.nodeName].loadXMLTree(subtree)
+        
+        # Basic check. Better to fail immediately.
+        if(self.BaseParams.getName() != PlugName):
+            raise Exception, "Project tree layout do not match plugin.xml %s!=%s "%(PlugName,self.BaseParams.getName())
+        # Now, self.PlugPath() should be OK
+
+    def LoadChilds(self):
+        # Iterate over all PlugName@PlugType in plugin directory, and try to open them
+        for PlugDir in os.listdir(self.PlugPath()):
+            if os.path.isdir(os.path.join(self.PlugPath(),PlugDir)) and \
+               PlugDir.count(NameTypeSeparator) == 1:
+                try:
+                    self.PlugAddChild(*PlugDir.split[NameTypeSeparator])
+                except Exception, e:
+                    print e
--- a/plugins/canfestival/canfestival.py	Tue Aug 21 17:21:26 2007 +0200
+++ b/plugins/canfestival/canfestival.py	Mon Aug 27 17:54:55 2007 +0200
@@ -4,12 +4,14 @@
 import config_utils, gen_cfile
 from networkedit import networkedit
 
-class _NetworkEditPlugg(networkedit):
+class _NetworkEdit(networkedit):
+    " Overload some of CanFestival Network Editor methods "
     def OnCloseFrame(self, event):
-        self.OnPluggClose()
+        " Do reset _NodeListPlug.View when closed"
+        self._onclose()
         event.Skip()
 
-class BusController(NodeList):
+class _NodeListPlug(NodeList):
     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       <xsd:element name="CanFestivalNode">
@@ -20,17 +22,29 @@
     </xsd:schema>
     """
 
-    ViewClass = _NetworkEditPlugg
-    
     def __init__(self, buspath):
         manager = NodeManager()
         NodeList.__init__(self, manager)
         self.LoadProject(buspath)
 
-    def TestModified(self):
+    _View = None
+    def _OpenView(self):
+        if not self._View:
+            def _onclose():
+                self.View = None
+            self._View = _NetworkEdit()
+            self._View._onclose = _onclose
+        return self.View
+    PluginMethods = [("NetworkEdit",_OpenView)]
+
+    def OnPlugClose(self):
+        if self._View:
+            self._View.Close()
+
+    def PlugTestModified(self):
         return self.HasChanged()
         
-    def ReqSave(self):
+    def PlugRequestSave(self):
         self.SaveProject()
         return True
 
@@ -43,14 +57,14 @@
         res = gen_cfile.GenerateFile(filepath, master)
         if not res:
              s = str(self.BaseParams.BusId)+"_IN(){}\n"
-             s += "CanOpen(str(\""+self.CanFestivalNode.CAN_Device)+"\")"
+             s += "CanOpen(\""+self.CanFestivalNode.CAN_Device+"\")"
              f = file(filepath, 'a')
              f.write(s)
         else:
              pass # error
         return {"headers":["master.h"],"sources":["master.c"]}
     
-class PluginController:
+class RootClass:
     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       <xsd:element name="CanFestivalInstance">
@@ -61,6 +75,8 @@
     </xsd:schema>
     """
 
+    PlugChildsTypes = [("CanOpenNode",_NodeListPlug)]
+
     def Generate_C(self, filepath, locations):
         """
         return C code for network dictionnary
@@ -69,7 +85,7 @@
         res = gen_cfile.GenerateFile(filepath, master)
         if not res:
              s = str(self.BaseParams.BusId)+"_IN(){}\n"
-             s += "CanOpen(str(\""+self.CanFestivalNode.CAN_Device)+"\")"
+             s += "CanOpen(str(\""+self.CanFestivalNode.CAN_Device+"\")"
              f = file(filepath, 'a')
              f.write(s)
         else:
--- a/plugins/svgui/svgui.py	Tue Aug 21 17:21:26 2007 +0200
+++ b/plugins/svgui/svgui.py	Mon Aug 27 17:54:55 2007 +0200
@@ -2,20 +2,20 @@
 from DEFControler import DEFControler
 from defeditor import EditorFrame
 
-class _EditorFramePlugg(EditorFrame):
+class _EditorFramePlug(EditorFrame):
     def OnClose(self, event):
-        self.OnPluggClose()
+        self.OnPlugClose()
         event.Skip()
 
-class BusController(DEFControler):
+class _DEFControlerPlug(DEFControler):
 
-    ViewClass = _EditorFramePlugg
+    ViewClass = _EditorFramePlug
     
     def __init__(self, buspath):
         filepath = os.path.join(buspath, "gui.def")
         if os.path.isfile(filepath):
             self.OpenXMLFile(filepath)
-        else
+        else:
             self.CreateRootElement()
             self.SetFilePath(filepath)
 
@@ -31,7 +31,10 @@
     "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
     "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
 
-class PluginController:
+class RootClass:
+    
+    ChildsType = _DEFControlerPlug
+    
     def BlockTypesFactory(self):
         def generate_svgui_block(generator, block, body, link):
             controller = generator.GetController()
@@ -39,7 +42,7 @@
             type = block.getTypeName()
             block_infos = GetBlockType(type)
             bus_id, name = [word for word in name.split("_") if word != ""]
-            block_id = self.PluginBuses[bus_id].GetElementIdFromName(name)
+            block_id = self.PlugChilds[bus_id].GetElementIdFromName(name)
             if block_id == None:
                 raise ValueError, "No corresponding block found"
             if not generator.ComputedBlocks.get(name, False):