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