author | Laurent Bessard |
Thu, 06 Jun 2013 00:22:22 +0200 | |
changeset 1229 | 137fd7e7b102 |
parent 1223 | d51cea72baa7 |
child 1254 | ebc765355536 |
permissions | -rw-r--r-- |
814 | 1 |
#!/usr/bin/env python |
2 |
# -*- coding: utf-8 -*- |
|
3 |
||
4 |
#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
|
5 |
#based on the plcopen standard. |
|
6 |
# |
|
7 |
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
|
8 |
# |
|
9 |
#See COPYING file for copyrights details. |
|
10 |
# |
|
11 |
#This library is free software; you can redistribute it and/or |
|
12 |
#modify it under the terms of the GNU General Public |
|
13 |
#License as published by the Free Software Foundation; either |
|
14 |
#version 2.1 of the License, or (at your option) any later version. |
|
15 |
# |
|
16 |
#This library is distributed in the hope that it will be useful, |
|
17 |
#but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 |
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
19 |
#General Public License for more details. |
|
20 |
# |
|
21 |
#You should have received a copy of the GNU General Public |
|
22 |
#License along with this library; if not, write to the Free Software |
|
23 |
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
24 |
||
25 |
from xml.dom import minidom |
|
26 |
from types import StringType, UnicodeType, TupleType |
|
27 |
import cPickle |
|
28 |
import os,sys,re |
|
29 |
import datetime |
|
30 |
from time import localtime |
|
31 |
||
32 |
from plcopen import plcopen |
|
33 |
from plcopen.structures import * |
|
34 |
from graphics.GraphicCommons import * |
|
35 |
from PLCGenerator import * |
|
36 |
||
37 |
duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:\.[0-9]*)?)ms)?") |
|
38 |
||
39 |
ITEMS_EDITABLE = [ITEM_PROJECT, |
|
40 |
ITEM_POU, |
|
41 |
ITEM_VARIABLE, |
|
42 |
ITEM_TRANSITION, |
|
43 |
ITEM_ACTION, |
|
44 |
ITEM_CONFIGURATION, |
|
45 |
ITEM_RESOURCE, |
|
46 |
ITEM_DATATYPE |
|
47 |
] = range(8) |
|
48 |
||
49 |
ITEMS_UNEDITABLE = [ITEM_DATATYPES, |
|
50 |
ITEM_FUNCTION, |
|
51 |
ITEM_FUNCTIONBLOCK, |
|
52 |
ITEM_PROGRAM, |
|
53 |
ITEM_TRANSITIONS, |
|
54 |
ITEM_ACTIONS, |
|
55 |
ITEM_CONFIGURATIONS, |
|
56 |
ITEM_RESOURCES, |
|
57 |
ITEM_PROPERTIES |
|
58 |
] = range(8, 17) |
|
59 |
||
60 |
ITEMS_VARIABLE = [ITEM_VAR_LOCAL, |
|
61 |
ITEM_VAR_GLOBAL, |
|
62 |
ITEM_VAR_EXTERNAL, |
|
63 |
ITEM_VAR_TEMP, |
|
64 |
ITEM_VAR_INPUT, |
|
65 |
ITEM_VAR_OUTPUT, |
|
66 |
ITEM_VAR_INOUT |
|
67 |
] = range(17, 24) |
|
68 |
||
69 |
VAR_CLASS_INFOS = {"Local" : (plcopen.interface_localVars, ITEM_VAR_LOCAL), |
|
70 |
"Global" : (plcopen.interface_globalVars, ITEM_VAR_GLOBAL), |
|
71 |
"External" : (plcopen.interface_externalVars, ITEM_VAR_EXTERNAL), |
|
72 |
"Temp" : (plcopen.interface_tempVars, ITEM_VAR_TEMP), |
|
73 |
"Input" : (plcopen.interface_inputVars, ITEM_VAR_INPUT), |
|
74 |
"Output" : (plcopen.interface_outputVars, ITEM_VAR_OUTPUT), |
|
75 |
"InOut" : (plcopen.interface_inOutVars, ITEM_VAR_INOUT) |
|
76 |
} |
|
77 |
||
78 |
POU_TYPES = {"program": ITEM_PROGRAM, |
|
79 |
"functionBlock": ITEM_FUNCTIONBLOCK, |
|
80 |
"function": ITEM_FUNCTION, |
|
81 |
} |
|
82 |
||
83 |
LOCATIONS_ITEMS = [LOCATION_CONFNODE, |
|
84 |
LOCATION_MODULE, |
|
85 |
LOCATION_GROUP, |
|
86 |
LOCATION_VAR_INPUT, |
|
87 |
LOCATION_VAR_OUTPUT, |
|
88 |
LOCATION_VAR_MEMORY] = range(6) |
|
89 |
||
90 |
ScriptDirectory = os.path.split(os.path.realpath(__file__))[0] |
|
91 |
||
92 |
def GetUneditableNames(): |
|
93 |
_ = lambda x:x |
|
94 |
return [_("User-defined POUs"), _("Functions"), _("Function Blocks"), |
|
95 |
_("Programs"), _("Data Types"), _("Transitions"), _("Actions"), |
|
96 |
_("Configurations"), _("Resources"), _("Properties")] |
|
97 |
UNEDITABLE_NAMES = GetUneditableNames() |
|
98 |
[USER_DEFINED_POUS, FUNCTIONS, FUNCTION_BLOCKS, PROGRAMS, |
|
99 |
DATA_TYPES, TRANSITIONS, ACTIONS, CONFIGURATIONS, |
|
100 |
RESOURCES, PROPERTIES] = UNEDITABLE_NAMES |
|
101 |
||
102 |
#------------------------------------------------------------------------------- |
|
103 |
# Undo Buffer for PLCOpenEditor |
|
104 |
#------------------------------------------------------------------------------- |
|
105 |
||
106 |
# Length of the buffer |
|
107 |
UNDO_BUFFER_LENGTH = 20 |
|
108 |
||
109 |
""" |
|
110 |
Class implementing a buffer of changes made on the current editing model |
|
111 |
""" |
|
112 |
class UndoBuffer: |
|
113 |
||
114 |
# Constructor initialising buffer |
|
115 |
def __init__(self, currentstate, issaved = False): |
|
116 |
self.Buffer = [] |
|
117 |
self.CurrentIndex = -1 |
|
118 |
self.MinIndex = -1 |
|
119 |
self.MaxIndex = -1 |
|
120 |
# if current state is defined |
|
121 |
if currentstate: |
|
122 |
self.CurrentIndex = 0 |
|
123 |
self.MinIndex = 0 |
|
124 |
self.MaxIndex = 0 |
|
125 |
# Initialising buffer with currentstate at the first place |
|
126 |
for i in xrange(UNDO_BUFFER_LENGTH): |
|
127 |
if i == 0: |
|
128 |
self.Buffer.append(currentstate) |
|
129 |
else: |
|
130 |
self.Buffer.append(None) |
|
131 |
# Initialising index of state saved |
|
132 |
if issaved: |
|
133 |
self.LastSave = 0 |
|
134 |
else: |
|
135 |
self.LastSave = -1 |
|
136 |
||
137 |
# Add a new state in buffer |
|
138 |
def Buffering(self, currentstate): |
|
139 |
self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH |
|
140 |
self.Buffer[self.CurrentIndex] = currentstate |
|
141 |
# Actualising buffer limits |
|
142 |
self.MaxIndex = self.CurrentIndex |
|
143 |
if self.MinIndex == self.CurrentIndex: |
|
144 |
# If the removed state was the state saved, there is no state saved in the buffer |
|
145 |
if self.LastSave == self.MinIndex: |
|
146 |
self.LastSave = -1 |
|
147 |
self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH |
|
148 |
self.MinIndex = max(self.MinIndex, 0) |
|
149 |
||
150 |
# Return current state of buffer |
|
151 |
def Current(self): |
|
152 |
return self.Buffer[self.CurrentIndex] |
|
153 |
||
154 |
# Change current state to previous in buffer and return new current state |
|
155 |
def Previous(self): |
|
156 |
if self.CurrentIndex != self.MinIndex: |
|
157 |
self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH |
|
158 |
return self.Buffer[self.CurrentIndex] |
|
159 |
return None |
|
160 |
||
161 |
# Change current state to next in buffer and return new current state |
|
162 |
def Next(self): |
|
163 |
if self.CurrentIndex != self.MaxIndex: |
|
164 |
self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH |
|
165 |
return self.Buffer[self.CurrentIndex] |
|
166 |
return None |
|
167 |
||
168 |
# Return True if current state is the first in buffer |
|
169 |
def IsFirst(self): |
|
170 |
return self.CurrentIndex == self.MinIndex |
|
171 |
||
172 |
# Return True if current state is the last in buffer |
|
173 |
def IsLast(self): |
|
174 |
return self.CurrentIndex == self.MaxIndex |
|
175 |
||
176 |
# Note that current state is saved |
|
177 |
def CurrentSaved(self): |
|
178 |
self.LastSave = self.CurrentIndex |
|
179 |
||
180 |
# Return True if current state is saved |
|
181 |
def IsCurrentSaved(self): |
|
182 |
return self.LastSave == self.CurrentIndex |
|
183 |
||
184 |
||
185 |
#------------------------------------------------------------------------------- |
|
186 |
# Controler for PLCOpenEditor |
|
187 |
#------------------------------------------------------------------------------- |
|
188 |
||
189 |
""" |
|
190 |
Class which controls the operations made on the plcopen model and answers to view requests |
|
191 |
""" |
|
192 |
class PLCControler: |
|
193 |
||
194 |
# Create a new PLCControler |
|
195 |
def __init__(self): |
|
196 |
self.LastNewIndex = 0 |
|
197 |
self.Reset() |
|
198 |
||
199 |
# Reset PLCControler internal variables |
|
200 |
def Reset(self): |
|
201 |
self.Project = None |
|
202 |
self.ProjectBufferEnabled = True |
|
203 |
self.ProjectBuffer = None |
|
204 |
self.ProjectSaved = True |
|
205 |
self.Buffering = False |
|
206 |
self.FilePath = "" |
|
207 |
self.FileName = "" |
|
208 |
self.ProgramChunks = [] |
|
209 |
self.ProgramOffset = 0 |
|
210 |
self.NextCompiledProject = None |
|
211 |
self.CurrentCompiledProject = None |
|
212 |
self.ConfNodeTypes = [] |
|
213 |
self.ProgramFilePath = "" |
|
214 |
||
215 |
def GetQualifierTypes(self): |
|
216 |
return plcopen.QualifierList |
|
217 |
||
218 |
def GetProject(self, debug = False): |
|
219 |
if debug and self.CurrentCompiledProject is not None: |
|
220 |
return self.CurrentCompiledProject |
|
221 |
else: |
|
222 |
return self.Project |
|
223 |
||
224 |
#------------------------------------------------------------------------------- |
|
225 |
# Project management functions |
|
226 |
#------------------------------------------------------------------------------- |
|
227 |
||
228 |
# Return if a project is opened |
|
229 |
def HasOpenedProject(self): |
|
230 |
return self.Project is not None |
|
231 |
||
232 |
# Create a new project by replacing the current one |
|
233 |
def CreateNewProject(self, properties): |
|
234 |
# Create the project |
|
235 |
self.Project = plcopen.project() |
|
236 |
properties["creationDateTime"] = datetime.datetime(*localtime()[:6]) |
|
237 |
self.Project.setfileHeader(properties) |
|
238 |
self.Project.setcontentHeader(properties) |
|
239 |
self.SetFilePath("") |
|
240 |
# Initialize the project buffer |
|
241 |
self.CreateProjectBuffer(False) |
|
242 |
self.ProgramChunks = [] |
|
243 |
self.ProgramOffset = 0 |
|
244 |
self.NextCompiledProject = self.Copy(self.Project) |
|
245 |
self.CurrentCompiledProject = None |
|
246 |
self.Buffering = False |
|
247 |
||
248 |
# Return project data type names |
|
249 |
def GetProjectDataTypeNames(self, debug = False): |
|
250 |
project = self.GetProject(debug) |
|
251 |
if project is not None: |
|
252 |
return [datatype.getname() for datatype in project.getdataTypes()] |
|
253 |
return [] |
|
254 |
||
255 |
# Return project pou names |
|
256 |
def GetProjectPouNames(self, debug = False): |
|
257 |
project = self.GetProject(debug) |
|
258 |
if project is not None: |
|
259 |
return [pou.getname() for pou in project.getpous()] |
|
260 |
return [] |
|
261 |
||
262 |
# Return project pou names |
|
263 |
def GetProjectConfigNames(self, debug = False): |
|
264 |
project = self.GetProject(debug) |
|
265 |
if project is not None: |
|
266 |
return [config.getname() for config in project.getconfigurations()] |
|
267 |
return [] |
|
268 |
||
1171
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
269 |
# Return project pou variable names |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
270 |
def GetProjectPouVariableNames(self, pou_name = None, debug = False): |
814 | 271 |
variables = [] |
272 |
project = self.GetProject(debug) |
|
273 |
if project is not None: |
|
274 |
for pou in project.getpous(): |
|
275 |
if pou_name is None or pou_name == pou.getname(): |
|
276 |
variables.extend([var["Name"] for var in self.GetPouInterfaceVars(pou, debug)]) |
|
277 |
for transition in pou.gettransitionList(): |
|
278 |
variables.append(transition.getname()) |
|
279 |
for action in pou.getactionList(): |
|
280 |
variables.append(action.getname()) |
|
281 |
return variables |
|
282 |
||
283 |
# Return file path if project is an open file |
|
284 |
def GetFilePath(self): |
|
285 |
return self.FilePath |
|
286 |
||
287 |
# Return file path if project is an open file |
|
288 |
def GetProgramFilePath(self): |
|
289 |
return self.ProgramFilePath |
|
290 |
||
291 |
# Return file name and point out if file is up to date |
|
292 |
def GetFilename(self): |
|
293 |
if self.Project is not None: |
|
294 |
if self.ProjectIsSaved(): |
|
295 |
return self.FileName |
|
296 |
else: |
|
297 |
return "~%s~"%self.FileName |
|
298 |
return "" |
|
299 |
||
300 |
# Change file path and save file name or create a default one if file path not defined |
|
301 |
def SetFilePath(self, filepath): |
|
302 |
self.FilePath = filepath |
|
303 |
if filepath == "": |
|
304 |
self.LastNewIndex += 1 |
|
305 |
self.FileName = _("Unnamed%d")%self.LastNewIndex |
|
306 |
else: |
|
307 |
self.FileName = os.path.splitext(os.path.basename(filepath))[0] |
|
308 |
||
309 |
# Change project properties |
|
310 |
def SetProjectProperties(self, name = None, properties = None, buffer = True): |
|
311 |
if self.Project is not None: |
|
312 |
if name is not None: |
|
313 |
self.Project.setname(name) |
|
314 |
if properties is not None: |
|
315 |
self.Project.setfileHeader(properties) |
|
316 |
self.Project.setcontentHeader(properties) |
|
317 |
if buffer and (name is not None or properties is not None): |
|
318 |
self.BufferProject() |
|
319 |
||
320 |
# Return project name |
|
321 |
def GetProjectName(self, debug=False): |
|
322 |
project = self.GetProject(debug) |
|
323 |
if project is not None: |
|
324 |
return project.getname() |
|
325 |
return None |
|
326 |
||
327 |
# Return project properties |
|
328 |
def GetProjectProperties(self, debug = False): |
|
329 |
project = self.GetProject(debug) |
|
330 |
if project is not None: |
|
331 |
properties = project.getfileHeader() |
|
332 |
properties.update(project.getcontentHeader()) |
|
333 |
return properties |
|
334 |
return None |
|
335 |
||
336 |
# Return project informations |
|
337 |
def GetProjectInfos(self, debug = False): |
|
338 |
project = self.GetProject(debug) |
|
339 |
if project is not None: |
|
340 |
infos = {"name": project.getname(), "type": ITEM_PROJECT} |
|
341 |
datatypes = {"name": DATA_TYPES, "type": ITEM_DATATYPES, "values":[]} |
|
342 |
for datatype in project.getdataTypes(): |
|
343 |
datatypes["values"].append({"name": datatype.getname(), "type": ITEM_DATATYPE, |
|
344 |
"tagname": self.ComputeDataTypeName(datatype.getname()), "values": []}) |
|
345 |
pou_types = {"function": {"name": FUNCTIONS, "type": ITEM_FUNCTION, "values":[]}, |
|
346 |
"functionBlock": {"name": FUNCTION_BLOCKS, "type": ITEM_FUNCTIONBLOCK, "values":[]}, |
|
347 |
"program": {"name": PROGRAMS, "type": ITEM_PROGRAM, "values":[]}} |
|
348 |
for pou in project.getpous(): |
|
349 |
pou_type = pou.getpouType() |
|
350 |
pou_infos = {"name": pou.getname(), "type": ITEM_POU, |
|
351 |
"tagname": self.ComputePouName(pou.getname())} |
|
352 |
pou_values = [] |
|
353 |
if pou.getbodyType() == "SFC": |
|
354 |
transitions = [] |
|
355 |
for transition in pou.gettransitionList(): |
|
356 |
transitions.append({"name": transition.getname(), "type": ITEM_TRANSITION, |
|
357 |
"tagname": self.ComputePouTransitionName(pou.getname(), transition.getname()), |
|
358 |
"values": []}) |
|
359 |
pou_values.append({"name": TRANSITIONS, "type": ITEM_TRANSITIONS, "values": transitions}) |
|
360 |
actions = [] |
|
361 |
for action in pou.getactionList(): |
|
362 |
actions.append({"name": action.getname(), "type": ITEM_ACTION, |
|
363 |
"tagname": self.ComputePouActionName(pou.getname(), action.getname()), |
|
364 |
"values": []}) |
|
365 |
pou_values.append({"name": ACTIONS, "type": ITEM_ACTIONS, "values": actions}) |
|
366 |
if pou_type in pou_types: |
|
367 |
pou_infos["values"] = pou_values |
|
368 |
pou_types[pou_type]["values"].append(pou_infos) |
|
369 |
configurations = {"name": CONFIGURATIONS, "type": ITEM_CONFIGURATIONS, "values": []} |
|
370 |
for config in project.getconfigurations(): |
|
371 |
config_name = config.getname() |
|
372 |
config_infos = {"name": config_name, "type": ITEM_CONFIGURATION, |
|
373 |
"tagname": self.ComputeConfigurationName(config.getname()), |
|
374 |
"values": []} |
|
375 |
resources = {"name": RESOURCES, "type": ITEM_RESOURCES, "values": []} |
|
376 |
for resource in config.getresource(): |
|
377 |
resource_name = resource.getname() |
|
378 |
resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, |
|
379 |
"tagname": self.ComputeConfigurationResourceName(config.getname(), resource.getname()), |
|
380 |
"values": []} |
|
381 |
resources["values"].append(resource_infos) |
|
382 |
config_infos["values"] = [resources] |
|
383 |
configurations["values"].append(config_infos) |
|
384 |
infos["values"] = [datatypes, pou_types["function"], pou_types["functionBlock"], |
|
385 |
pou_types["program"], configurations] |
|
386 |
return infos |
|
387 |
return None |
|
388 |
||
389 |
def GetPouVariableInfos(self, project, variable, var_class, debug=False): |
|
390 |
vartype_content = variable.gettype().getcontent() |
|
391 |
if vartype_content["name"] == "derived": |
|
392 |
var_type = vartype_content["value"].getname() |
|
393 |
pou_type = None |
|
394 |
pou = project.getpou(var_type) |
|
395 |
if pou is not None: |
|
396 |
pou_type = pou.getpouType() |
|
397 |
edit = debug = pou_type is not None |
|
398 |
if pou_type is None: |
|
399 |
block_infos = self.GetBlockType(var_type, debug = debug) |
|
400 |
if block_infos is not None: |
|
401 |
pou_type = block_infos["type"] |
|
402 |
if pou_type is not None: |
|
403 |
var_class = None |
|
404 |
if pou_type == "program": |
|
405 |
var_class = ITEM_PROGRAM |
|
406 |
elif pou_type != "function": |
|
407 |
var_class = ITEM_FUNCTIONBLOCK |
|
408 |
if var_class is not None: |
|
409 |
return {"name": variable.getname(), |
|
410 |
"type": var_type, |
|
411 |
"class": var_class, |
|
412 |
"edit": edit, |
|
413 |
"debug": debug} |
|
414 |
elif var_type in self.GetDataTypes(debug = debug): |
|
415 |
return {"name": variable.getname(), |
|
416 |
"type": var_type, |
|
417 |
"class": var_class, |
|
418 |
"edit": False, |
|
419 |
"debug": False} |
|
420 |
elif vartype_content["name"] in ["string", "wstring"]: |
|
421 |
return {"name": variable.getname(), |
|
422 |
"type": vartype_content["name"].upper(), |
|
423 |
"class": var_class, |
|
424 |
"edit": False, |
|
425 |
"debug": True} |
|
426 |
else: |
|
427 |
return {"name": variable.getname(), |
|
428 |
"type": vartype_content["name"], |
|
429 |
"class": var_class, |
|
430 |
"edit": False, |
|
431 |
"debug": True} |
|
432 |
return None |
|
433 |
||
434 |
def GetPouVariables(self, tagname, debug = False): |
|
435 |
vars = [] |
|
436 |
pou_type = None |
|
437 |
project = self.GetProject(debug) |
|
438 |
if project is not None: |
|
439 |
words = tagname.split("::") |
|
440 |
if words[0] == "P": |
|
441 |
pou = project.getpou(words[1]) |
|
442 |
if pou is not None: |
|
443 |
pou_type = pou.getpouType() |
|
444 |
if (pou_type in ["program", "functionBlock"] and |
|
445 |
pou.interface is not None): |
|
446 |
# Extract variables from every varLists |
|
447 |
for varlist_type, varlist in pou.getvars(): |
|
448 |
var_infos = VAR_CLASS_INFOS.get(varlist_type, None) |
|
449 |
if var_infos is not None: |
|
450 |
var_class = var_infos[1] |
|
451 |
else: |
|
452 |
var_class = ITEM_VAR_LOCAL |
|
453 |
for variable in varlist.getvariable(): |
|
454 |
var_infos = self.GetPouVariableInfos(project, variable, var_class, debug) |
|
455 |
if var_infos is not None: |
|
456 |
vars.append(var_infos) |
|
826
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
457 |
if pou.getbodyType() == "SFC": |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
458 |
for transition in pou.gettransitionList(): |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
459 |
vars.append({ |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
460 |
"name": transition.getname(), |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
461 |
"type": None, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
462 |
"class": ITEM_TRANSITION, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
463 |
"edit": True, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
464 |
"debug": True}) |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
465 |
for action in pou.getactionList(): |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
466 |
vars.append({ |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
467 |
"name": action.getname(), |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
468 |
"type": None, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
469 |
"class": ITEM_ACTION, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
470 |
"edit": True, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
471 |
"debug": True}) |
814 | 472 |
return {"class": POU_TYPES[pou_type], |
473 |
"type": words[1], |
|
474 |
"variables": vars, |
|
475 |
"edit": True, |
|
476 |
"debug": True} |
|
477 |
else: |
|
478 |
block_infos = self.GetBlockType(words[1], debug = debug) |
|
479 |
if (block_infos is not None and |
|
480 |
block_infos["type"] in ["program", "functionBlock"]): |
|
481 |
for varname, vartype, varmodifier in block_infos["inputs"]: |
|
482 |
vars.append({"name" : varname, |
|
483 |
"type" : vartype, |
|
484 |
"class" : ITEM_VAR_INPUT, |
|
485 |
"edit": False, |
|
486 |
"debug": True}) |
|
487 |
for varname, vartype, varmodifier in block_infos["outputs"]: |
|
488 |
vars.append({"name" : varname, |
|
489 |
"type" : vartype, |
|
490 |
"class" : ITEM_VAR_OUTPUT, |
|
491 |
"edit": False, |
|
492 |
"debug": True}) |
|
493 |
return {"class": POU_TYPES[block_infos["type"]], |
|
494 |
"type": None, |
|
495 |
"variables": vars, |
|
496 |
"edit": False, |
|
497 |
"debug": False} |
|
826
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
498 |
elif words[0] in ['A', 'T']: |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
499 |
pou_vars = self.GetPouVariables(self.ComputePouName(words[1]), debug) |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
500 |
if pou_vars is not None: |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
501 |
if words[0] == 'A': |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
502 |
element_type = ITEM_ACTION |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
503 |
elif words[0] == 'T': |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
504 |
element_type = ITEM_TRANSITION |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
505 |
return {"class": element_type, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
506 |
"type": None, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
507 |
"variables": [var for var in pou_vars["variables"] |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
508 |
if var["class"] not in [ITEM_ACTION, ITEM_TRANSITION]], |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
509 |
"edit": True, |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
510 |
"debug": True} |
814 | 511 |
elif words[0] in ['C', 'R']: |
512 |
if words[0] == 'C': |
|
513 |
element_type = ITEM_CONFIGURATION |
|
514 |
element = project.getconfiguration(words[1]) |
|
515 |
if element is not None: |
|
516 |
for resource in element.getresource(): |
|
517 |
vars.append({"name": resource.getname(), |
|
518 |
"type": None, |
|
519 |
"class": ITEM_RESOURCE, |
|
520 |
"edit": True, |
|
521 |
"debug": False}) |
|
522 |
elif words[0] == 'R': |
|
523 |
element_type = ITEM_RESOURCE |
|
524 |
element = project.getconfigurationResource(words[1], words[2]) |
|
525 |
if element is not None: |
|
526 |
for task in element.gettask(): |
|
527 |
for pou in task.getpouInstance(): |
|
528 |
vars.append({"name": pou.getname(), |
|
529 |
"type": pou.gettypeName(), |
|
530 |
"class": ITEM_PROGRAM, |
|
531 |
"edit": True, |
|
532 |
"debug": True}) |
|
533 |
for pou in element.getpouInstance(): |
|
534 |
vars.append({"name": pou.getname(), |
|
535 |
"type": pou.gettypeName(), |
|
536 |
"class": ITEM_PROGRAM, |
|
537 |
"edit": True, |
|
538 |
"debug": True}) |
|
539 |
if element is not None: |
|
540 |
for varlist in element.getglobalVars(): |
|
541 |
for variable in varlist.getvariable(): |
|
542 |
var_infos = self.GetPouVariableInfos(project, variable, ITEM_VAR_GLOBAL, debug) |
|
543 |
if var_infos is not None: |
|
544 |
vars.append(var_infos) |
|
545 |
return {"class": element_type, |
|
546 |
"type": None, |
|
547 |
"variables": vars, |
|
548 |
"edit": True, |
|
549 |
"debug": False} |
|
550 |
return None |
|
551 |
||
552 |
def RecursiveSearchPouInstances(self, project, pou_type, parent_path, varlists, debug = False): |
|
553 |
instances = [] |
|
554 |
for varlist in varlists: |
|
555 |
for variable in varlist.getvariable(): |
|
556 |
vartype_content = variable.gettype().getcontent() |
|
557 |
if vartype_content["name"] == "derived": |
|
558 |
var_path = "%s.%s" % (parent_path, variable.getname()) |
|
559 |
var_type = vartype_content["value"].getname() |
|
560 |
if var_type == pou_type: |
|
561 |
instances.append(var_path) |
|
562 |
else: |
|
563 |
pou = project.getpou(var_type) |
|
1222
775b48a2be3b
Fixed flickering and lag when refreshing PouInstanceVariablesPanel
Laurent Bessard
parents:
1186
diff
changeset
|
564 |
if pou is not None and project.ElementIsUsedBy(pou_type, var_type): |
814 | 565 |
instances.extend( |
566 |
self.RecursiveSearchPouInstances( |
|
567 |
project, pou_type, var_path, |
|
568 |
[varlist for type, varlist in pou.getvars()], |
|
569 |
debug)) |
|
570 |
return instances |
|
571 |
||
572 |
def SearchPouInstances(self, tagname, debug = False): |
|
573 |
project = self.GetProject(debug) |
|
574 |
if project is not None: |
|
575 |
words = tagname.split("::") |
|
576 |
if words[0] == "P": |
|
577 |
instances = [] |
|
578 |
for config in project.getconfigurations(): |
|
579 |
config_name = config.getname() |
|
580 |
instances.extend( |
|
581 |
self.RecursiveSearchPouInstances( |
|
582 |
project, words[1], config_name, |
|
583 |
config.getglobalVars(), debug)) |
|
584 |
for resource in config.getresource(): |
|
585 |
res_path = "%s.%s" % (config_name, resource.getname()) |
|
586 |
instances.extend( |
|
587 |
self.RecursiveSearchPouInstances( |
|
588 |
project, words[1], res_path, |
|
589 |
resource.getglobalVars(), debug)) |
|
590 |
pou_instances = resource.getpouInstance()[:] |
|
591 |
for task in resource.gettask(): |
|
592 |
pou_instances.extend(task.getpouInstance()) |
|
593 |
for pou_instance in pou_instances: |
|
594 |
pou_path = "%s.%s" % (res_path, pou_instance.getname()) |
|
595 |
pou_type = pou_instance.gettypeName() |
|
596 |
if pou_type == words[1]: |
|
597 |
instances.append(pou_path) |
|
598 |
pou = project.getpou(pou_type) |
|
1222
775b48a2be3b
Fixed flickering and lag when refreshing PouInstanceVariablesPanel
Laurent Bessard
parents:
1186
diff
changeset
|
599 |
if pou is not None and project.ElementIsUsedBy(words[1], pou_type): |
814 | 600 |
instances.extend( |
601 |
self.RecursiveSearchPouInstances( |
|
602 |
project, words[1], pou_path, |
|
603 |
[varlist for type, varlist in pou.getvars()], |
|
604 |
debug)) |
|
605 |
return instances |
|
606 |
elif words[0] == 'C': |
|
607 |
return [words[1]] |
|
608 |
elif words[0] == 'R': |
|
609 |
return ["%s.%s" % (words[1], words[2])] |
|
826
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
610 |
elif words[0] in ['T', 'A']: |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
611 |
return ["%s.%s" % (instance, words[2]) |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
612 |
for instance in self.SearchPouInstances( |
098f822ef308
Adding transition and action in list of instances of SFC POU in PouInstanceVariablesPanel
laurent
parents:
823
diff
changeset
|
613 |
self.ComputePouName(words[1]), debug)] |
814 | 614 |
return [] |
615 |
||
886
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
616 |
def RecursiveGetPouInstanceTagName(self, project, pou_type, parts, debug = False): |
814 | 617 |
pou = project.getpou(pou_type) |
618 |
if pou is not None: |
|
619 |
if len(parts) == 0: |
|
620 |
return self.ComputePouName(pou_type) |
|
621 |
||
622 |
for varlist_type, varlist in pou.getvars(): |
|
623 |
for variable in varlist.getvariable(): |
|
827
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
624 |
if variable.getname() == parts[0]: |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
625 |
vartype_content = variable.gettype().getcontent() |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
626 |
if vartype_content["name"] == "derived": |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
627 |
return self.RecursiveGetPouInstanceTagName( |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
628 |
project, |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
629 |
vartype_content["value"].getname(), |
886
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
630 |
parts[1:], debug) |
827
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
631 |
|
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
632 |
if pou.getbodyType() == "SFC" and len(parts) == 1: |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
633 |
for action in pou.getactionList(): |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
634 |
if action.getname() == parts[0]: |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
635 |
return self.ComputePouActionName(pou_type, parts[0]) |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
636 |
for transition in pou.gettransitionList(): |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
637 |
if transition.getname() == parts[0]: |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
638 |
return self.ComputePouTransitionName(pou_type, parts[0]) |
886
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
639 |
else: |
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
640 |
block_infos = self.GetBlockType(pou_type, debug=debug) |
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
641 |
if (block_infos is not None and |
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
642 |
block_infos["type"] in ["program", "functionBlock"]): |
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
643 |
|
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
644 |
if len(parts) == 0: |
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
645 |
return self.ComputePouName(pou_type) |
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
646 |
|
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
647 |
for varname, vartype, varmodifier in block_infos["inputs"] + block_infos["outputs"]: |
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
648 |
if varname == parts[0]: |
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
649 |
return self.RecursiveGetPouInstanceTagName(project, vartype, parts[1:], debug) |
814 | 650 |
return None |
651 |
||
652 |
def GetPouInstanceTagName(self, instance_path, debug = False): |
|
653 |
parts = instance_path.split(".") |
|
654 |
if len(parts) == 1: |
|
655 |
return self.ComputeConfigurationName(parts[0]) |
|
656 |
elif len(parts) == 2: |
|
657 |
return self.ComputeConfigurationResourceName(parts[0], parts[1]) |
|
658 |
else: |
|
659 |
project = self.GetProject(debug) |
|
660 |
for config in project.getconfigurations(): |
|
661 |
if config.getname() == parts[0]: |
|
662 |
for resource in config.getresource(): |
|
663 |
if resource.getname() == parts[1]: |
|
664 |
pou_instances = resource.getpouInstance()[:] |
|
665 |
for task in resource.gettask(): |
|
666 |
pou_instances.extend(task.getpouInstance()) |
|
667 |
for pou_instance in pou_instances: |
|
668 |
if pou_instance.getname() == parts[2]: |
|
669 |
if len(parts) == 3: |
|
670 |
return self.ComputePouName( |
|
671 |
pou_instance.gettypeName()) |
|
672 |
else: |
|
673 |
return self.RecursiveGetPouInstanceTagName( |
|
674 |
project, |
|
675 |
pou_instance.gettypeName(), |
|
886
ace92afe9100
Fix bug debug variables from standard and library function blocks unregistered when transferring program
Laurent Bessard
parents:
884
diff
changeset
|
676 |
parts[3:], debug) |
814 | 677 |
return None |
678 |
||
679 |
def GetInstanceInfos(self, instance_path, debug = False): |
|
680 |
tagname = self.GetPouInstanceTagName(instance_path) |
|
681 |
if tagname is not None: |
|
827
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
682 |
infos = self.GetPouVariables(tagname, debug) |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
683 |
infos["type"] = tagname |
a2ce084fb598
Fix restore project tab layout with transition and action debug tabs
laurent
parents:
826
diff
changeset
|
684 |
return infos |
814 | 685 |
else: |
686 |
pou_path, var_name = instance_path.rsplit(".", 1) |
|
687 |
tagname = self.GetPouInstanceTagName(pou_path) |
|
688 |
if tagname is not None: |
|
689 |
pou_infos = self.GetPouVariables(tagname, debug) |
|
690 |
for var_infos in pou_infos["variables"]: |
|
691 |
if var_infos["name"] == var_name: |
|
692 |
return var_infos |
|
693 |
return None |
|
694 |
||
695 |
# Return if data type given by name is used by another data type or pou |
|
696 |
def DataTypeIsUsed(self, name, debug = False): |
|
697 |
project = self.GetProject(debug) |
|
698 |
if project is not None: |
|
699 |
return project.ElementIsUsed(name) or project.DataTypeIsDerived(name) |
|
700 |
return False |
|
701 |
||
702 |
# Return if pou given by name is used by another pou |
|
703 |
def PouIsUsed(self, name, debug = False): |
|
704 |
project = self.GetProject(debug) |
|
705 |
if project is not None: |
|
706 |
return project.ElementIsUsed(name) |
|
707 |
return False |
|
708 |
||
709 |
# Return if pou given by name is directly or undirectly used by the reference pou |
|
710 |
def PouIsUsedBy(self, name, reference, debug = False): |
|
711 |
project = self.GetProject(debug) |
|
712 |
if project is not None: |
|
713 |
return project.ElementIsUsedBy(name, reference) |
|
714 |
return False |
|
715 |
||
716 |
def GenerateProgram(self, filepath=None): |
|
717 |
errors = [] |
|
718 |
warnings = [] |
|
719 |
if self.Project is not None: |
|
720 |
try: |
|
721 |
self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings) |
|
722 |
self.NextCompiledProject = self.Copy(self.Project) |
|
901
ab43f3e40b9d
Fix bug when compiling project containing non-ascii characters
Laurent Bessard
parents:
887
diff
changeset
|
723 |
program_text = "".join([item[0] for item in self.ProgramChunks]) |
814 | 724 |
if filepath is not None: |
725 |
programfile = open(filepath, "w") |
|
726 |
programfile.write(program_text.encode("utf-8")) |
|
727 |
programfile.close() |
|
728 |
self.ProgramFilePath = filepath |
|
729 |
return program_text, errors, warnings |
|
730 |
except PLCGenException, e: |
|
731 |
errors.append(e.message) |
|
732 |
else: |
|
733 |
errors.append("No project opened") |
|
734 |
return "", errors, warnings |
|
735 |
||
736 |
def DebugAvailable(self): |
|
737 |
return self.CurrentCompiledProject is not None |
|
738 |
||
739 |
def ProgramTransferred(self): |
|
740 |
if self.NextCompiledProject is None: |
|
741 |
self.CurrentCompiledProject = self.NextCompiledProject |
|
742 |
else: |
|
743 |
self.CurrentCompiledProject = self.Copy(self.Project) |
|
744 |
||
745 |
def GetChunkInfos(self, from_location, to_location): |
|
746 |
row = self.ProgramOffset + 1 |
|
747 |
col = 1 |
|
748 |
infos = [] |
|
749 |
for chunk, chunk_infos in self.ProgramChunks: |
|
750 |
lines = chunk.split("\n") |
|
751 |
if len(lines) > 1: |
|
752 |
next_row = row + len(lines) - 1 |
|
753 |
next_col = len(lines[-1]) + 1 |
|
754 |
else: |
|
755 |
next_row = row |
|
756 |
next_col = col + len(chunk) |
|
757 |
if (next_row > from_location[0] or next_row == from_location[0] and next_col >= from_location[1]) and len(chunk_infos) > 0: |
|
758 |
infos.append((chunk_infos, (row, col))) |
|
759 |
if next_row == to_location[0] and next_col > to_location[1] or next_row > to_location[0]: |
|
760 |
return infos |
|
761 |
row, col = next_row, next_col |
|
762 |
return infos |
|
763 |
||
764 |
#------------------------------------------------------------------------------- |
|
765 |
# Project Pous management functions |
|
766 |
#------------------------------------------------------------------------------- |
|
767 |
||
768 |
# Add a Data Type to Project |
|
769 |
def ProjectAddDataType(self, datatype_name=None): |
|
770 |
if self.Project is not None: |
|
771 |
if datatype_name is None: |
|
772 |
datatype_name = self.GenerateNewName(None, None, "datatype%d") |
|
773 |
# Add the datatype to project |
|
774 |
self.Project.appenddataType(datatype_name) |
|
775 |
self.BufferProject() |
|
776 |
return self.ComputeDataTypeName(datatype_name) |
|
777 |
return None |
|
778 |
||
779 |
# Remove a Data Type from project |
|
780 |
def ProjectRemoveDataType(self, datatype_name): |
|
781 |
if self.Project is not None: |
|
782 |
self.Project.removedataType(datatype_name) |
|
783 |
self.BufferProject() |
|
784 |
||
785 |
# Add a Pou to Project |
|
786 |
def ProjectAddPou(self, pou_name, pou_type, body_type): |
|
787 |
if self.Project is not None: |
|
788 |
# Add the pou to project |
|
789 |
self.Project.appendpou(pou_name, pou_type, body_type) |
|
790 |
if pou_type == "function": |
|
791 |
self.SetPouInterfaceReturnType(pou_name, "BOOL") |
|
792 |
self.BufferProject() |
|
793 |
return self.ComputePouName(pou_name) |
|
794 |
return None |
|
795 |
||
796 |
def ProjectChangePouType(self, name, pou_type): |
|
797 |
if self.Project is not None: |
|
798 |
pou = self.Project.getpou(name) |
|
799 |
if pou is not None: |
|
800 |
pou.setpouType(pou_type) |
|
801 |
self.Project.RefreshCustomBlockTypes() |
|
802 |
self.BufferProject() |
|
803 |
||
804 |
def GetPouXml(self, pou_name): |
|
805 |
if self.Project is not None: |
|
806 |
pou = self.Project.getpou(pou_name) |
|
807 |
if pou is not None: |
|
808 |
return pou.generateXMLText('pou', 0) |
|
809 |
return None |
|
810 |
||
811 |
def PastePou(self, pou_type, pou_xml): |
|
812 |
''' |
|
813 |
Adds the POU defined by 'pou_xml' to the current project with type 'pou_type' |
|
814 |
''' |
|
815 |
try: |
|
816 |
tree = minidom.parseString(pou_xml.encode("utf-8")) |
|
817 |
root = tree.childNodes[0] |
|
818 |
except: |
|
819 |
return _("Couldn't paste non-POU object.") |
|
820 |
||
821 |
if root.nodeName == "pou": |
|
822 |
new_pou = plcopen.pous_pou() |
|
823 |
new_pou.loadXMLTree(root) |
|
824 |
||
825 |
name = new_pou.getname() |
|
826 |
||
827 |
idx = 0 |
|
828 |
new_name = name |
|
829 |
while self.Project.getpou(new_name): |
|
830 |
# a POU with that name already exists. |
|
831 |
# make a new name and test if a POU with that name exists. |
|
832 |
# append an incrementing numeric suffix to the POU name. |
|
833 |
idx += 1 |
|
834 |
new_name = "%s%d" % (name, idx) |
|
835 |
||
836 |
# we've found a name that does not already exist, use it |
|
837 |
new_pou.setname(new_name) |
|
838 |
||
839 |
if pou_type is not None: |
|
840 |
orig_type = new_pou.getpouType() |
|
841 |
||
842 |
# prevent violations of POU content restrictions: |
|
843 |
# function blocks cannot be pasted as functions, |
|
844 |
# programs cannot be pasted as functions or function blocks |
|
845 |
if orig_type == 'functionBlock' and pou_type == 'function' or \ |
|
846 |
orig_type == 'program' and pou_type in ['function', 'functionBlock']: |
|
847 |
return _('''%s "%s" can't be pasted as a %s.''') % (orig_type, name, pou_type) |
|
848 |
||
849 |
new_pou.setpouType(pou_type) |
|
850 |
||
851 |
self.Project.insertpou(-1, new_pou) |
|
852 |
self.BufferProject() |
|
853 |
||
854 |
return self.ComputePouName(new_name), |
|
855 |
else: |
|
856 |
return _("Couldn't paste non-POU object.") |
|
857 |
||
858 |
# Remove a Pou from project |
|
859 |
def ProjectRemovePou(self, pou_name): |
|
860 |
if self.Project is not None: |
|
861 |
self.Project.removepou(pou_name) |
|
862 |
self.BufferProject() |
|
863 |
||
864 |
# Return the name of the configuration if only one exist |
|
865 |
def GetProjectMainConfigurationName(self): |
|
866 |
if self.Project is not None: |
|
867 |
# Found the configuration corresponding to old name and change its name to new name |
|
868 |
configurations = self.Project.getconfigurations() |
|
869 |
if len(configurations) == 1: |
|
870 |
return configurations[0].getname() |
|
871 |
return None |
|
872 |
||
873 |
# Add a configuration to Project |
|
874 |
def ProjectAddConfiguration(self, config_name=None): |
|
875 |
if self.Project is not None: |
|
876 |
if config_name is None: |
|
877 |
config_name = self.GenerateNewName(None, None, "configuration%d") |
|
878 |
self.Project.addconfiguration(config_name) |
|
879 |
self.BufferProject() |
|
880 |
return self.ComputeConfigurationName(config_name) |
|
881 |
return None |
|
882 |
||
883 |
# Remove a configuration from project |
|
884 |
def ProjectRemoveConfiguration(self, config_name): |
|
885 |
if self.Project is not None: |
|
886 |
self.Project.removeconfiguration(config_name) |
|
887 |
self.BufferProject() |
|
888 |
||
889 |
# Add a resource to a configuration of the Project |
|
890 |
def ProjectAddConfigurationResource(self, config_name, resource_name=None): |
|
891 |
if self.Project is not None: |
|
892 |
if resource_name is None: |
|
893 |
resource_name = self.GenerateNewName(None, None, "resource%d") |
|
894 |
self.Project.addconfigurationResource(config_name, resource_name) |
|
895 |
self.BufferProject() |
|
896 |
return self.ComputeConfigurationResourceName(config_name, resource_name) |
|
897 |
return None |
|
898 |
||
899 |
# Remove a resource from a configuration of the project |
|
900 |
def ProjectRemoveConfigurationResource(self, config_name, resource_name): |
|
901 |
if self.Project is not None: |
|
902 |
self.Project.removeconfigurationResource(config_name, resource_name) |
|
903 |
self.BufferProject() |
|
904 |
||
905 |
# Add a Transition to a Project Pou |
|
906 |
def ProjectAddPouTransition(self, pou_name, transition_name, transition_type): |
|
907 |
if self.Project is not None: |
|
908 |
pou = self.Project.getpou(pou_name) |
|
909 |
if pou is not None: |
|
910 |
pou.addtransition(transition_name, transition_type) |
|
911 |
self.BufferProject() |
|
912 |
return self.ComputePouTransitionName(pou_name, transition_name) |
|
913 |
return None |
|
914 |
||
915 |
# Remove a Transition from a Project Pou |
|
916 |
def ProjectRemovePouTransition(self, pou_name, transition_name): |
|
917 |
# Search if the pou removed is currently opened |
|
918 |
if self.Project is not None: |
|
919 |
pou = self.Project.getpou(pou_name) |
|
920 |
if pou is not None: |
|
921 |
pou.removetransition(transition_name) |
|
922 |
self.BufferProject() |
|
923 |
||
924 |
# Add an Action to a Project Pou |
|
925 |
def ProjectAddPouAction(self, pou_name, action_name, action_type): |
|
926 |
if self.Project is not None: |
|
927 |
pou = self.Project.getpou(pou_name) |
|
928 |
if pou is not None: |
|
929 |
pou.addaction(action_name, action_type) |
|
930 |
self.BufferProject() |
|
931 |
return self.ComputePouActionName(pou_name, action_name) |
|
932 |
return None |
|
933 |
||
934 |
# Remove an Action from a Project Pou |
|
935 |
def ProjectRemovePouAction(self, pou_name, action_name): |
|
936 |
# Search if the pou removed is currently opened |
|
937 |
if self.Project is not None: |
|
938 |
pou = self.Project.getpou(pou_name) |
|
939 |
if pou is not None: |
|
940 |
pou.removeaction(action_name) |
|
941 |
self.BufferProject() |
|
942 |
||
943 |
# Change the name of a pou |
|
944 |
def ChangeDataTypeName(self, old_name, new_name): |
|
945 |
if self.Project is not None: |
|
946 |
# Found the pou corresponding to old name and change its name to new name |
|
947 |
datatype = self.Project.getdataType(old_name) |
|
948 |
if datatype is not None: |
|
949 |
datatype.setname(new_name) |
|
950 |
self.Project.updateElementName(old_name, new_name) |
|
951 |
self.Project.RefreshElementUsingTree() |
|
952 |
self.Project.RefreshDataTypeHierarchy() |
|
953 |
self.BufferProject() |
|
954 |
||
955 |
# Change the name of a pou |
|
956 |
def ChangePouName(self, old_name, new_name): |
|
957 |
if self.Project is not None: |
|
958 |
# Found the pou corresponding to old name and change its name to new name |
|
959 |
pou = self.Project.getpou(old_name) |
|
960 |
if pou is not None: |
|
961 |
pou.setname(new_name) |
|
962 |
self.Project.updateElementName(old_name, new_name) |
|
963 |
self.Project.RefreshElementUsingTree() |
|
964 |
self.Project.RefreshCustomBlockTypes() |
|
965 |
self.BufferProject() |
|
966 |
||
967 |
# Change the name of a pou transition |
|
968 |
def ChangePouTransitionName(self, pou_name, old_name, new_name): |
|
969 |
if self.Project is not None: |
|
970 |
# Found the pou transition corresponding to old name and change its name to new name |
|
971 |
pou = self.Project.getpou(pou_name) |
|
972 |
if pou is not None: |
|
973 |
transition = pou.gettransition(old_name) |
|
974 |
if transition is not None: |
|
975 |
transition.setname(new_name) |
|
976 |
pou.updateElementName(old_name, new_name) |
|
977 |
self.BufferProject() |
|
978 |
||
979 |
# Change the name of a pou action |
|
980 |
def ChangePouActionName(self, pou_name, old_name, new_name): |
|
981 |
if self.Project is not None: |
|
982 |
# Found the pou action corresponding to old name and change its name to new name |
|
983 |
pou = self.Project.getpou(pou_name) |
|
984 |
if pou is not None: |
|
985 |
action = pou.getaction(old_name) |
|
986 |
if action is not None: |
|
987 |
action.setname(new_name) |
|
988 |
pou.updateElementName(old_name, new_name) |
|
989 |
self.BufferProject() |
|
990 |
||
991 |
# Change the name of a pou variable |
|
992 |
def ChangePouVariableName(self, pou_name, old_name, new_name): |
|
993 |
if self.Project is not None: |
|
994 |
# Found the pou action corresponding to old name and change its name to new name |
|
995 |
pou = self.Project.getpou(pou_name) |
|
996 |
if pou is not None: |
|
997 |
for type, varlist in pou.getvars(): |
|
998 |
for var in varlist.getvariable(): |
|
999 |
if var.getname() == old_name: |
|
1000 |
var.setname(new_name) |
|
1001 |
self.Project.RefreshCustomBlockTypes() |
|
1002 |
self.BufferProject() |
|
1003 |
||
1004 |
# Change the name of a configuration |
|
1005 |
def ChangeConfigurationName(self, old_name, new_name): |
|
1006 |
if self.Project is not None: |
|
1007 |
# Found the configuration corresponding to old name and change its name to new name |
|
1008 |
configuration = self.Project.getconfiguration(old_name) |
|
1009 |
if configuration is not None: |
|
1010 |
configuration.setname(new_name) |
|
1011 |
self.BufferProject() |
|
1012 |
||
1013 |
# Change the name of a configuration resource |
|
1014 |
def ChangeConfigurationResourceName(self, config_name, old_name, new_name): |
|
1015 |
if self.Project is not None: |
|
1016 |
# Found the resource corresponding to old name and change its name to new name |
|
1017 |
resource = self.Project.getconfigurationResource(config_name, old_name) |
|
1018 |
if resource is not None: |
|
1019 |
resource.setname(new_name) |
|
1020 |
self.BufferProject() |
|
1021 |
||
1022 |
# Return the description of the pou given by its name |
|
1023 |
def GetPouDescription(self, name, debug = False): |
|
1024 |
project = self.GetProject(debug) |
|
1025 |
if project is not None: |
|
1026 |
# Found the pou correponding to name and return its type |
|
1027 |
pou = project.getpou(name) |
|
1028 |
if pou is not None: |
|
1029 |
return pou.getdescription() |
|
1030 |
return "" |
|
1031 |
||
1032 |
# Return the description of the pou given by its name |
|
1033 |
def SetPouDescription(self, name, description, debug = False): |
|
1034 |
project = self.GetProject(debug) |
|
1035 |
if project is not None: |
|
1036 |
# Found the pou correponding to name and return its type |
|
1037 |
pou = project.getpou(name) |
|
1038 |
if pou is not None: |
|
1039 |
pou.setdescription(description) |
|
1040 |
project.RefreshCustomBlockTypes() |
|
1041 |
self.BufferProject() |
|
1042 |
||
1043 |
# Return the type of the pou given by its name |
|
1044 |
def GetPouType(self, name, debug = False): |
|
1045 |
project = self.GetProject(debug) |
|
1046 |
if project is not None: |
|
1047 |
# Found the pou correponding to name and return its type |
|
1048 |
pou = project.getpou(name) |
|
1049 |
if pou is not None: |
|
1050 |
return pou.getpouType() |
|
1051 |
return None |
|
1052 |
||
1053 |
# Return pous with SFC language |
|
1054 |
def GetSFCPous(self, debug = False): |
|
1055 |
list = [] |
|
1056 |
project = self.GetProject(debug) |
|
1057 |
if project is not None: |
|
1058 |
for pou in project.getpous(): |
|
1059 |
if pou.getBodyType() == "SFC": |
|
1060 |
list.append(pou.getname()) |
|
1061 |
return list |
|
1062 |
||
1063 |
# Return the body language of the pou given by its name |
|
1064 |
def GetPouBodyType(self, name, debug = False): |
|
1065 |
project = self.GetProject(debug) |
|
1066 |
if project is not None: |
|
1067 |
# Found the pou correponding to name and return its body language |
|
1068 |
pou = project.getpou(name) |
|
1069 |
if pou is not None: |
|
1070 |
return pou.getbodyType() |
|
1071 |
return None |
|
1072 |
||
1073 |
# Return the actions of a pou |
|
1074 |
def GetPouTransitions(self, pou_name, debug = False): |
|
1075 |
transitions = [] |
|
1076 |
project = self.GetProject(debug) |
|
1077 |
if project is not None: |
|
1078 |
# Found the pou correponding to name and return its transitions if SFC |
|
1079 |
pou = project.getpou(pou_name) |
|
1080 |
if pou is not None and pou.getbodyType() == "SFC": |
|
1081 |
for transition in pou.gettransitionList(): |
|
1082 |
transitions.append(transition.getname()) |
|
1083 |
return transitions |
|
1084 |
||
1085 |
# Return the body language of the transition given by its name |
|
1086 |
def GetTransitionBodyType(self, pou_name, pou_transition, debug = False): |
|
1087 |
project = self.GetProject(debug) |
|
1088 |
if project is not None: |
|
1089 |
# Found the pou correponding to name |
|
1090 |
pou = project.getpou(pou_name) |
|
1091 |
if pou is not None: |
|
1092 |
# Found the pou transition correponding to name and return its body language |
|
1093 |
transition = pou.gettransition(pou_transition) |
|
1094 |
if transition is not None: |
|
1095 |
return transition.getbodyType() |
|
1096 |
return None |
|
1097 |
||
1098 |
# Return the actions of a pou |
|
1099 |
def GetPouActions(self, pou_name, debug = False): |
|
1100 |
actions = [] |
|
1101 |
project = self.GetProject(debug) |
|
1102 |
if project is not None: |
|
1103 |
# Found the pou correponding to name and return its actions if SFC |
|
1104 |
pou = project.getpou(pou_name) |
|
1105 |
if pou.getbodyType() == "SFC": |
|
1106 |
for action in pou.getactionList(): |
|
1107 |
actions.append(action.getname()) |
|
1108 |
return actions |
|
1109 |
||
1110 |
# Return the body language of the pou given by its name |
|
1111 |
def GetActionBodyType(self, pou_name, pou_action, debug = False): |
|
1112 |
project = self.GetProject(debug) |
|
1113 |
if project is not None: |
|
1114 |
# Found the pou correponding to name and return its body language |
|
1115 |
pou = project.getpou(pou_name) |
|
1116 |
if pou is not None: |
|
1117 |
action = pou.getaction(pou_action) |
|
1118 |
if action is not None: |
|
1119 |
return action.getbodyType() |
|
1120 |
return None |
|
1121 |
||
1122 |
# Extract varlists from a list of vars |
|
1123 |
def ExtractVarLists(self, vars): |
|
1124 |
varlist_list = [] |
|
1125 |
current_varlist = None |
|
1126 |
current_type = None |
|
1127 |
for var in vars: |
|
1128 |
next_type = (var["Class"], |
|
1129 |
var["Option"], |
|
1130 |
var["Location"] in ["", None] or |
|
1131 |
# When declaring globals, located |
|
1132 |
# and not located variables are |
|
1133 |
# in the same declaration block |
|
1134 |
var["Class"] == "Global") |
|
1135 |
if current_type != next_type: |
|
1136 |
current_type = next_type |
|
1137 |
infos = VAR_CLASS_INFOS.get(var["Class"], None) |
|
1138 |
if infos is not None: |
|
1139 |
current_varlist = infos[0]() |
|
1140 |
else: |
|
1141 |
current_varlist = plcopen.varList() |
|
1142 |
varlist_list.append((var["Class"], current_varlist)) |
|
1143 |
if var["Option"] == "Constant": |
|
1144 |
current_varlist.setconstant(True) |
|
1145 |
elif var["Option"] == "Retain": |
|
1146 |
current_varlist.setretain(True) |
|
1147 |
elif var["Option"] == "Non-Retain": |
|
1148 |
current_varlist.setnonretain(True) |
|
1149 |
# Create variable and change its properties |
|
1150 |
tempvar = plcopen.varListPlain_variable() |
|
1151 |
tempvar.setname(var["Name"]) |
|
1152 |
||
1153 |
var_type = plcopen.dataType() |
|
1154 |
if isinstance(var["Type"], TupleType): |
|
1155 |
if var["Type"][0] == "array": |
|
1156 |
array_type, base_type_name, dimensions = var["Type"] |
|
1157 |
array = plcopen.derivedTypes_array() |
|
1158 |
for i, dimension in enumerate(dimensions): |
|
1159 |
dimension_range = plcopen.rangeSigned() |
|
1160 |
dimension_range.setlower(dimension[0]) |
|
1161 |
dimension_range.setupper(dimension[1]) |
|
1162 |
if i == 0: |
|
1163 |
array.setdimension([dimension_range]) |
|
1164 |
else: |
|
1165 |
array.appenddimension(dimension_range) |
|
1166 |
if base_type_name in self.GetBaseTypes(): |
|
1167 |
if base_type_name == "STRING": |
|
1168 |
array.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) |
|
1169 |
elif base_type_name == "WSTRING": |
|
1170 |
array.baseType.setcontent({"name" : "wstring", "value" : plcopen.wstring()}) |
|
1171 |
else: |
|
1172 |
array.baseType.setcontent({"name" : base_type_name, "value" : None}) |
|
1173 |
else: |
|
1174 |
derived_datatype = plcopen.derivedTypes_derived() |
|
1175 |
derived_datatype.setname(base_type_name) |
|
1176 |
array.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) |
|
1177 |
var_type.setcontent({"name" : "array", "value" : array}) |
|
1178 |
elif var["Type"] in self.GetBaseTypes(): |
|
1179 |
if var["Type"] == "STRING": |
|
1180 |
var_type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) |
|
1181 |
elif var["Type"] == "WSTRING": |
|
1182 |
var_type.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()}) |
|
1183 |
else: |
|
1184 |
var_type.setcontent({"name" : var["Type"], "value" : None}) |
|
1185 |
else: |
|
1186 |
derived_type = plcopen.derivedTypes_derived() |
|
1187 |
derived_type.setname(var["Type"]) |
|
1188 |
var_type.setcontent({"name" : "derived", "value" : derived_type}) |
|
1189 |
tempvar.settype(var_type) |
|
1190 |
||
1191 |
if var["Initial Value"] != "": |
|
1192 |
value = plcopen.value() |
|
1193 |
value.setvalue(var["Initial Value"]) |
|
1194 |
tempvar.setinitialValue(value) |
|
1195 |
if var["Location"] != "": |
|
1196 |
tempvar.setaddress(var["Location"]) |
|
1197 |
else: |
|
1198 |
tempvar.setaddress(None) |
|
1199 |
if var['Documentation'] != "": |
|
1200 |
ft = plcopen.formattedText() |
|
1201 |
ft.settext(var['Documentation']) |
|
1202 |
tempvar.setdocumentation(ft) |
|
1203 |
||
1204 |
# Add variable to varList |
|
1205 |
current_varlist.appendvariable(tempvar) |
|
1206 |
return varlist_list |
|
1207 |
||
1208 |
def GetVariableDictionary(self, varlist, var): |
|
1209 |
''' |
|
1210 |
convert a PLC variable to the dictionary representation |
|
1211 |
returned by Get*Vars) |
|
1212 |
''' |
|
1213 |
||
1214 |
tempvar = {"Name": var.getname()} |
|
1215 |
||
1216 |
vartype_content = var.gettype().getcontent() |
|
1217 |
if vartype_content["name"] == "derived": |
|
1218 |
tempvar["Type"] = vartype_content["value"].getname() |
|
1219 |
elif vartype_content["name"] == "array": |
|
1220 |
dimensions = [] |
|
1221 |
for dimension in vartype_content["value"].getdimension(): |
|
1222 |
dimensions.append((dimension.getlower(), dimension.getupper())) |
|
1223 |
base_type = vartype_content["value"].baseType.getcontent() |
|
864
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1224 |
if base_type["value"] is None or base_type["name"] in ["string", "wstring"]: |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1225 |
base_type_name = base_type["name"].upper() |
814 | 1226 |
else: |
1227 |
base_type_name = base_type["value"].getname() |
|
1228 |
tempvar["Type"] = ("array", base_type_name, dimensions) |
|
1229 |
elif vartype_content["name"] in ["string", "wstring"]: |
|
1230 |
tempvar["Type"] = vartype_content["name"].upper() |
|
1231 |
else: |
|
1232 |
tempvar["Type"] = vartype_content["name"] |
|
1233 |
||
1234 |
tempvar["Edit"] = True |
|
1235 |
||
1236 |
initial = var.getinitialValue() |
|
1237 |
if initial: |
|
1238 |
tempvar["Initial Value"] = initial.getvalue() |
|
1239 |
else: |
|
1240 |
tempvar["Initial Value"] = "" |
|
1241 |
||
1242 |
address = var.getaddress() |
|
1243 |
if address: |
|
1244 |
tempvar["Location"] = address |
|
1245 |
else: |
|
1246 |
tempvar["Location"] = "" |
|
1247 |
||
1248 |
if varlist.getconstant(): |
|
1249 |
tempvar["Option"] = "Constant" |
|
1250 |
elif varlist.getretain(): |
|
1251 |
tempvar["Option"] = "Retain" |
|
1252 |
elif varlist.getnonretain(): |
|
1253 |
tempvar["Option"] = "Non-Retain" |
|
1254 |
else: |
|
1255 |
tempvar["Option"] = "" |
|
1256 |
||
1257 |
doc = var.getdocumentation() |
|
1258 |
if doc: |
|
1259 |
tempvar["Documentation"] = doc.gettext() |
|
1260 |
else: |
|
1261 |
tempvar["Documentation"] = "" |
|
1262 |
||
1263 |
return tempvar |
|
1171
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1264 |
|
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1265 |
# Add a global var to configuration to configuration |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1266 |
def AddConfigurationGlobalVar(self, config_name, type, var_name, |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1267 |
location="", description=""): |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1268 |
if self.Project is not None: |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1269 |
# Found the configuration corresponding to name |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1270 |
configuration = self.Project.getconfiguration(config_name) |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1271 |
if configuration is not None: |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1272 |
# Set configuration global vars |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1273 |
configuration.addglobalVar(type, var_name, location, description) |
814 | 1274 |
|
1275 |
# Replace the configuration globalvars by those given |
|
1276 |
def SetConfigurationGlobalVars(self, name, vars): |
|
1277 |
if self.Project is not None: |
|
1278 |
# Found the configuration corresponding to name |
|
1279 |
configuration = self.Project.getconfiguration(name) |
|
1280 |
if configuration is not None: |
|
1281 |
# Set configuration global vars |
|
1282 |
configuration.setglobalVars([]) |
|
1283 |
for vartype, varlist in self.ExtractVarLists(vars): |
|
1284 |
configuration.globalVars.append(varlist) |
|
1285 |
||
1286 |
# Return the configuration globalvars |
|
1287 |
def GetConfigurationGlobalVars(self, name, debug = False): |
|
1288 |
vars = [] |
|
1289 |
project = self.GetProject(debug) |
|
1290 |
if project is not None: |
|
1291 |
# Found the configuration corresponding to name |
|
1292 |
configuration = project.getconfiguration(name) |
|
1293 |
if configuration is not None: |
|
1294 |
# Extract variables from every varLists |
|
1295 |
for varlist in configuration.getglobalVars(): |
|
1296 |
for var in varlist.getvariable(): |
|
1297 |
tempvar = self.GetVariableDictionary(varlist, var) |
|
1298 |
tempvar["Class"] = "Global" |
|
1299 |
vars.append(tempvar) |
|
1300 |
return vars |
|
1301 |
||
1171
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1302 |
# Return configuration variable names |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1303 |
def GetConfigurationVariableNames(self, config_name = None, debug = False): |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1304 |
variables = [] |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1305 |
project = self.GetProject(debug) |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1306 |
if project is not None: |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1307 |
for configuration in self.Project.getconfigurations(): |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1308 |
if config_name is None or config_name == configuration.getname(): |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1309 |
variables.extend( |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1310 |
[var.getname() for var in reduce( |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1311 |
lambda x, y: x + y, [varlist.getvariable() |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1312 |
for varlist in configuration.globalVars], |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1313 |
[])]) |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1314 |
return variables |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1315 |
|
814 | 1316 |
# Replace the resource globalvars by those given |
1317 |
def SetConfigurationResourceGlobalVars(self, config_name, name, vars): |
|
1318 |
if self.Project is not None: |
|
1319 |
# Found the resource corresponding to name |
|
1320 |
resource = self.Project.getconfigurationResource(config_name, name) |
|
1321 |
# Set resource global vars |
|
1322 |
if resource is not None: |
|
1323 |
resource.setglobalVars([]) |
|
1324 |
for vartype, varlist in self.ExtractVarLists(vars): |
|
1325 |
resource.globalVars.append(varlist) |
|
1326 |
||
1327 |
# Return the resource globalvars |
|
1328 |
def GetConfigurationResourceGlobalVars(self, config_name, name, debug = False): |
|
1329 |
vars = [] |
|
1330 |
project = self.GetProject(debug) |
|
1331 |
if project is not None: |
|
1332 |
# Found the resource corresponding to name |
|
1333 |
resource = project.getconfigurationResource(config_name, name) |
|
1334 |
if resource: |
|
1335 |
# Extract variables from every varLists |
|
1336 |
for varlist in resource.getglobalVars(): |
|
1337 |
for var in varlist.getvariable(): |
|
1338 |
tempvar = self.GetVariableDictionary(varlist, var) |
|
1339 |
tempvar["Class"] = "Global" |
|
1340 |
vars.append(tempvar) |
|
1341 |
return vars |
|
1342 |
||
1171
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1343 |
# Return resource variable names |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1344 |
def GetConfigurationResourceVariableNames(self, |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1345 |
config_name = None, resource_name = None, debug = False): |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1346 |
variables = [] |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1347 |
project = self.GetProject(debug) |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1348 |
if project is not None: |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1349 |
for configuration in self.Project.getconfigurations(): |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1350 |
if config_name is None or config_name == configuration.getname(): |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1351 |
for resource in configuration.getresource(): |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1352 |
if resource_name is None or resource.getname() == resource_name: |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1353 |
variables.extend( |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1354 |
[var.getname() for var in reduce( |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1355 |
lambda x, y: x + y, [varlist.getvariable() |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1356 |
for varlist in resource.globalVars], |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1357 |
[])]) |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1358 |
return variables |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
1359 |
|
814 | 1360 |
# Recursively generate element name tree for a structured variable |
1361 |
def GenerateVarTree(self, typename, debug = False): |
|
1362 |
project = self.GetProject(debug) |
|
1363 |
if project is not None: |
|
1364 |
blocktype = self.GetBlockType(typename, debug = debug) |
|
1365 |
if blocktype is not None: |
|
1366 |
tree = [] |
|
1367 |
en = False |
|
1368 |
eno = False |
|
1369 |
for var_name, var_type, var_modifier in blocktype["inputs"] + blocktype["outputs"]: |
|
1370 |
en |= var_name.upper() == "EN" |
|
1371 |
eno |= var_name.upper() == "ENO" |
|
1372 |
tree.append((var_name, var_type, self.GenerateVarTree(var_type, debug))) |
|
1373 |
if not eno: |
|
1374 |
tree.insert(0, ("ENO", "BOOL", ([], []))) |
|
1375 |
if not en: |
|
1376 |
tree.insert(0, ("EN", "BOOL", ([], []))) |
|
1377 |
return tree, [] |
|
1378 |
datatype = project.getdataType(typename) |
|
1379 |
if datatype is None: |
|
1380 |
datatype = self.GetConfNodeDataType(typename) |
|
1381 |
if datatype is not None: |
|
1382 |
tree = [] |
|
1383 |
basetype_content = datatype.baseType.getcontent() |
|
1384 |
if basetype_content["name"] == "derived": |
|
1385 |
return self.GenerateVarTree(basetype_content["value"].getname()) |
|
1386 |
elif basetype_content["name"] == "array": |
|
1387 |
dimensions = [] |
|
1388 |
base_type = basetype_content["value"].baseType.getcontent() |
|
1389 |
if base_type["name"] == "derived": |
|
1390 |
tree = self.GenerateVarTree(base_type["value"].getname()) |
|
1391 |
if len(tree[1]) == 0: |
|
1392 |
tree = tree[0] |
|
1393 |
for dimension in basetype_content["value"].getdimension(): |
|
1394 |
dimensions.append((dimension.getlower(), dimension.getupper())) |
|
1395 |
return tree, dimensions |
|
1396 |
elif basetype_content["name"] == "struct": |
|
1397 |
for element in basetype_content["value"].getvariable(): |
|
1398 |
element_type = element.type.getcontent() |
|
1399 |
if element_type["name"] == "derived": |
|
1400 |
tree.append((element.getname(), element_type["value"].getname(), self.GenerateVarTree(element_type["value"].getname()))) |
|
1401 |
else: |
|
1402 |
tree.append((element.getname(), element_type["name"], ([], []))) |
|
1403 |
return tree, [] |
|
1404 |
return [], [] |
|
1405 |
||
1406 |
# Return the interface for the given pou |
|
1407 |
def GetPouInterfaceVars(self, pou, debug = False): |
|
1408 |
vars = [] |
|
1409 |
# Verify that the pou has an interface |
|
1410 |
if pou.interface is not None: |
|
1411 |
# Extract variables from every varLists |
|
1412 |
for type, varlist in pou.getvars(): |
|
1413 |
for var in varlist.getvariable(): |
|
1414 |
tempvar = self.GetVariableDictionary(varlist, var) |
|
1415 |
||
1416 |
tempvar["Class"] = type |
|
1417 |
tempvar["Tree"] = ([], []) |
|
1418 |
||
1419 |
vartype_content = var.gettype().getcontent() |
|
1420 |
if vartype_content["name"] == "derived": |
|
1421 |
tempvar["Edit"] = not pou.hasblock(tempvar["Name"]) |
|
1422 |
tempvar["Tree"] = self.GenerateVarTree(tempvar["Type"], debug) |
|
1423 |
||
1424 |
vars.append(tempvar) |
|
1425 |
return vars |
|
1426 |
||
1427 |
# Replace the Pou interface by the one given |
|
1428 |
def SetPouInterfaceVars(self, name, vars): |
|
1429 |
if self.Project is not None: |
|
1430 |
# Found the pou corresponding to name and add interface if there isn't one yet |
|
1431 |
pou = self.Project.getpou(name) |
|
1432 |
if pou is not None: |
|
1433 |
if pou.interface is None: |
|
1434 |
pou.interface = plcopen.pou_interface() |
|
1435 |
# Set Pou interface |
|
1436 |
pou.setvars(self.ExtractVarLists(vars)) |
|
1437 |
self.Project.RefreshElementUsingTree() |
|
1438 |
self.Project.RefreshCustomBlockTypes() |
|
1439 |
||
1440 |
# Replace the return type of the pou given by its name (only for functions) |
|
1441 |
def SetPouInterfaceReturnType(self, name, type): |
|
1442 |
if self.Project is not None: |
|
1443 |
pou = self.Project.getpou(name) |
|
1444 |
if pou is not None: |
|
1445 |
if pou.interface is None: |
|
1446 |
pou.interface = plcopen.pou_interface() |
|
1447 |
# If there isn't any return type yet, add it |
|
1448 |
return_type = pou.interface.getreturnType() |
|
1449 |
if not return_type: |
|
1450 |
return_type = plcopen.dataType() |
|
1451 |
pou.interface.setreturnType(return_type) |
|
1452 |
# Change return type |
|
1453 |
if type in self.GetBaseTypes(): |
|
1454 |
if type == "STRING": |
|
1455 |
return_type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) |
|
1456 |
elif type == "WSTRING": |
|
1457 |
return_type.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()}) |
|
1458 |
else: |
|
1459 |
return_type.setcontent({"name" : type, "value" : None}) |
|
1460 |
else: |
|
1461 |
derived_type = plcopen.derivedTypes_derived() |
|
1462 |
derived_type.setname(type) |
|
1463 |
return_type.setcontent({"name" : "derived", "value" : derived_type}) |
|
1464 |
self.Project.RefreshElementUsingTree() |
|
1465 |
self.Project.RefreshCustomBlockTypes() |
|
1466 |
||
1467 |
def UpdateProjectUsedPous(self, old_name, new_name): |
|
1468 |
if self.Project: |
|
1469 |
self.Project.updateElementName(old_name, new_name) |
|
1470 |
||
1471 |
def UpdateEditedElementUsedVariable(self, tagname, old_name, new_name): |
|
1472 |
pou = self.GetEditedElement(tagname) |
|
1473 |
if pou: |
|
1474 |
pou.updateElementName(old_name, new_name) |
|
1475 |
||
1476 |
# Return the return type of the pou given by its name |
|
1477 |
def GetPouInterfaceReturnTypeByName(self, name): |
|
1478 |
project = self.GetProject(debug) |
|
1479 |
if project is not None: |
|
1480 |
# Found the pou correponding to name and return the return type |
|
1481 |
pou = project.getpou(name) |
|
1482 |
if pou is not None: |
|
1483 |
return self.GetPouInterfaceReturnType(pou) |
|
1484 |
return False |
|
1485 |
||
1486 |
# Return the return type of the given pou |
|
1487 |
def GetPouInterfaceReturnType(self, pou): |
|
1488 |
# Verify that the pou has an interface |
|
1489 |
if pou.interface is not None: |
|
1490 |
# Return the return type if there is one |
|
1491 |
return_type = pou.interface.getreturnType() |
|
1492 |
if return_type: |
|
1493 |
returntype_content = return_type.getcontent() |
|
1494 |
if returntype_content["name"] == "derived": |
|
1495 |
return returntype_content["value"].getname() |
|
1496 |
elif returntype_content["name"] in ["string", "wstring"]: |
|
1497 |
return returntype_content["name"].upper() |
|
1498 |
else: |
|
1499 |
return returntype_content["name"] |
|
1500 |
return None |
|
1501 |
||
1502 |
# Function that add a new confnode to the confnode list |
|
1503 |
def AddConfNodeTypesList(self, typeslist): |
|
1504 |
self.ConfNodeTypes.extend(typeslist) |
|
1505 |
||
1506 |
# Function that clear the confnode list |
|
1507 |
def ClearConfNodeTypes(self): |
|
1508 |
for i in xrange(len(self.ConfNodeTypes)): |
|
1509 |
self.ConfNodeTypes.pop(0) |
|
1510 |
||
1511 |
def GetConfNodeBlockTypes(self): |
|
1512 |
return [{"name": _("%s POUs") % confnodetypes["name"], |
|
1513 |
"list": confnodetypes["types"].GetCustomBlockTypes()} |
|
1514 |
for confnodetypes in self.ConfNodeTypes] |
|
1515 |
||
863
b1ead41fbd3b
Fix bug in VariablePanel 'Type' cell editor menu entry 'User Data Types' containing ConfNodes data types
Laurent Bessard
parents:
853
diff
changeset
|
1516 |
def GetConfNodeDataTypes(self, exclude = "", only_locatables = False): |
814 | 1517 |
return [{"name": _("%s Data Types") % confnodetypes["name"], |
863
b1ead41fbd3b
Fix bug in VariablePanel 'Type' cell editor menu entry 'User Data Types' containing ConfNodes data types
Laurent Bessard
parents:
853
diff
changeset
|
1518 |
"list": [datatype["name"] for datatype in confnodetypes["types"].GetCustomDataTypes(exclude, only_locatables)]} |
814 | 1519 |
for confnodetypes in self.ConfNodeTypes] |
1520 |
||
1521 |
def GetConfNodeDataType(self, type): |
|
1522 |
for confnodetype in self.ConfNodeTypes: |
|
1523 |
datatype = confnodetype["types"].getdataType(type) |
|
1524 |
if datatype is not None: |
|
1525 |
return datatype |
|
1526 |
return None |
|
1527 |
||
1528 |
def GetVariableLocationTree(self): |
|
1529 |
return [] |
|
1530 |
||
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1531 |
def GetConfNodeGlobalInstances(self): |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1532 |
return [] |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1533 |
|
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1534 |
def GetConfigurationExtraVariables(self): |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1535 |
global_vars = [] |
1096
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1536 |
for var_name, var_type, var_initial in self.GetConfNodeGlobalInstances(): |
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1537 |
tempvar = plcopen.varListPlain_variable() |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1538 |
tempvar.setname(var_name) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1539 |
|
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1540 |
tempvartype = plcopen.dataType() |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1541 |
if var_type in self.GetBaseTypes(): |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1542 |
if var_type == "STRING": |
1096
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1543 |
tempvartype.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) |
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1544 |
elif var_type == "WSTRING": |
1096
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1545 |
tempvartype.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()}) |
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1546 |
else: |
1096
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1547 |
tempvartype.setcontent({"name" : var_type, "value" : None}) |
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1548 |
else: |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1549 |
tempderivedtype = plcopen.derivedTypes_derived() |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1550 |
tempderivedtype.setname(var_type) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1551 |
tempvartype.setcontent({"name" : "derived", "value" : tempderivedtype}) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1552 |
tempvar.settype(tempvartype) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1553 |
|
1096
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1554 |
if var_initial != "": |
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1555 |
value = plcopen.value() |
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1556 |
value.setvalue(var_initial) |
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1557 |
tempvar.setinitialValue(value) |
c9ace6a881c9
Fixed CFileEditor replacing folding panels by variable panel and STC
Laurent Bessard
parents:
901
diff
changeset
|
1558 |
|
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1559 |
global_vars.append(tempvar) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1560 |
return global_vars |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1561 |
|
814 | 1562 |
# Function that returns the block definition associated to the block type given |
1563 |
def GetBlockType(self, type, inputs = None, debug = False): |
|
1564 |
result_blocktype = None |
|
1565 |
for category in BlockTypes + self.GetConfNodeBlockTypes(): |
|
1566 |
for blocktype in category["list"]: |
|
1567 |
if blocktype["name"] == type: |
|
1568 |
if inputs is not None and inputs != "undefined": |
|
1569 |
block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]]) |
|
1570 |
if reduce(lambda x, y: x and y, map(lambda x: x[0] == "ANY" or self.IsOfType(*x), zip(inputs, block_inputs)), True): |
|
1571 |
return blocktype |
|
1572 |
else: |
|
1573 |
if result_blocktype is not None: |
|
1574 |
if inputs == "undefined": |
|
1575 |
return None |
|
1576 |
else: |
|
1577 |
result_blocktype["inputs"] = [(i[0], "ANY", i[2]) for i in result_blocktype["inputs"]] |
|
1578 |
result_blocktype["outputs"] = [(o[0], "ANY", o[2]) for o in result_blocktype["outputs"]] |
|
1579 |
return result_blocktype |
|
1223
d51cea72baa7
Fixed bug when adding standard function like ADD, SUB, MUL,... that are overloaded. Block type was not selected and shown when opening FBDBlockDialog to edit it.
Laurent Bessard
parents:
1222
diff
changeset
|
1580 |
result_blocktype = blocktype.copy() |
814 | 1581 |
if result_blocktype is not None: |
1582 |
return result_blocktype |
|
1583 |
project = self.GetProject(debug) |
|
1584 |
if project is not None: |
|
1585 |
return project.GetCustomBlockType(type, inputs) |
|
1586 |
return None |
|
1587 |
||
1588 |
# Return Block types checking for recursion |
|
1589 |
def GetBlockTypes(self, tagname = "", debug = False): |
|
1590 |
type = None |
|
1591 |
words = tagname.split("::") |
|
1592 |
if self.Project: |
|
1593 |
name = "" |
|
1594 |
if words[0] in ["P","T","A"]: |
|
1595 |
name = words[1] |
|
1596 |
type = self.GetPouType(name, debug) |
|
823
c6ed7b933617
Remove restriction of function block usage in SFC transitions body
laurent
parents:
814
diff
changeset
|
1597 |
if type == "function": |
814 | 1598 |
blocktypes = [] |
1599 |
for category in BlockTypes + self.GetConfNodeBlockTypes(): |
|
1600 |
cat = {"name" : category["name"], "list" : []} |
|
1601 |
for block in category["list"]: |
|
1602 |
if block["type"] == "function": |
|
1603 |
cat["list"].append(block) |
|
1604 |
if len(cat["list"]) > 0: |
|
1605 |
blocktypes.append(cat) |
|
1606 |
else: |
|
1607 |
blocktypes = [category for category in BlockTypes + self.GetConfNodeBlockTypes()] |
|
1608 |
project = self.GetProject(debug) |
|
1609 |
if project is not None: |
|
1610 |
blocktypes.append({"name" : USER_DEFINED_POUS, "list": project.GetCustomBlockTypes(name, type == "function" or words[0] == "T")}) |
|
1611 |
return blocktypes |
|
1612 |
||
1613 |
# Return Function Block types checking for recursion |
|
1614 |
def GetFunctionBlockTypes(self, tagname = "", debug = False): |
|
1615 |
blocktypes = [] |
|
1616 |
for category in BlockTypes + self.GetConfNodeBlockTypes(): |
|
1617 |
for block in category["list"]: |
|
1618 |
if block["type"] == "functionBlock": |
|
1619 |
blocktypes.append(block["name"]) |
|
1620 |
project = self.GetProject(debug) |
|
1621 |
if project is not None: |
|
1622 |
name = "" |
|
1623 |
words = tagname.split("::") |
|
1624 |
if words[0] in ["P","T","A"]: |
|
1625 |
name = words[1] |
|
1626 |
blocktypes.extend(project.GetCustomFunctionBlockTypes(name)) |
|
1627 |
return blocktypes |
|
1628 |
||
1629 |
# Return Block types checking for recursion |
|
1630 |
def GetBlockResource(self, debug = False): |
|
1631 |
blocktypes = [] |
|
1632 |
for category in BlockTypes[:-1]: |
|
1633 |
for blocktype in category["list"]: |
|
1634 |
if blocktype["type"] == "program": |
|
1635 |
blocktypes.append(blocktype["name"]) |
|
1636 |
project = self.GetProject(debug) |
|
1637 |
if project is not None: |
|
1638 |
blocktypes.extend(project.GetCustomBlockResource()) |
|
1639 |
return blocktypes |
|
1640 |
||
1641 |
# Return Data Types checking for recursion |
|
863
b1ead41fbd3b
Fix bug in VariablePanel 'Type' cell editor menu entry 'User Data Types' containing ConfNodes data types
Laurent Bessard
parents:
853
diff
changeset
|
1642 |
def GetDataTypes(self, tagname = "", basetypes = True, confnodetypes = True, only_locatables = False, debug = False): |
814 | 1643 |
if basetypes: |
1644 |
datatypes = self.GetBaseTypes() |
|
1645 |
else: |
|
1646 |
datatypes = [] |
|
1647 |
project = self.GetProject(debug) |
|
1648 |
if project is not None: |
|
1649 |
name = "" |
|
1650 |
words = tagname.split("::") |
|
1651 |
if words[0] in ["D"]: |
|
1652 |
name = words[1] |
|
1653 |
datatypes.extend([datatype["name"] for datatype in project.GetCustomDataTypes(name, only_locatables)]) |
|
863
b1ead41fbd3b
Fix bug in VariablePanel 'Type' cell editor menu entry 'User Data Types' containing ConfNodes data types
Laurent Bessard
parents:
853
diff
changeset
|
1654 |
if confnodetypes: |
b1ead41fbd3b
Fix bug in VariablePanel 'Type' cell editor menu entry 'User Data Types' containing ConfNodes data types
Laurent Bessard
parents:
853
diff
changeset
|
1655 |
for category in self.GetConfNodeDataTypes(name, only_locatables): |
b1ead41fbd3b
Fix bug in VariablePanel 'Type' cell editor menu entry 'User Data Types' containing ConfNodes data types
Laurent Bessard
parents:
853
diff
changeset
|
1656 |
datatypes.extend(category["list"]) |
814 | 1657 |
return datatypes |
1658 |
||
1659 |
# Return Base Type of given possible derived type |
|
1660 |
def GetBaseType(self, type, debug = False): |
|
1661 |
project = self.GetProject(debug) |
|
1662 |
if project is not None: |
|
1663 |
result = project.GetBaseType(type) |
|
1664 |
if result is not None: |
|
1665 |
return result |
|
1666 |
for confnodetype in self.ConfNodeTypes: |
|
1667 |
result = confnodetype["types"].GetBaseType(type) |
|
1668 |
if result is not None: |
|
1669 |
return result |
|
1670 |
return None |
|
1671 |
||
1672 |
def GetBaseTypes(self): |
|
1673 |
''' |
|
1674 |
return the list of datatypes defined in IEC 61131-3. |
|
1675 |
TypeHierarchy_list has a rough order to it (e.g. SINT, INT, DINT, ...), |
|
1676 |
which makes it easy for a user to find a type in a menu. |
|
1677 |
''' |
|
1678 |
return [x for x,y in TypeHierarchy_list if not x.startswith("ANY")] |
|
1679 |
||
1680 |
def IsOfType(self, type, reference, debug = False): |
|
1681 |
if reference is None: |
|
1682 |
return True |
|
1683 |
elif type == reference: |
|
1684 |
return True |
|
1685 |
elif type in TypeHierarchy: |
|
1686 |
return self.IsOfType(TypeHierarchy[type], reference) |
|
1687 |
else: |
|
1688 |
project = self.GetProject(debug) |
|
1689 |
if project is not None and project.IsOfType(type, reference): |
|
1690 |
return True |
|
1691 |
for confnodetype in self.ConfNodeTypes: |
|
1692 |
if confnodetype["types"].IsOfType(type, reference): |
|
1693 |
return True |
|
1694 |
return False |
|
1695 |
||
1696 |
def IsEndType(self, type): |
|
1697 |
if type is not None: |
|
1698 |
return not type.startswith("ANY") |
|
1699 |
return True |
|
1700 |
||
1701 |
def IsLocatableType(self, type, debug = False): |
|
1702 |
if isinstance(type, TupleType): |
|
1703 |
return False |
|
884
e12228fd8773
Add function block types as data types that are not locatable
Laurent Bessard
parents:
883
diff
changeset
|
1704 |
if self.GetBlockType(type) is not None: |
e12228fd8773
Add function block types as data types that are not locatable
Laurent Bessard
parents:
883
diff
changeset
|
1705 |
return False |
814 | 1706 |
project = self.GetProject(debug) |
1707 |
if project is not None: |
|
1708 |
datatype = project.getdataType(type) |
|
1709 |
if datatype is None: |
|
1710 |
datatype = self.GetConfNodeDataType(type) |
|
1711 |
if datatype is not None: |
|
1712 |
return project.IsLocatableType(datatype) |
|
1713 |
return True |
|
1714 |
||
1715 |
def IsEnumeratedType(self, type, debug = False): |
|
1716 |
project = self.GetProject(debug) |
|
1717 |
if project is not None: |
|
1718 |
datatype = project.getdataType(type) |
|
1719 |
if datatype is None: |
|
1720 |
datatype = self.GetConfNodeDataType(type) |
|
1721 |
if datatype is not None: |
|
1722 |
basetype_content = datatype.baseType.getcontent() |
|
1723 |
return basetype_content["name"] == "enum" |
|
1724 |
return False |
|
1725 |
||
887
d3c6c4ab8b28
Adding support for displaying graphs of debugged numeric variables in 2D and 3D in DebugVariablePanel
Laurent Bessard
parents:
886
diff
changeset
|
1726 |
def IsNumType(self, type, debug = False): |
d3c6c4ab8b28
Adding support for displaying graphs of debugged numeric variables in 2D and 3D in DebugVariablePanel
Laurent Bessard
parents:
886
diff
changeset
|
1727 |
return self.IsOfType(type, "ANY_NUM", debug) or\ |
d3c6c4ab8b28
Adding support for displaying graphs of debugged numeric variables in 2D and 3D in DebugVariablePanel
Laurent Bessard
parents:
886
diff
changeset
|
1728 |
self.IsOfType(type, "ANY_BIT", debug) |
d3c6c4ab8b28
Adding support for displaying graphs of debugged numeric variables in 2D and 3D in DebugVariablePanel
Laurent Bessard
parents:
886
diff
changeset
|
1729 |
|
814 | 1730 |
def GetDataTypeRange(self, type, debug = False): |
1731 |
if type in DataTypeRange: |
|
1732 |
return DataTypeRange[type] |
|
1733 |
else: |
|
1734 |
project = self.GetProject(debug) |
|
1735 |
if project is not None: |
|
1736 |
result = project.GetDataTypeRange(type) |
|
1737 |
if result is not None: |
|
1738 |
return result |
|
1739 |
for confnodetype in self.ConfNodeTypes: |
|
1740 |
result = confnodetype["types"].GetDataTypeRange(type) |
|
1741 |
if result is not None: |
|
1742 |
return result |
|
1743 |
return None |
|
1744 |
||
1745 |
# Return Subrange types |
|
1746 |
def GetSubrangeBaseTypes(self, exclude, debug = False): |
|
1747 |
subrange_basetypes = [] |
|
1748 |
project = self.GetProject(debug) |
|
1749 |
if project is not None: |
|
1750 |
subrange_basetypes.extend(project.GetSubrangeBaseTypes(exclude)) |
|
1751 |
for confnodetype in self.ConfNodeTypes: |
|
1752 |
subrange_basetypes.extend(confnodetype["types"].GetSubrangeBaseTypes(exclude)) |
|
1753 |
return DataTypeRange.keys() + subrange_basetypes |
|
1754 |
||
1755 |
# Return Enumerated Values |
|
1756 |
def GetEnumeratedDataValues(self, type = None, debug = False): |
|
1757 |
values = [] |
|
1758 |
project = self.GetProject(debug) |
|
1759 |
if project is not None: |
|
1760 |
values.extend(project.GetEnumeratedDataTypeValues(type)) |
|
1761 |
if type is None and len(values) > 0: |
|
1762 |
return values |
|
1763 |
for confnodetype in self.ConfNodeTypes: |
|
1764 |
values.extend(confnodetype["types"].GetEnumeratedDataTypeValues(type)) |
|
1765 |
if type is None and len(values) > 0: |
|
1766 |
return values |
|
1767 |
return values |
|
1768 |
||
1769 |
#------------------------------------------------------------------------------- |
|
1770 |
# Project Element tag name computation functions |
|
1771 |
#------------------------------------------------------------------------------- |
|
1772 |
||
1773 |
# Compute a data type name |
|
1774 |
def ComputeDataTypeName(self, datatype): |
|
1775 |
return "D::%s" % datatype |
|
1776 |
||
1777 |
# Compute a pou name |
|
1778 |
def ComputePouName(self, pou): |
|
1779 |
return "P::%s" % pou |
|
1780 |
||
1781 |
# Compute a pou transition name |
|
1782 |
def ComputePouTransitionName(self, pou, transition): |
|
1783 |
return "T::%s::%s" % (pou, transition) |
|
1784 |
||
1785 |
# Compute a pou action name |
|
1786 |
def ComputePouActionName(self, pou, action): |
|
1787 |
return "A::%s::%s" % (pou, action) |
|
1788 |
||
1789 |
# Compute a pou name |
|
1790 |
def ComputeConfigurationName(self, config): |
|
1791 |
return "C::%s" % config |
|
1792 |
||
1793 |
# Compute a pou name |
|
1794 |
def ComputeConfigurationResourceName(self, config, resource): |
|
1795 |
return "R::%s::%s" % (config, resource) |
|
1796 |
||
1797 |
def GetElementType(self, tagname): |
|
1798 |
words = tagname.split("::") |
|
1799 |
return {"D" : ITEM_DATATYPE, "P" : ITEM_POU, |
|
1800 |
"T" : ITEM_TRANSITION, "A" : ITEM_ACTION, |
|
1801 |
"C" : ITEM_CONFIGURATION, "R" : ITEM_RESOURCE}[words[0]] |
|
1802 |
||
1803 |
#------------------------------------------------------------------------------- |
|
1804 |
# Project opened Data types management functions |
|
1805 |
#------------------------------------------------------------------------------- |
|
1806 |
||
1807 |
# Return the data type informations |
|
1808 |
def GetDataTypeInfos(self, tagname, debug = False): |
|
1809 |
project = self.GetProject(debug) |
|
1810 |
if project is not None: |
|
1811 |
words = tagname.split("::") |
|
1812 |
if words[0] == "D": |
|
1813 |
infos = {} |
|
1814 |
datatype = project.getdataType(words[1]) |
|
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1815 |
if datatype is None: |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
1816 |
return None |
814 | 1817 |
basetype_content = datatype.baseType.getcontent() |
1818 |
if basetype_content["value"] is None or basetype_content["name"] in ["string", "wstring"]: |
|
1819 |
infos["type"] = "Directly" |
|
1820 |
infos["base_type"] = basetype_content["name"].upper() |
|
1821 |
elif basetype_content["name"] == "derived": |
|
1822 |
infos["type"] = "Directly" |
|
1823 |
infos["base_type"] = basetype_content["value"].getname() |
|
1824 |
elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]: |
|
1825 |
infos["type"] = "Subrange" |
|
1826 |
infos["min"] = basetype_content["value"].range.getlower() |
|
1827 |
infos["max"] = basetype_content["value"].range.getupper() |
|
1828 |
base_type = basetype_content["value"].baseType.getcontent() |
|
1829 |
if base_type["value"] is None: |
|
1830 |
infos["base_type"] = base_type["name"] |
|
1831 |
else: |
|
1832 |
infos["base_type"] = base_type["value"].getname() |
|
1833 |
elif basetype_content["name"] == "enum": |
|
1834 |
infos["type"] = "Enumerated" |
|
1835 |
infos["values"] = [] |
|
1836 |
for value in basetype_content["value"].values.getvalue(): |
|
1837 |
infos["values"].append(value.getname()) |
|
1838 |
elif basetype_content["name"] == "array": |
|
1839 |
infos["type"] = "Array" |
|
1840 |
infos["dimensions"] = [] |
|
1841 |
for dimension in basetype_content["value"].getdimension(): |
|
1842 |
infos["dimensions"].append((dimension.getlower(), dimension.getupper())) |
|
1843 |
base_type = basetype_content["value"].baseType.getcontent() |
|
1844 |
if base_type["value"] is None or base_type["name"] in ["string", "wstring"]: |
|
1845 |
infos["base_type"] = base_type["name"].upper() |
|
1846 |
else: |
|
1847 |
infos["base_type"] = base_type["value"].getname() |
|
1848 |
elif basetype_content["name"] == "struct": |
|
1849 |
infos["type"] = "Structure" |
|
1850 |
infos["elements"] = [] |
|
1851 |
for element in basetype_content["value"].getvariable(): |
|
1852 |
element_infos = {} |
|
1853 |
element_infos["Name"] = element.getname() |
|
1854 |
element_type = element.type.getcontent() |
|
1855 |
if element_type["value"] is None or element_type["name"] in ["string", "wstring"]: |
|
1856 |
element_infos["Type"] = element_type["name"].upper() |
|
864
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1857 |
elif element_type["name"] == "array": |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1858 |
dimensions = [] |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1859 |
for dimension in element_type["value"].getdimension(): |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1860 |
dimensions.append((dimension.getlower(), dimension.getupper())) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1861 |
base_type = element_type["value"].baseType.getcontent() |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1862 |
if base_type["value"] is None or base_type["name"] in ["string", "wstring"]: |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1863 |
base_type_name = base_type["name"].upper() |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1864 |
else: |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1865 |
base_type_name = base_type["value"].getname() |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1866 |
element_infos["Type"] = ("array", base_type_name, dimensions) |
814 | 1867 |
else: |
1868 |
element_infos["Type"] = element_type["value"].getname() |
|
1869 |
if element.initialValue is not None: |
|
1870 |
element_infos["Initial Value"] = str(element.initialValue.getvalue()) |
|
1871 |
else: |
|
1872 |
element_infos["Initial Value"] = "" |
|
1873 |
infos["elements"].append(element_infos) |
|
1874 |
if datatype.initialValue is not None: |
|
1875 |
infos["initial"] = str(datatype.initialValue.getvalue()) |
|
1876 |
else: |
|
1877 |
infos["initial"] = "" |
|
1878 |
return infos |
|
1879 |
return None |
|
1880 |
||
1881 |
# Change the data type informations |
|
1882 |
def SetDataTypeInfos(self, tagname, infos): |
|
1883 |
words = tagname.split("::") |
|
1884 |
if self.Project is not None and words[0] == "D": |
|
1885 |
datatype = self.Project.getdataType(words[1]) |
|
1886 |
if infos["type"] == "Directly": |
|
1887 |
if infos["base_type"] in self.GetBaseTypes(): |
|
1888 |
if infos["base_type"] == "STRING": |
|
1889 |
datatype.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) |
|
1890 |
elif infos["base_type"] == "WSTRING": |
|
1891 |
datatype.baseType.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()}) |
|
1892 |
else: |
|
1893 |
datatype.baseType.setcontent({"name" : infos["base_type"], "value" : None}) |
|
1894 |
else: |
|
1895 |
derived_datatype = plcopen.derivedTypes_derived() |
|
1896 |
derived_datatype.setname(infos["base_type"]) |
|
1897 |
datatype.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) |
|
1898 |
elif infos["type"] == "Subrange": |
|
1899 |
if infos["base_type"] in GetSubTypes("ANY_UINT"): |
|
1900 |
subrange = plcopen.derivedTypes_subrangeUnsigned() |
|
1901 |
datatype.baseType.setcontent({"name" : "subrangeUnsigned", "value" : subrange}) |
|
1902 |
else: |
|
1903 |
subrange = plcopen.derivedTypes_subrangeSigned() |
|
1904 |
datatype.baseType.setcontent({"name" : "subrangeSigned", "value" : subrange}) |
|
1905 |
subrange.range.setlower(infos["min"]) |
|
1906 |
subrange.range.setupper(infos["max"]) |
|
1907 |
if infos["base_type"] in self.GetBaseTypes(): |
|
1908 |
subrange.baseType.setcontent({"name" : infos["base_type"], "value" : None}) |
|
1909 |
else: |
|
1910 |
derived_datatype = plcopen.derivedTypes_derived() |
|
1911 |
derived_datatype.setname(infos["base_type"]) |
|
1912 |
subrange.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) |
|
1913 |
elif infos["type"] == "Enumerated": |
|
1914 |
enumerated = plcopen.derivedTypes_enum() |
|
1915 |
for i, enum_value in enumerate(infos["values"]): |
|
1916 |
value = plcopen.values_value() |
|
1917 |
value.setname(enum_value) |
|
1918 |
if i == 0: |
|
1919 |
enumerated.values.setvalue([value]) |
|
1920 |
else: |
|
1921 |
enumerated.values.appendvalue(value) |
|
1922 |
datatype.baseType.setcontent({"name" : "enum", "value" : enumerated}) |
|
1923 |
elif infos["type"] == "Array": |
|
1924 |
array = plcopen.derivedTypes_array() |
|
1925 |
for i, dimension in enumerate(infos["dimensions"]): |
|
1926 |
dimension_range = plcopen.rangeSigned() |
|
1927 |
dimension_range.setlower(dimension[0]) |
|
1928 |
dimension_range.setupper(dimension[1]) |
|
1929 |
if i == 0: |
|
1930 |
array.setdimension([dimension_range]) |
|
1931 |
else: |
|
1932 |
array.appenddimension(dimension_range) |
|
1933 |
if infos["base_type"] in self.GetBaseTypes(): |
|
1934 |
if infos["base_type"] == "STRING": |
|
1935 |
array.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) |
|
1936 |
elif infos["base_type"] == "WSTRING": |
|
1937 |
array.baseType.setcontent({"name" : "wstring", "value" : plcopen.wstring()}) |
|
1938 |
else: |
|
1939 |
array.baseType.setcontent({"name" : infos["base_type"], "value" : None}) |
|
1940 |
else: |
|
1941 |
derived_datatype = plcopen.derivedTypes_derived() |
|
1942 |
derived_datatype.setname(infos["base_type"]) |
|
1943 |
array.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) |
|
1944 |
datatype.baseType.setcontent({"name" : "array", "value" : array}) |
|
1945 |
elif infos["type"] == "Structure": |
|
1946 |
struct = plcopen.varListPlain() |
|
1947 |
for i, element_infos in enumerate(infos["elements"]): |
|
1948 |
element = plcopen.varListPlain_variable() |
|
1949 |
element.setname(element_infos["Name"]) |
|
864
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1950 |
if isinstance(element_infos["Type"], TupleType): |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1951 |
if element_infos["Type"][0] == "array": |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1952 |
array_type, base_type_name, dimensions = element_infos["Type"] |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1953 |
array = plcopen.derivedTypes_array() |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1954 |
for j, dimension in enumerate(dimensions): |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1955 |
dimension_range = plcopen.rangeSigned() |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1956 |
dimension_range.setlower(dimension[0]) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1957 |
dimension_range.setupper(dimension[1]) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1958 |
if j == 0: |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1959 |
array.setdimension([dimension_range]) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1960 |
else: |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1961 |
array.appenddimension(dimension_range) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1962 |
if base_type_name in self.GetBaseTypes(): |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1963 |
if base_type_name == "STRING": |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1964 |
array.baseType.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1965 |
elif base_type_name == "WSTRING": |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1966 |
array.baseType.setcontent({"name" : "wstring", "value" : plcopen.wstring()}) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1967 |
else: |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1968 |
array.baseType.setcontent({"name" : base_type_name, "value" : None}) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1969 |
else: |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1970 |
derived_datatype = plcopen.derivedTypes_derived() |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1971 |
derived_datatype.setname(base_type_name) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1972 |
array.baseType.setcontent({"name" : "derived", "value" : derived_datatype}) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1973 |
element.type.setcontent({"name" : "array", "value" : array}) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
863
diff
changeset
|
1974 |
elif element_infos["Type"] in self.GetBaseTypes(): |
814 | 1975 |
if element_infos["Type"] == "STRING": |
1976 |
element.type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) |
|
1977 |
elif element_infos["Type"] == "WSTRING": |
|
1978 |
element.type.setcontent({"name" : "wstring", "value" : plcopen.wstring()}) |
|
1979 |
else: |
|
1980 |
element.type.setcontent({"name" : element_infos["Type"], "value" : None}) |
|
1981 |
else: |
|
1982 |
derived_datatype = plcopen.derivedTypes_derived() |
|
1983 |
derived_datatype.setname(element_infos["Type"]) |
|
1984 |
element.type.setcontent({"name" : "derived", "value" : derived_datatype}) |
|
1985 |
if element_infos["Initial Value"] != "": |
|
1986 |
value = plcopen.value() |
|
1987 |
value.setvalue(element_infos["Initial Value"]) |
|
1988 |
element.setinitialValue(value) |
|
1989 |
if i == 0: |
|
1990 |
struct.setvariable([element]) |
|
1991 |
else: |
|
1992 |
struct.appendvariable(element) |
|
1993 |
datatype.baseType.setcontent({"name" : "struct", "value" : struct}) |
|
1994 |
if infos["initial"] != "": |
|
1995 |
if datatype.initialValue is None: |
|
1996 |
datatype.initialValue = plcopen.value() |
|
1997 |
datatype.initialValue.setvalue(infos["initial"]) |
|
1998 |
else: |
|
1999 |
datatype.initialValue = None |
|
2000 |
self.Project.RefreshDataTypeHierarchy() |
|
2001 |
self.Project.RefreshElementUsingTree() |
|
2002 |
self.BufferProject() |
|
2003 |
||
2004 |
#------------------------------------------------------------------------------- |
|
2005 |
# Project opened Pous management functions |
|
2006 |
#------------------------------------------------------------------------------- |
|
2007 |
||
2008 |
# Return edited element |
|
2009 |
def GetEditedElement(self, tagname, debug = False): |
|
2010 |
project = self.GetProject(debug) |
|
2011 |
if project is not None: |
|
2012 |
words = tagname.split("::") |
|
2013 |
if words[0] == "D": |
|
2014 |
return project.getdataType(words[1]) |
|
2015 |
elif words[0] == "P": |
|
2016 |
return project.getpou(words[1]) |
|
2017 |
elif words[0] in ['T', 'A']: |
|
2018 |
pou = project.getpou(words[1]) |
|
2019 |
if pou is not None: |
|
2020 |
if words[0] == 'T': |
|
2021 |
return pou.gettransition(words[2]) |
|
2022 |
elif words[0] == 'A': |
|
2023 |
return pou.getaction(words[2]) |
|
2024 |
elif words[0] == 'C': |
|
2025 |
return project.getconfiguration(words[1]) |
|
2026 |
elif words[0] == 'R': |
|
2027 |
return project.getconfigurationResource(words[1], words[2]) |
|
2028 |
return None |
|
2029 |
||
2030 |
# Return edited element name |
|
2031 |
def GetEditedElementName(self, tagname): |
|
2032 |
words = tagname.split("::") |
|
2033 |
if words[0] in ["P","C","D"]: |
|
2034 |
return words[1] |
|
2035 |
else: |
|
2036 |
return words[2] |
|
2037 |
return None |
|
2038 |
||
2039 |
# Return edited element name and type |
|
2040 |
def GetEditedElementType(self, tagname, debug = False): |
|
2041 |
words = tagname.split("::") |
|
2042 |
if words[0] in ["P","T","A"]: |
|
2043 |
return words[1], self.GetPouType(words[1], debug) |
|
2044 |
return None, None |
|
2045 |
||
2046 |
# Return language in which edited element is written |
|
2047 |
def GetEditedElementBodyType(self, tagname, debug = False): |
|
2048 |
words = tagname.split("::") |
|
2049 |
if words[0] == "P": |
|
2050 |
return self.GetPouBodyType(words[1], debug) |
|
2051 |
elif words[0] == 'T': |
|
2052 |
return self.GetTransitionBodyType(words[1], words[2], debug) |
|
2053 |
elif words[0] == 'A': |
|
2054 |
return self.GetActionBodyType(words[1], words[2], debug) |
|
2055 |
return None |
|
2056 |
||
2057 |
# Return the edited element variables |
|
2058 |
def GetEditedElementInterfaceVars(self, tagname, debug = False): |
|
2059 |
words = tagname.split("::") |
|
2060 |
if words[0] in ["P","T","A"]: |
|
2061 |
project = self.GetProject(debug) |
|
2062 |
if project is not None: |
|
2063 |
pou = project.getpou(words[1]) |
|
2064 |
if pou is not None: |
|
2065 |
return self.GetPouInterfaceVars(pou, debug) |
|
2066 |
return [] |
|
2067 |
||
2068 |
# Return the edited element return type |
|
2069 |
def GetEditedElementInterfaceReturnType(self, tagname, debug = False): |
|
2070 |
words = tagname.split("::") |
|
2071 |
if words[0] == "P": |
|
2072 |
project = self.GetProject(debug) |
|
2073 |
if project is not None: |
|
2074 |
pou = self.Project.getpou(words[1]) |
|
2075 |
if pou is not None: |
|
2076 |
return self.GetPouInterfaceReturnType(pou) |
|
2077 |
elif words[0] == 'T': |
|
2078 |
return "BOOL" |
|
2079 |
return None |
|
2080 |
||
2081 |
# Change the edited element text |
|
2082 |
def SetEditedElementText(self, tagname, text): |
|
2083 |
if self.Project is not None: |
|
2084 |
element = self.GetEditedElement(tagname) |
|
2085 |
if element is not None: |
|
2086 |
element.settext(text) |
|
2087 |
self.Project.RefreshElementUsingTree() |
|
2088 |
||
2089 |
# Return the edited element text |
|
2090 |
def GetEditedElementText(self, tagname, debug = False): |
|
2091 |
element = self.GetEditedElement(tagname, debug) |
|
2092 |
if element is not None: |
|
2093 |
return element.gettext() |
|
2094 |
return "" |
|
2095 |
||
2096 |
# Return the edited element transitions |
|
2097 |
def GetEditedElementTransitions(self, tagname, debug = False): |
|
2098 |
pou = self.GetEditedElement(tagname, debug) |
|
2099 |
if pou is not None and pou.getbodyType() == "SFC": |
|
2100 |
transitions = [] |
|
2101 |
for transition in pou.gettransitionList(): |
|
2102 |
transitions.append(transition.getname()) |
|
2103 |
return transitions |
|
2104 |
return [] |
|
2105 |
||
2106 |
# Return edited element transitions |
|
2107 |
def GetEditedElementActions(self, tagname, debug = False): |
|
2108 |
pou = self.GetEditedElement(tagname, debug) |
|
2109 |
if pou is not None and pou.getbodyType() == "SFC": |
|
2110 |
actions = [] |
|
2111 |
for action in pou.getactionList(): |
|
2112 |
actions.append(action.getname()) |
|
2113 |
return actions |
|
2114 |
return [] |
|
2115 |
||
2116 |
# Return the names of the pou elements |
|
2117 |
def GetEditedElementVariables(self, tagname, debug = False): |
|
2118 |
words = tagname.split("::") |
|
2119 |
if words[0] in ["P","T","A"]: |
|
1171
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
2120 |
return self.GetProjectPouVariableNames(words[1], debug) |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
2121 |
elif words[0] in ["C", "R"]: |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
2122 |
names = self.GetConfigurationVariableNames(words[1], debug) |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
2123 |
if words[0] == "R": |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
2124 |
names.extend(self.GetConfigurationResourceVariableNames( |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
2125 |
words[1], words[2], debug)) |
a506e4de8f84
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block
Laurent Bessard
parents:
1127
diff
changeset
|
2126 |
return names |
814 | 2127 |
return [] |
2128 |
||
2129 |
def GetEditedElementCopy(self, tagname, debug = False): |
|
2130 |
element = self.GetEditedElement(tagname, debug) |
|
2131 |
if element is not None: |
|
2132 |
name = element.__class__.__name__ |
|
2133 |
return element.generateXMLText(name.split("_")[-1], 0) |
|
2134 |
return "" |
|
2135 |
||
2136 |
def GetEditedElementInstancesCopy(self, tagname, blocks_id = None, wires = None, debug = False): |
|
2137 |
element = self.GetEditedElement(tagname, debug) |
|
2138 |
text = "" |
|
2139 |
if element is not None: |
|
2140 |
wires = dict([(wire, True) for wire in wires if wire[0] in blocks_id and wire[1] in blocks_id]) |
|
2141 |
for id in blocks_id: |
|
2142 |
instance = element.getinstance(id) |
|
2143 |
if instance is not None: |
|
2144 |
instance_copy = self.Copy(instance) |
|
2145 |
instance_copy.filterConnections(wires) |
|
2146 |
name = instance_copy.__class__.__name__ |
|
2147 |
text += instance_copy.generateXMLText(name.split("_")[-1], 0) |
|
2148 |
return text |
|
2149 |
||
1122
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2150 |
def GenerateNewName(self, tagname, name, format, start_idx=0, exclude={}, debug=False): |
814 | 2151 |
names = exclude.copy() |
2152 |
if tagname is not None: |
|
1122
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2153 |
names.update(dict([(varname.upper(), True) |
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2154 |
for varname in self.GetEditedElementVariables(tagname, debug)])) |
1127
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2155 |
words = tagname.split("::") |
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2156 |
if words[0] in ["P","T","A"]: |
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2157 |
element = self.GetEditedElement(tagname, debug) |
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2158 |
if element is not None and element.getbodyType() not in ["ST", "IL"]: |
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2159 |
for instance in element.getinstances(): |
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2160 |
if isinstance(instance, (plcopen.sfcObjects_step, |
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2161 |
plcopen.commonObjects_connector, |
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2162 |
plcopen.commonObjects_continuation)): |
5315f26642e0
Fixed bug when generating new name for configuration and resource variable in VariablePanel
Laurent Bessard
parents:
1122
diff
changeset
|
2163 |
names[instance.getname().upper()] = True |
814 | 2164 |
else: |
2165 |
project = self.GetProject(debug) |
|
2166 |
if project is not None: |
|
2167 |
for datatype in project.getdataTypes(): |
|
2168 |
names[datatype.getname().upper()] = True |
|
2169 |
for pou in project.getpous(): |
|
2170 |
names[pou.getname().upper()] = True |
|
2171 |
for var in self.GetPouInterfaceVars(pou, debug): |
|
2172 |
names[var["Name"].upper()] = True |
|
2173 |
for transition in pou.gettransitionList(): |
|
2174 |
names[transition.getname().upper()] = True |
|
2175 |
for action in pou.getactionList(): |
|
2176 |
names[action.getname().upper()] = True |
|
2177 |
for config in project.getconfigurations(): |
|
2178 |
names[config.getname().upper()] = True |
|
2179 |
for resource in config.getresource(): |
|
2180 |
names[resource.getname().upper()] = True |
|
2181 |
||
1122
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2182 |
i = start_idx |
814 | 2183 |
while name is None or names.get(name.upper(), False): |
2184 |
name = (format%i) |
|
2185 |
i += 1 |
|
2186 |
return name |
|
2187 |
||
2188 |
CheckPasteCompatibility = {"SFC": lambda name: True, |
|
2189 |
"LD": lambda name: not name.startswith("sfcObjects"), |
|
2190 |
"FBD": lambda name: name.startswith("fbdObjects") or name.startswith("commonObjects")} |
|
2191 |
||
2192 |
def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False): |
|
2193 |
element = self.GetEditedElement(tagname, debug) |
|
2194 |
element_name, element_type = self.GetEditedElementType(tagname, debug) |
|
2195 |
if element is not None: |
|
2196 |
bodytype = element.getbodyType() |
|
2197 |
||
2198 |
# Get edited element type scaling |
|
2199 |
scaling = None |
|
2200 |
project = self.GetProject(debug) |
|
2201 |
if project is not None: |
|
2202 |
properties = project.getcontentHeader() |
|
2203 |
scaling = properties["scaling"][bodytype] |
|
2204 |
||
2205 |
# Get ids already by all the instances in edited element |
|
2206 |
used_id = dict([(instance.getlocalId(), True) for instance in element.getinstances()]) |
|
2207 |
new_id = {} |
|
2208 |
||
2209 |
text = "<paste>%s</paste>"%text |
|
2210 |
||
2211 |
try: |
|
1186
0ce4104d58ed
Fixed bug when copy/paste element containing unicode characters
Laurent Bessard
parents:
1171
diff
changeset
|
2212 |
tree = minidom.parseString(text.encode("utf-8")) |
814 | 2213 |
except: |
2214 |
return _("Invalid plcopen element(s)!!!") |
|
2215 |
instances = [] |
|
2216 |
exclude = {} |
|
2217 |
for root in tree.childNodes: |
|
2218 |
if root.nodeType == tree.ELEMENT_NODE and root.nodeName == "paste": |
|
2219 |
for child in root.childNodes: |
|
2220 |
if child.nodeType == tree.ELEMENT_NODE: |
|
2221 |
if not child.nodeName in plcopen.ElementNameToClass: |
|
2222 |
return _("\"%s\" element can't be pasted here!!!")%child.nodeName |
|
2223 |
||
2224 |
classname = plcopen.ElementNameToClass[child.nodeName] |
|
2225 |
if not self.CheckPasteCompatibility[bodytype](classname): |
|
2226 |
return _("\"%s\" element can't be pasted here!!!")%child.nodeName |
|
2227 |
||
2228 |
classobj = getattr(plcopen, classname, None) |
|
2229 |
if classobj is not None: |
|
2230 |
instance = classobj() |
|
2231 |
instance.loadXMLTree(child) |
|
2232 |
if child.nodeName == "block": |
|
2233 |
blockname = instance.getinstanceName() |
|
2234 |
if blockname is not None: |
|
2235 |
blocktype = instance.gettypeName() |
|
2236 |
if element_type == "function": |
|
2237 |
return _("FunctionBlock \"%s\" can't be pasted in a Function!!!")%blocktype |
|
1122
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2238 |
blockname = self.GenerateNewName(tagname, |
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2239 |
blockname, |
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2240 |
"%s%%d"%blocktype, |
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2241 |
debug=debug) |
814 | 2242 |
exclude[blockname] = True |
2243 |
instance.setinstanceName(blockname) |
|
2244 |
self.AddEditedElementPouVar(tagname, blocktype, blockname) |
|
2245 |
elif child.nodeName == "step": |
|
1122
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2246 |
stepname = self.GenerateNewName(tagname, |
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2247 |
instance.getname(), |
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2248 |
"Step%d", |
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2249 |
exclude=exclude, |
84de51ab40d2
Adding support for using current selected variable for generate newly added variable informations in VariablePanel
Laurent Bessard
parents:
1096
diff
changeset
|
2250 |
debug=debug) |
814 | 2251 |
exclude[stepname] = True |
2252 |
instance.setname(stepname) |
|
2253 |
localid = instance.getlocalId() |
|
2254 |
if not used_id.has_key(localid): |
|
2255 |
new_id[localid] = True |
|
2256 |
instances.append((child.nodeName, instance)) |
|
2257 |
||
2258 |
if len(instances) == 0: |
|
2259 |
return _("Invalid plcopen element(s)!!!") |
|
2260 |
||
2261 |
idx = 1 |
|
2262 |
translate_id = {} |
|
2263 |
bbox = plcopen.rect() |
|
2264 |
for name, instance in instances: |
|
2265 |
localId = instance.getlocalId() |
|
2266 |
bbox.union(instance.getBoundingBox()) |
|
2267 |
if used_id.has_key(localId): |
|
2268 |
while used_id.has_key(idx) or new_id.has_key(idx): |
|
2269 |
idx += 1 |
|
2270 |
new_id[idx] = True |
|
2271 |
instance.setlocalId(idx) |
|
2272 |
translate_id[localId] = idx |
|
2273 |
||
2274 |
x, y, width, height = bbox.bounding_box() |
|
2275 |
if middle: |
|
2276 |
new_pos[0] -= width / 2 |
|
2277 |
new_pos[1] -= height / 2 |
|
2278 |
else: |
|
2279 |
new_pos = map(lambda x: x + 30, new_pos) |
|
2280 |
if scaling[0] != 0 and scaling[1] != 0: |
|
2281 |
min_pos = map(lambda x: 30 / x, scaling) |
|
2282 |
minx = round(min_pos[0]) |
|
2283 |
if int(min_pos[0]) == round(min_pos[0]): |
|
2284 |
minx += 1 |
|
2285 |
miny = round(min_pos[1]) |
|
2286 |
if int(min_pos[1]) == round(min_pos[1]): |
|
2287 |
miny += 1 |
|
2288 |
minx *= scaling[0] |
|
2289 |
miny *= scaling[1] |
|
2290 |
new_pos = (max(minx, round(new_pos[0] / scaling[0]) * scaling[0]), |
|
2291 |
max(miny, round(new_pos[1] / scaling[1]) * scaling[1])) |
|
2292 |
else: |
|
2293 |
new_pos = (max(30, new_pos[0]), max(30, new_pos[1])) |
|
2294 |
diff = (new_pos[0] - x, new_pos[1] - y) |
|
2295 |
||
2296 |
connections = {} |
|
2297 |
for name, instance in instances: |
|
2298 |
connections.update(instance.updateConnectionsId(translate_id)) |
|
2299 |
if getattr(instance, "setexecutionOrderId", None) is not None: |
|
2300 |
instance.setexecutionOrderId(0) |
|
2301 |
instance.translate(*diff) |
|
2302 |
element.addinstance(name, instance) |
|
2303 |
||
2304 |
return new_id, connections |
|
2305 |
||
2306 |
# Return the current pou editing informations |
|
2307 |
def GetEditedElementInstanceInfos(self, tagname, id = None, exclude = [], debug = False): |
|
2308 |
infos = {} |
|
2309 |
instance = None |
|
2310 |
element = self.GetEditedElement(tagname, debug) |
|
2311 |
if element is not None: |
|
2312 |
# if id is defined |
|
2313 |
if id is not None: |
|
2314 |
instance = element.getinstance(id) |
|
2315 |
else: |
|
2316 |
instance = element.getrandomInstance(exclude) |
|
2317 |
if instance is not None: |
|
2318 |
infos = instance.getinfos() |
|
2319 |
if infos["type"] in ["input", "output", "inout"]: |
|
2320 |
var_type = self.GetEditedElementVarValueType(tagname, infos["specific_values"]["name"], debug) |
|
2321 |
infos["specific_values"]["value_type"] = var_type |
|
2322 |
return infos |
|
2323 |
return None |
|
2324 |
||
2325 |
def ClearEditedElementExecutionOrder(self, tagname): |
|
2326 |
element = self.GetEditedElement(tagname) |
|
2327 |
if element is not None: |
|
2328 |
element.resetexecutionOrder() |
|
2329 |
||
2330 |
def ResetEditedElementExecutionOrder(self, tagname): |
|
2331 |
element = self.GetEditedElement(tagname) |
|
2332 |
if element is not None: |
|
2333 |
element.compileexecutionOrder() |
|
2334 |
||
2335 |
# Return the variable type of the given pou |
|
2336 |
def GetEditedElementVarValueType(self, tagname, varname, debug = False): |
|
2337 |
project = self.GetProject(debug) |
|
2338 |
if project is not None: |
|
2339 |
words = tagname.split("::") |
|
2340 |
if words[0] in ["P","T","A"]: |
|
2341 |
pou = self.Project.getpou(words[1]) |
|
2342 |
if pou is not None: |
|
2343 |
if words[0] == "T" and varname == words[2]: |
|
2344 |
return "BOOL" |
|
2345 |
if words[1] == varname: |
|
2346 |
return self.GetPouInterfaceReturnType(pou) |
|
2347 |
for type, varlist in pou.getvars(): |
|
2348 |
for var in varlist.getvariable(): |
|
2349 |
if var.getname() == varname: |
|
2350 |
vartype_content = var.gettype().getcontent() |
|
2351 |
if vartype_content["name"] == "derived": |
|
2352 |
return vartype_content["value"].getname() |
|
2353 |
elif vartype_content["name"] in ["string", "wstring"]: |
|
2354 |
return vartype_content["name"].upper() |
|
2355 |
else: |
|
2356 |
return vartype_content["name"] |
|
2357 |
return None |
|
2358 |
||
2359 |
def SetConnectionWires(self, connection, connector): |
|
2360 |
wires = connector.GetWires() |
|
2361 |
idx = 0 |
|
2362 |
for wire, handle in wires: |
|
2363 |
points = wire.GetPoints(handle != 0) |
|
2364 |
if handle == 0: |
|
2365 |
result = wire.GetConnectedInfos(-1) |
|
2366 |
else: |
|
2367 |
result = wire.GetConnectedInfos(0) |
|
2368 |
if result != None: |
|
2369 |
refLocalId, formalParameter = result |
|
2370 |
connections = connection.getconnections() |
|
2371 |
if connections is None or len(connection.getconnections()) <= idx: |
|
2372 |
connection.addconnection() |
|
2373 |
connection.setconnectionId(idx, refLocalId) |
|
2374 |
connection.setconnectionPoints(idx, points) |
|
2375 |
if formalParameter != "": |
|
2376 |
connection.setconnectionParameter(idx, formalParameter) |
|
2377 |
else: |
|
2378 |
connection.setconnectionParameter(idx, None) |
|
2379 |
idx += 1 |
|
2380 |
||
2381 |
def AddEditedElementPouVar(self, tagname, type, name, location="", description=""): |
|
2382 |
if self.Project is not None: |
|
2383 |
words = tagname.split("::") |
|
2384 |
if words[0] in ['P', 'T', 'A']: |
|
2385 |
pou = self.Project.getpou(words[1]) |
|
2386 |
if pou is not None: |
|
2387 |
pou.addpouLocalVar(type, name, location, description) |
|
2388 |
||
2389 |
def AddEditedElementPouExternalVar(self, tagname, type, name): |
|
2390 |
if self.Project is not None: |
|
2391 |
words = tagname.split("::") |
|
2392 |
if words[0] in ['P', 'T', 'A']: |
|
2393 |
pou = self.Project.getpou(words[1]) |
|
2394 |
if pou is not None: |
|
2395 |
pou.addpouExternalVar(type, name) |
|
2396 |
||
2397 |
def ChangeEditedElementPouVar(self, tagname, old_type, old_name, new_type, new_name): |
|
2398 |
if self.Project is not None: |
|
2399 |
words = tagname.split("::") |
|
2400 |
if words[0] in ['P', 'T', 'A']: |
|
2401 |
pou = self.Project.getpou(words[1]) |
|
2402 |
if pou is not None: |
|
2403 |
pou.changepouVar(old_type, old_name, new_type, new_name) |
|
2404 |
||
2405 |
def RemoveEditedElementPouVar(self, tagname, type, name): |
|
2406 |
if self.Project is not None: |
|
2407 |
words = tagname.split("::") |
|
2408 |
if words[0] in ['P', 'T', 'A']: |
|
2409 |
pou = self.Project.getpou(words[1]) |
|
2410 |
if pou is not None: |
|
2411 |
pou.removepouVar(type, name) |
|
2412 |
||
2413 |
def AddEditedElementBlock(self, tagname, id, blocktype, blockname = None): |
|
2414 |
element = self.GetEditedElement(tagname) |
|
2415 |
if element is not None: |
|
2416 |
block = plcopen.fbdObjects_block() |
|
2417 |
block.setlocalId(id) |
|
2418 |
block.settypeName(blocktype) |
|
2419 |
blocktype_infos = self.GetBlockType(blocktype) |
|
2420 |
if blocktype_infos["type"] != "function" and blockname is not None: |
|
2421 |
block.setinstanceName(blockname) |
|
2422 |
self.AddEditedElementPouVar(tagname, blocktype, blockname) |
|
2423 |
element.addinstance("block", block) |
|
2424 |
self.Project.RefreshElementUsingTree() |
|
2425 |
||
2426 |
def SetEditedElementBlockInfos(self, tagname, id, infos): |
|
2427 |
element = self.GetEditedElement(tagname) |
|
2428 |
if element is not None: |
|
2429 |
block = element.getinstance(id) |
|
2430 |
if block is None: |
|
2431 |
return |
|
2432 |
old_name = block.getinstanceName() |
|
2433 |
old_type = block.gettypeName() |
|
2434 |
new_name = infos.get("name", old_name) |
|
2435 |
new_type = infos.get("type", old_type) |
|
2436 |
if new_type != old_type: |
|
2437 |
old_typeinfos = self.GetBlockType(old_type) |
|
2438 |
new_typeinfos = self.GetBlockType(new_type) |
|
2439 |
if old_typeinfos is None or new_typeinfos is None: |
|
2440 |
self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) |
|
2441 |
elif new_typeinfos["type"] != old_typeinfos["type"]: |
|
2442 |
if new_typeinfos["type"] == "function": |
|
2443 |
self.RemoveEditedElementPouVar(tagname, old_type, old_name) |
|
2444 |
else: |
|
2445 |
self.AddEditedElementPouVar(tagname, new_type, new_name) |
|
2446 |
elif new_typeinfos["type"] != "function": |
|
2447 |
self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) |
|
2448 |
elif new_name != old_name: |
|
2449 |
self.ChangeEditedElementPouVar(tagname, old_type, old_name, new_type, new_name) |
|
2450 |
for param, value in infos.items(): |
|
2451 |
if param == "name": |
|
2452 |
block.setinstanceName(value) |
|
2453 |
elif param == "type": |
|
2454 |
block.settypeName(value) |
|
2455 |
elif param == "executionOrder" and block.getexecutionOrderId() != value: |
|
2456 |
element.setelementExecutionOrder(block, value) |
|
2457 |
elif param == "height": |
|
2458 |
block.setheight(value) |
|
2459 |
elif param == "width": |
|
2460 |
block.setwidth(value) |
|
2461 |
elif param == "x": |
|
2462 |
block.setx(value) |
|
2463 |
elif param == "y": |
|
2464 |
block.sety(value) |
|
2465 |
elif param == "connectors": |
|
2466 |
block.inputVariables.setvariable([]) |
|
2467 |
block.outputVariables.setvariable([]) |
|
2468 |
for connector in value["inputs"]: |
|
2469 |
variable = plcopen.inputVariables_variable() |
|
2470 |
variable.setformalParameter(connector.GetName()) |
|
2471 |
if connector.IsNegated(): |
|
2472 |
variable.setnegated(True) |
|
2473 |
if connector.GetEdge() != "none": |
|
2474 |
variable.setedge(connector.GetEdge()) |
|
2475 |
position = connector.GetRelPosition() |
|
2476 |
variable.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2477 |
self.SetConnectionWires(variable.connectionPointIn, connector) |
|
2478 |
block.inputVariables.appendvariable(variable) |
|
2479 |
for connector in value["outputs"]: |
|
2480 |
variable = plcopen.outputVariables_variable() |
|
2481 |
variable.setformalParameter(connector.GetName()) |
|
2482 |
if connector.IsNegated(): |
|
2483 |
variable.setnegated(True) |
|
2484 |
if connector.GetEdge() != "none": |
|
2485 |
variable.setedge(connector.GetEdge()) |
|
2486 |
position = connector.GetRelPosition() |
|
2487 |
variable.addconnectionPointOut() |
|
2488 |
variable.connectionPointOut.setrelPositionXY(position.x, position.y) |
|
2489 |
block.outputVariables.appendvariable(variable) |
|
2490 |
self.Project.RefreshElementUsingTree() |
|
2491 |
||
2492 |
def AddEditedElementVariable(self, tagname, id, type): |
|
2493 |
element = self.GetEditedElement(tagname) |
|
2494 |
if element is not None: |
|
2495 |
if type == INPUT: |
|
2496 |
name = "inVariable" |
|
2497 |
variable = plcopen.fbdObjects_inVariable() |
|
2498 |
elif type == OUTPUT: |
|
2499 |
name = "outVariable" |
|
2500 |
variable = plcopen.fbdObjects_outVariable() |
|
2501 |
elif type == INOUT: |
|
2502 |
name = "inOutVariable" |
|
2503 |
variable = plcopen.fbdObjects_inOutVariable() |
|
2504 |
variable.setlocalId(id) |
|
2505 |
element.addinstance(name, variable) |
|
2506 |
||
2507 |
def SetEditedElementVariableInfos(self, tagname, id, infos): |
|
2508 |
element = self.GetEditedElement(tagname) |
|
2509 |
if element is not None: |
|
2510 |
variable = element.getinstance(id) |
|
2511 |
if variable is None: |
|
2512 |
return |
|
2513 |
for param, value in infos.items(): |
|
2514 |
if param == "name": |
|
2515 |
variable.setexpression(value) |
|
2516 |
elif param == "executionOrder" and variable.getexecutionOrderId() != value: |
|
2517 |
element.setelementExecutionOrder(variable, value) |
|
2518 |
elif param == "height": |
|
2519 |
variable.setheight(value) |
|
2520 |
elif param == "width": |
|
2521 |
variable.setwidth(value) |
|
2522 |
elif param == "x": |
|
2523 |
variable.setx(value) |
|
2524 |
elif param == "y": |
|
2525 |
variable.sety(value) |
|
2526 |
elif param == "connectors": |
|
2527 |
if len(value["outputs"]) > 0: |
|
2528 |
output = value["outputs"][0] |
|
2529 |
if len(value["inputs"]) > 0: |
|
2530 |
variable.setnegatedOut(output.IsNegated()) |
|
2531 |
variable.setedgeOut(output.GetEdge()) |
|
2532 |
else: |
|
2533 |
variable.setnegated(output.IsNegated()) |
|
2534 |
variable.setedge(output.GetEdge()) |
|
2535 |
position = output.GetRelPosition() |
|
2536 |
variable.addconnectionPointOut() |
|
2537 |
variable.connectionPointOut.setrelPositionXY(position.x, position.y) |
|
2538 |
if len(value["inputs"]) > 0: |
|
2539 |
input = value["inputs"][0] |
|
2540 |
if len(value["outputs"]) > 0: |
|
2541 |
variable.setnegatedIn(input.IsNegated()) |
|
2542 |
variable.setedgeIn(input.GetEdge()) |
|
2543 |
else: |
|
2544 |
variable.setnegated(input.IsNegated()) |
|
2545 |
variable.setedge(input.GetEdge()) |
|
2546 |
position = input.GetRelPosition() |
|
2547 |
variable.addconnectionPointIn() |
|
2548 |
variable.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2549 |
self.SetConnectionWires(variable.connectionPointIn, input) |
|
2550 |
||
2551 |
def AddEditedElementConnection(self, tagname, id, type): |
|
2552 |
element = self.GetEditedElement(tagname) |
|
2553 |
if element is not None: |
|
2554 |
if type == CONNECTOR: |
|
2555 |
name = "connector" |
|
2556 |
connection = plcopen.commonObjects_connector() |
|
2557 |
elif type == CONTINUATION: |
|
2558 |
name = "continuation" |
|
2559 |
connection = plcopen.commonObjects_continuation() |
|
2560 |
connection.setlocalId(id) |
|
2561 |
element.addinstance(name, connection) |
|
2562 |
||
2563 |
def SetEditedElementConnectionInfos(self, tagname, id, infos): |
|
2564 |
element = self.GetEditedElement(tagname) |
|
2565 |
if element is not None: |
|
2566 |
connection = element.getinstance(id) |
|
2567 |
if connection is None: |
|
2568 |
return |
|
2569 |
for param, value in infos.items(): |
|
2570 |
if param == "name": |
|
2571 |
connection.setname(value) |
|
2572 |
elif param == "height": |
|
2573 |
connection.setheight(value) |
|
2574 |
elif param == "width": |
|
2575 |
connection.setwidth(value) |
|
2576 |
elif param == "x": |
|
2577 |
connection.setx(value) |
|
2578 |
elif param == "y": |
|
2579 |
connection.sety(value) |
|
2580 |
elif param == "connector": |
|
2581 |
position = value.GetRelPosition() |
|
2582 |
if isinstance(connection, plcopen.commonObjects_continuation): |
|
2583 |
connection.addconnectionPointOut() |
|
2584 |
connection.connectionPointOut.setrelPositionXY(position.x, position.y) |
|
2585 |
elif isinstance(connection, plcopen.commonObjects_connector): |
|
2586 |
connection.addconnectionPointIn() |
|
2587 |
connection.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2588 |
self.SetConnectionWires(connection.connectionPointIn, value) |
|
2589 |
||
2590 |
def AddEditedElementComment(self, tagname, id): |
|
2591 |
element = self.GetEditedElement(tagname) |
|
2592 |
if element is not None: |
|
2593 |
comment = plcopen.commonObjects_comment() |
|
2594 |
comment.setlocalId(id) |
|
2595 |
element.addinstance("comment", comment) |
|
2596 |
||
2597 |
def SetEditedElementCommentInfos(self, tagname, id, infos): |
|
2598 |
element = self.GetEditedElement(tagname) |
|
2599 |
if element is not None: |
|
2600 |
comment = element.getinstance(id) |
|
2601 |
for param, value in infos.items(): |
|
2602 |
if param == "content": |
|
2603 |
comment.setcontentText(value) |
|
2604 |
elif param == "height": |
|
2605 |
comment.setheight(value) |
|
2606 |
elif param == "width": |
|
2607 |
comment.setwidth(value) |
|
2608 |
elif param == "x": |
|
2609 |
comment.setx(value) |
|
2610 |
elif param == "y": |
|
2611 |
comment.sety(value) |
|
2612 |
||
2613 |
def AddEditedElementPowerRail(self, tagname, id, type): |
|
2614 |
element = self.GetEditedElement(tagname) |
|
2615 |
if element is not None: |
|
2616 |
if type == LEFTRAIL: |
|
2617 |
name = "leftPowerRail" |
|
2618 |
powerrail = plcopen.ldObjects_leftPowerRail() |
|
2619 |
elif type == RIGHTRAIL: |
|
2620 |
name = "rightPowerRail" |
|
2621 |
powerrail = plcopen.ldObjects_rightPowerRail() |
|
2622 |
powerrail.setlocalId(id) |
|
2623 |
element.addinstance(name, powerrail) |
|
2624 |
||
2625 |
def SetEditedElementPowerRailInfos(self, tagname, id, infos): |
|
2626 |
element = self.GetEditedElement(tagname) |
|
2627 |
if element is not None: |
|
2628 |
powerrail = element.getinstance(id) |
|
2629 |
if powerrail is None: |
|
2630 |
return |
|
2631 |
for param, value in infos.items(): |
|
2632 |
if param == "height": |
|
2633 |
powerrail.setheight(value) |
|
2634 |
elif param == "width": |
|
2635 |
powerrail.setwidth(value) |
|
2636 |
elif param == "x": |
|
2637 |
powerrail.setx(value) |
|
2638 |
elif param == "y": |
|
2639 |
powerrail.sety(value) |
|
2640 |
elif param == "connectors": |
|
2641 |
if isinstance(powerrail, plcopen.ldObjects_leftPowerRail): |
|
2642 |
powerrail.setconnectionPointOut([]) |
|
2643 |
for connector in value["outputs"]: |
|
2644 |
position = connector.GetRelPosition() |
|
2645 |
connection = plcopen.leftPowerRail_connectionPointOut() |
|
2646 |
connection.setrelPositionXY(position.x, position.y) |
|
2647 |
powerrail.connectionPointOut.append(connection) |
|
2648 |
elif isinstance(powerrail, plcopen.ldObjects_rightPowerRail): |
|
2649 |
powerrail.setconnectionPointIn([]) |
|
2650 |
for connector in value["inputs"]: |
|
2651 |
position = connector.GetRelPosition() |
|
2652 |
connection = plcopen.connectionPointIn() |
|
2653 |
connection.setrelPositionXY(position.x, position.y) |
|
2654 |
self.SetConnectionWires(connection, connector) |
|
2655 |
powerrail.connectionPointIn.append(connection) |
|
2656 |
||
2657 |
def AddEditedElementContact(self, tagname, id): |
|
2658 |
element = self.GetEditedElement(tagname) |
|
2659 |
if element is not None: |
|
2660 |
contact = plcopen.ldObjects_contact() |
|
2661 |
contact.setlocalId(id) |
|
2662 |
element.addinstance("contact", contact) |
|
2663 |
||
2664 |
def SetEditedElementContactInfos(self, tagname, id, infos): |
|
2665 |
element = self.GetEditedElement(tagname) |
|
2666 |
if element is not None: |
|
2667 |
contact = element.getinstance(id) |
|
2668 |
if contact is None: |
|
2669 |
return |
|
2670 |
for param, value in infos.items(): |
|
2671 |
if param == "name": |
|
2672 |
contact.setvariable(value) |
|
2673 |
elif param == "type": |
|
2674 |
if value == CONTACT_NORMAL: |
|
2675 |
contact.setnegated(False) |
|
2676 |
contact.setedge("none") |
|
2677 |
elif value == CONTACT_REVERSE: |
|
2678 |
contact.setnegated(True) |
|
2679 |
contact.setedge("none") |
|
2680 |
elif value == CONTACT_RISING: |
|
2681 |
contact.setnegated(False) |
|
2682 |
contact.setedge("rising") |
|
2683 |
elif value == CONTACT_FALLING: |
|
2684 |
contact.setnegated(False) |
|
2685 |
contact.setedge("falling") |
|
2686 |
elif param == "height": |
|
2687 |
contact.setheight(value) |
|
2688 |
elif param == "width": |
|
2689 |
contact.setwidth(value) |
|
2690 |
elif param == "x": |
|
2691 |
contact.setx(value) |
|
2692 |
elif param == "y": |
|
2693 |
contact.sety(value) |
|
2694 |
elif param == "connectors": |
|
2695 |
input_connector = value["inputs"][0] |
|
2696 |
position = input_connector.GetRelPosition() |
|
2697 |
contact.addconnectionPointIn() |
|
2698 |
contact.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2699 |
self.SetConnectionWires(contact.connectionPointIn, input_connector) |
|
2700 |
output_connector = value["outputs"][0] |
|
2701 |
position = output_connector.GetRelPosition() |
|
2702 |
contact.addconnectionPointOut() |
|
2703 |
contact.connectionPointOut.setrelPositionXY(position.x, position.y) |
|
2704 |
||
2705 |
def AddEditedElementCoil(self, tagname, id): |
|
2706 |
element = self.GetEditedElement(tagname) |
|
2707 |
if element is not None: |
|
2708 |
coil = plcopen.ldObjects_coil() |
|
2709 |
coil.setlocalId(id) |
|
2710 |
element.addinstance("coil", coil) |
|
2711 |
||
2712 |
def SetEditedElementCoilInfos(self, tagname, id, infos): |
|
2713 |
element = self.GetEditedElement(tagname) |
|
2714 |
if element is not None: |
|
2715 |
coil = element.getinstance(id) |
|
2716 |
if coil is None: |
|
2717 |
return |
|
2718 |
for param, value in infos.items(): |
|
2719 |
if param == "name": |
|
2720 |
coil.setvariable(value) |
|
2721 |
elif param == "type": |
|
2722 |
if value == COIL_NORMAL: |
|
2723 |
coil.setnegated(False) |
|
2724 |
coil.setstorage("none") |
|
2725 |
coil.setedge("none") |
|
2726 |
elif value == COIL_REVERSE: |
|
2727 |
coil.setnegated(True) |
|
2728 |
coil.setstorage("none") |
|
2729 |
coil.setedge("none") |
|
2730 |
elif value == COIL_SET: |
|
2731 |
coil.setnegated(False) |
|
2732 |
coil.setstorage("set") |
|
2733 |
coil.setedge("none") |
|
2734 |
elif value == COIL_RESET: |
|
2735 |
coil.setnegated(False) |
|
2736 |
coil.setstorage("reset") |
|
2737 |
coil.setedge("none") |
|
2738 |
elif value == COIL_RISING: |
|
2739 |
coil.setnegated(False) |
|
2740 |
coil.setstorage("none") |
|
2741 |
coil.setedge("rising") |
|
2742 |
elif value == COIL_FALLING: |
|
2743 |
coil.setnegated(False) |
|
2744 |
coil.setstorage("none") |
|
2745 |
coil.setedge("falling") |
|
2746 |
elif param == "height": |
|
2747 |
coil.setheight(value) |
|
2748 |
elif param == "width": |
|
2749 |
coil.setwidth(value) |
|
2750 |
elif param == "x": |
|
2751 |
coil.setx(value) |
|
2752 |
elif param == "y": |
|
2753 |
coil.sety(value) |
|
2754 |
elif param == "connectors": |
|
2755 |
input_connector = value["inputs"][0] |
|
2756 |
position = input_connector.GetRelPosition() |
|
2757 |
coil.addconnectionPointIn() |
|
2758 |
coil.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2759 |
self.SetConnectionWires(coil.connectionPointIn, input_connector) |
|
2760 |
output_connector = value["outputs"][0] |
|
2761 |
position = output_connector.GetRelPosition() |
|
2762 |
coil.addconnectionPointOut() |
|
2763 |
coil.connectionPointOut.setrelPositionXY(position.x, position.y) |
|
2764 |
||
2765 |
def AddEditedElementStep(self, tagname, id): |
|
2766 |
element = self.GetEditedElement(tagname) |
|
2767 |
if element is not None: |
|
2768 |
step = plcopen.sfcObjects_step() |
|
2769 |
step.setlocalId(id) |
|
2770 |
element.addinstance("step", step) |
|
2771 |
||
2772 |
def SetEditedElementStepInfos(self, tagname, id, infos): |
|
2773 |
element = self.GetEditedElement(tagname) |
|
2774 |
if element is not None: |
|
2775 |
step = element.getinstance(id) |
|
2776 |
if step is None: |
|
2777 |
return |
|
2778 |
for param, value in infos.items(): |
|
2779 |
if param == "name": |
|
2780 |
step.setname(value) |
|
2781 |
elif param == "initial": |
|
2782 |
step.setinitialStep(value) |
|
2783 |
elif param == "height": |
|
2784 |
step.setheight(value) |
|
2785 |
elif param == "width": |
|
2786 |
step.setwidth(value) |
|
2787 |
elif param == "x": |
|
2788 |
step.setx(value) |
|
2789 |
elif param == "y": |
|
2790 |
step.sety(value) |
|
2791 |
elif param == "connectors": |
|
2792 |
if len(value["inputs"]) > 0: |
|
2793 |
input_connector = value["inputs"][0] |
|
2794 |
position = input_connector.GetRelPosition() |
|
2795 |
step.addconnectionPointIn() |
|
2796 |
step.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2797 |
self.SetConnectionWires(step.connectionPointIn, input_connector) |
|
2798 |
else: |
|
2799 |
step.deleteconnectionPointIn() |
|
2800 |
if len(value["outputs"]) > 0: |
|
2801 |
output_connector = value["outputs"][0] |
|
2802 |
position = output_connector.GetRelPosition() |
|
2803 |
step.addconnectionPointOut() |
|
2804 |
step.connectionPointOut.setrelPositionXY(position.x, position.y) |
|
2805 |
else: |
|
2806 |
step.deleteconnectionPointOut() |
|
2807 |
elif param == "action": |
|
2808 |
if value: |
|
2809 |
position = value.GetRelPosition() |
|
2810 |
step.addconnectionPointOutAction() |
|
2811 |
step.connectionPointOutAction.setrelPositionXY(position.x, position.y) |
|
2812 |
else: |
|
2813 |
step.deleteconnectionPointOutAction() |
|
2814 |
||
2815 |
def AddEditedElementTransition(self, tagname, id): |
|
2816 |
element = self.GetEditedElement(tagname) |
|
2817 |
if element is not None: |
|
2818 |
transition = plcopen.sfcObjects_transition() |
|
2819 |
transition.setlocalId(id) |
|
2820 |
element.addinstance("transition", transition) |
|
2821 |
||
2822 |
def SetEditedElementTransitionInfos(self, tagname, id, infos): |
|
2823 |
element = self.GetEditedElement(tagname) |
|
2824 |
if element is not None: |
|
2825 |
transition = element.getinstance(id) |
|
2826 |
if transition is None: |
|
2827 |
return |
|
2828 |
for param, value in infos.items(): |
|
2829 |
if param == "type" and value != "connection": |
|
2830 |
transition.setconditionContent(value, infos["condition"]) |
|
2831 |
elif param == "height": |
|
2832 |
transition.setheight(value) |
|
2833 |
elif param == "width": |
|
2834 |
transition.setwidth(value) |
|
2835 |
elif param == "x": |
|
2836 |
transition.setx(value) |
|
2837 |
elif param == "y": |
|
2838 |
transition.sety(value) |
|
2839 |
elif param == "priority": |
|
2840 |
if value != 0: |
|
2841 |
transition.setpriority(value) |
|
2842 |
else: |
|
2843 |
transition.setpriority(None) |
|
2844 |
elif param == "connectors": |
|
2845 |
input_connector = value["inputs"][0] |
|
2846 |
position = input_connector.GetRelPosition() |
|
2847 |
transition.addconnectionPointIn() |
|
2848 |
transition.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2849 |
self.SetConnectionWires(transition.connectionPointIn, input_connector) |
|
2850 |
output_connector = value["outputs"][0] |
|
2851 |
position = output_connector.GetRelPosition() |
|
2852 |
transition.addconnectionPointOut() |
|
2853 |
transition.connectionPointOut.setrelPositionXY(position.x, position.y) |
|
2854 |
elif infos.get("type", None) == "connection" and param == "connection" and value: |
|
2855 |
transition.setconditionContent("connection", None) |
|
2856 |
self.SetConnectionWires(transition.condition.content["value"], value) |
|
2857 |
||
2858 |
def AddEditedElementDivergence(self, tagname, id, type): |
|
2859 |
element = self.GetEditedElement(tagname) |
|
2860 |
if element is not None: |
|
2861 |
if type == SELECTION_DIVERGENCE: |
|
2862 |
name = "selectionDivergence" |
|
2863 |
divergence = plcopen.sfcObjects_selectionDivergence() |
|
2864 |
elif type == SELECTION_CONVERGENCE: |
|
2865 |
name = "selectionConvergence" |
|
2866 |
divergence = plcopen.sfcObjects_selectionConvergence() |
|
2867 |
elif type == SIMULTANEOUS_DIVERGENCE: |
|
2868 |
name = "simultaneousDivergence" |
|
2869 |
divergence = plcopen.sfcObjects_simultaneousDivergence() |
|
2870 |
elif type == SIMULTANEOUS_CONVERGENCE: |
|
2871 |
name = "simultaneousConvergence" |
|
2872 |
divergence = plcopen.sfcObjects_simultaneousConvergence() |
|
2873 |
divergence.setlocalId(id) |
|
2874 |
element.addinstance(name, divergence) |
|
2875 |
||
2876 |
def SetEditedElementDivergenceInfos(self, tagname, id, infos): |
|
2877 |
element = self.GetEditedElement(tagname) |
|
2878 |
if element is not None: |
|
2879 |
divergence = element.getinstance(id) |
|
2880 |
if divergence is None: |
|
2881 |
return |
|
2882 |
for param, value in infos.items(): |
|
2883 |
if param == "height": |
|
2884 |
divergence.setheight(value) |
|
2885 |
elif param == "width": |
|
2886 |
divergence.setwidth(value) |
|
2887 |
elif param == "x": |
|
2888 |
divergence.setx(value) |
|
2889 |
elif param == "y": |
|
2890 |
divergence.sety(value) |
|
2891 |
elif param == "connectors": |
|
2892 |
input_connectors = value["inputs"] |
|
2893 |
if isinstance(divergence, (plcopen.sfcObjects_selectionDivergence, plcopen.sfcObjects_simultaneousDivergence)): |
|
2894 |
position = input_connectors[0].GetRelPosition() |
|
2895 |
divergence.addconnectionPointIn() |
|
2896 |
divergence.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2897 |
self.SetConnectionWires(divergence.connectionPointIn, input_connectors[0]) |
|
2898 |
else: |
|
2899 |
divergence.setconnectionPointIn([]) |
|
2900 |
for input_connector in input_connectors: |
|
2901 |
position = input_connector.GetRelPosition() |
|
2902 |
if isinstance(divergence, plcopen.sfcObjects_selectionConvergence): |
|
2903 |
connection = plcopen.selectionConvergence_connectionPointIn() |
|
2904 |
else: |
|
2905 |
connection = plcopen.connectionPointIn() |
|
2906 |
connection.setrelPositionXY(position.x, position.y) |
|
2907 |
self.SetConnectionWires(connection, input_connector) |
|
2908 |
divergence.appendconnectionPointIn(connection) |
|
2909 |
output_connectors = value["outputs"] |
|
2910 |
if isinstance(divergence, (plcopen.sfcObjects_selectionConvergence, plcopen.sfcObjects_simultaneousConvergence)): |
|
2911 |
position = output_connectors[0].GetRelPosition() |
|
2912 |
divergence.addconnectionPointOut() |
|
2913 |
divergence.connectionPointOut.setrelPositionXY(position.x, position.y) |
|
2914 |
else: |
|
2915 |
divergence.setconnectionPointOut([]) |
|
2916 |
for output_connector in output_connectors: |
|
2917 |
position = output_connector.GetRelPosition() |
|
2918 |
if isinstance(divergence, plcopen.sfcObjects_selectionDivergence): |
|
2919 |
connection = plcopen.selectionDivergence_connectionPointOut() |
|
2920 |
else: |
|
2921 |
connection = plcopen.simultaneousDivergence_connectionPointOut() |
|
2922 |
connection.setrelPositionXY(position.x, position.y) |
|
2923 |
divergence.appendconnectionPointOut(connection) |
|
2924 |
||
2925 |
def AddEditedElementJump(self, tagname, id): |
|
2926 |
element = self.GetEditedElement(tagname) |
|
2927 |
if element is not None: |
|
2928 |
jump = plcopen.sfcObjects_jumpStep() |
|
2929 |
jump.setlocalId(id) |
|
2930 |
element.addinstance("jumpStep", jump) |
|
2931 |
||
2932 |
def SetEditedElementJumpInfos(self, tagname, id, infos): |
|
2933 |
element = self.GetEditedElement(tagname) |
|
2934 |
if element is not None: |
|
2935 |
jump = element.getinstance(id) |
|
2936 |
if jump is None: |
|
2937 |
return |
|
2938 |
for param, value in infos.items(): |
|
2939 |
if param == "target": |
|
2940 |
jump.settargetName(value) |
|
2941 |
elif param == "height": |
|
2942 |
jump.setheight(value) |
|
2943 |
elif param == "width": |
|
2944 |
jump.setwidth(value) |
|
2945 |
elif param == "x": |
|
2946 |
jump.setx(value) |
|
2947 |
elif param == "y": |
|
2948 |
jump.sety(value) |
|
2949 |
elif param == "connector": |
|
2950 |
position = value.GetRelPosition() |
|
2951 |
jump.addconnectionPointIn() |
|
2952 |
jump.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2953 |
self.SetConnectionWires(jump.connectionPointIn, value) |
|
2954 |
||
2955 |
def AddEditedElementActionBlock(self, tagname, id): |
|
2956 |
element = self.GetEditedElement(tagname) |
|
2957 |
if element is not None: |
|
2958 |
actionBlock = plcopen.commonObjects_actionBlock() |
|
2959 |
actionBlock.setlocalId(id) |
|
2960 |
element.addinstance("actionBlock", actionBlock) |
|
2961 |
||
2962 |
def SetEditedElementActionBlockInfos(self, tagname, id, infos): |
|
2963 |
element = self.GetEditedElement(tagname) |
|
2964 |
if element is not None: |
|
2965 |
actionBlock = element.getinstance(id) |
|
2966 |
if actionBlock is None: |
|
2967 |
return |
|
2968 |
for param, value in infos.items(): |
|
2969 |
if param == "actions": |
|
2970 |
actionBlock.setactions(value) |
|
2971 |
elif param == "height": |
|
2972 |
actionBlock.setheight(value) |
|
2973 |
elif param == "width": |
|
2974 |
actionBlock.setwidth(value) |
|
2975 |
elif param == "x": |
|
2976 |
actionBlock.setx(value) |
|
2977 |
elif param == "y": |
|
2978 |
actionBlock.sety(value) |
|
2979 |
elif param == "connector": |
|
2980 |
position = value.GetRelPosition() |
|
2981 |
actionBlock.addconnectionPointIn() |
|
2982 |
actionBlock.connectionPointIn.setrelPositionXY(position.x, position.y) |
|
2983 |
self.SetConnectionWires(actionBlock.connectionPointIn, value) |
|
2984 |
||
2985 |
def RemoveEditedElementInstance(self, tagname, id): |
|
2986 |
element = self.GetEditedElement(tagname) |
|
2987 |
if element is not None: |
|
2988 |
instance = element.getinstance(id) |
|
2989 |
if isinstance(instance, plcopen.fbdObjects_block): |
|
2990 |
self.RemoveEditedElementPouVar(tagname, instance.gettypeName(), instance.getinstanceName()) |
|
2991 |
element.removeinstance(id) |
|
2992 |
self.Project.RefreshElementUsingTree() |
|
2993 |
||
2994 |
def GetEditedResourceVariables(self, tagname, debug = False): |
|
2995 |
varlist = [] |
|
2996 |
words = tagname.split("::") |
|
2997 |
for var in self.GetConfigurationGlobalVars(words[1], debug): |
|
2998 |
if var["Type"] == "BOOL": |
|
2999 |
varlist.append(var["Name"]) |
|
3000 |
for var in self.GetConfigurationResourceGlobalVars(words[1], words[2], debug): |
|
3001 |
if var["Type"] == "BOOL": |
|
3002 |
varlist.append(var["Name"]) |
|
3003 |
return varlist |
|
3004 |
||
3005 |
def SetEditedResourceInfos(self, tagname, tasks, instances): |
|
3006 |
resource = self.GetEditedElement(tagname) |
|
3007 |
if resource is not None: |
|
3008 |
resource.settask([]) |
|
3009 |
resource.setpouInstance([]) |
|
3010 |
task_list = {} |
|
3011 |
for task in tasks: |
|
3012 |
new_task = plcopen.resource_task() |
|
3013 |
new_task.setname(task["Name"]) |
|
3014 |
if task["Triggering"] == "Interrupt": |
|
3015 |
new_task.setsingle(task["Single"]) |
|
3016 |
## result = duration_model.match(task["Interval"]).groups() |
|
3017 |
## if reduce(lambda x, y: x or y != None, result): |
|
3018 |
## values = [] |
|
3019 |
## for value in result[:-1]: |
|
3020 |
## if value != None: |
|
3021 |
## values.append(int(value)) |
|
3022 |
## else: |
|
3023 |
## values.append(0) |
|
3024 |
## if result[-1] is not None: |
|
3025 |
## values.append(int(float(result[-1]) * 1000)) |
|
3026 |
## new_task.setinterval(datetime.time(*values)) |
|
3027 |
if task["Triggering"] == "Cyclic": |
|
3028 |
new_task.setinterval(task["Interval"]) |
|
3029 |
new_task.setpriority(int(task["Priority"])) |
|
3030 |
if task["Name"] != "": |
|
3031 |
task_list[task["Name"]] = new_task |
|
3032 |
resource.appendtask(new_task) |
|
3033 |
for instance in instances: |
|
3034 |
new_instance = plcopen.pouInstance() |
|
3035 |
new_instance.setname(instance["Name"]) |
|
3036 |
new_instance.settypeName(instance["Type"]) |
|
3037 |
task_list.get(instance["Task"], resource).appendpouInstance(new_instance) |
|
3038 |
||
3039 |
def GetEditedResourceInfos(self, tagname, debug = False): |
|
3040 |
resource = self.GetEditedElement(tagname, debug) |
|
3041 |
if resource is not None: |
|
3042 |
tasks = resource.gettask() |
|
3043 |
instances = resource.getpouInstance() |
|
3044 |
tasks_data = [] |
|
3045 |
instances_data = [] |
|
3046 |
for task in tasks: |
|
3047 |
new_task = {} |
|
3048 |
new_task["Name"] = task.getname() |
|
3049 |
single = task.getsingle() |
|
3050 |
if single is not None: |
|
3051 |
new_task["Single"] = single |
|
3052 |
else: |
|
3053 |
new_task["Single"] = "" |
|
3054 |
interval = task.getinterval() |
|
3055 |
if interval is not None: |
|
3056 |
## text = "" |
|
3057 |
## if interval.hour != 0: |
|
3058 |
## text += "%dh"%interval.hour |
|
3059 |
## if interval.minute != 0: |
|
3060 |
## text += "%dm"%interval.minute |
|
3061 |
## if interval.second != 0: |
|
3062 |
## text += "%ds"%interval.second |
|
3063 |
## if interval.microsecond != 0: |
|
3064 |
## if interval.microsecond % 1000 != 0: |
|
3065 |
## text += "%.3fms"%(float(interval.microsecond) / 1000) |
|
3066 |
## else: |
|
3067 |
## text += "%dms"%(interval.microsecond / 1000) |
|
3068 |
## new_task["Interval"] = text |
|
3069 |
new_task["Interval"] = interval |
|
3070 |
else: |
|
3071 |
new_task["Interval"] = "" |
|
3072 |
if single is not None and interval is None: |
|
3073 |
new_task["Triggering"] = "Interrupt" |
|
3074 |
elif interval is not None and single is None: |
|
3075 |
new_task["Triggering"] = "Cyclic" |
|
3076 |
else: |
|
3077 |
new_task["Triggering"] = "" |
|
3078 |
new_task["Priority"] = str(task.getpriority()) |
|
3079 |
tasks_data.append(new_task) |
|
3080 |
for instance in task.getpouInstance(): |
|
3081 |
new_instance = {} |
|
3082 |
new_instance["Name"] = instance.getname() |
|
3083 |
new_instance["Type"] = instance.gettypeName() |
|
3084 |
new_instance["Task"] = task.getname() |
|
3085 |
instances_data.append(new_instance) |
|
3086 |
for instance in instances: |
|
3087 |
new_instance = {} |
|
3088 |
new_instance["Name"] = instance.getname() |
|
3089 |
new_instance["Type"] = instance.gettypeName() |
|
3090 |
new_instance["Task"] = "" |
|
3091 |
instances_data.append(new_instance) |
|
3092 |
return tasks_data, instances_data |
|
3093 |
||
3094 |
def OpenXMLFile(self, filepath): |
|
3095 |
xmlfile = open(filepath, 'r') |
|
3096 |
tree = minidom.parse(xmlfile) |
|
3097 |
xmlfile.close() |
|
3098 |
||
3099 |
self.Project = plcopen.project() |
|
3100 |
for child in tree.childNodes: |
|
3101 |
if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "project": |
|
3102 |
try: |
|
3103 |
result = self.Project.loadXMLTree(child) |
|
3104 |
except ValueError, e: |
|
3105 |
return _("Project file syntax error:\n\n") + str(e) |
|
3106 |
self.SetFilePath(filepath) |
|
3107 |
self.Project.RefreshElementUsingTree() |
|
3108 |
self.Project.RefreshDataTypeHierarchy() |
|
3109 |
self.Project.RefreshCustomBlockTypes() |
|
3110 |
self.CreateProjectBuffer(True) |
|
3111 |
self.ProgramChunks = [] |
|
3112 |
self.ProgramOffset = 0 |
|
3113 |
self.NextCompiledProject = self.Copy(self.Project) |
|
3114 |
self.CurrentCompiledProject = None |
|
3115 |
self.Buffering = False |
|
3116 |
self.CurrentElementEditing = None |
|
3117 |
return None |
|
3118 |
return _("No PLC project found") |
|
3119 |
||
3120 |
def SaveXMLFile(self, filepath = None): |
|
3121 |
if not filepath and self.FilePath == "": |
|
3122 |
return False |
|
3123 |
else: |
|
3124 |
contentheader = {"modificationDateTime": datetime.datetime(*localtime()[:6])} |
|
3125 |
self.Project.setcontentHeader(contentheader) |
|
3126 |
||
3127 |
text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
|
3128 |
extras = {"xmlns" : "http://www.plcopen.org/xml/tc6.xsd", |
|
3129 |
"xmlns:xhtml" : "http://www.w3.org/1999/xhtml", |
|
3130 |
"xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance", |
|
3131 |
"xsi:schemaLocation" : "http://www.plcopen.org/xml/tc6.xsd"} |
|
3132 |
text += self.Project.generateXMLText("project", 0, extras) |
|
3133 |
||
3134 |
if filepath: |
|
3135 |
xmlfile = open(filepath,"w") |
|
3136 |
else: |
|
3137 |
xmlfile = open(self.FilePath,"w") |
|
3138 |
xmlfile.write(text.encode("utf-8")) |
|
3139 |
xmlfile.close() |
|
3140 |
self.MarkProjectAsSaved() |
|
3141 |
if filepath: |
|
3142 |
self.SetFilePath(filepath) |
|
3143 |
return True |
|
3144 |
||
3145 |
#------------------------------------------------------------------------------- |
|
3146 |
# Search in Current Project Functions |
|
3147 |
#------------------------------------------------------------------------------- |
|
3148 |
||
3149 |
def SearchInProject(self, criteria): |
|
3150 |
return self.Project.Search(criteria) |
|
3151 |
||
3152 |
def SearchInPou(self, tagname, criteria, debug=False): |
|
3153 |
pou = self.GetEditedElement(tagname, debug) |
|
3154 |
if pou is not None: |
|
3155 |
return pou.Search(criteria) |
|
3156 |
return [] |
|
3157 |
||
3158 |
#------------------------------------------------------------------------------- |
|
3159 |
# Current Buffering Management Functions |
|
3160 |
#------------------------------------------------------------------------------- |
|
3161 |
||
3162 |
""" |
|
3163 |
Return a copy of the project |
|
3164 |
""" |
|
3165 |
def Copy(self, model): |
|
3166 |
return cPickle.loads(cPickle.dumps(model)) |
|
3167 |
||
3168 |
def CreateProjectBuffer(self, saved): |
|
3169 |
if self.ProjectBufferEnabled: |
|
3170 |
self.ProjectBuffer = UndoBuffer(cPickle.dumps(self.Project), saved) |
|
3171 |
else: |
|
3172 |
self.ProjectBuffer = None |
|
3173 |
self.ProjectSaved = saved |
|
3174 |
||
3175 |
def IsProjectBufferEnabled(self): |
|
3176 |
return self.ProjectBufferEnabled |
|
3177 |
||
3178 |
def EnableProjectBuffer(self, enable): |
|
3179 |
self.ProjectBufferEnabled = enable |
|
3180 |
if self.Project is not None: |
|
3181 |
if enable: |
|
3182 |
current_saved = self.ProjectSaved |
|
3183 |
else: |
|
3184 |
current_saved = self.ProjectBuffer.IsCurrentSaved() |
|
3185 |
self.CreateProjectBuffer(current_saved) |
|
3186 |
||
3187 |
def BufferProject(self): |
|
3188 |
if self.ProjectBuffer is not None: |
|
3189 |
self.ProjectBuffer.Buffering(cPickle.dumps(self.Project)) |
|
3190 |
else: |
|
3191 |
self.ProjectSaved = False |
|
3192 |
||
3193 |
def StartBuffering(self): |
|
3194 |
if self.ProjectBuffer is not None: |
|
3195 |
self.Buffering = True |
|
3196 |
else: |
|
3197 |
self.ProjectSaved = False |
|
3198 |
||
3199 |
def EndBuffering(self): |
|
3200 |
if self.ProjectBuffer is not None and self.Buffering: |
|
3201 |
self.ProjectBuffer.Buffering(cPickle.dumps(self.Project)) |
|
3202 |
self.Buffering = False |
|
3203 |
||
3204 |
def MarkProjectAsSaved(self): |
|
3205 |
self.EndBuffering() |
|
3206 |
if self.ProjectBuffer is not None: |
|
3207 |
self.ProjectBuffer.CurrentSaved() |
|
3208 |
else: |
|
3209 |
self.ProjectSaved = True |
|
3210 |
||
3211 |
# Return if project is saved |
|
3212 |
def ProjectIsSaved(self): |
|
3213 |
if self.ProjectBuffer is not None: |
|
3214 |
return self.ProjectBuffer.IsCurrentSaved() and not self.Buffering |
|
3215 |
else: |
|
3216 |
return self.ProjectSaved |
|
3217 |
||
3218 |
def LoadPrevious(self): |
|
3219 |
self.EndBuffering() |
|
3220 |
if self.ProjectBuffer is not None: |
|
3221 |
self.Project = cPickle.loads(self.ProjectBuffer.Previous()) |
|
3222 |
||
3223 |
def LoadNext(self): |
|
3224 |
if self.ProjectBuffer is not None: |
|
3225 |
self.Project = cPickle.loads(self.ProjectBuffer.Next()) |
|
3226 |
||
3227 |
def GetBufferState(self): |
|
3228 |
if self.ProjectBuffer is not None: |
|
3229 |
first = self.ProjectBuffer.IsFirst() and not self.Buffering |
|
3230 |
last = self.ProjectBuffer.IsLast() |
|
3231 |
return not first, not last |
|
3232 |
return False, False |