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