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