PLCControler.py
changeset 1411 805d13d216c0
parent 1406 82db84fe88ea
child 1418 c97dc5281419
equal deleted inserted replaced
1410:0d34b69cc9b5 1411:805d13d216c0
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     2 # -*- coding: utf-8 -*-
     3 
     3 
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     5 #based on the plcopen standard. 
     5 #based on the plcopen standard.
     6 #
     6 #
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     8 #
     8 #
     9 #See COPYING file for copyrights details.
     9 #See COPYING file for copyrights details.
    10 #
    10 #
    55                     ITEM_ACTIONS,
    55                     ITEM_ACTIONS,
    56                     ITEM_CONFIGURATIONS,
    56                     ITEM_CONFIGURATIONS,
    57                     ITEM_RESOURCES,
    57                     ITEM_RESOURCES,
    58                     ITEM_PROPERTIES
    58                     ITEM_PROPERTIES
    59                    ] = range(8, 17)
    59                    ] = range(8, 17)
    60  
    60 
    61 ITEMS_VARIABLE = [ITEM_VAR_LOCAL,
    61 ITEMS_VARIABLE = [ITEM_VAR_LOCAL,
    62                   ITEM_VAR_GLOBAL,
    62                   ITEM_VAR_GLOBAL,
    63                   ITEM_VAR_EXTERNAL,
    63                   ITEM_VAR_EXTERNAL,
    64                   ITEM_VAR_TEMP,
    64                   ITEM_VAR_TEMP,
    65                   ITEM_VAR_INPUT,
    65                   ITEM_VAR_INPUT,
    90 
    90 
    91 ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
    91 ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
    92 
    92 
    93 def GetUneditableNames():
    93 def GetUneditableNames():
    94     _ = lambda x:x
    94     _ = lambda x:x
    95     return [_("User-defined POUs"), _("Functions"), _("Function Blocks"), 
    95     return [_("User-defined POUs"), _("Functions"), _("Function Blocks"),
    96             _("Programs"), _("Data Types"), _("Transitions"), _("Actions"), 
    96             _("Programs"), _("Data Types"), _("Transitions"), _("Actions"),
    97             _("Configurations"), _("Resources"), _("Properties")]
    97             _("Configurations"), _("Resources"), _("Properties")]
    98 UNEDITABLE_NAMES = GetUneditableNames()
    98 UNEDITABLE_NAMES = GetUneditableNames()
    99 [USER_DEFINED_POUS, FUNCTIONS, FUNCTION_BLOCKS, PROGRAMS, 
    99 [USER_DEFINED_POUS, FUNCTIONS, FUNCTION_BLOCKS, PROGRAMS,
   100  DATA_TYPES, TRANSITIONS, ACTIONS, CONFIGURATIONS, 
   100  DATA_TYPES, TRANSITIONS, ACTIONS, CONFIGURATIONS,
   101  RESOURCES, PROPERTIES] = UNEDITABLE_NAMES
   101  RESOURCES, PROPERTIES] = UNEDITABLE_NAMES
   102 
   102 
   103 #-------------------------------------------------------------------------------
   103 #-------------------------------------------------------------------------------
   104 #                 Helper object for loading library in xslt stylesheets
   104 #                 Helper object for loading library in xslt stylesheets
   105 #-------------------------------------------------------------------------------
   105 #-------------------------------------------------------------------------------
   131 
   131 
   132 _StringValue = lambda x: x
   132 _StringValue = lambda x: x
   133 _BoolValue = lambda x: x in ["true", "0"]
   133 _BoolValue = lambda x: x in ["true", "0"]
   134 
   134 
   135 def _translate_args(translations, args):
   135 def _translate_args(translations, args):
   136     return [translate(arg[0]) if len(arg) > 0 else None 
   136     return [translate(arg[0]) if len(arg) > 0 else None
   137             for translate, arg in
   137             for translate, arg in
   138             zip(translations, args)]
   138             zip(translations, args)]
   139 
   139 
   140 #-------------------------------------------------------------------------------
   140 #-------------------------------------------------------------------------------
   141 #                 Helpers object for generating pou var list
   141 #                 Helpers object for generating pou var list
   142 #-------------------------------------------------------------------------------
   142 #-------------------------------------------------------------------------------
   143 
   143 
   144 class _VariableInfos(object):
   144 class _VariableInfos(object):
   145     __slots__ = ["Name", "Class", "Option", "Location", "InitialValue", 
   145     __slots__ = ["Name", "Class", "Option", "Location", "InitialValue",
   146                  "Edit", "Documentation", "Type", "Tree", "Number"]
   146                  "Edit", "Documentation", "Type", "Tree", "Number"]
   147     def __init__(self, *args):
   147     def __init__(self, *args):
   148         for attr, value in zip(self.__slots__, args):
   148         for attr, value in zip(self.__slots__, args):
   149             setattr(self, attr, value if value is not None else "")
   149             setattr(self, attr, value if value is not None else "")
   150     def copy(self):
   150     def copy(self):
   151         return _VariableInfos(*[getattr(self, attr) for attr in self.__slots__])
   151         return _VariableInfos(*[getattr(self, attr) for attr in self.__slots__])
   152 
   152 
   153 class VariablesInfosFactory:
   153 class VariablesInfosFactory:
   154     
   154 
   155     def __init__(self, variables):
   155     def __init__(self, variables):
   156         self.Variables = variables
   156         self.Variables = variables
   157         self.TreeStack = []
   157         self.TreeStack = []
   158         self.Type = None
   158         self.Type = None
   159         self.Dimensions = None
   159         self.Dimensions = None
   160     
   160 
   161     def SetType(self, context, *args):
   161     def SetType(self, context, *args):
   162         self.Type = args[0][0]
   162         self.Type = args[0][0]
   163         
   163 
   164     def GetType(self):
   164     def GetType(self):
   165         if len(self.Dimensions) > 0:
   165         if len(self.Dimensions) > 0:
   166             return ("array", self.Type, self.Dimensions)
   166             return ("array", self.Type, self.Dimensions)
   167         return self.Type
   167         return self.Type
   168     
   168 
   169     def GetTree(self):
   169     def GetTree(self):
   170         return (self.TreeStack.pop(-1), self.Dimensions)
   170         return (self.TreeStack.pop(-1), self.Dimensions)
   171     
   171 
   172     def AddDimension(self, context, *args):
   172     def AddDimension(self, context, *args):
   173         self.Dimensions.append(tuple(
   173         self.Dimensions.append(tuple(
   174             _translate_args([_StringValue] * 2, args)))
   174             _translate_args([_StringValue] * 2, args)))
   175     
   175 
   176     def AddTree(self, context, *args):
   176     def AddTree(self, context, *args):
   177         self.TreeStack.append([])
   177         self.TreeStack.append([])
   178         self.Dimensions = []
   178         self.Dimensions = []
   179     
   179 
   180     def AddVarToTree(self, context, *args):
   180     def AddVarToTree(self, context, *args):
   181         var = (args[0][0], self.Type, self.GetTree())
   181         var = (args[0][0], self.Type, self.GetTree())
   182         self.TreeStack[-1].append(var)
   182         self.TreeStack[-1].append(var)
   183     
   183 
   184     def AddVariable(self, context, *args):
   184     def AddVariable(self, context, *args):
   185         self.Variables.append(_VariableInfos(*(_translate_args(
   185         self.Variables.append(_VariableInfos(*(_translate_args(
   186             [_StringValue] * 5 + [_BoolValue] + [_StringValue], args) + 
   186             [_StringValue] * 5 + [_BoolValue] + [_StringValue], args) +
   187             [self.GetType(), self.GetTree()])))
   187             [self.GetType(), self.GetTree()])))
   188 
   188 
   189 #-------------------------------------------------------------------------------
   189 #-------------------------------------------------------------------------------
   190 #            Helpers object for generating pou variable instance list
   190 #            Helpers object for generating pou variable instance list
   191 #-------------------------------------------------------------------------------
   191 #-------------------------------------------------------------------------------
   197         "action": ITEM_ACTION,
   197         "action": ITEM_ACTION,
   198         "transition": ITEM_TRANSITION,
   198         "transition": ITEM_TRANSITION,
   199         "program": ITEM_PROGRAM}.get(value)
   199         "program": ITEM_PROGRAM}.get(value)
   200     if class_type is not None:
   200     if class_type is not None:
   201         return class_type
   201         return class_type
   202     
   202 
   203     pou_type = POU_TYPES.get(value)
   203     pou_type = POU_TYPES.get(value)
   204     if pou_type is not None:
   204     if pou_type is not None:
   205         return pou_type
   205         return pou_type
   206     
   206 
   207     var_type = VAR_CLASS_INFOS.get(value)
   207     var_type = VAR_CLASS_INFOS.get(value)
   208     if var_type is not None:
   208     if var_type is not None:
   209         return var_type[1]
   209         return var_type[1]
   210     
   210 
   211     return None
   211     return None
   212 
   212 
   213 class _VariablesTreeItemInfos(object):
   213 class _VariablesTreeItemInfos(object):
   214     __slots__ = ["name", "var_class", "type", "edit", "debug", "variables"]
   214     __slots__ = ["name", "var_class", "type", "edit", "debug", "variables"]
   215     def __init__(self, *args):
   215     def __init__(self, *args):
   217             setattr(self, attr, value if value is not None else "")
   217             setattr(self, attr, value if value is not None else "")
   218     def copy(self):
   218     def copy(self):
   219         return _VariableTreeItem(*[getattr(self, attr) for attr in self.__slots__])
   219         return _VariableTreeItem(*[getattr(self, attr) for attr in self.__slots__])
   220 
   220 
   221 class VariablesTreeInfosFactory:
   221 class VariablesTreeInfosFactory:
   222     
   222 
   223     def __init__(self):
   223     def __init__(self):
   224         self.Root = None
   224         self.Root = None
   225     
   225 
   226     def GetRoot(self):
   226     def GetRoot(self):
   227         return self.Root
   227         return self.Root
   228     
   228 
   229     def SetRoot(self, context, *args):
   229     def SetRoot(self, context, *args):
   230         self.Root = _VariablesTreeItemInfos(
   230         self.Root = _VariablesTreeItemInfos(
   231             *([''] + _translate_args(
   231             *([''] + _translate_args(
   232                 [class_extraction, _StringValue] + [_BoolValue] * 2, 
   232                 [class_extraction, _StringValue] + [_BoolValue] * 2,
   233                 args) + [[]]))
   233                 args) + [[]]))
   234 
   234 
   235     def AddVariable(self, context, *args):
   235     def AddVariable(self, context, *args):
   236         if self.Root is not None:
   236         if self.Root is not None:
   237             self.Root.variables.append(_VariablesTreeItemInfos(
   237             self.Root.variables.append(_VariablesTreeItemInfos(
   238                 *(_translate_args(
   238                 *(_translate_args(
   239                     [_StringValue, class_extraction, _StringValue] + 
   239                     [_StringValue, class_extraction, _StringValue] +
   240                     [_BoolValue] * 2, args) + [[]])))
   240                     [_BoolValue] * 2, args) + [[]])))
   241 
   241 
   242 #-------------------------------------------------------------------------------
   242 #-------------------------------------------------------------------------------
   243 #            Helpers object for generating instances path list
   243 #            Helpers object for generating instances path list
   244 #-------------------------------------------------------------------------------
   244 #-------------------------------------------------------------------------------
   245 
   245 
   246 class InstancesPathFactory:
   246 class InstancesPathFactory:
   247     
   247 
   248     def __init__(self, instances):
   248     def __init__(self, instances):
   249         self.Instances = instances
   249         self.Instances = instances
   250         
   250 
   251     def AddInstance(self, context, *args):
   251     def AddInstance(self, context, *args):
   252         self.Instances.append(args[0][0])
   252         self.Instances.append(args[0][0])
   253 
   253 
   254 #-------------------------------------------------------------------------------
   254 #-------------------------------------------------------------------------------
   255 #            Helpers object for generating instance tagname
   255 #            Helpers object for generating instance tagname
   258 class InstanceTagName:
   258 class InstanceTagName:
   259 
   259 
   260     def __init__(self, controller):
   260     def __init__(self, controller):
   261         self.Controller = controller
   261         self.Controller = controller
   262         self.TagName = None
   262         self.TagName = None
   263     
   263 
   264     def GetTagName(self):
   264     def GetTagName(self):
   265         return self.TagName
   265         return self.TagName
   266     
   266 
   267     def ConfigTagName(self, context, *args):
   267     def ConfigTagName(self, context, *args):
   268         self.TagName = self.Controller.ComputeConfigurationName(args[0][0])
   268         self.TagName = self.Controller.ComputeConfigurationName(args[0][0])
   269         
   269 
   270     def ResourceTagName(self, context, *args):
   270     def ResourceTagName(self, context, *args):
   271         self.TagName = self.Controller.ComputeConfigurationResourceName(args[0][0], args[1][0])
   271         self.TagName = self.Controller.ComputeConfigurationResourceName(args[0][0], args[1][0])
   272 
   272 
   273     def PouTagName(self, context, *args):
   273     def PouTagName(self, context, *args):
   274         self.TagName = self.Controller.ComputePouName(args[0][0])
   274         self.TagName = self.Controller.ComputePouName(args[0][0])
   283 #           Helpers object for generating pou block instances list
   283 #           Helpers object for generating pou block instances list
   284 #-------------------------------------------------------------------------------
   284 #-------------------------------------------------------------------------------
   285 
   285 
   286 _Point = namedtuple("Point", ["x", "y"])
   286 _Point = namedtuple("Point", ["x", "y"])
   287 
   287 
   288 _BlockInstanceInfos = namedtuple("BlockInstanceInfos", 
   288 _BlockInstanceInfos = namedtuple("BlockInstanceInfos",
   289     ["type", "id", "x", "y", "width", "height", "specific_values", "inputs", "outputs"])
   289     ["type", "id", "x", "y", "width", "height", "specific_values", "inputs", "outputs"])
   290 
   290 
   291 _BlockSpecificValues = (
   291 _BlockSpecificValues = (
   292     namedtuple("BlockSpecificValues", 
   292     namedtuple("BlockSpecificValues",
   293                ["name", "execution_order"]),
   293                ["name", "execution_order"]),
   294     [_StringValue, int])
   294     [_StringValue, int])
   295 _VariableSpecificValues = (
   295 _VariableSpecificValues = (
   296     namedtuple("VariableSpecificValues", 
   296     namedtuple("VariableSpecificValues",
   297                ["name", "value_type", "execution_order"]),
   297                ["name", "value_type", "execution_order"]),
   298     [_StringValue, _StringValue, int])
   298     [_StringValue, _StringValue, int])
   299 _ConnectionSpecificValues = (
   299 _ConnectionSpecificValues = (
   300     namedtuple("ConnectionSpecificValues", ["name"]),
   300     namedtuple("ConnectionSpecificValues", ["name"]),
   301     [_StringValue])
   301     [_StringValue])
   303 _PowerRailSpecificValues = (
   303 _PowerRailSpecificValues = (
   304     namedtuple("PowerRailSpecificValues", ["connectors"]),
   304     namedtuple("PowerRailSpecificValues", ["connectors"]),
   305     [int])
   305     [int])
   306 
   306 
   307 _LDElementSpecificValues = (
   307 _LDElementSpecificValues = (
   308     namedtuple("LDElementSpecificValues", 
   308     namedtuple("LDElementSpecificValues",
   309                ["name", "negated", "edge", "storage", "execution_order"]),
   309                ["name", "negated", "edge", "storage", "execution_order"]),
   310     [_StringValue, _BoolValue, _StringValue, _StringValue, int])
   310     [_StringValue, _BoolValue, _StringValue, _StringValue, int])
   311 
   311 
   312 _DivergenceSpecificValues = (
   312 _DivergenceSpecificValues = (
   313     namedtuple("DivergenceSpecificValues", ["connectors"]),
   313     namedtuple("DivergenceSpecificValues", ["connectors"]),
   328     "coil": _LDElementSpecificValues,
   328     "coil": _LDElementSpecificValues,
   329     "step": (
   329     "step": (
   330         namedtuple("StepSpecificValues", ["name", "initial", "action"]),
   330         namedtuple("StepSpecificValues", ["name", "initial", "action"]),
   331         [_StringValue, _BoolValue, lambda x: x]),
   331         [_StringValue, _BoolValue, lambda x: x]),
   332     "transition": (
   332     "transition": (
   333         namedtuple("TransitionSpecificValues", 
   333         namedtuple("TransitionSpecificValues",
   334                    ["priority", "condition_type", "condition", "connection"]),
   334                    ["priority", "condition_type", "condition", "connection"]),
   335         [int, _StringValue, _StringValue, lambda x: x]),
   335         [int, _StringValue, _StringValue, lambda x: x]),
   336     "selectionDivergence": _DivergenceSpecificValues,
   336     "selectionDivergence": _DivergenceSpecificValues,
   337     "selectionConvergence": _DivergenceSpecificValues,
   337     "selectionConvergence": _DivergenceSpecificValues,
   338     "simultaneousDivergence": _DivergenceSpecificValues,
   338     "simultaneousDivergence": _DivergenceSpecificValues,
   358             setattr(self, attr, value if value is not None else "")
   358             setattr(self, attr, value if value is not None else "")
   359     def copy(self):
   359     def copy(self):
   360         return _ActionInfos(*[getattr(self, attr) for attr in self.__slots__])
   360         return _ActionInfos(*[getattr(self, attr) for attr in self.__slots__])
   361 
   361 
   362 class BlockInstanceFactory:
   362 class BlockInstanceFactory:
   363     
   363 
   364     def __init__(self, block_instances):
   364     def __init__(self, block_instances):
   365         self.BlockInstances = block_instances
   365         self.BlockInstances = block_instances
   366         self.CurrentInstance = None
   366         self.CurrentInstance = None
   367         self.SpecificValues = None
   367         self.SpecificValues = None
   368         self.CurrentConnection = None
   368         self.CurrentConnection = None
   369         self.CurrentLink = None
   369         self.CurrentLink = None
   370     
   370 
   371     def SetSpecificValues(self, context, *args):
   371     def SetSpecificValues(self, context, *args):
   372         self.SpecificValues = list(args)
   372         self.SpecificValues = list(args)
   373         self.CurrentInstance = None
   373         self.CurrentInstance = None
   374         self.CurrentConnection = None
   374         self.CurrentConnection = None
   375         self.CurrentLink = None
   375         self.CurrentLink = None
   376     
   376 
   377     def AddBlockInstance(self, context, *args):
   377     def AddBlockInstance(self, context, *args):
   378         specific_values_tuple, specific_values_translation = \
   378         specific_values_tuple, specific_values_translation = \
   379             _SpecificValuesTuples.get(args[0][0], _BlockSpecificValues)
   379             _SpecificValuesTuples.get(args[0][0], _BlockSpecificValues)
   380         
   380 
   381         if (args[0][0] == "step" and len(self.SpecificValues) < 3 or
   381         if (args[0][0] == "step" and len(self.SpecificValues) < 3 or
   382             args[0][0] == "transition" and len(self.SpecificValues) < 4):
   382             args[0][0] == "transition" and len(self.SpecificValues) < 4):
   383             self.SpecificValues.append([None])
   383             self.SpecificValues.append([None])
   384         elif args[0][0] == "actionBlock" and len(self.SpecificValues) < 1:
   384         elif args[0][0] == "actionBlock" and len(self.SpecificValues) < 1:
   385             self.SpecificValues.append([[]])
   385             self.SpecificValues.append([[]])
   386         specific_values = specific_values_tuple(*_translate_args(
   386         specific_values = specific_values_tuple(*_translate_args(
   387             specific_values_translation, self.SpecificValues))
   387             specific_values_translation, self.SpecificValues))
   388         self.SpecificValues = None
   388         self.SpecificValues = None
   389         
   389 
   390         self.CurrentInstance = _BlockInstanceInfos(
   390         self.CurrentInstance = _BlockInstanceInfos(
   391             *(_translate_args([_StringValue, int] + [float] * 4, args) + 
   391             *(_translate_args([_StringValue, int] + [float] * 4, args) +
   392               [specific_values, [], []]))
   392               [specific_values, [], []]))
   393         
   393 
   394         self.BlockInstances[self.CurrentInstance.id] = self.CurrentInstance
   394         self.BlockInstances[self.CurrentInstance.id] = self.CurrentInstance
   395         
   395 
   396     def AddInstanceConnection(self, context, *args):
   396     def AddInstanceConnection(self, context, *args):
   397         connection_args = _translate_args(
   397         connection_args = _translate_args(
   398             [_StringValue] * 2 + [_BoolValue, _StringValue] + [float] * 2, args)
   398             [_StringValue] * 2 + [_BoolValue, _StringValue] + [float] * 2, args)
   399         
   399 
   400         self.CurrentConnection = _InstanceConnectionInfos(
   400         self.CurrentConnection = _InstanceConnectionInfos(
   401             *(connection_args[1:4] + [
   401             *(connection_args[1:4] + [
   402                 _Point(*connection_args[4:6]), []]))
   402                 _Point(*connection_args[4:6]), []]))
   403         
   403 
   404         if self.CurrentInstance is not None:
   404         if self.CurrentInstance is not None:
   405             if connection_args[0] == "input":
   405             if connection_args[0] == "input":
   406                 self.CurrentInstance.inputs.append(self.CurrentConnection)
   406                 self.CurrentInstance.inputs.append(self.CurrentConnection)
   407             else:
   407             else:
   408                 self.CurrentInstance.outputs.append(self.CurrentConnection)
   408                 self.CurrentInstance.outputs.append(self.CurrentConnection)
   409         else:
   409         else:
   410             self.SpecificValues.append([self.CurrentConnection])
   410             self.SpecificValues.append([self.CurrentConnection])
   411     
   411 
   412     def AddConnectionLink(self, context, *args):
   412     def AddConnectionLink(self, context, *args):
   413         self.CurrentLink = _ConnectionLinkInfos(
   413         self.CurrentLink = _ConnectionLinkInfos(
   414             *(_translate_args([int, _StringValue], args) + [[]]))
   414             *(_translate_args([int, _StringValue], args) + [[]]))
   415         self.CurrentConnection.links.append(self.CurrentLink)
   415         self.CurrentConnection.links.append(self.CurrentLink)
   416     
   416 
   417     def AddLinkPoint(self, context, *args):
   417     def AddLinkPoint(self, context, *args):
   418         self.CurrentLink.points.append(_Point(
   418         self.CurrentLink.points.append(_Point(
   419             *_translate_args([float] * 2, args)))
   419             *_translate_args([float] * 2, args)))
   420     
   420 
   421     def AddAction(self, context, *args):
   421     def AddAction(self, context, *args):
   422         if len(self.SpecificValues) == 0:
   422         if len(self.SpecificValues) == 0:
   423             self.SpecificValues.append([[]])
   423             self.SpecificValues.append([[]])
   424         translated_args = _translate_args([_StringValue] * 5, args)
   424         translated_args = _translate_args([_StringValue] * 5, args)
   425         self.SpecificValues[0][0].append(_ActionInfos(*translated_args))
   425         self.SpecificValues[0][0].append(_ActionInfos(*translated_args))
   426     
   426 
   427 pou_block_instances_xslt = etree.parse(
   427 pou_block_instances_xslt = etree.parse(
   428     os.path.join(ScriptDirectory, "plcopen", "pou_block_instances.xslt"))
   428     os.path.join(ScriptDirectory, "plcopen", "pou_block_instances.xslt"))
   429 
   429 
   430 #-------------------------------------------------------------------------------
   430 #-------------------------------------------------------------------------------
   431 #                         Undo Buffer for PLCOpenEditor
   431 #                         Undo Buffer for PLCOpenEditor
   459         # Initialising index of state saved
   459         # Initialising index of state saved
   460         if issaved:
   460         if issaved:
   461             self.LastSave = 0
   461             self.LastSave = 0
   462         else:
   462         else:
   463             self.LastSave = -1
   463             self.LastSave = -1
   464     
   464 
   465     # Add a new state in buffer
   465     # Add a new state in buffer
   466     def Buffering(self, currentstate):
   466     def Buffering(self, currentstate):
   467         self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH
   467         self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH
   468         self.Buffer[self.CurrentIndex] = currentstate
   468         self.Buffer[self.CurrentIndex] = currentstate
   469         # Actualising buffer limits
   469         # Actualising buffer limits
   472             # If the removed state was the state saved, there is no state saved in the buffer
   472             # If the removed state was the state saved, there is no state saved in the buffer
   473             if self.LastSave == self.MinIndex:
   473             if self.LastSave == self.MinIndex:
   474                 self.LastSave = -1
   474                 self.LastSave = -1
   475             self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH
   475             self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH
   476         self.MinIndex = max(self.MinIndex, 0)
   476         self.MinIndex = max(self.MinIndex, 0)
   477     
   477 
   478     # Return current state of buffer
   478     # Return current state of buffer
   479     def Current(self):
   479     def Current(self):
   480         return self.Buffer[self.CurrentIndex]
   480         return self.Buffer[self.CurrentIndex]
   481     
   481 
   482     # Change current state to previous in buffer and return new current state
   482     # Change current state to previous in buffer and return new current state
   483     def Previous(self):
   483     def Previous(self):
   484         if self.CurrentIndex != self.MinIndex:
   484         if self.CurrentIndex != self.MinIndex:
   485             self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH
   485             self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH
   486             return self.Buffer[self.CurrentIndex]
   486             return self.Buffer[self.CurrentIndex]
   487         return None
   487         return None
   488     
   488 
   489     # Change current state to next in buffer and return new current state
   489     # Change current state to next in buffer and return new current state
   490     def Next(self):
   490     def Next(self):
   491         if self.CurrentIndex != self.MaxIndex:
   491         if self.CurrentIndex != self.MaxIndex:
   492             self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH
   492             self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH
   493             return self.Buffer[self.CurrentIndex]
   493             return self.Buffer[self.CurrentIndex]
   494         return None
   494         return None
   495     
   495 
   496     # Return True if current state is the first in buffer
   496     # Return True if current state is the first in buffer
   497     def IsFirst(self):
   497     def IsFirst(self):
   498         return self.CurrentIndex == self.MinIndex
   498         return self.CurrentIndex == self.MinIndex
   499     
   499 
   500     # Return True if current state is the last in buffer
   500     # Return True if current state is the last in buffer
   501     def IsLast(self):
   501     def IsLast(self):
   502         return self.CurrentIndex == self.MaxIndex
   502         return self.CurrentIndex == self.MaxIndex
   503 
   503 
   504     # Note that current state is saved
   504     # Note that current state is saved
   505     def CurrentSaved(self):
   505     def CurrentSaved(self):
   506         self.LastSave = self.CurrentIndex
   506         self.LastSave = self.CurrentIndex
   507         
   507 
   508     # Return True if current state is saved
   508     # Return True if current state is saved
   509     def IsCurrentSaved(self):
   509     def IsCurrentSaved(self):
   510         return self.LastSave == self.CurrentIndex
   510         return self.LastSave == self.CurrentIndex
   511 
   511 
   512 
   512 
   516 
   516 
   517 """
   517 """
   518 Class which controls the operations made on the plcopen model and answers to view requests
   518 Class which controls the operations made on the plcopen model and answers to view requests
   519 """
   519 """
   520 class PLCControler:
   520 class PLCControler:
   521     
   521 
   522     # Create a new PLCControler
   522     # Create a new PLCControler
   523     def __init__(self):
   523     def __init__(self):
   524         self.LastNewIndex = 0
   524         self.LastNewIndex = 0
   525         self.Reset()
   525         self.Reset()
   526     
   526 
   527     # Reset PLCControler internal variables
   527     # Reset PLCControler internal variables
   528     def Reset(self):
   528     def Reset(self):
   529         self.Project = None
   529         self.Project = None
   530         self.ProjectBufferEnabled = True
   530         self.ProjectBufferEnabled = True
   531         self.ProjectBuffer = None
   531         self.ProjectBuffer = None
   539         self.CurrentCompiledProject = None
   539         self.CurrentCompiledProject = None
   540         self.ConfNodeTypes = []
   540         self.ConfNodeTypes = []
   541         self.TotalTypesDict = StdBlckDct.copy()
   541         self.TotalTypesDict = StdBlckDct.copy()
   542         self.TotalTypes = StdBlckLst[:]
   542         self.TotalTypes = StdBlckLst[:]
   543         self.ProgramFilePath = ""
   543         self.ProgramFilePath = ""
   544             
   544 
   545     def GetQualifierTypes(self):
   545     def GetQualifierTypes(self):
   546         return QualifierList
   546         return QualifierList
   547 
   547 
   548     def GetProject(self, debug = False):
   548     def GetProject(self, debug = False):
   549         if debug and self.CurrentCompiledProject is not None:
   549         if debug and self.CurrentCompiledProject is not None:
   565         self.Project = PLCOpenParser.CreateRoot()
   565         self.Project = PLCOpenParser.CreateRoot()
   566         properties["creationDateTime"] = datetime.datetime(*localtime()[:6])
   566         properties["creationDateTime"] = datetime.datetime(*localtime()[:6])
   567         self.Project.setfileHeader(properties)
   567         self.Project.setfileHeader(properties)
   568         self.Project.setcontentHeader(properties)
   568         self.Project.setcontentHeader(properties)
   569         self.SetFilePath("")
   569         self.SetFilePath("")
   570         
   570 
   571         # Initialize the project buffer
   571         # Initialize the project buffer
   572         self.CreateProjectBuffer(False)
   572         self.CreateProjectBuffer(False)
   573         self.ProgramChunks = []
   573         self.ProgramChunks = []
   574         self.ProgramOffset = 0
   574         self.ProgramOffset = 0
   575         self.NextCompiledProject = self.Copy(self.Project)
   575         self.NextCompiledProject = self.Copy(self.Project)
   576         self.CurrentCompiledProject = None
   576         self.CurrentCompiledProject = None
   577         self.Buffering = False
   577         self.Buffering = False
   578     
   578 
   579     # Return project data type names
   579     # Return project data type names
   580     def GetProjectDataTypeNames(self, debug = False):
   580     def GetProjectDataTypeNames(self, debug = False):
   581         project = self.GetProject(debug)
   581         project = self.GetProject(debug)
   582         if project is not None:
   582         if project is not None:
   583             return [datatype.getname() for datatype in project.getdataTypes()]
   583             return [datatype.getname() for datatype in project.getdataTypes()]
   584         return []
   584         return []
   585     
   585 
   586     # Return project pou names
   586     # Return project pou names
   587     def GetProjectPouNames(self, debug = False):
   587     def GetProjectPouNames(self, debug = False):
   588         project = self.GetProject(debug)
   588         project = self.GetProject(debug)
   589         if project is not None:
   589         if project is not None:
   590             return [pou.getname() for pou in project.getpous()]
   590             return [pou.getname() for pou in project.getpous()]
   591         return []
   591         return []
   592     
   592 
   593     # Return project pou names
   593     # Return project pou names
   594     def GetProjectConfigNames(self, debug = False):
   594     def GetProjectConfigNames(self, debug = False):
   595         project = self.GetProject(debug)
   595         project = self.GetProject(debug)
   596         if project is not None:
   596         if project is not None:
   597             return [config.getname() for config in project.getconfigurations()]
   597             return [config.getname() for config in project.getconfigurations()]
   598         return []
   598         return []
   599     
   599 
   600     # Return project pou variable names
   600     # Return project pou variable names
   601     def GetProjectPouVariableNames(self, pou_name = None, debug = False):
   601     def GetProjectPouVariableNames(self, pou_name = None, debug = False):
   602         variables = []
   602         variables = []
   603         project = self.GetProject(debug)
   603         project = self.GetProject(debug)
   604         if project is not None:
   604         if project is not None:
   608                     for transition in pou.gettransitionList():
   608                     for transition in pou.gettransitionList():
   609                         variables.append(transition.getname())
   609                         variables.append(transition.getname())
   610                     for action in pou.getactionList():
   610                     for action in pou.getactionList():
   611                         variables.append(action.getname())
   611                         variables.append(action.getname())
   612         return variables
   612         return variables
   613     
   613 
   614     # Return file path if project is an open file
   614     # Return file path if project is an open file
   615     def GetFilePath(self):
   615     def GetFilePath(self):
   616         return self.FilePath
   616         return self.FilePath
   617     
   617 
   618     # Return file path if project is an open file
   618     # Return file path if project is an open file
   619     def GetProgramFilePath(self):
   619     def GetProgramFilePath(self):
   620         return self.ProgramFilePath
   620         return self.ProgramFilePath
   621     
   621 
   622     # Return file name and point out if file is up to date
   622     # Return file name and point out if file is up to date
   623     def GetFilename(self):
   623     def GetFilename(self):
   624         if self.Project is not None:
   624         if self.Project is not None:
   625             if self.ProjectIsSaved():
   625             if self.ProjectIsSaved():
   626                 return self.FileName
   626                 return self.FileName
   627             else:
   627             else:
   628                 return "~%s~"%self.FileName
   628                 return "~%s~"%self.FileName
   629         return ""
   629         return ""
   630     
   630 
   631     # Change file path and save file name or create a default one if file path not defined
   631     # Change file path and save file name or create a default one if file path not defined
   632     def SetFilePath(self, filepath):
   632     def SetFilePath(self, filepath):
   633         self.FilePath = filepath
   633         self.FilePath = filepath
   634         if filepath == "":
   634         if filepath == "":
   635             self.LastNewIndex += 1
   635             self.LastNewIndex += 1
   636             self.FileName = _("Unnamed%d")%self.LastNewIndex
   636             self.FileName = _("Unnamed%d")%self.LastNewIndex
   637         else:
   637         else:
   638             self.FileName = os.path.splitext(os.path.basename(filepath))[0]
   638             self.FileName = os.path.splitext(os.path.basename(filepath))[0]
   639     
   639 
   640     # Change project properties
   640     # Change project properties
   641     def SetProjectProperties(self, name = None, properties = None, buffer = True):
   641     def SetProjectProperties(self, name = None, properties = None, buffer = True):
   642         if self.Project is not None:
   642         if self.Project is not None:
   643             if name is not None:
   643             if name is not None:
   644                 self.Project.setname(name)
   644                 self.Project.setname(name)
   645             if properties is not None:
   645             if properties is not None:
   646                 self.Project.setfileHeader(properties)
   646                 self.Project.setfileHeader(properties)
   647                 self.Project.setcontentHeader(properties)
   647                 self.Project.setcontentHeader(properties)
   648             if buffer and (name is not None or properties is not None):
   648             if buffer and (name is not None or properties is not None):
   649                 self.BufferProject()
   649                 self.BufferProject()
   650     
   650 
   651     # Return project name
   651     # Return project name
   652     def GetProjectName(self, debug=False):
   652     def GetProjectName(self, debug=False):
   653         project = self.GetProject(debug)
   653         project = self.GetProject(debug)
   654         if project is not None:
   654         if project is not None:
   655             return project.getname()
   655             return project.getname()
   656         return None
   656         return None
   657     
   657 
   658     # Return project properties
   658     # Return project properties
   659     def GetProjectProperties(self, debug = False):
   659     def GetProjectProperties(self, debug = False):
   660         project = self.GetProject(debug)
   660         project = self.GetProject(debug)
   661         if project is not None:
   661         if project is not None:
   662             properties = project.getfileHeader()
   662             properties = project.getfileHeader()
   663             properties.update(project.getcontentHeader())
   663             properties.update(project.getcontentHeader())
   664             return properties
   664             return properties
   665         return None
   665         return None
   666     
   666 
   667     # Return project informations
   667     # Return project informations
   668     def GetProjectInfos(self, debug = False):
   668     def GetProjectInfos(self, debug = False):
   669         project = self.GetProject(debug)
   669         project = self.GetProject(debug)
   670         if project is not None:
   670         if project is not None:
   671             infos = {"name": project.getname(), "type": ITEM_PROJECT}
   671             infos = {"name": project.getname(), "type": ITEM_PROJECT}
   672             datatypes = {"name": DATA_TYPES, "type": ITEM_DATATYPES, "values":[]}
   672             datatypes = {"name": DATA_TYPES, "type": ITEM_DATATYPES, "values":[]}
   673             for datatype in project.getdataTypes():
   673             for datatype in project.getdataTypes():
   674                 datatypes["values"].append({"name": datatype.getname(), "type": ITEM_DATATYPE, 
   674                 datatypes["values"].append({"name": datatype.getname(), "type": ITEM_DATATYPE,
   675                     "tagname": self.ComputeDataTypeName(datatype.getname()), "values": []})
   675                     "tagname": self.ComputeDataTypeName(datatype.getname()), "values": []})
   676             pou_types = {"function": {"name": FUNCTIONS, "type": ITEM_FUNCTION, "values":[]},
   676             pou_types = {"function": {"name": FUNCTIONS, "type": ITEM_FUNCTION, "values":[]},
   677                          "functionBlock": {"name": FUNCTION_BLOCKS, "type": ITEM_FUNCTIONBLOCK, "values":[]},
   677                          "functionBlock": {"name": FUNCTION_BLOCKS, "type": ITEM_FUNCTIONBLOCK, "values":[]},
   678                          "program": {"name": PROGRAMS, "type": ITEM_PROGRAM, "values":[]}}
   678                          "program": {"name": PROGRAMS, "type": ITEM_PROGRAM, "values":[]}}
   679             for pou in project.getpous():
   679             for pou in project.getpous():
   682                              "tagname": self.ComputePouName(pou.getname())}
   682                              "tagname": self.ComputePouName(pou.getname())}
   683                 pou_values = []
   683                 pou_values = []
   684                 if pou.getbodyType() == "SFC":
   684                 if pou.getbodyType() == "SFC":
   685                     transitions = []
   685                     transitions = []
   686                     for transition in pou.gettransitionList():
   686                     for transition in pou.gettransitionList():
   687                         transitions.append({"name": transition.getname(), "type": ITEM_TRANSITION, 
   687                         transitions.append({"name": transition.getname(), "type": ITEM_TRANSITION,
   688                             "tagname": self.ComputePouTransitionName(pou.getname(), transition.getname()), 
   688                             "tagname": self.ComputePouTransitionName(pou.getname(), transition.getname()),
   689                             "values": []})
   689                             "values": []})
   690                     pou_values.append({"name": TRANSITIONS, "type": ITEM_TRANSITIONS, "values": transitions})
   690                     pou_values.append({"name": TRANSITIONS, "type": ITEM_TRANSITIONS, "values": transitions})
   691                     actions = []
   691                     actions = []
   692                     for action in pou.getactionList():
   692                     for action in pou.getactionList():
   693                         actions.append({"name": action.getname(), "type": ITEM_ACTION, 
   693                         actions.append({"name": action.getname(), "type": ITEM_ACTION,
   694                             "tagname": self.ComputePouActionName(pou.getname(), action.getname()), 
   694                             "tagname": self.ComputePouActionName(pou.getname(), action.getname()),
   695                             "values": []})
   695                             "values": []})
   696                     pou_values.append({"name": ACTIONS, "type": ITEM_ACTIONS, "values": actions})
   696                     pou_values.append({"name": ACTIONS, "type": ITEM_ACTIONS, "values": actions})
   697                 if pou_type in pou_types:
   697                 if pou_type in pou_types:
   698                     pou_infos["values"] = pou_values
   698                     pou_infos["values"] = pou_values
   699                     pou_types[pou_type]["values"].append(pou_infos)
   699                     pou_types[pou_type]["values"].append(pou_infos)
   700             configurations = {"name": CONFIGURATIONS, "type": ITEM_CONFIGURATIONS, "values": []}
   700             configurations = {"name": CONFIGURATIONS, "type": ITEM_CONFIGURATIONS, "values": []}
   701             for config in project.getconfigurations():
   701             for config in project.getconfigurations():
   702                 config_name = config.getname()
   702                 config_name = config.getname()
   703                 config_infos = {"name": config_name, "type": ITEM_CONFIGURATION, 
   703                 config_infos = {"name": config_name, "type": ITEM_CONFIGURATION,
   704                     "tagname": self.ComputeConfigurationName(config.getname()), 
   704                     "tagname": self.ComputeConfigurationName(config.getname()),
   705                     "values": []}
   705                     "values": []}
   706                 resources = {"name": RESOURCES, "type": ITEM_RESOURCES, "values": []}
   706                 resources = {"name": RESOURCES, "type": ITEM_RESOURCES, "values": []}
   707                 for resource in config.getresource():
   707                 for resource in config.getresource():
   708                     resource_name = resource.getname()
   708                     resource_name = resource.getname()
   709                     resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, 
   709                     resource_infos = {"name": resource_name, "type": ITEM_RESOURCE,
   710                         "tagname": self.ComputeConfigurationResourceName(config.getname(), resource.getname()), 
   710                         "tagname": self.ComputeConfigurationResourceName(config.getname(), resource.getname()),
   711                         "values": []}
   711                         "values": []}
   712                     resources["values"].append(resource_infos)
   712                     resources["values"].append(resource_infos)
   713                 config_infos["values"] = [resources]
   713                 config_infos["values"] = [resources]
   714                 configurations["values"].append(config_infos)
   714                 configurations["values"].append(config_infos)
   715             infos["values"] = [datatypes, pou_types["function"], pou_types["functionBlock"], 
   715             infos["values"] = [datatypes, pou_types["function"], pou_types["functionBlock"],
   716                                pou_types["program"], configurations]
   716                                pou_types["program"], configurations]
   717             return infos
   717             return infos
   718         return None
   718         return None
   719 
   719 
   720     def GetPouVariables(self, tagname, debug = False):
   720     def GetPouVariables(self, tagname, debug = False):
   721         pou_type = None
   721         pou_type = None
   722         project = self.GetProject(debug)
   722         project = self.GetProject(debug)
   723         if project is not None:
   723         if project is not None:
   724             factory = VariablesTreeInfosFactory()
   724             factory = VariablesTreeInfosFactory()
   725             
   725 
   726             parser = etree.XMLParser()
   726             parser = etree.XMLParser()
   727             parser.resolvers.add(LibraryResolver(self, debug))
   727             parser.resolvers.add(LibraryResolver(self, debug))
   728             
   728 
   729             pou_variable_xslt_tree = etree.XSLT(
   729             pou_variable_xslt_tree = etree.XSLT(
   730                 etree.parse(
   730                 etree.parse(
   731                     os.path.join(ScriptDirectory, "plcopen", "pou_variables.xslt"),
   731                     os.path.join(ScriptDirectory, "plcopen", "pou_variables.xslt"),
   732                     parser), 
   732                     parser),
   733                 extensions = {("pou_vars_ns", name): getattr(factory, name)
   733                 extensions = {("pou_vars_ns", name): getattr(factory, name)
   734                               for name in ["SetRoot", "AddVariable"]})
   734                               for name in ["SetRoot", "AddVariable"]})
   735             
   735 
   736             obj = None
   736             obj = None
   737             words = tagname.split("::")
   737             words = tagname.split("::")
   738             if words[0] == "P":
   738             if words[0] == "P":
   739                 obj = self.GetPou(words[1], debug)
   739                 obj = self.GetPou(words[1], debug)
   740             elif words[0] != "D":
   740             elif words[0] != "D":
   741                 obj = self.GetEditedElement(tagname, debug)
   741                 obj = self.GetEditedElement(tagname, debug)
   742             if obj is not None:
   742             if obj is not None:
   743                 pou_variable_xslt_tree(obj)
   743                 pou_variable_xslt_tree(obj)
   744                 return factory.GetRoot()
   744                 return factory.GetRoot()
   745             
   745 
   746         return None
   746         return None
   747 
   747 
   748     def GetInstanceList(self, root, name, debug = False):
   748     def GetInstanceList(self, root, name, debug = False):
   749         instances = []
   749         instances = []
   750         project = self.GetProject(debug)
   750         project = self.GetProject(debug)
   751         if project is not None:
   751         if project is not None:
   752             factory = InstancesPathFactory(instances)
   752             factory = InstancesPathFactory(instances)
   753             
   753 
   754             parser = etree.XMLParser()
   754             parser = etree.XMLParser()
   755             parser.resolvers.add(LibraryResolver(self, debug))
   755             parser.resolvers.add(LibraryResolver(self, debug))
   756             
   756 
   757             instances_path_xslt_tree = etree.XSLT(
   757             instances_path_xslt_tree = etree.XSLT(
   758                 etree.parse(
   758                 etree.parse(
   759                     os.path.join(ScriptDirectory, "plcopen", "instances_path.xslt"),
   759                     os.path.join(ScriptDirectory, "plcopen", "instances_path.xslt"),
   760                     parser), 
   760                     parser),
   761                 extensions = {
   761                 extensions = {
   762                     ("instances_ns", "AddInstance"): factory.AddInstance})
   762                     ("instances_ns", "AddInstance"): factory.AddInstance})
   763             
   763 
   764             instances_path_xslt_tree(root, 
   764             instances_path_xslt_tree(root,
   765                 instance_type=etree.XSLT.strparam(name))
   765                 instance_type=etree.XSLT.strparam(name))
   766             
   766 
   767         return instances
   767         return instances
   768         
   768 
   769     def SearchPouInstances(self, tagname, debug = False):
   769     def SearchPouInstances(self, tagname, debug = False):
   770         project = self.GetProject(debug)
   770         project = self.GetProject(debug)
   771         if project is not None:
   771         if project is not None:
   772             words = tagname.split("::")
   772             words = tagname.split("::")
   773             if words[0] == "P":
   773             if words[0] == "P":
   779             elif words[0] in ['T', 'A']:
   779             elif words[0] in ['T', 'A']:
   780                 return ["%s.%s" % (instance, words[2])
   780                 return ["%s.%s" % (instance, words[2])
   781                         for instance in self.SearchPouInstances(
   781                         for instance in self.SearchPouInstances(
   782                             self.ComputePouName(words[1]), debug)]
   782                             self.ComputePouName(words[1]), debug)]
   783         return []
   783         return []
   784     
   784 
   785     def GetPouInstanceTagName(self, instance_path, debug = False):
   785     def GetPouInstanceTagName(self, instance_path, debug = False):
   786         project = self.GetProject(debug)
   786         project = self.GetProject(debug)
   787         factory = InstanceTagName(self)
   787         factory = InstanceTagName(self)
   788         
   788 
   789         parser = etree.XMLParser()
   789         parser = etree.XMLParser()
   790         parser.resolvers.add(LibraryResolver(self, debug))
   790         parser.resolvers.add(LibraryResolver(self, debug))
   791         
   791 
   792         instance_tagname_xslt_tree = etree.XSLT(
   792         instance_tagname_xslt_tree = etree.XSLT(
   793             etree.parse(
   793             etree.parse(
   794                 os.path.join(ScriptDirectory, "plcopen", "instance_tagname.xslt"),
   794                 os.path.join(ScriptDirectory, "plcopen", "instance_tagname.xslt"),
   795                 parser), 
   795                 parser),
   796             extensions = {("instance_tagname_ns", name): getattr(factory, name)
   796             extensions = {("instance_tagname_ns", name): getattr(factory, name)
   797                           for name in ["ConfigTagName", "ResourceTagName",
   797                           for name in ["ConfigTagName", "ResourceTagName",
   798                                        "PouTagName", "ActionTagName", 
   798                                        "PouTagName", "ActionTagName",
   799                                        "TransitionTagName"]})
   799                                        "TransitionTagName"]})
   800         
   800 
   801         instance_tagname_xslt_tree(project, 
   801         instance_tagname_xslt_tree(project,
   802             instance_path=etree.XSLT.strparam(instance_path))
   802             instance_path=etree.XSLT.strparam(instance_path))
   803         
   803 
   804         return factory.GetTagName()
   804         return factory.GetTagName()
   805     
   805 
   806     def GetInstanceInfos(self, instance_path, debug = False):
   806     def GetInstanceInfos(self, instance_path, debug = False):
   807         tagname = self.GetPouInstanceTagName(instance_path)
   807         tagname = self.GetPouInstanceTagName(instance_path)
   808         if tagname is not None:
   808         if tagname is not None:
   809             infos = self.GetPouVariables(tagname, debug)
   809             infos = self.GetPouVariables(tagname, debug)
   810             infos.type = tagname
   810             infos.type = tagname
   816                 pou_infos = self.GetPouVariables(tagname, debug)
   816                 pou_infos = self.GetPouVariables(tagname, debug)
   817                 for var_infos in pou_infos.variables:
   817                 for var_infos in pou_infos.variables:
   818                     if var_infos.name == var_name:
   818                     if var_infos.name == var_name:
   819                         return var_infos
   819                         return var_infos
   820         return None
   820         return None
   821     
   821 
   822     # Return if data type given by name is used by another data type or pou
   822     # Return if data type given by name is used by another data type or pou
   823     def DataTypeIsUsed(self, name, debug = False):
   823     def DataTypeIsUsed(self, name, debug = False):
   824         project = self.GetProject(debug)
   824         project = self.GetProject(debug)
   825         if project is not None:
   825         if project is not None:
   826             return len(self.GetInstanceList(project, name, debug)) > 0
   826             return len(self.GetInstanceList(project, name, debug)) > 0
   885                 infos.append((chunk_infos, (row, col)))
   885                 infos.append((chunk_infos, (row, col)))
   886             if next_row == to_location[0] and next_col > to_location[1] or next_row > to_location[0]:
   886             if next_row == to_location[0] and next_col > to_location[1] or next_row > to_location[0]:
   887                 return infos
   887                 return infos
   888             row, col = next_row, next_col
   888             row, col = next_row, next_col
   889         return infos
   889         return infos
   890         
   890 
   891 #-------------------------------------------------------------------------------
   891 #-------------------------------------------------------------------------------
   892 #                        Project Pous management functions
   892 #                        Project Pous management functions
   893 #-------------------------------------------------------------------------------
   893 #-------------------------------------------------------------------------------
   894     
   894 
   895     # Add a Data Type to Project
   895     # Add a Data Type to Project
   896     def ProjectAddDataType(self, datatype_name=None):
   896     def ProjectAddDataType(self, datatype_name=None):
   897         if self.Project is not None:
   897         if self.Project is not None:
   898             if datatype_name is None:
   898             if datatype_name is None:
   899                 datatype_name = self.GenerateNewName(None, None, "datatype%d")
   899                 datatype_name = self.GenerateNewName(None, None, "datatype%d")
   900             # Add the datatype to project
   900             # Add the datatype to project
   901             self.Project.appenddataType(datatype_name)
   901             self.Project.appenddataType(datatype_name)
   902             self.BufferProject()
   902             self.BufferProject()
   903             return self.ComputeDataTypeName(datatype_name)
   903             return self.ComputeDataTypeName(datatype_name)
   904         return None
   904         return None
   905         
   905 
   906     # Remove a Data Type from project
   906     # Remove a Data Type from project
   907     def ProjectRemoveDataType(self, datatype_name):
   907     def ProjectRemoveDataType(self, datatype_name):
   908         if self.Project is not None:
   908         if self.Project is not None:
   909             self.Project.removedataType(datatype_name)
   909             self.Project.removedataType(datatype_name)
   910             self.BufferProject()
   910             self.BufferProject()
   911     
   911 
   912     # Add a Pou to Project
   912     # Add a Pou to Project
   913     def ProjectAddPou(self, pou_name, pou_type, body_type):
   913     def ProjectAddPou(self, pou_name, pou_type, body_type):
   914         if self.Project is not None:
   914         if self.Project is not None:
   915             # Add the pou to project
   915             # Add the pou to project
   916             self.Project.appendpou(pou_name, pou_type, body_type)
   916             self.Project.appendpou(pou_name, pou_type, body_type)
   917             if pou_type == "function":
   917             if pou_type == "function":
   918                 self.SetPouInterfaceReturnType(pou_name, "BOOL")
   918                 self.SetPouInterfaceReturnType(pou_name, "BOOL")
   919             self.BufferProject()
   919             self.BufferProject()
   920             return self.ComputePouName(pou_name)
   920             return self.ComputePouName(pou_name)
   921         return None
   921         return None
   922     
   922 
   923     def ProjectChangePouType(self, name, pou_type):
   923     def ProjectChangePouType(self, name, pou_type):
   924         if self.Project is not None:
   924         if self.Project is not None:
   925             pou = self.Project.getpou(name)
   925             pou = self.Project.getpou(name)
   926             if pou is not None:
   926             if pou is not None:
   927                 pou.setpouType(pou_type)
   927                 pou.setpouType(pou_type)
   928                 self.BufferProject()
   928                 self.BufferProject()
   929                 
   929 
   930     def GetPouXml(self, pou_name):
   930     def GetPouXml(self, pou_name):
   931         if self.Project is not None:
   931         if self.Project is not None:
   932             pou = self.Project.getpou(pou_name)
   932             pou = self.Project.getpou(pou_name)
   933             if pou is not None:
   933             if pou is not None:
   934                 return pou.tostring()
   934                 return pou.tostring()
   935         return None
   935         return None
   936     
   936 
   937     def PastePou(self, pou_type, pou_xml):
   937     def PastePou(self, pou_type, pou_xml):
   938         '''
   938         '''
   939         Adds the POU defined by 'pou_xml' to the current project with type 'pou_type'
   939         Adds the POU defined by 'pou_xml' to the current project with type 'pou_type'
   940         '''
   940         '''
   941         try:
   941         try:
   942             new_pou, error = LoadPou(pou_xml)
   942             new_pou, error = LoadPou(pou_xml)
   943         except:
   943         except:
   944             error = ""
   944             error = ""
   945         if error is not None:
   945         if error is not None:
   946             return _("Couldn't paste non-POU object.")
   946             return _("Couldn't paste non-POU object.")
   947         
   947 
   948         name = new_pou.getname()
   948         name = new_pou.getname()
   949         
   949 
   950         idx = 0
   950         idx = 0
   951         new_name = name
   951         new_name = name
   952         while self.Project.getpou(new_name):
   952         while self.Project.getpou(new_name) is not None:
   953             # a POU with that name already exists.
   953             # a POU with that name already exists.
   954             # make a new name and test if a POU with that name exists.
   954             # make a new name and test if a POU with that name exists.
   955             # append an incrementing numeric suffix to the POU name.
   955             # append an incrementing numeric suffix to the POU name.
   956             idx += 1
   956             idx += 1
   957             new_name = "%s%d" % (name, idx)
   957             new_name = "%s%d" % (name, idx)
   958             
   958 
   959         # we've found a name that does not already exist, use it
   959         # we've found a name that does not already exist, use it
   960         new_pou.setname(new_name)
   960         new_pou.setname(new_name)
   961         
   961 
   962         if pou_type is not None:
   962         if pou_type is not None:
   963             orig_type = new_pou.getpouType()
   963             orig_type = new_pou.getpouType()
   964 
   964 
   965             # prevent violations of POU content restrictions:
   965             # prevent violations of POU content restrictions:
   966             # function blocks cannot be pasted as functions,
   966             # function blocks cannot be pasted as functions,
   967             # programs cannot be pasted as functions or function blocks
   967             # programs cannot be pasted as functions or function blocks
   968             if orig_type == 'functionBlock' and pou_type == 'function' or \
   968             if orig_type == 'functionBlock' and pou_type == 'function' or \
   969                orig_type == 'program' and pou_type in ['function', 'functionBlock']:
   969                orig_type == 'program' and pou_type in ['function', 'functionBlock']:
   970                 return _('''%s "%s" can't be pasted as a %s.''') % (orig_type, name, pou_type)
   970                 return _('''%s "%s" can't be pasted as a %s.''') % (orig_type, name, pou_type)
   971             
   971 
   972             new_pou.setpouType(pou_type)
   972             new_pou.setpouType(pou_type)
   973 
   973 
   974         self.Project.insertpou(-1, new_pou)
   974         self.Project.insertpou(0, new_pou)
   975         self.BufferProject()
   975         self.BufferProject()
   976         
   976 
   977         return self.ComputePouName(new_name),
   977         return self.ComputePouName(new_name),
   978 
   978 
   979     # Remove a Pou from project
   979     # Remove a Pou from project
   980     def ProjectRemovePou(self, pou_name):
   980     def ProjectRemovePou(self, pou_name):
   981         if self.Project is not None:
   981         if self.Project is not None:
   982             self.Project.removepou(pou_name)
   982             self.Project.removepou(pou_name)
   983             self.BufferProject()
   983             self.BufferProject()
   984     
   984 
   985     # Return the name of the configuration if only one exist
   985     # Return the name of the configuration if only one exist
   986     def GetProjectMainConfigurationName(self):
   986     def GetProjectMainConfigurationName(self):
   987         if self.Project is not None:
   987         if self.Project is not None:
   988             # Found the configuration corresponding to old name and change its name to new name
   988             # Found the configuration corresponding to old name and change its name to new name
   989             configurations = self.Project.getconfigurations()
   989             configurations = self.Project.getconfigurations()
   990             if len(configurations) == 1:
   990             if len(configurations) == 1:
   991                 return configurations[0].getname()
   991                 return configurations[0].getname()
   992         return None
   992         return None
   993                 
   993 
   994     # Add a configuration to Project
   994     # Add a configuration to Project
   995     def ProjectAddConfiguration(self, config_name=None):
   995     def ProjectAddConfiguration(self, config_name=None):
   996         if self.Project is not None:
   996         if self.Project is not None:
   997             if config_name is None:
   997             if config_name is None:
   998                 config_name = self.GenerateNewName(None, None, "configuration%d")
   998                 config_name = self.GenerateNewName(None, None, "configuration%d")
   999             self.Project.addconfiguration(config_name)
   999             self.Project.addconfiguration(config_name)
  1000             self.BufferProject()
  1000             self.BufferProject()
  1001             return self.ComputeConfigurationName(config_name)
  1001             return self.ComputeConfigurationName(config_name)
  1002         return None
  1002         return None
  1003     
  1003 
  1004     # Remove a configuration from project
  1004     # Remove a configuration from project
  1005     def ProjectRemoveConfiguration(self, config_name):
  1005     def ProjectRemoveConfiguration(self, config_name):
  1006         if self.Project is not None:
  1006         if self.Project is not None:
  1007             self.Project.removeconfiguration(config_name)
  1007             self.Project.removeconfiguration(config_name)
  1008             self.BufferProject()
  1008             self.BufferProject()
  1009     
  1009 
  1010     # Add a resource to a configuration of the Project
  1010     # Add a resource to a configuration of the Project
  1011     def ProjectAddConfigurationResource(self, config_name, resource_name=None):
  1011     def ProjectAddConfigurationResource(self, config_name, resource_name=None):
  1012         if self.Project is not None:
  1012         if self.Project is not None:
  1013             if resource_name is None:
  1013             if resource_name is None:
  1014                 resource_name = self.GenerateNewName(None, None, "resource%d")
  1014                 resource_name = self.GenerateNewName(None, None, "resource%d")
  1015             self.Project.addconfigurationResource(config_name, resource_name)
  1015             self.Project.addconfigurationResource(config_name, resource_name)
  1016             self.BufferProject()
  1016             self.BufferProject()
  1017             return self.ComputeConfigurationResourceName(config_name, resource_name)
  1017             return self.ComputeConfigurationResourceName(config_name, resource_name)
  1018         return None
  1018         return None
  1019     
  1019 
  1020     # Remove a resource from a configuration of the project
  1020     # Remove a resource from a configuration of the project
  1021     def ProjectRemoveConfigurationResource(self, config_name, resource_name):
  1021     def ProjectRemoveConfigurationResource(self, config_name, resource_name):
  1022         if self.Project is not None:
  1022         if self.Project is not None:
  1023             self.Project.removeconfigurationResource(config_name, resource_name)
  1023             self.Project.removeconfigurationResource(config_name, resource_name)
  1024             self.BufferProject()
  1024             self.BufferProject()
  1025     
  1025 
  1026     # Add a Transition to a Project Pou
  1026     # Add a Transition to a Project Pou
  1027     def ProjectAddPouTransition(self, pou_name, transition_name, transition_type):
  1027     def ProjectAddPouTransition(self, pou_name, transition_name, transition_type):
  1028         if self.Project is not None:
  1028         if self.Project is not None:
  1029             pou = self.Project.getpou(pou_name)
  1029             pou = self.Project.getpou(pou_name)
  1030             if pou is not None:
  1030             if pou is not None:
  1031                 pou.addtransition(transition_name, transition_type)
  1031                 pou.addtransition(transition_name, transition_type)
  1032                 self.BufferProject()
  1032                 self.BufferProject()
  1033                 return self.ComputePouTransitionName(pou_name, transition_name)
  1033                 return self.ComputePouTransitionName(pou_name, transition_name)
  1034         return None
  1034         return None
  1035     
  1035 
  1036     # Remove a Transition from a Project Pou
  1036     # Remove a Transition from a Project Pou
  1037     def ProjectRemovePouTransition(self, pou_name, transition_name):
  1037     def ProjectRemovePouTransition(self, pou_name, transition_name):
  1038         # Search if the pou removed is currently opened
  1038         # Search if the pou removed is currently opened
  1039         if self.Project is not None:
  1039         if self.Project is not None:
  1040             pou = self.Project.getpou(pou_name)
  1040             pou = self.Project.getpou(pou_name)
  1041             if pou is not None:
  1041             if pou is not None:
  1042                 pou.removetransition(transition_name)
  1042                 pou.removetransition(transition_name)
  1043                 self.BufferProject()
  1043                 self.BufferProject()
  1044     
  1044 
  1045     # Add an Action to a Project Pou
  1045     # Add an Action to a Project Pou
  1046     def ProjectAddPouAction(self, pou_name, action_name, action_type):
  1046     def ProjectAddPouAction(self, pou_name, action_name, action_type):
  1047         if self.Project is not None:
  1047         if self.Project is not None:
  1048             pou = self.Project.getpou(pou_name)
  1048             pou = self.Project.getpou(pou_name)
  1049             if pou is not None:
  1049             if pou is not None:
  1050                 pou.addaction(action_name, action_type)
  1050                 pou.addaction(action_name, action_type)
  1051                 self.BufferProject()
  1051                 self.BufferProject()
  1052                 return self.ComputePouActionName(pou_name, action_name)
  1052                 return self.ComputePouActionName(pou_name, action_name)
  1053         return None
  1053         return None
  1054     
  1054 
  1055     # Remove an Action from a Project Pou
  1055     # Remove an Action from a Project Pou
  1056     def ProjectRemovePouAction(self, pou_name, action_name):
  1056     def ProjectRemovePouAction(self, pou_name, action_name):
  1057         # Search if the pou removed is currently opened
  1057         # Search if the pou removed is currently opened
  1058         if self.Project is not None:
  1058         if self.Project is not None:
  1059             pou = self.Project.getpou(pou_name)
  1059             pou = self.Project.getpou(pou_name)
  1060             if pou is not None:
  1060             if pou is not None:
  1061                 pou.removeaction(action_name)
  1061                 pou.removeaction(action_name)
  1062                 self.BufferProject()
  1062                 self.BufferProject()
  1063     
  1063 
  1064     # Change the name of a pou
  1064     # Change the name of a pou
  1065     def ChangeDataTypeName(self, old_name, new_name):
  1065     def ChangeDataTypeName(self, old_name, new_name):
  1066         if self.Project is not None:
  1066         if self.Project is not None:
  1067             # Found the pou corresponding to old name and change its name to new name
  1067             # Found the pou corresponding to old name and change its name to new name
  1068             datatype = self.Project.getdataType(old_name)
  1068             datatype = self.Project.getdataType(old_name)
  1069             if datatype is not None:
  1069             if datatype is not None:
  1070                 datatype.setname(new_name)
  1070                 datatype.setname(new_name)
  1071                 self.Project.updateElementName(old_name, new_name)
  1071                 self.Project.updateElementName(old_name, new_name)
  1072                 self.BufferProject()
  1072                 self.BufferProject()
  1073     
  1073 
  1074     # Change the name of a pou
  1074     # Change the name of a pou
  1075     def ChangePouName(self, old_name, new_name):
  1075     def ChangePouName(self, old_name, new_name):
  1076         if self.Project is not None:
  1076         if self.Project is not None:
  1077             # Found the pou corresponding to old name and change its name to new name
  1077             # Found the pou corresponding to old name and change its name to new name
  1078             pou = self.Project.getpou(old_name)
  1078             pou = self.Project.getpou(old_name)
  1079             if pou is not None:
  1079             if pou is not None:
  1080                 pou.setname(new_name)
  1080                 pou.setname(new_name)
  1081                 self.Project.updateElementName(old_name, new_name)
  1081                 self.Project.updateElementName(old_name, new_name)
  1082                 self.BufferProject()
  1082                 self.BufferProject()
  1083     
  1083 
  1084     # Change the name of a pou transition
  1084     # Change the name of a pou transition
  1085     def ChangePouTransitionName(self, pou_name, old_name, new_name):
  1085     def ChangePouTransitionName(self, pou_name, old_name, new_name):
  1086         if self.Project is not None:
  1086         if self.Project is not None:
  1087             # Found the pou transition corresponding to old name and change its name to new name
  1087             # Found the pou transition corresponding to old name and change its name to new name
  1088             pou = self.Project.getpou(pou_name)
  1088             pou = self.Project.getpou(pou_name)
  1090                 transition = pou.gettransition(old_name)
  1090                 transition = pou.gettransition(old_name)
  1091                 if transition is not None:
  1091                 if transition is not None:
  1092                     transition.setname(new_name)
  1092                     transition.setname(new_name)
  1093                     pou.updateElementName(old_name, new_name)
  1093                     pou.updateElementName(old_name, new_name)
  1094                     self.BufferProject()
  1094                     self.BufferProject()
  1095     
  1095 
  1096     # Change the name of a pou action
  1096     # Change the name of a pou action
  1097     def ChangePouActionName(self, pou_name, old_name, new_name):
  1097     def ChangePouActionName(self, pou_name, old_name, new_name):
  1098         if self.Project is not None:
  1098         if self.Project is not None:
  1099             # Found the pou action corresponding to old name and change its name to new name
  1099             # Found the pou action corresponding to old name and change its name to new name
  1100             pou = self.Project.getpou(pou_name)
  1100             pou = self.Project.getpou(pou_name)
  1102                 action = pou.getaction(old_name)
  1102                 action = pou.getaction(old_name)
  1103                 if action is not None:
  1103                 if action is not None:
  1104                     action.setname(new_name)
  1104                     action.setname(new_name)
  1105                     pou.updateElementName(old_name, new_name)
  1105                     pou.updateElementName(old_name, new_name)
  1106                     self.BufferProject()
  1106                     self.BufferProject()
  1107     
  1107 
  1108     # Change the name of a pou variable
  1108     # Change the name of a pou variable
  1109     def ChangePouVariableName(self, pou_name, old_name, new_name):
  1109     def ChangePouVariableName(self, pou_name, old_name, new_name):
  1110         if self.Project is not None:
  1110         if self.Project is not None:
  1111             # Found the pou action corresponding to old name and change its name to new name
  1111             # Found the pou action corresponding to old name and change its name to new name
  1112             pou = self.Project.getpou(pou_name)
  1112             pou = self.Project.getpou(pou_name)
  1114                 for type, varlist in pou.getvars():
  1114                 for type, varlist in pou.getvars():
  1115                     for var in varlist.getvariable():
  1115                     for var in varlist.getvariable():
  1116                         if var.getname() == old_name:
  1116                         if var.getname() == old_name:
  1117                             var.setname(new_name)
  1117                             var.setname(new_name)
  1118                 self.BufferProject()
  1118                 self.BufferProject()
  1119         
  1119 
  1120     # Change the name of a configuration
  1120     # Change the name of a configuration
  1121     def ChangeConfigurationName(self, old_name, new_name):
  1121     def ChangeConfigurationName(self, old_name, new_name):
  1122         if self.Project is not None:
  1122         if self.Project is not None:
  1123             # Found the configuration corresponding to old name and change its name to new name
  1123             # Found the configuration corresponding to old name and change its name to new name
  1124             configuration = self.Project.getconfiguration(old_name)
  1124             configuration = self.Project.getconfiguration(old_name)
  1125             if configuration is not None:
  1125             if configuration is not None:
  1126                 configuration.setname(new_name)
  1126                 configuration.setname(new_name)
  1127                 self.BufferProject()
  1127                 self.BufferProject()
  1128     
  1128 
  1129     # Change the name of a configuration resource
  1129     # Change the name of a configuration resource
  1130     def ChangeConfigurationResourceName(self, config_name, old_name, new_name):
  1130     def ChangeConfigurationResourceName(self, config_name, old_name, new_name):
  1131         if self.Project is not None:
  1131         if self.Project is not None:
  1132             # Found the resource corresponding to old name and change its name to new name
  1132             # Found the resource corresponding to old name and change its name to new name
  1133             resource = self.Project.getconfigurationResource(config_name, old_name)
  1133             resource = self.Project.getconfigurationResource(config_name, old_name)
  1134             if resource is not None:
  1134             if resource is not None:
  1135                 resource.setname(new_name)
  1135                 resource.setname(new_name)
  1136                 self.BufferProject()
  1136                 self.BufferProject()
  1137     
  1137 
  1138     # Return the description of the pou given by its name
  1138     # Return the description of the pou given by its name
  1139     def GetPouDescription(self, name, debug = False):
  1139     def GetPouDescription(self, name, debug = False):
  1140         project = self.GetProject(debug)
  1140         project = self.GetProject(debug)
  1141         if project is not None:
  1141         if project is not None:
  1142             # Found the pou correponding to name and return its type
  1142             # Found the pou correponding to name and return its type
  1143             pou = project.getpou(name)
  1143             pou = project.getpou(name)
  1144             if pou is not None:
  1144             if pou is not None:
  1145                 return pou.getdescription()
  1145                 return pou.getdescription()
  1146         return ""
  1146         return ""
  1147     
  1147 
  1148     # Return the description of the pou given by its name
  1148     # Return the description of the pou given by its name
  1149     def SetPouDescription(self, name, description, debug = False):
  1149     def SetPouDescription(self, name, description, debug = False):
  1150         project = self.GetProject(debug)
  1150         project = self.GetProject(debug)
  1151         if project is not None:
  1151         if project is not None:
  1152             # Found the pou correponding to name and return its type
  1152             # Found the pou correponding to name and return its type
  1153             pou = project.getpou(name)
  1153             pou = project.getpou(name)
  1154             if pou is not None:
  1154             if pou is not None:
  1155                 pou.setdescription(description)
  1155                 pou.setdescription(description)
  1156                 self.BufferProject()
  1156                 self.BufferProject()
  1157     
  1157 
  1158     # Return the type of the pou given by its name
  1158     # Return the type of the pou given by its name
  1159     def GetPouType(self, name, debug = False):
  1159     def GetPouType(self, name, debug = False):
  1160         project = self.GetProject(debug)
  1160         project = self.GetProject(debug)
  1161         if project is not None:
  1161         if project is not None:
  1162             # Found the pou correponding to name and return its type
  1162             # Found the pou correponding to name and return its type
  1163             pou = project.getpou(name)
  1163             pou = project.getpou(name)
  1164             if pou is not None:
  1164             if pou is not None:
  1165                 return pou.getpouType()
  1165                 return pou.getpouType()
  1166         return None
  1166         return None
  1167     
  1167 
  1168     # Return pous with SFC language
  1168     # Return pous with SFC language
  1169     def GetSFCPous(self, debug = False):
  1169     def GetSFCPous(self, debug = False):
  1170         list = []
  1170         list = []
  1171         project = self.GetProject(debug)
  1171         project = self.GetProject(debug)
  1172         if project is not None:
  1172         if project is not None:
  1173             for pou in project.getpous():
  1173             for pou in project.getpous():
  1174                 if pou.getBodyType() == "SFC":
  1174                 if pou.getBodyType() == "SFC":
  1175                     list.append(pou.getname())
  1175                     list.append(pou.getname())
  1176         return list
  1176         return list
  1177     
  1177 
  1178     # Return the body language of the pou given by its name
  1178     # Return the body language of the pou given by its name
  1179     def GetPouBodyType(self, name, debug = False):
  1179     def GetPouBodyType(self, name, debug = False):
  1180         project = self.GetProject(debug)
  1180         project = self.GetProject(debug)
  1181         if project is not None:
  1181         if project is not None:
  1182             # Found the pou correponding to name and return its body language
  1182             # Found the pou correponding to name and return its body language
  1183             pou = project.getpou(name)
  1183             pou = project.getpou(name)
  1184             if pou is not None:
  1184             if pou is not None:
  1185                 return pou.getbodyType()
  1185                 return pou.getbodyType()
  1186         return None
  1186         return None
  1187     
  1187 
  1188     # Return the actions of a pou
  1188     # Return the actions of a pou
  1189     def GetPouTransitions(self, pou_name, debug = False):
  1189     def GetPouTransitions(self, pou_name, debug = False):
  1190         transitions = []
  1190         transitions = []
  1191         project = self.GetProject(debug)
  1191         project = self.GetProject(debug)
  1192         if project is not None:
  1192         if project is not None:
  1194             pou = project.getpou(pou_name)
  1194             pou = project.getpou(pou_name)
  1195             if pou is not None and pou.getbodyType() == "SFC":
  1195             if pou is not None and pou.getbodyType() == "SFC":
  1196                 for transition in pou.gettransitionList():
  1196                 for transition in pou.gettransitionList():
  1197                     transitions.append(transition.getname())
  1197                     transitions.append(transition.getname())
  1198         return transitions
  1198         return transitions
  1199     
  1199 
  1200     # Return the body language of the transition given by its name
  1200     # Return the body language of the transition given by its name
  1201     def GetTransitionBodyType(self, pou_name, pou_transition, debug = False):
  1201     def GetTransitionBodyType(self, pou_name, pou_transition, debug = False):
  1202         project = self.GetProject(debug)
  1202         project = self.GetProject(debug)
  1203         if project is not None:
  1203         if project is not None:
  1204             # Found the pou correponding to name
  1204             # Found the pou correponding to name
  1207                 # Found the pou transition correponding to name and return its body language
  1207                 # Found the pou transition correponding to name and return its body language
  1208                 transition = pou.gettransition(pou_transition)
  1208                 transition = pou.gettransition(pou_transition)
  1209                 if transition is not None:
  1209                 if transition is not None:
  1210                     return transition.getbodyType()
  1210                     return transition.getbodyType()
  1211         return None
  1211         return None
  1212     
  1212 
  1213     # Return the actions of a pou
  1213     # Return the actions of a pou
  1214     def GetPouActions(self, pou_name, debug = False):
  1214     def GetPouActions(self, pou_name, debug = False):
  1215         actions = []
  1215         actions = []
  1216         project = self.GetProject(debug)
  1216         project = self.GetProject(debug)
  1217         if project is not None:
  1217         if project is not None:
  1219             pou = project.getpou(pou_name)
  1219             pou = project.getpou(pou_name)
  1220             if pou.getbodyType() == "SFC":
  1220             if pou.getbodyType() == "SFC":
  1221                 for action in pou.getactionList():
  1221                 for action in pou.getactionList():
  1222                     actions.append(action.getname())
  1222                     actions.append(action.getname())
  1223         return actions
  1223         return actions
  1224     
  1224 
  1225     # Return the body language of the pou given by its name
  1225     # Return the body language of the pou given by its name
  1226     def GetActionBodyType(self, pou_name, pou_action, debug = False):
  1226     def GetActionBodyType(self, pou_name, pou_action, debug = False):
  1227         project = self.GetProject(debug)
  1227         project = self.GetProject(debug)
  1228         if project is not None:
  1228         if project is not None:
  1229             # Found the pou correponding to name and return its body language
  1229             # Found the pou correponding to name and return its body language
  1231             if pou is not None:
  1231             if pou is not None:
  1232                 action = pou.getaction(pou_action)
  1232                 action = pou.getaction(pou_action)
  1233                 if action is not None:
  1233                 if action is not None:
  1234                     return action.getbodyType()
  1234                     return action.getbodyType()
  1235         return None
  1235         return None
  1236     
  1236 
  1237     # Extract varlists from a list of vars
  1237     # Extract varlists from a list of vars
  1238     def ExtractVarLists(self, vars):
  1238     def ExtractVarLists(self, vars):
  1239         varlist_list = []
  1239         varlist_list = []
  1240         current_varlist = None
  1240         current_varlist = None
  1241         current_type = None
  1241         current_type = None
  1242         for var in vars:
  1242         for var in vars:
  1243             next_type = (var.Class, 
  1243             next_type = (var.Class,
  1244                          var.Option, 
  1244                          var.Option,
  1245                          var.Location in ["", None] or 
  1245                          var.Location in ["", None] or
  1246                          # When declaring globals, located 
  1246                          # When declaring globals, located
  1247                          # and not located variables are 
  1247                          # and not located variables are
  1248                          # in the same declaration block
  1248                          # in the same declaration block
  1249                          var.Class == "Global")
  1249                          var.Class == "Global")
  1250             if current_type != next_type:
  1250             if current_type != next_type:
  1251                 current_type = next_type
  1251                 current_type = next_type
  1252                 infos = VAR_CLASS_INFOS.get(var.Class, None)
  1252                 infos = VAR_CLASS_INFOS.get(var.Class, None)
  1262                 elif var.Option == "Non-Retain":
  1262                 elif var.Option == "Non-Retain":
  1263                     current_varlist.setnonretain(True)
  1263                     current_varlist.setnonretain(True)
  1264             # Create variable and change its properties
  1264             # Create variable and change its properties
  1265             tempvar = PLCOpenParser.CreateElement("variable", "varListPlain")
  1265             tempvar = PLCOpenParser.CreateElement("variable", "varListPlain")
  1266             tempvar.setname(var.Name)
  1266             tempvar.setname(var.Name)
  1267             
  1267 
  1268             var_type = PLCOpenParser.CreateElement("type", "variable")
  1268             var_type = PLCOpenParser.CreateElement("type", "variable")
  1269             if isinstance(var.Type, TupleType):
  1269             if isinstance(var.Type, TupleType):
  1270                 if var.Type[0] == "array":
  1270                 if var.Type[0] == "array":
  1271                     array_type, base_type_name, dimensions = var.Type
  1271                     array_type, base_type_name, dimensions = var.Type
  1272                     array = PLCOpenParser.CreateElement("array", "dataType")
  1272                     array = PLCOpenParser.CreateElement("array", "dataType")
  1315                 tempvar.setdocumentation(ft)
  1315                 tempvar.setdocumentation(ft)
  1316 
  1316 
  1317             # Add variable to varList
  1317             # Add variable to varList
  1318             current_varlist.appendvariable(tempvar)
  1318             current_varlist.appendvariable(tempvar)
  1319         return varlist_list
  1319         return varlist_list
  1320     
  1320 
  1321     def GetVariableDictionary(self, object_with_vars, tree=False, debug=False):
  1321     def GetVariableDictionary(self, object_with_vars, tree=False, debug=False):
  1322         variables = []
  1322         variables = []
  1323         factory = VariablesInfosFactory(variables)
  1323         factory = VariablesInfosFactory(variables)
  1324         
  1324 
  1325         parser = etree.XMLParser()
  1325         parser = etree.XMLParser()
  1326         parser.resolvers.add(LibraryResolver(self, debug))
  1326         parser.resolvers.add(LibraryResolver(self, debug))
  1327         
  1327 
  1328         variables_infos_xslt_tree = etree.XSLT(
  1328         variables_infos_xslt_tree = etree.XSLT(
  1329             etree.parse(
  1329             etree.parse(
  1330                 os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"),
  1330                 os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"),
  1331                 parser), 
  1331                 parser),
  1332             extensions = {("var_infos_ns", name): getattr(factory, name)
  1332             extensions = {("var_infos_ns", name): getattr(factory, name)
  1333                 for name in ["SetType", "AddDimension", "AddTree",
  1333                 for name in ["SetType", "AddDimension", "AddTree",
  1334                              "AddVarToTree", "AddVariable"]})
  1334                              "AddVarToTree", "AddVariable"]})
  1335         variables_infos_xslt_tree(object_with_vars,
  1335         variables_infos_xslt_tree(object_with_vars,
  1336             tree=etree.XSLT.strparam(str(tree)))
  1336             tree=etree.XSLT.strparam(str(tree)))
  1337         
  1337 
  1338         return variables
  1338         return variables
  1339             
  1339 
  1340     # Add a global var to configuration to configuration
  1340     # Add a global var to configuration to configuration
  1341     def AddConfigurationGlobalVar(self, config_name, var_type, var_name, 
  1341     def AddConfigurationGlobalVar(self, config_name, var_type, var_name,
  1342                                            location="", description=""):
  1342                                            location="", description=""):
  1343         if self.Project is not None:
  1343         if self.Project is not None:
  1344             # Found the configuration corresponding to name
  1344             # Found the configuration corresponding to name
  1345             configuration = self.Project.getconfiguration(config_name)
  1345             configuration = self.Project.getconfiguration(config_name)
  1346             if configuration is not None:
  1346             if configuration is not None:
  1347                 # Set configuration global vars
  1347                 # Set configuration global vars
  1348                 configuration.addglobalVar(
  1348                 configuration.addglobalVar(
  1349                     self.GetVarTypeObject(var_type), 
  1349                     self.GetVarTypeObject(var_type),
  1350                     var_name, location, description)
  1350                     var_name, location, description)
  1351 
  1351 
  1352     # Replace the configuration globalvars by those given
  1352     # Replace the configuration globalvars by those given
  1353     def SetConfigurationGlobalVars(self, name, vars):
  1353     def SetConfigurationGlobalVars(self, name, vars):
  1354         if self.Project is not None:
  1354         if self.Project is not None:
  1357             if configuration is not None:
  1357             if configuration is not None:
  1358                 # Set configuration global vars
  1358                 # Set configuration global vars
  1359                 configuration.setglobalVars([
  1359                 configuration.setglobalVars([
  1360                     varlist for vartype, varlist
  1360                     varlist for vartype, varlist
  1361                     in self.ExtractVarLists(vars)])
  1361                     in self.ExtractVarLists(vars)])
  1362     
  1362 
  1363     # Return the configuration globalvars
  1363     # Return the configuration globalvars
  1364     def GetConfigurationGlobalVars(self, name, debug = False):
  1364     def GetConfigurationGlobalVars(self, name, debug = False):
  1365         project = self.GetProject(debug)
  1365         project = self.GetProject(debug)
  1366         if project is not None:
  1366         if project is not None:
  1367             # Found the configuration corresponding to name
  1367             # Found the configuration corresponding to name
  1368             configuration = project.getconfiguration(name)
  1368             configuration = project.getconfiguration(name)
  1369             if configuration is not None:
  1369             if configuration is not None:
  1370                 # Extract variables defined in configuration
  1370                 # Extract variables defined in configuration
  1371                 return self.GetVariableDictionary(configuration, debug)
  1371                 return self.GetVariableDictionary(configuration, debug)
  1372         
  1372 
  1373         return []
  1373         return []
  1374 
  1374 
  1375     # Return configuration variable names
  1375     # Return configuration variable names
  1376     def GetConfigurationVariableNames(self, config_name = None, debug = False):
  1376     def GetConfigurationVariableNames(self, config_name = None, debug = False):
  1377         variables = []
  1377         variables = []
  1379         if project is not None:
  1379         if project is not None:
  1380             for configuration in self.Project.getconfigurations():
  1380             for configuration in self.Project.getconfigurations():
  1381                 if config_name is None or config_name == configuration.getname():
  1381                 if config_name is None or config_name == configuration.getname():
  1382                     variables.extend(
  1382                     variables.extend(
  1383                         [var.getname() for var in reduce(
  1383                         [var.getname() for var in reduce(
  1384                             lambda x, y: x + y, [varlist.getvariable() 
  1384                             lambda x, y: x + y, [varlist.getvariable()
  1385                                 for varlist in configuration.globalVars],
  1385                                 for varlist in configuration.globalVars],
  1386                             [])])
  1386                             [])])
  1387         return variables
  1387         return variables
  1388 
  1388 
  1389     # Replace the resource globalvars by those given
  1389     # Replace the resource globalvars by those given
  1394             # Set resource global vars
  1394             # Set resource global vars
  1395             if resource is not None:
  1395             if resource is not None:
  1396                 resource.setglobalVars([
  1396                 resource.setglobalVars([
  1397                     varlist for vartype, varlist
  1397                     varlist for vartype, varlist
  1398                     in self.ExtractVarLists(vars)])
  1398                     in self.ExtractVarLists(vars)])
  1399     
  1399 
  1400     # Return the resource globalvars
  1400     # Return the resource globalvars
  1401     def GetConfigurationResourceGlobalVars(self, config_name, name, debug = False):
  1401     def GetConfigurationResourceGlobalVars(self, config_name, name, debug = False):
  1402         project = self.GetProject(debug)
  1402         project = self.GetProject(debug)
  1403         if project is not None:
  1403         if project is not None:
  1404             # Found the resource corresponding to name
  1404             # Found the resource corresponding to name
  1405             resource = project.getconfigurationResource(config_name, name)
  1405             resource = project.getconfigurationResource(config_name, name)
  1406             if resource is not None:
  1406             if resource is not None:
  1407                 # Extract variables defined in configuration
  1407                 # Extract variables defined in configuration
  1408                 return self.GetVariableDictionary(resource, debug)
  1408                 return self.GetVariableDictionary(resource, debug)
  1409         
  1409 
  1410         return []
  1410         return []
  1411     
  1411 
  1412     # Return resource variable names
  1412     # Return resource variable names
  1413     def GetConfigurationResourceVariableNames(self, 
  1413     def GetConfigurationResourceVariableNames(self,
  1414                 config_name = None, resource_name = None, debug = False):
  1414                 config_name = None, resource_name = None, debug = False):
  1415         variables = []
  1415         variables = []
  1416         project = self.GetProject(debug)
  1416         project = self.GetProject(debug)
  1417         if project is not None:
  1417         if project is not None:
  1418             for configuration in self.Project.getconfigurations():
  1418             for configuration in self.Project.getconfigurations():
  1419                 if config_name is None or config_name == configuration.getname():
  1419                 if config_name is None or config_name == configuration.getname():
  1420                     for resource in configuration.getresource():
  1420                     for resource in configuration.getresource():
  1421                         if resource_name is None or resource.getname() == resource_name:
  1421                         if resource_name is None or resource.getname() == resource_name:
  1422                             variables.extend(
  1422                             variables.extend(
  1423                                 [var.getname() for var in reduce(
  1423                                 [var.getname() for var in reduce(
  1424                                     lambda x, y: x + y, [varlist.getvariable() 
  1424                                     lambda x, y: x + y, [varlist.getvariable()
  1425                                         for varlist in resource.globalVars],
  1425                                         for varlist in resource.globalVars],
  1426                                     [])])
  1426                                     [])])
  1427         return variables
  1427         return variables
  1428 
  1428 
  1429     # Return the interface for the given pou
  1429     # Return the interface for the given pou
  1443             if pou is not None:
  1443             if pou is not None:
  1444                 if pou.interface is None:
  1444                 if pou.interface is None:
  1445                     pou.interface = PLCOpenParser.CreateElement("interface", "pou")
  1445                     pou.interface = PLCOpenParser.CreateElement("interface", "pou")
  1446                 # Set Pou interface
  1446                 # Set Pou interface
  1447                 pou.setvars([varlist for varlist_type, varlist in self.ExtractVarLists(vars)])
  1447                 pou.setvars([varlist for varlist_type, varlist in self.ExtractVarLists(vars)])
  1448                 
  1448 
  1449     # Replace the return type of the pou given by its name (only for functions)
  1449     # Replace the return type of the pou given by its name (only for functions)
  1450     def SetPouInterfaceReturnType(self, name, return_type):
  1450     def SetPouInterfaceReturnType(self, name, return_type):
  1451         if self.Project is not None:
  1451         if self.Project is not None:
  1452             pou = self.Project.getpou(name)
  1452             pou = self.Project.getpou(name)
  1453             if pou is not None:
  1453             if pou is not None:
  1466                         else return_type, "dataType"))
  1466                         else return_type, "dataType"))
  1467                 else:
  1467                 else:
  1468                     derived_type = PLCOpenParser.CreateElement("derived", "dataType")
  1468                     derived_type = PLCOpenParser.CreateElement("derived", "dataType")
  1469                     derived_type.setname(return_type)
  1469                     derived_type.setname(return_type)
  1470                     return_type.setcontent(derived_type)
  1470                     return_type.setcontent(derived_type)
  1471                 
  1471 
  1472     def UpdateProjectUsedPous(self, old_name, new_name):
  1472     def UpdateProjectUsedPous(self, old_name, new_name):
  1473         if self.Project is not None:
  1473         if self.Project is not None:
  1474             self.Project.updateElementName(old_name, new_name)
  1474             self.Project.updateElementName(old_name, new_name)
  1475     
  1475 
  1476     def UpdateEditedElementUsedVariable(self, tagname, old_name, new_name):
  1476     def UpdateEditedElementUsedVariable(self, tagname, old_name, new_name):
  1477         pou = self.GetEditedElement(tagname)
  1477         pou = self.GetEditedElement(tagname)
  1478         if pou is not None:
  1478         if pou is not None:
  1479             pou.updateElementName(old_name, new_name)
  1479             pou.updateElementName(old_name, new_name)
  1480     
  1480 
  1481     # Return the return type of the given pou
  1481     # Return the return type of the given pou
  1482     def GetPouInterfaceReturnType(self, pou, tree=False, debug=False):
  1482     def GetPouInterfaceReturnType(self, pou, tree=False, debug=False):
  1483         # Verify that the pou has an interface
  1483         # Verify that the pou has an interface
  1484         if pou.interface is not None:
  1484         if pou.interface is not None:
  1485             # Return the return type if there is one
  1485             # Return the return type if there is one
  1486             return_type = pou.interface.getreturnType()
  1486             return_type = pou.interface.getreturnType()
  1487             if return_type is not None:
  1487             if return_type is not None:
  1488                 factory = VariablesInfosFactory([])
  1488                 factory = VariablesInfosFactory([])
  1489         
  1489 
  1490                 parser = etree.XMLParser()
  1490                 parser = etree.XMLParser()
  1491                 parser.resolvers.add(LibraryResolver(self))
  1491                 parser.resolvers.add(LibraryResolver(self))
  1492                 
  1492 
  1493                 return_type_infos_xslt_tree = etree.XSLT(
  1493                 return_type_infos_xslt_tree = etree.XSLT(
  1494                     etree.parse(
  1494                     etree.parse(
  1495                         os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"),
  1495                         os.path.join(ScriptDirectory, "plcopen", "variables_infos.xslt"),
  1496                         parser), 
  1496                         parser),
  1497                     extensions = {("var_infos_ns", name): getattr(factory, name)
  1497                     extensions = {("var_infos_ns", name): getattr(factory, name)
  1498                                   for name in ["SetType", "AddDimension", 
  1498                                   for name in ["SetType", "AddDimension",
  1499                                                "AddTree", "AddVarToTree"]})
  1499                                                "AddTree", "AddVarToTree"]})
  1500                 return_type_infos_xslt_tree(return_type,
  1500                 return_type_infos_xslt_tree(return_type,
  1501                     tree=etree.XSLT.strparam(str(tree)))
  1501                     tree=etree.XSLT.strparam(str(tree)))
  1502                 if tree:
  1502                 if tree:
  1503                     return [factory.GetType(), factory.GetTree()]
  1503                     return [factory.GetType(), factory.GetTree()]
  1504                 return factory.GetType()
  1504                 return factory.GetType()
  1505         
  1505 
  1506         if tree:
  1506         if tree:
  1507             return [None, ([], [])]
  1507             return [None, ([], [])]
  1508         return None
  1508         return None
  1509 
  1509 
  1510     # Function that add a new confnode to the confnode list
  1510     # Function that add a new confnode to the confnode list
  1517         self.TotalTypes.extend(addedcat)
  1517         self.TotalTypes.extend(addedcat)
  1518         for cat in addedcat:
  1518         for cat in addedcat:
  1519             for desc in cat["list"]:
  1519             for desc in cat["list"]:
  1520                 BlkLst = self.TotalTypesDict.setdefault(desc["name"],[])
  1520                 BlkLst = self.TotalTypesDict.setdefault(desc["name"],[])
  1521                 BlkLst.append((section["name"], desc))
  1521                 BlkLst.append((section["name"], desc))
  1522         
  1522 
  1523     # Function that clear the confnode list
  1523     # Function that clear the confnode list
  1524     def ClearConfNodeTypes(self):
  1524     def ClearConfNodeTypes(self):
  1525         self.ConfNodeTypes = []
  1525         self.ConfNodeTypes = []
  1526         self.TotalTypesDict = StdBlckDct.copy()
  1526         self.TotalTypesDict = StdBlckDct.copy()
  1527         self.TotalTypes = StdBlckLst[:]
  1527         self.TotalTypes = StdBlckLst[:]
  1528 
  1528 
  1529     def GetConfNodeDataTypes(self, exclude = None, only_locatables = False):
  1529     def GetConfNodeDataTypes(self, exclude = None, only_locatables = False):
  1530         return [{"name": _("%s Data Types") % confnodetypes["name"],
  1530         return [{"name": _("%s Data Types") % confnodetypes["name"],
  1531                  "list": [
  1531                  "list": [
  1532                     datatype.getname() 
  1532                     datatype.getname()
  1533                     for datatype in confnodetypes["types"].getdataTypes()
  1533                     for datatype in confnodetypes["types"].getdataTypes()
  1534                     if not only_locatables or self.IsLocatableDataType(datatype, debug)]}
  1534                     if not only_locatables or self.IsLocatableDataType(datatype, debug)]}
  1535                 for confnodetypes in self.ConfNodeTypes]
  1535                 for confnodetypes in self.ConfNodeTypes]
  1536     
  1536 
  1537     def GetVariableLocationTree(self):
  1537     def GetVariableLocationTree(self):
  1538         return []
  1538         return []
  1539 
  1539 
  1540     def GetConfNodeGlobalInstances(self):
  1540     def GetConfNodeGlobalInstances(self):
  1541         return []
  1541         return []
  1543     def GetConfigurationExtraVariables(self):
  1543     def GetConfigurationExtraVariables(self):
  1544         global_vars = []
  1544         global_vars = []
  1545         for var_name, var_type, var_initial in self.GetConfNodeGlobalInstances():
  1545         for var_name, var_type, var_initial in self.GetConfNodeGlobalInstances():
  1546             tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
  1546             tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
  1547             tempvar.setname(var_name)
  1547             tempvar.setname(var_name)
  1548             
  1548 
  1549             tempvartype = PLCOpenParser.CreateElement("type", "variable")
  1549             tempvartype = PLCOpenParser.CreateElement("type", "variable")
  1550             if var_type in self.GetBaseTypes():
  1550             if var_type in self.GetBaseTypes():
  1551                 tempvartype.setcontent(PLCOpenParser.CreateElement(
  1551                 tempvartype.setcontent(PLCOpenParser.CreateElement(
  1552                     var_type.lower()
  1552                     var_type.lower()
  1553                     if var_type in ["STRING", "WSTRING"]
  1553                     if var_type in ["STRING", "WSTRING"]
  1555             else:
  1555             else:
  1556                 tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType")
  1556                 tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType")
  1557                 tempderivedtype.setname(var_type)
  1557                 tempderivedtype.setname(var_type)
  1558                 tempvartype.setcontent(tempderivedtype)
  1558                 tempvartype.setcontent(tempderivedtype)
  1559             tempvar.settype(tempvartype)
  1559             tempvar.settype(tempvartype)
  1560             
  1560 
  1561             if var_initial != "":
  1561             if var_initial != "":
  1562                 value = PLCOpenParser.CreateElement("initialValue", "variable")
  1562                 value = PLCOpenParser.CreateElement("initialValue", "variable")
  1563                 value.setvalue(var_initial)
  1563                 value.setvalue(var_initial)
  1564                 tempvar.setinitialValue(value)
  1564                 tempvar.setinitialValue(value)
  1565             
  1565 
  1566             global_vars.append(tempvar)
  1566             global_vars.append(tempvar)
  1567         return global_vars
  1567         return global_vars
  1568 
  1568 
  1569     # Function that returns the block definition associated to the block type given
  1569     # Function that returns the block definition associated to the block type given
  1570     def GetBlockType(self, typename, inputs = None, debug = False):
  1570     def GetBlockType(self, typename, inputs = None, debug = False):
  1590             blocktype = project.getpou(typename)
  1590             blocktype = project.getpou(typename)
  1591             if blocktype is not None:
  1591             if blocktype is not None:
  1592                 blocktype_infos = blocktype.getblockInfos()
  1592                 blocktype_infos = blocktype.getblockInfos()
  1593                 if inputs in [None, "undefined"]:
  1593                 if inputs in [None, "undefined"]:
  1594                     return blocktype_infos
  1594                     return blocktype_infos
  1595             
  1595 
  1596                 if inputs == tuple([var_type 
  1596                 if inputs == tuple([var_type
  1597                     for name, var_type, modifier in blocktype_infos["inputs"]]):
  1597                     for name, var_type, modifier in blocktype_infos["inputs"]]):
  1598                     return blocktype_infos
  1598                     return blocktype_infos
  1599         
  1599 
  1600         return None
  1600         return None
  1601 
  1601 
  1602     # Return Block types checking for recursion
  1602     # Return Block types checking for recursion
  1603     def GetBlockTypes(self, tagname = "", debug = False):
  1603     def GetBlockTypes(self, tagname = "", debug = False):
  1604         typename = None
  1604         typename = None
  1608         if project is not None:
  1608         if project is not None:
  1609             pou_type = None
  1609             pou_type = None
  1610             if words[0] in ["P","T","A"]:
  1610             if words[0] in ["P","T","A"]:
  1611                 name = words[1]
  1611                 name = words[1]
  1612                 pou_type = self.GetPouType(name, debug)
  1612                 pou_type = self.GetPouType(name, debug)
  1613             filter = (["function"] 
  1613             filter = (["function"]
  1614                       if pou_type == "function" or words[0] == "T" 
  1614                       if pou_type == "function" or words[0] == "T"
  1615                       else ["functionBlock", "function"])
  1615                       else ["functionBlock", "function"])
  1616             blocktypes = [
  1616             blocktypes = [
  1617                 {"name": category["name"],
  1617                 {"name": category["name"],
  1618                  "list": [block for block in category["list"]
  1618                  "list": [block for block in category["list"]
  1619                           if block["type"] in filter]}
  1619                           if block["type"] in filter]}
  1620                 for category in self.TotalTypes]
  1620                 for category in self.TotalTypes]
  1621             blocktypes.append({"name" : USER_DEFINED_POUS, 
  1621             blocktypes.append({"name" : USER_DEFINED_POUS,
  1622                 "list": [pou.getblockInfos()
  1622                 "list": [pou.getblockInfos()
  1623                          for pou in project.getpous(name, filter)
  1623                          for pou in project.getpous(name, filter)
  1624                          if (name is None or 
  1624                          if (name is None or
  1625                              len(self.GetInstanceList(pou, name, debug)) == 0)]})
  1625                              len(self.GetInstanceList(pou, name, debug)) == 0)]})
  1626             return blocktypes
  1626             return blocktypes
  1627         return self.TotalTypes
  1627         return self.TotalTypes
  1628 
  1628 
  1629     # Return Function Block types checking for recursion
  1629     # Return Function Block types checking for recursion
  1639                 if block["type"] == "functionBlock":
  1639                 if block["type"] == "functionBlock":
  1640                     blocktypes.append(block["name"])
  1640                     blocktypes.append(block["name"])
  1641         if project is not None:
  1641         if project is not None:
  1642             blocktypes.extend([pou.getname()
  1642             blocktypes.extend([pou.getname()
  1643                 for pou in project.getpous(name, ["functionBlock"])
  1643                 for pou in project.getpous(name, ["functionBlock"])
  1644                 if (name is None or 
  1644                 if (name is None or
  1645                     len(self.GetInstanceList(pou, name, debug)) == 0)])
  1645                     len(self.GetInstanceList(pou, name, debug)) == 0)])
  1646         return blocktypes
  1646         return blocktypes
  1647 
  1647 
  1648     # Return Block types checking for recursion
  1648     # Return Block types checking for recursion
  1649     def GetBlockResource(self, debug = False):
  1649     def GetBlockResource(self, debug = False):
  1670         if project is not None:
  1670         if project is not None:
  1671             words = tagname.split("::")
  1671             words = tagname.split("::")
  1672             if words[0] in ["D"]:
  1672             if words[0] in ["D"]:
  1673                 name = words[1]
  1673                 name = words[1]
  1674             datatypes.extend([
  1674             datatypes.extend([
  1675                 datatype.getname() 
  1675                 datatype.getname()
  1676                 for datatype in project.getdataTypes(name)
  1676                 for datatype in project.getdataTypes(name)
  1677                 if (not only_locatables or self.IsLocatableDataType(datatype, debug))
  1677                 if (not only_locatables or self.IsLocatableDataType(datatype, debug))
  1678                     and (name is None or 
  1678                     and (name is None or
  1679                          len(self.GetInstanceList(datatype, name, debug)) == 0)])
  1679                          len(self.GetInstanceList(datatype, name, debug)) == 0)])
  1680         if confnodetypes:
  1680         if confnodetypes:
  1681             for category in self.GetConfNodeDataTypes(name, only_locatables):
  1681             for category in self.GetConfNodeDataTypes(name, only_locatables):
  1682                 datatypes.extend(category["list"])
  1682                 datatypes.extend(category["list"])
  1683         return datatypes
  1683         return datatypes
  1728 
  1728 
  1729     # Return Base Type of given possible derived type
  1729     # Return Base Type of given possible derived type
  1730     def GetBaseType(self, typename, debug = False):
  1730     def GetBaseType(self, typename, debug = False):
  1731         if TypeHierarchy.has_key(typename):
  1731         if TypeHierarchy.has_key(typename):
  1732             return typename
  1732             return typename
  1733         
  1733 
  1734         datatype = self.GetDataType(typename, debug)
  1734         datatype = self.GetDataType(typename, debug)
  1735         if datatype is not None:
  1735         if datatype is not None:
  1736             basetype = self.GetDataTypeBaseType(datatype)
  1736             basetype = self.GetDataTypeBaseType(datatype)
  1737             if basetype is not None:
  1737             if basetype is not None:
  1738                 return self.GetBaseType(basetype, debug)
  1738                 return self.GetBaseType(basetype, debug)
  1739             return typename
  1739             return typename
  1740         
  1740 
  1741         return None
  1741         return None
  1742 
  1742 
  1743     def GetBaseTypes(self):
  1743     def GetBaseTypes(self):
  1744         '''
  1744         '''
  1745         return the list of datatypes defined in IEC 61131-3.
  1745         return the list of datatypes defined in IEC 61131-3.
  1749         return [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]
  1749         return [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]
  1750 
  1750 
  1751     def IsOfType(self, typename, reference, debug = False):
  1751     def IsOfType(self, typename, reference, debug = False):
  1752         if reference is None or typename == reference:
  1752         if reference is None or typename == reference:
  1753             return True
  1753             return True
  1754         
  1754 
  1755         basetype = TypeHierarchy.get(typename)
  1755         basetype = TypeHierarchy.get(typename)
  1756         if basetype is not None:
  1756         if basetype is not None:
  1757             return self.IsOfType(basetype, reference)
  1757             return self.IsOfType(basetype, reference)
  1758         
  1758 
  1759         datatype = self.GetDataType(typename, debug)
  1759         datatype = self.GetDataType(typename, debug)
  1760         if datatype is not None:
  1760         if datatype is not None:
  1761             basetype = self.GetDataTypeBaseType(datatype)
  1761             basetype = self.GetDataTypeBaseType(datatype)
  1762             if basetype is not None:
  1762             if basetype is not None:
  1763                 return self.IsOfType(basetype, reference, debug)
  1763                 return self.IsOfType(basetype, reference, debug)
  1764         
  1764 
  1765         return False
  1765         return False
  1766     
  1766 
  1767     def IsEndType(self, typename):
  1767     def IsEndType(self, typename):
  1768         if typename is not None:
  1768         if typename is not None:
  1769             return not typename.startswith("ANY")
  1769             return not typename.startswith("ANY")
  1770         return True
  1770         return True
  1771 
  1771 
  1779         elif basetype_content_type == "array":
  1779         elif basetype_content_type == "array":
  1780             array_base_type = basetype_content.baseType.getcontent()
  1780             array_base_type = basetype_content.baseType.getcontent()
  1781             if array_base_type.getLocalTag() == "derived":
  1781             if array_base_type.getLocalTag() == "derived":
  1782                 return self.IsLocatableType(array_base_type.getname(), debug)
  1782                 return self.IsLocatableType(array_base_type.getname(), debug)
  1783         return True
  1783         return True
  1784         
  1784 
  1785     def IsLocatableType(self, typename, debug = False):
  1785     def IsLocatableType(self, typename, debug = False):
  1786         if isinstance(typename, TupleType) or self.GetBlockType(typename) is not None:
  1786         if isinstance(typename, TupleType) or self.GetBlockType(typename) is not None:
  1787             return False
  1787             return False
  1788         
  1788 
  1789         datatype = self.GetDataType(typename, debug)
  1789         datatype = self.GetDataType(typename, debug)
  1790         if datatype is not None:
  1790         if datatype is not None:
  1791             return self.IsLocatableDataType(datatype)
  1791             return self.IsLocatableDataType(datatype)
  1792         return True
  1792         return True
  1793     
  1793 
  1794     def IsEnumeratedType(self, typename, debug = False):
  1794     def IsEnumeratedType(self, typename, debug = False):
  1795         if isinstance(typename, TupleType):
  1795         if isinstance(typename, TupleType):
  1796             typename = typename[1]
  1796             typename = typename[1]
  1797         datatype = self.GetDataType(typename, debug)
  1797         datatype = self.GetDataType(typename, debug)
  1798         if datatype is not None:
  1798         if datatype is not None:
  1820         return False
  1820         return False
  1821 
  1821 
  1822     def IsNumType(self, typename, debug = False):
  1822     def IsNumType(self, typename, debug = False):
  1823         return self.IsOfType(typename, "ANY_NUM", debug) or\
  1823         return self.IsOfType(typename, "ANY_NUM", debug) or\
  1824                self.IsOfType(typename, "ANY_BIT", debug)
  1824                self.IsOfType(typename, "ANY_BIT", debug)
  1825             
  1825 
  1826     def GetDataTypeRange(self, typename, debug = False):
  1826     def GetDataTypeRange(self, typename, debug = False):
  1827         range = DataTypeRange.get(typename)
  1827         range = DataTypeRange.get(typename)
  1828         if range is not None:
  1828         if range is not None:
  1829             return range
  1829             return range
  1830         datatype = self.GetDataType(typename, debug)
  1830         datatype = self.GetDataType(typename, debug)
  1835                 return (basetype_content.range.getlower(),
  1835                 return (basetype_content.range.getlower(),
  1836                         basetype_content.range.getupper())
  1836                         basetype_content.range.getupper())
  1837             elif basetype_content_type == "derived":
  1837             elif basetype_content_type == "derived":
  1838                 return self.GetDataTypeRange(basetype_content.getname(), debug)
  1838                 return self.GetDataTypeRange(basetype_content.getname(), debug)
  1839         return None
  1839         return None
  1840     
  1840 
  1841     # Return Subrange types
  1841     # Return Subrange types
  1842     def GetSubrangeBaseTypes(self, exclude, debug = False):
  1842     def GetSubrangeBaseTypes(self, exclude, debug = False):
  1843         subrange_basetypes = DataTypeRange.keys()
  1843         subrange_basetypes = DataTypeRange.keys()
  1844         project = self.GetProject(debug)
  1844         project = self.GetProject(debug)
  1845         if project is not None:
  1845         if project is not None:
  1849         for confnodetype in self.ConfNodeTypes:
  1849         for confnodetype in self.ConfNodeTypes:
  1850             subrange_basetypes.extend(
  1850             subrange_basetypes.extend(
  1851                 [datatype.getname() for datatype in confnodetype["types"].getdataTypes()
  1851                 [datatype.getname() for datatype in confnodetype["types"].getdataTypes()
  1852                  if self.IsSubrangeType(datatype.getname(), exclude, debug)])
  1852                  if self.IsSubrangeType(datatype.getname(), exclude, debug)])
  1853         return subrange_basetypes
  1853         return subrange_basetypes
  1854     
  1854 
  1855     # Return Enumerated Values
  1855     # Return Enumerated Values
  1856     def GetEnumeratedDataValues(self, typename = None, debug = False):
  1856     def GetEnumeratedDataValues(self, typename = None, debug = False):
  1857         values = []
  1857         values = []
  1858         if typename is not None:
  1858         if typename is not None:
  1859             datatype_obj = self.GetDataType(typename, debug)
  1859             datatype_obj = self.GetDataType(typename, debug)
  1860             if datatype_obj is not None:
  1860             if datatype_obj is not None:
  1861                 basetype_content = datatype_obj.baseType.getcontent()
  1861                 basetype_content = datatype_obj.baseType.getcontent()
  1862                 basetype_content_type = basetype_content.getLocalTag()
  1862                 basetype_content_type = basetype_content.getLocalTag()
  1863                 if basetype_content_type == "enum":
  1863                 if basetype_content_type == "enum":
  1864                     return [value.getname() 
  1864                     return [value.getname()
  1865                             for value in basetype_content.xpath(
  1865                             for value in basetype_content.xpath(
  1866                                 "ppx:values/ppx:value",
  1866                                 "ppx:values/ppx:value",
  1867                                 namespaces=PLCOpenParser.NSMAP)]
  1867                                 namespaces=PLCOpenParser.NSMAP)]
  1868                 elif basetype_content_type == "derived":
  1868                 elif basetype_content_type == "derived":
  1869                     return self.GetEnumeratedDataValues(basetype_content.getname(), debug)
  1869                     return self.GetEnumeratedDataValues(basetype_content.getname(), debug)
  1876         return values
  1876         return values
  1877 
  1877 
  1878 #-------------------------------------------------------------------------------
  1878 #-------------------------------------------------------------------------------
  1879 #                   Project Element tag name computation functions
  1879 #                   Project Element tag name computation functions
  1880 #-------------------------------------------------------------------------------
  1880 #-------------------------------------------------------------------------------
  1881     
  1881 
  1882     # Compute a data type name
  1882     # Compute a data type name
  1883     def ComputeDataTypeName(self, datatype):
  1883     def ComputeDataTypeName(self, datatype):
  1884         return "D::%s" % datatype
  1884         return "D::%s" % datatype
  1885     
  1885 
  1886     # Compute a pou name
  1886     # Compute a pou name
  1887     def ComputePouName(self, pou):
  1887     def ComputePouName(self, pou):
  1888         return "P::%s" % pou
  1888         return "P::%s" % pou
  1889     
  1889 
  1890     # Compute a pou transition name
  1890     # Compute a pou transition name
  1891     def ComputePouTransitionName(self, pou, transition):
  1891     def ComputePouTransitionName(self, pou, transition):
  1892         return "T::%s::%s" % (pou, transition)
  1892         return "T::%s::%s" % (pou, transition)
  1893     
  1893 
  1894     # Compute a pou action name
  1894     # Compute a pou action name
  1895     def ComputePouActionName(self, pou, action):
  1895     def ComputePouActionName(self, pou, action):
  1896         return "A::%s::%s" % (pou, action)
  1896         return "A::%s::%s" % (pou, action)
  1897 
  1897 
  1898     # Compute a pou  name
  1898     # Compute a pou  name
  1903     def ComputeConfigurationResourceName(self, config, resource):
  1903     def ComputeConfigurationResourceName(self, config, resource):
  1904         return "R::%s::%s" % (config, resource)
  1904         return "R::%s::%s" % (config, resource)
  1905 
  1905 
  1906     def GetElementType(self, tagname):
  1906     def GetElementType(self, tagname):
  1907         words = tagname.split("::")
  1907         words = tagname.split("::")
  1908         return {"D" : ITEM_DATATYPE, "P" : ITEM_POU, 
  1908         return {"D" : ITEM_DATATYPE, "P" : ITEM_POU,
  1909                 "T" : ITEM_TRANSITION, "A" : ITEM_ACTION,
  1909                 "T" : ITEM_TRANSITION, "A" : ITEM_ACTION,
  1910                 "C" : ITEM_CONFIGURATION, "R" : ITEM_RESOURCE}[words[0]]
  1910                 "C" : ITEM_CONFIGURATION, "R" : ITEM_RESOURCE}[words[0]]
  1911 
  1911 
  1912 #-------------------------------------------------------------------------------
  1912 #-------------------------------------------------------------------------------
  1913 #                    Project opened Data types management functions
  1913 #                    Project opened Data types management functions
  1961                             dimensions = []
  1961                             dimensions = []
  1962                             for dimension in element_type.getdimension():
  1962                             for dimension in element_type.getdimension():
  1963                                 dimensions.append((dimension.getlower(), dimension.getupper()))
  1963                                 dimensions.append((dimension.getlower(), dimension.getupper()))
  1964                             base_type = element_type.baseType.getcontent()
  1964                             base_type = element_type.baseType.getcontent()
  1965                             base_type_type = element_type.getLocalTag()
  1965                             base_type_type = element_type.getLocalTag()
  1966                             element_infos["Type"] = ("array", 
  1966                             element_infos["Type"] = ("array",
  1967                                 base_type.getname()
  1967                                 base_type.getname()
  1968                                 if base_type_type == "derived"
  1968                                 if base_type_type == "derived"
  1969                                 else base_type_type.upper(), dimensions)
  1969                                 else base_type_type.upper(), dimensions)
  1970                         elif element_type_type == "derived":
  1970                         elif element_type_type == "derived":
  1971                             element_infos["Type"] = element_type.getname()
  1971                             element_infos["Type"] = element_type.getname()
  1979                 else:
  1979                 else:
  1980                     infos["type"] = "Directly"
  1980                     infos["type"] = "Directly"
  1981                     infos["base_type"] = (basetype_content.getname()
  1981                     infos["base_type"] = (basetype_content.getname()
  1982                         if basetype_content_type == "derived"
  1982                         if basetype_content_type == "derived"
  1983                         else basetype_content_type.upper())
  1983                         else basetype_content_type.upper())
  1984                 
  1984 
  1985                 if datatype.initialValue is not None:
  1985                 if datatype.initialValue is not None:
  1986                     infos["initial"] = str(datatype.initialValue.getvalue())
  1986                     infos["initial"] = str(datatype.initialValue.getvalue())
  1987                 else:
  1987                 else:
  1988                     infos["initial"] = ""
  1988                     infos["initial"] = ""
  1989                 return infos
  1989                 return infos
  1990         return None
  1990         return None
  1991     
  1991 
  1992     # Change the data type informations
  1992     # Change the data type informations
  1993     def SetDataTypeInfos(self, tagname, infos):
  1993     def SetDataTypeInfos(self, tagname, infos):
  1994         words = tagname.split("::")
  1994         words = tagname.split("::")
  1995         if self.Project is not None and words[0] == "D":
  1995         if self.Project is not None and words[0] == "D":
  1996             datatype = self.Project.getdataType(words[1])
  1996             datatype = self.Project.getdataType(words[1])
  2004                     derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
  2004                     derived_datatype = PLCOpenParser.CreateElement("derived", "dataType")
  2005                     derived_datatype.setname(infos["base_type"])
  2005                     derived_datatype.setname(infos["base_type"])
  2006                     datatype.baseType.setcontent(derived_datatype)
  2006                     datatype.baseType.setcontent(derived_datatype)
  2007             elif infos["type"] == "Subrange":
  2007             elif infos["type"] == "Subrange":
  2008                 subrange = PLCOpenParser.CreateElement(
  2008                 subrange = PLCOpenParser.CreateElement(
  2009                     "subrangeUnsigned" 
  2009                     "subrangeUnsigned"
  2010                     if infos["base_type"] in GetSubTypes("ANY_UINT")
  2010                     if infos["base_type"] in GetSubTypes("ANY_UINT")
  2011                     else "subrangeSigned", "dataType")
  2011                     else "subrangeSigned", "dataType")
  2012                 datatype.baseType.setcontent(subrange)
  2012                 datatype.baseType.setcontent(subrange)
  2013                 subrange.range.setlower(infos["min"])
  2013                 subrange.range.setlower(infos["min"])
  2014                 subrange.range.setupper(infos["max"])
  2014                 subrange.range.setupper(infos["max"])
  2104                     datatype.initialValue = PLCOpenParser.CreateElement("initialValue", "dataType")
  2104                     datatype.initialValue = PLCOpenParser.CreateElement("initialValue", "dataType")
  2105                 datatype.initialValue.setvalue(infos["initial"])
  2105                 datatype.initialValue.setvalue(infos["initial"])
  2106             else:
  2106             else:
  2107                 datatype.initialValue = None
  2107                 datatype.initialValue = None
  2108             self.BufferProject()
  2108             self.BufferProject()
  2109     
  2109 
  2110 #-------------------------------------------------------------------------------
  2110 #-------------------------------------------------------------------------------
  2111 #                       Project opened Pous management functions
  2111 #                       Project opened Pous management functions
  2112 #-------------------------------------------------------------------------------
  2112 #-------------------------------------------------------------------------------
  2113 
  2113 
  2114     # Return edited element
  2114     # Return edited element
  2130             elif words[0] == 'C':
  2130             elif words[0] == 'C':
  2131                 return project.getconfiguration(words[1])
  2131                 return project.getconfiguration(words[1])
  2132             elif words[0] == 'R':
  2132             elif words[0] == 'R':
  2133                 return project.getconfigurationResource(words[1], words[2])
  2133                 return project.getconfigurationResource(words[1], words[2])
  2134         return None
  2134         return None
  2135     
  2135 
  2136     # Return edited element name
  2136     # Return edited element name
  2137     def GetEditedElementName(self, tagname):
  2137     def GetEditedElementName(self, tagname):
  2138         words = tagname.split("::")
  2138         words = tagname.split("::")
  2139         if words[0] in ["P","C","D"]:
  2139         if words[0] in ["P","C","D"]:
  2140             return words[1]
  2140             return words[1]
  2141         else:
  2141         else:
  2142             return words[2]
  2142             return words[2]
  2143         return None
  2143         return None
  2144     
  2144 
  2145     # Return edited element name and type
  2145     # Return edited element name and type
  2146     def GetEditedElementType(self, tagname, debug = False):
  2146     def GetEditedElementType(self, tagname, debug = False):
  2147         words = tagname.split("::")
  2147         words = tagname.split("::")
  2148         if words[0] in ["P","T","A"]:
  2148         if words[0] in ["P","T","A"]:
  2149             return words[1], self.GetPouType(words[1], debug)
  2149             return words[1], self.GetPouType(words[1], debug)
  2181                 if pou is not None:
  2181                 if pou is not None:
  2182                     return self.GetPouInterfaceReturnType(pou, tree, debug)
  2182                     return self.GetPouInterfaceReturnType(pou, tree, debug)
  2183         elif words[0] == 'T':
  2183         elif words[0] == 'T':
  2184             return "BOOL"
  2184             return "BOOL"
  2185         return None
  2185         return None
  2186     
  2186 
  2187     # Change the edited element text
  2187     # Change the edited element text
  2188     def SetEditedElementText(self, tagname, text):
  2188     def SetEditedElementText(self, tagname, text):
  2189         if self.Project is not None:
  2189         if self.Project is not None:
  2190             element = self.GetEditedElement(tagname)
  2190             element = self.GetEditedElement(tagname)
  2191             if element is not None:
  2191             if element is not None:
  2192                 element.settext(text)
  2192                 element.settext(text)
  2193     
  2193 
  2194     # Return the edited element text
  2194     # Return the edited element text
  2195     def GetEditedElementText(self, tagname, debug = False):
  2195     def GetEditedElementText(self, tagname, debug = False):
  2196         element = self.GetEditedElement(tagname, debug)
  2196         element = self.GetEditedElement(tagname, debug)
  2197         if element is not None:
  2197         if element is not None:
  2198             return element.gettext()
  2198             return element.gettext()
  2234     def GetEditedElementCopy(self, tagname, debug = False):
  2234     def GetEditedElementCopy(self, tagname, debug = False):
  2235         element = self.GetEditedElement(tagname, debug)
  2235         element = self.GetEditedElement(tagname, debug)
  2236         if element is not None:
  2236         if element is not None:
  2237             return element.tostring()
  2237             return element.tostring()
  2238         return ""
  2238         return ""
  2239         
  2239 
  2240     def GetEditedElementInstancesCopy(self, tagname, blocks_id = None, wires = None, debug = False):
  2240     def GetEditedElementInstancesCopy(self, tagname, blocks_id = None, wires = None, debug = False):
  2241         element = self.GetEditedElement(tagname, debug)
  2241         element = self.GetEditedElement(tagname, debug)
  2242         text = ""
  2242         text = ""
  2243         if element is not None:
  2243         if element is not None:
  2244             wires = dict([(wire, True) 
  2244             wires = dict([(wire, True)
  2245                           for wire in wires 
  2245                           for wire in wires
  2246                           if wire[0] in blocks_id and wire[1] in blocks_id])
  2246                           if wire[0] in blocks_id and wire[1] in blocks_id])
  2247             copy_body = PLCOpenParser.CreateElement("body", "pou")
  2247             copy_body = PLCOpenParser.CreateElement("body", "pou")
  2248             element.append(copy_body)
  2248             element.append(copy_body)
  2249             copy_body.setcontent(
  2249             copy_body.setcontent(
  2250                 PLCOpenParser.CreateElement(element.getbodyType(), "body"))
  2250                 PLCOpenParser.CreateElement(element.getbodyType(), "body"))
  2255                     instance_copy = copy_body.getcontentInstance(id)
  2255                     instance_copy = copy_body.getcontentInstance(id)
  2256                     instance_copy.filterConnections(wires)
  2256                     instance_copy.filterConnections(wires)
  2257                     text += instance_copy.tostring()
  2257                     text += instance_copy.tostring()
  2258             element.remove(copy_body)
  2258             element.remove(copy_body)
  2259         return text
  2259         return text
  2260     
  2260 
  2261     def GenerateNewName(self, tagname, name, format, start_idx=0, exclude={}, debug=False):
  2261     def GenerateNewName(self, tagname, name, format, start_idx=0, exclude={}, debug=False):
  2262         names = exclude.copy()
  2262         names = exclude.copy()
  2263         if tagname is not None:
  2263         if tagname is not None:
  2264             names.update(dict([(varname.upper(), True) 
  2264             names.update(dict([(varname.upper(), True)
  2265                                for varname in self.GetEditedElementVariables(tagname, debug)]))
  2265                                for varname in self.GetEditedElementVariables(tagname, debug)]))
  2266             words = tagname.split("::")
  2266             words = tagname.split("::")
  2267             if words[0] in ["P","T","A"]:
  2267             if words[0] in ["P","T","A"]:
  2268                 element = self.GetEditedElement(tagname, debug)
  2268                 element = self.GetEditedElement(tagname, debug)
  2269                 if element is not None and element.getbodyType() not in ["ST", "IL"]:
  2269                 if element is not None and element.getbodyType() not in ["ST", "IL"]:
  2270                     for instance in element.getinstances():
  2270                     for instance in element.getinstances():
  2271                         if isinstance(instance, 
  2271                         if isinstance(instance,
  2272                             (PLCOpenParser.GetElementClass("step", "sfcObjects"), 
  2272                             (PLCOpenParser.GetElementClass("step", "sfcObjects"),
  2273                              PLCOpenParser.GetElementClass("connector", "commonObjects"), 
  2273                              PLCOpenParser.GetElementClass("connector", "commonObjects"),
  2274                              PLCOpenParser.GetElementClass("continuation", "commonObjects"))):
  2274                              PLCOpenParser.GetElementClass("continuation", "commonObjects"))):
  2275                             names[instance.getname().upper()] = True
  2275                             names[instance.getname().upper()] = True
  2276         else:
  2276         else:
  2277             project = self.GetProject(debug)
  2277             project = self.GetProject(debug)
  2278             if project is not None:
  2278             if project is not None:
  2288                         names[action.getname().upper()] = True
  2288                         names[action.getname().upper()] = True
  2289                 for config in project.getconfigurations():
  2289                 for config in project.getconfigurations():
  2290                     names[config.getname().upper()] = True
  2290                     names[config.getname().upper()] = True
  2291                     for resource in config.getresource():
  2291                     for resource in config.getresource():
  2292                         names[resource.getname().upper()] = True
  2292                         names[resource.getname().upper()] = True
  2293             
  2293 
  2294         i = start_idx
  2294         i = start_idx
  2295         while name is None or names.get(name.upper(), False):
  2295         while name is None or names.get(name.upper(), False):
  2296             name = (format%i)
  2296             name = (format%i)
  2297             i += 1
  2297             i += 1
  2298         return name
  2298         return name
  2299     
  2299 
  2300     def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False):
  2300     def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False):
  2301         element = self.GetEditedElement(tagname, debug)
  2301         element = self.GetEditedElement(tagname, debug)
  2302         element_name, element_type = self.GetEditedElementType(tagname, debug)
  2302         element_name, element_type = self.GetEditedElementType(tagname, debug)
  2303         if element is not None:
  2303         if element is not None:
  2304             bodytype = element.getbodyType()
  2304             bodytype = element.getbodyType()
  2305             
  2305 
  2306             # Get edited element type scaling
  2306             # Get edited element type scaling
  2307             scaling = None
  2307             scaling = None
  2308             project = self.GetProject(debug)
  2308             project = self.GetProject(debug)
  2309             if project is not None:
  2309             if project is not None:
  2310                 properties = project.getcontentHeader()
  2310                 properties = project.getcontentHeader()
  2311                 scaling = properties["scaling"][bodytype]
  2311                 scaling = properties["scaling"][bodytype]
  2312             
  2312 
  2313             # Get ids already by all the instances in edited element
  2313             # Get ids already by all the instances in edited element
  2314             used_id = dict([(instance.getlocalId(), True) for instance in element.getinstances()])
  2314             used_id = dict([(instance.getlocalId(), True) for instance in element.getinstances()])
  2315             new_id = {}
  2315             new_id = {}
  2316             
  2316 
  2317             try:
  2317             try:
  2318                 instances, error = LoadPouInstances(text.encode("utf-8"), bodytype)
  2318                 instances, error = LoadPouInstances(text.encode("utf-8"), bodytype)
  2319             except:
  2319             except:
  2320                 instances, error = [], ""
  2320                 instances, error = [], ""
  2321             if error is not None or len(instances) == 0:
  2321             if error is not None or len(instances) == 0:
  2322                 return _("Invalid plcopen element(s)!!!")
  2322                 return _("Invalid plcopen element(s)!!!")
  2323             
  2323 
  2324             exclude = {}
  2324             exclude = {}
  2325             for instance in instances:
  2325             for instance in instances:
  2326                 element.addinstance(instance)
  2326                 element.addinstance(instance)
  2327                 instance_type = instance.getLocalTag()
  2327                 instance_type = instance.getLocalTag()
  2328                 if instance_type == "block":
  2328                 if instance_type == "block":
  2330                     blocktype_infos = self.GetBlockType(blocktype)
  2330                     blocktype_infos = self.GetBlockType(blocktype)
  2331                     blockname = instance.getinstanceName()
  2331                     blockname = instance.getinstanceName()
  2332                     if blocktype_infos["type"] != "function" and blockname is not None:
  2332                     if blocktype_infos["type"] != "function" and blockname is not None:
  2333                         if element_type == "function":
  2333                         if element_type == "function":
  2334                             return _("FunctionBlock \"%s\" can't be pasted in a Function!!!")%blocktype
  2334                             return _("FunctionBlock \"%s\" can't be pasted in a Function!!!")%blocktype
  2335                         blockname = self.GenerateNewName(tagname, 
  2335                         blockname = self.GenerateNewName(tagname,
  2336                                                          blockname, 
  2336                                                          blockname,
  2337                                                          "%s%%d"%blocktype, 
  2337                                                          "%s%%d"%blocktype,
  2338                                                          debug=debug)
  2338                                                          debug=debug)
  2339                         exclude[blockname] = True
  2339                         exclude[blockname] = True
  2340                         instance.setinstanceName(blockname)
  2340                         instance.setinstanceName(blockname)
  2341                         self.AddEditedElementPouVar(tagname, blocktype, blockname)
  2341                         self.AddEditedElementPouVar(tagname, blocktype, blockname)
  2342                 elif instance_type == "step":
  2342                 elif instance_type == "step":
  2343                     stepname = self.GenerateNewName(tagname, 
  2343                     stepname = self.GenerateNewName(tagname,
  2344                                                     instance.getname(), 
  2344                                                     instance.getname(),
  2345                                                     "Step%d", 
  2345                                                     "Step%d",
  2346                                                     exclude=exclude, 
  2346                                                     exclude=exclude,
  2347                                                     debug=debug)
  2347                                                     debug=debug)
  2348                     exclude[stepname] = True
  2348                     exclude[stepname] = True
  2349                     instance.setname(stepname)
  2349                     instance.setname(stepname)
  2350                 localid = instance.getlocalId()
  2350                 localid = instance.getlocalId()
  2351                 if not used_id.has_key(localid):
  2351                 if not used_id.has_key(localid):
  2352                     new_id[localid] = True
  2352                     new_id[localid] = True
  2353             
  2353 
  2354             idx = 1
  2354             idx = 1
  2355             translate_id = {}
  2355             translate_id = {}
  2356             bbox = rect()
  2356             bbox = rect()
  2357             for instance in instances:
  2357             for instance in instances:
  2358                 localId = instance.getlocalId()
  2358                 localId = instance.getlocalId()
  2361                     while used_id.has_key(idx) or new_id.has_key(idx):
  2361                     while used_id.has_key(idx) or new_id.has_key(idx):
  2362                         idx += 1
  2362                         idx += 1
  2363                     new_id[idx] = True
  2363                     new_id[idx] = True
  2364                     instance.setlocalId(idx)
  2364                     instance.setlocalId(idx)
  2365                     translate_id[localId] = idx
  2365                     translate_id[localId] = idx
  2366             
  2366 
  2367             x, y, width, height = bbox.bounding_box()
  2367             x, y, width, height = bbox.bounding_box()
  2368             if middle:
  2368             if middle:
  2369                 new_pos[0] -= width / 2
  2369                 new_pos[0] -= width / 2
  2370                 new_pos[1] -= height / 2
  2370                 new_pos[1] -= height / 2
  2371             else:
  2371             else:
  2383                 new_pos = (max(minx, round(new_pos[0] / scaling[0]) * scaling[0]),
  2383                 new_pos = (max(minx, round(new_pos[0] / scaling[0]) * scaling[0]),
  2384                            max(miny, round(new_pos[1] / scaling[1]) * scaling[1]))
  2384                            max(miny, round(new_pos[1] / scaling[1]) * scaling[1]))
  2385             else:
  2385             else:
  2386                 new_pos = (max(30, new_pos[0]), max(30, new_pos[1]))
  2386                 new_pos = (max(30, new_pos[0]), max(30, new_pos[1]))
  2387             diff = (int(new_pos[0] - x), int(new_pos[1] - y))
  2387             diff = (int(new_pos[0] - x), int(new_pos[1] - y))
  2388             
  2388 
  2389             connections = {}
  2389             connections = {}
  2390             for instance in instances:
  2390             for instance in instances:
  2391                 connections.update(instance.updateConnectionsId(translate_id))
  2391                 connections.update(instance.updateConnectionsId(translate_id))
  2392                 if getattr(instance, "setexecutionOrderId", None) is not None:
  2392                 if getattr(instance, "setexecutionOrderId", None) is not None:
  2393                     instance.setexecutionOrderId(0)
  2393                     instance.setexecutionOrderId(0)
  2394                 instance.translate(*diff)
  2394                 instance.translate(*diff)
  2395             
  2395 
  2396             return new_id, connections
  2396             return new_id, connections
  2397     
  2397 
  2398     def GetEditedElementInstancesInfos(self, tagname, debug = False):
  2398     def GetEditedElementInstancesInfos(self, tagname, debug = False):
  2399         element_instances = OrderedDict()
  2399         element_instances = OrderedDict()
  2400         element = self.GetEditedElement(tagname, debug)
  2400         element = self.GetEditedElement(tagname, debug)
  2401         if element is not None:
  2401         if element is not None:
  2402             factory = BlockInstanceFactory(element_instances)
  2402             factory = BlockInstanceFactory(element_instances)
  2403             
  2403 
  2404             pou_block_instances_xslt_tree = etree.XSLT(
  2404             pou_block_instances_xslt_tree = etree.XSLT(
  2405                 pou_block_instances_xslt, 
  2405                 pou_block_instances_xslt,
  2406                 extensions = {
  2406                 extensions = {
  2407                     ("pou_block_instances_ns", name): getattr(factory, name)
  2407                     ("pou_block_instances_ns", name): getattr(factory, name)
  2408                     for name in ["AddBlockInstance", "SetSpecificValues",
  2408                     for name in ["AddBlockInstance", "SetSpecificValues",
  2409                                  "AddInstanceConnection", "AddConnectionLink",
  2409                                  "AddInstanceConnection", "AddConnectionLink",
  2410                                  "AddLinkPoint", "AddAction"]})
  2410                                  "AddLinkPoint", "AddAction"]})
  2411         
  2411 
  2412             pou_block_instances_xslt_tree(element)
  2412             pou_block_instances_xslt_tree(element)
  2413         return element_instances
  2413         return element_instances
  2414     
  2414 
  2415     def ClearEditedElementExecutionOrder(self, tagname):
  2415     def ClearEditedElementExecutionOrder(self, tagname):
  2416         element = self.GetEditedElement(tagname)
  2416         element = self.GetEditedElement(tagname)
  2417         if element is not None:
  2417         if element is not None:
  2418             element.resetexecutionOrder()
  2418             element.resetexecutionOrder()
  2419     
  2419 
  2420     def ResetEditedElementExecutionOrder(self, tagname):
  2420     def ResetEditedElementExecutionOrder(self, tagname):
  2421         element = self.GetEditedElement(tagname)
  2421         element = self.GetEditedElement(tagname)
  2422         if element is not None:
  2422         if element is not None:
  2423             element.compileexecutionOrder()
  2423             element.compileexecutionOrder()
  2424     
  2424 
  2425     def SetConnectionWires(self, connection, connector):
  2425     def SetConnectionWires(self, connection, connector):
  2426         wires = connector.GetWires()
  2426         wires = connector.GetWires()
  2427         idx = 0
  2427         idx = 0
  2428         for wire, handle in wires:
  2428         for wire, handle in wires:
  2429             points = wire.GetPoints(handle != 0)
  2429             points = wire.GetPoints(handle != 0)
  2441                 if formalParameter != "":
  2441                 if formalParameter != "":
  2442                     connection.setconnectionParameter(idx, formalParameter)
  2442                     connection.setconnectionParameter(idx, formalParameter)
  2443                 else:
  2443                 else:
  2444                     connection.setconnectionParameter(idx, None)
  2444                     connection.setconnectionParameter(idx, None)
  2445                 idx += 1
  2445                 idx += 1
  2446     
  2446 
  2447     def GetVarTypeObject(self, var_type):
  2447     def GetVarTypeObject(self, var_type):
  2448         var_type_obj = PLCOpenParser.CreateElement("type", "variable")
  2448         var_type_obj = PLCOpenParser.CreateElement("type", "variable")
  2449         if not var_type.startswith("ANY") and TypeHierarchy.get(var_type):
  2449         if not var_type.startswith("ANY") and TypeHierarchy.get(var_type):
  2450             var_type_obj.setcontent(PLCOpenParser.CreateElement(
  2450             var_type_obj.setcontent(PLCOpenParser.CreateElement(
  2451                 var_type.lower() if var_type in ["STRING", "WSTRING"]
  2451                 var_type.lower() if var_type in ["STRING", "WSTRING"]
  2453         else:
  2453         else:
  2454             derived_type = PLCOpenParser.CreateElement("derived", "dataType")
  2454             derived_type = PLCOpenParser.CreateElement("derived", "dataType")
  2455             derived_type.setname(var_type)
  2455             derived_type.setname(var_type)
  2456             var_type_obj.setcontent(derived_type)
  2456             var_type_obj.setcontent(derived_type)
  2457         return var_type_obj
  2457         return var_type_obj
  2458     
  2458 
  2459     def AddEditedElementPouVar(self, tagname, var_type, name,**args):
  2459     def AddEditedElementPouVar(self, tagname, var_type, name,**args):
  2460         if self.Project is not None:
  2460         if self.Project is not None:
  2461             words = tagname.split("::")
  2461             words = tagname.split("::")
  2462             if words[0] in ['P', 'T', 'A']:
  2462             if words[0] in ['P', 'T', 'A']:
  2463                 pou = self.Project.getpou(words[1])
  2463                 pou = self.Project.getpou(words[1])
  2464                 if pou is not None:
  2464                 if pou is not None:
  2465                     pou.addpouLocalVar(
  2465                     pou.addpouLocalVar(
  2466                         self.GetVarTypeObject(var_type), 
  2466                         self.GetVarTypeObject(var_type),
  2467                         name, **args)
  2467                         name, **args)
  2468     
  2468 
  2469     def AddEditedElementPouExternalVar(self, tagname, var_type, name):
  2469     def AddEditedElementPouExternalVar(self, tagname, var_type, name):
  2470         if self.Project is not None:
  2470         if self.Project is not None:
  2471             words = tagname.split("::")
  2471             words = tagname.split("::")
  2472             if words[0] in ['P', 'T', 'A']:
  2472             if words[0] in ['P', 'T', 'A']:
  2473                 pou = self.Project.getpou(words[1])
  2473                 pou = self.Project.getpou(words[1])
  2474                 if pou is not None:
  2474                 if pou is not None:
  2475                     pou.addpouExternalVar(
  2475                     pou.addpouExternalVar(
  2476                         self.GetVarTypeObject(var_type), name)
  2476                         self.GetVarTypeObject(var_type), name)
  2477             
  2477 
  2478     def ChangeEditedElementPouVar(self, tagname, old_type, old_name, new_type, new_name):
  2478     def ChangeEditedElementPouVar(self, tagname, old_type, old_name, new_type, new_name):
  2479         if self.Project is not None:
  2479         if self.Project is not None:
  2480             words = tagname.split("::")
  2480             words = tagname.split("::")
  2481             if words[0] in ['P', 'T', 'A']:
  2481             if words[0] in ['P', 'T', 'A']:
  2482                 pou = self.Project.getpou(words[1])
  2482                 pou = self.Project.getpou(words[1])
  2483                 if pou is not None:
  2483                 if pou is not None:
  2484                     pou.changepouVar(old_type, old_name, new_type, new_name)
  2484                     pou.changepouVar(old_type, old_name, new_type, new_name)
  2485     
  2485 
  2486     def RemoveEditedElementPouVar(self, tagname, type, name):
  2486     def RemoveEditedElementPouVar(self, tagname, type, name):
  2487         if self.Project is not None:
  2487         if self.Project is not None:
  2488             words = tagname.split("::")
  2488             words = tagname.split("::")
  2489             if words[0] in ['P', 'T', 'A']:
  2489             if words[0] in ['P', 'T', 'A']:
  2490                 pou = self.Project.getpou(words[1])
  2490                 pou = self.Project.getpou(words[1])
  2491                 if pou is not None:
  2491                 if pou is not None:
  2492                     pou.removepouVar(type, name)
  2492                     pou.removepouVar(type, name)
  2493     
  2493 
  2494     def AddEditedElementBlock(self, tagname, id, blocktype, blockname = None):
  2494     def AddEditedElementBlock(self, tagname, id, blocktype, blockname = None):
  2495         element = self.GetEditedElement(tagname)
  2495         element = self.GetEditedElement(tagname)
  2496         if element is not None:
  2496         if element is not None:
  2497             block = PLCOpenParser.CreateElement("block", "fbdObjects")
  2497             block = PLCOpenParser.CreateElement("block", "fbdObjects")
  2498             block.setlocalId(id)
  2498             block.setlocalId(id)
  2500             blocktype_infos = self.GetBlockType(blocktype)
  2500             blocktype_infos = self.GetBlockType(blocktype)
  2501             if blocktype_infos["type"] != "function" and blockname is not None:
  2501             if blocktype_infos["type"] != "function" and blockname is not None:
  2502                 block.setinstanceName(blockname)
  2502                 block.setinstanceName(blockname)
  2503                 self.AddEditedElementPouVar(tagname, blocktype, blockname)
  2503                 self.AddEditedElementPouVar(tagname, blocktype, blockname)
  2504             element.addinstance(block)
  2504             element.addinstance(block)
  2505     
  2505 
  2506     def SetEditedElementBlockInfos(self, tagname, id, infos):
  2506     def SetEditedElementBlockInfos(self, tagname, id, infos):
  2507         element = self.GetEditedElement(tagname)
  2507         element = self.GetEditedElement(tagname)
  2508         if element is not None:
  2508         if element is not None:
  2509             block = element.getinstance(id)
  2509             block = element.getinstance(id)
  2510             if block is None:
  2510             if block is None:
  2511                 return 
  2511                 return
  2512             old_name = block.getinstanceName()
  2512             old_name = block.getinstanceName()
  2513             old_type = block.gettypeName()
  2513             old_type = block.gettypeName()
  2514             new_name = infos.get("name", old_name)
  2514             new_name = infos.get("name", old_name)
  2515             new_type = infos.get("type", old_type)
  2515             new_type = infos.get("type", old_type)
  2516             if new_type != old_type:
  2516             if new_type != old_type:
  2569                             variable.setedge(connector.GetEdge())
  2569                             variable.setedge(connector.GetEdge())
  2570                         position = connector.GetRelPosition()
  2570                         position = connector.GetRelPosition()
  2571                         variable.addconnectionPointOut()
  2571                         variable.addconnectionPointOut()
  2572                         variable.connectionPointOut.setrelPositionXY(position.x, position.y)
  2572                         variable.connectionPointOut.setrelPositionXY(position.x, position.y)
  2573             block.tostring()
  2573             block.tostring()
  2574         
  2574 
  2575     def AddEditedElementVariable(self, tagname, id, var_type):
  2575     def AddEditedElementVariable(self, tagname, id, var_type):
  2576         element = self.GetEditedElement(tagname)
  2576         element = self.GetEditedElement(tagname)
  2577         if element is not None:
  2577         if element is not None:
  2578             variable = PLCOpenParser.CreateElement(
  2578             variable = PLCOpenParser.CreateElement(
  2579                 {INPUT: "inVariable",
  2579                 {INPUT: "inVariable",
  2580                  OUTPUT: "outVariable",
  2580                  OUTPUT: "outVariable",
  2581                  INOUT: "inOutVariable"}[var_type], "fbdObjects")
  2581                  INOUT: "inOutVariable"}[var_type], "fbdObjects")
  2582             variable.setlocalId(id)
  2582             variable.setlocalId(id)
  2583             element.addinstance(variable)
  2583             element.addinstance(variable)
  2584         
  2584 
  2585     def SetEditedElementVariableInfos(self, tagname, id, infos):
  2585     def SetEditedElementVariableInfos(self, tagname, id, infos):
  2586         element = self.GetEditedElement(tagname)
  2586         element = self.GetEditedElement(tagname)
  2587         if element is not None:
  2587         if element is not None:
  2588             variable = element.getinstance(id)
  2588             variable = element.getinstance(id)
  2589             if variable is None:
  2589             if variable is None:
  2590                 return 
  2590                 return
  2591             for param, value in infos.items():
  2591             for param, value in infos.items():
  2592                 if param == "name":
  2592                 if param == "name":
  2593                     variable.setexpression(value)
  2593                     variable.setexpression(value)
  2594                 elif param == "executionOrder" and variable.getexecutionOrderId() != value:
  2594                 elif param == "executionOrder" and variable.getexecutionOrderId() != value:
  2595                     element.setelementExecutionOrder(variable, value)
  2595                     element.setelementExecutionOrder(variable, value)
  2632             connection = PLCOpenParser.CreateElement(
  2632             connection = PLCOpenParser.CreateElement(
  2633                 {CONNECTOR: "connector",
  2633                 {CONNECTOR: "connector",
  2634                  CONTINUATION: "continuation"}[connection_type], "commonObjects")
  2634                  CONTINUATION: "continuation"}[connection_type], "commonObjects")
  2635             connection.setlocalId(id)
  2635             connection.setlocalId(id)
  2636             element.addinstance(connection)
  2636             element.addinstance(connection)
  2637         
  2637 
  2638     def SetEditedElementConnectionInfos(self, tagname, id, infos):
  2638     def SetEditedElementConnectionInfos(self, tagname, id, infos):
  2639         element = self.GetEditedElement(tagname)
  2639         element = self.GetEditedElement(tagname)
  2640         if element is not None:
  2640         if element is not None:
  2641             connection = element.getinstance(id)
  2641             connection = element.getinstance(id)
  2642             if connection is None:
  2642             if connection is None:
  2643                 return
  2643                 return
  2644             for param, value in infos.items():
  2644             for param, value in infos.items():
  2645                 if param == "name":
  2645                 if param == "name":
  2646                     connection.setname(value)    
  2646                     connection.setname(value)
  2647                 elif param == "height":
  2647                 elif param == "height":
  2648                     connection.setheight(value)
  2648                     connection.setheight(value)
  2649                 elif param == "width":
  2649                 elif param == "width":
  2650                     connection.setwidth(value)
  2650                     connection.setwidth(value)
  2651                 elif param == "x":
  2651                 elif param == "x":
  2666         element = self.GetEditedElement(tagname)
  2666         element = self.GetEditedElement(tagname)
  2667         if element is not None:
  2667         if element is not None:
  2668             comment = PLCOpenParser.CreateElement("comment", "commonObjects")
  2668             comment = PLCOpenParser.CreateElement("comment", "commonObjects")
  2669             comment.setlocalId(id)
  2669             comment.setlocalId(id)
  2670             element.addinstance(comment)
  2670             element.addinstance(comment)
  2671     
  2671 
  2672     def SetEditedElementCommentInfos(self, tagname, id, infos):
  2672     def SetEditedElementCommentInfos(self, tagname, id, infos):
  2673         element = self.GetEditedElement(tagname)
  2673         element = self.GetEditedElement(tagname)
  2674         if element is not None:
  2674         if element is not None:
  2675             comment = element.getinstance(id)
  2675             comment = element.getinstance(id)
  2676             for param, value in infos.items():
  2676             for param, value in infos.items():
  2691             powerrail = PLCOpenParser.CreateElement(
  2691             powerrail = PLCOpenParser.CreateElement(
  2692                 {LEFTRAIL: "leftPowerRail",
  2692                 {LEFTRAIL: "leftPowerRail",
  2693                  RIGHTRAIL: "rightPowerRail"}[powerrail_type], "ldObjects")
  2693                  RIGHTRAIL: "rightPowerRail"}[powerrail_type], "ldObjects")
  2694             powerrail.setlocalId(id)
  2694             powerrail.setlocalId(id)
  2695             element.addinstance(powerrail)
  2695             element.addinstance(powerrail)
  2696     
  2696 
  2697     def SetEditedElementPowerRailInfos(self, tagname, id, infos):
  2697     def SetEditedElementPowerRailInfos(self, tagname, id, infos):
  2698         element = self.GetEditedElement(tagname)
  2698         element = self.GetEditedElement(tagname)
  2699         if element is not None:
  2699         if element is not None:
  2700             powerrail = element.getinstance(id)
  2700             powerrail = element.getinstance(id)
  2701             if powerrail is None:
  2701             if powerrail is None:
  2723                             position = connector.GetRelPosition()
  2723                             position = connector.GetRelPosition()
  2724                             connection = PLCOpenParser.CreateElement("connectionPointIn", "rightPowerRail")
  2724                             connection = PLCOpenParser.CreateElement("connectionPointIn", "rightPowerRail")
  2725                             powerrail.appendconnectionPointIn(connection)
  2725                             powerrail.appendconnectionPointIn(connection)
  2726                             connection.setrelPositionXY(position.x, position.y)
  2726                             connection.setrelPositionXY(position.x, position.y)
  2727                             self.SetConnectionWires(connection, connector)
  2727                             self.SetConnectionWires(connection, connector)
  2728                             
  2728 
  2729     def AddEditedElementContact(self, tagname, id):
  2729     def AddEditedElementContact(self, tagname, id):
  2730         element = self.GetEditedElement(tagname)
  2730         element = self.GetEditedElement(tagname)
  2731         if element is not None:
  2731         if element is not None:
  2732             contact = PLCOpenParser.CreateElement("contact", "ldObjects")
  2732             contact = PLCOpenParser.CreateElement("contact", "ldObjects")
  2733             contact.setlocalId(id)
  2733             contact.setlocalId(id)
  2819         element = self.GetEditedElement(tagname)
  2819         element = self.GetEditedElement(tagname)
  2820         if element is not None:
  2820         if element is not None:
  2821             step = PLCOpenParser.CreateElement("step", "sfcObjects")
  2821             step = PLCOpenParser.CreateElement("step", "sfcObjects")
  2822             step.setlocalId(id)
  2822             step.setlocalId(id)
  2823             element.addinstance(step)
  2823             element.addinstance(step)
  2824     
  2824 
  2825     def SetEditedElementStepInfos(self, tagname, id, infos):
  2825     def SetEditedElementStepInfos(self, tagname, id, infos):
  2826         element = self.GetEditedElement(tagname)
  2826         element = self.GetEditedElement(tagname)
  2827         if element is not None:
  2827         if element is not None:
  2828             step = element.getinstance(id)
  2828             step = element.getinstance(id)
  2829             if step is None:
  2829             if step is None:
  2862                         position = value.GetRelPosition()
  2862                         position = value.GetRelPosition()
  2863                         step.addconnectionPointOutAction()
  2863                         step.addconnectionPointOutAction()
  2864                         step.connectionPointOutAction.setrelPositionXY(position.x, position.y)
  2864                         step.connectionPointOutAction.setrelPositionXY(position.x, position.y)
  2865                     else:
  2865                     else:
  2866                         step.deleteconnectionPointOutAction()
  2866                         step.deleteconnectionPointOutAction()
  2867     
  2867 
  2868     def AddEditedElementTransition(self, tagname, id):
  2868     def AddEditedElementTransition(self, tagname, id):
  2869         element = self.GetEditedElement(tagname)
  2869         element = self.GetEditedElement(tagname)
  2870         if element is not None:
  2870         if element is not None:
  2871             transition = PLCOpenParser.CreateElement("transition", "sfcObjects")
  2871             transition = PLCOpenParser.CreateElement("transition", "sfcObjects")
  2872             transition.setlocalId(id)
  2872             transition.setlocalId(id)
  2873             element.addinstance(transition)
  2873             element.addinstance(transition)
  2874     
  2874 
  2875     def SetEditedElementTransitionInfos(self, tagname, id, infos):
  2875     def SetEditedElementTransitionInfos(self, tagname, id, infos):
  2876         element = self.GetEditedElement(tagname)
  2876         element = self.GetEditedElement(tagname)
  2877         if element is not None:
  2877         if element is not None:
  2878             transition = element.getinstance(id)
  2878             transition = element.getinstance(id)
  2879             if transition is None:
  2879             if transition is None:
  2905                     transition.addconnectionPointOut()
  2905                     transition.addconnectionPointOut()
  2906                     transition.connectionPointOut.setrelPositionXY(position.x, position.y)
  2906                     transition.connectionPointOut.setrelPositionXY(position.x, position.y)
  2907                 elif infos.get("type", None) == "connection" and param == "connection" and value:
  2907                 elif infos.get("type", None) == "connection" and param == "connection" and value:
  2908                     transition.setconditionContent("connection", None)
  2908                     transition.setconditionContent("connection", None)
  2909                     self.SetConnectionWires(transition.condition.content, value)
  2909                     self.SetConnectionWires(transition.condition.content, value)
  2910     
  2910 
  2911     def AddEditedElementDivergence(self, tagname, id, divergence_type):
  2911     def AddEditedElementDivergence(self, tagname, id, divergence_type):
  2912         element = self.GetEditedElement(tagname)
  2912         element = self.GetEditedElement(tagname)
  2913         if element is not None:
  2913         if element is not None:
  2914             divergence = PLCOpenParser.CreateElement(
  2914             divergence = PLCOpenParser.CreateElement(
  2915                 {SELECTION_DIVERGENCE: "selectionDivergence",
  2915                 {SELECTION_DIVERGENCE: "selectionDivergence",
  2917                  SIMULTANEOUS_DIVERGENCE: "simultaneousDivergence",
  2917                  SIMULTANEOUS_DIVERGENCE: "simultaneousDivergence",
  2918                  SIMULTANEOUS_CONVERGENCE: "simultaneousConvergence"}.get(
  2918                  SIMULTANEOUS_CONVERGENCE: "simultaneousConvergence"}.get(
  2919                     divergence_type), "sfcObjects")
  2919                     divergence_type), "sfcObjects")
  2920             divergence.setlocalId(id)
  2920             divergence.setlocalId(id)
  2921             element.addinstance(divergence)
  2921             element.addinstance(divergence)
  2922     
  2922 
  2923     DivergenceTypes = [
  2923     DivergenceTypes = [
  2924         (divergence_type, 
  2924         (divergence_type,
  2925          PLCOpenParser.GetElementClass(divergence_type, "sfcObjects"))
  2925          PLCOpenParser.GetElementClass(divergence_type, "sfcObjects"))
  2926         for divergence_type in ["selectionDivergence", "simultaneousDivergence",
  2926         for divergence_type in ["selectionDivergence", "simultaneousDivergence",
  2927                                 "selectionConvergence", "simultaneousConvergence"]]
  2927                                 "selectionConvergence", "simultaneousConvergence"]]
  2928     
  2928 
  2929     def GetDivergenceType(self, divergence):
  2929     def GetDivergenceType(self, divergence):
  2930         for divergence_type, divergence_class in self.DivergenceTypes:
  2930         for divergence_type, divergence_class in self.DivergenceTypes:
  2931             if isinstance(divergence, divergence_class):
  2931             if isinstance(divergence, divergence_class):
  2932                 return divergence_type
  2932                 return divergence_type
  2933         return None
  2933         return None
  2934     
  2934 
  2935     def SetEditedElementDivergenceInfos(self, tagname, id, infos):
  2935     def SetEditedElementDivergenceInfos(self, tagname, id, infos):
  2936         element = self.GetEditedElement(tagname)
  2936         element = self.GetEditedElement(tagname)
  2937         if element is not None:
  2937         if element is not None:
  2938             divergence = element.getinstance(id)
  2938             divergence = element.getinstance(id)
  2939             if divergence is None:
  2939             if divergence is None:
  2973                         for output_connector in output_connectors:
  2973                         for output_connector in output_connectors:
  2974                             position = output_connector.GetRelPosition()
  2974                             position = output_connector.GetRelPosition()
  2975                             connection = PLCOpenParser.CreateElement("connectionPointOut", divergence_type)
  2975                             connection = PLCOpenParser.CreateElement("connectionPointOut", divergence_type)
  2976                             divergence.appendconnectionPointOut(connection)
  2976                             divergence.appendconnectionPointOut(connection)
  2977                             connection.setrelPositionXY(position.x, position.y)
  2977                             connection.setrelPositionXY(position.x, position.y)
  2978                             
  2978 
  2979     def AddEditedElementJump(self, tagname, id):
  2979     def AddEditedElementJump(self, tagname, id):
  2980         element = self.GetEditedElement(tagname)
  2980         element = self.GetEditedElement(tagname)
  2981         if element is not None:
  2981         if element is not None:
  2982             jump = PLCOpenParser.CreateElement("jumpStep", "sfcObjects")
  2982             jump = PLCOpenParser.CreateElement("jumpStep", "sfcObjects")
  2983             jump.setlocalId(id)
  2983             jump.setlocalId(id)
  2984             element.addinstance(jump)
  2984             element.addinstance(jump)
  2985     
  2985 
  2986     def SetEditedElementJumpInfos(self, tagname, id, infos):
  2986     def SetEditedElementJumpInfos(self, tagname, id, infos):
  2987         element = self.GetEditedElement(tagname)
  2987         element = self.GetEditedElement(tagname)
  2988         if element is not None:
  2988         if element is not None:
  2989             jump = element.getinstance(id)
  2989             jump = element.getinstance(id)
  2990             if jump is None:
  2990             if jump is None:
  3003                 elif param == "connector":
  3003                 elif param == "connector":
  3004                     position = value.GetRelPosition()
  3004                     position = value.GetRelPosition()
  3005                     jump.addconnectionPointIn()
  3005                     jump.addconnectionPointIn()
  3006                     jump.connectionPointIn.setrelPositionXY(position.x, position.y)
  3006                     jump.connectionPointIn.setrelPositionXY(position.x, position.y)
  3007                     self.SetConnectionWires(jump.connectionPointIn, value)
  3007                     self.SetConnectionWires(jump.connectionPointIn, value)
  3008  
  3008 
  3009     def AddEditedElementActionBlock(self, tagname, id):
  3009     def AddEditedElementActionBlock(self, tagname, id):
  3010         element = self.GetEditedElement(tagname)
  3010         element = self.GetEditedElement(tagname)
  3011         if element is not None:
  3011         if element is not None:
  3012             actionBlock = PLCOpenParser.CreateElement("actionBlock", "commonObjects")
  3012             actionBlock = PLCOpenParser.CreateElement("actionBlock", "commonObjects")
  3013             actionBlock.setlocalId(id)
  3013             actionBlock.setlocalId(id)
  3014             element.addinstance(actionBlock)
  3014             element.addinstance(actionBlock)
  3015     
  3015 
  3016     def SetEditedElementActionBlockInfos(self, tagname, id, infos):
  3016     def SetEditedElementActionBlockInfos(self, tagname, id, infos):
  3017         element = self.GetEditedElement(tagname)
  3017         element = self.GetEditedElement(tagname)
  3018         if element is not None:
  3018         if element is not None:
  3019             actionBlock = element.getinstance(id)
  3019             actionBlock = element.getinstance(id)
  3020             if actionBlock is None:
  3020             if actionBlock is None:
  3033                 elif param == "connector":
  3033                 elif param == "connector":
  3034                     position = value.GetRelPosition()
  3034                     position = value.GetRelPosition()
  3035                     actionBlock.addconnectionPointIn()
  3035                     actionBlock.addconnectionPointIn()
  3036                     actionBlock.connectionPointIn.setrelPositionXY(position.x, position.y)
  3036                     actionBlock.connectionPointIn.setrelPositionXY(position.x, position.y)
  3037                     self.SetConnectionWires(actionBlock.connectionPointIn, value)
  3037                     self.SetConnectionWires(actionBlock.connectionPointIn, value)
  3038     
  3038 
  3039     def RemoveEditedElementInstance(self, tagname, id):
  3039     def RemoveEditedElementInstance(self, tagname, id):
  3040         element = self.GetEditedElement(tagname)
  3040         element = self.GetEditedElement(tagname)
  3041         if element is not None:
  3041         if element is not None:
  3042             instance = element.getinstance(id)
  3042             instance = element.getinstance(id)
  3043             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
  3043             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
  3160         self.NextCompiledProject = self.Copy(self.Project)
  3160         self.NextCompiledProject = self.Copy(self.Project)
  3161         self.CurrentCompiledProject = None
  3161         self.CurrentCompiledProject = None
  3162         self.Buffering = False
  3162         self.Buffering = False
  3163         self.CurrentElementEditing = None
  3163         self.CurrentElementEditing = None
  3164         return error
  3164         return error
  3165         
  3165 
  3166     def SaveXMLFile(self, filepath = None):
  3166     def SaveXMLFile(self, filepath = None):
  3167         if not filepath and self.FilePath == "":
  3167         if not filepath and self.FilePath == "":
  3168             return False
  3168             return False
  3169         else:
  3169         else:
  3170             contentheader = {"modificationDateTime": datetime.datetime(*localtime()[:6])}
  3170             contentheader = {"modificationDateTime": datetime.datetime(*localtime()[:6])}
  3171             self.Project.setcontentHeader(contentheader)
  3171             self.Project.setcontentHeader(contentheader)
  3172             
  3172 
  3173             if filepath:
  3173             if filepath:
  3174                 SaveProject(self.Project, filepath)
  3174                 SaveProject(self.Project, filepath)
  3175             else:
  3175             else:
  3176                 SaveProject(self.Project, self.FilePath)
  3176                 SaveProject(self.Project, self.FilePath)
  3177             
  3177 
  3178             self.MarkProjectAsSaved()
  3178             self.MarkProjectAsSaved()
  3179             if filepath:
  3179             if filepath:
  3180                 self.SetFilePath(filepath)
  3180                 self.SetFilePath(filepath)
  3181             return True
  3181             return True
  3182 
  3182 
  3231     def StartBuffering(self):
  3231     def StartBuffering(self):
  3232         if self.ProjectBuffer is not None:
  3232         if self.ProjectBuffer is not None:
  3233             self.Buffering = True
  3233             self.Buffering = True
  3234         else:
  3234         else:
  3235             self.ProjectSaved = False
  3235             self.ProjectSaved = False
  3236         
  3236 
  3237     def EndBuffering(self):
  3237     def EndBuffering(self):
  3238         if self.ProjectBuffer is not None and self.Buffering:
  3238         if self.ProjectBuffer is not None and self.Buffering:
  3239             self.ProjectBuffer.Buffering(PLCOpenParser.Dumps(self.Project))
  3239             self.ProjectBuffer.Buffering(PLCOpenParser.Dumps(self.Project))
  3240             self.Buffering = False
  3240             self.Buffering = False
  3241 
  3241 
  3243         self.EndBuffering()
  3243         self.EndBuffering()
  3244         if self.ProjectBuffer is not None:
  3244         if self.ProjectBuffer is not None:
  3245             self.ProjectBuffer.CurrentSaved()
  3245             self.ProjectBuffer.CurrentSaved()
  3246         else:
  3246         else:
  3247             self.ProjectSaved = True
  3247             self.ProjectSaved = True
  3248     
  3248 
  3249     # Return if project is saved
  3249     # Return if project is saved
  3250     def ProjectIsSaved(self):
  3250     def ProjectIsSaved(self):
  3251         if self.ProjectBuffer is not None:
  3251         if self.ProjectBuffer is not None:
  3252             return self.ProjectBuffer.IsCurrentSaved() and not self.Buffering
  3252             return self.ProjectBuffer.IsCurrentSaved() and not self.Buffering
  3253         else:
  3253         else:
  3255 
  3255 
  3256     def LoadPrevious(self):
  3256     def LoadPrevious(self):
  3257         self.EndBuffering()
  3257         self.EndBuffering()
  3258         if self.ProjectBuffer is not None:
  3258         if self.ProjectBuffer is not None:
  3259             self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Previous())
  3259             self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Previous())
  3260     
  3260 
  3261     def LoadNext(self):
  3261     def LoadNext(self):
  3262         if self.ProjectBuffer is not None:
  3262         if self.ProjectBuffer is not None:
  3263             self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Next())
  3263             self.Project = PLCOpenParser.Loads(self.ProjectBuffer.Next())
  3264     
  3264 
  3265     def GetBufferState(self):
  3265     def GetBufferState(self):
  3266         if self.ProjectBuffer is not None:
  3266         if self.ProjectBuffer is not None:
  3267             first = self.ProjectBuffer.IsFirst() and not self.Buffering
  3267             first = self.ProjectBuffer.IsFirst() and not self.Buffering
  3268             last = self.ProjectBuffer.IsLast()
  3268             last = self.ProjectBuffer.IsLast()
  3269             return not first, not last
  3269             return not first, not last