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: |
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 |