]> rtime.felk.cvut.cz Git - CanFestival-3.git/blobdiff - objdictgen/nodemanager.py
Some instance type test improved
[CanFestival-3.git] / objdictgen / nodemanager.py
index e2d94a66ed3e39d43306cead502bb662c0e19165..e48c145f1a860f3350f3e5f6cf72534d7691134e 100755 (executable)
@@ -26,7 +26,7 @@ from gnosis.xml.pickle.util import setParanoia
 setParanoia(0)
 
 from node import *
-import xml_in, gen_cfile
+import eds_utils, gen_cfile
 
 from types import *
 import os, re
@@ -35,165 +35,15 @@ UndoBufferLength = 20
 
 type_model = re.compile('([\_A-Z]*)([0-9]*)')
 range_model = re.compile('([\_A-Z]*)([0-9]*)\[([\-0-9]*)-([\-0-9]*)\]')
-name_model = re.compile('(.*)\[(.*)\]')
 
-def IsOfType(object, typedef):
-    return type(object) == typedef
-
-#-------------------------------------------------------------------------------
-#                           Formating Name of an Entry
-#-------------------------------------------------------------------------------
-
-"""
-Format the text given with the index and subindex defined
-"""
-
-def StringFormat(text, idx, sub):
-    result = name_model.match(text)
-    if result:
-        format = result.groups()
-        return format[0]%eval(format[1])
-    else:
-        return text
-
-#-------------------------------------------------------------------------------
-#                         Search in a Mapping Dictionary
-#-------------------------------------------------------------------------------
-
-"""
-Return the index of the informations in the Object Dictionary in case of identical
-indexes
-"""
-def FindIndex(index, mappingdictionary):
-    if index in mappingdictionary:
-        return index
-    else:
-        listpluri = [idx for idx in mappingdictionary.keys() if mappingdictionary[idx]["struct"] & OD_IdenticalIndexes]
-        listpluri.sort()
-        for idx in listpluri:
-            nb_max = mappingdictionary[idx]["nbmax"]
-            incr = mappingdictionary[idx]["incr"]
-            if idx < index < idx + incr * nb_max and (index - idx)%incr == 0:
-                return idx
-    return None
-
-"""
-Return the index of the typename given by searching in mappingdictionary 
-"""
-def FindTypeIndex(typename, mappingdictionary):
-    testdic = {}
-    for index, values in mappingdictionary.iteritems():
-        if index < 0x1000:
-            testdic[values["name"]] = index
-    if typename in testdic:
-        return testdic[typename]
-    return None
-
-"""
-Return the name of the type by searching in mappingdictionary 
-"""
-def FindTypeName(typeindex, mappingdictionary):
-    if typeindex < 0x1000 and typeindex in mappingdictionary:
-        return mappingdictionary[typeindex]["name"]
-    return None
-
-"""
-Return the default value of the type by searching in mappingdictionary 
-"""
-def FindTypeDefaultValue(typeindex, mappingdictionary):
-    if typeindex < 0x1000 and typeindex in mappingdictionary:
-        return mappingdictionary[typeindex]["default"]
-    return None
-
-"""
-Return the list of types defined in mappingdictionary 
-"""
-def FindTypeList(mappingdictionary):
-    list = []
-    for index in mappingdictionary.keys():
-        if index < 0x1000:
-            list.append((index, mappingdictionary[index]["name"]))
-    return list
-
-"""
-Return the name of an entry by searching in mappingdictionary 
-"""
-def FindEntryName(index, mappingdictionary):
-    base_index = FindIndex(index, mappingdictionary)
-    if base_index:
-        infos = mappingdictionary[base_index]
-        if infos["struct"] & OD_IdenticalIndexes:
-            return StringFormat(infos["name"], (index - base_index) / infos["incr"] + 1, 0)
-        else:
-            return infos["name"]
-    return None
-
-"""
-Return the informations of one entry by searching in mappingdictionary 
-"""
-def FindEntryInfos(index, mappingdictionary):
-    base_index = FindIndex(index, mappingdictionary)
-    if base_index:
-        copy = mappingdictionary[base_index].copy()
-        if copy["struct"] & OD_IdenticalIndexes:
-            copy["name"] = StringFormat(copy["name"], (index - base_index) / copy["incr"] + 1, 0)
-        copy.pop("values")
-        return copy
-    return None
-
-"""
-Return the informations of one subentry of an entry by searching in mappingdictionary 
-"""
-def FindSubentryInfos(index, subIndex, mappingdictionary):
-    base_index = FindIndex(index, mappingdictionary)
-    if base_index:
-        struct = mappingdictionary[base_index]["struct"]
-        if struct & OD_Subindex:
-            if struct & OD_IdenticalSubindexes:
-                if struct & OD_IdenticalIndexes:
-                    incr = mappingdictionary[base_index]["incr"]
-                else:
-                    incr = 1
-                if subIndex == 0:
-                    return mappingdictionary[base_index]["values"][0].copy()
-                elif 0 < subIndex <= mappingdictionary[base_index]["values"][1]["nbmax"]:
-                    copy = mappingdictionary[base_index]["values"][1].copy()
-                    copy["name"] = StringFormat(copy["name"], (index - base_index) / incr + 1, subIndex)
-                    return copy
-            elif struct & OD_MultipleSubindexes and 0 <= subIndex < len(mappingdictionary[base_index]["values"]):
-                return mappingdictionary[base_index]["values"][subIndex].copy()
-            elif subIndex == 0:
-                return mappingdictionary[base_index]["values"][0].copy()
-    return None
-
-"""
-Return the list of variables that can be mapped defined in mappingdictionary 
-"""
-def FindMapVariableList(mappingdictionary, Manager):
-    list = []
-    for index in mappingdictionary.iterkeys():
-        if Manager.IsCurrentEntry(index):
-            for subIndex, values in enumerate(mappingdictionary[index]["values"]):
-                if mappingdictionary[index]["values"][subIndex]["pdo"]:
-                    infos = Manager.GetEntryInfos(mappingdictionary[index]["values"][subIndex]["type"])
-                    if mappingdictionary[index]["struct"] & OD_IdenticalSubindexes:
-                        values = Manager.GetCurrentEntry(index)
-                        for i in xrange(len(values) - 1):
-                            list.append((index, i + 1, infos["size"], StringFormat(mappingdictionary[index]["values"][subIndex]["name"],1,i+1)))
-                    else:
-                        list.append((index, subIndex, infos["size"], mappingdictionary[index]["values"][subIndex]["name"]))
-    return list
-
-"""
-Return the list of mandatory indexes defined in mappingdictionary 
-"""
-def FindMandatoryIndexes(mappingdictionary):
-    list = []
-    for index in mappingdictionary.iterkeys():
-        if index >= 0x1000 and mappingdictionary[index]["need"]:
-            list.append(index)
-    return list
+# ID for the file viewed
+CurrentID = 0
 
+# Returns a new id
+def GetNewId():
+    global CurrentID
+    CurrentID += 1
+    return CurrentID
 
 """
 Class implementing a buffer of changes made on the current editing Object Dictionary
@@ -302,54 +152,33 @@ class NodeManager:
     """
     def __init__(self):
         self.LastNewIndex = 0
-        self.FilePaths = []
-        self.FileNames = []
-        self.NodeIndex = -1
+        self.FilePaths = {}
+        self.FileNames = {}
+        self.NodeIndex = None
         self.CurrentNode = None
-        self.UndoBuffers = []
+        self.UndoBuffers = {}
 
 #-------------------------------------------------------------------------------
 #                         Type and Map Variable Lists
 #-------------------------------------------------------------------------------
-
-    """
-    Generate the list of types defined for the current node
-    """
-    def GenerateTypeList(self):
-        self.TypeList = ""
-        self.TypeTranslation = {}
-        list = self.GetTypeList()
-        sep = ""
-        for index, name in list:
-            self.TypeList += "%s%s"%(sep,name)
-            self.TypeTranslation[name] = index
-            sep = ","
-    
-    """
-    Generate the list of variables that can be mapped for the current node
-    """
-    def GenerateMapList(self):
-        self.MapList = "None"
-        self.NameTranslation = {"None" : "00000000"}
-        self.MapTranslation = {"00000000" : "None"}
-        list = self.GetMapVariableList()
-        for index, subIndex, size, name in list:
-            self.MapList += ",%s"%name
-            map = "%04X%02X%02X"%(index,subIndex,size)
-            self.NameTranslation[name] = map
-            self.MapTranslation[map] = name
     
     """
     Return the list of types defined for the current node
     """
     def GetCurrentTypeList(self):
-        return self.TypeList
+        if self.CurrentNode:
+            return self.CurrentNode.GetTypeList()
+        else:
+            return ""
 
     """
     Return the list of variables that can be mapped for the current node
     """
     def GetCurrentMapList(self):
-        return self.MapList
+        if self.CurrentNode:
+            return self.CurrentNode.GetMapList()
+        else:
+            return ""
 
 #-------------------------------------------------------------------------------
 #                        Create Load and Save Functions
@@ -358,30 +187,31 @@ class NodeManager:
     """
     Create a new node and add a new buffer for storing it
     """
-    def CreateNewNode(self, name, id, type, profile, filepath, NMT, options):
+    def CreateNewNode(self, name, id, type, description, profile, filepath, NMT, options):
         # Create a new node
         node = Node()
         # Try to load profile given
         result = self.LoadProfile(profile, filepath, node)
-        if not IsOfType(result, StringType):
+        if not result:
             # if success, initialising node
             self.CurrentNode = node
             self.CurrentNode.SetNodeName(name)
             self.CurrentNode.SetNodeID(id)
             self.CurrentNode.SetNodeType(type)
+            self.CurrentNode.SetNodeDescription(description)
             AddIndexList = self.GetMandatoryIndexes()
+            AddSubIndexList = []
             if NMT == "NodeGuarding":
                 AddIndexList.extend([0x100C, 0x100D])
             elif NMT == "Heartbeat":
                 AddIndexList.append(0x1017)
             for option in options:
                 if option == "DS302":
+                    DS302Path = os.path.join(os.path.split(__file__)[0], "config/DS-302.prf")
                     # Charging DS-302 profile if choosen by user
-                    if os.path.isfile("config/DS-302.prf"):
+                    if os.path.isfile(DS302Path):
                         try:
-                            Mapping = {}
-                            AddMenuEntries = []
-                            execfile("config/DS-302.prf")
+                            execfile(DS302Path)
                             self.CurrentNode.SetDS302Profile(Mapping)
                             self.CurrentNode.ExtendSpecificMenu(AddMenuEntries)
                         except:
@@ -396,15 +226,25 @@ class NodeManager:
                     AddIndexList.extend([0x1010, 0x1011, 0x1020])
                 elif option == "StoreEDS":
                     AddIndexList.extend([0x1021, 0x1022])
+            if type == "slave":
+                # add default SDO server
+                AddIndexList.append(0x1200)
+                # add default 4 receive and 4 transmit PDO
+                for comm, mapping in [(0x1400, 0x1600),(0x1800, 0x1A00)]:
+                    firstparamindex = self.GetLineFromIndex(comm)
+                    firstmappingindex = self.GetLineFromIndex(mapping)
+                    AddIndexList.extend(range(firstparamindex, firstparamindex + 4))
+                    for idx in range(firstmappingindex, firstmappingindex + 4):
+                        AddIndexList.append(idx)
+                        AddSubIndexList.append((idx, 8))
             # Add a new buffer 
-            self.AddNodeBuffer()
+            index = self.AddNodeBuffer(self.CurrentNode.Copy(), False)
             self.SetCurrentFilePath("")
             # Add Mandatory indexes
             self.ManageEntriesOfCurrent(AddIndexList, [])
-            # Regenerate lists
-            self.GenerateTypeList()
-            self.GenerateMapList()
-            return True
+            for idx, num in AddSubIndexList:
+                self.AddSubentriesToCurrent(idx, num)
+            return index
         else:
             return result
     
@@ -419,32 +259,33 @@ class NodeManager:
                 node.SetProfileName(profile)
                 node.SetProfile(Mapping)
                 node.SetSpecificMenu(AddMenuEntries)
-                return True
+                return None
             except:
-                return "Bad OD Profile file!\nSyntax Error."
+                return "Syntax Error\nBad OD Profile file!"
         else:
             # Default profile
             node.SetProfileName("None")
             node.SetProfile({})
             node.SetSpecificMenu([])
-            return True
+            return None
 
     """
     Open a file and store it in a new buffer
     """
     def OpenFileInCurrent(self, filepath):
-        # Open and load file
-        file = open(filepath, "r")
-        node = load(file)
-        file.close()
-        self.CurrentNode = node
-        # Add a new buffer and defining current state
-        self.AddNodeBuffer(self.CurrentNode.Copy(), True)
-        self.SetCurrentFilePath(filepath)
-        # Regenerate lists
-        self.GenerateTypeList()
-        self.GenerateMapList()
-        return True
+        try:
+            # Open and load file
+            file = open(filepath, "r")
+            node = load(file)
+            file.close()
+            self.CurrentNode = node
+            self.CurrentNode.SetNodeID(0)
+            # Add a new buffer and defining current state
+            index = self.AddNodeBuffer(self.CurrentNode.Copy(), True)
+            self.SetCurrentFilePath(filepath)
+            return index
+        except:
+            return "Unable to load file \"%s\"!"%filepath
 
     """
     Save current node in  a file
@@ -469,32 +310,50 @@ class NodeManager:
     """
     def CloseCurrent(self, ignore = False):
         # Verify if it's not forced that the current node is saved before closing it
-        if self.UndoBuffers[self.NodeIndex].IsCurrentSaved() or ignore:
+        if self.NodeIndex in self.UndoBuffers and (self.UndoBuffers[self.NodeIndex].IsCurrentSaved() or ignore):
             self.RemoveNodeBuffer(self.NodeIndex)
+            if len(self.UndoBuffers) > 0:
+                previousindexes = [idx for idx in self.UndoBuffers.keys() if idx < self.NodeIndex]
+                nextindexes = [idx for idx in self.UndoBuffers.keys() if idx > self.NodeIndex]
+                if len(previousindexes) > 0:
+                    previousindexes.sort()
+                    self.NodeIndex = previousindexes[-1]
+                elif len(nextindexes) > 0:
+                    nextindexes.sort()
+                    self.NodeIndex = nextindexes[0]
+                else:
+                    self.NodeIndex = None
+            else:
+                self.NodeIndex = None
             return True
         return False
 
     """
-    Import a xml file and store it in a new buffer if no node edited
+    Import an eds file and store it in a new buffer if no node edited
     """
-    def ImportCurrentFromFile(self, filepath):
+    def ImportCurrentFromEDSFile(self, filepath):
         # Generate node from definition in a xml file
-        node = xml_in.GenerateNode(filepath, self)
-        if node:
-            self.CurrentNode = node
-            self.GenerateTypeList()
-            self.GenerateMapList()
-            if len(self.UndoBuffers) == 0:
-                self.AddNodeBuffer()
-                self.SetCurrentFilePath("")
-            self.BufferCurrentNode()
-        return result
+        result = eds_utils.GenerateNode(filepath)
+        if isinstance(result, Node):
+            self.CurrentNode = result
+            index = self.AddNodeBuffer(self.CurrentNode.Copy(), False)
+            self.SetCurrentFilePath("")
+            return index
+        else:
+            return result
+    
+    """
+    Export to an eds file and store it in a new buffer if no node edited
+    """
+    def ExportCurrentToEDSFile(self, filepath):
+        return eds_utils.GenerateEDSFile(filepath, self.CurrentNode)
     
     """
     Build the C definition of Object Dictionary for current node 
     """
-    def ExportCurrentToFile(self, filepath):
-        return gen_cfile.GenerateFile(filepath, self)
+    def ExportCurrentToCFile(self, filepath):
+        if self.CurrentNode:
+            return gen_cfile.GenerateFile(filepath, self.CurrentNode)
 
 #-------------------------------------------------------------------------------
 #                        Add Entries to Current Functions
@@ -504,28 +363,36 @@ class NodeManager:
     Add the specified number of subentry for the given entry. Verify that total
     number of subentry (except 0) doesn't exceed nbmax defined
     """
-    def AddSubentriesToCurrent(self, index, number):
+    def AddSubentriesToCurrent(self, index, number, node = None):
+        disable_buffer = node != None
+        if node == None:
+            node = self.CurrentNode
         # Informations about entry
-        length = self.CurrentNode.GetEntry(index, 0)
-        infos = self.GetEntryInfos(index)
-        subentry_infos = self.GetSubentryInfos(index, 1)
+        length = node.GetEntry(index, 0)
+        infos = node.GetEntryInfos(index)
+        subentry_infos = node.GetSubentryInfos(index, 1)
         # Get default value for subindex
         if "default" in subentry_infos:
             default = subentry_infos["default"]
         else:
             default = self.GetTypeDefaultValue(subentry_infos["type"])   
         # First case entry is record
-        if infos["struct"] & OD_IdenticalSubindexes:
+        if infos["struct"] & OD_IdenticalSubindexes: 
             for i in xrange(1, min(number,subentry_infos["nbmax"]-length) + 1):
-                self.CurrentNode.AddEntry(index, length + i, default)
-            self.BufferCurrentNode()
+                node.AddEntry(index, length + i, default)
+            if not disable_buffer:
+                self.BufferCurrentNode()
+            return None
         # Second case entry is array, only possible for manufacturer specific
         elif infos["struct"] & OD_MultipleSubindexes and 0x2000 <= index <= 0x5FFF:
             values = {"name" : "Undefined", "type" : 5, "access" : "rw", "pdo" : True}
             for i in xrange(1, min(number,0xFE-length) + 1):
-                self.CurrentNode.AddMappingEntry(index, length + i, values = values.copy())
-                self.CurrentNode.AddEntry(index, length + i, 0)
-            self.BufferCurrentNode()
+                node.AddMappingEntry(index, length + i, values = values.copy())
+                node.AddEntry(index, length + i, 0)
+            if not disable_buffer:
+                self.BufferCurrentNode()
+            return None
+            
 
     """
     Remove the specified number of subentry for the given entry. Verify that total
@@ -535,9 +402,13 @@ class NodeManager:
         # Informations about entry
         infos = self.GetEntryInfos(index)
         length = self.CurrentNode.GetEntry(index, 0)
+        if "nbmin" in infos:
+            nbmin = infos["nbmin"]
+        else:
+            nbmin = 1
         # Entry is a record, or is an array of manufacturer specific
         if infos["struct"] & OD_IdenticalSubindexes or 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_IdenticalSubindexes:
-            for i in xrange(min(number, length - 1)):
+            for i in xrange(min(number, length - nbmin)):
                 self.RemoveCurrentVariable(index, length - i)
             self.BufferCurrentNode()
 
@@ -609,7 +480,10 @@ class NodeManager:
     """
     Add entries specified in addinglist and remove entries specified in removinglist
     """
-    def ManageEntriesOfCurrent(self, addinglist, removinglist):
+    def ManageEntriesOfCurrent(self, addinglist, removinglist, node = None):
+        disable_buffer = node != None
+        if node == None:
+            node = self.CurrentNode
         # Add all the entries in addinglist
         for index in addinglist:
             infos = self.GetEntryInfos(index)
@@ -621,7 +495,12 @@ class NodeManager:
                         default = subentry_infos["default"]
                     else:
                         default = self.GetTypeDefaultValue(subentry_infos["type"])
-                    self.CurrentNode.AddEntry(index, 1, default)
+                    node.AddEntry(index, value = [])
+                    if "nbmin" in subentry_infos:
+                        for i in xrange(subentry_infos["nbmin"]):
+                            node.AddEntry(index, i + 1, default)
+                    else:
+                        node.AddEntry(index, 1, default)
                 # Second case entry is a record
                 else:
                     i = 1
@@ -631,7 +510,7 @@ class NodeManager:
                             default = subentry_infos["default"]
                         else:
                             default = self.GetTypeDefaultValue(subentry_infos["type"])
-                        self.CurrentNode.AddEntry(index, i, default)
+                        node.AddEntry(index, i, default)
                         i += 1
                         subentry_infos = self.GetSubentryInfos(index, i)
             # Third case entry is a record
@@ -641,11 +520,31 @@ class NodeManager:
                     default = subentry_infos["default"]
                 else:
                     default = self.GetTypeDefaultValue(subentry_infos["type"])
-                self.CurrentNode.AddEntry(index, 0, default)
+                node.AddEntry(index, 0, default)
         # Remove all the entries in removinglist
         for index in removinglist:
             self.RemoveCurrentVariable(index)
-        self.BufferCurrentNode()
+        if not disable_buffer:
+            self.BufferCurrentNode()
+        return None
+
+
+    """
+    Reset an subentry from current node to its default value
+    """
+    def SetCurrentEntryToDefault(self, index, subindex, node = None):
+        disable_buffer = node != None
+        if node == None:
+            node = self.CurrentNode
+        if node.IsEntry(index, subindex):
+            subentry_infos = self.GetSubentryInfos(index, subindex)
+            if "default" in subentry_infos:
+                default = subentry_infos["default"]
+            else:
+                default = self.GetTypeDefaultValue(subentry_infos["type"])
+            node.SetEntry(index, subindex, default)
+            if not disable_buffer:
+                self.BufferCurrentNode()
 
     """
     Remove an entry from current node. Analize the index to perform the correct
@@ -696,31 +595,33 @@ class NodeManager:
                     self.CurrentNode.RemoveEntry(index, subIndex)
             if index in Mappings[-1]:
                 self.CurrentNode.RemoveMappingEntry(index, subIndex)
-            self.GenerateMapList()
 
-    def AddMapVariableToCurrent(self, index, name, struct, number):
+    def AddMapVariableToCurrent(self, index, name, struct, number, node = None):
         if 0x2000 <= index <= 0x5FFF:
-            if not self.CurrentNode.IsEntry(index):
-                self.CurrentNode.AddMappingEntry(index, name = name, struct = struct)
+            disable_buffer = node != None
+            if node == None:
+                node = self.CurrentNode
+            if not node.IsEntry(index):
+                node.AddMappingEntry(index, name = name, struct = struct)
                 if struct == var:
-                    values = {"name" : name, "type" : 5, "access" : "rw", "pdo" : True}
-                    self.CurrentNode.AddMappingEntry(index, 0, values = values)
-                    self.CurrentNode.AddEntry(index, 0, 0)
+                    values = {"name" : name, "type" : 0x05, "access" : "rw", "pdo" : True}
+                    node.AddMappingEntry(index, 0, values = values)
+                    node.AddEntry(index, 0, 0)
                 else:
-                    values = {"name" : "Number of Entries", "type" : 2, "access" : "ro", "pdo" : False}
-                    self.CurrentNode.AddMappingEntry(index, 0, values = values)
+                    values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False}
+                    node.AddMappingEntry(index, 0, values = values)
                     if struct == rec:
-                        values = {"name" : name + " %d[(sub)]", "type" : 5, "access" : "rw", "pdo" : True, "nbmax" : 0xFE}
-                        self.CurrentNode.AddMappingEntry(index, 1, values = values)
+                        values = {"name" : name + " %d[(sub)]", "type" : 0x05, "access" : "rw", "pdo" : True, "nbmax" : 0xFE}
+                        node.AddMappingEntry(index, 1, values = values)
                         for i in xrange(number):
-                            self.CurrentNode.AddEntry(index, i + 1, 0)
+                            node.AddEntry(index, i + 1, 0)
                     else:
                         for i in xrange(number):
-                            values = {"name" : "Undefined", "type" : 5, "access" : "rw", "pdo" : True}
-                            self.CurrentNode.AddMappingEntry(index, i + 1, values = values)
-                            self.CurrentNode.AddEntry(index, i + 1, 0)
-                self.GenerateMapList()
-                self.BufferCurrentNode()
+                            values = {"name" : "Undefined", "type" : 0x05, "access" : "rw", "pdo" : True}
+                            node.AddMappingEntry(index, i + 1, values = values)
+                            node.AddEntry(index, i + 1, 0)
+                if not disable_buffer:
+                    self.BufferCurrentNode()
                 return None
             else:
                 return "Index 0x%04X already defined!"%index
@@ -738,8 +639,8 @@ class NodeManager:
             default = self.GetTypeDefaultValue(type)
             if valuetype == 0:
                 self.CurrentNode.AddMappingEntry(index, name = "%s[%d-%d]"%(name, min, max), struct = 3, size = size, default = default)
-                self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
-                self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
+                self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
+                self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x05, "access" : "ro", "pdo" : False})
                 self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False})
                 self.CurrentNode.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False})
                 self.CurrentNode.AddEntry(index, 1, type)
@@ -747,12 +648,11 @@ class NodeManager:
                 self.CurrentNode.AddEntry(index, 3, max)
             elif valuetype == 1:
                 self.CurrentNode.AddMappingEntry(index, name = "%s%d"%(name, length), struct = 3, size = length * size, default = default)
-                self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
-                self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
-                self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False})
+                self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
+                self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x05, "access" : "ro", "pdo" : False})
+                self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x05, "access" : "ro", "pdo" : False})
                 self.CurrentNode.AddEntry(index, 1, type)
                 self.CurrentNode.AddEntry(index, 2, length)
-            self.GenerateTypeList()
             self.BufferCurrentNode()
             return None
         else:
@@ -769,15 +669,41 @@ class NodeManager:
                 self.CurrentNode.SetParamsEntry(index, None, callback = value)
                 self.BufferCurrentNode()
 
-    def SetCurrentEntry(self, index, subIndex, value, name, editor):
-        if self.CurrentNode and self.CurrentNode.IsEntry(index):
+    def SetCurrentEntry(self, index, subIndex, value, name, editor, node = None):
+        disable_buffer = node != None
+        if node == None:
+            node = self.CurrentNode
+        if node and node.IsEntry(index):
             if name == "value":
                 if editor == "map":
-                    value = eval("0x%s"%self.NameTranslation[value])
-                    self.CurrentNode.SetEntry(index, subIndex, value)
+                    value = node.GetMapValue(value)
+                    if value:
+                        node.SetEntry(index, subIndex, value)
                 elif editor == "bool":
                     value = value == "True"
-                    self.CurrentNode.SetEntry(index, subIndex, value)
+                    node.SetEntry(index, subIndex, value)
+                elif editor == "time":
+                    node.SetEntry(index, subIndex, value)
+                elif editor == "number":
+                    try:
+                        node.SetEntry(index, subIndex, int(value))
+                    except:
+                        pass
+                elif editor == "float":
+                    try:
+                        node.SetEntry(index, subIndex, float(value))
+                    except:
+                        pass
+                elif editor == "domain":
+                    try:
+                        if len(value) % 2 != 0:
+                            value = "0" + value
+                        value = value.decode('hex_codec')
+                        node.SetEntry(index, subIndex, value)
+                    except:
+                        pass
+                elif editor == "dcf":
+                    node.SetEntry(index, subIndex, value)
                 else:
                     subentry_infos = self.GetSubentryInfos(index, subIndex)
                     type = subentry_infos["type"]
@@ -785,34 +711,46 @@ class NodeManager:
                     for typeindex, typevalue in CustomisableTypes:
                         dic[typeindex] = typevalue
                     if type not in dic:
-                        type = self.CurrentNode.GetEntry(type)[1]
+                        type = node.GetEntry(type)[1]
                     if dic[type] == 0:
                         try:
-                            value = eval(value, {})
-                            self.CurrentNode.SetEntry(index, subIndex, value)
+                            if value.startswith("$NODEID"):
+                                value = "\"%s\""%value
+                            elif value.startswith("0x"):
+                                value = int(value, 16)
+                            else:
+                                value = int(value)
+                            node.SetEntry(index, subIndex, value)
                         except:
                             pass
                     else:
-                        self.CurrentNode.SetEntry(index, subIndex, value)
+                        node.SetEntry(index, subIndex, value)
             elif name in ["comment", "save"]:
                 if editor == "option":
                     value = value == "Yes"
                 if name == "save":
-                    self.CurrentNode.SetParamsEntry(index, subIndex, save = value)
+                    node.SetParamsEntry(index, subIndex, save = value)
                 elif name == "comment":
-                    self.CurrentNode.SetParamsEntry(index, subIndex, comment = value)
+                    node.SetParamsEntry(index, subIndex, comment = value)
             else:
                 if editor == "type":
-                    value = self.TypeTranslation[value]
-                elif editor == "access":
+                    value = self.GetTypeIndex(value)
+                    size = self.GetEntryInfos(value)["size"]
+                    node.UpdateMapVariable(index, subIndex, size)
+                elif editor in ["access","raccess"]:
                     dic = {}
                     for abbrev,access in AccessType.iteritems():
                         dic[access] = abbrev
                     value = dic[value]
-                self.CurrentNode.SetMappingEntry(index, subIndex, values = {name : value})
-                if name == "name":
-                    self.GenerateMapList()
-            self.BufferCurrentNode()
+                    if editor == "raccess" and not node.IsMappingEntry(index):
+                        entry_infos = self.GetEntryInfos(index)
+                        node.AddMappingEntry(index, name = entry_infos["name"], struct = 7)
+                        node.AddMappingEntry(index, 0, values = self.GetSubentryInfos(index, 0, False).copy())
+                        node.AddMappingEntry(index, 1, values = self.GetSubentryInfos(index, 1, False).copy())
+                node.SetMappingEntry(index, subIndex, values = {name : value})
+            if not disable_buffer:
+                self.BufferCurrentNode()
+            return None
 
     def SetCurrentEntryName(self, index, name):
         self.CurrentNode.SetMappingEntry(index, name=name)
@@ -858,13 +796,16 @@ class NodeManager:
 
     def OneFileHasChanged(self):
         result = False
-        for buffer in self.UndoBuffers:
+        for buffer in self.UndoBuffers.values():
             result |= not buffer.IsCurrentSaved()
         return result
 
     def GetBufferNumber(self):
         return len(self.UndoBuffers)
 
+    def GetBufferIndexes(self):
+        return self.UndoBuffers.keys()
+
     def LoadCurrentPrevious(self):
         self.CurrentNode = self.UndoBuffers[self.NodeIndex].Previous().Copy()
     
@@ -872,29 +813,21 @@ class NodeManager:
         self.CurrentNode = self.UndoBuffers[self.NodeIndex].Next().Copy()
 
     def AddNodeBuffer(self, currentstate = None, issaved = False):
-        self.NodeIndex = len(self.UndoBuffers)
-        self.UndoBuffers.append(UndoBuffer(currentstate, issaved))
-        self.FilePaths.append("")
-        self.FileNames.append("")
+        self.NodeIndex = GetNewId()
+        self.UndoBuffers[self.NodeIndex] = UndoBuffer(currentstate, issaved)
+        self.FilePaths[self.NodeIndex] = ""
+        self.FileNames[self.NodeIndex] = ""
+        return self.NodeIndex
 
     def ChangeCurrentNode(self, index):
-        if index < len(self.UndoBuffers):
+        if index in self.UndoBuffers.keys():
             self.NodeIndex = index
             self.CurrentNode = self.UndoBuffers[self.NodeIndex].Current().Copy()
-            self.GenerateTypeList()
-            self.GenerateMapList()
     
     def RemoveNodeBuffer(self, index):
         self.UndoBuffers.pop(index)
         self.FilePaths.pop(index)
         self.FileNames.pop(index)
-        self.NodeIndex = min(self.NodeIndex, len(self.UndoBuffers) - 1)
-        if len(self.UndoBuffers) > 0:
-            self.CurrentNode = self.UndoBuffers[self.NodeIndex].Current().Copy()
-            self.GenerateTypeList()
-            self.GenerateMapList()
-        else:
-            self.CurrentNode = None
     
     def GetCurrentNodeIndex(self):
         return self.NodeIndex
@@ -903,10 +836,9 @@ class NodeManager:
         return self.GetFilename(self.NodeIndex)
     
     def GetAllFilenames(self):
-        filenames = []
-        for i in xrange(len(self.UndoBuffers)):
-            filenames.append(self.GetFilename(i))
-        return filenames
+        indexes = self.UndoBuffers.keys()
+        indexes.sort()
+        return [self.GetFilename(idx) for idx in indexes]
     
     def GetFilename(self, index):
         if self.UndoBuffers[index].IsCurrentSaved():
@@ -987,19 +919,51 @@ class NodeManager:
 #-------------------------------------------------------------------------------
 #                         Node State and Values Functions
 #-------------------------------------------------------------------------------
+    
+    def GetCurrentNodeName(self):
+        if self.CurrentNode:
+            return self.CurrentNode.GetNodeName()
+        else:
+            return ""
+
+    def GetCurrentNodeCopy(self):
+        if self.CurrentNode:
+            return self.CurrentNode.Copy()
+        else:
+            return None
+    
+    def GetCurrentNodeID(self, node = None):
+        if self.CurrentNode:
+            return self.CurrentNode.GetNodeID()
+        else:
+            return None
 
     def GetCurrentNodeInfos(self):
         name = self.CurrentNode.GetNodeName()
         id = self.CurrentNode.GetNodeID()
         type = self.CurrentNode.GetNodeType()
-        return name, id, type
-        
-    def SetCurrentNodeInfos(self, name, id, type):
+        description = self.CurrentNode.GetNodeDescription()
+        return name, id, type, description
+    
+    def SetCurrentNodeInfos(self, name, id, type, description):
         self.CurrentNode.SetNodeName(name)
         self.CurrentNode.SetNodeID(id)
         self.CurrentNode.SetNodeType(type)
+        self.CurrentNode.SetNodeDescription(description)
         self.BufferCurrentNode()
 
+    def GetCurrentNodeDefaultStringSize(self):
+        if self.CurrentNode:
+            return self.CurrentNode.GetDefaultStringSize()
+        else:
+            return Node.DefaultStringSize
+    
+    def SetCurrentNodeDefaultStringSize(self, size):
+        if self.CurrentNode:
+            self.CurrentNode.SetDefaultStringSize(size)
+        else:
+            Node.DefaultStringSize = size
+
     def GetCurrentProfileName(self):
         if self.CurrentNode:
             return self.CurrentNode.GetProfileName()
@@ -1010,9 +974,9 @@ class NodeManager:
             return self.CurrentNode.IsEntry(index)
         return False
     
-    def GetCurrentEntry(self, index, subIndex = None):
+    def GetCurrentEntry(self, index, subIndex = None, compute = True):
         if self.CurrentNode:
-            return self.CurrentNode.GetEntry(index, subIndex)
+            return self.CurrentNode.GetEntry(index, subIndex, compute)
         return None
     
     def GetCurrentParamsEntry(self, index, subIndex = None):
@@ -1048,39 +1012,43 @@ class NodeManager:
         return validchoices
     
     def HasCurrentEntryCallbacks(self, index):
-        if self.CurrentNode and self.CurrentNode.IsEntry(index):
-            entry_infos = self.GetEntryInfos(index)
-            if "callback" in entry_infos:
-                return entry_infos["callback"]
+        if self.CurrentNode:
             return self.CurrentNode.HasEntryCallbacks(index)
         return False
     
     def GetCurrentEntryValues(self, index):
-        if self.CurrentNode and self.CurrentNode.IsEntry(index):
-            entry_infos = self.GetEntryInfos(index)
+        if self.CurrentNode:
+            return self.GetNodeEntryValues(self.CurrentNode, index)
+    
+    def GetNodeEntryValues(self, node, index):
+        if node and node.IsEntry(index):
+            entry_infos = node.GetEntryInfos(index)
             data = []
             editors = []
-            values = self.CurrentNode.GetEntry(index)
-            params = self.CurrentNode.GetParamsEntry(index)
-            if type(values) == ListType:
+            values = node.GetEntry(index, compute = False)
+            params = node.GetParamsEntry(index)
+            if isinstance(values, ListType):
                 for i, value in enumerate(values):
                     data.append({"value" : value})
-                    data[-1].update(params[i])
+                    data[-1].update(params[i])      
             else:
                 data.append({"value" : values})
                 data[-1].update(params)
             for i, dic in enumerate(data):
-                infos = self.GetSubentryInfos(index, i)
+                infos = node.GetSubentryInfos(index, i)
                 dic["subindex"] = "0x%02X"%i
                 dic["name"] = infos["name"]
-                dic["type"] = self.GetTypeName(infos["type"])
+                dic["type"] = node.GetTypeName(infos["type"])
                 dic["access"] = AccessType[infos["access"]]
                 dic["save"] = OptionType[dic["save"]]
                 editor = {"subindex" : None, "save" : "option", "callback" : "option", "comment" : "string"}
-                if type(values) == ListType and i == 0:
+                if isinstance(values, ListType) and i == 0:
                     editor["name"] = None
                     editor["type"] = None
-                    editor["access"] = None
+                    if 0x1600 <= index <= 0x17FF or 0x1A00 <= index <= 0x1C00:
+                        editor["access"] = "raccess"
+                    else:
+                        editor["access"] = None
                     editor["value"] = None
                 else:
                     if infos["user_defined"]:
@@ -1106,132 +1074,124 @@ class NodeManager:
                     if index < 0x260:
                         editor["value"] = None
                         if i == 1:
-                            dic["value"] = self.GetTypeName(dic["value"])
+                            dic["value"] = node.GetTypeName(dic["value"])
                     elif 0x1600 <= index <= 0x17FF or 0x1A00 <= index <= 0x1C00:
                         editor["value"] = "map"
-                        dic["value"] = self.MapTranslation["%08X"%dic["value"]]
+                        dic["value"] = node.GetMapName(dic["value"])
                     else:
-                        if dic["type"].startswith("VISIBLE_STRING"):
+                        if dic["type"].startswith("VISIBLE_STRING") or dic["type"].startswith("OCTET_STRING"):
                             editor["value"] = "string"
+                        elif dic["type"] in ["TIME_OF_DAY","TIME_DIFFERENCE"]:
+                            editor["value"] = "time"
+                        elif dic["type"] == "DOMAIN":
+                            if index == 0x1F22:
+                                editor["value"] = "dcf"
+                            else:
+                                editor["value"] = "domain"
+                            dic["value"] = dic["value"].encode('hex_codec')
                         elif dic["type"] == "BOOLEAN":
                             editor["value"] = "bool"
                             dic["value"] = BoolType[dic["value"]]
                         result = type_model.match(dic["type"])
                         if result:
                             values = result.groups()
-                            if values[0] in ["INTEGER", "UNSIGNED"]:
-                                format = "0x%0" + str(int(values[1])/4) + "X"
-                                dic["value"] = format%dic["value"]
+                            if values[0] == "UNSIGNED":
+                                try:
+                                    format = "0x%0" + str(int(values[1])/4) + "X"
+                                    dic["value"] = format%dic["value"]
+                                except:
+                                    pass
                                 editor["value"] = "string"
+                            if values[0] == "INTEGER":
+                                editor["value"] = "number"
                             elif values[0] == "REAL":
                                 editor["value"] = "float"
-                            elif values[0] == "VISIBLE_STRING":
+                            elif values[0] in ["VISIBLE_STRING", "OCTET_STRING"]:
                                 editor["length"] = values[0]
                         result = range_model.match(dic["type"])
                         if result:
                             values = result.groups()
-                            if values[0] in ("UNSIGNED", "REAL"):
+                            if values[0] in ["UNSIGNED", "INTEGER", "REAL"]:
                                 editor["min"] = values[2]
                                 editor["max"] = values[3]
                 editors.append(editor)
             return data, editors
         else:
             return None
-    
+
+    def AddToDCF(self, node_id, index, subindex, size, value):
+        if self.CurrentNode.IsEntry(0x1F22, node_id):
+            dcf_value = self.CurrentNode.GetEntry(0x1F22, node_id)
+            if dcf_value != "":
+                nbparams = BE_to_LE(dcf_value[:4])
+            else:
+                nbparams = 0
+            new_value = LE_to_BE(nbparams + 1, 4) + dcf_value[4:]
+            new_value += LE_to_BE(index, 2) + LE_to_BE(subindex, 1) + LE_to_BE(size, 4) + LE_to_BE(value, size)
+            self.CurrentNode.SetEntry(0x1F22, node_id, new_value)
+
 #-------------------------------------------------------------------------------
 #                         Node Informations Functions
 #-------------------------------------------------------------------------------
 
     def GetCustomisedTypeValues(self, index):
-        values = self.CurrentNode.GetEntry(index)
-        customisabletypes = self.GetCustomisableTypes()
-        return values, customisabletypes[values[1]][1]
-
-    def GetEntryName(self, index, node = True):
-        result = FindEntryName(index, MappingDictionary)
-        if result == None and node:
-            NodeMappings = self.CurrentNode.GetMappings()
-            i = 0
-            while not result and i < len(NodeMappings):
-                result = FindEntryName(index, NodeMappings[i])
-                i += 1
-        return result
-    
-    def GetEntryInfos(self, index, node = True):
-        result = FindEntryInfos(index, MappingDictionary)
-        if result == None and node:
-            NodeMappings = self.CurrentNode.GetMappings()
-            i = 0
-            while not result and i < len(NodeMappings):
-                result = FindEntryInfos(index, NodeMappings[i])
-                i += 1
-        return result
+        if self.CurrentNode:
+            values = self.CurrentNode.GetEntry(index)
+            customisabletypes = self.GetCustomisableTypes()
+            return values, customisabletypes[values[1]][1]
+        else:
+            return None, None
+
+    def GetEntryName(self, index):
+        if self.CurrentNode:
+            return self.CurrentNode.GetEntryName(index)
+        else:
+            return FindEntryName(index, MappingDictionary)
     
-    def GetSubentryInfos(self, index, subIndex, node = True):
-        result = FindSubentryInfos(index, subIndex, MappingDictionary)
-        if result == None and node:
-            NodeMappings = self.CurrentNode.GetMappings()
-            i = 0
-            while not result and i < len(NodeMappings):
-                result = FindSubentryInfos(index, subIndex, NodeMappings[i])
-                if result:
-                    result["user_defined"] = i == len(NodeMappings) - 1 and index >= 0x1000
-                i += 1
-        else :
-            result["user_defined"] = False
-        return result
+    def GetEntryInfos(self, index):
+        if self.CurrentNode:
+            return self.CurrentNode.GetEntryInfos(index)
+        else:
+            return FindEntryInfos(index, MappingDictionary)
     
-    def GetTypeIndex(self, typename, node = True):
-        result = FindTypeIndex(typename, MappingDictionary)
-        if result == None and node:
-            NodeMappings = self.CurrentNode.GetMappings()
-            i = 0
-            while not result and i < len(NodeMappings):
-                result = FindTypeIndex(typename, NodeMappings[i])
-                i += 1
-        return result
+    def GetSubentryInfos(self, index, subindex):
+        if self.CurrentNode:
+            return self.CurrentNode.GetSubentryInfos(index, subindex)
+        else:
+            result = FindSubentryInfos(index, subindex, MappingDictionary)
+            if result:
+                result["user_defined"] = False
+            return result
     
-    def GetTypeName(self, typeindex, node = True):
-        result = FindTypeName(typeindex, MappingDictionary)
-        if result == None and node:
-            NodeMappings = self.CurrentNode.GetMappings()
-            i = 0
-            while not result and i < len(NodeMappings):
-                result = FindTypeName(typeindex, NodeMappings[i])
-                i += 1
-        return result
+    def GetTypeIndex(self, typename):
+        if self.CurrentNode:
+            return self.CurrentNode.GetTypeIndex(typename)
+        else:
+            return FindTypeIndex(typename, MappingDictionary)
     
-    def GetTypeDefaultValue(self, typeindex, node = True):
-        result = FindTypeDefaultValue(typeindex, MappingDictionary)
-        if result == None and node:
-            NodeMappings = self.CurrentNode.GetMappings()
-            i = 0
-            while not result and i < len(NodeMappings):
-                result = FindTypeDefaultValue(typeindex, NodeMappings[i])
-                i += 1
-        return result
+    def GetTypeName(self, typeindex):
+        if self.CurrentNode:
+            return self.CurrentNode.GetTypeName(typeindex)
+        else:
+            return FindTypeName(typeindex, MappingDictionary)
     
-    def GetTypeList(self, node = True):
-        list = FindTypeList(MappingDictionary)
-        if node:
-            for NodeMapping in self.CurrentNode.GetMappings():
-                list.extend(FindTypeList(NodeMapping))
-        list.sort()
-        return list
+    def GetTypeDefaultValue(self, typeindex):
+        if self.CurrentNode:
+            return self.CurrentNode.GetTypeDefaultValue(typeindex)
+        else:
+            return FindTypeDefaultValue(typeindex, MappingDictionary)
     
     def GetMapVariableList(self):
-        list = FindMapVariableList(MappingDictionary, self)
-        for NodeMapping in self.CurrentNode.GetMappings():
-            list.extend(FindMapVariableList(NodeMapping, self))
-        list.sort()
-        return list
-    
-    def GetMandatoryIndexes(self, node = True):
-        list = FindMandatoryIndexes(MappingDictionary)
-        if node:
-            for NodeMapping in self.CurrentNode.GetMappings():
-                list.extend(FindMandatoryIndexes(NodeMapping))
-        return list
+        if self.CurrentNode:
+            return self.CurrentNode.GetMapVariableList()
+        else:
+            return []
+
+    def GetMandatoryIndexes(self):
+        if self.CurrentNode:
+            return self.CurrentNode.GetMandatoryIndexes()
+        else:
+            return FindMandatoryIndexes(MappingDictionary)
     
     def GetCustomisableTypes(self):
         dic = {}
@@ -1245,4 +1205,3 @@ class NodeManager:
             return self.CurrentNode.GetSpecificMenu()
         return []
 
-    
\ No newline at end of file