ConfigTreeNode.py
changeset 725 31dade089db5
parent 722 a94f361fc42e
child 728 e0424e96e3fd
equal deleted inserted replaced
724:e0630d262ac3 725:31dade089db5
       
     1 """
       
     2 Config Tree Node base class.
       
     3 
       
     4 - A Beremiz project is organized in a tree each node derivate from ConfigTreeNode
       
     5 - Project tree organization match filesystem organization of project directory.
       
     6 - Each node of the tree have its own xml configuration, whose grammar is defined for each node type, as XSD
       
     7 - ... TODO : document
       
     8 """
       
     9 
       
    10 import os,traceback,types
       
    11 import shutil
       
    12 from xml.dom import minidom
       
    13 
       
    14 from xmlclass import GenerateClassesFromXSDstring
       
    15 from util import opjimg, GetClassImporter
       
    16 
       
    17 from PLCControler import PLCControler, LOCATION_CONFNODE
       
    18 
       
    19 _BaseParamsClass = GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
       
    20         <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       
    21           <xsd:element name="BaseParams">
       
    22             <xsd:complexType>
       
    23               <xsd:attribute name="Name" type="xsd:string" use="optional" default="__unnamed__"/>
       
    24               <xsd:attribute name="IEC_Channel" type="xsd:integer" use="required"/>
       
    25               <xsd:attribute name="Enabled" type="xsd:boolean" use="optional" default="true"/>
       
    26             </xsd:complexType>
       
    27           </xsd:element>
       
    28         </xsd:schema>""")["BaseParams"]
       
    29 
       
    30 NameTypeSeparator = '@'
       
    31 
       
    32 class ConfigTreeNode:
       
    33     """
       
    34     This class is the one that define confnodes.
       
    35     """
       
    36 
       
    37     XSD = None
       
    38     CTNChildrenTypes = []
       
    39     CTNMaxCount = None
       
    40     ConfNodeMethods = []
       
    41     LibraryControler = None
       
    42     EditorType = None
       
    43 
       
    44     def _AddParamsMembers(self):
       
    45         self.CTNParams = None
       
    46         if self.XSD:
       
    47             self.Classes = GenerateClassesFromXSDstring(self.XSD)
       
    48             Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass]
       
    49             if len(Classes) == 1:
       
    50                 name, XSDclass = Classes[0]
       
    51                 obj = XSDclass()
       
    52                 self.CTNParams = (name, obj)
       
    53                 setattr(self, name, obj)
       
    54 
       
    55     def __init__(self):
       
    56         # Create BaseParam 
       
    57         self.BaseParams = _BaseParamsClass()
       
    58         self.MandatoryParams = ("BaseParams", self.BaseParams)
       
    59         self._AddParamsMembers()
       
    60         self.Children = {}
       
    61         self._View = None
       
    62         # copy ConfNodeMethods so that it can be later customized
       
    63         self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods]
       
    64         self.LoadSTLibrary()
       
    65         
       
    66     def ConfNodeBaseXmlFilePath(self, CTNName=None):
       
    67         return os.path.join(self.CTNPath(CTNName), "baseconfnode.xml")
       
    68     
       
    69     def ConfNodeXmlFilePath(self, CTNName=None):
       
    70         return os.path.join(self.CTNPath(CTNName), "confnode.xml")
       
    71 
       
    72     def ConfNodeLibraryFilePath(self):
       
    73         return os.path.join(self.ConfNodePath(), "pous.xml")
       
    74 
       
    75     def ConfNodePath(self):
       
    76         return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType)
       
    77 
       
    78     def CTNPath(self,CTNName=None):
       
    79         if not CTNName:
       
    80             CTNName = self.CTNName()
       
    81         return os.path.join(self.CTNParent.CTNPath(),
       
    82                             CTNName + NameTypeSeparator + self.CTNType)
       
    83     
       
    84     def CTNName(self):
       
    85         return self.BaseParams.getName()
       
    86     
       
    87     def CTNEnabled(self):
       
    88         return self.BaseParams.getEnabled()
       
    89     
       
    90     def CTNFullName(self):
       
    91         parent = self.CTNParent.CTNFullName()
       
    92         if parent != "":
       
    93             return parent + "." + self.CTNName()
       
    94         return self.BaseParams.getName()
       
    95     
       
    96     def GetIconPath(self, name):
       
    97         return opjimg(name)
       
    98     
       
    99     def CTNTestModified(self):
       
   100         return self.ChangesToSave
       
   101 
       
   102     def ProjectTestModified(self):
       
   103         """
       
   104         recursively check modified status
       
   105         """
       
   106         if self.CTNTestModified():
       
   107             return True
       
   108 
       
   109         for CTNChild in self.IterChildren():
       
   110             if CTNChild.ProjectTestModified():
       
   111                 return True
       
   112 
       
   113         return False
       
   114     
       
   115     def RemoteExec(self, script, **kwargs):
       
   116         return self.CTNParent.RemoteExec(script, **kwargs)
       
   117     
       
   118     def OnCTNSave(self):
       
   119         #Default, do nothing and return success
       
   120         return True
       
   121 
       
   122     def GetParamsAttributes(self, path = None):
       
   123         if path:
       
   124             parts = path.split(".", 1)
       
   125             if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
       
   126                 return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
       
   127             elif self.CTNParams and parts[0] == self.CTNParams[0]:
       
   128                 return self.CTNParams[1].getElementInfos(parts[0], parts[1])
       
   129         else:
       
   130             params = []
       
   131             if self.CTNParams:
       
   132                 params.append(self.CTNParams[1].getElementInfos(self.CTNParams[0]))
       
   133             return params
       
   134         
       
   135     def SetParamsAttribute(self, path, value):
       
   136         self.ChangesToSave = True
       
   137         # Filter IEC_Channel and Name, that have specific behavior
       
   138         if path == "BaseParams.IEC_Channel":
       
   139             old_leading = ".".join(map(str, self.GetCurrentLocation()))
       
   140             new_value = self.FindNewIEC_Channel(value)
       
   141             new_leading = ".".join(map(str, self.CTNParent.GetCurrentLocation() + (new_value,)))
       
   142             self.GetCTRoot().UpdateProjectVariableLocation(old_leading, new_leading)
       
   143             return new_value, True
       
   144         elif path == "BaseParams.Name":
       
   145             res = self.FindNewName(value)
       
   146             self.CTNRequestSave()
       
   147             return res, True
       
   148         
       
   149         parts = path.split(".", 1)
       
   150         if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
       
   151             self.MandatoryParams[1].setElementValue(parts[1], value)
       
   152         elif self.CTNParams and parts[0] == self.CTNParams[0]:
       
   153             self.CTNParams[1].setElementValue(parts[1], value)
       
   154         return value, False
       
   155 
       
   156     def CTNMakeDir(self):
       
   157         os.mkdir(self.CTNPath())
       
   158 
       
   159     def CTNRequestSave(self):
       
   160         if self.GetCTRoot().CheckProjectPathPerm(False):
       
   161             # If confnode do not have corresponding directory
       
   162             ctnpath = self.CTNPath()
       
   163             if not os.path.isdir(ctnpath):
       
   164                 # Create it
       
   165                 os.mkdir(ctnpath)
       
   166     
       
   167             # generate XML for base XML parameters controller of the confnode
       
   168             if self.MandatoryParams:
       
   169                 BaseXMLFile = open(self.ConfNodeBaseXmlFilePath(),'w')
       
   170                 BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
       
   171                 BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
       
   172                 BaseXMLFile.close()
       
   173             
       
   174             # generate XML for XML parameters controller of the confnode
       
   175             if self.CTNParams:
       
   176                 XMLFile = open(self.ConfNodeXmlFilePath(),'w')
       
   177                 XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
       
   178                 XMLFile.write(self.CTNParams[1].generateXMLText(self.CTNParams[0], 0).encode("utf-8"))
       
   179                 XMLFile.close()
       
   180             
       
   181             # Call the confnode specific OnCTNSave method
       
   182             result = self.OnCTNSave()
       
   183             if not result:
       
   184                 return _("Error while saving \"%s\"\n")%self.CTNPath()
       
   185     
       
   186             # mark confnode as saved
       
   187             self.ChangesToSave = False
       
   188             # go through all children and do the same
       
   189             for CTNChild in self.IterChildren():
       
   190                 result = CTNChild.CTNRequestSave()
       
   191                 if result:
       
   192                     return result
       
   193         return None
       
   194     
       
   195     def CTNImport(self, src_CTNPath):
       
   196         shutil.copytree(src_CTNPath, self.CTNPath)
       
   197         return True
       
   198 
       
   199     def CTNGenerate_C(self, buildpath, locations):
       
   200         """
       
   201         Generate C code
       
   202         @param locations: List of complete variables locations \
       
   203             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
       
   204             "NAME" : name of the variable (generally "__IW0_1_2" style)
       
   205             "DIR" : direction "Q","I" or "M"
       
   206             "SIZE" : size "X", "B", "W", "D", "L"
       
   207             "LOC" : tuple of interger for IEC location (0,1,2,...)
       
   208             }, ...]
       
   209         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
       
   210         """
       
   211         self.GetCTRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n")
       
   212         return [],"",False
       
   213     
       
   214     def _Generate_C(self, buildpath, locations):
       
   215         # Generate confnodes [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files
       
   216         # extra_files = [(fname,fobject), ...]
       
   217         gen_result = self.CTNGenerate_C(buildpath, locations)
       
   218         CTNCFilesAndCFLAGS, CTNLDFLAGS, DoCalls = gen_result[:3]
       
   219         extra_files = gen_result[3:]
       
   220         # if some files have been generated put them in the list with their location
       
   221         if CTNCFilesAndCFLAGS:
       
   222             LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), CTNCFilesAndCFLAGS, DoCalls)]
       
   223         else:
       
   224             LocationCFilesAndCFLAGS = []
       
   225 
       
   226         # confnode asks for some LDFLAGS
       
   227         if CTNLDFLAGS:
       
   228             # LDFLAGS can be either string
       
   229             if type(CTNLDFLAGS)==type(str()):
       
   230                 LDFLAGS=[CTNLDFLAGS]
       
   231             #or list of strings
       
   232             elif type(CTNLDFLAGS)==type(list()):
       
   233                 LDFLAGS=CTNLDFLAGS[:]
       
   234         else:
       
   235             LDFLAGS=[]
       
   236         
       
   237         # recurse through all children, and stack their results
       
   238         for CTNChild in self.IECSortedChildren():
       
   239             new_location = CTNChild.GetCurrentLocation()
       
   240             # How deep are we in the tree ?
       
   241             depth=len(new_location)
       
   242             _LocationCFilesAndCFLAGS, _LDFLAGS, _extra_files = \
       
   243                 CTNChild._Generate_C(
       
   244                     #keep the same path
       
   245                     buildpath,
       
   246                     # filter locations that start with current IEC location
       
   247                     [loc for loc in locations if loc["LOC"][0:depth] == new_location ])
       
   248             # stack the result
       
   249             LocationCFilesAndCFLAGS += _LocationCFilesAndCFLAGS
       
   250             LDFLAGS += _LDFLAGS
       
   251             extra_files += _extra_files
       
   252         
       
   253         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
       
   254 
       
   255     def ConfNodeTypesFactory(self):
       
   256         if self.LibraryControler is not None:
       
   257             return [{"name" : self.CTNType, "types": self.LibraryControler.Project}]
       
   258         return []
       
   259 
       
   260     def ParentsTypesFactory(self):
       
   261         return self.CTNParent.ParentsTypesFactory() + self.ConfNodeTypesFactory()
       
   262 
       
   263     def ConfNodesTypesFactory(self):
       
   264         list = self.ConfNodeTypesFactory()
       
   265         for CTNChild in self.IterChildren():
       
   266             list += CTNChild.ConfNodesTypesFactory()
       
   267         return list
       
   268 
       
   269     def STLibraryFactory(self):
       
   270         if self.LibraryControler is not None:
       
   271             program, errors, warnings = self.LibraryControler.GenerateProgram()
       
   272             return program + "\n"
       
   273         return ""
       
   274 
       
   275     def ConfNodesSTLibraryFactory(self):
       
   276         program = self.STLibraryFactory()
       
   277         for CTNChild in self.IECSortedChildren():
       
   278             program += CTNChild.ConfNodesSTLibraryFactory()
       
   279         return program
       
   280         
       
   281     def IterChildren(self):
       
   282         for CTNType, Children in self.Children.items():
       
   283             for CTNInstance in Children:
       
   284                 yield CTNInstance
       
   285     
       
   286     def IECSortedChildren(self):
       
   287         # reorder children by IEC_channels
       
   288         ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChildren()]
       
   289         if ordered:
       
   290             ordered.sort()
       
   291             return zip(*ordered)[1]
       
   292         else:
       
   293             return []
       
   294     
       
   295     def _GetChildBySomething(self, something, toks):
       
   296         for CTNInstance in self.IterChildren():
       
   297             # if match component of the name
       
   298             if getattr(CTNInstance.BaseParams, something) == toks[0]:
       
   299                 # if Name have other components
       
   300                 if len(toks) >= 2:
       
   301                     # Recurse in order to find the latest object
       
   302                     return CTNInstance._GetChildBySomething( something, toks[1:])
       
   303                 # No sub name -> found
       
   304                 return CTNInstance
       
   305         # Not found
       
   306         return None
       
   307 
       
   308     def GetChildByName(self, Name):
       
   309         if Name:
       
   310             toks = Name.split('.')
       
   311             return self._GetChildBySomething("Name", toks)
       
   312         else:
       
   313             return self
       
   314 
       
   315     def GetChildByIECLocation(self, Location):
       
   316         if Location:
       
   317             return self._GetChildBySomething("IEC_Channel", Location)
       
   318         else:
       
   319             return self
       
   320     
       
   321     def GetCurrentLocation(self):
       
   322         """
       
   323         @return:  Tupple containing confnode IEC location of current confnode : %I0.0.4.5 => (0,0,4,5)
       
   324         """
       
   325         return self.CTNParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),)
       
   326 
       
   327     def GetCurrentName(self):
       
   328         """
       
   329         @return:  String "ParentParentName.ParentName.Name"
       
   330         """
       
   331         return  self.CTNParent._GetCurrentName() + self.BaseParams.getName()
       
   332 
       
   333     def _GetCurrentName(self):
       
   334         """
       
   335         @return:  String "ParentParentName.ParentName.Name."
       
   336         """
       
   337         return  self.CTNParent._GetCurrentName() + self.BaseParams.getName() + "."
       
   338 
       
   339     def GetCTRoot(self):
       
   340         return self.CTNParent.GetCTRoot()
       
   341 
       
   342     def GetFullIEC_Channel(self):
       
   343         return ".".join([str(i) for i in self.GetCurrentLocation()]) + ".x"
       
   344 
       
   345     def GetLocations(self):
       
   346         location = self.GetCurrentLocation()
       
   347         return [loc for loc in self.CTNParent.GetLocations() if loc["LOC"][0:len(location)] == location]
       
   348 
       
   349     def GetVariableLocationTree(self):
       
   350         '''
       
   351         This function is meant to be overridden by confnodes.
       
   352 
       
   353         It should returns an list of dictionaries
       
   354         
       
   355         - IEC_type is an IEC type like BOOL/BYTE/SINT/...
       
   356         - location is a string of this variable's location, like "%IX0.0.0"
       
   357         '''
       
   358         children = []
       
   359         for child in self.IECSortedChildren():
       
   360             children.append(child.GetVariableLocationTree())
       
   361         return {"name": self.BaseParams.getName(),
       
   362                 "type": LOCATION_CONFNODE,
       
   363                 "location": self.GetFullIEC_Channel(),
       
   364                 "children": children}
       
   365 
       
   366     def FindNewName(self, DesiredName):
       
   367         """
       
   368         Changes Name to DesiredName if available, Name-N if not.
       
   369         @param DesiredName: The desired Name (string)
       
   370         """
       
   371         # Get Current Name
       
   372         CurrentName = self.BaseParams.getName()
       
   373         # Do nothing if no change
       
   374         #if CurrentName == DesiredName: return CurrentName
       
   375         # Build a list of used Name out of parent's Children
       
   376         AllNames=[]
       
   377         for CTNInstance in self.CTNParent.IterChildren():
       
   378             if CTNInstance != self:
       
   379                 AllNames.append(CTNInstance.BaseParams.getName())
       
   380 
       
   381         # Find a free name, eventually appending digit
       
   382         res = DesiredName
       
   383         suffix = 1
       
   384         while res in AllNames:
       
   385             res = "%s-%d"%(DesiredName, suffix)
       
   386             suffix += 1
       
   387         
       
   388         # Get old path
       
   389         oldname = self.CTNPath()
       
   390         # Check previous confnode existance
       
   391         dontexist = self.BaseParams.getName() == "__unnamed__"
       
   392         # Set the new name
       
   393         self.BaseParams.setName(res)
       
   394         # Rename confnode dir if exist
       
   395         if not dontexist:
       
   396             shutil.move(oldname, self.CTNPath())
       
   397         # warn user he has two left hands
       
   398         if DesiredName != res:
       
   399             self.GetCTRoot().logger.write_warning(_("A child names \"%s\" already exist -> \"%s\"\n")%(DesiredName,res))
       
   400         return res
       
   401 
       
   402     def GetAllChannels(self):
       
   403         AllChannels=[]
       
   404         for CTNInstance in self.CTNParent.IterChildren():
       
   405             if CTNInstance != self:
       
   406                 AllChannels.append(CTNInstance.BaseParams.getIEC_Channel())
       
   407         AllChannels.sort()
       
   408         return AllChannels
       
   409 
       
   410     def FindNewIEC_Channel(self, DesiredChannel):
       
   411         """
       
   412         Changes IEC Channel number to DesiredChannel if available, nearest available if not.
       
   413         @param DesiredChannel: The desired IEC channel (int)
       
   414         """
       
   415         # Get Current IEC channel
       
   416         CurrentChannel = self.BaseParams.getIEC_Channel()
       
   417         # Do nothing if no change
       
   418         #if CurrentChannel == DesiredChannel: return CurrentChannel
       
   419         # Build a list of used Channels out of parent's Children
       
   420         AllChannels = self.GetAllChannels()
       
   421         
       
   422         # Now, try to guess the nearest available channel
       
   423         res = DesiredChannel
       
   424         while res in AllChannels: # While channel not free
       
   425             if res < CurrentChannel: # Want to go down ?
       
   426                 res -=  1 # Test for n-1
       
   427                 if res < 0 :
       
   428                     self.GetCTRoot().logger.write_warning(_("Cannot find lower free IEC channel than %d\n")%CurrentChannel)
       
   429                     return CurrentChannel # Can't go bellow 0, do nothing
       
   430             else : # Want to go up ?
       
   431                 res +=  1 # Test for n-1
       
   432         # Finally set IEC Channel
       
   433         self.BaseParams.setIEC_Channel(res)
       
   434         return res
       
   435 
       
   436     def _OpenView(self, name=None):
       
   437         if self.EditorType is not None and self._View is None:
       
   438             app_frame = self.GetCTRoot().AppFrame
       
   439             
       
   440             self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
       
   441             
       
   442             app_frame.EditProjectElement(self._View, self.CTNName())
       
   443             
       
   444             return self._View
       
   445         return None
       
   446 
       
   447     def OnCloseEditor(self, view):
       
   448         if self._View == view:
       
   449             self._View = None
       
   450 
       
   451     def OnCTNClose(self):
       
   452         if self._View is not None:
       
   453             app_frame = self.GetCTRoot().AppFrame
       
   454             if app_frame is not None:
       
   455                 app_frame.DeletePage(self._View)
       
   456         return True
       
   457 
       
   458     def _doRemoveChild(self, CTNInstance):
       
   459         # Remove all children of child
       
   460         for SubCTNInstance in CTNInstance.IterChildren():
       
   461             CTNInstance._doRemoveChild(SubCTNInstance)
       
   462         # Call the OnCloseMethod
       
   463         CTNInstance.OnCTNClose()
       
   464         # Delete confnode dir
       
   465         shutil.rmtree(CTNInstance.CTNPath())
       
   466         # Remove child of Children
       
   467         self.Children[CTNInstance.CTNType].remove(CTNInstance)
       
   468         # Forget it... (View have to refresh)
       
   469 
       
   470     def CTNRemove(self):
       
   471         # Fetch the confnode
       
   472         #CTNInstance = self.GetChildByName(CTNName)
       
   473         # Ask to his parent to remove it
       
   474         self.CTNParent._doRemoveChild(self)
       
   475 
       
   476     def CTNAddChild(self, CTNName, CTNType, IEC_Channel=0):
       
   477         """
       
   478         Create the confnodes that may be added as child to this node self
       
   479         @param CTNType: string desining the confnode class name (get name from CTNChildrenTypes)
       
   480         @param CTNName: string for the name of the confnode instance
       
   481         """
       
   482         # reorganize self.CTNChildrenTypes tuples from (name, CTNClass, Help)
       
   483         # to ( name, (CTNClass, Help)), an make a dict
       
   484         transpose = zip(*self.CTNChildrenTypes)
       
   485         CTNChildrenTypes = dict(zip(transpose[0],zip(transpose[1],transpose[2])))
       
   486         # Check that adding this confnode is allowed
       
   487         try:
       
   488             CTNClass, CTNHelp = CTNChildrenTypes[CTNType]
       
   489         except KeyError:
       
   490             raise Exception, _("Cannot create child %s of type %s ")%(CTNName, CTNType)
       
   491         
       
   492         # if CTNClass is a class factory, call it. (prevent unneeded imports)
       
   493         if type(CTNClass) == types.FunctionType:
       
   494             CTNClass = CTNClass()
       
   495         
       
   496         # Eventualy Initialize child instance list for this class of confnode
       
   497         ChildrenWithSameClass = self.Children.setdefault(CTNType, list())
       
   498         # Check count
       
   499         if getattr(CTNClass, "CTNMaxCount", None) and len(ChildrenWithSameClass) >= CTNClass.CTNMaxCount:
       
   500             raise Exception, _("Max count (%d) reached for this confnode of type %s ")%(CTNClass.CTNMaxCount, CTNType)
       
   501         
       
   502         # create the final class, derived of provided confnode and template
       
   503         class FinalCTNClass(CTNClass, ConfigTreeNode):
       
   504             """
       
   505             ConfNode class is derivated into FinalCTNClass before being instanciated
       
   506             This way __init__ is overloaded to ensure ConfigTreeNode.__init__ is called 
       
   507             before CTNClass.__init__, and to do the file related stuff.
       
   508             """
       
   509             def __init__(_self):
       
   510                 # self is the parent
       
   511                 _self.CTNParent = self
       
   512                 # Keep track of the confnode type name
       
   513                 _self.CTNType = CTNType
       
   514                 # remind the help string, for more fancy display
       
   515                 _self.CTNHelp = CTNHelp
       
   516                 # Call the base confnode template init - change XSD into class members
       
   517                 ConfigTreeNode.__init__(_self)
       
   518                 # check name is unique
       
   519                 NewCTNName = _self.FindNewName(CTNName)
       
   520                 # If dir have already be made, and file exist
       
   521                 if os.path.isdir(_self.CTNPath(NewCTNName)): #and os.path.isfile(_self.ConfNodeXmlFilePath(CTNName)):
       
   522                     #Load the confnode.xml file into parameters members
       
   523                     _self.LoadXMLParams(NewCTNName)
       
   524                     # Basic check. Better to fail immediately.
       
   525                     if (_self.BaseParams.getName() != NewCTNName):
       
   526                         raise Exception, _("Project tree layout do not match confnode.xml %s!=%s ")%(NewCTNName, _self.BaseParams.getName())
       
   527 
       
   528                     # Now, self.CTNPath() should be OK
       
   529                     
       
   530                     # Check that IEC_Channel is not already in use.
       
   531                     _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
       
   532                     # Call the confnode real __init__
       
   533                     if getattr(CTNClass, "__init__", None):
       
   534                         CTNClass.__init__(_self)
       
   535                     #Load and init all the children
       
   536                     _self.LoadChildren()
       
   537                     #just loaded, nothing to saved
       
   538                     _self.ChangesToSave = False
       
   539                 else:
       
   540                     # If confnode do not have corresponding file/dirs - they will be created on Save
       
   541                     _self.CTNMakeDir()
       
   542                     # Find an IEC number
       
   543                     _self.FindNewIEC_Channel(IEC_Channel)
       
   544                     # Call the confnode real __init__
       
   545                     if getattr(CTNClass, "__init__", None):
       
   546                         CTNClass.__init__(_self)
       
   547                     _self.CTNRequestSave()
       
   548                     #just created, must be saved
       
   549                     _self.ChangesToSave = True
       
   550                 
       
   551             def _getBuildPath(_self):
       
   552                 return self._getBuildPath()
       
   553             
       
   554         # Create the object out of the resulting class
       
   555         newConfNodeOpj = FinalCTNClass()
       
   556         # Store it in CTNgedChils
       
   557         ChildrenWithSameClass.append(newConfNodeOpj)
       
   558         
       
   559         return newConfNodeOpj
       
   560     
       
   561     def ClearChildren(self):
       
   562         for child in self.IterChildren():
       
   563             child.ClearChildren()
       
   564         self.Children = {}
       
   565     
       
   566     def LoadSTLibrary(self):
       
   567         # Get library blocks if plcopen library exist
       
   568         library_path = self.ConfNodeLibraryFilePath()
       
   569         if os.path.isfile(library_path):
       
   570             self.LibraryControler = PLCControler()
       
   571             self.LibraryControler.OpenXMLFile(library_path)
       
   572             self.LibraryControler.ClearConfNodeTypes()
       
   573             self.LibraryControler.AddConfNodeTypesList(self.ParentsTypesFactory())
       
   574 
       
   575     def LoadXMLParams(self, CTNName = None):
       
   576         methode_name = os.path.join(self.CTNPath(CTNName), "methods.py")
       
   577         if os.path.isfile(methode_name):
       
   578             execfile(methode_name)
       
   579         
       
   580         # Get the base xml tree
       
   581         if self.MandatoryParams:
       
   582             try:
       
   583                 basexmlfile = open(self.ConfNodeBaseXmlFilePath(CTNName), 'r')
       
   584                 basetree = minidom.parse(basexmlfile)
       
   585                 self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
       
   586                 basexmlfile.close()
       
   587             except Exception, exc:
       
   588                 self.GetCTRoot().logger.write_error(_("Couldn't load confnode base parameters %s :\n %s") % (CTNName, str(exc)))
       
   589                 self.GetCTRoot().logger.write_error(traceback.format_exc())
       
   590         
       
   591         # Get the xml tree
       
   592         if self.CTNParams:
       
   593             try:
       
   594                 xmlfile = open(self.ConfNodeXmlFilePath(CTNName), 'r')
       
   595                 tree = minidom.parse(xmlfile)
       
   596                 self.CTNParams[1].loadXMLTree(tree.childNodes[0])
       
   597                 xmlfile.close()
       
   598             except Exception, exc:
       
   599                 self.GetCTRoot().logger.write_error(_("Couldn't load confnode parameters %s :\n %s") % (CTNName, str(exc)))
       
   600                 self.GetCTRoot().logger.write_error(traceback.format_exc())
       
   601         
       
   602     def LoadChildren(self):
       
   603         # Iterate over all CTNName@CTNType in confnode directory, and try to open them
       
   604         for CTNDir in os.listdir(self.CTNPath()):
       
   605             if os.path.isdir(os.path.join(self.CTNPath(), CTNDir)) and \
       
   606                CTNDir.count(NameTypeSeparator) == 1:
       
   607                 pname, ptype = CTNDir.split(NameTypeSeparator)
       
   608                 try:
       
   609                     self.CTNAddChild(pname, ptype)
       
   610                 except Exception, exc:
       
   611                     self.GetCTRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc)))
       
   612                     self.GetCTRoot().logger.write_error(traceback.format_exc())
       
   613 
       
   614     def EnableMethod(self, method, value):
       
   615         for d in self.ConfNodeMethods:
       
   616             if d["method"]==method:
       
   617                 d["enabled"]=value
       
   618                 return True
       
   619         return False
       
   620 
       
   621     def ShowMethod(self, method, value):
       
   622         for d in self.ConfNodeMethods:
       
   623             if d["method"]==method:
       
   624                 d["shown"]=value
       
   625                 return True
       
   626         return False
       
   627 
       
   628     def CallMethod(self, method):
       
   629         for d in self.ConfNodeMethods:
       
   630             if d["method"]==method and d.get("enabled", True) and d.get("shown", True):
       
   631                 getattr(self, method)()
       
   632