]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/nodemanager.py
Adding support for importing and exporting EDS files
[CanFestival-3.git] / objdictgen / nodemanager.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 #This file is part of CanFestival, a library implementing CanOpen Stack. 
5 #
6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
7 #
8 #See COPYING file for copyrights details.
9 #
10 #This library is free software; you can redistribute it and/or
11 #modify it under the terms of the GNU Lesser General Public
12 #License as published by the Free Software Foundation; either
13 #version 2.1 of the License, or (at your option) any later version.
14 #
15 #This library is distributed in the hope that it will be useful,
16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 #Lesser General Public License for more details.
19 #
20 #You should have received a copy of the GNU Lesser General Public
21 #License along with this library; if not, write to the Free Software
22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
24 from gnosis.xml.pickle import *
25 from gnosis.xml.pickle.util import setParanoia
26 setParanoia(0)
27
28 from node import *
29 import eds_utils, gen_cfile
30
31 from types import *
32 import os, re
33
34 UndoBufferLength = 20
35
36 type_model = re.compile('([\_A-Z]*)([0-9]*)')
37 range_model = re.compile('([\_A-Z]*)([0-9]*)\[([\-0-9]*)-([\-0-9]*)\]')
38 name_model = re.compile('(.*)\[(.*)\]')
39
40 def IsOfType(object, typedef):
41     return type(object) == typedef
42
43 #-------------------------------------------------------------------------------
44 #                           Formating Name of an Entry
45 #-------------------------------------------------------------------------------
46
47 """
48 Format the text given with the index and subindex defined
49 """
50
51 def StringFormat(text, idx, sub):
52     result = name_model.match(text)
53     if result:
54         format = result.groups()
55         return format[0]%eval(format[1])
56     else:
57         return text
58
59 #-------------------------------------------------------------------------------
60 #                         Search in a Mapping Dictionary
61 #-------------------------------------------------------------------------------
62
63 """
64 Return the index of the informations in the Object Dictionary in case of identical
65 indexes
66 """
67 def FindIndex(index, mappingdictionary):
68     if index in mappingdictionary:
69         return index
70     else:
71         listpluri = [idx for idx in mappingdictionary.keys() if mappingdictionary[idx]["struct"] & OD_IdenticalIndexes]
72         listpluri.sort()
73         for idx in listpluri:
74             nb_max = mappingdictionary[idx]["nbmax"]
75             incr = mappingdictionary[idx]["incr"]
76             if idx < index < idx + incr * nb_max and (index - idx)%incr == 0:
77                 return idx
78     return None
79
80 """
81 Return the index of the typename given by searching in mappingdictionary 
82 """
83 def FindTypeIndex(typename, mappingdictionary):
84     testdic = {}
85     for index, values in mappingdictionary.iteritems():
86         if index < 0x1000:
87             testdic[values["name"]] = index
88     if typename in testdic:
89         return testdic[typename]
90     return None
91
92 """
93 Return the name of the type by searching in mappingdictionary 
94 """
95 def FindTypeName(typeindex, mappingdictionary):
96     if typeindex < 0x1000 and typeindex in mappingdictionary:
97         return mappingdictionary[typeindex]["name"]
98     return None
99
100 """
101 Return the default value of the type by searching in mappingdictionary 
102 """
103 def FindTypeDefaultValue(typeindex, mappingdictionary):
104     if typeindex < 0x1000 and typeindex in mappingdictionary:
105         return mappingdictionary[typeindex]["default"]
106     return None
107
108 """
109 Return the list of types defined in mappingdictionary 
110 """
111 def FindTypeList(mappingdictionary):
112     list = []
113     for index in mappingdictionary.keys():
114         if index < 0x1000:
115             list.append((index, mappingdictionary[index]["name"]))
116     return list
117
118 """
119 Return the name of an entry by searching in mappingdictionary 
120 """
121 def FindEntryName(index, mappingdictionary):
122     base_index = FindIndex(index, mappingdictionary)
123     if base_index:
124         infos = mappingdictionary[base_index]
125         if infos["struct"] & OD_IdenticalIndexes:
126             return StringFormat(infos["name"], (index - base_index) / infos["incr"] + 1, 0)
127         else:
128             return infos["name"]
129     return None
130
131 """
132 Return the informations of one entry by searching in mappingdictionary 
133 """
134 def FindEntryInfos(index, mappingdictionary):
135     base_index = FindIndex(index, mappingdictionary)
136     if base_index:
137         copy = mappingdictionary[base_index].copy()
138         if copy["struct"] & OD_IdenticalIndexes:
139             copy["name"] = StringFormat(copy["name"], (index - base_index) / copy["incr"] + 1, 0)
140         copy.pop("values")
141         return copy
142     return None
143
144 """
145 Return the informations of one subentry of an entry by searching in mappingdictionary 
146 """
147 def FindSubentryInfos(index, subIndex, mappingdictionary):
148     base_index = FindIndex(index, mappingdictionary)
149     if base_index:
150         struct = mappingdictionary[base_index]["struct"]
151         if struct & OD_Subindex:
152             if struct & OD_IdenticalSubindexes:
153                 if struct & OD_IdenticalIndexes:
154                     incr = mappingdictionary[base_index]["incr"]
155                 else:
156                     incr = 1
157                 if subIndex == 0:
158                     return mappingdictionary[base_index]["values"][0].copy()
159                 elif 0 < subIndex <= mappingdictionary[base_index]["values"][1]["nbmax"]:
160                     copy = mappingdictionary[base_index]["values"][1].copy()
161                     copy["name"] = StringFormat(copy["name"], (index - base_index) / incr + 1, subIndex)
162                     return copy
163             elif struct & OD_MultipleSubindexes and 0 <= subIndex < len(mappingdictionary[base_index]["values"]):
164                 return mappingdictionary[base_index]["values"][subIndex].copy()
165             elif subIndex == 0:
166                 return mappingdictionary[base_index]["values"][0].copy()
167     return None
168
169 """
170 Return the list of variables that can be mapped defined in mappingdictionary 
171 """
172 def FindMapVariableList(mappingdictionary, Manager):
173     list = []
174     for index in mappingdictionary.iterkeys():
175         if Manager.IsCurrentEntry(index):
176             for subIndex, values in enumerate(mappingdictionary[index]["values"]):
177                 if mappingdictionary[index]["values"][subIndex]["pdo"]:
178                     infos = Manager.GetEntryInfos(mappingdictionary[index]["values"][subIndex]["type"])
179                     if mappingdictionary[index]["struct"] & OD_IdenticalSubindexes:
180                         values = Manager.GetCurrentEntry(index)
181                         for i in xrange(len(values) - 1):
182                             list.append((index, i + 1, infos["size"], StringFormat(mappingdictionary[index]["values"][subIndex]["name"],1,i+1)))
183                     else:
184                         list.append((index, subIndex, infos["size"], mappingdictionary[index]["values"][subIndex]["name"]))
185     return list
186
187 """
188 Return the list of mandatory indexes defined in mappingdictionary 
189 """
190 def FindMandatoryIndexes(mappingdictionary):
191     list = []
192     for index in mappingdictionary.iterkeys():
193         if index >= 0x1000 and mappingdictionary[index]["need"]:
194             list.append(index)
195     return list
196
197
198 """
199 Class implementing a buffer of changes made on the current editing Object Dictionary
200 """
201
202 class UndoBuffer:
203
204     """
205     Constructor initialising buffer
206     """
207     def __init__(self, currentstate, issaved = False):
208         self.Buffer = []
209         self.CurrentIndex = -1
210         self.MinIndex = -1
211         self.MaxIndex = -1
212         # if current state is defined
213         if currentstate:
214             self.CurrentIndex = 0
215             self.MinIndex = 0
216             self.MaxIndex = 0
217         # Initialising buffer with currentstate at the first place
218         for i in xrange(UndoBufferLength):
219             if i == 0:
220                 self.Buffer.append(currentstate)
221             else:
222                 self.Buffer.append(None)
223         # Initialising index of state saved
224         if issaved:
225             self.LastSave = 0
226         else:
227             self.LastSave = -1
228     
229     """
230     Add a new state in buffer
231     """
232     def Buffering(self, currentstate):
233         self.CurrentIndex = (self.CurrentIndex + 1) % UndoBufferLength
234         self.Buffer[self.CurrentIndex] = currentstate
235         # Actualising buffer limits
236         self.MaxIndex = self.CurrentIndex
237         if self.MinIndex == self.CurrentIndex:
238             # If the removed state was the state saved, there is no state saved in the buffer
239             if self.LastSave == self.MinIndex:
240                 self.LastSave = -1
241             self.MinIndex = (self.MinIndex + 1) % UndoBufferLength
242         self.MinIndex = max(self.MinIndex, 0)
243     
244     """
245     Return current state of buffer
246     """
247     def Current(self):
248         return self.Buffer[self.CurrentIndex]
249     
250     """
251     Change current state to previous in buffer and return new current state
252     """
253     def Previous(self):
254         if self.CurrentIndex != self.MinIndex:
255             self.CurrentIndex = (self.CurrentIndex - 1) % UndoBufferLength
256             return self.Buffer[self.CurrentIndex]
257         return None
258     
259     """
260     Change current state to next in buffer and return new current state
261     """
262     def Next(self):
263         if self.CurrentIndex != self.MaxIndex:
264             self.CurrentIndex = (self.CurrentIndex + 1) % UndoBufferLength
265             return self.Buffer[self.CurrentIndex]
266         return None
267     
268     """
269     Return True if current state is the first in buffer
270     """
271     def IsFirst(self):
272         return self.CurrentIndex == self.MinIndex
273     
274     """
275     Return True if current state is the last in buffer
276     """
277     def IsLast(self):
278         return self.CurrentIndex == self.MaxIndex
279
280     """
281     Note that current state is saved
282     """
283     def CurrentSaved(self):
284         self.LastSave = self.CurrentIndex
285         
286     """
287     Return True if current state is saved
288     """
289     def IsCurrentSaved(self):
290         return self.LastSave == self.CurrentIndex
291
292
293
294 """
295 Class which control the operations made on the node and answer to view requests
296 """
297
298 class NodeManager:
299
300     """
301     Constructor
302     """
303     def __init__(self, cwd):
304         self.LastNewIndex = 0
305         self.FilePaths = []
306         self.FileNames = []
307         self.NodeIndex = -1
308         self.CurrentNode = None
309         self.ScriptDirectory = cwd
310         self.UndoBuffers = []
311
312 #-------------------------------------------------------------------------------
313 #                         Type and Map Variable Lists
314 #-------------------------------------------------------------------------------
315
316     """
317     Generate the list of types defined for the current node
318     """
319     def GenerateTypeList(self):
320         self.TypeList = ""
321         self.TypeTranslation = {}
322         list = self.GetTypeList()
323         sep = ""
324         for index, name in list:
325             self.TypeList += "%s%s"%(sep,name)
326             self.TypeTranslation[name] = index
327             sep = ","
328     
329     """
330     Generate the list of variables that can be mapped for the current node
331     """
332     def GenerateMapList(self):
333         self.MapList = "None"
334         self.NameTranslation = {"None" : "00000000"}
335         self.MapTranslation = {"00000000" : "None"}
336         list = self.GetMapVariableList()
337         for index, subIndex, size, name in list:
338             self.MapList += ",%s"%name
339             map = "%04X%02X%02X"%(index,subIndex,size)
340             self.NameTranslation[name] = map
341             self.MapTranslation[map] = name
342     
343     """
344     Return the list of types defined for the current node
345     """
346     def GetCurrentTypeList(self):
347         return self.TypeList
348
349     """
350     Return the list of variables that can be mapped for the current node
351     """
352     def GetCurrentMapList(self):
353         return self.MapList
354
355 #-------------------------------------------------------------------------------
356 #                        Create Load and Save Functions
357 #-------------------------------------------------------------------------------
358
359     """
360     Create a new node and add a new buffer for storing it
361     """
362     def CreateNewNode(self, name, id, type, description, profile, filepath, NMT, options):
363         # Create a new node
364         node = Node()
365         # Try to load profile given
366         result = self.LoadProfile(profile, filepath, node)
367         if not result:
368             # if success, initialising node
369             self.CurrentNode = node
370             self.CurrentNode.SetNodeName(name)
371             self.CurrentNode.SetNodeID(id)
372             self.CurrentNode.SetNodeType(type)
373             self.CurrentNode.SetNodeDescription(description)
374             AddIndexList = self.GetMandatoryIndexes()
375             if NMT == "NodeGuarding":
376                 AddIndexList.extend([0x100C, 0x100D])
377             elif NMT == "Heartbeat":
378                 AddIndexList.append(0x1017)
379             for option in options:
380                 if option == "DS302":
381                     DS302Path = os.path.join(self.ScriptDirectory, "config/DS-302.prf")
382                     # Charging DS-302 profile if choosen by user
383                     if os.path.isfile(DS302Path):
384                         try:
385                             execfile(DS302Path)
386                             self.CurrentNode.SetDS302Profile(Mapping)
387                             self.CurrentNode.ExtendSpecificMenu(AddMenuEntries)
388                         except:
389                             return "Problem with DS-302! Syntax Error."
390                     else:
391                         return "Couldn't find DS-302 in 'config' folder!"
392                 elif option == "GenSYNC":
393                     AddIndexList.extend([0x1005, 0x1006])
394                 elif option == "Emergency":
395                     AddIndexList.append(0x1014)
396                 elif option == "SaveConfig":
397                     AddIndexList.extend([0x1010, 0x1011, 0x1020])
398                 elif option == "StoreEDS":
399                     AddIndexList.extend([0x1021, 0x1022])
400             # Add a new buffer 
401             self.AddNodeBuffer()
402             self.SetCurrentFilePath("")
403             # Add Mandatory indexes
404             self.ManageEntriesOfCurrent(AddIndexList, [])
405             # Regenerate lists
406             self.GenerateTypeList()
407             self.GenerateMapList()
408             return True
409         else:
410             return result
411     
412     """
413     Load a profile in node
414     """
415     def LoadProfile(self, profile, filepath, node):
416         if profile != "None":
417             # Try to charge the profile given
418             try:
419                 execfile(filepath)
420                 node.SetProfileName(profile)
421                 node.SetProfile(Mapping)
422                 node.SetSpecificMenu(AddMenuEntries)
423                 return None
424             except:
425                 return "Syntax Error\nBad OD Profile file!."
426         else:
427             # Default profile
428             node.SetProfileName("None")
429             node.SetProfile({})
430             node.SetSpecificMenu([])
431             return None
432
433     """
434     Open a file and store it in a new buffer
435     """
436     def OpenFileInCurrent(self, filepath):
437         # Open and load file
438         file = open(filepath, "r")
439         node = load(file)
440         file.close()
441         self.CurrentNode = node
442         # Add a new buffer and defining current state
443         self.AddNodeBuffer(self.CurrentNode.Copy(), True)
444         self.SetCurrentFilePath(filepath)
445         # Regenerate lists
446         self.GenerateTypeList()
447         self.GenerateMapList()
448         return True
449
450     """
451     Save current node in  a file
452     """
453     def SaveCurrentInFile(self, filepath = None):
454         # if no filepath given, verify if current node has a filepath defined
455         if not filepath:
456             filepath = self.GetCurrentFilePath()
457             if filepath == "":
458                 return False
459         # Save node in file
460         file = open(filepath, "w")
461         dump(self.CurrentNode, file)
462         file.close()
463         self.SetCurrentFilePath(filepath)
464         # Update saved state in buffer
465         self.UndoBuffers[self.NodeIndex].CurrentSaved()
466         return True
467
468     """
469     Close current state
470     """
471     def CloseCurrent(self, ignore = False):
472         # Verify if it's not forced that the current node is saved before closing it
473         if self.UndoBuffers[self.NodeIndex].IsCurrentSaved() or ignore:
474             self.RemoveNodeBuffer(self.NodeIndex)
475             return True
476         return False
477
478     """
479     Import an eds file and store it in a new buffer if no node edited
480     """
481     def ImportCurrentFromEDSFile(self, filepath):
482         # Generate node from definition in a xml file
483         result = eds_utils.GenerateNode(filepath, self, self.ScriptDirectory)
484         if isinstance(result, Node):
485             self.CurrentNode = result
486             self.GenerateTypeList()
487             self.GenerateMapList()
488             if len(self.UndoBuffers) == 0:
489                 self.AddNodeBuffer()
490                 self.SetCurrentFilePath("")
491             self.BufferCurrentNode()
492             return None
493         else:
494             return result
495     
496     """
497     Export to an eds file and store it in a new buffer if no node edited
498     """
499     def ExportCurrentToEDSFile(self, filepath):
500         return eds_utils.GenerateEDSFile(filepath, self)
501     
502     """
503     Build the C definition of Object Dictionary for current node 
504     """
505     def ExportCurrentToCFile(self, filepath):
506         return gen_cfile.GenerateFile(filepath, self)
507
508 #-------------------------------------------------------------------------------
509 #                        Add Entries to Current Functions
510 #-------------------------------------------------------------------------------
511
512     """
513     Add the specified number of subentry for the given entry. Verify that total
514     number of subentry (except 0) doesn't exceed nbmax defined
515     """
516     def AddSubentriesToCurrent(self, index, number):
517         # Informations about entry
518         length = self.CurrentNode.GetEntry(index, 0)
519         infos = self.GetEntryInfos(index)
520         subentry_infos = self.GetSubentryInfos(index, 1)
521         # Get default value for subindex
522         if "default" in subentry_infos:
523             default = subentry_infos["default"]
524         else:
525             default = self.GetTypeDefaultValue(subentry_infos["type"])   
526         # First case entry is record
527         if infos["struct"] & OD_IdenticalSubindexes:
528             for i in xrange(1, min(number,subentry_infos["nbmax"]-length) + 1):
529                 self.CurrentNode.AddEntry(index, length + i, default)
530             self.BufferCurrentNode()
531         # Second case entry is array, only possible for manufacturer specific
532         elif infos["struct"] & OD_MultipleSubindexes and 0x2000 <= index <= 0x5FFF:
533             values = {"name" : "Undefined", "type" : 5, "access" : "rw", "pdo" : True}
534             for i in xrange(1, min(number,0xFE-length) + 1):
535                 self.CurrentNode.AddMappingEntry(index, length + i, values = values.copy())
536                 self.CurrentNode.AddEntry(index, length + i, 0)
537             self.BufferCurrentNode()
538
539     """
540     Remove the specified number of subentry for the given entry. Verify that total
541     number of subentry (except 0) isn't less than 1
542     """
543     def RemoveSubentriesFromCurrent(self, index, number):
544         # Informations about entry
545         infos = self.GetEntryInfos(index)
546         length = self.CurrentNode.GetEntry(index, 0)
547         # Entry is a record, or is an array of manufacturer specific
548         if infos["struct"] & OD_IdenticalSubindexes or 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_IdenticalSubindexes:
549             for i in xrange(min(number, length - 1)):
550                 self.RemoveCurrentVariable(index, length - i)
551             self.BufferCurrentNode()
552
553     """
554     Add a SDO Server to current node
555     """
556     def AddSDOServerToCurrent(self):
557         # An SDO Server is already defined at index 0x1200
558         if self.CurrentNode.IsEntry(0x1200):
559             indexlist = [self.GetLineFromIndex(0x1201)]
560             if None not in indexlist:
561                 self.ManageEntriesOfCurrent(indexlist, [])
562         # Add an SDO Server at index 0x1200
563         else:
564             self.ManageEntriesOfCurrent([0x1200], [])
565         
566     """
567     Add a SDO Server to current node
568     """
569     def AddSDOClientToCurrent(self):
570         indexlist = [self.GetLineFromIndex(0x1280)]
571         if None not in indexlist:
572             self.ManageEntriesOfCurrent(indexlist, [])
573
574     """
575     Add a Transmit PDO to current node
576     """
577     def AddPDOTransmitToCurrent(self):
578         indexlist = [self.GetLineFromIndex(0x1800),self.GetLineFromIndex(0x1A00)]
579         if None not in indexlist:
580             self.ManageEntriesOfCurrent(indexlist, [])
581         
582     """
583     Add a Receive PDO to current node
584     """
585     def AddPDOReceiveToCurrent(self):
586         indexlist = [self.GetLineFromIndex(0x1400),self.GetLineFromIndex(0x1600)]
587         if None not in indexlist:
588             self.ManageEntriesOfCurrent(indexlist, [])
589
590     """
591     Add a list of entries defined in profile for menu item selected to current node
592     """
593     def AddSpecificEntryToCurrent(self, menuitem):
594         indexlist = []
595         for menu, indexes in self.CurrentNode.GetSpecificMenu():
596             if menuitem == menu:
597                 for index in indexes:
598                     indexlist.append(self.GetLineFromIndex(index))
599         if None not in indexlist:
600             self.ManageEntriesOfCurrent(indexlist, [])
601
602     """
603     Search the first index available for a pluri entry from base_index
604     """
605     def GetLineFromIndex(self, base_index):
606         found = False
607         index = base_index
608         infos = self.GetEntryInfos(base_index)
609         while index < base_index + infos["incr"]*infos["nbmax"] and not found:
610             if not self.CurrentNode.IsEntry(index):
611                 found = True
612             else:
613                 index += infos["incr"]
614         if found:
615             return index
616         return None
617     
618     """
619     Add entries specified in addinglist and remove entries specified in removinglist
620     """
621     def ManageEntriesOfCurrent(self, addinglist, removinglist):
622         # Add all the entries in addinglist
623         for index in addinglist:
624             infos = self.GetEntryInfos(index)
625             if infos["struct"] & OD_MultipleSubindexes:
626                 # First case entry is a record
627                 if infos["struct"] & OD_IdenticalSubindexes:
628                     subentry_infos = self.GetSubentryInfos(index, 1)
629                     if "default" in subentry_infos:
630                         default = subentry_infos["default"]
631                     else:
632                         default = self.GetTypeDefaultValue(subentry_infos["type"])
633                     self.CurrentNode.AddEntry(index, 1, default)
634                 # Second case entry is a record
635                 else:
636                     i = 1
637                     subentry_infos = self.GetSubentryInfos(index, i)
638                     while subentry_infos:
639                         if "default" in subentry_infos:
640                             default = subentry_infos["default"]
641                         else:
642                             default = self.GetTypeDefaultValue(subentry_infos["type"])
643                         self.CurrentNode.AddEntry(index, i, default)
644                         i += 1
645                         subentry_infos = self.GetSubentryInfos(index, i)
646             # Third case entry is a record
647             else:
648                 subentry_infos = self.GetSubentryInfos(index, 0)
649                 if "default" in subentry_infos:
650                     default = subentry_infos["default"]
651                 else:
652                     default = self.GetTypeDefaultValue(subentry_infos["type"])
653                 self.CurrentNode.AddEntry(index, 0, default)
654         # Remove all the entries in removinglist
655         for index in removinglist:
656             self.RemoveCurrentVariable(index)
657         self.BufferCurrentNode()
658
659
660     """
661     Remove an entry from current node. Analize the index to perform the correct
662     method
663     """
664     def RemoveCurrentVariable(self, index, subIndex = None):
665         Mappings = self.CurrentNode.GetMappings()
666         if index < 0x1000 and subIndex == None:
667             type = self.CurrentNode.GetEntry(index, 1)
668             for i in Mappings[-1]:
669                 for value in Mappings[-1][i]["values"]:
670                     if value["type"] == index:
671                         value["type"] = type
672             self.CurrentNode.RemoveMappingEntry(index)
673             self.CurrentNode.RemoveEntry(index)
674         elif index == 0x1200 and subIndex == None:
675             self.CurrentNode.RemoveEntry(0x1200)
676         elif 0x1201 <= index <= 0x127F and subIndex == None:
677             self.CurrentNode.RemoveLine(index, 0x127F)
678         elif 0x1280 <= index <= 0x12FF and subIndex == None:
679             self.CurrentNode.RemoveLine(index, 0x12FF)
680         elif 0x1400 <= index <= 0x15FF or 0x1600 <= index <= 0x17FF and subIndex == None:
681             if 0x1600 <= index <= 0x17FF and subIndex == None:
682                 index -= 0x200
683             self.CurrentNode.RemoveLine(index, 0x15FF)
684             self.CurrentNode.RemoveLine(index + 0x200, 0x17FF)
685         elif 0x1800 <= index <= 0x19FF or 0x1A00 <= index <= 0x1BFF and subIndex == None:
686             if 0x1A00 <= index <= 0x1BFF:
687                 index -= 0x200
688             self.CurrentNode.RemoveLine(index, 0x19FF)
689             self.CurrentNode.RemoveLine(index + 0x200, 0x1BFF)
690         else:
691             found = False
692             for menu,list in self.CurrentNode.GetSpecificMenu():
693                 for i in list:
694                     iinfos = self.GetEntryInfos(i)
695                     indexes = [i + incr * iinfos["incr"] for incr in xrange(iinfos["nbmax"])] 
696                     if index in indexes:
697                         found = True
698                         diff = index - i
699                         for j in list:
700                             jinfos = self.GetEntryInfos(j)
701                             self.CurrentNode.RemoveLine(j + diff, j + jinfos["incr"]*jinfos["nbmax"], jinfos["incr"])
702             self.CurrentNode.RemoveMapVariable(index, subIndex)
703             if not found:
704                 infos = self.GetEntryInfos(index)
705                 if not infos["need"]:
706                     self.CurrentNode.RemoveEntry(index, subIndex)
707             if index in Mappings[-1]:
708                 self.CurrentNode.RemoveMappingEntry(index, subIndex)
709             self.GenerateMapList()
710
711     def AddMapVariableToCurrent(self, index, name, struct, number):
712         if 0x2000 <= index <= 0x5FFF:
713             if not self.CurrentNode.IsEntry(index):
714                 self.CurrentNode.AddMappingEntry(index, name = name, struct = struct)
715                 if struct == var:
716                     values = {"name" : name, "type" : 5, "access" : "rw", "pdo" : True}
717                     self.CurrentNode.AddMappingEntry(index, 0, values = values)
718                     self.CurrentNode.AddEntry(index, 0, 0)
719                 else:
720                     values = {"name" : "Number of Entries", "type" : 2, "access" : "ro", "pdo" : False}
721                     self.CurrentNode.AddMappingEntry(index, 0, values = values)
722                     if struct == rec:
723                         values = {"name" : name + " %d[(sub)]", "type" : 5, "access" : "rw", "pdo" : True, "nbmax" : 0xFE}
724                         self.CurrentNode.AddMappingEntry(index, 1, values = values)
725                         for i in xrange(number):
726                             self.CurrentNode.AddEntry(index, i + 1, 0)
727                     else:
728                         for i in xrange(number):
729                             values = {"name" : "Undefined", "type" : 5, "access" : "rw", "pdo" : True}
730                             self.CurrentNode.AddMappingEntry(index, i + 1, values = values)
731                             self.CurrentNode.AddEntry(index, i + 1, 0)
732                 self.GenerateMapList()
733                 self.BufferCurrentNode()
734                 return None
735             else:
736                 return "Index 0x%04X already defined!"%index
737         else:
738             return "Index 0x%04X isn't a valid index for Map Variable!"%index
739
740     def AddUserTypeToCurrent(self, type, min, max, length):
741         index = 0xA0
742         while index < 0x100 and self.CurrentNode.IsEntry(index):
743             index += 1
744         if index < 0x100:
745             customisabletypes = self.GetCustomisableTypes()
746             name, valuetype = customisabletypes[type]
747             size = self.GetEntryInfos(type)["size"]
748             default = self.GetTypeDefaultValue(type)
749             if valuetype == 0:
750                 self.CurrentNode.AddMappingEntry(index, name = "%s[%d-%d]"%(name, min, max), struct = 3, size = size, default = default)
751                 self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
752                 self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
753                 self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False})
754                 self.CurrentNode.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False})
755                 self.CurrentNode.AddEntry(index, 1, type)
756                 self.CurrentNode.AddEntry(index, 2, min)
757                 self.CurrentNode.AddEntry(index, 3, max)
758             elif valuetype == 1:
759                 self.CurrentNode.AddMappingEntry(index, name = "%s%d"%(name, length), struct = 3, size = length * size, default = default)
760                 self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
761                 self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
762                 self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False})
763                 self.CurrentNode.AddEntry(index, 1, type)
764                 self.CurrentNode.AddEntry(index, 2, length)
765             self.GenerateTypeList()
766             self.BufferCurrentNode()
767             return None
768         else:
769             return "Too many User Types have already been defined!"
770
771 #-------------------------------------------------------------------------------
772 #                      Modify Entry and Mapping Functions
773 #-------------------------------------------------------------------------------
774
775     def SetCurrentEntryCallbacks(self, index, value):
776         if self.CurrentNode and self.CurrentNode.IsEntry(index):
777             entry_infos = self.GetEntryInfos(index)
778             if "callback" not in entry_infos:
779                 self.CurrentNode.SetParamsEntry(index, None, callback = value)
780                 self.BufferCurrentNode()
781
782     def SetCurrentEntry(self, index, subIndex, value, name, editor):
783         if self.CurrentNode and self.CurrentNode.IsEntry(index):
784             if name == "value":
785                 if editor == "map":
786                     try:
787                         value = int(self.NameTranslation[value], 16)
788                         self.CurrentNode.SetEntry(index, subIndex, value)
789                     except:
790                         pass
791                 elif editor == "bool":
792                     value = value == "True"
793                     self.CurrentNode.SetEntry(index, subIndex, value)
794                 elif editor == "time":
795                     self.CurrentNode.SetEntry(index, subIndex, value)
796                 elif editor == "number":
797                     self.CurrentNode.SetEntry(index, subIndex, value)
798                 elif editor == "domain":
799                     try:
800                         if len(value) % 2 != 0:
801                             value = "0" + value
802                         value = value.decode('hex_codec')
803                         self.CurrentNode.SetEntry(index, subIndex, value)
804                     except:
805                         pass
806                 else:
807                     subentry_infos = self.GetSubentryInfos(index, subIndex)
808                     type = subentry_infos["type"]
809                     dic = {}
810                     for typeindex, typevalue in CustomisableTypes:
811                         dic[typeindex] = typevalue
812                     if type not in dic:
813                         type = self.CurrentNode.GetEntry(type)[1]
814                     if dic[type] == 0:
815                         try:
816                             value = int(value, 16)
817                             self.CurrentNode.SetEntry(index, subIndex, value)
818                         except:
819                             pass
820                     else:
821                         self.CurrentNode.SetEntry(index, subIndex, value)
822             elif name in ["comment", "save"]:
823                 if editor == "option":
824                     value = value == "Yes"
825                 if name == "save":
826                     self.CurrentNode.SetParamsEntry(index, subIndex, save = value)
827                 elif name == "comment":
828                     self.CurrentNode.SetParamsEntry(index, subIndex, comment = value)
829             else:
830                 if editor == "type":
831                     value = self.TypeTranslation[value]
832                     size = self.GetEntryInfos(value)["size"]
833                     self.CurrentNode.UpdateMapVariable(index, subIndex, size)
834                 elif editor in ["access","raccess"]:
835                     dic = {}
836                     for abbrev,access in AccessType.iteritems():
837                         dic[access] = abbrev
838                     value = dic[value]
839                     if editor == "raccess" and not self.CurrentNode.IsMappingEntry(index):
840                         entry_infos = self.GetEntryInfos(index)
841                         self.CurrentNode.AddMappingEntry(index, name = entry_infos["name"], struct = 7)
842                         self.CurrentNode.AddMappingEntry(index, 0, values = self.GetSubentryInfos(index, 0, False).copy())
843                         self.CurrentNode.AddMappingEntry(index, 1, values = self.GetSubentryInfos(index, 1, False).copy())
844                 self.CurrentNode.SetMappingEntry(index, subIndex, values = {name : value})
845                 if name == "name" or editor == "type":
846                     self.GenerateMapList()
847             self.BufferCurrentNode()
848
849     def SetCurrentEntryName(self, index, name):
850         self.CurrentNode.SetMappingEntry(index, name=name)
851         self.BufferCurrentNode()
852
853     def SetCurrentUserType(self, index, type, min, max, length):
854         customisabletypes = self.GetCustomisableTypes()
855         values, valuetype = self.GetCustomisedTypeValues(index)
856         name, new_valuetype = customisabletypes[type]
857         size = self.GetEntryInfos(type)["size"]
858         default = self.GetTypeDefaultValue(type)
859         if new_valuetype == 0:
860             self.CurrentNode.SetMappingEntry(index, name = "%s[%d-%d]"%(name, min, max), struct = 3, size = size, default = default) 
861             if valuetype == 1:
862                 self.CurrentNode.SetMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False})
863                 self.CurrentNode.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False})
864             self.CurrentNode.SetEntry(index, 1, type)
865             self.CurrentNode.SetEntry(index, 2, min)
866             if valuetype == 1:
867                 self.CurrentNode.AddEntry(index, 3, max)
868             else:
869                 self.CurrentNode.SetEntry(index, 3, max)
870         elif new_valuetype == 1:
871             self.CurrentNode.SetMappingEntry(index, name = "%s%d"%(name, length), struct = 3, size = size, default = default)
872             if valuetype == 0:
873                 self.CurrentNode.SetMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False})
874                 self.CurrentNode.RemoveMappingEntry(index, 3)
875             self.CurrentNode.SetEntry(index, 1, type)
876             self.CurrentNode.SetEntry(index, 2, length)
877             if valuetype == 0:
878                 self.CurrentNode.RemoveEntry(index, 3)
879         self.BufferCurrentNode()
880
881 #-------------------------------------------------------------------------------
882 #                      Current Buffering Management Functions
883 #-------------------------------------------------------------------------------
884
885     def BufferCurrentNode(self):
886         self.UndoBuffers[self.NodeIndex].Buffering(self.CurrentNode.Copy())
887
888     def CurrentIsSaved(self):
889         return self.UndoBuffers[self.NodeIndex].IsCurrentSaved()
890
891     def OneFileHasChanged(self):
892         result = False
893         for buffer in self.UndoBuffers:
894             result |= not buffer.IsCurrentSaved()
895         return result
896
897     def GetBufferNumber(self):
898         return len(self.UndoBuffers)
899
900     def LoadCurrentPrevious(self):
901         self.CurrentNode = self.UndoBuffers[self.NodeIndex].Previous().Copy()
902     
903     def LoadCurrentNext(self):
904         self.CurrentNode = self.UndoBuffers[self.NodeIndex].Next().Copy()
905
906     def AddNodeBuffer(self, currentstate = None, issaved = False):
907         self.NodeIndex = len(self.UndoBuffers)
908         self.UndoBuffers.append(UndoBuffer(currentstate, issaved))
909         self.FilePaths.append("")
910         self.FileNames.append("")
911
912     def ChangeCurrentNode(self, index):
913         if index < len(self.UndoBuffers):
914             self.NodeIndex = index
915             self.CurrentNode = self.UndoBuffers[self.NodeIndex].Current().Copy()
916             self.GenerateTypeList()
917             self.GenerateMapList()
918     
919     def RemoveNodeBuffer(self, index):
920         self.UndoBuffers.pop(index)
921         self.FilePaths.pop(index)
922         self.FileNames.pop(index)
923         self.NodeIndex = min(self.NodeIndex, len(self.UndoBuffers) - 1)
924         if len(self.UndoBuffers) > 0:
925             self.CurrentNode = self.UndoBuffers[self.NodeIndex].Current().Copy()
926             self.GenerateTypeList()
927             self.GenerateMapList()
928         else:
929             self.CurrentNode = None
930     
931     def GetCurrentNodeIndex(self):
932         return self.NodeIndex
933     
934     def GetCurrentFilename(self):
935         return self.GetFilename(self.NodeIndex)
936     
937     def GetAllFilenames(self):
938         filenames = []
939         for i in xrange(len(self.UndoBuffers)):
940             filenames.append(self.GetFilename(i))
941         return filenames
942     
943     def GetFilename(self, index):
944         if self.UndoBuffers[index].IsCurrentSaved():
945             return self.FileNames[index]
946         else:
947             return "~%s~"%self.FileNames[index]
948     
949     def SetCurrentFilePath(self, filepath):
950         self.FilePaths[self.NodeIndex] = filepath
951         if filepath == "":
952             self.LastNewIndex += 1
953             self.FileNames[self.NodeIndex] = "Unnamed%d"%self.LastNewIndex
954         else:
955             self.FileNames[self.NodeIndex] = os.path.splitext(os.path.basename(filepath))[0]
956                 
957     def GetCurrentFilePath(self):
958         if len(self.FilePaths) > 0:
959             return self.FilePaths[self.NodeIndex]
960         else:
961             return ""
962     
963     def GetCurrentBufferState(self):
964         first = self.UndoBuffers[self.NodeIndex].IsFirst()
965         last = self.UndoBuffers[self.NodeIndex].IsLast()
966         return not first, not last
967
968 #-------------------------------------------------------------------------------
969 #                         Profiles Management Functions
970 #-------------------------------------------------------------------------------
971
972     def GetCurrentCommunicationLists(self):
973         list = []
974         for index in MappingDictionary.iterkeys():
975             if 0x1000 <= index < 0x1200:
976                 list.append(index)
977         return self.GetProfileLists(MappingDictionary, list)
978     
979     def GetCurrentDS302Lists(self):
980         return self.GetSpecificProfileLists(self.CurrentNode.GetDS302Profile())
981     
982     def GetCurrentProfileLists(self):
983         return self.GetSpecificProfileLists(self.CurrentNode.GetProfile())
984     
985     def GetSpecificProfileLists(self, mappingdictionary):
986         validlist = []
987         exclusionlist = []
988         for name, list in self.CurrentNode.GetSpecificMenu():
989             exclusionlist.extend(list)
990         for index in mappingdictionary.iterkeys():
991             if index not in exclusionlist:
992                 validlist.append(index)
993         return self.GetProfileLists(mappingdictionary, validlist)
994     
995     def GetProfileLists(self, mappingdictionary, list):
996         dictionary = {}
997         current = []
998         for index in list:
999             dictionary[index] = (mappingdictionary[index]["name"], mappingdictionary[index]["need"])
1000             if self.CurrentNode.IsEntry(index):
1001                 current.append(index)
1002         return dictionary, current
1003
1004     def GetCurrentNextMapIndex(self):
1005         if self.CurrentNode:
1006             index = 0x2000
1007             while self.CurrentNode.IsEntry(index) and index < 0x5FFF:
1008                 index += 1
1009             if index < 0x6000:
1010                 return index
1011             else:
1012                 return None
1013
1014     def CurrentDS302Defined(self):
1015         if self.CurrentNode:
1016             return len(self.CurrentNode.GetDS302Profile()) > 0
1017         return False
1018
1019 #-------------------------------------------------------------------------------
1020 #                         Node State and Values Functions
1021 #-------------------------------------------------------------------------------
1022
1023     def GetCurrentNodeInfos(self):
1024         name = self.CurrentNode.GetNodeName()
1025         id = self.CurrentNode.GetNodeID()
1026         type = self.CurrentNode.GetNodeType()
1027         description = self.CurrentNode.GetNodeDescription()
1028         return name, id, type, description
1029         
1030     def SetCurrentNodeInfos(self, name, id, type, description):
1031         self.CurrentNode.SetNodeName(name)
1032         self.CurrentNode.SetNodeID(id)
1033         self.CurrentNode.SetNodeType(type)
1034         self.CurrentNode.SetNodeDescription(description)
1035         self.BufferCurrentNode()
1036
1037     def GetCurrentProfileName(self):
1038         if self.CurrentNode:
1039             return self.CurrentNode.GetProfileName()
1040         return ""
1041
1042     def IsCurrentEntry(self, index):
1043         if self.CurrentNode:
1044             return self.CurrentNode.IsEntry(index)
1045         return False
1046     
1047     def GetCurrentEntry(self, index, subIndex = None):
1048         if self.CurrentNode:
1049             return self.CurrentNode.GetEntry(index, subIndex)
1050         return None
1051     
1052     def GetCurrentParamsEntry(self, index, subIndex = None):
1053         if self.CurrentNode:
1054             return self.CurrentNode.GetParamsEntry(index, subIndex)
1055         return None
1056     
1057     def GetCurrentValidIndexes(self, min, max):
1058         validindexes = []
1059         for index in self.CurrentNode.GetIndexes():
1060             if min <= index <= max:
1061                 validindexes.append((self.GetEntryName(index), index))
1062         return validindexes
1063         
1064     def GetCurrentValidChoices(self, min, max):
1065         validchoices = []
1066         exclusionlist = []
1067         for menu, indexes in self.CurrentNode.GetSpecificMenu():
1068             exclusionlist.extend(indexes)
1069             good = True
1070             for index in indexes:
1071                 good &= min <= index <= max
1072             if good:
1073                 validchoices.append((menu, None))
1074         list = [index for index in MappingDictionary.keys() if index >= 0x1000]
1075         profiles = self.CurrentNode.GetMappings(False)
1076         for profile in profiles:
1077             list.extend(profile.keys())
1078         list.sort()
1079         for index in list:
1080             if min <= index <= max and not self.CurrentNode.IsEntry(index) and index not in exclusionlist:
1081                 validchoices.append((self.GetEntryName(index), index))
1082         return validchoices
1083     
1084     def HasCurrentEntryCallbacks(self, index):
1085         if self.CurrentNode and self.CurrentNode.IsEntry(index):
1086             entry_infos = self.GetEntryInfos(index)
1087             if "callback" in entry_infos:
1088                 return entry_infos["callback"]
1089             return self.CurrentNode.HasEntryCallbacks(index)
1090         return False
1091     
1092     def GetCurrentEntryValues(self, index):
1093         if self.CurrentNode and self.CurrentNode.IsEntry(index):
1094             entry_infos = self.GetEntryInfos(index)
1095             data = []
1096             editors = []
1097             values = self.CurrentNode.GetEntry(index)
1098             params = self.CurrentNode.GetParamsEntry(index)
1099             if type(values) == ListType:
1100                 for i, value in enumerate(values):
1101                     data.append({"value" : value})
1102                     data[-1].update(params[i])      
1103             else:
1104                 data.append({"value" : values})
1105                 data[-1].update(params)
1106             for i, dic in enumerate(data):
1107                 infos = self.GetSubentryInfos(index, i)
1108                 dic["subindex"] = "0x%02X"%i
1109                 dic["name"] = infos["name"]
1110                 dic["type"] = self.GetTypeName(infos["type"])
1111                 dic["access"] = AccessType[infos["access"]]
1112                 dic["save"] = OptionType[dic["save"]]
1113                 editor = {"subindex" : None, "save" : "option", "callback" : "option", "comment" : "string"}
1114                 if type(values) == ListType and i == 0:
1115                     editor["name"] = None
1116                     editor["type"] = None
1117                     if 0x1600 <= index <= 0x17FF or 0x1A00 <= index <= 0x1C00:
1118                         editor["access"] = "raccess"
1119                     else:
1120                         editor["access"] = None
1121                     editor["value"] = None
1122                 else:
1123                     if infos["user_defined"]:
1124                         if entry_infos["struct"] & OD_IdenticalSubindexes:
1125                             editor["name"] = None
1126                             if i > 1:
1127                                 editor["type"] = None
1128                                 editor["access"] = None
1129                             else:
1130                                 editor["type"] = "type"
1131                                 editor["access"] = "access"
1132                         else:
1133                             if entry_infos["struct"] & OD_MultipleSubindexes:
1134                                 editor["name"] = "string"
1135                             else:
1136                                 editor["name"] = None
1137                             editor["type"] = "type"
1138                             editor["access"] = "access"
1139                     else:
1140                         editor["name"] = None
1141                         editor["type"] = None
1142                         editor["access"] = None
1143                     if index < 0x260:
1144                         editor["value"] = None
1145                         if i == 1:
1146                             dic["value"] = self.GetTypeName(dic["value"])
1147                     elif 0x1600 <= index <= 0x17FF or 0x1A00 <= index <= 0x1C00:
1148                         editor["value"] = "map"
1149                         dic["value"] = self.MapTranslation["%08X"%dic["value"]]
1150                     else:
1151                         if dic["type"].startswith("VISIBLE_STRING"):
1152                             editor["value"] = "string"
1153                         elif dic["type"] in ["TIME_OF_DAY","TIME_DIFFERENCE"]:
1154                             editor["value"] = "time"
1155                         elif dic["type"] == "DOMAIN":
1156                             editor["value"] = "domain"
1157                             dic["value"] = dic["value"].encode('hex_codec')
1158                         elif dic["type"] == "BOOLEAN":
1159                             editor["value"] = "bool"
1160                             dic["value"] = BoolType[dic["value"]]
1161                         result = type_model.match(dic["type"])
1162                         if result:
1163                             values = result.groups()
1164                             if values[0] == "UNSIGNED":
1165                                 format = "0x%0" + str(int(values[1])/4) + "X"
1166                                 dic["value"] = format%dic["value"]
1167                                 editor["value"] = "string"
1168                             if values[0] == "INTEGER":
1169                                 editor["value"] = "number"
1170                             elif values[0] == "REAL":
1171                                 editor["value"] = "float"
1172                             elif values[0] == "VISIBLE_STRING":
1173                                 editor["length"] = values[0]
1174                         result = range_model.match(dic["type"])
1175                         if result:
1176                             values = result.groups()
1177                             if values[0] in ["UNSIGNED", "INTEGER", "REAL"]:
1178                                 editor["min"] = values[2]
1179                                 editor["max"] = values[3]
1180                 editors.append(editor)
1181             return data, editors
1182         else:
1183             return None
1184     
1185 #-------------------------------------------------------------------------------
1186 #                         Node Informations Functions
1187 #-------------------------------------------------------------------------------
1188
1189     def GetCustomisedTypeValues(self, index):
1190         values = self.CurrentNode.GetEntry(index)
1191         customisabletypes = self.GetCustomisableTypes()
1192         return values, customisabletypes[values[1]][1]
1193
1194     def GetEntryName(self, index, node = None):
1195         result = None
1196         if node == None:
1197             node = self.CurrentNode
1198         NodeMappings = node.GetMappings()
1199         i = 0
1200         while not result and i < len(NodeMappings):
1201             result = FindEntryName(index, NodeMappings[i])
1202             i += 1
1203         if result == None:
1204             result = FindEntryName(index, MappingDictionary)
1205         return result
1206     
1207     def GetEntryInfos(self, index, node = None):
1208         result = None
1209         if node == None:
1210             node = self.CurrentNode
1211         NodeMappings = node.GetMappings()
1212         i = 0
1213         while not result and i < len(NodeMappings):
1214             result = FindEntryInfos(index, NodeMappings[i])
1215             i += 1
1216         if result == None:
1217             result = FindEntryInfos(index, MappingDictionary)
1218         return result
1219     
1220     def GetSubentryInfos(self, index, subIndex, node = None):
1221         result = None
1222         if node == None:
1223             node = self.CurrentNode
1224         NodeMappings = node.GetMappings()
1225         i = 0
1226         while not result and i < len(NodeMappings):
1227             result = FindSubentryInfos(index, subIndex, NodeMappings[i])
1228             if result:
1229                 result["user_defined"] = i == len(NodeMappings) - 1 and index >= 0x1000
1230             i += 1
1231         if result == None:    
1232             result = FindSubentryInfos(index, subIndex, MappingDictionary)
1233             if result:
1234                 result["user_defined"] = False
1235         return result
1236     
1237     def GetTypeIndex(self, typename, node = None):
1238         result = None
1239         if node == None:
1240             node = self.CurrentNode
1241         NodeMappings = node.GetMappings()
1242         i = 0
1243         while not result and i < len(NodeMappings):
1244             result = FindTypeIndex(typename, NodeMappings[i])
1245             i += 1
1246         if result == None:
1247             result = FindTypeIndex(typename, MappingDictionary)
1248         return result
1249     
1250     def GetTypeName(self, typeindex, node = None):
1251         result = None
1252         if node == None:
1253             node = self.CurrentNode
1254         NodeMappings = node.GetMappings()
1255         i = 0
1256         while not result and i < len(NodeMappings):
1257             result = FindTypeName(typeindex, NodeMappings[i])
1258             i += 1
1259         if result == None:
1260             result = FindTypeName(typeindex, MappingDictionary)
1261         return result
1262     
1263     def GetTypeDefaultValue(self, typeindex, node = None):
1264         result = None
1265         if node == None:
1266             node = self.CurrentNode
1267         if node:
1268             NodeMappings = node.GetMappings()
1269             i = 0
1270             while not result and i < len(NodeMappings):
1271                 result = FindTypeDefaultValue(typeindex, NodeMappings[i])
1272                 i += 1
1273         if result == None:
1274             result = FindTypeDefaultValue(typeindex, MappingDictionary)
1275         return result
1276     
1277     def GetTypeList(self, node = None):
1278         list = FindTypeList(MappingDictionary)
1279         if node == None:
1280             node = self.CurrentNode
1281         for NodeMapping in self.CurrentNode.GetMappings():
1282             list.extend(FindTypeList(NodeMapping))
1283         list.sort()
1284         return list
1285     
1286     def GetMapVariableList(self, node = None):
1287         list = FindMapVariableList(MappingDictionary, self)
1288         if node == None:
1289             node = self.CurrentNode
1290         for NodeMapping in node.GetMappings():
1291             list.extend(FindMapVariableList(NodeMapping, self))
1292         list.sort()
1293         return list
1294     
1295     def GetMandatoryIndexes(self, node = None):
1296         list = FindMandatoryIndexes(MappingDictionary)
1297         if node == None:
1298             node = self.CurrentNode
1299         for NodeMapping in node.GetMappings():
1300             list.extend(FindMandatoryIndexes(NodeMapping))
1301         return list
1302     
1303     def GetCustomisableTypes(self):
1304         dic = {}
1305         for index, valuetype in CustomisableTypes:
1306             name = self.GetTypeName(index)
1307             dic[index] = [name, valuetype]
1308         return dic
1309     
1310     def GetCurrentSpecificMenu(self):
1311         if self.CurrentNode:
1312             return self.CurrentNode.GetSpecificMenu()
1313         return []
1314