ConfigTree.py
changeset 718 5d4dc150b956
parent 717 1c23952dbde1
child 720 6be032177e2a
equal deleted inserted replaced
717:1c23952dbde1 718:5d4dc150b956
    34 class MiniTextControler:
    34 class MiniTextControler:
    35     
    35     
    36     def __init__(self, filepath):
    36     def __init__(self, filepath):
    37         self.FilePath = filepath
    37         self.FilePath = filepath
    38     
    38     
    39     def PlugFullName(self):
    39     def CTNFullName(self):
    40         return ""
    40         return ""
    41     
    41     
    42     def SetEditedElementText(self, tagname, text):
    42     def SetEditedElementText(self, tagname, text):
    43         file = open(self.FilePath, "w")
    43         file = open(self.FilePath, "w")
    44         file.write(text)
    44         file.write(text)
    94     """
    94     """
    95     This class is the one that define confnodes.
    95     This class is the one that define confnodes.
    96     """
    96     """
    97 
    97 
    98     XSD = None
    98     XSD = None
    99     PlugChildsTypes = []
    99     CTNChildrenTypes = []
   100     PlugMaxCount = None
   100     CTNMaxCount = None
   101     ConfNodeMethods = []
   101     ConfNodeMethods = []
   102     LibraryControler = None
   102     LibraryControler = None
   103     EditorType = None
   103     EditorType = None
   104 
   104 
   105     def _AddParamsMembers(self):
   105     def _AddParamsMembers(self):
   106         self.PlugParams = None
   106         self.CTNParams = None
   107         if self.XSD:
   107         if self.XSD:
   108             self.Classes = GenerateClassesFromXSDstring(self.XSD)
   108             self.Classes = GenerateClassesFromXSDstring(self.XSD)
   109             Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass]
   109             Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass]
   110             if len(Classes) == 1:
   110             if len(Classes) == 1:
   111                 name, XSDclass = Classes[0]
   111                 name, XSDclass = Classes[0]
   112                 obj = XSDclass()
   112                 obj = XSDclass()
   113                 self.PlugParams = (name, obj)
   113                 self.CTNParams = (name, obj)
   114                 setattr(self, name, obj)
   114                 setattr(self, name, obj)
   115 
   115 
   116     def __init__(self):
   116     def __init__(self):
   117         # Create BaseParam 
   117         # Create BaseParam 
   118         self.BaseParams = _BaseParamsClass()
   118         self.BaseParams = _BaseParamsClass()
   119         self.MandatoryParams = ("BaseParams", self.BaseParams)
   119         self.MandatoryParams = ("BaseParams", self.BaseParams)
   120         self._AddParamsMembers()
   120         self._AddParamsMembers()
   121         self.PluggedChilds = {}
   121         self.Children = {}
   122         self._View = None
   122         self._View = None
   123         # copy ConfNodeMethods so that it can be later customized
   123         # copy ConfNodeMethods so that it can be later customized
   124         self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods]
   124         self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods]
   125         self.LoadSTLibrary()
   125         self.LoadSTLibrary()
   126         
   126         
   127     def ConfNodeBaseXmlFilePath(self, PlugName=None):
   127     def ConfNodeBaseXmlFilePath(self, CTNName=None):
   128         return os.path.join(self.PlugPath(PlugName), "baseconfnode.xml")
   128         return os.path.join(self.CTNPath(CTNName), "baseconfnode.xml")
   129     
   129     
   130     def ConfNodeXmlFilePath(self, PlugName=None):
   130     def ConfNodeXmlFilePath(self, CTNName=None):
   131         return os.path.join(self.PlugPath(PlugName), "confnode.xml")
   131         return os.path.join(self.CTNPath(CTNName), "confnode.xml")
   132 
   132 
   133     def ConfNodeLibraryFilePath(self):
   133     def ConfNodeLibraryFilePath(self):
   134         return os.path.join(self.ConfNodePath(), "pous.xml")
   134         return os.path.join(self.ConfNodePath(), "pous.xml")
   135 
   135 
   136     def ConfNodePath(self):
   136     def ConfNodePath(self):
   137         return os.path.join(self.PlugParent.ConfNodePath(), self.PlugType)
   137         return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType)
   138 
   138 
   139     def PlugPath(self,PlugName=None):
   139     def CTNPath(self,CTNName=None):
   140         if not PlugName:
   140         if not CTNName:
   141             PlugName = self.PlugName()
   141             CTNName = self.CTNName()
   142         return os.path.join(self.PlugParent.PlugPath(),
   142         return os.path.join(self.CTNParent.CTNPath(),
   143                             PlugName + NameTypeSeparator + self.PlugType)
   143                             CTNName + NameTypeSeparator + self.CTNType)
   144     
   144     
   145     def PlugName(self):
   145     def CTNName(self):
   146         return self.BaseParams.getName()
   146         return self.BaseParams.getName()
   147     
   147     
   148     def PlugEnabled(self):
   148     def CTNEnabled(self):
   149         return self.BaseParams.getEnabled()
   149         return self.BaseParams.getEnabled()
   150     
   150     
   151     def PlugFullName(self):
   151     def CTNFullName(self):
   152         parent = self.PlugParent.PlugFullName()
   152         parent = self.CTNParent.CTNFullName()
   153         if parent != "":
   153         if parent != "":
   154             return parent + "." + self.PlugName()
   154             return parent + "." + self.CTNName()
   155         return self.BaseParams.getName()
   155         return self.BaseParams.getName()
   156     
   156     
   157     def GetIconPath(self, name):
   157     def GetIconPath(self, name):
   158         return opjimg(name)
   158         return opjimg(name)
   159     
   159     
   160     def PlugTestModified(self):
   160     def CTNTestModified(self):
   161         return self.ChangesToSave
   161         return self.ChangesToSave
   162 
   162 
   163     def ProjectTestModified(self):
   163     def ProjectTestModified(self):
   164         """
   164         """
   165         recursively check modified status
   165         recursively check modified status
   166         """
   166         """
   167         if self.PlugTestModified():
   167         if self.CTNTestModified():
   168             return True
   168             return True
   169 
   169 
   170         for PlugChild in self.IterChilds():
   170         for CTNChild in self.IterChildren():
   171             if PlugChild.ProjectTestModified():
   171             if CTNChild.ProjectTestModified():
   172                 return True
   172                 return True
   173 
   173 
   174         return False
   174         return False
   175     
   175     
   176     def RemoteExec(self, script, **kwargs):
   176     def RemoteExec(self, script, **kwargs):
   177         return self.PlugParent.RemoteExec(script, **kwargs)
   177         return self.CTNParent.RemoteExec(script, **kwargs)
   178     
   178     
   179     def OnPlugSave(self):
   179     def OnCTNSave(self):
   180         #Default, do nothing and return success
   180         #Default, do nothing and return success
   181         return True
   181         return True
   182 
   182 
   183     def GetParamsAttributes(self, path = None):
   183     def GetParamsAttributes(self, path = None):
   184         if path:
   184         if path:
   185             parts = path.split(".", 1)
   185             parts = path.split(".", 1)
   186             if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
   186             if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
   187                 return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
   187                 return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
   188             elif self.PlugParams and parts[0] == self.PlugParams[0]:
   188             elif self.CTNParams and parts[0] == self.CTNParams[0]:
   189                 return self.PlugParams[1].getElementInfos(parts[0], parts[1])
   189                 return self.CTNParams[1].getElementInfos(parts[0], parts[1])
   190         else:
   190         else:
   191             params = []
   191             params = []
   192             if wx.VERSION < (2, 8, 0) and self.MandatoryParams:
   192             if wx.VERSION < (2, 8, 0) and self.MandatoryParams:
   193                 params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0]))
   193                 params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0]))
   194             if self.PlugParams:
   194             if self.CTNParams:
   195                 params.append(self.PlugParams[1].getElementInfos(self.PlugParams[0]))
   195                 params.append(self.CTNParams[1].getElementInfos(self.CTNParams[0]))
   196             return params
   196             return params
   197         
   197         
   198     def SetParamsAttribute(self, path, value):
   198     def SetParamsAttribute(self, path, value):
   199         self.ChangesToSave = True
   199         self.ChangesToSave = True
   200         # Filter IEC_Channel and Name, that have specific behavior
   200         # Filter IEC_Channel and Name, that have specific behavior
   201         if path == "BaseParams.IEC_Channel":
   201         if path == "BaseParams.IEC_Channel":
   202             old_leading = ".".join(map(str, self.GetCurrentLocation()))
   202             old_leading = ".".join(map(str, self.GetCurrentLocation()))
   203             new_value = self.FindNewIEC_Channel(value)
   203             new_value = self.FindNewIEC_Channel(value)
   204             new_leading = ".".join(map(str, self.PlugParent.GetCurrentLocation() + (new_value,)))
   204             new_leading = ".".join(map(str, self.CTNParent.GetCurrentLocation() + (new_value,)))
   205             self.GetPlugRoot().UpdateProjectVariableLocation(old_leading, new_leading)
   205             self.GetCTRoot().UpdateProjectVariableLocation(old_leading, new_leading)
   206             return new_value, True
   206             return new_value, True
   207         elif path == "BaseParams.Name":
   207         elif path == "BaseParams.Name":
   208             res = self.FindNewName(value)
   208             res = self.FindNewName(value)
   209             self.PlugRequestSave()
   209             self.CTNRequestSave()
   210             return res, True
   210             return res, True
   211         
   211         
   212         parts = path.split(".", 1)
   212         parts = path.split(".", 1)
   213         if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
   213         if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
   214             self.MandatoryParams[1].setElementValue(parts[1], value)
   214             self.MandatoryParams[1].setElementValue(parts[1], value)
   215         elif self.PlugParams and parts[0] == self.PlugParams[0]:
   215         elif self.CTNParams and parts[0] == self.CTNParams[0]:
   216             self.PlugParams[1].setElementValue(parts[1], value)
   216             self.CTNParams[1].setElementValue(parts[1], value)
   217         return value, False
   217         return value, False
   218 
   218 
   219     def PlugMakeDir(self):
   219     def CTNMakeDir(self):
   220         os.mkdir(self.PlugPath())
   220         os.mkdir(self.CTNPath())
   221 
   221 
   222     def PlugRequestSave(self):
   222     def CTNRequestSave(self):
   223         if self.GetPlugRoot().CheckProjectPathPerm(False):
   223         if self.GetCTRoot().CheckProjectPathPerm(False):
   224             # If confnode do not have corresponding directory
   224             # If confnode do not have corresponding directory
   225             plugpath = self.PlugPath()
   225             ctnpath = self.CTNPath()
   226             if not os.path.isdir(plugpath):
   226             if not os.path.isdir(ctnpath):
   227                 # Create it
   227                 # Create it
   228                 os.mkdir(plugpath)
   228                 os.mkdir(ctnpath)
   229     
   229     
   230             # generate XML for base XML parameters controller of the confnode
   230             # generate XML for base XML parameters controller of the confnode
   231             if self.MandatoryParams:
   231             if self.MandatoryParams:
   232                 BaseXMLFile = open(self.ConfNodeBaseXmlFilePath(),'w')
   232                 BaseXMLFile = open(self.ConfNodeBaseXmlFilePath(),'w')
   233                 BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
   233                 BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
   234                 BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
   234                 BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
   235                 BaseXMLFile.close()
   235                 BaseXMLFile.close()
   236             
   236             
   237             # generate XML for XML parameters controller of the confnode
   237             # generate XML for XML parameters controller of the confnode
   238             if self.PlugParams:
   238             if self.CTNParams:
   239                 XMLFile = open(self.ConfNodeXmlFilePath(),'w')
   239                 XMLFile = open(self.ConfNodeXmlFilePath(),'w')
   240                 XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
   240                 XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
   241                 XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0).encode("utf-8"))
   241                 XMLFile.write(self.CTNParams[1].generateXMLText(self.CTNParams[0], 0).encode("utf-8"))
   242                 XMLFile.close()
   242                 XMLFile.close()
   243             
   243             
   244             # Call the confnode specific OnPlugSave method
   244             # Call the confnode specific OnCTNSave method
   245             result = self.OnPlugSave()
   245             result = self.OnCTNSave()
   246             if not result:
   246             if not result:
   247                 return _("Error while saving \"%s\"\n")%self.PlugPath()
   247                 return _("Error while saving \"%s\"\n")%self.CTNPath()
   248     
   248     
   249             # mark confnode as saved
   249             # mark confnode as saved
   250             self.ChangesToSave = False
   250             self.ChangesToSave = False
   251             # go through all childs and do the same
   251             # go through all children and do the same
   252             for PlugChild in self.IterChilds():
   252             for CTNChild in self.IterChildren():
   253                 result = PlugChild.PlugRequestSave()
   253                 result = CTNChild.CTNRequestSave()
   254                 if result:
   254                 if result:
   255                     return result
   255                     return result
   256         return None
   256         return None
   257     
   257     
   258     def PlugImport(self, src_PlugPath):
   258     def CTNImport(self, src_CTNPath):
   259         shutil.copytree(src_PlugPath, self.PlugPath)
   259         shutil.copytree(src_CTNPath, self.CTNPath)
   260         return True
   260         return True
   261 
   261 
   262     def PlugGenerate_C(self, buildpath, locations):
   262     def CTNGenerate_C(self, buildpath, locations):
   263         """
   263         """
   264         Generate C code
   264         Generate C code
   265         @param locations: List of complete variables locations \
   265         @param locations: List of complete variables locations \
   266             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
   266             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
   267             "NAME" : name of the variable (generally "__IW0_1_2" style)
   267             "NAME" : name of the variable (generally "__IW0_1_2" style)
   269             "SIZE" : size "X", "B", "W", "D", "L"
   269             "SIZE" : size "X", "B", "W", "D", "L"
   270             "LOC" : tuple of interger for IEC location (0,1,2,...)
   270             "LOC" : tuple of interger for IEC location (0,1,2,...)
   271             }, ...]
   271             }, ...]
   272         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   272         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   273         """
   273         """
   274         self.GetPlugRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n")
   274         self.GetCTRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n")
   275         return [],"",False
   275         return [],"",False
   276     
   276     
   277     def _Generate_C(self, buildpath, locations):
   277     def _Generate_C(self, buildpath, locations):
   278         # Generate confnodes [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files
   278         # Generate confnodes [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files
   279         # extra_files = [(fname,fobject), ...]
   279         # extra_files = [(fname,fobject), ...]
   280         gen_result = self.PlugGenerate_C(buildpath, locations)
   280         gen_result = self.CTNGenerate_C(buildpath, locations)
   281         PlugCFilesAndCFLAGS, PlugLDFLAGS, DoCalls = gen_result[:3]
   281         CTNCFilesAndCFLAGS, CTNLDFLAGS, DoCalls = gen_result[:3]
   282         extra_files = gen_result[3:]
   282         extra_files = gen_result[3:]
   283         # if some files have been generated put them in the list with their location
   283         # if some files have been generated put them in the list with their location
   284         if PlugCFilesAndCFLAGS:
   284         if CTNCFilesAndCFLAGS:
   285             LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), PlugCFilesAndCFLAGS, DoCalls)]
   285             LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), CTNCFilesAndCFLAGS, DoCalls)]
   286         else:
   286         else:
   287             LocationCFilesAndCFLAGS = []
   287             LocationCFilesAndCFLAGS = []
   288 
   288 
   289         # confnode asks for some LDFLAGS
   289         # confnode asks for some LDFLAGS
   290         if PlugLDFLAGS:
   290         if CTNLDFLAGS:
   291             # LDFLAGS can be either string
   291             # LDFLAGS can be either string
   292             if type(PlugLDFLAGS)==type(str()):
   292             if type(CTNLDFLAGS)==type(str()):
   293                 LDFLAGS=[PlugLDFLAGS]
   293                 LDFLAGS=[CTNLDFLAGS]
   294             #or list of strings
   294             #or list of strings
   295             elif type(PlugLDFLAGS)==type(list()):
   295             elif type(CTNLDFLAGS)==type(list()):
   296                 LDFLAGS=PlugLDFLAGS[:]
   296                 LDFLAGS=CTNLDFLAGS[:]
   297         else:
   297         else:
   298             LDFLAGS=[]
   298             LDFLAGS=[]
   299         
   299         
   300         # recurse through all childs, and stack their results
   300         # recurse through all children, and stack their results
   301         for PlugChild in self.IECSortedChilds():
   301         for CTNChild in self.IECSortedChildren():
   302             new_location = PlugChild.GetCurrentLocation()
   302             new_location = CTNChild.GetCurrentLocation()
   303             # How deep are we in the tree ?
   303             # How deep are we in the tree ?
   304             depth=len(new_location)
   304             depth=len(new_location)
   305             _LocationCFilesAndCFLAGS, _LDFLAGS, _extra_files = \
   305             _LocationCFilesAndCFLAGS, _LDFLAGS, _extra_files = \
   306                 PlugChild._Generate_C(
   306                 CTNChild._Generate_C(
   307                     #keep the same path
   307                     #keep the same path
   308                     buildpath,
   308                     buildpath,
   309                     # filter locations that start with current IEC location
   309                     # filter locations that start with current IEC location
   310                     [loc for loc in locations if loc["LOC"][0:depth] == new_location ])
   310                     [loc for loc in locations if loc["LOC"][0:depth] == new_location ])
   311             # stack the result
   311             # stack the result
   315         
   315         
   316         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
   316         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
   317 
   317 
   318     def ConfNodeTypesFactory(self):
   318     def ConfNodeTypesFactory(self):
   319         if self.LibraryControler is not None:
   319         if self.LibraryControler is not None:
   320             return [{"name" : self.PlugType, "types": self.LibraryControler.Project}]
   320             return [{"name" : self.CTNType, "types": self.LibraryControler.Project}]
   321         return []
   321         return []
   322 
   322 
   323     def ParentsTypesFactory(self):
   323     def ParentsTypesFactory(self):
   324         return self.PlugParent.ParentsTypesFactory() + self.ConfNodeTypesFactory()
   324         return self.CTNParent.ParentsTypesFactory() + self.ConfNodeTypesFactory()
   325 
   325 
   326     def ConfNodesTypesFactory(self):
   326     def ConfNodesTypesFactory(self):
   327         list = self.ConfNodeTypesFactory()
   327         list = self.ConfNodeTypesFactory()
   328         for PlugChild in self.IterChilds():
   328         for CTNChild in self.IterChildren():
   329             list += PlugChild.ConfNodesTypesFactory()
   329             list += CTNChild.ConfNodesTypesFactory()
   330         return list
   330         return list
   331 
   331 
   332     def STLibraryFactory(self):
   332     def STLibraryFactory(self):
   333         if self.LibraryControler is not None:
   333         if self.LibraryControler is not None:
   334             program, errors, warnings = self.LibraryControler.GenerateProgram()
   334             program, errors, warnings = self.LibraryControler.GenerateProgram()
   335             return program + "\n"
   335             return program + "\n"
   336         return ""
   336         return ""
   337 
   337 
   338     def ConfNodesSTLibraryFactory(self):
   338     def ConfNodesSTLibraryFactory(self):
   339         program = self.STLibraryFactory()
   339         program = self.STLibraryFactory()
   340         for PlugChild in self.IECSortedChilds():
   340         for CTNChild in self.IECSortedChildren():
   341             program += PlugChild.ConfNodesSTLibraryFactory()
   341             program += CTNChild.ConfNodesSTLibraryFactory()
   342         return program
   342         return program
   343         
   343         
   344     def IterChilds(self):
   344     def IterChildren(self):
   345         for PlugType, PluggedChilds in self.PluggedChilds.items():
   345         for CTNType, Children in self.Children.items():
   346             for PlugInstance in PluggedChilds:
   346             for CTNInstance in Children:
   347                 yield PlugInstance
   347                 yield CTNInstance
   348     
   348     
   349     def IECSortedChilds(self):
   349     def IECSortedChildren(self):
   350         # reorder childs by IEC_channels
   350         # reorder children by IEC_channels
   351         ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChilds()]
   351         ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChildren()]
   352         if ordered:
   352         if ordered:
   353             ordered.sort()
   353             ordered.sort()
   354             return zip(*ordered)[1]
   354             return zip(*ordered)[1]
   355         else:
   355         else:
   356             return []
   356             return []
   357     
   357     
   358     def _GetChildBySomething(self, something, toks):
   358     def _GetChildBySomething(self, something, toks):
   359         for PlugInstance in self.IterChilds():
   359         for CTNInstance in self.IterChildren():
   360             # if match component of the name
   360             # if match component of the name
   361             if getattr(PlugInstance.BaseParams, something) == toks[0]:
   361             if getattr(CTNInstance.BaseParams, something) == toks[0]:
   362                 # if Name have other components
   362                 # if Name have other components
   363                 if len(toks) >= 2:
   363                 if len(toks) >= 2:
   364                     # Recurse in order to find the latest object
   364                     # Recurse in order to find the latest object
   365                     return PlugInstance._GetChildBySomething( something, toks[1:])
   365                     return CTNInstance._GetChildBySomething( something, toks[1:])
   366                 # No sub name -> found
   366                 # No sub name -> found
   367                 return PlugInstance
   367                 return CTNInstance
   368         # Not found
   368         # Not found
   369         return None
   369         return None
   370 
   370 
   371     def GetChildByName(self, Name):
   371     def GetChildByName(self, Name):
   372         if Name:
   372         if Name:
   383     
   383     
   384     def GetCurrentLocation(self):
   384     def GetCurrentLocation(self):
   385         """
   385         """
   386         @return:  Tupple containing confnode IEC location of current confnode : %I0.0.4.5 => (0,0,4,5)
   386         @return:  Tupple containing confnode IEC location of current confnode : %I0.0.4.5 => (0,0,4,5)
   387         """
   387         """
   388         return self.PlugParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),)
   388         return self.CTNParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),)
   389 
   389 
   390     def GetCurrentName(self):
   390     def GetCurrentName(self):
   391         """
   391         """
   392         @return:  String "ParentParentName.ParentName.Name"
   392         @return:  String "ParentParentName.ParentName.Name"
   393         """
   393         """
   394         return  self.PlugParent._GetCurrentName() + self.BaseParams.getName()
   394         return  self.CTNParent._GetCurrentName() + self.BaseParams.getName()
   395 
   395 
   396     def _GetCurrentName(self):
   396     def _GetCurrentName(self):
   397         """
   397         """
   398         @return:  String "ParentParentName.ParentName.Name."
   398         @return:  String "ParentParentName.ParentName.Name."
   399         """
   399         """
   400         return  self.PlugParent._GetCurrentName() + self.BaseParams.getName() + "."
   400         return  self.CTNParent._GetCurrentName() + self.BaseParams.getName() + "."
   401 
   401 
   402     def GetPlugRoot(self):
   402     def GetCTRoot(self):
   403         return self.PlugParent.GetPlugRoot()
   403         return self.CTNParent.GetCTRoot()
   404 
   404 
   405     def GetFullIEC_Channel(self):
   405     def GetFullIEC_Channel(self):
   406         return ".".join([str(i) for i in self.GetCurrentLocation()]) + ".x"
   406         return ".".join([str(i) for i in self.GetCurrentLocation()]) + ".x"
   407 
   407 
   408     def GetLocations(self):
   408     def GetLocations(self):
   409         location = self.GetCurrentLocation()
   409         location = self.GetCurrentLocation()
   410         return [loc for loc in self.PlugParent.GetLocations() if loc["LOC"][0:len(location)] == location]
   410         return [loc for loc in self.CTNParent.GetLocations() if loc["LOC"][0:len(location)] == location]
   411 
   411 
   412     def GetVariableLocationTree(self):
   412     def GetVariableLocationTree(self):
   413         '''
   413         '''
   414         This function is meant to be overridden by confnodes.
   414         This function is meant to be overridden by confnodes.
   415 
   415 
   417         
   417         
   418         - IEC_type is an IEC type like BOOL/BYTE/SINT/...
   418         - IEC_type is an IEC type like BOOL/BYTE/SINT/...
   419         - location is a string of this variable's location, like "%IX0.0.0"
   419         - location is a string of this variable's location, like "%IX0.0.0"
   420         '''
   420         '''
   421         children = []
   421         children = []
   422         for child in self.IECSortedChilds():
   422         for child in self.IECSortedChildren():
   423             children.append(child.GetVariableLocationTree())
   423             children.append(child.GetVariableLocationTree())
   424         return {"name": self.BaseParams.getName(),
   424         return {"name": self.BaseParams.getName(),
   425                 "type": LOCATION_CONFNODE,
   425                 "type": LOCATION_CONFNODE,
   426                 "location": self.GetFullIEC_Channel(),
   426                 "location": self.GetFullIEC_Channel(),
   427                 "children": children}
   427                 "children": children}
   433         """
   433         """
   434         # Get Current Name
   434         # Get Current Name
   435         CurrentName = self.BaseParams.getName()
   435         CurrentName = self.BaseParams.getName()
   436         # Do nothing if no change
   436         # Do nothing if no change
   437         #if CurrentName == DesiredName: return CurrentName
   437         #if CurrentName == DesiredName: return CurrentName
   438         # Build a list of used Name out of parent's PluggedChilds
   438         # Build a list of used Name out of parent's Children
   439         AllNames=[]
   439         AllNames=[]
   440         for PlugInstance in self.PlugParent.IterChilds():
   440         for CTNInstance in self.CTNParent.IterChildren():
   441             if PlugInstance != self:
   441             if CTNInstance != self:
   442                 AllNames.append(PlugInstance.BaseParams.getName())
   442                 AllNames.append(CTNInstance.BaseParams.getName())
   443 
   443 
   444         # Find a free name, eventually appending digit
   444         # Find a free name, eventually appending digit
   445         res = DesiredName
   445         res = DesiredName
   446         suffix = 1
   446         suffix = 1
   447         while res in AllNames:
   447         while res in AllNames:
   448             res = "%s-%d"%(DesiredName, suffix)
   448             res = "%s-%d"%(DesiredName, suffix)
   449             suffix += 1
   449             suffix += 1
   450         
   450         
   451         # Get old path
   451         # Get old path
   452         oldname = self.PlugPath()
   452         oldname = self.CTNPath()
   453         # Check previous confnode existance
   453         # Check previous confnode existance
   454         dontexist = self.BaseParams.getName() == "__unnamed__"
   454         dontexist = self.BaseParams.getName() == "__unnamed__"
   455         # Set the new name
   455         # Set the new name
   456         self.BaseParams.setName(res)
   456         self.BaseParams.setName(res)
   457         # Rename confnode dir if exist
   457         # Rename confnode dir if exist
   458         if not dontexist:
   458         if not dontexist:
   459             shutil.move(oldname, self.PlugPath())
   459             shutil.move(oldname, self.CTNPath())
   460         # warn user he has two left hands
   460         # warn user he has two left hands
   461         if DesiredName != res:
   461         if DesiredName != res:
   462             self.GetPlugRoot().logger.write_warning(_("A child names \"%s\" already exist -> \"%s\"\n")%(DesiredName,res))
   462             self.GetCTRoot().logger.write_warning(_("A child names \"%s\" already exist -> \"%s\"\n")%(DesiredName,res))
   463         return res
   463         return res
   464 
   464 
   465     def GetAllChannels(self):
   465     def GetAllChannels(self):
   466         AllChannels=[]
   466         AllChannels=[]
   467         for PlugInstance in self.PlugParent.IterChilds():
   467         for CTNInstance in self.CTNParent.IterChildren():
   468             if PlugInstance != self:
   468             if CTNInstance != self:
   469                 AllChannels.append(PlugInstance.BaseParams.getIEC_Channel())
   469                 AllChannels.append(CTNInstance.BaseParams.getIEC_Channel())
   470         AllChannels.sort()
   470         AllChannels.sort()
   471         return AllChannels
   471         return AllChannels
   472 
   472 
   473     def FindNewIEC_Channel(self, DesiredChannel):
   473     def FindNewIEC_Channel(self, DesiredChannel):
   474         """
   474         """
   477         """
   477         """
   478         # Get Current IEC channel
   478         # Get Current IEC channel
   479         CurrentChannel = self.BaseParams.getIEC_Channel()
   479         CurrentChannel = self.BaseParams.getIEC_Channel()
   480         # Do nothing if no change
   480         # Do nothing if no change
   481         #if CurrentChannel == DesiredChannel: return CurrentChannel
   481         #if CurrentChannel == DesiredChannel: return CurrentChannel
   482         # Build a list of used Channels out of parent's PluggedChilds
   482         # Build a list of used Channels out of parent's Children
   483         AllChannels = self.GetAllChannels()
   483         AllChannels = self.GetAllChannels()
   484         
   484         
   485         # Now, try to guess the nearest available channel
   485         # Now, try to guess the nearest available channel
   486         res = DesiredChannel
   486         res = DesiredChannel
   487         while res in AllChannels: # While channel not free
   487         while res in AllChannels: # While channel not free
   488             if res < CurrentChannel: # Want to go down ?
   488             if res < CurrentChannel: # Want to go down ?
   489                 res -=  1 # Test for n-1
   489                 res -=  1 # Test for n-1
   490                 if res < 0 :
   490                 if res < 0 :
   491                     self.GetPlugRoot().logger.write_warning(_("Cannot find lower free IEC channel than %d\n")%CurrentChannel)
   491                     self.GetCTRoot().logger.write_warning(_("Cannot find lower free IEC channel than %d\n")%CurrentChannel)
   492                     return CurrentChannel # Can't go bellow 0, do nothing
   492                     return CurrentChannel # Can't go bellow 0, do nothing
   493             else : # Want to go up ?
   493             else : # Want to go up ?
   494                 res +=  1 # Test for n-1
   494                 res +=  1 # Test for n-1
   495         # Finally set IEC Channel
   495         # Finally set IEC Channel
   496         self.BaseParams.setIEC_Channel(res)
   496         self.BaseParams.setIEC_Channel(res)
   497         return res
   497         return res
   498 
   498 
   499     def _OpenView(self, name=None):
   499     def _OpenView(self, name=None):
   500         if self.EditorType is not None and self._View is None:
   500         if self.EditorType is not None and self._View is None:
   501             app_frame = self.GetPlugRoot().AppFrame
   501             app_frame = self.GetCTRoot().AppFrame
   502             
   502             
   503             self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
   503             self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
   504             
   504             
   505             app_frame.EditProjectElement(self._View, self.PlugName())
   505             app_frame.EditProjectElement(self._View, self.CTNName())
   506             
   506             
   507             return self._View
   507             return self._View
   508         return None
   508         return None
   509 
   509 
   510     def OnCloseEditor(self, view):
   510     def OnCloseEditor(self, view):
   511         if self._View == view:
   511         if self._View == view:
   512             self._View = None
   512             self._View = None
   513 
   513 
   514     def OnPlugClose(self):
   514     def OnCTNClose(self):
   515         if self._View is not None:
   515         if self._View is not None:
   516             app_frame = self.GetPlugRoot().AppFrame
   516             app_frame = self.GetCTRoot().AppFrame
   517             if app_frame is not None:
   517             if app_frame is not None:
   518                 app_frame.DeletePage(self._View)
   518                 app_frame.DeletePage(self._View)
   519         return True
   519         return True
   520 
   520 
   521     def _doRemoveChild(self, PlugInstance):
   521     def _doRemoveChild(self, CTNInstance):
   522         # Remove all childs of child
   522         # Remove all children of child
   523         for SubPlugInstance in PlugInstance.IterChilds():
   523         for SubCTNInstance in CTNInstance.IterChildren():
   524             PlugInstance._doRemoveChild(SubPlugInstance)
   524             CTNInstance._doRemoveChild(SubCTNInstance)
   525         # Call the OnCloseMethod
   525         # Call the OnCloseMethod
   526         PlugInstance.OnPlugClose()
   526         CTNInstance.OnCTNClose()
   527         # Delete confnode dir
   527         # Delete confnode dir
   528         shutil.rmtree(PlugInstance.PlugPath())
   528         shutil.rmtree(CTNInstance.CTNPath())
   529         # Remove child of PluggedChilds
   529         # Remove child of Children
   530         self.PluggedChilds[PlugInstance.PlugType].remove(PlugInstance)
   530         self.Children[CTNInstance.CTNType].remove(CTNInstance)
   531         # Forget it... (View have to refresh)
   531         # Forget it... (View have to refresh)
   532 
   532 
   533     def PlugRemove(self):
   533     def CTNRemove(self):
   534         # Fetch the confnode
   534         # Fetch the confnode
   535         #PlugInstance = self.GetChildByName(PlugName)
   535         #CTNInstance = self.GetChildByName(CTNName)
   536         # Ask to his parent to remove it
   536         # Ask to his parent to remove it
   537         self.PlugParent._doRemoveChild(self)
   537         self.CTNParent._doRemoveChild(self)
   538 
   538 
   539     def PlugAddChild(self, PlugName, PlugType, IEC_Channel=0):
   539     def CTNAddChild(self, CTNName, CTNType, IEC_Channel=0):
   540         """
   540         """
   541         Create the confnodes that may be added as child to this node self
   541         Create the confnodes that may be added as child to this node self
   542         @param PlugType: string desining the confnode class name (get name from PlugChildsTypes)
   542         @param CTNType: string desining the confnode class name (get name from CTNChildrenTypes)
   543         @param PlugName: string for the name of the confnode instance
   543         @param CTNName: string for the name of the confnode instance
   544         """
   544         """
   545         # reorgabize self.PlugChildsTypes tuples from (name, PlugClass, Help)
   545         # reorgabize self.CTNChildrenTypes tuples from (name, CTNClass, Help)
   546         # to ( name, (PlugClass, Help)), an make a dict
   546         # to ( name, (CTNClass, Help)), an make a dict
   547         transpose = zip(*self.PlugChildsTypes)
   547         transpose = zip(*self.CTNChildrenTypes)
   548         PlugChildsTypes = dict(zip(transpose[0],zip(transpose[1],transpose[2])))
   548         CTNChildrenTypes = dict(zip(transpose[0],zip(transpose[1],transpose[2])))
   549         # Check that adding this confnode is allowed
   549         # Check that adding this confnode is allowed
   550         try:
   550         try:
   551             PlugClass, PlugHelp = PlugChildsTypes[PlugType]
   551             CTNClass, CTNHelp = CTNChildrenTypes[CTNType]
   552         except KeyError:
   552         except KeyError:
   553             raise Exception, _("Cannot create child %s of type %s ")%(PlugName, PlugType)
   553             raise Exception, _("Cannot create child %s of type %s ")%(CTNName, CTNType)
   554         
   554         
   555         # if PlugClass is a class factory, call it. (prevent unneeded imports)
   555         # if CTNClass is a class factory, call it. (prevent unneeded imports)
   556         if type(PlugClass) == types.FunctionType:
   556         if type(CTNClass) == types.FunctionType:
   557             PlugClass = PlugClass()
   557             CTNClass = CTNClass()
   558         
   558         
   559         # Eventualy Initialize child instance list for this class of confnode
   559         # Eventualy Initialize child instance list for this class of confnode
   560         PluggedChildsWithSameClass = self.PluggedChilds.setdefault(PlugType, list())
   560         ChildrenWithSameClass = self.Children.setdefault(CTNType, list())
   561         # Check count
   561         # Check count
   562         if getattr(PlugClass, "PlugMaxCount", None) and len(PluggedChildsWithSameClass) >= PlugClass.PlugMaxCount:
   562         if getattr(CTNClass, "CTNMaxCount", None) and len(ChildrenWithSameClass) >= CTNClass.CTNMaxCount:
   563             raise Exception, _("Max count (%d) reached for this confnode of type %s ")%(PlugClass.PlugMaxCount, PlugType)
   563             raise Exception, _("Max count (%d) reached for this confnode of type %s ")%(CTNClass.CTNMaxCount, CTNType)
   564         
   564         
   565         # create the final class, derived of provided confnode and template
   565         # create the final class, derived of provided confnode and template
   566         class FinalPlugClass(PlugClass, ConfigTreeNode):
   566         class FinalCTNClass(CTNClass, ConfigTreeNode):
   567             """
   567             """
   568             ConfNode class is derivated into FinalPlugClass before being instanciated
   568             ConfNode class is derivated into FinalCTNClass before being instanciated
   569             This way __init__ is overloaded to ensure ConfigTreeNode.__init__ is called 
   569             This way __init__ is overloaded to ensure ConfigTreeNode.__init__ is called 
   570             before PlugClass.__init__, and to do the file related stuff.
   570             before CTNClass.__init__, and to do the file related stuff.
   571             """
   571             """
   572             def __init__(_self):
   572             def __init__(_self):
   573                 # self is the parent
   573                 # self is the parent
   574                 _self.PlugParent = self
   574                 _self.CTNParent = self
   575                 # Keep track of the confnode type name
   575                 # Keep track of the confnode type name
   576                 _self.PlugType = PlugType
   576                 _self.CTNType = CTNType
   577                 # remind the help string, for more fancy display
   577                 # remind the help string, for more fancy display
   578                 _self.PlugHelp = PlugHelp
   578                 _self.CTNHelp = CTNHelp
   579                 # Call the base confnode template init - change XSD into class members
   579                 # Call the base confnode template init - change XSD into class members
   580                 ConfigTreeNode.__init__(_self)
   580                 ConfigTreeNode.__init__(_self)
   581                 # check name is unique
   581                 # check name is unique
   582                 NewPlugName = _self.FindNewName(PlugName)
   582                 NewCTNName = _self.FindNewName(CTNName)
   583                 # If dir have already be made, and file exist
   583                 # If dir have already be made, and file exist
   584                 if os.path.isdir(_self.PlugPath(NewPlugName)): #and os.path.isfile(_self.ConfNodeXmlFilePath(PlugName)):
   584                 if os.path.isdir(_self.CTNPath(NewCTNName)): #and os.path.isfile(_self.ConfNodeXmlFilePath(CTNName)):
   585                     #Load the confnode.xml file into parameters members
   585                     #Load the confnode.xml file into parameters members
   586                     _self.LoadXMLParams(NewPlugName)
   586                     _self.LoadXMLParams(NewCTNName)
   587                     # Basic check. Better to fail immediately.
   587                     # Basic check. Better to fail immediately.
   588                     if (_self.BaseParams.getName() != NewPlugName):
   588                     if (_self.BaseParams.getName() != NewCTNName):
   589                         raise Exception, _("Project tree layout do not match confnode.xml %s!=%s ")%(NewPlugName, _self.BaseParams.getName())
   589                         raise Exception, _("Project tree layout do not match confnode.xml %s!=%s ")%(NewCTNName, _self.BaseParams.getName())
   590 
   590 
   591                     # Now, self.PlugPath() should be OK
   591                     # Now, self.CTNPath() should be OK
   592                     
   592                     
   593                     # Check that IEC_Channel is not already in use.
   593                     # Check that IEC_Channel is not already in use.
   594                     _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
   594                     _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
   595                     # Call the confnode real __init__
   595                     # Call the confnode real __init__
   596                     if getattr(PlugClass, "__init__", None):
   596                     if getattr(CTNClass, "__init__", None):
   597                         PlugClass.__init__(_self)
   597                         CTNClass.__init__(_self)
   598                     #Load and init all the childs
   598                     #Load and init all the children
   599                     _self.LoadChilds()
   599                     _self.LoadChildren()
   600                     #just loaded, nothing to saved
   600                     #just loaded, nothing to saved
   601                     _self.ChangesToSave = False
   601                     _self.ChangesToSave = False
   602                 else:
   602                 else:
   603                     # If confnode do not have corresponding file/dirs - they will be created on Save
   603                     # If confnode do not have corresponding file/dirs - they will be created on Save
   604                     _self.PlugMakeDir()
   604                     _self.CTNMakeDir()
   605                     # Find an IEC number
   605                     # Find an IEC number
   606                     _self.FindNewIEC_Channel(IEC_Channel)
   606                     _self.FindNewIEC_Channel(IEC_Channel)
   607                     # Call the confnode real __init__
   607                     # Call the confnode real __init__
   608                     if getattr(PlugClass, "__init__", None):
   608                     if getattr(CTNClass, "__init__", None):
   609                         PlugClass.__init__(_self)
   609                         CTNClass.__init__(_self)
   610                     _self.PlugRequestSave()
   610                     _self.CTNRequestSave()
   611                     #just created, must be saved
   611                     #just created, must be saved
   612                     _self.ChangesToSave = True
   612                     _self.ChangesToSave = True
   613                 
   613                 
   614             def _getBuildPath(_self):
   614             def _getBuildPath(_self):
   615                 return self._getBuildPath()
   615                 return self._getBuildPath()
   616             
   616             
   617         # Create the object out of the resulting class
   617         # Create the object out of the resulting class
   618         newConfNodeOpj = FinalPlugClass()
   618         newConfNodeOpj = FinalCTNClass()
   619         # Store it in PluggedChils
   619         # Store it in CTNgedChils
   620         PluggedChildsWithSameClass.append(newConfNodeOpj)
   620         ChildrenWithSameClass.append(newConfNodeOpj)
   621         
   621         
   622         return newConfNodeOpj
   622         return newConfNodeOpj
   623     
   623     
   624     def ClearPluggedChilds(self):
   624     def ClearChildren(self):
   625         for child in self.IterChilds():
   625         for child in self.IterChildren():
   626             child.ClearPluggedChilds()
   626             child.ClearChildren()
   627         self.PluggedChilds = {}
   627         self.Children = {}
   628     
   628     
   629     def LoadSTLibrary(self):
   629     def LoadSTLibrary(self):
   630         # Get library blocks if plcopen library exist
   630         # Get library blocks if plcopen library exist
   631         library_path = self.ConfNodeLibraryFilePath()
   631         library_path = self.ConfNodeLibraryFilePath()
   632         if os.path.isfile(library_path):
   632         if os.path.isfile(library_path):
   633             self.LibraryControler = PLCControler()
   633             self.LibraryControler = PLCControler()
   634             self.LibraryControler.OpenXMLFile(library_path)
   634             self.LibraryControler.OpenXMLFile(library_path)
   635             self.LibraryControler.ClearConfNodeTypes()
   635             self.LibraryControler.ClearConfNodeTypes()
   636             self.LibraryControler.AddConfNodeTypesList(self.ParentsTypesFactory())
   636             self.LibraryControler.AddConfNodeTypesList(self.ParentsTypesFactory())
   637 
   637 
   638     def LoadXMLParams(self, PlugName = None):
   638     def LoadXMLParams(self, CTNName = None):
   639         methode_name = os.path.join(self.PlugPath(PlugName), "methods.py")
   639         methode_name = os.path.join(self.CTNPath(CTNName), "methods.py")
   640         if os.path.isfile(methode_name):
   640         if os.path.isfile(methode_name):
   641             execfile(methode_name)
   641             execfile(methode_name)
   642         
   642         
   643         # Get the base xml tree
   643         # Get the base xml tree
   644         if self.MandatoryParams:
   644         if self.MandatoryParams:
   645             try:
   645             try:
   646                 basexmlfile = open(self.ConfNodeBaseXmlFilePath(PlugName), 'r')
   646                 basexmlfile = open(self.ConfNodeBaseXmlFilePath(CTNName), 'r')
   647                 basetree = minidom.parse(basexmlfile)
   647                 basetree = minidom.parse(basexmlfile)
   648                 self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
   648                 self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
   649                 basexmlfile.close()
   649                 basexmlfile.close()
   650             except Exception, exc:
   650             except Exception, exc:
   651                 self.GetPlugRoot().logger.write_error(_("Couldn't load confnode base parameters %s :\n %s") % (PlugName, str(exc)))
   651                 self.GetCTRoot().logger.write_error(_("Couldn't load confnode base parameters %s :\n %s") % (CTNName, str(exc)))
   652                 self.GetPlugRoot().logger.write_error(traceback.format_exc())
   652                 self.GetCTRoot().logger.write_error(traceback.format_exc())
   653         
   653         
   654         # Get the xml tree
   654         # Get the xml tree
   655         if self.PlugParams:
   655         if self.CTNParams:
   656             try:
   656             try:
   657                 xmlfile = open(self.ConfNodeXmlFilePath(PlugName), 'r')
   657                 xmlfile = open(self.ConfNodeXmlFilePath(CTNName), 'r')
   658                 tree = minidom.parse(xmlfile)
   658                 tree = minidom.parse(xmlfile)
   659                 self.PlugParams[1].loadXMLTree(tree.childNodes[0])
   659                 self.CTNParams[1].loadXMLTree(tree.childNodes[0])
   660                 xmlfile.close()
   660                 xmlfile.close()
   661             except Exception, exc:
   661             except Exception, exc:
   662                 self.GetPlugRoot().logger.write_error(_("Couldn't load confnode parameters %s :\n %s") % (PlugName, str(exc)))
   662                 self.GetCTRoot().logger.write_error(_("Couldn't load confnode parameters %s :\n %s") % (CTNName, str(exc)))
   663                 self.GetPlugRoot().logger.write_error(traceback.format_exc())
   663                 self.GetCTRoot().logger.write_error(traceback.format_exc())
   664         
   664         
   665     def LoadChilds(self):
   665     def LoadChildren(self):
   666         # Iterate over all PlugName@PlugType in confnode directory, and try to open them
   666         # Iterate over all CTNName@CTNType in confnode directory, and try to open them
   667         for PlugDir in os.listdir(self.PlugPath()):
   667         for CTNDir in os.listdir(self.CTNPath()):
   668             if os.path.isdir(os.path.join(self.PlugPath(), PlugDir)) and \
   668             if os.path.isdir(os.path.join(self.CTNPath(), CTNDir)) and \
   669                PlugDir.count(NameTypeSeparator) == 1:
   669                CTNDir.count(NameTypeSeparator) == 1:
   670                 pname, ptype = PlugDir.split(NameTypeSeparator)
   670                 pname, ptype = CTNDir.split(NameTypeSeparator)
   671                 try:
   671                 try:
   672                     self.PlugAddChild(pname, ptype)
   672                     self.CTNAddChild(pname, ptype)
   673                 except Exception, exc:
   673                 except Exception, exc:
   674                     self.GetPlugRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc)))
   674                     self.GetCTRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc)))
   675                     self.GetPlugRoot().logger.write_error(traceback.format_exc())
   675                     self.GetCTRoot().logger.write_error(traceback.format_exc())
   676 
   676 
   677     def EnableMethod(self, method, value):
   677     def EnableMethod(self, method, value):
   678         for d in self.ConfNodeMethods:
   678         for d in self.ConfNodeMethods:
   679             if d["method"]==method:
   679             if d["method"]==method:
   680                 d["enabled"]=value
   680                 d["enabled"]=value
   740     This class define Root object of the confnode tree. 
   740     This class define Root object of the confnode tree. 
   741     It is responsible of :
   741     It is responsible of :
   742     - Managing project directory
   742     - Managing project directory
   743     - Building project
   743     - Building project
   744     - Handling PLCOpenEditor controler and view
   744     - Handling PLCOpenEditor controler and view
   745     - Loading user confnodes and instanciante them as childs
   745     - Loading user confnodes and instanciante them as children
   746     - ...
   746     - ...
   747     
   747     
   748     """
   748     """
   749 
   749 
   750     # For root object, available Childs Types are modules of the confnode packages.
   750     # For root object, available Children Types are modules of the confnode packages.
   751     PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(confnodes.__all__,confnodes.helps)]
   751     CTNChildrenTypes = [(name, _GetClassFunction(name), help) for name, help in zip(confnodes.__all__,confnodes.helps)]
   752 
   752 
   753     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   753     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   754     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   754     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   755       <xsd:element name="BeremizRoot">
   755       <xsd:element name="BeremizRoot">
   756         <xsd:complexType>
   756         <xsd:complexType>
   788         self.DebugTimer=None
   788         self.DebugTimer=None
   789         self.ResetIECProgramsAndVariables()
   789         self.ResetIECProgramsAndVariables()
   790         
   790         
   791         #This method are not called here... but in NewProject and OpenProject
   791         #This method are not called here... but in NewProject and OpenProject
   792         #self._AddParamsMembers()
   792         #self._AddParamsMembers()
   793         #self.PluggedChilds = {}
   793         #self.Children = {}
   794 
   794 
   795         # In both new or load scenario, no need to save
   795         # In both new or load scenario, no need to save
   796         self.ChangesToSave = False
   796         self.ChangesToSave = False
   797         # root have no parent
   797         # root have no parent
   798         self.PlugParent = None
   798         self.CTNParent = None
   799         # Keep track of the confnode type name
   799         # Keep track of the confnode type name
   800         self.PlugType = "Beremiz"
   800         self.CTNType = "Beremiz"
   801         self.PluggedChilds = {}
   801         self.Children = {}
   802         # After __init__ root confnode is not valid
   802         # After __init__ root confnode is not valid
   803         self.ProjectPath = None
   803         self.ProjectPath = None
   804         self._setBuildPath(None)
   804         self._setBuildPath(None)
   805         self.DebugThread = None
   805         self.DebugThread = None
   806         self.debug_break = False
   806         self.debug_break = False
   836         self.logger = logger
   836         self.logger = logger
   837 
   837 
   838     def ConfNodeLibraryFilePath(self):
   838     def ConfNodeLibraryFilePath(self):
   839         return os.path.join(os.path.split(__file__)[0], "pous.xml")
   839         return os.path.join(os.path.split(__file__)[0], "pous.xml")
   840 
   840 
   841     def PlugTestModified(self):
   841     def CTNTestModified(self):
   842          return self.ChangesToSave or not self.ProjectIsSaved()
   842          return self.ChangesToSave or not self.ProjectIsSaved()
   843 
   843 
   844     def PlugFullName(self):
   844     def CTNFullName(self):
   845         return ""
   845         return ""
   846 
   846 
   847     def GetPlugRoot(self):
   847     def GetCTRoot(self):
   848         return self
   848         return self
   849 
   849 
   850     def GetIECLibPath(self):
   850     def GetIECLibPath(self):
   851         return self.ieclib_path
   851         return self.ieclib_path
   852     
   852     
   934         
   934         
   935         # Create PLCOpen program
   935         # Create PLCOpen program
   936         self.CreateNewProject(values)
   936         self.CreateNewProject(values)
   937         # Change XSD into class members
   937         # Change XSD into class members
   938         self._AddParamsMembers()
   938         self._AddParamsMembers()
   939         self.PluggedChilds = {}
   939         self.Children = {}
   940         # Keep track of the root confnode (i.e. project path)
   940         # Keep track of the root confnode (i.e. project path)
   941         self.ProjectPath = ProjectPath
   941         self.ProjectPath = ProjectPath
   942         self._setBuildPath(BuildPath)
   942         self._setBuildPath(BuildPath)
   943         # get confnodes bloclist (is that usefull at project creation?)
   943         # get confnodes bloclist (is that usefull at project creation?)
   944         self.RefreshConfNodesBlockLists()
   944         self.RefreshConfNodesBlockLists()
   961         result = self.OpenXMLFile(plc_file)
   961         result = self.OpenXMLFile(plc_file)
   962         if result:
   962         if result:
   963             return result
   963             return result
   964         # Change XSD into class members
   964         # Change XSD into class members
   965         self._AddParamsMembers()
   965         self._AddParamsMembers()
   966         self.PluggedChilds = {}
   966         self.Children = {}
   967         # Keep track of the root confnode (i.e. project path)
   967         # Keep track of the root confnode (i.e. project path)
   968         self.ProjectPath = ProjectPath
   968         self.ProjectPath = ProjectPath
   969         self._setBuildPath(BuildPath)
   969         self._setBuildPath(BuildPath)
   970         # If dir have already be made, and file exist
   970         # If dir have already be made, and file exist
   971         if os.path.isdir(self.PlugPath()) and os.path.isfile(self.ConfNodeXmlFilePath()):
   971         if os.path.isdir(self.CTNPath()) and os.path.isfile(self.ConfNodeXmlFilePath()):
   972             #Load the confnode.xml file into parameters members
   972             #Load the confnode.xml file into parameters members
   973             result = self.LoadXMLParams()
   973             result = self.LoadXMLParams()
   974             if result:
   974             if result:
   975                 return result
   975                 return result
   976             #Load and init all the childs
   976             #Load and init all the children
   977             self.LoadChilds()
   977             self.LoadChildren()
   978         self.RefreshConfNodesBlockLists()
   978         self.RefreshConfNodesBlockLists()
   979         
   979         
   980         if os.path.exists(self._getBuildPath()):
   980         if os.path.exists(self._getBuildPath()):
   981             self.EnableMethod("_Clean", True)
   981             self.EnableMethod("_Clean", True)
   982 
   982 
   984             self.ShowMethod("_showIECcode", True)
   984             self.ShowMethod("_showIECcode", True)
   985 
   985 
   986         return None
   986         return None
   987     
   987     
   988     def CloseProject(self):
   988     def CloseProject(self):
   989         self.ClearPluggedChilds()
   989         self.ClearChildren()
   990         self.ResetAppFrame(None)
   990         self.ResetAppFrame(None)
   991         
   991         
   992     def SaveProject(self):
   992     def SaveProject(self):
   993         if self.CheckProjectPathPerm(False):
   993         if self.CheckProjectPathPerm(False):
   994             self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
   994             self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
   995             result = self.PlugRequestSave()
   995             result = self.CTNRequestSave()
   996             if result:
   996             if result:
   997                 self.logger.write_error(result)
   997                 self.logger.write_error(result)
   998     
   998     
   999     def SaveProjectAs(self, dosave=True):
   999     def SaveProjectAs(self, dosave=True):
  1000         # Ask user to choose a path with write permissions
  1000         # Ask user to choose a path with write permissions
  1015                 return True
  1015                 return True
  1016         return False
  1016         return False
  1017     
  1017     
  1018     # Update PLCOpenEditor ConfNode Block types from loaded confnodes
  1018     # Update PLCOpenEditor ConfNode Block types from loaded confnodes
  1019     def RefreshConfNodesBlockLists(self):
  1019     def RefreshConfNodesBlockLists(self):
  1020         if getattr(self, "PluggedChilds", None) is not None:
  1020         if getattr(self, "Children", None) is not None:
  1021             self.ClearConfNodeTypes()
  1021             self.ClearConfNodeTypes()
  1022             self.AddConfNodeTypesList(self.ConfNodesTypesFactory())
  1022             self.AddConfNodeTypesList(self.ConfNodesTypesFactory())
  1023         if self.AppFrame is not None:
  1023         if self.AppFrame is not None:
  1024             self.AppFrame.RefreshLibraryPanel()
  1024             self.AppFrame.RefreshLibraryPanel()
  1025             self.AppFrame.RefreshEditor()
  1025             self.AppFrame.RefreshEditor()
  1043         
  1043         
  1044         - IEC_type is an IEC type like BOOL/BYTE/SINT/...
  1044         - IEC_type is an IEC type like BOOL/BYTE/SINT/...
  1045         - location is a string of this variable's location, like "%IX0.0.0"
  1045         - location is a string of this variable's location, like "%IX0.0.0"
  1046         '''
  1046         '''
  1047         children = []
  1047         children = []
  1048         for child in self.IECSortedChilds():
  1048         for child in self.IECSortedChildren():
  1049             children.append(child.GetVariableLocationTree())
  1049             children.append(child.GetVariableLocationTree())
  1050         return children
  1050         return children
  1051     
  1051     
  1052     def ConfNodePath(self):
  1052     def ConfNodePath(self):
  1053         return os.path.join(os.path.split(__file__)[0], "confnodes")
  1053         return os.path.join(os.path.split(__file__)[0], "confnodes")
  1054     
  1054     
  1055     def PlugPath(self, PlugName=None):
  1055     def CTNPath(self, CTNName=None):
  1056         return self.ProjectPath
  1056         return self.ProjectPath
  1057     
  1057     
  1058     def ConfNodeXmlFilePath(self, PlugName=None):
  1058     def ConfNodeXmlFilePath(self, CTNName=None):
  1059         return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
  1059         return os.path.join(self.CTNPath(CTNName), "beremiz.xml")
  1060 
  1060 
  1061     def ParentsTypesFactory(self):
  1061     def ParentsTypesFactory(self):
  1062         return self.ConfNodeTypesFactory()
  1062         return self.ConfNodeTypesFactory()
  1063 
  1063 
  1064     def _setBuildPath(self, buildpath):
  1064     def _setBuildPath(self, buildpath):
  1100         # define name for IEC generated code file
  1100         # define name for IEC generated code file
  1101         return os.path.join(self._getBuildPath(), "generated_plc.st")
  1101         return os.path.join(self._getBuildPath(), "generated_plc.st")
  1102     
  1102     
  1103     def _getIECrawcodepath(self):
  1103     def _getIECrawcodepath(self):
  1104         # define name for IEC raw code file
  1104         # define name for IEC raw code file
  1105         return os.path.join(self.PlugPath(), "raw_plc.st")
  1105         return os.path.join(self.CTNPath(), "raw_plc.st")
  1106     
  1106     
  1107     def GetLocations(self):
  1107     def GetLocations(self):
  1108         locations = []
  1108         locations = []
  1109         filepath = os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h")
  1109         filepath = os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h")
  1110         if os.path.isfile(filepath):
  1110         if os.path.isfile(filepath):
  1220         # transform those base names to full names with path
  1220         # transform those base names to full names with path
  1221         C_files = map(lambda filename:os.path.join(buildpath, filename), C_files)
  1221         C_files = map(lambda filename:os.path.join(buildpath, filename), C_files)
  1222         self.logger.write(_("Extracting Located Variables...\n"))
  1222         self.logger.write(_("Extracting Located Variables...\n"))
  1223         # Keep track of generated located variables for later use by self._Generate_C
  1223         # Keep track of generated located variables for later use by self._Generate_C
  1224         self.PLCGeneratedLocatedVars = self.GetLocations()
  1224         self.PLCGeneratedLocatedVars = self.GetLocations()
  1225         # Keep track of generated C files for later use by self.PlugGenerate_C
  1225         # Keep track of generated C files for later use by self.CTNGenerate_C
  1226         self.PLCGeneratedCFiles = C_files
  1226         self.PLCGeneratedCFiles = C_files
  1227         # compute CFLAGS for plc
  1227         # compute CFLAGS for plc
  1228         self.plcCFLAGS = "\"-I"+self.ieclib_path+"\""
  1228         self.plcCFLAGS = "\"-I"+self.ieclib_path+"\""
  1229         return True
  1229         return True
  1230 
  1230 
  1272     #
  1272     #
  1273     #                C CODE GENERATION METHODS
  1273     #                C CODE GENERATION METHODS
  1274     #
  1274     #
  1275     #######################################################################
  1275     #######################################################################
  1276     
  1276     
  1277     def PlugGenerate_C(self, buildpath, locations):
  1277     def CTNGenerate_C(self, buildpath, locations):
  1278         """
  1278         """
  1279         Return C code generated by iec2c compiler 
  1279         Return C code generated by iec2c compiler 
  1280         when _generate_softPLC have been called
  1280         when _generate_softPLC have been called
  1281         @param locations: ignored
  1281         @param locations: ignored
  1282         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
  1282         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND