]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/nodemanager.py
Support for DCF (DS-302)
[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_in, 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):
304         self.LastNewIndex = 0
305         self.FilePaths = []
306         self.FileNames = []
307         self.NodeIndex = -1
308         self.CurrentNode = None
309         self.UndoBuffers = []
310
311 #-------------------------------------------------------------------------------
312 #                         Type and Map Variable Lists
313 #-------------------------------------------------------------------------------
314
315     """
316     Generate the list of types defined for the current node
317     """
318     def GenerateTypeList(self):
319         self.TypeList = ""
320         self.TypeTranslation = {}
321         list = self.GetTypeList()
322         sep = ""
323         for index, name in list:
324             self.TypeList += "%s%s"%(sep,name)
325             self.TypeTranslation[name] = index
326             sep = ","
327     
328     """
329     Generate the list of variables that can be mapped for the current node
330     """
331     def GenerateMapList(self):
332         self.MapList = "None"
333         self.NameTranslation = {"None" : "00000000"}
334         self.MapTranslation = {"00000000" : "None"}
335         list = self.GetMapVariableList()
336         for index, subIndex, size, name in list:
337             self.MapList += ",%s"%name
338             map = "%04X%02X%02X"%(index,subIndex,size)
339             self.NameTranslation[name] = map
340             self.MapTranslation[map] = name
341     
342     """
343     Return the list of types defined for the current node
344     """
345     def GetCurrentTypeList(self):
346         return self.TypeList
347
348     """
349     Return the list of variables that can be mapped for the current node
350     """
351     def GetCurrentMapList(self):
352         return self.MapList
353
354 #-------------------------------------------------------------------------------
355 #                        Create Load and Save Functions
356 #-------------------------------------------------------------------------------
357
358     """
359     Create a new node and add a new buffer for storing it
360     """
361     def CreateNewNode(self, name, id, type, profile, filepath, NMT, options):
362         # Create a new node
363         node = Node()
364         # Try to load profile given
365         result = self.LoadProfile(profile, filepath, node)
366         if not IsOfType(result, StringType):
367             # if success, initialising node
368             self.CurrentNode = node
369             self.CurrentNode.SetNodeName(name)
370             self.CurrentNode.SetNodeID(id)
371             self.CurrentNode.SetNodeType(type)
372             AddIndexList = self.GetMandatoryIndexes()
373             if NMT == "NodeGuarding":
374                 AddIndexList.extend([0x100C, 0x100D])
375             elif NMT == "Heartbeat":
376                 AddIndexList.append(0x1017)
377             for option in options:
378                 if option == "DS302":
379                     # Charging DS-302 profile if choosen by user
380                     if os.path.isfile("config/DS-302.prf"):
381                         try:
382                                 execfile("config/DS-302.prf")
383                                 self.CurrentNode.SetDS302Profile(Mapping)
384                                 self.CurrentNode.ExtendSpecificMenu(AddMenuEntries)
385                         except:
386                             return "Problem with DS-302! Syntax Error."
387                     else:
388                         return "Couldn't find DS-302 in 'config' folder!"
389                 elif option == "GenSYNC":
390                     AddIndexList.extend([0x1005, 0x1006])
391                 elif option == "Emergency":
392                     AddIndexList.append(0x1014)
393                 elif option == "SaveConfig":
394                     AddIndexList.extend([0x1010, 0x1011, 0x1020])
395                 elif option == "StoreEDS":
396                     AddIndexList.extend([0x1021, 0x1022])
397             # Add a new buffer 
398             self.AddNodeBuffer()
399             self.SetCurrentFilePath("")
400             # Add Mandatory indexes
401             self.ManageEntriesOfCurrent(AddIndexList, [])
402             # Regenerate lists
403             self.GenerateTypeList()
404             self.GenerateMapList()
405             return True
406         else:
407             return result
408     
409     """
410     Load a profile in node
411     """
412     def LoadProfile(self, profile, filepath, node):
413         if profile != "None":
414             # Try to charge the profile given
415             try:
416                 execfile(filepath)
417                 node.SetProfileName(profile)
418                 node.SetProfile(Mapping)
419                 node.SetSpecificMenu(AddMenuEntries)
420                 return True
421             except:
422                 return "Bad OD Profile file!\nSyntax Error."
423         else:
424             # Default profile
425             node.SetProfileName("None")
426             node.SetProfile({})
427             node.SetSpecificMenu([])
428             return True
429
430     """
431     Open a file and store it in a new buffer
432     """
433     def OpenFileInCurrent(self, filepath):
434         # Open and load file
435         file = open(filepath, "r")
436         node = load(file)
437         file.close()
438         self.CurrentNode = node
439         # Add a new buffer and defining current state
440         self.AddNodeBuffer(self.CurrentNode.Copy(), True)
441         self.SetCurrentFilePath(filepath)
442         # Regenerate lists
443         self.GenerateTypeList()
444         self.GenerateMapList()
445         return True
446
447     """
448     Save current node in  a file
449     """
450     def SaveCurrentInFile(self, filepath = None):
451         # if no filepath given, verify if current node has a filepath defined
452         if not filepath:
453             filepath = self.GetCurrentFilePath()
454             if filepath == "":
455                 return False
456         # Save node in file
457         file = open(filepath, "w")
458         dump(self.CurrentNode, file)
459         file.close()
460         self.SetCurrentFilePath(filepath)
461         # Update saved state in buffer
462         self.UndoBuffers[self.NodeIndex].CurrentSaved()
463         return True
464
465     """
466     Close current state
467     """
468     def CloseCurrent(self, ignore = False):
469         # Verify if it's not forced that the current node is saved before closing it
470         if self.UndoBuffers[self.NodeIndex].IsCurrentSaved() or ignore:
471             self.RemoveNodeBuffer(self.NodeIndex)
472             return True
473         return False
474
475     """
476     Import a xml file and store it in a new buffer if no node edited
477     """
478     def ImportCurrentFromFile(self, filepath):
479         # Generate node from definition in a xml file
480         node = eds_in.GenerateNode(filepath, self)
481         if node:
482             self.CurrentNode = node
483             self.GenerateTypeList()
484             self.GenerateMapList()
485             if len(self.UndoBuffers) == 0:
486                 self.AddNodeBuffer()
487                 self.SetCurrentFilePath("")
488             self.BufferCurrentNode()
489         return result
490     
491     """
492     Build the C definition of Object Dictionary for current node 
493     """
494     def ExportCurrentToFile(self, filepath):
495         return gen_cfile.GenerateFile(filepath, self)
496
497 #-------------------------------------------------------------------------------
498 #                        Add Entries to Current Functions
499 #-------------------------------------------------------------------------------
500
501     """
502     Add the specified number of subentry for the given entry. Verify that total
503     number of subentry (except 0) doesn't exceed nbmax defined
504     """
505     def AddSubentriesToCurrent(self, index, number):
506         # Informations about entry
507         length = self.CurrentNode.GetEntry(index, 0)
508         infos = self.GetEntryInfos(index)
509         subentry_infos = self.GetSubentryInfos(index, 1)
510         # Get default value for subindex
511         if "default" in subentry_infos:
512             default = subentry_infos["default"]
513         else:
514             default = self.GetTypeDefaultValue(subentry_infos["type"])   
515         # First case entry is record
516         if infos["struct"] & OD_IdenticalSubindexes:
517             for i in xrange(1, min(number,subentry_infos["nbmax"]-length) + 1):
518                 self.CurrentNode.AddEntry(index, length + i, default)
519             self.BufferCurrentNode()
520         # Second case entry is array, only possible for manufacturer specific
521         elif infos["struct"] & OD_MultipleSubindexes and 0x2000 <= index <= 0x5FFF:
522             values = {"name" : "Undefined", "type" : 5, "access" : "rw", "pdo" : True}
523             for i in xrange(1, min(number,0xFE-length) + 1):
524                 self.CurrentNode.AddMappingEntry(index, length + i, values = values.copy())
525                 self.CurrentNode.AddEntry(index, length + i, 0)
526             self.BufferCurrentNode()
527
528     """
529     Remove the specified number of subentry for the given entry. Verify that total
530     number of subentry (except 0) isn't less than 1
531     """
532     def RemoveSubentriesFromCurrent(self, index, number):
533         # Informations about entry
534         infos = self.GetEntryInfos(index)
535         length = self.CurrentNode.GetEntry(index, 0)
536         # Entry is a record, or is an array of manufacturer specific
537         if infos["struct"] & OD_IdenticalSubindexes or 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_IdenticalSubindexes:
538             for i in xrange(min(number, length - 1)):
539                 self.RemoveCurrentVariable(index, length - i)
540             self.BufferCurrentNode()
541
542     """
543     Add a SDO Server to current node
544     """
545     def AddSDOServerToCurrent(self):
546         # An SDO Server is already defined at index 0x1200
547         if self.CurrentNode.IsEntry(0x1200):
548             indexlist = [self.GetLineFromIndex(0x1201)]
549             if None not in indexlist:
550                 self.ManageEntriesOfCurrent(indexlist, [])
551         # Add an SDO Server at index 0x1200
552         else:
553             self.ManageEntriesOfCurrent([0x1200], [])
554         
555     """
556     Add a SDO Server to current node
557     """
558     def AddSDOClientToCurrent(self):
559         indexlist = [self.GetLineFromIndex(0x1280)]
560         if None not in indexlist:
561             self.ManageEntriesOfCurrent(indexlist, [])
562
563     """
564     Add a Transmit PDO to current node
565     """
566     def AddPDOTransmitToCurrent(self):
567         indexlist = [self.GetLineFromIndex(0x1800),self.GetLineFromIndex(0x1A00)]
568         if None not in indexlist:
569             self.ManageEntriesOfCurrent(indexlist, [])
570         
571     """
572     Add a Receive PDO to current node
573     """
574     def AddPDOReceiveToCurrent(self):
575         indexlist = [self.GetLineFromIndex(0x1400),self.GetLineFromIndex(0x1600)]
576         if None not in indexlist:
577             self.ManageEntriesOfCurrent(indexlist, [])
578
579     """
580     Add a list of entries defined in profile for menu item selected to current node
581     """
582     def AddSpecificEntryToCurrent(self, menuitem):
583         indexlist = []
584         for menu, indexes in self.CurrentNode.GetSpecificMenu():
585             if menuitem == menu:
586                 for index in indexes:
587                     indexlist.append(self.GetLineFromIndex(index))
588         if None not in indexlist:
589             self.ManageEntriesOfCurrent(indexlist, [])
590
591     """
592     Search the first index available for a pluri entry from base_index
593     """
594     def GetLineFromIndex(self, base_index):
595         found = False
596         index = base_index
597         infos = self.GetEntryInfos(base_index)
598         while index < base_index + infos["incr"]*infos["nbmax"] and not found:
599             if not self.CurrentNode.IsEntry(index):
600                 found = True
601             else:
602                 index += infos["incr"]
603         if found:
604             return index
605         return None
606     
607     """
608     Add entries specified in addinglist and remove entries specified in removinglist
609     """
610     def ManageEntriesOfCurrent(self, addinglist, removinglist):
611         # Add all the entries in addinglist
612         for index in addinglist:
613             infos = self.GetEntryInfos(index)
614             if infos["struct"] & OD_MultipleSubindexes:
615                 # First case entry is a record
616                 if infos["struct"] & OD_IdenticalSubindexes:
617                     subentry_infos = self.GetSubentryInfos(index, 1)
618                     if "default" in subentry_infos:
619                         default = subentry_infos["default"]
620                     else:
621                         default = self.GetTypeDefaultValue(subentry_infos["type"])
622                     self.CurrentNode.AddEntry(index, 1, default)
623                 # Second case entry is a record
624                 else:
625                     i = 1
626                     subentry_infos = self.GetSubentryInfos(index, i)
627                     while subentry_infos:
628                         if "default" in subentry_infos:
629                             default = subentry_infos["default"]
630                         else:
631                             default = self.GetTypeDefaultValue(subentry_infos["type"])
632                         self.CurrentNode.AddEntry(index, i, default)
633                         i += 1
634                         subentry_infos = self.GetSubentryInfos(index, i)
635             # Third case entry is a record
636             else:
637                 subentry_infos = self.GetSubentryInfos(index, 0)
638                 if "default" in subentry_infos:
639                     default = subentry_infos["default"]
640                 else:
641                     default = self.GetTypeDefaultValue(subentry_infos["type"])
642                 self.CurrentNode.AddEntry(index, 0, default)
643         # Remove all the entries in removinglist
644         for index in removinglist:
645             self.RemoveCurrentVariable(index)
646         self.BufferCurrentNode()
647
648     """
649     Remove an entry from current node. Analize the index to perform the correct
650     method
651     """
652     def RemoveCurrentVariable(self, index, subIndex = None):
653         Mappings = self.CurrentNode.GetMappings()
654         if index < 0x1000 and subIndex == None:
655             type = self.CurrentNode.GetEntry(index, 1)
656             for i in Mappings[-1]:
657                 for value in Mappings[-1][i]["values"]:
658                     if value["type"] == index:
659                         value["type"] = type
660             self.CurrentNode.RemoveMappingEntry(index)
661             self.CurrentNode.RemoveEntry(index)
662         elif index == 0x1200 and subIndex == None:
663             self.CurrentNode.RemoveEntry(0x1200)
664         elif 0x1201 <= index <= 0x127F and subIndex == None:
665             self.CurrentNode.RemoveLine(index, 0x127F)
666         elif 0x1280 <= index <= 0x12FF and subIndex == None:
667             self.CurrentNode.RemoveLine(index, 0x12FF)
668         elif 0x1400 <= index <= 0x15FF or 0x1600 <= index <= 0x17FF and subIndex == None:
669             if 0x1600 <= index <= 0x17FF and subIndex == None:
670                 index -= 0x200
671             self.CurrentNode.RemoveLine(index, 0x15FF)
672             self.CurrentNode.RemoveLine(index + 0x200, 0x17FF)
673         elif 0x1800 <= index <= 0x19FF or 0x1A00 <= index <= 0x1BFF and subIndex == None:
674             if 0x1A00 <= index <= 0x1BFF:
675                 index -= 0x200
676             self.CurrentNode.RemoveLine(index, 0x19FF)
677             self.CurrentNode.RemoveLine(index + 0x200, 0x1BFF)
678         else:
679             found = False
680             for menu,list in self.CurrentNode.GetSpecificMenu():
681                 for i in list:
682                     iinfos = self.GetEntryInfos(i)
683                     indexes = [i + incr * iinfos["incr"] for incr in xrange(iinfos["nbmax"])] 
684                     if index in indexes:
685                         found = True
686                         diff = index - i
687                         for j in list:
688                             jinfos = self.GetEntryInfos(j)
689                             self.CurrentNode.RemoveLine(j + diff, j + jinfos["incr"]*jinfos["nbmax"], jinfos["incr"])
690             self.CurrentNode.RemoveMapVariable(index, subIndex)
691             if not found:
692                 infos = self.GetEntryInfos(index)
693                 if not infos["need"]:
694                     self.CurrentNode.RemoveEntry(index, subIndex)
695             if index in Mappings[-1]:
696                 self.CurrentNode.RemoveMappingEntry(index, subIndex)
697             self.GenerateMapList()
698
699     def AddMapVariableToCurrent(self, index, name, struct, number):
700         if 0x2000 <= index <= 0x5FFF:
701             if not self.CurrentNode.IsEntry(index):
702                 self.CurrentNode.AddMappingEntry(index, name = name, struct = struct)
703                 if struct == var:
704                     values = {"name" : name, "type" : 5, "access" : "rw", "pdo" : True}
705                     self.CurrentNode.AddMappingEntry(index, 0, values = values)
706                     self.CurrentNode.AddEntry(index, 0, 0)
707                 else:
708                     values = {"name" : "Number of Entries", "type" : 2, "access" : "ro", "pdo" : False}
709                     self.CurrentNode.AddMappingEntry(index, 0, values = values)
710                     if struct == rec:
711                         values = {"name" : name + " %d[(sub)]", "type" : 5, "access" : "rw", "pdo" : True, "nbmax" : 0xFE}
712                         self.CurrentNode.AddMappingEntry(index, 1, values = values)
713                         for i in xrange(number):
714                             self.CurrentNode.AddEntry(index, i + 1, 0)
715                     else:
716                         for i in xrange(number):
717                             values = {"name" : "Undefined", "type" : 5, "access" : "rw", "pdo" : True}
718                             self.CurrentNode.AddMappingEntry(index, i + 1, values = values)
719                             self.CurrentNode.AddEntry(index, i + 1, 0)
720                 self.GenerateMapList()
721                 self.BufferCurrentNode()
722                 return None
723             else:
724                 return "Index 0x%04X already defined!"%index
725         else:
726             return "Index 0x%04X isn't a valid index for Map Variable!"%index
727
728     def AddUserTypeToCurrent(self, type, min, max, length):
729         index = 0xA0
730         while index < 0x100 and self.CurrentNode.IsEntry(index):
731             index += 1
732         if index < 0x100:
733             customisabletypes = self.GetCustomisableTypes()
734             name, valuetype = customisabletypes[type]
735             size = self.GetEntryInfos(type)["size"]
736             default = self.GetTypeDefaultValue(type)
737             if valuetype == 0:
738                 self.CurrentNode.AddMappingEntry(index, name = "%s[%d-%d]"%(name, min, max), struct = 3, size = size, default = default)
739                 self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
740                 self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
741                 self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False})
742                 self.CurrentNode.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False})
743                 self.CurrentNode.AddEntry(index, 1, type)
744                 self.CurrentNode.AddEntry(index, 2, min)
745                 self.CurrentNode.AddEntry(index, 3, max)
746             elif valuetype == 1:
747                 self.CurrentNode.AddMappingEntry(index, name = "%s%d"%(name, length), struct = 3, size = length * size, default = default)
748                 self.CurrentNode.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
749                 self.CurrentNode.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
750                 self.CurrentNode.AddMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False})
751                 self.CurrentNode.AddEntry(index, 1, type)
752                 self.CurrentNode.AddEntry(index, 2, length)
753             self.GenerateTypeList()
754             self.BufferCurrentNode()
755             return None
756         else:
757             return "Too many User Types have already been defined!"
758
759 #-------------------------------------------------------------------------------
760 #                      Modify Entry and Mapping Functions
761 #-------------------------------------------------------------------------------
762
763     def SetCurrentEntryCallbacks(self, index, value):
764         if self.CurrentNode and self.CurrentNode.IsEntry(index):
765             entry_infos = self.GetEntryInfos(index)
766             if "callback" not in entry_infos:
767                 self.CurrentNode.SetParamsEntry(index, None, callback = value)
768                 self.BufferCurrentNode()
769
770     def SetCurrentEntry(self, index, subIndex, value, name, editor):
771         if self.CurrentNode and self.CurrentNode.IsEntry(index):
772             if name == "value":
773                 if editor == "map":
774                     value = eval("0x%s"%self.NameTranslation[value])
775                     self.CurrentNode.SetEntry(index, subIndex, value)
776                 elif editor == "bool":
777                     value = value == "True"
778                     self.CurrentNode.SetEntry(index, subIndex, value)
779                 elif editor == "time":
780                     self.CurrentNode.SetEntry(index, subIndex, value)
781                 elif editor == "domain":
782                     try:
783                         if len(value) % 2 != 0:
784                             value = "0" + value
785                         value = value.decode('hex_codec')
786                         self.CurrentNode.SetEntry(index, subIndex, value)
787                     except:
788                         pass
789                 else:
790                     subentry_infos = self.GetSubentryInfos(index, subIndex)
791                     type = subentry_infos["type"]
792                     dic = {}
793                     for typeindex, typevalue in CustomisableTypes:
794                         dic[typeindex] = typevalue
795                     if type not in dic:
796                         type = self.CurrentNode.GetEntry(type)[1]
797                     if dic[type] == 0:
798                         try:
799                             value = eval(value, {})
800                             self.CurrentNode.SetEntry(index, subIndex, value)
801                         except:
802                             pass
803                     else:
804                         self.CurrentNode.SetEntry(index, subIndex, value)
805             elif name in ["comment", "save"]:
806                 if editor == "option":
807                     value = value == "Yes"
808                 if name == "save":
809                     self.CurrentNode.SetParamsEntry(index, subIndex, save = value)
810                 elif name == "comment":
811                     self.CurrentNode.SetParamsEntry(index, subIndex, comment = value)
812             else:
813                 if editor == "type":
814                     value = self.TypeTranslation[value]
815                     size = self.GetEntryInfos(value)["size"]
816                     self.CurrentNode.UpdateMapVariable(index, subIndex, size)
817                 elif editor in ["access","raccess"]:
818                     dic = {}
819                     for abbrev,access in AccessType.iteritems():
820                         dic[access] = abbrev
821                     value = dic[value]
822                     if editor == "raccess" and not self.CurrentNode.IsMappingEntry(index):
823                         entry_infos = self.GetEntryInfos(index)
824                         self.CurrentNode.AddMappingEntry(index, name = entry_infos["name"], struct = 7)
825                         self.CurrentNode.AddMappingEntry(index, 0, values = self.GetSubentryInfos(index, 0, False).copy())
826                         self.CurrentNode.AddMappingEntry(index, 1, values = self.GetSubentryInfos(index, 1, False).copy())
827                 self.CurrentNode.SetMappingEntry(index, subIndex, values = {name : value})
828                 if name == "name" or editor == "type":
829                     self.GenerateMapList()
830             self.BufferCurrentNode()
831
832     def SetCurrentEntryName(self, index, name):
833         self.CurrentNode.SetMappingEntry(index, name=name)
834         self.BufferCurrentNode()
835
836     def SetCurrentUserType(self, index, type, min, max, length):
837         customisabletypes = self.GetCustomisableTypes()
838         values, valuetype = self.GetCustomisedTypeValues(index)
839         name, new_valuetype = customisabletypes[type]
840         size = self.GetEntryInfos(type)["size"]
841         default = self.GetTypeDefaultValue(type)
842         if new_valuetype == 0:
843             self.CurrentNode.SetMappingEntry(index, name = "%s[%d-%d]"%(name, min, max), struct = 3, size = size, default = default) 
844             if valuetype == 1:
845                 self.CurrentNode.SetMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False})
846                 self.CurrentNode.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False})
847             self.CurrentNode.SetEntry(index, 1, type)
848             self.CurrentNode.SetEntry(index, 2, min)
849             if valuetype == 1:
850                 self.CurrentNode.AddEntry(index, 3, max)
851             else:
852                 self.CurrentNode.SetEntry(index, 3, max)
853         elif new_valuetype == 1:
854             self.CurrentNode.SetMappingEntry(index, name = "%s%d"%(name, length), struct = 3, size = size, default = default)
855             if valuetype == 0:
856                 self.CurrentNode.SetMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False})
857                 self.CurrentNode.RemoveMappingEntry(index, 3)
858             self.CurrentNode.SetEntry(index, 1, type)
859             self.CurrentNode.SetEntry(index, 2, length)
860             if valuetype == 0:
861                 self.CurrentNode.RemoveEntry(index, 3)
862         self.BufferCurrentNode()
863
864 #-------------------------------------------------------------------------------
865 #                      Current Buffering Management Functions
866 #-------------------------------------------------------------------------------
867
868     def BufferCurrentNode(self):
869         self.UndoBuffers[self.NodeIndex].Buffering(self.CurrentNode.Copy())
870
871     def CurrentIsSaved(self):
872         return self.UndoBuffers[self.NodeIndex].IsCurrentSaved()
873
874     def OneFileHasChanged(self):
875         result = False
876         for buffer in self.UndoBuffers:
877             result |= not buffer.IsCurrentSaved()
878         return result
879
880     def GetBufferNumber(self):
881         return len(self.UndoBuffers)
882
883     def LoadCurrentPrevious(self):
884         self.CurrentNode = self.UndoBuffers[self.NodeIndex].Previous().Copy()
885     
886     def LoadCurrentNext(self):
887         self.CurrentNode = self.UndoBuffers[self.NodeIndex].Next().Copy()
888
889     def AddNodeBuffer(self, currentstate = None, issaved = False):
890         self.NodeIndex = len(self.UndoBuffers)
891         self.UndoBuffers.append(UndoBuffer(currentstate, issaved))
892         self.FilePaths.append("")
893         self.FileNames.append("")
894
895     def ChangeCurrentNode(self, index):
896         if index < len(self.UndoBuffers):
897             self.NodeIndex = index
898             self.CurrentNode = self.UndoBuffers[self.NodeIndex].Current().Copy()
899             self.GenerateTypeList()
900             self.GenerateMapList()
901     
902     def RemoveNodeBuffer(self, index):
903         self.UndoBuffers.pop(index)
904         self.FilePaths.pop(index)
905         self.FileNames.pop(index)
906         self.NodeIndex = min(self.NodeIndex, len(self.UndoBuffers) - 1)
907         if len(self.UndoBuffers) > 0:
908             self.CurrentNode = self.UndoBuffers[self.NodeIndex].Current().Copy()
909             self.GenerateTypeList()
910             self.GenerateMapList()
911         else:
912             self.CurrentNode = None
913     
914     def GetCurrentNodeIndex(self):
915         return self.NodeIndex
916     
917     def GetCurrentFilename(self):
918         return self.GetFilename(self.NodeIndex)
919     
920     def GetAllFilenames(self):
921         filenames = []
922         for i in xrange(len(self.UndoBuffers)):
923             filenames.append(self.GetFilename(i))
924         return filenames
925     
926     def GetFilename(self, index):
927         if self.UndoBuffers[index].IsCurrentSaved():
928             return self.FileNames[index]
929         else:
930             return "~%s~"%self.FileNames[index]
931     
932     def SetCurrentFilePath(self, filepath):
933         self.FilePaths[self.NodeIndex] = filepath
934         if filepath == "":
935             self.LastNewIndex += 1
936             self.FileNames[self.NodeIndex] = "Unnamed%d"%self.LastNewIndex
937         else:
938             self.FileNames[self.NodeIndex] = os.path.splitext(os.path.basename(filepath))[0]
939                 
940     def GetCurrentFilePath(self):
941         if len(self.FilePaths) > 0:
942             return self.FilePaths[self.NodeIndex]
943         else:
944             return ""
945     
946     def GetCurrentBufferState(self):
947         first = self.UndoBuffers[self.NodeIndex].IsFirst()
948         last = self.UndoBuffers[self.NodeIndex].IsLast()
949         return not first, not last
950
951 #-------------------------------------------------------------------------------
952 #                         Profiles Management Functions
953 #-------------------------------------------------------------------------------
954
955     def GetCurrentCommunicationLists(self):
956         list = []
957         for index in MappingDictionary.iterkeys():
958             if 0x1000 <= index < 0x1200:
959                 list.append(index)
960         return self.GetProfileLists(MappingDictionary, list)
961     
962     def GetCurrentDS302Lists(self):
963         return self.GetSpecificProfileLists(self.CurrentNode.GetDS302Profile())
964     
965     def GetCurrentProfileLists(self):
966         return self.GetSpecificProfileLists(self.CurrentNode.GetProfile())
967     
968     def GetSpecificProfileLists(self, mappingdictionary):
969         validlist = []
970         exclusionlist = []
971         for name, list in self.CurrentNode.GetSpecificMenu():
972             exclusionlist.extend(list)
973         for index in mappingdictionary.iterkeys():
974             if index not in exclusionlist:
975                 validlist.append(index)
976         return self.GetProfileLists(mappingdictionary, validlist)
977     
978     def GetProfileLists(self, mappingdictionary, list):
979         dictionary = {}
980         current = []
981         for index in list:
982             dictionary[index] = (mappingdictionary[index]["name"], mappingdictionary[index]["need"])
983             if self.CurrentNode.IsEntry(index):
984                 current.append(index)
985         return dictionary, current
986
987     def GetCurrentNextMapIndex(self):
988         if self.CurrentNode:
989             index = 0x2000
990             while self.CurrentNode.IsEntry(index) and index < 0x5FFF:
991                 index += 1
992             if index < 0x6000:
993                 return index
994             else:
995                 return None
996
997     def CurrentDS302Defined(self):
998         if self.CurrentNode:
999             return len(self.CurrentNode.GetDS302Profile()) > 0
1000         return False
1001
1002 #-------------------------------------------------------------------------------
1003 #                         Node State and Values Functions
1004 #-------------------------------------------------------------------------------
1005
1006     def GetCurrentNodeInfos(self):
1007         name = self.CurrentNode.GetNodeName()
1008         id = self.CurrentNode.GetNodeID()
1009         type = self.CurrentNode.GetNodeType()
1010         return name, id, type
1011         
1012     def SetCurrentNodeInfos(self, name, id, type):
1013         self.CurrentNode.SetNodeName(name)
1014         self.CurrentNode.SetNodeID(id)
1015         self.CurrentNode.SetNodeType(type)
1016         self.BufferCurrentNode()
1017
1018     def GetCurrentProfileName(self):
1019         if self.CurrentNode:
1020             return self.CurrentNode.GetProfileName()
1021         return ""
1022
1023     def IsCurrentEntry(self, index):
1024         if self.CurrentNode:
1025             return self.CurrentNode.IsEntry(index)
1026         return False
1027     
1028     def GetCurrentEntry(self, index, subIndex = None):
1029         if self.CurrentNode:
1030             return self.CurrentNode.GetEntry(index, subIndex)
1031         return None
1032     
1033     def GetCurrentParamsEntry(self, index, subIndex = None):
1034         if self.CurrentNode:
1035             return self.CurrentNode.GetParamsEntry(index, subIndex)
1036         return None
1037     
1038     def GetCurrentValidIndexes(self, min, max):
1039         validindexes = []
1040         for index in self.CurrentNode.GetIndexes():
1041             if min <= index <= max:
1042                 validindexes.append((self.GetEntryName(index), index))
1043         return validindexes
1044         
1045     def GetCurrentValidChoices(self, min, max):
1046         validchoices = []
1047         exclusionlist = []
1048         for menu, indexes in self.CurrentNode.GetSpecificMenu():
1049             exclusionlist.extend(indexes)
1050             good = True
1051             for index in indexes:
1052                 good &= min <= index <= max
1053             if good:
1054                 validchoices.append((menu, None))
1055         list = [index for index in MappingDictionary.keys() if index >= 0x1000]
1056         profiles = self.CurrentNode.GetMappings(False)
1057         for profile in profiles:
1058             list.extend(profile.keys())
1059         list.sort()
1060         for index in list:
1061             if min <= index <= max and not self.CurrentNode.IsEntry(index) and index not in exclusionlist:
1062                 validchoices.append((self.GetEntryName(index), index))
1063         return validchoices
1064     
1065     def HasCurrentEntryCallbacks(self, index):
1066         if self.CurrentNode and self.CurrentNode.IsEntry(index):
1067             entry_infos = self.GetEntryInfos(index)
1068             if "callback" in entry_infos:
1069                 return entry_infos["callback"]
1070             return self.CurrentNode.HasEntryCallbacks(index)
1071         return False
1072     
1073     def GetCurrentEntryValues(self, index):
1074         if self.CurrentNode and self.CurrentNode.IsEntry(index):
1075             entry_infos = self.GetEntryInfos(index)
1076             data = []
1077             editors = []
1078             values = self.CurrentNode.GetEntry(index)
1079             params = self.CurrentNode.GetParamsEntry(index)
1080             if type(values) == ListType:
1081                 for i, value in enumerate(values):
1082                     data.append({"value" : value})
1083                     data[-1].update(params[i])      
1084             else:
1085                 data.append({"value" : values})
1086                 data[-1].update(params)
1087             for i, dic in enumerate(data):
1088                 infos = self.GetSubentryInfos(index, i)
1089                 dic["subindex"] = "0x%02X"%i
1090                 dic["name"] = infos["name"]
1091                 dic["type"] = self.GetTypeName(infos["type"])
1092                 dic["access"] = AccessType[infos["access"]]
1093                 dic["save"] = OptionType[dic["save"]]
1094                 editor = {"subindex" : None, "save" : "option", "callback" : "option", "comment" : "string"}
1095                 if type(values) == ListType and i == 0:
1096                     editor["name"] = None
1097                     editor["type"] = None
1098                     if 0x1600 <= index <= 0x17FF or 0x1A00 <= index <= 0x1C00:
1099                         editor["access"] = "raccess"
1100                     else:
1101                         editor["access"] = None
1102                     editor["value"] = None
1103                 else:
1104                     if infos["user_defined"]:
1105                         if entry_infos["struct"] & OD_IdenticalSubindexes:
1106                             editor["name"] = None
1107                             if i > 1:
1108                                 editor["type"] = None
1109                                 editor["access"] = None
1110                             else:
1111                                 editor["type"] = "type"
1112                                 editor["access"] = "access"
1113                         else:
1114                             if entry_infos["struct"] & OD_MultipleSubindexes:
1115                                 editor["name"] = "string"
1116                             else:
1117                                 editor["name"] = None
1118                             editor["type"] = "type"
1119                             editor["access"] = "access"
1120                     else:
1121                         editor["name"] = None
1122                         editor["type"] = None
1123                         editor["access"] = None
1124                     if index < 0x260:
1125                         editor["value"] = None
1126                         if i == 1:
1127                             dic["value"] = self.GetTypeName(dic["value"])
1128                     elif 0x1600 <= index <= 0x17FF or 0x1A00 <= index <= 0x1C00:
1129                         editor["value"] = "map"
1130                         dic["value"] = self.MapTranslation["%08X"%dic["value"]]
1131                     else:
1132                         if dic["type"].startswith("VISIBLE_STRING"):
1133                             editor["value"] = "string"
1134                         elif dic["type"] in ["TIME_OF_DAY","TIME_DIFFERENCE"]:
1135                             editor["value"] = "time"
1136                         elif dic["type"] == "DOMAIN":
1137                             editor["value"] = "domain"
1138                             dic["value"] = dic["value"].encode('hex_codec')
1139                         elif dic["type"] == "BOOLEAN":
1140                             editor["value"] = "bool"
1141                             dic["value"] = BoolType[dic["value"]]
1142                         result = type_model.match(dic["type"])
1143                         if result:
1144                             values = result.groups()
1145                             if values[0] in ["INTEGER", "UNSIGNED"]:
1146                                 format = "0x%0" + str(int(values[1])/4) + "X"
1147                                 dic["value"] = format%dic["value"]
1148                                 editor["value"] = "string"
1149                             elif values[0] == "REAL":
1150                                 editor["value"] = "float"
1151                             elif values[0] == "VISIBLE_STRING":
1152                                 editor["length"] = values[0]
1153                         result = range_model.match(dic["type"])
1154                         if result:
1155                             values = result.groups()
1156                             if values[0] in ("UNSIGNED", "REAL"):
1157                                 editor["min"] = values[2]
1158                                 editor["max"] = values[3]
1159                 editors.append(editor)
1160             return data, editors
1161         else:
1162             return None
1163     
1164 #-------------------------------------------------------------------------------
1165 #                         Node Informations Functions
1166 #-------------------------------------------------------------------------------
1167
1168     def GetCustomisedTypeValues(self, index):
1169         values = self.CurrentNode.GetEntry(index)
1170         customisabletypes = self.GetCustomisableTypes()
1171         return values, customisabletypes[values[1]][1]
1172
1173     def GetEntryName(self, index, node = True):
1174         result = None
1175         if node:
1176             NodeMappings = self.CurrentNode.GetMappings()
1177             i = 0
1178             while not result and i < len(NodeMappings):
1179                 result = FindEntryName(index, NodeMappings[i])
1180                 i += 1
1181         if result == None:
1182             result = FindEntryName(index, MappingDictionary)
1183         return result
1184     
1185     def GetEntryInfos(self, index, node = True):
1186         result = None
1187         if node:
1188             NodeMappings = self.CurrentNode.GetMappings()
1189             i = 0
1190             while not result and i < len(NodeMappings):
1191                 result = FindEntryInfos(index, NodeMappings[i])
1192                 i += 1
1193         if result == None:
1194             result = FindEntryInfos(index, MappingDictionary)
1195         return result
1196     
1197     def GetSubentryInfos(self, index, subIndex, node = True):
1198         result = None
1199         if node:
1200             NodeMappings = self.CurrentNode.GetMappings()
1201             i = 0
1202             while not result and i < len(NodeMappings):
1203                 result = FindSubentryInfos(index, subIndex, NodeMappings[i])
1204                 if result:
1205                     result["user_defined"] = i == len(NodeMappings) - 1 and index >= 0x1000
1206                 i += 1
1207         if result == None:    
1208             result = FindSubentryInfos(index, subIndex, MappingDictionary)
1209             if result:
1210                 result["user_defined"] = False
1211         return result
1212     
1213     def GetTypeIndex(self, typename, node = True):
1214         result = None
1215         if node:
1216             NodeMappings = self.CurrentNode.GetMappings()
1217             i = 0
1218             while not result and i < len(NodeMappings):
1219                 result = FindTypeIndex(typename, NodeMappings[i])
1220                 i += 1
1221         if result == None:
1222             result = FindTypeIndex(typename, MappingDictionary)
1223         return result
1224     
1225     def GetTypeName(self, typeindex, node = True):
1226         result = None
1227         if node:
1228             NodeMappings = self.CurrentNode.GetMappings()
1229             i = 0
1230             while not result and i < len(NodeMappings):
1231                 result = FindTypeName(typeindex, NodeMappings[i])
1232                 i += 1
1233         if result == None:
1234             result = FindTypeName(typeindex, MappingDictionary)
1235         return result
1236     
1237     def GetTypeDefaultValue(self, typeindex, node = True):
1238         result = None
1239         if node:
1240             NodeMappings = self.CurrentNode.GetMappings()
1241             i = 0
1242             while not result and i < len(NodeMappings):
1243                 result = FindTypeDefaultValue(typeindex, NodeMappings[i])
1244                 i += 1
1245         if result == None:
1246             result = FindTypeDefaultValue(typeindex, MappingDictionary)
1247         return result
1248     
1249     def GetTypeList(self, node = True):
1250         list = FindTypeList(MappingDictionary)
1251         if node:
1252             for NodeMapping in self.CurrentNode.GetMappings():
1253                 list.extend(FindTypeList(NodeMapping))
1254         list.sort()
1255         return list
1256     
1257     def GetMapVariableList(self):
1258         list = FindMapVariableList(MappingDictionary, self)
1259         for NodeMapping in self.CurrentNode.GetMappings():
1260             list.extend(FindMapVariableList(NodeMapping, self))
1261         list.sort()
1262         return list
1263     
1264     def GetMandatoryIndexes(self, node = True):
1265         list = FindMandatoryIndexes(MappingDictionary)
1266         if node:
1267             for NodeMapping in self.CurrentNode.GetMappings():
1268                 list.extend(FindMandatoryIndexes(NodeMapping))
1269         return list
1270     
1271     def GetCustomisableTypes(self):
1272         dic = {}
1273         for index, valuetype in CustomisableTypes:
1274             name = self.GetTypeName(index)
1275             dic[index] = [name, valuetype]
1276         return dic
1277     
1278     def GetCurrentSpecificMenu(self):
1279         if self.CurrentNode:
1280             return self.CurrentNode.GetSpecificMenu()
1281         return []
1282
1283